* [PATCH 4/4] ASoC: fsl_easrc: expose individual DAIs per conversion context
From: shengjiu.wang @ 2026-07-20 9:54 UTC (permalink / raw)
To: lgirdwood, broonie, robh, krzk+dt, conor+dt, Frank.Li, s.hauer,
kernel, festevam, shawnguo, linux-sound, devicetree, imx,
linux-arm-kernel, linux-kernel, shengjiu.wang, Xiubo.Lee,
nicoleotsuka, perex, tiwai, linuxppc-dev
Cc: Shengjiu Wang
In-Reply-To: <20260720095450.1618747-1-shengjiu.wang@oss.nxp.com>
From: Shengjiu Wang <shengjiu.wang@nxp.com>
The i.MX EASRC hardware supports four independent conversion contexts
(A, B, C, D). The driver previously registered a single DAI with generic
stream names "ASRC-Playback" and "ASRC-Capture", which prevents
individual contexts from being routed to separate audio paths
simultaneously.
Replace the single fsl_easrc_dai instance with an array of four DAI
drivers, one per context:
ctxa -- ASRC-Playback / ASRC-Capture (backward compatible)
ctxb -- ASRCB-Playback / ASRCB-Capture
ctxc -- ASRCC-Playback / ASRCC-Capture
ctxd -- ASRCD-Playback / ASRCD-Capture
Context A retains the original generic stream names to preserve backward
compatibility with existing machine drivers and board configurations.
Each DAI retains the same channel, rate and format capabilities as the
original, including IEC958 subframe support on the capture side. Update
the devm_snd_soc_register_component() call to register all four DAIs.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl_easrc.c | 112 +++++++++++++++++++++++++++++++-------
1 file changed, 92 insertions(+), 20 deletions(-)
diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index edfd943197a0..3c5303d9b9cf 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1600,27 +1600,99 @@ static const struct snd_soc_dai_ops fsl_easrc_dai_ops = {
.hw_free = fsl_easrc_hw_free,
};
-static struct snd_soc_dai_driver fsl_easrc_dai = {
- .playback = {
- .stream_name = "ASRC-Playback",
- .channels_min = 1,
- .channels_max = 32,
- .rate_min = 8000,
- .rate_max = 768000,
- .rates = SNDRV_PCM_RATE_KNOT,
- .formats = FSL_EASRC_FORMATS,
+static struct snd_soc_dai_driver fsl_easrc_dai[] = {
+ {
+ .name = "ctxa",
+ .playback = {
+ .stream_name = "ASRC-Playback",
+ .channels_min = 1,
+ .channels_max = 32,
+ .rate_min = 8000,
+ .rate_max = 768000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_EASRC_FORMATS,
+ },
+ .capture = {
+ .stream_name = "ASRC-Capture",
+ .channels_min = 1,
+ .channels_max = 32,
+ .rate_min = 8000,
+ .rate_max = 768000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_EASRC_FORMATS |
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
+ },
+ .ops = &fsl_easrc_dai_ops,
},
- .capture = {
- .stream_name = "ASRC-Capture",
- .channels_min = 1,
- .channels_max = 32,
- .rate_min = 8000,
- .rate_max = 768000,
- .rates = SNDRV_PCM_RATE_KNOT,
- .formats = FSL_EASRC_FORMATS |
- SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
+ {
+ .name = "ctxb",
+ .playback = {
+ .stream_name = "ASRCB-Playback",
+ .channels_min = 1,
+ .channels_max = 32,
+ .rate_min = 8000,
+ .rate_max = 768000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_EASRC_FORMATS,
+ },
+ .capture = {
+ .stream_name = "ASRCB-Capture",
+ .channels_min = 1,
+ .channels_max = 32,
+ .rate_min = 8000,
+ .rate_max = 768000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_EASRC_FORMATS |
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
+ },
+ .ops = &fsl_easrc_dai_ops,
+ },
+ {
+ .name = "ctxc",
+ .playback = {
+ .stream_name = "ASRCC-Playback",
+ .channels_min = 1,
+ .channels_max = 32,
+ .rate_min = 8000,
+ .rate_max = 768000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_EASRC_FORMATS,
+ },
+ .capture = {
+ .stream_name = "ASRCC-Capture",
+ .channels_min = 1,
+ .channels_max = 32,
+ .rate_min = 8000,
+ .rate_max = 768000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_EASRC_FORMATS |
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
+ },
+ .ops = &fsl_easrc_dai_ops,
+ },
+ {
+ .name = "ctxd",
+ .playback = {
+ .stream_name = "ASRCD-Playback",
+ .channels_min = 1,
+ .channels_max = 32,
+ .rate_min = 8000,
+ .rate_max = 768000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_EASRC_FORMATS,
+ },
+ .capture = {
+ .stream_name = "ASRCD-Capture",
+ .channels_min = 1,
+ .channels_max = 32,
+ .rate_min = 8000,
+ .rate_max = 768000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_EASRC_FORMATS |
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
+ },
+ .ops = &fsl_easrc_dai_ops,
},
- .ops = &fsl_easrc_dai_ops,
};
static const struct snd_soc_component_driver fsl_easrc_component = {
@@ -2245,7 +2317,7 @@ static int fsl_easrc_probe(struct platform_device *pdev)
regcache_cache_only(easrc->regmap, true);
ret = devm_snd_soc_register_component(dev, &fsl_easrc_component,
- &fsl_easrc_dai, 1);
+ fsl_easrc_dai, ARRAY_SIZE(fsl_easrc_dai));
if (ret) {
dev_err(dev, "failed to register ASoC DAI\n");
goto err_pm_disable;
--
2.34.1
^ permalink raw reply related
* [PATCH 3/4] ASoC: fsl_asrc: expose individual DAIs per conversion pair
From: shengjiu.wang @ 2026-07-20 9:54 UTC (permalink / raw)
To: lgirdwood, broonie, robh, krzk+dt, conor+dt, Frank.Li, s.hauer,
kernel, festevam, shawnguo, linux-sound, devicetree, imx,
linux-arm-kernel, linux-kernel, shengjiu.wang, Xiubo.Lee,
nicoleotsuka, perex, tiwai, linuxppc-dev
Cc: Shengjiu Wang
In-Reply-To: <20260720095450.1618747-1-shengjiu.wang@oss.nxp.com>
From: Shengjiu Wang <shengjiu.wang@nxp.com>
The i.MX ASRC hardware supports three independent conversion pairs
(A, B, C). The driver previously registered a single DAI with generic
stream names "ASRC-Playback" and "ASRC-Capture", which prevents
individual pairs from being routed to separate audio paths simultaneously.
Replace the single fsl_asrc_dai instance with an array of three DAI
drivers, one per pair:
paira -- ASRC-Playback / ASRC-Capture (backward compatible)
pairb -- ASRCB-Playback / ASRCB-Capture
pairc -- ASRCC-Playback / ASRCC-Capture
Pair A retains the original generic stream names to preserve backward
compatibility with existing machine drivers and board configurations.
Each DAI retains the same channel, rate and format capabilities as the
original. Update the devm_snd_soc_register_component() call to register
all three DAIs.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl_asrc.c | 89 +++++++++++++++++++++++++++++++---------
1 file changed, 69 insertions(+), 20 deletions(-)
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 0b28bcfa47fe..f83d6cdc6412 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -803,27 +803,76 @@ static const struct snd_soc_dai_ops fsl_asrc_dai_ops = {
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_3LE)
-static struct snd_soc_dai_driver fsl_asrc_dai = {
- .playback = {
- .stream_name = "ASRC-Playback",
- .channels_min = 1,
- .channels_max = 10,
- .rate_min = 5512,
- .rate_max = 192000,
- .rates = SNDRV_PCM_RATE_KNOT,
- .formats = FSL_ASRC_FORMATS |
- SNDRV_PCM_FMTBIT_S8,
+static struct snd_soc_dai_driver fsl_asrc_dai[] = {
+ {
+ .name = "paira",
+ .playback = {
+ .stream_name = "ASRC-Playback",
+ .channels_min = 1,
+ .channels_max = 10,
+ .rate_min = 5512,
+ .rate_max = 192000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_ASRC_FORMATS |
+ SNDRV_PCM_FMTBIT_S8,
+ },
+ .capture = {
+ .stream_name = "ASRC-Capture",
+ .channels_min = 1,
+ .channels_max = 10,
+ .rate_min = 5512,
+ .rate_max = 192000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_ASRC_FORMATS,
+ },
+ .ops = &fsl_asrc_dai_ops,
+ },
+ {
+ .name = "pairb",
+ .playback = {
+ .stream_name = "ASRCB-Playback",
+ .channels_min = 1,
+ .channels_max = 10,
+ .rate_min = 5512,
+ .rate_max = 192000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_ASRC_FORMATS |
+ SNDRV_PCM_FMTBIT_S8,
+ },
+ .capture = {
+ .stream_name = "ASRCB-Capture",
+ .channels_min = 1,
+ .channels_max = 10,
+ .rate_min = 5512,
+ .rate_max = 192000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_ASRC_FORMATS,
+ },
+ .ops = &fsl_asrc_dai_ops,
},
- .capture = {
- .stream_name = "ASRC-Capture",
- .channels_min = 1,
- .channels_max = 10,
- .rate_min = 5512,
- .rate_max = 192000,
- .rates = SNDRV_PCM_RATE_KNOT,
- .formats = FSL_ASRC_FORMATS,
+ {
+ .name = "pairc",
+ .playback = {
+ .stream_name = "ASRCC-Playback",
+ .channels_min = 1,
+ .channels_max = 10,
+ .rate_min = 5512,
+ .rate_max = 192000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_ASRC_FORMATS |
+ SNDRV_PCM_FMTBIT_S8,
+ },
+ .capture = {
+ .stream_name = "ASRCC-Capture",
+ .channels_min = 1,
+ .channels_max = 10,
+ .rate_min = 5512,
+ .rate_max = 192000,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = FSL_ASRC_FORMATS,
+ },
+ .ops = &fsl_asrc_dai_ops,
},
- .ops = &fsl_asrc_dai_ops,
};
static bool fsl_asrc_readable_reg(struct device *dev, unsigned int reg)
@@ -1404,7 +1453,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
goto err_pm_get_sync;
ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component,
- &fsl_asrc_dai, 1);
+ fsl_asrc_dai, ARRAY_SIZE(fsl_asrc_dai));
if (ret) {
dev_err(&pdev->dev, "failed to register ASoC DAI\n");
goto err_pm_get_sync;
--
2.34.1
^ permalink raw reply related
* [PATCH 2/4] dt-bindings: sound: fsl,easrc: add ports binding for multiple contexts
From: shengjiu.wang @ 2026-07-20 9:54 UTC (permalink / raw)
To: lgirdwood, broonie, robh, krzk+dt, conor+dt, Frank.Li, s.hauer,
kernel, festevam, shawnguo, linux-sound, devicetree, imx,
linux-arm-kernel, linux-kernel, shengjiu.wang, Xiubo.Lee,
nicoleotsuka, perex, tiwai, linuxppc-dev
Cc: Shengjiu Wang
In-Reply-To: <20260720095450.1618747-1-shengjiu.wang@oss.nxp.com>
From: Shengjiu Wang <shengjiu.wang@nxp.com>
The i.MX EASRC hardware supports up to four conversion contexts
(A, B, C, D). Add a ports container property to the binding to allow
each context to be represented as an individual audio-graph port:
port@0 -- context A
port@1 -- context B
port@2 -- context C
port@3 -- context D
Each sub-port references audio-graph-port.yaml and follows the standard
audio-graph binding conventions.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
.../devicetree/bindings/sound/fsl,easrc.yaml | 79 +++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/fsl,easrc.yaml b/Documentation/devicetree/bindings/sound/fsl,easrc.yaml
index d5727f8bfb0b..0f579870110d 100644
--- a/Documentation/devicetree/bindings/sound/fsl,easrc.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,easrc.yaml
@@ -55,6 +55,29 @@ properties:
- const: imx/easrc/easrc-imx8mn.bin
description: The coefficient table for the filters
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ properties:
+ port@0:
+ $ref: audio-graph-port.yaml#
+ unevaluatedProperties: false
+ description: port for context A
+
+ port@1:
+ $ref: audio-graph-port.yaml#
+ unevaluatedProperties: false
+ description: port for context B
+
+ port@2:
+ $ref: audio-graph-port.yaml#
+ unevaluatedProperties: false
+ description: port for context C
+
+ port@3:
+ $ref: audio-graph-port.yaml#
+ unevaluatedProperties: false
+ description: port for context D
+
fsl,asrc-rate:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 8000
@@ -107,3 +130,59 @@ examples:
fsl,asrc-rate = <8000>;
fsl,asrc-format = <2>;
};
+
+ - |
+ #include <dt-bindings/clock/imx8mn-clock.h>
+
+ easrc1: easrc@300c0000 {
+ compatible = "fsl,imx8mn-easrc";
+ reg = <0x300c0000 0x10000>;
+ interrupts = <0x0 122 0x4>;
+ clocks = <&clk IMX8MN_CLK_ASRC_ROOT>;
+ clock-names = "mem";
+ dmas = <&sdma2 16 23 0> , <&sdma2 17 23 0>,
+ <&sdma2 18 23 0> , <&sdma2 19 23 0>,
+ <&sdma2 20 23 0> , <&sdma2 21 23 0>,
+ <&sdma2 22 23 0> , <&sdma2 23 23 0>;
+ dma-names = "ctx0_rx", "ctx0_tx",
+ "ctx1_rx", "ctx1_tx",
+ "ctx2_rx", "ctx2_tx",
+ "ctx3_rx", "ctx3_tx";
+ firmware-name = "imx/easrc/easrc-imx8mn.bin";
+ fsl,asrc-rate = <8000>;
+ fsl,asrc-format = <2>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ playback-only;
+ easrc1_endpoint0: endpoint {
+ remote-endpoint = <&fe00_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ capture-only;
+ easrc1_endpoint1: endpoint {
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ capture-only;
+ easrc1_endpoint2: endpoint {
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ capture-only;
+ easrc1_endpoint3: endpoint {
+ };
+ };
+ };
+ };
--
2.34.1
^ permalink raw reply related
* [PATCH 1/4] dt-bindings: sound: fsl,imx-asrc: update port binding to support multiple pairs
From: shengjiu.wang @ 2026-07-20 9:54 UTC (permalink / raw)
To: lgirdwood, broonie, robh, krzk+dt, conor+dt, Frank.Li, s.hauer,
kernel, festevam, shawnguo, linux-sound, devicetree, imx,
linux-arm-kernel, linux-kernel, shengjiu.wang, Xiubo.Lee,
nicoleotsuka, perex, tiwai, linuxppc-dev
Cc: Shengjiu Wang
In-Reply-To: <20260720095450.1618747-1-shengjiu.wang@oss.nxp.com>
From: Shengjiu Wang <shengjiu.wang@nxp.com>
The i.MX ASRC hardware supports up to three conversion pairs (A, B, C).
The existing binding exposed only a single generic audio-graph port,
which cannot represent the individual pair endpoints.
Add a ports container that enumerates three named sub-ports:
port@0 -- pair A
port@1 -- pair B
port@2 -- pair C
Each sub-port references audio-graph-port.yaml as before.
For backwards compatibility, keep the old single port property but mark
it deprecated. A schema constraint (not: required: [port, ports]) ensures
that both forms cannot be used at the same time. Update the examples to
show both the new ports form and the deprecated port form.
No existing upstream DTS file for fsl,imx-asrc uses the previously
documented single 'port' node, so this change does not break any
in-tree device tree.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
.../bindings/sound/fsl,imx-asrc.yaml | 78 +++++++++++++++++++
1 file changed, 78 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
index 608defc93c1e..18d252722aa8 100644
--- a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
@@ -78,9 +78,29 @@ properties:
power-domains:
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ properties:
+ port@0:
+ $ref: audio-graph-port.yaml#
+ unevaluatedProperties: false
+ description: port for pair A
+
+ port@1:
+ $ref: audio-graph-port.yaml#
+ unevaluatedProperties: false
+ description: port for pair B
+
+ port@2:
+ $ref: audio-graph-port.yaml#
+ unevaluatedProperties: false
+ description: port for pair C
+
port:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
+ deprecated: true
+ description: deprecated, use ports instead
fsl,asrc-rate:
$ref: /schemas/types.yaml#/definitions/uint32
@@ -125,6 +145,10 @@ required:
- fsl,asrc-width
allOf:
+ - not:
+ required:
+ - port
+ - ports
- $ref: dai-common.yaml#
- if:
properties:
@@ -188,3 +212,57 @@ examples:
};
};
};
+
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/clock/imx6qdl-clock.h>
+ asrc1: asrc@2034000 {
+ compatible = "fsl,imx53-asrc";
+ reg = <0x02034000 0x4000>;
+ interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_ASRC_IPG>,
+ <&clks IMX6QDL_CLK_ASRC_MEM>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks IMX6QDL_CLK_ASRC>, <&clks 0>, <&clks 0>,
+ <&clks IMX6QDL_CLK_SPBA>;
+ clock-names = "mem", "ipg", "asrck_0",
+ "asrck_1", "asrck_2", "asrck_3", "asrck_4",
+ "asrck_5", "asrck_6", "asrck_7", "asrck_8",
+ "asrck_9", "asrck_a", "asrck_b", "asrck_c",
+ "asrck_d", "asrck_e", "asrck_f", "spba";
+ dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
+ <&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
+ dma-names = "rxa", "rxb", "rxc",
+ "txa", "txb", "txc";
+ fsl,asrc-rate = <48000>;
+ fsl,asrc-width = <16>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ playback-only;
+ asrc1_endpoint0: endpoint {
+ remote-endpoint = <&fe00_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ capture-only;
+ asrc1_endpoint1: endpoint {
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ capture-only;
+ asrc1_endpoint2: endpoint {
+ };
+ };
+ };
+ };
--
2.34.1
^ permalink raw reply related
* [PATCH 0/4] ASoC: fsl: expose individual DAIs per ASRC/EASRC conversion pair/context
From: shengjiu.wang @ 2026-07-20 9:54 UTC (permalink / raw)
To: lgirdwood, broonie, robh, krzk+dt, conor+dt, Frank.Li, s.hauer,
kernel, festevam, shawnguo, linux-sound, devicetree, imx,
linux-arm-kernel, linux-kernel, shengjiu.wang, Xiubo.Lee,
nicoleotsuka, perex, tiwai, linuxppc-dev
Cc: Shengjiu Wang
From: Shengjiu Wang <shengjiu.wang@nxp.com>
The i.MX ASRC and EASRC hardware each support multiple independent
conversion pairs or contexts, but both drivers previously registered
only a single DAI with generic stream names. This prevented individual
pairs or contexts from being routed to separate audio paths at the same
time.
This series updates the DT bindings and drivers to expose one DAI per
conversion unit:
- fsl,imx-asrc: add a ports container (port@0/1/2 for pairs A/B/C)
alongside the deprecated single port property
- fsl,easrc: add a ports container (port@0/1/2/3 for contexts A/B/C/D)
- fsl_asrc: register three DAIs (paira/pairb/pairc); pair A keeps the
original stream names for backward compatibility
- fsl_easrc: register four DAIs (ctxa/ctxb/ctxc/ctxd); context A keeps
the original stream names for backward compatibility
Shengjiu Wang (4):
dt-bindings: sound: fsl,imx-asrc: update port binding to support
multiple pairs
dt-bindings: sound: fsl,easrc: add ports binding for multiple contexts
ASoC: fsl_asrc: expose individual DAIs per conversion pair
ASoC: fsl_easrc: expose individual DAIs per conversion context
.../devicetree/bindings/sound/fsl,easrc.yaml | 79 ++++++++++++
.../bindings/sound/fsl,imx-asrc.yaml | 78 ++++++++++++
sound/soc/fsl/fsl_asrc.c | 89 ++++++++++----
sound/soc/fsl/fsl_easrc.c | 112 ++++++++++++++----
4 files changed, 318 insertions(+), 40 deletions(-)
--
2.34.1
^ permalink raw reply
* Re: [PATCH v2 3/3] arm64: dts: amlogic: a9: Add reset controller support
From: Neil Armstrong @ 2026-07-20 9:50 UTC (permalink / raw)
To: xianwei.zhao, Philipp Zabel, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Kevin Hilman, Jerome Brunet, Martin Blumenstingl
Cc: devicetree, linux-arm-kernel, linux-amlogic, linux-kernel
In-Reply-To: <20260714-a9-reset-v2-3-8df09b2f437c@amlogic.com>
On 7/14/26 04:33, Xianwei Zhao via B4 Relay wrote:
> From: Xianwei Zhao <xianwei.zhao@amlogic.com>
>
> Add reset controller descriptions for the Amlogic A9 SoC and include the
> corresponding reset IDs header.
>
> Signed-off-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
> ---
> arch/arm64/boot/dts/amlogic/amlogic-a9-reset.h | 247 +++++++++++++++++++++++++
> arch/arm64/boot/dts/amlogic/amlogic-a9.dtsi | 14 ++
> 2 files changed, 261 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a9-reset.h b/arch/arm64/boot/dts/amlogic/amlogic-a9-reset.h
> new file mode 100644
> index 000000000000..55fcaa54cd56
> --- /dev/null
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a9-reset.h
> @@ -0,0 +1,247 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/*
> + * Copyright (c) 2026 Amlogic, Inc. All rights reserved.
> + * Author: Zelong Dong <zelong.dong@amlogic.com>
> + *
> + */
> +
> +#ifndef _DT_BINDINGS_AMLOGIC_MESON_A9_RESET_H
> +#define _DT_BINDINGS_AMLOGIC_MESON_A9_RESET_H
> +
> +/* AO RESET0 */
> +#define AO_RESET_APB 0
> +#define AO_RESET_RTC 1
> +#define AO_RESET_BRG_NIC_RTC 2
> +#define AO_RESET_AO2EE 3
> +#define AO_RESET_BRG_NIC_EE 4
> +#define AO_RESET_WATCHDOG 5
> +#define AO_RESET_I3C 6
> +#define AO_RESET_PWR 7
> +#define AO_RESET_PWM_A 8
> +#define AO_RESET_PWM_B 9
> +#define AO_RESET_PWM_C 10
> +#define AO_RESET_PWM_D 11
> +#define AO_RESET_PWM_E 12
> +#define AO_RESET_PWM_F 13
> +#define AO_RESET_PWM_G 14
> +#define AO_RESET_I2C_M_A 15
> +#define AO_RESET_I2C_M_B 16
> +#define AO_RESET_I2C_M_C 17
> +#define AO_RESET_I2C_M_D 18
> +#define AO_RESET_IR 19
> +#define AO_RESET_UART_B 20
> +#define AO_RESET_UART_C 21
> +#define AO_RESET_UART_D 22
> +#define AO_RESET_SPISG 23
> +#define AO_RESET_SED 24
> +#define AO_RESET_CEC 25
> +#define AO_RESET_AOCPU 26
> +#define AO_RESET_AOCPU_POR 27
> +#define AO_RESET_AOCPU_CORE 28
> +#define AO_RESET_SRAM 29
> +#define AO_RESET_CAPU 30
> +#define AO_RESET_UART_E 31
> +
> +/* RESET0 */
> +#define RESET_ETH_1G 0
> +#define RESET_ISP 1
> +#define RESET_U3DRD_USB3PHY_APB 2
> +#define RESET_U3DRD_USB3PHY 3
> +#define RESET_U3DRD_USB2PHY 4
> +#define RESET_U3DRD 5
> +#define RESET_U3DRD_COMB 6
> +#define RESET_U3DRD_USB2PHY_APB 7
> +#define RESET_DP_PHY_APB 8
> +#define RESET_DP_PHY 9
> +#define RESET_DPTX_1P4 10
> +#define RESET_DPTX_1P4_APB 11
> +#define RESET_EDPTX_1P4 12
> +#define RESET_USB2DRD_PHY_APB 13
> +#define RESET_U2DRD_COMB 14
> +#define RESET_U2DRD 15
> +#define RESET_HDMI20_AES 16
> +#define RESET_HDMITX_CBUS_APB 17
> +#define RESET_BRG_VCBUS_DEC 18
> +#define RESET_VCBUS 19
> +#define RESET_VID_PLL_DIV 20
> +#define RESET_VDI6 21
> +#define RESET_HDMITXPHY 22
> +#define RESET_VID_LOCK 23
> +#define RESET_VENC_2 24
> +#define RESET_VDAC 25
> +#define RESET_VENC_1 26
> +#define RESET_VENC_0 27
> +#define RESET_RDMA 28
> +#define RESET_HDMITX 29
> +#define RESET_VIU 30
> +#define RESET_VENC 31
> +
> +/* RESET1 */
> +#define RESET_AUDIO 32
> +#define RESET_MALI_CBUS_APB 33
> +#define RESET_MALI 34
> +#define RESET_PCIE_B_PHY 35
> +#define RESET_PCIE_B_POR 36
> +#define RESET_DOS_CBUS_APB 37
> +#define RESET_DOS 38
> +#define RESET_MALI_SYS 39
> +#define RESET_CC 40
> +#define RESET_DSP_A_DEBUG 41
> +#define RESET_PCIE_A_PHY_APB 42
> +#define RESET_PCIE_A_PIPE 43
> +#define RESET_PCIE_A_POR 44
> +#define RESET_PCIE_A_PHY 45
> +#define RESET_PCIE_A_MAC_APB 46
> +#define RESET_AMFC_APB 47
> +#define RESET_ETH 48
> +/* 49 */
> +#define RESET_MALI_MBIST 50
> +#define RESET_ETH_1G_AXI 51
> +#define RESET_VICP 52
> +#define RESET_DEWARP 53
> +#define RESET_GE2D 54
> +#define RESET_VGE 55
> +#define RESET_PCIE_A_0 56
> +#define RESET_PCIE_A_1 57
> +#define RESET_PCIE_A_2 58
> +#define RESET_PCIE_A_3 59
> +#define RESET_PCIE_A_4 60
> +#define RESET_PCIE_A_5 61
> +#define RESET_PCIE_A_6 62
> +#define RESET_PCIE_A_7 63
> +
> +/* RESET2 */
> +#define RESET_AM2AXI 64
> +#define RESET_DSP_A 65
> +#define RESET_MIPI_DSI_PHY 66
> +#define RESET_TS_PLL 67
> +#define RESET_TS_A55 68
> +#define RESET_ETH_AXI 69
> +#define RESET_TS_CORE 70
> +#define RESET_MIPI_DSI1_PHY 71
> +#define RESET_SMART_CARD 72
> +#define RESET_SPISG 73
> +#define RESET_TS_DOS 74
> +#define RESET_U2DRD_USB2PHY 75
> +#define RESET_PIO 76
> +#define RESET_U2H_COMB 77
> +#define RESET_U2H 78
> +#define RESET_USB2H_PHY_APB 79
> +#define RESET_MSR_CLK 80
> +/* 81 */
> +#define RESET_AUX_DIG 82
> +/* 83 */
> +#define RESET_U2H_USB2PHY 84
> +#define RESET_U3HSG_PCIE_PIPE 85
> +#define RESET_AMFC 86
> +#define RESET_U3HSG_PCIE_PHY_APB 87
> +#define RESET_U3HSG_PCIE_PHY 88
> +#define RESET_PP_DMA 89
> +#define RESET_I3C 90
> +#define RESET_WATCHDOG 91
> +#define RESET_PP_WRAPPER 92
> +#define RESET_MIPI_DSI_HOST 93
> +#define RESET_DSI_PLL_DIV 94
> +#define RESET_MIPI_DSI_B_HOST 95
> +
> +/* RESET3 */
> +/* 96 */
> +#define RESET_HDMIRX_WRAP_APB 97
> +#define RESET_HDMIRX 98
> +#define RESET_PCIE_B_0 99
> +#define RESET_PCIE_B_1 100
> +#define RESET_PCIE_B_2 101
> +#define RESET_PCIE_B_3 102
> +#define RESET_PCIE_B_4 103
> +#define RESET_PCIE_B_5 104
> +#define RESET_PCIE_B_6 105
> +#define RESET_PCIE_B_7 106
> +#define RESET_PCIE_B_PIPE 107
> +#define RESET_PCIE_B_MAC_APB 108
> +#define RESET_NNA_TO_VGA_PIPE 109
> +#define RESET_CVE 110
> +#define RESET_GLOBAL_TIMER 111
> +#define RESET_COMBO_DPHY_PCLK 112
> +#define RESET_COMBO_DPHY 113
> +/* 114 - 118 */
> +#define RESET_U3PHY30_APB 119
> +#define RESET_U3PHY30 120
> +#define RESET_HSG 121
> +#define RESET_U3HSG_HSG 122
> +#define RESET_U3DRDB 123
> +#define RESET_U3DRDB_APB 124
> +#define RESET_U3PHY20_APB 125
> +#define RESET_U3PHY20 126
> +#define RESET_A55_ACE 127
> +
> +/* RESET4 */
> +#define RESET_CAN_0 128
> +#define RESET_CAN_1 129
> +#define RESET_TAHOE_CORE 130
> +#define RESET_TAHOE 131
> +#define RESET_TAHOE_APB 132
> +#define RESET_TAHOE_SYS 133
> +/* 134 - 135 */
> +#define RESET_PWM_I 136
> +#define RESET_PWM_J 137
> +#define RESET_UART_A 138
> +/* 139 - 143 */
> +#define RESET_MALI_AVBCD 144
> +#define RESET_MALI_AVBCD_APB 145
> +#define RESET_MALI_MCR_TOP 146
> +#define RESET_I2C_M_E 147
> +#define RESET_I2C_M_F 148
> +#define RESET_I2C_M_G 149
> +#define RESET_I2C_M_H 150
> +#define RESET_I2C_M_I 151
> +#define RESET_SD_EMMC_A 152
> +#define RESET_SD_EMMC_B 153
> +#define RESET_SD_EMMC_C 154
> +#define RESET_UART_F 155
> +#define RESET_PWM_N 156
> +#define RESET_PWM_M 157
> +#define RESET_PWM_L 158
> +#define RESET_PWM_K 159
> +
> +/* RESET5 */
> +#define RESET_BRG_ISP_PIPE 160
> +#define RESET_BRG_HEVCF_DMC_PIPE 161
> +#define RESET_BRG_HEVCB_PIPE 162
> +#define RESET_BRG_EMMC_PIPE 163
> +#define RESET_BRG_VGE_PIPE 164
> +#define RESET_BRG_DMC_VPU1_PIPE 165
> +#define RESET_BRG_DMC_VPU0_PIPE 166
> +#define RESET_BRG_NNA_PIPE 167
> +#define RESET_BRG_NNA_SRAM_PIPE 168
> +#define RESET_BRG_U2DRDA_PIPE 169
> +#define RESET_BRG_U3DRDA_PIPE 170
> +/* 171 - 173 */
> +#define RESET_BRG_NIC_AOSYS 174
> +#define RESET_BRG_NIC_AMFC 175
> +#define RESET_BRG_NIC_GIC 176
> +#define RESET_BRG_SRAM_NIC_NNA 177
> +#define RESET_BRG_SRAM_NIC_MAIN 178
> +#define RESET_BRG_SRAM_NIC_ALL 179
> +#define RESET_BRG_NIC_SOC_BRG 180
> +#define RESET_BRG_NIC_GPV 181
> +#define RESET_BRG_NIC_AO 182
> +#define RESET_BRG_NIC_EMMC 183
> +#define RESET_BRG_NIC_DSP_A 184
> +#define RESET_BRG_NIC_SDIO_B 185
> +#define RESET_BRG_NIC_SDIO_A 186
> +#define RESET_BRG_NIC_VAP_B 187
> +#define RESET_BRG_NIC_DSU 188
> +#define RESET_BRG_NIC_CLK81 189
> +#define RESET_BRG_NIC_MAIN 190
> +#define RESET_BRG_NIC_ALL 191
> +
> +/* RESET6 */
> +/* 192 - 216 */
> +#define RESET_BRG_PP_CLK 217
> +#define RESET_BRG_PP_NIC_CLK81 218
> +/* 219 - 220 */
> +#define RESET_BRG_PERIPH_APB_SYNC 221
> +#define RESET_BRG_VPU_APB_SYNC 222
> +#define RESET_BRG_DSP_A_PIPE 223
> +
> +#endif
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a9.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a9.dtsi
> index b0e0fadeed82..fedde52c2e89 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-a9.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a9.dtsi
> @@ -7,6 +7,7 @@
> #include <dt-bindings/interrupt-controller/arm-gic.h>
> #include <dt-bindings/gpio/gpio.h>
> #include <dt-bindings/pinctrl/amlogic,pinctrl.h>
> +#include "amlogic-a9-reset.h"
>
> / {
> interrupt-parent = <&gic>;
> @@ -105,6 +106,13 @@ apb: bus@fe000000 {
> #size-cells = <2>;
> ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
>
> + reset: reset-controller@2000 {
> + compatible = "amlogic,a9-reset",
> + "amlogic,t7-reset";
> + reg = <0x0 0x2000 0x0 0x98>;
> + #reset-cells = <1>;
> + };
> +
> periphs_pinctrl: pinctrl@4000 {
> compatible = "amlogic,pinctrl-a9";
> #address-cells = <2>;
> @@ -204,6 +212,12 @@ aobus: bus@ffa00000 {
> #size-cells = <2>;
> ranges = <0x0 0x0 0x0 0xffa00000 0x0 0x100000>;
>
> + ao_reset: reset-controller@2000 {
> + compatible = "amlogic,a9-ao-reset";
> + reg = <0x0 0x2000 0x0 0xc>;
> + #reset-cells = <1>;
> + };
> +
> aobus_pinctrl: pinctrl@4000 {
> compatible = "amlogic,pinctrl-a9";
> #address-cells = <2>;
>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Thanks,
Neil
^ permalink raw reply
* Re: [PATCH v7 1/3] dt-bindings: pwm: Add Raspberry Pi RP1 PWM controller
From: sashiko-bot @ 2026-07-20 9:50 UTC (permalink / raw)
To: Andrea della Porta; +Cc: conor+dt, devicetree, robh
In-Reply-To: <67d51a7210f0d7410dbe34e3d93813db1fecd622.1784539788.git.andrea.porta@suse.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The binding description states the device acts as a syscon provider for shared registers, but the schema prohibits the use of the "syscon" compatible string.
--
--- Patch [1]: [PATCH v7 1/3] dt-bindings: pwm: Add Raspberry Pi RP1 PWM controller ---
commit 06ebdbe78362ab02ea5e88d503ad7c179855b48a
Author: Naushir Patuck <naush@raspberrypi.com>
dt-bindings: pwm: Add Raspberry Pi RP1 PWM controller
This commit adds the devicetree binding documentation for the PWM controller
found in the Raspberry Pi RP1 chipset.
> diff --git a/Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml b/Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml
> new file mode 100644
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml
> @@ -0,0 +1,66 @@
[ ... ]
> +description: |
> + The PWM peripheral is a flexible waveform generator with a
> + variety of operational modes. It has the following features:
> + - four independent output channels
> + - 32-bit counter widths
> + - Seven output generation modes
> + - Optional per-channel output inversion
> + - Optional duty-cycle data FIFO with DMA support
> + - Optional sigma-delta noise shaping engine
> + Serves as a fan speed provider to other nodes for a PWM-connected
> + fan using shared registers (syscon).
> +
> +properties:
> + compatible:
> + const: raspberrypi,rp1-pwm
[Severity: Medium]
The description states this device acts as a syscon provider for shared
registers, but the compatible property is restricted to a single string.
Will device tree validation fail if a user includes the "syscon" string
normally required for standard kernel syscon lookup APIs alongside the
"raspberrypi,rp1-pwm" compatible string?
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1784539788.git.andrea.porta@suse.com?part=1
^ permalink raw reply
* Re: [PATCH v5 1/3] ASoC: dt-bindings: qcom,q6apm-lpass-dais: Document DAI subnode
From: Mohammad Rafi Shaik @ 2026-07-20 9:48 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
linux-arm-msm, linux-sound, devicetree, linux-kernel,
Srinivas Kandagatla
In-Reply-To: <e1c57781-846a-4d5a-95e1-90038f88afef@kernel.org>
On 7/16/2026 11:49 AM, Krzysztof Kozlowski wrote:
> On 15/07/2026 08:58, Mohammad Rafi Shaik wrote:
>>
>>
>> On 7/15/2026 11:35 AM, Krzysztof Kozlowski wrote:
>>> On Tue, Jul 14, 2026 at 08:22:48PM +0530, Mohammad Rafi Shaik wrote:
>>>> Extend the qcom,q6apm-lpass-dais device tree binding to explicitly
>>>> describe Digital Audio Interface (DAI) child nodes.
>>>>
>>>> Add #address-cells and #size-cells to allow representation of multiple
>>>> DAI instances as child nodes, and define a dai@<id> pattern to document
>>>> per-DAI properties such as the interface ID and associated clocks.
>>>>
>>>> On platforms such as Monaco and Lemans, third-party codecs are hardware
>>>> wired to the SoC and do not always have an in-tree codec driver to manage
>>>> their clocks. For these designs, clock line enablement must be driven
>>>> from the platform side, and this series provides the necessary support
>>>> for that.
>>>>
>>>> On QAIF-based platforms such as Shikra and Hawi, responsibility for voting
>>>> I2S MCLK and BCLK has moved from the DSP to the kernel. This series
>>>> introduces the required device tree binding support to represent and
>>>> vote for these clocks from the kernel.
>>>>
>>>> Co-developed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
>>>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
>>>> Signed-off-by: Mohammad Rafi Shaik <mohammad.rafi.shaik@oss.qualcomm.com>
>>>> ---
>>>> .../bindings/sound/qcom,q6apm-lpass-dais.yaml | 89 +++++++++++++++++++
>>>> 1 file changed, 89 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml
>>>> index 2fb95544d..b37c62ccd 100644
>>>> --- a/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml
>>>> +++ b/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml
>>>> @@ -21,6 +21,82 @@ properties:
>>>> '#sound-dai-cells':
>>>> const: 1
>>>>
>>>> + '#address-cells':
>>>> + const: 1
>>>> +
>>>> + '#size-cells':
>>>> + const: 0
>>>> +
>>>> +# Digital Audio Interfaces
>>>> +patternProperties:
>>>> + '^dai@[0-9a-f]+$':
>>>> + type: object
>>>> + description:
>>>> + Q6DSP Digital Audio Interfaces.
>>>> +
>>>> + properties:
>>>> + reg:
>>>> + maxItems: 1
>>>> + description:
>>>> + Digital Audio Interface ID
>>>> +
>>>> + clocks:
>>>> + minItems: 1
>>>> + maxItems: 2
>>>> + description: MI2S clocks (mclk, bclk and/or eclk).
>>>> +
>>>> + clock-names:
>>>> + minItems: 1
>>>> + maxItems: 2
>>>> +
>>>> + allOf:
>>>> + - oneOf:
>>>> + - properties:
>>>
>>> Please don't do such stuff. Did you find it somewhere? If yes, then
>>> where - so we can remove it?
>>>
>>
>> It was not copied from another binding.
>>
>> It was my attempt to model the valid clock combinations.
>>
>>> I gave you the close-to-exact syntax I expect. It was nothing like this.
>>
>> clocks:
>> minItems: 1
>> maxItems: 3
>>
>>
>> clock-names:
>> minItems: 1
>> maxItems: 3
>> items:
>> enum:
>> - mclk
>> - bclk
>> - eclk
>
> But I did not wrote anything like that.
>
>>
>> The enum version does not enforce the positional relationship between
>> clocks and clock-names,
>
> So you do not use my code, but something completely different and does
> not work, therefore you come up with another approach.
>
> I don't know what to advise, but repeating myself seems pointless.
>
> Previous review stays valid.
>
Sorry about this patch.
I attempted to address the AI and Sashiko review comments.
will fall back to the suggested approach from the previous version.
Thanks & regards,
Rafi.
>
>
>>
>> which is why I tried the oneOf approach.
>>
>> My concern with the suggested syntax is that mclk is not mandatory for
>> all platforms.
>>
>> For example, HAWI only requires bclk and does not use mclk, so requiring
>> mclk as the first clock-name would reject valid DTs.
>
> Luckily I did not require mclk as first, so I do not understand why you
> refer to something like that.
>
>
> Best regards,
> Krzysztof
^ permalink raw reply
* Re: [PATCH] arm64: dts: qcom: sm8150: Add slim nodes
From: sashiko-bot @ 2026-07-20 9:42 UTC (permalink / raw)
To: XiaoYeZi; +Cc: conor+dt, devicetree, robh
In-Reply-To: <tencent_DF2E181B86AC588DD7B70DE904F6670BC207@qq.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The newly added `slimbam` and `slim` device tree nodes are not sorted by their unit address, violating standard DT conventions.
--
--- Patch [1]: [PATCH] arm64: dts: qcom: sm8150: Add slim nodes ---
commit 47169c779220744d341492a384ae3d049c3c3c92
Author: XiaoYeZi <qaz6750@qq.com>
arm64: dts: qcom: sm8150: Add slim nodes
This commit adds the slimbus node which is an important node in audio.
> diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
> index 0e101096209ab..941043e0139a1 100644
> --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
> @@ -4410,6 +4410,18 @@ watchdog@17c10000 {
> interrupts = <GIC_SPI 0 IRQ_TYPE_EDGE_RISING>;
> };
>
> + slimbam: dma-controller@17184000 {
[Severity: Low]
This isn't a bug, but are these nodes placed out of order? Device tree nodes
within a bus are typically sorted alphanumerically by their unit address in
ascending order. The dma-controller@17184000 node is being inserted after
the watchdog@17c10000 node (17184000 < 17c10000). Should it be moved
earlier in the file?
[ ... ]
> @@ -4577,6 +4589,20 @@ cpufreq_hw: cpufreq@18323000 {
> #clock-cells = <1>;
> };
>
> + slim: slim-ngd@171c0000 {
[Severity: Low]
Similarly, the slim-ngd@171c0000 node is being placed after the
cpufreq@18323000 node (171c0000 < 18323000). Should this node also be placed
earlier to maintain standard unit-address sorting?
--
Sashiko AI review · https://sashiko.dev/#/patchset/tencent_DF2E181B86AC588DD7B70DE904F6670BC207@qq.com?part=1
^ permalink raw reply
* [PATCH v7 3/3] arm64: dts: broadcom: rpi-5: Add RP1 PWM node
From: Andrea della Porta @ 2026-07-20 9:44 UTC (permalink / raw)
To: Uwe Kleine-König, linux-pwm, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Broadcom internal kernel review list, Andrea della Porta,
devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
Naushir Patuck, Stanimir Varbanov, mbrugger, Sean Young,
Julian Braha
In-Reply-To: <cover.1784539788.git.andrea.porta@suse.com>
From: Stanimir Varbanov <svarbanov@suse.de>
The RP1 chipset used on the Raspberry Pi 5 features an integrated
PWM controller to drive the cooling fan.
Add the corresponding DT node for this PWM controller.
Signed-off-by: Stanimir Varbanov <svarbanov@suse.de>
Co-developed-by: Andrea della Porta <andrea.porta@suse.com>
Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
---
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts | 12 ++++++++++++
arch/arm64/boot/dts/broadcom/rp1-common.dtsi | 9 +++++++++
2 files changed, 21 insertions(+)
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
index 0fc57e72632ed..748be8f1ee9e2 100644
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
@@ -64,6 +64,12 @@ phy1: ethernet-phy@1 {
};
&rp1_gpio {
+ fan_pwm_default_state: fan-pwm-default-state {
+ function = "pwm1";
+ pins = "gpio45";
+ bias-pull-down;
+ };
+
usb_vbus_default_state: usb-vbus-default-state {
function = "vbus1";
groups = "vbus1";
@@ -94,6 +100,12 @@ &rp1_i2c6 {
pinctrl-names = "default";
};
+&rp1_pwm1 {
+ pinctrl-0 = <&fan_pwm_default_state>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&rp1_usb0 {
pinctrl-0 = <&usb_vbus_default_state>;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/broadcom/rp1-common.dtsi b/arch/arm64/boot/dts/broadcom/rp1-common.dtsi
index 16f5359395835..df4c2d09c8d34 100644
--- a/arch/arm64/boot/dts/broadcom/rp1-common.dtsi
+++ b/arch/arm64/boot/dts/broadcom/rp1-common.dtsi
@@ -99,7 +99,16 @@ rp1_i2c6: i2c@40088000 {
clocks = <&rp1_clocks RP1_CLK_SYS>;
i2c-scl-rising-time-ns = <65>;
i2c-scl-falling-time-ns = <100>;
+ status = "disabled";
+ };
+ rp1_pwm1: pwm@4009c000 {
+ compatible = "raspberrypi,rp1-pwm";
+ reg = <0x00 0x4009c000 0x0 0x100>;
+ clocks = <&rp1_clocks RP1_CLK_PWM1>;
+ assigned-clocks = <&rp1_clocks RP1_CLK_PWM1>;
+ assigned-clock-rates = <50000000>;
+ #pwm-cells = <3>;
status = "disabled";
};
--
2.35.3
^ permalink raw reply related
* [PATCH v7 2/3] pwm: rp1: Add RP1 PWM controller driver
From: Andrea della Porta @ 2026-07-20 9:44 UTC (permalink / raw)
To: Uwe Kleine-König, linux-pwm, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Broadcom internal kernel review list, Andrea della Porta,
devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
Naushir Patuck, Stanimir Varbanov, mbrugger, Sean Young,
Julian Braha
In-Reply-To: <cover.1784539788.git.andrea.porta@suse.com>
From: Naushir Patuck <naush@raspberrypi.com>
The Raspberry Pi RP1 southbridge features an embedded PWM
controller with 4 output channels, alongside an RPM interface
to read the fan speed on the Raspberry Pi 5.
Add the supporting driver.
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Co-developed-by: Stanimir Varbanov <svarbanov@suse.de>
Signed-off-by: Stanimir Varbanov <svarbanov@suse.de>
Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
---
drivers/pwm/Kconfig | 9 +
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-rp1.c | 428 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 438 insertions(+)
create mode 100644 drivers/pwm/pwm-rp1.c
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index e8886a9b64d96..0373dcf8d400d 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -637,6 +637,15 @@ config PWM_ROCKCHIP
Generic PWM framework driver for the PWM controller found on
Rockchip SoCs.
+config PWM_RASPBERRYPI_RP1
+ tristate "RP1 PWM support"
+ depends on MISC_RP1 || COMPILE_TEST
+ depends on HAS_IOMEM
+ select REGMAP_MMIO
+ select MFD_SYSCON
+ help
+ PWM framework driver for Raspberry Pi RP1 controller.
+
config PWM_SAMSUNG
tristate "Samsung PWM support"
depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 5630a521a7cff..c07fd24f69f39 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_PWM_RENESAS_RZG2L_GPT) += pwm-rzg2l-gpt.o
obj-$(CONFIG_PWM_RENESAS_RZ_MTU3) += pwm-rz-mtu3.o
obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o
obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
+obj-$(CONFIG_PWM_RASPBERRYPI_RP1) += pwm-rp1.o
obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o
obj-$(CONFIG_PWM_SL28CPLD) += pwm-sl28cpld.o
diff --git a/drivers/pwm/pwm-rp1.c b/drivers/pwm/pwm-rp1.c
new file mode 100644
index 0000000000000..e2d7af80dc071
--- /dev/null
+++ b/drivers/pwm/pwm-rp1.c
@@ -0,0 +1,428 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * pwm-rp1.c
+ *
+ * Raspberry Pi RP1 PWM.
+ *
+ * Copyright © 2026 Raspberry Pi Ltd.
+ *
+ * Author: Naushir Patuck (naush@raspberrypi.com)
+ *
+ * Based on the pwm-bcm2835 driver by:
+ * Bart Tanghe <bart.tanghe@thomasmore.be>
+ *
+ * Datasheet: https://pip-assets.raspberrypi.com/categories/892-raspberry-pi-5/documents/RP-008370-DS-1-rp1-peripherals.pdf?disposition=inline
+ *
+ * Limitations:
+ * - Channels can be enabled/disabled through a global update flag, while the
+ * period and duty per-channel registers are independently updatable, and
+ * they are latched on the end of (specific channel) period strobe.
+ * This means that period and duty changes might result in glitches if the
+ * period/duty is changed exactly during an end of period strobe.
+ * - Since the duty/period registers are freely updatable (do not depend on
+ * the global update flag), setting one of them close to the period end and
+ * the other right afterwards results in a mixed output for that cycle because
+ * the write ops are not atomic.
+ * - The global update flag prevents mis-sampling of multi-bit bus signals in
+ * the PWM clock domain. This ensures that all PWM channel settings update
+ * on the same PWM clock cycle. Channels start in sync only if they share the
+ * same period.
+ * - If both duty and period are set to 0, the output is a constant low signal
+ * if polarity is normal or a constant high signal if polarity is inversed.
+ * - When disabled the output is driven to 0 if polarity is normal, or to 1
+ * if polarity is inversed.
+ * - Disabling the PWM stops the output immediately, without waiting for current
+ * period to complete first.
+ * - Channels are phase-capable, but on RPi5, the firmware can use a channel
+ * phase register to report the RPM of the fan connected to that PWM
+ * channel. As a result, phase control will be ignored for now.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/units.h>
+
+#define RP1_PWM_GLB_CTRL 0x000
+#define RP1_PWM_GLB_CTRL_CHANNEL_ENABLE(chan) BIT(chan)
+#define RP1_PWM_GLB_CTRL_SET_UPDATE BIT(31)
+
+#define RP1_PWM_CHAN_CTRL(chan) (0x014 + ((chan) * 0x10))
+#define RP1_PWM_CHAN_CTRL_POLARITY BIT(3)
+#define RP1_PWM_CHAN_CTRL_FIFO_POP_MASK BIT(8)
+#define RP1_PWM_CHAN_CTRL_MODE GENMASK(2, 0)
+enum rp1_pwm_ctrl_mode {
+ RP1_PWM_CHAN_CTRL_MODE_ZERO,
+ RP1_PWM_CHAN_CTRL_MODE_TE_MS,
+ RP1_PWM_CHAN_CTRL_MODE_PC_MS,
+ RP1_PWM_CHAN_CTRL_MODE_PD_ENC,
+ RP1_PWM_CHAN_CTRL_MODE_MSB_SER,
+ RP1_PWM_CHAN_CTRL_MODE_PPM,
+ RP1_PWM_CHAN_CTRL_MODE_LE_MS,
+ RP1_PWM_CHAN_CTRL_MODE_LSB_SER,
+};
+
+#define RP1_PWM_CHAN_CTRL_DEFAULT (RP1_PWM_CHAN_CTRL_FIFO_POP_MASK + \
+ FIELD_PREP(RP1_PWM_CHAN_CTRL_MODE, \
+ RP1_PWM_CHAN_CTRL_MODE_TE_MS))
+
+#define RP1_PWM_RANGE(chan) (0x018 + ((chan) * 0x10))
+#define RP1_PWM_PHASE(chan) (0x01C + ((chan) * 0x10))
+#define RP1_PWM_DUTY(chan) (0x020 + ((chan) * 0x10))
+
+#define RP1_PWM_NUM_PWMS 4
+
+struct rp1_pwm {
+ struct regmap *regmap;
+ struct clk *clk;
+ unsigned long clk_rate;
+ bool clk_enabled;
+};
+
+struct rp1_pwm_waveform {
+ u32 period_ticks;
+ u32 duty_ticks;
+ bool enabled;
+ bool inverted_polarity;
+};
+
+static const struct regmap_config rp1_pwm_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x60,
+};
+
+static void rp1_pwm_apply_config(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
+ u32 value;
+
+ /* update the changed registers on the next strobe to avoid glitches */
+ regmap_read(rp1->regmap, RP1_PWM_GLB_CTRL, &value);
+ value |= RP1_PWM_GLB_CTRL_SET_UPDATE;
+ regmap_write(rp1->regmap, RP1_PWM_GLB_CTRL, value);
+}
+
+static int rp1_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
+
+ /* init channel to reset defaults, preserving the polarity bit */
+ regmap_update_bits(rp1->regmap, RP1_PWM_CHAN_CTRL(pwm->hwpwm),
+ ~(u32)RP1_PWM_CHAN_CTRL_POLARITY, RP1_PWM_CHAN_CTRL_DEFAULT);
+ return 0;
+}
+
+static int rp1_pwm_round_waveform_tohw(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ const struct pwm_waveform *wf,
+ void *_wfhw)
+{
+ struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
+ u64 period_ticks, duty_ticks, offset_ticks;
+ struct rp1_pwm_waveform *wfhw = _wfhw;
+ u64 clk_rate = rp1->clk_rate;
+ int ret = 0;
+
+ if (!wf->period_length_ns) {
+ *wfhw = (typeof(*wfhw)){
+ .enabled = false,
+ .inverted_polarity = false,
+ };
+ return 0;
+ }
+
+ period_ticks = mul_u64_u64_div_u64(wf->period_length_ns, clk_rate, NSEC_PER_SEC);
+
+ /*
+ * The period is limited to U32_MAX, and it will be decremented by one later
+ * to allow 100% duty cycle.
+ */
+ if (period_ticks > U32_MAX) {
+ period_ticks = U32_MAX;
+ } else if (period_ticks < 2) {
+ period_ticks = 2;
+ ret = 1;
+ }
+
+ duty_ticks = mul_u64_u64_div_u64(wf->duty_length_ns, clk_rate, NSEC_PER_SEC);
+ duty_ticks = min(duty_ticks, period_ticks);
+ offset_ticks = mul_u64_u64_div_u64(wf->duty_offset_ns, clk_rate, NSEC_PER_SEC);
+ if (offset_ticks >= period_ticks)
+ offset_ticks = period_ticks - 1;
+ if (duty_ticks && offset_ticks &&
+ duty_ticks + offset_ticks >= period_ticks) {
+ wfhw->duty_ticks = period_ticks - duty_ticks;
+ wfhw->inverted_polarity = true;
+ } else {
+ wfhw->duty_ticks = duty_ticks;
+ wfhw->inverted_polarity = false;
+ }
+ /* Account for the extra tick at the end of the period */
+ wfhw->period_ticks = period_ticks - 1;
+
+ wfhw->enabled = true;
+
+ return ret;
+}
+
+static int rp1_pwm_round_waveform_fromhw(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ const void *_wfhw,
+ struct pwm_waveform *wf)
+{
+ struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
+ const struct rp1_pwm_waveform *wfhw = _wfhw;
+ u64 clk_rate = rp1->clk_rate;
+ u64 ticks;
+
+ *wf = (struct pwm_waveform){ };
+
+ if (!wfhw->enabled)
+ return 0;
+
+ wf->period_length_ns = DIV_ROUND_UP_ULL(((u64)wfhw->period_ticks + 1) * NSEC_PER_SEC,
+ clk_rate);
+
+ if (!wfhw->inverted_polarity) {
+ wf->duty_length_ns = DIV_ROUND_UP_ULL((u64)wfhw->duty_ticks * NSEC_PER_SEC,
+ (u32)clk_rate);
+ } else {
+ if (wfhw->duty_ticks > (u64)wfhw->period_ticks + 1) {
+ /* 100% duty cycle case */
+ ticks = 0;
+ } else {
+ ticks = (u64)wfhw->period_ticks + 1 - wfhw->duty_ticks;
+ }
+ wf->duty_length_ns = DIV_ROUND_UP_ULL(ticks * NSEC_PER_SEC, clk_rate);
+ wf->duty_offset_ns = DIV_ROUND_UP_ULL((u64)(wfhw->period_ticks + 1 - ticks) *
+ NSEC_PER_SEC, clk_rate);
+ }
+
+ return 0;
+}
+
+static int rp1_pwm_write_waveform(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ const void *_wfhw)
+{
+ struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
+ const struct rp1_pwm_waveform *wfhw = _wfhw;
+ u32 value, ctrl;
+
+ /* set polarity */
+ regmap_read(rp1->regmap, RP1_PWM_CHAN_CTRL(pwm->hwpwm), &value);
+ if (!wfhw->inverted_polarity)
+ value &= ~RP1_PWM_CHAN_CTRL_POLARITY;
+ else
+ value |= RP1_PWM_CHAN_CTRL_POLARITY;
+ regmap_write(rp1->regmap, RP1_PWM_CHAN_CTRL(pwm->hwpwm), value);
+
+ /* early exit if disabled */
+ regmap_read(rp1->regmap, RP1_PWM_GLB_CTRL, &ctrl);
+ if (!wfhw->enabled) {
+ ctrl &= ~RP1_PWM_GLB_CTRL_CHANNEL_ENABLE(pwm->hwpwm);
+ /* just disable the channel and bail out early */
+ regmap_write(rp1->regmap, RP1_PWM_GLB_CTRL, ctrl);
+ rp1_pwm_apply_config(chip, pwm);
+ return 0;
+ }
+
+ /* set period and duty cycle */
+ regmap_write(rp1->regmap,
+ RP1_PWM_RANGE(pwm->hwpwm), wfhw->period_ticks);
+ regmap_write(rp1->regmap,
+ RP1_PWM_DUTY(pwm->hwpwm), wfhw->duty_ticks);
+
+ /* enable the channel */
+ ctrl |= RP1_PWM_GLB_CTRL_CHANNEL_ENABLE(pwm->hwpwm);
+ regmap_write(rp1->regmap, RP1_PWM_GLB_CTRL, ctrl);
+
+ rp1_pwm_apply_config(chip, pwm);
+
+ return 0;
+}
+
+static int rp1_pwm_read_waveform(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ void *_wfhw)
+{
+ struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
+ struct rp1_pwm_waveform *wfhw = _wfhw;
+ u32 value;
+
+ regmap_read(rp1->regmap, RP1_PWM_GLB_CTRL, &value);
+ wfhw->enabled = !!(value & RP1_PWM_GLB_CTRL_CHANNEL_ENABLE(pwm->hwpwm));
+
+ regmap_read(rp1->regmap, RP1_PWM_CHAN_CTRL(pwm->hwpwm), &value);
+ wfhw->inverted_polarity = !!(value & RP1_PWM_CHAN_CTRL_POLARITY);
+
+ if (wfhw->enabled) {
+ regmap_read(rp1->regmap, RP1_PWM_RANGE(pwm->hwpwm), &wfhw->period_ticks);
+ regmap_read(rp1->regmap, RP1_PWM_DUTY(pwm->hwpwm), &wfhw->duty_ticks);
+ } else {
+ *wfhw = (typeof(*wfhw)) {
+ .period_ticks = 0,
+ .duty_ticks = 0,
+ };
+ }
+
+ return 0;
+}
+
+static const struct pwm_ops rp1_pwm_ops = {
+ .sizeof_wfhw = sizeof(struct rp1_pwm_waveform),
+ .request = rp1_pwm_request,
+ .round_waveform_tohw = rp1_pwm_round_waveform_tohw,
+ .round_waveform_fromhw = rp1_pwm_round_waveform_fromhw,
+ .read_waveform = rp1_pwm_read_waveform,
+ .write_waveform = rp1_pwm_write_waveform,
+};
+
+static int rp1_pwm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ unsigned long clk_rate;
+ struct pwm_chip *chip;
+ void __iomem *base;
+ struct rp1_pwm *rp1;
+ int ret;
+
+ chip = devm_pwmchip_alloc(dev, RP1_PWM_NUM_PWMS, sizeof(*rp1));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+
+ rp1 = pwmchip_get_drvdata(chip);
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ rp1->regmap = devm_regmap_init_mmio(dev, base, &rp1_pwm_regmap_config);
+ if (IS_ERR(rp1->regmap))
+ return dev_err_probe(dev, PTR_ERR(rp1->regmap), "Cannot initialize regmap\n");
+
+ rp1->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(rp1->clk))
+ return dev_err_probe(dev, PTR_ERR(rp1->clk), "Clock not found\n");
+
+ ret = clk_prepare_enable(rp1->clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable clock\n");
+ rp1->clk_enabled = true;
+
+ ret = devm_clk_rate_exclusive_get(dev, rp1->clk);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to get exclusive rate\n");
+ goto err_disable_clk;
+ }
+
+ clk_rate = clk_get_rate(rp1->clk);
+ if (!clk_rate) {
+ ret = dev_err_probe(dev, -EINVAL, "Failed to get clock rate\n");
+ goto err_disable_clk;
+ }
+ /*
+ * To prevent u64 overflow in period calculations:
+ * mul_u64_u64_div_u64(period_ns, clk_rate, NSEC_PER_SEC)
+ * If clk_rate > 1 GHz, the result can overflow.
+ */
+ if (clk_rate > HZ_PER_GHZ) {
+ ret = dev_err_probe(dev, -EINVAL, "Clock rate > 1 GHz is not supported\n");
+ goto err_disable_clk;
+ }
+ rp1->clk_rate = clk_rate;
+
+ chip->ops = &rp1_pwm_ops;
+ chip->atomic = true;
+
+ platform_set_drvdata(pdev, chip);
+
+ ret = pwmchip_add(chip);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to register PWM chip\n");
+ goto err_disable_clk;
+ }
+
+ ret = of_syscon_register_regmap(np, rp1->regmap);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to register syscon\n");
+ goto err_remove_chip;
+ }
+
+ return 0;
+
+err_remove_chip:
+ pwmchip_remove(chip);
+err_disable_clk:
+ clk_disable_unprepare(rp1->clk);
+
+ return ret;
+}
+
+static int rp1_pwm_suspend(struct device *dev)
+{
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
+
+ if (rp1->clk_enabled) {
+ clk_disable_unprepare(rp1->clk);
+ rp1->clk_enabled = false;
+ }
+
+ return 0;
+}
+
+static int rp1_pwm_resume(struct device *dev)
+{
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
+ int ret;
+
+ ret = clk_prepare_enable(rp1->clk);
+ if (ret) {
+ dev_err(dev, "Failed to enable clock on resume: %pe\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ rp1->clk_enabled = true;
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(rp1_pwm_pm_ops, rp1_pwm_suspend, rp1_pwm_resume);
+
+static const struct of_device_id rp1_pwm_of_match[] = {
+ { .compatible = "raspberrypi,rp1-pwm" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rp1_pwm_of_match);
+
+static struct platform_driver rp1_pwm_driver = {
+ .probe = rp1_pwm_probe,
+ /*
+ * .remove is not needed because this driver cannot be removed/unbound
+ * cause it relies on syscon which cannot be removed
+ */
+ .driver = {
+ .name = "rp1-pwm",
+ .of_match_table = rp1_pwm_of_match,
+ .pm = pm_ptr(&rp1_pwm_pm_ops),
+ .suppress_bind_attrs = true,
+ },
+};
+builtin_platform_driver(rp1_pwm_driver);
+
+MODULE_DESCRIPTION("RP1 PWM driver");
+MODULE_AUTHOR("Naushir Patuck <naush@raspberrypi.com>");
+MODULE_AUTHOR("Andrea della Porta <andrea.porta@suse.com>");
+MODULE_LICENSE("GPL");
--
2.35.3
^ permalink raw reply related
* [PATCH v7 1/3] dt-bindings: pwm: Add Raspberry Pi RP1 PWM controller
From: Andrea della Porta @ 2026-07-20 9:44 UTC (permalink / raw)
To: Uwe Kleine-König, linux-pwm, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Broadcom internal kernel review list, Andrea della Porta,
devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
Naushir Patuck, Stanimir Varbanov, mbrugger, Sean Young,
Julian Braha
Cc: Krzysztof Kozlowski
In-Reply-To: <cover.1784539788.git.andrea.porta@suse.com>
From: Naushir Patuck <naush@raspberrypi.com>
Add the devicetree binding documentation for the PWM
controller found in the Raspberry Pi RP1 chipset.
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Co-developed-by: Stanimir Varbanov <svarbanov@suse.de>
Signed-off-by: Stanimir Varbanov <svarbanov@suse.de>
Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
.../bindings/pwm/raspberrypi,rp1-pwm.yaml | 66 +++++++++++++++++++
1 file changed, 66 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml
diff --git a/Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml b/Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml
new file mode 100644
index 0000000000000..970d0f3b33bbb
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/raspberrypi,rp1-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Raspberry Pi RP1 PWM controller
+
+maintainers:
+ - Naushir Patuck <naush@raspberrypi.com>
+ - Andrea della Porta <andrea.porta@suse.com>
+ - Stanimir Varbanov <svarbanov@suse.de>
+
+allOf:
+ - $ref: pwm.yaml#
+
+description: |
+ The PWM peripheral is a flexible waveform generator with a
+ variety of operational modes. It has the following features:
+ - four independent output channels
+ - 32-bit counter widths
+ - Seven output generation modes
+ - Optional per-channel output inversion
+ - Optional duty-cycle data FIFO with DMA support
+ - Optional sigma-delta noise shaping engine
+ Serves as a fan speed provider to other nodes for a PWM-connected
+ fan using shared registers (syscon).
+
+properties:
+ compatible:
+ const: raspberrypi,rp1-pwm
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ "#pwm-cells":
+ const: 3
+
+ dmas:
+ maxItems: 1
+ description: |
+ Phandle to the DMA controller and the channel specifier for
+ the duty-cycle FIFO.
+
+ dma-names:
+ items:
+ - const: tx
+
+required:
+ - compatible
+ - reg
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ pwm@98000 {
+ compatible = "raspberrypi,rp1-pwm";
+ reg = <0x98000 0x100>;
+ clocks = <&rp1_clocks 17>;
+ #pwm-cells = <3>;
+ };
--
2.35.3
^ permalink raw reply related
* [PATCH v7 0/3] Add RP1 PWM controller support
From: Andrea della Porta @ 2026-07-20 9:44 UTC (permalink / raw)
To: Uwe Kleine-König, linux-pwm, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Broadcom internal kernel review list, Andrea della Porta,
devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
Naushir Patuck, Stanimir Varbanov, mbrugger, Sean Young,
Julian Braha
This patchset adds support for the PWM controller found on the
Raspberry Pi RP1 southbridge. This is necessary to operate the
cooling fan connected to one of the PWM channels.
The tachometer pin for the fan speed is managed by the firmware
running on the RP1's M-core. It uses the PHASE2 register
to report the RPM, which is then exported by this driver via
syscon registers. A subsequent patch will add a new device
and driver to read the RPM and export this value via hwmon.
Subsequent patches will also add the CPU thermal zone, which
acts as a consumer of the PWM device.
Best regards,
Andrea
CHANGES in V7:
- _tohw(): use *wfhw = (typeof(*wfhw)){...} to initialize the
structure in the disable case
- _tohw(): fixed the offset_ticks calculation
- _fromhw(): fixed a rounding error in the duty_offset_ns calculation
- _write_waveform(): dropped the goto in favor of return in diasble
channel exit path
- _read_waveform(): use *wfhw = (typeof(*wfhw)){...} to initialize
the structure in the disable case
- dropped rp1_pwm_remove() since this driver depends on syscon
and cannot be removed/unbound (added a comment to explain that)
Naushir Patuck (2):
dt-bindings: pwm: Add Raspberry Pi RP1 PWM controller
pwm: rp1: Add RP1 PWM controller driver
Stanimir Varbanov (1):
arm64: dts: broadcom: rpi-5: Add RP1 PWM node
.../bindings/pwm/raspberrypi,rp1-pwm.yaml | 66 +++
.../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 12 +
arch/arm64/boot/dts/broadcom/rp1-common.dtsi | 9 +
drivers/pwm/Kconfig | 9 +
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-rp1.c | 428 ++++++++++++++++++
6 files changed, 525 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml
create mode 100644 drivers/pwm/pwm-rp1.c
--
2.35.3
^ permalink raw reply
* [PATCH] arm64: dts: qcom: sm8150: Add slim nodes
From: XiaoYeZi @ 2026-07-20 9:33 UTC (permalink / raw)
To: andersson, konradybcio, robh, krzk+dt
Cc: conor+dt, linux-arm-msm, devicetree, linux-kernel, XiaoYeZi
The slimbus node is an important node in audio.
Signed-off-by: XiaoYeZi <qaz6750@qq.com>
---
arch/arm64/boot/dts/qcom/sm8150.dtsi | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index 661848ef5..2a83ba554 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -4410,6 +4410,18 @@ watchdog@17c10000 {
interrupts = <GIC_SPI 0 IRQ_TYPE_EDGE_RISING>;
};
+ slimbam: dma-controller@17184000 {
+ compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0";
+ qcom,controlled-remotely;
+ reg = <0 0x17184000 0 0x2c000>;
+ num-channels = <31>;
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ qcom,ee = <1>;
+ qcom,num-ees = <2>;
+ iommus = <&apps_smmu 0x1b46 0x0>;
+ };
+
timer@17c20000 {
#address-cells = <1>;
#size-cells = <1>;
@@ -4577,6 +4589,20 @@ cpufreq_hw: cpufreq@18323000 {
#clock-cells = <1>;
};
+ slim: slim-ngd@171c0000 {
+ compatible = "qcom,slim-ngd-v2.1.0";
+ reg = <0 0x171c0000 0 0x2c000>;
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
+
+ dmas = <&slimbam 3>, <&slimbam 4>;
+ dma-names = "rx", "tx";
+
+ iommus = <&apps_smmu 0x1b46 0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
lmh_cluster1: lmh@18350800 {
compatible = "qcom,sm8150-lmh";
reg = <0 0x18350800 0 0x400>;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2] of: property: Create devlink between PCI Host bridge and Root Port supplies
From: Konrad Dybcio @ 2026-07-20 9:30 UTC (permalink / raw)
To: Manivannan Sadhasivam, robh, saravanak
Cc: devicetree, linux-kernel, qiang.yu, linux-arm-msm,
Bjorn Andersson
In-Reply-To: <fa5c5ed6-afd3-4e5d-80bb-921d6f96dfac@oss.qualcomm.com>
On 5/8/26 12:32 PM, Konrad Dybcio wrote:
> On 5/6/26 9:56 AM, Manivannan Sadhasivam wrote:
>> Recently, devicetree started to represent the PCI Host bridge supplies like
>> PHY in the Root Port nodes as seen in commit 38fcbfbd4207
>> ("dt-bindings: PCI: qcom: Move PHY & reset GPIO to Root Port node"). But
>> the Host bridge drivers still control the Root Port supplies as a part of
>> their controller initialization/deinitialization sequence.
[...]
>> + /*
>> + * Since the host bridge drivers parse and control the Root Port
>> + * supplies, create a devlink between host bridge and Root Port
>> + * supplies. This will prevent the host bridge drivers from being
>> + * probed before the supplies become available.
>> + *
>> + * For checking the host bridge node, first ensure that it is a PCI node
>> + * and its parent is not a PCI node. Only host bridge nodes will have
>> + * this structure.
>> + */
>> + if (of_node_is_type(con_np, "pci") && !of_node_is_type(con_np->parent, "pci")) {
>> + for_each_available_child_of_node_scoped(con_np, child) {
>> + if (of_node_is_type(child, "pci")) {
>
> Doesn't this go a level too deep now? (a change vs v1)
>
> for example, in x1e80100.dtsi:
>
> con_np = &pcie3_port0
> con_np->parent = &pcie3
>
> And I think the code now looks for device(such that device_type="pci")
> *under* &pcie3_port0
No, clearly I managed to misunderstand this.
Tested-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> # Glymur CRD
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* RE: [PATCH v28 4/7] firmware: imx: device context dedicated to priv
From: Pankaj Gupta (OSS) @ 2026-07-20 9:30 UTC (permalink / raw)
To: Frank Li (OSS), sashiko-reviews@lists.linux.dev
Cc: Pankaj Gupta (OSS), Frank.Li@kernel.org, robh@kernel.org,
conor+dt@kernel.org, devicetree@vger.kernel.org,
imx@lists.linux.dev
In-Reply-To: <alpU8weYCU95_c6E@SMW015318>
> -----Original Message-----
> From: Frank Li (OSS) <frank.li@oss.nxp.com>
> Sent: 17 July 2026 21:45
> To: sashiko-reviews@lists.linux.dev
> Cc: Pankaj Gupta (OSS) <pankaj.gupta@oss.nxp.com>; Frank.Li@kernel.org;
> robh@kernel.org; conor+dt@kernel.org; devicetree@vger.kernel.org;
> imx@lists.linux.dev
> Subject: Re: [PATCH v28 4/7] firmware: imx: device context dedicated to priv
>
> On Fri, Jul 17, 2026 at 11:13:53AM +0000, sashiko-bot@kernel.org wrote:
> > Thank you for your contribution! Sashiko AI review found 2 potential issue(s)
> to consider:
> > - [High] Data race in `ele_msg_send_rcv()` when initializing
> `waiting_rsp_clbk_hdl` state, leading to a potential NULL pointer dereference
> in the RX interrupt handler.
> > - [Low] Unused variable `flags` in `ele_msg_send_rcv()`.
> > --
> >
> > --- Patch [4]: [PATCH v28 4/7] firmware: imx: device context dedicated
> > to priv --- commit 64e554919e156aa88c2007ef9dd9fafde735e583
> > Author: Pankaj Gupta <pankaj.gupta@nxp.com>
> >
> > firmware: imx: device context dedicated to priv
> >
> > Add priv_dev_ctx to prepare enabling misc-device context based
> > send-receive path, to communicate with FW. No functionality change.
> >
> > Closes:
> > https://sashiko.dev/#/patchset/20260715-imx-se-if-v27-0-
> bb7c45952f06@n
> > xp.com?part=4
> >
> > > diff --git a/drivers/firmware/imx/ele_common.c
> > > b/drivers/firmware/imx/ele_common.c
> > > index ca8a32a82689b..1ca22c53b55c4 100644
> > > --- a/drivers/firmware/imx/ele_common.c
> > > +++ b/drivers/firmware/imx/ele_common.c
> >
> > [ ... ]
> >
> > > @@ -149,34 +151,38 @@ static void ele_msg_send_rcv_cleanup(struct
> se_if_priv *priv)
> > > unsigned long flags;
> > >
> > > spin_lock_irqsave(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock,
> > > flags);
> > > + priv->waiting_rsp_clbk_hdl.dev_ctx = NULL;
> > > priv->waiting_rsp_clbk_hdl.rx_msg = NULL;
> > > priv->waiting_rsp_clbk_hdl.rx_msg_sz = 0;
> > > spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock,
> > > flags); }
> > >
> > > /* API used for send/receive blocking call. */ -int
> > > ele_msg_send_rcv(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz,
> > > - void *rx_msg, int exp_rx_msg_sz)
> > > +int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx, void *tx_msg,
> > > + int tx_msg_sz, void *rx_msg, int exp_rx_msg_sz)
> > > {
> > > + struct se_if_priv *priv = dev_ctx->priv;
> > > + unsigned long flags;
> >
> > [Severity: Low]
> > Is this flags variable used anywhere in this function?
> >
> > It appears to be declared but never utilized in the function scope,
> > which will trigger a -Wunused-variable compiler warning.
>
> Yes, fix it.
[Accepted] But no need to remove this. As to fix the next comment, this flag is needed.
>
> >
> > > int err;
> > >
> > > guard(mutex)(&priv->se_if_cmd_lock);
> > >
> > > if (atomic_read(&priv->fw_busy)) {
> > > - dev_dbg(priv->dev, "ELE became unresponsive.\n");
> > > + dev_dbg(priv->dev, "%s: ELE became unresponsive.\n",
> > > +dev_ctx->devname);
> > > return -EBUSY;
> > > }
> > > reinit_completion(&priv->waiting_rsp_clbk_hdl.done);
> > > + priv->waiting_rsp_clbk_hdl.dev_ctx = dev_ctx;
> > > priv->waiting_rsp_clbk_hdl.rx_msg_sz = exp_rx_msg_sz;
> > > priv->waiting_rsp_clbk_hdl.rx_msg = rx_msg;
> >
> > [Severity: High]
> > Could these lockless updates result in a data race with the interrupt
> > handler?
> >
> > They are updated here without acquiring clbk_rx_lock. If a delayed
> > firmware response from a previous command arrives concurrently, the
> > interrupt handler
> > se_if_rx_callback() will execute.
> >
> > Due to CPU reordering or compiler optimizations, can the interrupt
> > handler observe the new rx_msg pointer before the new dev_ctx pointer
> > becomes visible?
>
> Please check this
>
> Frank
[Accepted] priv->waiting_rsp_clbk_hdl.dev_ctx, priv->waiting_rsp_clbk_hdl.rx_msg, priv->waiting_rsp_clbk_hdl.rx_msg_sz
will be updated after acquiring the clbk_rx_lock.
>
> >
> > > - err = ele_msg_send(priv, tx_msg, tx_msg_sz);
> > > + err = ele_msg_send(dev_ctx, tx_msg, tx_msg_sz);
> >
> > [ ... ]
> >
> > > @@ -302,8 +310,8 @@ void se_if_rx_callback(struct mbox_client
> *mbox_cl, void *msg)
> > > dev_info(dev, "ELE responded (late), recovery FW
> available.");
> > > return;
> > > }
> > > - dev_dbg(dev, "Selecting resp waiter: for mesg header:0x%x.",
> > > - *(u32 *)header);
> > > + dev_dbg(dev, "Selecting resp waiter:%s for mesg
> header:0x%x.",
> > > + se_clbk_hdl->dev_ctx->devname, *(u32 *)header);
> >
> > If the interrupt handler sees a non-NULL rx_msg, it assumes the
> > transaction is active and attempts to access
> > se_clbk_hdl->dev_ctx->devname here. If dev_ctx is still NULL from the
> > previous cleanup, won't this result in a NULL pointer dereference?
> >
> > >
> > > /*
> > > * For rsp_tag traffic, the sender provides the expected
> response
[Accepted] Create a local variable "const char *devname" and assigned its value under the clbk_rx_lock in se_if_rx_callback().
> >
> > --
> > Sashiko AI review *
> > https://sashiko.dev/#/patchset/20260717-imx-se-if-v28-0-
> 0a9659c7e69d@n
> > xp.com?part=4
^ permalink raw reply
* [PATCH] arm64: dts: mediatek: mt8192-asurada: Disable mmc1 on Spherion
From: Chen-Yu Tsai @ 2026-07-20 9:27 UTC (permalink / raw)
To: Matthias Brugger, AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-mediatek, devicetree, linux-arm-kernel,
linux-kernel
Spherion does not have an micro SD card slot.
Disable mmc1.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
index c02edba73eaf..0b976b09d47f 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
@@ -64,6 +64,10 @@ &rt5682 {
VBAT-supply = <&pp3300_ldo_z>;
};
+&mmc1 {
+ status = "disabled";
+};
+
&sound {
compatible = "mediatek,mt8192_mt6359_rt1015p_rt5682";
--
2.55.0.229.g6434b31f56-goog
^ permalink raw reply related
* Re: [PATCH RESEND] dt-bindings: PCI: mediatek-gen3: Allow memory-region for restricted DMA buffer
From: sashiko-bot @ 2026-07-20 9:26 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: devicetree, linux-pci, robh, conor+dt
In-Reply-To: <20260720092116.1823562-1-wenst@chromium.org>
> On some SoCs without an IOMMU behind the PCIe controller, the PCIe
> controller memory access could be limited to a small region by the
> firmware configuring a memory protection unit. This memory region
> must be assigned to the PCIe controller so that the OS knows to
> use that region. Otherwise PCIe devices would not work properly.
>
> Allow the memory-region property with one item pointing to a
> restricted DMA buffer.
>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Acked-by: Rob Herring (Arm) <robh@kernel.org>
> Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260720092116.1823562-1-wenst@chromium.org?part=1
^ permalink raw reply
* [PATCH RESEND] dt-bindings: PCI: mediatek-gen3: Allow memory-region for restricted DMA buffer
From: Chen-Yu Tsai @ 2026-07-20 9:21 UTC (permalink / raw)
To: Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Chen-Yu Tsai,
linux-pci, linux-mediatek, devicetree, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, Conor Dooley
On some SoCs without an IOMMU behind the PCIe controller, the PCIe
controller memory access could be limited to a small region by the
firmware configuring a memory protection unit. This memory region
must be assigned to the PCIe controller so that the OS knows to
use that region. Otherwise PCIe devices would not work properly.
Allow the memory-region property with one item pointing to a
restricted DMA buffer.
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Can we get this merged for v7.2? A matching device tree change was
already merged in v7.2-rc1.
Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
index fbc0378392d4..b88717dec1fa 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
@@ -116,6 +116,10 @@ properties:
power-domains:
maxItems: 1
+ memory-region:
+ maxItems: 1
+ description: phandle to restricted DMA buffer
+
mediatek,pbus-csr:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
--
2.55.0.229.g6434b31f56-goog
^ permalink raw reply related
* Re: [PATCH v6 04/16] clk: qcom: dispcc-qcm2290: Enable runtime PM support
From: Konrad Dybcio @ 2026-07-20 9:13 UTC (permalink / raw)
To: Imran Shaik, Bjorn Andersson, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio,
Loic Poulain, Brian Masney, Dmitry Baryshkov
Cc: Ajit Pandey, Taniya Das, Jagadeesh Kona, linux-arm-msm, linux-clk,
devicetree, linux-kernel
In-Reply-To: <20260718-shikra-dispcc-gpucc-v6-4-62703e05ef0f@oss.qualcomm.com>
On 7/18/26 2:56 PM, Imran Shaik wrote:
> The QCM2290 DISPCC is now associated with a power domain (RPMPD_CX) to
> propagate genpd performance state votes to the CX rail. Set use_rpm to
> true so that a runtime PM reference is acquired and released around probe,
> instead of leaving a permanent 'enable' vote on the power domain.
>
> Fixes: cc517ea3333f ("clk: qcom: Add display clock controller driver for QCM2290")
> Signed-off-by: Imran Shaik <imran.shaik@oss.qualcomm.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* Re: [PATCH 3/3] arm64: dts: qcom: Add INT2_GDSC to MDSS on Kaanapali and Glymur
From: sashiko-bot @ 2026-07-20 9:05 UTC (permalink / raw)
To: Yongxing Mou; +Cc: conor+dt, robh, dri-devel, devicetree
In-Reply-To: <20260720-msm_gdsc2-v1-3-4687866d6cb0@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] The patch omits `sm8750.dtsi`, failing to add the `INT2_GDSC` power domain for SM8750 despite the commit message explicitly declaring that SM8750 requires it.
- [High] Missing cleanup of the IRQ domain and chained handler when power domain attachment fails, leading to a Use-After-Free.
--
--- Patch [3]: [PATCH 3/3] arm64: dts: qcom: Add INT2_GDSC to MDSS on Kaanapali and Glymur ---
commit a757d0e4c829d9c4eb6cdd0c681fb7e3459e226e
Author: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
arm64: dts: qcom: Add INT2_GDSC to MDSS on Kaanapali and Glymur
Kaanapali (SM8750) and Glymur use two display power domains.
CORE_GDSC powers the main display hardware while INT2_GDSC powers
a subset of SSPP blocks (VIG2/VIG3/DMA5/DMA6).
Add DISP_CC_MDSS_CORE_INT2_GDSC alongside the existing CORE_GDSC
reference in the MDSS node on both platforms and provide matching
power-domain-names entries for the display power domains.
> Kaanapali (SM8750) and Glymur use two display power domains.
> CORE_GDSC powers the main display hardware while INT2_GDSC powers
> a subset of SSPP blocks (VIG2/VIG3/DMA5/DMA6).
[Severity: High]
The commit message explicitly states that Kaanapali (SM8750) requires the
INT2_GDSC power domain. However, the patch omits updating sm8750.dtsi.
Could this omission cause SM8750 platforms using sm8750.dtsi to fall back
to single-domain mode and fail to attach the secondary power domain, leaving
a subset of SSPP blocks (VIG2/VIG3/DMA5/DMA6) unpowered and inaccessible?
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index 9087c4b290dba..63ece55c4f2ec 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
[ ... ]
@@ -421,6 +451,27 @@ static struct msm_mdss *msm_mdss_init(struct platform_device *pdev, bool is_mdp5
irq_set_chained_handler_and_data(irq, msm_mdss_irq,
msm_mdss);
+ /*
+ * When two power domains are listed in DT, the core framework does not
+ * auto-attach either of them. Attach and manage both explicitly so
+ * that INT2_GDSC (needed for VIG2/VIG3) is enabled alongside the main
+ * CORE_GDSC. Single-domain platforms are unaffected.
+ */
+ if (of_count_phandle_with_args(pdev->dev.of_node, "power-domains",
+ "#power-domain-cells") > 1) {
+ static const char * const mdss_pd_names[] = { "core", "int2" };
+ static const struct dev_pm_domain_attach_data pd_data = {
+ .pd_names = mdss_pd_names,
+ .num_pd_names = ARRAY_SIZE(mdss_pd_names),
+ .pd_flags = PD_FLAG_NO_DEV_LINK,
+ };
+
+ ret = devm_pm_domain_attach_list(&pdev->dev, &pd_data,
+ &msm_mdss->pd_list);
+ if (ret < 0)
+ return ERR_PTR(ret);
[Severity: High]
Is it possible this error path leaves a dangling pointer registered in the IRQ
subsystem?
In msm_mdss_init(), irq_set_chained_handler_and_data() is called earlier to
install the chained handler with msm_mdss as the data pointer, and the IRQ
domain is created via irq_domain_create_linear(). If
devm_pm_domain_attach_list() fails (e.g., due to probe deferral), this block
directly returns an error without calling irq_set_chained_handler_and_data()
with NULL to clean it up, or calling irq_domain_remove().
Because msm_mdss is devres-allocated, it will be freed upon probe failure.
If a spurious or shared interrupt fires on that IRQ line, will the kernel
execute msm_mdss_irq() and dereference the freed msm_mdss pointer, causing a
use-after-free and a kernel panic?
+ }
+
pm_runtime_enable(&pdev->dev);
return msm_mdss;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260720-msm_gdsc2-v1-0-4687866d6cb0@oss.qualcomm.com?part=3
^ permalink raw reply
* Re: [PATCH v6 2/3] clk: cs2600: Add Fractional-N clock driver
From: Richard Fitzgerald @ 2026-07-20 9:03 UTC (permalink / raw)
To: Brian Masney
Cc: mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk, devicetree,
linux-kernel, patches
In-Reply-To: <ak0iEAJsZJOkvkX1@redhat.com>
On 07/07/2026 4:58 pm, Brian Masney wrote:
> Hi Richard,
>
> Thanks for the patch.
>
> On Tue, Jun 30, 2026 at 04:55:48PM +0100, Richard Fitzgerald wrote:
>> From: Paul Handrigan <paulha@opensource.cirrus.com>
>>
>> Add driver for the Cirrus Logic CS2600 fractional-N clock synthesizer
>> and multiplier.
>>
<SNIP>
>> +
>> +DEFINE_GUARD(cs2600_unfreeze, struct cs2600 *,
>> + cs2600_clear_freeze(_T), cs2600_set_freeze(_T))
>
> Can you go through the Sashiko output for this series?
I sent an email responding to those, but it was reply-all to the Sashiko
bot email and I didn't notice that Sashiko had stripped a lot of the
original email recipients.
My responses to Sashiko are here:
https://lore.kernel.org/all/dc5a1c0c-8c6b-4f4b-90f1-e9c83a8b91b8@opensource.cirrus.com/
> https://sashiko.dev/#/message/20260630161121.020FB1F000E9%40smtp.kernel.org
>
> The clear/set inverted looks questionable to me. If this is expected,
> then a comment clarifying why should be added.
I'll add a comment in the next version explaining the order.
> [snip]
>
>> +static int cs2600_clk_register(struct cs2600 *cs2600)
>> +{
>> + static const char *parent_names[2];
>
> I wouldn't worry too about about Sashiko asking about multiple driver
> instances for this section, unless you think it will eventually be used
> in that way.
Trivial to fix though. That 'static' shouldn't be there.
>> + const struct clk_hw *out_clocks_parent;
>> + struct clk_init_data init[ARRAY_SIZE(cs2600->hw)] = { };
>> + int ret, i, n, input_num = 0;
>> + const char *names[ARRAY_SIZE(cs2600_clks)];
>
> Reverse Christmas tree order.
Will do.
> I can do a more thorough review once you go through the Sashiko results.
>
> Brian
>
^ permalink raw reply
* Re: [PATCH 3/5] arm64: dts: qcom: Add Kalambo CRD
From: Konrad Dybcio @ 2026-07-20 8:58 UTC (permalink / raw)
To: Gopikrishna Garmidi, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sibi Sankar, Pankaj Patil
Cc: Rajendra Nayak, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260718-b4-kalambo-crd-v1-3-a1069b5a2757@oss.qualcomm.com>
On 7/18/26 2:06 PM, Gopikrishna Garmidi wrote:
> Introduce support for the CRD based on the Qualcomm Kalambo SoC. Similar
> to Mahua, it is pin-to-pin compatible with the Glymur CRD. It reuses the
> common CRD board description and drops the PMIC nodes not present on this
> design.
>
> Signed-off-by: Gopikrishna Garmidi <gopikrishna.garmidi@oss.qualcomm.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* Re: [PATCH 2/3] drm/msm/mdss: Enable INT2_GDSC alongside CORE_GDSC
From: sashiko-bot @ 2026-07-20 8:58 UTC (permalink / raw)
To: Yongxing Mou; +Cc: dri-devel, robh, conor+dt, devicetree
In-Reply-To: <20260720-msm_gdsc2-v1-2-4687866d6cb0@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Missing cleanup for IRQ domain and chained handler on power domain attach failure.
--
--- Patch [2]: [PATCH 2/3] drm/msm/mdss: Enable INT2_GDSC alongside CORE_GDSC ---
commit 9d271e868146fa30f583363d709a200283bfe76e
Author: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
drm/msm/mdss: Enable INT2_GDSC alongside CORE_GDSC
This patch explicitly attaches and manages the secondary INT2_GDSC power
domain for platforms that use it. It also ensures both power domains are
enabled during MDSS runtime PM activation.
> diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
> index 9087c4b290dba..63ece55c4f2ec 100644
> --- a/drivers/gpu/drm/msm/msm_mdss.c
> +++ b/drivers/gpu/drm/msm/msm_mdss.c
[ ... ]
> @@ -421,6 +451,27 @@ static struct msm_mdss *msm_mdss_init(struct platform_device *pdev, bool is_mdp5
> irq_set_chained_handler_and_data(irq, msm_mdss_irq,
> msm_mdss);
>
> + /*
> + * When two power domains are listed in DT, the core framework does not
> + * auto-attach either of them. Attach and manage both explicitly so
> + * that INT2_GDSC (needed for VIG2/VIG3) is enabled alongside the main
> + * CORE_GDSC. Single-domain platforms are unaffected.
> + */
> + if (of_count_phandle_with_args(pdev->dev.of_node, "power-domains",
> + "#power-domain-cells") > 1) {
> + static const char * const mdss_pd_names[] = { "core", "int2" };
> + static const struct dev_pm_domain_attach_data pd_data = {
> + .pd_names = mdss_pd_names,
> + .num_pd_names = ARRAY_SIZE(mdss_pd_names),
> + .pd_flags = PD_FLAG_NO_DEV_LINK,
> + };
> +
> + ret = devm_pm_domain_attach_list(&pdev->dev, &pd_data,
> + &msm_mdss->pd_list);
> + if (ret < 0)
> + return ERR_PTR(ret);
[Severity: High]
If devm_pm_domain_attach_list() fails here, we return directly with an error
pointer. Since the msm_mdss structure is allocated with devm_kzalloc(), it
will be automatically freed by the devres subsystem when the probe fails.
However, irq_set_chained_handler_and_data() was already called just above to
register msm_mdss_irq() with msm_mdss as its data pointer.
Could this leave a dangling pointer in the active chained handler, resulting
in a use-after-free if an interrupt fires? Also, do we need to clean up the
IRQ domain created by _msm_mdss_irq_domain_add() before returning on this
error path?
> + }
> +
> pm_runtime_enable(&pdev->dev);
>
> return msm_mdss;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260720-msm_gdsc2-v1-0-4687866d6cb0@oss.qualcomm.com?part=2
^ permalink raw reply
* Re: [PATCH 2/5] arm64: dts: qcom: Add Kalambo SoC
From: Konrad Dybcio @ 2026-07-20 8:57 UTC (permalink / raw)
To: Gopikrishna Garmidi, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sibi Sankar, Pankaj Patil
Cc: Rajendra Nayak, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260718-b4-kalambo-crd-v1-2-a1069b5a2757@oss.qualcomm.com>
On 7/18/26 2:06 PM, Gopikrishna Garmidi wrote:
> Introduce support for the Qualcomm Kalambo SoC. It is derived from Mahua
> with CPU cluster 0 removed, leaving it with just cluster 1. As a result,
> the PDP mailbox and SCP low-priority register windows are updated to
> match the reduced CPU complex. Everything else should work as-is.
>
> Add a label to the Glymur cluster0 cpu-map node to allow its removal on
> derived SoCs.
>
> Signed-off-by: Gopikrishna Garmidi <gopikrishna.garmidi@oss.qualcomm.com>
> ---
> arch/arm64/boot/dts/qcom/glymur.dtsi | 2 +-
> arch/arm64/boot/dts/qcom/kalambo.dtsi | 29 +++++++++++++++++++++++++++++
> 2 files changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi
> index 55d91c696a3a..f2feef362be5 100644
> --- a/arch/arm64/boot/dts/qcom/glymur.dtsi
> +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi
> @@ -275,7 +275,7 @@ cpu17: cpu@20500 {
> };
>
> cpu-map {
> - cluster0 {
> + cpu_map_cluster0: cluster0 {
I doubt the code that parses this will be happy about not
being able to start from 'cluster0'
[...]
> +&pdp0_mbox {
> + reg = <0 0x17610000 0 0x8000>, <0 0x1a980000 0 0x8000>;
> +};
Are you sure about this change?
> +&cpu_scp_lpri1 {
> + reg = <0x180 0x60>;
> +};
This is specific to old firmware, at least it was on Glymur, I believe..
Konrad
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox