* [PATCH 02/15] arm64: dts: st: add SDMMC2 support on stm32mp25
From: Dario Binacchi @ 2026-05-18 14:31 UTC (permalink / raw)
To: linux-kernel
Cc: linux-amarula, domenico.acri, francesco.utel, Dario Binacchi,
Alexandre Torgue, Conor Dooley, Krzysztof Kozlowski,
Maxime Coquelin, Rob Herring, devicetree, linux-arm-kernel,
linux-stm32
In-Reply-To: <20260518143150.3138712-1-dario.binacchi@amarulasolutions.com>
The SDMMC2 controller supports SD cards, eMMC memories and SDIO devices.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
arch/arm64/boot/dts/st/stm32mp251.dtsi | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index 673fbc5632e6..5e46024d2215 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -1667,6 +1667,21 @@ sdmmc1: mmc@48220000 {
status = "disabled";
};
+ sdmmc2: mmc@48230000 {
+ compatible = "st,stm32mp25-sdmmc2", "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00353180>;
+ reg = <0x48230000 0x400>, <0x44230800 0x8>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_SDMMC2>;
+ clock-names = "apb_pclk";
+ resets = <&rcc SDMMC2_R>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ max-frequency = <120000000>;
+ access-controllers = <&rifsc 77>;
+ status = "disabled";
+ };
+
ethernet1: ethernet@482c0000 {
compatible = "st,stm32mp25-dwmac", "snps,dwmac-5.20";
reg = <0x482c0000 0x4000>;
--
2.43.0
^ permalink raw reply related
* [PATCH 01/15] dt-bindings: arm: stm32: support Engicam MicroGEA-STM32MP257-RMM board
From: Dario Binacchi @ 2026-05-18 14:31 UTC (permalink / raw)
To: linux-kernel
Cc: linux-amarula, domenico.acri, francesco.utel, Dario Binacchi,
Alexandre Torgue, Christophe Parant, Conor Dooley,
Himanshu Bhavani, Krzysztof Kozlowski, Maxime Coquelin,
Rob Herring, devicetree, linux-arm-kernel, linux-stm32
In-Reply-To: <20260518143150.3138712-1-dario.binacchi@amarulasolutions.com>
Add devicetree bindings for Engicam MicroGEA-STM32MP257-RMM board based
on the Engicam MicroGEA-STM32MP257 SoM (System-on-Module).
The use of an enum for a single element is justified by the future
addition of other boards based on the same SoM.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
Documentation/devicetree/bindings/arm/stm32/stm32.yaml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
index c6af3a46364f..c5ce81e3ce45 100644
--- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
@@ -203,6 +203,13 @@ properties:
- st,stm32mp257f-ev1
- const: st,stm32mp257
+ - description: Engicam MicroGEA STM32MP257 SoM based Boards
+ items:
+ - enum:
+ - engicam,microgea-stm32mp257-rmm
+ - const: engicam,microgea-stm32mp257
+ - const: st,stm32mp257
+
- description: ST STM32MP235 based Boards
items:
- enum:
--
2.43.0
^ permalink raw reply related
* [PATCH 00/15] arm64: support Engicam MicroGEA-STM32MP257-RMM board
From: Dario Binacchi @ 2026-05-18 14:31 UTC (permalink / raw)
To: linux-kernel
Cc: linux-amarula, domenico.acri, francesco.utel, Dario Binacchi,
Alexandre Torgue, Arnd Bergmann, Bjorn Andersson,
Christophe Parant, Conor Dooley, Dmitry Baryshkov, Eric Biggers,
Geert Uytterhoeven, Himanshu Bhavani, Krzysztof Kozlowski,
Krzysztof Kozlowski, Luca Weiss, Maxime Coquelin, Michal Simek,
Rob Herring, Sven Peter, devicetree, linux-arm-kernel,
linux-stm32
This series adds initial support for the Engicam MicroGEA-STM32MP257-RMM
board based on the MicroGEA-STM32MP257 SoM.
The support includes device tree descriptions for both the SoM and the
carrier board, together with the required pinctrl definitions for the
peripherals used.
The series also updates the arm64 defconfig accordingly and performs a
small cleanup to keep it consistent with the newly added configurations.
Dario Binacchi (15):
dt-bindings: arm: stm32: support Engicam MicroGEA-STM32MP257-RMM board
arm64: dts: st: add SDMMC2 support on stm32mp25
arm64: dts: st: add CAN1 support on stm32mp25
arm64: dts: st: add i2c1 pins for stm32mp25
arm64: dts: st: add ltdc pins for stm32mp25
arm64: dts: st: add can1 pins for stm32mp25
arm64: dts: st: add pwm2/pwm4 pins for stm32mp25
arm64: dts: st: add sai1 pins for stm32mp25
arm64: dts: st: add sdmmc2 pins for stm32mp25
arm64: dts: st: add spi1 pins for stm32mp25
arm64: dts: st: add usart1 pins for stm32mp25
arm64: dts: st: support Engicam MicroGEA-STM32MP257 SoM
arm64: dts: st: support Engicam MicroGEA-STM32MP257-RMM board
arm64: defconfig: cleanup the defconfig
arm64: defconfig: enable configs for Engicam MicroGEA-STM32MP257-RMM
.../devicetree/bindings/arm/stm32/stm32.yaml | 7 +
arch/arm64/boot/dts/st/Makefile | 1 +
arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 328 ++++++++++++++++++
arch/arm64/boot/dts/st/stm32mp251.dtsi | 15 +
arch/arm64/boot/dts/st/stm32mp253.dtsi | 15 +
.../st/stm32mp257-engicam-microgea-rmm.dts | 321 +++++++++++++++++
.../dts/st/stm32mp257-engicam-microgea.dtsi | 64 ++++
arch/arm64/configs/defconfig | 293 ++++++----------
8 files changed, 862 insertions(+), 182 deletions(-)
create mode 100644 arch/arm64/boot/dts/st/stm32mp257-engicam-microgea-rmm.dts
create mode 100644 arch/arm64/boot/dts/st/stm32mp257-engicam-microgea.dtsi
--
2.43.0
base-commit: 70eda68668d1476b459b64e69b8f36659fa9dfa8
branch: stm32mp257d-microgea
^ permalink raw reply
* Re: [PATCH 2/3] usb: dwc3: xilinx: use reset_control_reset() in versal init
From: Pandey, Radhey Shyam @ 2026-05-18 14:28 UTC (permalink / raw)
To: Thinh Nguyen, Radhey Shyam Pandey
Cc: gregkh@linuxfoundation.org, michal.simek@amd.com,
p.zabel@pengutronix.de, linux-usb@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, git@amd.com
In-Reply-To: <agUltzvDFgJtPa6j@vbox>
On 5/14/2026 7:04 AM, Thinh Nguyen wrote:
> On Mon, May 11, 2026, Radhey Shyam Pandey wrote:
>> Replace separate reset_control_assert() and reset_control_deassert() calls
>> with reset_control_reset(), which pulses the reset in one step. Report
>> failures with dev_err_probe() and a single message. No functional change.
>>
>
> The behavior of reset_control_reset() is a little different. I wouldn't
> call this "No functional change". However, I assumed this was tested.
> Please provide a proper reason for this change in the change log.
In the dwc3-xilinx case, reset_control_reset() routes through the
zynqmp reset driver and invokes PM_RESET_ACTION_PULSE. This triggers
the Xilinx firmware reset implementation, which performs both assert
and deassert. Effectively, reset() issues a single SMC call for a
reset pulse instead of separate assert and deassert calls and moves
IP out of reset.
Yes this new reset sequence is validated on HW. I will include
above description and respin v2..
>
>> Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
>> ---
>> drivers/usb/dwc3/dwc3-xilinx.c | 16 ++++------------
>> 1 file changed, 4 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
>> index a3c7dc258c7d..94458b3da1a0 100644
>> --- a/drivers/usb/dwc3/dwc3-xilinx.c
>> +++ b/drivers/usb/dwc3/dwc3-xilinx.c
>> @@ -98,18 +98,10 @@ static int dwc3_xlnx_init_versal(struct dwc3_xlnx *priv_data)
>>
>> dwc3_xlnx_mask_phy_rst(priv_data, false);
>>
>> - /* Assert and De-assert reset */
>> - ret = reset_control_assert(crst);
>> - if (ret < 0) {
>> - dev_err_probe(dev, ret, "failed to assert Reset\n");
>> - return ret;
>> - }
>> -
>> - ret = reset_control_deassert(crst);
>> - if (ret < 0) {
>> - dev_err_probe(dev, ret, "failed to De-assert Reset\n");
>> - return ret;
>> - }
>> + /* assert and deassert reset */
>> + ret = reset_control_reset(crst);
>> + if (ret)
>> + return dev_err_probe(dev, ret, "failed to assert and deassert reset\n");
>>
>> dwc3_xlnx_mask_phy_rst(priv_data, true);
>> dwc3_xlnx_set_coherency(priv_data, XLNX_USB2_TRAFFIC_ROUTE_CONFIG);
>> --
>> 2.44.4
^ permalink raw reply
* Re: [PATCH 0/4] drm/mediatek: fix sparse warnings
From: Chun-Kuang Hu @ 2026-05-18 14:26 UTC (permalink / raw)
To: Louis-Alexis Eyraud
Cc: Chun-Kuang Hu, Philipp Zabel, David Airlie, Simona Vetter,
Matthias Brugger, AngeloGioacchino Del Regno, CK Hu,
Alexandre Mergnat, kernel, dri-devel, linux-mediatek,
linux-kernel, linux-arm-kernel, kernel test robot
In-Reply-To: <20260429-mediatek-drm-fix-sparse-warnings-v1-0-d95c4d118b83@collabora.com>
Hi, Louis:
Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com> 於 2026年4月29日週三 上午9:59寫道:
>
> This series fixes in the mediatek-drm driver the sparse warnings
> reported by [1] and two others introduced during v6.16 development
> cycle.
>
> The series has compile-tested and is based on linux-next (tag:
> next-2040428).
>
> [1]: https://lore.kernel.org/all/202604132044.fcYjEcU8-lkp@intel.com/
For this series, applied to mediatek-drm-fixes [1], thanks.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-fixes
Regards,
Chun-Kuang.
>
> Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
> ---
> Louis-Alexis Eyraud (4):
> drm/mediatek: mtk_hdmi_ddc_v2: Fix non-static global variable
> drm/mediatek: mtk_hdmi_v2: Fix non-static global variable
> drm/mediatek: mtk_cec: Fix non-static global variable
> drm/mediatek: mtk_hdmi_ddc: Fix non-static global variable
>
> drivers/gpu/drm/mediatek/mtk_cec.c | 2 +-
> drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c | 2 +-
> drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c | 2 +-
> drivers/gpu/drm/mediatek/mtk_hdmi_v2.c | 2 +-
> 4 files changed, 4 insertions(+), 4 deletions(-)
> ---
> base-commit: 0f3ef35b0747832b58b97171bad99011d084c6b1
> change-id: 20260424-mediatek-drm-fix-sparse-warnings-7404de18204c
>
> Best regards,
> --
> Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
>
^ permalink raw reply
* Re: [PATCH v13 3/4] gpio: rpmsg: add generic rpmsg GPIO driver
From: Shenwei Wang @ 2026-05-18 14:24 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Arnaud POULIQUEN, Beleswar Prasad Padhi, Andrew Lunn,
Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Frank Li,
Sascha Hauer, Shuah Khan, linux-gpio@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
devicetree@vger.kernel.org, linux-remoteproc@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
dl-linux-imx, Bartosz Golaszewski
In-Reply-To: <agYHzH-nJLl1HFIn@p14s>
>
> On Thu, May 07, 2026 at 07:43:33PM +0000, Shenwei Wang wrote:
> >
> >
> > > That was my initial approach. We don't even need an additional
> > > "rpmsg-io-*" in rpmsg_gpio_channel_id_table[]. All we need is:
> > >
> > > /* rpmsg devices and drivers are matched using the service name */
> > > static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
> > > const struct rpmsg_device_id *id) {
> > > + size_t len = strnlen(id->name, RPMSG_NAME_SIZE);
> > >
> > > - return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
> > > + return strncmp(id->name, rpdev->id.name, len) == 0;
> > > }
> > >
> >
> > If we encode the port index directly into ept->src, for example:
> >
> > ept->src = (baseaddr << 8) | port_index;
> >
>
> There is no rpmsg_endpoint::src. You likely meant ept->addr. This would work
> but not optimal on two front:
>
> (1) rpms_endpoint::addr is a u32 and idr_alloc() returns an 'int'. As such there is a
> possibility of conflict. I concede the possibility is marginal, but it still exists.
>
I think there may be a misunderstanding in the implementation. In this case, we do not
need the return value from idr_alloc.
When the driver calls rpmsg_create_ept, it can pass an rpmsg_channel_info structure as an
input parameter. This allows you to specify the source address you want to bind.
Please refer to the definitions below:
struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
rpmsg_rx_cb_t cb, void *priv,
struct rpmsg_channel_info chinfo)
struct rpmsg_channel_info {
char name[RPMSG_NAME_SIZE];
u32 src;
u32 dst;
};
> (2) By proceeding this way, the kernel exposes the GPIO controller it knows
> about. It is preferrable to have the remote processor tell the kernel about the
> GPIO controller it wants.
>
If everyone agrees with this namespace announcement approach, I will prepare the
next revision based on it, even though it is not as clean as the source address encoding solution.
Shenwei
> I am done reviewing this revision. Given the amount of refactoring needed, I will
> not look at the code. Please refer to this reply [1] for what I am expecting in the
> next revision.
>
^ permalink raw reply
* Re: [PATCH v2 0/6] fsl-mc: Move over to device MSI infrastructure
From: Marc Zyngier @ 2026-05-18 14:24 UTC (permalink / raw)
To: Christophe Leroy (CS GROUP)
Cc: Arnd Bergmann, Ioana Ciornei, Thomas Gleixner, Sascha Bischoff,
linux-kernel, linux-arm-kernel, linuxppc-dev
In-Reply-To: <4f34dc22-8dd7-42fb-8c16-4e359faf60d6@kernel.org>
On Mon, 18 May 2026 14:51:48 +0100,
"Christophe Leroy (CS GROUP)" <chleroy@kernel.org> wrote:
>
> > > Do I need to respin it?
>
> No, I'd like to avoid having to rebase again. If you have changes to
> the series please send followup patches.
No follow-up patches for that particular series, I just wanted to find
out whether I could start posting additional changes that do not
directly involve fsl-mc, but that are prevented by the current state
of the code (such as trying to move the ITS initialisation much later
in the boot process).
I'll postpone my changes to 7.3, and keep my fingers crossed for this
to hit 7.2.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v6 0/8] Add VIM4 MCU/FAN support
From: Neil Armstrong @ 2026-05-18 14:17 UTC (permalink / raw)
To: linux-kernel-dev, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Conor Dooley
In-Reply-To: <20260516-add-mcu-fan-khadas-vim4-v6-0-cccc9b61f465@aliel.fr>
Hi,
On 5/16/26 19:17, Ronald Claveau via B4 Relay wrote:
> The Khadas VIM4 board features a different MCU variant compared to
> previous VIM boards.
> While it shares the same I2C-based communication model,
> it differs in some ways:
>
> - A distinct register map with its own volatile/writeable register set
> - A fan control with 0–100 levels instead of the 0–3 levels previously
> - A fan power supply gated through a regulator
>
> This series adds support for this new variant by:
>
> 1. Refactoring the khadas-mcu MFD driver to use per-variant data
> structures (regmap config, cells, fan platform data),
> and adding the khadas,vim4-mcu compatible string.
>
> 2. Extending the fan thermal driver to retrieve the fan register
> and maximum level from platform_data,
> and to optionally manage a power regulator for the fan supply.
>
> 3. Adding the corresponding DTS node for the VIM4, wiring the MCU to
> the I2C AO_A bus and exposing it as a thermal cooling device.
I will directly pick patch 6 now, and patch 7 & 8 later when patches 1,2,3,4 are picked
by the i2c & mfd maintainers.
Patch 5 should not be applied without path 4.
Neil
>
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
> Changes in v6:
> - PATCH 4: Address Lee's review comments:
> - Use an enum to discriminate between MCU types instead of passing
> MFD data through the DT match table
> - Fix error code from -EINVAL to -ENODEV when no MCU type is matched
> - Make khadas_mcu_fan_cells and khadas_mcu_cells const
> - Use dev_err_probe() for regmap initialization error
> - Document fan speed levels for max_level
> - Link to v5: https://lore.kernel.org/r/20260424-add-mcu-fan-khadas-vim4-v5-0-afcfa7157b23@aliel.fr
>
> Changes in v5:
> - PATCH 5: Replace devm_regulator_get_optional() with devm_regulator_get()
> to simplify error handling and remove NULL checks, also
> ordering as reverse christmas according to Neil's feedback.
> - Link to v4: https://lore.kernel.org/r/20260421-add-mcu-fan-khadas-vim4-v4-0-447114a28f2d@aliel.fr
>
> Changes in v4:
> - PATCH 1: limit fan-supply property by compatible according to Conor's feedback.
> - Link to v3: https://lore.kernel.org/r/20260417-add-mcu-fan-khadas-vim4-v3-0-a6a7f570b11b@aliel.fr
>
> Changes in v3:
> - PATCH 1: adding comment on vim4 compatible saying it is not discoverable,
> thanks to Rob's and Neil's feedback.
> - Link to v2: https://lore.kernel.org/r/20260403-add-mcu-fan-khadas-vim4-v2-0-70536b22439a@aliel.fr
>
> Changes in v2:
> - PATCH 5: Add regulator_disable on suspend thanks to Neil's feedback.
> - Link to v1: https://lore.kernel.org/r/20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr
>
> ---
> Ronald Claveau (8):
> dt-bindings: mfd: khadas: Add new compatible for Khadas VIM4 MCU
> dt-bindings: i2c: amlogic: Add compatible for T7 SOC
> mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
> mfd: khadas-mcu: Add support for VIM4 MCU variant
> thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
> arm64: dts: amlogic: t7: Add i2c pinctrl node
> arm64: dts: amlogic: t7: Add i2c controller node
> arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node
>
> .../bindings/i2c/amlogic,meson6-i2c.yaml | 13 ++-
> .../devicetree/bindings/mfd/khadas,mcu.yaml | 18 ++++
> .../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 13 +++
> arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 20 ++++
> drivers/mfd/khadas-mcu.c | 119 ++++++++++++++++++---
> drivers/thermal/khadas_mcu_fan.c | 37 +++++--
> include/linux/mfd/khadas-mcu.h | 44 +++++++-
> 7 files changed, 236 insertions(+), 28 deletions(-)
> ---
> base-commit: f7b64ed948718290209074a50bb0df17e5944873
> change-id: 20260402-add-mcu-fan-khadas-vim4-ac1cbe553c9b
> prerequisite-message-id: <20260326092645.1053261-1-jian.hu@amlogic.com>
> prerequisite-patch-id: f03a086b4137158412b2d47b3de793b858de8dde
> prerequisite-patch-id: 123970c9b29c2090440f2fd71c85d3c6fd8e36de
> prerequisite-patch-id: 3e2e56b0926ba327b520f935df4ced5089bbe503
> prerequisite-patch-id: 65a5d76ffdbc9b3aab3385bb65cb027004c30e7e
> prerequisite-patch-id: 237269801826dd3ad7fb16eb4d7d6d4eab504278
> prerequisite-patch-id: 57e9b08a968aedf543d3d0d56cf1ca4db20b2a16
> prerequisite-change-id: 20260326-add-bcm43752-compatible-e264a4f7973a:v2
> prerequisite-patch-id: cd98b74fa56af72af2553f391c400981d83cd4f4
> prerequisite-patch-id: b730f5e42be1d89d193e63a0265495cdbf2c7d7b
> prerequisite-change-id: 20260330-fix-invalid-property-bbe54d933f71:v2
> prerequisite-patch-id: 8d675e7a239985c762843515b241f0a2f45f9c92
> prerequisite-change-id: 20260331-fix-aml-t7-null-reset-2b608ebf9da4:v1
> prerequisite-patch-id: 5b5de77af11747ce964404fb827d2ee2bff47ea5
> prerequisite-patch-id: 1e37fc75fed1e533adee0f3e7e6ead1f8ff3c55c
> prerequisite-patch-id: 65a5d76ffdbc9b3aab3385bb65cb027004c30e7e
> prerequisite-patch-id: 2daf583fb5e7449a02bd217d8aca330171b598aa
> prerequisite-patch-id: 237269801826dd3ad7fb16eb4d7d6d4eab504278
> prerequisite-patch-id: d1ddf9b7710e91f8062de83bd7ba55afb2c4c112
> prerequisite-patch-id: 57e9b08a968aedf543d3d0d56cf1ca4db20b2a16
> prerequisite-patch-id: cd98b74fa56af72af2553f391c400981d83cd4f4
> prerequisite-patch-id: b730f5e42be1d89d193e63a0265495cdbf2c7d7b
> prerequisite-patch-id: 9debd88fa60febed9cd7208f86603b4c2d270520
> prerequisite-patch-id: 314ef9ff0c4d1d15dab1dea9d92aa065f1eac3e9
>
> Best regards,
^ permalink raw reply
* Re: [PATCH v2 3/3] arm64: dts: allwinner: A133: add support for Baijie Helper A133 board
From: Paul Kocialkowski @ 2026-05-18 14:14 UTC (permalink / raw)
To: Alexander Sverdlin
Cc: linux-sunxi, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <579c7c33123c4cd0bd486301e56daf5962ca55ec.camel@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1349 bytes --]
Hi Alexander,
Le Mon 18 May 26, 14:09, Alexander Sverdlin a écrit :
> Hi Paul,
>
> On Mon, 2026-05-18 at 13:52 +0200, Paul Kocialkowski wrote:
> > Just in case you missed it, there was a previous submission for this
> > board which wasn't followed up on.
> >
> > I also have one of this board and wanted to respin support, but it looks
> > like you beat me to it :)
>
> thanks for the hint!
> Do you mean this series:
> https://lore.kernel.org/all/20241227-a133-display-support-v1-0-13b52f71fb14@linumiz.com/
> ?
>
> I've missed it indeed! I'll look into it!
Yes that's the one! But I don't think there are features that your
series is missing, as long as you apply the suggestions I made earlier.
I also have a U-Boot config ready for it, which I could send once the
device-trees are merged on the kernel side. I could send it to you if
you're interested.
I will also get back to you about your TF-A series so we can move all of
this forward!
By the way it's good to wait a few days before sending new versions of
patch series, to avoid overwhelmind the developers.
All the best,
Paul
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v4 2/2] drm/mediatek: dsi: Add compatible for mt8167-dsi
From: Chun-Kuang Hu @ 2026-05-18 14:11 UTC (permalink / raw)
To: Luca Leonardo Scorcia
Cc: linux-mediatek, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno, Chun-Kuang Hu,
Philipp Zabel, David Airlie, Simona Vetter, devicetree,
linux-kernel, linux-arm-kernel, dri-devel
In-Reply-To: <20260505214541.333657-3-l.scorcia@gmail.com>
Hi, Luca:
Luca Leonardo Scorcia <l.scorcia@gmail.com> 於 2026年5月5日週二 下午9:46寫道:
>
> The mt8167 DSI controller is fully compatible with the one found in
> mt2701. Unfortunately the device tree has a dedicated compatible for
> mt8167 since 2022 and it cannot be changed with a fallback nor removed at
> this point. The only way to get the device to work is to add the
> compatible to the driver.
Applied to mediatek-drm-next [1], thanks.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next
Regards,
Chun-Kuang.
>
> Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
> ---
> drivers/gpu/drm/mediatek/mtk_dsi.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5aa71fcdcfab..167e33fef025 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -1305,6 +1305,7 @@ static const struct mtk_dsi_driver_data mt8188_dsi_driver_data = {
>
> static const struct of_device_id mtk_dsi_of_match[] = {
> { .compatible = "mediatek,mt2701-dsi", .data = &mt2701_dsi_driver_data },
> + { .compatible = "mediatek,mt8167-dsi", .data = &mt2701_dsi_driver_data },
> { .compatible = "mediatek,mt8173-dsi", .data = &mt8173_dsi_driver_data },
> { .compatible = "mediatek,mt8183-dsi", .data = &mt8183_dsi_driver_data },
> { .compatible = "mediatek,mt8186-dsi", .data = &mt8186_dsi_driver_data },
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH 3/5] arm_mpam: add MPAM-Fb MSC firmware access support
From: Sudeep Holla @ 2026-05-18 14:11 UTC (permalink / raw)
To: Andre Przywara
Cc: Lorenzo Pieralisi, Sudeep Holla, Hanjun Guo, Catalin Marinas,
Will Deacon, Rafael J . Wysocki, Len Brown, James Morse,
Ben Horgan, Reinette Chatre, Fenghua Yu, Jonathan Cameron,
linux-acpi, linux-arm-kernel, linux-kernel
In-Reply-To: <20260429141339.3171205-4-andre.przywara@arm.com>
On Wed, Apr 29, 2026 at 04:13:37PM +0200, Andre Przywara wrote:
[...]
> diff --git a/drivers/resctrl/mpam_fb.c b/drivers/resctrl/mpam_fb.c
> new file mode 100644
> index 000000000000..bfb5798c74b0
> --- /dev/null
> +++ b/drivers/resctrl/mpam_fb.c
> @@ -0,0 +1,158 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2024 Arm Ltd.
> +
> +#include <linux/arm_mpam.h>
> +#include <linux/cleanup.h>
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/gfp.h>
> +#include <linux/iopoll.h>
> +#include <linux/list.h>
> +#include <linux/mailbox_client.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/printk.h>
> +#include <linux/processor.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/types.h>
> +
> +#include <acpi/pcc.h>
> +
> +#include <asm/mpam.h>
> +
> +#include "mpam_fb.h"
> +
> +#define MPAM_FB_PROTOCOL_ID 0x1a
This is only possible place where referring to SCMI is Okay but good
that you have avoided by keeping it MPAM_FB_PROTOCOL_ID. You can add a
note if that is helpful but other than that remove any reference to SCMI
from this file as it is not needed and might be misleading.
Consider a system that just implements SCMI for sake of MPAM_FB_PROTOCOL
and need not be completely SCMI conformant in terms of base and other
protocol if it is not used on such a system. Using or referring SCMI must
give a misunderstanding that SCMI is needed for this to work.
> +#define MPAM_MSC_ATTRIBUTES_CMD 0x3
> +#define MPAM_MSC_READ_CMD 0x4
> +#define MPAM_MSC_WRITE_CMD 0x5
> +
> +#define MPAM_MSC_PROT_ID_MASK GENMASK(17, 10)
> +#define MPAM_MSC_TOKEN_MASK GENMASK(27, 18)
> +
> +#define SCMI_CHAN_RSVD_OFS 0x00
> +#define SCMI_CHAN_STATUS_OFS 0x04
> +#define SCMI_CHAN_STATUS_FREE_BIT BIT(0)
> +#define SCMI_CHAN_FLAGS_OFS 0x10
> +#define SCMI_CHAN_FLAGS_IRQ BIT(0)
> +#define SCMI_MSG_LENGTH_OFS 0x14
> +#define SCMI_MSG_HEADER_OFS 0x18
> +#define SCMI_MSG_PAYLOAD_OFS 0x1c
> +
However, there is nothing SCMI specific in all the above, plain PCC shared
memory layout and hence SCMI needs to be dropped. Also you don't need
all these offsets if you use acpi_pcct_ext_pcc_shared_memory directly.
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH 04/16] media: sun8i-a83t-mipi-csi2: Use V4L2 subdev active state
From: Paul Kocialkowski @ 2026-05-18 14:09 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Mauro Carvalho Chehab, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
In-Reply-To: <20260518102451.417971-5-paulk@sys-base.io>
[-- Attachment #1: Type: text/plain, Size: 10308 bytes --]
Le Mon 18 May 26, 12:24, Paul Kocialkowski a écrit :
> From: Arash Golgol <arash.golgol@gmail.com>
>
> Use the V4L2 subdev active state API to store the active format.
> This simplifies the driver not only by dropping the bridge mbus_format
> field, but it also allows dropping the bridge lock, replaced with
> the state lock.
>
> The sun8i-a83t-mipi-csi2 hardware does not perform any format
> conversion. Enforce identical formats on the sink and source pads in
> the set_fmt() and init_state() callbacks.
>
> Signed-off-by: Arash Golgol <arash.golgol@gmail.com>
I forgot to pick it up but this is already:
Reviewed-by: Paul Kocialkowski <paulk@sys-base.io>
Tested-by: Paul Kocialkowski <paulk@sys-base.io>
Paul
> ---
> .../sun8i_a83t_mipi_csi2.c | 113 +++++++++---------
> .../sun8i_a83t_mipi_csi2.h | 2 -
> 2 files changed, 56 insertions(+), 59 deletions(-)
>
> diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
> index dbc51daa4fe3..2b7635f3952d 100644
> --- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
> +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
> @@ -144,12 +144,12 @@ sun8i_a83t_mipi_csi2_disable(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
> }
>
> static void
> -sun8i_a83t_mipi_csi2_configure(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
> +sun8i_a83t_mipi_csi2_configure(struct sun8i_a83t_mipi_csi2_device *csi2_dev,
> + const struct v4l2_mbus_framefmt *mbus_format)
> {
> struct regmap *regmap = csi2_dev->regmap;
> unsigned int lanes_count =
> csi2_dev->bridge.endpoint.bus.mipi_csi2.num_data_lanes;
> - struct v4l2_mbus_framefmt *mbus_format = &csi2_dev->bridge.mbus_format;
> const struct sun8i_a83t_mipi_csi2_format *format;
> struct device *dev = csi2_dev->dev;
> u32 version = 0;
> @@ -205,7 +205,8 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
> struct v4l2_subdev *source_subdev = csi2_dev->bridge.source_subdev;
> union phy_configure_opts dphy_opts = { 0 };
> struct phy_configure_opts_mipi_dphy *dphy_cfg = &dphy_opts.mipi_dphy;
> - struct v4l2_mbus_framefmt *mbus_format = &csi2_dev->bridge.mbus_format;
> + struct v4l2_subdev_state *state;
> + const struct v4l2_mbus_framefmt *mbus_format;
> const struct sun8i_a83t_mipi_csi2_format *format;
> struct phy *dphy = csi2_dev->dphy;
> struct device *dev = csi2_dev->dev;
> @@ -215,8 +216,12 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
> unsigned long pixel_rate;
> int ret;
>
> - if (!source_subdev)
> - return -ENODEV;
> + state = v4l2_subdev_lock_and_get_active_state(subdev);
> +
> + if (!source_subdev) {
> + ret = -ENODEV;
> + goto unlock;
> + }
>
> if (!on) {
> v4l2_subdev_call(source_subdev, video, s_stream, 0);
> @@ -228,7 +233,7 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
>
> ret = pm_runtime_resume_and_get(dev);
> if (ret < 0)
> - return ret;
> + goto unlock;
>
> /* Sensor pixel rate */
>
> @@ -254,6 +259,9 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
> goto error_pm;
> }
>
> + mbus_format =
> + v4l2_subdev_state_get_format(state,
> + SUN8I_A83T_MIPI_CSI2_PAD_SINK);
> format = sun8i_a83t_mipi_csi2_format_find(mbus_format->code);
> if (WARN_ON(!format)) {
> ret = -ENODEV;
> @@ -292,7 +300,7 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
>
> /* Controller */
>
> - sun8i_a83t_mipi_csi2_configure(csi2_dev);
> + sun8i_a83t_mipi_csi2_configure(csi2_dev, mbus_format);
> sun8i_a83t_mipi_csi2_enable(csi2_dev);
>
> /* D-PHY */
> @@ -309,7 +317,8 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
> if (ret && ret != -ENOIOCTLCMD)
> goto disable;
>
> - return 0;
> + ret = 0;
> + goto unlock;
>
> disable:
> phy_power_off(dphy);
> @@ -318,6 +327,8 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
> error_pm:
> pm_runtime_put(dev);
>
> +unlock:
> + v4l2_subdev_unlock_state(state);
> return ret;
> }
>
> @@ -341,22 +352,24 @@ sun8i_a83t_mipi_csi2_mbus_format_prepare(struct v4l2_mbus_framefmt *mbus_format)
> static int sun8i_a83t_mipi_csi2_init_state(struct v4l2_subdev *subdev,
> struct v4l2_subdev_state *state)
> {
> - struct sun8i_a83t_mipi_csi2_device *csi2_dev =
> - v4l2_get_subdevdata(subdev);
> - unsigned int pad = SUN8I_A83T_MIPI_CSI2_PAD_SINK;
> - struct v4l2_mbus_framefmt *mbus_format =
> - v4l2_subdev_state_get_format(state, pad);
> - struct mutex *lock = &csi2_dev->bridge.lock;
> + unsigned int pad;
>
> - mutex_lock(lock);
> + /*
> + * This subdev does not perform format conversion,
> + * initialize both pads identically.
> + */
> + for (pad = 0; pad < subdev->entity.num_pads; pad++) {
> + struct v4l2_mbus_framefmt *mbus_format;
>
> - mbus_format->code = sun8i_a83t_mipi_csi2_formats[0].mbus_code;
> - mbus_format->width = 640;
> - mbus_format->height = 480;
> + mbus_format = v4l2_subdev_state_get_format(state, pad);
> +
> + mbus_format->code = sun8i_a83t_mipi_csi2_formats[0].mbus_code;
> + mbus_format->width = 640;
> + mbus_format->height = 480;
>
> - sun8i_a83t_mipi_csi2_mbus_format_prepare(mbus_format);
> + sun8i_a83t_mipi_csi2_mbus_format_prepare(mbus_format);
> + }
>
> - mutex_unlock(lock);
>
> return 0;
> }
> @@ -375,55 +388,33 @@ sun8i_a83t_mipi_csi2_enum_mbus_code(struct v4l2_subdev *subdev,
> return 0;
> }
>
> -static int sun8i_a83t_mipi_csi2_get_fmt(struct v4l2_subdev *subdev,
> - struct v4l2_subdev_state *state,
> - struct v4l2_subdev_format *format)
> -{
> - struct sun8i_a83t_mipi_csi2_device *csi2_dev =
> - v4l2_get_subdevdata(subdev);
> - struct v4l2_mbus_framefmt *mbus_format = &format->format;
> - struct mutex *lock = &csi2_dev->bridge.lock;
> -
> - mutex_lock(lock);
> -
> - if (format->which == V4L2_SUBDEV_FORMAT_TRY)
> - *mbus_format = *v4l2_subdev_state_get_format(state,
> - format->pad);
> - else
> - *mbus_format = csi2_dev->bridge.mbus_format;
> -
> - mutex_unlock(lock);
> -
> - return 0;
> -}
> -
> static int sun8i_a83t_mipi_csi2_set_fmt(struct v4l2_subdev *subdev,
> struct v4l2_subdev_state *state,
> struct v4l2_subdev_format *format)
> {
> - struct sun8i_a83t_mipi_csi2_device *csi2_dev =
> - v4l2_get_subdevdata(subdev);
> - struct v4l2_mbus_framefmt *mbus_format = &format->format;
> - struct mutex *lock = &csi2_dev->bridge.lock;
> + struct v4l2_mbus_framefmt *fmt;
>
> - mutex_lock(lock);
> + /* The format on the source pad always matches the sink pad. */
> + if (format->pad != SUN8I_A83T_MIPI_CSI2_PAD_SINK)
> + return v4l2_subdev_get_fmt(subdev, state, format);
>
> - sun8i_a83t_mipi_csi2_mbus_format_prepare(mbus_format);
> + sun8i_a83t_mipi_csi2_mbus_format_prepare(&format->format);
>
> - if (format->which == V4L2_SUBDEV_FORMAT_TRY)
> - *v4l2_subdev_state_get_format(state, format->pad) =
> - *mbus_format;
> - else
> - csi2_dev->bridge.mbus_format = *mbus_format;
> + /* Set the format on the sink pad. */
> + fmt = v4l2_subdev_state_get_format(state, format->pad);
> + *fmt = format->format;
>
> - mutex_unlock(lock);
> + /* Propagate the format to the source pad. */
> + fmt = v4l2_subdev_state_get_format(state,
> + SUN8I_A83T_MIPI_CSI2_PAD_SOURCE);
> + *fmt = format->format;
>
> return 0;
> }
>
> static const struct v4l2_subdev_pad_ops sun8i_a83t_mipi_csi2_pad_ops = {
> .enum_mbus_code = sun8i_a83t_mipi_csi2_enum_mbus_code,
> - .get_fmt = sun8i_a83t_mipi_csi2_get_fmt,
> + .get_fmt = v4l2_subdev_get_fmt,
> .set_fmt = sun8i_a83t_mipi_csi2_set_fmt,
> };
>
> @@ -540,8 +531,6 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
> bool notifier_registered = false;
> int ret;
>
> - mutex_init(&bridge->lock);
> -
> /* V4L2 Subdev */
>
> v4l2_subdev_init(subdev, &sun8i_a83t_mipi_csi2_subdev_ops);
> @@ -570,6 +559,12 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
> if (ret)
> return ret;
>
> + /* V4L2 Subdev finalize */
> +
> + ret = v4l2_subdev_init_finalize(subdev);
> + if (ret < 0)
> + goto error_media_entity_cleanup;
> +
> /* V4L2 Async */
>
> v4l2_async_subdev_nf_init(notifier, subdev);
> @@ -603,6 +598,9 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
> error_v4l2_notifier_cleanup:
> v4l2_async_nf_cleanup(notifier);
>
> + v4l2_subdev_cleanup(subdev);
> +
> +error_media_entity_cleanup:
> media_entity_cleanup(&subdev->entity);
>
> return ret;
> @@ -617,6 +615,7 @@ sun8i_a83t_mipi_csi2_bridge_cleanup(struct sun8i_a83t_mipi_csi2_device *csi2_dev
> v4l2_async_unregister_subdev(subdev);
> v4l2_async_nf_unregister(notifier);
> v4l2_async_nf_cleanup(notifier);
> + v4l2_subdev_cleanup(subdev);
> media_entity_cleanup(&subdev->entity);
> }
>
> diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h
> index f1e64c53434c..819527bcd64d 100644
> --- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h
> +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h
> @@ -33,8 +33,6 @@ struct sun8i_a83t_mipi_csi2_bridge {
> struct media_pad pads[SUN8I_A83T_MIPI_CSI2_PAD_COUNT];
> struct v4l2_fwnode_endpoint endpoint;
> struct v4l2_async_notifier notifier;
> - struct v4l2_mbus_framefmt mbus_format;
> - struct mutex lock; /* Mbus format lock. */
>
> struct v4l2_subdev *source_subdev;
> };
> --
> 2.54.0
>
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [RFC PATCH 0/2] Optimize S2 page splitting
From: Leonardo Bras @ 2026-05-18 14:09 UTC (permalink / raw)
To: Marc Zyngier
Cc: Leonardo Bras, Oliver Upton, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Catalin Marinas, Will Deacon, Fuad Tabba,
Raghavendra Rao Ananta, linux-arm-kernel, kvmarm, linux-kernel
In-Reply-To: <87o6ifaf5z.wl-maz@kernel.org>
On Sat, May 16, 2026 at 10:15:36AM +0100, Marc Zyngier wrote:
> On Fri, 15 May 2026 20:59:01 +0100,
> Leonardo Bras <leo.bras@arm.com> wrote:
> >
> > While playing with dirty-bit tracking, I decided to take a look on how page
> > splitting works. Found out all entries are walked, even though we can infer,
> > for instance that:
> > - If a level-3 entry is walked, it means the parent level-2 entry is split
> > - If a split just succeeded in an table entry, it means all children nodes
> > are already split
> >
> > So I tried to optimize it in a way that it does not break other users.
> >
> > My main idea is to introduce positive return values that hint to the
> > pagetable walking mechanism that either siblings or children can be
> > skipped. That should be contained to the visitor function, that returns
> > zero if no error was detected.
> >
> > Numbers on above optimization are promising:
> > A 1GB VM, running on the model, splitting all at the beginning
> > (no manual protect):
> > - Memory was already split (4k pages): -97.33% runtime (-172ms) - 20 runs
> > - THP backed memory: -19.82% runtime (-153ms) - 10 runs
> > - 1x1GB hugetlb memory: -20.65% runtime (-150ms) - 10 runs
> >
>
> I haven't looked at the changes in details, but the methodology is
> quite flawed. For a start, measuring anything on a software model
> (QEMU or FVP) doesn't mean anything performance-wise. The trade-offs
> are completely different from a HW implementation, and even the notion
> of time is pretty inconsistent.
>
> Please run this on actual HW. I'm sure your employer can give you
> access to one of these mythical arm64 toys.
Ok, will use real hardware next.
> Measure things from
> userspace, not from the kernel, so that you have all the overheads.
> Don't add console output, because that will make things far worse.
>
> I'm sure you can hack one of the selftests for this purpose.
I think the dirty_log_perf_test should have an config I can use for that
without introducing any change.
Thanks!
Leo
^ permalink raw reply
* Re: [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups
From: Paul Kocialkowski @ 2026-05-18 14:08 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Nicolas Dufresne
In-Reply-To: <20260518121511.GD21216@killaraus.ideasonboard.com>
[-- Attachment #1: Type: text/plain, Size: 3050 bytes --]
Hi Laurent,
Le Mon 18 May 26, 14:15, Laurent Pinchart a écrit :
> On Mon, May 18, 2026 at 12:24:35PM +0200, Paul Kocialkowski wrote:
> > This series first introduces some fixes and new formats to v4l2 format
> > info, one of which we need for the sun6i-csi driver. Support for
> > MC-centric format enumeration is then added, along with cleanups and
> > improvements for both the sun6i-csi and sun6i-isp drivers.
> >
> > The first 4 patches are already reviewed and ready to go and are
> > included here as a reminder that this series depends on them.
>
> Patch 04/16 has no R-b tag.
Oops you're right, I added the tag in my reply to the patch yesterday
but did not add it when resending it with this series.
All the best,
Paul
> > Arash Golgol (4):
> > media: sun6i-csi: bridge: Use V4L2 subdev active state
> > media: sun6i-csi: capture: Implement vidioc_enum_framesizes
> > media: sun6i-mipi-csi2: Use V4L2 subdev active state
> > media: sun8i-a83t-mipi-csi2: Use V4L2 subdev active state
> >
> > Paul Kocialkowski (12):
> > media: v4l2-common: Fix NV15_4L4 format info block height
> > media: v4l2-common: Add missing tiled format info block sizes
> > media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info
> > media: v4l2-common: Add NV12_32L32 pixel format to v4l2 format info
> > media: sun6i-csi: Split format validation to a dedicated helper
> > media: sun6i-csi: Add support for MC-centric format enumeration
> > media: sun6i-csi: Tidy up and unify coding style
> > media: sun6i-mipi-csi2: Fix parenthesis alignment
> > media: sun6i-isp: Add dummy params link_validate implementation
> > media: sun6i-isp: Use V4L2 subdev active state
> > media: sun6i-isp: Add support for MC-centric format enumeration
> > media: sun6i-isp: Add support for frame size enumeration
> >
> > .../sunxi/sun6i-csi/sun6i_csi_bridge.c | 153 +++++++---------
> > .../sunxi/sun6i-csi/sun6i_csi_bridge.h | 9 -
> > .../sunxi/sun6i-csi/sun6i_csi_capture.c | 168 +++++++++++++-----
> > .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c | 107 ++++++-----
> > .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h | 2 -
> > .../sun8i_a83t_mipi_csi2.c | 113 ++++++------
> > .../sun8i_a83t_mipi_csi2.h | 2 -
> > drivers/media/v4l2-core/v4l2-common.c | 12 +-
> > .../media/sunxi/sun6i-isp/sun6i_isp_capture.c | 47 ++++-
> > .../media/sunxi/sun6i-isp/sun6i_isp_params.c | 37 +++-
> > .../media/sunxi/sun6i-isp/sun6i_isp_params.h | 4 +-
> > .../media/sunxi/sun6i-isp/sun6i_isp_proc.c | 117 ++++++------
> > .../media/sunxi/sun6i-isp/sun6i_isp_proc.h | 7 -
> > 13 files changed, 437 insertions(+), 341 deletions(-)
>
> --
> Regards,
>
> Laurent Pinchart
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v4 0/2] Add Meta (Facebook) SanMiguel BMC (AST2620)
From: Andrew Jeffery @ 2026-05-18 14:02 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Patrick Williams, Potin Lai
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
Cosmo Chou, Mike Hsieh, Potin Lai, Conor Dooley, Andrew Lunn
In-Reply-To: <20260323-sanmiguel_init_dts-v4-0-caaa48a7f7be@gmail.com>
On Mon, 23 Mar 2026 20:41:04 +0800, Potin Lai wrote:
> Add Linux device tree entries for Meta (Facebook) SanMiguel specific
> devices connected to the AST2620 BMC SoC.
Thanks, I've applied this to the BMC tree.
--
Andrew Jeffery <andrew@codeconstruct.com.au>
^ permalink raw reply
* Re: [PATCH v3 0/4] KVM: arm64: vgic: Fix IGROUPR writability and IIDR revision control
From: David Woodhouse @ 2026-05-18 13:56 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Jonathan Corbet, Shuah Khan, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Will Deacon, Jonathan Cameron, Sascha Bischoff, Eric Auger,
Raghavendra Rao Ananta, Maxim Levitsky, Kees Cook, Timothy Hayes,
Arnd Bergmann, kvm, linux-doc, linux-kernel, linux-arm-kernel,
kvmarm, linux-kselftest, Peter Maydell, qemu-arm, qemu-devel
In-Reply-To: <20260511113558.3325004-1-dwmw2@infradead.org>
[-- Attachment #1: Type: text/plain, Size: 876 bytes --]
On Mon, 2026-05-11 at 12:30 +0100, David Woodhouse wrote:
> Maintaining precise guest compatibility across host kernel upgrades —
> and even downgrades, since rollback is sometimes necessary — is not
> optional. That *shouldn't* need saying, but maybe it does:
> https://lore.kernel.org/all/6856b269d2af706eae397e0cf9c1231f89d9a932.camel@infradead.org/
>
> This series fixes the GICv2/v3 IGROUPR writability model to be
> consistently controlled by the GICD_IIDR implementation revision,
> replacing the ad-hoc v2_groups_user_writable flag.
The more generic question of whether KVM should actually maintain guest
compatibility from one version of the host kernel to another is being
discussed in that other thread.
Setting that aside, is there any *technical* feedback on this series? I
believe I've dealt with all of Marc's feedback on v1 (thanks).
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]
^ permalink raw reply
* [PATCH v6 12/12] powercap: arm_scmi: Synthetic zone enable/disable
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
Add functionality to disable and enable the synthetic zone which
also affects the immediate children of the synthetic zone by applying
the same command to them.
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
V5->V6
- Added use of to_scmi_powercap_root macro
- Changed instance_root_set_enable_state to bail out on any error
- Changed logic in instance_root_get_enable to not check child states
---
drivers/powercap/arm_scmi_powercap.c | 128 +++++++++++++++++++++++++++
1 file changed, 128 insertions(+)
diff --git a/drivers/powercap/arm_scmi_powercap.c b/drivers/powercap/arm_scmi_powercap.c
index f1cb25a408bb..d911e623e2d7 100644
--- a/drivers/powercap/arm_scmi_powercap.c
+++ b/drivers/powercap/arm_scmi_powercap.c
@@ -36,6 +36,7 @@ struct scmi_powercap_zone {
struct scmi_powercap_root {
unsigned int num_zones;
+ bool enabled;
struct scmi_powercap_zone *spzones;
struct list_head *registered_zones;
struct list_head scmi_zones;
@@ -276,6 +277,127 @@ static int instance_root_release(struct powercap_zone *pz)
return 0;
}
+static int instance_root_read_children_enable_state(struct scmi_powercap_root *pr,
+ bool *mode)
+{
+ struct scmi_powercap_zone *child;
+ bool enabled;
+ int i, ret;
+
+ if (!pr || !mode)
+ return -EINVAL;
+
+ *mode = true;
+
+ for (i = 0; i < pr->num_zones; i++) {
+ child = &pr->spzones[i];
+
+ if (!child->registered || child->invalid)
+ continue;
+ if (child->info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID)
+ continue;
+
+ ret = powercap_ops->cap_enable_get(child->ph, child->info->id, &enabled);
+ if (ret)
+ return ret;
+
+ if (!enabled) {
+ *mode = false;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int instance_root_set_enable_state(struct powercap_zone *pz, bool enable)
+{
+ struct scmi_powercap_zone *child;
+ struct scmi_powercap_root *pr = to_scmi_powercap_root(pz);
+ int i, ret;
+ bool *prev_state;
+
+ if (!pz)
+ return -EINVAL;
+
+ prev_state = kcalloc(pr->num_zones, sizeof(*prev_state), GFP_KERNEL);
+ if (!prev_state)
+ return -ENOMEM;
+
+ for (i = 0; i < pr->num_zones; i++) {
+ child = &pr->spzones[i];
+
+ if (!child->registered || child->invalid)
+ continue;
+ if (child->info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID)
+ continue;
+
+ ret = powercap_ops->cap_enable_get(child->ph, child->info->id,
+ &prev_state[i]);
+
+ if (ret)
+ goto revert;
+
+ if (prev_state[i] == enable)
+ continue;
+
+ ret = powercap_ops->cap_enable_set(child->ph, child->info->id, enable);
+
+ if (ret) {
+ dev_err(child->dev, "failed to %s zone %s: %d\n",
+ enable ? "enable" : "disable",
+ child->info->name, ret);
+ goto revert;
+ }
+ }
+
+ kfree(prev_state);
+ return 0;
+
+revert:
+ while (--i >= 0) {
+ child = &pr->spzones[i];
+
+ if (!child->registered || child->invalid)
+ continue;
+ if (child->info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID)
+ continue;
+ if (!child->info->cpli[0].cap_config)
+ continue;
+ if (prev_state[i] == enable)
+ continue;
+
+ powercap_ops->cap_enable_set(child->ph, child->info->id,
+ prev_state[i]);
+ }
+
+ kfree(prev_state);
+ return ret;
+}
+
+static int instance_root_set_enable(struct powercap_zone *pz, bool mode)
+{
+ struct scmi_powercap_root *pr = to_scmi_powercap_root(pz);
+ int ret;
+
+ ret = instance_root_set_enable_state(pz, mode);
+ if (!ret)
+ pr->enabled = mode;
+
+ return ret;
+}
+
+static int instance_root_get_enable(struct powercap_zone *pz, bool *mode)
+{
+ struct scmi_powercap_root *pr = to_scmi_powercap_root(pz);
+
+ if (!pz || !mode)
+ return -EINVAL;
+
+ *mode = pr->enabled;
+ return 0;
+}
+
static int instance_root_get_power_uw(struct powercap_zone *pz, u64 *power_uw)
{
struct scmi_powercap_root *pr = to_scmi_powercap_root(pz);
@@ -324,6 +446,8 @@ static const struct powercap_zone_ops instance_root_ops = {
.get_max_power_range_uw = scmi_powercap_get_max_power_range_uw,
.get_power_uw = instance_root_get_power_uw,
.release = instance_root_release,
+ .set_enable = instance_root_set_enable,
+ .get_enable = instance_root_get_enable,
};
static const struct powercap_zone_constraint_ops instance_root_const_ops = {
@@ -600,6 +724,10 @@ static int scmi_powercap_probe(struct scmi_device *sdev)
if (ret)
return ret;
+ ret = instance_root_read_children_enable_state(pr, &pr->enabled);
+ if (ret)
+ return ret;
+
dev_set_drvdata(dev, pr);
return ret;
--
2.47.3
^ permalink raw reply related
* [PATCH v6 11/12] powercap: arm_scmi: Add get_power_uw to synthetic node
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
Exposes the current power usage from the immediate children of the synthetic
(root) powercap node. Iterates over pr->spzones and sums per-zone power.
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
V5->V6
- Moved multiple u64 values to the same line
- Reworked logic to walk SCMI zones and filter by parent
- Added to_scmi_powercap_root macro
---
drivers/powercap/arm_scmi_powercap.c | 35 ++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/drivers/powercap/arm_scmi_powercap.c b/drivers/powercap/arm_scmi_powercap.c
index 5e7b7a3b79f2..f1cb25a408bb 100644
--- a/drivers/powercap/arm_scmi_powercap.c
+++ b/drivers/powercap/arm_scmi_powercap.c
@@ -17,6 +17,9 @@
#define to_scmi_powercap_zone(z) \
container_of(z, struct scmi_powercap_zone, zone)
+#define to_scmi_powercap_root(z) \
+ container_of(z, struct scmi_powercap_root, instance_root.zone)
+
static const struct scmi_powercap_proto_ops *powercap_ops;
struct scmi_powercap_zone {
@@ -273,9 +276,37 @@ static int instance_root_release(struct powercap_zone *pz)
return 0;
}
-static int instance_root_get_power_uw(struct powercap_zone *pz, u64 *v)
+static int instance_root_get_power_uw(struct powercap_zone *pz, u64 *power_uw)
{
- *v = 0;
+ struct scmi_powercap_root *pr = to_scmi_powercap_root(pz);
+ struct scmi_powercap_zone *child;
+
+ u64 p, acc = 0;
+ int i, ret;
+
+ if (!pz || !power_uw)
+ return -EINVAL;
+
+ if (!pr)
+ return -ENODEV;
+
+ for (i = 0; i < pr->num_zones; i++) {
+ child = &pr->spzones[i];
+
+ if (!child->registered || child->invalid)
+ continue;
+
+ if (child->info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID)
+ continue;
+
+ ret = scmi_powercap_get_power_uw(&child->zone, &p);
+ if (!ret)
+ acc += p;
+ else
+ dev_dbg(child->dev, "Failed to read child power: %u\n", ret);
+ }
+
+ *power_uw = acc;
return 0;
}
--
2.47.3
^ permalink raw reply related
* [PATCH v6 10/12] powercap: arm_scmi: Create synthetic parent node for multi-instance
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
An SCMI powercap instance may expose a hierarchy of domains, or even a
forest of multiple domain trees rooted at SCMI_POWERCAP_ROOT_ZONE_ID.
Those hierarchies are valid within the namespace of a single SCMI instance.
Currently, the powercap framework has no notion of SCMI instances. If root
domains from multiple SCMI instances are registered directly under the same
Linux powercap control type, the per-instance boundaries are lost and the
resulting Linux hierarchy becomes a merge of otherwise independent SCMI
topologies.
Add a synthetic top-level powercap zone per SCMI instance and register that
instance's SCMI root domains beneath it. This keeps each instance's SCMI
hierarchy grouped together.
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
V5->V6
- Amended omission of spz initialization
- Tested unloading and loading powercap module
- Re-wrote commit message
---
drivers/powercap/arm_scmi_powercap.c | 78 ++++++++++++++++++++++++++--
1 file changed, 74 insertions(+), 4 deletions(-)
diff --git a/drivers/powercap/arm_scmi_powercap.c b/drivers/powercap/arm_scmi_powercap.c
index 7f2bb162f96c..5e7b7a3b79f2 100644
--- a/drivers/powercap/arm_scmi_powercap.c
+++ b/drivers/powercap/arm_scmi_powercap.c
@@ -36,6 +36,7 @@ struct scmi_powercap_root {
struct scmi_powercap_zone *spzones;
struct list_head *registered_zones;
struct list_head scmi_zones;
+ struct scmi_powercap_zone instance_root;
};
static struct powercap_control_type *scmi_top_pcntrl;
@@ -263,12 +264,50 @@ static const struct powercap_zone_constraint_ops constraint_ops = {
.get_name = scmi_powercap_get_name,
};
+/*
+ * Multi-instance constraints to meet driver requrements due to the fact
+ * that full zone semantics aren't available for the synthetic zone.
+ */
+static int instance_root_release(struct powercap_zone *pz)
+{
+ return 0;
+}
+
+static int instance_root_get_power_uw(struct powercap_zone *pz, u64 *v)
+{
+ *v = 0;
+ return 0;
+}
+
+static int instance_root_set_constraint(struct powercap_zone *pz, int cid, u64 v)
+{
+ return -EOPNOTSUPP;
+}
+
+static int instance_root_get_constraint(struct powercap_zone *pz, int cid, u64 *v)
+{
+ return -EOPNOTSUPP;
+}
+
+static const struct powercap_zone_ops instance_root_ops = {
+ .get_max_power_range_uw = scmi_powercap_get_max_power_range_uw,
+ .get_power_uw = instance_root_get_power_uw,
+ .release = instance_root_release,
+};
+
+static const struct powercap_zone_constraint_ops instance_root_const_ops = {
+ .set_power_limit_uw = instance_root_set_constraint,
+ .get_power_limit_uw = instance_root_get_constraint,
+ .set_time_window_us = instance_root_set_constraint,
+ .get_time_window_us = instance_root_get_constraint,
+};
+
static void scmi_powercap_unregister_all_zones(struct scmi_powercap_root *pr)
{
int i;
/* Un-register children zones first starting from the leaves */
- for (i = pr->num_zones - 1; i >= 0; i--) {
+ for (i = pr->num_zones; i >= 0; i--) {
if (!list_empty(&pr->registered_zones[i])) {
struct scmi_powercap_zone *spz;
@@ -313,7 +352,10 @@ static int scmi_powercap_register_zone(struct scmi_powercap_root *pr,
parent ? &parent->zone : NULL,
&zone_ops, spz->info->num_cpli, &constraint_ops);
if (!IS_ERR(z)) {
- spz->height = scmi_powercap_get_zone_height(spz);
+ if (parent)
+ spz->height = parent->height + 1;
+ else
+ spz->height = 0;
spz->registered = true;
list_move(&spz->node, &pr->registered_zones[spz->height]);
dev_dbg(spz->dev, "Registered node %s - parent %s - height:%d\n",
@@ -384,6 +426,8 @@ static int scmi_zones_register(struct device *dev,
struct scmi_powercap_zone *parent;
parent = scmi_powercap_get_parent_zone(spz);
+ if (!parent)
+ parent = &pr->instance_root;
if (parent && !parent->registered) {
zones_stack[sp++] = spz;
spz = parent;
@@ -424,8 +468,11 @@ static int scmi_powercap_probe(struct scmi_device *sdev)
int ret, i;
struct scmi_powercap_root *pr;
struct scmi_powercap_zone *spz;
+ struct scmi_powercap_zone *ir;
struct scmi_protocol_handle *ph;
struct device *dev = &sdev->dev;
+ char *instance_name;
+ struct powercap_zone *z;
if (!sdev->handle)
return -ENODEV;
@@ -453,7 +500,7 @@ static int scmi_powercap_probe(struct scmi_device *sdev)
return -ENOMEM;
/* Allocate for worst possible scenario of maximum tree height. */
- pr->registered_zones = devm_kcalloc(dev, pr->num_zones,
+ pr->registered_zones = devm_kcalloc(dev, pr->num_zones + 1,
sizeof(*pr->registered_zones),
GFP_KERNEL);
if (!pr->registered_zones)
@@ -461,6 +508,9 @@ static int scmi_powercap_probe(struct scmi_device *sdev)
INIT_LIST_HEAD(&pr->scmi_zones);
+ for (i = 0; i <= pr->num_zones; i++)
+ INIT_LIST_HEAD(&pr->registered_zones[i]);
+
for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) {
/*
* Powercap domains are validate by the protocol layer, i.e.
@@ -473,7 +523,6 @@ static int scmi_powercap_probe(struct scmi_device *sdev)
spz->ph = ph;
spz->spzones = pr->spzones;
INIT_LIST_HEAD(&spz->node);
- INIT_LIST_HEAD(&pr->registered_zones[i]);
list_add_tail(&spz->node, &pr->scmi_zones);
/*
@@ -491,6 +540,27 @@ static int scmi_powercap_probe(struct scmi_device *sdev)
}
}
+ ir = &pr->instance_root;
+ ir->dev = dev;
+ INIT_LIST_HEAD(&ir->node);
+ instance_name = devm_kasprintf(dev, GFP_KERNEL, "instance_%s", dev_name(dev));
+ if (!instance_name)
+ return -ENOMEM;
+
+ z = powercap_register_zone(&ir->zone, scmi_top_pcntrl,
+ instance_name, NULL, &instance_root_ops, 0,
+ &instance_root_const_ops);
+
+ if (IS_ERR(z)) {
+ ret = PTR_ERR(z);
+ dev_err(dev, "Failed to register sysnthetic instance root: %d\n", ret);
+ return ret;
+ }
+
+ ir->registered = true;
+ ir->height = 0;
+ list_add_tail(&ir->node, &pr->registered_zones[0]);
+
/*
* Scan array of retrieved SCMI powercap domains and register them
* recursively starting from the root domains.
--
2.47.3
^ permalink raw reply related
* [PATCH v6 08/12] powercap: arm_scmi: Enable multiple constraints support
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Cristian Marussi,
Rafael J. Wysocki, Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
From: Cristian Marussi <cristian.marussi@arm.com>
Initialize the domains with all the discovered available constraints,
making available multiple per-domain constraints when the platform has
advertised support for multiple concurrent power limits.
CC: "Rafael J. Wysocki" <rafael@kernel.org>
CC: linux-pm@vger.kernel.org
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
[Philip: Amended Copyright]
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
drivers/powercap/arm_scmi_powercap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/powercap/arm_scmi_powercap.c b/drivers/powercap/arm_scmi_powercap.c
index be3007206a74..7f2bb162f96c 100644
--- a/drivers/powercap/arm_scmi_powercap.c
+++ b/drivers/powercap/arm_scmi_powercap.c
@@ -2,7 +2,7 @@
/*
* SCMI Powercap support.
*
- * Copyright (C) 2022 ARM Ltd.
+ * Copyright (C) 2022-2026 ARM Ltd.
*/
#include <linux/device.h>
@@ -311,7 +311,7 @@ static int scmi_powercap_register_zone(struct scmi_powercap_root *pr,
z = powercap_register_zone(&spz->zone, scmi_top_pcntrl, spz->info->name,
parent ? &parent->zone : NULL,
- &zone_ops, 1, &constraint_ops);
+ &zone_ops, spz->info->num_cpli, &constraint_ops);
if (!IS_ERR(z)) {
spz->height = scmi_powercap_get_zone_height(spz);
spz->registered = true;
--
2.47.3
^ permalink raw reply related
* [PATCH v6 09/12] firmware: arm_scmi: add Powercap MAI get/set support
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
Add support for Power Measurement Averaging Interval (MAI) get and set
operations to the SCMI powercap protocol driver. Extends scmi_powercap_info
to store MAI configuration and implement MAI get/set via xfer and optional
fast-channel support.
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
V5->V6
- Fixed comment length
- Changed warning message wording
- Fixed line lengths and alignment
- Updated docs for new fields
---
drivers/firmware/arm_scmi/powercap.c | 127 +++++++++++++++++++++++++++
include/linux/scmi_protocol.h | 18 ++++
2 files changed, 145 insertions(+)
diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c
index 09152bb8642c..dfec09fd687f 100644
--- a/drivers/firmware/arm_scmi/powercap.c
+++ b/drivers/firmware/arm_scmi/powercap.c
@@ -403,6 +403,34 @@ scmi_powercap_domain_attrs_process(const struct scmi_protocol_handle *ph,
dom_info->notify_powercap_measurement_change =
SUPPORTS_POWERCAP_MEASUREMENTS_CHANGE_NOTIFY(flags);
+ if (PROTOCOL_REV_MAJOR(ph->version) >= 0x3) {
+ struct scmi_msg_resp_powercap_domain_attributes_v3 *resp_v3 = r;
+
+ flags = le32_to_cpu(resp_v3->attributes);
+ if (pinfo->notify_measurements_cmd)
+ dom_info->notify_powercap_measurement_change =
+ SUPPORTS_POWERCAP_MEASUREMENTS_CHANGE_NOTIFY(flags);
+
+ dom_info->mai_config = SUPPORTS_POWERCAP_MAI_CONFIGURATION(flags);
+ dom_info->min_mai = le32_to_cpu(resp_v3->min_mai);
+ dom_info->max_mai = le32_to_cpu(resp_v3->max_mai);
+ dom_info->mai_step = le32_to_cpu(resp_v3->mai_step);
+
+ if (dom_info->mai_config) {
+ ret = scmi_powercap_validate(dom_info->min_mai,
+ dom_info->max_mai,
+ dom_info->mai_step,
+ dom_info->mai_config);
+
+ if (ret) {
+ dev_warn(ph->dev, "Platform reported invalid MAI config for domain %d - %s\n",
+ dom_info->id, dom_info->name);
+
+ return ret;
+ }
+ }
+ }
+
dom_info->extended_names = SUPPORTS_EXTENDED_NAMES(flags);
dom_info->async_powercap_cap_set =
@@ -1084,6 +1112,103 @@ static int scmi_powercap_cap_enable_get(const struct scmi_protocol_handle *ph,
return 0;
}
+static int scmi_powercap_xfer_mai_get(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 *mai)
+{
+ int ret;
+ struct scmi_xfer *t;
+
+ ret = ph->xops->xfer_get_init(ph, POWERCAP_MAI_GET, sizeof(u32),
+ sizeof(u32), &t);
+
+ if (ret)
+ return ret;
+
+ put_unaligned_le32(domain_id, t->tx.buf);
+
+ ret = ph->xops->do_xfer(ph, t);
+ if (!ret)
+ *mai = get_unaligned_le32(t->rx.buf);
+
+ ph->xops->xfer_put(ph, t);
+ return ret;
+}
+
+static int scmi_powercap_xfer_mai_set(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 mai)
+{
+ int ret;
+ struct scmi_xfer *t;
+ struct scmi_msg_powercap_cap_or_pai_set *msg;
+
+ ret = ph->xops->xfer_get_init(ph, POWERCAP_MAI_SET, sizeof(*msg),
+ 0, &t);
+ if (ret)
+ return ret;
+
+ msg = t->tx.buf;
+ msg->domain_id = cpu_to_le32(domain_id);
+ msg->flags = cpu_to_le32(0);
+ msg->value = cpu_to_le32(mai);
+
+ ret = ph->xops->do_xfer(ph, t);
+
+ ph->xops->xfer_put(ph, t);
+ return ret;
+}
+
+static int
+scmi_powercap_measurements_interval_get(const struct scmi_protocol_handle *ph,
+ u32 domain_id,
+ u32 *val)
+{
+ const struct scmi_powercap_info *pc;
+ struct scmi_fc_info *fci;
+
+ if (!val)
+ return -EINVAL;
+
+ pc = scmi_powercap_dom_info_get(ph, domain_id);
+ if (!pc)
+ return -EINVAL;
+
+ fci = pc->cpli[CPL0].fc_info;
+ if (fci && fci[POWERCAP_FC_MAI].get_addr) {
+ *val = ioread32(fci[POWERCAP_FC_MAI].get_addr);
+ trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_MAI_GET,
+ domain_id, 0, *val, 0);
+ return 0;
+ }
+
+ return scmi_powercap_xfer_mai_get(ph, domain_id, val);
+}
+
+static int
+scmi_powercap_measurements_interval_set(const struct scmi_protocol_handle *ph,
+ u32 domain_id,
+ u32 val)
+{
+ const struct scmi_powercap_info *pc;
+ struct scmi_fc_info *fci;
+
+ pc = scmi_powercap_dom_info_get(ph, domain_id);
+ if (!pc)
+ return -EINVAL;
+
+ if (!pc->mai_config || !val || val < pc->min_mai || val > pc->max_mai)
+ return -EINVAL;
+
+ fci = pc->cpli[CPL0].fc_info;
+ if (fci && fci[POWERCAP_FC_MAI].set_addr) {
+ iowrite32(val, fci[POWERCAP_FC_MAI].set_addr);
+ ph->hops->fastchannel_db_ring(fci[POWERCAP_FC_MAI].set_db);
+ trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_MAI_SET, domain_id, 0, val, 0);
+ return 0;
+ }
+
+ return scmi_powercap_xfer_mai_set(ph, domain_id, val);
+}
+
static const struct scmi_powercap_proto_ops powercap_proto_ops = {
.num_domains_get = scmi_powercap_num_domains_get,
.info_get = scmi_powercap_dom_info_get,
@@ -1096,6 +1221,8 @@ static const struct scmi_powercap_proto_ops powercap_proto_ops = {
.measurements_get = scmi_powercap_measurements_get,
.measurements_threshold_set = scmi_powercap_measurements_threshold_set,
.measurements_threshold_get = scmi_powercap_measurements_threshold_get,
+ .measurements_interval_get = scmi_powercap_measurements_interval_get,
+ .measurements_interval_set = scmi_powercap_measurements_interval_set,
};
static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph,
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index d0f6c0102559..90615611be4a 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -654,6 +654,12 @@ struct scmi_powercap_cpl_info {
* reports power data on an abstract linear scale.
* @extended_names: Support for long names.
* @fastchannels: Support for at least one fastchannel,
+ * @mai_config: MAI configuration support.
+ * @min_mai: Minimum supported Power Measurement Averaging Interval in
+ * microseconds.
+ * @max_mai: Maximum supporte Power Measurement Averaging Interval in
+ microseconds.
+ * @mai_step: Step size between supported MAI values in microseconds.
* @name: name assigned to the Powercap Domain by platform.
* @sustainable_power: Maximum sustainable power consumption for this domain
* under normal conditions.
@@ -675,6 +681,10 @@ struct scmi_powercap_info {
bool powercap_scale_uw;
bool extended_names;
bool fastchannels;
+ bool mai_config;
+ u32 min_mai;
+ u32 max_mai;
+ u32 mai_step;
char name[SCMI_MAX_STR_SIZE];
unsigned int sustainable_power;
unsigned int accuracy;
@@ -733,6 +743,10 @@ struct scmi_powercap_info {
* @measurements_threshold_get: get the currently configured low and high power
* thresholds used when registering callbacks for
* notification POWERCAP_MEASUREMENTS_NOTIFY.
+ * @measurements_interval_get: get the current Power Measurement Averaging
+ * Interval (MAI) value for the specified domain.
+ * @measurements_interval_set: set the Power Measurement Averaging Interval
+ * (MAI) value for the specified domain.
*/
struct scmi_powercap_proto_ops {
int (*num_domains_get)(const struct scmi_protocol_handle *ph);
@@ -758,6 +772,10 @@ struct scmi_powercap_proto_ops {
int (*measurements_threshold_get)(const struct scmi_protocol_handle *ph,
u32 domain_id, u32 *power_thresh_low,
u32 *power_thresh_high);
+ int (*measurements_interval_get)(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 *val);
+ int (*measurements_interval_set)(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 val);
};
enum scmi_pinctrl_selector_type {
--
2.47.3
^ permalink raw reply related
* [PATCH v6 07/12] include: trace: Add new parameter to trace_scmi_fc_call
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Cristian Marussi,
Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
From: Cristian Marussi <cristian.marussi@arm.com>
Since SCMIv4.0 some of the supported Fastchannels can be configured using
an additional parameter like CPL_ID or Capability_ID.
Add equivalent support in the SCMI fastchannel traces to printout also such
parameter and fix all the existent call sites.
When such parameter is not used, it will simply show up as zero.
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
drivers/firmware/arm_scmi/perf.c | 8 ++++----
drivers/firmware/arm_scmi/powercap.c | 12 +++++++-----
include/trace/events/scmi.h | 12 +++++++-----
3 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 7f283f457e02..88d614e3184b 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -552,7 +552,7 @@ static int __scmi_perf_limits_set(const struct scmi_protocol_handle *ph,
struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LIMIT];
trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LIMITS_SET,
- dom->id, min_perf, max_perf);
+ dom->id, 0, min_perf, max_perf);
iowrite32(max_perf, fci->set_addr);
iowrite32(min_perf, fci->set_addr + 4);
ph->hops->fastchannel_db_ring(fci->set_db);
@@ -636,7 +636,7 @@ static int __scmi_perf_limits_get(const struct scmi_protocol_handle *ph,
*max_perf = ioread32(fci->get_addr);
*min_perf = ioread32(fci->get_addr + 4);
trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LIMITS_GET,
- dom->id, *min_perf, *max_perf);
+ dom->id, 0, *min_perf, *max_perf);
return 0;
}
@@ -706,7 +706,7 @@ static int __scmi_perf_level_set(const struct scmi_protocol_handle *ph,
struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LEVEL];
trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LEVEL_SET,
- dom->id, level, 0);
+ dom->id, 0, level, 0);
iowrite32(level, fci->set_addr);
ph->hops->fastchannel_db_ring(fci->set_db);
return 0;
@@ -769,7 +769,7 @@ static int __scmi_perf_level_get(const struct scmi_protocol_handle *ph,
if (dom->fc_info && dom->fc_info[PERF_FC_LEVEL].get_addr) {
*level = ioread32(dom->fc_info[PERF_FC_LEVEL].get_addr);
trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LEVEL_GET,
- dom->id, *level, 0);
+ dom->id, 0, *level, 0);
return 0;
}
diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c
index fdfaf03277ab..09152bb8642c 100644
--- a/drivers/firmware/arm_scmi/powercap.c
+++ b/drivers/firmware/arm_scmi/powercap.c
@@ -599,7 +599,7 @@ static int __scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
dom->cpli[cpl_id].fc_info[POWERCAP_FC_CAP].get_addr) {
*power_cap = ioread32(dom->cpli[cpl_id].fc_info[POWERCAP_FC_CAP].get_addr);
trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_GET,
- dom->id, *power_cap, 0);
+ dom->id, cpl_id, *power_cap, 0);
return 0;
}
@@ -732,7 +732,7 @@ static int __scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
iowrite32(power_cap, fci->set_addr);
ph->hops->fastchannel_db_ring(fci->set_db);
trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_SET,
- domain_id, power_cap, 0);
+ domain_id, cpl_id, power_cap, 0);
ret = 0;
} else {
ret = pi->xfer_cap_set(ph, pc, cpl_id, power_cap, ignore_dresp);
@@ -837,7 +837,8 @@ static int scmi_powercap_avg_interval_get(const struct scmi_protocol_handle *ph,
POWERCAP_PAI_GET : POWERCAP_CAI_GET;
*val = ioread32(dom->cpli[cpl_id].fc_info[POWERCAP_FC_XAI].get_addr);
- trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, trace_cmd, domain_id, *val, 0);
+ trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, trace_cmd, domain_id,
+ cpl_id, *val, 0);
return 0;
}
@@ -910,7 +911,8 @@ static int scmi_powercap_avg_interval_set(const struct scmi_protocol_handle *ph,
POWERCAP_PAI_SET : POWERCAP_CAI_SET;
struct scmi_fc_info *fci = &pc->cpli[cpl_id].fc_info[POWERCAP_FC_XAI];
- trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, trace_cmd, domain_id, ivl, 0);
+ trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, trace_cmd, domain_id,
+ cpl_id, ivl, 0);
iowrite32(ivl, fci->set_addr);
ph->hops->fastchannel_db_ring(fci->set_db);
return 0;
@@ -963,7 +965,7 @@ static int scmi_powercap_measurements_get(const struct scmi_protocol_handle *ph,
/* See SCMIv4.0 3.10.2 - Payload is 32bit ONLY avg_power */
*avg_ivl = 0;
trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_MEASUREMENTS_GET,
- pc->id, *avg_power, *avg_ivl);
+ pc->id, 0, *avg_power, *avg_ivl);
return 0;
}
diff --git a/include/trace/events/scmi.h b/include/trace/events/scmi.h
index 703b7bb68e44..b03da7323d04 100644
--- a/include/trace/events/scmi.h
+++ b/include/trace/events/scmi.h
@@ -10,13 +10,14 @@
#define TRACE_SCMI_MAX_TAG_LEN 6
TRACE_EVENT(scmi_fc_call,
- TP_PROTO(u8 protocol_id, u8 msg_id, u32 res_id, u32 val1, u32 val2),
- TP_ARGS(protocol_id, msg_id, res_id, val1, val2),
+ TP_PROTO(u8 protocol_id, u8 msg_id, u32 res_id, u32 sub_id, u32 val1, u32 val2),
+ TP_ARGS(protocol_id, msg_id, res_id, sub_id, val1, val2),
TP_STRUCT__entry(
__field(u8, protocol_id)
__field(u8, msg_id)
__field(u32, res_id)
+ __field(u32, sub_id)
__field(u32, val1)
__field(u32, val2)
),
@@ -25,13 +26,14 @@ TRACE_EVENT(scmi_fc_call,
__entry->protocol_id = protocol_id;
__entry->msg_id = msg_id;
__entry->res_id = res_id;
+ __entry->sub_id = sub_id;
__entry->val1 = val1;
__entry->val2 = val2;
),
- TP_printk("pt=%02X msg_id=%02X res_id:%u vals=%u:%u",
- __entry->protocol_id, __entry->msg_id,
- __entry->res_id, __entry->val1, __entry->val2)
+ TP_printk("pt=%02X msg_id=%02X res_id:%u sub_id:%u vals=%u:%u",
+ __entry->protocol_id, __entry->msg_id,
+ __entry->res_id, __entry->sub_id, __entry->val1, __entry->val2)
);
TRACE_EVENT(scmi_xfer_begin,
--
2.47.3
^ permalink raw reply related
* [PATCH v6 04/12] firmware: arm_scmi: Add SCMIv4.0 Powercap FCs support
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Cristian Marussi,
Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
From: Cristian Marussi <cristian.marussi@arm.com>
Add support for new SCMIv4.0 Powercap Fastchannels.
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
[Philip: removed reference to old versioning logic]
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
V2->V4
- moved fastchannel inits outside of loop
- renamed arguments for consistency
---
drivers/firmware/arm_scmi/powercap.c | 331 ++++++++++++++++++---------
1 file changed, 229 insertions(+), 102 deletions(-)
diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c
index 3291bde78367..db5bc4f38ea4 100644
--- a/drivers/firmware/arm_scmi/powercap.c
+++ b/drivers/firmware/arm_scmi/powercap.c
@@ -27,19 +27,25 @@ enum scmi_powercap_protocol_cmd {
POWERCAP_CAP_GET = 0x4,
POWERCAP_CAP_SET = 0x5,
POWERCAP_PAI_GET = 0x6,
+ POWERCAP_MAI_GET = POWERCAP_PAI_GET,
POWERCAP_PAI_SET = 0x7,
+ POWERCAP_MAI_SET = POWERCAP_PAI_SET,
POWERCAP_DOMAIN_NAME_GET = 0x8,
POWERCAP_MEASUREMENTS_GET = 0x9,
POWERCAP_CAP_NOTIFY = 0xa,
POWERCAP_MEASUREMENTS_NOTIFY = 0xb,
POWERCAP_DESCRIBE_FASTCHANNEL = 0xc,
POWERCAP_CPC_ATTRIBUTES = 0xd,
+ POWERCAP_CAI_GET = 0xe,
+ POWERCAP_CAI_SET = 0xf,
};
enum {
POWERCAP_FC_CAP,
- POWERCAP_FC_PAI,
- POWERCAP_FC_MAX,
+ POWERCAP_FC_XAI,
+ POWERCAP_FC_MAI,
+ POWERCAP_FC_MEASUREMENT,
+ POWERCAP_FC_MAX
};
struct scmi_msg_resp_powercap_domain_attributes {
@@ -91,12 +97,12 @@ struct scmi_msg_resp_powercap_domain_attributes_v3 {
__le32 cai_step;
};
-struct scmi_msg_powercap_get_v3 {
+struct scmi_msg_powercap_cap_or_cai_get_v3 {
__le32 domain_id;
__le32 cpli;
};
-struct scmi_msg_powercap_set_cap_or_pai {
+struct scmi_msg_powercap_cap_or_pai_set {
__le32 domain_id;
__le32 flags;
#define CAP_SET_ASYNC BIT(1)
@@ -104,13 +110,20 @@ struct scmi_msg_powercap_set_cap_or_pai {
__le32 value;
};
-struct scmi_msg_powercap_set_cap_v3 {
+struct scmi_msg_powercap_cap_set_v3 {
__le32 domain_id;
__le32 cpli;
__le32 flags;
__le32 power_cap;
};
+struct scmi_msg_powercap_cai_set {
+ __le32 domain_id;
+ __le32 flags;
+ __le32 cai;
+ __le32 cpli;
+};
+
struct scmi_msg_resp_powercap_cap_set_complete {
__le32 domain_id;
__le32 power_cap;
@@ -201,6 +214,10 @@ struct powercap_info {
int (*xfer_cap_set)(const struct scmi_protocol_handle *ph,
const struct scmi_powercap_info *pc,
u32 cpl_id, u32 power_cap, bool ignore_dresp);
+ int (*xfer_avg_ivl_get)(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 *ivl);
+ int (*xfer_avg_ivl_set)(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 ivl);
};
static enum scmi_powercap_protocol_cmd evt_2_cmd[] = {
@@ -501,17 +518,6 @@ scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph,
return ret;
}
-static int
-scmi_powercap_domain_initialize(const struct scmi_protocol_handle *ph,
- struct powercap_info *pinfo, u32 domain)
-{
- struct scmi_powercap_info *dom_info = pinfo->powercaps + domain;
-
- dom_info->id = domain;
-
- return scmi_powercap_domain_attributes_get(ph, pinfo, dom_info);
-}
-
static int scmi_powercap_num_domains_get(const struct scmi_protocol_handle *ph)
{
struct powercap_info *pi = ph->get_priv(ph);
@@ -558,7 +564,7 @@ static int scmi_powercap_xfer_cap_get_v3(const struct scmi_protocol_handle *ph,
{
int ret;
struct scmi_xfer *t;
- struct scmi_msg_powercap_get_v3 *msg;
+ struct scmi_msg_powercap_cap_or_cai_get_v3 *msg;
ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_GET, sizeof(*msg),
sizeof(u32), &t);
@@ -617,7 +623,7 @@ static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph,
{
int ret;
struct scmi_xfer *t;
- struct scmi_msg_powercap_set_cap_or_pai *msg;
+ struct scmi_msg_powercap_cap_or_pai_set *msg;
ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_SET,
sizeof(*msg), 0, &t);
@@ -660,7 +666,7 @@ static int scmi_powercap_xfer_cap_set_v3(const struct scmi_protocol_handle *ph,
{
int ret;
struct scmi_xfer *t;
- struct scmi_msg_powercap_set_cap_v3 *msg;
+ struct scmi_msg_powercap_cap_set_v3 *msg;
ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_SET,
sizeof(*msg), 0, &t);
@@ -759,8 +765,9 @@ static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
power_cap, ignore_dresp);
}
-static int scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 *pai)
+static int
+scmi_powercap_xfer_avg_interval_get(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 *ivl)
{
int ret;
struct scmi_xfer *t;
@@ -773,58 +780,105 @@ static int scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle *ph,
put_unaligned_le32(domain_id, t->tx.buf);
ret = ph->xops->do_xfer(ph, t);
if (!ret)
- *pai = get_unaligned_le32(t->rx.buf);
+ *ivl = get_unaligned_le32(t->rx.buf);
+
+ ph->xops->xfer_put(ph, t);
+
+ return ret;
+}
+
+static int
+scmi_powercap_xfer_avg_interval_get_v3(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 *ivl)
+{
+ int ret;
+ struct scmi_xfer *t;
+ struct scmi_msg_powercap_cap_or_cai_get_v3 *msg;
+
+ ret = ph->xops->xfer_get_init(ph, POWERCAP_CAI_GET, sizeof(*msg),
+ sizeof(u32), &t);
+ if (ret)
+ return ret;
+
+ msg = t->tx.buf;
+ msg->domain_id = cpu_to_le32(domain_id);
+ msg->cpli = cpu_to_le32(cpl_id);
+
+ ret = ph->xops->do_xfer(ph, t);
+ if (!ret)
+ *ivl = get_unaligned_le32(t->rx.buf);
ph->xops->xfer_put(ph, t);
return ret;
}
-static int scmi_powercap_pai_get(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 cpl_id, u32 *pai)
+static int scmi_powercap_avg_interval_get(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 *val)
{
struct scmi_powercap_info *dom;
struct powercap_info *pi = ph->get_priv(ph);
- if (!pai || domain_id >= pi->num_domains)
+ if (!val || domain_id >= pi->num_domains)
return -EINVAL;
dom = pi->powercaps + domain_id;
if (cpl_id >= dom->num_cpli)
return -EINVAL;
- if (dom->cpli[cpl_id].fc_info && dom->cpli[cpl_id].fc_info[POWERCAP_FC_PAI].get_addr) {
- *pai = ioread32(dom->cpli[cpl_id].fc_info[POWERCAP_FC_PAI].get_addr);
- trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_GET,
- domain_id, *pai, 0);
+ if (dom->cpli[cpl_id].fc_info &&
+ dom->cpli[cpl_id].fc_info[POWERCAP_FC_XAI].get_addr) {
+ int trace_cmd = (PROTOCOL_REV_MAJOR(ph->version) < 0x3) ?
+ POWERCAP_PAI_GET : POWERCAP_CAI_GET;
+
+ *val = ioread32(dom->cpli[cpl_id].fc_info[POWERCAP_FC_XAI].get_addr);
+ trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, trace_cmd, domain_id, *val, 0);
return 0;
}
- return scmi_powercap_xfer_pai_get(ph, domain_id, pai);
+ return pi->xfer_avg_ivl_get(ph, domain_id, cpl_id, val);
}
-static int scmi_powercap_avg_interval_get(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 cpl_id, u32 *val)
+static int
+scmi_powercap_xfer_avg_interval_set(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 ivl)
{
- return scmi_powercap_pai_get(ph, domain_id, cpl_id, val);
+ int ret;
+ struct scmi_xfer *t;
+ struct scmi_msg_powercap_cap_or_pai_set *msg;
+
+ ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_SET, sizeof(*msg), 0, &t);
+ if (ret)
+ return ret;
+
+ msg = t->tx.buf;
+ msg->domain_id = cpu_to_le32(domain_id);
+ msg->flags = cpu_to_le32(0);
+ msg->value = cpu_to_le32(ivl);
+
+ ret = ph->xops->do_xfer(ph, t);
+
+ ph->xops->xfer_put(ph, t);
+ return ret;
}
-static int scmi_powercap_xfer_pai_set(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 pai)
+static int
+scmi_powercap_xfer_avg_interval_set_v3(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 ivl)
{
int ret;
struct scmi_xfer *t;
- struct scmi_msg_powercap_set_cap_or_pai *msg;
+ struct scmi_msg_powercap_cai_set *msg;
- ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_SET,
- sizeof(*msg), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, POWERCAP_CAI_SET, sizeof(*msg), 0, &t);
if (ret)
return ret;
msg = t->tx.buf;
msg->domain_id = cpu_to_le32(domain_id);
msg->flags = cpu_to_le32(0);
- msg->value = cpu_to_le32(pai);
+ msg->cai = cpu_to_le32(ivl);
+ msg->cpli = cpu_to_le32(cpl_id);
ret = ph->xops->do_xfer(ph, t);
@@ -832,48 +886,42 @@ static int scmi_powercap_xfer_pai_set(const struct scmi_protocol_handle *ph,
return ret;
}
-static int scmi_powercap_pai_set(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 cpl_id, u32 pai)
+static int scmi_powercap_avg_interval_set(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 ivl)
{
const struct scmi_powercap_info *pc;
+ struct powercap_info *pi = ph->get_priv(ph);
pc = scmi_powercap_dom_info_get(ph, domain_id);
if (!pc || cpl_id >= pc->num_cpli || !pc->cpli[cpl_id].avg_ivl_config ||
- !pai || pai < pc->cpli[cpl_id].min_avg_ivl ||
- pai > pc->cpli[cpl_id].max_avg_ivl)
+ !ivl || ivl < pc->cpli[cpl_id].min_avg_ivl ||
+ ivl > pc->cpli[cpl_id].max_avg_ivl)
return -EINVAL;
- if (pc->cpli[cpl_id].fc_info && pc->cpli[cpl_id].fc_info[POWERCAP_FC_PAI].set_addr) {
- struct scmi_fc_info *fci = &pc->cpli[cpl_id].fc_info[POWERCAP_FC_PAI];
+ /* Note that fc_info descriptors for any unsupported FC will be NULL */
+ if (pc->cpli[cpl_id].fc_info &&
+ pc->cpli[cpl_id].fc_info[POWERCAP_FC_XAI].set_addr) {
+ int trace_cmd = (PROTOCOL_REV_MAJOR(ph->version) < 0x3) ?
+ POWERCAP_PAI_SET : POWERCAP_CAI_SET;
+ struct scmi_fc_info *fci = &pc->cpli[cpl_id].fc_info[POWERCAP_FC_XAI];
- trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_SET,
- domain_id, pai, 0);
- iowrite32(pai, fci->set_addr);
+ trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, trace_cmd, domain_id, ivl, 0);
+ iowrite32(ivl, fci->set_addr);
ph->hops->fastchannel_db_ring(fci->set_db);
return 0;
}
- return scmi_powercap_xfer_pai_set(ph, domain_id, pai);
-}
-
-static int scmi_powercap_avg_interval_set(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 cpl_id, u32 val)
-{
- return scmi_powercap_pai_set(ph, domain_id, cpl_id, val);
+ return pi->xfer_avg_ivl_set(ph, domain_id, cpl_id, ivl);
}
-static int scmi_powercap_measurements_get(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 *average_power,
- u32 *pai)
+static int
+scmi_powercap_xfer_measurements_get(const struct scmi_protocol_handle *ph,
+ const struct scmi_powercap_info *pc,
+ u32 *avg_power, u32 *avg_ivl)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_resp_powercap_meas_get *resp;
- const struct scmi_powercap_info *pc;
-
- pc = scmi_powercap_dom_info_get(ph, domain_id);
- if (!pc || !pc->powercap_monitoring || !pai || !average_power)
- return -EINVAL;
ret = ph->xops->xfer_get_init(ph, POWERCAP_MEASUREMENTS_GET,
sizeof(u32), sizeof(*resp), &t);
@@ -881,17 +929,42 @@ static int scmi_powercap_measurements_get(const struct scmi_protocol_handle *ph,
return ret;
resp = t->rx.buf;
- put_unaligned_le32(domain_id, t->tx.buf);
+ put_unaligned_le32(pc->id, t->tx.buf);
ret = ph->xops->do_xfer(ph, t);
if (!ret) {
- *average_power = le32_to_cpu(resp->power);
- *pai = le32_to_cpu(resp->pai);
+ *avg_power = le32_to_cpu(resp->power);
+ *avg_ivl = le32_to_cpu(resp->pai);
}
ph->xops->xfer_put(ph, t);
return ret;
}
+static int scmi_powercap_measurements_get(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 *avg_power,
+ u32 *avg_ivl)
+{
+ const struct scmi_powercap_info *pc;
+ struct scmi_fc_info *fci;
+
+ pc = scmi_powercap_dom_info_get(ph, domain_id);
+ if (!pc || !pc->powercap_monitoring || !avg_ivl || !avg_power)
+ return -EINVAL;
+
+ /* Note that fc_info descriptors for any unsupported FC will be NULL */
+ fci = pc->cpli[CPL0].fc_info;
+ if (fci && fci[POWERCAP_FC_MEASUREMENT].get_addr) {
+ *avg_power = ioread32(fci[POWERCAP_FC_MEASUREMENT].get_addr);
+ /* See SCMIv4.0 3.10.2 - Payload is 32bit ONLY avg_power */
+ *avg_ivl = 0;
+ trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_MEASUREMENTS_GET,
+ pc->id, *avg_power, *avg_ivl);
+ return 0;
+ }
+
+ return scmi_powercap_xfer_measurements_get(ph, pc, avg_power, avg_ivl);
+}
+
static int
scmi_powercap_measurements_threshold_get(const struct scmi_protocol_handle *ph,
u32 domain_id, u32 *power_thresh_low,
@@ -1019,37 +1092,85 @@ static const struct scmi_powercap_proto_ops powercap_proto_ops = {
};
static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph,
- u32 domain, struct scmi_fc_info **p_fc)
+ struct scmi_powercap_info *dom_info)
{
- struct scmi_fc_info *fc;
-
- fc = devm_kcalloc(ph->dev, POWERCAP_FC_MAX, sizeof(*fc), GFP_KERNEL);
- if (!fc)
- return;
-
- ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
- POWERCAP_CAP_SET, 4, domain, NULL,
- &fc[POWERCAP_FC_CAP].set_addr,
- &fc[POWERCAP_FC_CAP].set_db,
- &fc[POWERCAP_FC_CAP].rate_limit);
-
- ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
- POWERCAP_CAP_GET, 4, domain, NULL,
- &fc[POWERCAP_FC_CAP].get_addr, NULL,
- &fc[POWERCAP_FC_CAP].rate_limit);
-
- ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
- POWERCAP_PAI_SET, 4, domain, NULL,
- &fc[POWERCAP_FC_PAI].set_addr,
- &fc[POWERCAP_FC_PAI].set_db,
- &fc[POWERCAP_FC_PAI].rate_limit);
-
- ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
- POWERCAP_PAI_GET, 4, domain, NULL,
- &fc[POWERCAP_FC_PAI].get_addr, NULL,
- &fc[POWERCAP_FC_PAI].rate_limit);
-
- *p_fc = fc;
+ struct scmi_fc_info *fc_cpl0;
+
+ for (int id = 0; id < dom_info->num_cpli; id++) {
+ struct scmi_fc_info *fc;
+ u32 *cpl_id, zero_cpl_id = 0;
+
+ fc = devm_kcalloc(ph->dev, POWERCAP_FC_MAX, sizeof(*fc), GFP_KERNEL);
+ if (!fc)
+ return;
+
+ /* NOTE THAT when num_cpli == 1 the arg *cpl_id is 0 */
+ cpl_id = (PROTOCOL_REV_MAJOR(ph->version) >= 0x3) ? &id : NULL;
+
+ ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
+ POWERCAP_CAP_SET, 4, dom_info->id,
+ cpl_id,
+ &fc[POWERCAP_FC_CAP].set_addr,
+ &fc[POWERCAP_FC_CAP].set_db,
+ &fc[POWERCAP_FC_CAP].rate_limit);
+
+ ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
+ POWERCAP_CAP_GET, 4, dom_info->id,
+ cpl_id,
+ &fc[POWERCAP_FC_CAP].get_addr, NULL,
+ &fc[POWERCAP_FC_CAP].rate_limit);
+
+ if (PROTOCOL_REV_MAJOR(ph->version) >= 0x3) {
+ ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
+ POWERCAP_CAI_SET, 4,
+ dom_info->id, cpl_id,
+ &fc[POWERCAP_FC_XAI].set_addr,
+ &fc[POWERCAP_FC_XAI].set_db,
+ &fc[POWERCAP_FC_XAI].rate_limit);
+ ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
+ POWERCAP_CAI_GET, 4,
+ dom_info->id, cpl_id,
+ &fc[POWERCAP_FC_XAI].get_addr, NULL,
+ &fc[POWERCAP_FC_XAI].rate_limit);
+ ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
+ POWERCAP_MAI_SET, 4,
+ dom_info->id, &zero_cpl_id,
+ &fc[POWERCAP_FC_MAI].set_addr,
+ &fc[POWERCAP_FC_MAI].set_db,
+ &fc[POWERCAP_FC_MAI].rate_limit);
+
+ ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
+ POWERCAP_MAI_GET, 4,
+ dom_info->id, &zero_cpl_id,
+ &fc[POWERCAP_FC_MAI].get_addr, NULL,
+ &fc[POWERCAP_FC_MAI].rate_limit);
+
+ ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
+ POWERCAP_MEASUREMENTS_GET, 4,
+ dom_info->id, &zero_cpl_id,
+ &fc[POWERCAP_FC_MEASUREMENT].get_addr, NULL,
+ &fc[POWERCAP_FC_MEASUREMENT].rate_limit);
+ }
+
+ dom_info->cpli[id].fc_info = fc;
+ }
+
+ if (PROTOCOL_REV_MAJOR(ph->version) < 0x3) {
+ fc_cpl0 = dom_info->cpli[CPL0].fc_info;
+ ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
+ POWERCAP_PAI_SET, 4,
+ dom_info->id, NULL,
+ &fc_cpl0[POWERCAP_FC_XAI].set_addr,
+ &fc_cpl0[POWERCAP_FC_XAI].set_db,
+ &fc_cpl0[POWERCAP_FC_XAI].rate_limit);
+
+ ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
+ POWERCAP_PAI_GET, 4,
+ dom_info->id, NULL,
+ &fc_cpl0[POWERCAP_FC_XAI].get_addr, NULL,
+ &fc_cpl0[POWERCAP_FC_XAI].rate_limit);
+ }
+
}
static int scmi_powercap_notify(const struct scmi_protocol_handle *ph,
@@ -1286,9 +1407,14 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
if (PROTOCOL_REV_MAJOR(ph->version) < 0x3) {
pinfo->xfer_cap_get = scmi_powercap_xfer_cap_get;
pinfo->xfer_cap_set = scmi_powercap_xfer_cap_set;
+ pinfo->xfer_avg_ivl_get = scmi_powercap_xfer_avg_interval_get;
+ pinfo->xfer_avg_ivl_set = scmi_powercap_xfer_avg_interval_set;
+
} else {
pinfo->xfer_cap_get = scmi_powercap_xfer_cap_get_v3;
pinfo->xfer_cap_set = scmi_powercap_xfer_cap_set_v3;
+ pinfo->xfer_avg_ivl_get = scmi_powercap_xfer_avg_interval_get_v3;
+ pinfo->xfer_avg_ivl_set = scmi_powercap_xfer_avg_interval_set_v3;
}
ret = scmi_powercap_attributes_get(ph, pinfo);
@@ -1313,18 +1439,19 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
* formed and correlated by sane parent-child relationship (if any).
*/
for (domain = 0; domain < pinfo->num_domains; domain++) {
- ret = scmi_powercap_domain_initialize(ph, pinfo, domain);
+ struct scmi_powercap_info *dom_info = pinfo->powercaps + domain;
+
+ dom_info->id = domain;
+ ret = scmi_powercap_domain_attributes_get(ph, pinfo, dom_info);
if (ret)
return ret;
- if (pinfo->powercaps[domain].fastchannels)
- scmi_powercap_domain_init_fc(ph, domain,
- &pinfo->powercaps[domain].cpli[CPL0].fc_info);
+ if (dom_info->fastchannels)
+ scmi_powercap_domain_init_fc(ph, dom_info);
/* Grab initial state when disable is supported. */
if (PROTOCOL_REV_MAJOR(ph->version) >= 0x2) {
- ret = __scmi_powercap_cap_get(ph,
- &pinfo->powercaps[domain], CPL0,
+ ret = __scmi_powercap_cap_get(ph, dom_info, CPL0,
&pinfo->states[domain].last_pcap);
if (ret)
return ret;
--
2.47.3
^ permalink raw reply related
* [PATCH v6 06/12] firmware: arm_scmi: Extend powercap report to include MAI
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
Extend scmi_powercap_meas_changed_report to include MAI change
notifications.
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
V5->V6
- Re-worded existing comment for POWERCAP_MEASUREMENTS_NOTIFY
- Added define for V2/V3 sizes
- Used new definitions
---
drivers/firmware/arm_scmi/powercap.c | 28 +++++++++++++++-------------
include/linux/scmi_protocol.h | 1 +
2 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c
index 1d1188e98d49..fdfaf03277ab 100644
--- a/drivers/firmware/arm_scmi/powercap.c
+++ b/drivers/firmware/arm_scmi/powercap.c
@@ -11,6 +11,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/scmi_protocol.h>
+#include <linux/stddef.h>
#include <trace/events/scmi.h>
@@ -21,6 +22,8 @@
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x30000
#define CPL0 0
+#define SZ_V2 (sizeof(struct scmi_powercap_meas_changed_notify_payld))
+#define SZ_V3 (SZ_V2 - sizeof(__le32))
enum scmi_powercap_protocol_cmd {
POWERCAP_DOMAIN_ATTRIBUTES = 0x3,
@@ -164,6 +167,7 @@ struct scmi_powercap_meas_changed_notify_payld {
__le32 agent_id;
__le32 domain_id;
__le32 power;
+ __le32 mai;
};
struct scmi_msg_powercap_cpc {
@@ -1201,24 +1205,18 @@ static int scmi_powercap_notify(const struct scmi_protocol_handle *ph,
struct scmi_msg_powercap_notify_thresh *notify;
/*
- * Note that we have to pick the most recently configured
- * thresholds to build a proper POWERCAP_MEASUREMENTS_NOTIFY
- * enable request and we fail, complaining, if no thresholds
- * were ever set, since this is an indication the API has been
- * used wrongly.
+ * Build the POWERCAP_MEASUREMENTS_NOTIFY enable request using the
+ * most recently configured thresholds.
+ *
+ * The absence of thresholds is not considered an error:
+ * notifications can still be generated to report MAI changes, even
+ * when low and high are set to zero.
*/
ret = scmi_powercap_measurements_threshold_get(ph, domain,
&low, &high);
if (ret)
return ret;
- if (enable && !low && !high) {
- dev_err(ph->dev,
- "Invalid Measurements Notify thresholds: %u/%u\n",
- low, high);
- return -EINVAL;
- }
-
ret = ph->xops->xfer_get_init(ph, message_id,
sizeof(*notify), 0, &t);
if (ret)
@@ -1334,13 +1332,17 @@ scmi_powercap_fill_custom_report(const struct scmi_protocol_handle *ph,
const struct scmi_powercap_meas_changed_notify_payld *p = payld;
struct scmi_powercap_meas_changed_report *r = report;
- if (sizeof(*p) != payld_sz)
+ if (payld_sz != SZ_V2 && payld_sz != SZ_V3)
break;
r->timestamp = timestamp;
r->agent_id = le32_to_cpu(p->agent_id);
r->domain_id = le32_to_cpu(p->domain_id);
r->power = le32_to_cpu(p->power);
+ r->mai = 0;
+ if (payld_sz == SZ_V3 && PROTOCOL_REV_MAJOR(ph->version) >= 0x3)
+ r->mai = le32_to_cpu(p->mai);
+
*src_id = r->domain_id;
rep = r;
break;
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 299fa8499b3f..d0f6c0102559 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -1134,5 +1134,6 @@ struct scmi_powercap_meas_changed_report {
unsigned int agent_id;
unsigned int domain_id;
unsigned int power;
+ unsigned int mai;
};
#endif /* _LINUX_SCMI_PROTOCOL_H */
--
2.47.3
^ permalink raw reply related
* [PATCH v6 05/12] firmware: arm_scmi: Add SCMIV4.0 Powercap notifications support
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Cristian Marussi,
Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
From: Cristian Marussi <cristian.marussi@arm.com>
Extend notification support to the new SCMIv4.0 Powercap format that carry
also a CPL identifier where specified.
Since this addition completes SCMIv4.0 Powercap support bump also the
protocol version define.
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
drivers/firmware/arm_scmi/powercap.c | 13 +++++++++----
include/linux/scmi_protocol.h | 3 ++-
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c
index db5bc4f38ea4..1d1188e98d49 100644
--- a/drivers/firmware/arm_scmi/powercap.c
+++ b/drivers/firmware/arm_scmi/powercap.c
@@ -18,7 +18,7 @@
#include "notify.h"
/* Updated only after ALL the mandatory features for that version are merged */
-#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20000
+#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x30000
#define CPL0 0
@@ -156,7 +156,8 @@ struct scmi_powercap_cap_changed_notify_payld {
__le32 agent_id;
__le32 domain_id;
__le32 power_cap;
- __le32 pai;
+ __le32 avg_ivl;
+ __le32 cpli;
};
struct scmi_powercap_meas_changed_notify_payld {
@@ -1312,14 +1313,18 @@ scmi_powercap_fill_custom_report(const struct scmi_protocol_handle *ph,
const struct scmi_powercap_cap_changed_notify_payld *p = payld;
struct scmi_powercap_cap_changed_report *r = report;
- if (sizeof(*p) != payld_sz)
+ if (sizeof(*p) > payld_sz)
break;
r->timestamp = timestamp;
r->agent_id = le32_to_cpu(p->agent_id);
r->domain_id = le32_to_cpu(p->domain_id);
r->power_cap = le32_to_cpu(p->power_cap);
- r->pai = le32_to_cpu(p->pai);
+ r->avg_ivl = le32_to_cpu(p->avg_ivl);
+ if (sizeof(*p) == payld_sz)
+ r->cpli = le32_to_cpu(p->cpli);
+ else
+ r->cpli = 0;
*src_id = r->domain_id;
rep = r;
break;
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 547ab4763a63..299fa8499b3f 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -1125,7 +1125,8 @@ struct scmi_powercap_cap_changed_report {
unsigned int agent_id;
unsigned int domain_id;
unsigned int power_cap;
- unsigned int pai;
+ unsigned int avg_ivl;
+ unsigned int cpli;
};
struct scmi_powercap_meas_changed_report {
--
2.47.3
^ 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