Devicetree
 help / color / mirror / Atom feed
* [PATCH v5 2/4] media: dt-bindings: qcom-sc7180-venus: move video-firmware here
From: Dmitry Baryshkov @ 2026-03-27 20:19 UTC (permalink / raw)
  To: Vikash Garodia, Dikshita Agarwal, Abhinav Kumar,
	Bryan O'Donoghue, Mauro Carvalho Chehab,
	cros-qcom-dts-watchers, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Stanimir Varbanov
  Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
	Krzysztof Kozlowski
In-Reply-To: <20260327-venus-iris-flip-switch-v5-0-2f4b6c636927@oss.qualcomm.com>

As SC7180 is the only remaining user of the non-TZ / non-PAS setup which
uses the video-firmware subnode, move its definition from the common
schema to the SC7180-specific one.

These properties do not accurately describe the hardware.  Future
platforms that are going to support non-TZ setup will use different
semantics and different DT ABI (using the iommu-map property).

Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
 .../devicetree/bindings/media/qcom,sc7180-venus.yaml      | 15 +++++++++++++++
 .../devicetree/bindings/media/qcom,venus-common.yaml      | 15 ---------------
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml b/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml
index bfd8b1ad4731..b21bed314848 100644
--- a/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml
+++ b/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml
@@ -91,6 +91,21 @@ properties:
     deprecated: true
     additionalProperties: false
 
+  video-firmware:
+    type: object
+    additionalProperties: false
+
+    description: |
+      Firmware subnode is needed when the platform does not
+      have TrustZone.
+
+    properties:
+      iommus:
+        maxItems: 1
+
+    required:
+      - iommus
+
 required:
   - compatible
   - power-domain-names
diff --git a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml
index 3153d91f9d18..59a3fde846d2 100644
--- a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml
+++ b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml
@@ -47,21 +47,6 @@ properties:
     minItems: 1
     maxItems: 4
 
-  video-firmware:
-    type: object
-    additionalProperties: false
-
-    description: |
-      Firmware subnode is needed when the platform does not
-      have TrustZone.
-
-    properties:
-      iommus:
-        maxItems: 1
-
-    required:
-      - iommus
-
 required:
   - reg
   - clocks

-- 
2.47.3


^ permalink raw reply related

* [PATCH v5 1/4] media: dt-bindings: qcom,sc7280-venus: drop non-PAS support
From: Dmitry Baryshkov @ 2026-03-27 20:19 UTC (permalink / raw)
  To: Vikash Garodia, Dikshita Agarwal, Abhinav Kumar,
	Bryan O'Donoghue, Mauro Carvalho Chehab,
	cros-qcom-dts-watchers, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Stanimir Varbanov
  Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
	Krzysztof Kozlowski
In-Reply-To: <20260327-venus-iris-flip-switch-v5-0-2f4b6c636927@oss.qualcomm.com>

The only users of the non-PAS setup on SC7280 platform are the ChromeOS
devices, which were cancelled before reaching end users. Iris, the
alternative driver for the same hardware, does not support non-PAS
setup. It is expected that in future both Venus and Iris devices will
use different ABI for non-PAS (EL2) setup.

In order to declare only the future-proof hardware description drop
support for non-PAS setup from the SC7280 Venus schema (breaking almost
non-existing SC7280 ChromeOS devices).

The dropped iommus entry reflects the extra stream, which should not be
treated in the same way as the main one (which doesn't match the usage
described by the iommus definition).

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
 Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml b/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml
index 413c5b4ee650..9725fcb761dc 100644
--- a/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml
+++ b/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml
@@ -43,8 +43,7 @@ properties:
       - const: vcodec_bus
 
   iommus:
-    minItems: 1
-    maxItems: 2
+    maxItems: 1
 
   interconnects:
     maxItems: 2
@@ -120,12 +119,7 @@ examples:
                         <&mmss_noc MASTER_VIDEO_P0 0 &mc_virt SLAVE_EBI1 0>;
         interconnect-names = "cpu-cfg", "video-mem";
 
-        iommus = <&apps_smmu 0x2180 0x20>,
-                 <&apps_smmu 0x2184 0x20>;
+        iommus = <&apps_smmu 0x2180 0x20>;
 
         memory-region = <&video_mem>;
-
-        video-firmware {
-            iommus = <&apps_smmu 0x21a2 0x0>;
-        };
     };

-- 
2.47.3


^ permalink raw reply related

* [PATCH v5 0/4] media: qcom: flip the switch between Venus and Iris drivers
From: Dmitry Baryshkov @ 2026-03-27 20:19 UTC (permalink / raw)
  To: Vikash Garodia, Dikshita Agarwal, Abhinav Kumar,
	Bryan O'Donoghue, Mauro Carvalho Chehab,
	cros-qcom-dts-watchers, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Stanimir Varbanov
  Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
	Krzysztof Kozlowski, Konrad Dybcio

As the Venus and Iris drivers are close to the "feature parity" for the
common platforms (SC7280, SM8250), in order to get more attention to
squashing bugs from the Iris driver, flip the switch and default to the
Iris driver if both are enabled. The Iris driver has several
regressions, but hopefully they can be fixed through the development
cycle by the respective team. Also it is better to fail the test than
crash the device (which Venus driver does a lot).

Note: then intention is to land this in 6.21, which might let us to
drop those platforms from the Venus driver in 6.22+.

Testing methodology: fluster test-suite, single-threaded mode, SM8250
device (RB5).

$ ./fluster.py r -j 1 -d  GStreamer-H.264-V4L2-Gst1.0 -s -so out-h264.md -ts JVT-AVC_V1
$ ./fluster.py r -j 1 -d  GStreamer-H.265-V4L2-Gst1.0 -s -so out-h265.md -ts JCT-VC-HEVC_V1
$ ./fluster.py r -j 1 -d  GStreamer-VP9-V4L2-Gst1.0 -s -so out-vp9.md

For H.264:

Only the main set was used on both platforms

On Venus pass 126/135
On Iris  pass 78/135

- Fail on Iris, but pass on Venus:
  cabac_mot_fld0_full, cabac_mot_mbaff0_full, cabac_mot_picaff0_full,
  CAFI1_SVA_C, CAMA1_Sony_C, cama1_vtc_c, cama2_vtc_b, cama3_vtc_b,
  CAMACI3_Sony_C, CAMASL3_Sony_B, CAMP_MOT_MBAFF_L30,
  CAMP_MOT_MBAFF_L31, CANLMA2_Sony_C, CANLMA3_Sony_C,
  cavlc_mot_fld0_full_B, cavlc_mot_mbaff0_full_B,
  cavlc_mot_picaff0_full_B, CVCANLMA2_Sony_C, CVFI1_Sony_D, CVFI1_SVA_C,
  CVFI2_Sony_H, CVFI2_SVA_C, CVMA1_Sony_D, CVMAPAQP3_Sony_E,
  CVMAQP2_Sony_G, CVMAQP3_Sony_D, CVMP_MOT_FLD_L30_B,
  CVMP_MOT_FRM_L31_B, CVNLFI1_Sony_C, CVNLFI2_Sony_H, FI1_Sony_E,
  MR9_BT_B, Sharp_MP_Field_1_B, Sharp_MP_Field_2_B, Sharp_MP_Field_3_B,
  Sharp_MP_PAFF_1r2, Sharp_MP_PAFF_2r

- Fail on Venus, but pass on Iris:
  BA3_SVA_C

For Venus several tests crash the firmware or crash the device,
so test-suite was executed with extra:

-sv CABREF3_Sand_D CAMANL1_TOSHIBA_B CAMA1_TOSHIBA_B \
  CAMA3_Sand_E CAMANL2_TOSHIBA_B CAMANL3_Sand_E CAPA1_TOSHIBA_B \
  CAPAMA3_Sand_F CVMA1_TOSHIBA_B CVMANL1_TOSHIBA_B CVMANL2_TOSHIBA_B \
  CVPA1_TOSHIBA_B

For H.265:

Only the main set was used on both platforms

On Venus pass 135/147
On Iris  pass 133/147

- Fail on Iris, but pass on Venus:
  INITQP_B_Main10_Sony_1, WP_A_MAIN10_Toshiba_3,
  WPP_A_ericsson_MAIN10_2, WPP_B_ericsson_MAIN10_2,
  WPP_C_ericsson_MAIN10_2, WPP_E_ericsson_MAIN10_2,
  WPP_F_ericsson_MAIN10_2

- Fail on Venus, but pass on Iris:
  ipcm_A_NEC_3, ipcm_B_NEC_3, ipcm_C_NEC_3, ipcm_D_NEC_3, ipcm_E_NEC_2,
  IPRED_B_Nokia_3, VPSSPSPPS_A_MainConcept_1

For VP9 codec:

On Venus pass 174/311
On Iris  pass 232/311

- Fail on Venus, but pass on Iris:
  vp90-2-05-resize.ivf, vp90-2-14-resize-10frames-fp-tiles-1-2-4-8,
  vp90-2-14-resize-10frames-fp-tiles-1-2,
  vp90-2-14-resize-10frames-fp-tiles-1-4,
  vp90-2-14-resize-10frames-fp-tiles-1-8,
  vp90-2-14-resize-10frames-fp-tiles-2-1,
  vp90-2-14-resize-10frames-fp-tiles-2-4,
  vp90-2-14-resize-10frames-fp-tiles-2-8,
  vp90-2-14-resize-10frames-fp-tiles-4-1,
  vp90-2-14-resize-10frames-fp-tiles-4-2,
  vp90-2-14-resize-10frames-fp-tiles-4-8,
  vp90-2-14-resize-10frames-fp-tiles-8-1,
  vp90-2-14-resize-10frames-fp-tiles-8-2,
  vp90-2-14-resize-10frames-fp-tiles-8-4-2-1,
  vp90-2-14-resize-10frames-fp-tiles-8-4, vp90-2-14-resize-fp-tiles-1-16,
  vp90-2-14-resize-fp-tiles-1-2-4-8-16, vp90-2-14-resize-fp-tiles-1-2,
  vp90-2-14-resize-fp-tiles-1-4, vp90-2-14-resize-fp-tiles-16-1,
  vp90-2-14-resize-fp-tiles-16-2, vp90-2-14-resize-fp-tiles-16-4,
  vp90-2-14-resize-fp-tiles-16-8-4-2-1, vp90-2-14-resize-fp-tiles-16-8,
  vp90-2-14-resize-fp-tiles-1-8, vp90-2-14-resize-fp-tiles-2-16,
  vp90-2-14-resize-fp-tiles-2-1, vp90-2-14-resize-fp-tiles-2-4,
  vp90-2-14-resize-fp-tiles-2-8, vp90-2-14-resize-fp-tiles-4-16,
  vp90-2-14-resize-fp-tiles-4-1, vp90-2-14-resize-fp-tiles-4-2,
  vp90-2-14-resize-fp-tiles-4-8, vp90-2-14-resize-fp-tiles-8-16,
  vp90-2-14-resize-fp-tiles-8-1, vp90-2-14-resize-fp-tiles-8-2,
  vp90-2-14-resize-fp-tiles-8-4, vp90-2-15-segkey,
  vp90-2-21-resize_inter_1280x720_5_1-2, vp90-2-21-resize_inter_1280x720_5_3-4,
  vp90-2-21-resize_inter_1280x720_7_1-2, vp90-2-21-resize_inter_1280x720_7_3-4,
  vp90-2-21-resize_inter_1920x1080_5_1-2,
  vp90-2-21-resize_inter_1920x1080_5_3-4,
  vp90-2-21-resize_inter_1920x1080_7_1-2,
  vp90-2-21-resize_inter_1920x1080_7_3-4,
  vp90-2-21-resize_inter_320x180_5_3-4, vp90-2-21-resize_inter_320x180_7_3-4,
  vp90-2-21-resize_inter_320x240_5_3-4, vp90-2-21-resize_inter_320x240_7_3-4,
  vp90-2-21-resize_inter_640x360_5_1-2, vp90-2-21-resize_inter_640x360_5_3-4,
  vp90-2-21-resize_inter_640x360_7_1-2, vp90-2-21-resize_inter_640x360_7_3-4,
  vp90-2-21-resize_inter_640x480_5_1-2, vp90-2-21-resize_inter_640x480_5_3-4,
  vp90-2-21-resize_inter_640x480_7_1-2, vp90-2-21-resize_inter_640x480_7_3-4

$ v4l2-compliance -d /dev/video0
v4l2-compliance 1.30.1, 64 bits, 64-bit time_t

Compliance test for iris_driver device /dev/video0:

Driver Info:
        Driver name      : iris_driver
        Card type        : Iris Decoder
        Bus info         : platform:aa00000.video-codec
        Driver version   : 6.19.0
        Capabilities     : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps      : 0x04204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
        Detected Stateful Decoder

Required ioctls:
        test VIDIOC_QUERYCAP: OK
        test invalid ioctls: OK

Allow for multiple opens:
        test second /dev/video0 open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK
        test for unlimited opens: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

Control ioctls:
        test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
        test VIDIOC_QUERYCTRL: OK
        test VIDIOC_G/S_CTRL: OK
        test VIDIOC_G/S/TRY_EXT_CTRLS: OK
        test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
        test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
        Standard Controls: 2 Private Controls: 0

Format ioctls:
        test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
        test VIDIOC_G/S_PARM: OK (Not Supported)
        test VIDIOC_G_FBUF: OK (Not Supported)
        test VIDIOC_G_FMT: OK
        test VIDIOC_TRY_FMT: OK
        test VIDIOC_S_FMT: OK
        test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
        test Cropping: OK
        test Composing: OK
        test Scaling: OK (Not Supported)

Codec ioctls:
        test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
        test VIDIOC_G_ENC_INDEX: OK (Not Supported)
        test VIDIOC_(TRY_)DECODER_CMD: OK

Buffer ioctls:
        test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
        test CREATE_BUFS maximum buffers: OK
        test VIDIOC_REMOVE_BUFS: OK
        test VIDIOC_EXPBUF: OK
        test Requests: OK (Not Supported)
        test blocking wait: OK

$ v4l2-compliance -d /dev/video1
v4l2-compliance 1.30.1, 64 bits, 64-bit time_t

Compliance test for iris_driver device /dev/video1:

Driver Info:
        Driver name      : iris_driver
        Card type        : Iris Encoder
        Bus info         : platform:aa00000.video-codec
        Driver version   : 6.19.0
        Capabilities     : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps      : 0x04204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
        Detected Stateful Encoder

Required ioctls:
        test VIDIOC_QUERYCAP: OK
        test invalid ioctls: OK

Allow for multiple opens:
        test second /dev/video1 open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK
        test for unlimited opens: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

Control ioctls:
        test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
        test VIDIOC_QUERYCTRL: OK
        test VIDIOC_G/S_CTRL: OK
        test VIDIOC_G/S/TRY_EXT_CTRLS: OK
        test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
        test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
        Standard Controls: 18 Private Controls: 0

Format ioctls:
        test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
        test VIDIOC_G/S_PARM: OK
        test VIDIOC_G_FBUF: OK (Not Supported)
        test VIDIOC_G_FMT: OK
        test VIDIOC_TRY_FMT: OK
        test VIDIOC_S_FMT: OK
        test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
        test Cropping: OK
        test Composing: OK (Not Supported)
        test Scaling: OK (Not Supported)

Codec ioctls:
        test VIDIOC_(TRY_)ENCODER_CMD: OK
        test VIDIOC_G_ENC_INDEX: OK (Not Supported)
        test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

Buffer ioctls:
        test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
        test CREATE_BUFS maximum buffers: OK
        test VIDIOC_REMOVE_BUFS: OK
        test VIDIOC_EXPBUF: OK
        test Requests: OK (Not Supported)
        test blocking wait: OK

Total for iris_driver device /dev/video1: 48, Succeeded: 48, Failed: 0, Warnings: 0

For SC7280, the results match the SM8250 ones.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
Changes in v5:
- Rebased on linux-next, dropping applied patch
- No other changes from the previous patchset, the previous patchset can
  still be applied, if it was already.
- Link to v4: https://lore.kernel.org/r/20260131-venus-iris-flip-switch-v4-0-e10b886771e1@oss.qualcomm.com

Changes in v4:
- Fixed building (Dikshita)
- Changed H265D_MAX_SLICE to have the same value as in Venus, fixing
  H.265 decoding on SC7280
- Link to v3: https://lore.kernel.org/r/20260127-venus-iris-flip-switch-v3-0-7f37689f4b39@oss.qualcomm.com

Changes in v3:
- Dropped dependency on the sc8280xp patchset, this will probably go in
  earlier.
- Updated commit messages for DT bindings (Konrad)
- Link to v2: https://lore.kernel.org/r/20260126-venus-iris-flip-switch-v2-0-b0ea05e1739a@oss.qualcomm.com

Changes in v2:
- Sorted out SC7280 Chromebook bindings (Stephan)
- Dropped most of ifdef from venus (Vikash, Konrad)
- Added testign results to the cover letter.
- Link to v1: https://lore.kernel.org/r/20251119-venus-iris-flip-switch-v1-1-852369f66e36@oss.qualcomm.com

---
Dmitry Baryshkov (4):
      media: dt-bindings: qcom,sc7280-venus: drop non-PAS support
      media: dt-bindings: qcom-sc7180-venus: move video-firmware here
      media: qcom: iris: increase H265D_MAX_SLICE to fix H.265 decoding on SC7280
      media: qcom: venus: flip the venus/iris switch

 .../devicetree/bindings/media/qcom,sc7180-venus.yaml      | 15 +++++++++++++++
 .../devicetree/bindings/media/qcom,sc7280-venus.yaml      | 10 ++--------
 .../devicetree/bindings/media/qcom,venus-common.yaml      | 15 ---------------
 drivers/media/platform/qcom/iris/Makefile                 |  5 +----
 drivers/media/platform/qcom/iris/iris_probe.c             |  2 --
 drivers/media/platform/qcom/iris/iris_vpu_buffer.h        |  2 +-
 drivers/media/platform/qcom/venus/core.c                  |  6 ++++++
 drivers/media/platform/qcom/venus/core.h                  | 11 +++++++++++
 8 files changed, 36 insertions(+), 30 deletions(-)
---
base-commit: e77a5a5cfe43b4c25bd44a3818e487033287517f
change-id: 20251119-venus-iris-flip-switch-d59a3fbc6a4b

Best regards,
--  
With best wishes
Dmitry


^ permalink raw reply

* [PATCH 6/7] remoteproc: qcom_q6v5_mss: Add SDM632 MSS
From: Barnabás Czémán @ 2026-03-27 20:11 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Ulf Hansson, Mathieu Poirier, Konrad Dybcio, Stephan Gerhold
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-pm,
	linux-remoteproc, Barnabás Czémán
In-Reply-To: <20260327-sdm632-rpmpd-v1-0-6098dc997d66@mainlining.org>

Add support for SDM632 mss, it is very similar to MSM8953 mss only
difference SDM632 is using mss-supply as pm domain.

Signed-off-by: Barnabás Czémán <barnabas.czeman@mainlining.org>
---
 drivers/remoteproc/qcom_q6v5_mss.c | 47 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 86edd826ede8..e63432184767 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -271,6 +271,7 @@ enum {
 	MSS_MSM8998,
 	MSS_SC7180,
 	MSS_SC7280,
+	MSS_SDM632,
 	MSS_SDM660,
 	MSS_SDM845,
 };
@@ -760,6 +761,7 @@ static int q6v5proc_reset(struct q6v5 *qproc)
 		   qproc->version == MSS_MSM8953 ||
 		   qproc->version == MSS_MSM8996 ||
 		   qproc->version == MSS_MSM8998 ||
+		   qproc->version == MSS_SDM632 ||
 		   qproc->version == MSS_SDM660) {
 
 		/* Override the ACC value if required */
@@ -770,7 +772,9 @@ static int q6v5proc_reset(struct q6v5 *qproc)
 			writel(QDSP6SS_ACC_OVERRIDE_VAL_9607,
 			       qproc->reg_base + QDSP6SS_STRAP_ACC);
 		else if (qproc->version != MSS_MSM8909 &&
-			 qproc->version != MSS_MSM8953)
+			 qproc->version != MSS_MSM8953 &&
+			 qproc->version != MSS_SDM632)
+			/* Override the ACC value if required */
 			writel(QDSP6SS_ACC_OVERRIDE_VAL,
 			       qproc->reg_base + QDSP6SS_STRAP_ACC);
 
