* Re: [PATCH V2 5/5] dmaengine: xilinx_dma: Add support for reporting transfer size to AXI DMA / MCDMA client when app fields are unavailable
From: Neeli, Srinivas @ 2026-04-07 5:42 UTC (permalink / raw)
To: Frank Li, Srinivas Neeli
Cc: Vinod Koul, git, Frank Li, Michal Simek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Suraj Gupta,
Radhey Shyam Pandey, Thomas Gessler, Folker Schwesinger,
Tomi Valkeinen, Kees Cook, Abin Joseph, dmaengine, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <acqe_AF3YHPLNzoV@lizhi-Precision-Tower-5810>
Hi Frank,
On 3/30/2026 9:34 PM, Frank Li wrote:
> On Fri, Mar 13, 2026 at 11:55:33AM +0530, Srinivas Neeli wrote:
>> From: Suraj Gupta <suraj.gupta2@amd.com>
>>
>> The AXI4-stream status and control interface is optional in the AXI DMA /
>> MCDMA IP design; when it is not present, app fields are not available in
>> DMA descriptor. In such cases, the transferred byte count can be
>> communicated to the client using the status field (bits 0-25) of
>> AXI DMA / MCDMA descriptor.
>>
>> Add a xferred_bytes field to struct xilinx_dma_tx_descriptor to record the
>> number of bytes transferred for each transaction. The value is calculated
>> using the existing xilinx_dma_get_residue() function, which traverses all
>> hardware descriptors associated with the async transaction descriptor,
>> avoiding redundant traversal.
> Can you split this change to new patch?
>
> Frank
The changes related to the xferred_bytes field and the
has_stsctrl_stream property are tightly coupled and cannot be cleanly
separated without breaking functionality or resulting in incomplete commits.
The xferred_bytes field does not serve any meaningful purpose without
the has_stsctrl_stream check:
- xferred_bytes is computed in xilinx_dma_get_residue(), but it is only
exposed to clients through xilinx_dma_get_metadata_ptr().
- The metadata accessor relies on has_stsctrl_stream to determine
whether to return APP fields or xferred_bytes.
- Without this conditional logic, xferred_bytes would still be
calculated but would never be consumed by any client
Thanks
Neeli Srinivas
>> The driver uses the xlnx,include-stscntrl-strm device tree property to
>> determine if the status/control stream interface is present and selects the
>> appropriate metadata source accordingly.
>>
>> Signed-off-by: Suraj Gupta <suraj.gupta2@amd.com>
>> ---
>> drivers/dma/xilinx/xilinx_dma.c | 28 ++++++++++++++++++++++++----
>> 1 file changed, 24 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
>> index 52203d44e7a4..f5ef03a1297c 100644
>> --- a/drivers/dma/xilinx/xilinx_dma.c
>> +++ b/drivers/dma/xilinx/xilinx_dma.c
>> @@ -380,6 +380,8 @@ struct xilinx_cdma_tx_segment {
>> * @cyclic: Check for cyclic transfers.
>> * @err: Whether the descriptor has an error.
>> * @residue: Residue of the completed descriptor
>> + * @xferred_bytes: Number of bytes transferred by this transaction
>> + * descriptor.
>> */
>> struct xilinx_dma_tx_descriptor {
>> struct xilinx_dma_chan *chan;
>> @@ -389,6 +391,7 @@ struct xilinx_dma_tx_descriptor {
>> bool cyclic;
>> bool err;
>> u32 residue;
>> + u32 xferred_bytes;
>> };
>>
>> /**
>> @@ -515,6 +518,7 @@ struct xilinx_dma_config {
>> * @mm2s_chan_id: DMA mm2s channel identifier
>> * @max_buffer_len: Max buffer length
>> * @has_axistream_connected: AXI DMA connected to AXI Stream IP
>> + * @has_stsctrl_stream: AXI4-stream status and control interface is enabled
>> */
>> struct xilinx_dma_device {
>> void __iomem *regs;
>> @@ -534,6 +538,7 @@ struct xilinx_dma_device {
>> u32 mm2s_chan_id;
>> u32 max_buffer_len;
>> bool has_axistream_connected;
>> + bool has_stsctrl_stream;
>> };
>>
>> /* Macros */
>> @@ -672,8 +677,12 @@ static void *xilinx_dma_get_metadata_ptr(struct dma_async_tx_descriptor *tx,
>> struct xilinx_axidma_tx_segment, node);
>> metadata_ptr = seg->hw.app;
>> }
>> - *max_len = *payload_len = sizeof(u32) * XILINX_DMA_NUM_APP_WORDS;
>> - return metadata_ptr;
>> + if (desc->chan->xdev->has_stsctrl_stream) {
>> + *max_len = *payload_len = sizeof(u32) * XILINX_DMA_NUM_APP_WORDS;
>> + return metadata_ptr;
>> + }
>> + *max_len = *payload_len = sizeof(desc->xferred_bytes);
>> + return (void *)&desc->xferred_bytes;
>> }
>>
>> static struct dma_descriptor_metadata_ops xilinx_dma_metadata_ops = {
>> @@ -864,6 +873,7 @@ xilinx_dma_alloc_tx_descriptor(struct xilinx_dma_chan *chan)
>> return NULL;
>>
>> desc->chan = chan;
>> + desc->xferred_bytes = 0;
>> INIT_LIST_HEAD(&desc->segments);
>>
>> return desc;
>> @@ -1014,6 +1024,7 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan,
>> struct xilinx_aximcdma_desc_hw *aximcdma_hw;
>> struct list_head *entry;
>> u32 residue = 0;
>> + u32 xferred = 0;
>>
>> list_for_each(entry, &desc->segments) {
>> if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
>> @@ -1031,25 +1042,32 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan,
>> axidma_hw = &axidma_seg->hw;
>> residue += (axidma_hw->control - axidma_hw->status) &
>> chan->xdev->max_buffer_len;
>> + xferred += axidma_hw->status & chan->xdev->max_buffer_len;
>> } else {
>> aximcdma_seg =
>> list_entry(entry,
>> struct xilinx_aximcdma_tx_segment,
>> node);
>> aximcdma_hw = &aximcdma_seg->hw;
>> - if (chan->direction == DMA_DEV_TO_MEM)
>> + if (chan->direction == DMA_DEV_TO_MEM) {
>> residue +=
>> (aximcdma_hw->control -
>> aximcdma_hw->s2mm_status) &
>> chan->xdev->max_buffer_len;
>> - else
>> + xferred += aximcdma_hw->s2mm_status &
>> + chan->xdev->max_buffer_len;
>> + } else {
>> residue +=
>> (aximcdma_hw->control -
>> aximcdma_hw->mm2s_status) &
>> chan->xdev->max_buffer_len;
>> + xferred += aximcdma_hw->mm2s_status &
>> + chan->xdev->max_buffer_len;
>> + }
>> }
>> }
>>
>> + desc->xferred_bytes = xferred;
>> return residue;
>> }
>>
>> @@ -3284,6 +3302,8 @@ static int xilinx_dma_probe(struct platform_device *pdev)
>> xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
>> xdev->has_axistream_connected =
>> of_property_read_bool(node, "xlnx,axistream-connected");
>> + xdev->has_stsctrl_stream =
>> + of_property_read_bool(node, "xlnx,include-stscntrl-strm");
>> }
>>
>> if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
>> --
>> 2.43.0
>>
^ permalink raw reply
* Re: [PATCH v3 1/2] ti,j721e-system-controller.yaml: Allow audio-refclk as clock-controller child
From: Moteen Shah @ 2026-04-07 5:46 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: krzk+dt, robh, conor+dt, nm, vigneshr, kristo, devicetree,
linux-arm-kernel, linux-kernel, u-kumar1, gehariprasath,
y-abhilashchandra
In-Reply-To: <20260331-flashy-hilarious-whale-6e606c@quoll>
Hey Krzysztof,
On 31/03/26 12:39, Krzysztof Kozlowski wrote:
> On Mon, Mar 30, 2026 at 03:14:58PM +0530, Moteen Shah wrote:
>> The ti,j721e-system-controller binding currently only allows
>> clock-controller@ child nodes to reference the ti,am654-ehrpwm-tbclk
>> schema. However, the system controller on J721S2 also contains audio
> J721S2 or AM62?
>
>> reference clock controllers (ti,am62-audio-refclk) that use the same
>> clock-controller@XXXX naming pattern.
>>
>> Hence, extend the clock-controller pattern to accept either ehrpwm-tbclk
>> or audio-refclk schemas using a oneOf constraint.
>>
>> Signed-off-by: Moteen Shah <m-shah@ti.com>
>> ---
>> .../bindings/soc/ti/ti,j721e-system-controller.yaml | 6 ++++--
>> 1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml b/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
>> index f3bd0be3b279..d5d84a8f1257 100644
>> --- a/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
>> +++ b/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
>> @@ -53,9 +53,11 @@ patternProperties:
>>
>> "^clock-controller@[0-9a-f]+$":
>> type: object
>> - $ref: /schemas/clock/ti,am654-ehrpwm-tbclk.yaml#
>> + oneOf:
>> + - $ref: /schemas/clock/ti,am654-ehrpwm-tbclk.yaml#
>> + - $ref: /schemas/clock/ti,am62-audio-refclk.yaml#
> Alphanumerical order.
>
> There is no ti,am62 in the top level compatibles, so why am62 is here?
> Top level has j721s2 but this ti,am62-audio-refclk.yaml only am62.
>
> Best regards,
> Krzysztof
The "ti,am62-audio-refclk" compatible refers to a shared audio reference
clock IP block that was first introduced/named on AM62 but is present on
other TI K3 SoCs as well, including J721S2. The compatible string
identifies the IP block, not the SoC family.
This is already an established pattern —
k3-j784s4-j742s2-main-common.dtsi uses the same compatible for the
J784S4/J742S2 audio refclk node.
The ti,j721e-system-controller.yaml binding (which covers
ti,j721s2-system-controller) already lists ti,am62-audio-refclk as an
allowed clock-controller child, which was updated in patch 1/2 of this
series to make room for this node.
Best regards,
Moteen Shah
^ permalink raw reply
* Re: [PATCH v3 1/2] ti,j721e-system-controller.yaml: Allow audio-refclk as clock-controller child
From: Krzysztof Kozlowski @ 2026-04-07 5:53 UTC (permalink / raw)
To: Moteen Shah
Cc: krzk+dt, robh, conor+dt, nm, vigneshr, kristo, devicetree,
linux-arm-kernel, linux-kernel, u-kumar1, gehariprasath,
y-abhilashchandra
In-Reply-To: <62dd6a7f-7a5b-4939-a18d-8b763f6e8f9b@ti.com>
On 07/04/2026 07:46, Moteen Shah wrote:
> Hey Krzysztof,
>
> On 31/03/26 12:39, Krzysztof Kozlowski wrote:
>> On Mon, Mar 30, 2026 at 03:14:58PM +0530, Moteen Shah wrote:
>>> The ti,j721e-system-controller binding currently only allows
>>> clock-controller@ child nodes to reference the ti,am654-ehrpwm-tbclk
>>> schema. However, the system controller on J721S2 also contains audio
>> J721S2 or AM62?
>>
>>> reference clock controllers (ti,am62-audio-refclk) that use the same
>>> clock-controller@XXXX naming pattern.
>>>
>>> Hence, extend the clock-controller pattern to accept either ehrpwm-tbclk
>>> or audio-refclk schemas using a oneOf constraint.
>>>
>>> Signed-off-by: Moteen Shah <m-shah@ti.com>
>>> ---
>>> .../bindings/soc/ti/ti,j721e-system-controller.yaml | 6 ++++--
>>> 1 file changed, 4 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml b/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
>>> index f3bd0be3b279..d5d84a8f1257 100644
>>> --- a/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
>>> +++ b/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
>>> @@ -53,9 +53,11 @@ patternProperties:
>>>
>>> "^clock-controller@[0-9a-f]+$":
>>> type: object
>>> - $ref: /schemas/clock/ti,am654-ehrpwm-tbclk.yaml#
>>> + oneOf:
>>> + - $ref: /schemas/clock/ti,am654-ehrpwm-tbclk.yaml#
>>> + - $ref: /schemas/clock/ti,am62-audio-refclk.yaml#
>> Alphanumerical order.
>>
>> There is no ti,am62 in the top level compatibles, so why am62 is here?
>> Top level has j721s2 but this ti,am62-audio-refclk.yaml only am62.
>>
>> Best regards,
>> Krzysztof
>
> The "ti,am62-audio-refclk" compatible refers to a shared audio reference
> clock IP block that was first introduced/named on AM62 but is present on
> other TI K3 SoCs as well, including J721S2. The compatible string
> identifies the IP block, not the SoC family.
>
> This is already an established pattern —
> k3-j784s4-j742s2-main-common.dtsi uses the same compatible for the
> J784S4/J742S2 audio refclk node.
Please read carefully writing-bindings doc.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v16 6/7] coresight: ctcu: enable byte-cntr for TMC ETR devices
From: Jie Gan @ 2026-04-07 5:59 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Tingwei Zhang,
Bjorn Andersson, Konrad Dybcio
Cc: coresight, linux-arm-kernel, linux-kernel, linux-arm-msm,
devicetree
In-Reply-To: <20260323-enable-byte-cntr-for-ctcu-v16-6-7a413d211b8d@oss.qualcomm.com>
On 3/23/2026 5:49 PM, Jie Gan wrote:
> The byte-cntr function provided by the CTCU device is used to transfer data
> from the ETR buffer to the userspace. An interrupt is triggered if the data
> size exceeds the threshold set in the BYTECNTRVAL register. The interrupt
> handler counts the number of triggered interruptions and the read function
> will read the data from the synced ETR buffer.
>
> Switching the sysfs_buf when current buffer is full or the timeout is
> triggered and resets rrp and rwp registers after switched the buffer.
> The synced buffer will become available for reading after the switch.
>
> Byte-cntr workflow:
> start -> ctcu_enable(ctcu_byte_cntr_start) -> tmc_enable_etr_sink ->
> tmc_read_prepare_etr(jump to tmc_read_prepare_byte_cntr) ->
> tmc_etr_get_sysfs_trace(jump to tmc_byte_cntr_get_data) ->
> tmc_disable_etr_sink -> ctcu_disable(ctcu_byte_cntr_stop) ->
> tmc_read_unprepare_etr(jump to tmc_read_unprepare_byte_cntr) -> finish
>
> Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com>
> ---
> .../ABI/testing/sysfs-bus-coresight-devices-ctcu | 9 +
> drivers/hwtracing/coresight/Makefile | 2 +-
> .../hwtracing/coresight/coresight-ctcu-byte-cntr.c | 286 +++++++++++++++++++++
> drivers/hwtracing/coresight/coresight-ctcu-core.c | 104 +++++++-
> drivers/hwtracing/coresight/coresight-ctcu.h | 79 +++++-
> drivers/hwtracing/coresight/coresight-tmc-core.c | 3 +-
> drivers/hwtracing/coresight/coresight-tmc-etr.c | 104 +++++++-
> drivers/hwtracing/coresight/coresight-tmc.h | 9 +
> 8 files changed, 571 insertions(+), 25 deletions(-)
>
[...]
> +
> +static int tmc_read_prepare_byte_cntr(struct tmc_drvdata *etr_drvdata)
> +{
> + struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata);
> + struct ctcu_byte_cntr *byte_cntr_data;
> + int ret = 0;
> +
> + /* byte-cntr is operating with SYSFS mode being enabled only */
> + if (coresight_get_mode(etr_drvdata->csdev) != CS_MODE_SYSFS)
> + return -EINVAL;
> +
> + byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev);
> + if (!byte_cntr_data || !byte_cntr_data->irq_enabled)
> + return -EINVAL;
> +
> + if (byte_cntr_data->reading)
> + return -EBUSY;
> +
Found a potential race condition here.
I should set the byte_cntr_data->reading as earlier as possible, reset
it if we suffered an issue for creating buffer list to prevent to create
the etr_buf_list twice.
After the correction:
unsigned long flags;
raw_spin_lock_irqsave(&byte_cntr_data->spin_lock, flags);
if (byte_cntr_data->reading)
return -EBUSY;
byte_cntr_data->reading = true;
raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags);
/* Setup an available etr_buf_list for byte-cntr */
ret = tmc_create_etr_buf_list(etr_drvdata, 2);
if (ret) {
byte_cntr_data->reading = false;
return ret;
}
guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
...
Thanks,
Jie
> + /* Setup an available etr_buf_list for byte-cntr */
> + ret = tmc_create_etr_buf_list(etr_drvdata, 2);
> + if (ret)
> + return ret;
> +
> + guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> + atomic_set(&byte_cntr_data->irq_cnt, 0);
> + /*
> + * Configure the byte-cntr register to enable IRQ. The configured
> + * size is 5% of the buffer_size.
> + */
> + ctcu_cfg_byte_cntr_reg(byte_cntr_data->ctcu_drvdata,
> + etr_drvdata->size / MAX_IRQ_CNT,
> + byte_cntr_data->irq_ctrl_offset);
> + enable_irq_wake(byte_cntr_data->irq);
> + byte_cntr_data->buf_node = NULL;
> + byte_cntr_data->reading = true;
> +
> + return 0;
> +}
> +
> +static int tmc_read_unprepare_byte_cntr(struct tmc_drvdata *etr_drvdata)
> +{
> + struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata);
> + struct ctcu_byte_cntr *byte_cntr_data;
> +
> + byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev);
> + if (!byte_cntr_data || !byte_cntr_data->irq_enabled)
> + return -EINVAL;
> +
> + tmc_clean_etr_buf_list(etr_drvdata);
> + guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> + /* Configure the byte-cntr register to disable IRQ */
> + ctcu_cfg_byte_cntr_reg(byte_cntr_data->ctcu_drvdata, 0,
> + byte_cntr_data->irq_ctrl_offset);
> + disable_irq_wake(byte_cntr_data->irq);
> + byte_cntr_data->buf_node = NULL;
> + byte_cntr_data->reading = false;
> +
> + return 0;
> +}
> +
> +const struct tmc_sysfs_ops byte_cntr_sysfs_ops = {
> + .read_prepare = tmc_read_prepare_byte_cntr,
> + .read_unprepare = tmc_read_unprepare_byte_cntr,
> + .get_trace_data = tmc_byte_cntr_get_data,
> +};
> +
> +/* Start the byte-cntr function when the path is enabled. */
> +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path)
> +{
> + struct coresight_device *sink = coresight_get_sink(path);
> + struct ctcu_byte_cntr *byte_cntr_data;
> +
> + byte_cntr_data = ctcu_get_byte_cntr(csdev, sink);
> + if (!byte_cntr_data)
> + return;
> +
> + /* Don't start byte-cntr function when irq_enabled is not set. */
> + if (!byte_cntr_data->irq_enabled || byte_cntr_data->enable)
> + return;
> +
> + guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> + byte_cntr_data->enable = true;
> +}
> +
> +/* Stop the byte-cntr function when the path is disabled. */
> +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path)
> +{
> + struct coresight_device *sink = coresight_get_sink(path);
> + struct ctcu_byte_cntr *byte_cntr_data;
> +
> + if (coresight_get_mode(sink) == CS_MODE_SYSFS)
> + return;
> +
> + byte_cntr_data = ctcu_get_byte_cntr(csdev, sink);
> + if (!byte_cntr_data)
> + return;
> +
> + guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> + byte_cntr_data->enable = false;
> +}
> +
> +void ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int etr_num)
> +{
> + struct ctcu_byte_cntr *byte_cntr_data;
> + struct device_node *nd = dev->of_node;
> + int irq_num, ret, i;
> +
> + tmc_etr_set_byte_cntr_sysfs_ops(&byte_cntr_sysfs_ops);
> + for (i = 0; i < etr_num; i++) {
> + byte_cntr_data = &drvdata->byte_cntr_data[i];
> + irq_num = of_irq_get(nd, i);
> + if (irq_num < 0) {
> + dev_err(dev, "Failed to get IRQ from DT for port%d\n", i);
> + continue;
> + }
> +
> + ret = devm_request_irq(dev, irq_num, byte_cntr_handler,
> + IRQF_TRIGGER_RISING | IRQF_SHARED,
> + dev_name(dev), byte_cntr_data);
> + if (ret) {
> + dev_err(dev, "Failed to register IRQ for port%d\n", i);
> + continue;
> + }
> +
> + byte_cntr_data->irq = irq_num;
> + byte_cntr_data->ctcu_drvdata = drvdata;
> + init_waitqueue_head(&byte_cntr_data->wq);
> + raw_spin_lock_init(&byte_cntr_data->spin_lock);
> + }
> +}
> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
> index e8720026c9e3..56590f22ad79 100644
> --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
> +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /*
> - * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2024-2026 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> */
>
> #include <linux/clk.h>
> @@ -18,6 +19,7 @@
>
> #include "coresight-ctcu.h"
> #include "coresight-priv.h"
> +#include "coresight-tmc.h"
>
> #define ctcu_writel(drvdata, val, offset) __raw_writel((val), drvdata->base + offset)
> #define ctcu_readl(drvdata, offset) __raw_readl(drvdata->base + offset)
> @@ -43,17 +45,21 @@
>
> #define CTCU_ATID_REG_BIT(traceid) (traceid % 32)
> #define CTCU_ATID_REG_SIZE 0x10
> +#define CTCU_ETR0_IRQCTRL 0x6c
> +#define CTCU_ETR1_IRQCTRL 0x70
> #define CTCU_ETR0_ATID0 0xf8
> #define CTCU_ETR1_ATID0 0x108
>
> static const struct ctcu_etr_config sa8775p_etr_cfgs[] = {
> {
> - .atid_offset = CTCU_ETR0_ATID0,
> - .port_num = 0,
> + .atid_offset = CTCU_ETR0_ATID0,
> + .irq_ctrl_offset = CTCU_ETR0_IRQCTRL,
> + .port_num = 0,
> },
> {
> - .atid_offset = CTCU_ETR1_ATID0,
> - .port_num = 1,
> + .atid_offset = CTCU_ETR1_ATID0,
> + .irq_ctrl_offset = CTCU_ETR1_IRQCTRL,
> + .port_num = 1,
> },
> };
>
> @@ -62,6 +68,85 @@ static const struct ctcu_config sa8775p_cfgs = {
> .num_etr_config = ARRAY_SIZE(sa8775p_etr_cfgs),
> };
>
> +void ctcu_program_register(struct ctcu_drvdata *drvdata, u32 val, u32 offset)
> +{
> + CS_UNLOCK(drvdata->base);
> + ctcu_writel(drvdata, val, offset);
> + CS_LOCK(drvdata->base);
> +}
> +
> +static ssize_t irq_enabled_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct ctcu_byte_cntr_irq_attribute *irq_attr =
> + container_of(attr, struct ctcu_byte_cntr_irq_attribute, attr);
> + struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> + u8 port = irq_attr->port;
> +
> + if (!drvdata->byte_cntr_data[port].irq_ctrl_offset)
> + return -EINVAL;
> +
> + return sysfs_emit(buf, "%u\n",
> + (unsigned int)drvdata->byte_cntr_data[port].irq_enabled);
> +}
> +
> +static ssize_t irq_enabled_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf,
> + size_t size)
> +{
> + struct ctcu_byte_cntr_irq_attribute *irq_attr =
> + container_of(attr, struct ctcu_byte_cntr_irq_attribute, attr);
> + struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> + u8 port = irq_attr->port;
> + unsigned long val;
> +
> + if (kstrtoul(buf, 0, &val))
> + return -EINVAL;
> +
> + guard(raw_spinlock_irqsave)(&drvdata->spin_lock);
> + if (drvdata->byte_cntr_data[port].reading)
> + return -EBUSY;
> + else if (drvdata->byte_cntr_data[port].irq_ctrl_offset)
> + drvdata->byte_cntr_data[port].irq_enabled = !!val;
> +
> + return size;
> +}
> +
> +static umode_t irq_enabled_is_visible(struct kobject *kobj,
> + struct attribute *attr, int n)
> +{
> + struct device_attribute *dev_attr =
> + container_of(attr, struct device_attribute, attr);
> + struct ctcu_byte_cntr_irq_attribute *irq_attr =
> + container_of(dev_attr, struct ctcu_byte_cntr_irq_attribute, attr);
> + struct device *dev = kobj_to_dev(kobj);
> + struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> + u8 port = irq_attr->port;
> +
> + if (drvdata && drvdata->byte_cntr_data[port].irq_ctrl_offset)
> + return attr->mode;
> +
> + return 0;
> +}
> +
> +static struct attribute *ctcu_attrs[] = {
> + ctcu_byte_cntr_irq_rw(0),
> + ctcu_byte_cntr_irq_rw(1),
> + NULL,
> +};
> +
> +static struct attribute_group ctcu_attr_grp = {
> + .attrs = ctcu_attrs,
> + .is_visible = irq_enabled_is_visible,
> +};
> +
> +static const struct attribute_group *ctcu_attr_grps[] = {
> + &ctcu_attr_grp,
> + NULL,
> +};
> +
> static void ctcu_program_atid_register(struct ctcu_drvdata *drvdata, u32 reg_offset,
> u8 bit, bool enable)
> {
> @@ -140,11 +225,15 @@ static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight
> static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode,
> struct coresight_path *path)
> {
> + ctcu_byte_cntr_start(csdev, path);
> +
> return ctcu_set_etr_traceid(csdev, path, true);
> }
>
> static int ctcu_disable(struct coresight_device *csdev, struct coresight_path *path)
> {
> + ctcu_byte_cntr_stop(csdev, path);
> +
> return ctcu_set_etr_traceid(csdev, path, false);
> }
>
> @@ -195,7 +284,10 @@ static int ctcu_probe(struct platform_device *pdev)
> for (i = 0; i < cfgs->num_etr_config; i++) {
> etr_cfg = &cfgs->etr_cfgs[i];
> drvdata->atid_offset[i] = etr_cfg->atid_offset;
> + drvdata->byte_cntr_data[i].irq_ctrl_offset =
> + etr_cfg->irq_ctrl_offset;
> }
> + ctcu_byte_cntr_init(dev, drvdata, cfgs->num_etr_config);
> }
> }
>
> @@ -209,6 +301,7 @@ static int ctcu_probe(struct platform_device *pdev)
> desc.dev = dev;
> desc.ops = &ctcu_ops;
> desc.access = CSDEV_ACCESS_IOMEM(base);
> + desc.groups = ctcu_attr_grps;
> raw_spin_lock_init(&drvdata->spin_lock);
>
> drvdata->csdev = coresight_register(&desc);
> @@ -248,6 +341,7 @@ static void ctcu_platform_remove(struct platform_device *pdev)
> if (WARN_ON(!drvdata))
> return;
>
> + tmc_etr_reset_byte_cntr_sysfs_ops();
> ctcu_remove(pdev);
> pm_runtime_disable(&pdev->dev);
> }
> diff --git a/drivers/hwtracing/coresight/coresight-ctcu.h b/drivers/hwtracing/coresight/coresight-ctcu.h
> index e9594c38dd91..a2ae0a0d91d0 100644
> --- a/drivers/hwtracing/coresight/coresight-ctcu.h
> +++ b/drivers/hwtracing/coresight/coresight-ctcu.h
> @@ -1,23 +1,31 @@
> /* SPDX-License-Identifier: GPL-2.0-only */
> /*
> - * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2024-2026 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> */
>
> #ifndef _CORESIGHT_CTCU_H
> #define _CORESIGHT_CTCU_H
> +
> +#include <linux/time.h>
> #include "coresight-trace-id.h"
>
> /* Maximum number of supported ETR devices for a single CTCU. */
> #define ETR_MAX_NUM 2
>
> +#define BYTE_CNTR_TIMEOUT (3 * HZ)
> +#define MAX_IRQ_CNT 20
> +
> /**
> * struct ctcu_etr_config
> * @atid_offset: offset to the ATID0 Register.
> - * @port_num: in-port number of CTCU device that connected to ETR.
> + * @port_num: in-port number of the CTCU device that connected to ETR.
> + * @irq_ctrl_offset: offset to the BYTECNTRVAL register.
> */
> struct ctcu_etr_config {
> const u32 atid_offset;
> const u32 port_num;
> + const u32 irq_ctrl_offset;
> };
>
> struct ctcu_config {
> @@ -25,15 +33,68 @@ struct ctcu_config {
> int num_etr_config;
> };
>
> -struct ctcu_drvdata {
> - void __iomem *base;
> - struct clk *apb_clk;
> - struct device *dev;
> - struct coresight_device *csdev;
> +/**
> + * struct ctcu_byte_cntr
> + * @enable: indicates that byte_cntr function is enabled or not.
> + * @irq_enabled: indicates that the interruption is enabled.
> + * @reading: indicates that byte_cntr is reading.
> + * @irq: allocated number of the IRQ.
> + * @irq_cnt: IRQ count number of the triggered interruptions.
> + * @wq: waitqueue for reading data from ETR buffer.
> + * @spin_lock: spinlock of the byte_cntr_data.
> + * @irq_ctrl_offset: offset to the BYTECNTVAL Register.
> + * @ctcu_drvdata: drvdata of the CTCU device.
> + * @buf_node: etr_buf_node for reading.
> + */
> +struct ctcu_byte_cntr {
> + bool enable;
> + bool irq_enabled;
> + bool reading;
> + int irq;
> + atomic_t irq_cnt;
> + wait_queue_head_t wq;
> raw_spinlock_t spin_lock;
> - u32 atid_offset[ETR_MAX_NUM];
> + u32 irq_ctrl_offset;
> + struct ctcu_drvdata *ctcu_drvdata;
> + struct etr_buf_node *buf_node;
> +};
> +
> +struct ctcu_drvdata {
> + void __iomem *base;
> + struct clk *apb_clk;
> + struct device *dev;
> + struct coresight_device *csdev;
> + struct ctcu_byte_cntr byte_cntr_data[ETR_MAX_NUM];
> + raw_spinlock_t spin_lock;
> + u32 atid_offset[ETR_MAX_NUM];
> /* refcnt for each traceid of each sink */
> - u8 traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP];
> + u8 traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP];
> };
>
> +/**
> + * struct ctcu_byte_cntr_irq_attribute
> + * @attr: The device attribute.
> + * @port: port number.
> + */
> +struct ctcu_byte_cntr_irq_attribute {
> + struct device_attribute attr;
> + u8 port;
> +};
> +
> +#define ctcu_byte_cntr_irq_rw(port) \
> + (&((struct ctcu_byte_cntr_irq_attribute[]) { \
> + { \
> + __ATTR(irq_enabled##port, 0644, irq_enabled_show, \
> + irq_enabled_store), \
> + port, \
> + } \
> + })[0].attr.attr)
> +
> +void ctcu_program_register(struct ctcu_drvdata *drvdata, u32 val, u32 offset);
> +
> +/* Byte-cntr functions */
> +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path);
> +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path);
> +void ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int port_num);
> +
> #endif
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
> index 110eedde077f..9f4fd86e8c32 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-core.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
> @@ -293,7 +293,8 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
> return -EFAULT;
> }
>
> - *ppos += actual;
> + if (!tmc_etr_update_buf_node_pos(drvdata, actual))
> + *ppos += actual;
> dev_dbg(&drvdata->csdev->dev, "%zu bytes copied\n", actual);
>
> return actual;
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index d4a99c77dd90..3253964d1ce7 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -1168,6 +1168,8 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
> return rc;
> }
>
> +static const struct tmc_sysfs_ops *byte_cntr_sysfs_ops;
> +
> /*
> * Return the available trace data in the buffer (starts at etr_buf->offset,
> * limited by etr_buf->len) from @pos, with a maximum limit of @len,
> @@ -1178,23 +1180,39 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
> * We are protected here by drvdata->reading != 0, which ensures the
> * sysfs_buf stays alive.
> */
> -ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata,
> - loff_t pos, size_t len, char **bufpp)
> +ssize_t tmc_etr_read_sysfs_buf(struct etr_buf *sysfs_buf, loff_t pos,
> + size_t len, char **bufpp)
> {
> s64 offset;
> ssize_t actual = len;
> - struct etr_buf *etr_buf = drvdata->sysfs_buf;
>
> - if (pos + actual > etr_buf->len)
> - actual = etr_buf->len - pos;
> + if (pos + actual > sysfs_buf->len)
> + actual = sysfs_buf->len - pos;
> if (actual <= 0)
> return actual;
>
> /* Compute the offset from which we read the data */
> - offset = etr_buf->offset + pos;
> - if (offset >= etr_buf->size)
> - offset -= etr_buf->size;
> - return tmc_etr_buf_get_data(etr_buf, offset, actual, bufpp);
> + offset = sysfs_buf->offset + pos;
> + if (offset >= sysfs_buf->size)
> + offset -= sysfs_buf->size;
> + return tmc_etr_buf_get_data(sysfs_buf, offset, actual, bufpp);
> +}
> +EXPORT_SYMBOL_GPL(tmc_etr_read_sysfs_buf);
> +
> +ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata,
> + loff_t pos, size_t len, char **bufpp)
> +{
> + ssize_t ret;
> +
> + if (byte_cntr_sysfs_ops) {
> + ret = byte_cntr_sysfs_ops->get_trace_data(drvdata, pos,
> + len, bufpp);
> + /* Return the filled buffer */
> + if (ret > 0 || ret == -ENOMEM)
> + return ret;
> + }
> +
> + return tmc_etr_read_sysfs_buf(drvdata->sysfs_buf, pos, len, bufpp);
> }
>
> static struct etr_buf *
> @@ -1248,6 +1266,33 @@ static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
>
> }
>
> +static void tmc_etr_reset_sysfs_buf(struct tmc_drvdata *drvdata)
> +{
> + u32 sts;
> +
> + CS_UNLOCK(drvdata->base);
> + tmc_write_rrp(drvdata, drvdata->sysfs_buf->hwaddr);
> + tmc_write_rwp(drvdata, drvdata->sysfs_buf->hwaddr);
> + sts = readl_relaxed(drvdata->base + TMC_STS) & ~TMC_STS_FULL;
> + writel_relaxed(sts, drvdata->base + TMC_STS);
> + CS_LOCK(drvdata->base);
> +}
> +
> +/**
> + * tmc_etr_enable_disable_hw - enable/disable the ETR hw.
> + * @drvdata: drvdata of the TMC device.
> + * @enable: indicates enable/disable.
> + */
> +void tmc_etr_enable_disable_hw(struct tmc_drvdata *drvdata, bool enable)
> +{
> + if (enable) {
> + tmc_etr_reset_sysfs_buf(drvdata);
> + __tmc_etr_enable_hw(drvdata);
> + } else
> + __tmc_etr_disable_hw(drvdata);
> +}
> +EXPORT_SYMBOL_GPL(tmc_etr_enable_disable_hw);
> +
> void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
> {
> __tmc_etr_disable_hw(drvdata);
> @@ -2040,6 +2085,35 @@ int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes)
> }
> EXPORT_SYMBOL_GPL(tmc_create_etr_buf_list);
>
> +void tmc_etr_set_byte_cntr_sysfs_ops(const struct tmc_sysfs_ops *sysfs_ops)
> +{
> + byte_cntr_sysfs_ops = sysfs_ops;
> +}
> +EXPORT_SYMBOL_GPL(tmc_etr_set_byte_cntr_sysfs_ops);
> +
> +void tmc_etr_reset_byte_cntr_sysfs_ops(void)
> +{
> + byte_cntr_sysfs_ops = NULL;
> +}
> +EXPORT_SYMBOL_GPL(tmc_etr_reset_byte_cntr_sysfs_ops);
> +
> +bool tmc_etr_update_buf_node_pos(struct tmc_drvdata *drvdata, ssize_t size)
> +{
> + struct etr_buf_node *nd, *next;
> +
> + if (drvdata->config_type != TMC_CONFIG_TYPE_ETR)
> + return false;
> +
> + list_for_each_entry_safe(nd, next, &drvdata->etr_buf_list, link) {
> + if (nd && nd->reading) {
> + nd->pos += size;
> + return true;
> + }
> + }
> +
> + return false;
> +}
> +
> int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
> {
> int ret = 0;
> @@ -2049,6 +2123,14 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
> if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
> return -EINVAL;
>
> + if (byte_cntr_sysfs_ops) {
> + ret = byte_cntr_sysfs_ops->read_prepare(drvdata);
> + if (!ret || ret == -EBUSY)
> + return ret;
> +
> + ret = 0;
> + }
> +
> raw_spin_lock_irqsave(&drvdata->spinlock, flags);
> if (drvdata->reading) {
> ret = -EBUSY;
> @@ -2085,6 +2167,10 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
> if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
> return -EINVAL;
>
> + if (byte_cntr_sysfs_ops)
> + if (!byte_cntr_sysfs_ops->read_unprepare(drvdata))
> + return 0;
> +
> raw_spin_lock_irqsave(&drvdata->spinlock, flags);
>
> /* RE-enable the TMC if need be */
> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
> index fbb015079872..a15e2f93f16a 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc.h
> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
> @@ -211,12 +211,15 @@ struct tmc_resrv_buf {
> /**
> * @sysfs_buf: Allocated sysfs_buf.
> * @is_free: Indicates whether the buffer is free to choose.
> + * @reading: Indicates byte_cntr is reading the buffer attached to
> + * the node.
> * @pos: Offset to the start of the buffer.
> * @link: list_head of the node.
> */
> struct etr_buf_node {
> struct etr_buf *sysfs_buf;
> bool is_free;
> + bool reading;
> loff_t pos;
> struct list_head link;
> };
> @@ -480,5 +483,11 @@ struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
> extern const struct attribute_group coresight_etr_group;
> void tmc_clean_etr_buf_list(struct tmc_drvdata *drvdata);
> int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes);
> +void tmc_etr_set_byte_cntr_sysfs_ops(const struct tmc_sysfs_ops *sysfs_ops);
> +void tmc_etr_reset_byte_cntr_sysfs_ops(void);
> +void tmc_etr_enable_disable_hw(struct tmc_drvdata *drvdata, bool enable);
> +bool tmc_etr_update_buf_node_pos(struct tmc_drvdata *drvdata, ssize_t size);
> +ssize_t tmc_etr_read_sysfs_buf(struct etr_buf *sysfs_buf, loff_t pos,
> + size_t len, char **bufpp);
>
> #endif
>
^ permalink raw reply
* Re: [PATCH 3/3] arm64: dts: imx8mp-ab2: Correct interrupt flags
From: Daniel Baluta @ 2026-04-07 6:13 UTC (permalink / raw)
To: Krzysztof Kozlowski, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Marek Vasut, Peng Fan, Fedor Ross, Shawn Guo,
Shengjiu Wang, Viorel Suman, devicetree, imx, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260406063810.25531-6-krzysztof.kozlowski@oss.qualcomm.com>
On 4/6/26 09:38, Krzysztof Kozlowski wrote:
> GPIO_ACTIVE_x flags are not correct in the context of interrupt flags.
> These are simple defines so they could be used in DTS but they will not
> have the same meaning:
> 1. GPIO_ACTIVE_HIGH = 0 => IRQ_TYPE_NONE
> 2. GPIO_ACTIVE_LOW = 1 => IRQ_TYPE_EDGE_RISING
>
> Correct the interrupt flags, assuming the author of the code wanted the
> same logical behavior behind the name "ACTIVE_xxx", this is:
> ACTIVE_LOW => IRQ_TYPE_LEVEL_LOW
>
> Fixes: bf68c18150ef ("arm64: dts: imx8mp-ab2: add support for NXP i.MX8MP audio board (version 2)")
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
^ permalink raw reply
* Re: [PATCH 6/6] mm: change to return bool for the MMU notifier's young flag check
From: Baolin Wang @ 2026-04-07 6:23 UTC (permalink / raw)
To: Sean Christopherson
Cc: Lorenzo Stoakes (Oracle), akpm, david, Liam.Howlett, vbabka, rppt,
surenb, mhocko, linux-arm-kernel, x86, linux-parisc, linuxppc-dev,
linux-riscv, linux-s390, kvm, open, linux-kernel
In-Reply-To: <adBJTXeE6G2vQNKX@google.com>
On 4/4/26 7:12 AM, Sean Christopherson wrote:
> On Fri, Mar 20, 2026, Baolin Wang wrote:
>>>> -static __always_inline int kvm_age_hva_range(struct mmu_notifier *mn,
>>>> - unsigned long start,
>>>> - unsigned long end,
>>>> - gfn_handler_t handler,
>>>> - bool flush_on_ret)
>>>> +static __always_inline bool kvm_age_hva_range(struct mmu_notifier *mn,
>>>> + unsigned long start,
>>>> + unsigned long end,
>>>> + gfn_handler_t handler,
>>>> + bool flush_on_ret)
>>>
>>> Can we please fix this terrrible indentation while we're here :)?
>>>
>>> static __always_inline bool kvm_age_hva_range(struct mmu_notifier *mn,
>>> unsigned long start, unsigned long end, gfn_handler_t handler,
>>> bool flush_on_ret)
>>>
>>> Would be nicer, thanks!
>
> No, please keep this as-is. KVM's preferred style is exactly this (and I personally
> find mm's style much harder to parse).
Um, Andrew has already queued v2[1] into the mm-stable branch. Do you
want me to send a follow-up patch to restore the original KVM coding style?
[1]
https://lore.kernel.org/all/cover.1774075004.git.baolin.wang@linux.alibaba.com/T/#u
^ permalink raw reply
* Re: [PATCH v2 1/2] drm: lcdif: Set undocumented bit to clear FIFO at vsync
From: Liu Ying @ 2026-04-07 6:31 UTC (permalink / raw)
To: Paul Kocialkowski, dri-devel, imx, linux-arm-kernel, linux-kernel
Cc: Marek Vasut, Stefan Agner, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Lucas Stach,
Krzysztof Hałasa, Marco Felsch
In-Reply-To: <20260402183351.3281123-2-paulk@sys-base.io>
On Thu, Apr 02, 2026 at 08:33:50PM +0200, Paul Kocialkowski wrote:
> There is an undocumented bit used in the NXP BSP to clear the FIFO
> systematically at vsync. In normal operation, the FIFO should already
> be empty but it doesn't hurt to add it as an extra safety measure.
>
> Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
> Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
> ---
> drivers/gpu/drm/mxsfb/lcdif_kms.c | 3 ++-
> drivers/gpu/drm/mxsfb/lcdif_regs.h | 1 +
> 2 files changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Liu Ying <victor.liu@nxp.com>
Thanks!
--
Regards,
Liu Ying
^ permalink raw reply
* Re: [PATCH v4 1/4] dt-bindings: arm: hpe,gxp: Add HPE GSC platform compatible
From: Krzysztof Kozlowski @ 2026-04-07 6:31 UTC (permalink / raw)
To: nick.hawkins
Cc: catalin.marinas, will, robh, krzk+dt, conor+dt, linux-arm-kernel,
devicetree, linux-kernel
In-Reply-To: <20260406143821.1843621-2-nick.hawkins@hpe.com>
On Mon, Apr 06, 2026 at 02:38:18PM +0000, nick.hawkins@hpe.com wrote:
> From: Nick Hawkins <nick.hawkins@hpe.com>
>
> From: Nick Hawkins <nick.hawkins@hpe.com>
Duplicated From parts.
With this fixed:
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 2/2] drm: lcdif: Wait for vblank before disabling DMA
From: Liu Ying @ 2026-04-07 6:34 UTC (permalink / raw)
To: Paul Kocialkowski, dri-devel, imx, linux-arm-kernel, linux-kernel
Cc: Marek Vasut, Stefan Agner, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Lucas Stach,
Krzysztof Hałasa, Marco Felsch
In-Reply-To: <20260402183351.3281123-3-paulk@sys-base.io>
Hi Paul,
On Thu, Apr 02, 2026 at 08:33:51PM +0200, Paul Kocialkowski wrote:
> It is necessary to wait for the full frame to finish streaming
> through the DMA engine before we can safely disable it by removing
> the DISP_PARA_DISP_ON bit. Disabling it in-flight can leave the
> hardware confused and unable to resume streaming for the next frame.
>
> This causes the FIFO underrun and empty status bits to be set and
> a single solid color to be shown on the display, coming from one of
> the pixels of the previous frame. The issue occurs sporadically when
> a new mode is set, which triggers the crtc disable and enable paths.
>
> Setting the shadow load bit and waiting for it to be cleared by the
> DMA engine allows waiting for completion.
>
> The NXP BSP driver addresses this issue with a hardcoded 25 ms sleep.
>
> Fixes: 9db35bb349a0 ("drm: lcdif: Add support for i.MX8MP LCDIF variant")
> Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
> Co-developed-by: Lucas Stach <l.stach@pengutronix.de>
There is a warning reported by checkpatch.pl:
WARNING: Co-developed-by: must be immediately followed by Signed-off-by:
#23:
Co-developed-by: Lucas Stach <l.stach@pengutronix.de>
With this fixed:
Acked-by: Liu Ying <victor.liu@nxp.com>
Thanks!
--
Regards,
Liu Ying
^ permalink raw reply
* Re: [PATCH v3] ACPI: AGDI: fix missing newline in error message
From: Hanjun Guo @ 2026-04-07 6:36 UTC (permalink / raw)
To: Haoyu Lu, Rafael J . Wysocki, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon
Cc: Len Brown, Ilkka Koskinen, Russell King, linux-acpi,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260407033117.100-1-hechushiguitu666@gmail.com>
On 2026/4/7 11:31, Haoyu Lu wrote:
> Add the missing trailing newline to the dev_err() message
> printed when SDEI event registration fails.
>
> This keeps the error output as a properly terminated log line.
>
> Fixes: a2a591fb76e6f5461dfd04715b69c317e50c43a5 ("ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset device")
> Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
> Signed-off-by: Haoyu Lu <hechushiguitu666@gmail.com>
> ---
> Changes in v2:
> - Change subject prefix from "acpi: arm64: agdi:" to "ACPI: AGDI:"
>
> Changes in v3:
> - Move version history below the "---" separator as per review feedback
>
> drivers/acpi/arm64/agdi.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/acpi/arm64/agdi.c b/drivers/acpi/arm64/agdi.c
> index feb4b2cb4618..0c2d9d6c160b 100644
> --- a/drivers/acpi/arm64/agdi.c
> +++ b/drivers/acpi/arm64/agdi.c
> @@ -36,7 +36,7 @@ static int agdi_sdei_probe(struct platform_device *pdev,
>
> err = sdei_event_register(adata->sdei_event, agdi_sdei_handler, pdev);
> if (err) {
> - dev_err(&pdev->dev, "Failed to register for SDEI event %d",
> + dev_err(&pdev->dev, "Failed to register for SDEI event %d\n",
> adata->sdei_event);
> return err;
> }
Reviewed-by: Hanjun Guo <guohanjun@huawei.com>
Thanks
Hanjun
^ permalink raw reply
* RE: [PATCH V10 04/13] PCI: imx6: Assert PERST# before enabling regulators
From: Sherry Sun @ 2026-04-07 6:38 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
Frank Li, s.hauer@pengutronix.de, kernel@pengutronix.de,
festevam@gmail.com, lpieralisi@kernel.org, kwilczynski@kernel.org,
bhelgaas@google.com, Hongxing Zhu, l.stach@pengutronix.de,
imx@lists.linux.dev, linux-pci@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <jwazawvhuoafkhfwpjfgccc3hz6kej7i6iwkh5be2qena2b4di@yzv6e75zezfu>
> On Thu, Apr 02, 2026 at 05:50:58PM +0800, Sherry Sun wrote:
> > According to the PCIe initialization requirements, PERST# signal
> > should be asserted before applying power to the PCIe device, and
> > deasserted after power and reference clock are stable.
> >
>
> Spec wording is not quite like this. Spec mandates asserting PERST# *before*
> stopping refclk and powering down the device and deasserting it *after*
> applying power and refclk stable.
>
> I believe you want to assert PERST# before enabling regulator to prevent the
> endpoint from functioning? If so, is it due to refclk not available yet or some
> other reason?
You are right. My commit message wording was not that precise.
The PCIe endpoint may start responding or driving signals as
soon as its supply is enabled, even before the reference clock is stable.
Asserting PERST# before enabling the regulator ensures that the endpoint
remains in reset throughout the entire power-up sequence, until both
power and refclk are known to be stable and link initialization can safely
begin. This is mainly to avoid undefined behavior during early power-up.
I will update the commit message to better reflect this.
>
> > Currently, the driver enables the vpcie3v3aux regulator in
> > imx_pcie_probe() before PERST# is asserted in imx_pcie_host_init(),
> > which violates the PCIe power sequencing requirements. However, there
> > is no issue so far because PERST# is requested as GPIOD_OUT_HIGH in
> > imx_pcie_probe(), which guarantees that PERST# is asserted before
> > enabling the vpcie3v3aux regulator.
> >
> > This is prepare for the upcoming changes that will parse the reset
> > property using the new Root Port binding, which will use GPIOD_ASIS
> > when requesting the reset GPIO. With GPIOD_ASIS, the GPIO state is not
> > guaranteed, so explicit sequencing is required.
> >
> > Fix the power sequencing by:
> > 1. Moving vpcie3v3aux regulator enable from probe to
> > imx_pcie_host_init(), where it can be properly sequenced with PERST#.
> > 2. Moving imx_pcie_assert_perst() before regulator and clock enable to
> > ensure correct ordering.
> >
> > The vpcie3v3aux regulator is kept enabled for the entire PCIe
> > controller lifecycle and automatically disabled on device removal via devm
> cleanup.
> >
>
> vpcie3v3aux handling should be in a separate patch.
Actually the handling of vpcie3v3aux itself remains unchanged, I just adjust the
sequence of regulator/clock enable and perst#.
Previously, the imx driver enabled the vpcie3v3aux regulator in imx_pcie_probe()
before PERST# is asserted in imx_pcie_host_init(), which violates the PCIe power
sequencing requirements.
This patch moves vpcie3v3aux regulator enable from probe to imx_pcie_host_init(),
where it can be properly sequenced with PERST#.
Perhaps I should just remove this description to avoid confusion.
Best Regards
Sherry
>
> - Mani
>
> > Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
> > ---
> > drivers/pci/controller/dwc/pci-imx6.c | 49
> > +++++++++++++++++++++------
> > 1 file changed, 39 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > b/drivers/pci/controller/dwc/pci-imx6.c
> > index 45d70ae7e04f..948ffb75d122 100644
> > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > @@ -166,6 +166,8 @@ struct imx_pcie {
> > u32 tx_swing_full;
> > u32 tx_swing_low;
> > struct regulator *vpcie;
> > + struct regulator *vpcie_aux;
> > + bool vpcie_aux_enabled;
> > struct regulator *vph;
> > void __iomem *phy_base;
> >
> > @@ -1220,6 +1222,13 @@ static void imx_pcie_disable_device(struct
> pci_host_bridge *bridge,
> > imx_pcie_remove_lut(imx_pcie, pci_dev_id(pdev)); }
> >
> > +static void imx_pcie_vpcie_aux_disable(void *data) {
> > + struct regulator *vpcie_aux = data;
> > +
> > + regulator_disable(vpcie_aux);
> > +}
> > +
> > static void imx_pcie_assert_perst(struct imx_pcie *imx_pcie, bool
> > assert) {
> > if (assert) {
> > @@ -1240,6 +1249,24 @@ static int imx_pcie_host_init(struct dw_pcie_rp
> *pp)
> > struct imx_pcie *imx_pcie = to_imx_pcie(pci);
> > int ret;
> >
> > + imx_pcie_assert_perst(imx_pcie, true);
> > +
> > + /* Keep 3.3Vaux supply enabled for the entire PCIe controller lifecycle
> */
> > + if (imx_pcie->vpcie_aux && !imx_pcie->vpcie_aux_enabled) {
> > + ret = regulator_enable(imx_pcie->vpcie_aux);
> > + if (ret) {
> > + dev_err(dev, "failed to enable vpcie_aux
> regulator: %d\n",
> > + ret);
> > + return ret;
> > + }
> > + imx_pcie->vpcie_aux_enabled = true;
> > +
> > + ret = devm_add_action_or_reset(dev,
> imx_pcie_vpcie_aux_disable,
> > + imx_pcie->vpcie_aux);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > if (imx_pcie->vpcie) {
> > ret = regulator_enable(imx_pcie->vpcie);
> > if (ret) {
> > @@ -1249,25 +1276,24 @@ static int imx_pcie_host_init(struct dw_pcie_rp
> *pp)
> > }
> > }
> >
> > + ret = imx_pcie_clk_enable(imx_pcie);
> > + if (ret) {
> > + dev_err(dev, "unable to enable pcie clocks: %d\n", ret);
> > + goto err_reg_disable;
> > + }
> > +
> > if (pp->bridge && imx_check_flag(imx_pcie,
> IMX_PCIE_FLAG_HAS_LUT)) {
> > pp->bridge->enable_device = imx_pcie_enable_device;
> > pp->bridge->disable_device = imx_pcie_disable_device;
> > }
> >
> > imx_pcie_assert_core_reset(imx_pcie);
> > - imx_pcie_assert_perst(imx_pcie, true);
> >
> > if (imx_pcie->drvdata->init_phy)
> > imx_pcie->drvdata->init_phy(imx_pcie);
> >
> > imx_pcie_configure_type(imx_pcie);
> >
> > - ret = imx_pcie_clk_enable(imx_pcie);
> > - if (ret) {
> > - dev_err(dev, "unable to enable pcie clocks: %d\n", ret);
> > - goto err_reg_disable;
> > - }
> > -
> > if (imx_pcie->phy) {
> > ret = phy_init(imx_pcie->phy);
> > if (ret) {
> > @@ -1780,9 +1806,12 @@ static int imx_pcie_probe(struct platform_device
> *pdev)
> > of_property_read_u32(node, "fsl,max-link-speed", &pci-
> >max_link_speed);
> > imx_pcie->supports_clkreq = of_property_read_bool(node,
> > "supports-clkreq");
> >
> > - ret = devm_regulator_get_enable_optional(&pdev->dev,
> "vpcie3v3aux");
> > - if (ret < 0 && ret != -ENODEV)
> > - return dev_err_probe(dev, ret, "failed to enable Vaux
> supply\n");
> > + imx_pcie->vpcie_aux = devm_regulator_get_optional(&pdev->dev,
> "vpcie3v3aux");
> > + if (IS_ERR(imx_pcie->vpcie_aux)) {
> > + if (PTR_ERR(imx_pcie->vpcie_aux) != -ENODEV)
> > + return PTR_ERR(imx_pcie->vpcie_aux);
> > + imx_pcie->vpcie_aux = NULL;
> > + }
> >
> > imx_pcie->vpcie = devm_regulator_get_optional(&pdev->dev,
> "vpcie");
> > if (IS_ERR(imx_pcie->vpcie)) {
> > --
> > 2.37.1
> >
>
> --
> மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH v5 0/7] pinctrl: Add generic pinctrl for board-level mux chips
From: Linus Walleij @ 2026-04-07 6:42 UTC (permalink / raw)
To: Frank Li, Peter Rosin
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Rafał Miłecki, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, linux-kernel, linux-gpio, devicetree, imx,
linux-arm-kernel, Haibo Chen, Conor Dooley, Ahmad Fatoum
In-Reply-To: <20260327-pinctrl-mux-v5-0-d4aec9d62c62@nxp.com>
Hi Frank,
OK let's apply it!
On Fri, Mar 27, 2026 at 10:34 PM Frank Li <Frank.Li@nxp.com> wrote:
> mux: add devm_mux_control_get_from_np() to get mux from child node
Didn't get an ACK from the mux maintainer for this but this has been going
on for long now so I applied it.
Peter: protest if you don't like this and I will back it out.
> dt-bindings: pinctrl: Add generic pinctrl for board-level mux chips
> pinctrl: extract pinctrl_generic_to_map() from pinctrl_generic_pins_function_dt_node_to_map()
> pinctrl: add optional .release_mux() callback
> pinctrl: add generic board-level pinctrl driver using mux framework
Those applied.
> arm64: dts: imx8mp-evk: add board-level mux for CAN2 and MICFIL
> arm64: dts: imx8mp-evk: add flexcan2 overlay file
Please funnel these through the SoC tree!
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v2 0/3] i2c: ma35d1: Add support for MA35D1 I2C controller
From: zychen @ 2026-04-07 6:45 UTC (permalink / raw)
To: andi.shyti, ychuang3
Cc: robh, krzk+dt, conor+dt, linux-i2c, devicetree, linux-arm-kernel,
Krzysztof Kozlowski
In-Reply-To: <20260316063726.41048-1-zychennvt@gmail.com>
Hi Andi and Krzysztof,
I'm following up on this series. As detailed in the change log, v2 addresses the feedback from v1 regarding the modernization of legacy code.
I am preparing v3 to address minor formatting issues in Patch 3 (DTS). Before sending it out, I would highly appreciate any technical feedback on the driver logic in Patch 2 to ensure it aligns with your expectations.
Best regards,
Zi-Yu
Zi-Yu Chen 於 2026/3/16 下午 02:37 寫道:
> This series adds support for the I2C controller found in the Nuvoton
> MA35D1 SoC. The driver supports controller and optional target mode
> and runtime power management.
>
> The implementation has been tested on the Nuvoton MA35D1 SOM board.
>
> Changes in v2:
> - Overall:
> - Rebase on linux-i2c/i2c-next
> - Switched terminology from "master/slave" to "controller/target".
>
> - Patch 1 (dt-bindings):
> - Simplified description and fixed 'reg' size in example.
>
> - Patch 2 (driver):
> - Modernized using devm_*, generic device properties, and FIELD_PREP/GENMASK.
> - Optimized power management by moving clock control to runtime PM.
> - Simplified code by removing redundant .remove(), .owner, and inlines.
> - Added dev_err_probe() and default bus frequency handling.
>
> - Patch 3 (dts):
> - Moved i2c aliases to board dts and reordered nodes alphabetically.
>
> -Link to v1: https://lore.kernel.org/r/20260302020822.13936-1-zychennvt@gmail.com
>
> Zi-Yu Chen (3):
> dt-bindings: i2c: nuvoton,ma35d1-i2c: Add MA35D1 I2C controller
> i2c: ma35d1: Add Nuvoton MA35D1 I2C driver support
> arm64: dts: nuvoton: Add I2C nodes for MA35D1 SoC
>
> .../bindings/i2c/nuvoton,ma35d1-i2c.yaml | 63 ++
> .../boot/dts/nuvoton/ma35d1-som-256m.dts | 18 +-
> arch/arm64/boot/dts/nuvoton/ma35d1.dtsi | 60 ++
> drivers/i2c/busses/Kconfig | 13 +
> drivers/i2c/busses/Makefile | 1 +
> drivers/i2c/busses/i2c-ma35d1.c | 792 ++++++++++++++++++
> 6 files changed, 946 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/devicetree/bindings/i2c/nuvoton,ma35d1-i2c.yaml
> create mode 100644 drivers/i2c/busses/i2c-ma35d1.c
>
^ permalink raw reply
* Re: [PATCH V10 04/13] PCI: imx6: Assert PERST# before enabling regulators
From: Manivannan Sadhasivam @ 2026-04-07 6:46 UTC (permalink / raw)
To: Sherry Sun
Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
Frank Li, s.hauer@pengutronix.de, kernel@pengutronix.de,
festevam@gmail.com, lpieralisi@kernel.org, kwilczynski@kernel.org,
bhelgaas@google.com, Hongxing Zhu, l.stach@pengutronix.de,
imx@lists.linux.dev, linux-pci@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <VI0PR04MB12114917D17B5B8FB67E68DB9925AA@VI0PR04MB12114.eurprd04.prod.outlook.com>
On Tue, Apr 07, 2026 at 06:38:50AM +0000, Sherry Sun wrote:
>
> > On Thu, Apr 02, 2026 at 05:50:58PM +0800, Sherry Sun wrote:
> > > According to the PCIe initialization requirements, PERST# signal
> > > should be asserted before applying power to the PCIe device, and
> > > deasserted after power and reference clock are stable.
> > >
> >
> > Spec wording is not quite like this. Spec mandates asserting PERST# *before*
> > stopping refclk and powering down the device and deasserting it *after*
> > applying power and refclk stable.
> >
> > I believe you want to assert PERST# before enabling regulator to prevent the
> > endpoint from functioning? If so, is it due to refclk not available yet or some
> > other reason?
>
> You are right. My commit message wording was not that precise.
> The PCIe endpoint may start responding or driving signals as
> soon as its supply is enabled, even before the reference clock is stable.
> Asserting PERST# before enabling the regulator ensures that the endpoint
> remains in reset throughout the entire power-up sequence, until both
> power and refclk are known to be stable and link initialization can safely
> begin. This is mainly to avoid undefined behavior during early power-up.
>
> I will update the commit message to better reflect this.
>
> >
> > > Currently, the driver enables the vpcie3v3aux regulator in
> > > imx_pcie_probe() before PERST# is asserted in imx_pcie_host_init(),
> > > which violates the PCIe power sequencing requirements. However, there
> > > is no issue so far because PERST# is requested as GPIOD_OUT_HIGH in
> > > imx_pcie_probe(), which guarantees that PERST# is asserted before
> > > enabling the vpcie3v3aux regulator.
> > >
> > > This is prepare for the upcoming changes that will parse the reset
> > > property using the new Root Port binding, which will use GPIOD_ASIS
> > > when requesting the reset GPIO. With GPIOD_ASIS, the GPIO state is not
> > > guaranteed, so explicit sequencing is required.
> > >
> > > Fix the power sequencing by:
> > > 1. Moving vpcie3v3aux regulator enable from probe to
> > > imx_pcie_host_init(), where it can be properly sequenced with PERST#.
> > > 2. Moving imx_pcie_assert_perst() before regulator and clock enable to
> > > ensure correct ordering.
> > >
> > > The vpcie3v3aux regulator is kept enabled for the entire PCIe
> > > controller lifecycle and automatically disabled on device removal via devm
> > cleanup.
> > >
> >
> > vpcie3v3aux handling should be in a separate patch.
>
> Actually the handling of vpcie3v3aux itself remains unchanged, I just adjust the
> sequence of regulator/clock enable and perst#.
> Previously, the imx driver enabled the vpcie3v3aux regulator in imx_pcie_probe()
> before PERST# is asserted in imx_pcie_host_init(), which violates the PCIe power
> sequencing requirements.
> This patch moves vpcie3v3aux regulator enable from probe to imx_pcie_host_init(),
> where it can be properly sequenced with PERST#.
> Perhaps I should just remove this description to avoid confusion.
>
Yeah.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* [PATCH net v3] net: airoha: Add dma_rmb() and READ_ONCE() in airoha_qdma_rx_process()
From: Lorenzo Bianconi @ 2026-04-07 6:48 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Lorenzo Bianconi
Cc: Xuegang Lu, Simon Horman, linux-arm-kernel, linux-mediatek,
netdev
Add missing dma_rmb() in airoha_qdma_rx_process routine to make sure the
DMA read operations are completed when the NIC reports the processing on
the current descriptor is done. Moreover, add missing READ_ONCE() in
airoha_qdma_rx_process() for DMA descriptor control fields in order to
avoid any compiler reordering.
Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
Changes in v3:
- Move page pointer initialization before checking error condition on
payload length in order avoid using page pointer uninitialized in the
airoha_qdma_rx_process() error path.
- Link to v2: https://lore.kernel.org/r/20260403-airoha_qdma_rx_process-fix-reordering-v2-1-181e6e23d27b@kernel.org
Changes in v2:
- Use msg1 in airoha_qdma_get_gdm_port() signature to avoid missing
READ_ONCE().
- Link to v1: https://lore.kernel.org/r/20260402-airoha_qdma_rx_process-fix-reordering-v1-1-53278474f062@kernel.org
---
drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 91cb63a32d99..9285a68f435f 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -584,7 +584,7 @@ static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
static int airoha_qdma_get_gdm_port(struct airoha_eth *eth,
struct airoha_qdma_desc *desc)
{
- u32 port, sport, msg1 = le32_to_cpu(desc->msg1);
+ u32 port, sport, msg1 = le32_to_cpu(READ_ONCE(desc->msg1));
sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1);
switch (sport) {
@@ -612,21 +612,24 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
while (done < budget) {
struct airoha_queue_entry *e = &q->entry[q->tail];
struct airoha_qdma_desc *desc = &q->desc[q->tail];
- u32 hash, reason, msg1 = le32_to_cpu(desc->msg1);
- struct page *page = virt_to_head_page(e->buf);
- u32 desc_ctrl = le32_to_cpu(desc->ctrl);
+ u32 hash, reason, msg1, desc_ctrl;
struct airoha_gdm_port *port;
int data_len, len, p;
+ struct page *page;
+ desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
if (!(desc_ctrl & QDMA_DESC_DONE_MASK))
break;
+ dma_rmb();
+
q->tail = (q->tail + 1) % q->ndesc;
q->queued--;
dma_sync_single_for_cpu(eth->dev, e->dma_addr,
SKB_WITH_OVERHEAD(q->buf_size), dir);
+ page = virt_to_head_page(e->buf);
len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl);
data_len = q->skb ? q->buf_size
: SKB_WITH_OVERHEAD(q->buf_size);
@@ -670,8 +673,8 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
* DMA descriptor. Report DSA tag to the DSA stack
* via skb dst info.
*/
- u32 sptag = FIELD_GET(QDMA_ETH_RXMSG_SPTAG,
- le32_to_cpu(desc->msg0));
+ u32 msg0 = le32_to_cpu(READ_ONCE(desc->msg0));
+ u32 sptag = FIELD_GET(QDMA_ETH_RXMSG_SPTAG, msg0);
if (sptag < ARRAY_SIZE(port->dsa_meta) &&
port->dsa_meta[sptag])
@@ -679,6 +682,7 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
&port->dsa_meta[sptag]->dst);
}
+ msg1 = le32_to_cpu(READ_ONCE(desc->msg1));
hash = FIELD_GET(AIROHA_RXD4_FOE_ENTRY, msg1);
if (hash != AIROHA_RXD4_FOE_ENTRY)
skb_set_hash(q->skb, jhash_1word(hash, 0),
---
base-commit: a9d4f4f6e65e0bf9bbddedecc84d67249991979c
change-id: 20260402-airoha_qdma_rx_process-fix-reordering-722308255b65
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* Re: [PATCH v5 0/7] pinctrl: Add generic pinctrl for board-level mux chips
From: Linus Walleij @ 2026-04-07 6:48 UTC (permalink / raw)
To: Frank Li, Peter Rosin
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Rafał Miłecki, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, linux-kernel, linux-gpio, devicetree, imx,
linux-arm-kernel, Haibo Chen, Conor Dooley, Ahmad Fatoum
In-Reply-To: <CAD++jLmoHiJWV3J8f3TtpmQWLpUFD24icQEv2cbO3+x7775zxw@mail.gmail.com>
On Tue, Apr 7, 2026 at 8:42 AM Linus Walleij <linusw@kernel.org> wrote:
> > mux: add devm_mux_control_get_from_np() to get mux from child node
>
> Didn't get an ACK from the mux maintainer for this but this has been going
> on for long now so I applied it.
>
> Peter: protest if you don't like this and I will back it out.
I created an immutable branch for Peter to pull in if he want it:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git/log/?h=ib-mux-pinctrl
(You can also pull in just the bottom commit which is just the mux change)
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH V10 03/13] PCI: dwc: Parse Root Port nodes in dw_pcie_host_init()
From: Manivannan Sadhasivam @ 2026-04-07 6:52 UTC (permalink / raw)
To: Sherry Sun
Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
Frank Li, s.hauer@pengutronix.de, kernel@pengutronix.de,
festevam@gmail.com, lpieralisi@kernel.org, kwilczynski@kernel.org,
bhelgaas@google.com, Hongxing Zhu, l.stach@pengutronix.de,
imx@lists.linux.dev, linux-pci@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <VI0PR04MB121147E4D3F9FDC95391C1153925AA@VI0PR04MB12114.eurprd04.prod.outlook.com>
On Tue, Apr 07, 2026 at 03:21:30AM +0000, Sherry Sun wrote:
> > On Thu, Apr 02, 2026 at 05:50:57PM +0800, Sherry Sun wrote:
> > > Add support for parsing Root Port child nodes in dw_pcie_host_init()
> > > using pci_host_common_parse_ports(). This allows DWC-based drivers to
> > > specify Root Port properties (like reset GPIOs) in individual Root
> > > Port nodes rather than in the host bridge node.
> > >
> > > Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
> > > ---
> > > drivers/pci/controller/dwc/pcie-designware-host.c | 8 ++++++++
> > > 1 file changed, 8 insertions(+)
> > >
> > > diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c
> > > b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > index da152c31bb2e..f6fca984fb34 100644
> > > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > @@ -20,6 +20,7 @@
> > > #include <linux/platform_device.h>
> > >
> > > #include "../../pci.h"
> > > +#include "../pci-host-common.h"
> > > #include "pcie-designware.h"
> > >
> > > static struct pci_ops dw_pcie_ops;
> > > @@ -581,6 +582,13 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
> > >
> > > pp->bridge = bridge;
> > >
> > > + /* Parse Root Port nodes if present */
> > > + ret = pci_host_common_parse_ports(dev, bridge);
> > > + if (ret && ret != -ENOENT) {
> > > + dev_err(dev, "Failed to parse Root Port nodes: %d\n", ret);
> > > + return ret;
> >
> > Won't this change break drivers that parse Root Ports on their own? Either
> > you need to modify them also in this change or call this API from imx6 driver
> > and let other drivers switch to it in a phased manner.
> >
> > I perfer the latter.
>
> Hi Mani, sorry I didn't fully get your point here, there are no changes to this part
> V10, for drivers that parse Root Ports on their own, here pci_host_common_parse_ports()
> will return -ENOENT, so nothing break as we discussed this in V8
> https://lore.kernel.org/all/dcl3bdljrdzgeaybrg3dc5uaxkebkjns7pajix6mxxftao5g4m@vm3ywyyp4ujh/.
>
So if this API gets called first, it will acquire PERST# from the Root Port node
and if the controller drivers try to do the same in their own parsing code,
PERST# request will return -EBUSY and the probe will fail.
On the other hand, if the controller drivers parse PERST# first, this API will
return -EBUSY and will result in probe failure.
Only way to fix this issue would be to call this API from imx6 driver for now
and start migrating other drivers later.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH 0/3] ARM: pxa: attach software nodes to the GPIO controllers
From: Linus Walleij @ 2026-04-07 7:14 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Daniel Mack, Haojian Zhuang, Robert Jarzmik, Russell King,
Dmitry Torokhov, Arnd Bergmann, brgl, linux-arm-kernel,
linux-gpio, linux-kernel
In-Reply-To: <20260331-pxa-gpio-swnodes-v1-0-f66d86d10d8d@oss.qualcomm.com>
On Tue, Mar 31, 2026 at 11:11 AM Bartosz Golaszewski
<bartosz.golaszewski@oss.qualcomm.com> wrote:
> I was looking for a use-case where automatic secondary fwnode assignment
> would make sense for a DT platform. With the paz00 issue having been
> addressed by Dmitry, PXA looked like the last one that could match the
> idea but it turned out that we can just easily attach the software nodes
> to their controllers enabling fwnode lookup of GPIOs.
>
> After that the only GPIO consumers that still use label lookup with
> dangling software nodes are ACPI platform devices and a single PCI
> use-case. In that case, I won't be doing anything OF-related and will
> limit the x86 tablets series to an ACPI-centric solution.
>
> With that being said: here's a series attaching software nodes to GPIO
> controllers on the PXA platform. Since everything happens in a
> bord-file, it's quite straightforward.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
This makes things better, thanks!
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 1/2] KVM: arm64: Factor out TG0/1 decoding of VTCR and TCR
From: Marc Zyngier @ 2026-04-07 7:17 UTC (permalink / raw)
To: Wei-Lin Chang
Cc: linux-arm-kernel, kvmarm, linux-kernel, Oliver Upton, Joey Gouly,
Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon
In-Reply-To: <20260406164618.3312473-2-weilin.chang@arm.com>
On Mon, 06 Apr 2026 17:46:17 +0100,
Wei-Lin Chang <weilin.chang@arm.com> wrote:
>
> The current code decodes TCR.TG0/TG1 and VTCR.TG0 inline at several
> places. Extract this logic into helpers so the granule size is derived
> in one place. This enables us to alter the effective granule size in
> the same place, which we will need in a later patch.
>
> Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> ---
> arch/arm64/kvm/at.c | 73 +++++++++++++++++++++++++----------------
> arch/arm64/kvm/nested.c | 70 ++++++++++++++++++++++++---------------
> 2 files changed, 89 insertions(+), 54 deletions(-)
>
> diff --git a/arch/arm64/kvm/at.c b/arch/arm64/kvm/at.c
> index c5c5644b1878..ff8ba30e917b 100644
> --- a/arch/arm64/kvm/at.c
> +++ b/arch/arm64/kvm/at.c
> @@ -135,14 +135,54 @@ static void compute_s1poe(struct kvm_vcpu *vcpu, struct s1_walk_info *wi)
> wi->e0poe = (wi->regime != TR_EL2) && (val & TCR2_EL1_E0POE);
> }
>
> +static unsigned int tg0_to_shift(u64 tg0)
> +{
It'd be better to abstract these helpers a bit more by making them
take the full TCR_ELx value, and to give them a slightly better name.
I'd suggest something like:
static unsigned int tcr_to_tg0_pgshift(u64 tcr)
{
u64 tg0 = tcr & TCR_TG0_MASK, tcr;
which makes it clear that the result is a page shift, as required by
wi->pgshift.
> + switch (tg0) {
> + case TCR_EL1_TG0_4K:
> + return 12;
> + case TCR_EL1_TG0_16K:
> + return 14;
> + case TCR_EL1_TG0_64K:
Please don't mix the _EL1 definition and those without _EL1 in the
same file. For a start, that's not always EL1. Also, this makes very
hard to reason about what is shifted and what is not.
> + default: /* IMPDEF: treat any other value as 64k */
> + return 16;
> + }
> +}
> +
> +static unsigned int tg1_to_shift(u64 tg1)
> +{
> + switch (tg1) {
> + case TCR_EL1_TG1_4K:
> + return 12;
> + case TCR_EL1_TG1_16K:
> + return 14;
> + case TCR_EL1_TG1_64K:
> + default: /* IMPDEF: treat any other value as 64k */
> + return 16;
> + }
> +}
> +
> +static u64 tcr_tg_shift(struct kvm *kvm, u64 tcr, bool upper_range)
> +{
> + unsigned int shift;
> +
> + /* Someone was silly enough to encode TG0/TG1 differently */
> + if (upper_range)
> + shift = tg1_to_shift(FIELD_GET(TCR_EL1_TG1_MASK, tcr));
> + else
> + shift = tg0_to_shift(FIELD_GET(TCR_EL1_TG0_MASK, tcr));
> +
> + return shift;
> +}
> +
> static int setup_s1_walk(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
> struct s1_walk_result *wr, u64 va)
> {
> - u64 hcr, sctlr, tcr, tg, ps, ia_bits, ttbr;
> + u64 hcr, sctlr, tcr, ps, ia_bits, ttbr;
> unsigned int stride, x;
> - bool va55, tbi, lva;
> + bool va55, tbi, lva, upper_range;
>
> va55 = va & BIT(55);
> + upper_range = va55 && wi->regime != TR_EL2;
>
> if (vcpu_has_nv(vcpu)) {
> hcr = __vcpu_sys_reg(vcpu, HCR_EL2);
> @@ -173,35 +213,12 @@ static int setup_s1_walk(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
> BUG();
> }
>
> - /* Someone was silly enough to encode TG0/TG1 differently */
> - if (va55 && wi->regime != TR_EL2) {
> + if (upper_range)
> wi->txsz = FIELD_GET(TCR_T1SZ_MASK, tcr);
> - tg = FIELD_GET(TCR_TG1_MASK, tcr);
> -
> - switch (tg << TCR_TG1_SHIFT) {
> - case TCR_TG1_4K:
> - wi->pgshift = 12; break;
> - case TCR_TG1_16K:
> - wi->pgshift = 14; break;
> - case TCR_TG1_64K:
> - default: /* IMPDEF: treat any other value as 64k */
> - wi->pgshift = 16; break;
> - }
> - } else {
> + else
> wi->txsz = FIELD_GET(TCR_T0SZ_MASK, tcr);
> - tg = FIELD_GET(TCR_TG0_MASK, tcr);
> -
> - switch (tg << TCR_TG0_SHIFT) {
> - case TCR_TG0_4K:
> - wi->pgshift = 12; break;
> - case TCR_TG0_16K:
> - wi->pgshift = 14; break;
> - case TCR_TG0_64K:
> - default: /* IMPDEF: treat any other value as 64k */
> - wi->pgshift = 16; break;
> - }
> - }
>
> + wi->pgshift = tcr_tg_shift(vcpu->kvm, tcr, upper_range);
> wi->pa52bit = has_52bit_pa(vcpu, wi, tcr);
>
> ia_bits = get_ia_size(wi);
> diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> index 883b6c1008fb..2bfab3007cb3 100644
> --- a/arch/arm64/kvm/nested.c
> +++ b/arch/arm64/kvm/nested.c
> @@ -378,20 +378,36 @@ static int walk_nested_s2_pgd(struct kvm_vcpu *vcpu, phys_addr_t ipa,
> return 0;
> }
>
> -static void vtcr_to_walk_info(u64 vtcr, struct s2_walk_info *wi)
> +static unsigned int tg0_to_shift(u64 tg0)
Same comments as above.
> +{
> + switch (tg0) {
> + case VTCR_EL2_TG0_4K:
> + return 12;
> + case VTCR_EL2_TG0_16K:
> + return 14;
> + case VTCR_EL2_TG0_64K:
> + default: /* IMPDEF: treat any other value as 64k */
> + return 16;
> + }
> +}
> +
> +static u64 vtcr_tg0_shift(struct kvm *kvm, u64 vtcr)
> +{
> + u64 tg0 = FIELD_GET(VTCR_EL2_TG0_MASK, vtcr);
> + unsigned int shift = tg0_to_shift(tg0);
> +
> + return shift;
shift is an unsigned int. Why is the return value a u64? Try and make
sure that types are consistent, even if they cast nicely in C.
> +}
> +
> +static size_t vtcr_tg0_size(struct kvm *kvm, u64 vtcr)
> +{
> + return BIT(vtcr_tg0_shift(kvm, vtcr));
> +}
> +
> +static void vtcr_to_walk_info(struct kvm *kvm, u64 vtcr, struct s2_walk_info *wi)
This prototype reads bizarrely. vtcr is per CPU, the walk info is
evidently per CPU, and yet you pass a kvm struct.
Instead, rename this to:
static void setup_s2_walk(struct kvm_vcpu *vcpu,
struct s2_walk_info *wi)
{
u64 vtcr = vcpu_read_sys_reg(vcpu, VTCR_EL2);
and call that directly. You can then extract vcpu->kvm as needed. It
also aligns the naming on the s1 part, which isn't a bad thing to do.
> {
> wi->t0sz = vtcr & TCR_EL2_T0SZ_MASK;
> -
> - switch (FIELD_GET(VTCR_EL2_TG0_MASK, vtcr)) {
> - case VTCR_EL2_TG0_4K:
> - wi->pgshift = 12; break;
> - case VTCR_EL2_TG0_16K:
> - wi->pgshift = 14; break;
> - case VTCR_EL2_TG0_64K:
> - default: /* IMPDEF: treat any other value as 64k */
> - wi->pgshift = 16; break;
> - }
> -
> + wi->pgshift = vtcr_tg0_shift(kvm, vtcr);
> wi->sl = FIELD_GET(VTCR_EL2_SL0_MASK, vtcr);
> /* Global limit for now, should eventually be per-VM */
> wi->max_oa_bits = min(get_kvm_ipa_limit(),
> @@ -414,7 +430,7 @@ int kvm_walk_nested_s2(struct kvm_vcpu *vcpu, phys_addr_t gipa,
>
> wi.baddr = vcpu_read_sys_reg(vcpu, VTTBR_EL2);
>
> - vtcr_to_walk_info(vtcr, &wi);
> + vtcr_to_walk_info(vcpu->kvm, vtcr, &wi);
>
> wi.be = vcpu_read_sys_reg(vcpu, SCTLR_EL2) & SCTLR_ELx_EE;
>
> @@ -515,17 +531,19 @@ static u8 get_guest_mapping_ttl(struct kvm_s2_mmu *mmu, u64 addr)
> u64 tmp, sz = 0, vtcr = mmu->tlb_vtcr;
> kvm_pte_t pte;
> u8 ttl, level;
> + struct kvm *kvm = kvm_s2_mmu_to_kvm(mmu);
> + size_t tg0_size = vtcr_tg0_size(kvm, vtcr);
>
> - lockdep_assert_held_write(&kvm_s2_mmu_to_kvm(mmu)->mmu_lock);
> + lockdep_assert_held_write(&kvm->mmu_lock);
>
> - switch (FIELD_GET(VTCR_EL2_TG0_MASK, vtcr)) {
> - case VTCR_EL2_TG0_4K:
> + switch (tg0_size) {
> + case SZ_4K:
> ttl = (TLBI_TTL_TG_4K << 2);
> break;
> - case VTCR_EL2_TG0_16K:
> + case SZ_16K:
> ttl = (TLBI_TTL_TG_16K << 2);
> break;
> - case VTCR_EL2_TG0_64K:
> + case SZ_64K:
All these unit changes make the patch harder to read than it should
be. Consider having a separate patch to do that.
Thanks,
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply
* Re: [PATCH v1] PCI: imx6: Add force_suspend flag to override L1SS suspend skip
From: mani @ 2026-04-07 7:24 UTC (permalink / raw)
To: Hongxing Zhu
Cc: Bjorn Helgaas, Frank Li, jingoohan1@gmail.com,
l.stach@pengutronix.de, lpieralisi@kernel.org,
kwilczynski@kernel.org, robh@kernel.org, bhelgaas@google.com,
s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com,
linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
imx@lists.linux.dev, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
In-Reply-To: <AS8PR04MB8833C20B6FF92F96EE7641E38C5AA@AS8PR04MB8833.eurprd04.prod.outlook.com>
On Tue, Apr 07, 2026 at 03:31:57AM +0000, Hongxing Zhu wrote:
> > -----Original Message-----
> > From: mani@kernel.org <mani@kernel.org>
> > Sent: 2026年4月4日 1:03
> > To: Hongxing Zhu <hongxing.zhu@nxp.com>
> > Cc: Bjorn Helgaas <helgaas@kernel.org>; Frank Li <frank.li@nxp.com>;
> > jingoohan1@gmail.com; l.stach@pengutronix.de; lpieralisi@kernel.org;
> > kwilczynski@kernel.org; robh@kernel.org; bhelgaas@google.com;
> > s.hauer@pengutronix.de; kernel@pengutronix.de; festevam@gmail.com;
> > linux-pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > imx@lists.linux.dev; linux-kernel@vger.kernel.org; stable@vger.kernel.org
> > Subject: Re: [PATCH v1] PCI: imx6: Add force_suspend flag to override L1SS
> > suspend skip
> >
> > On Tue, Mar 24, 2026 at 02:01:58AM +0000, Hongxing Zhu wrote:
> > > > -----Original Message-----
> > > > From: Bjorn Helgaas <helgaas@kernel.org>
> > > > Sent: 2026年3月24日 6:09
> > > > To: Hongxing Zhu <hongxing.zhu@nxp.com>
> > > > Cc: Frank Li <frank.li@nxp.com>; jingoohan1@gmail.com;
> > > > l.stach@pengutronix.de; lpieralisi@kernel.org;
> > > > kwilczynski@kernel.org; mani@kernel.org; robh@kernel.org;
> > > > bhelgaas@google.com; s.hauer@pengutronix.de; kernel@pengutronix.de;
> > > > festevam@gmail.com; linux-pci@vger.kernel.org;
> > > > linux-arm-kernel@lists.infradead.org;
> > > > imx@lists.linux.dev; linux-kernel@vger.kernel.org;
> > > > stable@vger.kernel.org
> > > > Subject: Re: [PATCH v1] PCI: imx6: Add force_suspend flag to
> > > > override L1SS suspend skip
> > > >
> > > > On Wed, Mar 18, 2026 at 02:55:45AM +0000, Hongxing Zhu wrote:
> > > > > > -----Original Message-----
> > > > > > From: Bjorn Helgaas <helgaas@kernel.org>
> > > > > ... [messed up quoting]
> > > >
> > > > > > On Tue, Mar 17, 2026 at 02:12:56PM +0800, Richard Zhu wrote:
> > > > > > > Add a force_suspend flag to allow platform drivers to force
> > > > > > > the PCIe link into L2 state during suspend, even when L1SS
> > > > > > > (ASPM L1
> > > > > > > Sub-States) is enabled.
> > > > > > >
> > > > > > > By default, the DesignWare PCIe host controller skips L2
> > > > > > > suspend when L1SS is supported to meet low resume latency
> > > > > > > requirements for devices like NVMe. However, some platforms
> > > > > > > like i.MX PCIe need to enter L2 state for proper power
> > > > > > > management regardless of L1SS
> > > > support.
> > > > > > >
> > > > > > > Enable force_suspend for i.MX PCIe to ensure the link enters
> > > > > > > L2 during system suspend.
> > > > > >
> > > > > > I'm a little bit skeptical about this.
> > > > > >
> > > > > > What exactly does a "low resume latency requirement" mean? Is
> > > > > > this an actual functional requirement that's special to NVMe, or
> > > > > > is it just the desire for low resume latency that everybody has
> > > > > > for all devices?
> > > > >
> > > > > From my understanding, L1SS mode is characterized by lower latency
> > > > > when compared to L2 or L3 modes.
> > > > >
> > > > > It can be used on all devices, avoiding frequent power on/off cycles.
> > > > > NVMe can also extend the service life of the equipment.
> > > >
> > > > All the above applies to all platforms, so it's not an argument for
> > > > i.MX-specific code here.
> > > >
> > > Hi Bjorn:
> > > Thanks for your kindly review.
> > > Yes, it is.
> > > > > > Is there something special about i.MX here? Why do we want i.MX
> > > > > > to be different from other host controllers?
> > > > >
> > > > > i.MX PCIe loses power supply during Deep Sleep Mode (DSM),
> > > > > requiring full reinitialization after system wake-up.
> > > >
> > > > I don't know what DSM means in PCIe or how it would help justify
> > > > this change.
> > > >
> > > i.MX PCIe power is gated off during suspend, requiring full
> > > reinitialization on resume
> > >
> >
> > Is this an unconditional behavior? What if the PCIe device is configured as a
> > wakeup source like WOL, WOW? And if you connect NVMe, this behavior will
> > result in resume failure as NVMe driver expects the power to be retained if
> > ASPM is supported.
>
> Yes, this is unconditional behavior. The i.MX PCIe controller exclusively
> supports sideband wakeup mechanisms, which operate independently of the
> PCIe link state and device power configuration.
>
I believe you are referring to WAKE# as the sideband wakeup mechanism. If so,
both host and device has to support WAKE#.
> For devices configured as wakeup sources (WOL, WOW, etc.): The sideband
> wakeup path bypasses the standard PCIe power management, so these
> configurations do not impact the i.MX PCIe RC controller's suspend/resume
> behavior.
>
Once user enables wakeup for a device, PCI core will configure PME_EN only if
the device supports toggling WAKE# from D3Cold. So the wakeup functionality
depends on device too, not just the RC.
> For NVMe devices with ASPM: While NVMe drivers typically expect power
> retention when ASPM is enabled, the i.MX implementation's sideband wakeup
> mechanism operates through a separate signaling path. The wakeup functionality
> does not depend on maintaining PCIe link power, thus avoiding conflicts with
> NVMe power state expectations.
>
There is no relation between WAKE# and NVMe. NVMe is a passive device, so it
doesn't support WAKE#. With this patch alone, the NVMe driver won't resume (is
ASPM is enabled). You need to tell the NVMe driver to perpare for power loss
too. Maybe this patch can help you:
https://lore.kernel.org/all/20251231162126.7728-1-manivannan.sadhasivam@oss.qualcomm.com/
But that patch will only help if your platform supports S2RAM through PSCI.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH net-next v9 0/4] net: stmmac: Add PCI driver support for BCM8958x
From: Russell King (Oracle) @ 2026-04-07 7:24 UTC (permalink / raw)
To: Jitendra Vegiraju
Cc: netdev, alexandre.torgue, davem, edumazet, kuba, pabeni,
mcoquelin.stm32, bcm-kernel-feedback-list, richardcochran, ast,
daniel, hawk, john.fastabend, rohan.g.thomas, linux-kernel,
linux-stm32, linux-arm-kernel, bpf, andrew+netdev, horms, sdf, me,
siyanteng, prabhakar.mahadev-lad.rj, weishangjuan, wens,
vladimir.oltean, lizhi2, boon.khai.ng, maxime.chevallier,
chenchuangyu, yangtiezhu, ovidiu.panait.rb, chenhuacai,
florian.fainelli, quic_abchauha
In-Reply-To: <20260402213629.1996133-1-jitendra.vegiraju@broadcom.com>
On Thu, Apr 02, 2026 at 02:36:25PM -0700, Jitendra Vegiraju wrote:
> From: Jitendra Vegiraju <jitendra.vegiraju@broadcom.com>
>
> This patchset adds basic PCI ethernet device driver support for Broadcom
> BCM8958x Automotive Ethernet switch SoC devices.
>
> This SoC device has PCIe ethernet MAC attached to an integrated ethernet
> switch using XGMII interface. The PCIe ethernet controller is presented to
> the Linux host as PCI network device.
> Management of integrated ethernet switch on this SoC is not handled via
> the PCIe interface.
>
> The following block diagram gives an overview of the application.
> +=================================+
> | Host CPU/Linux |
> +=================================+
> || PCIe
> ||
> +==========================================+
> | +--------------+ |
> | | PCIE Endpoint| |
> | | Ethernet | |
> | | Controller | |
> | | DMA | |
> | +--------------+ |
> | | MAC | BCM8958X |
> | +--------------+ SoC |
> | || XGMII |
> | || |
> | +--------------+ |
> | | Ethernet | |
> | | switch | |
> | +--------------+ |
> | || || || || |
> +==========================================+
> || || || || More external interfaces
>
> The MAC block on BCM8958x is based on Synopsis XGMAC 4.00a core. This
> MAC IP introduces new DMA architecture called Hyper-DMA for virtualization
> scalability.
>
> Driver functionality specific to new MAC (DW25GMAC) is implemented in
> new file dw25gmac.c.
Sorry for suggesting this rather late, but I recently came across
another stmmac driver in the kernel - drivers/net/ethernet/synopsys.
This is for XLGMAC, but I wonder whether it may be a better bet for
this core. Have you looked at it?
--
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
* [PATCH V2] spi: mtk-snfi: unregister ECC engine on probe failure and remove() callback
From: Pei Xiao @ 2026-04-07 7:26 UTC (permalink / raw)
To: broonie, matthias.bgg, angelogioacchino.delregno, linux-spi,
linux-kernel, linux-arm-kernel, linux-mediatek
Cc: Pei Xiao
mtk_snand_probe() registers the on-host NAND ECC engine, but teardown was
missing from both probe unwind and remove-time cleanup. Add a devm cleanup
action after successful registration so
nand_ecc_unregister_on_host_hw_engine() runs automatically on probe
failures and during device removal.
Fixes: 764f1b748164 ("spi: add driver for MTK SPI NAND Flash Interface")
Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn>
---
changlog in v2: dev_err changes to dev_err_probe
---
drivers/spi/spi-mtk-snfi.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/spi/spi-mtk-snfi.c b/drivers/spi/spi-mtk-snfi.c
index 437edbd658aa..73fa84475f0e 100644
--- a/drivers/spi/spi-mtk-snfi.c
+++ b/drivers/spi/spi-mtk-snfi.c
@@ -1303,6 +1303,13 @@ static const struct spi_controller_mem_caps mtk_snand_mem_caps = {
.ecc = true,
};
+static void mtk_unregister_ecc_engine(void *data)
+{
+ struct nand_ecc_engine *eng = data;
+
+ nand_ecc_unregister_on_host_hw_engine(eng);
+}
+
static irqreturn_t mtk_snand_irq(int irq, void *id)
{
struct mtk_snand *snf = id;
@@ -1443,6 +1450,13 @@ static int mtk_snand_probe(struct platform_device *pdev)
goto release_ecc;
}
+ ret = devm_add_action_or_reset(&pdev->dev, mtk_unregister_ecc_engine,
+ &ms->ecc_eng);
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "failed to add ECC unregister action\n");
+ goto release_ecc;
+ }
+
ctlr->num_chipselect = 1;
ctlr->mem_ops = &mtk_snand_mem_ops;
ctlr->mem_caps = &mtk_snand_mem_caps;
--
2.25.1
^ permalink raw reply related
* Re: [PATCH 3/3] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC
From: Linus Walleij @ 2026-04-07 7:27 UTC (permalink / raw)
To: Yu-Chun Lin
Cc: brgl, robh, krzk+dt, conor+dt, afaerber, tychang, linux-gpio,
devicetree, linux-kernel, linux-arm-kernel, linux-realtek-soc,
cy.huang, stanley_chang, james.tai
In-Reply-To: <20260331113835.3510341-4-eleanor.lin@realtek.com>
On Tue, Mar 31, 2026 at 1:38 PM Yu-Chun Lin <eleanor.lin@realtek.com> wrote:
> From: Tzuyi Chang <tychang@realtek.com>
>
> Add support for the GPIO controller found on Realtek DHC RTD1625 SoCs.
>
> Unlike the existing Realtek GPIO driver (drivers/gpio/gpio-rtd.c),
> which manages pins via shared bank registers, the RTD1625 introduces
> a per-pin register architecture. Each GPIO line now has its own
> dedicated 32-bit control register to manage configuration independently,
> including direction, output value, input value, interrupt enable, and
> debounce. Therefore, this distinct hardware design requires a separate
> driver.
>
> Signed-off-by: Tzuyi Chang <tychang@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
With Bartosz comment addressed:
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v5 8/9] driver core: Replace dev->of_node_reused with dev_of_node_reused()
From: Manivannan Sadhasivam @ 2026-04-07 7:27 UTC (permalink / raw)
To: Douglas Anderson
Cc: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
Alan Stern, Alexey Kardashevskiy, Johan Hovold, Eric Dumazet,
Leon Romanovsky, Christoph Hellwig, Robin Murphy, maz,
Alexander Lobakin, Saravana Kannan, Mark Brown, alexander.stein,
andrew, andrew, andriy.shevchenko, astewart, bhelgaas, brgl,
davem, devicetree, driver-core, hkallweit1, jirislaby, joel, kees,
kuba, lgirdwood, linux-arm-kernel, linux-aspeed, linux-kernel,
linux-pci, linux-serial, linux-usb, linux, netdev, pabeni, robh
In-Reply-To: <20260406162231.v5.8.I806b8636cd3724f6cd1f5e199318ab8694472d90@changeid>
On Mon, Apr 06, 2026 at 04:23:01PM -0700, Douglas Anderson wrote:
> In C, bitfields are not necessarily safe to modify from multiple
> threads without locking. Switch "of_node_reused" over to the "flags"
> field so modifications are safe.
>
> Cc: Johan Hovold <johan@kernel.org>
> Acked-by: Mark Brown <broonie@kernel.org>
> Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
> Reviewed-by: Danilo Krummrich <dakr@kernel.org>
> Signed-off-by: Douglas Anderson <dianders@chromium.org>
Acked-by: Manivannan Sadhasivam <mani@kernel.org> # PCI_PWRCTRL
- Mani
> ---
> Not fixing any known bugs; problem is theoretical and found by code
> inspection. Change is done somewhat manually and only lightly tested
> (mostly compile-time tested).
>
> (no changes since v4)
>
> Changes in v4:
> - Use accessor functions for flags
>
> Changes in v3:
> - New
>
> drivers/base/core.c | 2 +-
> drivers/base/pinctrl.c | 2 +-
> drivers/base/platform.c | 2 +-
> drivers/net/pcs/pcs-xpcs-plat.c | 2 +-
> drivers/of/device.c | 6 +++---
> drivers/pci/of.c | 2 +-
> drivers/pci/pwrctrl/core.c | 2 +-
> drivers/regulator/bq257xx-regulator.c | 2 +-
> drivers/regulator/rk808-regulator.c | 2 +-
> drivers/tty/serial/serial_base_bus.c | 2 +-
> drivers/usb/gadget/udc/aspeed-vhub/dev.c | 2 +-
> include/linux/device.h | 7 ++++---
> 12 files changed, 17 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/base/core.c b/drivers/base/core.c
> index 8a83d7c93361..30825bf83234 100644
> --- a/drivers/base/core.c
> +++ b/drivers/base/core.c
> @@ -5283,7 +5283,7 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
> {
> of_node_put(dev->of_node);
> dev->of_node = of_node_get(dev2->of_node);
> - dev->of_node_reused = true;
> + dev_set_of_node_reused(dev);
> }
> EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
>
> diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c
> index 6e250272c843..0bbc83231234 100644
> --- a/drivers/base/pinctrl.c
> +++ b/drivers/base/pinctrl.c
> @@ -24,7 +24,7 @@ int pinctrl_bind_pins(struct device *dev)
> {
> int ret;
>
> - if (dev->of_node_reused)
> + if (dev_of_node_reused(dev))
> return 0;
>
> dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL);
> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> index d44591d52e36..199e6fb25770 100644
> --- a/drivers/base/platform.c
> +++ b/drivers/base/platform.c
> @@ -856,7 +856,7 @@ struct platform_device *platform_device_register_full(
> pdev->dev.parent = pdevinfo->parent;
> pdev->dev.fwnode = pdevinfo->fwnode;
> pdev->dev.of_node = of_node_get(to_of_node(pdev->dev.fwnode));
> - pdev->dev.of_node_reused = pdevinfo->of_node_reused;
> + dev_assign_of_node_reused(&pdev->dev, pdevinfo->of_node_reused);
>
> if (pdevinfo->dma_mask) {
> pdev->platform_dma_mask = pdevinfo->dma_mask;
> diff --git a/drivers/net/pcs/pcs-xpcs-plat.c b/drivers/net/pcs/pcs-xpcs-plat.c
> index b8c48f9effbf..f4b1b8246ce9 100644
> --- a/drivers/net/pcs/pcs-xpcs-plat.c
> +++ b/drivers/net/pcs/pcs-xpcs-plat.c
> @@ -349,7 +349,7 @@ static int xpcs_plat_init_dev(struct dw_xpcs_plat *pxpcs)
> * up later. Make sure DD-core is aware of the OF-node being re-used.
> */
> device_set_node(&mdiodev->dev, fwnode_handle_get(dev_fwnode(dev)));
> - mdiodev->dev.of_node_reused = true;
> + dev_set_of_node_reused(&mdiodev->dev);
>
> /* Pass the data further so the DW XPCS driver core could use it */
> mdiodev->dev.platform_data = (void *)device_get_match_data(dev);
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index f7e75e527667..be4e1584e0af 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -26,7 +26,7 @@
> const struct of_device_id *of_match_device(const struct of_device_id *matches,
> const struct device *dev)
> {
> - if (!matches || !dev->of_node || dev->of_node_reused)
> + if (!matches || !dev->of_node || dev_of_node_reused(dev))
> return NULL;
> return of_match_node(matches, dev->of_node);
> }
> @@ -192,7 +192,7 @@ ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
> {
> ssize_t sl;
>
> - if (!dev || !dev->of_node || dev->of_node_reused)
> + if (!dev || !dev->of_node || dev_of_node_reused(dev))
> return -ENODEV;
>
> sl = of_modalias(dev->of_node, str, len - 2);
> @@ -254,7 +254,7 @@ int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *
> {
> int sl;
>
> - if ((!dev) || (!dev->of_node) || dev->of_node_reused)
> + if ((!dev) || (!dev->of_node) || dev_of_node_reused(dev))
> return -ENODEV;
>
> /* Devicetree modalias is tricky, we add it in 2 steps */
> diff --git a/drivers/pci/of.c b/drivers/pci/of.c
> index 9f8eb5df279e..1f9b669abdb0 100644
> --- a/drivers/pci/of.c
> +++ b/drivers/pci/of.c
> @@ -38,7 +38,7 @@ int pci_set_of_node(struct pci_dev *dev)
> struct device *pdev __free(put_device) =
> bus_find_device_by_of_node(&platform_bus_type, node);
> if (pdev)
> - dev->bus->dev.of_node_reused = true;
> + dev_set_of_node_reused(&dev->bus->dev);
>
> device_set_node(&dev->dev, of_fwnode_handle(no_free_ptr(node)));
> return 0;
> diff --git a/drivers/pci/pwrctrl/core.c b/drivers/pci/pwrctrl/core.c
> index 7754baed67f2..72963a92362a 100644
> --- a/drivers/pci/pwrctrl/core.c
> +++ b/drivers/pci/pwrctrl/core.c
> @@ -39,7 +39,7 @@ static int pci_pwrctrl_notify(struct notifier_block *nb, unsigned long action,
> * If we got here then the PCI device is the second after the
> * power control platform device. Mark its OF node as reused.
> */
> - dev->of_node_reused = true;
> + dev_set_of_node_reused(dev);
> break;
> }
>
> diff --git a/drivers/regulator/bq257xx-regulator.c b/drivers/regulator/bq257xx-regulator.c
> index dab8f1ab4450..40e0f1a7ae81 100644
> --- a/drivers/regulator/bq257xx-regulator.c
> +++ b/drivers/regulator/bq257xx-regulator.c
> @@ -143,7 +143,7 @@ static int bq257xx_regulator_probe(struct platform_device *pdev)
> struct regulator_config cfg = {};
>
> pdev->dev.of_node = pdev->dev.parent->of_node;
> - pdev->dev.of_node_reused = true;
> + dev_set_of_node_reused(&pdev->dev);
>
> pdata = devm_kzalloc(&pdev->dev, sizeof(struct bq257xx_reg_data), GFP_KERNEL);
> if (!pdata)
> diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
> index e66408f23bb6..8297d31cde9f 100644
> --- a/drivers/regulator/rk808-regulator.c
> +++ b/drivers/regulator/rk808-regulator.c
> @@ -2115,7 +2115,7 @@ static int rk808_regulator_probe(struct platform_device *pdev)
> int ret, i, nregulators;
>
> pdev->dev.of_node = pdev->dev.parent->of_node;
> - pdev->dev.of_node_reused = true;
> + dev_set_of_node_reused(&pdev->dev);
>
> regmap = dev_get_regmap(pdev->dev.parent, NULL);
> if (!regmap)
> diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/serial_base_bus.c
> index a12935f6b992..5f23284a8778 100644
> --- a/drivers/tty/serial/serial_base_bus.c
> +++ b/drivers/tty/serial/serial_base_bus.c
> @@ -74,7 +74,7 @@ static int serial_base_device_init(struct uart_port *port,
> dev->parent = parent_dev;
> dev->bus = &serial_base_bus_type;
> dev->release = release;
> - dev->of_node_reused = true;
> + dev_set_of_node_reused(dev);
>
> device_set_node(dev, fwnode_handle_get(dev_fwnode(parent_dev)));
>
> diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
> index 2ecd049dacc2..8b9449d16324 100644
> --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c
> +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
> @@ -593,7 +593,7 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx)
> d->gadget.max_speed = USB_SPEED_HIGH;
> d->gadget.speed = USB_SPEED_UNKNOWN;
> d->gadget.dev.of_node = vhub->pdev->dev.of_node;
> - d->gadget.dev.of_node_reused = true;
> + dev_set_of_node_reused(&d->gadget.dev);
>
> rc = usb_add_gadget_udc(d->port_dev, &d->gadget);
> if (rc != 0)
> diff --git a/include/linux/device.h b/include/linux/device.h
> index 5b0fb6ad4c72..a79865a212e9 100644
> --- a/include/linux/device.h
> +++ b/include/linux/device.h
> @@ -483,6 +483,8 @@ struct device_physical_location {
> * driver/bus sync_state() callback.
> * @DEV_FLAG_DMA_COHERENT: This particular device is dma coherent, even if the
> * architecture supports non-coherent devices.
> + * @DEV_FLAG_OF_NODE_REUSED: Set if the device-tree node is shared with an
> + * ancestor device.
> */
> enum struct_device_flags {
> DEV_FLAG_READY_TO_PROBE = 0,
> @@ -492,6 +494,7 @@ enum struct_device_flags {
> DEV_FLAG_DMA_OPS_BYPASS = 4,
> DEV_FLAG_STATE_SYNCED = 5,
> DEV_FLAG_DMA_COHERENT = 6,
> + DEV_FLAG_OF_NODE_REUSED = 7,
>
> DEV_FLAG_COUNT
> };
> @@ -573,8 +576,6 @@ enum struct_device_flags {
> *
> * @offline_disabled: If set, the device is permanently online.
> * @offline: Set after successful invocation of bus type's .offline().
> - * @of_node_reused: Set if the device-tree node is shared with an ancestor
> - * device.
> * @flags: DEV_FLAG_XXX flags. Use atomic bitfield operations to modify.
> *
> * At the lowest level, every device in a Linux system is represented by an
> @@ -681,7 +682,6 @@ struct device {
>
> bool offline_disabled:1;
> bool offline:1;
> - bool of_node_reused:1;
>
> DECLARE_BITMAP(flags, DEV_FLAG_COUNT);
> };
> @@ -715,6 +715,7 @@ __create_dev_flag_accessors(dma_skip_sync, DEV_FLAG_DMA_SKIP_SYNC);
> __create_dev_flag_accessors(dma_ops_bypass, DEV_FLAG_DMA_OPS_BYPASS);
> __create_dev_flag_accessors(state_synced, DEV_FLAG_STATE_SYNCED);
> __create_dev_flag_accessors(dma_coherent, DEV_FLAG_DMA_COHERENT);
> +__create_dev_flag_accessors(of_node_reused, DEV_FLAG_OF_NODE_REUSED);
>
> #undef __create_dev_flag_accessors
>
> --
> 2.53.0.1213.gd9a14994de-goog
>
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* [PATCH] spi: uniphier: Simplify clock handling with devm_clk_get_enabled()
From: Pei Xiao @ 2026-04-07 7:30 UTC (permalink / raw)
To: hayashi.kunihiko, mhiramat, linux-spi, linux-arm-kernel,
linux-kernel
Cc: broonie, Pei Xiao
Replace devm_clk_get() followed by clk_prepare_enable() with
devm_clk_get_enabled() for the clock. This removes the need for
explicit clock enable and disable calls, as the managed API automatically
handles clock disabling on device removal or probe failure.
Remove the now-unnecessary clk_disable_unprepare() calls from the probe
error path and the remove callback. Adjust error labels accordingly.
Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn>
---
drivers/spi/spi-uniphier.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c
index 9e1d364a6198..1b815ee2ed1b 100644
--- a/drivers/spi/spi-uniphier.c
+++ b/drivers/spi/spi-uniphier.c
@@ -666,28 +666,24 @@ static int uniphier_spi_probe(struct platform_device *pdev)
}
priv->base_dma_addr = res->start;
- priv->clk = devm_clk_get(&pdev->dev, NULL);
+ priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
ret = PTR_ERR(priv->clk);
goto out_host_put;
}
- ret = clk_prepare_enable(priv->clk);
- if (ret)
- goto out_host_put;
-
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
ret = irq;
- goto out_disable_clk;
+ goto out_host_put;
}
ret = devm_request_irq(&pdev->dev, irq, uniphier_spi_handler,
0, "uniphier-spi", priv);
if (ret) {
dev_err(&pdev->dev, "failed to request IRQ\n");
- goto out_disable_clk;
+ goto out_host_put;
}
init_completion(&priv->xfer_done);
@@ -716,7 +712,7 @@ static int uniphier_spi_probe(struct platform_device *pdev)
if (IS_ERR_OR_NULL(host->dma_tx)) {
if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
- goto out_disable_clk;
+ goto out_host_put;
}
host->dma_tx = NULL;
dma_tx_burst = INT_MAX;
@@ -766,9 +762,6 @@ static int uniphier_spi_probe(struct platform_device *pdev)
host->dma_tx = NULL;
}
-out_disable_clk:
- clk_disable_unprepare(priv->clk);
-
out_host_put:
spi_controller_put(host);
return ret;
@@ -777,14 +770,11 @@ static int uniphier_spi_probe(struct platform_device *pdev)
static void uniphier_spi_remove(struct platform_device *pdev)
{
struct spi_controller *host = platform_get_drvdata(pdev);
- struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
if (host->dma_tx)
dma_release_channel(host->dma_tx);
if (host->dma_rx)
dma_release_channel(host->dma_rx);
-
- clk_disable_unprepare(priv->clk);
}
static const struct of_device_id uniphier_spi_match[] = {
--
2.25.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox