* [PATCH v2] firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get()
From: Unnathi Chalicheemala @ 2026-06-17 23:35 UTC (permalink / raw)
To: Sudeep Holla, Jens Wiklander
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, kernel,
Trilok Soni, Satya Durga Srinivasu Prabhala,
Unnathi Chalicheemala
ffa_partition_info_get() passes uuid_str directly to uuid_parse()
without a NULL check. When a caller passes NULL, uuid_parse() ->
__uuid_parse() -> uuid_is_valid() dereferences the pointer, causing
a kernel panic:
Unable to handle kernel NULL pointer dereference at virtual address
0000000000000040
pc : uuid_parse+0x40/0xac
lr : ffa_partition_info_get+0x1c/0x94 [arm_ffa]
Add a NULL guard before uuid_parse() so a NULL argument returns
-ENODEV instead of crashing. Callers are expected to always supply
a valid partition UUID, so NULL is not a supported input.
Fixes: d0c0bce83122 ("firmware: arm_ffa: Setup in-kernel users of FFA partitions")
Signed-off-by: Unnathi Chalicheemala <unnathi.chalicheemala@oss.qualcomm.com>
---
Changes in v2:
- Drop special-casing of NULL/empty string to uuid_null; treat NULL as
an error instead - as pointed out by Sudeep in v1.
- Simplify to a single NULL guard before uuid_parse() rather than a
separate branch
- Link to v1: https://patch.msgid.link/20260611-ffa_partition_nullptr_fix-v1-1-ec2b7ef7e130@oss.qualcomm.com
---
drivers/firmware/arm_ffa/driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index b9f17fda7243..4090be782329 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1129,7 +1129,7 @@ static int ffa_partition_info_get(const char *uuid_str,
uuid_t uuid;
struct ffa_partition_info *pbuf;
- if (uuid_parse(uuid_str, &uuid)) {
+ if (!uuid_str || uuid_parse(uuid_str, &uuid)) {
pr_err("invalid uuid (%s)\n", uuid_str);
return -ENODEV;
}
---
base-commit: ba3e43a9e601636f5edb54e259a74f96ca3b8fd8
change-id: 20260604-ffa_partition_nullptr_fix-66f37bb2630b
Best regards,
--
Unnathi Chalicheemala <unnathi.chalicheemala@oss.qualcomm.com>
^ permalink raw reply related
* Re: [PATCH net v3] net: airoha: Fix skb->priority underflow in airoha_dev_select_queue()
From: Jakub Kicinski @ 2026-06-17 23:19 UTC (permalink / raw)
To: lorenzo
Cc: Wayen Yan, netdev, horms, pabeni, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In-Reply-To: <178161373805.2167512.2544164327472822616@gmail.com>
On Sun, 14 Jun 2026 07:30:54 +0800 Wayen Yan wrote:
> In airoha_dev_select_queue(), the expression:
>
> queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES;
>
> implicitly converts to unsigned arithmetic: when skb->priority is 0
> (the default for unclassified traffic), (0u - 1u) wraps to UINT_MAX,
> and UINT_MAX % 8 = 7, routing default best-effort packets to the
> highest-priority QoS queue. This causes QoS inversion where the
> majority of traffic on a PON gateway starves actual high-priority
> flows (VoIP, gaming, etc.).
>
> Fix by guarding the subtraction: when priority is 0, map to queue 0
> (lowest priority), otherwise apply the original (priority - 1) % 8
> mapping.
>
> Fixes: 2b288b81560b ("net: airoha: Introduce ndo_select_queue callback")
> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Reviewed-by: Joe Damato <joe@dama.to>
> Signed-off-by: Wayen Yan <win847@gmail.com>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 31cdb11cd7..d476ef83c3 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -1933,7 +1933,7 @@ static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb,
> */
> channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id;
> channel = channel % AIROHA_NUM_QOS_CHANNELS;
> - queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */
> + queue = skb->priority ? (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES : 0;
Hi Lorenzo, is there a reason we're subtracting 1 here in the first
place? Could be just me, but may be worth adding a comment here.
Intuitively if we are "narrowing" 16 prios to 8 queues it'd make most
sense to group the adjacent ones -- divide by two.
Please respin with some sort of an explanation..
> queue = channel * AIROHA_NUM_QOS_QUEUES + queue;
>
> return queue < dev->num_tx_queues ? queue : 0;
--
pw-bot: cr
^ permalink raw reply
* Re: [PATCH] net: stmmac: loongson1: Use dev_err_probe()
From: Jacob Keller @ 2026-06-17 22:36 UTC (permalink / raw)
To: Jakub Kicinski
Cc: keguang.zhang, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue, linux-mips,
netdev, linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <20260617150744.05756f0b@kernel.org>
On 6/17/2026 3:07 PM, Jakub Kicinski wrote:
> On Wed, 17 Jun 2026 14:26:25 -0700 Jacob Keller wrote:
>> It does claim that it has benefit since you get the error code emitted
>> symbolically. But we have %pe for that. I wonder if dev_err_probe
>> predates %pe?
>
> I'd argue
>
> No of match data provided: -EINVAL
>
> is more confusing than just:
>
> No of match data provided
>
> the EINVAL is meaningless and hardcoded in this case?
Yea, it is a bit more pointless with a hard-coded error.
^ permalink raw reply
* Re: [PATCH v5 2/8] media: v4l2-fwnode: Add common helper library for 1-to-1 subdev registration
From: Sakari Ailus @ 2026-06-17 22:36 UTC (permalink / raw)
To: Frank.Li
Cc: Mauro Carvalho Chehab, Michael Riesch, Laurent Pinchart, Frank Li,
Martin Kepplinger-Novakovic, Rui Miguel Silva, Purism Kernel Team,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-media, linux-kernel,
imx, devicetree, linux-arm-kernel
In-Reply-To: <20260617-imx8qxp_pcam-v5-2-7fa6c8e7fba7@nxp.com>
Hi Frank,
Thanks for the patch.
On Wed, Jun 17, 2026 at 03:50:12PM -0400, Frank.Li@oss.nxp.com wrote:
> From: Frank Li <Frank.Li@nxp.com>
>
> Many V4L2 subdev drivers implement the same registration and media pad
> setup logic for simple pipelines consisting of a single sink pad and a
> single source pad. As a result, the same boilerplate code is duplicated
> across multiple drivers.
>
> Introduce a common helper library for 1-to-1 subdevs to encapsulate the
> registration, media entity initialization, and cleanup paths. Drivers
> can embed a struct v4l2_subdev_1to1 instance and use the provided helper
> APIs instead of open-coding the setup sequence.
I appreciate your efforts in trying to reduce the amount of code drivers
need simply to get things done but I think there are a few issues with the
approach taken in this patch:
- The new helpers aren't generic enough, but require two pads; one sink,
one source. You could provide special helpers for just this case, but
right now it looks like that if there's something you need that the
helper assumes you don't, you can't use the helper at all. In other
words, more modularity would be nice.
- The new helper should work with the existing types and not add new types
(struct v4l2_subdev_1to1).
- There should be a way to provide default V4L2 fwnode endpoint
configuration as well as to validate the obtained configuration.
I don't have a good proposal to address the above but at least one way I
can think of making error handling easier would be to use devm_() for
teardown in more places we to today. That certainly does have its own
issues though.
--
Kind regards,
Sakari Ailus
^ permalink raw reply
* Re: [PATCH] net: stmmac: loongson1: Use dev_err_probe()
From: Jakub Kicinski @ 2026-06-17 22:07 UTC (permalink / raw)
To: Jacob Keller
Cc: keguang.zhang, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue, linux-mips,
netdev, linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <6b8db599-5bb2-47f9-ab53-a0b5141af2e5@intel.com>
On Wed, 17 Jun 2026 14:26:25 -0700 Jacob Keller wrote:
> It does claim that it has benefit since you get the error code emitted
> symbolically. But we have %pe for that. I wonder if dev_err_probe
> predates %pe?
I'd argue
No of match data provided: -EINVAL
is more confusing than just:
No of match data provided
the EINVAL is meaningless and hardcoded in this case?
^ permalink raw reply
* [PATCH] pinctrl: bcm2835: Don't remove an unregistered GPIO chip
From: Daniel McCarthy @ 2026-06-17 22:04 UTC (permalink / raw)
To: Linus Walleij, Florian Fainelli, Ray Jui, Scott Branden
Cc: linux-gpio, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
Daniel McCarthy
If the devm_pinctrl_register() function fails,
bcm2835_pinctrl_probe() calls gpiochip_remove()
before gpiochip_add_data() has registered the GPIO chip.
This means that upon failure the gpio_chip.gpiodev
is NULL resulting in a null pointer dereference
inside the gpiochip_remove() function.
Remove the unnecessary function call to gpiochip_remove().
No GPIO cleanup is required because the GPIO chip
has not yet been registered. Without this change there
is potential for a kernel panic upon registration failure
Fixes: 266423e60ea1 ("pinctrl: bcm2835: Change init order for gpio hogs")
Signed-off-by: Daniel McCarthy <daniel@dragonzap.com>
---
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index e7b35019a5a7..725e880ae086 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -1350,7 +1350,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
pc->pctl_desc = *pdata->pctl_desc;
pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
if (IS_ERR(pc->pctl_dev)) {
- gpiochip_remove(&pc->gpio_chip);
return PTR_ERR(pc->pctl_dev);
}
--
2.53.0
^ permalink raw reply related
* [PATCH 3/3] dt-bindings: spi: nxp,imx94-xspi: add DMA properties
From: han.xu @ 2026-06-17 21:55 UTC (permalink / raw)
To: Han Xu, Haibo Chen, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam
Cc: linux-spi, imx, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260617215520.3327836-1-han.xu@oss.nxp.com>
From: Han Xu <han.xu@nxp.com>
Add dmas and dma-names to describe TX and RX DMA channels for the i.MX94
XSPI controller.
Signed-off-by: Han Xu <han.xu@nxp.com>
---
.../devicetree/bindings/spi/nxp,imx94-xspi.yaml | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/spi/nxp,imx94-xspi.yaml b/Documentation/devicetree/bindings/spi/nxp,imx94-xspi.yaml
index 16a0598c6d033..ccf841f194c06 100644
--- a/Documentation/devicetree/bindings/spi/nxp,imx94-xspi.yaml
+++ b/Documentation/devicetree/bindings/spi/nxp,imx94-xspi.yaml
@@ -30,6 +30,16 @@ properties:
- const: base
- const: mmap
+ dmas:
+ items:
+ - description: Transmit DMA
+ - description: Receive DMA
+
+ dma-names:
+ items:
+ - const: tx
+ - const: rx
+
interrupts:
items:
- description: interrupt for EENV0
--
2.34.1
^ permalink raw reply related
* [PATCH 1/3] arm64: dts: imx94-xspi: add the DMA channels
From: han.xu @ 2026-06-17 21:55 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
Cc: Han Xu, devicetree, imx, linux-arm-kernel, linux-kernel
From: Han Xu <han.xu@nxp.com>
Add the DMA channels for iMX94 XSPI controller.
Signed-off-by: Han Xu <han.xu@nxp.com>
---
arch/arm64/boot/dts/freescale/imx94.dtsi | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx94.dtsi b/arch/arm64/boot/dts/freescale/imx94.dtsi
index c460ece6070f8..9de1b9754450e 100644
--- a/arch/arm64/boot/dts/freescale/imx94.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx94.dtsi
@@ -820,6 +820,8 @@ xspi1: spi@42b90000 {
#size-cells = <0>;
clocks = <&scmi_clk IMX94_CLK_XSPI1>;
clock-names = "per";
+ dmas = <&edma2 27 0 0>, <&edma2 28 0 FSL_EDMA_RX>;
+ dma-names = "tx", "rx";
status = "disabled";
};
@@ -836,6 +838,8 @@ xspi2: spi@42be0000 {
#size-cells = <0>;
clocks = <&scmi_clk IMX94_CLK_XSPI2>;
clock-names = "per";
+ dmas = <&edma4 42 0 0>, <&edma4 43 0 FSL_EDMA_RX>;
+ dma-names = "tx", "rx";
status = "disabled";
};
};
--
2.34.1
^ permalink raw reply related
* Re: [PATCH RFC v4 01/12] dt-bindings: clk: zte: Add zx297520v3 top clock and reset bindings
From: Conor Dooley @ 2026-06-17 21:41 UTC (permalink / raw)
To: Stefan Dösinger
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, Brian Masney, linux-clk, devicetree,
linux-kernel, linux-arm-kernel
In-Reply-To: <20260617-deed-snap-4649ffae0e27@spud>
[-- Attachment #1: Type: text/plain, Size: 2788 bytes --]
On Wed, Jun 17, 2026 at 10:23:56PM +0100, Conor Dooley wrote:
> On Wed, Jun 17, 2026 at 08:47:53PM +0300, Stefan Dösinger wrote:
> > Am Mittwoch, 17. Juni 2026, 19:08:02 Ostafrikanische Zeit schrieb Conor
> > Dooley:
> > > On Tue, Jun 16, 2026 at 11:26:21PM +0300, Stefan Dösinger wrote:
> >
> > > > +F: Documentation/devicetree/zte,zx297520v3-*
> > >
> > > Sashiko complaint here looks valid.
> >
> > Yes, it is valid.
> >
> > It also brought up another concern in patch 12 that has an impact on this
> > binding:
> >
> > Am Dienstag, 16. Juni 2026, 23:42:19 Ostafrikanische Zeit schrieb sashiko-
> > bot@kernel.org:
> > > issue(s) to consider: - [Low] The `syscon-reboot` node is incorrectly
> > > defined at the root level using the explicitly deprecated `regmap`
> > > property. --
> >
> > And indeed "regmap" is deprecated and I missed it somehow. As far as I
> > understand, to put syscon-reboot as a child of the clock, I need to add the
> > simple-mfd .compatible:
> >
> > Either
> >
> > topclk: clock-controller@13b000 {
> > compatible = "zte,zx297520v3-topclk", "syscon", "simple-mfd";
> > reg = <0x0013b000 0x400>;
> > ...
> > syscon-reboot {
> > compatible = "syscon-reboot";
> > regmap = <&topclk>;
> > offset = <0x0>;
> > mask = <0x1>;
> > };
> > };
> >
> > --- or ---
> >
> > something@13b000 {
> > compatible = "zte,zx297520v3-topcrm", "syscon", "simple-mfd";
> > reg = <0x0013b000 0x400>;
> > ranges;
> >
> > topclk: clock-controller@0 {
> > compatible = "zte,zx297520v3-topclk";
> > ...
> > }
> >
> > syscon-reboot {
> > compatible = "syscon-reboot";
> > offset = <0x0>;
> > mask = <0x1>;
> > };
> > };
> >
> > I see both ways in existing DTS files (e.g. imx6sl.dtsi for the fomer,
> > uniphier-pro4.dtsi for the latter). Is there a preferred way? I have a mild
> > preference for the first, as it would keep all 3 clocks in the same way. If I
> > go for the second, the clock driver would have to query its own node and the
> > parent node for the regmap.
>
> The first one is more natural...
>
> > AFAIU unrelated to syscon-reboot option 2 would give me the opportunity to
> > have separate clock and reset nodes and bindings and skip the aux bus, but
> > this would not be a correct representation of how the hardware works.
>
> ...for this reason!
> Do you actually need an aux bus here though? Since you have to add
> simple-mfd for your the syscon-reboot and simple-mfd is a real bus, can you
> set the reset controller up with an mfd_cell + devm_mfd_add_devices()
> instead?
Although, the /naming/ is more natural in the second case. "topcrm"
sounds like the actual name of this register region. And syscon@ for the
node name.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH] net: stmmac: loongson1: Use dev_err_probe()
From: Jacob Keller @ 2026-06-17 21:26 UTC (permalink / raw)
To: Jakub Kicinski
Cc: keguang.zhang, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue, linux-mips,
netdev, linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <20260617135407.6ff54e27@kernel.org>
On 6/17/2026 1:54 PM, Jakub Kicinski wrote:
> On Tue, 16 Jun 2026 16:42:18 -0700 Jacob Keller wrote:
>> I'd probably also argue this may go against the desired goals of
>> net-next with only wanting such cleanups when in the context of other
>> larger work. Of course that decision ultimately belongs to the maintainers.
>
> Yes, feeding const EINVAL into dev_err_probe() is pretty pointless
> so if this helps it's just by "saving" 2 LoC. I'm not sure it's worth
> it even in context of larger work, let along by itself.
It does claim that it has benefit since you get the error code emitted
symbolically. But we have %pe for that. I wonder if dev_err_probe
predates %pe?
Per commit: 532888a59505 ("driver core: Better advertise dev_err_probe()"):
> Describing the usage of dev_err_probe() as being (only?) "deemed
> acceptable" has a bad connotation. In fact dev_err_probe() fulfills
> three tasks:
>
> - handling of EPROBE_DEFER (even more than degrading to dev_dbg())
> - symbolic output of the error code
> - return err for compact error code paths
This was in 2023.. %pe was introduced in 2019, so I guess %pe is even older.
I personally find dev_err_probe acceptable and might find it nice when
writing new code, but I agree its not really meaningful gain to refactor
existing legacy code.
Anyways, all this to say in too many words: this patch doesn't seem to
have much value for netdev.
Thanks,
Jake
^ permalink raw reply
* Re: [PATCH RFC v4 01/12] dt-bindings: clk: zte: Add zx297520v3 top clock and reset bindings
From: Conor Dooley @ 2026-06-17 21:23 UTC (permalink / raw)
To: Stefan Dösinger
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, Brian Masney, linux-clk, devicetree,
linux-kernel, linux-arm-kernel
In-Reply-To: <-l2OM6P0RNSYRQfOSObOyw@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2420 bytes --]
On Wed, Jun 17, 2026 at 08:47:53PM +0300, Stefan Dösinger wrote:
> Am Mittwoch, 17. Juni 2026, 19:08:02 Ostafrikanische Zeit schrieb Conor
> Dooley:
> > On Tue, Jun 16, 2026 at 11:26:21PM +0300, Stefan Dösinger wrote:
>
> > > +F: Documentation/devicetree/zte,zx297520v3-*
> >
> > Sashiko complaint here looks valid.
>
> Yes, it is valid.
>
> It also brought up another concern in patch 12 that has an impact on this
> binding:
>
> Am Dienstag, 16. Juni 2026, 23:42:19 Ostafrikanische Zeit schrieb sashiko-
> bot@kernel.org:
> > issue(s) to consider: - [Low] The `syscon-reboot` node is incorrectly
> > defined at the root level using the explicitly deprecated `regmap`
> > property. --
>
> And indeed "regmap" is deprecated and I missed it somehow. As far as I
> understand, to put syscon-reboot as a child of the clock, I need to add the
> simple-mfd .compatible:
>
> Either
>
> topclk: clock-controller@13b000 {
> compatible = "zte,zx297520v3-topclk", "syscon", "simple-mfd";
> reg = <0x0013b000 0x400>;
> ...
> syscon-reboot {
> compatible = "syscon-reboot";
> regmap = <&topclk>;
> offset = <0x0>;
> mask = <0x1>;
> };
> };
>
> --- or ---
>
> something@13b000 {
> compatible = "zte,zx297520v3-topcrm", "syscon", "simple-mfd";
> reg = <0x0013b000 0x400>;
> ranges;
>
> topclk: clock-controller@0 {
> compatible = "zte,zx297520v3-topclk";
> ...
> }
>
> syscon-reboot {
> compatible = "syscon-reboot";
> offset = <0x0>;
> mask = <0x1>;
> };
> };
>
> I see both ways in existing DTS files (e.g. imx6sl.dtsi for the fomer,
> uniphier-pro4.dtsi for the latter). Is there a preferred way? I have a mild
> preference for the first, as it would keep all 3 clocks in the same way. If I
> go for the second, the clock driver would have to query its own node and the
> parent node for the regmap.
The first one is more natural...
> AFAIU unrelated to syscon-reboot option 2 would give me the opportunity to
> have separate clock and reset nodes and bindings and skip the aux bus, but
> this would not be a correct representation of how the hardware works.
...for this reason!
Do you actually need an aux bus here though? Since you have to add
simple-mfd for your the syscon-reboot and simple-mfd is a real bus, can you
set the reset controller up with an mfd_cell + devm_mfd_add_devices()
instead?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 2/3] dt-bindings: phy: rockchip-inno-csi-dphy: add rockchip,clk-lane-phase property
From: Conor Dooley @ 2026-06-17 21:17 UTC (permalink / raw)
To: Gerald Loacker
Cc: Vinod Koul, Neil Armstrong, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-phy, linux-arm-kernel,
linux-rockchip, linux-kernel, devicetree
In-Reply-To: <c34d4167-1a33-4e20-820c-735811b6a966@wolfvision.net>
[-- Attachment #1: Type: text/plain, Size: 2405 bytes --]
On Wed, Jun 17, 2026 at 06:20:19PM +0200, Gerald Loacker wrote:
> Hi Conor,
>
> Am 17.06.2026 um 17:51 schrieb Conor Dooley:
> > On Wed, Jun 17, 2026 at 02:23:14PM +0200, Gerald Loacker wrote:
> >> Add support for the optional rockchip,clk-lane-phase device tree property
> >> to allow board-specific tuning of the clock lane sampling phase for
> >> improved signal integrity across supported data rates.
> >>
> >> Signed-off-by: Gerald Loacker <gerald.loacker@wolfvision.net>
> >> ---
> >> Documentation/devicetree/bindings/phy/rockchip-inno-csi-dphy.yaml | 7 +++++++
> >> 1 file changed, 7 insertions(+)
> >>
> >> diff --git a/Documentation/devicetree/bindings/phy/rockchip-inno-csi-dphy.yaml b/Documentation/devicetree/bindings/phy/rockchip-inno-csi-dphy.yaml
> >> index 03950b3cad08c..0d824d1511bc0 100644
> >> --- a/Documentation/devicetree/bindings/phy/rockchip-inno-csi-dphy.yaml
> >> +++ b/Documentation/devicetree/bindings/phy/rockchip-inno-csi-dphy.yaml
> >> @@ -56,6 +56,13 @@ properties:
> >> description:
> >> Some additional phy settings are access through GRF regs.
> >>
> >> + rockchip,clk-lane-phase:
> >> + $ref: /schemas/types.yaml#/definitions/uint32
> >> + minimum: 0
> >> + maximum: 7
> >> + description:
> >> + Clock lane sampling phase in 40 ps steps. The hardware default is 3.
> >
> > Can this instead become rockchip,clk-lane-phase-ps and be listed in the
> > actual unit?
> > With the -ps suffix, you can then drop the $ref.
> > The default should be listed as "default: 3" (or default: 120)
> >
> > pw-bot: changes-requested
> >
>
> Thanks for the suggestion.
>
> The phase setting is a hardware tap index (0–7) selecting a delay line
> position. The datasheet mentions “about 40 ps” per step, but this is not
> a calibrated or guaranteed value and may vary with PVT.
>
> Because of that, I’d prefer to keep the property as an index and
> document the approximate delay in the description:
>
> Clock lane sampling phase selection (hardware tap index 0–7). Each step
> corresponds to an approximately 40 ps delay as described in the hardware
> specification.
>
> This matches the hardware model more closely. Happy to adjust if needed.
>
Sure, I think that's fair.
> >> +
> >> required:
> >> - compatible
> >> - reg
> >>
> >> --
> >> 2.34.1
> >>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 00/19] init: discoverable root partitions, a.k.a. an omittable "root=" cmdline option
From: Vincent Mailhol @ 2026-06-17 20:56 UTC (permalink / raw)
To: Christian Brauner
Cc: Jens Axboe, Davidlohr Bueso, Alexander Viro, Jan Kara,
linux-kernel, linux-block, linux-efi, linux-fsdevel,
Richard Henderson, Matt Turner, Magnus Lindholm, linux-alpha,
Vineet Gupta, linux-snps-arc, Russell King, linux-arm-kernel,
Catalin Marinas, Will Deacon, Huacai Chen, WANG Xuerui, loongarch,
Thomas Bogendoerfer, linux-mips, James E.J. Bottomley,
Helge Deller, linux-parisc, Madhavan Srinivasan, Michael Ellerman,
linuxppc-dev, Paul Walmsley, Palmer Dabbelt, Albert Ou,
linux-riscv, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
linux-s390, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, Jonathan Corbet, Shuah Khan, linux-doc
In-Reply-To: <20260617-irritation-rollen-wirst-7d636cbfec92@brauner>
On 17/06/2026 at 14:41, Christian Brauner wrote:
> On Mon, Jun 15, 2026 at 06:08:56PM +0200, Vincent Mailhol wrote:
>> DPS [1] defines GPT partition type UUIDs for OS partitions and
>> attributes that control whether such partitions should be
>> automatically discovered. The specification states that:
>>
>> The OS can discover and mount the necessary file systems with a
>> non-existent or incomplete /etc/fstab file and without the root=
>> kernel command line option.
>>
>> DPS is already implemented in systemd-gpt-auto-generator [2], which,
>> when embedded in an initrd, indeed allows automatic detection of the
>> root filesystem through its partition type UUID.
>>
>> This series adds this discovery feature directly into the kernel so
>> that people who are not using systemd or not using an initrd can still
>> benefit from it. The implementation follows the same model as
>> systemd-gpt-auto-generator:
>
> I happen to co-maintain the DPS. It is userspace policy and complex
> userspace policy at that and does not belong into the kernel.
>
> This also implements a really tiny portion of the spec. It deals with a
> lot more complex concepts such as automatic partitioning during
> installation, verity, LUKS, containers. This is really not intended for
> the kernel at all. I mean, it's great that this spec is being used but I
> do not want this in the kernel just for the sake of auto-discovery.
The implementation of a tiny portion is voluntary. If I can draw a
parallel, it would be the same as saying that the root= cmdline option
is a tiny portion of what an fstab can do.
Yes it does not manage the LUKS, containers and so on, the same way it
is not possible to directly boot those things directly from the kernel.
So, I don't think this conflicts with the actual userland
implementations, the same way you can add root= to your command line and
still have an initrd next to it.
I did not intend to write this as a replacement but just as a complement
to fill the gap of kernel with no initrd.
> The DPS is completely generic and can be implemented by tooling other
> than systemd (util-linux implements it and so does refind iirc). I think
> not wanting to use or build alternative userspace tooling for this is a
> really weak argument for pushing this into the kernel.
Well, I might explain to you where I come from. Time to time, I mess up
my configuration. When this issue is in a userland config file (e.g. bad
fstab), the recovery is always easy.
But when I mess up the bootloader firmware configuration (e.g. grub,
u-boot, edk2), the fix is always painful. I have to fight with a shell
with which I am not familiar with to figure out what the correct
configuration is.
And an initrd would help but:
- it is still one more file to look for pass as a parameter
- on some machine I do not have one anyway
I think it would have been very neet to have a method to boot a kernel
with zero config (understand here: no cmdline, no initrd) and I find out
that DPS could achieve that if just a tiny part of it were implemented
in the kernel.
For example, in edk2, I would be able to just browse the disk from the
"Boot from file" menu and select a kernel. Currently it panics because
no configuration is attached. With DPS, we could have it boot linux from
that menu. All in a graphical interface, with just up/down arrows and
one enter keypress.
And this is my motivation. This non LUKS root read-only part of the DPS
is the only piece which makes sense for me in the kernel. Not that I
don't *want* to implement it in userland, but just that it doesn't
achieve what would be helpful to me (and I guess others).
I thought I wouldn't be the only one in the world to see value in that
this is why I posted it.
Yours sincerely,
Vincent Mailhol
^ permalink raw reply
* Re: [PATCH v3] dmaengine: sun6i-dma: Fix memory leak in sun6i_dma_terminate_all
From: Frank Li @ 2026-06-17 20:55 UTC (permalink / raw)
To: Hongling Zeng
Cc: vkoul, Frank.Li, wens, jernej.skrabec, samuel, mripard, arnd,
dmaengine, linux-arm-kernel, linux-sunxi, linux-kernel,
zhongling0719
In-Reply-To: <20260617023411.574488-1-zenghongling@kylinos.cn>
On Wed, Jun 17, 2026 at 10:34:11AM +0800, Hongling Zeng wrote:
> When terminating a non-cyclic DMA transfer, the active descriptor
> is not properly reclaimed. The descriptor is removed from the
> desc_issued list in sun6i_dma_start_desc(), but in
> sun6i_dma_terminate_all(), only cyclic transfer descriptors are
> added to the desc_completed list before cleanup.
>
> For non-cyclic transfers, pchan->desc is set to NULL without first
> adding the descriptor back to a list that vchan_get_all_descriptors()
> can collect. This causes the descriptor and its associated LLI chain
> to be permanently leaked.
>
> Fix by ensuring both cyclic and non-cyclic active descriptors are
> added to the desc_completed list before setting pchan->desc to NULL.
Can you update this to match your change.
Frank
>
> Fixes: 555859308723 ("dmaengine: sun6i: Add driver for the Allwinner A31 DMA controller")
> Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
> Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
> Suggested-by: Frank Li <Frank.li@oss.nxp.com>
>
> ---
> Change in v2;
> -Add pchan->desc != pchan->done check to prevent race condition
> where completed descriptors could be double-added to desc_completed
> list, causing list corruption
> ---
> Change in v3:
> -Fix by using vchan_terminate_vdesc() as suggested by Frank Li
> ---
> drivers/dma/sun6i-dma.c | 13 +++++--------
> 1 file changed, 5 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index 7a79f346250a..134ae840f176 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -946,16 +946,13 @@ static int sun6i_dma_terminate_all(struct dma_chan *chan)
>
> spin_lock_irqsave(&vchan->vc.lock, flags);
>
> - if (vchan->cyclic) {
> - vchan->cyclic = false;
> - if (pchan && pchan->desc) {
> - struct virt_dma_desc *vd = &pchan->desc->vd;
> - struct virt_dma_chan *vc = &vchan->vc;
> -
> - list_add_tail(&vd->node, &vc->desc_completed);
> - }
> + if (pchan && pchan->desc && pchan->desc != pchan->done) {
> + struct virt_dma_desc *vd = &pchan->desc->vd;
> +
> + vchan_terminate_vdesc(vd);
> }
>
> + vchan->cyclic = false;
> vchan_get_all_descriptors(&vchan->vc, &head);
>
> if (pchan) {
> --
> 2.25.1
>
^ permalink raw reply
* Re: [PATCH] net: stmmac: loongson1: Use dev_err_probe()
From: Jakub Kicinski @ 2026-06-17 20:54 UTC (permalink / raw)
To: Jacob Keller
Cc: keguang.zhang, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue, linux-mips,
netdev, linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <31630db0-85cb-421b-8ebe-bbae07521533@intel.com>
On Tue, 16 Jun 2026 16:42:18 -0700 Jacob Keller wrote:
> I'd probably also argue this may go against the desired goals of
> net-next with only wanting such cleanups when in the context of other
> larger work. Of course that decision ultimately belongs to the maintainers.
Yes, feeding const EINVAL into dev_err_probe() is pretty pointless
so if this helps it's just by "saving" 2 LoC. I'm not sure it's worth
it even in context of larger work, let along by itself.
--
pw-bot: reject
^ permalink raw reply
* Re: [PATCH] PCI: meson: Fix PERST# timing by asserting reset before LTSSM enable
From: gowtham @ 2026-06-17 20:30 UTC (permalink / raw)
To: neil.armstrong
Cc: Ronald Claveau, robh, bhelgaas, khilman, jbrunet,
martin.blumenstingl, linux-pci, linux-amlogic, linux-arm-kernel,
linux-kernel, yue.wang, lpieralisi, kwilczynski, mani
In-Reply-To: <20260617050627.4d01ed54@slick.ferryfair.com>
[-- Attachment #1: Type: text/plain, Size: 4506 bytes --]
Hi Ronald,
I see you submitted the patch. Last couple of days I've been fixing the
etherenet of my BPiCM4+Waveshare-io-base-b due to which I couldn't test
your patch any sooner. Now I got my ethernet working but now I couldn't
reproduce the issue *without* either of our patches!!!
Anyway it's proper to initialize PCIe with RESET Active but I think
meson_pcie_assert_reset(mp) will give sufficient time to PCIe devices
to complete the reset cycle.
---
drivers/pci/controller/dwc/pci-meson.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/controller/dwc/pci-meson.c
b/drivers/pci/controller/dwc/pci-meson.c index 0694084f612..c28ab40c9ff
100644 --- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -308,8 +308,8 @@ static int meson_pcie_start_link(struct dw_pcie
*pci) {
struct meson_pcie *mp = to_meson_pcie(pci);
- meson_pcie_ltssm_enable(mp);
meson_pcie_assert_reset(mp);
+ meson_pcie_ltssm_enable(mp);
return 0;
}
--
---
drivers/pci/controller/dwc/pci-meson.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/controller/dwc/pci-meson.c
b/drivers/pci/controller/dwc/pci-meson.c index c28ab40c9ff..2ef75157530
100644 --- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -308,7 +308,6 @@ static int meson_pcie_start_link(struct dw_pcie
*pci) {
struct meson_pcie *mp = to_meson_pcie(pci);
- meson_pcie_assert_reset(mp);
meson_pcie_ltssm_enable(mp);
return 0;
@@ -362,6 +361,8 @@ static int meson_pcie_host_init(struct dw_pcie_rp
*pp)
pp->bridge->ops = &meson_pci_ops;
+ meson_pcie_assert_reset(mp);
+
meson_set_max_payload(mp, MAX_PAYLOAD_SIZE);
meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE);
--
...Gowtham
On Wed, 17 Jun 2026 05:06:27 +0530
gowtham <gowtham@ferryfair.com> wrote:
> Hi,
>
> As Neil suggested I moved the PCIe reset to init; I've updated the tag
> at
> https://github.com/GowthamKudupudi/linux/tree/meson-pcie-warm-reset-linux-7.0.y
>
> Ronald, yes, I do think its proper to initialize PCIe with RESET
> Active. Anyway we need the reset *cycle*. Please submit your patch as
> well.
>
> Thank you!
>
> ...Gowtham
>
> On Tue, 16 Jun 2026 08:06:02 +0200
> neil.armstrong@linaro.org wrote:
>
> > On 6/15/26 12:34, Ronald Claveau wrote:
> > > On 6/14/26 3:56 AM, Gowtham Kudupudi wrote:
> > >> On warm reboot, the PCIe controller's LTSSM starts link training
> > >> immediately if PERST# is already deasserted from the previous
> > >> boot. The driver then pulses PERST# for only 500us, which is too
> > >> short to properly reset the endpoint device that has already
> > >> started training.
> > >>
> > >> Fix by moving the PERST# assert/deassert pulse BEFORE enabling
> > >> LTSSM, so the endpoint gets a clean reset cycle before link
> > >> training begins.
> > >>
> > >> This was found on Amlogic G12B (A311D) with NVMe on an M.2 slot.
> > >> Cold boot worked because POR held PERST# low; warm reboot did
> > >> not. The fix was confirmed on a Banana Pi CM4 with Waveshare IO
> > >> base board.
> > >>
> > >> Signed-off-by: Gowtham Kudupudi <gowtham@ferryfair.com>
> > >> ---
> > >> drivers/pci/controller/dwc/pci-meson.c | 2 +-
> > >> 1 file changed, 1 insertion(+), 1 deletion(-)
> > >>
> > >> diff --git a/drivers/pci/controller/dwc/pci-meson.c
> > >> b/drivers/pci/controller/dwc/pci-meson.c index
> > >> 5f8e2f4b3c12..3a7e9f1d5b8c 100644 ---
> > >> a/drivers/pci/controller/dwc/pci-meson.c +++
> > >> b/drivers/pci/controller/dwc/pci-meson.c @@ -310,8 +310,8 @@
> > >> static int meson_pcie_start_link(struct dw_pcie *pci) {
> > >> struct meson_pcie *mp = to_meson_pcie(pci);
> > >>
> > >> + meson_pcie_assert_reset(mp);
> > >> meson_pcie_ltssm_enable(mp);
> > >> - meson_pcie_assert_reset(mp);
> >
> > I think this change is valid, other controllers resets PERST
> > in the host init callback, so either this or move to the
> > init callback.
> >
> > Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
> >
> > >>
> > >> return 0;
> > >> }
> > >
> > > Hi Gowtham,
> > >
> > > I have a patch [1] that I haven't submitted yet.
> > > This might be related to your issue, what do you think ?
> >
> > Ronald, This fix is valid, it's definitely better to probe the
> > driver with PERST asserted, please send it.
> >
> > Neil
> >
> > >
> > > [1]
> > > https://github.com/rclaveau-tech/linux-khadas/commit/bee0a02d9756
> > >
> >
>
[-- Attachment #2: 0001-PCI-meson-Fix-PERST-timing-by-asserting-reset-before.patch --]
[-- Type: text/x-patch, Size: 1488 bytes --]
From 852811b11795ee389ea6a953ed0db69b76722469 Mon Sep 17 00:00:00 2001
From: Gowtham Kudupudi <gowtham@ferryfair.com>
Date: Sun, 14 Jun 2026 09:41:01 +0530
Subject: [PATCH 1/2] PCI: meson: Fix PERST# timing by asserting reset before
LTSSM enable
On warm reboot, the PCIe controller's LTSSM starts link training
immediately if PERST# is already deasserted from the previous boot.
The driver then pulses PERST# for only 500us, which is too short to
properly reset the endpoint device that has already started training.
Fix by moving the PERST# assert/deassert pulse BEFORE enabling LTSSM,
so the endpoint gets a clean reset cycle before link training begins.
This was found on Amlogic G12B (A311D) with NVMe on an M.2 slot.
Cold boot worked because POR held PERST# low; warm reboot did not.
The fix was confirmed on a Banana Pi CM4 with Waveshare IO base board.
Signed-off-by: Gowtham Kudupudi <gowtham@ferryfair.com>
---
drivers/pci/controller/dwc/pci-meson.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 0694084f612..c28ab40c9ff 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -308,8 +308,8 @@ static int meson_pcie_start_link(struct dw_pcie *pci)
{
struct meson_pcie *mp = to_meson_pcie(pci);
- meson_pcie_ltssm_enable(mp);
meson_pcie_assert_reset(mp);
+ meson_pcie_ltssm_enable(mp);
return 0;
}
--
2.54.0
[-- Attachment #3: 0002-PCI-meson-pcie-reset-moved-to-meson_pcie_host_init.patch --]
[-- Type: text/x-patch, Size: 1159 bytes --]
From 1bcf2c787d72b2c25852cc598b1201510b4132b0 Mon Sep 17 00:00:00 2001
From: Gowtham Kudupudi <gowtham@ferryfair.com>
Date: Wed, 17 Jun 2026 04:29:45 +0530
Subject: [PATCH 2/2] PCI: meson: pcie reset moved to meson_pcie_host_init
As per the Neil's suggestion, inititial PCIe reset is moved to init
to make it proper.
Signed-off-by: Gowtham Kudupudi <gowtham@ferryfair.com>
---
drivers/pci/controller/dwc/pci-meson.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index c28ab40c9ff..2ef75157530 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -308,7 +308,6 @@ static int meson_pcie_start_link(struct dw_pcie *pci)
{
struct meson_pcie *mp = to_meson_pcie(pci);
- meson_pcie_assert_reset(mp);
meson_pcie_ltssm_enable(mp);
return 0;
@@ -362,6 +361,8 @@ static int meson_pcie_host_init(struct dw_pcie_rp *pp)
pp->bridge->ops = &meson_pci_ops;
+ meson_pcie_assert_reset(mp);
+
meson_set_max_payload(mp, MAX_PAYLOAD_SIZE);
meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE);
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v4 1/4] firmware: arm_sdei: add sdei_is_present()
From: Doug Anderson @ 2026-06-17 20:02 UTC (permalink / raw)
To: Kiryl Shutsemau
Cc: Catalin Marinas, Will Deacon, James Morse, Mark Rutland,
Marc Zyngier, Petr Mladek, Thomas Gleixner, Andrew Morton,
Baoquan He, Puranjay Mohan, Usama Arif, Breno Leitao,
Julien Thierry, Lecopzer Chen, Sumit Garg, kernel-team, kexec,
linux-arm-kernel, linux-kernel, Kiryl Shutsemau (Meta)
In-Reply-To: <b4fa56527950c27715cb603f8b35dc8652be955a.1781709543.git.kas@kernel.org>
Hi,
On Wed, Jun 17, 2026 at 12:20 PM Kiryl Shutsemau <kirill@shutemov.name> wrote:
>
> From: "Kiryl Shutsemau (Meta)" <kas@kernel.org>
>
> invoke_sdei_fn() returns -EIO when no SDEI conduit was probed, and the
> core warns ("Failed to create event ...") on any registration that hits
> that. An optional consumer that registers an event from an unconditional
> initcall would therefore make every boot on a non-SDEI system emit that
> warning for what is simply absent firmware.
>
> Expose whether SDEI firmware is present so such a consumer can skip
> registration -- and the warning -- when there is nothing to talk to.
>
> Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
> ---
> drivers/firmware/arm_sdei.c | 10 ++++++++++
> include/linux/arm_sdei.h | 3 +++
> 2 files changed, 13 insertions(+)
From a non-expert in SDEI, but FWIW:
Reviewed-by: Douglas Anderson <dianders@chromium.org>
^ permalink raw reply
* Re: [PATCH v4 4/4] arm64: escalate smp_send_stop() to an SDEI NMI as a last resort
From: Doug Anderson @ 2026-06-17 20:02 UTC (permalink / raw)
To: Kiryl Shutsemau
Cc: Catalin Marinas, Will Deacon, James Morse, Mark Rutland,
Marc Zyngier, Petr Mladek, Thomas Gleixner, Andrew Morton,
Baoquan He, Puranjay Mohan, Usama Arif, Breno Leitao,
Julien Thierry, Lecopzer Chen, Sumit Garg, kernel-team, kexec,
linux-arm-kernel, linux-kernel, Kiryl Shutsemau (Meta)
In-Reply-To: <97a870d0670b7e1c2fb9f5142f6e36c594282017.1781709543.git.kas@kernel.org>
Hi,
On Wed, Jun 17, 2026 at 12:20 PM Kiryl Shutsemau <kirill@shutemov.name> wrote:
>
> From: "Kiryl Shutsemau (Meta)" <kas@kernel.org>
>
> A CPU wedged with interrupts masked ignores the stop IPI, and without
> pseudo-NMI there is no NMI IPI to escalate to: a reboot proceeds with
> the CPU still running, and a kdump misses its registers.
>
> Add a third rung to smp_send_stop(): once the IPI (and pseudo-NMI IPI,
> if enabled) rungs have run, signal SDEI event 0 at whatever stayed
> online. Firmware delivers it regardless of the target's DAIF, so it
> reaches a CPU a plain IPI cannot; the target acks by going offline,
> which the caller already polls for.
>
> Fold the stop bookkeeping into one arm64_nmi_cpu_stop(regs,
> die_on_crash), shared by the stop IPI handlers, panic_smp_self_stop()
> and the SDEI handler, replacing the near-duplicate local_cpu_stop() and
> ipi_cpu_crash_stop(). @die_on_crash is the only difference: the IPI
> handlers pass true and PSCI CPU_OFF the CPU on a crash stop so a capture
> kernel can reclaim it; the SDEI handler and self-stop pass false and
> park. The SDEI park is required, not conservative -- its handler runs
> inside an SDEI event that is never completed (completing it resumes the
> wedged context), and a CPU_OFF from that unfinished-event context wedges
> EL3 on some firmware (left as a follow-up). The dump is unaffected; only
> re-onlining the CPU in an SMP capture kernel is lost.
>
> Suggested-by: Douglas Anderson <dianders@chromium.org>
> Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
> ---
> arch/arm64/include/asm/nmi.h | 24 +++++++
> arch/arm64/kernel/smp.c | 113 +++++++++++++++++++++-----------
> drivers/firmware/Kconfig | 2 +
> drivers/firmware/arm_sdei_nmi.c | 86 ++++++++++++++++++++++++
> 4 files changed, 187 insertions(+), 38 deletions(-)
Reviewed-by: Douglas Anderson <dianders@chromium.org>
^ permalink raw reply
* Re: [PATCH 3/9] firmware: imx: ele: Add API functions for OCOTP fuse access
From: Frank Li @ 2026-06-17 19:56 UTC (permalink / raw)
To: Frieder Schrempf
Cc: Pankaj Gupta, Peng Fan (OSS), Frieder Schrempf,
Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, devicetree, imx, linux-arm-kernel,
linux-kernel
In-Reply-To: <9c1d34ec-0b96-471e-8b60-6b4c852878bf@kontron.de>
On Wed, Jun 17, 2026 at 08:54:35AM +0200, Frieder Schrempf wrote:
> On 16.06.26 22:05, Frank Li wrote:
> > On Tue, Jun 16, 2026 at 07:59:54PM +0200, Frieder Schrempf wrote:
> >> On 16.06.26 17:36, Frank Li wrote:
> >>> On Tue, Jun 16, 2026 at 01:52:18PM +0200, Frieder Schrempf wrote:
> >>>> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> >>>>
> >>>> The ELE S400 API provides read and write access to the OCOTP fuse
> >>>> registers. This adds the necessary API functions imx_se_read_fuse()
> >>>> and imx_se_write_fuse() to be used by other drivers such as the
> >>>> OCOTP S400 NVMEM driver.
> >>>>
> >>>> This is ported from the downstream vendor kernel.
> >>>>
> >>>> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> >>>> ---
> >>>> drivers/firmware/imx/ele_base_msg.c | 122 ++++++++++++++++++++++++++++++++++++
> >>>> drivers/firmware/imx/ele_base_msg.h | 6 ++
> >>>> include/linux/firmware/imx/se_api.h | 3 +
> >>>> 3 files changed, 131 insertions(+)
> >>>>
> >>> ...
> >>>> +++ b/include/linux/firmware/imx/se_api.h
> >>>> @@ -11,4 +11,7 @@
> >>>> #define SOC_ID_OF_IMX8ULP 0x084d
> >>>> #define SOC_ID_OF_IMX93 0x9300
> >>>>
> >>>> +int imx_se_read_fuse(void *se_if_data, uint16_t fuse_id, u32 *value);
> >>>> +int imx_se_write_fuse(void *se_if_data, uint16_t fuse_id, u32 value);
> >>>> +
> >>>
> >>> This API should implement in fuse drivers. Other consume should use standard
> >>> fuse API to get value. If put here, it may bypass fuse driver.
> >>
> >> The reason this is here, is the downstream implementation in linux-imx
> >> and the current code organization.
> >
> > Downstream may not good enough, sometime, it is quick solution.
>
> Ok, but the code structure and API design has been upstreamed like this
> and the refactoring could have been done before, if downstream is known
> to not be well organized.
>
> >
> >> I thought there is some good reason
> >> to have shared functions and it looks like Pankaj structured it like
> >> this so all API functions live in ele_base_msg.c and the internal
> >> structs and defines in ele_base_msg.h and se_ctrl.h are not exposed to
> >> other drivers.
> >>
> >> If I would move this into imx-ocotp-ele.c, then I would also need to
> >> change how the code is organized and make the internal se_api functions
> >> exposed to other drivers. I don't know if that is really a good idea.
> >>
> >> I get your point but it looks like this contradicts the intention of
> >> having a clean API in the firmware driver.
> >
> > You can refer imx-ocotp-scu.c, structure should be similar, only difference
> > is that lower transfer APIs.
> Ok, this would mean that I expose the generic SE functions and structs
> required for fuse handling. In practice, I would remove
> imx_se_read_fuse() and imx_se_write_fuse() from se_api.h and instead add
> the following:
>
> struct se_msg_hdr { ... };
> struct se_api_msg { ... };
> struct se_if_priv;
> se_fill_cmd_msg_hdr( ... );
> se_msg_send_rcv( ... );
> se_val_rsp_hdr_n_status( ... );
>
> Then I would export the functions in ele_common.c and put the fuse
> read/write functions in the NVMEM driver.
>
> Is that what you want me to do?
Yes, Idealy, it should be children device under ele, ELE like a bus, which
previous lower level data transfer, ocotp should be base on top then it.
like spi/i2c, which provide low level data transfer.
Frank
>
> Pankaj (and maybe Peng), do you have any comments on this?
>
> Thanks!
^ permalink raw reply
* [PATCH v5 8/8] arm64: dts: imx8qxp-mek: add parallel ov5640 camera support
From: Frank.Li @ 2026-06-17 19:50 UTC (permalink / raw)
To: Sakari Ailus, Mauro Carvalho Chehab, Michael Riesch,
Laurent Pinchart, Frank Li, Martin Kepplinger-Novakovic,
Rui Miguel Silva, Purism Kernel Team, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-media, linux-kernel, imx, devicetree, linux-arm-kernel
In-Reply-To: <20260617-imx8qxp_pcam-v5-0-7fa6c8e7fba7@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Add parallel ov5640 nodes in imx8qxp-mek and create overlay file to enable
it because it can work at two mode: MIPI CSI and parallel mode.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
changes in v4
- add hsync-active = <1>
changes in v3
- replace csi with cpi.
- use imx8qxp-mek-ov5640-cpi.dtso since csi use imx8qxp-mek-ov5640-csi.dtso
change in v2
- move ov5640 part to overlay file
- rename to imx8qxp-mek-ov5640-parallel.dtso
- remove data-lanes
---
arch/arm64/boot/dts/freescale/Makefile | 3 +
.../boot/dts/freescale/imx8qxp-mek-ov5640-cpi.dtso | 83 ++++++++++++++++++++++
2 files changed, 86 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 001ca3a12c0ae..3b9e9844f11ef 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -554,6 +554,9 @@ dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek-pcie-ep.dtb
imx8qxp-mek-ov5640-csi-dtbs := imx8qxp-mek.dtb imx8qxp-mek-ov5640-csi.dtbo
dtb-${CONFIG_ARCH_MXC} += imx8qxp-mek-ov5640-csi.dtb
+imx8qxp-mek-ov5640-cpi-dtbs := imx8qxp-mek.dtb imx8qxp-mek-ov5640-cpi.dtbo
+dtb-${CONFIG_ARCH_MXC} += imx8qxp-mek-ov5640-cpi.dtb
+
dtb-$(CONFIG_ARCH_MXC) += imx8qxp-tqma8xqp-mba8xx.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8qxp-tqma8xqps-mb-smarc-2.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8ulp-9x9-evk.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-mek-ov5640-cpi.dtso b/arch/arm64/boot/dts/freescale/imx8qxp-mek-ov5640-cpi.dtso
new file mode 100644
index 0000000000000..9fbdd798f17d6
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-mek-ov5640-cpi.dtso
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2025 NXP
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/imx8-lpcg.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/media/video-interfaces.h>
+#include <dt-bindings/pinctrl/pads-imx8qxp.h>
+
+&cm40_i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ov5640_pi: camera@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ clocks = <&pi0_misc_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "xclk";
+ assigned-clocks = <&pi0_misc_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <24000000>;
+ AVDD-supply = <®_2v8>;
+ DOVDD-supply = <®_1v8>;
+ DVDD-supply = <®_1v5>;
+ pinctrl-0 = <&pinctrl_parallel_cpi>;
+ pinctrl-names = "default";
+ powerdown-gpios = <&lsio_gpio3 2 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&lsio_gpio3 3 GPIO_ACTIVE_LOW>;
+
+ port {
+ ov5640_pi_ep: endpoint {
+ bus-type = <MEDIA_BUS_TYPE_PARALLEL>;
+ bus-width = <8>;
+ hsync-active = <1>;
+ pclk-sample = <1>;
+ remote-endpoint = <¶llel_cpi_in>;
+ vsync-active = <0>;
+ };
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl_parallel_cpi: parallelcpigrp {
+ fsl,pins = <
+ IMX8QXP_CSI_D00_CI_PI_D02 0xc0000041
+ IMX8QXP_CSI_D01_CI_PI_D03 0xc0000041
+ IMX8QXP_CSI_D02_CI_PI_D04 0xc0000041
+ IMX8QXP_CSI_D03_CI_PI_D05 0xc0000041
+ IMX8QXP_CSI_D04_CI_PI_D06 0xc0000041
+ IMX8QXP_CSI_D05_CI_PI_D07 0xc0000041
+ IMX8QXP_CSI_D06_CI_PI_D08 0xc0000041
+ IMX8QXP_CSI_D07_CI_PI_D09 0xc0000041
+
+ IMX8QXP_CSI_MCLK_CI_PI_MCLK 0xc0000041
+ IMX8QXP_CSI_PCLK_CI_PI_PCLK 0xc0000041
+ IMX8QXP_CSI_HSYNC_CI_PI_HSYNC 0xc0000041
+ IMX8QXP_CSI_VSYNC_CI_PI_VSYNC 0xc0000041
+ IMX8QXP_CSI_EN_LSIO_GPIO3_IO02 0xc0000041
+ IMX8QXP_CSI_RESET_LSIO_GPIO3_IO03 0xc0000041
+ >;
+ };
+};
+
+&isi {
+ status = "okay";
+};
+
+¶llel_cpi {
+ status = "okay";
+
+ ports {
+ port@0 {
+ parallel_cpi_in: endpoint {
+ hsync-active = <1>;
+ remote-endpoint = <&ov5640_pi_ep>;
+ };
+ };
+ };
+};
--
2.43.0
^ permalink raw reply related
* [PATCH v5 7/8] arm64: dts: imx8: add camera parallel interface (CPI) node
From: Frank.Li @ 2026-06-17 19:50 UTC (permalink / raw)
To: Sakari Ailus, Mauro Carvalho Chehab, Michael Riesch,
Laurent Pinchart, Frank Li, Martin Kepplinger-Novakovic,
Rui Miguel Silva, Purism Kernel Team, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-media, linux-kernel, imx, devicetree, linux-arm-kernel
In-Reply-To: <20260617-imx8qxp_pcam-v5-0-7fa6c8e7fba7@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Add camera parallel interface (CPI) node.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
changes in v4
- none
changes in v3
- replace csi with cpi.
changes in v2
- update compatible string to match binding's change
---
arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi | 13 +++++++++++
arch/arm64/boot/dts/freescale/imx8qxp-ss-img.dtsi | 27 +++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi
index a72b2f1c4a1b2..b504f99f6acdb 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi
@@ -222,6 +222,19 @@ irqsteer_parallel: irqsteer@58260000 {
status = "disabled";
};
+ parallel_cpi: cpi@58261000 {
+ compatible = "fsl,imx8qxp-pcif";
+ reg = <0x58261000 0x1000>;
+ clocks = <&pi0_pxl_lpcg IMX_LPCG_CLK_0>,
+ <&pi0_ipg_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "pixel", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_PI_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-parents = <&clk IMX_SC_R_PI_0_PLL IMX_SC_PM_CLK_PLL>;
+ assigned-clock-rates = <160000000>;
+ power-domains = <&pd IMX_SC_R_PI_0>;
+ status = "disabled";
+ };
+
pi0_ipg_lpcg: clock-controller@58263004 {
compatible = "fsl,imx8qxp-lpcg";
reg = <0x58263004 0x4>;
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-ss-img.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-ss-img.dtsi
index 232cf25dadfcd..5aae15540d6cb 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-ss-img.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-ss-img.dtsi
@@ -62,6 +62,14 @@ isi_in_2: endpoint {
remote-endpoint = <&mipi_csi0_out>;
};
};
+
+ port@4 {
+ reg = <4>;
+
+ isi_in_4: endpoint {
+ remote-endpoint = <¶llel_cpi_out>;
+ };
+ };
};
};
@@ -95,3 +103,22 @@ &jpegenc {
&mipi_csi_1 {
status = "disabled";
};
+
+¶llel_cpi {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+
+ port@1 {
+ reg = <1>;
+
+ parallel_cpi_out: endpoint {
+ remote-endpoint = <&isi_in_4>;
+ };
+ };
+ };
+};
--
2.43.0
^ permalink raw reply related
* [PATCH v5 6/8] media: nxp: add V4L2 subdev driver for camera parallel interface (CPI)
From: Frank.Li @ 2026-06-17 19:50 UTC (permalink / raw)
To: Sakari Ailus, Mauro Carvalho Chehab, Michael Riesch,
Laurent Pinchart, Frank Li, Martin Kepplinger-Novakovic,
Rui Miguel Silva, Purism Kernel Team, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-media, linux-kernel, imx, devicetree, linux-arm-kernel,
Alice Yuan, Robert Chiras, Zhipeng Wang
In-Reply-To: <20260617-imx8qxp_pcam-v5-0-7fa6c8e7fba7@nxp.com>
From: Alice Yuan <alice.yuan@nxp.com>
Add a V4L2 sub-device driver for the CPI controller found on i.MX8QXP,
i.MX8QM, and i.MX93 SoCs. This controller supports parallel camera sensors
and enables image data capture through a parallel interface.
Signed-off-by: Alice Yuan <alice.yuan@nxp.com>
Signed-off-by: Robert Chiras <robert.chiras@nxp.com>
Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Change in v5
- Use subdev_1to1 register function
- Use v4l2_subdev_get_frame_desc_passthrough
- Use dwc csi2 similar logic enable/disable stream
- Add route settup at imx_cpi_init_state()
- Remove V2 register layout support, add it later
change in v4
- remove unnecesary header file.
- use devm_bulk_clk_get().
- update kConfig i.MX8/i.MX9
- Remove define IMX_CPI_DEF_PIX_WIDTH ..., which used once only
- drop get_interface_ctrl_reg1_param
- drop uv-swap
- drop imx_cpi_link_setup by use immutable link.
- use enable/disable_stream() replace depericated .s_stream.
- remove dbg print and reg dump functions.
- use goto/.remove() to do manual cleanup.
- remove imx93 support. Add it later.
change in v3
- replace csi with cpi
- use __free(fwnode_handle) to simpilfy code
- remove imx91 driver data, which is the same as imx93
change in v2
- remove MODULE_ALIAS
- use devm_pm_runtime_enable() and cleanup remove function
- change output format to 1x16. controller convert 2x8 to 1x16 format
---
MAINTAINERS | 1 +
drivers/media/platform/nxp/Kconfig | 12 +
drivers/media/platform/nxp/Makefile | 1 +
drivers/media/platform/nxp/imx-parallel-cpi.c | 614 ++++++++++++++++++++++++++
4 files changed, 628 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index deeec900ad071..e28b395734ef5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16263,6 +16263,7 @@ F: Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml
F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
F: Documentation/devicetree/bindings/media/nxp,imx8mq-mipi-csi2.yaml
F: drivers/media/platform/nxp/imx-mipi-csis.c
+F: drivers/media/platform/nxp/imx-parallel-cpi.c
F: drivers/media/platform/nxp/imx7-media-csi.c
F: drivers/media/platform/nxp/imx8mq-mipi-csi2.c
diff --git a/drivers/media/platform/nxp/Kconfig b/drivers/media/platform/nxp/Kconfig
index 40e3436669e21..90f7c792003f2 100644
--- a/drivers/media/platform/nxp/Kconfig
+++ b/drivers/media/platform/nxp/Kconfig
@@ -39,6 +39,18 @@ config VIDEO_IMX_MIPI_CSIS
Video4Linux2 sub-device driver for the MIPI CSI-2 CSIS receiver
v3.3/v3.6.3 found on some i.MX7 and i.MX8 SoCs.
+config VIDEO_IMX_PARALLEL_CPI
+ tristate "NXP i.MX8/i.MX9 Parallel CPI Driver"
+ depends on ARCH_MXC || COMPILE_TEST
+ depends on VIDEO_DEV
+ select MEDIA_CONTROLLER
+ select V4L2_1TO1
+ select V4L2_FWNODE
+ select VIDEO_V4L2_SUBDEV_API
+ help
+ Video4Linux2 sub-device driver for PARALLEL CPI receiver found
+ on some iMX8 and iMX9 SoCs.
+
source "drivers/media/platform/nxp/imx8-isi/Kconfig"
# mem2mem drivers
diff --git a/drivers/media/platform/nxp/Makefile b/drivers/media/platform/nxp/Makefile
index 4d90eb7136525..5346919d2f108 100644
--- a/drivers/media/platform/nxp/Makefile
+++ b/drivers/media/platform/nxp/Makefile
@@ -7,5 +7,6 @@ obj-y += imx8-isi/
obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
obj-$(CONFIG_VIDEO_IMX8MQ_MIPI_CSI2) += imx8mq-mipi-csi2.o
obj-$(CONFIG_VIDEO_IMX_MIPI_CSIS) += imx-mipi-csis.o
+obj-$(CONFIG_VIDEO_IMX_PARALLEL_CPI) += imx-parallel-cpi.o
obj-$(CONFIG_VIDEO_IMX_PXP) += imx-pxp.o
obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o
diff --git a/drivers/media/platform/nxp/imx-parallel-cpi.c b/drivers/media/platform/nxp/imx-parallel-cpi.c
new file mode 100644
index 0000000000000..00f5d5f47644b
--- /dev/null
+++ b/drivers/media/platform/nxp/imx-parallel-cpi.c
@@ -0,0 +1,614 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * i.MX Parallel CPI receiver driver.
+ *
+ * Copyright 2019-2025 NXP
+ *
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-device-1to1.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+
+/* CI_PI INTERFACE CONTROL */
+#define IF_CTRL_REG_PL_ENABLE BIT(0)
+#define IF_CTRL_REG_PL_VALID BIT(1)
+#define IF_CTRL_REG_DATA_TYPE_SEL BIT(8)
+#define IF_CTRL_REG_DATA_TYPE(x) FIELD_PREP(GENMASK(13, 9), (x))
+
+#define DATA_TYPE_OUT_NULL 0x00
+#define DATA_TYPE_OUT_RGB 0x04
+#define DATA_TYPE_OUT_YUV444 0x08
+#define DATA_TYPE_OUT_YYU420_ODD 0x10
+#define DATA_TYPE_OUT_YYU420_EVEN 0x12
+#define DATA_TYPE_OUT_YYY_ODD 0x18
+#define DATA_TYPE_OUT_UYVY_EVEN 0x1a
+#define DATA_TYPE_OUT_RAW 0x1c
+
+#define IF_CTRL_REG_IF_FORCE_HSYNV_OVERRIDE 0x4
+#define IF_CTRL_REG_IF_FORCE_VSYNV_OVERRIDE 0x2
+#define IF_CTRL_REG_IF_FORCE_DATA_ENABLE_OVERRIDE 0x1
+
+/* CPI INTERFACE CONTROL REG */
+#define CPI_CTRL_REG_CPI_EN BIT(0)
+#define CPI_CTRL_REG_PIXEL_CLK_POL BIT(1)
+#define CPI_CTRL_REG_HSYNC_POL BIT(2)
+#define CPI_CTRL_REG_VSYNC_POL BIT(3)
+#define CPI_CTRL_REG_DE_POL BIT(4)
+#define CPI_CTRL_REG_PIXEL_DATA_POL BIT(5)
+#define CPI_CTRL_REG_CCIR_EXT_VSYNC_EN BIT(6)
+#define CPI_CTRL_REG_CCIR_EN BIT(7)
+#define CPI_CTRL_REG_CCIR_VIDEO_MODE BIT(8)
+#define CPI_CTRL_REG_CCIR_NTSC_EN BIT(9)
+#define CPI_CTRL_REG_CCIR_VSYNC_RESET_EN BIT(10)
+#define CPI_CTRL_REG_CCIR_ECC_ERR_CORRECT_EN BIT(11)
+#define CPI_CTRL_REG_HSYNC_FORCE_EN BIT(12)
+#define CPI_CTRL_REG_VSYNC_FORCE_EN BIT(13)
+#define CPI_CTRL_REG_GCLK_MODE_EN BIT(14)
+#define CPI_CTRL_REG_VALID_SEL BIT(15)
+#define CPI_CTRL_REG_RAW_OUT_SEL BIT(16)
+#define CPI_CTRL_REG_HSYNC_OUT_SEL BIT(17)
+#define CPI_CTRL_REG_HSYNC_PULSE(x) FIELD_PREP(GENMASK(21, 19), (x))
+#define CPI_CTRL_REG_UV_SWAP_EN BIT(22)
+#define CPI_CTRL_REG_DATA_TYPE_IN(x) FIELD_PREP(GENMASK(26, 23), (x))
+#define CPI_CTRL_REG_MASK_VSYNC_COUNTER(x) FIELD_PREP(GENMASK(28, 27), (x))
+#define CPI_CTRL_REG_SOFTRST BIT(31)
+
+/* CPI INTERFACE STATUS */
+#define CPI_STATUS_FIELD_TOGGLE BIT(0)
+#define CPI_STATUS_ECC_ERROR BIT(1)
+
+/* CPI INTERFACE CONTROL REG1 */
+#define CPI_CTRL_REG1_PIXEL_WIDTH(v) FIELD_PREP(GENMASK(15, 0), (v))
+#define CPI_CTRL_REG1_VSYNC_PULSE(v) FIELD_PREP(GENMASK(31, 16), (v))
+
+#define CPI_CTRL_V2_REG1_PIXEL_WIDTH(v) FIELD_PREP(GENMASK(16, 0), (v))
+#define CPI_CTRL_V2_REG1_VSYNC_PULSE(v) FIELD_PREP(GENMASK(31, 16), (v))
+
+/* Need match field DATA_TYPE_IN definition at CPI CTRL register */
+enum cpi_in_data_type {
+ CPI_IN_DT_UYVY_BT656_8 = 0x0,
+ CPI_IN_DT_UYVY_BT656_10,
+ CPI_IN_DT_RGB_8,
+ CPI_IN_DT_BGR_8,
+ CPI_IN_DT_YVYU_8 = 0x5,
+ CPI_IN_DT_YUV_8,
+ CPI_IN_DT_RAW_8 = 0x9,
+ CPI_IN_DT_RAW_10,
+};
+
+enum {
+ PI_GATE_CLOCK_MODE,
+ PI_CCIR_MODE,
+};
+
+enum {
+ PI_V1,
+};
+
+struct imx_cpi_plat_data {
+ u32 version;
+ u32 if_ctrl_reg;
+ u32 interface_status;
+ u32 interface_ctrl_reg;
+ u32 interface_ctrl_reg1;
+};
+
+struct imx_cpi_device {
+ struct device *dev;
+ void __iomem *regs;
+ struct clk_bulk_data *clks;
+ int num_clks;
+
+ struct v4l2_subdev_1to1 sd_1to1;
+
+ const struct imx_cpi_plat_data *pdata;
+
+ u32 enabled_streams;
+ u8 mode;
+};
+
+struct imx_cpi_pix_format {
+ u32 code;
+ u32 output;
+ u32 data_type;
+ u8 width;
+};
+
+static const struct imx_cpi_pix_format imx_cpi_formats[] = {
+ /* YUV formats. */
+ {
+ .code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .output = MEDIA_BUS_FMT_UYVY8_1X16,
+ .data_type = CPI_IN_DT_UYVY_BT656_8,
+ .width = 16,
+ }, {
+ .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .output = MEDIA_BUS_FMT_YUYV8_1X16,
+ .data_type = CPI_IN_DT_YVYU_8,
+ .width = 16,
+ },
+};
+
+static const struct imx_cpi_plat_data imx8qxp_pdata = {
+ .version = PI_V1,
+ .if_ctrl_reg = 0x0,
+ .interface_status = 0x20,
+ .interface_ctrl_reg = 0x10,
+ .interface_ctrl_reg1 = 0x30,
+};
+
+static const struct imx_cpi_pix_format *find_imx_cpi_format(u32 code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(imx_cpi_formats); i++)
+ if (code == imx_cpi_formats[i].code)
+ return &imx_cpi_formats[i];
+
+ return NULL;
+}
+
+static void imx_cpi_sw_reset(struct imx_cpi_device *pcpidev)
+{
+ const struct imx_cpi_plat_data *pdata = pcpidev->pdata;
+ u32 val;
+
+ /* Softwaret Reset */
+ val = readl(pcpidev->regs + pdata->interface_ctrl_reg);
+ val |= CPI_CTRL_REG_SOFTRST;
+ writel(val, pcpidev->regs + pdata->interface_ctrl_reg);
+
+ fsleep(500);
+ val = readl(pcpidev->regs + pdata->interface_ctrl_reg);
+ val &= ~CPI_CTRL_REG_SOFTRST;
+ writel(val, pcpidev->regs + pdata->interface_ctrl_reg);
+}
+
+static void imx_cpi_hw_config(struct imx_cpi_device *pcpidev,
+ const struct imx_cpi_pix_format *pcpidev_fmt)
+{
+ const struct imx_cpi_plat_data *pdata = pcpidev->pdata;
+ u32 flags = pcpidev->sd_1to1.vep.bus.parallel.flags;
+ bool hsync_pol = flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH;
+ bool vsync_pol = flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH;
+ u32 val;
+
+ /* Software Reset */
+ imx_cpi_sw_reset(pcpidev);
+
+ /* Config PL Data Type */
+ val = IF_CTRL_REG_DATA_TYPE(DATA_TYPE_OUT_YUV444);
+ val |= IF_CTRL_REG_PL_ENABLE | IF_CTRL_REG_PL_VALID;
+ writel(val, pcpidev->regs + pdata->if_ctrl_reg);
+
+ /* Config CTRL REG */
+ val = CPI_CTRL_REG_HSYNC_FORCE_EN | CPI_CTRL_REG_VSYNC_FORCE_EN;
+
+ val |= CPI_CTRL_REG_DATA_TYPE_IN(pcpidev_fmt->data_type) |
+ FIELD_PREP(CPI_CTRL_REG_HSYNC_POL, hsync_pol) |
+ FIELD_PREP(CPI_CTRL_REG_VSYNC_POL, vsync_pol) |
+ FIELD_PREP(CPI_CTRL_REG_PIXEL_CLK_POL, 0) |
+ CPI_CTRL_REG_MASK_VSYNC_COUNTER(3) |
+ CPI_CTRL_REG_HSYNC_PULSE(2);
+
+ if (pcpidev_fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
+ pcpidev_fmt->code == MEDIA_BUS_FMT_UYVY8_2X8)
+ val |= CPI_CTRL_REG_UV_SWAP_EN;
+
+ if (pcpidev->mode == PI_GATE_CLOCK_MODE) {
+ val |= CPI_CTRL_REG_GCLK_MODE_EN;
+ } else if (pcpidev->mode == PI_CCIR_MODE) {
+ val |= (CPI_CTRL_REG_CCIR_EN |
+ CPI_CTRL_REG_CCIR_VSYNC_RESET_EN |
+ CPI_CTRL_REG_CCIR_EXT_VSYNC_EN |
+ CPI_CTRL_REG_CCIR_ECC_ERR_CORRECT_EN);
+ }
+
+ writel(val, pcpidev->regs + pdata->interface_ctrl_reg);
+}
+
+static void imx_cpi_config_ctrl_reg1(struct imx_cpi_device *pcpidev,
+ const struct v4l2_mbus_framefmt *format)
+{
+ const struct imx_cpi_plat_data *pdata = pcpidev->pdata;
+ u32 pixel_width;
+ u32 vsync_pulse;
+ u32 val;
+
+ pixel_width = format->width - 1;
+ vsync_pulse = format->width << 1;
+
+ switch (pcpidev->pdata->version) {
+ case PI_V1:
+ val = CPI_CTRL_REG1_PIXEL_WIDTH(pixel_width) |
+ CPI_CTRL_REG1_VSYNC_PULSE(vsync_pulse);
+ break;
+ default:
+ val = 0; /* Never happen */
+ }
+
+ val = CPI_CTRL_REG1_PIXEL_WIDTH(pixel_width) |
+ CPI_CTRL_REG1_VSYNC_PULSE(vsync_pulse);
+ writel(val, pcpidev->regs + pdata->interface_ctrl_reg1);
+}
+
+static void imx_cpi_enable(struct imx_cpi_device *pcpidev)
+{
+ const struct imx_cpi_plat_data *pdata = pcpidev->pdata;
+ u32 val;
+
+ /* Enable CPI */
+ val = readl(pcpidev->regs + pdata->interface_ctrl_reg);
+ val |= CPI_CTRL_REG_CPI_EN;
+ writel(val, pcpidev->regs + pdata->interface_ctrl_reg);
+
+ /* Disable SYNC Force */
+ val = readl(pcpidev->regs + pdata->interface_ctrl_reg);
+ val &= ~(CPI_CTRL_REG_HSYNC_FORCE_EN | CPI_CTRL_REG_VSYNC_FORCE_EN);
+ writel(val, pcpidev->regs + pdata->interface_ctrl_reg);
+}
+
+static void imx_cpi_disable(struct imx_cpi_device *pcpidev)
+{
+ const struct imx_cpi_plat_data *pdata = pcpidev->pdata;
+ u32 val;
+
+ /* Enable Sync Force */
+ val = readl(pcpidev->regs + pdata->interface_ctrl_reg);
+ val |= CPI_CTRL_REG_HSYNC_FORCE_EN | CPI_CTRL_REG_VSYNC_FORCE_EN;
+ writel(val, pcpidev->regs + pdata->interface_ctrl_reg);
+
+ /* Disable CPI */
+ val = readl(pcpidev->regs + pdata->interface_ctrl_reg);
+ val &= ~CPI_CTRL_REG_CPI_EN;
+ writel(val, pcpidev->regs + pdata->interface_ctrl_reg);
+
+ /* Disable Pixel Link */
+ val = readl(pcpidev->regs + pdata->if_ctrl_reg);
+ val &= ~(IF_CTRL_REG_PL_VALID | IF_CTRL_REG_PL_ENABLE);
+ writel(val, pcpidev->regs + pdata->if_ctrl_reg);
+}
+
+static struct imx_cpi_device *sd_to_imx_cpi_device(struct v4l2_subdev *sdev)
+{
+ return container_of(sdev, struct imx_cpi_device, sd_1to1.sd);
+}
+
+static const struct media_entity_operations imx_cpi_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+ .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
+};
+
+static int imx_cpi_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *sdformat)
+{
+ struct imx_cpi_pix_format const *pcpidev_fmt;
+ struct v4l2_mbus_framefmt *fmt;
+
+ /*
+ * The Parallel cpi can't transcode in any way, the source format
+ * can't be modified.
+ */
+ if (sdformat->pad == V4L2_SUBDEV_1TO1_PADS_SOURCE)
+ return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
+
+ pcpidev_fmt = find_imx_cpi_format(sdformat->format.code);
+ if (!pcpidev_fmt)
+ pcpidev_fmt = &imx_cpi_formats[0];
+
+ fmt = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
+
+ fmt->code = pcpidev_fmt->code;
+ fmt->width = sdformat->format.width;
+ fmt->height = sdformat->format.height;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = sdformat->format.colorspace;
+ fmt->quantization = sdformat->format.quantization;
+ fmt->xfer_func = sdformat->format.xfer_func;
+ fmt->ycbcr_enc = sdformat->format.ycbcr_enc;
+
+ sdformat->format = *fmt;
+
+ /* Propagate the format from sink to source. */
+ fmt = v4l2_subdev_state_get_format(sd_state, V4L2_SUBDEV_1TO1_PADS_SOURCE);
+ *fmt = sdformat->format;
+
+ /* The format on the source pad might change due to unpacking. */
+ fmt->code = pcpidev_fmt->output;
+
+ return 0;
+}
+
+static int imx_cpi_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ struct v4l2_subdev_route routes[] = {
+ {
+ .sink_pad = V4L2_SUBDEV_1TO1_PADS_SINK,
+ .sink_stream = 0,
+ .source_pad = V4L2_SUBDEV_1TO1_PADS_SOURCE,
+ .source_stream = 0,
+ .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+ },
+ };
+ struct v4l2_subdev_krouting routing = {
+ .len_routes = ARRAY_SIZE(routes),
+ .num_routes = ARRAY_SIZE(routes),
+ .routes = routes,
+ };
+ struct v4l2_mbus_framefmt *fmt;
+
+ fmt = v4l2_subdev_state_get_format(state, 0);
+
+ fmt->code = imx_cpi_formats[0].code;
+ fmt->width = 1920;
+ fmt->height = 1080;
+
+ fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
+ fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
+ fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(false,
+ fmt->colorspace,
+ fmt->ycbcr_enc);
+
+ return v4l2_subdev_set_routing_with_fmt(sd, state, &routing, fmt);
+}
+
+static int imx_cpi_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
+{
+ struct imx_cpi_device *pcpidev = sd_to_imx_cpi_device(sd);
+ struct media_pad *sink_pad, *remote_pad;
+ struct device *dev = pcpidev->dev;
+ struct v4l2_subdev *remote_sd;
+ u64 mask;
+ int ret;
+
+ sink_pad = &sd->entity.pads[V4L2_SUBDEV_1TO1_PADS_SINK];
+ remote_pad = media_pad_remote_pad_first(sink_pad);
+ remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+ mask = v4l2_subdev_state_xlate_streams(state, V4L2_SUBDEV_1TO1_PADS_SINK,
+ V4L2_SUBDEV_1TO1_PADS_SOURCE,
+ &streams_mask);
+
+ ret = v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask);
+ if (ret)
+ dev_err(dev, "failed to disable streams on remote subdev: %d\n", ret);
+
+ pcpidev->enabled_streams &= ~streams_mask;
+
+ if (!pcpidev->enabled_streams) {
+ imx_cpi_disable(pcpidev);
+ pm_runtime_put_autosuspend(dev);
+ }
+
+ return 0;
+}
+
+static int imx_cpi_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
+{
+ struct imx_cpi_device *pcpidev = sd_to_imx_cpi_device(sd);
+ const struct imx_cpi_pix_format *pcpidev_fmt;
+ const struct v4l2_mbus_framefmt *format;
+ struct media_pad *sink_pad, *remote_pad;
+ struct device *dev = pcpidev->dev;
+ struct v4l2_subdev *remote_sd;
+ u64 mask;
+ int ret;
+
+ sink_pad = &sd->entity.pads[V4L2_SUBDEV_1TO1_PADS_SINK];
+ remote_pad = media_pad_remote_pad_first(sink_pad);
+ remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+ mask = v4l2_subdev_state_xlate_streams(state, V4L2_SUBDEV_1TO1_PADS_SINK,
+ V4L2_SUBDEV_1TO1_PADS_SOURCE,
+ &streams_mask);
+
+ format = v4l2_subdev_state_get_format(state, V4L2_SUBDEV_1TO1_PADS_SINK);
+ pcpidev_fmt = find_imx_cpi_format(format->code);
+
+ if (!pcpidev->enabled_streams) {
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ imx_cpi_hw_config(pcpidev, pcpidev_fmt);
+ imx_cpi_config_ctrl_reg1(pcpidev, format);
+ imx_cpi_enable(pcpidev);
+ }
+
+ ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index, mask);
+ if (ret)
+ goto err_cpi_stop;
+
+ pcpidev->enabled_streams |= streams_mask;
+
+ return 0;
+
+err_cpi_stop:
+ /* Stop CSI hardware if no streams are enabled */
+ if (!pcpidev->enabled_streams)
+ imx_cpi_disable(pcpidev);
+
+ pm_runtime_put_autosuspend(dev);
+
+ return ret;
+}
+
+static int imx_cpi_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ /*
+ * The PARALLEL CPI can't transcode in any way, the source format
+ * is identical to the sink format.
+ */
+ if (code->pad == V4L2_SUBDEV_1TO1_PADS_SOURCE) {
+ struct v4l2_mbus_framefmt *fmt;
+
+ if (code->index > 0)
+ return -EINVAL;
+
+ fmt = v4l2_subdev_state_get_format(sd_state, code->pad);
+ code->code = fmt->code;
+ return 0;
+ }
+
+ if (code->pad != V4L2_SUBDEV_1TO1_PADS_SINK)
+ return -EINVAL;
+
+ if (code->index >= ARRAY_SIZE(imx_cpi_formats))
+ return -EINVAL;
+
+ code->code = imx_cpi_formats[code->index].code;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_video_ops imx_cpi_video_ops = {
+ .s_stream = v4l2_subdev_s_stream_helper,
+};
+
+static const struct v4l2_subdev_pad_ops imx_cpi_pad_ops = {
+ .enum_mbus_code = imx_cpi_enum_mbus_code,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = imx_cpi_set_fmt,
+ .get_frame_desc = v4l2_subdev_get_frame_desc_passthrough,
+ .enable_streams = imx_cpi_enable_streams,
+ .disable_streams = imx_cpi_disable_streams,
+};
+
+static const struct v4l2_subdev_ops imx_cpi_subdev_ops = {
+ .pad = &imx_cpi_pad_ops,
+ .video = &imx_cpi_video_ops,
+};
+
+static const struct v4l2_subdev_internal_ops imx_cpi_internal_ops = {
+ .init_state = imx_cpi_init_state,
+};
+
+/* ----------------------------------------------------------------------
+ * Suspend/resume
+ */
+
+static int imx_cpi_runtime_suspend(struct device *dev)
+{
+ struct imx_cpi_device *pcpidev = dev_get_drvdata(dev);
+
+ clk_bulk_disable_unprepare(pcpidev->num_clks, pcpidev->clks);
+
+ return 0;
+}
+
+static int imx_cpi_runtime_resume(struct device *dev)
+{
+ struct imx_cpi_device *pcpidev = dev_get_drvdata(dev);
+
+ return clk_bulk_prepare_enable(pcpidev->num_clks, pcpidev->clks);
+}
+
+static const struct dev_pm_ops imx_cpi_pm_ops = {
+ RUNTIME_PM_OPS(imx_cpi_runtime_suspend, imx_cpi_runtime_resume, NULL)
+};
+
+static void imx_cpi_remove(struct platform_device *pdev)
+{
+ struct imx_cpi_device *pcpidev = platform_get_drvdata(pdev);
+
+ media_async_subdev_1to1_cleanup(&pcpidev->sd_1to1);
+}
+
+static int imx_cpi_probe(struct platform_device *pdev)
+{
+ struct imx_cpi_device *pcpidev;
+ struct device *dev = &pdev->dev;
+ struct v4l2_subdev *sd;
+ int ret;
+
+ pcpidev = devm_kzalloc(dev, sizeof(*pcpidev), GFP_KERNEL);
+ if (!pcpidev)
+ return -ENOMEM;
+
+ pcpidev->dev = dev;
+ platform_set_drvdata(pdev, pcpidev);
+
+ pcpidev->pdata = of_device_get_match_data(dev);
+ pcpidev->mode = PI_GATE_CLOCK_MODE;
+
+ pcpidev->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pcpidev->regs))
+ return dev_err_probe(dev, PTR_ERR(pcpidev->regs),
+ "Failed to get regs\n");
+
+ pcpidev->num_clks = devm_clk_bulk_get_all(dev, &pcpidev->clks);
+ if (pcpidev->num_clks < 0)
+ return pcpidev->num_clks;
+
+ sd = &pcpidev->sd_1to1.sd;
+
+ v4l2_subdev_init(sd, &imx_cpi_subdev_ops);
+
+ sd->internal_ops = &imx_cpi_internal_ops;
+ snprintf(sd->name, sizeof(sd->name), "parallel-%s",
+ dev_name(pcpidev->dev));
+
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+ sd->entity.ops = &imx_cpi_entity_ops;
+
+ sd->dev = pcpidev->dev;
+ pcpidev->sd_1to1.remote_bustype_cap_mask = BIT(V4L2_MBUS_PARALLEL);
+
+ pm_runtime_use_autosuspend(dev);
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ return media_async_register_subdev_1to1(&pcpidev->sd_1to1);
+}
+
+static const struct of_device_id imx_cpi_of_match[] = {
+ { .compatible = "fsl,imx8qxp-pcif", .data = &imx8qxp_pdata },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, imx_cpi_of_match);
+
+static struct platform_driver imx_cpi_driver = {
+ .probe = imx_cpi_probe,
+ .remove = imx_cpi_remove,
+ .driver = {
+ .of_match_table = imx_cpi_of_match,
+ .name = "imx-parallel-cpi",
+ .pm = pm_ptr(&imx_cpi_pm_ops),
+ },
+};
+
+module_platform_driver(imx_cpi_driver);
+
+MODULE_DESCRIPTION("i.MX9 Parallel CPI receiver driver");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply related
* [PATCH v5 5/8] dt-bindings: media: add i.MX parallel CPI support
From: Frank.Li @ 2026-06-17 19:50 UTC (permalink / raw)
To: Sakari Ailus, Mauro Carvalho Chehab, Michael Riesch,
Laurent Pinchart, Frank Li, Martin Kepplinger-Novakovic,
Rui Miguel Silva, Purism Kernel Team, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-media, linux-kernel, imx, devicetree, linux-arm-kernel,
Alice Yuan, Krzysztof Kozlowski
In-Reply-To: <20260617-imx8qxp_pcam-v5-0-7fa6c8e7fba7@nxp.com>
From: Alice Yuan <alice.yuan@nxp.com>
Document the binding for parallel CPI controller found in i.MX8QXP, i.MX93
and i.MX91 SoCs.
Signed-off-by: Alice Yuan <alice.yuan@nxp.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Chagnes in v4
- add Laurent Pinchart's review by tag
- fix $ref: /schemas/graph.yaml#/$defs/port-base, original is
$ref: /schemas/graph.yaml#/properties/port-base
Change in v3:
- use enum at compatible string
- add ref to video-interfaces.yaml#
- use cpi as node name in examples.
- replace csi (Camera Serial Interface) with CPI (Camera Parallel Interface)
in commit message.
Change in v2:
- use pcif surfix as Laurent Pinchart's suggest.
- put power-domains into required list
---
.../devicetree/bindings/media/fsl,imx93-pcif.yaml | 126 +++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 127 insertions(+)
diff --git a/Documentation/devicetree/bindings/media/fsl,imx93-pcif.yaml b/Documentation/devicetree/bindings/media/fsl,imx93-pcif.yaml
new file mode 100644
index 0000000000000..9dd0331f6ef75
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/fsl,imx93-pcif.yaml
@@ -0,0 +1,126 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/fsl,imx93-pcif.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: i.MX8/9 Parallel Camera Interface
+
+maintainers:
+ - Frank Li <Frank.Li@nxp.com>
+
+description: |
+ This is device node for the Parallel Camera Interface which enables the
+ chip to connect directly to external Parallel CMOS image sensors.
+ Supports up to 80MHz input clock from sensor.
+ Supports the following input data formats
+ - 8-bit/10-bit Camera Sensor Interface (CSI)
+ - 8-bit data port for RGB, YCbCr, and YUV data input
+ - 8-bit/10-bit data ports for Bayer data input
+ Parallel Camera Interface is hooked to the Imaging subsystem via the
+ Pixel Link.
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - fsl,imx8qxp-pcif
+ - fsl,imx93-pcif
+ - items:
+ - enum:
+ - fsl,imx91-pcif
+ - const: fsl,imx93-pcif
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: pixel
+ - const: ipg
+
+ power-domains:
+ maxItems: 1
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: Input port node.
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ bus-type:
+ const: 5
+
+ port@1:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: Output port node.
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ bus-type:
+ const: 5
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - power-domains
+ - ports
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx93-clock.h>
+ #include <dt-bindings/power/fsl,imx93-power.h>
+
+ cpi@4ac10070 {
+ compatible = "fsl,imx93-pcif";
+ reg = <0x4ac10070 0x10>;
+ clocks = <&clk IMX93_CLK_MIPI_CSI_GATE>,
+ <&clk IMX93_CLK_MEDIA_APB>;
+ clock-names = "pixel", "ipg";
+ assigned-clocks = <&clk IMX93_CLK_CAM_PIX>;
+ assigned-clock-parents = <&clk IMX93_CLK_VIDEO_PLL>;
+ assigned-clock-rates = <140000000>;
+ power-domains = <&media_blk_ctrl IMX93_MEDIABLK_PD_MIPI_CSI>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&mt9m114_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ endpoint {
+ remote-endpoint = <&isi_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 825e7cd2d6739..deeec900ad071 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16258,6 +16258,7 @@ L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media.git
F: Documentation/admin-guide/media/imx7.rst
+F: Documentation/devicetree/bindings/media/fsl,imx93-pcif.yaml
F: Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml
F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
F: Documentation/devicetree/bindings/media/nxp,imx8mq-mipi-csi2.yaml
--
2.43.0
^ permalink raw reply related
* [PATCH v5 4/8] media: synopsys: Use V4L2 1-to-1 subdev helpers
From: Frank.Li @ 2026-06-17 19:50 UTC (permalink / raw)
To: Sakari Ailus, Mauro Carvalho Chehab, Michael Riesch,
Laurent Pinchart, Frank Li, Martin Kepplinger-Novakovic,
Rui Miguel Silva, Purism Kernel Team, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-media, linux-kernel, imx, devicetree, linux-arm-kernel
In-Reply-To: <20260617-imx8qxp_pcam-v5-0-7fa6c8e7fba7@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Use the V4L2 1-to-1 subdev infrastructure to simplify the driver.
Replace the local subdev registration and media pad setup code with
media_async_register_subdev_1to1() and struct v4l2_subdev_1to1. Reduce
boilerplate code and aligns the driver with the common pattern used by
simple subdevices that have a single sink and a single source pad.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v5
new patch
previous method:
https://lore.kernel.org/imx/20260226-v4l2_init_register-v2-2-902d7140f9fa@nxp.com/
---
drivers/media/platform/synopsys/Kconfig | 1 +
drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 172 ++++-------------------
2 files changed, 28 insertions(+), 145 deletions(-)
diff --git a/drivers/media/platform/synopsys/Kconfig b/drivers/media/platform/synopsys/Kconfig
index b109de2c8111c..8d7aabf93af34 100644
--- a/drivers/media/platform/synopsys/Kconfig
+++ b/drivers/media/platform/synopsys/Kconfig
@@ -10,6 +10,7 @@ config VIDEO_DW_MIPI_CSI2RX
depends on PM && COMMON_CLK
select GENERIC_PHY_MIPI_DPHY
select MEDIA_CONTROLLER
+ select V4L2_1TO1
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
help
diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index f51367409ff46..b70e3783adcd3 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -22,6 +22,7 @@
#include <media/mipi-csi2.h>
#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device-1to1.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mc.h>
#include <media/v4l2-subdev.h>
@@ -78,12 +79,6 @@ enum dw_mipi_csi2rx_regs_index {
DW_MIPI_CSI2RX_MAX,
};
-enum {
- DW_MIPI_CSI2RX_PAD_SINK,
- DW_MIPI_CSI2RX_PAD_SRC,
- DW_MIPI_CSI2RX_PAD_MAX,
-};
-
struct dw_mipi_csi2rx_device;
struct dw_mipi_csi2rx_drvdata {
@@ -112,12 +107,8 @@ struct dw_mipi_csi2rx_device {
const struct dw_mipi_csi2rx_format *formats;
unsigned int formats_num;
- struct media_pad pads[DW_MIPI_CSI2RX_PAD_MAX];
- struct v4l2_async_notifier notifier;
- struct v4l2_subdev sd;
+ struct v4l2_subdev_1to1 sd_1to1;
- enum v4l2_mbus_type bus_type;
- u32 lanes_num;
u64 enabled_streams;
const struct dw_mipi_csi2rx_drvdata *drvdata;
@@ -294,7 +285,7 @@ static const struct dw_mipi_csi2rx_format formats[] = {
static inline struct dw_mipi_csi2rx_device *to_csi2(struct v4l2_subdev *sd)
{
- return container_of(sd, struct dw_mipi_csi2rx_device, sd);
+ return container_of(sd, struct dw_mipi_csi2rx_device, sd_1to1.sd);
}
static bool dw_mipi_csi2rx_has_reg(struct dw_mipi_csi2rx_device *csi2,
@@ -360,9 +351,9 @@ dw_mipi_csi2rx_find_format(struct dw_mipi_csi2rx_device *csi2, u32 mbus_code)
static int dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device *csi2)
{
+ u32 lanes = csi2->sd_1to1.vep.bus.mipi_csi2.num_data_lanes;
struct media_pad *source_pad;
union phy_configure_opts opts;
- u32 lanes = csi2->lanes_num;
u32 control = 0;
s64 link_freq;
int ret;
@@ -371,7 +362,7 @@ static int dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device *csi2)
return -EINVAL;
source_pad = media_pad_remote_pad_unique(
- &csi2->pads[DW_MIPI_CSI2RX_PAD_SINK]);
+ &csi2->sd_1to1.pads[V4L2_SUBDEV_1TO1_PADS_SINK]);
if (IS_ERR(source_pad))
return PTR_ERR(source_pad);
@@ -380,7 +371,7 @@ static int dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device *csi2)
if (link_freq < 0)
return link_freq;
- switch (csi2->bus_type) {
+ switch (csi2->sd_1to1.vep.bus_type) {
case V4L2_MBUS_CSI2_DPHY:
ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq * 2,
lanes, &opts.mipi_dphy);
@@ -458,16 +449,16 @@ dw_mipi_csi2rx_enum_mbus_code(struct v4l2_subdev *sd,
struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
switch (code->pad) {
- case DW_MIPI_CSI2RX_PAD_SRC:
+ case V4L2_SUBDEV_1TO1_PADS_SOURCE:
if (code->index)
return -EINVAL;
code->code =
v4l2_subdev_state_get_format(sd_state,
- DW_MIPI_CSI2RX_PAD_SINK)->code;
+ V4L2_SUBDEV_1TO1_PADS_SINK)->code;
return 0;
- case DW_MIPI_CSI2RX_PAD_SINK:
+ case V4L2_SUBDEV_1TO1_PADS_SINK:
if (code->index >= csi2->formats_num)
return -EINVAL;
@@ -487,7 +478,7 @@ static int dw_mipi_csi2rx_set_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *sink, *src;
/* the format on the source pad always matches the sink pad */
- if (format->pad == DW_MIPI_CSI2RX_PAD_SRC)
+ if (format->pad == V4L2_SUBDEV_1TO1_PADS_SOURCE)
return v4l2_subdev_get_fmt(sd, state, format);
sink = v4l2_subdev_state_get_format(state, format->pad, format->stream);
@@ -549,12 +540,12 @@ static int dw_mipi_csi2rx_enable_streams(struct v4l2_subdev *sd,
u64 mask;
int ret;
- sink_pad = &sd->entity.pads[DW_MIPI_CSI2RX_PAD_SINK];
+ sink_pad = &sd->entity.pads[V4L2_SUBDEV_1TO1_PADS_SINK];
remote_pad = media_pad_remote_pad_first(sink_pad);
remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
- mask = v4l2_subdev_state_xlate_streams(state, DW_MIPI_CSI2RX_PAD_SINK,
- DW_MIPI_CSI2RX_PAD_SRC,
+ mask = v4l2_subdev_state_xlate_streams(state, V4L2_SUBDEV_1TO1_PADS_SINK,
+ V4L2_SUBDEV_1TO1_PADS_SOURCE,
&streams_mask);
if (!csi2->enabled_streams) {
@@ -608,12 +599,12 @@ static int dw_mipi_csi2rx_disable_streams(struct v4l2_subdev *sd,
u64 mask;
int ret;
- sink_pad = &sd->entity.pads[DW_MIPI_CSI2RX_PAD_SINK];
+ sink_pad = &sd->entity.pads[V4L2_SUBDEV_1TO1_PADS_SINK];
remote_pad = media_pad_remote_pad_first(sink_pad);
remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
- mask = v4l2_subdev_state_xlate_streams(state, DW_MIPI_CSI2RX_PAD_SINK,
- DW_MIPI_CSI2RX_PAD_SRC,
+ mask = v4l2_subdev_state_xlate_streams(state, V4L2_SUBDEV_1TO1_PADS_SINK,
+ V4L2_SUBDEV_1TO1_PADS_SOURCE,
&streams_mask);
ret = v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask);
@@ -649,9 +640,9 @@ static int dw_mipi_csi2rx_init_state(struct v4l2_subdev *sd,
{
struct v4l2_subdev_route routes[] = {
{
- .sink_pad = DW_MIPI_CSI2RX_PAD_SINK,
+ .sink_pad = V4L2_SUBDEV_1TO1_PADS_SINK,
.sink_stream = 0,
- .source_pad = DW_MIPI_CSI2RX_PAD_SRC,
+ .source_pad = V4L2_SUBDEV_1TO1_PADS_SOURCE,
.source_stream = 0,
.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
},
@@ -670,91 +661,11 @@ static const struct v4l2_subdev_internal_ops dw_mipi_csi2rx_internal_ops = {
.init_state = dw_mipi_csi2rx_init_state,
};
-static int dw_mipi_csi2rx_notifier_bound(struct v4l2_async_notifier *notifier,
- struct v4l2_subdev *sd,
- struct v4l2_async_connection *asd)
-{
- struct dw_mipi_csi2rx_device *csi2 =
- container_of(notifier, struct dw_mipi_csi2rx_device, notifier);
- struct media_pad *sink_pad = &csi2->pads[DW_MIPI_CSI2RX_PAD_SINK];
- int ret;
-
- ret = v4l2_create_fwnode_links_to_pad(sd, sink_pad,
- MEDIA_LNK_FL_ENABLED);
- if (ret) {
- dev_err(csi2->dev, "failed to link source pad of %s\n",
- sd->name);
- return ret;
- }
-
- return 0;
-}
-
-static const struct v4l2_async_notifier_operations dw_mipi_csi2rx_notifier_ops = {
- .bound = dw_mipi_csi2rx_notifier_bound,
-};
-
-static int dw_mipi_csi2rx_register_notifier(struct dw_mipi_csi2rx_device *csi2)
-{
- struct v4l2_async_connection *asd;
- struct v4l2_async_notifier *ntf = &csi2->notifier;
- struct v4l2_fwnode_endpoint vep;
- struct v4l2_subdev *sd = &csi2->sd;
- struct device *dev = csi2->dev;
- int ret;
-
- struct fwnode_handle *ep __free(fwnode_handle) =
- fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
- if (!ep)
- return dev_err_probe(dev, -ENODEV, "failed to get endpoint\n");
-
- vep.bus_type = V4L2_MBUS_UNKNOWN;
- ret = v4l2_fwnode_endpoint_parse(ep, &vep);
- if (ret)
- return dev_err_probe(dev, ret, "failed to parse endpoint\n");
-
- if (vep.bus_type != V4L2_MBUS_CSI2_DPHY &&
- vep.bus_type != V4L2_MBUS_CSI2_CPHY)
- return dev_err_probe(dev, -EINVAL,
- "invalid bus type of endpoint\n");
-
- csi2->bus_type = vep.bus_type;
- csi2->lanes_num = vep.bus.mipi_csi2.num_data_lanes;
-
- v4l2_async_subdev_nf_init(ntf, sd);
- ntf->ops = &dw_mipi_csi2rx_notifier_ops;
-
- asd = v4l2_async_nf_add_fwnode_remote(ntf, ep,
- struct v4l2_async_connection);
- if (IS_ERR(asd)) {
- ret = PTR_ERR(asd);
- goto err_nf_cleanup;
- }
-
- ret = v4l2_async_nf_register(ntf);
- if (ret) {
- ret = dev_err_probe(dev, ret, "failed to register notifier\n");
- goto err_nf_cleanup;
- }
-
- return 0;
-
-err_nf_cleanup:
- v4l2_async_nf_cleanup(ntf);
-
- return ret;
-}
-
static int dw_mipi_csi2rx_register(struct dw_mipi_csi2rx_device *csi2)
{
- struct media_pad *pads = csi2->pads;
- struct v4l2_subdev *sd = &csi2->sd;
+ struct v4l2_subdev *sd = &csi2->sd_1to1.sd;
int ret;
- ret = dw_mipi_csi2rx_register_notifier(csi2);
- if (ret)
- goto err;
-
v4l2_subdev_init(sd, &dw_mipi_csi2rx_ops);
sd->dev = csi2->dev;
sd->entity.ops = &dw_mipi_csi2rx_media_ops;
@@ -764,45 +675,15 @@ static int dw_mipi_csi2rx_register(struct dw_mipi_csi2rx_device *csi2)
snprintf(sd->name, sizeof(sd->name), "dw-mipi-csi2rx %s",
dev_name(csi2->dev));
- pads[DW_MIPI_CSI2RX_PAD_SINK].flags = MEDIA_PAD_FL_SINK |
- MEDIA_PAD_FL_MUST_CONNECT;
- pads[DW_MIPI_CSI2RX_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
- ret = media_entity_pads_init(&sd->entity, DW_MIPI_CSI2RX_PAD_MAX, pads);
- if (ret)
- goto err_notifier_unregister;
+ csi2->sd_1to1.remote_bustype_cap_mask = BIT(V4L2_MBUS_CSI2_DPHY) |
+ BIT(V4L2_MBUS_CSI2_CPHY);
- ret = v4l2_subdev_init_finalize(sd);
+ ret = media_async_register_subdev_1to1(&csi2->sd_1to1);
if (ret)
- goto err_entity_cleanup;
-
- ret = v4l2_async_register_subdev(sd);
- if (ret) {
- dev_err(sd->dev, "failed to register CSI-2 subdev\n");
- goto err_subdev_cleanup;
- }
+ return dev_err_probe(sd->dev, ret,
+ "failed to register CSI-2 subdev\n");
return 0;
-
-err_subdev_cleanup:
- v4l2_subdev_cleanup(sd);
-err_entity_cleanup:
- media_entity_cleanup(&sd->entity);
-err_notifier_unregister:
- v4l2_async_nf_unregister(&csi2->notifier);
- v4l2_async_nf_cleanup(&csi2->notifier);
-err:
- return ret;
-}
-
-static void dw_mipi_csi2rx_unregister(struct dw_mipi_csi2rx_device *csi2)
-{
- struct v4l2_subdev *sd = &csi2->sd;
-
- v4l2_async_unregister_subdev(sd);
- v4l2_subdev_cleanup(sd);
- media_entity_cleanup(&sd->entity);
- v4l2_async_nf_unregister(&csi2->notifier);
- v4l2_async_nf_cleanup(&csi2->notifier);
}
static void imx93_csi2rx_dphy_assert_reset(struct dw_mipi_csi2rx_device *csi2)
@@ -879,12 +760,13 @@ static void imx93_csi2rx_dphy_ipi_enable(struct dw_mipi_csi2rx_device *csi2)
static int imx93_csi2rx_wait_for_phy_stopstate(struct dw_mipi_csi2rx_device *csi2)
{
+ u32 num_lanes = csi2->sd_1to1.vep.bus.mipi_csi2.num_data_lanes;
struct device *dev = csi2->dev;
u32 stopstate_mask;
u32 val;
int ret;
- stopstate_mask = DPHY_STOPSTATE_CLK_LANE | GENMASK(csi2->lanes_num - 1, 0);
+ stopstate_mask = DPHY_STOPSTATE_CLK_LANE | GENMASK(num_lanes - 1, 0);
ret = read_poll_timeout(dw_mipi_csi2rx_read, val,
(val & stopstate_mask) == stopstate_mask,
@@ -993,7 +875,7 @@ static void dw_mipi_csi2rx_remove(struct platform_device *pdev)
{
struct dw_mipi_csi2rx_device *csi2 = platform_get_drvdata(pdev);
- dw_mipi_csi2rx_unregister(csi2);
+ media_async_subdev_1to1_cleanup(&csi2->sd_1to1);
phy_exit(csi2->phy);
}
--
2.43.0
^ permalink raw reply related
* [PATCH v5 3/8] media: synopsys: Use v4l2_subdev_get_frame_desc_passthrough()
From: Frank.Li @ 2026-06-17 19:50 UTC (permalink / raw)
To: Sakari Ailus, Mauro Carvalho Chehab, Michael Riesch,
Laurent Pinchart, Frank Li, Martin Kepplinger-Novakovic,
Rui Miguel Silva, Purism Kernel Team, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-media, linux-kernel, imx, devicetree, linux-arm-kernel
In-Reply-To: <20260617-imx8qxp_pcam-v5-0-7fa6c8e7fba7@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Replace the local frame descriptor callback implementation with
v4l2_subdev_get_frame_desc_passthrough().
This helper provides the same functionality while avoiding duplicate
code and simplifying the driver implementation.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v5
- new patch
---
drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 22 +---------------------
1 file changed, 1 insertion(+), 21 deletions(-)
diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index 41e48365167e5..f51367409ff46 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -630,31 +630,11 @@ static int dw_mipi_csi2rx_disable_streams(struct v4l2_subdev *sd,
return ret;
}
-static int
-dw_mipi_csi2rx_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
- struct v4l2_mbus_frame_desc *fd)
-{
- struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
- struct v4l2_subdev *remote_sd;
- struct media_pad *remote_pad;
-
- remote_pad = media_pad_remote_pad_unique(&csi2->pads[DW_MIPI_CSI2RX_PAD_SINK]);
- if (IS_ERR(remote_pad)) {
- dev_err(csi2->dev, "can't get remote source pad\n");
- return PTR_ERR(remote_pad);
- }
-
- remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
-
- return v4l2_subdev_call(remote_sd, pad, get_frame_desc,
- remote_pad->index, fd);
-}
-
static const struct v4l2_subdev_pad_ops dw_mipi_csi2rx_pad_ops = {
.enum_mbus_code = dw_mipi_csi2rx_enum_mbus_code,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = dw_mipi_csi2rx_set_fmt,
- .get_frame_desc = dw_mipi_csi2rx_get_frame_desc,
+ .get_frame_desc = v4l2_subdev_get_frame_desc_passthrough,
.set_routing = dw_mipi_csi2rx_set_routing,
.enable_streams = dw_mipi_csi2rx_enable_streams,
.disable_streams = dw_mipi_csi2rx_disable_streams,
--
2.43.0
^ 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