Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 3/5] arm_mpam: add MPAM-Fb MSC firmware access support
From: Niyas Sait @ 2026-05-18  8:52 UTC (permalink / raw)
  To: andre.przywara
  Cc: ben.horgan, catalin.marinas, fenghuay, guohanjun, james.morse,
	jic23, lenb, linux-acpi, linux-arm-kernel, linux-kernel,
	lpieralisi, rafael, reinette.chatre, sudeep.holla, will
In-Reply-To: <20260429141339.3171205-4-andre.przywara@arm.com>

Hi Andre,

On Wed, Apr 29, 2026 at 04:13:37PM +0200, Andre Przywara wrote:

> +#define SCMI_CHAN_FLAGS_OFS	0x10
> +#define SCMI_CHAN_FLAGS_IRQ		BIT(0)
> +#define SCMI_MSG_LENGTH_OFS	0x14
> +#define SCMI_MSG_HEADER_OFS	0x18
> +#define SCMI_MSG_PAYLOAD_OFS	0x1c

I think this will not work for the ACPI PCC Type 3 MPAM Fb path.

SCMI shared memory transport layout and ACPI Extended PCC subspace
shared memory layout use different offsets for the flags, length, command,
and payload fields.

For Extended PCC subspace, the layout is:

Flags   @ 0x04
Length  @ 0x08
Command @ 0x0c
Payload @ 0x10

SCMI shared memory layout uses:

Flags   @ 0x10
Length  @ 0x14
Command @ 0x18
Payload @ 0x1c

You will need to use the extended PCC subspace layout for the ACPI path.

> +static int mpam_fb_wait_for_channel(struct pcc_mbox_chan *chan,
> +				    bool free)
> +{
> +	u32 status = free ? SCMI_CHAN_STATUS_FREE_BIT : 0;
> +	u32 val;
> +
> +	/*
> +	 * The channel should really be free always at this point, as we take
> +	 * a lock for every read or write request. Check the free bit anyway,
> +	 * for good measure and to catch corner cases.
> +	 */
> +	return readl_poll_timeout(chan->shmem + SCMI_CHAN_STATUS_OFS, val,
> +				  (val & SCMI_CHAN_STATUS_FREE_BIT) == status,
> +				  1, 10000);
> +}

This also assumes SCMI channel status completion semantics in shared memory.
For PCC Type 3 transport, completion should follow PCC Type 3 completion mechanisms.

Thanks,
Niyas


^ permalink raw reply

* Re: [PATCH v22 08/13] mfd: core: Add firmware-node support to MFD cells
From: Bartosz Golaszewski @ 2026-05-18  8:57 UTC (permalink / raw)
  To: Shivendra Pratap
  Cc: linux-pm, linux-kernel, linux-arm-msm, linux-arm-kernel,
	devicetree, Florian Fainelli, Krzysztof Kozlowski,
	Dmitry Baryshkov, Mukesh Ojha, Andre Draszik, Greg Kroah-Hartman,
	Kathiravan Thirumoorthy, Srinivas Kandagatla, Bartosz Golaszewski,
	Sebastian Reichel, Mark Rutland, Lorenzo Pieralisi,
	Rafael J. Wysocki, Daniel Lezcano, Christian Loehle, Ulf Hansson,
	Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Konrad Dybcio, Arnd Bergmann, Souvik Chakravarty,
	Andy Yan, Matthias Brugger, John Stultz, Moritz Fischer,
	Bartosz Golaszewski, Sudeep Holla
In-Reply-To: <20260514-arm-psci-system_reset2-vendor-reboots-v22-8-28a5bde07483@oss.qualcomm.com>

On Thu, 14 May 2026 16:25:49 +0200, Shivendra Pratap
<shivendra.pratap@oss.qualcomm.com> said:
> MFD core has no way to register a child device using an explicit firmware
> node. This prevents drivers from registering child nodes when those nodes
> do not define a compatible string. One such example is the PSCI
> "reboot-mode" node, which omits a compatible string as it describes
> boot-states provided by the underlying firmware.
>
> Extend struct mfd_cell with a callback that allows drivers to provide an
> explicit firmware node. The node is added to the MFD child device during
> registration when none is assigned by device tree, ACPI, or software
> matching.
>
> Suggested-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> Signed-off-by: Shivendra Pratap <shivendra.pratap@oss.qualcomm.com>
> ---
>  drivers/mfd/mfd-core.c   | 30 ++++++++++++++++++++++++++++++
>  include/linux/mfd/core.h | 14 ++++++++++++++
>  2 files changed, 44 insertions(+)
>
> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> index 7aa32b90cf1eb7fa0a05bf3dc506e60a262c9850..cc2a2a924d6d3044e29a9f864b536ee325ed797b 100644
> --- a/drivers/mfd/mfd-core.c
> +++ b/drivers/mfd/mfd-core.c
> @@ -10,6 +10,7 @@
>  #include <linux/kernel.h>
>  #include <linux/platform_device.h>
>  #include <linux/acpi.h>
> +#include <linux/fwnode.h>
>  #include <linux/list.h>
>  #include <linux/property.h>
>  #include <linux/mfd/core.h>
> @@ -148,6 +149,11 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev,
>  	return 0;
>  }
>
> +static void mfd_child_fwnode_put(void *data)
> +{
> +	fwnode_handle_put(data);
> +}

Ah, this seems to answer my previous question, but...

> +
>  static int mfd_add_device(struct device *parent, int id,
>  			  const struct mfd_cell *cell,
>  			  struct resource *mem_base,
> @@ -156,6 +162,7 @@ static int mfd_add_device(struct device *parent, int id,
>  	struct resource *res;
>  	struct platform_device *pdev;
>  	struct mfd_of_node_entry *of_entry, *tmp;
> +	struct fwnode_handle *fwnode;
>  	bool disabled = false;
>  	int ret = -ENOMEM;
>  	int platform_id;
> @@ -224,6 +231,29 @@ static int mfd_add_device(struct device *parent, int id,
>
>  	mfd_acpi_add_device(cell, pdev);
>
> +	if (!pdev->dev.fwnode && cell->get_child_fwnode) {
> +		fwnode = cell->get_child_fwnode(parent);
> +		if (fwnode) {
> +			device_set_node(&pdev->dev, fwnode);
> +
> +			/*
> +			 * platform_device_release() drops only of_node refs.

Which is a separate problem we're discussing elsewhere. It should probably drop
the fwnode reference it holds, not the one of of_node.

> +			 * Track non-OF fwnodes explicitly so they are put on
> +			 * all teardown paths.
> +			 */
> +			if (!to_of_node(fwnode)) {
> +				ret = devm_add_action(&pdev->dev,
> +						      mfd_child_fwnode_put,
> +						      fwnode);

What if the device never gets bound to the driver? The release will never be
called, this is why it's wrong to schedule devres actions for unbound devices
and one of the reasons for patch 1 in this series.

What I suggest for now is: in tear-down path: see if the cell has the
get_child_fwnode() callback and - if so - drop the reference. Add a big, fat
comment saying that this must be removed if we decide to switch to dropping the
device's fwnode reference in platform driver core which may happen soon.

Bart

> +				if (ret) {
> +					device_set_node(&pdev->dev, NULL);
> +					fwnode_handle_put(fwnode);
> +					goto fail_of_entry;
> +				}
> +			}
> +		}
> +	}
> +
>  	if (cell->pdata_size) {
>  		ret = platform_device_add_data(pdev,
>  					cell->platform_data, cell->pdata_size);
> diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
> index faeea7abd688f223fb0b31cde0a9b69dfe2a61ff..abfc26c057d6ee46947ba2b6f2e99f420e74b127 100644
> --- a/include/linux/mfd/core.h
> +++ b/include/linux/mfd/core.h
> @@ -50,6 +50,7 @@
>  #define MFD_DEP_LEVEL_HIGH 1
>
>  struct irq_domain;
> +struct fwnode_handle;
>  struct software_node;
>
>  /* Matches ACPI PNP id, either _HID or _CID, or ACPI _ADR */
> @@ -80,6 +81,19 @@ struct mfd_cell {
>
>  	/* Software node for the device. */
>  	const struct software_node *swnode;
> +	/*
> +	 * Callback to return an explicit firmware node.
> +	 * @parent: MFD parent device passed to mfd_add_devices().
> +	 *
> +	 * Called only if OF/ACPI matching did not assign a fwnode.
> +	 * Ownership of the returned reference is transferred to MFD core.
> +	 *
> +	 * Return a referenced fwnode or NULL if none is available.
> +	 *
> +	 * mfd_cell must be zero-initialized or get_child_fwnode must be NULL
> +	 * when unused.
> +	 */
> +	struct fwnode_handle *(*get_child_fwnode)(struct device *parent);
>
>  	/*
>  	 * Device Tree compatible string
>
> --
> 2.34.1
>
>


^ permalink raw reply

* Re: [PATCH v22 07/13] power: reset: Add psci-reboot-mode driver
From: Bartosz Golaszewski @ 2026-05-18  8:58 UTC (permalink / raw)
  To: Shivendra Pratap
  Cc: linux-pm, linux-kernel, linux-arm-msm, linux-arm-kernel,
	devicetree, Florian Fainelli, Krzysztof Kozlowski,
	Dmitry Baryshkov, Mukesh Ojha, Andre Draszik, Greg Kroah-Hartman,
	Kathiravan Thirumoorthy, Srinivas Kandagatla, Sebastian Reichel,
	Mark Rutland, Lorenzo Pieralisi, Rafael J. Wysocki,
	Daniel Lezcano, Christian Loehle, Ulf Hansson, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Konrad Dybcio, Arnd Bergmann, Souvik Chakravarty, Andy Yan,
	Matthias Brugger, John Stultz, Moritz Fischer,
	Bartosz Golaszewski, Sudeep Holla
In-Reply-To: <20260514-arm-psci-system_reset2-vendor-reboots-v22-7-28a5bde07483@oss.qualcomm.com>

On Thu, 14 May 2026 16:25:48 +0200, Shivendra Pratap
<shivendra.pratap@oss.qualcomm.com> said:
> PSCI supports different types of resets like SYSTEM_RESET, SYSTEM_RESET2
> ARCH WARM reset and SYSTEM_RESET2 vendor-specific resets. Currently
> there is no common driver that handles all supported psci resets at one
> place. Additionally, there is no common mechanism to issue the supported
> psci resets from userspace.
>
> Add a psci-reboot-mode driver, and define two types of PSCI resets,
> predefined-resets and vendor-specific resets. Predefined-resets are
> defined by psci driver and vendor-specific resets are defined by SoC
> vendors, under the psci:reboot-mode node of SoC device tree.
>
> Register the driver with the reboot-mode framework to interface these
> resets to userspace. When userspace initiates a supported command, pass
> the reset arguments to the PSCI driver to enable command-based reset.
>
> This change allows userspace to issue supported PSCI reset commands
> using the standard reboot system calls while enabling SoC vendors to
> define their specific resets for PSCI.
>
> Signed-off-by: Shivendra Pratap <shivendra.pratap@oss.qualcomm.com>
> ---
>  MAINTAINERS                            |  1 +
>  drivers/power/reset/Kconfig            | 10 +++++
>  drivers/power/reset/Makefile           |  1 +
>  drivers/power/reset/psci-reboot-mode.c | 72 ++++++++++++++++++++++++++++++++++
>  4 files changed, 84 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 36ba42209c0b332813a296880cd55798a5592d2a..4b0815c31679550f5ab719de4a5852990c7cc643 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -21342,6 +21342,7 @@ S:	Maintained
>  F:	Documentation/devicetree/bindings/arm/psci.yaml
>  F:	drivers/firmware/psci/
>  F:	drivers/mfd/psci-mfd.c
> +F:	drivers/power/reset/psci-reboot-mode.c
>  F:	include/linux/psci.h
>  F:	include/uapi/linux/psci.h
>
> diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
> index 124afb99febe92450b6ae322aeed3b63fa2070df..d9d1f768b8691abc3b32f2675519f2ddbaf19b84 100644
> --- a/drivers/power/reset/Kconfig
> +++ b/drivers/power/reset/Kconfig
> @@ -348,6 +348,16 @@ config NVMEM_REBOOT_MODE
>  	  then the bootloader can read it and take different
>  	  action according to the mode.
>
> +config PSCI_REBOOT_MODE
> +	bool "PSCI reboot mode driver"
> +	depends on OF && ARM_PSCI_FW

Can you add COMPILE_TEST coverage here too please?

> +	select REBOOT_MODE
> +	help
> +	  Say y here will enable PSCI reboot mode driver. This gets
> +	  the PSCI reboot mode arguments and passes them to psci
> +	  driver. psci driver uses these arguments for issuing
> +	  device reset into different boot states.
> +
>  config POWER_MLXBF
>  	tristate "Mellanox BlueField power handling driver"
>  	depends on (GPIO_MLXBF2 || GPIO_MLXBF3) && ACPI
> diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
> index d7ae97241a838fe1b536b2f911868e7590d12e3b..02948622fe3d00e165f941108ab92ecb66b0f0e8 100644
> --- a/drivers/power/reset/Makefile
> +++ b/drivers/power/reset/Makefile
> @@ -40,5 +40,6 @@ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o
>  obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o
>  obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o
>  obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
> +obj-$(CONFIG_PSCI_REBOOT_MODE) += psci-reboot-mode.o
>  obj-$(CONFIG_POWER_MLXBF) += pwr-mlxbf.o
>  obj-$(CONFIG_POWER_RESET_QEMU_VIRT_CTRL) += qemu-virt-ctrl.o
> diff --git a/drivers/power/reset/psci-reboot-mode.c b/drivers/power/reset/psci-reboot-mode.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..845b2a1816ce53451dea8dfc4bffffda0d3e9293
> --- /dev/null
> +++ b/drivers/power/reset/psci-reboot-mode.c
> @@ -0,0 +1,72 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/psci.h>
> +#include <linux/reboot-mode.h>
> +#include <linux/types.h>
> +
> +/*
> + * Predefined modes:
> + *   reset_type = 0
> + *   cookie stored in magic[63:32]
> + */
> +#define PSCI_PREDEF_MAGIC(cookie)	((cookie) * BIT_ULL(32))
> +
> +static const struct reboot_mode_entry psci_resets[] = {
> +	{
> +		.name  = "psci-system-reset",
> +		.magic = PSCI_PREDEF_MAGIC(PSCI_RESET_TYPE_SYSTEM_RESET),
> +	},
> +	{
> +		.name  = "psci-system-reset2-arch-warm-reset",
> +		.magic = PSCI_PREDEF_MAGIC(PSCI_RESET_TYPE_SYSTEM_RESET2_ARCH_WARM),
> +	},
> +};
> +
> +/*
> + * magic is a pre-encoded value:
> + *   reset_type in low 32 bits
> + *   cookie in high 32 bits
> + */
> +static int psci_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic)
> +{
> +	psci_set_reset_cmd(magic);
> +	return 0;
> +}
> +
> +static int psci_reboot_mode_probe(struct platform_device *pdev)
> +{
> +	struct reboot_mode_driver *reboot;
> +	size_t count;
> +	int ret;
> +
> +	reboot = devm_kzalloc(&pdev->dev, sizeof(*reboot), GFP_KERNEL);
> +	if (!reboot)
> +		return -ENOMEM;
> +
> +	reboot_mode_driver_init(reboot, &pdev->dev, psci_reboot_mode_write);
> +
> +	/* Skip PSCI SYSTEM_RESET2 modes if unsupported */
> +	count = psci_has_system_reset2_support() ? ARRAY_SIZE(psci_resets) : 1;
> +	ret = reboot_mode_add_predefined_modes(reboot, psci_resets, count);
> +	if (ret)
> +		return ret;
> +
> +	return devm_reboot_mode_register(&pdev->dev, reboot);
> +}
> +
> +static struct platform_driver psci_reboot_mode_driver = {
> +	.probe  = psci_reboot_mode_probe,
> +	.driver = {
> +		.name	= "psci-reboot-mode",
> +	},
> +};
> +

You can drop the newline here.

> +module_platform_driver(psci_reboot_mode_driver);
> +
> +MODULE_LICENSE("GPL");
>
> --
> 2.34.1
>
>

With that:

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>


^ permalink raw reply

* Re: [PATCH v2 5/6] devfreq: Get and put module refcount when switching governor
From: Yaxiong Tian @ 2026-05-18  9:00 UTC (permalink / raw)
  To: Jie Zhan, cwchoi00, cw00.choi, myungjoo.ham, kyungmin.park,
	linux-pm, linux-arm-kernel
  Cc: linuxarm, zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <66a14821-fd14-440e-b75f-98bc37eedba7@hisilicon.com>


在 2026/5/18 16:39, Jie Zhan 写道:
>
> On 5/15/2026 6:39 PM, Jie Zhan wrote:
>>
>> On 5/14/2026 2:50 PM, Yaxiong Tian wrote:
>>> 在 2026/5/13 17:38, Jie Zhan 写道:
>>>> A governor module can be dynamically inserted or removed if compiled as a
>>>> kernel module.  'devfreq->governor' would become NULL if the governor
>>>> module is removed when it's in use.
>>>>
>>>> To prevent the governor module from being removed (except for force
>>>> unload) when it's in use, get and put a refcount of the governor module
>>>> when starting and stopping the governor.
>>>>
>>>> As a result, unloading a governor module in use returns an error, e.g.:
>>>>     $ cat governor
>>>>     performance
>>>>     $ rmmod governor_performance
>>>>     rmmod: ERROR: Module governor_performance is in use
>>>>
>>>> Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
>>>> ---
>>>>    drivers/devfreq/devfreq.c | 17 ++++++++++++++++-
>>>>    1 file changed, 16 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>>> index e1363ab69173..2ea42325d030 100644
>>>> --- a/drivers/devfreq/devfreq.c
>>>> +++ b/drivers/devfreq/devfreq.c
>>>> @@ -345,24 +345,37 @@ static int devfreq_set_governor(struct devfreq *df,
>>>>                     __func__, df->governor->name, ret);
>>>>                return ret;
>>>>            }
>>>> +        module_put(old_gov->owner);
>>>>        }
>>>>          /* Start the new governor */
>>>> +    if (!try_module_get(new_gov->owner)) {
>>>> +        df->governor = NULL;
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>> Here, new_gov has already been checked in try_then_request_governor() for whether the module can be obtained.
>>>
>>> I think it might be more reasonable to merge try_then_request_governor() and devfreq_set_governor(), so that when new_gov cannot be obtained, the operation of the old governor is not affected.
>>>
>> Well yeah, indeed! I'll take a look at how to implement this.
>> Thanks for the suggestion.
>>
>> Jie
> Hi Yaxiong,
>
> A follow-up after digging deeper.
>
> 1. To be clear, the try_module_get() / module_put() pairs in
> try_then_request_governor() and devfreq_set_governor() protect different
> ranges.  Assuming no FORCE_UNLOAD, the former protects the governor module
> from the time it's queried until it's set as the working governor, while
> the latter protects when the governor is in use.
>
> However, I realized the former protection is no longer needed since I
> removed the governor list lock in v2.  devfreq_remove_governor() and the
> 'request and set' governor sequence are already synchronized by
> 'devfreq_list_lock'. Thus, patch 6 should be dropped.
>
> 2. devfreq_add_device() needs error prints because it's a probe path.
> governor_store() doesn't want error prints since it's not a good practice
> to print on a sysfs read/write.  Merging the two functions will violate
> either of them.
>
> Thanks,
> Jie
Okay, please ignore my suggestion.
>>>>        df->governor = new_gov;
>>>>        ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>>>>        if (ret) {
>>>>            dev_warn(dev, "%s: Governor %s not started(%d)\n",
>>>>                 __func__, df->governor->name, ret);
>>>> +        module_put(new_gov->owner);
>>>>              /* Restore previous governor */
>>>>            df->governor = old_gov;
>>>>            if (!df->governor)
>>>>                return ret;
>>>>    +        if (!try_module_get(old_gov->owner)) {
>>>> +            df->governor = NULL;
>>>> +            return -EINVAL;
>>>> +        }
>>>> +
>>>>            ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>>>>            if (ret) {
>>>>                dev_err(dev, "%s: restore Governor %s failed (%d)\n",
>>>>                    __func__, df->governor->name, ret);
>>>> +            module_put(old_gov->owner);
>>>>                df->governor = NULL;
>>>>                return ret;
>>>>            }
>>>> @@ -1040,9 +1053,11 @@ int devfreq_remove_device(struct devfreq *devfreq)
>>>>          devfreq_cooling_unregister(devfreq->cdev);
>>>>    -    if (devfreq->governor)
>>>> +    if (devfreq->governor) {
>>>>            devfreq->governor->event_handler(devfreq,
>>>>                             DEVFREQ_GOV_STOP, NULL);
>>>> +        module_put(devfreq->governor->owner);
>>>> +    }
>>>>        device_unregister(&devfreq->dev);
>>>>          return 0;


^ permalink raw reply

* RE: [PATCH] ARM: dts: aspeed: anacapa: name EDSFF and thermtrip SGPIO lines
From: Fu, Rex @ 2026-05-18  9:01 UTC (permalink / raw)
  To: Andrew Jeffery, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley
  Cc: devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org
In-Reply-To: <bae3a186da639118d88ad2632c5edf8963946dc1.camel@codeconstruct.com.au>

AMD General

Hi Andrew,

Thanks for the review.

I agree that the original commit message was too vague, especially since these GPIO line names are visible to userspace.

There is no new board revision or underlying hardware change involved. This is a naming correction for the existing Anacapa hardware design.

I will remove the "legacy or unused" wording. The previous names do not match the actual Anacapa usage: some lines were named as CPU-related signals but are used for EDSFF power-good monitoring, and the thermtrip lines used raw active-low signal names while userspace monitors the asserted condition.

Changing these names is appropriate because the userspace monitoring configuration is based on the platform signal names. Keeping the old names would make the DTS inconsistent with the hardware design and userspace configuration.

I will send a v2 with the exact old-to-new mappings and a more precise explanation in the commit message.

Best regards,
Rex Fu
BMC Engineer  |  AMD
Data Center Platform Engineering Group
O +886 (2) 2655-8885
----------------------------------------------------------------------------------------------------------------------------------
3F, No. 3-2 Yuanqu Street, Nangang District, Taipei 115, Taiwan
LinkedIn  |  Instagram  |  X  |  amd.com


-----Original Message-----
From: Andrew Jeffery <andrew@codeconstruct.com.au>
Sent: Monday, May 18, 2026 2:48 PM
To: Fu, Rex <Rex.Fu@amd.com>; Rob Herring <robh@kernel.org>; Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Joel Stanley <joel@jms.id.au>
Cc: devicetree@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-aspeed@lists.ozlabs.org; linux-kernel@vger.kernel.org
Subject: Re: [PATCH] ARM: dts: aspeed: anacapa: name EDSFF and thermtrip SGPIO lines

[You don't often get email from andrew@codeconstruct.com.au. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]

Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.


Hello Rex,

On Thu, 2026-04-30 at 13:44 +0800, Rex Fu via B4 Relay wrote:
> From: Rex Fu <Rex.Fu@amd.com>
>
> Name the Anacapa SGPIO lines used for EDSFF power-good and thermtrip
> assertion signals.
>
> The affected lines replace legacy
>

Which are legacy?

>  or unused
>

Which are unused?

> CPU-related names with the
> platform signal names used by userspace monitoring.

This is the kind of change that has the potential to break old userspace. Why is it appropriate? I'd like a more precise discussion in the commit message.

Was there some other underlying change (e.g. a new revision of the platform design)?

Andrew

>
> Signed-off-by: Rex Fu <Rex.Fu@amd.com>
> ---
>  arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts | 10
> +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
> b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
> index 2cb7bd128d24..fe960bb7bc27 100644
> --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
> @@ -912,7 +912,7 @@ &sgpiom0 {
>       "PWRGD_PVDDIO_P0", "",
>       "PWRGD_PVDDIO_MEM_S3_P0", "",
>       "PWRGD_CHMP_CPU0_FPGA", "",
> -     "PWRGD_CHIL_CPU0_FPGA", "",
> +     "HPM_EDSFF_PG", "",
>       "PWRGD_CHEH_CPU0_FPGA", "",
>       "PWRGD_CHAD_CPU0_FPGA", "FM_BMC_READY_PLD",
>       "", "",
> @@ -957,8 +957,8 @@ &sgpiom0 {
>       "PDB_ALERT_R_N", "",
>
>       /* L0-L7 line 176-191 */
> -     "CPU0_SP7R1", "", "CPU0_SP7R2", "",
> -     "CPU0_SP7R3", "", "CPU0_SP7R4", "",
> +     "L_EDSFF2_PG", "", "L_EDSFF3_PG", "",
> +     "R_EDSFF2_PG", "", "R_EDSFF3_PG", "",
>       "CPU0_CORETYPE0", "", "CPU0_CORETYPE1", "",
>       "CPU0_CORETYPE2", "", "FM_BIOS_POST_CMPLT_R_N", "",
>
> @@ -984,8 +984,8 @@ &sgpiom0 {
>       "HPM_PWR_FAIL", "Port80_b0",
>       "FM_DIMM_IP_FAIL", "Port80_b1",
>       "FM_DIMM_AH_FAIL", "Port80_b2",
> -     "HPM_AMC_THERMTRIP_R_L", "Port80_b3",
> -     "FM_CPU0_THERMTRIP_N", "Port80_b4",
> +     "AMC_THERMTRIP_ASSERT", "Port80_b3",
> +     "CPU_THERMTRIP_ASSERT", "Port80_b4",
>       "PVDDCR_SOC_P0_OCP_L", "Port80_b5",
>       "CPLD_SGPIO_RDY", "Port80_b6",
>       "", "Port80_b7",
>
> ---
> base-commit: 9974969c14031a097d6b45bcb7a06bb4aa525c40
> change-id: 20260430-anacapa-sgpio-edsff-thermtrip-acb228bf61be
>
> Best regards,
> --
> Rex Fu <Rex.Fu@amd.com>
>

^ permalink raw reply

* Re: [PATCH v6 16/22] drm: bridge: dw_hdmi: Use display_info is_hdmi and has_audio
From: Jani Nikula @ 2026-05-18  9:02 UTC (permalink / raw)
  To: Jonas Karlman, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Heiko Stuebner, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Luca Ceresoli, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
	Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
	linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
	linux-kernel
In-Reply-To: <20260516183838.2024991-17-jonas@kwiboo.se>

On Sat, 16 May 2026, Jonas Karlman <jonas@kwiboo.se> wrote:
> -	/*
> -	 * FIXME: This should use connector->display_info.is_hdmi and
> -	 * connector->display_info.has_audio from a path that has read the EDID
> -	 * and called drm_edid_connector_update().
> -	 */
> -	edid = drm_edid_raw(drm_edid);
> -
> -	dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
> -		edid->width_cm, edid->height_cm);
> -
> -	hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
> -	hdmi->sink_has_audio = drm_detect_monitor_audio(edid);

Yay! \o/


>  
>  	return drm_edid;
>  }

-- 
Jani Nikula, Intel


^ permalink raw reply

* Re: [PATCH] iommu: Allow device driver to use its own PASID space for SVA
From: Joonwon Kang @ 2026-05-18  9:06 UTC (permalink / raw)
  To: jgg, kirill.shutemov
  Cc: Alexander.Grest, alexander.shishkin, amhetre, baolu.lu, bp,
	dave.hansen, easwar.hariharan, hpa, iommu, jacob.jun.pan,
	joonwonkang, joro, jpb, kas, kees, kevin.tian, linux-arm-kernel,
	linux-kernel, mingo, nicolinc, peterz, praan, robin.murphy,
	ryasuoka, smostafa, sohil.mehta, tglx, will, x86, xin
In-Reply-To: <20260515231808.GQ7702@ziepe.ca>

> On Fri, May 15, 2026 at 09:46:05AM +0000, Joonwon Kang wrote:
> > diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> > index 0ca3912ecb7f..61e2e52105e5 100644
> > --- a/arch/x86/kernel/traps.c
> > +++ b/arch/x86/kernel/traps.c
> > @@ -864,6 +864,8 @@ static bool try_fixup_enqcmd_gp(void)
> >  		return false;
> >  
> >  	pasid = mm_get_enqcmd_pasid(current->mm);
> > +	if (pasid == IOMMU_PASID_INVALID)
> > +		return false;
> 
> If you do this then probably you should get rid of mm_valid_pasid(),
> mm_get_enqcmd_pasid() already has the NULL check so the two functions
> are kind of pointless.
> 
> You also missed the other place calling mm_valid_pasid() that should
> really be sensitive to this as well:
> 
> static int prctl_enable_tagged_addr(struct mm_struct *mm, unsigned long nr_bits)
> {
> [..]
>         if (mm_valid_pasid(mm) &&
>             !test_bit(MM_CONTEXT_FORCE_TAGGED_SVA, &mm->context.flags))
>                 return -EINVAL;
> 
> Make that removal a prep patch
> 

Thanks for pointing this out. I think mm_valid_pasid() is to check if SVA
is currently in action while mm_get_enqcmd_pasid() is to get the PASID for
"ENQCMD instruction execution". What prctl_enable_tagged_addr()
semantically requires here seems to be only checking if SVA is activated
or not regardless of whether EL0 can execute ENQCMD instruction; the
function wants to return error if SVA has been activated when LAM is to be
activated as they are mutually exclusive [1]. So, I think we should leave
it as-is. I am adding the author Kiryl as a reviewer for confirmation.

Since it is now possible with this patch to activate SVA without involving
EL0(for ENQCMD-like instructions), callers should be able to distinguish
between if SVA is activated and if EL0 can execute ENQCMD-like
instructions in addition to the SVA activation. mm_valid_pasid() is for
the former and mm_get_enqcmd_pasid() is for the latter. So, I think there
will be loss if we make the latter API serve for the former.

Or, I guess we could rename mm_valid_pasid() to be more specific like
mm_sva_activated() or mm_sva_in_use(). What do you think?

> I didn't try to check the rest closely but the approach looked sane to
> me

Thanks. Sashiko reported valid points [2] and I will handle them in the
meantime.

[1] https://lore.kernel.org/all/20230312112612.31869-12-kirill.shutemov@linux.intel.com/
[2] https://sashiko.dev/#/patchset/20260515094605.3195841-1-joonwonkang%40google.com

Thanks,
Joonwon Kang


^ permalink raw reply

* Re: [PATCH v1] virt: arm-cca-guest: use raw variant of smp_processor_id() in arm_cca_report_new()
From: Suzuki K Poulose @ 2026-05-18  9:10 UTC (permalink / raw)
  To: Kohei Enju, Catalin Marinas, Will Deacon
  Cc: Sami Mujawar, Gavin Shan, Steven Price, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260518033157.1865498-1-enju.kohei@fujitsu.com>

On 18/05/2026 04:31, Kohei Enju wrote:
> With CONFIG_DEBUG_PREEMPT=y, smp_processor_id() becomes an alias of
> debug_smp_processor_id(). This debug function complains when certain
> conditions that ensure CPU ID stability are not met, specifically when
> it's called from a preemptible context.
> 
> In arm_cca_report_new(), which runs in a preemptible context,
> smp_processor_id() triggers a splat [0] due to this.
> 
> However, the CPU ID obtained here is used as the target CPU for
> smp_call_function_single() to designate a specific CPU for subsequent
> operations, not to assert that the current thread will continue to
> execute on the same CPU. Therefore, snapshotting the CPU ID itself is
> correct, and thus there's no actual harm except for the splat.
> 
> Use raw_smp_processor_id() instead, to directly retrieve the current CPU
> ID without the debug checks, avoiding the unnecessary warning message
> while preserving the correct functional behavior.
> 
> [0]
>   BUG: using smp_processor_id() in preemptible [00000000] code: cca-workload-at/134
>   caller is debug_smp_processor_id+0x20/0x2c
>   CPU: 0 UID: 0 PID: 134 Comm: cca-workload-at Not tainted 7.0.0-rc1-gc74a64d12073 #1 PREEMPT
>   Hardware name: linux,dummy-virt (DT)
>   Call trace:
>    [...]
>    check_preemption_disabled+0xf8/0x100
>    debug_smp_processor_id+0x20/0x2c
>    arm_cca_report_new+0x54/0x230
>    tsm_report_read+0x184/0x260
>    tsm_report_outblob_read+0x18/0x38
>    configfs_bin_read_iter+0xf4/0x1dc
>    vfs_read+0x230/0x31c
>    [...]
> 
> Fixes: 7999edc484ca ("virt: arm-cca-guest: TSM_REPORT support for realms")
> Signed-off-by: Kohei Enju <enju.kohei@fujitsu.com>

Thank for the fix,

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>


> ---
>   drivers/virt/coco/arm-cca-guest/arm-cca-guest.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> index 0c9ea24a200c..2d450caee3e4 100644
> --- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> +++ b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> @@ -108,7 +108,7 @@ static int arm_cca_report_new(struct tsm_report *report, void *data)
>   	 * allocate outblob based on the returned value from the 'init'
>   	 * call and that cannot be done in an atomic context.
>   	 */
> -	cpu = smp_processor_id();
> +	cpu = raw_smp_processor_id();
>   
>   	info.challenge = desc->inblob;
>   	info.challenge_size = desc->inblob_len;



^ permalink raw reply

* Re: [PATCH 3/4 v2] phy: s32g: Add serdes xpcs subsystem
From: Enric Balletbo i Serra @ 2026-05-18  9:11 UTC (permalink / raw)
  To: Vincent Guittot
  Cc: Russell King (Oracle), vkoul, neil.armstrong, krzk+dt, conor+dt,
	ciprianmarian.costea, s32, p.zabel, ghennadi.procopciuc,
	Ionut.Vicovan, linux-phy, devicetree, linux-kernel,
	linux-arm-kernel, netdev, horms, Frank.li
In-Reply-To: <CAKfTPtAAmwjwSJ_5kfARaOns-g5tnXdeGM4s2JOy5vnhNTTXYQ@mail.gmail.com>

Hi all,

Just in case I missed something.

On Thu, Feb 5, 2026 at 6:03 PM Vincent Guittot
<vincent.guittot@linaro.org> wrote:
>

Is there a new version of this patchset? I tried applying this one on
top of the current mainline, building it as a module, and I received
different build errors:

ERROR: modpost: missing MODULE_LICENSE() in drivers/net/pcs/pcs-nxp-s32g-xpcs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in
drivers/net/pcs/pcs-nxp-s32g-xpcs.o
ERROR: modpost: "s32g_xpcs_init"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_init_plls"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_pre_pcie_2g5"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_vreset"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_wait_vreset"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_reset_rx"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_disable_an"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!

Thanks,
 Enric

> On Wed, 4 Feb 2026 at 16:29, Russell King (Oracle)
> <linux@armlinux.org.uk> wrote:
> >
> > Sorry, I don't have time to finish this review, nor cut down the context
> > as I normally would do... I'm being bothered on company Slack, which now
> > has the really bloody annoying feature of popping up a window rather than
> > using KDE's notification subsystem, and that steals keyboard focus away
> > from whatever one is trying to do at the time.
> >
> > On Tue, Feb 03, 2026 at 05:19:16PM +0100, Vincent Guittot wrote:
> > > +static bool s32g_xpcs_poll_timeout(struct s32g_xpcs *xpcs, xpcs_poll_func_t func,
> > > +                                ktime_t timeout)
> > > +{
> > > +     ktime_t cur = ktime_get();
> > > +
> > > +     return func(xpcs) || ktime_after(cur, timeout);
> > > +}
> > > +
> > > +static int s32g_xpcs_wait(struct s32g_xpcs *xpcs, xpcs_poll_func_t func)
> > > +{
> > > +     ktime_t timeout = ktime_add_ms(ktime_get(), XPCS_TIMEOUT_MS);
> > > +
> > > +     spin_until_cond(s32g_xpcs_poll_timeout(xpcs, func, timeout));
> > > +     if (!func(xpcs))
> > > +             return -ETIMEDOUT;
> >
> > XPCS_TIMEOUT_MS is 300ms. spin_until_cond() spins until the condition is
> > true. Do you need to tie up this CPU for up to 300ms? That seems
> > excessive. What is the reason that read_poll_timeout() or similar
> > couldn't be used?
>
> This needs additional tests because some instabilities have been
> reported when using read_poll_timeout in some places
>
> >
> > The advantage of read_poll_timeout() is that it will correctly handle
> > the timeout vs condition being satisfied witout need for special code.
> >
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int s32g_xpcs_wait_bits(struct s32g_xpcs *xpcs, unsigned int reg,
> > > +                            unsigned int mask, unsigned int bits)
> > > +{
> > > +     ktime_t cur;
> > > +     ktime_t timeout = ktime_add_ms(ktime_get(), XPCS_TIMEOUT_MS);
> > > +
> > > +     spin_until_cond((cur = ktime_get(),
> > > +                      (s32g_xpcs_read(xpcs, reg) & mask) == bits ||
> > > +                      ktime_after(cur, timeout)));
> > > +     if ((s32g_xpcs_read(xpcs, reg) & mask) != bits)
> > > +             return -ETIMEDOUT;
> >
> > Same here:
> >
> >         return read_poll_timeout(s32g_xpcs_read, val, (val & mask) == bits,
> >                                  0, XPCS_TIMEOUT_MS, false,
> >                                  xpcs, reg);
> >
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static unsigned int s32g_xpcs_digital_status(struct s32g_xpcs *xpcs)
> > > +{
> > > +     return s32g_xpcs_read(xpcs, VR_MII_DIG_STS);
> > > +}
> > > +
> > > +static int s32g_xpcs_wait_power_good_state(struct s32g_xpcs *xpcs)
> > > +{
> > > +     unsigned int val;
> > > +
> > > +     return read_poll_timeout(s32g_xpcs_digital_status, val,
> > > +                              FIELD_GET(PSEQ_STATE_MASK, val) == POWER_GOOD_STATE,
> > > +                              0,
> > > +                              XPCS_TIMEOUT_MS, false, xpcs);
> >
> > This could be:
> >         return read_poll_timeout(s32g_xpcs_read, val,
> >                                  FIELD_GET(PSEQ_STATE_MASK, val) == POWER_GOOD_STATE,
> >                                  0, XPCS_TIMEOUT_MS, false,
> >                                  xpcs, VR_MII_DIG_STS);
> >
> > eliminating the need for s32g_xpcs_digital_status().
>
> fair enough
>
> >
> > > +}
> > > +
> > > +void s32g_xpcs_vreset(struct s32g_xpcs *xpcs)
> > > +{
> > > +     /* Step 19 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, VR_RST, VR_RST);
> > > +}
> > > +
> > > +static bool s32g_xpcs_is_not_in_reset(struct s32g_xpcs *xpcs)
> > > +{
> > > +     unsigned int val;
> > > +
> > > +     val = s32g_xpcs_read(xpcs, VR_MII_DIG_CTRL1);
> > > +
> > > +     return !(val & VR_RST);
> > > +}
> > > +
> > > +int s32g_xpcs_wait_vreset(struct s32g_xpcs *xpcs)
> > > +{
> > > +     int ret;
> > > +
> > > +     /* Step 20 */
> > > +     ret = s32g_xpcs_wait(xpcs, s32g_xpcs_is_not_in_reset);
> > > +     if (ret)
> > > +             dev_err(xpcs->dev, "XPCS%d is in reset\n", xpcs->id);
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +int s32g_xpcs_reset_rx(struct s32g_xpcs *xpcs)
> > > +{
> > > +     int ret = 0;
> > > +
> > > +     ret = s32g_xpcs_wait_power_good_state(xpcs);
> > > +     if (ret) {
> > > +             dev_err(xpcs->dev, "Failed to enter in PGOOD state after vendor reset\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     /* Step 21 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_RX_GENCTRL1,
> > > +                          RX_RST_0, RX_RST_0);
> > > +
> > > +     /* Step 22 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_RX_GENCTRL1,
> > > +                          RX_RST_0, 0);
> > > +
> > > +     /* Step 23 */
> > > +     /* Wait until SR_MII_STS[LINK_STS] = 1 */
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +static int s32g_xpcs_ref_clk_sel(struct s32g_xpcs *xpcs,
> > > +                              enum s32g_xpcs_pll ref_pll)
> > > +{
> > > +     switch (ref_pll) {
> > > +     case XPCS_PLLA:
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLL_CMN_CTRL,
> > > +                                  MPLLB_SEL_0, 0);
> > > +             xpcs->ref = XPCS_PLLA;
> > > +             break;
> > > +     case XPCS_PLLB:
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLL_CMN_CTRL,
> > > +                                  MPLLB_SEL_0, MPLLB_SEL_0);
> > > +             xpcs->ref = XPCS_PLLB;
> > > +             break;
> > > +     default:
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static void s32g_xpcs_electrical_configure(struct s32g_xpcs *xpcs)
> > > +{
> > > +     /* Step 2 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_EQ_CTRL0,
> > > +                          TX_EQ_MAIN_MASK, FIELD_PREP(TX_EQ_MAIN_MASK, 0xC));
> >
> > Prefer hex numbers to be lower case.
>
> ok
>
> >
> > > +
> > > +     /* Step 3 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_CONSUMER_10G_TX_TERM_CTRL,
> > > +                          TX0_TERM_MASK, FIELD_PREP(TX0_TERM_MASK, 0x4));
> > > +}
> > > +
> > > +static int s32g_xpcs_vco_cfg(struct s32g_xpcs *xpcs, enum s32g_xpcs_pll vco_pll)
> > > +{
> > > +     unsigned int vco_ld = 0;
> > > +     unsigned int vco_ref = 0;
> > > +     unsigned int rx_baud = 0;
> > > +     unsigned int tx_baud = 0;
> > > +
> > > +     switch (vco_pll) {
> > > +     case XPCS_PLLA:
> > > +             if (xpcs->mhz125) {
> > > +                     vco_ld = FIELD_PREP(VCO_LD_VAL_0_MASK, 1360);
> > > +                     vco_ref = FIELD_PREP(VCO_REF_LD_0_MASK, 17);
> > > +             } else {
> > > +                     vco_ld = FIELD_PREP(VCO_LD_VAL_0_MASK, 1350);
> > > +                     vco_ref = FIELD_PREP(VCO_REF_LD_0_MASK, 27);
> > > +             }
> > > +
> > > +             rx_baud = FIELD_PREP(RX0_RATE_MASK, RX0_BAUD_DIV_8);
> > > +             tx_baud = FIELD_PREP(TX0_RATE_MASK, TX0_BAUD_DIV_4);
> > > +             break;
> > > +     case XPCS_PLLB:
> > > +             if (xpcs->mhz125) {
> > > +                     vco_ld = FIELD_PREP(VCO_LD_VAL_0_MASK, 1350);
> > > +                     vco_ref = FIELD_PREP(VCO_REF_LD_0_MASK, 27);
> > > +             } else {
> > > +                     vco_ld = FIELD_PREP(VCO_LD_VAL_0_MASK, 1344);
> > > +                     vco_ref = FIELD_PREP(VCO_REF_LD_0_MASK, 43);
> > > +             }
> > > +
> > > +             rx_baud = FIELD_PREP(RX0_RATE_MASK, RX0_BAUD_DIV_2);
> > > +             tx_baud = FIELD_PREP(TX0_RATE_MASK, TX0_BAUD_DIV_1);
> > > +             break;
> > > +     default:
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_VCO_CAL_LD0,
> > > +                          VCO_LD_VAL_0_MASK, vco_ld);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_VCO_CAL_REF0,
> > > +                          VCO_REF_LD_0_MASK, vco_ref);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_RATE_CTRL,
> > > +                          TX0_RATE_MASK, tx_baud);
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_RX_RATE_CTRL,
> > > +                          RX0_RATE_MASK, rx_baud);
> > > +
> > > +     if (vco_pll == XPCS_PLLB) {
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_CDR_CTRL,
> > > +                                  VCO_LOW_FREQ_0, VCO_LOW_FREQ_0);
> > > +     } else {
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_CDR_CTRL,
> > > +                                  VCO_LOW_FREQ_0, 0);
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int s32g_xpcs_init_mplla(struct s32g_xpcs *xpcs)
> > > +{
> > > +     unsigned int val;
> > > +
> > > +     if (!xpcs)
> > > +             return -EINVAL;
> > > +
> > > +     /* Step 7 */
> > > +     val = 0;
> > > +     if (xpcs->ext_clk)
> > > +             val |= REF_USE_PAD;
> > > +
> > > +     if (xpcs->mhz125) {
> > > +             val |= REF_MPLLA_DIV2;
> > > +             val |= REF_CLK_DIV2;
> > > +             val |= FIELD_PREP(REF_RANGE_MASK, RANGE_52_78_MHZ);
> > > +     } else {
> > > +             val |= FIELD_PREP(REF_RANGE_MASK, RANGE_26_53_MHZ);
> > > +     }
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_REF_CLK_CTRL,
> > > +                          REF_MPLLA_DIV2 | REF_USE_PAD | REF_RANGE_MASK |
> > > +                          REF_CLK_DIV2, val);
> > > +
> > > +     /* Step 8 */
> > > +     if (xpcs->mhz125)
> > > +             val = FIELD_PREP(MLLA_MULTIPLIER_MASK, 80);
> > > +     else
> > > +             val = FIELD_PREP(MLLA_MULTIPLIER_MASK, 25);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLLA_CTRL0,
> > > +                          MPLLA_CAL_DISABLE | MLLA_MULTIPLIER_MASK,
> > > +                          val);
> > > +
> > > +     /* Step 9 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_MPLLA_CTRL1,
> > > +                          MPLLA_FRACN_CTRL_MASK, 0);
> > > +
> > > +     /* Step 10 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLLA_CTRL2,
> > > +                          MPLLA_TX_CLK_DIV_MASK | MPLLA_DIV10_CLK_EN,
> > > +                          FIELD_PREP(MPLLA_TX_CLK_DIV_MASK, 1) | MPLLA_DIV10_CLK_EN);
> > > +
> > > +     /* Step 11 */
> > > +     if (xpcs->mhz125)
> > > +             val = FIELD_PREP(MPLLA_BANDWIDTH_MASK, 43);
> > > +     else
> > > +             val = FIELD_PREP(MPLLA_BANDWIDTH_MASK, 357);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_MPLLA_CTRL3,
> > > +                          MPLLA_BANDWIDTH_MASK, val);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int s32g_xpcs_init_mpllb(struct s32g_xpcs *xpcs)
> > > +{
> > > +     unsigned int val;
> > > +
> > > +     if (!xpcs)
> > > +             return -EINVAL;
> > > +
> > > +     /* Step 7 */
> > > +     val = 0;
> > > +     if (xpcs->ext_clk)
> > > +             val |= REF_USE_PAD;
> > > +
> > > +     if (xpcs->mhz125) {
> > > +             val |= REF_MPLLB_DIV2;
> > > +             val |= REF_CLK_DIV2;
> > > +             val |= FIELD_PREP(REF_RANGE_MASK, RANGE_52_78_MHZ);
> > > +     } else {
> > > +             val |= FIELD_PREP(REF_RANGE_MASK, RANGE_26_53_MHZ);
> > > +     }
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_REF_CLK_CTRL,
> > > +                          REF_MPLLB_DIV2 | REF_USE_PAD | REF_RANGE_MASK |
> > > +                          REF_CLK_DIV2, val);
> > > +
> > > +     /* Step 8 */
> > > +     if (xpcs->mhz125)
> > > +             val = 125 << MLLB_MULTIPLIER_OFF;
> > > +     else
> > > +             val = 39 << MLLB_MULTIPLIER_OFF;
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLLB_CTRL0,
> > > +                          MPLLB_CAL_DISABLE | MLLB_MULTIPLIER_MASK,
> > > +                          val);
> > > +
> > > +     /* Step 9 */
> > > +     if (xpcs->mhz125)
> > > +             val = FIELD_PREP(MPLLB_FRACN_CTRL_MASK, 0);
> > > +     else
> > > +             val = FIELD_PREP(MPLLB_FRACN_CTRL_MASK, 1044);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_MPLLB_CTRL1,
> > > +                          MPLLB_FRACN_CTRL_MASK, val);
> > > +
> > > +     /* Step 10 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLLB_CTRL2,
> > > +                          MPLLB_TX_CLK_DIV_MASK | MPLLB_DIV10_CLK_EN,
> > > +                          FIELD_PREP(MPLLB_TX_CLK_DIV_MASK, 5) | MPLLB_DIV10_CLK_EN);
> > > +
> > > +     /* Step 11 */
> > > +     if (xpcs->mhz125)
> > > +             val = FIELD_PREP(MPLLB_BANDWIDTH_MASK, 68);
> > > +     else
> > > +             val = FIELD_PREP(MPLLB_BANDWIDTH_MASK, 102);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_MPLLB_CTRL3,
> > > +                          MPLLB_BANDWIDTH_MASK, val);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static void s32g_serdes_pma_high_freq_recovery(struct s32g_xpcs *xpcs)
> > > +{
> > > +     /* PCS signal protection, PLL railout recovery */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_DBG_CTRL, SUPPRESS_LOS_DET | RX_DT_EN_CTL,
> > > +                          SUPPRESS_LOS_DET | RX_DT_EN_CTL);
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MISC_CTRL0,
> > > +                          PLL_CTRL, PLL_CTRL);
> > > +}
> > > +
> > > +static void s32g_serdes_pma_configure_tx_eq_post(struct s32g_xpcs *xpcs)
> > > +{
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_EQ_CTRL1,
> > > +                          TX_EQ_OVR_RIDE, TX_EQ_OVR_RIDE);
> > > +}
> > > +
> > > +static int s32g_serdes_bifurcation_pll_transit(struct s32g_xpcs *xpcs,
> > > +                                            enum s32g_xpcs_pll target_pll)
> > > +{
> > > +     int ret = 0;
> > > +     struct device *dev = xpcs->dev;
> > > +
> > > +     /* Configure XPCS speed and VCO */
> > > +     if (target_pll == XPCS_PLLA) {
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, EN_2_5G_MODE, 0);
> > > +             s32g_xpcs_vco_cfg(xpcs, XPCS_PLLA);
> > > +     } else {
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1,
> > > +                                  EN_2_5G_MODE, EN_2_5G_MODE);
> > > +             s32g_xpcs_vco_cfg(xpcs, XPCS_PLLB);
> > > +     }
> >
> > I am really not happy with this driver being
> > PHY_INTERFACE_MODE_SGMII-only but supporting running that at 2.5Gbps.
> > In the kernel, PHY_INTERFACE_MODE_SGMII is strictly _Cisco_ SGMII only,
> > which means the version of it clocked at 1.25GHz, not 3.125GHz.
> >
> > OCSGMII or whatever random name you call it tends to be only supported
> > without inband AN, and we have pushed everyone to adopt
> > PHY_INTERFACE_MODE_2500BASEX for that. Please do the same.
> >
> > Should this SerDes be connected to a SFP cage, it will need to support
> > dynamically switching between Cisco SGMII and 2500BASE-X.
>
> okay, this needs to be checked with SoC Team
>
> >
> > > +
> > > +     /* Signal that clock are not available */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_GENCTRL1,
> > > +                          TX_CLK_RDY_0, 0);
> > > +
> > > +     /* Select PLL reference */
> > > +     if (target_pll == XPCS_PLLA)
> > > +             s32g_xpcs_ref_clk_sel(xpcs, XPCS_PLLA);
> > > +     else
> > > +             s32g_xpcs_ref_clk_sel(xpcs, XPCS_PLLB);
> > > +
> > > +     /* Initiate transmitter TX reconfiguration request */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_GENCTRL2,
> > > +                          TX_REQ_0, TX_REQ_0);
> > > +
> > > +     /* Wait for transmitter to reconfigure */
> > > +     ret = s32g_xpcs_wait_bits(xpcs, VR_MII_GEN5_12G_16G_TX_GENCTRL2,
> > > +                               TX_REQ_0, 0);
> > > +     if (ret) {
> > > +             dev_err(dev, "Switch to TX_REQ_0 failed\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     /* Initiate transmitter RX reconfiguration request */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_RX_GENCTRL2,
> > > +                          RX_REQ_0, RX_REQ_0);
> > > +
> > > +     /* Wait for receiver to reconfigure */
> > > +     ret = s32g_xpcs_wait_bits(xpcs, VR_MII_GEN5_12G_16G_RX_GENCTRL2,
> > > +                               RX_REQ_0, 0);
> > > +     if (ret) {
> > > +             dev_err(dev, "Switch to RX_REQ_0 failed\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     /* Signal that clock are available */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_GENCTRL1,
> > > +                          TX_CLK_RDY_0, TX_CLK_RDY_0);
> > > +
> > > +     /* Flush internal logic */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, INIT, INIT);
> > > +
> > > +     /* Wait for init */
> > > +     ret = s32g_xpcs_wait_bits(xpcs, VR_MII_DIG_CTRL1, INIT, 0);
> > > +     if (ret) {
> > > +             dev_err(dev, "XPCS INIT failed\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +/*
> > > + * phylink_pcs_ops
> > > + */
> > > +
> > > +static unsigned int s32cc_phylink_pcs_inband_caps(struct phylink_pcs *pcs,
> > > +                                               phy_interface_t interface)
> > > +{
> > > +     switch (interface) {
> > > +     case PHY_INTERFACE_MODE_SGMII:
> > > +             return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
> > > +
> > > +     default:
> > > +             return 0;
> > > +     }
> > > +}
> > > +
> > > +static int s32cc_phylink_pcs_config(struct phylink_pcs *pcs,
> > > +                                 unsigned int neg_mode,
> > > +                                 phy_interface_t interface,
> > > +                                 const unsigned long *advertising,
> > > +                                 bool permit_pause_to_mac)
> > > +{
> > > +     struct s32g_xpcs *xpcs = phylink_pcs_to_s32g_xpcs(pcs);
> > > +
> > > +     /* Step 1: Disable SGMII AN */
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, AN_ENABLE, 0);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL,
> > > +                          MII_AN_INTR_EN,
> > > +                          0);
> > > +
> > > +     if (!(neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED))
> > > +             return 0;
> > > +
> > > +     /* Step 2  */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL,
> > > +                          PCS_MODE_MASK,
> > > +                          FIELD_PREP(PCS_MODE_MASK, PCS_MODE_SGMII));
> > > +
> > > +     /* Step 3 */
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL,
> > > +                          SS13 | SS6,
> > > +                          SS6);
> > > +
> > > +     /* Step 4  */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL,
> > > +                          MII_CTRL,
> > > +                          0);
> > > +     /* Step 5 and 8 */
> > > +     if (xpcs->pcie_shared == PCIE_XPCS_2G5) {
> > > +             s32g_xpcs_write(xpcs, VR_MII_LINK_TIMER_CTRL, 0x2faf);
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1,
> > > +                                  MAC_AUTO_SW, MAC_AUTO_SW);
> > > +     } else {
> > > +             s32g_xpcs_write(xpcs, VR_MII_LINK_TIMER_CTRL, 0x7a1);
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, MAC_AUTO_SW, 0);
> > > +     }
> > > +
> > > +     /* Step 6 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1,
> > > +                          CL37_TMR_OVRRIDE, CL37_TMR_OVRRIDE);
> > > +
> > > +     /* Step 7 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL,
> > > +                          MII_AN_INTR_EN,
> > > +                          MII_AN_INTR_EN);
> > > +
> > > +     /* Step 9: Enable SGMII AN */
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, AN_ENABLE, AN_ENABLE);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static void s32cc_phylink_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
> > > +                                     struct phylink_link_state *state)
> > > +{
> > > +     struct s32g_xpcs *xpcs = phylink_pcs_to_s32g_xpcs(pcs);
> > > +     bool ss6, ss13, an_enabled;
> > > +     struct device *dev = xpcs->dev;
> > > +     unsigned int val, ss;
> > > +
> > > +     an_enabled = (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED);
> > > +
> > > +     if (an_enabled) {
> > > +             state->link = 0;
> > > +             val = s32g_xpcs_read(xpcs, VR_MII_AN_INTR_STS);
> > > +
> > > +             /* Interrupt is raised with each SGMII AN that is in cases
> > > +              * Link down - Every SGMII link timer expire
> > > +              * Link up - Once before link goes up
> > > +              * So either linkup or raised interrupt mean AN was completed
> > > +              */
> > > +             if ((val & CL37_ANCMPLT_INTR) || (val & CL37_ANSGM_STS_LINK)) {
> > > +                     state->an_complete = 1;
> > > +                     if (val & CL37_ANSGM_STS_LINK)
> > > +                             state->link = 1;
> > > +                     else
> > > +                             return;
> > > +                     if (val & CL37_ANSGM_STS_DUPLEX)
> > > +                             state->duplex = DUPLEX_FULL;
> > > +                     else
> > > +                             state->duplex = DUPLEX_HALF;
> > > +                     ss = FIELD_GET(CL37_ANSGM_STS_SPEED_MASK, val);
> > > +             } else {
> > > +                     return;
> > > +             }
> > > +
> > > +     } else {
> > > +             val = s32g_xpcs_read(xpcs, SR_MII_STS);
> > > +             state->link = !!(val & LINK_STS);
> > > +             state->an_complete = 0;
> > > +             state->pause = MLO_PAUSE_NONE;
> > > +
> > > +             val = s32g_xpcs_read(xpcs, SR_MII_CTRL);
> > > +             if (val & DUPLEX_MODE)
> > > +                     state->duplex = DUPLEX_FULL;
> > > +             else
> > > +                     state->duplex = DUPLEX_HALF;
> > > +
> > > +             /*
> > > +              * Build similar value as CL37_ANSGM_STS_SPEED with
> > > +              * SS6 and SS13 of SR_MII_CTRL:
> > > +              *   - 0 for 10 Mbps
> > > +              *   - 1 for 100 Mbps
> > > +              *   - 2 for 1000 Mbps
> > > +              */
> > > +             ss6 = !!(val & SS6);
> > > +             ss13 = !!(val & SS13);
> > > +             ss = ss6 << 1 | ss13;
> > > +     }
> > > +
> > > +     switch (ss) {
> > > +     case CL37_ANSGM_10MBPS:
> > > +             state->speed = SPEED_10;
> > > +             break;
> > > +     case CL37_ANSGM_100MBPS:
> > > +             state->speed = SPEED_100;
> > > +             break;
> > > +     case CL37_ANSGM_1000MBPS:
> > > +             state->speed = SPEED_1000;
> > > +             break;
> > > +     default:
> > > +             dev_err(dev, "Failed to interpret the value of SR_MII_CTRL\n");
> > > +             break;
> > > +     }
> > > +
> > > +     val = s32g_xpcs_read(xpcs, VR_MII_DIG_CTRL1);
> > > +     if ((val & EN_2_5G_MODE) && state->speed == SPEED_1000)
> > > +             state->speed = SPEED_2500;
> > > +
> > > +     /* Cover SGMII AN inability to distigunish between 1G and 2.5G */
> > > +     if ((val & EN_2_5G_MODE) &&
> > > +         state->speed != SPEED_2500 && an_enabled) {
> > > +             dev_err(dev, "Speed not supported in SGMII AN mode\n");
> > > +     }
> > > +}
> > > +
> > > +static void s32cc_phylink_pcs_link_up(struct phylink_pcs *pcs,
> > > +                                   unsigned int neg_mode,
> > > +                                   phy_interface_t interface, int speed,
> > > +                                   int duplex)
> > > +{
> > > +     struct s32g_xpcs *xpcs = phylink_pcs_to_s32g_xpcs(pcs);
> > > +     struct device *dev = xpcs->dev;
> > > +     bool an_enabled = (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED);
> > > +     unsigned int val;
> > > +     int ret;
> > > +
> > > +     dev_dbg(dev, "xpcs_%d: speed=%u duplex=%d an=%d\n", xpcs->id,
> > > +             speed, duplex, an_enabled);
> > > +
> > > +     if (an_enabled)
> > > +             return;
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, AN_ENABLE, 0);
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL, MII_AN_INTR_EN, 0);
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL, MII_CTRL, 0);
> >
> > Haven't you already disabled AN in .pcs_config() ? This method doesn't
> > change the AN enable state, the only time that happens is when
> > .pcs_config() will be called. All other cases of passing neg_mode are
> > merely informational.
>
> Fair enough, this is probably not needed anymore with the changes in .pcs_config
>
> >
> > > +
> > > +     if (duplex == DUPLEX_FULL)
> > > +             val = DUPLEX_MODE;
> > > +     else
> > > +             val = 0;
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, DUPLEX_MODE, val);
> > > +
> > > +     switch (speed) {
> > > +     case SPEED_10:
> > > +             val = 0;
> > > +             break;
> > > +     case SPEED_100:
> > > +             val = SS13;
> > > +             break;
> > > +     case SPEED_1000:
> > > +             val = SS6;
> > > +             break;
> > > +     case SPEED_2500:
> > > +             val = SS6;
> > > +             break;
> > > +     default:
> > > +             dev_err(dev, "Speed not supported\n");
> > > +             break;
> > > +     }
> > > +
> > > +     if (speed == SPEED_2500) {
> > > +             ret = s32g_serdes_bifurcation_pll_transit(xpcs, XPCS_PLLB);
> > > +             if (ret)
> > > +                     dev_err(dev, "Switch to PLLB failed\n");
> > > +     } else {
> > > +             ret = s32g_serdes_bifurcation_pll_transit(xpcs, XPCS_PLLA);
> > > +             if (ret)
> > > +                     dev_err(dev, "Switch to PLLA failed\n");
> > > +     }
> >
> > This is a protocol transition, and isn't something that can be handled
> > here. Cisco SGMII (PHY_INTERFACE_MODE_SGMII) does not support 2500Mbps
> > and phylink will not allow it.
> >
> > See my comments for s32g_serdes_bifurcation_pll_transit().
> >
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, SS6 | SS13, val);
> > > +}
> > > +
> > > +static const struct phylink_pcs_ops s32cc_phylink_pcs_ops = {
> > > +     .pcs_inband_caps = s32cc_phylink_pcs_inband_caps,
> > > +     .pcs_get_state = s32cc_phylink_pcs_get_state,
> > > +     .pcs_config = s32cc_phylink_pcs_config,
> > > +     .pcs_link_up = s32cc_phylink_pcs_link_up,
> > > +};
> > > +
> > > +/*
> > > + * Serdes functions for initializing/configuring/releasing the xpcs
> > > + */
> > > +
> > > +int s32g_xpcs_pre_pcie_2g5(struct s32g_xpcs *xpcs)
> > > +{
> > > +     int ret;
> > > +
> > > +     /* Enable voltage boost */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_GENCTRL1, VBOOST_EN_0,
> > > +                          VBOOST_EN_0);
> > > +
> > > +     /* TX rate baud  */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_RATE_CTRL, 0x7, 0x0U);
> > > +
> > > +     /* Rx rate baud/2 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_RX_RATE_CTRL, 0x3U, 0x1U);
> > > +
> > > +     /* Set low-frequency operating band */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_CDR_CTRL, CDR_SSC_EN_0,
> > > +                          VCO_LOW_FREQ_0);
> > > +
> > > +     ret = s32g_serdes_bifurcation_pll_transit(xpcs, XPCS_PLLB);
> > > +     if (ret)
> > > +             dev_err(xpcs->dev, "Switch to PLLB failed\n");
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +int s32g_xpcs_init_plls(struct s32g_xpcs *xpcs)
> > > +{
> > > +     int ret;
> > > +     struct device *dev = xpcs->dev;
> > > +
> > > +     if (!xpcs->ext_clk) {
> > > +             /* Step 1 */
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, BYP_PWRUP, BYP_PWRUP);
> > > +     } else if (xpcs->pcie_shared == NOT_SHARED) {
> > > +             ret = s32g_xpcs_wait_power_good_state(xpcs);
> > > +             if (ret)
> > > +                     return ret;
> > > +     } else if (xpcs->pcie_shared == PCIE_XPCS_2G5) {
> > > +             ret = s32g_xpcs_wait_power_good_state(xpcs);
> > > +             if (ret)
> > > +                     return ret;
> > > +             /* Configure equalization */
> > > +             s32g_serdes_pma_configure_tx_eq_post(xpcs);
> > > +             s32g_xpcs_electrical_configure(xpcs);
> > > +
> > > +             /* Enable receiver recover */
> > > +             s32g_serdes_pma_high_freq_recovery(xpcs);
> > > +             return 0;
> > > +     }
> > > +
> > > +     s32g_xpcs_electrical_configure(xpcs);
> > > +
> > > +     s32g_xpcs_ref_clk_sel(xpcs, XPCS_PLLA);
> > > +     ret = s32g_xpcs_init_mplla(xpcs);
> > > +     if (ret) {
> > > +             dev_err(dev, "Failed to initialize PLLA\n");
> > > +             return ret;
> > > +     }
> > > +     ret = s32g_xpcs_init_mpllb(xpcs);
> > > +     if (ret) {
> > > +             dev_err(dev, "Failed to initialize PLLB\n");
> > > +             return ret;
> > > +     }
> > > +     s32g_xpcs_vco_cfg(xpcs, XPCS_PLLA);
> > > +
> > > +     /* Step 18 */
> > > +     if (!xpcs->ext_clk)
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, BYP_PWRUP, 0);
> > > +
> > > +     /* Will be cleared by Step 19 Vreset */
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, AN_ENABLE, 0);
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, DUPLEX_MODE, DUPLEX_MODE);
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +void s32g_xpcs_disable_an(struct s32g_xpcs *xpcs)
> > > +{
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, DUPLEX_MODE, DUPLEX_MODE);
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, AN_ENABLE, 0);
> > > +}
> >
> > Sorry, but why? You should never override phylink's requests.
>
> Serdes sometimes needs to be reset and the AN is enabled by default
> after the reset and even before pcs_config has been called. This is
> called during the inti of serdes after an ip reset.
> That being said this might not be needed anymore after the change in
> pcs_config that disables AN
>
>
> >
> > > +
> > > +int s32g_xpcs_init(struct s32g_xpcs *xpcs, struct device *dev,
> > > +                unsigned char id, void __iomem *base, bool ext_clk,
> > > +                unsigned long rate, enum s32g_xpcs_shared pcie_shared)
> > > +{
> > > +     struct regmap_config conf;
> > > +
> > > +     if (rate != (125 * HZ_PER_MHZ) && rate != (100 * HZ_PER_MHZ)) {
> > > +             dev_err(dev, "XPCS cannot operate @%lu HZ\n", rate);
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     xpcs->base = base;
> > > +     xpcs->ext_clk = ext_clk;
> > > +     xpcs->id = id;
> > > +     xpcs->dev = dev;
> > > +     xpcs->pcie_shared = pcie_shared;
> > > +
> > > +     if (rate == (125 * HZ_PER_MHZ))
> > > +             xpcs->mhz125 = true;
> > > +     else
> > > +             xpcs->mhz125 = false;
> > > +
> > > +     conf = s32g_xpcs_regmap_config;
> > > +
> > > +     if (!id)
> > > +             conf.name = "xpcs0";
> > > +     else
> > > +             conf.name = "xpcs1";
> > > +
> > > +     xpcs->regmap = devm_regmap_init(dev, NULL, xpcs, &conf);
> > > +     if (IS_ERR(xpcs->regmap))
> > > +             return dev_err_probe(dev, PTR_ERR(xpcs->regmap),
> > > +                                  "Failed to init register amp\n");
> > > +
> > > +     /* Phylink PCS */
> > > +     xpcs->pcs.ops = &s32cc_phylink_pcs_ops;
> > > +     xpcs->pcs.poll = true;
> > > +     __set_bit(PHY_INTERFACE_MODE_SGMII, xpcs->pcs.supported_interfaces);
> > > +
> > > +     return 0;
> > > +}
> > > diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
> > > index 45184a3cdd69..bb7f59897faf 100644
> > > --- a/drivers/phy/freescale/Kconfig
> > > +++ b/drivers/phy/freescale/Kconfig
> > > @@ -66,6 +66,7 @@ config PHY_S32G_SERDES
> > >       tristate "NXP S32G SERDES support"
> > >       depends on ARCH_S32 || COMPILE_TEST
> > >       select GENERIC_PHY
> > > +     select REGMAP
> > >       help
> > >         This option enables support for S23G SerDes PHY used for
> > >         PCIe & Ethernet
> > > diff --git a/drivers/phy/freescale/phy-nxp-s32g-serdes.c b/drivers/phy/freescale/phy-nxp-s32g-serdes.c
> > > index 321a80c02be5..f2f7eb5aa327 100644
> > > --- a/drivers/phy/freescale/phy-nxp-s32g-serdes.c
> > > +++ b/drivers/phy/freescale/phy-nxp-s32g-serdes.c
> > > @@ -12,12 +12,14 @@
> > >  #include <linux/module.h>
> > >  #include <linux/of_platform.h>
> > >  #include <linux/of_address.h>
> > > +#include <linux/pcs/pcs-nxp-s32g-xpcs.h>
> > >  #include <linux/phy/phy.h>
> > >  #include <linux/platform_device.h>
> > >  #include <linux/processor.h>
> > >  #include <linux/reset.h>
> > >  #include <linux/units.h>
> > >
> > > +#define S32G_SERDES_XPCS_MAX                 2
> > >  #define S32G_SERDES_MODE_MAX                 5
> > >
> > >  #define EXTERNAL_CLK_NAME                    "ext"
> > > @@ -32,6 +34,52 @@
> > >  #define S32G_PCIE_PHY_MPLLA_CTRL             0x10
> > >  #define  MPLL_STATE                          BIT(30)
> > >
> > > +#define S32G_PCIE_PHY_MPLLB_CTRL             0x14
> > > +#define  MPLLB_SSC_EN                                BIT(1)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_CTRL_SEL           0x18
> > > +#define  EXT_PHY_CTRL_SEL                    BIT(0)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_BS_CTRL            0x1C
> > > +#define  EXT_BS_TX_LOWSWING                  BIT(6)
> > > +#define  EXT_BS_RX_BIGSWING                  BIT(5)
> > > +#define  EXT_BS_RX_LEVEL_MASK                        GENMASK(4, 0)
> > > +
> > > +#define S32G_PCIE_PHY_REF_CLK_CTRL           0x20
> > > +#define  EXT_REF_RANGE_MASK                  GENMASK(5, 3)
> > > +#define  REF_CLK_DIV2_EN                     BIT(2)
> > > +#define  REF_CLK_MPLLB_DIV2_EN                       BIT(1)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MPLLA_CTRL_1               0x30
> > > +#define  EXT_MPLLA_BANDWIDTH_MASK            GENMASK(15, 0)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MPLLB_CTRL_1               0x40
> > > +#define  EXT_MPLLB_DIV_MULTIPLIER_MASK               GENMASK(31, 24)
> > > +#define  EXT_MPLLB_DIV_CLK_EN                        BIT(19)
> > > +#define  EXT_MPLLB_DIV8_CLK_EN                       BIT(18)
> > > +#define  EXT_MPLLB_DIV10_CLK_EN                      BIT(16)
> > > +#define  EXT_MPLLB_BANDWIDTH_MASK            GENMASK(15, 0)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MPLLB_CTRL_2               0x44
> > > +#define  EXT_MPLLB_FRACN_CTRL_MASK           GENMASK(22, 12)
> > > +#define  MPLLB_MULTIPLIER_MASK                       GENMASK(8, 0)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MPLLB_CTRL_3               0x48
> > > +#define  EXT_MPLLB_WORD_DIV2_EN                      BIT(31)
> > > +#define  EXT_MPLLB_TX_CLK_DIV_MASK           GENMASK(30, 28)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MISC_CTRL_1                0xA0
> > > +#define  EXT_RX_LOS_THRESHOLD_MASK           GENMASK(7, 1)
> > > +#define  EXT_RX_VREF_CTRL_MASK                       GENMASK(28, 24)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MISC_CTRL_2                0xA4
> > > +#define  EXT_TX_VBOOST_LVL_MASK                      GENMASK(18, 16)
> > > +#define  EXT_TX_TERM_CTRL_MASK                       GENMASK(26, 24)
> > > +
> > > +#define S32G_PCIE_PHY_XPCS1_RX_OVRD_CTRL     0xD0
> > > +#define  XPCS1_RX_VCO_LD_VAL_MASK            GENMASK(28, 16)
> > > +#define  XPCS1_RX_REF_LD_VAL_MASK            GENMASK(14, 8)
> > > +
> > >  #define S32G_SS_RW_REG_0                     0xF0
> > >  #define  SUBMODE_MASK                                GENMASK(3, 0)
> > >  #define  CLKEN_MASK                          BIT(23)
> > > @@ -44,6 +92,9 @@
> > >
> > >  #define S32G_PHY_REG_DATA                    0x4
> > >
> > > +#define S32G_PHY_RST_CTRL                    0x8
> > > +#define  WARM_RST                            BIT(1)
> > > +
> > >  #define RAWLANE0_DIG_PCS_XF_RX_EQ_DELTA_IQ_OVRD_IN   0x3019
> > >  #define RAWLANE1_DIG_PCS_XF_RX_EQ_DELTA_IQ_OVRD_IN   0x3119
> > >
> > > @@ -76,16 +127,33 @@ struct s32g_pcie_ctrl {
> > >       bool powered_on;
> > >  };
> > >
> > > +struct s32g_xpcs_ctrl {
> > > +     struct s32g_xpcs *phys[2];
> > > +     void __iomem *base0, *base1;
> > > +};
> > > +
> > >  struct s32g_serdes {
> > >       struct s32g_serdes_ctrl ctrl;
> > >       struct s32g_pcie_ctrl pcie;
> > > +     struct s32g_xpcs_ctrl xpcs;
> > >       struct device *dev;
> > > +     u8 lanes_status;
> > >  };
> > >
> > >  /* PCIe phy subsystem */
> > >
> > >  #define S32G_SERDES_PCIE_FREQ                        (100 * HZ_PER_MHZ)
> > >
> > > +static void s32g_pcie_phy_reset(struct s32g_serdes *serdes)
> > > +{
> > > +     u32 val;
> > > +
> > > +     val = readl(serdes->pcie.phy_base + S32G_PHY_RST_CTRL);
> > > +     writel(val | WARM_RST, serdes->pcie.phy_base + S32G_PHY_RST_CTRL);
> > > +     usleep_range(1000, 1100);
> > > +     writel(val, serdes->pcie.phy_base + S32G_PHY_RST_CTRL);
> > > +}
> > > +
> > >  static int s32g_pcie_check_clk(struct s32g_serdes *serdes)
> > >  {
> > >       struct s32g_serdes_ctrl *sctrl = &serdes->ctrl;
> > > @@ -277,6 +345,192 @@ static struct phy *s32g_serdes_phy_xlate(struct device *dev,
> > >       return phy;
> > >  }
> > >
> > > +/* XPCS subsystem */
> > > +
> > > +static int s32g_serdes_xpcs_init(struct s32g_serdes *serdes, int id)
> > > +{
> > > +     struct s32g_serdes_ctrl *ctrl = &serdes->ctrl;
> > > +     struct s32g_xpcs_ctrl *xpcs = &serdes->xpcs;
> > > +     enum s32g_xpcs_shared shared = NOT_SHARED;
> > > +     unsigned long rate = ctrl->ref_clk_rate;
> > > +     struct device *dev = serdes->dev;
> > > +     void __iomem *base;
> > > +
> > > +     if (!id)
> > > +             base = xpcs->base0;
> > > +     else
> > > +             base = xpcs->base1;
> > > +
> > > +     if (ctrl->ss_mode == 1 || ctrl->ss_mode == 2)
> > > +             shared = PCIE_XPCS_1G;
> > > +     else if (ctrl->ss_mode == 5)
> > > +             shared = PCIE_XPCS_2G5;
> > > +
> > > +     return s32g_xpcs_init(xpcs->phys[id], dev, id, base,
> > > +                            ctrl->ext_clk, rate, shared);
> > > +}
> > > +
> > > +static void s32g_serdes_prepare_pma_mode5(struct s32g_serdes *serdes)
> > > +{
> > > +     u32 val;
> > > +     /* Configure TX_VBOOST_LVL and TX_TERM_CTRL */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MISC_CTRL_2);
> > > +     val &= ~(EXT_TX_VBOOST_LVL_MASK | EXT_TX_TERM_CTRL_MASK);
> > > +     val |= FIELD_PREP(EXT_TX_VBOOST_LVL_MASK, 0x3) |
> > > +             FIELD_PREP(EXT_TX_TERM_CTRL_MASK, 0x4);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MISC_CTRL_2);
> > > +
> > > +     /* Enable phy external control */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_CTRL_SEL);
> > > +     val |= EXT_PHY_CTRL_SEL;
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_CTRL_SEL);
> > > +
> > > +     /* Configure ref range, disable PLLB/ref div2 */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_REF_CLK_CTRL);
> > > +     val &= ~(REF_CLK_DIV2_EN | REF_CLK_MPLLB_DIV2_EN | EXT_REF_RANGE_MASK);
> > > +     val |= FIELD_PREP(EXT_REF_RANGE_MASK, 0x3);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_REF_CLK_CTRL);
> > > +
> > > +     /* Configure multiplier */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_2);
> > > +     val &= ~(MPLLB_MULTIPLIER_MASK | EXT_MPLLB_FRACN_CTRL_MASK | BIT(24) | BIT(28));
> > > +     val |= FIELD_PREP(MPLLB_MULTIPLIER_MASK, 0x27U) |
> > > +             FIELD_PREP(EXT_MPLLB_FRACN_CTRL_MASK, 0x414);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_2);
> > > +
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_MPLLB_CTRL);
> > > +     val &= ~MPLLB_SSC_EN;
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_MPLLB_CTRL);
> > > +
> > > +     /* Configure tx lane division, disable word clock div2*/
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_3);
> > > +     val &= ~(EXT_MPLLB_WORD_DIV2_EN | EXT_MPLLB_TX_CLK_DIV_MASK);
> > > +     val |= FIELD_PREP(EXT_MPLLB_TX_CLK_DIV_MASK, 0x5);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_3);
> > > +
> > > +     /* Configure bandwidth for filtering and div10*/
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_1);
> > > +     val &= ~(EXT_MPLLB_BANDWIDTH_MASK | EXT_MPLLB_DIV_CLK_EN |
> > > +              EXT_MPLLB_DIV8_CLK_EN | EXT_MPLLB_DIV_MULTIPLIER_MASK);
> > > +     val |= FIELD_PREP(EXT_MPLLB_BANDWIDTH_MASK, 0x5f) | EXT_MPLLB_DIV10_CLK_EN;
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_1);
> > > +
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLA_CTRL_1);
> > > +     val &= ~(EXT_MPLLA_BANDWIDTH_MASK);
> > > +     val |= FIELD_PREP(EXT_MPLLA_BANDWIDTH_MASK, 0xc5);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLA_CTRL_1);
> > > +
> > > +     /* Configure VCO */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_XPCS1_RX_OVRD_CTRL);
> > > +     val &= ~(XPCS1_RX_VCO_LD_VAL_MASK | XPCS1_RX_REF_LD_VAL_MASK);
> > > +     val |= FIELD_PREP(XPCS1_RX_VCO_LD_VAL_MASK, 0x540) |
> > > +             FIELD_PREP(XPCS1_RX_REF_LD_VAL_MASK, 0x2b);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_XPCS1_RX_OVRD_CTRL);
> > > +
> > > +     /* Boundary scan control */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_BS_CTRL);
> > > +     val &= ~(EXT_BS_RX_LEVEL_MASK | EXT_BS_TX_LOWSWING);
> > > +     val |= FIELD_PREP(EXT_BS_RX_LEVEL_MASK, 0xB) | EXT_BS_RX_BIGSWING;
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_BS_CTRL);
> > > +
> > > +     /* Rx loss threshold */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MISC_CTRL_1);
> > > +     val &= ~(EXT_RX_LOS_THRESHOLD_MASK | EXT_RX_VREF_CTRL_MASK);
> > > +     val |= FIELD_PREP(EXT_RX_LOS_THRESHOLD_MASK, 0x3U) |
> > > +             FIELD_PREP(EXT_RX_VREF_CTRL_MASK, 0x11U);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MISC_CTRL_1);
> > > +}
> > > +
> > > +static int s32g_serdes_enable_mode5(struct s32g_serdes *serdes, struct s32g_xpcs *xpcs)
> > > +{
> > > +     int ret;
> > > +
> > > +     s32g_serdes_prepare_pma_mode5(serdes);
> > > +
> > > +     ret = s32g_xpcs_pre_pcie_2g5(xpcs);
> > > +     if (ret) {
> > > +             dev_err(serdes->dev,
> > > +                     "Failed to prepare SerDes for PCIE & XPCS @ 2G5 mode\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     s32g_pcie_phy_reset(serdes);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int s32g_serdes_init_clks(struct s32g_serdes *serdes)
> > > +{
> > > +     struct s32g_serdes_ctrl *ctrl = &serdes->ctrl;
> > > +     struct s32g_xpcs_ctrl *xpcs = &serdes->xpcs;
> > > +     struct s32g_xpcs *order[2];
> > > +     size_t i;
> > > +     int ret;
> > > +
> > > +     switch (ctrl->ss_mode) {
> > > +     case 0:
> > > +             return 0;
> > > +     case 1:
> > > +             order[0] = xpcs->phys[0];
> > > +             order[1] = NULL;
> > > +             break;
> > > +     case 2:
> > > +     case 5:
> > > +             order[0] = xpcs->phys[1];
> > > +             order[1] = NULL;
> > > +             break;
> > > +     case 3:
> > > +             order[0] = xpcs->phys[1];
> > > +             order[1] = xpcs->phys[0];
> > > +             break;
> > > +     case 4:
> > > +             order[0] = xpcs->phys[0];
> > > +             order[1] = xpcs->phys[1];
> > > +             break;
> > > +     default:
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     for (i = 0; i < ARRAY_SIZE(order); i++) {
> > > +             if (!order[i])
> > > +                     continue;
> > > +
> > > +             ret = s32g_xpcs_init_plls(order[i]);
> > > +             if (ret)
> > > +                     return ret;
> > > +     }
> > > +
> > > +     for (i = 0; i < ARRAY_SIZE(order); i++) {
> > > +             if (!order[i])
> > > +                     continue;
> > > +
> > > +             if (ctrl->ss_mode == 5) {
> > > +                     ret = s32g_serdes_enable_mode5(serdes, order[i]);
> > > +                     if (ret)
> > > +                             return ret;
> > > +             } else {
> > > +                     s32g_xpcs_vreset(order[i]);
> > > +             }
> > > +     }
> > > +
> > > +     for (i = 0; i < ARRAY_SIZE(order); i++) {
> > > +             if (!order[i])
> > > +                     continue;
> > > +
> > > +             ret = s32g_xpcs_wait_vreset(order[i]);
> > > +             if (ret)
> > > +                     return ret;
> > > +
> > > +             ret = s32g_xpcs_reset_rx(order[i]);
> > > +             if (ret)
> > > +                     return ret;
> > > +
> > > +             s32g_xpcs_disable_an(order[i]);
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > >  /* Serdes subsystem */
> > >
> > >  static int s32g_serdes_assert_reset(struct s32g_serdes *serdes)
> > > @@ -331,6 +585,10 @@ static int s32g_serdes_init(struct s32g_serdes *serdes)
> > >               return ret;
> > >       }
> > >
> > > +     /*
> > > +      * We have a tight timing for the init sequence and any delay linked to
> > > +      * printk as an example can fail the init after reset
> > > +      */
> > >       ret = s32g_serdes_assert_reset(serdes);
> > >       if (ret)
> > >               goto disable_clks;
> > > @@ -363,7 +621,13 @@ static int s32g_serdes_init(struct s32g_serdes *serdes)
> > >       dev_info(serdes->dev, "Using mode %d for SerDes subsystem\n",
> > >                ctrl->ss_mode);
> > >
> > > -     return 0;
> > > +     ret = s32g_serdes_init_clks(serdes);
> > > +     if (ret) {
> > > +             dev_err(serdes->dev, "XPCS init failed\n");
> > > +             goto disable_clks;
> > > +     }
> > > +
> > > +     return ret;
> > >
> > >  disable_clks:
> > >       clk_bulk_disable_unprepare(serdes->ctrl.nclks,
> > > @@ -449,12 +713,32 @@ static int s32g_serdes_get_pcie_resources(struct platform_device *pdev, struct s
> > >       return 0;
> > >  }
> > >
> > > +static int s32g_serdes_get_xpcs_resources(struct platform_device *pdev, struct s32g_serdes *serdes)
> > > +{
> > > +     struct s32g_xpcs_ctrl *xpcs = &serdes->xpcs;
> > > +     struct device *dev = &pdev->dev;
> > > +
> > > +     xpcs->base0 = devm_platform_ioremap_resource_byname(pdev, "xpcs0");
> > > +     if (IS_ERR(xpcs->base0)) {
> > > +             dev_err(dev, "Failed to map 'xpcs0'\n");
> > > +             return PTR_ERR(xpcs->base0);
> > > +     }
> > > +
> > > +     xpcs->base1 = devm_platform_ioremap_resource_byname(pdev, "xpcs1");
> > > +     if (IS_ERR(xpcs->base1)) {
> > > +             dev_err(dev, "Failed to map 'xpcs1'\n");
> > > +             return PTR_ERR(xpcs->base1);
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > >  static int s32g2_serdes_create_phy(struct s32g_serdes *serdes, struct device_node *child_node)
> > >  {
> > >       struct s32g_serdes_ctrl *ctrl = &serdes->ctrl;
> > >       struct phy_provider *phy_provider;
> > >       struct device *dev = serdes->dev;
> > > -     int ss_mode = ctrl->ss_mode;
> > > +     int ret, ss_mode = ctrl->ss_mode;
> > >       struct phy *phy;
> > >
> > >       if (of_device_is_compatible(child_node, "nxp,s32g2-serdes-pcie-phy")) {
> > > @@ -476,6 +760,37 @@ static int s32g2_serdes_create_phy(struct s32g_serdes *serdes, struct device_nod
> > >               if (IS_ERR(phy_provider))
> > >                       return PTR_ERR(phy_provider);
> > >
> > > +     } else if (of_device_is_compatible(child_node, "nxp,s32g2-serdes-xpcs")) {
> > > +             struct s32g_xpcs_ctrl *xpcs_ctrl = &serdes->xpcs;
> > > +             struct s32g_xpcs *xpcs;
> > > +             int port;
> > > +
> > > +             /* no Ethernet phy lane */
> > > +             if (ss_mode == 0)
> > > +                     return 0;
> > > +
> > > +             /* Get XPCS port number connected to the lane */
> > > +             if (of_property_read_u32(child_node, "reg", &port))
> > > +                     return -EINVAL;
> > > +
> > > +             /* XPCS1 is not used */
> > > +             if (ss_mode == 1 && port == 1)
> > > +                     return -EINVAL;
> > > +
> > > +             /* XPCS0 is not used */
> > > +             if (ss_mode == 2 && port == 0)
> > > +                     return -EINVAL;
> > > +
> > > +             xpcs = devm_kmalloc(dev, sizeof(*xpcs), GFP_KERNEL);
> > > +             if (!xpcs)
> > > +                     return -ENOMEM;
> > > +
> > > +             xpcs_ctrl->phys[port] = xpcs;
> > > +
> > > +             ret = s32g_serdes_xpcs_init(serdes, port);
> > > +             if (ret)
> > > +                     return ret;
> > > +
> > >       } else {
> > >               dev_warn(dev, "Skipping unknown child node %pOFn\n", child_node);
> > >       }
> > > @@ -517,6 +832,10 @@ static int s32g_serdes_probe(struct platform_device *pdev)
> > >       if (ret)
> > >               return ret;
> > >
> > > +     ret = s32g_serdes_get_xpcs_resources(pdev, serdes);
> > > +     if (ret)
> > > +             return ret;
> > > +
> > >       ret = s32g_serdes_parse_lanes(dev, serdes);
> > >       if (ret)
> > >               return ret;
> > > @@ -555,6 +874,57 @@ static int __maybe_unused s32g_serdes_resume(struct device *device)
> > >       return ret;
> > >  }
> > >
> > > +struct phylink_pcs *s32g_serdes_pcs_create(struct device *dev, struct device_node *np)
> > > +{
> > > +     struct platform_device *pdev;
> > > +     struct device_node *pcs_np;
> > > +     struct s32g_serdes *serdes;
> > > +     u32 port;
> > > +
> > > +     if (of_property_read_u32(np, "reg", &port))
> > > +             return ERR_PTR(-EINVAL);
> > > +
> > > +     if (port >= S32G_SERDES_XPCS_MAX)
> > > +             return ERR_PTR(-EINVAL);
> > > +
> > > +     /* The PCS pdev is attached to the parent node */
> > > +     pcs_np = of_get_parent(np);
> > > +     if (!pcs_np)
> > > +             return ERR_PTR(-ENODEV);
> > > +
> > > +     if (!of_device_is_available(pcs_np)) {
> > > +             of_node_put(pcs_np);
> > > +             return ERR_PTR(-ENODEV);
> > > +     }
> > > +
> > > +     pdev = of_find_device_by_node(pcs_np);
> > > +     of_node_put(pcs_np);
> > > +     if (!pdev)
> > > +             return ERR_PTR(-EPROBE_DEFER);
> > > +
> > > +     serdes = platform_get_drvdata(pdev);
> > > +     if (!serdes) {
> > > +             put_device(&pdev->dev);
> > > +             return ERR_PTR(-EPROBE_DEFER);
> > > +     }
> > > +
> > > +     if (!serdes->xpcs.phys[port]) {
> > > +             put_device(&pdev->dev);
> > > +             return ERR_PTR(-EPROBE_DEFER);
> > > +     }
> > > +
> > > +     return &serdes->xpcs.phys[port]->pcs;
> > > +}
> > > +EXPORT_SYMBOL(s32g_serdes_pcs_create);
> > > +
> > > +void s32g_serdes_pcs_destroy(struct phylink_pcs *pcs)
> > > +{
> > > +     struct s32g_xpcs *xpcs = phylink_pcs_to_s32g_xpcs(pcs);
> > > +
> > > +     put_device(xpcs->dev);
> > > +}
> > > +EXPORT_SYMBOL(s32g_serdes_pcs_destroy);
> > > +
> > >  static const struct of_device_id s32g_serdes_match[] = {
> > >       {
> > >               .compatible = "nxp,s32g2-serdes",
> > > diff --git a/include/linux/pcs/pcs-nxp-s32g-xpcs.h b/include/linux/pcs/pcs-nxp-s32g-xpcs.h
> > > new file mode 100644
> > > index 000000000000..96a0049b93a6
> > > --- /dev/null
> > > +++ b/include/linux/pcs/pcs-nxp-s32g-xpcs.h
> > > @@ -0,0 +1,50 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +/**
> > > + * Copyright 2021-2026 NXP
> > > + */
> > > +#ifndef PCS_NXP_S32G_XPCS_H
> > > +#define PCS_NXP_S32G_XPCS_H
> > > +
> > > +#include <linux/phylink.h>
> > > +
> > > +enum s32g_xpcs_shared {
> > > +     NOT_SHARED,
> > > +     PCIE_XPCS_1G,
> > > +     PCIE_XPCS_2G5,
> > > +};
> > > +
> > > +enum s32g_xpcs_pll {
> > > +     XPCS_PLLA,      /* Slow PLL */
> > > +     XPCS_PLLB,      /* Fast PLL */
> > > +};
> > > +
> > > +struct s32g_xpcs {
> > > +     void __iomem *base;
> > > +     struct device *dev;
> > > +     unsigned char id;
> > > +     struct regmap *regmap;
> > > +     enum s32g_xpcs_pll ref;
> > > +     bool ext_clk;
> > > +     bool mhz125;
> > > +     enum s32g_xpcs_shared pcie_shared;
> > > +     struct phylink_pcs pcs;
> > > +};
> > > +
> > > +#define phylink_pcs_to_s32g_xpcs(pl_pcs) \
> > > +     container_of((pl_pcs), struct s32g_xpcs, pcs)
> > > +
> > > +int s32g_xpcs_init(struct s32g_xpcs *xpcs, struct device *dev,
> > > +                unsigned char id, void __iomem *base, bool ext_clk,
> > > +                unsigned long rate, enum s32g_xpcs_shared pcie_shared);
> > > +int s32g_xpcs_init_plls(struct s32g_xpcs *xpcs);
> > > +int s32g_xpcs_pre_pcie_2g5(struct s32g_xpcs *xpcs);
> > > +void s32g_xpcs_vreset(struct s32g_xpcs *xpcs);
> > > +int s32g_xpcs_wait_vreset(struct s32g_xpcs *xpcs);
> > > +int s32g_xpcs_reset_rx(struct s32g_xpcs *xpcs);
> > > +void s32g_xpcs_disable_an(struct s32g_xpcs *xpcs);
> > > +
> > > +struct phylink_pcs *s32g_serdes_pcs_create(struct device *dev, struct device_node *np);
> > > +void s32g_serdes_pcs_destroy(struct phylink_pcs *pcs);
> > > +
> > > +#endif /* PCS_NXP_S32G_XPCS_H */
> > > +
> > > --
> > > 2.43.0
> > >
> > >
> >
> >
> > --
> > RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> > FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
>



^ permalink raw reply

* Re: [PATCH RFC 05/12] usb: hub: Power on connected M.2 E-key connectors
From: Chen-Yu Tsai @ 2026-05-18  9:13 UTC (permalink / raw)
  To: Alan Stern
  Cc: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, linux-pm, linux-usb, devicetree,
	linux-mediatek, linux-arm-kernel, linux-kernel,
	Manivannan Sadhasivam
In-Reply-To: <41260a6d-46fa-4a45-9906-e1bc5e5dd83a@rowland.harvard.edu>

On Fri, May 15, 2026 at 10:39 PM Alan Stern <stern@rowland.harvard.edu> wrote:
>
> On Fri, May 15, 2026 at 05:01:41PM +0800, Chen-Yu Tsai wrote:
> > diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> > index 90ea597d42ae..4165f71e212b 100644
> > --- a/drivers/usb/core/hub.c
> > +++ b/drivers/usb/core/hub.c
> > @@ -31,7 +31,9 @@
> >  #include <linux/minmax.h>
> >  #include <linux/mutex.h>
> >  #include <linux/random.h>
> > +#include <linux/of_graph.h>
> >  #include <linux/pm_qos.h>
> > +#include <linux/pwrseq/consumer.h>
> >  #include <linux/kobject.h>
> >
> >  #include <linux/bitfield.h>
> > @@ -888,13 +890,25 @@ int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
> >  {
> >       int ret;
> >
> > +     if (set)
> > +             ret = pwrseq_power_on(hub->ports[port1 - 1]->pwrseq);
> > +     else
> > +             ret = pwrseq_power_off(hub->ports[port1 - 1]->pwrseq);
> > +     if (ret)
> > +             return ret;
> > +
> >       if (set)
> >               ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
> >       else
> >               ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
> >
> > -     if (ret)
> > +     if (ret) {
> > +             if (set)
> > +                     pwrseq_power_off(hub->ports[port1 - 1]->pwrseq);
> > +             else
> > +                     pwrseq_power_on(hub->ports[port1 - 1]->pwrseq);
> >               return ret;
> > +     }
> >
> >       if (set)
> >               set_bit(port1, hub->power_bits);
> > @@ -1867,6 +1881,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
> >       struct usb_host_interface *desc;
> >       struct usb_device *hdev;
> >       struct usb_hub *hub;
> > +     int ret;
> >
> >       desc = intf->cur_altsetting;
> >       hdev = interface_to_usbdev(intf);
>
> This change is totally useless.  Didn't you get a warning from the
> compiler when you built it?

Apologies. This should have been part of the previous patch.

> > diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
> > index 9ebc5ef54a32..6039e5f5dcd7 100644
> > --- a/drivers/usb/core/hub.h
> > +++ b/drivers/usb/core/hub.h
> > @@ -85,6 +85,7 @@ struct usb_hub {
> >   * @port_owner: port's owner
> >   * @peer: related usb2 and usb3 ports (share the same connector)
> >   * @connector: USB Type-C connector
> > + * @pwrseq: power sequencing descriptor for the port
> >   * @req: default pm qos request for hubs without port power control
> >   * @connect_type: port's connect type
> >   * @state: device state of the usb device attached to the port
> > @@ -104,6 +105,7 @@ struct usb_port {
> >       struct usb_dev_state *port_owner;
> >       struct usb_port *peer;
> >       struct typec_connector *connector;
> > +     struct pwrseq_desc *pwrseq;
> >       struct dev_pm_qos_request *req;
> >       enum usb_port_connect_type connect_type;
> >       enum usb_device_state state;
>
> The fact that hub.h uses struct pwrseq_desc indicates that it ought to
> #include <linux/pwrseq/consumer.h>, instead of making the .c files do
> so themselves.  Then you wouldn't have to add the #include lines to
> hub.c and port.c.

I couldn't tell if the existing pattern in this file was to include
the headers or not, as it's missing a whole bunch.

Regardless of whether this header file includes linux/pwrseq/consumer.h
or has a forward declaration or nothing, I think that if the .c files
use the API, then they should include the corresponding header file
directly.

> > diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
> > index b1364f0c384c..2d09037fee93 100644
> > --- a/drivers/usb/core/port.c
> > +++ b/drivers/usb/core/port.c
> > @@ -7,11 +7,14 @@
> >   * Author: Lan Tianyu <tianyu.lan@intel.com>
> >   */
> >
> > +#include <linux/cleanup.h>
>
> Why is this needed?

For the __free() in usb_hub_port_pwrseq_get() below:

    struct device_node *np __free(device_node) = NULL;


Thanks
ChenYu


> >  #include <linux/kstrtox.h>
> >  #include <linux/slab.h>
> >  #include <linux/string_choices.h>
> >  #include <linux/sysfs.h>
> > +#include <linux/of_graph.h>
> >  #include <linux/pm_qos.h>
> > +#include <linux/pwrseq/consumer.h>
> >  #include <linux/component.h>
> >  #include <linux/usb/of.h>
> >
>
> Alan Stern


^ permalink raw reply

* [PATCH v2] firmware: imx: scu-irq: drop wakeup_src sysfs file, log via dev_dbg()
From: Stepan Ionichev @ 2026-05-18  9:39 UTC (permalink / raw)
  To: Frank.Li
  Cc: peng.fan, s.hauer, kernel, festevam, shawnguo, gregkh, hcazarim,
	imx, linux-arm-kernel, linux-kernel, sozdayvek
In-Reply-To: <20260515175002.34853-1-sozdayvek@gmail.com>

wakeup_source_show() walks all IMX_SC_IRQ_NUM_GROUP groups and
rewrites buf from offset 0 each iteration, so userspace reading
/sys/firmware/scu_wakeup_source/wakeup_src only ever sees the last
group reported, and the trailing strlen(buf) reports only that
line length. sprintf() is also unbounded against the sysfs
PAGE_SIZE buffer.

The attribute is not documented under Documentation/ABI/ and a code
search across GitHub and Debian found no out-of-tree consumers.
Peng Fan (NXP) confirmed it is safe to drop.

Remove the attribute, the supporting kobject and the per-group
valid/wakeup_src state used only to feed it. Log the same wakeup
information via dev_dbg() from imx_scu_irq_work_handler() so it
can be enabled dynamically when needed.

Fixes: c081197a33a2 ("firmware: imx: scu-irq: support identifying SCU wakeup source from sysfs")
Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/all/2026051656-corral-edgy-290c@gregkh/
Signed-off-by: Stepan Ionichev <sozdayvek@gmail.com>
---
v2:
- Drop the sysfs file entirely instead of patching it (Greg)
- Log wakeup info via dev_dbg() in the IRQ work handler (Greg)
- Peng Fan (NXP) confirmed no out-of-tree consumers

v1: https://lore.kernel.org/all/20260515175002.34853-1-sozdayvek@gmail.com/

 drivers/firmware/imx/imx-scu-irq.c | 84 ++++++------------------------
 1 file changed, 16 insertions(+), 68 deletions(-)

diff --git a/drivers/firmware/imx/imx-scu-irq.c b/drivers/firmware/imx/imx-scu-irq.c
index a68d38f89..5969460ba 100644
--- a/drivers/firmware/imx/imx-scu-irq.c
+++ b/drivers/firmware/imx/imx-scu-irq.c
@@ -9,11 +9,9 @@
 #include <dt-bindings/firmware/imx/rsrc.h>
 #include <linux/firmware/imx/ipc.h>
 #include <linux/firmware/imx/sci.h>
-#include <linux/kobject.h>
 #include <linux/mailbox_client.h>
 #include <linux/of.h>
 #include <linux/suspend.h>
-#include <linux/sysfs.h>
 
 #define IMX_SC_IRQ_FUNC_ENABLE	1
 #define IMX_SC_IRQ_FUNC_STATUS	2
@@ -43,19 +41,8 @@ struct imx_sc_msg_irq_enable {
 	u8 enable;
 } __packed;
 
-struct scu_wakeup {
-	u32 mask;
-	u32 wakeup_src;
-	bool valid;
-};
-
-/* Sysfs functions */
-static struct kobject *wakeup_obj;
-static ssize_t wakeup_source_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
-static struct kobj_attribute wakeup_source_attr =
-		__ATTR(wakeup_src, 0660, wakeup_source_show, NULL);
-
-static struct scu_wakeup scu_irq_wakeup[IMX_SC_IRQ_NUM_GROUP];
+static u32 scu_irq_wakeup_mask[IMX_SC_IRQ_NUM_GROUP];
+static struct device *imx_sc_irq_dev;
 
 static struct imx_sc_ipc *imx_sc_irq_ipc_handle;
 static struct work_struct imx_sc_irq_work;
@@ -88,11 +75,6 @@ static void imx_scu_irq_work_handler(struct work_struct *work)
 	u8 i;
 
 	for (i = 0; i < IMX_SC_IRQ_NUM_GROUP; i++) {
-		if (scu_irq_wakeup[i].mask) {
-			scu_irq_wakeup[i].valid = false;
-			scu_irq_wakeup[i].wakeup_src = 0;
-		}
-
 		ret = imx_scu_irq_get_status(i, &irq_status);
 		if (ret) {
 			pr_err("get irq group %d status failed, ret %d\n",
@@ -102,12 +84,15 @@ static void imx_scu_irq_work_handler(struct work_struct *work)
 
 		if (!irq_status)
 			continue;
-		if (scu_irq_wakeup[i].mask & irq_status) {
-			scu_irq_wakeup[i].valid = true;
-			scu_irq_wakeup[i].wakeup_src = irq_status & scu_irq_wakeup[i].mask;
-		} else {
-			scu_irq_wakeup[i].wakeup_src = irq_status;
-		}
+
+		if (scu_irq_wakeup_mask[i] & irq_status)
+			dev_dbg(imx_sc_irq_dev,
+				"Wakeup source group = %d, irq = 0x%x\n",
+				i, irq_status & scu_irq_wakeup_mask[i]);
+		else
+			dev_dbg(imx_sc_irq_dev,
+				"Spurious SCU wakeup, group = %d, irq = 0x%x\n",
+				i, irq_status);
 
 		pm_system_wakeup();
 		imx_scu_irq_notifier_call_chain(irq_status, &i);
@@ -164,9 +149,9 @@ int imx_scu_irq_group_enable(u8 group, u32 mask, u8 enable)
 			group, mask, ret);
 
 	if (enable)
-		scu_irq_wakeup[group].mask |= mask;
+		scu_irq_wakeup_mask[group] |= mask;
 	else
-		scu_irq_wakeup[group].mask &= ~mask;
+		scu_irq_wakeup_mask[group] &= ~mask;
 
 	return ret;
 }
@@ -177,25 +162,6 @@ static void imx_scu_irq_callback(struct mbox_client *c, void *msg)
 	schedule_work(&imx_sc_irq_work);
 }
 
-static ssize_t wakeup_source_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
-{
-	int i;
-
-	for (i = 0; i < IMX_SC_IRQ_NUM_GROUP; i++) {
-		if (!scu_irq_wakeup[i].wakeup_src)
-			continue;
-
-		if (scu_irq_wakeup[i].valid)
-			sprintf(buf, "Wakeup source group = %d, irq = 0x%x\n",
-				i, scu_irq_wakeup[i].wakeup_src);
-		else
-			sprintf(buf, "Spurious SCU wakeup, group = %d, irq = 0x%x\n",
-				i, scu_irq_wakeup[i].wakeup_src);
-	}
-
-	return strlen(buf);
-}
-
 int imx_scu_enable_general_irq_channel(struct device *dev)
 {
 	struct of_phandle_args spec;
@@ -233,29 +199,11 @@ int imx_scu_enable_general_irq_channel(struct device *dev)
 	if (IS_ERR(ch)) {
 		ret = PTR_ERR(ch);
 		dev_err(dev, "failed to request mbox chan gip3, ret %d\n", ret);
-		goto free_cl;
-	}
-
-	/* Create directory under /sysfs/firmware */
-	wakeup_obj = kobject_create_and_add("scu_wakeup_source", firmware_kobj);
-	if (!wakeup_obj) {
-		ret = -ENOMEM;
-		goto free_ch;
+		devm_kfree(dev, cl);
+		return ret;
 	}
 
-	ret = sysfs_create_file(wakeup_obj, &wakeup_source_attr.attr);
-	if (ret) {
-		dev_err(dev, "Cannot create wakeup source src file......\n");
-		kobject_put(wakeup_obj);
-		goto free_ch;
-	}
+	imx_sc_irq_dev = dev;
 
 	return 0;
-
-free_ch:
-	mbox_free_channel(ch);
-free_cl:
-	devm_kfree(dev, cl);
-
-	return ret;
 }
-- 
2.43.0



^ permalink raw reply related

* Re: [PATCH 0/4] arm64: dts: mediatek: random Chromebook cleanups
From: AngeloGioacchino Del Regno @ 2026-05-18  9:40 UTC (permalink / raw)
  To: Matthias Brugger, Chen-Yu Tsai
  Cc: linux-mediatek, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260514101254.2749300-1-wenst@chromium.org>

On Thu, 14 May 2026 18:12:48 +0800, Chen-Yu Tsai wrote:
> Here are some random DT cleanups that are not directly related to other
> topics I'm working on, but came up when checking for warnings.
> 
> The regulator related changes overlap with my other "Regulator cleanup
> for Chromebooks" series [1].
> 
> Please have a look.
> 
> [...]

Applied to v7.1-next/dts64, thanks!

[1/4] arm64: dts: mediatek: mt8192-asurada: Fix SPI-NOR flash compatible
      commit: 95937cbb6d51e0c6f8ac937bd043fb3b442391ec
[2/4] arm64: dts: mediatek: mt8192-asurada: Add (BT|WIFI)_KILL_1V8_L GPIO line names
      commit: c42235145c52955ab20fcb648bb8c7818f58282b
[3/4] arm64: dts: mediatek: mt8195-cherry: Fix names for EC controlled regulators
      commit: 2066ac078402301d9aa50026dee017182d316eac
[4/4] arm64: dts: mediatek: mt8195-cherry: Sort top level nodes correctly
      commit: 559b8b1524760ad8dc18d52c4415d40ee24d02fc

Cheers,
Angelo




^ permalink raw reply

* RE: [PATCH 2/2] ARM: dts: aspeed: rainiera6: Add Meta Rainiera6 BMC
From: Biju Das @ 2026-05-18  9:45 UTC (permalink / raw)
  To: Neil Cheng, robh@kernel.org, krzk+dt@kernel.org,
	conor+dt@kernel.org, joel@jms.id.au, andrew@codeconstruct.com.au,
	geert+renesas@glider.be, magnus.damm
  Cc: devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <afee3ea3d6d697d039ce97cc7add47e97bbdab4e.1779088499.git.neilcheng0417@gmail.com>

Hi Neil Cheng, 

> -----Original Message-----
> From: Neil Cheng <neilcheng0417@gmail.com>
> Sent: 18 May 2026 09:13
> Subject: [PATCH 2/2] ARM: dts: aspeed: rainiera6: Add Meta Rainiera6 BMC
> 
> [You don't often get email from neilcheng0417@gmail.com. Learn why this is important at
> https://aka.ms/LearnAboutSenderIdentification ]
> 
> Add device tree for the Meta (Facebook) Rainiera6 compute node, based on
> AST2600 BMC.
> 
> Signed-off-by: Neil Cheng <neilcheng0417@gmail.com>
> ---
>  arch/arm/boot/dts/aspeed/Makefile             |    1 +
>  .../aspeed/aspeed-bmc-facebook-rainiera6.dts  | 1012 +++++++++++++++++
>  2 files changed, 1013 insertions(+)
>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-rainiera6.dts
> 
> diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
> index 767f7c7652d5..215429af1135 100644
> --- a/arch/arm/boot/dts/aspeed/Makefile
> +++ b/arch/arm/boot/dts/aspeed/Makefile
> @@ -34,6 +34,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
>         aspeed-bmc-facebook-harma.dtb \
>         aspeed-bmc-facebook-minerva.dtb \
>         aspeed-bmc-facebook-minipack.dtb \
> +       aspeed-bmc-facebook-rainiera6.dtb \
>         aspeed-bmc-facebook-santabarbara.dtb \
>         aspeed-bmc-facebook-tiogapass.dtb \
>         aspeed-bmc-facebook-wedge40.dtb \ diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-
> rainiera6.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-rainiera6.dts
> new file mode 100644
> index 000000000000..2c8c983db677
> --- /dev/null
> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-rainiera6.dts
> @@ -0,0 +1,1012 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright (c) 2026 Facebook Inc.
> +
> +/dts-v1/;
> +#include "aspeed-g6.dtsi"
> +#include <dt-bindings/gpio/aspeed-gpio.h> #include
> +<dt-bindings/i2c/i2c.h>
> +
> +/ {
> +       model = "Facebook Rainier BMC";
> +       compatible = "facebook,rainiera6-bmc", "aspeed,ast2600";
> +
> +       aliases {
> +               i2c16 = &i2c5mux0ch0;
> +               i2c17 = &i2c5mux0ch1;
> +               i2c18 = &i2c5mux1ch0;
> +               i2c19 = &i2c5mux1ch1;
> +               i2c20 = &i2c6mux0ch0;
> +               i2c21 = &i2c6mux0ch1;
> +               i2c22 = &i2c6mux0ch2;
> +               i2c23 = &i2c6mux0ch3;
> +               i2c24 = &i2c8mux0ch0;
> +               i2c25 = &i2c8mux0ch1;
> +               i2c26 = &i2c8mux0ch2;
> +               i2c27 = &i2c8mux0ch3;
> +               i2c28 = &i2c26mux0ch0;
> +               i2c29 = &i2c26mux0ch1;
> +               i2c30 = &i2c26mux0ch2;
> +               i2c31 = &i2c26mux0ch3;
> +               serial0 = &uart1;
> +               serial2 = &uart3;
> +               serial3 = &uart4;
> +               serial4 = &uart5;
> +       };
> +
> +       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 = "power_fault_amber";
> +                       default-state = "off";
> +                       gpios = <&gpio0 ASPEED_GPIO(P, 4) GPIO_ACTIVE_HIGH>;
> +               };
> +       };
> +
> +       memory@80000000 {
> +               device_type = "memory";
> +               reg = <0x80000000 0x80000000>;
> +       };
> +
> +       p1v8_adc_vref: regulator-p1v8-aux {
> +               compatible = "regulator-fixed";
> +               regulator-name = "p1v8_adc_vref";
> +               regulator-min-microvolt = <1800000>;
> +               regulator-max-microvolt = <1800000>;
> +               regulator-always-on;
> +       };
> +
> +       spi_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>;
> +               status = "okay";
> +
> +               tpm@0 {
> +                       compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
> +                       spi-max-frequency = <33000000>;
> +                       reg = <0>;
> +               };
> +       };
> +};
> +
> +&adc0 {
> +       vref-supply = <&p1v8_adc_vref>;
> +       status = "okay";

Maybe status after pinctrl entries to consistent with wdt1 and spi2 below??

Cheers,
Biju

> +       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 {
> +       aspeed,int-vref-microvolt = <2500000>;
> +       status = "okay";
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_adc10_default>; };
> +
> +&ehci0 {
> +       status = "okay";
> +};
> +
> +&ehci1 {
> +       status = "okay";
> +};
> +
> +&fmc {
> +       status = "okay";
> +
> +       flash@0 {
> +               status = "okay";
> +               m25p,fast-read;
> +               label = "bmc";
> +               spi-max-frequency = <50000000>; #include
> +"openbmc-flash-layout-128.dtsi"
> +       };
> +
> +       flash@1 {
> +               status = "okay";
> +               m25p,fast-read;
> +               label = "alt-bmc";
> +               spi-max-frequency = <50000000>;
> +       };
> +};
> +
> +&gpio0 {
> +       gpio-line-names =
> +       /*A0-A7*/       "","","","","","","","",
> +       /*B0-B7*/       "BATTERY_DETECT","","BMC_I2C1_FPGA_ALERT_L","BMC_READY_R",
> +                               "IOEXP_INT_3V3_L_R1","FM_ID_LED","","",
> +       /*C0-C7*/       "BMC_GPIOC0","","","","PMBUS_REQ_N","PSU_FW_UPDATE_REQ_N","",
> +                               "BMC_I2C_SSIF_ALERT_L",
> +       /*D0-D7*/       "","","","","BMC_GPIOD4","","","",
> +       /*E0-E7*/       "BMC_GPIOE0","BMC_GPIOE1","","","","","","",
> +       /*F0-F7*/       "","","","","","","","",
> +       /*G0-G7*/       "FM_BMC_MUX1_SEL_R","","","","","","FM_DEBUG_PORT_PRSNT_R1_N",
> +                       "FM_BMC_DBP_PRESENT_R_N",
> +       /*H0-H7*/       "","","","","","","","",
> +       /*I0-I7*/       "","","","","","FLASH_WP_STATUS_R1","BMC_JTAG_MUX_SEL","",
> +       /*J0-J7*/       "","","","","","","","",
> +       /*K0-K7*/       "","","","","","","","",
> +       /*L0-L7*/       "","","","","","","","",
> +       /*M0-M7*/       "PCIE_EP_RST_EN","BMC_FRU_WP","SCM_HPM_STBY_RST_N",
> +                               "SCM_HPM_STBY_R_EN","STBY_POWER_PG_3V3_R","TH500_SHDN_OK_L","","",
> +       /*N0-N7*/       "LED_POSTCODE_0","LED_POSTCODE_1","LED_POSTCODE_2",
> +                               "LED_POSTCODE_3","LED_POSTCODE_4","LED_POSTCODE_5",
> +                               "LED_POSTCODE_6","LED_POSTCODE_7",
> +       /*O0-O7*/       "RUN_POWER_PG","PWR_BRAKE_L","CHASSIS_AC_LOSS_L",
> +                               "BSM_PRSNT_R_N","PSU_SMB_ALERT_L","FM_TPM_PRSNT_0_N",
> +                               "PSU_FW_UPDATING_N","DEBUG_CARD_BYPASS",
> +       /*P0-P7*/       "PWR_BTN_BMC_R1_N","IPEX_CABLE_PRSNT_L","ID_RST_BTN_BMC_R_N",
> +                               "RST_BMC_RSTBTN_OUT_R_N","BMC_PWR_LED","RUN_POWER_EN",
> +                               "SHDN_FORCE_L","BMC_HEARTBEAT_N",
> +       /*Q0-Q7*/       "IRQ_PCH_TPM_SPI_LV3_N","USB_OC0_REAR_R_N","UART_MUX_SEL",
> +                               "I2C_MUX_RESET_L","RSVD_NV_PLT_DETECT","SPI_TPM_INT_L",
> +                               "CPU_JTAG_MUX_SELECT","THERM_BB_OVERT_L",
> +       /*R0-R7*/       "THERM_BB_WARN_L","SPI_BMC_FPGA_INT_L","CPU_BOOT_DONE",
> +                               "PMBUS_GNT_L","CHASSIS_PWR_BRK_L","PCIE_WAKE_L","PDB_THERM_OVERT_L",
> +                               "SHDN_REQ_L",
> +       /*S0-S7*/       "","","SYS_BMC_PWRBTN_R_N","FM_TPM_PRSNT_1_N",
> +                               "FM_BMC_DEBUG_SW_N","UID_LED_N","SYS_FAULT_LED_N",
> +                               "RUN_POWER_FAULT_L",
> +       /*T0-T7*/       "","","","","","","","",
> +       /*U0-U7*/       "","","","","","","","",
> +       /*V0-V7*/       "L2_RST_REQ_OUT_L","L0L1_RST_REQ_OUT_L","BMC_ID_BEEP_SEL_R1",
> +                               "BMC_I2C0_FPGA_ALERT_L","SMB_BMC_TMP_ALERT","PWR_LED_N",
> +                               "SYS_RST_OUT_L","IRQ_TPM_SPI_N",
> +       /*W0-W7*/       "","","","","","","","",
> +       /*X0-X7*/       "","FM_DBP_CPU_PREQ_GF_N_R1","","","","","","",
> +       /*Y0-Y7*/       "","RST_BMC_SELF_HW_R1","FM_FLASH_LATCH_N_R1","",
> +                               "BMC_GPIOY4_R","BMC_GPIOY5_R","","",
> +       /*Z0-Z7*/       "","","","","","","BMC_GPIOZ6_R","BMC_GPIOZ7_R";
> +};
> +
> +&gpio1 {
> +       gpio-line-names =
> +       /*18A0-18A7*/   "","","","","","","","",
> +       /*18B0-18B7*/   "","","","","FM_BOARD_BMC_REV_ID0","FM_BOARD_BMC_REV_ID1",
> +                       "FM_BOARD_BMC_REV_ID2","",
> +       /*18C0-18C7*/   "","","SPI_BMC_BIOS_ROM_IRQ0_R_N","","","","","",
> +       /*18D0-18D7*/   "","","","","","","","",
> +       /*18E0-18E3*/   "FM_BMC_PROT_LS_EN","AC_PWR_BMC_BTN_R_N","","";
> +};
> +
> +/* Rainiera6 SoC SSIF */
> +&i2c1 {
> +       status = "okay";
> +
> +       ssif_bmc: ssif-bmc@10 {
> +               compatible = "ssif-bmc";
> +               reg = <0x10>;
> +               status = "okay";
> +       };
> +};
> +
> +/* MCIO 2A I2C */
> +&i2c2 {
> +       status = "okay";
> +};
> +
> +&i2c4 {
> +       multi-master;
> +       mctp-controller;
> +       clock-frequency = <400000>;
> +       status = "okay";
> +
> +       mctp@10 {
> +               compatible = "mctp-i2c-controller";
> +               reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
> +       };
> +
> +       /* OCP NIC TEMP */
> +       temperature-sensor@1f {
> +               compatible = "ti,tmp421";
> +               reg = <0x1f>;
> +       };
> +
> +       /* OCP NIC FRU EEPROM */
> +       eeprom@50 {
> +               compatible = "atmel,24c64";
> +               reg = <0x50>;
> +       };
> +};
> +
> +&i2c5 {
> +       status = "okay";
> +
> +       gpio-expander@22 {
> +               compatible = "nxp,pca9535";
> +               reg = <0x22>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "JTAG_BMC_IOEXP_MUX_OE", "JTAG_BMC_MCIO_MUX_S1",
> +                       "JTAG_BMC_MCIO_MUX_S0", "JTAG_IOEXP_BMC_MUX_SEL",
> +                       "FM_USB_MUX_1_OE_N", "FM_USB_MUX_2_OE_N",
> +                       "PROGRAMN_CPLD", "",
> +                       "", "",
> +                       "", "",
> +                       "", "",
> +                       "", "";
> +       };
> +
> +       /* I2C MUX for MCIO 1A */
> +       i2c-mux@70 {
> +               compatible = "nxp,pca9546";
> +               reg = <0x70>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               i2c-mux-idle-disconnect;
> +
> +               i2c5mux0ch0: i2c@0 {
> +                       reg = <0>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               i2c5mux0ch1: i2c@1 {
> +                       reg = <1>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +       };
> +
> +       /* I2C MUX for MCIO 0A */
> +       i2c-mux@77 {
> +               compatible = "nxp,pca9546";
> +               reg = <0x77>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               i2c-mux-idle-disconnect;
> +
> +               i2c5mux1ch0: i2c@0 {
> +                       reg = <0>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               i2c5mux1ch1: i2c@1 {
> +                       reg = <1>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +       };
> +};
> +
> +&i2c6 {
> +       status = "okay";
> +
> +       /* I2C MUX for PWRPIC #13 ~ #16 */
> +       i2c-mux@77 {
> +               compatible = "nxp,pca9546";
> +               reg = <0x77>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               i2c-mux-idle-disconnect;
> +
> +               /* PWRPIC #13 */
> +               i2c6mux0ch0: i2c@0 {
> +                       reg = <0>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               /* PWRPIC #14 */
> +               i2c6mux0ch1: i2c@1 {
> +                       reg = <1>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               /* PWRPIC #16 */
> +               i2c6mux0ch2: i2c@2 {
> +                       reg = <2>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               /* PWRPIC #15 */
> +               i2c6mux0ch3: i2c@3 {
> +                       reg = <3>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +       };
> +};
> +
> +&i2c7 {
> +       multi-master;
> +       status = "okay";
> +
> +       ipmb@10 {
> +               compatible = "ipmb-dev";
> +               reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
> +               i2c-protocol;
> +       };
> +};
> +
> +&i2c8 {
> +       status = "okay";
> +
> +       power-monitor@14 {
> +               compatible = "infineon,xdp710";
> +               reg = <0x14>;
> +       };
> +
> +       adc@1d {
> +               compatible = "ti,adc128d818";
> +               reg = <0x1d>;
> +               ti,mode = /bits/ 8 <1>;
> +       };
> +
> +       /* PDB IOEXP0 */
> +       pdb_io_expander0: gpio-expander@24 {
> +               compatible = "nxp,pca9555";
> +               reg = <0x24>;
> +               interrupt-parent = <&sgpiom0>;
> +               interrupts = <92 IRQ_TYPE_LEVEL_LOW>;
> +               interrupt-controller;
> +               #interrupt-cells = <2>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "FM_P52V_AUX_FLT_N","FM_P12V_AUX_ALERT_N",
> +                       "FM_SLOT1_HSC_FAULT","FM_SLOT2_HSC_FAULT",
> +                       "FM_SLOT3_HSC_FAULT","FM_SLOT4_HSC_FAULT",
> +                       "FM_SLOT5_HSC_FAULT","FM_SLOT6_HSC_FAULT",
> +                       "PRSNT_FAN0","PRSNT_FAN1",
> +                       "PRSNT_FAN2","PRSNT_FAN3",
> +                       "","",
> +                       "","INT_SLOT";
> +       };
> +
> +       /* PDB IOEXP1 */
> +       gpio-expander@25 {
> +               compatible = "nxp,pca9555";
> +               reg = <0x25>;
> +               interrupt-parent = <&pdb_io_expander0>;
> +               interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "SLOT1_CM_UPDATE","SLOT2_CM_UPDATE",
> +                       "SLOT3_CM_UPDATE","SLOT4_CM_UPDATE",
> +                       "SLOT5_CM_UPDATE","SLOT6_CM_UPDATE",
> +                       "","",
> +                       "","",
> +                       "","",
> +                       "","",
> +                       "","";
> +       };
> +
> +       power-sensor@40 {
> +               compatible = "ti,ina238";
> +               reg = <0x40>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       /* PADDLE BD IOEXP */
> +       gpio-expander@41 {
> +               compatible = "nxp,pca9536";
> +               reg = <0x41>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "HSC_OC_GPIO0", "HSC_OC_GPIO1",
> +                       "HSC_OC_GPIO2", "HSC_OC_GPIO3";
> +       };
> +
> +       power-sensor@42 {
> +               compatible = "ti,ina238";
> +               reg = <0x42>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       power-monitor@43 {
> +               compatible = "lltc,ltc4287";
> +               reg = <0x43>;
> +               shunt-resistor-micro-ohms = <100>;
> +       };
> +
> +       power-sensor@44 {
> +               compatible = "ti,ina238";
> +               reg = <0x44>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       power-sensor@45 {
> +               compatible = "ti,ina238";
> +               reg = <0x45>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       power-monitor@46 {
> +               compatible = "mps,mp5998";
> +               reg = <0x46>;
> +       };
> +
> +       power-monitor@47 {
> +               compatible = "ti,tps25990";
> +               reg = <0x47>;
> +               ti,rimon-micro-ohms = <430000000>;
> +       };
> +
> +       temperature-sensor@48 {
> +               compatible = "ti,tmp75";
> +               reg = <0x48>;
> +       };
> +
> +       temperature-sensor@49 {
> +               compatible = "ti,tmp75";
> +               reg = <0x49>;
> +       };
> +
> +       /* PDB FRU */
> +       eeprom@56 {
> +               compatible = "atmel,24c128";
> +               reg = <0x56>;
> +       };
> +
> +       /* Paddle BD FRU */
> +       eeprom@57 {
> +               compatible = "atmel,24c128";
> +               reg = <0x57>;
> +       };
> +
> +       power-monitor@58 {
> +               compatible = "renesas,isl28022";
> +               reg = <0x58>;
> +               shunt-resistor-micro-ohms = <10000>;
> +       };
> +
> +       power-monitor@59 {
> +               compatible = "renesas,isl28022";
> +               reg = <0x59>;
> +               shunt-resistor-micro-ohms = <10000>;
> +       };
> +
> +       power-monitor@5a {
> +               compatible = "renesas,isl28022";
> +               reg = <0x5a>;
> +               shunt-resistor-micro-ohms = <10000>;
> +       };
> +
> +       power-monitor@5b {
> +               compatible = "renesas,isl28022";
> +               reg = <0x5b>;
> +               shunt-resistor-micro-ohms = <10000>;
> +       };
> +
> +       psu@5c {
> +               compatible = "renesas,raa228006";
> +               reg = <0x5c>;
> +       };
> +
> +       fan-controller@5e{
> +               compatible = "maxim,max31790";
> +               reg = <0x5e>;
> +       };
> +
> +       /* I2C MUX for PWRPIC #1, #2, #11, #12 */
> +       i2c-mux@77 {
> +               compatible = "nxp,pca9546";
> +               reg = <0x77>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               i2c-mux-idle-disconnect;
> +
> +               /* PWRPIC #1 */
> +               i2c8mux0ch0: i2c@0 {
> +                       reg = <0>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               /* PWRPIC #2 */
> +               i2c8mux0ch1: i2c@1 {
> +                       reg = <1>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               /* PWRPIC #12 (Connector to CXL BD) */
> +               i2c8mux0ch2: i2c@2 {
> +                       reg = <2>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +                       i2c-mux@70 {
> +                               compatible = "nxp,pca9546";
> +                               reg = <0x70>;
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +                               i2c-mux-idle-disconnect;
> +                               i2c26mux0ch0: i2c@0 {
> +                                       reg = <0>;
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                               };
> +                               i2c26mux0ch1: i2c@1 {
> +                                       reg = <1>;
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                               };
> +                               i2c26mux0ch2: i2c@2 {
> +                                       reg = <2>;
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                                       /* CXL FRU */
> +                                       eeprom@50 {
> +                                               compatible = "atmel,24c64";
> +                                               reg = <0x50>;
> +                                       };
> +                               };
> +                               i2c26mux0ch3: i2c@3 {
> +                                       reg = <3>;
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                               };
> +                       };
> +               };
> +
> +               /* PWRPIC #11 */
> +               i2c8mux0ch3: i2c@3 {
> +                       reg = <3>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +       };
> +};
> +
> +&i2c9 {
> +       status = "okay";
> +
> +       temperature-sensor@4b {
> +               compatible = "ti,tmp75";
> +               reg = <0x4b>;
> +       };
> +
> +       /* SCM FRU */
> +       eeprom@51 {
> +               compatible = "atmel,24c128";
> +               reg = <0x51>;
> +       };
> +
> +       /* BSM FRU */
> +       eeprom@56 {
> +               compatible = "atmel,24c64";
> +               reg = <0x56>;
> +       };
> +};
> +
> +/* MCIO 0A I2C */
> +&i2c10 {
> +       status = "okay";
> +};
> +
> +&i2c11 {
> +       status = "okay";
> +
> +       /* I2C11_IOEXP_3 */
> +       gpio-expander@20 {
> +               compatible = "nxp,pca9535";
> +               reg = <0x20>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "IRQ_INA230_FAN0_ALERT_N_CPLD", "IRQ_INA230_FAN1_ALERT_N_CPLD",
> +                       "IRQ_INA230_FAN2_ALERT_N_CPLD", "IRQ_INA230_FAN3_ALERT_N_CPLD",
> +                       "IRQ_INA230_P12V_DIMM_0_ALERT_N", "IRQ_INA230_P12V_DIMM_1_ALERT_N",
> +                       "IRQ_P3V3_E1S_0_FLT_N", "P12V_E1S_0_FAULT_R_N",
> +                       "IRQ_P3V3_E1S_1_FLT_N", "P12V_E1S_1_FAULT_R_N",
> +                       "IRQ_P3V3_NIC_FLT_N", "P12V_NIC_FAULT_R_N",
> +                       "SMB_SENSOR_ALERT_N", "FW_CPLD_RST_RTC_RST_R1",
> +                       "RTC_CLR", "RTC_U11_ALRT_N";
> +       };
> +
> +       /* I2C11_IOEXP_2 */
> +       gpio-expander@21 {
> +               compatible = "nxp,pca9535";
> +               reg = <0x21>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "FAN_0_PRESENT_CPLD", "FAN_1_PRESENT_CPLD",
> +                       "FAN_2_PRESENT_CPLD", "FAN_3_PRESENT_CPLD",
> +                       "FAN_FAIL_L_CPLD", "FULL_SPEED_N_R_CPLD",
> +                       "P12V_FAN0_PWRGD_CPLD", "P12V_FAN1_PWRGD_CPLD",
> +                       "P12V_FAN2_PWRGD_CPLD", "P12V_FAN3_PWRGD_CPLD",
> +                       "FM_P12V_FAN0_FLTB_N_CPLD", "FM_P12V_FAN1_FLTB_N_CPLD",
> +                       "FM_P12V_FAN2_FLTB_N_CPLD", "FM_P12V_FAN3_FLTB_N_CPLD",
> +                       "P12V_FAN_EN_R_CPLD", "";
> +       };
> +
> +       /* I2C11_IOEXP_1 */
> +       gpio-expander@27 {
> +               compatible = "nxp,pca9535";
> +               reg = <0x27>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "PWRGD_P12V_SCM", "PWRGD_P5V_STBY",
> +                       "PWRGD_P3V3_STBY", "PWRGD_P1V8_STBY",
> +                       "PWRGD_P1V2_STBY", "PWRGD_P1V1_STBY",
> +                       "PWRGD_P1V0_STBY", "",
> +                       "", "",
> +                       "", "",
> +                       "", "",
> +                       "", "";
> +       };
> +
> +       power-sensor@40 {
> +               compatible = "ti,ina230";
> +               reg = <0x40>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       power-sensor@41 {
> +               compatible = "ti,ina230";
> +               reg = <0x41>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       power-sensor@42 {
> +               compatible = "ti,ina230";
> +               reg = <0x42>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@43 {
> +               compatible = "ti,ina230";
> +               reg = <0x43>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@44 {
> +               compatible = "ti,ina230";
> +               reg = <0x44>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@45 {
> +               compatible = "ti,ina230";
> +               reg = <0x45>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       adc@49 {
> +               compatible = "ti,ads7830";
> +               reg = <0x49>;
> +       };
> +
> +       adc@4a {
> +               compatible = "ti,ads7830";
> +               reg = <0x4a>;
> +       };
> +
> +       adc@4b {
> +               compatible = "ti,ads7830";
> +               reg = <0x4b>;
> +       };
> +       rtc@6f {
> +               compatible = "nuvoton,nct3018y";
> +               reg = <0x6f>;
> +               status = "okay";
> +       };
> +};
> +
> +/* MCIO 4A I2C */
> +&i2c12 {
> +       multi-master;
> +       mctp-controller;
> +       clock-frequency = <400000>;
> +       status = "okay";
> +
> +       mctp@10 {
> +               compatible = "mctp-i2c-controller";
> +               reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
> +       };
> +};
> +
> +&i2c13 {
> +       status = "okay";
> +
> +       fan-controller@20 {
> +               compatible = "maxim,max31790";
> +               reg = <0x20>;
> +       };
> +
> +       power-sensor@40 {
> +               compatible = "ti,ina230";
> +               reg = <0x40>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@41 {
> +               compatible = "ti,ina230";
> +               reg = <0x41>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@44 {
> +               compatible = "ti,ina230";
> +               reg = <0x44>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@45 {
> +               compatible = "ti,ina230";
> +               reg = <0x45>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       temperature-sensor@48 {
> +               compatible = "national,lm75b";
> +               reg = <0x48>;
> +       };
> +
> +       temperature-sensor@49 {
> +               compatible = "national,lm75b";
> +               reg = <0x49>;
> +       };
> +
> +       /* MB FRU */
> +       eeprom@51 {
> +               compatible = "atmel,24c128";
> +               reg = <0x51>;
> +       };
> +};
> +
> +/* PROT reserve */
> +&i2c14 {
> +       status = "okay";
> +};
> +
> +/* MCIO 3A I2C */
> +&i2c15 {
> +       status = "okay";
> +};
> +
> +&mac2 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_ncsi3_default>;
> +       use-ncsi;
> +       status = "okay";
> +};
> +
> +&pinctrl {
> +       pinctrl_ncsi3_default: ncsi3_default {
> +               function = "RMII3";
> +               groups = "NCSI3";
> +       };
> +};
> +
> +&sgpiom0 {
> +       status = "okay";
> +       ngpios = <128>;
> +       bus-frequency = <2000000>;
> +       gpio-line-names =
> +       /*"input pin","output pin"*/
> +       "SOC_ERROR_N_CPLD","RST_SOC_SRST_N_CPLD",
> +       "SOC_ELASTOPCLK_N","SOC_BMC_READY_CPLD",
> +       "SOC_LINKSTOP_N","wIBB_BMC_SRST_OUT",
> +       "SOC_POST_COMPLETE_CPLD","I3C_MUX_SEL_DIMM_C0_024",
> +       "SOC_RESETREQ","I3C_MUX_SEL_DIMM_C0_135",
> +       "SOC_SYS_PWRDN_CPLD","I3C_MUX_SEL_DIMM_C1_024",
> +       "SOC_PORQ","I3C_MUX_SEL_DIMM_C1_135",
> +       "SOC_HOT_N_CPLD","BOOT_PWRDIS_CPLD",
> +       // IOB0-IOB7 bit8-15
> +       "PWRGD_V1P8_CPU","HDD0_PERST_N_CPLD",
> +       "PWRGD_V1P26_CPLD","HDD1_PERST_N_CPLD",
> +       "PWRGD_V1P2","MCIO_1A_PWRDIS_R",
> +       "","",
> +       "FM_CONFIG_ID","P3V_BAT_SCALED_EN",
> +       "wALL_POWER_OK","PERST_CEM0_N_CPLD",
> +       "wANDGATE_ALL_POWER_GD","PERST_CEM1_N_CPLD",
> +       "wAC_CYCLE_12V","PERST_PLD_TUSB7340_N",
> +       // IOC0-IOC7 bit16-23
> +       "wAC_CYCLE_54V","FM_USB_MUX_SEL_CPLD",
> +       "FM_PLD_CLKS_DEV_EN","SMB_BOOT_RST_N_CPLD",
> +       "PWRGD_P1V2_STBY","SMB_MCIO_0A_RST_R_N",
> +       "wIBB_BMC_SRST","RST_SMB_NIC_R_N",
> +       "PWRGD_P12V_E1S_0","FM_PPS_NIC_IN_BUF_OE_N_R",
> +       "PWRGD_P12V_E1S_1","FM_BUF_PPS_NIC_IN_EN_CPLD",
> +       "","FM_NIC_PPS_IN_OE_CPLD",
> +       "PWRGD_P12V_NIC","FM_PPS_NIC_IN_S0_CPLD",
> +       // IOD0-IOD7 bit24-31
> +       "wALL_POWER_OK_1","FM_NIC_PPS_IN_S1",
> +       "wALL_POWER_OK_2","FM_PPS_NIC_OUT_CPU_OE_N",
> +       "PWRGD_EAST_DIMM_CPLD","",
> +       "PWRGD_WEST_DIMM_CPLD","FM_BUF_PPS_NIC_OUT_EN_CPLD",
> +       "PWRGD_NIC_CPLD","",
> +       "","PMBUS_MUX_SEL_C0",
> +       "PHOENIX_PWRBTN_N_CPLD","PMBUS_MUX_SEL_C1",
> +       "IRQ_INA230_E1S_0_ALERT_N","",
> +       // IOE0-IOE7 bit32-39
> +       "IRQ_INA230_E1S_1_ALERT_N","PWR_ON_RST_TUSB7340_CPLD",
> +       "","RST_PCIE_BOOT_PERST_N_CPLD",
> +       "FM_NIC_WAKE_N_CPLD","RST_PCIE_CPLD_NIC_N_CPLD",
> +       "FM_TPM_CONN_PRSNT_N","RST_PCIE_MCIO_0A_PERST_N_CPLD",
> +       "HDD0_PRSNT_N_CPLD","RST_PCIE_MCIO_0B_PERST_N_CPLD",
> +       "IRQ_INA230_P12V_NIC_ALERT_N","RST_PCIE_MCIO_1A_PERST_N_CPLD",
> +       "IRQ_INA230_P12V_SCM_ALERT_N","RST_PCIE_MCIO_1A_SA_PERST_N_CPL",
> +       "IRQ_PMBUS_ALERT_PWR11_R_N","RST_PCIE_MCIO_1B_PERST_N_CPLD",
> +       // IOF0-IOF7 bit40-47
> +       "CHASSIS_LEAK_2A_R_N","RST_PCIE_MCIO_2A_PERST_N_CPLD",
> +       "CHASSIS_LEAK_3A_R_N","RST_PCIE_MCIO_2B_PERST_N_CPLD",
> +       "CHASSIS_LEAK_4A_R_N","RST_PCIE_MCIO_3A_PERST_N_CPLD",
> +       "OC_ALERT_PADDLE_R_N","RST_PCIE_MCIO_3B_PERST_N_CPLD",
> +       "OC_ALERT_PWR2_R_N","RST_PCIE_MCIO_4A_PERST_N_CPLD",
> +       "OC_ALERT_PWR11_R_N","RST_PCIE_MCIO_4B_PERST_N_CPLD",
> +       "FM_IOE_ALT_N","RST_PERST1_N_CPLD",
> +       "LEAK_DETECT_1_PWR14_R_N","RST_PERST2_N_CPLD",
> +       // IOG0-IOG7 bit48-55
> +       "LEAK_DETECT_2_PWR14_R_N","RST_PERST3_N_CPLD",
> +       "LEAK_DETECT_1_PWR15_R_N","RST_SMB_MUX_MCIO_0A_R_N",
> +       "LEAK_DETECT_2_PWR15_R_N","RST_SMB_MUX_MCIO_1A_R_N",
> +       "MCIO_0A_SMB_ALERT_N","RST_SOC_EXTWARMRESET_CPLD",
> +       "MCIO_1A_SMB_ALERT_N","RST_SOC_PORESET_N_BMC",
> +       "MCIO_2A_SMB_ALERT_N","RST_USB_HUB_R_N",
> +       "MCIO_2B_SMB_ALERT_N","SMB_MM7_MUX_RESET_N",
> +       "MCIO_3A_SMB_ALERT_N","SMB_MUX_RESET_N_CPLD",
> +       // IOH0-IOH7 bit56-63
> +       "MCIO_3B_SMB_ALERT_N","SOC_I2C_0_ALERT_CPLD",
> +       "MCIO_4A_SMB_ALERT_N","SOC_LINKSTOP_OUT_N",
> +       "MCIO_4B_SMB_ALERT_N","SPI_TPM_RST_R_N",
> +       "MCIO_1A_THERMTRIP_N","",
> +       "MCIO_2A_THERMTRIP_N","",
> +       "MCIO_3A_THERMTRIP_N","",
> +       "MCIO_4A_THERMTRIP_N_CPLD","",
> +       "UV_ALERT_PADDLE_R_N","wFM_USB_MUX_OE_N",
> +       // IOI0-IOI7 bit64-71
> +       "UV_ALERT_PWR2_R_N","wFM_USB_MUX_SEL",
> +       "UV_ALERT_PWR11_R_N","",
> +       "SOC_PMBUS_0_ALERT_R_CPLD","FM_BIOS_DEBUG_MODE_N",
> +       "HDD1_PRSNT_N_CPLD","",
> +       "","",
> +       "SOC_DRAM_0_HOT_N_CPLD","",
> +       "SOC_DRAM_1_HOT_N_CPLD","RST_PLTRST_PLD_B_N",
> +       "SOC_DRAM_2_HOT_N_CPLD","FM_TPM_MUX6_SEL",
> +       // IOJ0-IOJ7 bit72-79
> +       "SOC_DRAM_3_HOT_N_CPLD","CPLD_MUX6_EN_N",
> +       "IRQ_P3V3_NIC_FLT_MOS_N_CPLD","",
> +       "VRHOT_V0P75_PCIE_VDDQ_N","",
> +       "P12V_SCM_FAULT_R_N","",
> +       "SOC_I2C_1_ALERT_CPLD","",
> +       "","",
> +       "SOC_PLATHOT_N_CPLD","",
> +       "SOC_THRMTRIP_N_CPLD","",
> +       // IOK0-IOK7 bit80-87
> +       "VRHOT_VCPUC1_VCPUMC1_N","",
> +       "VRHOT_VSYSC0_VSOCC0_N","",
> +       "VRHOT_VSYSC1_VSOCC1_N","",
> +       "VRHOT_VCPUC0_VCPUMC0_N","",
> +       "","",
> +       "INT_IOEXP_N","",
> +       "RSVD_IOEXP_0A_SB1_R","",
> +       "RSVD_IOEXP_0A_SB2_R","",
> +       // IOL0-IOL7 bit88-95
> +       "IRQ_PMBUS_PWR2_ALERT_R_N","",
> +       "FM_BORD_REV_ID0","",
> +       "FM_BORD_REV_ID1","",
> +       "FM_BORD_REV_ID2","",
> +       "FM_VR_TYPE_0","",
> +       "FM_VR_TYPE_1","",
> +       "","",
> +       "MCIO_0B_SMB_ALERT_N","",
> +       // IOM0-IOM7 bit96-103
> +       "MCIO_1B_SMB_ALERT_N","",
> +       "PRSNT_BOOT_N","",
> +       "PRSNT_MCIO_1A_N","",
> +       "wPRSNT_NIC_N","",
> +       "","",
> +       "SOC_TEST_MODE0","",
> +       "PWRGD_V0P75_PCIE","",
> +       "PWRGD_VDDQ","",
> +       // ION0-ION7 bit104-111
> +       "PWRGD_VCPUC0","",
> +       "PWRGD_VCPUMC0","",
> +       "PWRGD_VCPUMC1","",
> +       "PWRGD_VCPUC1","",
> +       "PWRGD_VSYSC0","",
> +       "PWRGD_VSOCC0","",
> +       "PWRGD_VSYSC1","",
> +       "PWRGD_VSOCC1","",
> +       // IOO0-IOO7 bit112-119
> +       "SOC_PMBUS_1_ALERT_R_CPLD","",
> +       "SOC_GPIO_15","",
> +       "C0_POSTCODE_0_CPLD","",
> +       "C0_POSTCODE_1_CPLD","",
> +       "C0_POSTCODE_2_CPLD","",
> +       "C0_POSTCODE_3_CPLD","",
> +       "C0_POSTCODE_4_CPLD","",
> +       "C1_POSTCODE_0_CPLD","",
> +       // IOP0-IOP7 bit 120-127
> +       "C1_POSTCODE_1_CPLD","",
> +       "C1_POSTCODE_2_CPLD","",
> +       "C1_POSTCODE_3_CPLD","",
> +       "C1_POSTCODE_4_CPLD","",
> +       "","",
> +       "SOC_GPIO_17","",
> +       "SOC_GPIO_18","",
> +       "SOC_GPIO_37","";
> +};
> +
> +/* BIOS Flash */
> +&spi2 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_spi2_default>;
> +       status = "okay";
> +
> +       flash@0 {
> +               m25p,fast-read;
> +               label = "pnor";
> +               spi-max-frequency = <12000000>;
> +               spi-tx-bus-width = <2>;
> +               spi-rx-bus-width = <2>;
> +               status = "okay";
> +       };
> +};
> +
> +&uart1 {
> +       status = "okay";
> +};
> +
> +&uart2 {
> +       status = "okay";
> +};
> +
> +/* SOL */
> +&uart3 {
> +       status = "okay";
> +};
> +
> +&uart4 {
> +       status = "okay";
> +};
> +
> +/* BMC Console */
> +&uart5 {
> +       status = "okay";
> +};
> +
> +&wdt1 {
> +       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>;
> +       status = "okay";
> +};
> --
> 2.25.1
> 



^ permalink raw reply

* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Lorenzo Stoakes @ 2026-05-18  9:46 UTC (permalink / raw)
  To: Barry Song
  Cc: Matthew Wilcox, surenb, akpm, linux-mm, david, liam, vbabka, rppt,
	mhocko, jack, pfalcato, wanglian, chentao, lianux.mm, kunwu.chan,
	liyangouwen1, chrisl, kasong, shikemeng, nphamcs, bhe,
	youngjun.park, linux-arm-kernel, linux-kernel, loongarch,
	linuxppc-dev, linux-riscv, linux-s390, Nanzhe Zhao
In-Reply-To: <CAGsJ_4ysMcrmDLSOwBkf7qwCQrcDWeEMXkHDajTJFMLKUk0bSQ@mail.gmail.com>

On Sun, May 17, 2026 at 04:45:15PM +0800, Barry Song wrote:
> On Sat, May 2, 2026 at 1:58 AM Matthew Wilcox <willy@infradead.org> wrote:
> >
> > On Sat, May 02, 2026 at 01:44:34AM +0800, Barry Song wrote:
> > > On Fri, May 1, 2026 at 10:57 PM Matthew Wilcox <willy@infradead.org> wrote:
> > > >
> > > > On Fri, May 01, 2026 at 06:49:58AM +0800, Barry Song wrote:
> > > > > 1. There is no deterministic latency for I/O completion. It depends on
> > > > > both the hardware and the software stack (bio/request queues and the
> > > > > block scheduler). Sometimes the latency is short; at other times it can
> > > > > be quite long. In such cases, a high-priority thread performing operations
> > > > > such as mprotect, unmap, prctl_set_vma, or madvise may be forced to wait
> > > > > for an unpredictable amount of time.
> > > >
> > > > But does that actually happen?  I find it hard to believe that thread A
> > > > unmaps a VMA while thread B is in the middle of taking a page fault in
> > > > that same VMA.  mprotect() and madvise() are more likely to happen, but
> > > > it still seems really unlikely to me.
> > >
> > > It doesn’t have to involve unmapping or applying mprotect to
> > > the entire VMA—just a portion of it is sufficient.
> >
> > Yes, but that still fails to answer "does this actually happen".  How much
> > performance is all this complexity in the page fault handler buying us?
> > If you don't answer this question, I'm just going to go in and rip it
> > all out.
> >
>
> Hi Matthew (and Lorenzo, Jan, and anyone else who may be
> waiting for answers),
>
> As promised during LSF/MM/BPF, we conducted thorough
> testing on Android phones to determine whether performing
> I/O in `filemap_fault()` can block `vma_start_write()`.
> I wanted to give a quick update on this question.
>
> Nanzhe at Xiaomi created tracing scripts and ran various
> applications on Android devices with I/O performed under
> the VMA lock in `filemap_fault()`. We found that:
>
> 1. There are very few cases where unmap() is blocked by
>    page faults. I assume this is due to buggy user code
>    or poor synchronization between reads and unmap().
> So I assume it is not a problem.
>
> 2. We observed many cases where `vma_start_write()`
>    is blocked by page-fault I/O in some applications.
>    The blocking occurs in the `dup_mmap()` path during
>    fork().
>
> With Suren's commit fb49c455323ff ("fork: lock VMAs of
> the parent process when forking"), we now always hold
> `vma_write_lock()` for each VMA. Note that the
> `mmap_lock` write lock is also held, which could lead to
> chained waiting if page-fault I/O is performed without
> releasing the VMA lock.

Hm but did you observe this 'chained waiting'? And what were the latencies?

>
> My gut feeling is that Suren's commit may be overshooting,
> so my rough idea is that we might want to do something like
> the following (we haven't tested it yet and it might be
> wrong):

Yeah I'm really not sure about that.

Prior to the VMA locks, the mmap write lock would have guaranteed no concurrent
page faults, which is really what fb49c455323ff is about.

So Suren's patch was essentially restoring the _existing_ forking behaviour, and
now you're saying 'let's change the forking behaviour that's been like that for
forever'.

I think you would _really_ have to be sure that's safe. And forking is a very
dangerous time in terms of complexity and sensitivity and 'weird stuff'
happening so I'd tread _very_ carefully here.

>
> diff --git a/mm/mmap.c b/mm/mmap.c
> index 2311ae7c2ff4..5ddaf297f31a 100644
> --- a/mm/mmap.c
> +++ b/mm/mmap.c
> @@ -1762,7 +1762,13 @@ __latent_entropy int dup_mmap(struct mm_struct
> *mm, struct mm_struct *oldmm)
>         for_each_vma(vmi, mpnt) {
>                 struct file *file;
>
> -               retval = vma_start_write_killable(mpnt);
> +               /*
> +                * For anonymous or writable private VMAs, prevent
> +                * concurrent CoW faults.
> +                */

To nit pick I think the comment's confusing but also tells you you don't need to
specific anon check - writable private is sufficient. And it's not really just
CoW that's the issue, it's anon_vma population _at all_ as well as CoW.

> +               if (!mpnt->vm_file || (!(mpnt->vm_flags & VM_SHARED) &&
> +                                       (mpnt->vm_flags & VM_WRITE)))
> +                       retval = vma_start_write_killable(mpnt);

I think this has to be VM_MAYWRITE, because somebody could otherwise mprotect()
it R/W.

I also don't understand why !mpnt->vm_file for a read-only anon mapping (more
likely PROT_NONE) is here, just do the second check?

(Also please use the new interface, so !vma_test(mpnt, VMA_SHARED_BIT) &&
vma_test(mpnt, VMA_MAYWRITE_BIT))

>                 if (retval < 0)
>                         goto loop_out;
>                 if (mpnt->vm_flags & VM_DONTCOPY) {
>
> Based on the above, we may want to re-check whether fork()
> can be blocked by page faults. At the same time, if Suren,
> you, or anyone else has any comments, please feel free to
> share them.
>
> Best Regards
> Barry

Technical commentary above is sort of 'just cos' :) because I really question
doing this honestly.

I'd also like to get Suren's input, however.

Thanks, Lorenzo


^ permalink raw reply

* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: David Hildenbrand (Arm) @ 2026-05-18  9:53 UTC (permalink / raw)
  To: Barry Song, Matthew Wilcox, surenb
  Cc: akpm, linux-mm, ljs, liam, vbabka, rppt, mhocko, jack, pfalcato,
	wanglian, chentao, lianux.mm, kunwu.chan, liyangouwen1, chrisl,
	kasong, shikemeng, nphamcs, bhe, youngjun.park, linux-arm-kernel,
	linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390,
	Nanzhe Zhao
In-Reply-To: <CAGsJ_4ysMcrmDLSOwBkf7qwCQrcDWeEMXkHDajTJFMLKUk0bSQ@mail.gmail.com>

On 5/17/26 10:45, Barry Song wrote:
> On Sat, May 2, 2026 at 1:58 AM Matthew Wilcox <willy@infradead.org> wrote:
>>
>> On Sat, May 02, 2026 at 01:44:34AM +0800, Barry Song wrote:
>>>
>>> It doesn’t have to involve unmapping or applying mprotect to
>>> the entire VMA—just a portion of it is sufficient.
>>
>> Yes, but that still fails to answer "does this actually happen".  How much
>> performance is all this complexity in the page fault handler buying us?
>> If you don't answer this question, I'm just going to go in and rip it
>> all out.
>>
> 
> Hi Matthew (and Lorenzo, Jan, and anyone else who may be
> waiting for answers),
> 
> As promised during LSF/MM/BPF, we conducted thorough
> testing on Android phones to determine whether performing
> I/O in `filemap_fault()` can block `vma_start_write()`.
> I wanted to give a quick update on this question.
> 
> Nanzhe at Xiaomi created tracing scripts and ran various
> applications on Android devices with I/O performed under
> the VMA lock in `filemap_fault()`. We found that:
> 
> 1. There are very few cases where unmap() is blocked by
>    page faults. I assume this is due to buggy user code
>    or poor synchronization between reads and unmap().
> So I assume it is not a problem.
> 
> 2. We observed many cases where `vma_start_write()`
>    is blocked by page-fault I/O in some applications.
>    The blocking occurs in the `dup_mmap()` path during
>    fork().
> 
> With Suren's commit fb49c455323ff ("fork: lock VMAs of
> the parent process when forking"), we now always hold
> `vma_write_lock()` for each VMA. Note that the
> `mmap_lock` write lock is also held, which could lead to
> chained waiting if page-fault I/O is performed without
> releasing the VMA lock.
> 
> My gut feeling is that Suren's commit may be overshooting,
> so my rough idea is that we might want to do something like
> the following (we haven't tested it yet and it might be
> wrong):
> 
> diff --git a/mm/mmap.c b/mm/mmap.c
> index 2311ae7c2ff4..5ddaf297f31a 100644
> --- a/mm/mmap.c
> +++ b/mm/mmap.c
> @@ -1762,7 +1762,13 @@ __latent_entropy int dup_mmap(struct mm_struct
> *mm, struct mm_struct *oldmm)
>         for_each_vma(vmi, mpnt) {
>                 struct file *file;
> 
> -               retval = vma_start_write_killable(mpnt);
> +               /*
> +                * For anonymous or writable private VMAs, prevent
> +                * concurrent CoW faults.
> +                */
> +               if (!mpnt->vm_file || (!(mpnt->vm_flags & VM_SHARED) &&
> +                                       (mpnt->vm_flags & VM_WRITE)))
> +                       retval = vma_start_write_killable(mpnt);

Likely is_cow_mapping() is what you would want to check to handle VMAs that
could have anonymous pages in them.

-- 
Cheers,

David


^ permalink raw reply

* [PATCH 0/2] spi: aspeed: Fix __iomem annotation and VLA parameter
From: Chin-Ting Kuo @ 2026-05-18  9:57 UTC (permalink / raw)
  To: clg, broonie, joel, andrew, linux-aspeed, openbmc, linux-spi,
	linux-arm-kernel, linux-kernel, BMC-SW

This series fixes two sparse warnings reported by the kernel test robot.
The first patch fixes missing __iomem annotation on an MMIO pointer
parameter, which also caused a redundant cast at the call site.
A VLA function parameter warning is also fixed in this patch series.

Chin-Ting Kuo (2):
  spi: aspeed: Fix missing __iomem annotation in output transfer path
  spi: aspeed: Fix sparse warnings for VLA parameter in calibration
    helper

 drivers/spi/spi-aspeed-smc.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

-- 
2.34.1



^ permalink raw reply

* [PATCH 1/2] spi: aspeed: Fix missing __iomem annotation in output transfer path
From: Chin-Ting Kuo @ 2026-05-18  9:57 UTC (permalink / raw)
  To: clg, broonie, joel, andrew, linux-aspeed, openbmc, linux-spi,
	linux-arm-kernel, linux-kernel, BMC-SW
  Cc: kernel test robot
In-Reply-To: <20260518095708.2502537-1-chin-ting_kuo@aspeedtech.com>

The dst parameter of aspeed_spi_user_transfer_tx() is an MMIO address
obtained from chip->ahb_base, but it was typed as void * instead of
void __iomem *.  This caused a sparse warning report. Fix the
parameter type to void __iomem * and drop the now-unnecessary
cast at the call site.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605180441.uD3toFRJ-lkp@intel.com/
Signed-off-by: Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>
---
 drivers/spi/spi-aspeed-smc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
index c21323e07d3c..808659a1f460 100644
--- a/drivers/spi/spi-aspeed-smc.c
+++ b/drivers/spi/spi-aspeed-smc.c
@@ -891,7 +891,7 @@ static int aspeed_spi_user_unprepare_msg(struct spi_controller *ctlr,
 static void aspeed_spi_user_transfer_tx(struct aspeed_spi *aspi,
 					struct spi_device *spi,
 					const u8 *tx_buf, u8 *rx_buf,
-					void *dst, u32 len)
+					void __iomem *dst, u32 len)
 {
 	const struct aspeed_spi_data *data = aspi->data;
 	bool full_duplex_transfer = data->full_duplex && tx_buf == rx_buf;
@@ -936,7 +936,7 @@ static int aspeed_spi_user_transfer(struct spi_controller *ctlr,
 			aspeed_spi_set_io_mode(chip, CTRL_IO_QUAD_DATA);
 
 		aspeed_spi_user_transfer_tx(aspi, spi, tx_buf, rx_buf,
-					    (void *)ahb_base, xfer->len);
+					    ahb_base, xfer->len);
 	}
 
 	if (rx_buf && rx_buf != tx_buf) {
-- 
2.34.1



^ permalink raw reply related

* [PATCH] spi: aspeed: Replace VLA parameter with flat pointer in calibration helper
From: Chin-Ting Kuo @ 2026-05-18  9:57 UTC (permalink / raw)
  To: clg, broonie, joel, andrew, linux-aspeed, openbmc, linux-spi,
	linux-arm-kernel, linux-kernel, BMC-SW
  Cc: kernel test robot
In-Reply-To: <20260518095708.2502537-1-chin-ting_kuo@aspeedtech.com>

aspeed_spi_ast2600_optimized_timing() declared its buffer argument as a
variable-length array parameter (u8 buf[rows][cols]), which causes a
sparse warning. Replace the VLA parameter with a plain u8 * and compute
the 2-D index manually. The corresponding call site is also updated.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605180441.uD3toFRJ-lkp@intel.com/
Signed-off-by: Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>
---
 drivers/spi/spi-aspeed-smc.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
index 808659a1f460..c5275700de3d 100644
--- a/drivers/spi/spi-aspeed-smc.c
+++ b/drivers/spi/spi-aspeed-smc.c
@@ -1467,8 +1467,7 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
  * must contains the highest number of consecutive "pass"
  * results and not span across multiple rows.
  */
-static u32 aspeed_spi_ast2600_optimized_timing(u32 rows, u32 cols,
-					       u8 buf[rows][cols])
+static u32 aspeed_spi_ast2600_optimized_timing(u32 rows, u32 cols, u8 *buf)
 {
 	int r = 0, c = 0;
 	int max = 0;
@@ -1478,7 +1477,7 @@ static u32 aspeed_spi_ast2600_optimized_timing(u32 rows, u32 cols,
 		for (j = 0; j < cols;) {
 			int k = j;
 
-			while (k < cols && buf[i][k])
+			while (k < cols && buf[i * cols + k])
 				k++;
 
 			if (k - j > max) {
@@ -1541,7 +1540,7 @@ static int aspeed_spi_ast2600_calibrate(struct aspeed_spi_chip *chip, u32 hdiv,
 		}
 	}
 
-	calib_point = aspeed_spi_ast2600_optimized_timing(6, 17, calib_res);
+	calib_point = aspeed_spi_ast2600_optimized_timing(6, 17, &calib_res[0][0]);
 	/* No good setting for this frequency */
 	if (calib_point == 0)
 		return -1;
-- 
2.34.1



^ permalink raw reply related

* Re: [PATCH 2/3] memory: mtk-smi: Add a flag skip_rpm
From: AngeloGioacchino Del Regno @ 2026-05-18 10:02 UTC (permalink / raw)
  To: Xueqi Zhang (张雪琦), robh@kernel.org,
	matthias.bgg@gmail.com, Yong Wu (吴勇),
	krzk@kernel.org, conor+dt@kernel.org
  Cc: Wendy-ST Lin (林詩庭),
	linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org, iommu@lists.linux.dev,
	Project_Global_Chrome_Upstream_Group, devicetree@vger.kernel.org
In-Reply-To: <198865fb3184926d0b1b4e4855b5f863ad0d6a20.camel@mediatek.com>

On 5/18/26 09:16, Xueqi Zhang (张雪琦) wrote:
> Hi Angelo,
> 
> First of all, please accept my apologies for the delayed response. I
> have been deeply occupied with MT8196 Aluminium pKVM SMMU and SMI
> related tasks recently.
> 
> Regarding your question, my previous description in the patch was not
> accurate enough and may have caused some confusion. In fact, not
> all SMI commons have their backup/restore handled by the RTFF
> hardware. The SMI commons are distributed across various subsystems
> (e.g., mminfra, venc, display, cam, etc.). Currently, only the SMI
> common under the mminfra subsystem is backed up and restored by
> the RTFF hardware.
> 
> Therefore, I believe adding a specific 'skip_rpm' flag is more
> appropriate here. If we were to differentiate this based on a new
> MTK_SMI_GEN3 type, it would imply that all SMI common modules of
> that generation would skip the RPM operations, which is not the
> intended behavior.
> 
> To make this clearer, I plan to update the commit message in the
> next version as follows:
> 
> Subject: memory: mtk-smi: Add skip_rpm flag for certain MT8196 SMI
> commons

memory: mtk-smi: Allow no clocks for RTFF managed SMI commons

> 
> Body:
> On MT8196, certain SMI commons are backed up and restored by the RTFF
> hardware rather than by software.
> 
> For these specific SMI commons, software-controlled register backup
> and restore in the runtime callback is no longer necessary. Therefore,
> introduce a 'skip_rpm' flag to bypass these redundant RPMoperations
> for these SMI commons.
> 
> What do you think about this approach?
> 

That would be kind-of ok, but keep in mind: pm_runtime doesn't only manage clocks.

I think that the best option here would be to allow having no clocks instead,
and to still call pm_runtime_{en,dis}able() - as that would get a bit more
future-proof, should any other (newer, older, etc) SoC need to declare any power
domain but still no clocks.

So at this point, I think that just doing something like:

	if (common->plat->has_gals) {
		if (common->plat->rtff_managed) <--- not "skip_rpm"
			clk_required = 0;
		else 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)
			clk_required = MTK_SMI_SUB_COM_GALS_REQ_CLK_NR;
	}

should be sufficient (and/or check zero required clocks in smi_dts_clk_init).

Cheers,
Angelo

> Thanks,
> Xueqi
> 
> On Thu, 2025-03-20 at 13:11 +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 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@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;
>>>    }
>>
>>



^ permalink raw reply

* Re: [PATCH v4 07/13] dma-direct: make dma_direct_map_phys() honor DMA_ATTR_CC_SHARED
From: Christian Borntraeger @ 2026-05-18 10:04 UTC (permalink / raw)
  To: Aneesh Kumar K.V (Arm), iommu, linux-arm-kernel, linux-kernel,
	linux-coco
  Cc: Robin Murphy, Marek Szyprowski, Will Deacon, Marc Zyngier,
	Steven Price, Suzuki K Poulose, Catalin Marinas, Jiri Pirko,
	Jason Gunthorpe, Mostafa Saleh, Petr Tesarik,
	Alexey Kardashevskiy, Dan Williams, Xu Yilun, linuxppc-dev,
	linux-s390, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy (CS GROUP), Alexander Gordeev,
	Gerald Schaefer, Heiko Carstens, Vasily Gorbik, Sven Schnelle,
	x86, Halil Pasic, Matthew Rosato, Jaehoon Kim
In-Reply-To: <20260512090408.794195-8-aneesh.kumar@kernel.org>

cc Halil, Matt, Jaehoon.
Can you have a look what this means for virtio on secure execution?

Am 12.05.26 um 11:04 schrieb Aneesh Kumar K.V (Arm):
> Teach dma_direct_map_phys() to select the DMA address encoding based on
> DMA_ATTR_CC_SHARED.
> 
> Use phys_to_dma_unencrypted() for decrypted mappings and
> phys_to_dma_encrypted() otherwise. If a device requires unencrypted DMA
> but the source physical address is still encrypted, force the mapping
> through swiotlb so the DMA address and backing memory attributes remain
> consistent.
> 
> Update the arm64, x86, s390 and powerpc secure-guest setup to not use
> swiotlb force option
> 
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> ---
> Changes from v3:
> * Handle DMA_ATTR_MMIO
> ---
>   arch/arm64/mm/init.c                 |  4 +--
>   arch/powerpc/platforms/pseries/svm.c |  2 +-
>   arch/s390/mm/init.c                  |  2 +-
>   arch/x86/kernel/pci-dma.c            |  4 +--
>   kernel/dma/direct.c                  |  4 ++-
>   kernel/dma/direct.h                  | 38 +++++++++++++---------------
>   6 files changed, 24 insertions(+), 30 deletions(-)
> 
> diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> index 97987f850a33..acf67c7064db 100644
> --- a/arch/arm64/mm/init.c
> +++ b/arch/arm64/mm/init.c
> @@ -338,10 +338,8 @@ void __init arch_mm_preinit(void)
>   	unsigned int flags = SWIOTLB_VERBOSE;
>   	bool swiotlb = max_pfn > PFN_DOWN(arm64_dma_phys_limit);
>   
> -	if (is_realm_world()) {
> +	if (is_realm_world())
>   		swiotlb = true;
> -		flags |= SWIOTLB_FORCE;
> -	}
>   
>   	if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb) {
>   		/*
> diff --git a/arch/powerpc/platforms/pseries/svm.c b/arch/powerpc/platforms/pseries/svm.c
> index 384c9dc1899a..7a403dbd35ee 100644
> --- a/arch/powerpc/platforms/pseries/svm.c
> +++ b/arch/powerpc/platforms/pseries/svm.c
> @@ -29,7 +29,7 @@ static int __init init_svm(void)
>   	 * need to use the SWIOTLB buffer for DMA even if dma_capable() says
>   	 * otherwise.
>   	 */
> -	ppc_swiotlb_flags |= SWIOTLB_ANY | SWIOTLB_FORCE;
> +	ppc_swiotlb_flags |= SWIOTLB_ANY;
>   
>   	/* Share the SWIOTLB buffer with the host. */
>   	swiotlb_update_mem_attributes();
> diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
> index 1f72efc2a579..843dbd445124 100644
> --- a/arch/s390/mm/init.c
> +++ b/arch/s390/mm/init.c
> @@ -149,7 +149,7 @@ static void __init pv_init(void)
>   	virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc);
>   
>   	/* make sure bounce buffers are shared */
> -	swiotlb_init(true, SWIOTLB_FORCE | SWIOTLB_VERBOSE);
> +	swiotlb_init(true, SWIOTLB_VERBOSE);
>   	swiotlb_update_mem_attributes();
>   }
>   
> diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
> index 6267363e0189..75cf8f6ae8cd 100644
> --- a/arch/x86/kernel/pci-dma.c
> +++ b/arch/x86/kernel/pci-dma.c
> @@ -59,10 +59,8 @@ static void __init pci_swiotlb_detect(void)
>   	 * bounce buffers as the hypervisor can't access arbitrary VM memory
>   	 * that is not explicitly shared with it.
>   	 */
> -	if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
> +	if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
>   		x86_swiotlb_enable = true;
> -		x86_swiotlb_flags |= SWIOTLB_FORCE;
> -	}
>   }
>   #else
>   static inline void __init pci_swiotlb_detect(void)
> diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
> index ac315dd046c4..5aaa813c5509 100644
> --- a/kernel/dma/direct.c
> +++ b/kernel/dma/direct.c
> @@ -691,8 +691,10 @@ size_t dma_direct_max_mapping_size(struct device *dev)
>   {
>   	/* If SWIOTLB is active, use its maximum mapping size */
>   	if (is_swiotlb_active(dev) &&
> -	    (dma_addressing_limited(dev) || is_swiotlb_force_bounce(dev)))
> +	    (dma_addressing_limited(dev) || is_swiotlb_force_bounce(dev) ||
> +	     force_dma_unencrypted(dev)))
>   		return swiotlb_max_mapping_size(dev);
> +
>   	return SIZE_MAX;
>   }
>   
> diff --git a/kernel/dma/direct.h b/kernel/dma/direct.h
> index e05dc7649366..4e35264ab6f8 100644
> --- a/kernel/dma/direct.h
> +++ b/kernel/dma/direct.h
> @@ -89,36 +89,32 @@ static inline dma_addr_t dma_direct_map_phys(struct device *dev,
>   	dma_addr_t dma_addr;
>   
>   	if (is_swiotlb_force_bounce(dev)) {
> -		if (!(attrs & DMA_ATTR_CC_SHARED)) {
> -			if (attrs & (DMA_ATTR_MMIO | DMA_ATTR_REQUIRE_COHERENT))
> -				return DMA_MAPPING_ERROR;
> +		if (attrs & (DMA_ATTR_MMIO | DMA_ATTR_REQUIRE_COHERENT))
> +			return DMA_MAPPING_ERROR;
>   
> -			return swiotlb_map(dev, phys, size, dir, attrs);
> -		}
> -	} else if (attrs & DMA_ATTR_CC_SHARED) {
> -		return DMA_MAPPING_ERROR;
> +		return swiotlb_map(dev, phys, size, dir, attrs);
>   	}
>   
> -	if (attrs & DMA_ATTR_MMIO) {
> -		dma_addr = phys;
> -		if (unlikely(!dma_capable(dev, dma_addr, size, false, attrs)))
> -			goto err_overflow;
> -	} else if (attrs & DMA_ATTR_CC_SHARED) {
> +	if (attrs & DMA_ATTR_CC_SHARED)
>   		dma_addr = phys_to_dma_unencrypted(dev, phys);
> +	else
> +		dma_addr = phys_to_dma_encrypted(dev, phys);
> +
> +	if (attrs & DMA_ATTR_MMIO) {
>   		if (unlikely(!dma_capable(dev, dma_addr, size, false, attrs)))
>   			goto err_overflow;
> -	} else {
> -		dma_addr = phys_to_dma(dev, phys);
> -		if (unlikely(!dma_capable(dev, dma_addr, size, true, attrs)) ||
> -		    dma_kmalloc_needs_bounce(dev, size, dir)) {
> -			if (is_swiotlb_active(dev) &&
> -			    !(attrs & DMA_ATTR_REQUIRE_COHERENT))
> -				return swiotlb_map(dev, phys, size, dir, attrs);
> +		goto dma_mapped;
> +	}
>   
> -			goto err_overflow;
> -		}
> +	if (unlikely(!dma_capable(dev, dma_addr, size, true, attrs)) ||
> +	    dma_kmalloc_needs_bounce(dev, size, dir)) {
> +		if (is_swiotlb_active(dev) &&
> +		    !(attrs & DMA_ATTR_REQUIRE_COHERENT))
> +			return swiotlb_map(dev, phys, size, dir, attrs);
> +		goto err_overflow;
>   	}
>   
> +dma_mapped:
>   	if (!dev_is_dma_coherent(dev) &&
>   	    !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO))) {
>   		arch_sync_dma_for_device(phys, size, dir);



^ permalink raw reply

* [PATCH v2] ARM: dts: aspeed: anacapa: correct SGPIO names for monitoring
From: Rex Fu via B4 Relay @ 2026-05-18 10:00 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, Rex Fu

From: Rex Fu <Rex.Fu@amd.com>

Update several Anacapa SGPIO line names to match the existing platform
hardware design and the signal names consumed by userspace monitoring.

The previous names did not match the actual Anacapa SGPIO usage. Some
lines were named as CPU or CPU power-good signals, but they are wired and
used on Anacapa for EDSFF presence, EDSFF power-good, boot EDSFF
presence, and thermal-trip assertion monitoring.

Correct the mappings as follows:

  PWRGD_PVDDCR_SOC_P0     -> L_PRSNT_EDSFF0_N
  PWRGD_PVDDIO_P0         -> L_PRSNT_EDSFF1_N
  PWRGD_PVDDIO_MEM_S3_P0  -> R_PRSNT_EDSFF2_N
  PWRGD_CHMP_CPU0_FPGA    -> R_PRSNT_EDSFF3_N
  PWRGD_CHIL_CPU0_FPGA    -> HPM_EDSFF_PG
  EAM2_CPU_MOD_PWR_GD_R   -> PRSNT_EDSFF_BOOT_N
  CPU0_SP7R1              -> L_EDSFF0_PG
  CPU0_SP7R2              -> L_EDSFF1_PG
  CPU0_SP7R3              -> R_EDSFF2_PG
  CPU0_SP7R4              -> R_EDSFF3_PG
  HPM_AMC_THERMTRIP_R_L   -> AMC_THERMTRIP_ASSERT
  FM_CPU0_THERMTRIP_N     -> CPU_THERMTRIP_ASSERT

The left-side EDSFF slots are numbered as EDSFF0 and EDSFF1 to match
the platform slot numbering used by userspace. The thermtrip names are
also updated to describe the asserted condition monitored by userspace
instead of the raw active-low signal names.

This is a naming correction for the existing Anacapa hardware design.
There is no new board revision or underlying hardware change involved.

Signed-off-by: Rex Fu <Rex.Fu@amd.com>
---
Update the Anacapa SGPIO line names to match the existing hardware
design and the platform signal names used by userspace monitoring.

The v2 commit message now explains why changing these userspace-visible
GPIO line names is appropriate and lists the exact old-to-new mappings.
---
Changes in v2:
- Reworked the commit message to explain why these userspace-visible
  GPIO line names are changed.
- Listed the exact old-to-new SGPIO line name mappings.
- Clarified that this is a naming correction for the existing hardware
  design and not a board revision or hardware change.
- Link to v1: https://patch.msgid.link/20260430-anacapa-sgpio-edsff-thermtrip-v1-1-2fd5e72435d0@amd.com

To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Joel Stanley <joel@jms.id.au>
To: Andrew Jeffery <andrew@codeconstruct.com.au>
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-aspeed@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
---
 .../boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts  | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
index 2cb7bd128d24..e898bc11e6f5 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
@@ -908,11 +908,11 @@ &sgpiom0 {
 	"", "", "", "",
 
 	/* G0-G7 line 96-111 */
-	"PWRGD_PVDDCR_SOC_P0", "",
-	"PWRGD_PVDDIO_P0", "",
-	"PWRGD_PVDDIO_MEM_S3_P0", "",
-	"PWRGD_CHMP_CPU0_FPGA", "",
-	"PWRGD_CHIL_CPU0_FPGA", "",
+	"L_PRSNT_EDSFF0_N", "",
+	"L_PRSNT_EDSFF1_N", "",
+	"R_PRSNT_EDSFF2_N", "",
+	"R_PRSNT_EDSFF3_N", "",
+	"HPM_EDSFF_PG", "",
 	"PWRGD_CHEH_CPU0_FPGA", "",
 	"PWRGD_CHAD_CPU0_FPGA", "FM_BMC_READY_PLD",
 	"", "",
@@ -934,7 +934,7 @@ &sgpiom0 {
 	"EAM3_BRD_PRSNT_R_L", "",
 	"EAM0_CPU_MOD_PWR_GD_R", "",
 	"EAM1_CPU_MOD_PWR_GD_R", "",
-	"EAM2_CPU_MOD_PWR_GD_R", "",
+	"PRSNT_EDSFF_BOOT_N", "",
 	"EAM3_CPU_MOD_PWR_GD_R", "",
 
 	/* J0-J7 line 144-159 */
@@ -957,8 +957,8 @@ &sgpiom0 {
 	"PDB_ALERT_R_N", "",
 
 	/* L0-L7 line 176-191 */
-	"CPU0_SP7R1", "", "CPU0_SP7R2", "",
-	"CPU0_SP7R3", "", "CPU0_SP7R4", "",
+	"L_EDSFF0_PG", "", "L_EDSFF1_PG", "",
+	"R_EDSFF2_PG", "", "R_EDSFF3_PG", "",
 	"CPU0_CORETYPE0", "", "CPU0_CORETYPE1", "",
 	"CPU0_CORETYPE2", "", "FM_BIOS_POST_CMPLT_R_N", "",
 
@@ -984,8 +984,8 @@ &sgpiom0 {
 	"HPM_PWR_FAIL", "Port80_b0",
 	"FM_DIMM_IP_FAIL", "Port80_b1",
 	"FM_DIMM_AH_FAIL", "Port80_b2",
-	"HPM_AMC_THERMTRIP_R_L", "Port80_b3",
-	"FM_CPU0_THERMTRIP_N", "Port80_b4",
+	"AMC_THERMTRIP_ASSERT", "Port80_b3",
+	"CPU_THERMTRIP_ASSERT", "Port80_b4",
 	"PVDDCR_SOC_P0_OCP_L", "Port80_b5",
 	"CPLD_SGPIO_RDY", "Port80_b6",
 	"", "Port80_b7",

---
base-commit: 9974969c14031a097d6b45bcb7a06bb4aa525c40
change-id: 20260430-anacapa-sgpio-edsff-thermtrip-acb228bf61be

Best regards,
--  
Rex Fu <Rex.Fu@amd.com>




^ permalink raw reply related

* Re: [PATCH v2 3/3] arm64: dts: allwinner: A133: add support for Baijie Helper A133 board
From: Alexander Sverdlin @ 2026-05-18 10:12 UTC (permalink / raw)
  To: wens
  Cc: Andre Przywara, linux-sunxi, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jernej Skrabec, Samuel Holland, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <CAGb2v67tjOCE=Xk=pD84wBG4WTt1nYhDoW3gu_xfx4J0Ooc_VQ@mail.gmail.com>

Hi Checn-Yu,

thanks for the review!

On Mon, 2026-05-18 at 11:30 +0800, Chen-Yu Tsai wrote:
> > > And you should provide a top level 5V regulator here, to be the root of
> > > the regulator tree. Look at reg_vcc5v in the Liontron .dts.
> > 
> > It doesn't look to me as if Liontron had reg_vcc5v as its 5V "root" regulator.
> > It seems to be only used for reg_usb1_vbus, while HelperBoard A133 doesn't
> > have USB power control. The second issue with Helper/Core split is that
> > all PMIC story is inside Core board which has 5V input rail, while HelperBoard
> > around it has indeed 12V->5V DCDC regulator (similar to Liontron), but
> > putting it in the DT would introduce wierd dependency of the core to the
> > HelperBoard which carries it. Do you think it would make sense?
> 
> In that case I would probably put a 5v "fake root" regulator in the core
> dtsi. And in combined dts, I'd then add the 12v "real root", and use that
> as the supply for the 5v fake root.
> 
> Does that make sense?

"core" board has some battery management schematics, switching the 5V,
I'll look into specifying this part in "core" .dtsi, maybe it will result
in some kind of regulator in "core" part. I'll send v4.

-- 
Alexander Sverdlin.


^ permalink raw reply

* [PATCH v5 0/4] Enable sysfs module symlink for more built-in drivers
From: Shashank Balaji @ 2026-05-18 10:19 UTC (permalink / raw)
  To: Suzuki K Poulose, James Clark, Alexander Shishkin,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Jonathan Corbet, Shuah Khan, Luis Chamberlain, Petr Pavlu,
	Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Mike Leach, Leo Yan,
	Thierry Reding, Jonathan Hunter, Mike Leach
  Cc: Rahul Bukte, Shashank Balaji, linux-kernel, coresight,
	linux-arm-kernel, driver-core, rust-for-linux, linux-doc,
	Daniel Palmer, Tim Bird, linux-modules, linux-tegra, Sumit Gupta
In-Reply-To: <20260427-acpi_mod_name-v4-0-22b42240c9bf@sony.com>

struct device_driver's mod_name is not set by a number of bus' driver registration
functions. Without that, built-in drivers don't have the module symlink in sysfs.
We want this to go from unbound driver name -> module name -> kernel config name.
This is useful on embedded platforms to minimize kernel config, reduce kernel size,
and reduce boot time.

In order to achieve this, mod_name has to be set to KBUILD_MODNAME, and this has
to be done for all buses which don't yet do this.

Here are some treewide stats:
- 110 registration functions across all bus types
- 20 of them set mod_name
- Remaining 90 do not set mod_name:
    1. 36 functions under pattern 1:
        They have a __register function + register macro. KBUILD_MODNAME needs to
        be passed and the function needs to take mod_name as input.
    2. 42 functions under pattern 2:
        These have no macro wrapper. They need a double-underscore rename + macro
        wrapper to make them similar to pattern 1.
    3. Remaining 12 do not have such a clean registration interface. More analysis
       is required.

We plan to start with pattern 1, since it's the easiest category of changes.
Within that, for now we're only sending the platform patch. If we get the go-ahead
on that, we'll send the remaining ones.

Patch 4 depends on patches 1, 2, and 3.

Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
---
Changes in v5:
- Move tegra cbb driver init to core_initcall and module_kset init to pure_initcall (Gary)
- Rename coresight_init_driver() to coresight_init_driver_with_owner(), and
  declare function prototype before use (Leo)
- Merge doc change patch with code change patch, so that __platform_register_drivers()
  prototype is changed everywhere in the same patch
- Link to v4: https://patch.msgid.link/20260427-acpi_mod_name-v4-0-22b42240c9bf@sony.com

Changes in v4:
- Initialize module_kset in do_basic_setup() before do_initcalls() (Gary)
- Add commit body to the documentation patch (Greg)
- Link to v3: https://patch.msgid.link/20260422-acpi_mod_name-v3-0-a184eff9ff6f@sony.com

Changes in v3:
- Initialize module_kset on-demand (Greg)
- Make coresight driver registration happen through a macro (Greg)
- Split up the patch adding mod_name to platform driver registrations (Greg)
- Link to v2: https://patch.msgid.link/20260421-acpi_mod_name-v2-0-e73f9310dad3@sony.com

Changes in v2:
- Drop acpi patch, send platform instead (Rafael)
- Link to v1: https://patch.msgid.link/20260416-acpi_mod_name-v1-0-1a4d96fd86c9@sony.com

To: Suzuki K Poulose <suzuki.poulose@arm.com>
To: Mike Leach <mike.leach@linaro.org>
To: James Clark <james.clark@linaro.org>
To: Alexander Shishkin <alexander.shishkin@linux.intel.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: "Rafael J. Wysocki" <rafael@kernel.org>
To: Danilo Krummrich <dakr@kernel.org>
To: Miguel Ojeda <ojeda@kernel.org>
To: Boqun Feng <boqun@kernel.org>
To: Gary Guo <gary@garyguo.net>
To: Björn Roy Baron <bjorn3_gh@protonmail.com>
To: Benno Lossin <lossin@kernel.org>
To: Andreas Hindborg <a.hindborg@kernel.org>
To: Alice Ryhl <aliceryhl@google.com>
To: Trevor Gross <tmgross@umich.edu>
To: Jonathan Corbet <corbet@lwn.net>
To: Shuah Khan <skhan@linuxfoundation.org>
To: Luis Chamberlain <mcgrof@kernel.org>
To: Petr Pavlu <petr.pavlu@suse.com>
To: Daniel Gomez <da.gomez@kernel.org>
To: Sami Tolvanen <samitolvanen@google.com>
To: Aaron Tomlin <atomlin@atomlin.com>
To: Mike Leach <mike.leach@arm.com>
To: Leo Yan <leo.yan@arm.com>
To: Thierry Reding <thierry.reding@kernel.org>
To: Jonathan Hunter <jonathanh@nvidia.com>
Cc: linux-kernel@vger.kernel.org
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: driver-core@lists.linux.dev
Cc: rust-for-linux@vger.kernel.org
Cc: linux-doc@vger.kernel.org
Cc: Shashank Balaji <shashank.mahadasyam@sony.com>
Cc: Rahul Bukte <rahul.bukte@sony.com>
Cc: Daniel Palmer <daniel.palmer@sony.com>
Cc: Tim Bird <tim.bird@sony.com>
Cc: linux-modules@vger.kernel.org
Cc: linux-tegra@vger.kernel.org
Cc: Sumit Gupta <sumitg@nvidia.com>

---
Shashank Balaji (4):
      soc/tegra: cbb: Move driver registration from pure_initcall to core_initcall
      kernel: param: initialize module_kset in a pure_initcall
      coresight: pass THIS_MODULE implicitly through a macro
      driver core: platform: set mod_name in driver registration

 Documentation/driver-api/driver-model/platform.rst |  3 ++-
 drivers/base/platform.c                            | 21 ++++++++++++++-------
 drivers/hwtracing/coresight/coresight-catu.c       |  2 +-
 drivers/hwtracing/coresight/coresight-core.c       |  9 +++++----
 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-tnoc.c       |  2 +-
 drivers/hwtracing/coresight/coresight-tpdm.c       |  3 +--
 drivers/hwtracing/coresight/coresight-tpiu.c       |  2 +-
 drivers/soc/tegra/cbb/tegra194-cbb.c               |  2 +-
 drivers/soc/tegra/cbb/tegra234-cbb.c               |  2 +-
 include/linux/coresight.h                          |  7 +++++--
 include/linux/platform_device.h                    | 17 +++++++++--------
 kernel/params.c                                    |  2 +-
 rust/kernel/platform.rs                            |  4 +++-
 18 files changed, 50 insertions(+), 39 deletions(-)
---
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
change-id: 20260416-acpi_mod_name-f645a76e337b

Best regards,
--  
Shashank Balaji <shashank.mahadasyam@sony.com>



^ permalink raw reply

* [PATCH v5 2/4] kernel: param: initialize module_kset in a pure_initcall
From: Shashank Balaji @ 2026-05-18 10:19 UTC (permalink / raw)
  To: Suzuki K Poulose, James Clark, Alexander Shishkin,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Jonathan Corbet, Shuah Khan, Luis Chamberlain, Petr Pavlu,
	Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Mike Leach, Leo Yan,
	Thierry Reding, Jonathan Hunter, Mike Leach
  Cc: Rahul Bukte, Shashank Balaji, linux-kernel, coresight,
	linux-arm-kernel, driver-core, rust-for-linux, linux-doc,
	Daniel Palmer, Tim Bird, linux-modules, linux-tegra, Sumit Gupta
In-Reply-To: <20260518-acpi_mod_name-v5-0-705ccc430885@sony.com>

Commit "driver core: platform: set mod_name in driver registration" will set
struct device_driver's mod_name member for platform driver registration. For a
driver to be registered with its mod_name set, module_kset needs to be
initialized, which currently happens in a subsys_initcall in param_sysfs_init().
The tegra cbb drivers register themselves before module_kset init, in a
core_initcall. This works currently because lookup_or_create_module_kobject(),
which dereferences module_kset via kset_find_obj(), is not called if mod_name
is not set, which is the case now.

So in preparation for the commit "driver core: platform: set mod_name in driver registration",
move module_kset init to pure_initcall level, ensuring it happens before tegra
cbb driver registration.

Suggested-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
---
Patch 4 depends on this patch
---
 kernel/params.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/params.c b/kernel/params.c
index 74d620bc2521..ac088d4b09a9 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -957,7 +957,7 @@ static int __init param_sysfs_init(void)
 
 	return 0;
 }
-subsys_initcall(param_sysfs_init);
+pure_initcall(param_sysfs_init);
 
 /*
  * param_sysfs_builtin_init - add sysfs version and parameter

-- 
2.43.0



^ permalink raw reply related

* [PATCH v5 1/4] soc/tegra: cbb: Move driver registration from pure_initcall to core_initcall
From: Shashank Balaji @ 2026-05-18 10:19 UTC (permalink / raw)
  To: Suzuki K Poulose, James Clark, Alexander Shishkin,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Jonathan Corbet, Shuah Khan, Luis Chamberlain, Petr Pavlu,
	Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Mike Leach, Leo Yan,
	Thierry Reding, Jonathan Hunter, Mike Leach
  Cc: Rahul Bukte, Shashank Balaji, linux-kernel, coresight,
	linux-arm-kernel, driver-core, rust-for-linux, linux-doc,
	Daniel Palmer, Tim Bird, linux-modules, linux-tegra, Sumit Gupta
In-Reply-To: <20260518-acpi_mod_name-v5-0-705ccc430885@sony.com>

Commit "driver core: platform: set mod_name in driver registration" will set
struct device_driver's mod_name member for platform driver registration. For a
driver to be registered with its mod_name set, module_kset needs to be
initialized, which currently happens in a subsys_initcall in param_sysfs_init().
The tegra cbb drivers register themselves before module_kset init, in a
pure_initcall. This works currently because lookup_or_create_module_kobject(),
which dereferences module_kset via kset_find_obj(), is not called if mod_name
is not set, which is the case now.

So in preparation for the commit "driver core: platform: set mod_name in driver registration",
move tegra cbb driver registration to core_initcall level, and commit
"kernel: param: initialize module_kset in a pure_initcall" will move module_kset
init to pure_initcall level, ensuring module_kset init happens before tegra cbb
driver registration.

Suggested-by: Gary Guo <gary@garyguo.net>
Acked-by: Sumit Gupta <sumitg@nvidia.com>
Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
---
Patch 4 depends on this patch
---
 drivers/soc/tegra/cbb/tegra194-cbb.c | 2 +-
 drivers/soc/tegra/cbb/tegra234-cbb.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/cbb/tegra194-cbb.c b/drivers/soc/tegra/cbb/tegra194-cbb.c
index ab75d50cc85c..2f69e104c838 100644
--- a/drivers/soc/tegra/cbb/tegra194-cbb.c
+++ b/drivers/soc/tegra/cbb/tegra194-cbb.c
@@ -2342,7 +2342,7 @@ static int __init tegra194_cbb_init(void)
 {
 	return platform_driver_register(&tegra194_cbb_driver);
 }
-pure_initcall(tegra194_cbb_init);
+core_initcall(tegra194_cbb_init);
 
 static void __exit tegra194_cbb_exit(void)
 {
diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c
index fb26f085f691..785072fa4e85 100644
--- a/drivers/soc/tegra/cbb/tegra234-cbb.c
+++ b/drivers/soc/tegra/cbb/tegra234-cbb.c
@@ -1774,7 +1774,7 @@ static int __init tegra234_cbb_init(void)
 {
 	return platform_driver_register(&tegra234_cbb_driver);
 }
-pure_initcall(tegra234_cbb_init);
+core_initcall(tegra234_cbb_init);
 
 static void __exit tegra234_cbb_exit(void)
 {

-- 
2.43.0



^ permalink raw reply related


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