@@ -830,7 +834,8 @@ static int q6v5proc_reset(struct q6v5 *qproc)
 			/* Turn on L1, L2, ETB and JU memories 1 at a time */
 			if (qproc->version == MSS_MSM8940 ||
 			    qproc->version == MSS_MSM8953 ||
-			    qproc->version == MSS_MSM8996) {
+			    qproc->version == MSS_MSM8996 ||
+			    qproc->version == MSS_SDM632) {
 				mem_pwr_ctl = QDSP6SS_MEM_PWR_CTL;
 				i = 19;
 				reverse = 0;
@@ -2303,6 +2308,43 @@ static const struct rproc_hexagon_res sc7280_mss = {
 	.version = MSS_SC7280,
 };
 
+static const struct rproc_hexagon_res sdm632_mss = {
+	.hexagon_mba_image = "mba.mbn",
+	.proxy_supply = (struct qcom_mss_reg_res[]) {
+		{
+			.supply = "pll",
+			.uA = 100000,
+		},
+		{}
+	},
+	.proxy_clk_names = (char*[]){
+		"xo",
+		NULL
+	},
+	.active_clk_names = (char*[]){
+		"iface",
+		"bus",
+		"mem",
+		NULL
+	},
+	.proxy_pd_names = (char*[]) {
+		"cx",
+		"mx",
+		"mss",
+		NULL
+	},
+	.need_mem_protection = false,
+	.need_pas_mem_setup = true,
+	.has_alt_reset = false,
+	.has_mba_logs = false,
+	.has_spare_reg = false,
+	.has_qaccept_regs = false,
+	.has_ext_bhs_reg = false,
+	.has_ext_cntl_regs = false,
+	.has_vq6 = false,
+	.version = MSS_SDM632,
+};
+
 static const struct rproc_hexagon_res sdm660_mss = {
 	.hexagon_mba_image = "mba.mbn",
 	.proxy_clk_names = (char*[]){
@@ -2896,6 +2938,7 @@ static const struct of_device_id q6v5_of_match[] = {
 	{ .compatible = "qcom,msm8998-mss-pil", .data = &msm8998_mss},
 	{ .compatible = "qcom,sc7180-mss-pil", .data = &sc7180_mss},
 	{ .compatible = "qcom,sc7280-mss-pil", .data = &sc7280_mss},
+	{ .compatible = "qcom,sdm632-mss-pil", .data = &sdm632_mss},
 	{ .compatible = "qcom,sdm660-mss-pil", .data = &sdm660_mss},
 	{ .compatible = "qcom,sdm845-mss-pil", .data = &sdm845_mss},
 	{ },

-- 
2.53.0


^ permalink raw reply related

* [PATCH 5/7] dt-bindings: remoteproc: qcom,msm8916-mss-pil: Add SDM632
From: Barnabás Czémán @ 2026-03-27 20:11 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Ulf Hansson, Mathieu Poirier, Konrad Dybcio, Stephan Gerhold
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-pm,
	linux-remoteproc, Barnabás Czémán
In-Reply-To: <20260327-sdm632-rpmpd-v1-0-6098dc997d66@mainlining.org>

SDM632 MSS is very similar for MSM8953 mss the difference is
mss-supply is a pm domain on SDM632, previously SDM632 MSS
was represented by MSM8953 MSS. Correct the bindings to
described it correctly.

Signed-off-by: Barnabás Czémán <barnabas.czeman@mainlining.org>
---
 .../devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml     | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml
index 8c0ff4dfad10..9154d2b541e8 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml
@@ -27,6 +27,7 @@ properties:
           - qcom,msm8940-mss-pil
           - qcom,msm8953-mss-pil
           - qcom,msm8974-mss-pil
+          - qcom,sdm632-mss-pil
 
       - const: qcom,q6v5-pil
         description: Deprecated, prefer using qcom,msm8916-mss-pil
@@ -79,14 +80,14 @@ properties:
                      (not valid for qcom,msm8226-mss-pil, qcom,msm8926-mss-pil
                      and qcom,msm8974-mss-pil)
       - description: MSS proxy power domain (control handed over after startup)
-                     (only valid for qcom,msm8953-mss-pil)
+                     (only valid for qcom,sdm632-mss-pil)
     minItems: 1
 
   power-domain-names:
     items:
       - const: cx
       - const: mx # not valid for qcom,msm8226-mss-pil, qcom-msm8926-mss-pil and qcom,msm8974-mss-pil
-      - const: mss # only valid for qcom,msm8953-mss-pil
+      - const: mss # only valid for qcom,sdm632-mss-pil
     minItems: 1
 
   pll-supply:
@@ -214,7 +215,7 @@ allOf:
   - if:
       properties:
         compatible:
-          const: qcom,msm8953-mss-pil
+          const: qcom,sdm632-mss-pil
     then:
       properties:
         power-domains:
@@ -236,6 +237,7 @@ allOf:
               - qcom,msm8917-mss-pil
               - qcom,msm8937-mss-pil
               - qcom,msm8940-mss-pil
+              - qcom,msm8953-mss-pil
     then:
       properties:
         power-domains:
@@ -282,6 +284,7 @@ allOf:
               - qcom,msm8917-mss-pil
               - qcom,msm8937-mss-pil
               - qcom,msm8940-mss-pil
+              - qcom,msm8953-mss-pil
               - qcom,msm8974-mss-pil
     then:
       required:

-- 
2.53.0


^ permalink raw reply related

* [PATCH 7/7] arm64: dts: qcom: sdm632: Correct power domains
From: Barnabás Czémán @ 2026-03-27 20:11 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Ulf Hansson, Mathieu Poirier, Konrad Dybcio, Stephan Gerhold
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-pm,
	linux-remoteproc, Barnabás Czémán
In-Reply-To: <20260327-sdm632-rpmpd-v1-0-6098dc997d66@mainlining.org>

SDM632 is using different pm domains from MSM8953 override them
where it is needed.

Signed-off-by: Barnabás Czémán <barnabas.czeman@mainlining.org>
---
 arch/arm64/boot/dts/qcom/sdm632.dtsi | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sdm632.dtsi b/arch/arm64/boot/dts/qcom/sdm632.dtsi
index 40d86d91b67f..b1dbcffd51b6 100644
--- a/arch/arm64/boot/dts/qcom/sdm632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632.dtsi
@@ -87,3 +87,34 @@ opp-725000000 {
 		required-opps = <&rpmpd_opp_turbo>;
 	};
 };
+
+&lpass {
+	power-domains = <&rpmpd SDM632_VDDCX>;
+	power-domain-names = "cx";
+};
+
+&mpss {
+	compatible = "qcom,sdm632-mss-pil";
+	power-domains = <&rpmpd SDM632_VDDCX>,
+			<&rpmpd SDM632_VDDMX>,
+			<&rpmpd SDM632_VDDMD>;
+	power-domain-names = "cx", "mx", "mss";
+};
+
+&rpmpd {
+	compatible = "qcom,sdm632-rpmpd";
+};
+
+&sdhc_1 {
+	power-domains = <&rpmpd SDM632_VDDCX>;
+};
+
+&sdhc_2 {
+	power-domains = <&rpmpd SDM632_VDDCX>;
+};
+
+&wcnss {
+	power-domains = <&rpmpd SDM632_VDDCX>,
+			<&rpmpd SDM632_VDDMX>;
+	power-domain-names = "cx", "mx";
+};

-- 
2.53.0


^ permalink raw reply related

* [PATCH 4/7] arm64: dts: qcom: msm8953: fix modem pm domains
From: Barnabás Czémán @ 2026-03-27 20:11 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Ulf Hansson, Mathieu Poirier, Konrad Dybcio, Stephan Gerhold
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-pm,
	linux-remoteproc, Barnabás Czémán
In-Reply-To: <20260327-sdm632-rpmpd-v1-0-6098dc997d66@mainlining.org>

MSM8953 MSS is using mss-supply as regulator.

Signed-off-by: Barnabás Czémán <barnabas.czeman@mainlining.org>
---
 arch/arm64/boot/dts/qcom/msm8953.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index 753167c3f861..c7dc08858d54 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -1451,9 +1451,8 @@ mpss: remoteproc@4080000 {
 					  "handover", "stop-ack";
 
 			power-domains = <&rpmpd MSM8953_VDDCX>,
-					<&rpmpd MSM8953_VDDMX>,
-					<&rpmpd MSM8953_VDDMD>;
-			power-domain-names = "cx", "mx","mss";
+					<&rpmpd MSM8953_VDDMX>;
+			power-domain-names = "cx", "mx";
 
 			clocks = <&gcc GCC_MSS_CFG_AHB_CLK>,
 				 <&gcc GCC_MSS_Q6_BIMC_AXI_CLK>,

-- 
2.53.0


^ permalink raw reply related

* [PATCH 2/7] pmdomain: qcom: rpmpd: Split SDM632 pm domains from MSM8953
From: Barnabás Czémán @ 2026-03-27 20:11 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Ulf Hansson, Mathieu Poirier, Konrad Dybcio, Stephan Gerhold
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-pm,
	linux-remoteproc, Barnabás Czémán
In-Reply-To: <20260327-sdm632-rpmpd-v1-0-6098dc997d66@mainlining.org>

Remove modem related pm domains from MSM8953 rpmpd because MSM8953 MSS
is using mss-supply as regulator.
Split SDM632 rpmpd from MSM8953 because SDM632 MSS is using mss-supply
as pm domain.

Signed-off-by: Barnabás Czémán <barnabas.czeman@mainlining.org>
---
 drivers/pmdomain/qcom/rpmpd.c | 39 +++++++++++++++++++++------------------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/drivers/pmdomain/qcom/rpmpd.c b/drivers/pmdomain/qcom/rpmpd.c
index 15a11ff282c3..cff755306759 100644
--- a/drivers/pmdomain/qcom/rpmpd.c
+++ b/drivers/pmdomain/qcom/rpmpd.c
@@ -503,19 +503,8 @@ static struct rpmpd md_s1a_corner_ao = {
 	.key = KEY_CORNER,
 };
 
-static struct rpmpd md_s1a_lvl_ao;
 static struct rpmpd md_s1a_lvl = {
 	.pd = { .name = "md", },
-	.peer = &md_s1a_lvl_ao,
-	.res_type = RPMPD_SMPA,
-	.res_id = 1,
-	.key = KEY_LEVEL,
-};
-
-static struct rpmpd md_s1a_lvl_ao = {
-	.pd = { .name = "md_ao", },
-	.peer = &md_s1a_lvl,
-	.active_only = true,
 	.res_type = RPMPD_SMPA,
 	.res_id = 1,
 	.key = KEY_LEVEL,
@@ -703,13 +692,11 @@ static const struct rpmpd_desc msm8917_desc = {
 };
 
 static struct rpmpd *msm8953_rpmpds[] = {
-	[MSM8953_VDDMD] =	&md_s1a_lvl,
-	[MSM8953_VDDMD_AO] =	&md_s1a_lvl_ao,
-	[MSM8953_VDDCX] =	&cx_s2a_lvl,
-	[MSM8953_VDDCX_AO] =	&cx_s2a_lvl_ao,
-	[MSM8953_VDDCX_VFL] =	&cx_s2a_vfl,
-	[MSM8953_VDDMX] =	&mx_s7a_lvl,
-	[MSM8953_VDDMX_AO] =	&mx_s7a_lvl_ao,
+	[RPMPD_VDDCX] =		&cx_s2a_lvl,
+	[RPMPD_VDDCX_AO] =	&cx_s2a_lvl_ao,
+	[RPMPD_VDDCX_VFL] =	&cx_s2a_vfl,
+	[RPMPD_VDDMX] =		&mx_s7a_lvl,
+	[RPMPD_VDDMX_AO] =	&mx_s7a_lvl_ao,
 };
 
 static const struct rpmpd_desc msm8953_desc = {
@@ -844,6 +831,21 @@ static const struct rpmpd_desc qm215_desc = {
 	.max_state = RPM_SMD_LEVEL_TURBO,
 };
 
+static struct rpmpd *sdm632_rpmpds[] = {
+	[SDM632_VDDMD] =	&md_s1a_lvl,
+	[SDM632_VDDCX] =	&cx_s2a_lvl,
+	[SDM632_VDDCX_AO] =	&cx_s2a_lvl_ao,
+	[SDM632_VDDCX_VFL] =	&cx_s2a_vfl,
+	[SDM632_VDDMX] =	&mx_s7a_lvl,
+	[SDM632_VDDMX_AO] =	&mx_s7a_lvl_ao,
+};
+
+static const struct rpmpd_desc sdm632_desc = {
+	.rpmpds = sdm632_rpmpds,
+	.num_pds = ARRAY_SIZE(sdm632_rpmpds),
+	.max_state = RPM_SMD_LEVEL_TURBO,
+};
+
 static struct rpmpd *sdm660_rpmpds[] = {
 	[RPMPD_VDDCX] =		&cx_rwcx0_lvl,
 	[RPMPD_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
@@ -948,6 +950,7 @@ static const struct of_device_id rpmpd_match_table[] = {
 	{ .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc },
 	{ .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
 	{ .compatible = "qcom,qm215-rpmpd", .data = &qm215_desc },
+	{ .compatible = "qcom,sdm632-rpmpd", .data = &sdm632_desc },
 	{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
 	{ .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
 	{ .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },

-- 
2.53.0


^ permalink raw reply related

* [PATCH 0/7] MSM8953/SDM632 rpmpd/mss fixes
From: Barnabás Czémán @ 2026-03-27 20:11 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Ulf Hansson, Mathieu Poirier, Konrad Dybcio, Stephan Gerhold
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-pm,
	linux-remoteproc, Barnabás Czémán

SDM632 pm domains are different from MSM8953 because MSM8953
is defining pm8953_s1 as regulator but SDM632 is defining it
as pm domain.

This patch series correcting the pm domains defined in rpmpd
driver and splitting the MSS resources for the both SoC to match
the reality.

These changes was discussed in a previous threads:
https://lore.kernel.org/all/2b057aa5-4416-4fd4-aeab-6bc23acbb53d@oss.qualcomm.com/

Signed-off-by: Barnabás Czémán <barnabas.czeman@mainlining.org>
---
Barnabás Czémán (7):
      dt-bindings: power: qcom-rpmpd: Split MSM8953 and SDM632
      pmdomain: qcom: rpmpd: Split SDM632 pm domains from MSM8953
      remoteproc: qcom_q6v5_mss: Use mss as regulator for MSM8953
      arm64: dts: qcom: msm8953: fix modem pm domains
      dt-bindings: remoteproc: qcom,msm8916-mss-pil: Add SDM632
      remoteproc: qcom_q6v5_mss: Add SDM632 MSS
      arm64: dts: qcom: sdm632: Correct power domains

 .../devicetree/bindings/power/qcom,rpmpd.yaml      |  1 +
 .../bindings/remoteproc/qcom,msm8916-mss-pil.yaml  |  9 ++--
 arch/arm64/boot/dts/qcom/msm8953.dtsi              |  5 +-
 arch/arm64/boot/dts/qcom/sdm632.dtsi               | 31 ++++++++++++
 drivers/pmdomain/qcom/rpmpd.c                      | 39 ++++++++-------
 drivers/remoteproc/qcom_q6v5_mss.c                 | 56 ++++++++++++++++++++--
 include/dt-bindings/power/qcom-rpmpd.h             | 20 +++++---
 7 files changed, 127 insertions(+), 34 deletions(-)
---
base-commit: 8e42d2514a7e8eb8d740d0ba82339dd6c0b6463f
change-id: 20260319-sdm632-rpmpd-c0e3eb548f58

Best regards,
--  
Barnabás Czémán <barnabas.czeman@mainlining.org>


^ permalink raw reply

* [PATCH 3/7] remoteproc: qcom_q6v5_mss: Use mss as regulator for MSM8953
From: Barnabás Czémán @ 2026-03-27 20:11 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Ulf Hansson, Mathieu Poirier, Konrad Dybcio, Stephan Gerhold
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-pm,
	linux-remoteproc, Barnabás Czémán
In-Reply-To: <20260327-sdm632-rpmpd-v1-0-6098dc997d66@mainlining.org>

MSM8953 MSS is using mss-supply as regulator what is usually pm8953_s1.

Signed-off-by: Barnabás Czémán <barnabas.czeman@mainlining.org>
---
 drivers/remoteproc/qcom_q6v5_mss.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 4e9eb5bd11fa..86edd826ede8 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -2705,6 +2705,14 @@ static const struct rproc_hexagon_res msm8953_mss = {
 		},
 		{}
 	},
+	.active_supply = (struct qcom_mss_reg_res[]) {
+		{
+			.supply = "mss",
+			.uV = 1050000,
+			.uA = 100000,
+		},
+		{}
+	},
 	.proxy_clk_names = (char*[]){
 		"xo",
 		NULL
@@ -2718,7 +2726,6 @@ static const struct rproc_hexagon_res msm8953_mss = {
 	.proxy_pd_names = (char*[]) {
 		"cx",
 		"mx",
-		"mss",
 		NULL
 	},
 	.need_mem_protection = false,

-- 
2.53.0


^ permalink raw reply related

* [PATCH 1/7] dt-bindings: power: qcom-rpmpd: Split MSM8953 and SDM632
From: Barnabás Czémán @ 2026-03-27 20:11 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Ulf Hansson, Mathieu Poirier, Konrad Dybcio, Stephan Gerhold
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-pm,
	linux-remoteproc, Barnabás Czémán
In-Reply-To: <20260327-sdm632-rpmpd-v1-0-6098dc997d66@mainlining.org>

Remove modem related bindings from MSM8953 rpmpd because MSM8953 MSS
is using mss-supply as a regulator usually it is pm8953_s1.
Split SDM632 bindings from MSM8953 because SDM632 is using mss-supply
as a pm domain.

Signed-off-by: Barnabás Czémán <barnabas.czeman@mainlining.org>
---
 .../devicetree/bindings/power/qcom,rpmpd.yaml        |  1 +
 include/dt-bindings/power/qcom-rpmpd.h               | 20 +++++++++++++-------
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
index 8174ceeab572..659936d6a46e 100644
--- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
+++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
@@ -48,6 +48,7 @@ properties:
           - qcom,sc7280-rpmhpd
           - qcom,sc8180x-rpmhpd
           - qcom,sc8280xp-rpmhpd
+          - qcom,sdm632-rpmpd
           - qcom,sdm660-rpmpd
           - qcom,sdm670-rpmhpd
           - qcom,sdm845-rpmhpd
diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
index 4371ac941f29..2d82434b993c 100644
--- a/include/dt-bindings/power/qcom-rpmpd.h
+++ b/include/dt-bindings/power/qcom-rpmpd.h
@@ -84,13 +84,11 @@
 #define QM215_VDDMX_AO		MSM8917_VDDMX_AO
 
 /* MSM8953 Power Domain Indexes */
-#define MSM8953_VDDMD		0
-#define MSM8953_VDDMD_AO	1
-#define MSM8953_VDDCX		2
-#define MSM8953_VDDCX_AO	3
-#define MSM8953_VDDCX_VFL	4
-#define MSM8953_VDDMX		5
-#define MSM8953_VDDMX_AO	6
+#define MSM8953_VDDCX		RPMPD_VDDCX
+#define MSM8953_VDDCX_AO	RPMPD_VDDCX_AO
+#define MSM8953_VDDCX_VFL	RPMPD_VDDCX_VFL
+#define MSM8953_VDDMX		RPMPD_VDDMX
+#define MSM8953_VDDMX_AO	RPMPD_VDDMX_AO
 
 /* MSM8974 Power Domain Indexes */
 #define MSM8974_VDDCX		0
@@ -156,6 +154,14 @@
 #define QCS404_LPIMX		5
 #define QCS404_LPIMX_VFL	6
 
+/* SDM632 Power Domain Indexes */
+#define SDM632_VDDMD		0
+#define SDM632_VDDCX		1
+#define SDM632_VDDCX_AO		2
+#define SDM632_VDDCX_VFL	3
+#define SDM632_VDDMX		4
+#define SDM632_VDDMX_AO		5
+
 /* SDM660 Power Domains */
 #define SDM660_VDDCX		RPMPD_VDDCX
 #define SDM660_VDDCX_AO		RPMPD_VDDCX_AO

-- 
2.53.0


^ permalink raw reply related

* [PATCH 16/16] ARM: dts: renesas: r9a06g032: Describe the EIP-150 block
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

The EIP-150 is composed of 3 blocks:
* An interrupt controller named EIP-201 AIC
    - fed by a clock coming from the EIP-150
    - connected to the main GIC
* A random number generator named EIP-76
    - fed by a clock coming from the EIP-150
    - signalling interrupts through the AIC
* A public key accelerator engine named EIP-28
    - Fed by a clock coming from the EIP-150
    - Signalling interrupts through the AIC

Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 arch/arm/boot/dts/renesas/r9a06g032.dtsi | 42 ++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/arm/boot/dts/renesas/r9a06g032.dtsi b/arch/arm/boot/dts/renesas/r9a06g032.dtsi
index f4f760aff28b..6aaa93ed03d6 100644
--- a/arch/arm/boot/dts/renesas/r9a06g032.dtsi
+++ b/arch/arm/boot/dts/renesas/r9a06g032.dtsi
@@ -8,6 +8,7 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/r9a06g032-sysctrl.h>
+#include <dt-bindings/interrupt-controller/inside-secure,safexcel-eip201.h>
 
 / {
 	compatible = "renesas,r9a06g032";
@@ -170,6 +171,47 @@ usb@2,0 {
 			};
 		};
 
+		eip150: bus@40040000 {
+			compatible = "inside-secure,safexcel-eip150", "simple-pm-bus";
+			clocks = <&sysctrl R9A06G032_HCLK_CRYPTO_EIP150>;
+			#clock-cells = <0>;
+			clock-map = <&sysctrl R9A06G032_HCLK_CRYPTO_EIP150>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x40040000 0x40040000 0x10000>;
+			status = "disabled";
+
+			eip76_rng: rng@40040000 {
+				compatible = "inside-secure,safexcel-eip76";
+				reg = <0x40040000 0x80>;
+				interrupt-parent = <&eip201_aic>;
+				interrupts = <AIC_TRNG_INT IRQ_TYPE_EDGE_RISING>;
+				clocks = <&eip150>;
+				status = "disabled";
+			};
+
+			eip28_pka: crypto@40044000 {
+				compatible = "inside-secure,safexcel-eip28";
+				reg = <0x40044000 0x4000>;
+				interrupt-parent = <&eip201_aic>;
+				interrupts = <AIC_PKA_INT0 IRQ_TYPE_EDGE_RISING>,
+					     <AIC_PKA_INT1 IRQ_TYPE_EDGE_RISING>,
+					     <AIC_PKA_INT2 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&eip150>;
+				status = "disabled";
+			};
+
+			eip201_aic: interrupt-controller@40048000 {
+				compatible = "inside-secure,safexcel-eip201";
+				reg = <0x40048000 0x4000>;
+				interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				clocks = <&eip150>;
+				status = "disabled";
+			};
+		};
+
 		uart0: serial@40060000 {
 			compatible = "renesas,r9a06g032-uart", "renesas,rzn1-uart", "snps,dw-apb-uart";
 			reg = <0x40060000 0x400>;

-- 
2.51.1


^ permalink raw reply related

* [PATCH 15/16] crypto: eip28: Add support for SafeXcel EIP-28 Public Key Accelerator
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

This engine provides offload for:
- RSA (RSA-PKCS1, FIPS 186-3)
- ECDSA (FIPS 186-3)
- ECDH (SP 800-56B)

The driver is stable and working, but currently only implements the RSA
algorithm. It successfully passes RSA selftests.

Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
We are working on ECDSA and ECDH support, they will be added later.

We are also clarifying the terms and conditions to publish the firmware
in a repository like linux-firmwares, if ever possible.
---
 drivers/crypto/Kconfig                |  10 +
 drivers/crypto/inside-secure/Makefile |   1 +
 drivers/crypto/inside-secure/eip28.c  | 760 ++++++++++++++++++++++++++++++++++
 3 files changed, 771 insertions(+)

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index b3a6bbf0aacf..734649a223f7 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -877,6 +877,16 @@ config CRYPTO_DEV_SAFEXCEL
 	  SHA384 and SHA512 hash algorithms for both basic hash and HMAC.
 	  Additionally, it accelerates combined AES-CBC/HMAC-SHA AEAD operations.
 
+config CRYPTO_DEV_EIP28
+	tristate "Support Inside Secure's SafeXcel EIP28 PKA"
+	depends on SAFEXCEL_EIP201_AIC
+	select CRYPTO_AKCIPHER
+	help
+	  EIP28 is a public key accelerator. It provides offload for:
+	  - RSA (RSA-PKCS1, FIPS 186-3)
+	  - ECDSA (FIPS 186-3)
+	  - ECDH (SP 800-56B)
+
 source "drivers/crypto/inside-secure/eip93/Kconfig"
 source "drivers/crypto/ti/Kconfig"
 
diff --git a/drivers/crypto/inside-secure/Makefile b/drivers/crypto/inside-secure/Makefile
index 30d13fd5d58e..8a6f51dcec58 100644
--- a/drivers/crypto/inside-secure/Makefile
+++ b/drivers/crypto/inside-secure/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_CRYPTO_DEV_SAFEXCEL) += crypto_safexcel.o
 crypto_safexcel-objs := safexcel.o safexcel_ring.o safexcel_cipher.o safexcel_hash.o
+obj-$(CONFIG_CRYPTO_DEV_EIP28) += eip28.o
 obj-y += eip93/
diff --git a/drivers/crypto/inside-secure/eip28.c b/drivers/crypto/inside-secure/eip28.c
new file mode 100644
index 000000000000..495a8cf6dfc0
--- /dev/null
+++ b/drivers/crypto/inside-secure/eip28.c
@@ -0,0 +1,760 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2026 Schneider Electric
+ */
+
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/scatterlist.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/firmware.h>
+#include <crypto/internal/akcipher.h>
+#include <crypto/internal/rsa.h>
+
+#define EIP28_PKA_APTR 0x0
+#define EIP28_PKA_BPTR 0x04
+#define EIP28_PKA_CPTR 0x08
+#define EIP28_PKA_DPTR 0x0c
+#define EIP28_PKA_ALENGTH 0x10
+#define EIP28_PKA_BLENGTH 0x14
+#define   EIP28_PKA_VECTOR_MAXLEN 512
+#define EIP28_PKA_BITSHIFT 0x18
+#define EIP28_PKA_FUNCTION 0x1c
+#define   EIP28_FUNCTION_MULTIPLY 0
+#define   EIP28_FUNCTION_SEQ_MOD_EXP_CRT (1 << 12)
+#define   EIP28_FUNCTION_SEQ_MOD_EXP_ACT4 (2 << 12)
+#define   EIP28_FUNCTION_SEQ_ECC_ADD_AFFINE (3 << 12)
+#define   EIP28_FUNCTION_SEQ_MOD_EXP_ACT2 (4 << 12)
+#define   EIP28_FUNCTION_SEQ_ECC_MUL_AFFINE (5 << 12)
+#define   EIP28_FUNCTION_SEQ_MOD_EXP_VAR (6 << 12)
+#define   EIP28_FUNCTION_SEQ_MOD_INV (7 << 12)
+#define   EIP28_FUNCTION_RUN BIT(15)
+#define   EIP28_FUNCTION_SEQ_ECC_ADD_PROJECTIVE (16 << 12)
+#define   EIP28_FUNCTION_SEQ_ECC_MUL_PROJECTIVE (17 << 12)
+
+#define EIP28_PKA_SEQ_CTRL 0xc8
+#define   EIP28_CTRL_RESET BIT(31)
+#define   EIP28_CTRL_STATUS(reg) FIELD_GET(GENMASK(15, 8), (reg))
+#define   EIP28_CTRL_SEQ_IDLE 1
+
+#define EIP28_PKA_SW_REV 0xf8
+#define EIP28_PKA_REVISION 0xfc
+#define   EIP28_REV_MAJOR(reg) FIELD_GET(GENMASK(27, 24), (reg))
+#define   EIP28_REV_MINOR(reg) FIELD_GET(GENMASK(23, 20), (reg))
+#define   EIP28_REV_PATCH_LVL(reg) FIELD_GET(GENMASK(16, 16), (reg))
+#define   EIP28_REV_CAPABILITIES(reg) FIELD_GET(GENMASK(31, 28), (reg))
+
+#define EIP28_PKA_PROGRAM_RAM 0x2000
+#define EIP28_PKA_PROGRAM_RAM_SZ SZ_8K
+
+#define EIP28_PKA_NR_ODD_POW 2 /* 0 < bit_shift <= 16 */
+#define EIP28_FW_NAME "ram_code_eip28.bin"
+
+enum eip28_operation {
+	MOD_EXP_VAR,
+	MOD_EXP_ACT2,
+	MOD_EXP_ACT4,
+	MOD_EXP_CRT,
+	ECC_ADD_AFFINE,
+	ECC_ADD_PROJECTIVE,
+	ECC_MUL_AFFINE,
+	ECC_MUL_PROJECTIVE,
+	MULTIPLY,
+	MOD_INV
+};
+
+static struct eip28 *main_dev;
+
+struct eip28 {
+	void __iomem *regs;
+	struct device *dev;
+	struct clk *clk;
+	struct completion completion;
+	/* Serialize algorithms */
+	struct mutex lock;
+};
+
+struct eip28_rsa_ctx {
+	struct eip28 *priv;
+	u8 *n;
+	u8 *e;
+	u8 *d;
+	size_t n_sz;
+	size_t e_sz;
+	size_t d_sz;
+	unsigned char *message;
+};
+
+static void eip28_pkaram_write_word(struct eip28 *priv, u32 value, u32 word_off)
+{
+	writel(value, priv->regs + EIP28_PKA_PROGRAM_RAM + (word_off * 4));
+}
+
+static u32 eip28_pkaram_read_word(struct eip28 *priv, u32 word_off)
+{
+	return readl(priv->regs + EIP28_PKA_PROGRAM_RAM + (word_off * 4));
+}
+
+static void eip28_pkaram_write_vector(struct eip28 *priv, u32 *word_off,
+				      const u8 *buf, u32 bytes_count)
+{
+	u32 off;
+	int i;
+
+	off = *word_off + (bytes_count / 4) - 1;
+	for (i = 0; i < bytes_count; i += 4, off -= 1)
+		eip28_pkaram_write_word(priv, cpu_to_be32(*(u32 *)(buf + i)), off);
+
+	*word_off = round_up(*word_off * 4 + bytes_count + 1, 8) / 4;
+}
+
+static void eip28_pkaram_read_vector(struct eip28 *priv, u32 start_word,
+				     u8 *buf, u32 bytes_count)
+{
+	u32 off, *ptr;
+	int i;
+
+	memset(buf, 0, bytes_count);
+
+	off = start_word + (bytes_count / 4) - 1;
+	for (i = 0; i < bytes_count; i += 4, off -= 1) {
+		ptr = (u32 *)&buf[i];
+		*ptr = be32_to_cpu(eip28_pkaram_read_word(priv, off));
+	}
+}
+
+static size_t eip28_scratchpad_size(enum eip28_operation op)
+{
+	switch (op) {
+	case MOD_EXP_ACT2:
+	case MOD_EXP_ACT4:
+	case MOD_EXP_VAR:
+		return 9;
+	case MOD_EXP_CRT:
+		return 11;
+	case ECC_ADD_AFFINE:
+	case ECC_ADD_PROJECTIVE:
+	case ECC_MUL_AFFINE:
+	case ECC_MUL_PROJECTIVE:
+		return 19;
+	case MULTIPLY:
+		return 6;
+	case MOD_INV:
+		return 12;
+	default:
+		return 0;
+	}
+}
+
+static size_t eip28_work_area_size(enum eip28_operation op, u32 mod_len)
+{
+	u32 L = 0;
+
+	switch (op) {
+	case MOD_EXP_ACT2:
+	case MOD_EXP_ACT4:
+	case MOD_EXP_VAR:
+		/* (#odd powers + 3) x (B_len + 2) */
+		return (EIP28_PKA_NR_ODD_POW + 3) * (mod_len + 2);
+	case MOD_EXP_CRT:
+		/* (#odd powers + 3) x (B_len + 2) + (B_len + 2 - (B_len mod 2)) */
+		L = mod_len + 2 - (mod_len & 1);
+		return (EIP28_PKA_NR_ODD_POW + 3) * (mod_len + 2) + L;
+	case ECC_ADD_PROJECTIVE:
+	case ECC_ADD_AFFINE:
+	case ECC_MUL_PROJECTIVE:
+	case ECC_MUL_AFFINE:
+		/* 20 x (B_len + 2 + (B_len mod 2)) */
+		L = mod_len + 2 + (mod_len & 1);
+		return 20 * L;
+	case MULTIPLY:
+	case MOD_INV:
+	default:
+		return 0;
+	}
+}
+
+static size_t eip28_op_to_func(enum eip28_operation op)
+{
+	switch (op) {
+	case MOD_EXP_ACT2:
+		return EIP28_FUNCTION_SEQ_MOD_EXP_ACT2;
+	case MOD_EXP_ACT4:
+		return EIP28_FUNCTION_SEQ_MOD_EXP_ACT4;
+	case MOD_EXP_VAR:
+		return EIP28_FUNCTION_SEQ_MOD_EXP_VAR;
+	case MOD_EXP_CRT:
+		return EIP28_FUNCTION_SEQ_MOD_EXP_CRT;
+	case ECC_ADD_PROJECTIVE:
+		return EIP28_FUNCTION_SEQ_ECC_ADD_PROJECTIVE;
+	case ECC_ADD_AFFINE:
+		return EIP28_FUNCTION_SEQ_ECC_ADD_AFFINE;
+	case ECC_MUL_PROJECTIVE:
+		return EIP28_FUNCTION_SEQ_ECC_MUL_PROJECTIVE;
+	case ECC_MUL_AFFINE:
+		return EIP28_FUNCTION_SEQ_ECC_MUL_AFFINE;
+	case MULTIPLY:
+		return EIP28_FUNCTION_MULTIPLY;
+	case MOD_INV:
+		return EIP28_FUNCTION_SEQ_MOD_INV;
+	default:
+		WARN_ON_ONCE("EIP28 unsupported operation\n");
+		return 0;
+	}
+}
+
+static int eip28_vectors_overlap(u16 start_addr1, size_t len1, u16 start_addr2,	size_t len2)
+{
+	u32 end_addr1 = start_addr1 + len1 - 1;
+	u32 end_addr2 = start_addr2 + len2 - 1;
+
+	return !(end_addr1 < start_addr2 || end_addr2 < start_addr1);
+}
+
+static void eip28_trigger_operation(struct eip28 *priv, enum eip28_operation op)
+{
+	writel(eip28_op_to_func(op) | EIP28_FUNCTION_RUN,
+	       priv->regs + EIP28_PKA_FUNCTION);
+}
+
+static int eip28_run_mod_exp(struct eip28 *priv, u16 vector_a, u16 vector_b,
+			     u16 vector_c, u16 vector_d, size_t a_wlen, size_t bc_wlen)
+{
+	size_t scratchpad_off, result_wlen;
+	u32 val;
+
+	/* 0 < a_wlen <= MAX */
+	if (!a_wlen || a_wlen > EIP28_PKA_VECTOR_MAXLEN)
+		return -EINVAL;
+
+	/* 1 < b_wlen <= MAX */
+	if (bc_wlen < 2 ||  bc_wlen > EIP28_PKA_VECTOR_MAXLEN)
+		return -EINVAL;
+
+	scratchpad_off = (EIP28_PKA_PROGRAM_RAM_SZ / 4) - eip28_scratchpad_size(MOD_EXP_VAR);
+	result_wlen = eip28_work_area_size(MOD_EXP_VAR, bc_wlen);
+
+	/*
+	 * Make sure the area taken by each vector does not overlap with the
+	 * scratchpad, the other input vectors not the result vector.
+	 */
+	if ((vector_a + a_wlen > scratchpad_off) ||
+	    (vector_b + bc_wlen > scratchpad_off) ||
+	    (vector_c + bc_wlen > scratchpad_off) ||
+	    (vector_d + result_wlen > scratchpad_off))
+		return -EINVAL;
+
+	/* Ensure 64-bit alignment (offsets are words) */
+	if (!IS_ALIGNED(vector_a, 2) || !IS_ALIGNED(vector_b, 2) ||
+	    !IS_ALIGNED(vector_c, 2) || !IS_ALIGNED(vector_d, 2))
+		return -EINVAL;
+
+	/* Modulus must be odd */
+	val = eip28_pkaram_read_word(priv, vector_b);
+	if (!(val & 1))
+		return -EINVAL;
+
+	/*
+	 * Make sure there is no overlap between any of the input vectors and
+	 * the result vector. Only vector_c == vector_d is allowed.
+	 */
+	if (eip28_vectors_overlap(vector_a, a_wlen, vector_d, result_wlen) ||
+	    eip28_vectors_overlap(vector_b, bc_wlen, vector_d, result_wlen) ||
+	    (vector_c != vector_d &&
+	     eip28_vectors_overlap(vector_c, bc_wlen, vector_d, result_wlen)))
+		return -ERANGE;
+
+	writel(vector_a, priv->regs + EIP28_PKA_APTR);
+	writel(vector_b, priv->regs + EIP28_PKA_BPTR);
+	writel(vector_c, priv->regs + EIP28_PKA_CPTR);
+	writel(vector_d, priv->regs + EIP28_PKA_DPTR);
+	writel(a_wlen, priv->regs + EIP28_PKA_ALENGTH);
+	writel(bc_wlen, priv->regs + EIP28_PKA_BLENGTH);
+	writel(EIP28_PKA_NR_ODD_POW, priv->regs + EIP28_PKA_BITSHIFT);
+
+	eip28_trigger_operation(priv, MOD_EXP_VAR);
+
+	return 0;
+}
+
+/*
+ * EIP28 operates using vectors precisely located in PKARAM. A vector
+ * corresponds to a pointer of an element. In the RSA case:
+ *     vector A = exponent (e or d)
+ *     vector B = modulo (n)
+ *     vector C = message
+ *     vector D = result of the operations
+ *
+ *    PKARAM    Offset (pinternal_ram)
+ * +----------+ 0
+ * | vector A |
+ * +----------+ length(vector A)
+ * | vector B |
+ * +----------+ length(vector A) + length(vector B)
+ * | vector C |
+ * +----------+ length(vector A) + length(vector B) + length(vector C)
+ * | vector D |
+ * +----------+
+ */
+static int eip28_rsa_operation(struct akcipher_request *req, bool encrypt)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct eip28_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	u16 vector_a, vector_b, vector_c, vector_d;
+	struct eip28 *priv = ctx->priv;
+	unsigned int pkaram_off = 0;
+	size_t a_wlen, bc_wlen;
+	u32 reg;
+	int ret;
+
+	/* Sanity check */
+	if (req->src_len > ctx->n_sz)
+		return -EMSGSIZE;
+
+	/* Check if no computation is running */
+	reg = readl(priv->regs + EIP28_PKA_FUNCTION);
+	if (reg & EIP28_FUNCTION_RUN)
+		return -EBUSY;
+
+	/* Check if PKARAM is accessible */
+	reg = readl(priv->regs + EIP28_PKA_SEQ_CTRL);
+	if (reg & EIP28_CTRL_RESET) {
+		dev_err(priv->dev, "PKARAM not accessible\n");
+		return -EBUSY;
+	}
+
+	/* Initializes vector A with either 'e' or 'd' and move the internal pointer */
+	vector_a = 0;
+	if (encrypt) {
+		eip28_pkaram_write_vector(priv, &pkaram_off, ctx->e, ctx->e_sz);
+		a_wlen = ctx->e_sz / 4;
+	} else {
+		eip28_pkaram_write_vector(priv, &pkaram_off, ctx->d, ctx->d_sz);
+		a_wlen = ctx->d_sz / 4;
+	}
+
+	/* Initializes Vector B with the modulo 'n' */
+	vector_b = pkaram_off;
+	eip28_pkaram_write_vector(priv, &pkaram_off, ctx->n, ctx->n_sz);
+	bc_wlen = ctx->n_sz / 4;
+
+	/* Initializes Vector C with the message */
+	vector_c = pkaram_off;
+	memset(ctx->message, 0, ctx->n_sz - req->src_len);
+	sg_copy_to_buffer(req->src, 1, &ctx->message[ctx->n_sz - req->src_len], req->src_len);
+	eip28_pkaram_write_vector(priv, &pkaram_off, ctx->message, ctx->n_sz);
+
+	/* Initialize vector D, output will overwrite the message */
+	vector_d = vector_c;
+
+	/* Trigger operation */
+	ret = eip28_run_mod_exp(priv, vector_a, vector_b, vector_c, vector_d,
+				a_wlen, bc_wlen);
+	if (ret) {
+		dev_err(priv->dev, "Modular exponentiation error : %d\n", ret);
+		return ret;
+	}
+
+	ret = wait_for_completion_timeout(&priv->completion, msecs_to_jiffies(2000));
+	if (!ret) {
+		reinit_completion(&priv->completion);
+		return -ETIMEDOUT;
+	}
+
+	/* Retrieve result */
+	reg = readl(priv->regs + EIP28_PKA_SEQ_CTRL);
+	if (EIP28_CTRL_STATUS(reg) != EIP28_CTRL_SEQ_IDLE)
+		return -EIO;
+
+	memset(ctx->message, 0, ctx->n_sz);
+	eip28_pkaram_read_vector(priv, vector_d, ctx->message, ctx->n_sz);
+	sg_copy_from_buffer(req->dst, 1, ctx->message, ctx->n_sz);
+
+	return 0;
+}
+
+static int eip28_rsa_save_modulo(struct eip28_rsa_ctx *ctx, struct rsa_key *key)
+{
+	unsigned int nskip;
+
+	/* Skip the first empty bytes in the buffer */
+	for (nskip = 0; nskip < key->n_sz; nskip++)
+		if (key->n[nskip])
+			break;
+
+	ctx->n_sz = key->n_sz - nskip;
+
+	ctx->n = kzalloc(round_up(ctx->n_sz, 4), GFP_KERNEL);
+	if (!ctx->n)
+		return -ENOMEM;
+
+	memcpy(ctx->n, key->n + nskip, ctx->n_sz);
+	if (!ctx->n)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int eip28_rsa_save_keypart(u8 **dst, size_t *dest_sz, const u8 *src, size_t src_sz,
+				  size_t modulo_size)
+{
+	unsigned int nskip, real_size_buf;
+
+	/* Skip the first empty bytes in the buffer */
+	for (nskip = 0; nskip < src_sz; nskip++)
+		if (src[nskip])
+			break;
+
+	real_size_buf = src_sz - nskip;
+	if (real_size_buf > modulo_size)
+		return -EINVAL;
+
+	/* Write data at the end of the buffer */
+	*dst = kzalloc(round_up(modulo_size, 4), GFP_KERNEL);
+	if (!*dst)
+		return -ENOMEM;
+
+	memcpy(*dst + (modulo_size - real_size_buf), src + nskip, real_size_buf);
+	*dest_sz = modulo_size;
+
+	return 0;
+}
+
+static void eip28_rsa_clean_ctx(struct eip28_rsa_ctx *ctx)
+{
+	struct eip28 *priv;
+
+	kfree(ctx->e);
+	kfree(ctx->n);
+	kfree(ctx->d);
+	kfree(ctx->message);
+
+	priv = ctx->priv;
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->priv = priv;
+}
+
+static unsigned int eip28_rsa_max_size(struct crypto_akcipher *tfm)
+{
+	struct eip28_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+	return ctx->n_sz;
+}
+
+static int eip28_rsa_encrypt(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct eip28_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	int ret;
+
+	mutex_lock(&ctx->priv->lock);
+	ret = eip28_rsa_operation(req, true);
+	mutex_unlock(&ctx->priv->lock);
+
+	return ret;
+}
+
+static int eip28_rsa_decrypt(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct eip28_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	int ret;
+
+	mutex_lock(&ctx->priv->lock);
+	ret = eip28_rsa_operation(req, false);
+	mutex_unlock(&ctx->priv->lock);
+
+	return ret;
+}
+
+static int eip28_rsa_check_key_length(unsigned int len)
+{
+	switch (len) {
+	case 256:
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int eip28_rsa_setkey(struct eip28_rsa_ctx *ctx, const void *key,
+			    unsigned int key_len, bool private)
+{
+	struct rsa_key raw_key = {0};
+	int ret;
+
+	/* Parse the key elements: (n, e) for the public key, (n, d) for the private key */
+	if (private)
+		ret = rsa_parse_priv_key(&raw_key, key, key_len);
+	else
+		ret = rsa_parse_pub_key(&raw_key, key, key_len);
+	if (ret)
+		return ret;
+
+	/* Clean the buffers before copying the key elements */
+	eip28_rsa_clean_ctx(ctx);
+
+	/* Save the modulo 'n' */
+	ret = eip28_rsa_save_modulo(ctx, &raw_key);
+	if (ret)
+		goto clean_ctx;
+
+	ret = eip28_rsa_check_key_length(ctx->n_sz * 8);
+	if (ret)
+		goto clean_ctx;
+
+	/* Save the public exponent 'e' */
+	ret = eip28_rsa_save_keypart(&ctx->e, &ctx->e_sz,
+				     raw_key.e, raw_key.e_sz, ctx->n_sz);
+	if (ret)
+		goto clean_ctx;
+
+	/* Save the private exponent 'd', if known */
+	if (private) {
+		ret = eip28_rsa_save_keypart(&ctx->d, &ctx->d_sz,
+					     raw_key.d, raw_key.d_sz, ctx->n_sz);
+		if (ret)
+			goto clean_ctx;
+	}
+
+	/* Set the message buffer */
+	ctx->message = kzalloc(ctx->n_sz, GFP_KERNEL);
+	if (!ctx->message) {
+		ret = -ENOMEM;
+		goto clean_ctx;
+	}
+
+	return 0;
+
+clean_ctx:
+	eip28_rsa_clean_ctx(ctx);
+	return ret;
+}
+
+static int eip28_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
+				  unsigned int key_len)
+{
+	struct eip28_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+	return eip28_rsa_setkey(ctx, key, key_len, true);
+}
+
+static int eip28_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+				 unsigned int key_len)
+{
+	struct eip28_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+	return eip28_rsa_setkey(ctx, key, key_len, false);
+}
+
+static int eip28_rsa_init(struct crypto_akcipher *tfm)
+{
+	struct eip28_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+	ctx->priv = main_dev;
+
+	return 0;
+}
+
+static void eip28_rsa_exit(struct crypto_akcipher *tfm)
+{
+	struct eip28_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+	eip28_rsa_clean_ctx(ctx);
+}
+
+struct akcipher_alg eip28_rsa = {
+	.encrypt = eip28_rsa_encrypt,
+	.decrypt = eip28_rsa_decrypt,
+	.set_pub_key = eip28_rsa_set_pub_key,
+	.set_priv_key = eip28_rsa_set_priv_key,
+	.max_size = eip28_rsa_max_size,
+	.init = eip28_rsa_init,
+	.exit = eip28_rsa_exit,
+	.base = {
+		.cra_name = "rsa",
+		.cra_driver_name = "eip28-rsa",
+		.cra_flags = CRYPTO_ALG_TYPE_AKCIPHER,
+		.cra_priority = 300,
+		.cra_module = THIS_MODULE,
+		.cra_ctxsize = sizeof(struct eip28_rsa_ctx),
+	},
+};
+
+static int eip28_check_firmware(struct eip28 *priv)
+{
+	u32 reg;
+
+	reg = readl(priv->regs + EIP28_PKA_REVISION);
+	if (EIP28_REV_MAJOR(reg) != 2) {
+		dev_err(priv->dev, "Unsupported hardware revision: %lu.%lu.%lu\n",
+			EIP28_REV_MAJOR(reg), EIP28_REV_MINOR(reg), EIP28_REV_PATCH_LVL(reg));
+		return -EINVAL;
+	}
+
+	reg = readl(priv->regs + EIP28_PKA_SW_REV);
+	if ((EIP28_REV_MAJOR(reg) != 2) ||
+	    (EIP28_REV_MINOR(reg) != 1) ||
+	    (EIP28_REV_PATCH_LVL(reg) != 1) ||
+	    (EIP28_REV_CAPABILITIES(reg) != 2)) {
+		dev_err(priv->dev, "Unsupported firmware revision: %lu.%lu.%lu.%lu\n",
+			EIP28_REV_MAJOR(reg), EIP28_REV_MINOR(reg),
+			EIP28_REV_PATCH_LVL(reg), EIP28_REV_CAPABILITIES(reg));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int eip28_write_firmware(struct eip28 *priv, const struct firmware *eip28_fw)
+{
+	const u32 *data = (const u32 *)eip28_fw->data;
+	u32 reg;
+	int i;
+
+	if (eip28_fw->size > EIP28_PKA_PROGRAM_RAM_SZ)
+		return -EOPNOTSUPP;
+
+	/* Enter reset mode, which allows writing of PKA_PROGRAM_RAM registers */
+	writel(EIP28_CTRL_RESET, priv->regs + EIP28_PKA_SEQ_CTRL);
+	reg = readl(priv->regs + EIP28_PKA_SEQ_CTRL);
+	if (reg != EIP28_CTRL_RESET)
+		return -EIO;
+
+	for (i = 0; i < (eip28_fw->size / sizeof(u32)); i++)
+		writel(data[i], priv->regs + EIP28_PKA_PROGRAM_RAM + (i * 4));
+
+	/* Release reset mode, start the EIP28 */
+	writel(0, priv->regs + EIP28_PKA_SEQ_CTRL);
+	reg = readl(priv->regs + EIP28_PKA_SEQ_CTRL);
+	if (reg & EIP28_CTRL_RESET)
+		return -EIO;
+
+	return 0;
+}
+
+static int eip28_load_firmware(struct eip28 *priv)
+{
+	const struct firmware *eip28_fw;
+	int ret = 0;
+
+	ret = request_firmware(&eip28_fw, EIP28_FW_NAME, priv->dev);
+	if (ret)
+		return ret;
+
+	/* Write the EIP28 firmware in RAM CODE registers */
+	ret = eip28_write_firmware(priv, eip28_fw);
+	release_firmware(eip28_fw);
+	if (ret) {
+		dev_err(priv->dev, "Unable to write firmware (%d)\n", ret);
+		return ret;
+	}
+
+	/*
+	 * Once firmware is loaded, after releasing the reset bit the firmware
+	 * starts executing and after a few clock cycles it clears the RUN bit,
+	 * indicating initialization is done.
+	 */
+	ret = wait_for_completion_timeout(&priv->completion, msecs_to_jiffies(1000));
+	if (!ret) {
+		dev_err(priv->dev, "Firmware loading failed\n");
+		return -ETIMEDOUT;
+	}
+
+	/* Verify the firmware: can be read, is valid, has the correct version */
+	return eip28_check_firmware(priv);
+}
+
+static irqreturn_t eip28_irq_handler(int irq, void *dev_id)
+{
+	struct eip28 *priv = dev_id;
+
+	complete(&priv->completion);
+
+	return IRQ_HANDLED;
+}
+
+static int eip28_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct eip28 *priv;
+	int irq, ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	priv->clk = devm_clk_get_enabled(dev, NULL);
+	if (IS_ERR(priv->clk))
+		return PTR_ERR(priv->regs);
+
+	irq = platform_get_irq(pdev, 2);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_irq(dev, irq, eip28_irq_handler, 0, "eip28", priv);
+	if (ret)
+		return ret;
+
+	main_dev = priv;
+	priv->dev = dev;
+	init_completion(&priv->completion);
+	mutex_init(&priv->lock);
+
+	/* Initialize the code section of the internal RAM with the firmware */
+	ret = eip28_load_firmware(priv);
+	if (ret) {
+		dev_err(dev, "Unable to initialize EIP28 firmware (%d)\n", ret);
+		return ret;
+	}
+
+	/* Initializing crypto API for RSA keys */
+	ret = crypto_register_akcipher(&eip28_rsa);
+	if (ret) {
+		dev_err(dev, "Unable to initialize RSA\n");
+		return ret;
+	}
+
+	dev_info(dev, "EIP28 probed successfully\n");
+
+	return ret;
+}
+
+static void eip28_remove(struct platform_device *pdev)
+{
+	crypto_unregister_akcipher(&eip28_rsa);
+}
+
+static const struct of_device_id eip28_of_match_table[] = {
+	{ .compatible = "inside-secure,safexcel-eip28", },
+	{}
+};
+
+static struct platform_driver eip28_driver = {
+	.probe = eip28_probe,
+	.remove = eip28_remove,
+	.driver = {
+		.name = "Safexcel EIP28 PKA",
+		.of_match_table = eip28_of_match_table,
+	},
+};
+module_platform_driver(eip28_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pierre Castellan <pierre.castellan@non.se.com>");
+MODULE_AUTHOR("Thomas Ghesquiere <thomas.ghesquierre@non.se.com>");
+MODULE_AUTHOR("Mathieu Hadjimegrian <mathieu.hadjimegrian@non.se.com>");
+MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
+MODULE_DESCRIPTION("SafeXcel EIP28 Public Key Accelerator driver");
+MODULE_FIRMWARE(EIP28_FW_NAME);

-- 
2.51.1


^ permalink raw reply related

* [PATCH 14/16] crypto: Group Inside-Secure IPs together and align the titles
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

There are several drivers from the SafeXcel family already, the EIP-93,
the EIP-97 and EIP-197. We will soon also have the EIP-28.

Group them in the Kconfig menu and both titles to make explicit that
these components are from the same family and mimic the string used for
the Intel components (above in the menu).

Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 drivers/crypto/Kconfig                     | 45 +++++++++++++++---------------
 drivers/crypto/inside-secure/eip93/Kconfig |  2 +-
 2 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 8d3b5d2890f8..b3a6bbf0aacf 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -782,28 +782,6 @@ config CRYPTO_DEV_BCM_SPU
 
 source "drivers/crypto/stm32/Kconfig"
 
-config CRYPTO_DEV_SAFEXCEL
-	tristate "Inside Secure's SafeXcel cryptographic engine driver"
-	depends on (OF || PCI || COMPILE_TEST) && HAS_IOMEM
-	select CRYPTO_LIB_AES
-	select CRYPTO_AUTHENC
-	select CRYPTO_SKCIPHER
-	select CRYPTO_LIB_DES
-	select CRYPTO_HASH
-	select CRYPTO_HMAC
-	select CRYPTO_MD5
-	select CRYPTO_SHA1
-	select CRYPTO_SHA256
-	select CRYPTO_SHA512
-	select CRYPTO_CHACHA20POLY1305
-	select CRYPTO_SHA3
-	help
-	  This driver interfaces with the SafeXcel EIP-97 and EIP-197 cryptographic
-	  engines designed by Inside Secure. It currently accelerates DES, 3DES and
-	  AES block ciphers in ECB and CBC mode, as well as SHA1, SHA224, SHA256,
-	  SHA384 and SHA512 hash algorithms for both basic hash and HMAC.
-	  Additionally, it accelerates combined AES-CBC/HMAC-SHA AEAD operations.
-
 config CRYPTO_DEV_ARTPEC6
 	tristate "Support for Axis ARTPEC-6/7 hardware crypto acceleration."
 	depends on ARM && (ARCH_ARTPEC || COMPILE_TEST)
@@ -876,6 +854,29 @@ config CRYPTO_DEV_SA2UL
 
 source "drivers/crypto/aspeed/Kconfig"
 source "drivers/crypto/starfive/Kconfig"
+
+config CRYPTO_DEV_SAFEXCEL
+	tristate "Support for Inside Secure's SafeXcel EIP-97/EIP-197"
+	depends on (OF || PCI || COMPILE_TEST) && HAS_IOMEM
+	select CRYPTO_LIB_AES
+	select CRYPTO_AUTHENC
+	select CRYPTO_SKCIPHER
+	select CRYPTO_LIB_DES
+	select CRYPTO_HASH
+	select CRYPTO_HMAC
+	select CRYPTO_MD5
+	select CRYPTO_SHA1
+	select CRYPTO_SHA256
+	select CRYPTO_SHA512
+	select CRYPTO_CHACHA20POLY1305
+	select CRYPTO_SHA3
+	help
+	  This driver interfaces with the SafeXcel EIP-97 and EIP-197 cryptographic
+	  engines designed by Inside Secure. It currently accelerates DES, 3DES and
+	  AES block ciphers in ECB and CBC mode, as well as SHA1, SHA224, SHA256,
+	  SHA384 and SHA512 hash algorithms for both basic hash and HMAC.
+	  Additionally, it accelerates combined AES-CBC/HMAC-SHA AEAD operations.
+
 source "drivers/crypto/inside-secure/eip93/Kconfig"
 source "drivers/crypto/ti/Kconfig"
 
diff --git a/drivers/crypto/inside-secure/eip93/Kconfig b/drivers/crypto/inside-secure/eip93/Kconfig
index 8353d3d7ec9b..8a671b709a11 100644
--- a/drivers/crypto/inside-secure/eip93/Kconfig
+++ b/drivers/crypto/inside-secure/eip93/Kconfig
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 config CRYPTO_DEV_EIP93
-	tristate "Support for EIP93 crypto HW accelerators"
+	tristate "Support for Inside Secure's SafeXcel EIP93"
 	depends on SOC_MT7621 || ARCH_AIROHA ||COMPILE_TEST
 	select CRYPTO_LIB_AES
 	select CRYPTO_LIB_DES

-- 
2.51.1


^ permalink raw reply related

* [PATCH 13/16] hwrng: omap: Enable on Renesas RZ/N1D
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

The Kconfig symbol and associated seem to be badly named as they have
nothing OMAP specific but instead refer to Inside Secure Safexcel
devices which have been used in many SoCs from different
manufacturers (like OMAP, Marvell but also eg. Renesas).

The Renesas RZ/N1D features this IP, so add this architecture to the
dependency allow list. In practice this dependency list does not seem
very relevant and could be entirely dropped, given the fact that this IP
has been implemented by many different vendors and seems to be
architecture agnostic.

Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 drivers/char/hw_random/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 492a2a61a65b..a26b705fb111 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -193,7 +193,7 @@ config HW_RANDOM_IXP4XX
 
 config HW_RANDOM_OMAP
 	tristate "OMAP Random Number Generator support"
-	depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || ARCH_MVEBU || ARCH_K3 || COMPILE_TEST
+	depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || ARCH_MVEBU || ARCH_K3 || ARCH_RZN1 || COMPILE_TEST
 	default HW_RANDOM
 	help
 	  This driver provides kernel-side support for the Random Number

-- 
2.51.1


^ permalink raw reply related

* [PATCH 12/16] irqchip/eip201-aic: Add support for Safexcel EIP-201 AIC
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

Describe the EIP-201 Advanced Interrupt Controller from Inside Secure,
typically found in a bigger block named EIP-150. This controller is
rather simple and is driven using the generic irqchip model. Its
own interrupt domain is limited to just a few interrupts connected to
other inner blocks, such as a Random Number Generator and a Public Key
Accelerator.

The one I used receives only rising edge interrupts and uses its own
logic to track them. It is theoretically possible to wire devices with
level interrupts, but not in the context of the EIP-150.

Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 drivers/irqchip/Kconfig          |   8 ++
 drivers/irqchip/Makefile         |   1 +
 drivers/irqchip/irq-eip201-aic.c | 221 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 230 insertions(+)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index f07b00d7fef9..b098bb00a224 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -826,4 +826,12 @@ config SUNPLUS_SP7021_INTC
 	  chained controller, routing all interrupt source in P-Chip to
 	  the primary controller on C-Chip.
 
+config SAFEXCEL_EIP201_AIC
+        tristate "Safexcel EIP201 AIC"
+	select IRQ_DOMAIN
+	help
+	  Support for the Advanced Interrupt Controller (AIC) typically
+	  inside Safexcel EIP150 IPs, gathering Public Key Accelerator
+	  and True Random Number Generator interrupts.
+
 endmenu
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 26aa3b6ec99f..80784a02f4a8 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -136,3 +136,4 @@ obj-$(CONFIG_APPLE_AIC)			+= irq-apple-aic.o
 obj-$(CONFIG_MCHP_EIC)			+= irq-mchp-eic.o
 obj-$(CONFIG_SOPHGO_SG2042_MSI)		+= irq-sg2042-msi.o
 obj-$(CONFIG_SUNPLUS_SP7021_INTC)	+= irq-sp7021-intc.o
+obj-$(CONFIG_SAFEXCEL_EIP201_AIC)	+= irq-eip201-aic.o
diff --git a/drivers/irqchip/irq-eip201-aic.c b/drivers/irqchip/irq-eip201-aic.c
new file mode 100644
index 000000000000..514fd39e2777
--- /dev/null
+++ b/drivers/irqchip/irq-eip201-aic.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 Schneider Electric
+ * Authored by Miquel Raynal <miquel.raynal@bootlin.com>
+ * Based on the work from Mathieu Hadjimegrian <mathieu.hadjimegrian@non.se.com>
+ */
+
+#include "linux/irq.h"
+#include "linux/stddef.h"
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/interrupt-controller/inside-secure,safexcel-eip201.h>
+
+#define EIP201_AIC_POL_CTRL 0x0 /* RO */
+#define   EIP201_AIC_POL_LOW_FALLING 0
+#define   EIP201_AIC_POL_HIGH_RISING 1
+
+#define EIP201_AIC_TYP_CTRL 0x4 /* RO */
+#define   EIP201_AIC_TYP_LEVEL 0
+#define   EIP201_AIC_TYP_EDGE 1
+
+#define EIP201_AIC_ENABLE_SET 0xC /* WO */
+#define EIP201_AIC_ENABLED_STAT 0x10 /* RO */
+#define EIP201_AIC_ENABLE_CLR 0x14 /* WO */
+#define EIP201_AIC_ACK 0x10 /* WO */
+
+#define EIP201_AIC_REVISION 0x3FFC
+#define   EIP201_AIC_REV_NUM(reg) FIELD_GET(GENMASK(7, 0), reg)
+#define   EIP201_AIC_REV_COMP_NUM(reg) FIELD_GET(GENMASK(15, 8), reg)
+
+#define EIP201_AIC_INT(reg, int) field_get(BIT(int), reg)
+#define EIP201_AIC_NINT 7
+#define EIP201_AIC_INT_MASK (BIT(EIP201_AIC_NINT) - 1)
+
+struct eip201_aic {
+	struct device *dev;
+	void __iomem *regs;
+	struct irq_domain *domain;
+	struct irq_chip_generic *gc;
+	u32 type;
+	u32 pol;
+};
+
+static struct eip201_aic *irq_domain_to_aic(struct irq_domain *d)
+{
+	return d->host_data;
+}
+
+static int eip201_aic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
+				       const u32 *intspec, unsigned int intsize,
+				       irq_hw_number_t *out_hwirq, unsigned int *out_type)
+{
+	struct eip201_aic *aic = irq_domain_to_aic(d);
+	int ret;
+
+	ret = irq_domain_xlate_twocell(d, ctrlr, intspec, intsize, out_hwirq, out_type);
+	if (ret)
+		return ret;
+
+	/* One interrupt is reserved, two are for Inside Secure debugging purposes only */
+	switch (*out_hwirq) {
+	case AIC_PKA_INT0:
+	case AIC_PKA_INT1:
+	case AIC_RESERVED:
+		return -EINVAL;
+	default:
+		break;
+	}
+
+	/*
+	 * Flow type is implementation specific and hardcoded, make sure it is corect,
+	 * even though the documentation says EIP blocks generate edge interrupts.
+	 */
+
+	/* Type register indicates:
+	 * - '1' for edge interrupts
+	 * - '0' for level interrupts
+	 */
+	if (*out_type & IRQ_TYPE_LEVEL_MASK &&
+	    EIP201_AIC_INT(aic->type, *out_hwirq))
+		return -EINVAL;
+
+	/*
+	 * Polarity register indicates:
+	 * - '1' for level high or rising edge
+	 * - '0' for level low or falling edge
+	 */
+	if (*out_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING) &&
+	    EIP201_AIC_INT(aic->pol, *out_hwirq))
+		return -EINVAL;
+
+	return 0;
+}
+
+const struct irq_domain_ops eip201_aic_chip_ops = {
+	.map	= irq_map_generic_chip,
+	.unmap  = irq_unmap_generic_chip,
+	.xlate	= eip201_aic_irq_domain_xlate,
+};
+
+static irqreturn_t eip201_aic_irq_handler(int irq, void *dev_id)
+{
+	struct eip201_aic *aic = dev_id;
+	unsigned long pending;
+	irq_hw_number_t hwirq;
+
+	pending = readl(aic->regs + EIP201_AIC_ENABLED_STAT);
+	if (!pending)
+		return IRQ_NONE;
+
+	/* Ack interrupts ASAP to decrease the likelyhood of missing an edge one */
+	writel(pending, aic->regs + EIP201_AIC_ACK);
+
+	for_each_set_bit(hwirq, &pending, EIP201_AIC_NINT)
+		generic_handle_domain_irq(aic->domain, hwirq);
+
+	return IRQ_HANDLED;
+}
+
+static int eip201_aic_probe(struct platform_device *pdev)
+{
+	struct eip201_aic *aic;
+	struct clk *clk;
+	u32 rev;
+	int irq;
+	int ret;
+
+	aic = devm_kzalloc(&pdev->dev, sizeof(*aic), GFP_KERNEL);
+	if (!aic)
+		return -ENOMEM;
+
+	aic->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (!aic->regs)
+		return -EINVAL;
+
+	clk = devm_clk_get_enabled(&pdev->dev, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	rev = readl(aic->regs + EIP201_AIC_REVISION);
+	if (!(EIP201_AIC_REV_NUM(rev) ^ EIP201_AIC_REV_COMP_NUM(rev)))
+		return -ENXIO;
+
+	platform_set_drvdata(pdev, aic);
+	aic->dev = &pdev->dev;
+
+	/* Cache the RO type and polarity of all interrupts */
+	aic->type = readl(aic->regs + EIP201_AIC_TYP_CTRL);
+	aic->pol = readl(aic->regs + EIP201_AIC_POL_CTRL);
+
+	/* Disable/clear all interrupts */
+	writel(EIP201_AIC_INT_MASK, aic->regs + EIP201_AIC_ENABLE_CLR);
+	writel(EIP201_AIC_INT_MASK, aic->regs + EIP201_AIC_ACK);
+
+	aic->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), EIP201_AIC_NINT,
+					       &eip201_aic_chip_ops, aic);
+	if (!aic->domain)
+		return -ENXIO;
+
+	ret = irq_alloc_domain_generic_chips(aic->domain, EIP201_AIC_NINT, 1, "eip201-aic",
+					     handle_edge_irq, 0, 0, 0);
+	if (ret)
+		goto remove_domain;
+
+	aic->gc = irq_get_domain_generic_chip(aic->domain, 0);
+	aic->gc->reg_base = aic->regs;
+	aic->gc->chip_types[0].regs.ack = EIP201_AIC_ACK;
+	aic->gc->chip_types[0].regs.enable = EIP201_AIC_ENABLE_SET;
+	aic->gc->chip_types[0].regs.disable = EIP201_AIC_ENABLE_CLR;
+	aic->gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
+	aic->gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
+	aic->gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
+	aic->gc->chip_types[0].chip.flags = IRQCHIP_MASK_ON_SUSPEND;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_irq(&pdev->dev, irq, eip201_aic_irq_handler, 0,
+			       dev_name(&pdev->dev), aic);
+	if (ret < 0)
+		goto remove_gc;
+
+	return 0;
+
+remove_gc:
+	irq_remove_generic_chip(aic->gc, EIP201_AIC_INT_MASK, 0, 0);
+remove_domain:
+	irq_domain_remove(aic->domain);
+
+	return ret;
+}
+
+static void eip201_aic_remove(struct platform_device *pdev)
+{
+	struct eip201_aic *aic = platform_get_drvdata(pdev);
+
+	irq_remove_generic_chip(aic->gc, EIP201_AIC_INT_MASK, 0, 0);
+	irq_domain_remove(aic->domain);
+}
+
+static const struct of_device_id eip201_aic_of_match[] = {
+	{ .compatible = "inside-secure,safexcel-eip201", },
+	{},
+};
+
+static struct platform_driver eip201_aic_driver = {
+	.probe = eip201_aic_probe,
+	.remove = eip201_aic_remove,
+	.driver = {
+		.name = "safexcel-eip201-aic",
+		.of_match_table = eip201_aic_of_match,
+	},
+};
+module_platform_driver(eip201_aic_driver);

-- 
2.51.1


^ permalink raw reply related

* [PATCH 11/16] clk: tests: Add Kunit testing for nexus nodes
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

Add a nexus node with a child requesting a mapped clock in the fake DT
overlay to verify that the parsing is also correctly working.

Suggested-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 drivers/clk/clk_test.c                   | 20 ++++++++++++++++++++
 drivers/clk/kunit_clk_parse_clkspec.dtso | 10 ++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c
index 8a17ad0d185f..cb0071955146 100644
--- a/drivers/clk/clk_test.c
+++ b/drivers/clk/clk_test.c
@@ -3660,10 +3660,30 @@ static void clk_parse_and_get_parent_name(struct kunit *test)
 			   clk_parse_clkspec_1_init_data.name);
 }
 
+static void clk_parse_and_get_nexus(struct kunit *test)
+{
+	struct clk_parse_clkspec_ctx *ctx = test->priv;
+	struct clk_hw *hw1, *hw2;
+	struct device_node *np;
+
+	/* Get clocks by index */
+	np = of_find_node_by_name(NULL, "kunit-clock-nexus-child");
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np);
+	hw1 = of_clk_get_hw(np, 0, NULL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, hw1);
+
+	hw2 = of_clk_get_hw(ctx->cons_np, 1, NULL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, hw2);
+	KUNIT_EXPECT_PTR_EQ(test, hw1, hw2);
+
+	of_node_put(np);
+}
+
 static struct kunit_case clk_parse_clkspec_test_cases[] = {
 	KUNIT_CASE(clk_parse_clkspec_with_correct_index_and_name),
 	KUNIT_CASE(clk_parse_clkspec_with_incorrect_index_and_name),
 	KUNIT_CASE(clk_parse_and_get_parent_name),
+	KUNIT_CASE(clk_parse_and_get_nexus),
 	{}
 };
 
diff --git a/drivers/clk/kunit_clk_parse_clkspec.dtso b/drivers/clk/kunit_clk_parse_clkspec.dtso
index c93feb93e101..a4115216d2aa 100644
--- a/drivers/clk/kunit_clk_parse_clkspec.dtso
+++ b/drivers/clk/kunit_clk_parse_clkspec.dtso
@@ -18,4 +18,14 @@ kunit-clock-consumer {
 		clocks = <&kunit_clock_provider1 0>, <&kunit_clock_provider2 0>;
 		clock-names = "first_clock", "second_clock";
 	};
+
+	kunit_clock_nexus: kunit-clock-nexus {
+		clocks = <&kunit_clock_provider2 0>;
+		clock-map = <&kunit_clock_provider2 0>;
+		#clock-cells = <0>;
+
+		kunit-clock-nexus-child {
+			clocks = <&kunit_clock_nexus>;
+		};
+	};
 };

-- 
2.51.1


^ permalink raw reply related

* [PATCH 10/16] clk: Add support for clock nexus dt bindings
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric), Herve Codina
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

A nexus node is some kind of parent device abstracting the outer
connections. They are particularly useful for describing connectors-like
interfaces but not only. Certain IP blocks will typically include inner
blocks and distribute resources to them.

In the case of clocks, there is already the concept of clock controller,
but this usually indicates some kind of control over the said clock,
ie. gate or rate control. When there is none of this, an existing
approach is to reference the upper clock, which is wrong from a hardware
point of view.

Nexus nodes are already part of the device-tree specification and clocks
are already mentioned:
https://github.com/devicetree-org/devicetree-specification/blob/v0.4/source/chapter2-devicetree-basics.rst#nexus-nodes-and-specifier-mapping

Following the introductions of nexus nodes support for interrupts, gpios
and pwms, here is the same logic applied again to the clk subsystem,
just by transitioning from of_parse_phandle_with_args() to
of_parse_phandle_with_args_map():

* Nexus OF support:
commit bd6f2fd5a1d5 ("of: Support parsing phandle argument lists through a nexus node")
* GPIO adoption:
commit c11e6f0f04db ("gpio: Support gpio nexus dt bindings")
* PWM adoption:
commit e71e46a6f19c ("pwm: Add support for pwm nexus dt bindings")

Expected Nexus properties supported:
- clock-map: maps inner clocks to inlet clocks,
- clock-map-mask: specifier cell(s) which will be remapped,
- clock-map-pass-thru: specifier cell(s) not used for remapping,
  forwarded as-is.

In my own usage I had to deal with controllers where clock-map-mask and
clock-map-pass-thru were not relevant, but here is a made up example
showing how all these properties could go together:

Example:
    soc_clk: clock-controller {
        #clock-cells = <2>;
    };

    container: container {
        #clock-cells = <2>;
        clock-map = <0 0 &soc_clk 2 0>,
                    <1 0 &soc_clk 6 0>;
        clock-map-mask = <0xffffffff 0x0>;
        clock-map-pass-thru = <0x0 0xffffffff>;

        child-device {
            clocks = <&container 1 0>;
	    /* This is equivalent to <&soc_clk 6 0> */
        };
    };

The child device does not need to know about the outer implementation,
and only knows about what the nexus provides. The nexus acts as a
pass-through, with no extra control.

Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
Reviewed-by: Herve Codina <herve.codina@bootlin.com>
---
 drivers/clk/clk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 93e33ff30f3a..196ba727e84b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -5218,8 +5218,8 @@ static int of_parse_clkspec(const struct device_node *np, int index,
 		 */
 		if (name)
 			index = of_property_match_string(np, "clock-names", name);
-		ret = of_parse_phandle_with_args(np, "clocks", "#clock-cells",
-						 index, out_args);
+		ret = of_parse_phandle_with_args_map(np, "clocks", "clock",
+						     index, out_args);
 		if (!ret)
 			break;
 		if (name && index >= 0)

-- 
2.51.1


^ permalink raw reply related

* [PATCH 09/16] clk: Use the generic OF phandle parsing in only one place
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

There should be one single entry in the OF world, so that the way we
parse the DT is always the same. make sure this is the case by avoid
calling of_parse_phandle_with_args() from of_clk_get_parent_name(). This
is even more relevant as we currently fail to parse clock-ranges. As a
result, it seems to be safer to directly call of_parse_clkspec() there.

Suggested-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 drivers/clk/clk.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 591c0780b61e..93e33ff30f3a 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -5375,8 +5375,7 @@ const char *of_clk_get_parent_name(const struct device_node *np, int index)
 	int count;
 	struct clk *clk;
 
-	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
-					&clkspec);
+	rc = of_parse_clkspec(np, index, NULL, &clkspec);
 	if (rc)
 		return NULL;
 

-- 
2.51.1


^ permalink raw reply related

* [PATCH 08/16] clk: Improve a couple of comments
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

Avoid mentioning the function names directly in the comments, it makes
them easily out of sync with the rest of the code. Use a more generic
wording.

Suggested-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 drivers/clk/clk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 1795246b10a0..591c0780b61e 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -5213,7 +5213,7 @@ static int of_parse_clkspec(const struct device_node *np, int index,
 		/*
 		 * For named clocks, first look up the name in the
 		 * "clock-names" property.  If it cannot be found, then index
-		 * will be an error code and of_parse_phandle_with_args() will
+		 * will be an error code and the OF phandle parser will
 		 * return -EINVAL.
 		 */
 		if (name)
@@ -5286,7 +5286,7 @@ of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec)
  *
  * This function looks up a struct clk from the registered list of clock
  * providers, an input is a clock specifier data structure as returned
- * from the of_parse_phandle_with_args() function call.
+ * from the OF phandle parser.
  */
 struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
 {

-- 
2.51.1


^ permalink raw reply related

* [PATCH 07/16] clk: tests: Add Kunit testing for of_clk_get_parent_name()
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

Make sure this helper is never broken, especially since we will soon
make some changes in it.

Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 drivers/clk/clk_test.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c
index b814b45f1f7e..8a17ad0d185f 100644
--- a/drivers/clk/clk_test.c
+++ b/drivers/clk/clk_test.c
@@ -3651,9 +3651,19 @@ static void clk_parse_clkspec_with_incorrect_index_and_name(struct kunit *test)
 	KUNIT_EXPECT_TRUE(test, IS_ERR(hw));
 }
 
+static void clk_parse_and_get_parent_name(struct kunit *test)
+{
+	struct clk_parse_clkspec_ctx *ctx = test->priv;
+
+	KUNIT_EXPECT_STREQ(test,
+			   of_clk_get_parent_name(ctx->cons_np, 0),
+			   clk_parse_clkspec_1_init_data.name);
+}
+
 static struct kunit_case clk_parse_clkspec_test_cases[] = {
 	KUNIT_CASE(clk_parse_clkspec_with_correct_index_and_name),
 	KUNIT_CASE(clk_parse_clkspec_with_incorrect_index_and_name),
+	KUNIT_CASE(clk_parse_and_get_parent_name),
 	{}
 };
 

-- 
2.51.1


^ permalink raw reply related

* [PATCH 06/16] clk: tests: Add clk_parse_clkspec() Kunit testing
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

Create a new set of kunit tests to make sure clk_parse_clkspec() is
working as expected. We currently verify if we get a proper device when
using indexes and names. If we make an out of bounds request we expect
an error.

For testing purposes, we must ensure of_clk_get_hw()'s symbol is
exported.

Suggested-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 drivers/clk/Makefile                     |   1 +
 drivers/clk/clk.c                        |   1 +
 drivers/clk/clk_test.c                   | 124 +++++++++++++++++++++++++++++++
 drivers/clk/kunit_clk_parse_clkspec.dtso |  21 ++++++
 4 files changed, 147 insertions(+)

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f7bce3951a30..97b621456bf5 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -19,6 +19,7 @@ clk-test-y			:= clk_test.o \
 				   kunit_clk_assigned_rates_zero.dtbo.o \
 				   kunit_clk_assigned_rates_zero_consumer.dtbo.o \
 				   kunit_clk_hw_get_dev_of_node.dtbo.o \
+				   kunit_clk_parse_clkspec.dtbo.o \
 				   kunit_clk_parent_data_test.dtbo.o
 obj-$(CONFIG_COMMON_CLK)	+= clk-divider.o
 obj-$(CONFIG_COMMON_CLK)	+= clk-fixed-factor.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 47093cda9df3..1795246b10a0 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -5312,6 +5312,7 @@ struct clk_hw *of_clk_get_hw(struct device_node *np, int index,
 
 	return hw;
 }
+EXPORT_SYMBOL_GPL(of_clk_get_hw);
 
 static struct clk *__of_clk_get(struct device_node *np,
 				int index, const char *dev_id,
diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c
index a268d7b5d4cb..b814b45f1f7e 100644
--- a/drivers/clk/clk_test.c
+++ b/drivers/clk/clk_test.c
@@ -3541,10 +3541,134 @@ static struct kunit_suite clk_hw_get_dev_of_node_test_suite = {
 	.test_cases = clk_hw_get_dev_of_node_test_cases,
 };
 
+static const struct clk_init_data clk_parse_clkspec_1_init_data = {
+	.name = "clk_parse_clkspec_1",
+	.ops = &empty_clk_ops,
+};
+
+static const struct clk_init_data clk_parse_clkspec_2_init_data = {
+	.name = "clk_parse_clkspec_2",
+	.ops = &empty_clk_ops,
+};
+
+static struct clk_hw *kunit_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+	return (struct clk_hw *)data;
+}
+
+struct clk_parse_clkspec_ctx {
+	struct device_node *prov1_np;
+	struct device_node *prov2_np;
+	struct device_node *cons_np;
+};
+
+static int clk_parse_clkspec_init(struct kunit *test)
+{
+	struct clk_parse_clkspec_ctx *ctx;
+	struct clk_hw *hw1, *hw2;
+
+	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+	test->priv = ctx;
+
+	KUNIT_ASSERT_EQ(test, 0, of_overlay_apply_kunit(test, kunit_clk_parse_clkspec));
+
+	/* Register provider 1 */
+	hw1 = kunit_kzalloc(test, sizeof(*hw1), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw1);
+	hw1->init = &clk_parse_clkspec_1_init_data;
+
+	ctx->prov1_np = of_find_compatible_node(NULL, NULL, "test,clock-provider1");
+	KUNIT_ASSERT_NOT_NULL(test, ctx->prov1_np);
+
+	KUNIT_ASSERT_EQ(test, 0, of_clk_hw_register_kunit(test, ctx->prov1_np, hw1));
+	of_clk_add_hw_provider(ctx->prov1_np, kunit_clk_get, hw1);
+	of_node_put(ctx->prov1_np);
+
+	/* Register provider 2 */
+	hw2 = kunit_kzalloc(test, sizeof(*hw2), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw2);
+	hw2->init = &clk_parse_clkspec_2_init_data;
+
+	ctx->prov2_np = of_find_compatible_node(NULL, NULL, "test,clock-provider2");
+	KUNIT_ASSERT_NOT_NULL(test, ctx->prov2_np);
+
+	KUNIT_ASSERT_EQ(test, 0, of_clk_hw_register_kunit(test, ctx->prov2_np, hw2));
+	of_clk_add_hw_provider(ctx->prov2_np, kunit_clk_get, hw2);
+	of_node_put(ctx->prov2_np);
+
+	ctx->cons_np = of_find_compatible_node(NULL, NULL, "test,clock-consumer");
+	KUNIT_ASSERT_NOT_NULL(test, ctx->cons_np);
+
+	return 0;
+}
+
+static void clk_parse_clkspec_exit(struct kunit *test)
+{
+	struct clk_parse_clkspec_ctx *ctx = test->priv;
+
+	of_node_put(ctx->prov1_np);
+	of_node_put(ctx->prov2_np);
+	of_node_put(ctx->cons_np);
+}
+
+/* Test DT phandle lookups using correct index or name succeed */
+static void clk_parse_clkspec_with_correct_index_and_name(struct kunit *test)
+{
+	struct clk_parse_clkspec_ctx *ctx = test->priv;
+	struct clk_hw *hw1, *hw2, *hw3, *hw4;
+
+	/* Get clocks by index */
+	hw1 = of_clk_get_hw(ctx->cons_np, 0, NULL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, hw1);
+
+	hw2 = of_clk_get_hw(ctx->cons_np, 1, NULL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, hw2);
+	KUNIT_EXPECT_PTR_NE(test, hw1, hw2);
+
+	/* Get clocks by name */
+	hw3 = of_clk_get_hw(ctx->cons_np, 0, "first_clock");
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, hw3);
+	KUNIT_EXPECT_PTR_EQ(test, hw1, hw3);
+
+	hw4 = of_clk_get_hw(ctx->cons_np, 0, "second_clock");
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, hw4);
+	KUNIT_EXPECT_PTR_EQ(test, hw2, hw4);
+}
+
+/* Test DT phandle lookups using wrong index or name fail */
+static void clk_parse_clkspec_with_incorrect_index_and_name(struct kunit *test)
+{
+	struct clk_parse_clkspec_ctx *ctx = test->priv;
+	struct clk_hw *hw;
+
+	/* Get clock by index */
+	hw = of_clk_get_hw(ctx->cons_np, 2, NULL);
+	KUNIT_EXPECT_TRUE(test, IS_ERR(hw));
+
+	/* Get clock by name */
+	hw = of_clk_get_hw(ctx->cons_np, 0, "third_clock");
+	KUNIT_EXPECT_TRUE(test, IS_ERR(hw));
+}
+
+static struct kunit_case clk_parse_clkspec_test_cases[] = {
+	KUNIT_CASE(clk_parse_clkspec_with_correct_index_and_name),
+	KUNIT_CASE(clk_parse_clkspec_with_incorrect_index_and_name),
+	{}
+};
+
+/* Test suite to verify clk_parse_clkspec() */
+static struct kunit_suite clk_parse_clkspec_test_suite = {
+	.name = "clk_parse_clkspec",
+	.init = clk_parse_clkspec_init,
+	.exit = clk_parse_clkspec_exit,
+	.test_cases = clk_parse_clkspec_test_cases,
+};
 
 kunit_test_suites(
 	&clk_assigned_rates_suite,
 	&clk_hw_get_dev_of_node_test_suite,
+	&clk_parse_clkspec_test_suite,
 	&clk_leaf_mux_set_rate_parent_test_suite,
 	&clk_test_suite,
 	&clk_multiple_parents_mux_test_suite,
diff --git a/drivers/clk/kunit_clk_parse_clkspec.dtso b/drivers/clk/kunit_clk_parse_clkspec.dtso
new file mode 100644
index 000000000000..c93feb93e101
--- /dev/null
+++ b/drivers/clk/kunit_clk_parse_clkspec.dtso
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	kunit_clock_provider1: kunit-clock-provider1 {
+		compatible = "test,clock-provider1";
+		#clock-cells = <1>;
+	};
+
+	kunit_clock_provider2: kunit-clock-provider2 {
+		compatible = "test,clock-provider2";
+		#clock-cells = <1>;
+	};
+
+	kunit-clock-consumer {
+		compatible = "test,clock-consumer";
+		clocks = <&kunit_clock_provider1 0>, <&kunit_clock_provider2 0>;
+		clock-names = "first_clock", "second_clock";
+	};
+};

-- 
2.51.1


^ permalink raw reply related

* [PATCH 05/16] dt-bindings: bus: eip150: Describe the EIP-150 container node
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

Part of Inside-Secure's SafeXcel family, the EIP-150 is some kind of
container node composed of:
- a public key accelerator,
- random number generator,
- an interrupt controller.

It also acts as proxy for the clocks.

Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 .../bus/inside-secure,safexcel-eip150.yaml         | 58 ++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/Documentation/devicetree/bindings/bus/inside-secure,safexcel-eip150.yaml b/Documentation/devicetree/bindings/bus/inside-secure,safexcel-eip150.yaml
new file mode 100644
index 000000000000..1b3d83a852f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/inside-secure,safexcel-eip150.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/bus/inside-secure,safexcel-eip150.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Inside-Secure SafeXcel EIP-150 container
+
+maintainers:
+  - Miquel Raynal <miquel.raynal@bootlin.com>
+
+description:
+  The EIP-150 is a hardware container, it has its own interrupt
+  controller inside to which a random number generator and a public key
+  accelerator are wired.
+
+allOf:
+  - $ref: simple-pm-bus.yaml#
+  - $ref: /schemas/clock/clock-nexus-node.yaml#
+
+properties:
+  compatible:
+    items:
+      - const: inside-secure,safexcel-eip150
+      - {} # simple-pm-bus, but not listed here to avoid false select
+
+  clocks:
+    minItems: 1
+
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 1
+
+  ranges: true
+
+patternProperties:
+  "^interrupt-controller@[0-9a-f]+$":
+    type: object
+    $ref: /schemas/interrupt-controller/inside-secure,safexcel-eip201.yaml#
+
+  "^rng@[0-9a-f]+$":
+    type: object
+    $ref: /schemas/rng/inside-secure,safexcel-eip76.yaml#
+
+  "^crypto@[0-9a-f]+$":
+    type: object
+    $ref: /schemas/crypto/inside-secure,safexcel-eip28.yaml#
+
+required:
+  - compatible
+  - clocks
+  - "#address-cells"
+  - "#size-cells"
+  - ranges
+
+unevaluatedProperties: false

-- 
2.51.1


^ permalink raw reply related

* [PATCH 04/16] dt-bindings: crypto: eip28: Describe EIP-28 PKA
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

Describe the Public Key Accelerator named EIP-28 from Inside-Secure,
part of the SafeXcel family, it is typically included in a bigger
hardware container named EIP-150.

Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 .../crypto/inside-secure,safexcel-eip28.yaml       | 31 ++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/Documentation/devicetree/bindings/crypto/inside-secure,safexcel-eip28.yaml b/Documentation/devicetree/bindings/crypto/inside-secure,safexcel-eip28.yaml
new file mode 100644
index 000000000000..96acb257450a
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/inside-secure,safexcel-eip28.yaml
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/crypto/inside-secure,safexcel-eip28.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Inside-Secure SafeXcel EIP-28 Public Key Accelerator
+
+maintainers:
+  - Miquel Raynal <miquel.raynal@bootlin.com>
+
+properties:
+  compatible:
+    const: inside-secure,safexcel-eip28
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 3
+
+  clocks:
+    minItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+
+additionalProperties: false

-- 
2.51.1


^ permalink raw reply related

* [PATCH 03/16] dt-bindings: rng: Rename the title of the EIP-76 file
From: Miquel Raynal (Schneider Electric) @ 2026-03-27 20:09 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thomas Gleixner, Olivia Mackall, Herbert Xu,
	Jayesh Choudhary, David S. Miller, Christian Marangi,
	Antoine Tenart, Geert Uytterhoeven, Magnus Damm
  Cc: Thomas Petazzoni, Pascal EBERHARD, Wolfram Sang, linux-clk,
	devicetree, linux-kernel, linux-crypto, linux-renesas-soc,
	Miquel Raynal (Schneider Electric)
In-Reply-To: <20260327-schneider-v7-0-rc1-crypto-v1-0-5e6ff7853994@bootlin.com>

Be a little more precise in the title by giving the family name and the
own name of the hardware block. Despite the original compatibles, this
file describes a SafeXcel EIP-76 hardware random number generator.

Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
 Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml b/Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml
index f501fc7691c6..92d906998211 100644
--- a/Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml
+++ b/Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/rng/inside-secure,safexcel-eip76.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Inside-Secure HWRNG Module
+title: Inside-Secure SafeXcel EIP-76 HWRNG Module
 
 maintainers:
   - Jayesh Choudhary <j-choudhary@ti.com>

-- 
2.51.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox