* [PATCH] clk: mediatek: mt6735: Unregister PLLs on probe failure
From: Myeonghun Pak @ 2026-06-23 9:41 UTC (permalink / raw)
To: Yassine Oudjana, Michael Turquette, Stephen Boyd
Cc: Matthias Brugger, AngeloGioacchino Del Regno, linux-clk,
linux-mediatek, linux-kernel, linux-arm-kernel, Myeonghun Pak,
Ijae Kim
mtk_clk_register_plls() registers the apmixedsys PLL clocks manually, while
clk_mt6735_apmixed_remove() unregisters them on driver removal.
If devm_of_clk_add_hw_provider() fails after the PLL registration succeeds,
probe returns the error directly and the remove callback is not run. This
leaves the registered PLL clocks behind on the probe failure path.
Add an unregister_plls error path so provider registration failures unwind the
PLLs before returning the error.
Fixes: 43c04ed79189 ("clk: mediatek: Add drivers for MediaTek MT6735 main clock and reset drivers")
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
---
drivers/clk/mediatek/clk-mt6735-apmixedsys.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/mediatek/clk-mt6735-apmixedsys.c b/drivers/clk/mediatek/clk-mt6735-apmixedsys.c
index 9e30c089a2..04cf9665ec 100644
--- a/drivers/clk/mediatek/clk-mt6735-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt6735-apmixedsys.c
@@ -102,10 +102,17 @@ static int clk_mt6735_apmixed_probe(struct platform_device *pdev)
ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
clk_data);
- if (ret)
+ if (ret) {
dev_err(&pdev->dev,
"Failed to register clock provider: %d\n", ret);
+ goto unregister_plls;
+ }
+
+ return 0;
+unregister_plls:
+ mtk_clk_unregister_plls(apmixedsys_plls, ARRAY_SIZE(apmixedsys_plls),
+ clk_data);
return ret;
}
--
2.47.1
^ permalink raw reply related
* Re: [PATCH] iio: stm32-dfsdm: Treat flags as booleans
From: Olivier MOYSAN @ 2026-06-23 9:43 UTC (permalink / raw)
To: Jonathan Cameron, Andy Shevchenko
Cc: Rob Herring (Arm), David Lechner, Nuno Sá, Andy Shevchenko,
Maxime Coquelin, Alexandre Torgue, linux-iio, linux-stm32,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260621151026.69714694@jic23-huawei>
Hi Andy, Jonathan,
Sorry for the late answer.
On 6/21/26 16:10, Jonathan Cameron wrote:
> On Sat, 13 Jun 2026 16:39:16 +0300
> Andy Shevchenko <andriy.shevchenko@intel.com> wrote:
>
>> On Fri, Jun 12, 2026 at 04:51:50PM -0500, Rob Herring (Arm) wrote:
>>> The "st,adc-alt-channel" and "st,filter0-sync" properties are
>>> documented as boolean flags. The legacy parser read them as integer
>>> cells, unlike the child-node parser which already checks only for
>>> presence.
>>>
>>> Use presence and boolean helpers so both parsers follow the binding and
>>> the property type checker no longer reports the flags.
>>
>> For the patch
>> Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
>>
>> However one interesting remark below.
>>
>> ...
>>
>>> - ret = of_property_read_u32_index(indio_dev->dev.of_node,
>>> - "st,adc-alt-channel", chan_idx,
>>> - &df_ch->alt_si);
>>
>>> + df_ch->alt_si = of_property_present(indio_dev->dev.of_node,
>>
>> I believe it still has another (serious?) issue. We usually don't use indio_dev
>> for device properties. It's not a device that is described in DT.
>> It seems the only driver in IIO that does that. Note, I haven't conducted any
>> deeper research, it might be (however I'm quite in doubt) that this is correct
>> use and one device registers a few indio_dev:s.
>
> It is curious. The registration sequence in this driver is complex, but I'm not
> seeing anything that sets the fwnode for the struct iio_dev->dev before calling
> the init() callbacks that end up in this code. It is set later by iio_device_register()
> (iirc that has something to do with consumers turning up later).
>
> St folk could you take a look at this and see what we are missing
> if it does currently work?
>
> For now I'll apply this patch but might need to drop it if a fix clashes
> with it.
>
> Thanks,
>
> Jonathan
>
>
I confirm that the current legacy path is functional
(With the st,adc-alt-channel property fix applied)
It currently works because the driver initializes np from dev->of_node
in probe, and that value is then used in init callbacks.
I agree that this approach is not robust, as it depends on
initialization sequencing and on using an IIO object that is not the DT
owner object. I will prepare a patch to use the DT device directly as
the single source for DT properties.
I also suggest keeping a fallback path for st,adc-alt-channel so we do
not break legacy DTs that have not yet migrated to the new binding.
I prepare this also.
BRs
Olivier
>
>>
>>> + "st,adc-alt-channel");
>>
>
>
^ permalink raw reply
* Re: [PATCH v3 0/4] ROCK 4D audio enablement
From: Alexandre Belloni @ 2026-06-23 9:47 UTC (permalink / raw)
To: Nicolas Frattaroli
Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Heiko Stuebner, kernel, linux-input, devicetree, linux-kernel,
linux-arm-kernel, linux-rockchip, Krzysztof Kozlowski,
Cristian Ciocaltea
In-Reply-To: <wE1x9P2vQlC8kihOSm9uOA@collabora.com>
Hello Nicolas,
I guess Dmitry is the one that would take patches 1 to 3. You should
probably resend once the merge window has closed.
On 11/05/2026 18:21:40+0200, Nicolas Frattaroli wrote:
> Hi Alexandre, and other maintainers,
>
> On Wednesday, 8 April 2026 19:49:38 Central European Summer Time Nicolas Frattaroli wrote:
> > The ROCK 4D uses an ADC input to distinguish between a headphone (i.e.,
> > no mic) and a headset (i.e., with mic). After some searching, it appears
> > that the closest we can get to modelling this is by sending a particular
> > switch input event.
> >
> > So this series modifies the adc-keys bindings, extends the adc-keys
> > driver to allow sending other input types as well, and then adds the
> > analog audio nodes to ROCK 4D's device tree.
> >
> > It should be noted that analog capture from the TRRS jack currently
> > results in completely digitally silent audio for me, i.e. no data other
> > than 0xFF. There's a few reasons why this could happen, chief among them
> > that my SAI driver is broken or that the ES8328 codec driver is once
> > again broken. The DAPM routes when graphed out look fine though. So the
> > DTS part is correct, and I can fix the broken capture in a separate
> > follow-up patch that doesn't have to include DT people.
> >
> > Another possibility is that my phone headset, despite being 4 rings and
> > having a little pin hole at the back of the volume doodad, does not
> > actually have a microphone, but in that case I'd still expect some noise
> > in the PCM. Maybe it's just shy.
> >
> > Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> > ---
> > Changes in v3:
> > - bindings: use unevaluatedProperties instead of explicitly mentioning
> > linux,input-type.
> > - Link to v2: https://lore.kernel.org/r/20251215-rock4d-audio-v2-0-82a61de39b4c@collabora.com
> >
> > Changes in v2:
> > - Drop HDMI audio patch, as it was already merged.
> > - adc-keys: rename "keycode" to "code".
> > - adc-keys: make the keycode (now "code") local a u32 instead of an int
> > - adc-keys: only allow EV_KEY and EV_SW for now. Rename patch
> > accordingly.
> > - adc-keys: Add another patch to rework probe function error logging.
> > - Link to v1: https://lore.kernel.org/r/20250630-rock4d-audio-v1-0-0b3c8e8fda9c@collabora.com
> >
> > ---
> > Nicolas Frattaroli (4):
> > dt-bindings: input: adc-keys: allow all input properties
> > Input: adc-keys - support EV_SW as well, not just EV_KEY.
> > Input: adc-keys - Use dev_err_probe in probe function
> > arm64: dts: rockchip: add analog audio to ROCK 4D
> >
> > .../devicetree/bindings/input/adc-keys.yaml | 17 ++--
> > arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts | 90 ++++++++++++++++++++++
> > drivers/input/keyboard/adc-keys.c | 88 ++++++++++-----------
> > 3 files changed, 147 insertions(+), 48 deletions(-)
> > ---
> > base-commit: 8de395f35e79d9168a78504fed495578ec7bac52
> > change-id: 20250627-rock4d-audio-cfc07f168a08
> >
> > Best regards,
> > --
> > Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> >
> >
>
> What's the path forward here? All the patches are reviewed, but it
> has been almost a month without them being applied now.
>
> Which tree(s) would this be applied to, and who should I poke?
>
> Thanks :)
>
> Kind regards,
> Nicolas Frattaroli
>
>
>
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* [PATCH v2] PCI: cadence: skip the link polling when endpoint not connected
From: Aksh Garg @ 2026-06-23 9:51 UTC (permalink / raw)
To: linux-pci, vigneshr, s-vadapalli, lpieralisi, kwilczynski, mani,
robh, bhelgaas, mpillai, unicorn_wang, me, 18255117159
Cc: linux-arm-kernel, linux-kernel, danishanwar, a-garg7
cdns_pcie_host_wait_for_link() polls on link-up for 10 retries with a
delay of 90-100ms each (~1 second). A call to cdns_pcie_host_link_setup()
during the resume operation blocks the resume operation unnecessarily for
~1s even when no endpoint device is connected.
Add link_down_no_hotplug flag to track link state across suspend/resume
cycles (for the platforms that do not support hotplug). If link was
down before suspend in such platforms, skip the expensive polling in
resume since no endpoint was present.
Reviewed-by: Chen Wang <unicorn_wang@outlook.com>
Reviewed-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: Aksh Garg <a-garg7@ti.com>
---
Changes from v1 to v2:
- Updated the flag name from 'skip_link_polling' to 'link_down_no_hotplug'
v1: https://lore.kernel.org/all/20260605071922.1724499-1-a-garg7@ti.com/
drivers/pci/controller/cadence/pci-j721e.c | 5 +++++
drivers/pci/controller/cadence/pcie-cadence-host-hpa.c | 3 +++
drivers/pci/controller/cadence/pcie-cadence-host.c | 3 +++
drivers/pci/controller/cadence/pcie-cadence.h | 3 +++
4 files changed, 14 insertions(+)
diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
index bfdfe98d5aba..48db7a6cf754 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
+++ b/drivers/pci/controller/cadence/pci-j721e.c
@@ -686,6 +686,11 @@ static int j721e_pcie_suspend_noirq(struct device *dev)
struct j721e_pcie *pcie = dev_get_drvdata(dev);
if (pcie->mode == PCI_MODE_RC) {
+ struct cdns_pcie_rc *rc = cdns_pcie_to_rc(pcie->cdns_pcie);
+
+ /* If link is down before suspend, skip polling in resume */
+ rc->link_down_no_hotplug = !j721e_pcie_link_up(pcie->cdns_pcie);
+
gpiod_set_value_cansleep(pcie->reset_gpio, 0);
clk_disable_unprepare(pcie->refclk);
}
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c b/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
index 0f540bed58e8..31cf50cff8f8 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
@@ -301,6 +301,9 @@ int cdns_pcie_hpa_host_link_setup(struct cdns_pcie_rc *rc)
return ret;
}
+ if (rc->link_down_no_hotplug)
+ return 0;
+
ret = cdns_pcie_host_wait_for_link(pcie, cdns_pcie_hpa_link_up);
if (ret)
dev_dbg(dev, "PCIe link never came up\n");
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
index 0bc9e6e90e0e..50abc657a871 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
@@ -352,6 +352,9 @@ int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
return ret;
}
+ if (rc->link_down_no_hotplug)
+ return 0;
+
ret = cdns_pcie_host_start_link(rc, cdns_pcie_link_up);
if (ret)
dev_dbg(dev, "PCIe link never came up\n");
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
index 574e9cf4d003..1561022c1a8b 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
@@ -117,6 +117,8 @@ struct cdns_pcie {
* @no_inbound_map: Whether inbound mapping is supported
* @quirk_broken_aspm_l0s: Disable ASPM L0s support as quirk
* @quirk_broken_aspm_l1: Disable ASPM L1 support as quirk
+ * @link_down_no_hotplug: Skip link polling during resume on no-hotplug
+ * platforms when link was down before suspend
*/
struct cdns_pcie_rc {
struct cdns_pcie pcie;
@@ -131,6 +133,7 @@ struct cdns_pcie_rc {
unsigned int no_inbound_map:1;
unsigned int quirk_broken_aspm_l0s:1;
unsigned int quirk_broken_aspm_l1:1;
+ unsigned int link_down_no_hotplug:1;
};
/**
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v10 0/5] Add Qualcomm extended CTI support
From: Yingchao Deng (Consultant) @ 2026-06-23 9:52 UTC (permalink / raw)
To: Leo Yan, Yingchao Deng
Cc: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
coresight, linux-arm-kernel, linux-kernel, tingwei.zhang,
Jinlong Mao, jie.gan, Yingchao Deng
In-Reply-To: <20260623090432.GG31870@e132581.arm.com>
On 6/23/2026 5:04 PM, Leo Yan wrote:
> This series looks good to me and I tested:
>
> - Confirmed no any change for standard CTI;
> - Perf command;
> - Build bisection.
>
> Tested-by: Leo Yan<leo.yan@arm.com>
>
> Mike may also want to take a look in case there is any overlap with his
> claim tags init patch [1]. I don't have a strong preference on which
> series goes in first, as the claim tag handling in this series looks
> clean enough to me.
>
> @Yingchao, just a small suggestion: rc1–rc4 is usually the best window
> for getting patches merged. If you receive comments and are able to
> address them quickly, it may be worth respin patches during that
> period to try catching the next merge window. This is no guarantees,
> just thought it might be useful to share as a general tip 🙂
Thanks Leo for testing and the helpful suggestion.
Thanks,
Yingchao
^ permalink raw reply
* Re: [PATCH] iio: stm32-dfsdm: Treat flags as booleans
From: Andy Shevchenko @ 2026-06-23 9:54 UTC (permalink / raw)
To: Olivier MOYSAN
Cc: Jonathan Cameron, Rob Herring (Arm), David Lechner, Nuno Sá,
Andy Shevchenko, Maxime Coquelin, Alexandre Torgue, linux-iio,
linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <46fce99d-9dd5-435b-95cd-86ed4771aa83@foss.st.com>
On Tue, Jun 23, 2026 at 11:43:49AM +0200, Olivier MOYSAN wrote:
> On 6/21/26 16:10, Jonathan Cameron wrote:
> > On Sat, 13 Jun 2026 16:39:16 +0300
> > Andy Shevchenko <andriy.shevchenko@intel.com> wrote:
> > > On Fri, Jun 12, 2026 at 04:51:50PM -0500, Rob Herring (Arm) wrote:
...
> > > > - ret = of_property_read_u32_index(indio_dev->dev.of_node,
> > > > - "st,adc-alt-channel", chan_idx,
> > > > - &df_ch->alt_si);
> > >
> > > > + df_ch->alt_si = of_property_present(indio_dev->dev.of_node,
> > >
> > > I believe it still has another (serious?) issue. We usually don't use indio_dev
> > > for device properties. It's not a device that is described in DT.
> > > It seems the only driver in IIO that does that. Note, I haven't conducted any
> > > deeper research, it might be (however I'm quite in doubt) that this is correct
> > > use and one device registers a few indio_dev:s.
> >
> > It is curious. The registration sequence in this driver is complex, but I'm not
> > seeing anything that sets the fwnode for the struct iio_dev->dev before calling
> > the init() callbacks that end up in this code. It is set later by iio_device_register()
> > (iirc that has something to do with consumers turning up later).
> >
> > St folk could you take a look at this and see what we are missing
> > if it does currently work?
> >
> > For now I'll apply this patch but might need to drop it if a fix clashes
> > with it.
>
> I confirm that the current legacy path is functional
> (With the st,adc-alt-channel property fix applied)
Yeah, it's here
https://elixir.bootlin.com/linux/v7.1.1/source/drivers/iio/adc/stm32-dfsdm-adc.c#L1772
and should gone. Basically one wants to replace all these to use device and
fwnode propery APIs and proper device node, without that hack.
> It currently works because the driver initializes np from dev->of_node in
> probe, and that value is then used in init callbacks.
>
> I agree that this approach is not robust, as it depends on initialization
> sequencing and on using an IIO object that is not the DT owner object. I
> will prepare a patch to use the DT device directly as the single source for
> DT properties.
>
> I also suggest keeping a fallback path for st,adc-alt-channel so we do not
> break legacy DTs that have not yet migrated to the new binding.
> I prepare this also.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH] usb: dwc3: imx8mp: make dwc3_imx_glue_ops static and rename to imx8mp
From: Ben Dooks @ 2026-06-23 10:05 UTC (permalink / raw)
To: Thinh Nguyen, Greg Kroah-Hartman, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-usb, imx,
linux-arm-kernel, linux-kernel
Cc: Ben Dooks
The dwc3_imx_glue_ops is not used outside this file, and technically this
is the dwc3-imx8mp driver so whilst making this static to avoid the
following warning, rename it dwc3_imx8mp_glue_ops to distinguish it from
the other driver which also has dwc3_imx_glue_ops.
Fixes:
drivers/usb/dwc3/dwc3-imx8mp.c:176:22: warning: symbol 'dwc3_imx_glue_ops' was not declared. Should it be static?
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
---
drivers/usb/dwc3/dwc3-imx8mp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
index 1cf96540b66e..bc61a89b66b1 100644
--- a/drivers/usb/dwc3/dwc3-imx8mp.c
+++ b/drivers/usb/dwc3/dwc3-imx8mp.c
@@ -173,8 +173,8 @@ static void dwc3_imx_pre_set_role(struct dwc3 *dwc, enum usb_role role)
pm_runtime_use_autosuspend(dwc->dev);
}
-struct dwc3_glue_ops dwc3_imx_glue_ops = {
- .pre_set_role = dwc3_imx_pre_set_role,
+statc struct dwc3_glue_ops dwc3_imx8mp_glue_ops = {
+ .pre_set_role = dwc3_imx8mp_pre_set_role,
};
static int dwc3_imx8mp_probe(struct platform_device *pdev)
@@ -266,7 +266,7 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
goto put_dwc3;
}
- dwc3->glue_ops = &dwc3_imx_glue_ops;
+ dwc3->glue_ops = &dwc3_imx8mp_glue_ops;
if (dwc3->dr_mode == USB_DR_MODE_HOST)
pm_runtime_dont_use_autosuspend(dwc3->dev);
--
2.37.2.352.g3c44437643
^ permalink raw reply related
* Re: [PATCH] usb: dwc3: imx8mp: make dwc3_imx_glue_ops static and rename to imx8mp
From: Ahmad Fatoum @ 2026-06-23 10:07 UTC (permalink / raw)
To: Ben Dooks, Thinh Nguyen, Greg Kroah-Hartman, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, linux-usb,
imx, linux-arm-kernel, linux-kernel
In-Reply-To: <20260623100554.735080-1-ben.dooks@codethink.co.uk>
On 6/23/26 12:05 PM, Ben Dooks wrote:
> The dwc3_imx_glue_ops is not used outside this file, and technically this
> is the dwc3-imx8mp driver so whilst making this static to avoid the
> following warning, rename it dwc3_imx8mp_glue_ops to distinguish it from
> the other driver which also has dwc3_imx_glue_ops.
>
> Fixes:
> drivers/usb/dwc3/dwc3-imx8mp.c:176:22: warning: symbol 'dwc3_imx_glue_ops' was not declared. Should it be static?
>
> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
> ---
> drivers/usb/dwc3/dwc3-imx8mp.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
> index 1cf96540b66e..bc61a89b66b1 100644
> --- a/drivers/usb/dwc3/dwc3-imx8mp.c
> +++ b/drivers/usb/dwc3/dwc3-imx8mp.c
> @@ -173,8 +173,8 @@ static void dwc3_imx_pre_set_role(struct dwc3 *dwc, enum usb_role role)
> pm_runtime_use_autosuspend(dwc->dev);
> }
>
> -struct dwc3_glue_ops dwc3_imx_glue_ops = {
> - .pre_set_role = dwc3_imx_pre_set_role,
> +statc struct dwc3_glue_ops dwc3_imx8mp_glue_ops = {
Typo
> + .pre_set_role = dwc3_imx8mp_pre_set_role,
> };
>
> static int dwc3_imx8mp_probe(struct platform_device *pdev)
> @@ -266,7 +266,7 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
> goto put_dwc3;
> }
>
> - dwc3->glue_ops = &dwc3_imx_glue_ops;
> + dwc3->glue_ops = &dwc3_imx8mp_glue_ops;
>
> if (dwc3->dr_mode == USB_DR_MODE_HOST)
> pm_runtime_dont_use_autosuspend(dwc3->dev);
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* Re: [PATCH 1/4] device property: Introduce fwnode_graph_for_each_endpoint_scoped()
From: Andy Shevchenko @ 2026-06-23 10:09 UTC (permalink / raw)
To: Frank.Li
Cc: Daniel Scally, Heikki Krogerus, Sakari Ailus, Greg Kroah-Hartman,
Rafael J. Wysocki, Danilo Krummrich, Mauro Carvalho Chehab,
Dafna Hirschfeld, Laurent Pinchart, Heiko Stuebner,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
driver-core, linux-acpi, linux-kernel, linux-media,
linux-rockchip, linux-arm-kernel, linux-arm-msm, imx, Guoniu Zhou,
Frank Li
In-Reply-To: <20260622-fw_scoped-v1-1-a37d0aac0a68@nxp.com>
On Mon, Jun 22, 2026 at 10:30:11AM -0400, Frank.Li@oss.nxp.com wrote:
> From: Frank Li <Frank.Li@nxp.com>
>
> Similar to recently propose for_each_child_of_node_scoped() this new
> version of the loop macro instantiates a new local struct fwnode_handle *
> that uses the __free(fwnode_handle) auto cleanup handling so that if a
> reference to a node is held on early exit from the loop the reference will
> be released. If the loop runs to completion, the child pointer will be NULL
> and no action will be taken.
>
> The reason this is useful is that it removes the need for
> fwnode_handle_put() on early loop exits. If there is a need to retain the
Just be consistent with 1-space versus 2-spaces gaps in the same text.
> reference, then return_ptr(child) or no_free_ptr(child) may be used to
> safely disable the auto cleanup.
No objections from me.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
See one nit-pick below.
But you will need driver core maintainers to Ack this.
...
> +#define fwnode_graph_for_each_endpoint_scoped(fwnode, child) \
> + for (struct fwnode_handle *child __free(fwnode_handle) = \
> + fwnode_graph_get_next_endpoint(fwnode, NULL); \
You should follow the existing style, the 'f' in fwnode should be under 'u' in
struct.
> + child; child = fwnode_graph_get_next_endpoint(fwnode, child))
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Hongru Zhang @ 2026-06-23 10:10 UTC (permalink / raw)
To: david
Cc: akpm, baohua, bhe, chentao, chrisl, jack, kasong, kunwu.chan,
liam, lianux.mm, linux-arm-kernel, linux-kernel, linux-mm,
linux-riscv, linux-s390, linuxppc-dev, liyangouwen1, ljs,
loongarch, mhocko, nphamcs, nzzhao, pfalcato, rppt, shikemeng,
surenb, vbabka, wanglian, willy, youngjun.park, zhanghongru06
In-Reply-To: <d04f745d-eb3e-4d2c-8ea2-5fdcf2cf27b8@kernel.org>
On 6/23/26 10:02, David Hildenbrand wrote:
> I know that especially browser usually use fork servers: a tiny
> (single-threaded) process just to create new child processes. Any information
> regarding the apps above that use fork() on small vs. large processes?
I wrote a second BPF tool (fork_info) that captures nr_threads and
map_count (VMA count) from the calling process at the exact moment
fork() is triggered. Results from 3 representative apps:
App (category) Fork caller Threads VMAs
-----------------------------------------------------------
Taobao (shopping) DaemonThread-6 526 8,987
Amap (navigation) DaemonThread-6 289 7,120
UC Browser (browser) OneNativeThread 350 8,144
These are all heavyweight multi-threaded processes (hundreds of threads,
7,000-9,000 VMAs), not fork servers.
> Above you write "some call fork() from multiple threads". Any further
> information on that?
Xiaohongshu (com.xingin.xhs, social media) is a clear example. In just
tens of seconds of normal usage, fork() was called 22 times from 4
different threads:
PID COMM THREADS VMAS
4206 com.xingin.xhs 85 4,140
4216 Thread-2208 85 4,157
4208 Thread-2208 90 4,211
5200 Thread-3200 337 6,519
5200 Thread-3200 343 6,563
5200 Thread-3200 361 6,769
5200 Thread-3200 453 7,793
5200 Thread-3200 450 7,779
5202 Thread-2219 459 7,846
5202 Thread-2219 462 7,875
5202 Thread-2219 465 7,899
4219 Thread-2219 465 7,903
4219 Thread-2219 468 7,922
5202 Thread-2219 467 7,917
4219 Thread-2219 467 7,921
4219 Thread-2219 468 7,929
5202 Thread-2219 464 7,909
5202 Thread-2219 460 7,889
5202 Thread-2219 459 7,884
4219 Thread-2219 433 7,771
4219 Thread-2219 433 7,771
4219 Thread-2219 434 7,778
The process grew from 85 threads / 4,140 VMAs at first fork to
434 threads / 7,778 VMAs at last fork, showing these are long-lived
heavyweight processes that fork repeatedly throughout their lifecycle.
Tracing tool:
https://gist.github.com/zhr250/ba7725d0ea55594bcafd3cd4806eed98
Hongru
^ permalink raw reply
* [PATCH v2] usb: dwc3: imx8mp: make dwc3_imx_glue_ops static and rename to imx8mp
From: Ben Dooks @ 2026-06-23 10:10 UTC (permalink / raw)
To: Thinh Nguyen, Greg Kroah-Hartman, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-usb, imx,
linux-arm-kernel, linux-kernel
Cc: Ben Dooks
The dwc3_imx_glue_ops is not used outside this file, and technically this
is the dwc3-imx8mp driver so whilst making this static to avoid the
following warning, rename it dwc3_imx8mp_glue_ops to distinguish it from
the other driver which also has dwc3_imx_glue_ops.
Fixes:
drivers/usb/dwc3/dwc3-imx8mp.c:176:22: warning: symbol 'dwc3_imx_glue_ops' was not declared. Should it be static?
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
---
drivers/usb/dwc3/dwc3-imx8mp.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
index 1cf96540b66e..de8c17bc940d 100644
--- a/drivers/usb/dwc3/dwc3-imx8mp.c
+++ b/drivers/usb/dwc3/dwc3-imx8mp.c
@@ -158,7 +158,7 @@ static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
return IRQ_HANDLED;
}
-static void dwc3_imx_pre_set_role(struct dwc3 *dwc, enum usb_role role)
+static void dwc3_imx8mp_pre_set_role(struct dwc3 *dwc, enum usb_role role)
{
if (role == USB_ROLE_HOST)
/*
@@ -173,8 +173,8 @@ static void dwc3_imx_pre_set_role(struct dwc3 *dwc, enum usb_role role)
pm_runtime_use_autosuspend(dwc->dev);
}
-struct dwc3_glue_ops dwc3_imx_glue_ops = {
- .pre_set_role = dwc3_imx_pre_set_role,
+static struct dwc3_glue_ops dwc3_imx8mp_glue_ops = {
+ .pre_set_role = dwc3_imx8mp_pre_set_role,
};
static int dwc3_imx8mp_probe(struct platform_device *pdev)
@@ -266,7 +266,7 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
goto put_dwc3;
}
- dwc3->glue_ops = &dwc3_imx_glue_ops;
+ dwc3->glue_ops = &dwc3_imx8mp_glue_ops;
if (dwc3->dr_mode == USB_DR_MODE_HOST)
pm_runtime_dont_use_autosuspend(dwc3->dev);
--
2.37.2.352.g3c44437643
^ permalink raw reply related
* Re: [PATCH] usb: dwc3: imx8mp: make dwc3_imx_glue_ops static and rename to imx8mp
From: Ben Dooks @ 2026-06-23 10:11 UTC (permalink / raw)
To: Ahmad Fatoum, Thinh Nguyen, Greg Kroah-Hartman, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, linux-usb,
imx, linux-arm-kernel, linux-kernel
In-Reply-To: <39a5d53d-2eb9-4f72-aca9-95def11edf25@pengutronix.de>
On 23/06/2026 11:07, Ahmad Fatoum wrote:
>
>
> On 6/23/26 12:05 PM, Ben Dooks wrote:
>> The dwc3_imx_glue_ops is not used outside this file, and technically this
>> is the dwc3-imx8mp driver so whilst making this static to avoid the
>> following warning, rename it dwc3_imx8mp_glue_ops to distinguish it from
>> the other driver which also has dwc3_imx_glue_ops.
>>
>> Fixes:
>> drivers/usb/dwc3/dwc3-imx8mp.c:176:22: warning: symbol 'dwc3_imx_glue_ops' was not declared. Should it be static?
>>
>> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
>> ---
>> drivers/usb/dwc3/dwc3-imx8mp.c | 6 +++---
>> 1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
>> index 1cf96540b66e..bc61a89b66b1 100644
>> --- a/drivers/usb/dwc3/dwc3-imx8mp.c
>> +++ b/drivers/usb/dwc3/dwc3-imx8mp.c
>> @@ -173,8 +173,8 @@ static void dwc3_imx_pre_set_role(struct dwc3 *dwc, enum usb_role role)
>> pm_runtime_use_autosuspend(dwc->dev);
>> }
>>
>> -struct dwc3_glue_ops dwc3_imx_glue_ops = {
>> - .pre_set_role = dwc3_imx_pre_set_role,
>> +statc struct dwc3_glue_ops dwc3_imx8mp_glue_ops = {
>
> Typo
Thanks, forgot to re-run check after this. Sent v2
>
>> + .pre_set_role = dwc3_imx8mp_pre_set_role,
>> };
>>
>> static int dwc3_imx8mp_probe(struct platform_device *pdev)
>> @@ -266,7 +266,7 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
>> goto put_dwc3;
>> }
>>
>> - dwc3->glue_ops = &dwc3_imx_glue_ops;
>> + dwc3->glue_ops = &dwc3_imx8mp_glue_ops;
>>
>> if (dwc3->dr_mode == USB_DR_MODE_HOST)
>> pm_runtime_dont_use_autosuspend(dwc3->dev);
>
--
Ben Dooks http://www.codethink.co.uk/
Senior Engineer Codethink - Providing Genius
https://www.codethink.co.uk/privacy.html
^ permalink raw reply
* Re: [PATCH 3/4] media: rkisp1: use fwnode_graph_for_each_endpoint_scoped() to simplify code
From: Andy Shevchenko @ 2026-06-23 10:16 UTC (permalink / raw)
To: Frank.Li
Cc: Daniel Scally, Heikki Krogerus, Sakari Ailus, Greg Kroah-Hartman,
Rafael J. Wysocki, Danilo Krummrich, Mauro Carvalho Chehab,
Dafna Hirschfeld, Laurent Pinchart, Heiko Stuebner,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
driver-core, linux-acpi, linux-kernel, linux-media,
linux-rockchip, linux-arm-kernel, linux-arm-msm, imx, Guoniu Zhou,
Frank Li
In-Reply-To: <20260622-fw_scoped-v1-3-a37d0aac0a68@nxp.com>
On Mon, Jun 22, 2026 at 10:30:13AM -0400, Frank.Li@oss.nxp.com wrote:
> Use fwnode_graph_for_each_endpoint_scoped() to simplify code.
>
> No functional changes.
...
> - fwnode_graph_for_each_endpoint(fwnode, ep) {
> + fwnode_graph_for_each_endpoint_scoped(fwnode, ep) {
> struct fwnode_handle *port;
> struct v4l2_fwnode_endpoint vep = { };
> struct rkisp1_sensor_async *rk_asd;
> @@ -286,7 +285,6 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)
> }
>
> if (ret) {
> - fwnode_handle_put(ep);
> v4l2_async_nf_cleanup(ntf);
> return ret;
> }
In this case you can go further and actually replace all the
ret = -Exxx;
break;
with
v4l2_async_nf_cleanup(ntf);
return -Exx;
in the above loop.
but I assume the original is also fine as it's a common denominator for all of
them (and only one case has something in addition to that).
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 0/4] media: add and use fwnode_graph_for_each_endpoint_scoped()
From: Andy Shevchenko @ 2026-06-23 10:17 UTC (permalink / raw)
To: Frank.Li
Cc: Daniel Scally, Heikki Krogerus, Sakari Ailus, Greg Kroah-Hartman,
Rafael J. Wysocki, Danilo Krummrich, Mauro Carvalho Chehab,
Dafna Hirschfeld, Laurent Pinchart, Heiko Stuebner,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
driver-core, linux-acpi, linux-kernel, linux-media,
linux-rockchip, linux-arm-kernel, linux-arm-msm, imx, Guoniu Zhou,
Frank Li
In-Reply-To: <20260622-fw_scoped-v1-0-a37d0aac0a68@nxp.com>
On Mon, Jun 22, 2026 at 10:30:10AM -0400, Frank.Li@oss.nxp.com wrote:
> Add new helper macro fwnode_graph_for_each_endpoint_scoped() and use it
> simplify media code.
>
> Typical example should qualcomm's driver (camss.c), the v4l2_mc.c and
> rkisp1-dev.c only silience improvement.
>
> Anyways, *_for_each_*_scoped() already use widely and make code clean.
LGTM,
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
for patches 2, 3, and 4.
Patch 1 has individual comments.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* chipidea: usbmisc_imx: i.MX93 support
From: Stefan Wahren @ 2026-06-23 10:23 UTC (permalink / raw)
To: Xu Yang, Frank Li
Cc: Alexander Stein, Greg Kroah-Hartman, Linux ARM,
linux-usb@vger.kernel.org
Hi,
during debugging USB OTG on our custom i.MX93 board, we noticed
remarkable differences between the implementation of the
chipidea/usbmisc_imx and the official NXP i.MX93 Reference Manual [1].
Is the USB OTG part including PHY of the i.MX93 officially supported in
Linux Mainline?
According to imx91_93_common.dtsi the USB IP of the i.MX93 should be
identical to i.MX8MM [2]
usbmisc1: usbmisc@4c100200 {
compatible = "fsl,imx8mm-usbmisc", "fsl,imx7d-usbmisc",
"fsl,imx6q-usbmisc";
But looking at the PHY register definition and reset values in the NXP
i.MX93 Reference Manual,
the registers are comparable to the i.MX95 [3] ones.
Could you please clarify which source is correct (Mainline DTS vs
Reference Manual)?
Looking deeper at chipidea/usbmisc_imx shows the usage of the following
register bits
#define MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL BIT(0)
#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 BIT(1)
#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 BIT(2)
#define MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB BIT(3)
#define MX7D_USB_OTG_PHY_STATUS_LINE_STATE0 BIT(0)
#define MX7D_USB_OTG_PHY_STATUS_LINE_STATE1 BIT(1)
#define MX7D_USB_OTG_PHY_STATUS_CHRGDET BIT(29)
According to NXP i.MX93 & i.MX95 Reference Manual, these are bits reserved.
Is it correct that the chipidea/usbmisc_imx use these bits on i.MX93?
Best regards
[1] - https://www.nxp.com/docs/en/reference-manual/IMX93RM.pdf
<https://www.nxp.com/docs/en/reference-manual/IMX93RM.pdf>
[2] - https://www.nxp.com/docs/en/reference-manual/IMX8MMRM.pdf
<https://www.nxp.com/docs/en/reference-manual/IMX8MMRM.pdf>
[3] - https://www.nxp.com/docs/en/reference-manual/IMX95RM.pdf
<https://www.nxp.com/docs/en/reference-manual/IMX95RM.pdf>
^ permalink raw reply
* [PATCH] media: imx-jpeg: cancel timeout worker when streaming stops
From: Fan Wu @ 2026-06-23 10:30 UTC (permalink / raw)
To: mirela.rabulea, mchehab
Cc: shawnguo, s.hauer, kernel, festevam, imx, linux-media,
linux-arm-kernel, linux-kernel, stable, Fan Wu
Each per-fd context ctx owns a delayed_work (ctx->task_timer, callback
mxc_jpeg_device_run_timeout) armed via schedule_delayed_work() at the end
of mxc_jpeg_device_run() to recover a stalled encode/decode job. The only
existing cancellation is cancel_delayed_work() in the frame-done IRQ
handler, which de-queues a pending work item but does not wait for a
callback that has already started, and it only runs when a frame completes.
When the fd is closed while a job is in flight (the frame-done IRQ has not
fired yet), nothing syncs the worker before mxc_jpeg_release() frees ctx
with kfree() after v4l2_m2m_ctx_release(). A queued or executing
mxc_jpeg_device_run_timeout() can then recover ctx through
container_of(&ctx->task_timer) and dereference it (ctx->mxc_jpeg,
slot_data, dev_warn) after ctx has been freed.
Cancel the worker from mxc_jpeg_stop_streaming(). The cancel cannot live
in mxc_jpeg_release(): mxc_jpeg_device_run() arms the timer while holding
only hw_lock, not the mxc_jpeg->lock mutex that release holds, so a cancel
in release could still race a concurrent mxc_jpeg_device_run() that
re-arms the timer afterwards. mxc_jpeg_stop_streaming() instead runs inside
v4l2_m2m_ctx_release() -> vb2_queue_release(), i.e. after
v4l2_m2m_cancel_job() has set TRANS_ABORT and waited for any in-flight job
to finish (so __v4l2_m2m_try_queue() will not queue and v4l2_m2m_try_run()
will not run any further job for this context, which prevents
mxc_jpeg_device_run() from re-arming the timer) and before the m2m context
is freed. cancel_delayed_work_sync() removes a pending work item and waits
for a running callback, so the worker can no longer race with the
subsequent kfree(). The cancel is placed before the buffer-release loop so
a concurrently running timeout callback cannot race with it over the same
buffers. If the frame-done IRQ canceled a still-pending timer, this cancel
is a no-op; if the timeout callback has already started, it waits for the
callback to finish. The same mxc_jpeg_stop_streaming() call is also
reached from VIDIOC_STREAMOFF, which drains the worker early, although
STREAMOFF itself does not free ctx -- the use-after-free arises only
when the fd is later closed.
This bug was found by static analysis.
Fixes: cfed9632ca8e ("media: imx-jpeg: Add a timeout mechanism for each frame")
Cc: stable@vger.kernel.org
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
---
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index 9e4a813489c0..d85a9d196269 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -1735,6 +1735,8 @@ static void mxc_jpeg_stop_streaming(struct vb2_queue *q)
dev_dbg(ctx->mxc_jpeg->dev, "Stop streaming ctx=%p", ctx);
+ cancel_delayed_work_sync(&ctx->task_timer);
+
/* Release all active buffers */
for (;;) {
if (V4L2_TYPE_IS_OUTPUT(q->type))
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v3] drm/bridge: imx93-mipi-dsi: Fix mode validation
From: Luca Ceresoli @ 2026-06-23 10:41 UTC (permalink / raw)
To: Liu Ying, Luca Ceresoli
Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Dmitry Baryshkov, dri-devel, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <ajjpuroFPI_U2Fw6@raspi>
Hello Liu,
On Mon Jun 22, 2026 at 9:52 AM CEST, Liu Ying wrote:
> On Fri, Jun 19, 2026 at 06:49:55PM +0200, Luca Ceresoli wrote:
>> Hello Liu,
>
> Hi Luca,
>
>>
>> On Fri May 15, 2026 at 8:54 AM CEST, Liu Ying wrote:
>> > i.MX93 MIPI DPHY PLL has limitation for matching with some pixel clock
>> > rates, e.g., the best DPHY PLL frequency is 445.333333MHz for a typical
>> > 1920x1080p@60Hz CEA/DMT display mode with a pixel clock rate running
>> > at 148.5MHz with 4 data lanes + RGB888 pixel in MIPI DSI sync pulse mode,
>> > while the expected PLL frequency is (148.5 * 24) / 4 / 2 MHz = 445.5MHz.
>> > Fortunately, VESA Display Monitor Timing Standard allows +/-0.5% pixel
>> > clock rate deviation for timings. So, for those display modes read
>> > from EDID through a bridge with DRM_BRIDGE_OP_DETECT and DRM_BRIDGE_OP_EDID
>> > operation bit masks set, pixel clock rate could be adjusted to match
>> > with the PLL frequency(for the above example, the pixel clock rate is
>> > adjusted to be 148.444444MHz with about -0.03% deviation from the 148.5MHz
>> > nominal rate so that the adjusted rate matches with the 445.333333MHz PLL
>> > frequency).
>> >
>> > Instead of checking the last bridge's operation bit masks against
>> > DRM_BRIDGE_OP_DETECT and DRM_BRIDGE_OP_EDID to determine if allowing
>> > +/-0.5% pixel clock rate deviation, check any bridge after this bridge,
>> > because the last bridge is usually a display connector bridge without
>> > any operation bit mask when the clock rate deviation is allowed.
>> >
>> > Fixes: ce62f8ea7e3f ("drm/bridge: imx: Add i.MX93 MIPI DSI support")
>> > Fixes: 5849eff7f067 ("drm/bridge: imx93-mipi-dsi: use drm_bridge_chain_get_last_bridge()")
>> > Reviewed-by: Frank Li <Frank.Li@nxp.com>
>> > Signed-off-by: Liu Ying <victor.liu@nxp.com>
>>
>> I'm perhaps not the most qualified to review this change, but let me try.
>
> Thanks for your review.
>
>>
>> > --- a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
>> > +++ b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
>> > @@ -489,25 +489,43 @@ static int imx93_dsi_get_phy_configure_opts(struct imx93_dsi *dsi,
>> > return 0;
>> > }
>> >
>> > +static inline struct drm_bridge *
>> > +imx93_dsi_get_next_bridge_in_chain(struct drm_bridge *bridge)
>> > +{
>> > + struct drm_bridge *next = drm_bridge_get_next_bridge(bridge);
>> > +
>> > + drm_bridge_put(bridge);
>> > +
>> > + return next;
>> > +}
>> > +
>> > static enum drm_mode_status
>> > imx93_dsi_validate_mode(struct imx93_dsi *dsi, const struct drm_display_mode *mode)
>> > {
>> > struct drm_bridge *dmd_bridge = dw_mipi_dsi_get_bridge(dsi->dmd);
>> > - struct drm_bridge *last_bridge __free(drm_bridge_put) =
>> > - drm_bridge_chain_get_last_bridge(dmd_bridge->encoder);
>> > + struct drm_bridge *bridge;
>> >
>> > - if ((last_bridge->ops & DRM_BRIDGE_OP_DETECT) &&
>> > - (last_bridge->ops & DRM_BRIDGE_OP_EDID)) {
>> > - unsigned long pixel_clock_rate = mode->clock * 1000;
>> > - unsigned long rounded_rate;
>> > + for (bridge = drm_bridge_get_next_bridge(dmd_bridge);
>> > + bridge;
>> > + bridge = imx93_dsi_get_next_bridge_in_chain(bridge)) {
>> > + if ((bridge->ops & DRM_BRIDGE_OP_DETECT) &&
>> > + (bridge->ops & DRM_BRIDGE_OP_EDID)) {
>> > + unsigned long pixel_clock_rate = mode->clock * 1000;
>> > + unsigned long rounded_rate;
>> >
>> > - /* Allow +/-0.5% pixel clock rate deviation */
>> > - rounded_rate = clk_round_rate(dsi->clk_pixel, pixel_clock_rate);
>> > - if (rounded_rate < pixel_clock_rate * 995 / 1000 ||
>> > - rounded_rate > pixel_clock_rate * 1005 / 1000) {
>> > - dev_dbg(dsi->dev, "failed to round clock for mode " DRM_MODE_FMT "\n",
>> > - DRM_MODE_ARG(mode));
>> > - return MODE_NOCLOCK;
>> > + /* Allow +/-0.5% pixel clock rate deviation */
>> > + rounded_rate = clk_round_rate(dsi->clk_pixel, pixel_clock_rate);
>> > + if (rounded_rate < pixel_clock_rate * 995 / 1000 ||
>> > + rounded_rate > pixel_clock_rate * 1005 / 1000) {
>> > + dev_dbg(dsi->dev,
>> > + "failed to round clock for mode " DRM_MODE_FMT "\n",
>> > + DRM_MODE_ARG(mode));
>> > + drm_bridge_put(bridge);
>> > + return MODE_NOCLOCK;
>> > + }
>> > +
>> > + drm_bridge_put(bridge);
>> > + break;
>> > }
>> > }
>>
>> Is this logic specific to the imx93 MIPI DSI host only? Or should it be
>> made generic for all dw-hdmi users, or even every DSI host?
>
> I think it's kind of specific to the i.MX93 MIPI DSI host only, because
> 1) the i.MX93 MIPI DPHY PLL(integrated into i.MX93 MIPI DPHY IP) supports
> the best DPHY PLL frequency @445.333333MHz for the typical 1920x1080p@60Hz
> display mode, which is lower than the expected/nominal frequency @445.5MHz
> and 2) the generic DW MIPI DSI driver(dw-mipi-dsi.c) is PHY-agnostic, which
> means vendors may attach different MIPI DPHY IPs to the common MIPI DSI host
> IP and likely there would be no frequency mismatch between the pixel clock
> and the PLL like i.MX93 has.
I see, OK, thanks for the clarification!
>> Also, iterating over the bridge chain is not very clean. I'm working on
>> bridge hotplug (not upstream yet) and bad things would happen if a bridge
>> were hot-unplugged during this loop.
>
> The iterating is essentially the same to drm_for_each_bridge_in_chain_from()
> except that bridge_chain_mutex is not taken(since it's already taken) and
> the starting bridge is fixed to be the next bridge. A few bridge core APIs
> like drm_bridge_chain_mode_valid() call drm_for_each_bridge_in_chain_from().
> So, the iterating looks clean to me and I'm not aware of any bad things which
> would happen when bridge hotplug is considered.
I had missed this is called from drm_bridge_chain_mode_valid(), which
already takes the bridge_chain_mutex thanks to
drm_for_each_bridge_in_chain_from().
So that means this loop is safe, but it would be nice to add a comment to
make it clear to future readers. E.g. "/* we are called by
drm_bridge_chain_mode_valid(), so the bridge_chain_mutex is locked */".
Still I'm not a fan of having a loop over the bridge chain (this function)
inside another loop over the same bridge chain (in
drm_bridge_chain_mode_valid(). And even more I'm not a fan of drivers
walking around the bridge chain on their own, IMO the core (perhaps
drm_bridge.c in this case) should to the loops . However this is a general
concern, it happens also elsewhere, and I have no immediate proposal to
improve this, so don't consider it as a blocker for this patch.
>> If the core did this sort of algorithm
>> it would be able to be more robust.
>
> Is the core dw-mipi-dsi.c?
> If yes, do you think it's worth doing that even if the frequency mismatch
> between the pixel clock and the PLL is kind of specific to the i.MX93 MIPI
> DSI host?
>
>>
>> Finally, out of my utter ignorance on the subject, is the VESA +/-0.5%
>> margin generic enough that this driver can always rely on it?
>
> I see several upstream drivers rely on it, see "git grep '0.5%' drivers/gpu/"
> output. And every display mode allows -/+ 0.5% pixel clock rate deviation
> according to VESA Display Monitor Timing Standard [1], though [1] is a found
> by a random Google search.
>
> [1] https://glenwing.github.io/docs/VESA-DMT-1.13.pdf
As I said I'm quite ignorance about this aspect, so I asked to better
understand. In reply to another part fo the thread: no, I don't have a
specific concern if this is the common practice.
Luca
--
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH] ASoC: rockchip: rockchip_sai: Hand over hclk control exclusively to Runtime PM
From: Bui Duc Phuc @ 2026-06-23 10:53 UTC (permalink / raw)
To: Mark Brown
Cc: Heiko Stuebner, Liam Girdwood, Nicolas Frattaroli,
Krzysztof Kozlowski, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-rockchip, linux-arm-kernel, linux-kernel
In-Reply-To: <229ba136-66eb-4a30-a316-58377836b4dc@sirena.org.uk>
Hi Mark,
Thank you for your review.
> > 1 Reverting back to devm_clk_get() to remove the implicit devres
> > enable/disable behavior.
> > 2 Manually enabling and disabling hclk explicitly only around the
> > early register access before Runtime PM takes over.
> > 3 Dropping the stray clk_disable_unprepare() at the end of probe()
> > so Runtime PM solely owns hclk afterward.
>
> Note that runtime PM can be disabled at build time so we might not have
> runtime PM at all...
>
Thanks for pointing this out. You're right that with !CONFIG_PM, the
driver only relies on the
two manual calls to rokchip_sai_runtime_resume() / suspend(), so hclk
stays enabled the
whole time. I understand this is unvavoidable in that configuration,
throgh, since there's no
Runtime PM to re-enable the clock when it's needed.
I'll update the commit message to reflect that the driver uses a
combination of Runtime PM
and explicit manual enable/disable, rather than relying on Runtime PM alone.
> > Links:
> > 1 This change is based on the discussion around manual hclk handing during probe(),
> > as raised by Krysztof:
> > https://lore.kernel.org/all/20e4754b-ea9a-404d-b529-ec44a7263cbf@kernel.org/#t
> > 2 Background for the earlier devm_clk_get_enbabled() conversion:
> > https://lore.kernel.org/all/2818018.CQOukoFCf9@workhorse/
>
> > An alternative approach would be use devm_regmap_init_mmio_clk() and let regmap
> > manage clock enablement around register accesses. If preferred, I can rework the
> > driver accordingly.
>
> > - sai->hclk = devm_clk_get_enabled(&pdev->dev, "hclk");
> > + sai->hclk = devm_clk_get(&pdev->dev, "hclk");
> > if (IS_ERR(sai->hclk))
> > return dev_err_probe(&pdev->dev, PTR_ERR(sai->hclk),
> > "Failed to get hclk\n");
> >
> > + ret = clk_prepare_enable(sai->hclk);
> > + if (ret)
> > + return dev_err_probe(&pdev->dev, ret, "Failed to enable hclk\n");
> > +
>
> > @@ -1482,8 +1492,6 @@ static int rockchip_sai_probe(struct platform_device *pdev)
> > pm_runtime_use_autosuspend(&pdev->dev);
> > pm_runtime_put(&pdev->dev);
> >
> > - clk_disable_unprepare(sai->hclk);
> > -
> > return 0;
>
> Are you sure that the runtime PM state there is such that it knows a
> reference is held? The driver used pm_runtime_get_noresume() so the
> device didn't have RPM_ACTIVE set I think?
You are right, pm_runtime_get_noresume() doesn't set RPM_ACTIVE. I
think we need to add
pm_runtime_set_active() before pm_runtime_enable(). Otherwise, with CONFIG_PM,
the pm_runtime_put() at the end of probe() might skip the suspend,
since the core still considers
the device suspended .
>
> The runtime PM API really is a miserable collection of landmines :(
Yeah, plenty of landmines indeed :(
I checked, and rockchip_spdif.c does use devm_regmap_init_mmio_clk() for hclk,
rather than wrapping every register access in pm_runtime_get_sync() /
pm_runtime_put()
the way rockchip_sai does.
Best regards,
Phuc
^ permalink raw reply
* Re: [PATCH net v2] net: airoha: Add retry mechanism to airoha_qdma_set_trtcm_param()
From: Simon Horman @ 2026-06-23 10:53 UTC (permalink / raw)
To: lorenzo
Cc: Simon Horman, andrew+netdev, davem, edumazet, kuba, pabeni,
leto.liu, linux-arm-kernel, linux-mediatek, netdev, brown.huang
In-Reply-To: <20260622-airoha_qdma_set_trtcm_param-retry-fix-v2-1-95a83ac99dbd@kernel.org>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
Simon says: I'd appreciate it if you could look over the first two issues
flagged below in the context of this patch. While the third
and final issue looks like it is in possible separate follow-up
territory.
---
net: airoha: Add retry mechanism to airoha_qdma_set_trtcm_param()
This patch introduces a retry loop to airoha_qdma_set_trtcm_param() to mitigate
bus timeouts when configuring QDMA parameters. It attempts to verify that the
configuration is correctly applied to the hardware.
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 3370c3df7c107..bb5c0599a4eed 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -2673,14 +2673,30 @@ static int airoha_qdma_set_trtcm_param(struct airoha_qdma *qdma, int channel,
> FIELD_PREP(TRTCM_METER_GROUP_MASK, group) |
> FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) |
> FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode);
> + int i;
>
> - airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val);
> - airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config);
> + for (i = 0; i < 100; i++) {
> + u32 data;
>
> - return read_poll_timeout(airoha_qdma_rr, val,
> - val & TRTCM_PARAM_RW_DONE_MASK,
> - USEC_PER_MSEC, 10 * USEC_PER_MSEC, true,
> - qdma, REG_TRTCM_CFG_PARAM(addr));
> + airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val);
> + wmb();
> + airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config);
> +
> + if (read_poll_timeout(airoha_qdma_rr, data,
> + data & TRTCM_PARAM_RW_DONE_MASK,
> + USEC_PER_MSEC, 10 * USEC_PER_MSEC,
> + true, qdma, REG_TRTCM_CFG_PARAM(addr)))
> + return -ETIMEDOUT;
[Severity: High]
If a bus timeout causes the write phase's read_poll_timeout() in
airoha_qdma_set_trtcm_param() to fail, this immediately returns -ETIMEDOUT,
aborting the 100-iteration retry loop.
Doesn't this defeat the mitigation?
> +
> + if (airoha_qdma_get_trtcm_param(qdma, channel, addr, param,
> + mode, &data, NULL))
> + continue;
[Severity: High]
If airoha_qdma_get_trtcm_param() times out during the verification phase, it
indicates the hardware hasn't finished the read command (DONE bit is still 0).
The continue statement then immediately starts the next iteration, writing new
commands to DATA_LOW and CFG_PARAM.
Can writing to command registers while the hardware state machine is actively
busy violate hardware protocols and lead to unrecoverable lockups?
> +
> + if (data == val)
> + return 0;
[Severity: High]
This isn't a bug introduced by this patch, but if the bus drops the command
write to REG_TRTCM_CFG_PARAM, the hardware never executes the command and the
TRTCM_PARAM_RW_DONE_MASK bit remains set from the previous operation.
Consequently, read_poll_timeout() returns an immediate false success.
If both the set and get command writes are dropped by the bus, the get
operation will read back the newly written DATA_LOW register value.
Will the data == val check evaluate to true and falsely report success without
the hardware ever processing the configuration?
> + }
> +
> + return -EBUSY;
> }
>
[ ... ]
> static int airoha_qdma_set_trtcm_config(struct airoha_qdma *qdma, int channel,
> u32 addr, enum trtcm_mode_type mode,
> bool enable, u32 enable_mask)
> {
> u32 val;
>
> if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE,
> mode, &val, NULL))
> return -EINVAL;
[Severity: High]
Standalone calls to airoha_qdma_get_trtcm_param(), like this one in
airoha_qdma_set_trtcm_config(), lack a retry loop entirely.
Does this leave read-modify-write cycles fully vulnerable to the same bus
timeouts the patch attempts to mitigate?
[Severity: High]
This isn't a bug introduced by this patch, but the patch mitigates bus
timeouts in airoha_qdma_set_trtcm_param() while entirely missing
airoha_qdma_set_rl_param().
The latter performs the exact same write-and-poll sequence on identical QDMA
configuration registers:
drivers/net/ethernet/airoha/airoha_eth.c:airoha_qdma_set_rl_param() {
...
return read_poll_timeout(..., val & RATE_LIMIT_PARAM_RW_DONE_MASK, ...);
}
If bus timeouts affect QDMA access broadly as stated in the commit message, are
the rate-limiting configuration paths randomly vulnerable to the same failures?
[Severity: High]
This isn't a bug introduced by this patch, but in airoha_tc_remove_htb_queue(),
hardware teardown incorrectly uses queue + 1 instead of queue:
drivers/net/ethernet/airoha/airoha_eth.c:airoha_tc_remove_htb_queue() {
...
airoha_qdma_set_tx_rate_limit(netdev, queue + 1, 0, 0);
...
}
Does this leave the removed queue's hardware limits permanently active
(resource leak) and inadvertently disable the rate limits for queue + 1,
corrupting the QoS state of another active channel?
^ permalink raw reply
* [PATCH v2 00/12] Add thermal management support for sama7d65
From: Varshini Rajendran @ 2026-06-23 10:59 UTC (permalink / raw)
To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
linux-iio, devicetree, linux-arm-kernel, linux-kernel
Cc: varshini.rajendran
Apologies for the significant delay in following up this series.
Thank you for your patience and the earlier reviews.
This v2 reworks the series based on the feedback received on v1.
The thermal management system of sama7d65 includes:
- Temperature sensor as a part of ADC channel
- Temperature calibration data retrieved from the OTP memory for
improved accuracy of the readings
- DVFS implementation
- Thermal system with DVFS as cooling cell.
This patch series adds support for the following:
- Tag-based packet lookup for the NVMEM OTPC driver while preserving
backward compatibility with existing ID-based access
- Temperature calibration layout handling in the ADC driver to support
different SoC-specific calibration data formats
- ADC driver adaptation for sama7d65
- DT nodes for OTP, ADC, temperature sensor, and thermal zones for
sama7d65
Changes in v2:
- Preserved backward compatibility with ID-based packet lookup to
avoid breaking existing users
- Removed sama7g5 DTS changes (not needed with backward compatible
driver - will be sent later to update to the new access method)
- Preserved the packet data structure returned not to break the
consumers
- Reworked ADC driver to use a calibration layout structure instead of
hardcoded indexes, for scalability
- Fixed kernel-doc Return section
- Removed stray blank line in mchp_otpc_read()
- Removed unnecessary UL suffix in writel_relaxed()
- Dropped unused packet types
- Fixed stray spaces before exclamation marks in error messages
- Added ASCII representation to TAG macro definition
- Removed odd MAX enum with trailing comma and refactored
- Moved DTS patches to the end of series
- Used cleanup.h helpers for NVMEM data buffer handling in ADC driver
- Combined multiple v1 patches into logical units
- Used correct subject prefixes for dt-bindings patches
- Used fixed-layout NVMEM syntax for sama7d65 DTS and binding
instead of deprecated syntax
- Added cpu-supply linkage for proper DVFS voltage scaling
- Updated stale stride=4 comment in dt-bindings header
Link to v1: https://lore.kernel.org/linux-arm-kernel/20250804100219.63325-1-varshini.rajendran@microchip.com/
Varshini Rajendran (12):
dt-bindings: iio: adc: at91-sama5d2: document sama7d65
iio: adc: at91-sama5d2_adc: rework temp calibration layout handling
iio: adc: at91-sama5d2_adc: adapt the driver for sama7d65
dt-bindings: nvmem: microchip,sama7g5-otpc: add sama7d65 and dt node
example
nvmem: microchip-otpc: add tag-based packet lookup
ARM: dts: microchip: sama7d65: add cpu opps
ARM: dts: microchip: sama7d65: Add ADC node
ARM: dts: microchip: sama7d65_curiosity: Enable ADC, DVFS
ARM: dts: microchip: sama7d65: add otpc node
ARM: dts: microchip: sama7d65: add cells for temperature calibration
ARM: dts: microchip: sama7d65: add temperature sensor
ARM: dts: microchip: sama7d65: add thermal zones node
.../bindings/iio/adc/atmel,sama5d2-adc.yaml | 1 +
.../nvmem/microchip,sama7g5-otpc.yaml | 28 +++-
.../dts/microchip/at91-sama7d65_curiosity.dts | 27 ++++
arch/arm/boot/dts/microchip/sama7d65.dtsi | 132 ++++++++++++++++
drivers/iio/adc/at91-sama5d2_adc.c | 116 ++++++++++----
drivers/nvmem/microchip-otpc.c | 142 ++++++++++++++++--
.../nvmem/microchip,sama7g5-otpc.h | 4 +-
7 files changed, 409 insertions(+), 41 deletions(-)
--
2.34.1
^ permalink raw reply
* Re: [PATCH v3 4/4] clk: rockchip: rk3588: add GATE_GRF clocks for I2S MCLK output to IO
From: Diederik de Haas @ 2026-06-23 10:59 UTC (permalink / raw)
To: Daniele Briguglio, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: Nicolas Frattaroli, linux-clk, devicetree, linux-arm-kernel,
linux-rockchip, linux-kernel, Ricardo Pardini
In-Reply-To: <20260320-rk3588-mclk-gate-grf-v3-4-980338eacd2c@superkali.me>
Hi,
On Fri Mar 20, 2026 at 11:34 AM CET, Daniele Briguglio wrote:
> The I2S MCLK outputs on RK3588 are gated by bits in the SYS_GRF
> register SOC_CON6 (offset 0x318). These gates control whether the
> internal CRU MCLK signals reach the external IO pins connected to
> audio codecs.
>
> The kernel should explicitly manage these gates so that audio
> functionality does not depend on bootloader register state. This is
> analogous to what was done for RK3576 SAI MCLK outputs [1].
>
> Register the SYS_GRF as an auxiliary GRF with grf_type_sys in the
> early clock init, and add GATE_GRF entries for all four I2S MCLK
> output gates:
>
> - I2S0_8CH_MCLKOUT_TO_IO (bit 0)
> - I2S1_8CH_MCLKOUT_TO_IO (bit 1)
> - I2S2_2CH_MCLKOUT_TO_IO (bit 2)
> - I2S3_2CH_MCLKOUT_TO_IO (bit 7)
>
> Board DTS files that need MCLK on an IO pin can reference these
> clocks, e.g.:
>
> clocks = <&cru I2S0_8CH_MCLKOUT_TO_IO>;
>
> Tested on the Youyeetoo YY3588 (RK3588) with an ES8388 codec on I2S0.
Doesn't this break audio on a lot of RK3588 based boards?
I have a kernel with this patch set and since then analog audio on my NanoPC-T6
LTS and my WIP NanoPC-T6 Plus stopped working.
Until I did s/I2S0_8CH_MCLKOUT/I2S0_8CH_MCLKOUT_TO_IO/ in my dts[i] files.
And I wouldn't be surprised if the same thing applies to other RK3588 based
boards? The same dtb file with a 7.1 kernel, without this patch set, works.
Cheers,
Diederik
> [1] https://lore.kernel.org/r/20250305-rk3576-sai-v1-2-64e6cf863e9a@collabora.com/
>
> Reviewed-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> Tested-by: Ricardo Pardini <ricardo@pardini.net>
> Signed-off-by: Daniele Briguglio <hello@superkali.me>
> ---
> drivers/clk/rockchip/clk-rk3588.c | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
> index 1694223f4f84..2cc85fb5b2cc 100644
> --- a/drivers/clk/rockchip/clk-rk3588.c
> +++ b/drivers/clk/rockchip/clk-rk3588.c
> @@ -5,11 +5,14 @@
> */
>
> #include <linux/clk-provider.h>
> +#include <linux/mfd/syscon.h>
> #include <linux/of.h>
> +#include <linux/slab.h>
> #include <linux/of_address.h>
> #include <linux/platform_device.h>
> #include <linux/syscore_ops.h>
> #include <dt-bindings/clock/rockchip,rk3588-cru.h>
> +#include <soc/rockchip/rk3588_grf.h>
> #include "clk.h"
>
> #define RK3588_GRF_SOC_STATUS0 0x600
> @@ -892,6 +895,8 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
> RK3588_CLKGATE_CON(8), 0, GFLAGS),
> MUX(I2S2_2CH_MCLKOUT, "i2s2_2ch_mclkout", i2s2_2ch_mclkout_p, CLK_SET_RATE_PARENT,
> RK3588_CLKSEL_CON(30), 2, 1, MFLAGS),
> + GATE_GRF(I2S2_2CH_MCLKOUT_TO_IO, "i2s2_2ch_mclkout_to_io", "i2s2_2ch_mclkout",
> + 0, RK3588_SYSGRF_SOC_CON6, 2, GFLAGS, grf_type_sys),
>
> COMPOSITE(CLK_I2S3_2CH_SRC, "clk_i2s3_2ch_src", gpll_aupll_p, 0,
> RK3588_CLKSEL_CON(30), 8, 1, MFLAGS, 3, 5, DFLAGS,
> @@ -907,6 +912,8 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
> RK3588_CLKGATE_CON(8), 4, GFLAGS),
> MUX(I2S3_2CH_MCLKOUT, "i2s3_2ch_mclkout", i2s3_2ch_mclkout_p, CLK_SET_RATE_PARENT,
> RK3588_CLKSEL_CON(32), 2, 1, MFLAGS),
> + GATE_GRF(I2S3_2CH_MCLKOUT_TO_IO, "i2s3_2ch_mclkout_to_io", "i2s3_2ch_mclkout",
> + 0, RK3588_SYSGRF_SOC_CON6, 7, GFLAGS, grf_type_sys),
> GATE(PCLK_ACDCDIG, "pclk_acdcdig", "pclk_audio_root", 0,
> RK3588_CLKGATE_CON(7), 11, GFLAGS),
> GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_audio_root", 0,
> @@ -935,6 +942,8 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
> RK3588_CLKGATE_CON(7), 10, GFLAGS),
> MUX(I2S0_8CH_MCLKOUT, "i2s0_8ch_mclkout", i2s0_8ch_mclkout_p, CLK_SET_RATE_PARENT,
> RK3588_CLKSEL_CON(28), 2, 2, MFLAGS),
> + GATE_GRF(I2S0_8CH_MCLKOUT_TO_IO, "i2s0_8ch_mclkout_to_io", "i2s0_8ch_mclkout",
> + 0, RK3588_SYSGRF_SOC_CON6, 0, GFLAGS, grf_type_sys),
>
> GATE(HCLK_PDM1, "hclk_pdm1", "hclk_audio_root", 0,
> RK3588_CLKGATE_CON(9), 6, GFLAGS),
> @@ -2220,6 +2229,8 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
> RK3588_PMU_CLKGATE_CON(2), 13, GFLAGS),
> MUX(I2S1_8CH_MCLKOUT, "i2s1_8ch_mclkout", i2s1_8ch_mclkout_p, CLK_SET_RATE_PARENT,
> RK3588_PMU_CLKSEL_CON(9), 2, 2, MFLAGS),
> + GATE_GRF(I2S1_8CH_MCLKOUT_TO_IO, "i2s1_8ch_mclkout_to_io", "i2s1_8ch_mclkout",
> + 0, RK3588_SYSGRF_SOC_CON6, 1, GFLAGS, grf_type_sys),
> GATE(PCLK_PMU1, "pclk_pmu1", "pclk_pmu0_root", CLK_IS_CRITICAL,
> RK3588_PMU_CLKGATE_CON(1), 0, GFLAGS),
> GATE(CLK_DDR_FAIL_SAFE, "clk_ddr_fail_safe", "clk_pmu0", CLK_IGNORE_UNUSED,
> @@ -2439,6 +2450,8 @@ static struct rockchip_clk_branch rk3588_clk_branches[] = {
> static void __init rk3588_clk_early_init(struct device_node *np)
> {
> struct rockchip_clk_provider *ctx;
> + struct rockchip_aux_grf *sys_grf_e;
> + struct regmap *sys_grf;
> unsigned long clk_nr_clks, max_clk_id1, max_clk_id2;
> void __iomem *reg_base;
>
> @@ -2479,6 +2492,17 @@ static void __init rk3588_clk_early_init(struct device_node *np)
> &rk3588_cpub1clk_data, rk3588_cpub1clk_rates,
> ARRAY_SIZE(rk3588_cpub1clk_rates));
>
> + /* Register SYS_GRF for I2S MCLK output to IO gate clocks */
> + sys_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3588-sys-grf");
> + if (!IS_ERR(sys_grf)) {
> + sys_grf_e = kzalloc_obj(*sys_grf_e);
> + if (sys_grf_e) {
> + sys_grf_e->grf = sys_grf;
> + sys_grf_e->type = grf_type_sys;
> + hash_add(ctx->aux_grf_table, &sys_grf_e->node, grf_type_sys);
> + }
> + }
> +
> rockchip_clk_register_branches(ctx, rk3588_early_clk_branches,
> ARRAY_SIZE(rk3588_early_clk_branches));
>
^ permalink raw reply
* [PATCH v2 01/12] dt-bindings: iio: adc: at91-sama5d2: document sama7d65
From: Varshini Rajendran @ 2026-06-23 10:59 UTC (permalink / raw)
To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
linux-iio, devicetree, linux-arm-kernel, linux-kernel
Cc: varshini.rajendran, Krzysztof Kozlowski
In-Reply-To: <20260623105944.128840-1-varshini.rajendran@microchip.com>
Add dt-binding documentation for sama7d65 ADC.
Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml b/Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml
index 4817b840977a..e8a65fdcd018 100644
--- a/Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml
@@ -15,6 +15,7 @@ properties:
- atmel,sama5d2-adc
- microchip,sam9x60-adc
- microchip,sama7g5-adc
+ - microchip,sama7d65-adc
reg:
maxItems: 1
--
2.34.1
^ permalink raw reply related
* [PATCH v2 02/12] iio: adc: at91-sama5d2_adc: rework temp calibration layout handling
From: Varshini Rajendran @ 2026-06-23 10:59 UTC (permalink / raw)
To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
linux-iio, devicetree, linux-arm-kernel, linux-kernel
Cc: varshini.rajendran
In-Reply-To: <20260623105944.128840-1-varshini.rajendran@microchip.com>
Extend support to handle different temperature calibration layouts.
Add a temperature calibration data layout structure to describe indexes
of the factors P1, P4, P6, tag, minimum length of the packet and the
scaling factors for P1 (mul, div) which are SoC-specific instead of the
older non scalable id structure. This helps handle the differences in the
same function flow and prepare the calibration data to be applied. Add
additional condition to validate the calibration data read from the
NVMEM cell using the TAG of the packet.
Use cleanup helpers for NVMEM data buffer wherever applicable.
Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
drivers/iio/adc/at91-sama5d2_adc.c | 85 ++++++++++++++++++++----------
1 file changed, 58 insertions(+), 27 deletions(-)
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 255970b2e747..b569d175f4c3 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -445,6 +445,28 @@ static const struct at91_adc_reg_layout sama7g5_layout = {
#define at91_adc_writel(st, reg, val) \
writel_relaxed(val, (st)->base + (st)->soc_info.platform->layout->reg)
+#define AT91_TEMP_CALIB_TAG_ACST 0x41435354
+
+/**
+ * struct at91_adc_temp_calib_layout - temperature calibration packet layout
+ * @tag_idx: index of Packet tag in the NVMEM cell buffer
+ * @p1_idx: index of FT1_TEMP, equivalent to P1 in the NVMEM cell buffer
+ * @p4_idx: index of FT1_VPAT, equivalent to P4 in the NVMEM cell buffer
+ * @p6_idx: index of FT2_VBG, equivalent to P6 in the NVMEM cell buffer
+ * @min_len: minimum number of u32 words expected in the NVMEM cell buffer
+ * @p1_mul: multiplier applied to P1 to convert to millicelcius
+ * @p1_div: divider applied to P1 to convert to millicelcius
+ */
+struct at91_adc_temp_calib_layout {
+ unsigned int tag_idx;
+ unsigned int p1_idx;
+ unsigned int p4_idx;
+ unsigned int p6_idx;
+ unsigned int min_len;
+ unsigned int p1_mul;
+ unsigned int p1_div;
+};
+
/**
* struct at91_adc_platform - at91-sama5d2 platform information struct
* @layout: pointer to the reg layout struct
@@ -464,6 +486,7 @@ static const struct at91_adc_reg_layout sama7g5_layout = {
* @chan_realbits: realbits for registered channels
* @temp_chan: temperature channel index
* @temp_sensor: temperature sensor supported
+ * @temp_calib_layout: temperature calibration packet layout
*/
struct at91_adc_platform {
const struct at91_adc_reg_layout *layout;
@@ -481,6 +504,7 @@ struct at91_adc_platform {
unsigned int chan_realbits;
unsigned int temp_chan;
bool temp_sensor;
+ const struct at91_adc_temp_calib_layout *temp_calib_layout;
};
/**
@@ -496,18 +520,14 @@ struct at91_adc_temp_sensor_clb {
u32 p6;
};
-/**
- * enum at91_adc_ts_clb_idx - calibration indexes in NVMEM buffer
- * @AT91_ADC_TS_CLB_IDX_P1: index for P1
- * @AT91_ADC_TS_CLB_IDX_P4: index for P4
- * @AT91_ADC_TS_CLB_IDX_P6: index for P6
- * @AT91_ADC_TS_CLB_IDX_MAX: max index for temperature calibration packet in OTP
- */
-enum at91_adc_ts_clb_idx {
- AT91_ADC_TS_CLB_IDX_P1 = 2,
- AT91_ADC_TS_CLB_IDX_P4 = 5,
- AT91_ADC_TS_CLB_IDX_P6 = 7,
- AT91_ADC_TS_CLB_IDX_MAX = 19,
+static const struct at91_adc_temp_calib_layout sama7g5_temp_calib = {
+ .tag_idx = 1,
+ .p1_idx = 2,
+ .p4_idx = 5,
+ .p6_idx = 7,
+ .min_len = 19,
+ .p1_mul = 1000,
+ .p1_div = 1,
};
/* Temperature sensor calibration - Vtemp voltage sensitivity to temperature. */
@@ -745,6 +765,7 @@ static const struct at91_adc_platform sama7g5_platform = {
.chan_realbits = 16,
.temp_sensor = true,
.temp_chan = AT91_SAMA7G5_ADC_TEMP_CHANNEL,
+ .temp_calib_layout = &sama7g5_temp_calib,
};
static int at91_adc_chan_xlate(struct iio_dev *indio_dev, int chan)
@@ -2251,13 +2272,19 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st,
{
struct at91_adc_temp_sensor_clb *clb = &st->soc_info.temp_sensor_clb;
struct nvmem_cell *temp_calib;
- u32 *buf;
+ const struct at91_adc_temp_calib_layout *layout;
+ void *cell_data;
+ u32 *buf __free(kfree) = NULL;
size_t len;
int ret = 0;
if (!st->soc_info.platform->temp_sensor)
return 0;
+ layout = st->soc_info.platform->temp_calib_layout;
+ if (!layout || !layout->p1_div)
+ return -EINVAL;
+
/* Get the calibration data from NVMEM. */
temp_calib = nvmem_cell_get(dev, "temperature_calib");
if (IS_ERR(temp_calib)) {
@@ -2267,31 +2294,35 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st,
return ret;
}
- buf = nvmem_cell_read(temp_calib, &len);
+ cell_data = nvmem_cell_read(temp_calib, &len);
nvmem_cell_put(temp_calib);
- if (IS_ERR(buf)) {
+ if (IS_ERR(cell_data)) {
dev_err(dev, "Failed to read calibration data!\n");
- return PTR_ERR(buf);
+ return PTR_ERR(cell_data);
}
- if (len < AT91_ADC_TS_CLB_IDX_MAX * 4) {
+
+ buf = cell_data;
+
+ if (len < layout->min_len * sizeof(*buf) ||
+ buf[layout->tag_idx] != AT91_TEMP_CALIB_TAG_ACST) {
dev_err(dev, "Invalid calibration data!\n");
- ret = -EINVAL;
- goto free_buf;
+ return -EINVAL;
}
/* Store calibration data for later use. */
- clb->p1 = buf[AT91_ADC_TS_CLB_IDX_P1];
- clb->p4 = buf[AT91_ADC_TS_CLB_IDX_P4];
- clb->p6 = buf[AT91_ADC_TS_CLB_IDX_P6];
+ clb->p1 = buf[layout->p1_idx];
+ clb->p4 = buf[layout->p4_idx];
+ clb->p6 = buf[layout->p6_idx];
/*
- * We prepare here the conversion to milli to avoid doing it on hotpath.
+ * Here we prepare the conversion to milli to avoid doing it on hotpath.
+ * The p1 value is multiplied and divided with a scaling factor as per
+ * the SoC storage format described by per-platform calibration layout.
*/
- clb->p1 = clb->p1 * 1000;
+ clb->p1 *= layout->p1_mul;
+ clb->p1 /= layout->p1_div;
-free_buf:
- kfree(buf);
- return ret;
+ return 0;
}
static int at91_adc_probe(struct platform_device *pdev)
--
2.34.1
^ permalink raw reply related
* [PATCH v2 03/12] iio: adc: at91-sama5d2_adc: adapt the driver for sama7d65
From: Varshini Rajendran @ 2026-06-23 10:59 UTC (permalink / raw)
To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
linux-iio, devicetree, linux-arm-kernel, linux-kernel
Cc: varshini.rajendran
In-Reply-To: <20260623105944.128840-1-varshini.rajendran@microchip.com>
Add support for sama7d65 ADC. The differences are highlighted with the
compatible. The calibration data layout is the main difference.
Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
drivers/iio/adc/at91-sama5d2_adc.c | 31 ++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index b569d175f4c3..237d339f342a 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -530,6 +530,16 @@ static const struct at91_adc_temp_calib_layout sama7g5_temp_calib = {
.p1_div = 1,
};
+static const struct at91_adc_temp_calib_layout sama7d65_temp_calib = {
+ .tag_idx = 1,
+ .p1_idx = 3,
+ .p4_idx = 2,
+ .p6_idx = 5,
+ .min_len = 11,
+ .p1_mul = 1,
+ .p1_div = 1000,
+};
+
/* Temperature sensor calibration - Vtemp voltage sensitivity to temperature. */
#define AT91_ADC_TS_VTEMP_DT (2080U)
@@ -768,6 +778,24 @@ static const struct at91_adc_platform sama7g5_platform = {
.temp_calib_layout = &sama7g5_temp_calib,
};
+static const struct at91_adc_platform sama7d65_platform = {
+ .layout = &sama7g5_layout,
+ .adc_channels = &at91_sama7g5_adc_channels,
+ .nr_channels = AT91_SAMA7G5_SINGLE_CHAN_CNT +
+ AT91_SAMA7G5_DIFF_CHAN_CNT +
+ AT91_SAMA7G5_TEMP_CHAN_CNT,
+ .max_channels = ARRAY_SIZE(at91_sama7g5_adc_channels),
+ .max_index = AT91_SAMA7G5_MAX_CHAN_IDX,
+ .hw_trig_cnt = AT91_SAMA7G5_HW_TRIG_CNT,
+ .osr_mask = GENMASK(18, 16),
+ .oversampling_avail = { 1, 4, 16, 64, 256, },
+ .oversampling_avail_no = 5,
+ .chan_realbits = 16,
+ .temp_sensor = true,
+ .temp_chan = AT91_SAMA7G5_ADC_TEMP_CHANNEL,
+ .temp_calib_layout = &sama7d65_temp_calib,
+};
+
static int at91_adc_chan_xlate(struct iio_dev *indio_dev, int chan)
{
int i;
@@ -2638,6 +2666,9 @@ static const struct of_device_id at91_adc_dt_match[] = {
}, {
.compatible = "microchip,sama7g5-adc",
.data = (const void *)&sama7g5_platform,
+ }, {
+ .compatible = "microchip,sama7d65-adc",
+ .data = (const void *)&sama7d65_platform,
}, {
/* sentinel */
}
--
2.34.1
^ permalink raw reply related
* [PATCH v2 04/12] dt-bindings: nvmem: microchip,sama7g5-otpc: add sama7d65 and dt node example
From: Varshini Rajendran @ 2026-06-23 10:59 UTC (permalink / raw)
To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
linux-iio, devicetree, linux-arm-kernel, linux-kernel
Cc: varshini.rajendran
In-Reply-To: <20260623105944.128840-1-varshini.rajendran@microchip.com>
Add support for sama7d65 and a dt node example that shows tag can be used
to reference a packet stored in the OTP memory.
Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
.../nvmem/microchip,sama7g5-otpc.yaml | 28 +++++++++++++++++--
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml b/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
index cc25f2927682..3cc16b0044a6 100644
--- a/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
+++ b/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
@@ -20,9 +20,15 @@ allOf:
properties:
compatible:
- items:
- - const: microchip,sama7g5-otpc
- - const: syscon
+ oneOf:
+ - items:
+ - const: microchip,sama7g5-otpc
+ - const: syscon
+ - items:
+ - enum:
+ - microchip,sama7d65-otpc
+ - const: microchip,sama7g5-otpc
+ - const: syscon
reg:
maxItems: 1
@@ -48,4 +54,20 @@ examples:
};
};
+ - |
+ otp_controller: efuse@e8c00000 {
+ compatible = "microchip,sama7d65-otpc", "microchip,sama7g5-otpc", "syscon";
+ reg = <0xe8c00000 0x100>;
+
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ temp_calib: calib@41435354 {
+ reg = <0x41435354 0x2c>; /* Temp calib data packet TAG */
+ };
+ };
+ };
+
...
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox