Merge tag 'soc-drivers-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Apr 2023 19:02:16 +0000 (12:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Apr 2023 19:02:16 +0000 (12:02 -0700)
Pull ARM SoC driver updates from Arnd Bergmann:
 "The most notable updates this time are for Qualcomm Snapdragon
  platforms. The Inline-Crypto-Engine gets a new DT binding and driver,
  and a number of drivers now support additional Snapdragon variants, in
  particular the rsc, scm, geni, bwm, glink and socinfo, while the llcc
  (edac) and rpm drivers get notable functionality updates.

  Updates on other platforms include:

   - Various updates to the Mediatek mutex and mmsys drivers, including
     support for the Helio X10 SoC

   - Support for unidirectional mailbox channels in Arm SCMI firmware

   - Support for per cpu asynchronous notification in OP-TEE firmware

   - Minor updates for memory controller drivers.

   - Minor updates for Renesas, TI, Amlogic, Apple, Broadcom, Tegra,
     Allwinner, Versatile Express, Canaan, Microchip, Mediatek and i.MX
     SoC drivers, mainly updating the use of MODULE_LICENSE() macros and
     obsolete DT driver interfaces"

* tag 'soc-drivers-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (165 commits)
  soc: ti: smartreflex: Simplify getting the opam_sr pointer
  bus: vexpress-config: Add explicit of_platform.h include
  soc: mediatek: Kconfig: Add MTK_CMDQ dependency to MTK_MMSYS
  memory: mtk-smi: mt8365: Add SMI Support
  dt-bindings: memory-controllers: mediatek,smi-larb: add mt8365
  dt-bindings: memory-controllers: mediatek,smi-common: add mt8365
  memory: tegra: read values from correct device
  dt-bindings: crypto: Add Qualcomm Inline Crypto Engine
  soc: qcom: Make the Qualcomm UFS/SDCC ICE a dedicated driver
  dt-bindings: firmware: document Qualcomm QCM2290 SCM
  soc: qcom: rpmh-rsc: Support RSC v3 minor versions
  soc: qcom: smd-rpm: Use GFP_ATOMIC in write path
  soc/tegra: fuse: Remove nvmem root only access
  soc/tegra: cbb: tegra194: Use of_address_count() helper
  soc/tegra: cbb: Remove MODULE_LICENSE in non-modules
  ARM: tegra: Remove MODULE_LICENSE in non-modules
  soc/tegra: flowctrl: Use devm_platform_get_and_ioremap_resource()
  soc: tegra: cbb: Drop empty platform remove function
  firmware: arm_scmi: Add support for unidirectional mailbox channels
  dt-bindings: firmware: arm,scmi: Support mailboxes unidirectional channels
  ...

129 files changed:
Documentation/devicetree/bindings/arm/amlogic/amlogic,meson-gx-ao-secure.yaml
Documentation/devicetree/bindings/arm/amlogic/amlogic,meson-mx-secbus2.yaml
Documentation/devicetree/bindings/arm/firmware/linaro,optee-tz.yaml
Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml
Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/firmware/arm,scmi.yaml
Documentation/devicetree/bindings/firmware/qcom,scm.yaml
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.yaml
Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
Documentation/devicetree/bindings/memory-controllers/samsung,exynos5422-dmc.yaml
Documentation/devicetree/bindings/soc/amlogic/amlogic,canvas.yaml
Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt [deleted file]
Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml
Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml
Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
Documentation/devicetree/bindings/sram/qcom,imem.yaml
Documentation/staging/tee.rst
MAINTAINERS
drivers/amba/tegra-ahb.c
drivers/bus/brcmstb_gisb.c
drivers/bus/imx-weim.c
drivers/bus/ti-sysc.c
drivers/bus/vexpress-config.c
drivers/edac/qcom_edac.c
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/mailbox.c
drivers/firmware/arm_scmi/optee.c
drivers/firmware/imx/imx-scu.c
drivers/firmware/imx/scu-pd.c
drivers/firmware/meson/meson_sm.c
drivers/firmware/qcom_scm.c
drivers/firmware/tegra/bpmp-debugfs.c
drivers/firmware/tegra/bpmp.c
drivers/mailbox/mailbox-mpfs.c
drivers/memory/Kconfig
drivers/memory/atmel-ebi.c
drivers/memory/bt1-l2-ctl.c
drivers/memory/da8xx-ddrctl.c
drivers/memory/fsl_ifc.c
drivers/memory/mtk-smi.c
drivers/memory/mvebu-devbus.c
drivers/memory/tegra/mc.c
drivers/memory/tegra/tegra186-emc.c
drivers/memory/tegra/tegra210-emc-cc-r21021.c
drivers/memory/tegra/tegra210-emc-table.c
drivers/misc/fastrpc.c
drivers/net/wireless/ath/ath10k/qmi.c
drivers/remoteproc/qcom_q6v5_mss.c
drivers/remoteproc/qcom_q6v5_pas.c
drivers/soc/amlogic/meson-gx-pwrc-vpu.c
drivers/soc/apple/rtkit.c
drivers/soc/bcm/bcm2835-power.c
drivers/soc/bcm/brcmstb/Kconfig
drivers/soc/bcm/brcmstb/biuctrl.c
drivers/soc/bcm/brcmstb/pm/Makefile
drivers/soc/bcm/brcmstb/pm/aon_defs.h [deleted file]
drivers/soc/bcm/brcmstb/pm/pm-arm.c [deleted file]
drivers/soc/bcm/brcmstb/pm/s2-arm.S [deleted file]
drivers/soc/bcm/raspberrypi-power.c
drivers/soc/canaan/Kconfig
drivers/soc/imx/Kconfig
drivers/soc/imx/imx8m-blk-ctrl.c
drivers/soc/imx/imx8mp-blk-ctrl.c
drivers/soc/imx/soc-imx8m.c
drivers/soc/mediatek/Kconfig
drivers/soc/mediatek/mt8173-mmsys.h [new file with mode: 0644]
drivers/soc/mediatek/mt8195-mmsys.h
drivers/soc/mediatek/mtk-mmsys.c
drivers/soc/mediatek/mtk-mmsys.h
drivers/soc/mediatek/mtk-mutex.c
drivers/soc/mediatek/mtk-svs.c
drivers/soc/microchip/mpfs-sys-controller.c
drivers/soc/qcom/Kconfig
drivers/soc/qcom/Makefile
drivers/soc/qcom/icc-bwmon.c
drivers/soc/qcom/ice.c [new file with mode: 0644]
drivers/soc/qcom/llcc-qcom.c
drivers/soc/qcom/pmic_glink.c
drivers/soc/qcom/qcom_aoss.c
drivers/soc/qcom/qcom_gsbi.c
drivers/soc/qcom/rmtfs_mem.c
drivers/soc/qcom/rpmh-rsc.c
drivers/soc/qcom/rpmpd.c
drivers/soc/qcom/smd-rpm.c
drivers/soc/qcom/smem.c
drivers/soc/qcom/smsm.c
drivers/soc/qcom/socinfo.c
drivers/soc/renesas/Kconfig
drivers/soc/renesas/pwc-rzv2m.c
drivers/soc/renesas/r8a7795-sysc.c
drivers/soc/renesas/renesas-soc.c
drivers/soc/renesas/rmobile-sysc.c
drivers/soc/sunxi/sunxi_mbus.c
drivers/soc/sunxi/sunxi_sram.c
drivers/soc/tegra/cbb/tegra-cbb.c
drivers/soc/tegra/cbb/tegra194-cbb.c
drivers/soc/tegra/cbb/tegra234-cbb.c
drivers/soc/tegra/flowctrl.c
drivers/soc/tegra/fuse/fuse-tegra.c
drivers/soc/tegra/pmc.c
drivers/soc/tegra/powergate-bpmp.c
drivers/soc/ti/k3-ringacc.c
drivers/soc/ti/k3-socinfo.c
drivers/soc/ti/knav_dma.c
drivers/soc/ti/knav_qmss_acc.c
drivers/soc/ti/knav_qmss_queue.c
drivers/soc/ti/omap_prm.c
drivers/soc/ti/pm33xx.c
drivers/soc/ti/smartreflex.c
drivers/soc/ti/wkup_m3_ipc.c
drivers/tee/optee/Kconfig
drivers/tee/optee/optee_msg.h
drivers/tee/optee/optee_private.h
drivers/tee/optee/optee_smc.h
drivers/tee/optee/smc_abi.c
include/dt-bindings/arm/qcom,ids.h
include/dt-bindings/power/r8a7795-sysc.h
include/linux/firmware/qcom/qcom_scm.h
include/linux/soc/mediatek/mtk-cmdq.h
include/linux/soc/mediatek/mtk-mmsys.h
include/linux/soc/mediatek/mtk-mutex.h
include/linux/soc/qcom/geni-se.h
include/linux/soc/qcom/llcc-qcom.h
include/soc/qcom/ice.h [new file with mode: 0644]

index 1748f1605cc701b55ac97687c27c23e0e6716465..7dff32f373cb93cf55ca665d2ddfcecb942d7fff 100644 (file)
@@ -2,8 +2,8 @@
 # Copyright 2019 BayLibre, SAS
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/arm/amlogic/amlogic,meson-gx-ao-secure.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/arm/amlogic/amlogic,meson-gx-ao-secure.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Amlogic Meson Firmware registers Interface
 
index eee7cda9f91b670cfa404a26f64f4d266b9512cc..09b27e98d4c9797a24745a2f60c1aa8821b13165 100644 (file)
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/arm/amlogic/amlogic,meson-mx-secbus2.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/arm/amlogic/amlogic,meson-mx-secbus2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Amlogic Meson8/Meson8b/Meson8m2 SECBUS2 register interface
 
index d4dc0749f9fd1f257c05854fcc91a49498fd7102..5d033570b57bcf1b6a2b3b933c041922132d61a3 100644 (file)
@@ -28,7 +28,8 @@ properties:
     maxItems: 1
     description: |
       This interrupt which is used to signal an event by the secure world
-      software is expected to be edge-triggered.
+      software is expected to be either a per-cpu interrupt or an
+      edge-triggered peripheral interrupt.
 
   method:
     enum: [smc, hvc]
index 38efcad56dbdee6d1df0aa5c2abfe69bd37aee53..02cc6894eb135fc9a4195201515dcec642987d6d 100644 (file)
@@ -7,8 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Last Level Cache Controller
 
 maintainers:
-  - Rishabh Bhatnagar <rishabhb@codeaurora.org>
-  - Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
+  - Bjorn Andersson <andersson@kernel.org>
 
 description: |
   LLCC (Last Level Cache Controller) provides last level of cache memory in SoC,
@@ -27,6 +26,7 @@ properties:
       - qcom,sc8280xp-llcc
       - qcom,sdm845-llcc
       - qcom,sm6350-llcc
+      - qcom,sm7150-llcc
       - qcom,sm8150-llcc
       - qcom,sm8250-llcc
       - qcom,sm8350-llcc
@@ -34,14 +34,12 @@ properties:
       - qcom,sm8550-llcc
 
   reg:
-    items:
-      - description: LLCC base register region
-      - description: LLCC broadcast base register region
+    minItems: 2
+    maxItems: 9
 
   reg-names:
-    items:
-      - const: llcc_base
-      - const: llcc_broadcast_base
+    minItems: 2
+    maxItems: 9
 
   interrupts:
     maxItems: 1
@@ -51,15 +49,120 @@ required:
   - reg
   - reg-names
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,sc7180-llcc
+              - qcom,sm6350-llcc
+    then:
+      properties:
+        reg:
+          items:
+            - description: LLCC0 base register region
+            - description: LLCC broadcast base register region
+        reg-names:
+          items:
+            - const: llcc0_base
+            - const: llcc_broadcast_base
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,sc7280-llcc
+    then:
+      properties:
+        reg:
+          items:
+            - description: LLCC0 base register region
+            - description: LLCC1 base register region
+            - description: LLCC broadcast base register region
+        reg-names:
+          items:
+            - const: llcc0_base
+            - const: llcc1_base
+            - const: llcc_broadcast_base
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,sc8180x-llcc
+              - qcom,sc8280xp-llcc
+    then:
+      properties:
+        reg:
+          items:
+            - description: LLCC0 base register region
+            - description: LLCC1 base register region
+            - description: LLCC2 base register region
+            - description: LLCC3 base register region
+            - description: LLCC4 base register region
+            - description: LLCC5 base register region
+            - description: LLCC6 base register region
+            - description: LLCC7 base register region
+            - description: LLCC broadcast base register region
+        reg-names:
+          items:
+            - const: llcc0_base
+            - const: llcc1_base
+            - const: llcc2_base
+            - const: llcc3_base
+            - const: llcc4_base
+            - const: llcc5_base
+            - const: llcc6_base
+            - const: llcc7_base
+            - const: llcc_broadcast_base
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,sdm845-llcc
+              - qcom,sm8150-llcc
+              - qcom,sm8250-llcc
+              - qcom,sm8350-llcc
+              - qcom,sm8450-llcc
+    then:
+      properties:
+        reg:
+          items:
+            - description: LLCC0 base register region
+            - description: LLCC1 base register region
+            - description: LLCC2 base register region
+            - description: LLCC3 base register region
+            - description: LLCC broadcast base register region
+        reg-names:
+          items:
+            - const: llcc0_base
+            - const: llcc1_base
+            - const: llcc2_base
+            - const: llcc3_base
+            - const: llcc_broadcast_base
+
 additionalProperties: false
 
 examples:
   - |
     #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-    system-cache-controller@1100000 {
-      compatible = "qcom,sdm845-llcc";
-      reg = <0x1100000 0x200000>, <0x1300000 0x50000> ;
-      reg-names = "llcc_base", "llcc_broadcast_base";
-      interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>;
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        system-cache-controller@1100000 {
+            compatible = "qcom,sdm845-llcc";
+            reg = <0 0x01100000 0 0x50000>, <0 0x01180000 0 0x50000>,
+                <0 0x01200000 0 0x50000>, <0 0x01280000 0 0x50000>,
+                <0 0x01300000 0 0x50000>;
+            reg-names = "llcc0_base", "llcc1_base", "llcc2_base",
+                "llcc3_base", "llcc_broadcast_base";
+            interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>;
+        };
     };
diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
new file mode 100644 (file)
index 0000000..92e1d76
--- /dev/null
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/crypto/qcom,inline-crypto-engine.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. (QTI) Inline Crypto Engine
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - qcom,sm8550-inline-crypto-engine
+      - const: qcom,inline-crypto-engine
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,sm8550-gcc.h>
+
+    crypto@1d88000 {
+      compatible = "qcom,sm8550-inline-crypto-engine",
+                   "qcom,inline-crypto-engine";
+      reg = <0x01d88000 0x8000>;
+      clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
+    };
+...
index 2f7c51c75e85ae8d0c75bb4efe91c7df4ff6ec5a..5824c43e9893133f8a38cbf9bfb56e71eb768f48 100644 (file)
@@ -56,17 +56,38 @@ properties:
     description:
       Specifies the mailboxes used to communicate with SCMI compliant
       firmware.
-    items:
-      - const: tx
-      - const: rx
+    oneOf:
+      - items:
+          - const: tx
+          - const: rx
+        minItems: 1
+      - items:
+          - const: tx
+          - const: tx_reply
+          - const: rx
+        minItems: 2
 
   mboxes:
     description:
       List of phandle and mailbox channel specifiers. It should contain
-      exactly one or two mailboxes, one for transmitting messages("tx")
-      and another optional for receiving the notifications("rx") if supported.
+      exactly one, two or three mailboxes; the first one or two for transmitting
+      messages ("tx") and another optional ("rx") for receiving notifications
+      and delayed responses, if supported by the platform.
+      The number of mailboxes needed for transmitting messages depends on the
+      type of channels exposed by the specific underlying mailbox controller;
+      one single channel descriptor is enough if such channel is bidirectional,
+      while two channel descriptors are needed to represent the SCMI ("tx")
+      channel if the underlying mailbox channels are of unidirectional type.
+      The effective combination in numbers of mboxes and shmem descriptors let
+      the SCMI subsystem determine unambiguosly which type of SCMI channels are
+      made available by the underlying mailbox controller and how to use them.
+       1 mbox / 1 shmem => SCMI TX over 1 mailbox bidirectional channel
+       2 mbox / 2 shmem => SCMI TX and RX over 2 mailbox bidirectional channels
+       2 mbox / 1 shmem => SCMI TX over 2 mailbox unidirectional channels
+       3 mbox / 2 shmem => SCMI TX and RX over 3 mailbox unidirectional channels
+      Any other combination of mboxes and shmem is invalid.
     minItems: 1
-    maxItems: 2
+    maxItems: 3
 
   shmem:
     description:
@@ -228,13 +249,20 @@ $defs:
         maxItems: 1
 
       mbox-names:
-        items:
-          - const: tx
-          - const: rx
+        oneOf:
+          - items:
+              - const: tx
+              - const: rx
+            minItems: 1
+          - items:
+              - const: tx
+              - const: tx_reply
+              - const: rx
+            minItems: 2
 
       mboxes:
         minItems: 1
-        maxItems: 2
+        maxItems: 3
 
       shmem:
         minItems: 1
index a66e99812b1fc36cc6205e6546ac41e16cd6f6b2..367d04ad19236242d4c05bc88a43931964588cc6 100644 (file)
@@ -24,9 +24,11 @@ properties:
           - qcom,scm-apq8064
           - qcom,scm-apq8084
           - qcom,scm-ipq4019
+          - qcom,scm-ipq5332
           - qcom,scm-ipq6018
           - qcom,scm-ipq806x
           - qcom,scm-ipq8074
+          - qcom,scm-ipq9574
           - qcom,scm-mdm9607
           - qcom,scm-msm8226
           - qcom,scm-msm8660
@@ -38,10 +40,12 @@ properties:
           - qcom,scm-msm8994
           - qcom,scm-msm8996
           - qcom,scm-msm8998
+          - qcom,scm-qcm2290
           - qcom,scm-qdu1000
           - qcom,scm-sa8775p
           - qcom,scm-sc7180
           - qcom,scm-sc7280
+          - qcom,scm-sc8180x
           - qcom,scm-sc8280xp
           - qcom,scm-sdm670
           - qcom,scm-sdm845
@@ -107,6 +111,7 @@ allOf:
               - qcom,scm-msm8960
               - qcom,scm-msm8974
               - qcom,scm-msm8976
+              - qcom,scm-qcm2290
               - qcom,scm-sm6375
     then:
       required:
@@ -125,6 +130,7 @@ allOf:
               - qcom,scm-apq8064
               - qcom,scm-msm8660
               - qcom,scm-msm8960
+              - qcom,scm-qcm2290
               - qcom,scm-sm6375
     then:
       properties:
@@ -166,6 +172,7 @@ allOf:
           compatible:
             contains:
               enum:
+                - qcom,scm-qdu1000
                 - qcom,scm-sm8450
                 - qcom,scm-sm8550
     then:
index a8fda30cccbb5b605f929230715be90021d77505..2f36ac23604c50b1e9838c6a3d8b10bdc873bdac 100644 (file)
@@ -43,6 +43,7 @@ properties:
           - mediatek,mt8195-smi-common-vdo
           - mediatek,mt8195-smi-common-vpp
           - mediatek,mt8195-smi-sub-common
+          - mediatek,mt8365-smi-common
 
       - description: for mt7623
         items:
@@ -133,6 +134,7 @@ allOf:
             - mediatek,mt8192-smi-common
             - mediatek,mt8195-smi-common-vdo
             - mediatek,mt8195-smi-common-vpp
+            - mediatek,mt8365-smi-common
 
     then:
       properties:
index 5f4ac3609887f2975b5ed8cf0d6fb73da114aed7..aee7f6cf13003586c4a0d26912bde4f2a96b0067 100644 (file)
@@ -34,6 +34,10 @@ properties:
           - const: mediatek,mt7623-smi-larb
           - const: mediatek,mt2701-smi-larb
 
+      - items:
+          - const: mediatek,mt8365-smi-larb
+          - const: mediatek,mt8186-smi-larb
+
   reg:
     maxItems: 1
 
index 7056ccb7eb304cce9d0654a92833ec023ab480b1..8e3822314b25ac59dc9a9c56dadcfb38e39bbd41 100644 (file)
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/memory-controllers/renesas,dbsc.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/memory-controllers/renesas,dbsc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Renesas DDR Bus Controllers
 
index 30a403b1b79a2c73508259d296f94871f8dd5deb..56e62cd0b36abd7a89b1ad3a57c9e4f41a92f445 100644 (file)
@@ -20,7 +20,7 @@ description: |
   - if it contains "cfi-flash", then HyperFlash is used.
 
 allOf:
-  - $ref: "/schemas/spi/spi-controller.yaml#"
+  - $ref: /schemas/spi/spi-controller.yaml#
 
 properties:
   compatible:
index 098348b2b815eab70a680e8701c37bea1e75f2c8..783ac984d89849e6683c87a77123156a57a9c63e 100644 (file)
@@ -42,7 +42,7 @@ properties:
     maxItems: 8
 
   devfreq-events:
-    $ref: '/schemas/types.yaml#/definitions/phandle-array'
+    $ref: /schemas/types.yaml#/definitions/phandle-array
     minItems: 1
     maxItems: 16
     items:
@@ -50,7 +50,7 @@ properties:
     description: phandles of the PPMU events used by the controller.
 
   device-handle:
-    $ref: '/schemas/types.yaml#/definitions/phandle'
+    $ref: /schemas/types.yaml#/definitions/phandle
     description: |
       phandle of the connected DRAM memory device. For more information please
       refer to jedec,lpddr3.yaml.
@@ -73,7 +73,7 @@ properties:
       - description: registers of DREX1
 
   samsung,syscon-clk:
-    $ref: '/schemas/types.yaml#/definitions/phandle'
+    $ref: /schemas/types.yaml#/definitions/phandle
     description: |
       Phandle of the clock register set used by the controller, these registers
       are used for enabling a 'pause' feature and are not exposed by clock
index c3c59909635310d6a72a09b57f26c23412c10a0e..cd06865e1f2a81dee979a20a37e02583afae134c 100644 (file)
@@ -2,8 +2,8 @@
 # Copyright 2019 BayLibre, SAS
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/soc/amlogic/amlogic,canvas.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/soc/amlogic/amlogic,canvas.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Amlogic Canvas Video Lookup Table
 
diff --git a/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml b/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml
new file mode 100644 (file)
index 0000000..77c2811
--- /dev/null
@@ -0,0 +1,40 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/amlogic/amlogic,meson-gx-clk-measure.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic Internal Clock Measurer
+
+description:
+  The Amlogic SoCs contains an IP to measure the internal clocks.
+  The precision is multiple of MHz, useful to debug the clock states.
+
+maintainers:
+  - Neil Armstrong <neil.armstrong@linaro.org>
+
+properties:
+  compatible:
+    enum:
+      - amlogic,meson-gx-clk-measure
+      - amlogic,meson8-clk-measure
+      - amlogic,meson8b-clk-measure
+      - amlogic,meson-axg-clk-measure
+      - amlogic,meson-g12a-clk-measure
+      - amlogic,meson-sm1-clk-measure
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    clock-measure@8758 {
+        compatible = "amlogic,meson-gx-clk-measure";
+        reg = <0x8758 0x10>;
+    };
diff --git a/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt b/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt
deleted file mode 100644 (file)
index 3dd563c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-Amlogic Internal Clock Measurer
-===============================
-
-The Amlogic SoCs contains an IP to measure the internal clocks.
-The precision is multiple of MHz, useful to debug the clock states.
-
-Required properties:
-- compatible: Shall contain one of the following :
-                       "amlogic,meson-gx-clk-measure" for GX SoCs
-                       "amlogic,meson8-clk-measure" for Meson8 SoCs
-                       "amlogic,meson8b-clk-measure" for Meson8b SoCs
-                       "amlogic,meson-axg-clk-measure" for AXG SoCs
-                       "amlogic,meson-g12a-clk-measure" for G12a SoCs
-                       "amlogic,meson-sm1-clk-measure" for SM1 SoCs
-- reg: base address and size of the Clock Measurer register space.
-
-Example:
-       clock-measure@8758 {
-               compatible = "amlogic,meson-gx-clk-measure";
-               reg = <0x0 0x8758 0x0 0x10>;
-       };
index 15c133cac3157d971d54677b6f728b4bd2d94e13..ba2014a8725c3630d1935fa5c7f47f036e0b7cdb 100644 (file)
@@ -35,6 +35,8 @@ properties:
       - mediatek,mt8188-disp-mutex
       - mediatek,mt8192-disp-mutex
       - mediatek,mt8195-disp-mutex
+      - mediatek,mt8195-vpp-mutex
+      - mediatek,mt8365-disp-mutex
 
   reg:
     maxItems: 1
@@ -70,12 +72,30 @@ properties:
       4 arguments defined in this property. Each GCE subsys id is mapping to
       a client defined in the header include/dt-bindings/gce/<chip>-gce.h.
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - mediatek,mt2701-disp-mutex
+              - mediatek,mt2712-disp-mutex
+              - mediatek,mt6795-disp-mutex
+              - mediatek,mt8173-disp-mutex
+              - mediatek,mt8186-disp-mutex
+              - mediatek,mt8186-mdp3-mutex
+              - mediatek,mt8192-disp-mutex
+              - mediatek,mt8195-disp-mutex
+    then:
+      required:
+        - clocks
+
+
 required:
   - compatible
   - reg
   - interrupts
   - power-domains
-  - clocks
 
 additionalProperties: false
 
index ab607efbb64c1218dd75cfd5edc0fc5217dcc7de..798f15588ee259dd60e39077c99cd9f2b9c9fff3 100644 (file)
@@ -25,6 +25,7 @@ properties:
   compatible:
     items:
       - enum:
+          - qcom,qdu1000-aoss-qmp
           - qcom,sc7180-aoss-qmp
           - qcom,sc7280-aoss-qmp
           - qcom,sc8180x-aoss-qmp
index 6026c21736d880e4685ff0b227fd66c8b2c64cb7..4502458b066907af5b7411cdf23fe7cd6fbe09ea 100644 (file)
@@ -62,7 +62,14 @@ properties:
     maxItems: 1
 
   qcom,intents:
-    $ref: /schemas/types.yaml#/definitions/uint32-array
+    $ref: /schemas/types.yaml#/definitions/uint32-matrix
+    minItems: 1
+    maxItems: 32
+    items:
+      items:
+        - description: size of each intent to preallocate
+        - description: amount of intents to preallocate
+          minimum: 1
     description:
       List of (size, amount) pairs describing what intents should be
       preallocated for this virtual channel. This can be used to tweak the
index cf863683c21a8595a781c872f68af94396f34980..6440dc801387db748150fe8dc50e9e1d0db20464 100644 (file)
@@ -25,6 +25,8 @@ properties:
           - qcom,sc8180x-pmic-glink
           - qcom,sc8280xp-pmic-glink
           - qcom,sm8350-pmic-glink
+          - qcom,sm8450-pmic-glink
+          - qcom,sm8550-pmic-glink
       - const: qcom,pmic-glink
 
   '#address-cells':
index 16fd67c0bd1fd60cc919cdccd88e82a19e371f5c..94765fbc868e234a1926b1ae30ce1fbe73df6042 100644 (file)
@@ -33,6 +33,7 @@ properties:
     enum:
       - qcom,rpm-apq8084
       - qcom,rpm-ipq6018
+      - qcom,rpm-ipq9574
       - qcom,rpm-msm8226
       - qcom,rpm-msm8909
       - qcom,rpm-msm8916
@@ -40,6 +41,7 @@ properties:
       - qcom,rpm-msm8953
       - qcom,rpm-msm8974
       - qcom,rpm-msm8976
+      - qcom,rpm-msm8994
       - qcom,rpm-msm8996
       - qcom,rpm-msm8998
       - qcom,rpm-sdm660
@@ -84,6 +86,7 @@ if:
           - qcom,rpm-msm8974
           - qcom,rpm-msm8976
           - qcom,rpm-msm8953
+          - qcom,rpm-msm8994
 then:
   properties:
     qcom,glink-channels: false
index ba694ce4a037ca188e632bcca62e9d15faaf51a8..0548e8e0d30be616f994dbe10ab7363d3bde9970 100644 (file)
@@ -26,6 +26,7 @@ properties:
           - qcom,sdm845-imem
           - qcom,sdx55-imem
           - qcom,sdx65-imem
+          - qcom,sm6375-imem
           - qcom,sm8450-imem
       - const: syscon
       - const: simple-mfd
index 498343c7ab088e8ed6b981ead561dd94f39fbff6..22baa077a3b90842756c1500477ec4f9b6193d59 100644 (file)
@@ -214,6 +214,57 @@ call is done from the thread assisting the interrupt handler. This is a
 building block for OP-TEE OS in secure world to implement the top half and
 bottom half style of device drivers.
 
+OPTEE_INSECURE_LOAD_IMAGE Kconfig option
+----------------------------------------
+
+The OPTEE_INSECURE_LOAD_IMAGE Kconfig option enables the ability to load the
+BL32 OP-TEE image from the kernel after the kernel boots, rather than loading
+it from the firmware before the kernel boots. This also requires enabling the
+corresponding option in Trusted Firmware for Arm. The Trusted Firmware for Arm
+documentation [8] explains the security threat associated with enabling this as
+well as mitigations at the firmware and platform level.
+
+There are additional attack vectors/mitigations for the kernel that should be
+addressed when using this option.
+
+1. Boot chain security.
+
+   * Attack vector: Replace the OP-TEE OS image in the rootfs to gain control of
+     the system.
+
+   * Mitigation: There must be boot chain security that verifies the kernel and
+     rootfs, otherwise an attacker can modify the loaded OP-TEE binary by
+     modifying it in the rootfs.
+
+2. Alternate boot modes.
+
+   * Attack vector: Using an alternate boot mode (i.e. recovery mode), the
+     OP-TEE driver isn't loaded, leaving the SMC hole open.
+
+   * Mitigation: If there are alternate methods of booting the device, such as a
+     recovery mode, it should be ensured that the same mitigations are applied
+     in that mode.
+
+3. Attacks prior to SMC invocation.
+
+   * Attack vector: Code that is executed prior to issuing the SMC call to load
+     OP-TEE can be exploited to then load an alternate OS image.
+
+   * Mitigation: The OP-TEE driver must be loaded before any potential attack
+     vectors are opened up. This should include mounting of any modifiable
+     filesystems, opening of network ports or communicating with external
+     devices (e.g. USB).
+
+4. Blocking SMC call to load OP-TEE.
+
+   * Attack vector: Prevent the driver from being probed, so the SMC call to
+     load OP-TEE isn't executed when desired, leaving it open to being executed
+     later and loading a modified OS.
+
+   * Mitigation: It is recommended to build the OP-TEE driver as builtin driver
+     rather than as a module to prevent exploits that may cause the module to
+     not be loaded.
+
 AMD-TEE driver
 ==============
 
@@ -309,3 +360,5 @@ References
 [6] include/linux/psp-tee.h
 
 [7] drivers/tee/amdtee/amdtee_if.h
+
+[8] https://trustedfirmware-a.readthedocs.io/en/latest/threat_model/threat_model.html
index 74cf4b8964a7e4a2126ae2a9082a7d924c536166..39bda6f1d7176aaa9ee402868ab8f68dceb25a98 100644 (file)
@@ -2654,6 +2654,7 @@ F:        arch/arm64/boot/dts/renesas/
 F:     arch/riscv/boot/dts/renesas/
 F:     drivers/soc/renesas/
 F:     include/linux/soc/renesas/
+K:     \brenesas,
 
 ARM/RISCPC ARCHITECTURE
 M:     Russell King <linux@armlinux.org.uk>
index 0b2c20fddb7c5851e373b901a1330cedf43a93bd..c0e8b765522dc79be3756acf62788812ca6ea7a5 100644 (file)
@@ -285,5 +285,4 @@ module_platform_driver(tegra_ahb_driver);
 
 MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
 MODULE_DESCRIPTION("Tegra AHB driver");
-MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:" DRV_NAME);
index b0c3704777e9929c2b6a3805292f7c721762c099..b6dfe4340da2cbfc9af162f56e9621ffb0c481f6 100644 (file)
@@ -401,12 +401,10 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
        struct device_node *dn = pdev->dev.of_node;
        struct brcmstb_gisb_arb_device *gdev;
        const struct of_device_id *of_id;
-       struct resource *r;
        int err, timeout_irq, tea_irq, bp_irq;
        unsigned int num_masters, j = 0;
        int i, first, last;
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        timeout_irq = platform_get_irq(pdev, 0);
        tea_irq = platform_get_irq(pdev, 1);
        bp_irq = platform_get_irq(pdev, 2);
@@ -418,7 +416,7 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
        mutex_init(&gdev->lock);
        INIT_LIST_HEAD(&gdev->next);
 
-       gdev->base = devm_ioremap_resource(&pdev->dev, r);
+       gdev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(gdev->base))
                return PTR_ERR(gdev->base);
 
index cf463c1d2102c6fb9bb13bbaea33f1844c9daa17..52a5d04473908981937a539ad69142467e973a7e 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
@@ -86,8 +87,8 @@ MODULE_DEVICE_TABLE(of, weim_id_table);
 static int imx_weim_gpr_setup(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
-       struct property *prop;
-       const __be32 *p;
+       struct of_range_parser parser;
+       struct of_range range;
        struct regmap *gpr;
        u32 gprvals[4] = {
                05,     /* CS0(128M) CS1(0M)  CS2(0M)  CS3(0M)  */
@@ -106,13 +107,13 @@ static int imx_weim_gpr_setup(struct platform_device *pdev)
                return 0;
        }
 
-       of_property_for_each_u32(np, "ranges", prop, p, val) {
-               if (i % 4 == 0) {
-                       cs = val;
-               } else if (i % 4 == 3 && val) {
-                       val = (val / SZ_32M) | 1;
-                       gprval |= val << cs * 3;
-               }
+       if (of_range_parser_init(&parser, np))
+               goto err;
+
+       for_each_of_range(&parser, &range) {
+               cs = range.bus_addr >> 32;
+               val = (range.size / SZ_32M) | 1;
+               gprval |= val << cs * 3;
                i++;
        }
 
index 6afae98978434e2343e82e97679993bb398899a2..6c49de37d5e90f98cf63b2875bbe3d3ed18c8b76 100644 (file)
@@ -648,43 +648,20 @@ static int sysc_init_resets(struct sysc *ddata)
 static int sysc_parse_and_check_child_range(struct sysc *ddata)
 {
        struct device_node *np = ddata->dev->of_node;
-       const __be32 *ranges;
-       u32 nr_addr, nr_size;
-       int len, error;
-
-       ranges = of_get_property(np, "ranges", &len);
-       if (!ranges) {
-               dev_err(ddata->dev, "missing ranges for %pOF\n", np);
-
-               return -ENOENT;
-       }
-
-       len /= sizeof(*ranges);
-
-       if (len < 3) {
-               dev_err(ddata->dev, "incomplete ranges for %pOF\n", np);
-
-               return -EINVAL;
-       }
-
-       error = of_property_read_u32(np, "#address-cells", &nr_addr);
-       if (error)
-               return -ENOENT;
+       struct of_range_parser parser;
+       struct of_range range;
+       int error;
 
-       error = of_property_read_u32(np, "#size-cells", &nr_size);
+       error = of_range_parser_init(&parser, np);
        if (error)
-               return -ENOENT;
-
-       if (nr_addr != 1 || nr_size != 1) {
-               dev_err(ddata->dev, "invalid ranges for %pOF\n", np);
+               return error;
 
-               return -EINVAL;
+       for_each_of_range(&parser, &range) {
+               ddata->module_pa = range.cpu_addr;
+               ddata->module_size = range.size;
+               break;
        }
 
-       ranges++;
-       ddata->module_pa = of_translate_address(np, ranges++);
-       ddata->module_size = be32_to_cpup(ranges);
-
        return 0;
 }
 
@@ -913,7 +890,7 @@ static int sysc_check_registers(struct sysc *ddata)
  * within the interconnect target module range. For example, SGX has
  * them at offset 0x1fc00 in the 32MB module address space. And cpsw
  * has them at offset 0x1200 in the CPSW_WR child. Usually the
- * the interconnect target module registers are at the beginning of
+ * interconnect target module registers are at the beginning of
  * the module range though.
  */
 static int sysc_ioremap(struct sysc *ddata)
@@ -964,7 +941,7 @@ static int sysc_map_and_check_registers(struct sysc *ddata)
 
        sysc_check_children(ddata);
 
-       if (!of_get_property(np, "reg", NULL))
+       if (!of_property_present(np, "reg"))
                return 0;
 
        error = sysc_parse_registers(ddata);
@@ -2530,11 +2507,9 @@ static struct dev_pm_domain sysc_child_pm_domain = {
 static void sysc_reinit_modules(struct sysc_soc_info *soc)
 {
        struct sysc_module *module;
-       struct list_head *pos;
        struct sysc *ddata;
 
-       list_for_each(pos, &sysc_soc->restored_modules) {
-               module = list_entry(pos, struct sysc_module, node);
+       list_for_each_entry(module, &sysc_soc->restored_modules, node) {
                ddata = module->ddata;
                sysc_reinit_module(ddata, ddata->enabled);
        }
@@ -3214,12 +3189,10 @@ static void sysc_cleanup_static_data(void)
 static int sysc_check_disabled_devices(struct sysc *ddata)
 {
        struct sysc_address *disabled_module;
-       struct list_head *pos;
        int error = 0;
 
        mutex_lock(&sysc_soc->list_lock);
-       list_for_each(pos, &sysc_soc->disabled_modules) {
-               disabled_module = list_entry(pos, struct sysc_address, node);
+       list_for_each_entry(disabled_module, &sysc_soc->disabled_modules, node) {
                if (ddata->module_pa == disabled_module->base) {
                        dev_dbg(ddata->dev, "module disabled for this SoC\n");
                        error = -ENODEV;
index a58ac0c8e2826ada3a63d6557f0dc09e36bf08b8..472a570bd53a98c4a9233496d78d8b1c733b9794 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
-#include <linux/of_device.h>
+#include <linux/of_platform.h>
 #include <linux/sched/signal.h>
 #include <linux/slab.h>
 #include <linux/vexpress.h>
index 3256254c3722c6f7efffa42bd9328505e9b27ee4..265e0fb39bc7dcf87f682f5145d7c1274602f00a 100644 (file)
@@ -76,6 +76,8 @@
 #define DRP0_INTERRUPT_ENABLE           BIT(6)
 #define SB_DB_DRP_INTERRUPT_ENABLE      0x3
 
+#define ECC_POLL_MSEC                  5000
+
 enum {
        LLCC_DRAM_CE = 0,
        LLCC_DRAM_UE,
@@ -213,7 +215,7 @@ dump_syn_reg_values(struct llcc_drv_data *drv, u32 bank, int err_type)
 
        for (i = 0; i < reg_data.reg_cnt; i++) {
                synd_reg = reg_data.synd_reg + (i * 4);
-               ret = regmap_read(drv->regmap, drv->offsets[bank] + synd_reg,
+               ret = regmap_read(drv->regmaps[bank], synd_reg,
                                  &synd_val);
                if (ret)
                        goto clear;
@@ -222,8 +224,7 @@ dump_syn_reg_values(struct llcc_drv_data *drv, u32 bank, int err_type)
                            reg_data.name, i, synd_val);
        }
 
-       ret = regmap_read(drv->regmap,
-                         drv->offsets[bank] + reg_data.count_status_reg,
+       ret = regmap_read(drv->regmaps[bank], reg_data.count_status_reg,
                          &err_cnt);
        if (ret)
                goto clear;
@@ -233,8 +234,7 @@ dump_syn_reg_values(struct llcc_drv_data *drv, u32 bank, int err_type)
        edac_printk(KERN_CRIT, EDAC_LLCC, "%s: Error count: 0x%4x\n",
                    reg_data.name, err_cnt);
 
-       ret = regmap_read(drv->regmap,
-                         drv->offsets[bank] + reg_data.ways_status_reg,
+       ret = regmap_read(drv->regmaps[bank], reg_data.ways_status_reg,
                          &err_ways);
        if (ret)
                goto clear;
@@ -285,8 +285,7 @@ dump_syn_reg(struct edac_device_ctl_info *edev_ctl, int err_type, u32 bank)
        return ret;
 }
 
-static irqreturn_t
-llcc_ecc_irq_handler(int irq, void *edev_ctl)
+static irqreturn_t llcc_ecc_irq_handler(int irq, void *edev_ctl)
 {
        struct edac_device_ctl_info *edac_dev_ctl = edev_ctl;
        struct llcc_drv_data *drv = edac_dev_ctl->dev->platform_data;
@@ -296,8 +295,7 @@ llcc_ecc_irq_handler(int irq, void *edev_ctl)
 
        /* Iterate over the banks and look for Tag RAM or Data RAM errors */
        for (i = 0; i < drv->num_banks; i++) {
-               ret = regmap_read(drv->regmap,
-                                 drv->offsets[i] + DRP_INTERRUPT_STATUS,
+               ret = regmap_read(drv->regmaps[i], DRP_INTERRUPT_STATUS,
                                  &drp_error);
 
                if (!ret && (drp_error & SB_ECC_ERROR)) {
@@ -312,8 +310,7 @@ llcc_ecc_irq_handler(int irq, void *edev_ctl)
                if (!ret)
                        irq_rc = IRQ_HANDLED;
 
-               ret = regmap_read(drv->regmap,
-                                 drv->offsets[i] + TRP_INTERRUPT_0_STATUS,
+               ret = regmap_read(drv->regmaps[i], TRP_INTERRUPT_0_STATUS,
                                  &trp_error);
 
                if (!ret && (trp_error & SB_ECC_ERROR)) {
@@ -332,6 +329,11 @@ llcc_ecc_irq_handler(int irq, void *edev_ctl)
        return irq_rc;
 }
 
+static void llcc_ecc_check(struct edac_device_ctl_info *edev_ctl)
+{
+       llcc_ecc_irq_handler(0, edev_ctl);
+}
+
 static int qcom_llcc_edac_probe(struct platform_device *pdev)
 {
        struct llcc_drv_data *llcc_driv_data = pdev->dev.platform_data;
@@ -359,29 +361,31 @@ static int qcom_llcc_edac_probe(struct platform_device *pdev)
        edev_ctl->ctl_name = "llcc";
        edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE;
 
-       rc = edac_device_add_device(edev_ctl);
-       if (rc)
-               goto out_mem;
-
-       platform_set_drvdata(pdev, edev_ctl);
-
-       /* Request for ecc irq */
+       /* Check if LLCC driver has passed ECC IRQ */
        ecc_irq = llcc_driv_data->ecc_irq;
-       if (ecc_irq < 0) {
-               rc = -ENODEV;
-               goto out_dev;
-       }
-       rc = devm_request_irq(dev, ecc_irq, llcc_ecc_irq_handler,
+       if (ecc_irq > 0) {
+               /* Use interrupt mode if IRQ is available */
+               rc = devm_request_irq(dev, ecc_irq, llcc_ecc_irq_handler,
                              IRQF_TRIGGER_HIGH, "llcc_ecc", edev_ctl);
-       if (rc)
-               goto out_dev;
+               if (!rc) {
+                       edac_op_state = EDAC_OPSTATE_INT;
+                       goto irq_done;
+               }
+       }
 
-       return rc;
+       /* Fall back to polling mode otherwise */
+       edev_ctl->poll_msec = ECC_POLL_MSEC;
+       edev_ctl->edac_check = llcc_ecc_check;
+       edac_op_state = EDAC_OPSTATE_POLL;
 
-out_dev:
-       edac_device_del_device(edev_ctl->dev);
-out_mem:
-       edac_device_free_ctl_info(edev_ctl);
+irq_done:
+       rc = edac_device_add_device(edev_ctl);
+       if (rc) {
+               edac_device_free_ctl_info(edev_ctl);
+               return rc;
+       }
+
+       platform_set_drvdata(pdev, edev_ctl);
 
        return rc;
 }
index dbc474ff62b71362a510cd02ecba2c50d72f7b53..e7d97b59963b0ba989798ba9e31bb14458ad2871 100644 (file)
@@ -2289,7 +2289,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
                return ret;
 
        ret = __scmi_xfer_info_init(sinfo, &sinfo->tx_minfo);
-       if (!ret && idr_find(&sinfo->rx_idr, SCMI_PROTOCOL_BASE))
+       if (!ret && !idr_is_empty(&sinfo->rx_idr))
                ret = __scmi_xfer_info_init(sinfo, &sinfo->rx_minfo);
 
        return ret;
index 112c285deb97b768fa3c23f6d738d8c0d043025b..1efa5e9392c4214439f9bb9100e2fbff12e8e839 100644 (file)
  * struct scmi_mailbox - Structure representing a SCMI mailbox transport
  *
  * @cl: Mailbox Client
- * @chan: Transmit/Receive mailbox channel
+ * @chan: Transmit/Receive mailbox uni/bi-directional channel
+ * @chan_receiver: Optional Receiver mailbox unidirectional channel
  * @cinfo: SCMI channel info
  * @shmem: Transmit/Receive shared memory area
  */
 struct scmi_mailbox {
        struct mbox_client cl;
        struct mbox_chan *chan;
+       struct mbox_chan *chan_receiver;
        struct scmi_chan_info *cinfo;
        struct scmi_shared_mem __iomem *shmem;
 };
@@ -48,30 +50,62 @@ static void rx_callback(struct mbox_client *cl, void *m)
 
 static bool mailbox_chan_available(struct device_node *of_node, int idx)
 {
+       int num_mb;
+
+       /*
+        * Just check if bidirrectional channels are involved, and check the
+        * index accordingly; proper full validation will be made later
+        * in mailbox_chan_setup().
+        */
+       num_mb = of_count_phandle_with_args(of_node, "mboxes", "#mbox-cells");
+       if (num_mb == 3 && idx == 1)
+               idx = 2;
+
        return !of_parse_phandle_with_args(of_node, "mboxes",
                                           "#mbox-cells", idx, NULL);
 }
 
-static int mailbox_chan_validate(struct device *cdev)
+/**
+ * mailbox_chan_validate  - Validate transport configuration and map channels
+ *
+ * @cdev: Reference to the underlying transport device carrying the
+ *       of_node descriptor to analyze.
+ * @a2p_rx_chan: A reference to an optional unidirectional channel to use
+ *              for replies on the a2p channel. Set as zero if not present.
+ * @p2a_chan: A reference to the optional p2a channel.
+ *           Set as zero if not present.
+ *
+ * At first, validate the transport configuration as described in terms of
+ * 'mboxes' and 'shmem', then determin which mailbox channel indexes are
+ * appropriate to be use in the current configuration.
+ *
+ * Return: 0 on Success or error
+ */
+static int mailbox_chan_validate(struct device *cdev,
+                                int *a2p_rx_chan, int *p2a_chan)
 {
        int num_mb, num_sh, ret = 0;
        struct device_node *np = cdev->of_node;
 
        num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
        num_sh = of_count_phandle_with_args(np, "shmem", NULL);
+       dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh);
+
        /* Bail out if mboxes and shmem descriptors are inconsistent */
-       if (num_mb <= 0 || num_sh > 2 || num_mb != num_sh) {
-               dev_warn(cdev, "Invalid channel descriptor for '%s'\n",
-                        of_node_full_name(np));
+       if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 3 ||
+           (num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2)) {
+               dev_warn(cdev,
+                        "Invalid channel descriptor for '%s' - mbs:%d  shm:%d\n",
+                        of_node_full_name(np), num_mb, num_sh);
                return -EINVAL;
        }
 
+       /* Bail out if provided shmem descriptors do not refer distinct areas  */
        if (num_sh > 1) {
                struct device_node *np_tx, *np_rx;
 
                np_tx = of_parse_phandle(np, "shmem", 0);
                np_rx = of_parse_phandle(np, "shmem", 1);
-               /* SCMI Tx and Rx shared mem areas have to be distinct */
                if (!np_tx || !np_rx || np_tx == np_rx) {
                        dev_warn(cdev, "Invalid shmem descriptor for '%s'\n",
                                 of_node_full_name(np));
@@ -82,6 +116,29 @@ static int mailbox_chan_validate(struct device *cdev)
                of_node_put(np_rx);
        }
 
+       /* Calculate channels IDs to use depending on mboxes/shmem layout */
+       if (!ret) {
+               switch (num_mb) {
+               case 1:
+                       *a2p_rx_chan = 0;
+                       *p2a_chan = 0;
+                       break;
+               case 2:
+                       if (num_sh == 2) {
+                               *a2p_rx_chan = 0;
+                               *p2a_chan = 1;
+                       } else {
+                               *a2p_rx_chan = 1;
+                               *p2a_chan = 0;
+                       }
+                       break;
+               case 3:
+                       *a2p_rx_chan = 1;
+                       *p2a_chan = 2;
+                       break;
+               }
+       }
+
        return ret;
 }
 
@@ -92,15 +149,18 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
        struct device *cdev = cinfo->dev;
        struct scmi_mailbox *smbox;
        struct device_node *shmem;
-       int ret, idx = tx ? 0 : 1;
+       int ret, a2p_rx_chan, p2a_chan, idx = tx ? 0 : 1;
        struct mbox_client *cl;
        resource_size_t size;
        struct resource res;
 
-       ret = mailbox_chan_validate(cdev);
+       ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan);
        if (ret)
                return ret;
 
+       if (!tx && !p2a_chan)
+               return -ENODEV;
+
        smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
        if (!smbox)
                return -ENOMEM;
@@ -130,15 +190,26 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
        cl->tx_block = false;
        cl->knows_txdone = tx;
 
-       smbox->chan = mbox_request_channel(cl, tx ? 0 : 1);
+       smbox->chan = mbox_request_channel(cl, tx ? 0 : p2a_chan);
        if (IS_ERR(smbox->chan)) {
                ret = PTR_ERR(smbox->chan);
                if (ret != -EPROBE_DEFER)
-                       dev_err(cdev, "failed to request SCMI %s mailbox\n",
-                               tx ? "Tx" : "Rx");
+                       dev_err(cdev,
+                               "failed to request SCMI %s mailbox\n", desc);
                return ret;
        }
 
+       /* Additional unidirectional channel for TX if needed */
+       if (tx && a2p_rx_chan) {
+               smbox->chan_receiver = mbox_request_channel(cl, a2p_rx_chan);
+               if (IS_ERR(smbox->chan_receiver)) {
+                       ret = PTR_ERR(smbox->chan_receiver);
+                       if (ret != -EPROBE_DEFER)
+                               dev_err(cdev, "failed to request SCMI Tx Receiver mailbox\n");
+                       return ret;
+               }
+       }
+
        cinfo->transport_info = smbox;
        smbox->cinfo = cinfo;
 
@@ -152,8 +223,10 @@ static int mailbox_chan_free(int id, void *p, void *data)
 
        if (smbox && !IS_ERR(smbox->chan)) {
                mbox_free_channel(smbox->chan);
+               mbox_free_channel(smbox->chan_receiver);
                cinfo->transport_info = NULL;
                smbox->chan = NULL;
+               smbox->chan_receiver = NULL;
                smbox->cinfo = NULL;
        }
 
index 929720387102e6b85ffd709affdb9365f7ab27f0..e123de6e8c67a9719542666bd93116fe9cc41347 100644 (file)
@@ -403,7 +403,7 @@ out:
 static int setup_shmem(struct device *dev, struct scmi_chan_info *cinfo,
                       struct scmi_optee_channel *channel)
 {
-       if (of_find_property(cinfo->dev->of_node, "shmem", NULL))
+       if (of_property_present(cinfo->dev->of_node, "shmem"))
                return setup_static_shmem(dev, cinfo, channel);
        else
                return setup_dynamic_shmem(dev, channel);
index dca79caccd01c15ff5761423e24a247a858abf7a..47db49911e7b89a05747da22f1858ccd3e32067a 100644 (file)
@@ -310,9 +310,8 @@ static int imx_scu_probe(struct platform_device *pdev)
                sc_chan->ch = mbox_request_channel_byname(cl, chan_name);
                if (IS_ERR(sc_chan->ch)) {
                        ret = PTR_ERR(sc_chan->ch);
-                       if (ret != -EPROBE_DEFER)
-                               dev_err(dev, "Failed to request mbox chan %s ret %d\n",
-                                       chan_name, ret);
+                       dev_err_probe(dev, ret, "Failed to request mbox chan %s\n",
+                                     chan_name);
                        kfree(chan_name);
                        return ret;
                }
index 2a4f07423365aa29a42b49c6782aaec14f48332e..84b67342707333c68aaeb392ba3e710236cfebd0 100644 (file)
@@ -180,7 +180,11 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
 
        /* LVDS SS */
        { "lvds0", IMX_SC_R_LVDS_0, 1, false, 0 },
+       { "lvds0-pwm", IMX_SC_R_LVDS_0_PWM_0, 1, false, 0 },
+       { "lvds0-lpi2c", IMX_SC_R_LVDS_0_I2C_0, 2, true, 0 },
        { "lvds1", IMX_SC_R_LVDS_1, 1, false, 0 },
+       { "lvds1-pwm", IMX_SC_R_LVDS_1_PWM_0, 1, false, 0 },
+       { "lvds1-lpi2c", IMX_SC_R_LVDS_1_I2C_0, 2, true, 0 },
 
        /* DC SS */
        { "dc0", IMX_SC_R_DC_0, 1, false, 0 },
index 3f5ff9ed668ef54bebcaadfe4e179fb13c3ce162..798bcdb05d84ee067b6e7fb6c16a998ed4e9582a 100644 (file)
@@ -311,11 +311,14 @@ static int __init meson_sm_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, fw);
 
-       pr_info("secure-monitor enabled\n");
+       if (devm_of_platform_populate(dev))
+               goto out_in_base;
 
        if (sysfs_create_group(&pdev->dev.kobj, &meson_sm_sysfs_attr_group))
                goto out_in_base;
 
+       pr_info("secure-monitor enabled\n");
+
        return 0;
 
 out_in_base:
index b1e11f85b805462fb96def68632ae11fe3a7fd88..fde33acd46b756f2b9ac2bd1c9a2341084bcb974 100644 (file)
@@ -905,7 +905,7 @@ static int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region,
  * Return negative errno on failure or 0 on success with @srcvm updated.
  */
 int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
-                       unsigned int *srcvm,
+                       u64 *srcvm,
                        const struct qcom_scm_vmperm *newvm,
                        unsigned int dest_cnt)
 {
@@ -922,9 +922,9 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
        __le32 *src;
        void *ptr;
        int ret, i, b;
-       unsigned long srcvm_bits = *srcvm;
+       u64 srcvm_bits = *srcvm;
 
-       src_sz = hweight_long(srcvm_bits) * sizeof(*src);
+       src_sz = hweight64(srcvm_bits) * sizeof(*src);
        mem_to_map_sz = sizeof(*mem_to_map);
        dest_sz = dest_cnt * sizeof(*destvm);
        ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) +
@@ -937,8 +937,10 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
        /* Fill source vmid detail */
        src = ptr;
        i = 0;
-       for_each_set_bit(b, &srcvm_bits, BITS_PER_LONG)
-               src[i++] = cpu_to_le32(b);
+       for (b = 0; b < BITS_PER_TYPE(u64); b++) {
+               if (srcvm_bits & BIT(b))
+                       src[i++] = cpu_to_le32(b);
+       }
 
        /* Fill details of mem buff to map */
        mem_to_map = ptr + ALIGN(src_sz, SZ_64);
@@ -1506,8 +1508,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
 static void qcom_scm_shutdown(struct platform_device *pdev)
 {
        /* Clean shutdown, disable download mode to allow normal restart */
-       if (download_mode)
-               qcom_scm_set_download_mode(false);
+       qcom_scm_set_download_mode(false);
 }
 
 static const struct of_device_id qcom_scm_dt_match[] = {
@@ -1542,6 +1543,7 @@ static const struct of_device_id qcom_scm_dt_match[] = {
        },
        { .compatible = "qcom,scm-msm8994" },
        { .compatible = "qcom,scm-msm8996" },
+       { .compatible = "qcom,scm-sm6375", .data = (void *)SCM_HAS_CORE_CLK },
        { .compatible = "qcom,scm" },
        {}
 };
index 3ca2b5d9e66f5e058e6e5884e1852244790e2e8e..6dfe3d34109ee91a31d4fb0f515980e7c12a1765 100644 (file)
@@ -193,7 +193,7 @@ static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
                },
        };
        u32 fd = 0, len = 0;
-       int remaining, err;
+       int remaining, err, close_err;
 
        mutex_lock(&bpmp_debug_lock);
        err = mrq_debug_open(bpmp, name, &fd, &len, 0);
@@ -231,7 +231,9 @@ static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
        *nbytes = len;
 
 close:
-       err = mrq_debug_close(bpmp, fd);
+       close_err = mrq_debug_close(bpmp, fd);
+       if (!err)
+               err = close_err;
 out:
        mutex_unlock(&bpmp_debug_lock);
        return err;
@@ -319,7 +321,7 @@ static int bpmp_debug_show(struct seq_file *m, void *p)
                },
        };
        u32 fd = 0, len = 0;
-       int remaining, err;
+       int remaining, err, close_err;
 
        filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
        if (!filename)
@@ -353,7 +355,9 @@ static int bpmp_debug_show(struct seq_file *m, void *p)
        }
 
 close:
-       err = mrq_debug_close(bpmp, fd);
+       close_err = mrq_debug_close(bpmp, fd);
+       if (!err)
+               err = close_err;
 out:
        mutex_unlock(&bpmp_debug_lock);
        return err;
index 042c2043929d702763d6a4ff84819a0ad85b69a9..8b5e5daa9fae346ce42ea2fb69978364ae87ab91 100644 (file)
@@ -764,19 +764,19 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
        if (err < 0)
                goto free_mrq;
 
-       if (of_find_property(pdev->dev.of_node, "#clock-cells", NULL)) {
+       if (of_property_present(pdev->dev.of_node, "#clock-cells")) {
                err = tegra_bpmp_init_clocks(bpmp);
                if (err < 0)
                        goto free_mrq;
        }
 
-       if (of_find_property(pdev->dev.of_node, "#reset-cells", NULL)) {
+       if (of_property_present(pdev->dev.of_node, "#reset-cells")) {
                err = tegra_bpmp_init_resets(bpmp);
                if (err < 0)
                        goto free_mrq;
        }
 
-       if (of_find_property(pdev->dev.of_node, "#power-domain-cells", NULL)) {
+       if (of_property_present(pdev->dev.of_node, "#power-domain-cells")) {
                err = tegra_bpmp_init_powergates(bpmp);
                if (err < 0)
                        goto free_mrq;
index 853901acaeec23281fa70c7a1a95968deab52fdc..162df49654fba2e89ad7051cf13482af1e425d0a 100644 (file)
@@ -39,7 +39,7 @@
 #define SCB_CTRL_NOTIFY_MASK BIT(SCB_CTRL_NOTIFY)
 
 #define SCB_CTRL_POS (16)
-#define SCB_CTRL_MASK GENMASK_ULL(SCB_CTRL_POS + SCB_MASK_WIDTH, SCB_CTRL_POS)
+#define SCB_CTRL_MASK GENMASK(SCB_CTRL_POS + SCB_MASK_WIDTH - 1, SCB_CTRL_POS)
 
 /* SCBCTRL service status register */
 
@@ -79,6 +79,27 @@ static bool mpfs_mbox_busy(struct mpfs_mbox *mbox)
        return status & SCB_STATUS_BUSY_MASK;
 }
 
+static bool mpfs_mbox_last_tx_done(struct mbox_chan *chan)
+{
+       struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
+       struct mpfs_mss_response *response = mbox->response;
+       u32 val;
+
+       if (mpfs_mbox_busy(mbox))
+               return false;
+
+       /*
+        * The service status is stored in bits 31:16 of the SERVICES_SR
+        * register & is only valid when the system controller is not busy.
+        * Failed services are intended to generated interrupts, but in reality
+        * this does not happen, so the status must be checked here.
+        */
+       val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
+       response->resp_status = (val & SCB_STATUS_MASK) >> SCB_STATUS_POS;
+
+       return true;
+}
+
 static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
 {
        struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
@@ -118,6 +139,7 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
        }
 
        opt_sel = ((msg->mbox_offset << 7u) | (msg->cmd_opcode & 0x7fu));
+
        tx_trigger = (opt_sel << SCB_CTRL_POS) & SCB_CTRL_MASK;
        tx_trigger |= SCB_CTRL_REQ_MASK | SCB_STATUS_NOTIFY_MASK;
        writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET);
@@ -130,7 +152,7 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
        struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
        struct mpfs_mss_response *response = mbox->response;
        u16 num_words = ALIGN((response->resp_size), (4)) / 4U;
-       u32 i, status;
+       u32 i;
 
        if (!response->resp_msg) {
                dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM);
@@ -138,8 +160,6 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
        }
 
        /*
-        * The status is stored in bits 31:16 of the SERVICES_SR register.
-        * It is only valid when BUSY == 0.
         * We should *never* get an interrupt while the controller is
         * still in the busy state. If we do, something has gone badly
         * wrong & the content of the mailbox would not be valid.
@@ -150,24 +170,10 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
                return;
        }
 
-       status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
-
-       /*
-        * If the status of the individual servers is non-zero, the service has
-        * failed. The contents of the mailbox at this point are not be valid,
-        * so don't bother reading them. Set the status so that the driver
-        * implementing the service can handle the result.
-        */
-       response->resp_status = (status & SCB_STATUS_MASK) >> SCB_STATUS_POS;
-       if (response->resp_status)
-               return;
-
-       if (!mpfs_mbox_busy(mbox)) {
-               for (i = 0; i < num_words; i++) {
-                       response->resp_msg[i] =
-                               readl_relaxed(mbox->mbox_base
-                                             + mbox->resp_offset + i * 0x4);
-               }
+       for (i = 0; i < num_words; i++) {
+               response->resp_msg[i] =
+                       readl_relaxed(mbox->mbox_base
+                                     + mbox->resp_offset + i * 0x4);
        }
 
        mbox_chan_received_data(chan, response);
@@ -182,7 +188,6 @@ static irqreturn_t mpfs_mbox_inbox_isr(int irq, void *data)
 
        mpfs_mbox_rx_data(chan);
 
-       mbox_chan_txdone(chan, 0);
        return IRQ_HANDLED;
 }
 
@@ -212,6 +217,7 @@ static const struct mbox_chan_ops mpfs_mbox_ops = {
        .send_data = mpfs_mbox_send_data,
        .startup = mpfs_mbox_startup,
        .shutdown = mpfs_mbox_shutdown,
+       .last_tx_done = mpfs_mbox_last_tx_done,
 };
 
 static int mpfs_mbox_probe(struct platform_device *pdev)
@@ -247,7 +253,8 @@ static int mpfs_mbox_probe(struct platform_device *pdev)
        mbox->controller.num_chans = 1;
        mbox->controller.chans = mbox->chans;
        mbox->controller.ops = &mpfs_mbox_ops;
-       mbox->controller.txdone_irq = true;
+       mbox->controller.txdone_poll = true;
+       mbox->controller.txpoll_period = 10u;
 
        ret = devm_mbox_controller_register(&pdev->dev, &mbox->controller);
        if (ret) {
index fac290e48e0b86b84aa4d1a20e8e6eaec018b7fc..91774e6ee6240e3718c4a657c8ac35471caa56e4 100644 (file)
@@ -228,7 +228,7 @@ config RENESAS_RPCIF
 
 config STM32_FMC2_EBI
        tristate "Support for FMC2 External Bus Interface on STM32MP SoCs"
-       depends on MACH_STM32MP157 || COMPILE_TEST
+       depends on ARCH_STM32 || COMPILE_TEST
        select MFD_SYSCON
        help
          Select this option to enable the STM32 FMC2 External Bus Interface
index e749dcb3ddea93335a6ca5f5dd6e1de0e9a52418..635966d705cbb24502da0092af8ea39a90978830 100644 (file)
@@ -598,7 +598,7 @@ static int atmel_ebi_probe(struct platform_device *pdev)
        reg_cells += val;
 
        for_each_available_child_of_node(np, child) {
-               if (!of_find_property(child, "reg", NULL))
+               if (!of_property_present(child, "reg"))
                        continue;
 
                ret = atmel_ebi_dev_setup(ebi, child, reg_cells);
index 85965fa26e0bbbb50dca26668f4aa25366f0eba1..78bd71b203f2daa511749772f9c4b026faadc51b 100644 (file)
@@ -321,4 +321,3 @@ module_platform_driver(l2_ctl_driver);
 
 MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
 MODULE_DESCRIPTION("Baikal-T1 L2-cache driver");
-MODULE_LICENSE("GPL v2");
index b32005bf269cb426f731bcc12f4db4429452c0bf..0ef8cc878b95c5a3f7e5e59a663715fdf552c605 100644 (file)
@@ -164,4 +164,3 @@ module_platform_driver(da8xx_ddrctl_driver);
 
 MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
 MODULE_DESCRIPTION("TI da8xx DDR2/mDDR controller driver");
-MODULE_LICENSE("GPL v2");
index e83b61c925a4fdd061c89f8901a81bfeb50a7c3a..9e8d8e9c5ad868d0ff55d0063d3406adb7cb373b 100644 (file)
@@ -327,6 +327,5 @@ static int __init fsl_ifc_init(void)
 }
 subsys_initcall(fsl_ifc_init);
 
-MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Freescale Semiconductor");
 MODULE_DESCRIPTION("Freescale Integrated Flash Controller driver");
index 5a9754442bc75fa3f883b65c3461a1ca0d8c5f29..6523cb51051827c6f247206986fb27e16ec2a456 100644 (file)
@@ -713,6 +713,11 @@ static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8195 = {
        .has_gals = true,
 };
 
+static const struct mtk_smi_common_plat mtk_smi_common_mt8365 = {
+       .type     = MTK_SMI_GEN2,
+       .bus_sel  = F_MMU1_LARB(2) | F_MMU1_LARB(4),
+};
+
 static const struct of_device_id mtk_smi_common_of_ids[] = {
        {.compatible = "mediatek,mt2701-smi-common", .data = &mtk_smi_common_gen1},
        {.compatible = "mediatek,mt2712-smi-common", .data = &mtk_smi_common_gen2},
@@ -728,6 +733,7 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
        {.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
        {.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
        {.compatible = "mediatek,mt8195-smi-sub-common", .data = &mtk_smi_sub_common_mt8195},
+       {.compatible = "mediatek,mt8365-smi-common", .data = &mtk_smi_common_mt8365},
        {}
 };
 
index efc6c08db2b70a78ae2d6eb902305153fb8cf36e..406fddcdba02a01e35254c4e0d7216607d5350c9 100644 (file)
@@ -341,6 +341,5 @@ static int __init mvebu_devbus_init(void)
 }
 module_init(mvebu_devbus_init);
 
-MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
 MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller");
index 5cd28619ea9fbcc360ddfafbea9753221ef8aefa..9082b6c3763dcc16b11dcd418c9b95bd94fa0547 100644 (file)
@@ -983,4 +983,3 @@ arch_initcall(tegra_mc_init);
 
 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
 MODULE_DESCRIPTION("NVIDIA Tegra Memory Controller driver");
-MODULE_LICENSE("GPL v2");
index 26e763bde92a76278dda84fcda84855c496b0ec1..e935ad4e95b68729bd42e53de80e6a1e41154d3f 100644 (file)
@@ -280,4 +280,3 @@ module_platform_driver(tegra186_emc_driver);
 
 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
 MODULE_DESCRIPTION("NVIDIA Tegra186 External Memory Controller driver");
-MODULE_LICENSE("GPL v2");
index cc76adb8d7e8a111b6b1ae1993e59662ee83a795..4cb608c71ead5208cc7da9481cdb30bac2dc4622 100644 (file)
@@ -277,7 +277,7 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
                /*
                 * Dev1 LSB.
                 */
-               value = tegra210_emc_mrr_read(emc, 2, 18);
+               value = tegra210_emc_mrr_read(emc, 1, 18);
 
                for (i = 0; i < emc->num_channels; i++) {
                        temp[i][0] |= (value & 0x00ff) >> 0;
index 3e0598363b873b30534283b78a7028c93edf35b8..34a8785d2861aa80216451f6bb64cbf543894888 100644 (file)
@@ -22,8 +22,6 @@ static int tegra210_emc_table_device_init(struct reserved_mem *rmem,
                return -ENOMEM;
        }
 
-       count = 0;
-
        for (i = 0; i < TEGRA_EMC_MAX_FREQS; i++) {
                if (timings[i].revision == 0)
                        break;
index a701132638cf2a8439448b88f1469c50e571ed2c..f48466960f1b9c0f9b78ff4c6d0038c7719e124f 100644 (file)
@@ -262,7 +262,7 @@ struct fastrpc_channel_ctx {
        int domain_id;
        int sesscount;
        int vmcount;
-       u32 perms;
+       u64 perms;
        struct qcom_scm_vmperm vmperms[FASTRPC_MAX_VMIDS];
        struct rpmsg_device *rpdev;
        struct fastrpc_session_ctx session[FASTRPC_MAX_SESSIONS];
index 90f457b8e1feb8df6a9718fd411054bfc55f3e21..038c5903c0dc15789ae9d192ee308b74c5d796a5 100644 (file)
@@ -33,7 +33,7 @@ static int ath10k_qmi_map_msa_permission(struct ath10k_qmi *qmi,
 {
        struct qcom_scm_vmperm dst_perms[3];
        struct ath10k *ar = qmi->ar;
-       unsigned int src_perms;
+       u64 src_perms;
        u32 perm_count;
        int ret;
 
@@ -65,7 +65,7 @@ static int ath10k_qmi_unmap_msa_permission(struct ath10k_qmi *qmi,
 {
        struct qcom_scm_vmperm dst_perms;
        struct ath10k *ar = qmi->ar;
-       unsigned int src_perms;
+       u64 src_perms;
        int ret;
 
        src_perms = BIT(QCOM_SCM_VMID_MSS_MSA) | BIT(QCOM_SCM_VMID_WLAN);
index ab053084f7a22d3d6f21a11370f675e2b057b37c..1ba711bc01000beef454922fe35a58cc927c5445 100644 (file)
@@ -235,8 +235,8 @@ struct q6v5 {
        bool has_qaccept_regs;
        bool has_ext_cntl_regs;
        bool has_vq6;
-       int mpss_perm;
-       int mba_perm;
+       u64 mpss_perm;
+       u64 mba_perm;
        const char *hexagon_mdt_image;
        int version;
 };
@@ -414,7 +414,7 @@ static void q6v5_pds_disable(struct q6v5 *qproc, struct device **pds,
        }
 }
 
-static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm,
+static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, u64 *current_perm,
                                   bool local, bool remote, phys_addr_t addr,
                                   size_t size)
 {
@@ -967,7 +967,7 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw,
        unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
        dma_addr_t phys;
        void *metadata;
-       int mdata_perm;
+       u64 mdata_perm;
        int xferop_ret;
        size_t size;
        void *ptr;
index 0871108fb4dc5e4b9a07086437dd48ddbcd13f97..c99a20542685141c892f4f3813c36fca420d34e9 100644 (file)
@@ -94,7 +94,7 @@ struct qcom_adsp {
        size_t region_assign_size;
 
        int region_assign_idx;
-       int region_assign_perms;
+       u64 region_assign_perms;
 
        struct qcom_rproc_glink glink_subdev;
        struct qcom_rproc_subdev smd_subdev;
index 312fd9afccb01c1e7dc8a86999f173733dd5eeff..5d4f12800d9383084fc8ee53b88412a7be9f8d67 100644 (file)
@@ -308,11 +308,9 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
        }
 
        rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
-       if (IS_ERR(rstc)) {
-               if (PTR_ERR(rstc) != -EPROBE_DEFER)
-                       dev_err(&pdev->dev, "failed to get reset lines\n");
-               return PTR_ERR(rstc);
-       }
+       if (IS_ERR(rstc))
+               return dev_err_probe(&pdev->dev, PTR_ERR(rstc),
+                                    "failed to get reset lines\n");
 
        vpu_clk = devm_clk_get(&pdev->dev, "vpu");
        if (IS_ERR(vpu_clk)) {
index 35ec35aa500d67334a81231d87eaab3c6e7547d3..d9f19dc99da5e824b327c1a334e5d44e8f7c392b 100644 (file)
@@ -55,7 +55,7 @@ enum {
 
 #define APPLE_RTKIT_BUFFER_REQUEST     1
 #define APPLE_RTKIT_BUFFER_REQUEST_SIZE GENMASK_ULL(51, 44)
-#define APPLE_RTKIT_BUFFER_REQUEST_IOVA GENMASK_ULL(41, 0)
+#define APPLE_RTKIT_BUFFER_REQUEST_IOVA GENMASK_ULL(43, 0)
 
 #define APPLE_RTKIT_SYSLOG_TYPE GENMASK_ULL(59, 52)
 
@@ -409,11 +409,17 @@ static void apple_rtkit_syslog_rx_init(struct apple_rtkit *rtk, u64 msg)
                rtk->syslog_n_entries, rtk->syslog_msg_size);
 }
 
+static bool should_crop_syslog_char(char c)
+{
+       return c == '\n' || c == '\r' || c == ' ' || c == '\0';
+}
+
 static void apple_rtkit_syslog_rx_log(struct apple_rtkit *rtk, u64 msg)
 {
        u8 idx = msg & 0xff;
        char log_context[24];
        size_t entry_size = 0x20 + rtk->syslog_msg_size;
+       int msglen;
 
        if (!rtk->syslog_msg_buffer) {
                dev_warn(
@@ -446,7 +452,13 @@ static void apple_rtkit_syslog_rx_log(struct apple_rtkit *rtk, u64 msg)
                           rtk->syslog_msg_size);
 
        log_context[sizeof(log_context) - 1] = 0;
-       rtk->syslog_msg_buffer[rtk->syslog_msg_size - 1] = 0;
+
+       msglen = rtk->syslog_msg_size - 1;
+       while (msglen > 0 &&
+                  should_crop_syslog_char(rtk->syslog_msg_buffer[msglen - 1]))
+               msglen--;
+
+       rtk->syslog_msg_buffer[msglen] = 0;
        dev_info(rtk->dev, "RTKit: syslog message: %s: %s\n", log_context,
                 rtk->syslog_msg_buffer);
 
index bf51f03f77d6470ee39ab487793c582a6a28437e..1a179d4e011cfe98a3932be49852bae6137d16aa 100644 (file)
@@ -711,4 +711,3 @@ module_platform_driver(bcm2835_power_driver);
 
 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
 MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
-MODULE_LICENSE("GPL");
index 38e476905d96a8139f69e731ba99e1fa6ac07e90..c68d0e5267c42e68cb9c9703ad38e5a29835715b 100644 (file)
@@ -4,8 +4,6 @@ if SOC_BRCMSTB
 config BRCMSTB_PM
        bool "Support suspend/resume for STB platforms"
        default y
-       depends on PM
-       depends on ARCH_BRCMSTB || BMIPS_GENERIC
-       select ARM_CPU_SUSPEND if ARM
+       depends on PM && BMIPS_GENERIC
 
 endif # SOC_BRCMSTB
index e1d7b45432485a0601d26886a7834cc58e4c2963..364ddbe365c248ca3b8464492791f4a9485afc3e 100644 (file)
@@ -288,6 +288,10 @@ static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
        if (BRCM_ID(family_id) == 0x7260 && BRCM_REV(family_id) == 0)
                cpubiuctrl_regs = b53_cpubiuctrl_no_wb_regs;
 out:
+       if (ret && cpubiuctrl_base) {
+               iounmap(cpubiuctrl_base);
+               cpubiuctrl_base = NULL;
+       }
        return ret;
 }
 
index f849cfa69446b8c965e141456700d63f2b3ce2b4..9133a9ee0782d6c663f8d72303f7df5857c28e08 100644 (file)
@@ -1,3 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_ARM)              += s2-arm.o pm-arm.o
 obj-$(CONFIG_BMIPS_GENERIC)    += s2-mips.o s3-mips.o pm-mips.o
diff --git a/drivers/soc/bcm/brcmstb/pm/aon_defs.h b/drivers/soc/bcm/brcmstb/pm/aon_defs.h
deleted file mode 100644 (file)
index f695262..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Always ON (AON) register interface between bootloader and Linux
- *
- * Copyright Â© 2014-2017 Broadcom
- */
-
-#ifndef __BRCMSTB_AON_DEFS_H__
-#define __BRCMSTB_AON_DEFS_H__
-
-#include <linux/compiler.h>
-
-/* Magic number in upper 16-bits */
-#define BRCMSTB_S3_MAGIC_MASK                   0xffff0000
-#define BRCMSTB_S3_MAGIC_SHORT                  0x5AFE0000
-
-enum {
-       /* Restore random key for AES memory verification (off = fixed key) */
-       S3_FLAG_LOAD_RANDKEY            = (1 << 0),
-
-       /* Scratch buffer page table is present */
-       S3_FLAG_SCRATCH_BUFFER_TABLE    = (1 << 1),
-
-       /* Skip all memory verification */
-       S3_FLAG_NO_MEM_VERIFY           = (1 << 2),
-
-       /*
-        * Modification of this bit reserved for bootloader only.
-        * 1=PSCI started Linux, 0=Direct jump to Linux.
-        */
-       S3_FLAG_PSCI_BOOT               = (1 << 3),
-
-       /*
-        * Modification of this bit reserved for bootloader only.
-        * 1=64 bit boot, 0=32 bit boot.
-        */
-       S3_FLAG_BOOTED64                = (1 << 4),
-};
-
-#define BRCMSTB_HASH_LEN                       (128 / 8) /* 128-bit hash */
-
-#define AON_REG_MAGIC_FLAGS                    0x00
-#define AON_REG_CONTROL_LOW                    0x04
-#define AON_REG_CONTROL_HIGH                   0x08
-#define AON_REG_S3_HASH                                0x0c /* hash of S3 params */
-#define AON_REG_CONTROL_HASH_LEN               0x1c
-#define AON_REG_PANIC                          0x20
-
-#define BRCMSTB_S3_MAGIC               0x5AFEB007
-#define BRCMSTB_PANIC_MAGIC            0x512E115E
-#define BOOTLOADER_SCRATCH_SIZE                64
-#define BRCMSTB_DTU_STATE_MAP_ENTRIES  (8*1024)
-#define BRCMSTB_DTU_CONFIG_ENTRIES     (512)
-#define BRCMSTB_DTU_COUNT              (2)
-
-#define IMAGE_DESCRIPTORS_BUFSIZE      (2 * 1024)
-#define S3_BOOTLOADER_RESERVED         (S3_FLAG_PSCI_BOOT | S3_FLAG_BOOTED64)
-
-struct brcmstb_bootloader_dtu_table {
-       uint32_t        dtu_state_map[BRCMSTB_DTU_STATE_MAP_ENTRIES];
-       uint32_t        dtu_config[BRCMSTB_DTU_CONFIG_ENTRIES];
-};
-
-/*
- * Bootloader utilizes a custom parameter block left in DRAM for handling S3
- * warm resume
- */
-struct brcmstb_s3_params {
-       /* scratch memory for bootloader */
-       uint8_t scratch[BOOTLOADER_SCRATCH_SIZE];
-
-       uint32_t magic; /* BRCMSTB_S3_MAGIC */
-       uint64_t reentry; /* PA */
-
-       /* descriptors */
-       uint32_t hash[BRCMSTB_HASH_LEN / 4];
-
-       /*
-        * If 0, then ignore this parameter (there is only one set of
-        *   descriptors)
-        *
-        * If non-0, then a second set of descriptors is stored at:
-        *
-        *   descriptors + desc_offset_2
-        *
-        * The MAC result of both descriptors is XOR'd and stored in @hash
-        */
-       uint32_t desc_offset_2;
-
-       /*
-        * (Physical) address of a brcmstb_bootloader_scratch_table, for
-        * providing a large DRAM buffer to the bootloader
-        */
-       uint64_t buffer_table;
-
-       uint32_t spare[70];
-
-       uint8_t descriptors[IMAGE_DESCRIPTORS_BUFSIZE];
-       /*
-        * Must be last member of struct. See brcmstb_pm_s3_finish() for reason.
-        */
-       struct brcmstb_bootloader_dtu_table dtu[BRCMSTB_DTU_COUNT];
-} __packed;
-
-#endif /* __BRCMSTB_AON_DEFS_H__ */
diff --git a/drivers/soc/bcm/brcmstb/pm/pm-arm.c b/drivers/soc/bcm/brcmstb/pm/pm-arm.c
deleted file mode 100644 (file)
index d681cd2..0000000
+++ /dev/null
@@ -1,874 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * ARM-specific support for Broadcom STB S2/S3/S5 power management
- *
- * S2: clock gate CPUs and as many peripherals as possible
- * S3: power off all of the chip except the Always ON (AON) island; keep DDR is
- *     self-refresh
- * S5: (a.k.a. S3 cold boot) much like S3, except DDR is powered down, so we
- *     treat this mode like a soft power-off, with wakeup allowed from AON
- *
- * Copyright Â© 2014-2017 Broadcom
- */
-
-#define pr_fmt(fmt) "brcmstb-pm: " fmt
-
-#include <linux/bitops.h>
-#include <linux/compiler.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/kconfig.h>
-#include <linux/kernel.h>
-#include <linux/memblock.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/panic_notifier.h>
-#include <linux/platform_device.h>
-#include <linux/pm.h>
-#include <linux/printk.h>
-#include <linux/proc_fs.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/sort.h>
-#include <linux/suspend.h>
-#include <linux/types.h>
-#include <linux/uaccess.h>
-#include <linux/soc/brcmstb/brcmstb.h>
-
-#include <asm/fncpy.h>
-#include <asm/setup.h>
-#include <asm/suspend.h>
-
-#include "pm.h"
-#include "aon_defs.h"
-
-#define SHIMPHY_DDR_PAD_CNTRL          0x8c
-
-/* Method #0 */
-#define SHIMPHY_PAD_PLL_SEQUENCE       BIT(8)
-#define SHIMPHY_PAD_GATE_PLL_S3                BIT(9)
-
-/* Method #1 */
-#define PWRDWN_SEQ_NO_SEQUENCING       0
-#define PWRDWN_SEQ_HOLD_CHANNEL                1
-#define        PWRDWN_SEQ_RESET_PLL            2
-#define PWRDWN_SEQ_POWERDOWN_PLL       3
-
-#define SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK 0x00f00000
-#define SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT        20
-
-#define        DDR_FORCE_CKE_RST_N             BIT(3)
-#define        DDR_PHY_RST_N                   BIT(2)
-#define        DDR_PHY_CKE                     BIT(1)
-
-#define        DDR_PHY_NO_CHANNEL              0xffffffff
-
-#define MAX_NUM_MEMC                   3
-
-struct brcmstb_memc {
-       void __iomem *ddr_phy_base;
-       void __iomem *ddr_shimphy_base;
-       void __iomem *ddr_ctrl;
-};
-
-struct brcmstb_pm_control {
-       void __iomem *aon_ctrl_base;
-       void __iomem *aon_sram;
-       struct brcmstb_memc memcs[MAX_NUM_MEMC];
-
-       void __iomem *boot_sram;
-       size_t boot_sram_len;
-
-       bool support_warm_boot;
-       size_t pll_status_offset;
-       int num_memc;
-
-       struct brcmstb_s3_params *s3_params;
-       dma_addr_t s3_params_pa;
-       int s3entry_method;
-       u32 warm_boot_offset;
-       u32 phy_a_standby_ctrl_offs;
-       u32 phy_b_standby_ctrl_offs;
-       bool needs_ddr_pad;
-       struct platform_device *pdev;
-};
-
-enum bsp_initiate_command {
-       BSP_CLOCK_STOP          = 0x00,
-       BSP_GEN_RANDOM_KEY      = 0x4A,
-       BSP_RESTORE_RANDOM_KEY  = 0x55,
-       BSP_GEN_FIXED_KEY       = 0x63,
-};
-
-#define PM_INITIATE            0x01
-#define PM_INITIATE_SUCCESS    0x00
-#define PM_INITIATE_FAIL       0xfe
-
-static struct brcmstb_pm_control ctrl;
-
-noinline int brcmstb_pm_s3_finish(void);
-
-static int (*brcmstb_pm_do_s2_sram)(void __iomem *aon_ctrl_base,
-               void __iomem *ddr_phy_pll_status);
-
-static int brcmstb_init_sram(struct device_node *dn)
-{
-       void __iomem *sram;
-       struct resource res;
-       int ret;
-
-       ret = of_address_to_resource(dn, 0, &res);
-       if (ret)
-               return ret;
-
-       /* Uncached, executable remapping of SRAM */
-       sram = __arm_ioremap_exec(res.start, resource_size(&res), false);
-       if (!sram)
-               return -ENOMEM;
-
-       ctrl.boot_sram = sram;
-       ctrl.boot_sram_len = resource_size(&res);
-
-       return 0;
-}
-
-static const struct of_device_id sram_dt_ids[] = {
-       { .compatible = "mmio-sram" },
-       { /* sentinel */ }
-};
-
-static int do_bsp_initiate_command(enum bsp_initiate_command cmd)
-{
-       void __iomem *base = ctrl.aon_ctrl_base;
-       int ret;
-       int timeo = 1000 * 1000; /* 1 second */
-
-       writel_relaxed(0, base + AON_CTRL_PM_INITIATE);
-       (void)readl_relaxed(base + AON_CTRL_PM_INITIATE);
-
-       /* Go! */
-       writel_relaxed((cmd << 1) | PM_INITIATE, base + AON_CTRL_PM_INITIATE);
-
-       /*
-        * If firmware doesn't support the 'ack', then just assume it's done
-        * after 10ms. Note that this only works for command 0, BSP_CLOCK_STOP
-        */
-       if (of_machine_is_compatible("brcm,bcm74371a0")) {
-               (void)readl_relaxed(base + AON_CTRL_PM_INITIATE);
-               mdelay(10);
-               return 0;
-       }
-
-       for (;;) {
-               ret = readl_relaxed(base + AON_CTRL_PM_INITIATE);
-               if (!(ret & PM_INITIATE))
-                       break;
-               if (timeo <= 0) {
-                       pr_err("error: timeout waiting for BSP (%x)\n", ret);
-                       break;
-               }
-               timeo -= 50;
-               udelay(50);
-       }
-
-       return (ret & 0xff) != PM_INITIATE_SUCCESS;
-}
-
-static int brcmstb_pm_handshake(void)
-{
-       void __iomem *base = ctrl.aon_ctrl_base;
-       u32 tmp;
-       int ret;
-
-       /* BSP power handshake, v1 */
-       tmp = readl_relaxed(base + AON_CTRL_HOST_MISC_CMDS);
-       tmp &= ~1UL;
-       writel_relaxed(tmp, base + AON_CTRL_HOST_MISC_CMDS);
-       (void)readl_relaxed(base + AON_CTRL_HOST_MISC_CMDS);
-
-       ret = do_bsp_initiate_command(BSP_CLOCK_STOP);
-       if (ret)
-               pr_err("BSP handshake failed\n");
-
-       /*
-        * HACK: BSP may have internal race on the CLOCK_STOP command.
-        * Avoid touching the BSP for a few milliseconds.
-        */
-       mdelay(3);
-
-       return ret;
-}
-
-static inline void shimphy_set(u32 value, u32 mask)
-{
-       int i;
-
-       if (!ctrl.needs_ddr_pad)
-               return;
-
-       for (i = 0; i < ctrl.num_memc; i++) {
-               u32 tmp;
-
-               tmp = readl_relaxed(ctrl.memcs[i].ddr_shimphy_base +
-                       SHIMPHY_DDR_PAD_CNTRL);
-               tmp = value | (tmp & mask);
-               writel_relaxed(tmp, ctrl.memcs[i].ddr_shimphy_base +
-                       SHIMPHY_DDR_PAD_CNTRL);
-       }
-       wmb(); /* Complete sequence in order. */
-}
-
-static inline void ddr_ctrl_set(bool warmboot)
-{
-       int i;
-
-       for (i = 0; i < ctrl.num_memc; i++) {
-               u32 tmp;
-
-               tmp = readl_relaxed(ctrl.memcs[i].ddr_ctrl +
-                               ctrl.warm_boot_offset);
-               if (warmboot)
-                       tmp |= 1;
-               else
-                       tmp &= ~1; /* Cold boot */
-               writel_relaxed(tmp, ctrl.memcs[i].ddr_ctrl +
-                               ctrl.warm_boot_offset);
-       }
-       /* Complete sequence in order */
-       wmb();
-}
-
-static inline void s3entry_method0(void)
-{
-       shimphy_set(SHIMPHY_PAD_GATE_PLL_S3 | SHIMPHY_PAD_PLL_SEQUENCE,
-                   0xffffffff);
-}
-
-static inline void s3entry_method1(void)
-{
-       /*
-        * S3 Entry Sequence
-        * -----------------
-        * Step 1: SHIMPHY_ADDR_CNTL_0_DDR_PAD_CNTRL [ S3_PWRDWN_SEQ ] = 3
-        * Step 2: MEMC_DDR_0_WARM_BOOT [ WARM_BOOT ] = 1
-        */
-       shimphy_set((PWRDWN_SEQ_POWERDOWN_PLL <<
-                   SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
-                   ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
-
-       ddr_ctrl_set(true);
-}
-
-static inline void s5entry_method1(void)
-{
-       int i;
-
-       /*
-        * S5 Entry Sequence
-        * -----------------
-        * Step 1: SHIMPHY_ADDR_CNTL_0_DDR_PAD_CNTRL [ S3_PWRDWN_SEQ ] = 3
-        * Step 2: MEMC_DDR_0_WARM_BOOT [ WARM_BOOT ] = 0
-        * Step 3: DDR_PHY_CONTROL_REGS_[AB]_0_STANDBY_CONTROL[ CKE ] = 0
-        *         DDR_PHY_CONTROL_REGS_[AB]_0_STANDBY_CONTROL[ RST_N ] = 0
-        */
-       shimphy_set((PWRDWN_SEQ_POWERDOWN_PLL <<
-                   SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
-                   ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
-
-       ddr_ctrl_set(false);
-
-       for (i = 0; i < ctrl.num_memc; i++) {
-               u32 tmp;
-
-               /* Step 3: Channel A (RST_N = CKE = 0) */
-               tmp = readl_relaxed(ctrl.memcs[i].ddr_phy_base +
-                                 ctrl.phy_a_standby_ctrl_offs);
-               tmp &= ~(DDR_PHY_RST_N | DDR_PHY_RST_N);
-               writel_relaxed(tmp, ctrl.memcs[i].ddr_phy_base +
-                            ctrl.phy_a_standby_ctrl_offs);
-
-               /* Step 3: Channel B? */
-               if (ctrl.phy_b_standby_ctrl_offs != DDR_PHY_NO_CHANNEL) {
-                       tmp = readl_relaxed(ctrl.memcs[i].ddr_phy_base +
-                                         ctrl.phy_b_standby_ctrl_offs);
-                       tmp &= ~(DDR_PHY_RST_N | DDR_PHY_RST_N);
-                       writel_relaxed(tmp, ctrl.memcs[i].ddr_phy_base +
-                                    ctrl.phy_b_standby_ctrl_offs);
-               }
-       }
-       /* Must complete */
-       wmb();
-}
-
-/*
- * Run a Power Management State Machine (PMSM) shutdown command and put the CPU
- * into a low-power mode
- */
-static void brcmstb_do_pmsm_power_down(unsigned long base_cmd, bool onewrite)
-{
-       void __iomem *base = ctrl.aon_ctrl_base;
-
-       if ((ctrl.s3entry_method == 1) && (base_cmd == PM_COLD_CONFIG))
-               s5entry_method1();
-
-       /* pm_start_pwrdn transition 0->1 */
-       writel_relaxed(base_cmd, base + AON_CTRL_PM_CTRL);
-
-       if (!onewrite) {
-               (void)readl_relaxed(base + AON_CTRL_PM_CTRL);
-
-               writel_relaxed(base_cmd | PM_PWR_DOWN, base + AON_CTRL_PM_CTRL);
-               (void)readl_relaxed(base + AON_CTRL_PM_CTRL);
-       }
-       wfi();
-}
-
-/* Support S5 cold boot out of "poweroff" */
-static void brcmstb_pm_poweroff(void)
-{
-       brcmstb_pm_handshake();
-
-       /* Clear magic S3 warm-boot value */
-       writel_relaxed(0, ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
-       (void)readl_relaxed(ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
-
-       /* Skip wait-for-interrupt signal; just use a countdown */
-       writel_relaxed(0x10, ctrl.aon_ctrl_base + AON_CTRL_PM_CPU_WAIT_COUNT);
-       (void)readl_relaxed(ctrl.aon_ctrl_base + AON_CTRL_PM_CPU_WAIT_COUNT);
-
-       if (ctrl.s3entry_method == 1) {
-               shimphy_set((PWRDWN_SEQ_POWERDOWN_PLL <<
-                            SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
-                            ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
-               ddr_ctrl_set(false);
-               brcmstb_do_pmsm_power_down(M1_PM_COLD_CONFIG, true);
-               return; /* We should never actually get here */
-       }
-
-       brcmstb_do_pmsm_power_down(PM_COLD_CONFIG, false);
-}
-
-static void *brcmstb_pm_copy_to_sram(void *fn, size_t len)
-{
-       unsigned int size = ALIGN(len, FNCPY_ALIGN);
-
-       if (ctrl.boot_sram_len < size) {
-               pr_err("standby code will not fit in SRAM\n");
-               return NULL;
-       }
-
-       return fncpy(ctrl.boot_sram, fn, size);
-}
-
-/*
- * S2 suspend/resume picks up where we left off, so we must execute carefully
- * from SRAM, in order to allow DDR to come back up safely before we continue.
- */
-static int brcmstb_pm_s2(void)
-{
-       /* A previous S3 can set a value hazardous to S2, so make sure. */
-       if (ctrl.s3entry_method == 1) {
-               shimphy_set((PWRDWN_SEQ_NO_SEQUENCING <<
-                           SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
-                           ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
-               ddr_ctrl_set(false);
-       }
-
-       brcmstb_pm_do_s2_sram = brcmstb_pm_copy_to_sram(&brcmstb_pm_do_s2,
-                       brcmstb_pm_do_s2_sz);
-       if (!brcmstb_pm_do_s2_sram)
-               return -EINVAL;
-
-       return brcmstb_pm_do_s2_sram(ctrl.aon_ctrl_base,
-                       ctrl.memcs[0].ddr_phy_base +
-                       ctrl.pll_status_offset);
-}
-
-/*
- * This function is called on a new stack, so don't allow inlining (which will
- * generate stack references on the old stack). It cannot be made static because
- * it is referenced from brcmstb_pm_s3()
- */
-noinline int brcmstb_pm_s3_finish(void)
-{
-       struct brcmstb_s3_params *params = ctrl.s3_params;
-       dma_addr_t params_pa = ctrl.s3_params_pa;
-       phys_addr_t reentry = virt_to_phys(&cpu_resume_arm);
-       enum bsp_initiate_command cmd;
-       u32 flags;
-
-       /*
-        * Clear parameter structure, but not DTU area, which has already been
-        * filled in. We know DTU is a the end, so we can just subtract its
-        * size.
-        */
-       memset(params, 0, sizeof(*params) - sizeof(params->dtu));
-
-       flags = readl_relaxed(ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
-
-       flags &= S3_BOOTLOADER_RESERVED;
-       flags |= S3_FLAG_NO_MEM_VERIFY;
-       flags |= S3_FLAG_LOAD_RANDKEY;
-
-       /* Load random / fixed key */
-       if (flags & S3_FLAG_LOAD_RANDKEY)
-               cmd = BSP_GEN_RANDOM_KEY;
-       else
-               cmd = BSP_GEN_FIXED_KEY;
-       if (do_bsp_initiate_command(cmd)) {
-               pr_info("key loading failed\n");
-               return -EIO;
-       }
-
-       params->magic = BRCMSTB_S3_MAGIC;
-       params->reentry = reentry;
-
-       /* No more writes to DRAM */
-       flush_cache_all();
-
-       flags |= BRCMSTB_S3_MAGIC_SHORT;
-
-       writel_relaxed(flags, ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
-       writel_relaxed(lower_32_bits(params_pa),
-                      ctrl.aon_sram + AON_REG_CONTROL_LOW);
-       writel_relaxed(upper_32_bits(params_pa),
-                      ctrl.aon_sram + AON_REG_CONTROL_HIGH);
-
-       switch (ctrl.s3entry_method) {
-       case 0:
-               s3entry_method0();
-               brcmstb_do_pmsm_power_down(PM_WARM_CONFIG, false);
-               break;
-       case 1:
-               s3entry_method1();
-               brcmstb_do_pmsm_power_down(M1_PM_WARM_CONFIG, true);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* Must have been interrupted from wfi()? */
-       return -EINTR;
-}
-
-static int brcmstb_pm_do_s3(unsigned long sp)
-{
-       unsigned long save_sp;
-       int ret;
-
-       asm volatile (
-               "mov    %[save], sp\n"
-               "mov    sp, %[new]\n"
-               "bl     brcmstb_pm_s3_finish\n"
-               "mov    %[ret], r0\n"
-               "mov    %[new], sp\n"
-               "mov    sp, %[save]\n"
-               : [save] "=&r" (save_sp), [ret] "=&r" (ret)
-               : [new] "r" (sp)
-       );
-
-       return ret;
-}
-
-static int brcmstb_pm_s3(void)
-{
-       void __iomem *sp = ctrl.boot_sram + ctrl.boot_sram_len;
-
-       return cpu_suspend((unsigned long)sp, brcmstb_pm_do_s3);
-}
-
-static int brcmstb_pm_standby(bool deep_standby)
-{
-       int ret;
-
-       if (brcmstb_pm_handshake())
-               return -EIO;
-
-       if (deep_standby)
-               ret = brcmstb_pm_s3();
-       else
-               ret = brcmstb_pm_s2();
-       if (ret)
-               pr_err("%s: standby failed\n", __func__);
-
-       return ret;
-}
-
-static int brcmstb_pm_enter(suspend_state_t state)
-{
-       int ret = -EINVAL;
-
-       switch (state) {
-       case PM_SUSPEND_STANDBY:
-               ret = brcmstb_pm_standby(false);
-               break;
-       case PM_SUSPEND_MEM:
-               ret = brcmstb_pm_standby(true);
-               break;
-       }
-
-       return ret;
-}
-
-static int brcmstb_pm_valid(suspend_state_t state)
-{
-       switch (state) {
-       case PM_SUSPEND_STANDBY:
-               return true;
-       case PM_SUSPEND_MEM:
-               return ctrl.support_warm_boot;
-       default:
-               return false;
-       }
-}
-
-static const struct platform_suspend_ops brcmstb_pm_ops = {
-       .enter          = brcmstb_pm_enter,
-       .valid          = brcmstb_pm_valid,
-};
-
-static const struct of_device_id aon_ctrl_dt_ids[] = {
-       { .compatible = "brcm,brcmstb-aon-ctrl" },
-       {}
-};
-
-struct ddr_phy_ofdata {
-       bool supports_warm_boot;
-       size_t pll_status_offset;
-       int s3entry_method;
-       u32 warm_boot_offset;
-       u32 phy_a_standby_ctrl_offs;
-       u32 phy_b_standby_ctrl_offs;
-};
-
-static struct ddr_phy_ofdata ddr_phy_71_1 = {
-       .supports_warm_boot = true,
-       .pll_status_offset = 0x0c,
-       .s3entry_method = 1,
-       .warm_boot_offset = 0x2c,
-       .phy_a_standby_ctrl_offs = 0x198,
-       .phy_b_standby_ctrl_offs = DDR_PHY_NO_CHANNEL
-};
-
-static struct ddr_phy_ofdata ddr_phy_72_0 = {
-       .supports_warm_boot = true,
-       .pll_status_offset = 0x10,
-       .s3entry_method = 1,
-       .warm_boot_offset = 0x40,
-       .phy_a_standby_ctrl_offs = 0x2a4,
-       .phy_b_standby_ctrl_offs = 0x8a4
-};
-
-static struct ddr_phy_ofdata ddr_phy_225_1 = {
-       .supports_warm_boot = false,
-       .pll_status_offset = 0x4,
-       .s3entry_method = 0
-};
-
-static struct ddr_phy_ofdata ddr_phy_240_1 = {
-       .supports_warm_boot = true,
-       .pll_status_offset = 0x4,
-       .s3entry_method = 0
-};
-
-static const struct of_device_id ddr_phy_dt_ids[] = {
-       {
-               .compatible = "brcm,brcmstb-ddr-phy-v71.1",
-               .data = &ddr_phy_71_1,
-       },
-       {
-               .compatible = "brcm,brcmstb-ddr-phy-v72.0",
-               .data = &ddr_phy_72_0,
-       },
-       {
-               .compatible = "brcm,brcmstb-ddr-phy-v225.1",
-               .data = &ddr_phy_225_1,
-       },
-       {
-               .compatible = "brcm,brcmstb-ddr-phy-v240.1",
-               .data = &ddr_phy_240_1,
-       },
-       {
-               /* Same as v240.1, for the registers we care about */
-               .compatible = "brcm,brcmstb-ddr-phy-v240.2",
-               .data = &ddr_phy_240_1,
-       },
-       {}
-};
-
-struct ddr_seq_ofdata {
-       bool needs_ddr_pad;
-       u32 warm_boot_offset;
-};
-
-static const struct ddr_seq_ofdata ddr_seq_b22 = {
-       .needs_ddr_pad = false,
-       .warm_boot_offset = 0x2c,
-};
-
-static const struct ddr_seq_ofdata ddr_seq = {
-       .needs_ddr_pad = true,
-};
-
-static const struct of_device_id ddr_shimphy_dt_ids[] = {
-       { .compatible = "brcm,brcmstb-ddr-shimphy-v1.0" },
-       {}
-};
-
-static const struct of_device_id brcmstb_memc_of_match[] = {
-       {
-               .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.1",
-               .data = &ddr_seq,
-       },
-       {
-               .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.2",
-               .data = &ddr_seq_b22,
-       },
-       {
-               .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.3",
-               .data = &ddr_seq_b22,
-       },
-       {
-               .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.0",
-               .data = &ddr_seq_b22,
-       },
-       {
-               .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.1",
-               .data = &ddr_seq_b22,
-       },
-       {
-               .compatible = "brcm,brcmstb-memc-ddr",
-               .data = &ddr_seq,
-       },
-       {},
-};
-
-static void __iomem *brcmstb_ioremap_match(const struct of_device_id *matches,
-                                          int index, const void **ofdata)
-{
-       struct device_node *dn;
-       const struct of_device_id *match;
-
-       dn = of_find_matching_node_and_match(NULL, matches, &match);
-       if (!dn)
-               return ERR_PTR(-EINVAL);
-
-       if (ofdata)
-               *ofdata = match->data;
-
-       return of_io_request_and_map(dn, index, dn->full_name);
-}
-/*
- * The AON is a small domain in the SoC that can retain its state across
- * various system wide sleep states and specific reset conditions; the
- * AON DATA RAM is a small RAM of a few words (< 1KB) which can store
- * persistent information across such events.
- *
- * The purpose of the below panic notifier is to help with notifying
- * the bootloader that a panic occurred and so that it should try its
- * best to preserve the DRAM contents holding that buffer for recovery
- * by the kernel as opposed to wiping out DRAM clean again.
- *
- * Reference: comment from Florian Fainelli, at
- * https://lore.kernel.org/lkml/781cafb0-8d06-8b56-907a-5175c2da196a@gmail.com
- */
-static int brcmstb_pm_panic_notify(struct notifier_block *nb,
-               unsigned long action, void *data)
-{
-       writel_relaxed(BRCMSTB_PANIC_MAGIC, ctrl.aon_sram + AON_REG_PANIC);
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block brcmstb_pm_panic_nb = {
-       .notifier_call = brcmstb_pm_panic_notify,
-};
-
-static int brcmstb_pm_probe(struct platform_device *pdev)
-{
-       const struct ddr_phy_ofdata *ddr_phy_data;
-       const struct ddr_seq_ofdata *ddr_seq_data;
-       const struct of_device_id *of_id = NULL;
-       struct device_node *dn;
-       void __iomem *base;
-       int ret, i, s;
-
-       /* AON ctrl registers */
-       base = brcmstb_ioremap_match(aon_ctrl_dt_ids, 0, NULL);
-       if (IS_ERR(base)) {
-               pr_err("error mapping AON_CTRL\n");
-               ret = PTR_ERR(base);
-               goto aon_err;
-       }
-       ctrl.aon_ctrl_base = base;
-
-       /* AON SRAM registers */
-       base = brcmstb_ioremap_match(aon_ctrl_dt_ids, 1, NULL);
-       if (IS_ERR(base)) {
-               /* Assume standard offset */
-               ctrl.aon_sram = ctrl.aon_ctrl_base +
-                                    AON_CTRL_SYSTEM_DATA_RAM_OFS;
-               s = 0;
-       } else {
-               ctrl.aon_sram = base;
-               s = 1;
-       }
-
-       writel_relaxed(0, ctrl.aon_sram + AON_REG_PANIC);
-
-       /* DDR PHY registers */
-       base = brcmstb_ioremap_match(ddr_phy_dt_ids, 0,
-                                    (const void **)&ddr_phy_data);
-       if (IS_ERR(base)) {
-               pr_err("error mapping DDR PHY\n");
-               ret = PTR_ERR(base);
-               goto ddr_phy_err;
-       }
-       ctrl.support_warm_boot = ddr_phy_data->supports_warm_boot;
-       ctrl.pll_status_offset = ddr_phy_data->pll_status_offset;
-       /* Only need DDR PHY 0 for now? */
-       ctrl.memcs[0].ddr_phy_base = base;
-       ctrl.s3entry_method = ddr_phy_data->s3entry_method;
-       ctrl.phy_a_standby_ctrl_offs = ddr_phy_data->phy_a_standby_ctrl_offs;
-       ctrl.phy_b_standby_ctrl_offs = ddr_phy_data->phy_b_standby_ctrl_offs;
-       /*
-        * Slightly gross to use the phy ver to get a memc,
-        * offset but that is the only versioned things so far
-        * we can test for.
-        */
-       ctrl.warm_boot_offset = ddr_phy_data->warm_boot_offset;
-
-       /* DDR SHIM-PHY registers */
-       for_each_matching_node(dn, ddr_shimphy_dt_ids) {
-               i = ctrl.num_memc;
-               if (i >= MAX_NUM_MEMC) {
-                       of_node_put(dn);
-                       pr_warn("too many MEMCs (max %d)\n", MAX_NUM_MEMC);
-                       break;
-               }
-
-               base = of_io_request_and_map(dn, 0, dn->full_name);
-               if (IS_ERR(base)) {
-                       of_node_put(dn);
-                       if (!ctrl.support_warm_boot)
-                               break;
-
-                       pr_err("error mapping DDR SHIMPHY %d\n", i);
-                       ret = PTR_ERR(base);
-                       goto ddr_shimphy_err;
-               }
-               ctrl.memcs[i].ddr_shimphy_base = base;
-               ctrl.num_memc++;
-       }
-
-       /* Sequencer DRAM Param and Control Registers */
-       i = 0;
-       for_each_matching_node(dn, brcmstb_memc_of_match) {
-               base = of_iomap(dn, 0);
-               if (!base) {
-                       of_node_put(dn);
-                       pr_err("error mapping DDR Sequencer %d\n", i);
-                       ret = -ENOMEM;
-                       goto brcmstb_memc_err;
-               }
-
-               of_id = of_match_node(brcmstb_memc_of_match, dn);
-               if (!of_id) {
-                       iounmap(base);
-                       of_node_put(dn);
-                       ret = -EINVAL;
-                       goto brcmstb_memc_err;
-               }
-
-               ddr_seq_data = of_id->data;
-               ctrl.needs_ddr_pad = ddr_seq_data->needs_ddr_pad;
-               /* Adjust warm boot offset based on the DDR sequencer */
-               if (ddr_seq_data->warm_boot_offset)
-                       ctrl.warm_boot_offset = ddr_seq_data->warm_boot_offset;
-
-               ctrl.memcs[i].ddr_ctrl = base;
-               i++;
-       }
-
-       pr_debug("PM: supports warm boot:%d, method:%d, wboffs:%x\n",
-               ctrl.support_warm_boot, ctrl.s3entry_method,
-               ctrl.warm_boot_offset);
-
-       dn = of_find_matching_node(NULL, sram_dt_ids);
-       if (!dn) {
-               pr_err("SRAM not found\n");
-               ret = -EINVAL;
-               goto brcmstb_memc_err;
-       }
-
-       ret = brcmstb_init_sram(dn);
-       of_node_put(dn);
-       if (ret) {
-               pr_err("error setting up SRAM for PM\n");
-               goto brcmstb_memc_err;
-       }
-
-       ctrl.pdev = pdev;
-
-       ctrl.s3_params = kmalloc(sizeof(*ctrl.s3_params), GFP_KERNEL);
-       if (!ctrl.s3_params) {
-               ret = -ENOMEM;
-               goto s3_params_err;
-       }
-       ctrl.s3_params_pa = dma_map_single(&pdev->dev, ctrl.s3_params,
-                                          sizeof(*ctrl.s3_params),
-                                          DMA_TO_DEVICE);
-       if (dma_mapping_error(&pdev->dev, ctrl.s3_params_pa)) {
-               pr_err("error mapping DMA memory\n");
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       atomic_notifier_chain_register(&panic_notifier_list,
-                                      &brcmstb_pm_panic_nb);
-
-       pm_power_off = brcmstb_pm_poweroff;
-       suspend_set_ops(&brcmstb_pm_ops);
-
-       return 0;
-
-out:
-       kfree(ctrl.s3_params);
-s3_params_err:
-       iounmap(ctrl.boot_sram);
-brcmstb_memc_err:
-       for (i--; i >= 0; i--)
-               iounmap(ctrl.memcs[i].ddr_ctrl);
-ddr_shimphy_err:
-       for (i = 0; i < ctrl.num_memc; i++)
-               iounmap(ctrl.memcs[i].ddr_shimphy_base);
-
-       iounmap(ctrl.memcs[0].ddr_phy_base);
-ddr_phy_err:
-       iounmap(ctrl.aon_ctrl_base);
-       if (s)
-               iounmap(ctrl.aon_sram);
-aon_err:
-       pr_warn("PM: initialization failed with code %d\n", ret);
-
-       return ret;
-}
-
-static struct platform_driver brcmstb_pm_driver = {
-       .driver = {
-               .name   = "brcmstb-pm",
-               .of_match_table = aon_ctrl_dt_ids,
-       },
-};
-
-static int __init brcmstb_pm_init(void)
-{
-       return platform_driver_probe(&brcmstb_pm_driver,
-                                    brcmstb_pm_probe);
-}
-module_init(brcmstb_pm_init);
diff --git a/drivers/soc/bcm/brcmstb/pm/s2-arm.S b/drivers/soc/bcm/brcmstb/pm/s2-arm.S
deleted file mode 100644 (file)
index 0d69379..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright Â© 2014-2017 Broadcom
- */
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
-#include "pm.h"
-
-       .arch armv7-a
-       .text
-       .align  3
-
-#define AON_CTRL_REG           r10
-#define DDR_PHY_STATUS_REG     r11
-
-/*
- * r0: AON_CTRL base address
- * r1: DDRY PHY PLL status register address
- */
-ENTRY(brcmstb_pm_do_s2)
-       stmfd   sp!, {r4-r11, lr}
-       mov     AON_CTRL_REG, r0
-       mov     DDR_PHY_STATUS_REG, r1
-
-       /* Flush memory transactions */
-       dsb
-
-       /* Cache DDR_PHY_STATUS_REG translation */
-       ldr     r0, [DDR_PHY_STATUS_REG]
-
-       /* power down request */
-       ldr     r0, =PM_S2_COMMAND
-       ldr     r1, =0
-       str     r1, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-       ldr     r1, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-       str     r0, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-       ldr     r0, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-
-       /* Wait for interrupt */
-       wfi
-       nop
-
-       /* Bring MEMC back up */
-1:     ldr     r0, [DDR_PHY_STATUS_REG]
-       ands    r0, #1
-       beq     1b
-
-       /* Power-up handshake */
-       ldr     r0, =1
-       str     r0, [AON_CTRL_REG, #AON_CTRL_HOST_MISC_CMDS]
-       ldr     r0, [AON_CTRL_REG, #AON_CTRL_HOST_MISC_CMDS]
-
-       ldr     r0, =0
-       str     r0, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-       ldr     r0, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-
-       /* Return to caller */
-       ldr     r0, =0
-       ldmfd   sp!, {r4-r11, pc}
-
-       ENDPROC(brcmstb_pm_do_s2)
-
-       /* Place literal pool here */
-       .ltorg
-
-ENTRY(brcmstb_pm_do_s2_sz)
-       .word   . - brcmstb_pm_do_s2
index 068715d6e66d7e0bed4a2d099cc6385574e84bc7..58175af982a0dc836c07a1fc229508095967c90b 100644 (file)
@@ -243,4 +243,3 @@ builtin_platform_driver(rpi_power_driver);
 MODULE_AUTHOR("Alexander Aring <aar@pengutronix.de>");
 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
 MODULE_DESCRIPTION("Raspberry Pi power domain driver");
-MODULE_LICENSE("GPL v2");
index 2527cf5757ec9693d0a698d0c32a5fca71466a08..43ced2bf844479f70cfdc3a1f1473e2e46ff4351 100644 (file)
@@ -3,8 +3,9 @@
 config SOC_K210_SYSCTL
        bool "Canaan Kendryte K210 SoC system controller"
        depends on RISCV && SOC_CANAAN && OF
+       depends on COMMON_CLK_K210
        default SOC_CANAAN
-        select PM
-        select MFD_SYSCON
+       select PM
+       select MFD_SYSCON
        help
          Canaan Kendryte K210 SoC system controller driver.
index a8742fc58f018a541a34b8aadd6c3688f8820fed..76a4593baf0a2ecad591822de2da77819fb6afa7 100644 (file)
@@ -10,7 +10,7 @@ config IMX_GPCV2_PM_DOMAINS
        default y if SOC_IMX7D
 
 config SOC_IMX8M
-       bool "i.MX8M SoC family support"
+       tristate "i.MX8M SoC family support"
        depends on ARCH_MXC || COMPILE_TEST
        default ARCH_MXC && ARM64
        select SOC_BUS
index 399cb85105a181a934b74582e6a1c840724ec4ca..afbca0d48c14acc092849f332b4c26ca24fbb2e1 100644 (file)
@@ -38,10 +38,10 @@ struct imx8m_blk_ctrl {
 struct imx8m_blk_ctrl_domain_data {
        const char *name;
        const char * const *clk_names;
-       int num_clks;
        const char * const *path_names;
-       int num_paths;
        const char *gpc_name;
+       int num_clks;
+       int num_paths;
        u32 rst_mask;
        u32 clk_mask;
 
@@ -210,7 +210,7 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
        if (!bc->onecell_data.domains)
                return -ENOMEM;
 
-       bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus");
+       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
        if (IS_ERR(bc->bus_power_dev)) {
                if (PTR_ERR(bc->bus_power_dev) == -ENODEV)
                        return dev_err_probe(dev, -EPROBE_DEFER,
@@ -310,6 +310,10 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
 
        dev_set_drvdata(dev, bc);
 
+       ret = devm_of_platform_populate(dev);
+       if (ret)
+               goto cleanup_provider;
+
        return 0;
 
 cleanup_provider:
@@ -891,3 +895,4 @@ static struct platform_driver imx8m_blk_ctrl_driver = {
        },
 };
 module_platform_driver(imx8m_blk_ctrl_driver);
+MODULE_LICENSE("GPL");
index a0592db8fa8646c441ffc644bdbef703b17552fa..870aecc0202aebd88c9af6d62a4cb94aa8f57401 100644 (file)
@@ -642,7 +642,7 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
        if (!bc->onecell_data.domains)
                return -ENOMEM;
 
-       bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus");
+       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
        if (IS_ERR(bc->bus_power_dev))
                return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
                                     "failed to attach bus power domain\n");
@@ -852,7 +852,7 @@ static const struct of_device_id imx8mp_blk_ctrl_of_match[] = {
                /* Sentinel */
        }
 };
-MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
+MODULE_DEVICE_TABLE(of, imx8mp_blk_ctrl_of_match);
 
 static struct platform_driver imx8mp_blk_ctrl_driver = {
        .probe = imx8mp_blk_ctrl_probe,
@@ -864,3 +864,4 @@ static struct platform_driver imx8mp_blk_ctrl_driver = {
        },
 };
 module_platform_driver(imx8mp_blk_ctrl_driver);
+MODULE_LICENSE("GPL");
index 32ed9dc88e45563e346bbfdfda8b22d34b9c2139..1dcd243df5677aa39dcbc76b876cdbbd435ceb43 100644 (file)
@@ -242,3 +242,4 @@ free_soc:
        return ret;
 }
 device_initcall(imx8_soc_init);
+MODULE_LICENSE("GPL");
index d6b83a5508cab78018fe6961f32da315fc9c60dd..a88cf04fc803d54da72250cdff501c75e5f82eda 100644 (file)
@@ -76,6 +76,7 @@ config MTK_MMSYS
        tristate "MediaTek MMSYS Support"
        default ARCH_MEDIATEK
        depends on HAS_IOMEM
+       depends on MTK_CMDQ || MTK_CMDQ=n
        help
          Say yes here to add support for the MediaTek Multimedia
          Subsystem (MMSYS).
diff --git a/drivers/soc/mediatek/mt8173-mmsys.h b/drivers/soc/mediatek/mt8173-mmsys.h
new file mode 100644 (file)
index 0000000..9d24e38
--- /dev/null
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8173_MMSYS_H
+#define __SOC_MEDIATEK_MT8173_MMSYS_H
+
+#define MT8173_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN       0x040
+#define MT8173_DISP_REG_CONFIG_DISP_OVL1_MOUT_EN       0x044
+#define MT8173_DISP_REG_CONFIG_DISP_OD_MOUT_EN         0x048
+#define MT8173_DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN      0x04c
+#define MT8173_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN       0x050
+#define MT8173_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN      0x084
+#define MT8173_DISP_REG_CONFIG_DISP_COLOR1_SEL_IN      0x088
+#define MT8173_DISP_REG_CONFIG_DISP_AAL_SEL_IN         0x08c
+#define MT8173_DISP_REG_CONFIG_DISP_UFOE_SEL_IN                0x0a0
+#define MT8173_DISP_REG_CONFIG_DSI0_SEL_IN             0x0a4
+#define MT8173_DISP_REG_CONFIG_DPI_SEL_IN              0x0ac
+#define MT8173_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN  0x0b0
+#define MT8173_DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN      0x0c8
+#define MT8173_DISP_REG_CONFIG_DISP_COLOR0_SOUT_SEL_IN 0x0bc
+
+#define MT8173_AAL_SEL_IN_MERGE                                BIT(0)
+#define MT8173_COLOR0_SEL_IN_OVL0                      BIT(0)
+#define MT8173_COLOR0_SOUT_MERGE                       BIT(0)
+#define MT8173_DPI0_SEL_IN_MASK                                GENMASK(1, 0)
+#define MT8173_DPI0_SEL_IN_RDMA1                       BIT(0)
+#define MT8173_DSI0_SEL_IN_UFOE                                BIT(0)
+#define MT8173_GAMMA_MOUT_EN_RDMA1                     BIT(0)
+#define MT8173_OD0_MOUT_EN_RDMA0                       BIT(0)
+#define MT8173_OVL0_MOUT_EN_COLOR0                     BIT(0)
+#define MT8173_OVL1_MOUT_EN_COLOR1                     BIT(0)
+#define MT8173_UFOE_MOUT_EN_DSI0                       BIT(0)
+#define MT8173_UFOE_SEL_IN_RDMA0                       BIT(0)
+#define MT8173_RDMA0_SOUT_COLOR0                       BIT(0)
+
+static const struct mtk_mmsys_routes mt8173_mmsys_routing_table[] = {
+       {
+               DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0,
+               MT8173_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN,
+               MT8173_OVL0_MOUT_EN_COLOR0, MT8173_OVL0_MOUT_EN_COLOR0
+       }, {
+               DDP_COMPONENT_OD0, DDP_COMPONENT_RDMA0,
+               MT8173_DISP_REG_CONFIG_DISP_OD_MOUT_EN,
+               MT8173_OD0_MOUT_EN_RDMA0, MT8173_OD0_MOUT_EN_RDMA0
+       }, {
+               DDP_COMPONENT_UFOE, DDP_COMPONENT_DSI0,
+               MT8173_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN,
+               MT8173_UFOE_MOUT_EN_DSI0, MT8173_UFOE_MOUT_EN_DSI0
+       }, {
+               DDP_COMPONENT_COLOR0, DDP_COMPONENT_AAL0,
+               MT8173_DISP_REG_CONFIG_DISP_COLOR0_SOUT_SEL_IN,
+               MT8173_COLOR0_SOUT_MERGE, 0 /* SOUT to AAL */
+       }, {
+               DDP_COMPONENT_RDMA0, DDP_COMPONENT_UFOE,
+               MT8173_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN,
+               MT8173_RDMA0_SOUT_COLOR0, 0 /* SOUT to UFOE */
+       }, {
+               DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0,
+               MT8173_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN,
+               MT8173_COLOR0_SEL_IN_OVL0, MT8173_COLOR0_SEL_IN_OVL0
+       }, {
+               DDP_COMPONENT_AAL0, DDP_COMPONENT_COLOR0,
+               MT8173_DISP_REG_CONFIG_DISP_AAL_SEL_IN,
+               MT8173_AAL_SEL_IN_MERGE, 0 /* SEL_IN from COLOR0 */
+       }, {
+               DDP_COMPONENT_RDMA0, DDP_COMPONENT_UFOE,
+               MT8173_DISP_REG_CONFIG_DISP_UFOE_SEL_IN,
+               MT8173_UFOE_SEL_IN_RDMA0, 0 /* SEL_IN from RDMA0 */
+       }, {
+               DDP_COMPONENT_UFOE, DDP_COMPONENT_DSI0,
+               MT8173_DISP_REG_CONFIG_DSI0_SEL_IN,
+               MT8173_DSI0_SEL_IN_UFOE, 0, /* SEL_IN from UFOE */
+       }, {
+               DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1,
+               MT8173_DISP_REG_CONFIG_DISP_OVL1_MOUT_EN,
+               MT8173_OVL1_MOUT_EN_COLOR1, MT8173_OVL1_MOUT_EN_COLOR1
+       }, {
+               DDP_COMPONENT_GAMMA, DDP_COMPONENT_RDMA1,
+               MT8173_DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN,
+               MT8173_GAMMA_MOUT_EN_RDMA1, MT8173_GAMMA_MOUT_EN_RDMA1
+       }, {
+               DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
+               MT8173_DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN,
+               RDMA1_SOUT_MASK, RDMA1_SOUT_DPI0
+       }, {
+               DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1,
+               MT8173_DISP_REG_CONFIG_DISP_COLOR1_SEL_IN,
+               COLOR1_SEL_IN_OVL1, COLOR1_SEL_IN_OVL1
+       }, {
+               DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
+               MT8173_DISP_REG_CONFIG_DPI_SEL_IN,
+               MT8173_DPI0_SEL_IN_MASK, MT8173_DPI0_SEL_IN_RDMA1
+       }
+};
+
+#endif /* __SOC_MEDIATEK_MT8173_MMSYS_H */
index a6652ae63431a051fb0e842cc028bd0b013ecc51..9be2df2832a4797b8c78c4462a230021d8419a18 100644 (file)
 #define MT8195_VDO1_MIXER_SOUT_SEL_IN                          0xf68
 #define MT8195_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER                       0
 
+/* VPPSYS1 */
+#define MT8195_VPP1_HW_DCM_1ST_DIS0                            0x150
+#define MT8195_VPP1_HW_DCM_1ST_DIS1                            0x160
+#define MT8195_VPP1_HW_DCM_2ND_DIS0                            0x1a0
+#define MT8195_VPP1_HW_DCM_2ND_DIS1                            0x1b0
+#define MT8195_SVPP2_BUF_BF_RSZ_SWITCH                         0xf48
+#define MT8195_SVPP3_BUF_BF_RSZ_SWITCH                         0xf74
+
+/* VPPSYS1 HW DCM client*/
+#define MT8195_SVPP1_MDP_RSZ                                   BIT(25)
+#define MT8195_SVPP2_MDP_RSZ                                   BIT(4)
+#define MT8195_SVPP3_MDP_RSZ                                   BIT(5)
+
 static const struct mtk_mmsys_routes mmsys_mt8195_routing_table[] = {
        {
                DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
index eb4c7e57896cfb73dfe3b9146fe7f2a14636e28b..9619faa796e8fee95324ee9f0b79d435ce4ec432 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "mtk-mmsys.h"
 #include "mt8167-mmsys.h"
+#include "mt8173-mmsys.h"
 #include "mt8183-mmsys.h"
 #include "mt8186-mmsys.h"
 #include "mt8188-mmsys.h"
@@ -40,6 +41,14 @@ static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = {
        .clk_driver = "clk-mt6779-mm",
 };
 
+static const struct mtk_mmsys_driver_data mt6795_mmsys_driver_data = {
+       .clk_driver = "clk-mt6795-mm",
+       .routes = mt8173_mmsys_routing_table,
+       .num_routes = ARRAY_SIZE(mt8173_mmsys_routing_table),
+       .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B,
+       .num_resets = 64,
+};
+
 static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = {
        .clk_driver = "clk-mt6797-mm",
 };
@@ -52,10 +61,10 @@ static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = {
 
 static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
        .clk_driver = "clk-mt8173-mm",
-       .routes = mmsys_default_routing_table,
-       .num_routes = ARRAY_SIZE(mmsys_default_routing_table),
+       .routes = mt8173_mmsys_routing_table,
+       .num_routes = ARRAY_SIZE(mt8173_mmsys_routing_table),
        .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B,
-       .num_resets = 32,
+       .num_resets = 64,
 };
 
 static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
@@ -121,6 +130,8 @@ static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
 struct mtk_mmsys {
        void __iomem *regs;
        const struct mtk_mmsys_driver_data *data;
+       struct platform_device *clks_pdev;
+       struct platform_device *drm_pdev;
        spinlock_t lock; /* protects mmsys_sw_rst_b reg */
        struct reset_controller_dev rcdev;
        struct cmdq_client_reg cmdq_base;
@@ -129,21 +140,18 @@ struct mtk_mmsys {
 static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask, u32 val,
                                  struct cmdq_pkt *cmdq_pkt)
 {
+       int ret;
        u32 tmp;
 
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
-       if (cmdq_pkt) {
-               if (mmsys->cmdq_base.size == 0) {
-                       pr_err("mmsys lose gce property, failed to update mmsys bits with cmdq");
+       if (mmsys->cmdq_base.size && cmdq_pkt) {
+               ret = cmdq_pkt_write_mask(cmdq_pkt, mmsys->cmdq_base.subsys,
+                                         mmsys->cmdq_base.offset + offset, val,
+                                         mask);
+               if (ret)
+                       pr_debug("CMDQ unavailable: using CPU write\n");
+               else
                        return;
-               }
-               cmdq_pkt_write_mask(cmdq_pkt, mmsys->cmdq_base.subsys,
-                                   mmsys->cmdq_base.offset + offset, val,
-                                   mask);
-               return;
        }
-#endif
-
        tmp = readl_relaxed(mmsys->regs + offset);
        tmp = (tmp & ~mask) | (val & mask);
        writel_relaxed(tmp, mmsys->regs + offset);
@@ -242,6 +250,50 @@ void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val)
 }
 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_dpi_fmt_config);
 
+void mtk_mmsys_vpp_rsz_merge_config(struct device *dev, u32 id, bool enable,
+                                   struct cmdq_pkt *cmdq_pkt)
+{
+       u32 reg;
+
+       switch (id) {
+       case 2:
+               reg = MT8195_SVPP2_BUF_BF_RSZ_SWITCH;
+               break;
+       case 3:
+               reg = MT8195_SVPP3_BUF_BF_RSZ_SWITCH;
+               break;
+       default:
+               dev_err(dev, "Invalid id %d\n", id);
+               return;
+       }
+
+       mtk_mmsys_update_bits(dev_get_drvdata(dev), reg, ~0, enable, cmdq_pkt);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_vpp_rsz_merge_config);
+
+void mtk_mmsys_vpp_rsz_dcm_config(struct device *dev, bool enable,
+                                 struct cmdq_pkt *cmdq_pkt)
+{
+       u32 client;
+
+       client = MT8195_SVPP1_MDP_RSZ;
+       mtk_mmsys_update_bits(dev_get_drvdata(dev),
+                             MT8195_VPP1_HW_DCM_1ST_DIS0, client,
+                             ((enable) ? client : 0), cmdq_pkt);
+       mtk_mmsys_update_bits(dev_get_drvdata(dev),
+                             MT8195_VPP1_HW_DCM_2ND_DIS0, client,
+                             ((enable) ? client : 0), cmdq_pkt);
+
+       client = MT8195_SVPP2_MDP_RSZ | MT8195_SVPP3_MDP_RSZ;
+       mtk_mmsys_update_bits(dev_get_drvdata(dev),
+                             MT8195_VPP1_HW_DCM_1ST_DIS1, client,
+                             ((enable) ? client : 0), cmdq_pkt);
+       mtk_mmsys_update_bits(dev_get_drvdata(dev),
+                             MT8195_VPP1_HW_DCM_2ND_DIS1, client,
+                             ((enable) ? client : 0), cmdq_pkt);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_vpp_rsz_dcm_config);
+
 static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned long id,
                                  bool assert)
 {
@@ -330,11 +382,10 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
                }
        }
 
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+       /* CMDQ is optional */
        ret = cmdq_dev_get_client_reg(dev, &mmsys->cmdq_base, 0);
        if (ret)
                dev_dbg(dev, "No mediatek,gce-client-reg!\n");
-#endif
 
        platform_set_drvdata(pdev, mmsys);
 
@@ -342,6 +393,7 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
                                             PLATFORM_DEVID_AUTO, NULL, 0);
        if (IS_ERR(clks))
                return PTR_ERR(clks);
+       mmsys->clks_pdev = clks;
 
        if (mmsys->data->is_vppsys)
                goto out_probe_done;
@@ -352,78 +404,44 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
                platform_device_unregister(clks);
                return PTR_ERR(drm);
        }
+       mmsys->drm_pdev = drm;
 
 out_probe_done:
        return 0;
 }
 
+static int mtk_mmsys_remove(struct platform_device *pdev)
+{
+       struct mtk_mmsys *mmsys = platform_get_drvdata(pdev);
+
+       platform_device_unregister(mmsys->drm_pdev);
+       platform_device_unregister(mmsys->clks_pdev);
+
+       return 0;
+}
+
 static const struct of_device_id of_match_mtk_mmsys[] = {
-       {
-               .compatible = "mediatek,mt2701-mmsys",
-               .data = &mt2701_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt2712-mmsys",
-               .data = &mt2712_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt6779-mmsys",
-               .data = &mt6779_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt6797-mmsys",
-               .data = &mt6797_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8167-mmsys",
-               .data = &mt8167_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8173-mmsys",
-               .data = &mt8173_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8183-mmsys",
-               .data = &mt8183_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8186-mmsys",
-               .data = &mt8186_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8188-vdosys0",
-               .data = &mt8188_vdosys0_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8192-mmsys",
-               .data = &mt8192_mmsys_driver_data,
-       },
-       {       /* deprecated compatible */
-               .compatible = "mediatek,mt8195-mmsys",
-               .data = &mt8195_vdosys0_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8195-vdosys0",
-               .data = &mt8195_vdosys0_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8195-vdosys1",
-               .data = &mt8195_vdosys1_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8195-vppsys0",
-               .data = &mt8195_vppsys0_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8195-vppsys1",
-               .data = &mt8195_vppsys1_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8365-mmsys",
-               .data = &mt8365_mmsys_driver_data,
-       },
-       { }
+       { .compatible = "mediatek,mt2701-mmsys", .data = &mt2701_mmsys_driver_data },
+       { .compatible = "mediatek,mt2712-mmsys", .data = &mt2712_mmsys_driver_data },
+       { .compatible = "mediatek,mt6779-mmsys", .data = &mt6779_mmsys_driver_data },
+       { .compatible = "mediatek,mt6795-mmsys", .data = &mt6795_mmsys_driver_data },
+       { .compatible = "mediatek,mt6797-mmsys", .data = &mt6797_mmsys_driver_data },
+       { .compatible = "mediatek,mt8167-mmsys", .data = &mt8167_mmsys_driver_data },
+       { .compatible = "mediatek,mt8173-mmsys", .data = &mt8173_mmsys_driver_data },
+       { .compatible = "mediatek,mt8183-mmsys", .data = &mt8183_mmsys_driver_data },
+       { .compatible = "mediatek,mt8186-mmsys", .data = &mt8186_mmsys_driver_data },
+       { .compatible = "mediatek,mt8188-vdosys0", .data = &mt8188_vdosys0_driver_data },
+       { .compatible = "mediatek,mt8192-mmsys", .data = &mt8192_mmsys_driver_data },
+       /* "mediatek,mt8195-mmsys" compatible is deprecated */
+       { .compatible = "mediatek,mt8195-mmsys", .data = &mt8195_vdosys0_driver_data },
+       { .compatible = "mediatek,mt8195-vdosys0", .data = &mt8195_vdosys0_driver_data },
+       { .compatible = "mediatek,mt8195-vdosys1", .data = &mt8195_vdosys1_driver_data },
+       { .compatible = "mediatek,mt8195-vppsys0", .data = &mt8195_vppsys0_driver_data },
+       { .compatible = "mediatek,mt8195-vppsys1", .data = &mt8195_vppsys1_driver_data },
+       { .compatible = "mediatek,mt8365-mmsys", .data = &mt8365_mmsys_driver_data },
+       { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, of_match_mtk_mmsys);
 
 static struct platform_driver mtk_mmsys_drv = {
        .driver = {
@@ -431,20 +449,9 @@ static struct platform_driver mtk_mmsys_drv = {
                .of_match_table = of_match_mtk_mmsys,
        },
        .probe = mtk_mmsys_probe,
+       .remove = mtk_mmsys_remove,
 };
-
-static int __init mtk_mmsys_init(void)
-{
-       return platform_driver_register(&mtk_mmsys_drv);
-}
-
-static void __exit mtk_mmsys_exit(void)
-{
-       platform_driver_unregister(&mtk_mmsys_drv);
-}
-
-module_init(mtk_mmsys_init);
-module_exit(mtk_mmsys_exit);
+module_platform_driver(mtk_mmsys_drv);
 
 MODULE_AUTHOR("Yongqiang Niu <yongqiang.niu@mediatek.com>");
 MODULE_DESCRIPTION("MediaTek SoC MMSYS driver");
index 56f8cc3a97b72bd550c453747b2197370ebef0f0..6725403d2e3ac4a91956c07276814445588fff3e 100644 (file)
@@ -96,7 +96,7 @@ struct mtk_mmsys_driver_data {
 };
 
 /*
- * Routes in mt8173, mt2701, mt2712 are different. That means
+ * Routes in mt2701 and mt2712 are different. That means
  * in the same register address, it controls different input/output
  * selection for each SoC. But, right now, they use the same table as
  * default routes meet their requirements. But we don't have the complete
index c5b1b42303ac26f388defbd9e6c6161dd07df4ab..26f3d9a4149641639b5db6293dca4190d41866f7 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/soc/mediatek/mtk-mutex.h>
 #include <linux/soc/mediatek/mtk-cmdq.h>
 
+#define MTK_MUTEX_MAX_HANDLES                  10
+
 #define MT2701_MUTEX0_MOD0                     0x2c
 #define MT2701_MUTEX0_SOF0                     0x30
 #define MT8183_MUTEX0_MOD0                     0x30
@@ -23,6 +25,7 @@
 #define DISP_REG_MUTEX(n)                      (0x24 + 0x20 * (n))
 #define DISP_REG_MUTEX_RST(n)                  (0x28 + 0x20 * (n))
 #define DISP_REG_MUTEX_MOD(mutex_mod_reg, n)   (mutex_mod_reg + 0x20 * (n))
+#define DISP_REG_MUTEX_MOD1(mutex_mod_reg, n)  ((mutex_mod_reg) + 0x20 * (n) + 0x4)
 #define DISP_REG_MUTEX_SOF(mutex_sof_reg, n)   (mutex_sof_reg + 0x20 * (n))
 #define DISP_REG_MUTEX_MOD2(n)                 (0x34 + 0x20 * (n))
 
 #define MT8195_MUTEX_MOD_DISP1_DPI1            26
 #define MT8195_MUTEX_MOD_DISP1_DP_INTF0                27
 
+/* VPPSYS0 */
+#define MT8195_MUTEX_MOD_MDP_RDMA0             0
+#define MT8195_MUTEX_MOD_MDP_FG0               1
+#define MT8195_MUTEX_MOD_MDP_STITCH0           2
+#define MT8195_MUTEX_MOD_MDP_HDR0              3
+#define MT8195_MUTEX_MOD_MDP_AAL0              4
+#define MT8195_MUTEX_MOD_MDP_RSZ0              5
+#define MT8195_MUTEX_MOD_MDP_TDSHP0            6
+#define MT8195_MUTEX_MOD_MDP_COLOR0            7
+#define MT8195_MUTEX_MOD_MDP_OVL0              8
+#define MT8195_MUTEX_MOD_MDP_PAD0              9
+#define MT8195_MUTEX_MOD_MDP_TCC0              10
+#define MT8195_MUTEX_MOD_MDP_WROT0             11
+
+/* VPPSYS1 */
+#define MT8195_MUTEX_MOD_MDP_TCC1              3
+#define MT8195_MUTEX_MOD_MDP_RDMA1             4
+#define MT8195_MUTEX_MOD_MDP_RDMA2             5
+#define MT8195_MUTEX_MOD_MDP_RDMA3             6
+#define MT8195_MUTEX_MOD_MDP_FG1               7
+#define MT8195_MUTEX_MOD_MDP_FG2               8
+#define MT8195_MUTEX_MOD_MDP_FG3               9
+#define MT8195_MUTEX_MOD_MDP_HDR1              10
+#define MT8195_MUTEX_MOD_MDP_HDR2              11
+#define MT8195_MUTEX_MOD_MDP_HDR3              12
+#define MT8195_MUTEX_MOD_MDP_AAL1              13
+#define MT8195_MUTEX_MOD_MDP_AAL2              14
+#define MT8195_MUTEX_MOD_MDP_AAL3              15
+#define MT8195_MUTEX_MOD_MDP_RSZ1              16
+#define MT8195_MUTEX_MOD_MDP_RSZ2              17
+#define MT8195_MUTEX_MOD_MDP_RSZ3              18
+#define MT8195_MUTEX_MOD_MDP_TDSHP1            19
+#define MT8195_MUTEX_MOD_MDP_TDSHP2            20
+#define MT8195_MUTEX_MOD_MDP_TDSHP3            21
+#define MT8195_MUTEX_MOD_MDP_MERGE2            22
+#define MT8195_MUTEX_MOD_MDP_MERGE3            23
+#define MT8195_MUTEX_MOD_MDP_COLOR1            24
+#define MT8195_MUTEX_MOD_MDP_COLOR2            25
+#define MT8195_MUTEX_MOD_MDP_COLOR3            26
+#define MT8195_MUTEX_MOD_MDP_OVL1              27
+#define MT8195_MUTEX_MOD_MDP_PAD1              28
+#define MT8195_MUTEX_MOD_MDP_PAD2              29
+#define MT8195_MUTEX_MOD_MDP_PAD3              30
+#define MT8195_MUTEX_MOD_MDP_WROT1             31
+#define MT8195_MUTEX_MOD_MDP_WROT2             32
+#define MT8195_MUTEX_MOD_MDP_WROT3             33
+
 #define MT8365_MUTEX_MOD_DISP_OVL0             7
 #define MT8365_MUTEX_MOD_DISP_OVL0_2L          8
 #define MT8365_MUTEX_MOD_DISP_RDMA0            9
 #define MT8195_MUTEX_EOF_DPI1                  (MT8195_MUTEX_SOF_DPI1 << 7)
 
 struct mtk_mutex {
-       int id;
+       u8 id;
        bool claimed;
 };
 
@@ -264,7 +314,7 @@ struct mtk_mutex_ctx {
        struct device                   *dev;
        struct clk                      *clk;
        void __iomem                    *regs;
-       struct mtk_mutex                mutex[10];
+       struct mtk_mutex                mutex[MTK_MUTEX_MAX_HANDLES];
        const struct mtk_mutex_data     *data;
        phys_addr_t                     addr;
        struct cmdq_client_reg          cmdq_reg;
@@ -443,6 +493,52 @@ static const unsigned int mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
        [DDP_COMPONENT_DP_INTF1] = MT8195_MUTEX_MOD_DISP1_DP_INTF0,
 };
 
+static const unsigned int mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
+       [MUTEX_MOD_IDX_MDP_RDMA0] = MT8195_MUTEX_MOD_MDP_RDMA0,
+       [MUTEX_MOD_IDX_MDP_RDMA1] = MT8195_MUTEX_MOD_MDP_RDMA1,
+       [MUTEX_MOD_IDX_MDP_RDMA2] = MT8195_MUTEX_MOD_MDP_RDMA2,
+       [MUTEX_MOD_IDX_MDP_RDMA3] = MT8195_MUTEX_MOD_MDP_RDMA3,
+       [MUTEX_MOD_IDX_MDP_STITCH0] = MT8195_MUTEX_MOD_MDP_STITCH0,
+       [MUTEX_MOD_IDX_MDP_FG0] = MT8195_MUTEX_MOD_MDP_FG0,
+       [MUTEX_MOD_IDX_MDP_FG1] = MT8195_MUTEX_MOD_MDP_FG1,
+       [MUTEX_MOD_IDX_MDP_FG2] = MT8195_MUTEX_MOD_MDP_FG2,
+       [MUTEX_MOD_IDX_MDP_FG3] = MT8195_MUTEX_MOD_MDP_FG3,
+       [MUTEX_MOD_IDX_MDP_HDR0] = MT8195_MUTEX_MOD_MDP_HDR0,
+       [MUTEX_MOD_IDX_MDP_HDR1] = MT8195_MUTEX_MOD_MDP_HDR1,
+       [MUTEX_MOD_IDX_MDP_HDR2] = MT8195_MUTEX_MOD_MDP_HDR2,
+       [MUTEX_MOD_IDX_MDP_HDR3] = MT8195_MUTEX_MOD_MDP_HDR3,
+       [MUTEX_MOD_IDX_MDP_AAL0] = MT8195_MUTEX_MOD_MDP_AAL0,
+       [MUTEX_MOD_IDX_MDP_AAL1] = MT8195_MUTEX_MOD_MDP_AAL1,
+       [MUTEX_MOD_IDX_MDP_AAL2] = MT8195_MUTEX_MOD_MDP_AAL2,
+       [MUTEX_MOD_IDX_MDP_AAL3] = MT8195_MUTEX_MOD_MDP_AAL3,
+       [MUTEX_MOD_IDX_MDP_RSZ0] = MT8195_MUTEX_MOD_MDP_RSZ0,
+       [MUTEX_MOD_IDX_MDP_RSZ1] = MT8195_MUTEX_MOD_MDP_RSZ1,
+       [MUTEX_MOD_IDX_MDP_RSZ2] = MT8195_MUTEX_MOD_MDP_RSZ2,
+       [MUTEX_MOD_IDX_MDP_RSZ3] = MT8195_MUTEX_MOD_MDP_RSZ3,
+       [MUTEX_MOD_IDX_MDP_MERGE2] = MT8195_MUTEX_MOD_MDP_MERGE2,
+       [MUTEX_MOD_IDX_MDP_MERGE3] = MT8195_MUTEX_MOD_MDP_MERGE3,
+       [MUTEX_MOD_IDX_MDP_TDSHP0] = MT8195_MUTEX_MOD_MDP_TDSHP0,
+       [MUTEX_MOD_IDX_MDP_TDSHP1] = MT8195_MUTEX_MOD_MDP_TDSHP1,
+       [MUTEX_MOD_IDX_MDP_TDSHP2] = MT8195_MUTEX_MOD_MDP_TDSHP2,
+       [MUTEX_MOD_IDX_MDP_TDSHP3] = MT8195_MUTEX_MOD_MDP_TDSHP3,
+       [MUTEX_MOD_IDX_MDP_COLOR0] = MT8195_MUTEX_MOD_MDP_COLOR0,
+       [MUTEX_MOD_IDX_MDP_COLOR1] = MT8195_MUTEX_MOD_MDP_COLOR1,
+       [MUTEX_MOD_IDX_MDP_COLOR2] = MT8195_MUTEX_MOD_MDP_COLOR2,
+       [MUTEX_MOD_IDX_MDP_COLOR3] = MT8195_MUTEX_MOD_MDP_COLOR3,
+       [MUTEX_MOD_IDX_MDP_OVL0] = MT8195_MUTEX_MOD_MDP_OVL0,
+       [MUTEX_MOD_IDX_MDP_OVL1] = MT8195_MUTEX_MOD_MDP_OVL1,
+       [MUTEX_MOD_IDX_MDP_PAD0] = MT8195_MUTEX_MOD_MDP_PAD0,
+       [MUTEX_MOD_IDX_MDP_PAD1] = MT8195_MUTEX_MOD_MDP_PAD1,
+       [MUTEX_MOD_IDX_MDP_PAD2] = MT8195_MUTEX_MOD_MDP_PAD2,
+       [MUTEX_MOD_IDX_MDP_PAD3] = MT8195_MUTEX_MOD_MDP_PAD3,
+       [MUTEX_MOD_IDX_MDP_TCC0] = MT8195_MUTEX_MOD_MDP_TCC0,
+       [MUTEX_MOD_IDX_MDP_TCC1] = MT8195_MUTEX_MOD_MDP_TCC1,
+       [MUTEX_MOD_IDX_MDP_WROT0] = MT8195_MUTEX_MOD_MDP_WROT0,
+       [MUTEX_MOD_IDX_MDP_WROT1] = MT8195_MUTEX_MOD_MDP_WROT1,
+       [MUTEX_MOD_IDX_MDP_WROT2] = MT8195_MUTEX_MOD_MDP_WROT2,
+       [MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3,
+};
+
 static const unsigned int mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
        [DDP_COMPONENT_AAL0] = MT8365_MUTEX_MOD_DISP_AAL,
        [DDP_COMPONENT_CCORR] = MT8365_MUTEX_MOD_DISP_CCORR,
@@ -603,6 +699,13 @@ static const struct mtk_mutex_data mt8195_mutex_driver_data = {
        .mutex_sof_reg = MT8183_MUTEX0_SOF0,
 };
 
+static const struct mtk_mutex_data mt8195_vpp_mutex_driver_data = {
+       .mutex_sof = mt8195_mutex_sof,
+       .mutex_mod_reg = MT8183_MUTEX0_MOD0,
+       .mutex_sof_reg = MT8183_MUTEX0_SOF0,
+       .mutex_table_mod = mt8195_mutex_table_mod,
+};
+
 static const struct mtk_mutex_data mt8365_mutex_driver_data = {
        .mutex_mod = mt8365_mutex_mod,
        .mutex_sof = mt8183_mutex_sof,
@@ -616,7 +719,7 @@ struct mtk_mutex *mtk_mutex_get(struct device *dev)
        struct mtk_mutex_ctx *mtx = dev_get_drvdata(dev);
        int i;
 
-       for (i = 0; i < 10; i++)
+       for (i = 0; i < MTK_MUTEX_MAX_HANDLES; i++)
                if (!mtx->mutex[i].claimed) {
                        mtx->mutex[i].claimed = true;
                        return &mtx->mutex[i];
@@ -768,23 +871,18 @@ int mtk_mutex_enable_by_cmdq(struct mtk_mutex *mutex, void *pkt)
 {
        struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
                                                 mutex[mutex->id]);
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
        struct cmdq_pkt *cmdq_pkt = (struct cmdq_pkt *)pkt;
 
        WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
        if (!mtx->cmdq_reg.size) {
                dev_err(mtx->dev, "mediatek,gce-client-reg hasn't been set");
-               return -EINVAL;
+               return -ENODEV;
        }
 
        cmdq_pkt_write(cmdq_pkt, mtx->cmdq_reg.subsys,
                       mtx->addr + DISP_REG_MUTEX_EN(mutex->id), 1);
        return 0;
-#else
-       dev_err(mtx->dev, "Not support for enable MUTEX by CMDQ");
-       return -ENODEV;
-#endif
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_enable_by_cmdq);
 
@@ -828,7 +926,7 @@ int mtk_mutex_write_mod(struct mtk_mutex *mutex,
        struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
                                                 mutex[mutex->id]);
        unsigned int reg;
-       unsigned int offset;
+       u32 reg_offset, id_offset = 0;
 
        WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
@@ -838,16 +936,34 @@ int mtk_mutex_write_mod(struct mtk_mutex *mutex,
                return -EINVAL;
        }
 
-       offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
-                                   mutex->id);
-       reg = readl_relaxed(mtx->regs + offset);
+       /*
+        * Some SoCs may have multiple MUTEX_MOD registers as more than 32 mods
+        * are present, hence requiring multiple 32-bits registers.
+        *
+        * The mutex_table_mod fully represents that by defining the number of
+        * the mod sequentially, later used as a bit number, which can be more
+        * than 0..31.
+        *
+        * In order to retain compatibility with older SoCs, we perform R/W on
+        * the single 32 bits registers, but this requires us to translate the
+        * mutex ID bit accordingly.
+        */
+       if (mtx->data->mutex_table_mod[idx] < 32) {
+               reg_offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
+                                               mutex->id);
+       } else {
+               reg_offset = DISP_REG_MUTEX_MOD1(mtx->data->mutex_mod_reg,
+                                                mutex->id);
+               id_offset = 32;
+       }
 
+       reg = readl_relaxed(mtx->regs + reg_offset);
        if (clear)
-               reg &= ~BIT(mtx->data->mutex_table_mod[idx]);
+               reg &= ~BIT(mtx->data->mutex_table_mod[idx] - id_offset);
        else
-               reg |= BIT(mtx->data->mutex_table_mod[idx]);
+               reg |= BIT(mtx->data->mutex_table_mod[idx] - id_offset);
 
-       writel_relaxed(reg, mtx->regs + offset);
+       writel_relaxed(reg, mtx->regs + reg_offset);
 
        return 0;
 }
@@ -879,27 +995,21 @@ static int mtk_mutex_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct mtk_mutex_ctx *mtx;
        struct resource *regs;
-       int i;
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
-       int ret;
-#endif
+       int i, ret;
 
        mtx = devm_kzalloc(dev, sizeof(*mtx), GFP_KERNEL);
        if (!mtx)
                return -ENOMEM;
 
-       for (i = 0; i < 10; i++)
+       for (i = 0; i < MTK_MUTEX_MAX_HANDLES; i++)
                mtx->mutex[i].id = i;
 
        mtx->data = of_device_get_match_data(dev);
 
        if (!mtx->data->no_clk) {
                mtx->clk = devm_clk_get(dev, NULL);
-               if (IS_ERR(mtx->clk)) {
-                       if (PTR_ERR(mtx->clk) != -EPROBE_DEFER)
-                               dev_err(dev, "Failed to get clock\n");
-                       return PTR_ERR(mtx->clk);
-               }
+               if (IS_ERR(mtx->clk))
+                       return dev_err_probe(dev, PTR_ERR(mtx->clk), "Failed to get clock\n");
        }
 
        mtx->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &regs);
@@ -909,11 +1019,10 @@ static int mtk_mutex_probe(struct platform_device *pdev)
        }
        mtx->addr = regs->start;
 
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+       /* CMDQ is optional */
        ret = cmdq_dev_get_client_reg(dev, &mtx->cmdq_reg, 0);
        if (ret)
                dev_dbg(dev, "No mediatek,gce-client-reg!\n");
-#endif
 
        platform_set_drvdata(pdev, mtx);
 
@@ -921,31 +1030,20 @@ static int mtk_mutex_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id mutex_driver_dt_match[] = {
-       { .compatible = "mediatek,mt2701-disp-mutex",
-         .data = &mt2701_mutex_driver_data},
-       { .compatible = "mediatek,mt2712-disp-mutex",
-         .data = &mt2712_mutex_driver_data},
-       { .compatible = "mediatek,mt6795-disp-mutex",
-         .data = &mt6795_mutex_driver_data},
-       { .compatible = "mediatek,mt8167-disp-mutex",
-         .data = &mt8167_mutex_driver_data},
-       { .compatible = "mediatek,mt8173-disp-mutex",
-         .data = &mt8173_mutex_driver_data},
-       { .compatible = "mediatek,mt8183-disp-mutex",
-         .data = &mt8183_mutex_driver_data},
-       { .compatible = "mediatek,mt8186-disp-mutex",
-         .data = &mt8186_mutex_driver_data},
-       { .compatible = "mediatek,mt8186-mdp3-mutex",
-         .data = &mt8186_mdp_mutex_driver_data},
-       { .compatible = "mediatek,mt8188-disp-mutex",
-         .data = &mt8188_mutex_driver_data},
-       { .compatible = "mediatek,mt8192-disp-mutex",
-         .data = &mt8192_mutex_driver_data},
-       { .compatible = "mediatek,mt8195-disp-mutex",
-         .data = &mt8195_mutex_driver_data},
-       { .compatible = "mediatek,mt8365-disp-mutex",
-         .data = &mt8365_mutex_driver_data},
-       {},
+       { .compatible = "mediatek,mt2701-disp-mutex", .data = &mt2701_mutex_driver_data },
+       { .compatible = "mediatek,mt2712-disp-mutex", .data = &mt2712_mutex_driver_data },
+       { .compatible = "mediatek,mt6795-disp-mutex", .data = &mt6795_mutex_driver_data },
+       { .compatible = "mediatek,mt8167-disp-mutex", .data = &mt8167_mutex_driver_data },
+       { .compatible = "mediatek,mt8173-disp-mutex", .data = &mt8173_mutex_driver_data },
+       { .compatible = "mediatek,mt8183-disp-mutex", .data = &mt8183_mutex_driver_data },
+       { .compatible = "mediatek,mt8186-disp-mutex", .data = &mt8186_mutex_driver_data },
+       { .compatible = "mediatek,mt8186-mdp3-mutex", .data = &mt8186_mdp_mutex_driver_data },
+       { .compatible = "mediatek,mt8188-disp-mutex", .data = &mt8188_mutex_driver_data },
+       { .compatible = "mediatek,mt8192-disp-mutex", .data = &mt8192_mutex_driver_data },
+       { .compatible = "mediatek,mt8195-disp-mutex", .data = &mt8195_mutex_driver_data },
+       { .compatible = "mediatek,mt8195-vpp-mutex",  .data = &mt8195_vpp_mutex_driver_data },
+       { .compatible = "mediatek,mt8365-disp-mutex", .data = &mt8365_mutex_driver_data },
+       { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, mutex_driver_dt_match);
 
@@ -957,19 +1055,7 @@ static struct platform_driver mtk_mutex_driver = {
                .of_match_table = mutex_driver_dt_match,
        },
 };
-
-static int __init mtk_mutex_init(void)
-{
-       return platform_driver_register(&mtk_mutex_driver);
-}
-
-static void __exit mtk_mutex_exit(void)
-{
-       platform_driver_unregister(&mtk_mutex_driver);
-}
-
-module_init(mtk_mutex_init);
-module_exit(mtk_mutex_exit);
+module_platform_driver(mtk_mutex_driver);
 
 MODULE_AUTHOR("Yongqiang Niu <yongqiang.niu@mediatek.com>");
 MODULE_DESCRIPTION("MediaTek SoC MUTEX driver");
index f26eb2f637d522e381f78a008b4a408e78a341b9..b9c96182a46a63a4be1d4127fae3923b79c4f4ea 100644 (file)
@@ -558,7 +558,7 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
        }
 
        /* Get thermal effect */
-       if (svsb->phase == SVSB_PHASE_MON) {
+       if (!IS_ERR_OR_NULL(svsb->tzd)) {
                ret = thermal_zone_get_temp(svsb->tzd, &tzone_temp);
                if (ret || (svsb->temp > SVSB_TEMP_UPPER_BOUND &&
                            svsb->temp < SVSB_TEMP_LOWER_BOUND)) {
@@ -573,7 +573,8 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
                        temp_voffset += svsb->tzone_ltemp_voffset;
 
                /* 2-line bank update all opp volts when running mon mode */
-               if (svsb->type == SVSB_HIGH || svsb->type == SVSB_LOW) {
+               if (svsb->phase == SVSB_PHASE_MON && (svsb->type == SVSB_HIGH ||
+                                                     svsb->type == SVSB_LOW)) {
                        opp_start = 0;
                        opp_stop = svsb->opp_count;
                }
@@ -589,11 +590,6 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
                        /* do nothing */
                        goto unlock_mutex;
                case SVSB_PHASE_INIT02:
-                       svsb_volt = max(svsb->volt[i], svsb->vmin);
-                       opp_volt = svs_bank_volt_to_opp_volt(svsb_volt,
-                                                            svsb->volt_step,
-                                                            svsb->volt_base);
-                       break;
                case SVSB_PHASE_MON:
                        svsb_volt = max(svsb->volt[i] + temp_voffset, svsb->vmin);
                        opp_volt = svs_bank_volt_to_opp_volt(svsb_volt,
@@ -624,6 +620,25 @@ unlock_mutex:
        return ret;
 }
 
+static void svs_bank_disable_and_restore_default_volts(struct svs_platform *svsp,
+                                                      struct svs_bank *svsb)
+{
+       unsigned long flags;
+
+       if (svsb->mode_support == SVSB_MODE_ALL_DISABLE)
+               return;
+
+       spin_lock_irqsave(&svs_lock, flags);
+       svsp->pbank = svsb;
+       svs_switch_bank(svsp);
+       svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
+       svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
+       spin_unlock_irqrestore(&svs_lock, flags);
+
+       svsb->phase = SVSB_PHASE_ERROR;
+       svs_adjust_pm_opp_volts(svsb);
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int svs_dump_debug_show(struct seq_file *m, void *p)
 {
@@ -700,7 +715,6 @@ static ssize_t svs_enable_debug_write(struct file *filp,
 {
        struct svs_bank *svsb = file_inode(filp)->i_private;
        struct svs_platform *svsp = dev_get_drvdata(svsb->dev);
-       unsigned long flags;
        int enabled, ret;
        char *buf = NULL;
 
@@ -716,16 +730,8 @@ static ssize_t svs_enable_debug_write(struct file *filp,
                return ret;
 
        if (!enabled) {
-               spin_lock_irqsave(&svs_lock, flags);
-               svsp->pbank = svsb;
+               svs_bank_disable_and_restore_default_volts(svsp, svsb);
                svsb->mode_support = SVSB_MODE_ALL_DISABLE;
-               svs_switch_bank(svsp);
-               svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
-               svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
-               spin_unlock_irqrestore(&svs_lock, flags);
-
-               svsb->phase = SVSB_PHASE_ERROR;
-               svs_adjust_pm_opp_volts(svsb);
        }
 
        kfree(buf);
@@ -1508,16 +1514,7 @@ static int svs_init02(struct svs_platform *svsp)
 out_of_init02:
        for (idx = 0; idx < svsp->bank_max; idx++) {
                svsb = &svsp->banks[idx];
-
-               spin_lock_irqsave(&svs_lock, flags);
-               svsp->pbank = svsb;
-               svs_switch_bank(svsp);
-               svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
-               svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
-               spin_unlock_irqrestore(&svs_lock, flags);
-
-               svsb->phase = SVSB_PHASE_ERROR;
-               svs_adjust_pm_opp_volts(svsb);
+               svs_bank_disable_and_restore_default_volts(svsp, svsb);
        }
 
        return ret;
@@ -1563,23 +1560,12 @@ static int svs_suspend(struct device *dev)
 {
        struct svs_platform *svsp = dev_get_drvdata(dev);
        struct svs_bank *svsb;
-       unsigned long flags;
        int ret;
        u32 idx;
 
        for (idx = 0; idx < svsp->bank_max; idx++) {
                svsb = &svsp->banks[idx];
-
-               /* This might wait for svs_isr() process */
-               spin_lock_irqsave(&svs_lock, flags);
-               svsp->pbank = svsb;
-               svs_switch_bank(svsp);
-               svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
-               svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
-               spin_unlock_irqrestore(&svs_lock, flags);
-
-               svsb->phase = SVSB_PHASE_ERROR;
-               svs_adjust_pm_opp_volts(svsb);
+               svs_bank_disable_and_restore_default_volts(svsp, svsb);
        }
 
        ret = reset_control_assert(svsp->rst);
@@ -1693,7 +1679,7 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
                        }
                }
 
-               if (svsb->mode_support & SVSB_MODE_MON) {
+               if (!IS_ERR_OR_NULL(svsb->tzone_name)) {
                        svsb->tzd = thermal_zone_get_zone_by_name(svsb->tzone_name);
                        if (IS_ERR(svsb->tzd)) {
                                dev_err(svsb->dev, "cannot get \"%s\" thermal zone\n",
@@ -1729,26 +1715,28 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
        return 0;
 }
 
-static int svs_thermal_efuse_get_data(struct svs_platform *svsp)
+static int svs_get_efuse_data(struct svs_platform *svsp,
+                             const char *nvmem_cell_name,
+                             u32 **svsp_efuse, size_t *svsp_efuse_max)
 {
        struct nvmem_cell *cell;
 
-       /* Thermal efuse parsing */
-       cell = nvmem_cell_get(svsp->dev, "t-calibration-data");
-       if (IS_ERR_OR_NULL(cell)) {
-               dev_err(svsp->dev, "no \"t-calibration-data\"? %ld\n", PTR_ERR(cell));
+       cell = nvmem_cell_get(svsp->dev, nvmem_cell_name);
+       if (IS_ERR(cell)) {
+               dev_err(svsp->dev, "no \"%s\"? %ld\n",
+                       nvmem_cell_name, PTR_ERR(cell));
                return PTR_ERR(cell);
        }
 
-       svsp->tefuse = nvmem_cell_read(cell, &svsp->tefuse_max);
-       if (IS_ERR(svsp->tefuse)) {
-               dev_err(svsp->dev, "cannot read thermal efuse: %ld\n",
-                       PTR_ERR(svsp->tefuse));
+       *svsp_efuse = nvmem_cell_read(cell, svsp_efuse_max);
+       if (IS_ERR(*svsp_efuse)) {
+               dev_err(svsp->dev, "cannot read \"%s\" efuse: %ld\n",
+                       nvmem_cell_name, PTR_ERR(*svsp_efuse));
                nvmem_cell_put(cell);
-               return PTR_ERR(svsp->tefuse);
+               return PTR_ERR(*svsp_efuse);
        }
 
-       svsp->tefuse_max /= sizeof(u32);
+       *svsp_efuse_max /= sizeof(u32);
        nvmem_cell_put(cell);
 
        return 0;
@@ -1796,7 +1784,8 @@ static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp)
                svsb->vmax += svsb->dvt_fixed;
        }
 
-       ret = svs_thermal_efuse_get_data(svsp);
+       ret = svs_get_efuse_data(svsp, "t-calibration-data",
+                                &svsp->tefuse, &svsp->tefuse_max);
        if (ret)
                return false;
 
@@ -1901,7 +1890,8 @@ static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp)
                }
        }
 
-       ret = svs_thermal_efuse_get_data(svsp);
+       ret = svs_get_efuse_data(svsp, "t-calibration-data",
+                                &svsp->tefuse, &svsp->tefuse_max);
        if (ret)
                return false;
 
@@ -2003,32 +1993,6 @@ remove_mt8183_svsb_mon_mode:
        return true;
 }
 
-static bool svs_is_efuse_data_correct(struct svs_platform *svsp)
-{
-       struct nvmem_cell *cell;
-
-       /* Get svs efuse by nvmem */
-       cell = nvmem_cell_get(svsp->dev, "svs-calibration-data");
-       if (IS_ERR(cell)) {
-               dev_err(svsp->dev, "no \"svs-calibration-data\"? %ld\n",
-                       PTR_ERR(cell));
-               return false;
-       }
-
-       svsp->efuse = nvmem_cell_read(cell, &svsp->efuse_max);
-       if (IS_ERR(svsp->efuse)) {
-               dev_err(svsp->dev, "cannot read svs efuse: %ld\n",
-                       PTR_ERR(svsp->efuse));
-               nvmem_cell_put(cell);
-               return false;
-       }
-
-       svsp->efuse_max /= sizeof(u32);
-       nvmem_cell_put(cell);
-
-       return true;
-}
-
 static struct device *svs_get_subsys_device(struct svs_platform *svsp,
                                            const char *node_name)
 {
@@ -2059,11 +2023,6 @@ static struct device *svs_add_device_link(struct svs_platform *svsp,
        struct device *dev;
        struct device_link *sup_link;
 
-       if (!node_name) {
-               dev_err(svsp->dev, "node name cannot be null\n");
-               return ERR_PTR(-EINVAL);
-       }
-
        dev = svs_get_subsys_device(svsp, node_name);
        if (IS_ERR(dev))
                return dev;
@@ -2159,6 +2118,7 @@ static struct svs_bank svs_mt8192_banks[] = {
                .type                   = SVSB_LOW,
                .set_freq_pct           = svs_set_bank_freq_pct_v3,
                .get_volts              = svs_get_bank_volts_v3,
+               .tzone_name             = "gpu1",
                .volt_flags             = SVSB_REMOVE_DVTFIXED_VOLT,
                .mode_support           = SVSB_MODE_INIT02,
                .opp_count              = MAX_OPP_ENTRIES,
@@ -2176,6 +2136,10 @@ static struct svs_bank svs_mt8192_banks[] = {
                .core_sel               = 0x0fff0100,
                .int_st                 = BIT(0),
                .ctl0                   = 0x00540003,
+               .tzone_htemp            = 85000,
+               .tzone_htemp_voffset    = 0,
+               .tzone_ltemp            = 25000,
+               .tzone_ltemp_voffset    = 7,
        },
        {
                .sw_id                  = SVSB_GPU,
@@ -2364,8 +2328,9 @@ static int svs_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       if (!svs_is_efuse_data_correct(svsp)) {
-               dev_notice(svsp->dev, "efuse data isn't correct\n");
+       ret = svs_get_efuse_data(svsp, "svs-calibration-data",
+                                &svsp->efuse, &svsp->efuse_max);
+       if (ret) {
                ret = -EPERM;
                goto svs_probe_free_efuse;
        }
@@ -2373,19 +2338,19 @@ static int svs_probe(struct platform_device *pdev)
        if (!svsp_data->efuse_parsing(svsp)) {
                dev_err(svsp->dev, "efuse data parsing failed\n");
                ret = -EPERM;
-               goto svs_probe_free_resource;
+               goto svs_probe_free_tefuse;
        }
 
        ret = svs_bank_resource_setup(svsp);
        if (ret) {
                dev_err(svsp->dev, "svs bank resource setup fail: %d\n", ret);
-               goto svs_probe_free_resource;
+               goto svs_probe_free_tefuse;
        }
 
        svsp_irq = platform_get_irq(pdev, 0);
        if (svsp_irq < 0) {
                ret = svsp_irq;
-               goto svs_probe_free_resource;
+               goto svs_probe_free_tefuse;
        }
 
        svsp->main_clk = devm_clk_get(svsp->dev, "main");
@@ -2393,13 +2358,13 @@ static int svs_probe(struct platform_device *pdev)
                dev_err(svsp->dev, "failed to get clock: %ld\n",
                        PTR_ERR(svsp->main_clk));
                ret = PTR_ERR(svsp->main_clk);
-               goto svs_probe_free_resource;
+               goto svs_probe_free_tefuse;
        }
 
        ret = clk_prepare_enable(svsp->main_clk);
        if (ret) {
                dev_err(svsp->dev, "cannot enable main clk: %d\n", ret);
-               goto svs_probe_free_resource;
+               goto svs_probe_free_tefuse;
        }
 
        svsp->base = of_iomap(svsp->dev->of_node, 0);
@@ -2439,7 +2404,7 @@ svs_probe_iounmap:
 svs_probe_clk_disable:
        clk_disable_unprepare(svsp->main_clk);
 
-svs_probe_free_resource:
+svs_probe_free_tefuse:
        if (!IS_ERR_OR_NULL(svsp->tefuse))
                kfree(svsp->tefuse);
 
index 6e20207b57567b457b624849d14ceaee9865be90..216d9f4ea0ce936cec3e6a7da9bc99bef7e81cd5 100644 (file)
 #include <linux/slab.h>
 #include <linux/kref.h>
 #include <linux/module.h>
+#include <linux/jiffies.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
 #include <linux/mailbox_client.h>
 #include <linux/platform_device.h>
 #include <soc/microchip/mpfs.h>
 
+/*
+ * This timeout must be long, as some services (example: image authentication)
+ * take significant time to complete
+ */
+#define MPFS_SYS_CTRL_TIMEOUT_MS 30000
+
 static DEFINE_MUTEX(transaction_lock);
 
 struct mpfs_sys_controller {
@@ -28,35 +35,47 @@ struct mpfs_sys_controller {
 
 int mpfs_blocking_transaction(struct mpfs_sys_controller *sys_controller, struct mpfs_mss_msg *msg)
 {
-       int ret, err;
+       unsigned long timeout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS);
+       int ret;
 
-       err = mutex_lock_interruptible(&transaction_lock);
-       if (err)
-               return err;
+       ret = mutex_lock_interruptible(&transaction_lock);
+       if (ret)
+               return ret;
 
        reinit_completion(&sys_controller->c);
 
        ret = mbox_send_message(sys_controller->chan, msg);
-       if (ret >= 0) {
-               if (wait_for_completion_timeout(&sys_controller->c, HZ)) {
-                       ret = 0;
-               } else {
-                       ret = -ETIMEDOUT;
-                       dev_warn(sys_controller->client.dev,
-                                "MPFS sys controller transaction timeout\n");
-               }
+       if (ret < 0) {
+               dev_warn(sys_controller->client.dev, "MPFS sys controller service timeout\n");
+               goto out;
+       }
+
+       /*
+        * Unfortunately, the system controller will only deliver an interrupt
+        * if a service succeeds. mbox_send_message() will block until the busy
+        * flag is gone. If the busy flag is gone but no interrupt has arrived
+        * to trigger the rx callback then the service can be deemed to have
+        * failed.
+        * The caller can then interrogate msg::response::resp_status to
+        * determine the cause of the failure.
+        * mbox_send_message() returns positive integers in the success path, so
+        * ret needs to be cleared if we do get an interrupt.
+        */
+       if (!wait_for_completion_timeout(&sys_controller->c, timeout)) {
+               ret = -EBADMSG;
+               dev_warn(sys_controller->client.dev, "MPFS sys controller service failed\n");
        } else {
-               dev_err(sys_controller->client.dev,
-                       "mpfs sys controller transaction returned %d\n", ret);
+               ret = 0;
        }
 
+out:
        mutex_unlock(&transaction_lock);
 
        return ret;
 }
 EXPORT_SYMBOL(mpfs_blocking_transaction);
 
-static void rx_callback(struct mbox_client *client, void *msg)
+static void mpfs_sys_controller_rx_callback(struct mbox_client *client, void *msg)
 {
        struct mpfs_sys_controller *sys_controller =
                container_of(client, struct mpfs_sys_controller, client);
@@ -66,8 +85,8 @@ static void rx_callback(struct mbox_client *client, void *msg)
 
 static void mpfs_sys_controller_delete(struct kref *kref)
 {
-       struct mpfs_sys_controller *sys_controller = container_of(kref, struct mpfs_sys_controller,
-                                              consumers);
+       struct mpfs_sys_controller *sys_controller =
+               container_of(kref, struct mpfs_sys_controller, consumers);
 
        mbox_free_channel(sys_controller->chan);
        kfree(sys_controller);
@@ -102,8 +121,9 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        sys_controller->client.dev = dev;
-       sys_controller->client.rx_callback = rx_callback;
+       sys_controller->client.rx_callback = mpfs_sys_controller_rx_callback;
        sys_controller->client.tx_block = 1U;
+       sys_controller->client.tx_tout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS);
 
        sys_controller->chan = mbox_request_channel(&sys_controller->client, 0);
        if (IS_ERR(sys_controller->chan)) {
index a8f283086a2191b675f06509bd6fd688f89e25ac..a491718f8064f9b0c347e9851e75a7d8cf6fd246 100644 (file)
@@ -72,7 +72,7 @@ config QCOM_LLCC
 
 config QCOM_KRYO_L2_ACCESSORS
        bool
-       depends on ARCH_QCOM && ARM64 || COMPILE_TEST
+       depends on (ARCH_QCOM || COMPILE_TEST) && ARM64
 
 config QCOM_MDT_LOADER
        tristate
@@ -275,4 +275,8 @@ config QCOM_ICC_BWMON
          the fixed bandwidth votes from cpufreq (CPU nodes) thus achieve high
          memory throughput even with lower CPU frequencies.
 
+config QCOM_INLINE_CRYPTO_ENGINE
+       tristate
+       select QCOM_SCM
+
 endmenu
index 6e88da899f602c303b91ea5b6965916a8985e74f..0f43a88b4894e4675b7e456a08d906890c538829 100644 (file)
@@ -32,3 +32,4 @@ obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
 obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
 obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) +=        kryo-l2-accessors.o
 obj-$(CONFIG_QCOM_ICC_BWMON)   += icc-bwmon.o
+obj-$(CONFIG_QCOM_INLINE_CRYPTO_ENGINE)        += ice.o
index d07be3700db607a93a46708b13ac5466ad98022a..fd58c5b698978765d3213b8689d7db4dab39d415 100644 (file)
 /* Internal sampling clock frequency */
 #define HW_TIMER_HZ                            19200000
 
-#define BWMON_V4_GLOBAL_IRQ_CLEAR              0x008
-#define BWMON_V4_GLOBAL_IRQ_ENABLE             0x00c
+#define BWMON_V4_GLOBAL_IRQ_CLEAR              0x108
+#define BWMON_V4_GLOBAL_IRQ_ENABLE             0x10c
 /*
  * All values here and further are matching regmap fields, so without absolute
  * register offsets.
  */
 #define BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE      BIT(0)
 
+/*
+ * Starting with SDM845, the BWMON4 register space has changed a bit:
+ * the global registers were jammed into the beginning of the monitor region.
+ * To keep the proper offsets, one would have to map <GLOBAL_BASE 0x200> and
+ * <GLOBAL_BASE+0x100 0x300>, which is straight up wrong.
+ * To facilitate for that, while allowing the older, arguably more proper
+ * implementations to work, offset the global registers by -0x100 to avoid
+ * having to map half of the global registers twice.
+ */
+#define BWMON_V4_845_OFFSET                    0x100
+#define BWMON_V4_GLOBAL_IRQ_CLEAR_845          (BWMON_V4_GLOBAL_IRQ_CLEAR - BWMON_V4_845_OFFSET)
+#define BWMON_V4_GLOBAL_IRQ_ENABLE_845         (BWMON_V4_GLOBAL_IRQ_ENABLE - BWMON_V4_845_OFFSET)
+
 #define BWMON_V4_IRQ_STATUS                    0x100
 #define BWMON_V4_IRQ_CLEAR                     0x108
 
 #define BWMON_NEEDS_FORCE_CLEAR                        BIT(1)
 
 enum bwmon_fields {
+       /* Global region fields, keep them at the top */
        F_GLOBAL_IRQ_CLEAR,
        F_GLOBAL_IRQ_ENABLE,
-       F_IRQ_STATUS,
+       F_NUM_GLOBAL_FIELDS,
+
+       /* Monitor region fields */
+       F_IRQ_STATUS = F_NUM_GLOBAL_FIELDS,
        F_IRQ_CLEAR,
        F_IRQ_ENABLE,
        F_ENABLE,
@@ -157,6 +174,9 @@ struct icc_bwmon_data {
 
        const struct regmap_config *regmap_cfg;
        const struct reg_field *regmap_fields;
+
+       const struct regmap_config *global_regmap_cfg;
+       const struct reg_field *global_regmap_fields;
 };
 
 struct icc_bwmon {
@@ -164,8 +184,8 @@ struct icc_bwmon {
        const struct icc_bwmon_data *data;
        int irq;
 
-       struct regmap *regmap;
        struct regmap_field *regs[F_NUM_FIELDS];
+       struct regmap_field *global_regs[F_NUM_GLOBAL_FIELDS];
 
        unsigned int max_bw_kbps;
        unsigned int min_bw_kbps;
@@ -175,8 +195,8 @@ struct icc_bwmon {
 
 /* BWMON v4 */
 static const struct reg_field msm8998_bwmon_reg_fields[] = {
-       [F_GLOBAL_IRQ_CLEAR]    = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR, 0, 0),
-       [F_GLOBAL_IRQ_ENABLE]   = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE, 0, 0),
+       [F_GLOBAL_IRQ_CLEAR]    = {},
+       [F_GLOBAL_IRQ_ENABLE]   = {},
        [F_IRQ_STATUS]          = REG_FIELD(BWMON_V4_IRQ_STATUS, 4, 7),
        [F_IRQ_CLEAR]           = REG_FIELD(BWMON_V4_IRQ_CLEAR, 4, 7),
        [F_IRQ_ENABLE]          = REG_FIELD(BWMON_V4_IRQ_ENABLE, 4, 7),
@@ -202,7 +222,6 @@ static const struct reg_field msm8998_bwmon_reg_fields[] = {
 };
 
 static const struct regmap_range msm8998_bwmon_reg_noread_ranges[] = {
-       regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR, BWMON_V4_GLOBAL_IRQ_CLEAR),
        regmap_reg_range(BWMON_V4_IRQ_CLEAR, BWMON_V4_IRQ_CLEAR),
        regmap_reg_range(BWMON_V4_CLEAR, BWMON_V4_CLEAR),
 };
@@ -222,16 +241,33 @@ static const struct regmap_access_table msm8998_bwmon_reg_volatile_table = {
        .n_yes_ranges   = ARRAY_SIZE(msm8998_bwmon_reg_volatile_ranges),
 };
 
+static const struct reg_field msm8998_bwmon_global_reg_fields[] = {
+       [F_GLOBAL_IRQ_CLEAR]    = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR, 0, 0),
+       [F_GLOBAL_IRQ_ENABLE]   = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE, 0, 0),
+};
+
+static const struct regmap_range msm8998_bwmon_global_reg_noread_ranges[] = {
+       regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR, BWMON_V4_GLOBAL_IRQ_CLEAR),
+};
+
+static const struct regmap_access_table msm8998_bwmon_global_reg_read_table = {
+       .no_ranges      = msm8998_bwmon_global_reg_noread_ranges,
+       .n_no_ranges    = ARRAY_SIZE(msm8998_bwmon_global_reg_noread_ranges),
+};
+
 /*
  * Fill the cache for non-readable registers only as rest does not really
  * matter and can be read from the device.
  */
 static const struct reg_default msm8998_bwmon_reg_defaults[] = {
-       { BWMON_V4_GLOBAL_IRQ_CLEAR, 0x0 },
        { BWMON_V4_IRQ_CLEAR, 0x0 },
        { BWMON_V4_CLEAR, 0x0 },
 };
 
+static const struct reg_default msm8998_bwmon_global_reg_defaults[] = {
+       { BWMON_V4_GLOBAL_IRQ_CLEAR, 0x0 },
+};
+
 static const struct regmap_config msm8998_bwmon_regmap_cfg = {
        .reg_bits               = 32,
        .reg_stride             = 4,
@@ -252,6 +288,93 @@ static const struct regmap_config msm8998_bwmon_regmap_cfg = {
        .cache_type             = REGCACHE_RBTREE,
 };
 
+static const struct regmap_config msm8998_bwmon_global_regmap_cfg = {
+       .reg_bits               = 32,
+       .reg_stride             = 4,
+       .val_bits               = 32,
+       /*
+        * No concurrent access expected - driver has one interrupt handler,
+        * regmap is not shared, no driver or user-space API.
+        */
+       .disable_locking        = true,
+       .rd_table               = &msm8998_bwmon_global_reg_read_table,
+       .reg_defaults           = msm8998_bwmon_global_reg_defaults,
+       .num_reg_defaults       = ARRAY_SIZE(msm8998_bwmon_global_reg_defaults),
+       /*
+        * Cache is necessary for using regmap fields with non-readable
+        * registers.
+        */
+       .cache_type             = REGCACHE_RBTREE,
+};
+
+static const struct reg_field sdm845_cpu_bwmon_reg_fields[] = {
+       [F_GLOBAL_IRQ_CLEAR]    = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR_845, 0, 0),
+       [F_GLOBAL_IRQ_ENABLE]   = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE_845, 0, 0),
+       [F_IRQ_STATUS]          = REG_FIELD(BWMON_V4_IRQ_STATUS, 4, 7),
+       [F_IRQ_CLEAR]           = REG_FIELD(BWMON_V4_IRQ_CLEAR, 4, 7),
+       [F_IRQ_ENABLE]          = REG_FIELD(BWMON_V4_IRQ_ENABLE, 4, 7),
+       /* F_ENABLE covers entire register to disable other features */
+       [F_ENABLE]              = REG_FIELD(BWMON_V4_ENABLE, 0, 31),
+       [F_CLEAR]               = REG_FIELD(BWMON_V4_CLEAR, 0, 1),
+       [F_SAMPLE_WINDOW]       = REG_FIELD(BWMON_V4_SAMPLE_WINDOW, 0, 23),
+       [F_THRESHOLD_HIGH]      = REG_FIELD(BWMON_V4_THRESHOLD_HIGH, 0, 11),
+       [F_THRESHOLD_MED]       = REG_FIELD(BWMON_V4_THRESHOLD_MED, 0, 11),
+       [F_THRESHOLD_LOW]       = REG_FIELD(BWMON_V4_THRESHOLD_LOW, 0, 11),
+       [F_ZONE_ACTIONS_ZONE0]  = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 0, 7),
+       [F_ZONE_ACTIONS_ZONE1]  = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 8, 15),
+       [F_ZONE_ACTIONS_ZONE2]  = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 16, 23),
+       [F_ZONE_ACTIONS_ZONE3]  = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 24, 31),
+       [F_THRESHOLD_COUNT_ZONE0]       = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 0, 7),
+       [F_THRESHOLD_COUNT_ZONE1]       = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 8, 15),
+       [F_THRESHOLD_COUNT_ZONE2]       = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 16, 23),
+       [F_THRESHOLD_COUNT_ZONE3]       = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 24, 31),
+       [F_ZONE0_MAX]           = REG_FIELD(BWMON_V4_ZONE_MAX(0), 0, 11),
+       [F_ZONE1_MAX]           = REG_FIELD(BWMON_V4_ZONE_MAX(1), 0, 11),
+       [F_ZONE2_MAX]           = REG_FIELD(BWMON_V4_ZONE_MAX(2), 0, 11),
+       [F_ZONE3_MAX]           = REG_FIELD(BWMON_V4_ZONE_MAX(3), 0, 11),
+};
+
+static const struct regmap_range sdm845_cpu_bwmon_reg_noread_ranges[] = {
+       regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR_845, BWMON_V4_GLOBAL_IRQ_CLEAR_845),
+       regmap_reg_range(BWMON_V4_IRQ_CLEAR, BWMON_V4_IRQ_CLEAR),
+       regmap_reg_range(BWMON_V4_CLEAR, BWMON_V4_CLEAR),
+};
+
+static const struct regmap_access_table sdm845_cpu_bwmon_reg_read_table = {
+       .no_ranges      = sdm845_cpu_bwmon_reg_noread_ranges,
+       .n_no_ranges    = ARRAY_SIZE(sdm845_cpu_bwmon_reg_noread_ranges),
+};
+
+/*
+ * Fill the cache for non-readable registers only as rest does not really
+ * matter and can be read from the device.
+ */
+static const struct reg_default sdm845_cpu_bwmon_reg_defaults[] = {
+       { BWMON_V4_GLOBAL_IRQ_CLEAR_845, 0x0 },
+       { BWMON_V4_IRQ_CLEAR, 0x0 },
+       { BWMON_V4_CLEAR, 0x0 },
+};
+
+static const struct regmap_config sdm845_cpu_bwmon_regmap_cfg = {
+       .reg_bits               = 32,
+       .reg_stride             = 4,
+       .val_bits               = 32,
+       /*
+        * No concurrent access expected - driver has one interrupt handler,
+        * regmap is not shared, no driver or user-space API.
+        */
+       .disable_locking        = true,
+       .rd_table               = &sdm845_cpu_bwmon_reg_read_table,
+       .volatile_table         = &msm8998_bwmon_reg_volatile_table,
+       .reg_defaults           = sdm845_cpu_bwmon_reg_defaults,
+       .num_reg_defaults       = ARRAY_SIZE(sdm845_cpu_bwmon_reg_defaults),
+       /*
+        * Cache is necessary for using regmap fields with non-readable
+        * registers.
+        */
+       .cache_type             = REGCACHE_RBTREE,
+};
+
 /* BWMON v5 */
 static const struct reg_field sdm845_llcc_bwmon_reg_fields[] = {
        [F_GLOBAL_IRQ_CLEAR]    = {},
@@ -350,6 +473,13 @@ static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all)
 
 static void bwmon_clear_irq(struct icc_bwmon *bwmon)
 {
+       struct regmap_field *global_irq_clr;
+
+       if (bwmon->data->global_regmap_fields)
+               global_irq_clr = bwmon->global_regs[F_GLOBAL_IRQ_CLEAR];
+       else
+               global_irq_clr = bwmon->regs[F_GLOBAL_IRQ_CLEAR];
+
        /*
         * Clear zone and global interrupts. The order and barriers are
         * important. Quoting downstream Qualcomm msm-4.9 tree:
@@ -370,15 +500,22 @@ static void bwmon_clear_irq(struct icc_bwmon *bwmon)
        if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR)
                regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], 0);
        if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
-               regmap_field_force_write(bwmon->regs[F_GLOBAL_IRQ_CLEAR],
+               regmap_field_force_write(global_irq_clr,
                                         BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
 }
 
 static void bwmon_disable(struct icc_bwmon *bwmon)
 {
+       struct regmap_field *global_irq_en;
+
+       if (bwmon->data->global_regmap_fields)
+               global_irq_en = bwmon->global_regs[F_GLOBAL_IRQ_ENABLE];
+       else
+               global_irq_en = bwmon->regs[F_GLOBAL_IRQ_ENABLE];
+
        /* Disable interrupts. Strict ordering, see bwmon_clear_irq(). */
        if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
-               regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], 0x0);
+               regmap_field_write(global_irq_en, 0x0);
        regmap_field_write(bwmon->regs[F_IRQ_ENABLE], 0x0);
 
        /*
@@ -390,10 +527,18 @@ static void bwmon_disable(struct icc_bwmon *bwmon)
 
 static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable)
 {
+       struct regmap_field *global_irq_en;
+
+       if (bwmon->data->global_regmap_fields)
+               global_irq_en = bwmon->global_regs[F_GLOBAL_IRQ_ENABLE];
+       else
+               global_irq_en = bwmon->regs[F_GLOBAL_IRQ_ENABLE];
+
        /* Enable interrupts */
        if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
-               regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE],
+               regmap_field_write(global_irq_en,
                                   BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
+
        regmap_field_write(bwmon->regs[F_IRQ_ENABLE], irq_enable);
 
        /* Enable bwmon */
@@ -556,7 +701,9 @@ static int bwmon_init_regmap(struct platform_device *pdev,
        struct device *dev = &pdev->dev;
        void __iomem *base;
        struct regmap *map;
+       int ret;
 
+       /* Map the monitor base */
        base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(base))
                return dev_err_probe(dev, PTR_ERR(base),
@@ -567,12 +714,35 @@ static int bwmon_init_regmap(struct platform_device *pdev,
                return dev_err_probe(dev, PTR_ERR(map),
                                     "failed to initialize regmap\n");
 
+       BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_global_reg_fields) != F_NUM_GLOBAL_FIELDS);
        BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_reg_fields) != F_NUM_FIELDS);
+       BUILD_BUG_ON(ARRAY_SIZE(sdm845_cpu_bwmon_reg_fields) != F_NUM_FIELDS);
        BUILD_BUG_ON(ARRAY_SIZE(sdm845_llcc_bwmon_reg_fields) != F_NUM_FIELDS);
 
-       return devm_regmap_field_bulk_alloc(dev, map, bwmon->regs,
+       ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->regs,
                                           bwmon->data->regmap_fields,
                                           F_NUM_FIELDS);
+       if (ret)
+               return ret;
+
+       if (bwmon->data->global_regmap_cfg) {
+               /* Map the global base, if separate */
+               base = devm_platform_ioremap_resource(pdev, 1);
+               if (IS_ERR(base))
+                       return dev_err_probe(dev, PTR_ERR(base),
+                                            "failed to map bwmon global registers\n");
+
+               map = devm_regmap_init_mmio(dev, base, bwmon->data->global_regmap_cfg);
+               if (IS_ERR(map))
+                       return dev_err_probe(dev, PTR_ERR(map),
+                                            "failed to initialize global regmap\n");
+
+               ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->global_regs,
+                                                  bwmon->data->global_regmap_fields,
+                                                  F_NUM_GLOBAL_FIELDS);
+       }
+
+       return ret;
 }
 
 static int bwmon_probe(struct platform_device *pdev)
@@ -645,6 +815,21 @@ static const struct icc_bwmon_data msm8998_bwmon_data = {
        .quirks = BWMON_HAS_GLOBAL_IRQ,
        .regmap_fields = msm8998_bwmon_reg_fields,
        .regmap_cfg = &msm8998_bwmon_regmap_cfg,
+       .global_regmap_fields = msm8998_bwmon_global_reg_fields,
+       .global_regmap_cfg = &msm8998_bwmon_global_regmap_cfg,
+};
+
+static const struct icc_bwmon_data sdm845_cpu_bwmon_data = {
+       .sample_ms = 4,
+       .count_unit_kb = 64,
+       .default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */
+       .default_medbw_kbps = 512 * 1024, /* 512 MBps */
+       .default_lowbw_kbps = 0,
+       .zone1_thres_count = 16,
+       .zone3_thres_count = 1,
+       .quirks = BWMON_HAS_GLOBAL_IRQ,
+       .regmap_fields = sdm845_cpu_bwmon_reg_fields,
+       .regmap_cfg = &sdm845_cpu_bwmon_regmap_cfg,
 };
 
 static const struct icc_bwmon_data sdm845_llcc_bwmon_data = {
@@ -673,16 +858,18 @@ static const struct icc_bwmon_data sc7280_llcc_bwmon_data = {
 };
 
 static const struct of_device_id bwmon_of_match[] = {
-       {
-               .compatible = "qcom,msm8998-bwmon",
-               .data = &msm8998_bwmon_data
-       }, {
-               .compatible = "qcom,sdm845-llcc-bwmon",
-               .data = &sdm845_llcc_bwmon_data
-       }, {
-               .compatible = "qcom,sc7280-llcc-bwmon",
-               .data = &sc7280_llcc_bwmon_data
-       },
+       /* BWMONv4, separate monitor and global register spaces */
+       { .compatible = "qcom,msm8998-bwmon", .data = &msm8998_bwmon_data },
+       /* BWMONv4, unified register space */
+       { .compatible = "qcom,sdm845-bwmon", .data = &sdm845_cpu_bwmon_data },
+       /* BWMONv5 */
+       { .compatible = "qcom,sdm845-llcc-bwmon", .data = &sdm845_llcc_bwmon_data },
+       { .compatible = "qcom,sc7280-llcc-bwmon", .data = &sc7280_llcc_bwmon_data },
+
+       /* Compatibles kept for legacy reasons */
+       { .compatible = "qcom,sc7280-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
+       { .compatible = "qcom,sc8280xp-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
+       { .compatible = "qcom,sm8550-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
        {}
 };
 MODULE_DEVICE_TABLE(of, bwmon_of_match);
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
new file mode 100644 (file)
index 0000000..a6123ea
--- /dev/null
@@ -0,0 +1,366 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Qualcomm ICE (Inline Crypto Engine) support.
+ *
+ * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019, Google LLC
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/of_platform.h>
+
+#include <linux/firmware/qcom/qcom_scm.h>
+
+#include <soc/qcom/ice.h>
+
+#define AES_256_XTS_KEY_SIZE                   64
+
+/* QCOM ICE registers */
+#define QCOM_ICE_REG_VERSION                   0x0008
+#define QCOM_ICE_REG_FUSE_SETTING              0x0010
+#define QCOM_ICE_REG_BIST_STATUS               0x0070
+#define QCOM_ICE_REG_ADVANCED_CONTROL          0x1000
+
+/* BIST ("built-in self-test") status flags */
+#define QCOM_ICE_BIST_STATUS_MASK              GENMASK(31, 28)
+
+#define QCOM_ICE_FUSE_SETTING_MASK             0x1
+#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK    0x2
+#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK    0x4
+
+#define qcom_ice_writel(engine, val, reg)      \
+       writel((val), (engine)->base + (reg))
+
+#define qcom_ice_readl(engine, reg)    \
+       readl((engine)->base + (reg))
+
+struct qcom_ice {
+       struct device *dev;
+       void __iomem *base;
+       struct device_link *link;
+
+       struct clk *core_clk;
+};
+
+static bool qcom_ice_check_supported(struct qcom_ice *ice)
+{
+       u32 regval = qcom_ice_readl(ice, QCOM_ICE_REG_VERSION);
+       struct device *dev = ice->dev;
+       int major = FIELD_GET(GENMASK(31, 24), regval);
+       int minor = FIELD_GET(GENMASK(23, 16), regval);
+       int step = FIELD_GET(GENMASK(15, 0), regval);
+
+       /* For now this driver only supports ICE version 3 and 4. */
+       if (major != 3 && major != 4) {
+               dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n",
+                        major, minor, step);
+               return false;
+       }
+
+       dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n",
+                major, minor, step);
+
+       /* If fuses are blown, ICE might not work in the standard way. */
+       regval = qcom_ice_readl(ice, QCOM_ICE_REG_FUSE_SETTING);
+       if (regval & (QCOM_ICE_FUSE_SETTING_MASK |
+                     QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK |
+                     QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) {
+               dev_warn(dev, "Fuses are blown; ICE is unusable!\n");
+               return false;
+       }
+
+       return true;
+}
+
+static void qcom_ice_low_power_mode_enable(struct qcom_ice *ice)
+{
+       u32 regval;
+
+       regval = qcom_ice_readl(ice, QCOM_ICE_REG_ADVANCED_CONTROL);
+
+       /* Enable low power mode sequence */
+       regval |= 0x7000;
+       qcom_ice_writel(ice, regval, QCOM_ICE_REG_ADVANCED_CONTROL);
+}
+
+static void qcom_ice_optimization_enable(struct qcom_ice *ice)
+{
+       u32 regval;
+
+       /* ICE Optimizations Enable Sequence */
+       regval = qcom_ice_readl(ice, QCOM_ICE_REG_ADVANCED_CONTROL);
+       regval |= 0xd807100;
+       /* ICE HPG requires delay before writing */
+       udelay(5);
+       qcom_ice_writel(ice, regval, QCOM_ICE_REG_ADVANCED_CONTROL);
+       udelay(5);
+}
+
+/*
+ * Wait until the ICE BIST (built-in self-test) has completed.
+ *
+ * This may be necessary before ICE can be used.
+ * Note that we don't really care whether the BIST passed or failed;
+ * we really just want to make sure that it isn't still running. This is
+ * because (a) the BIST is a FIPS compliance thing that never fails in
+ * practice, (b) ICE is documented to reject crypto requests if the BIST
+ * fails, so we needn't do it in software too, and (c) properly testing
+ * storage encryption requires testing the full storage stack anyway,
+ * and not relying on hardware-level self-tests.
+ */
+static int qcom_ice_wait_bist_status(struct qcom_ice *ice)
+{
+       u32 regval;
+       int err;
+
+       err = readl_poll_timeout(ice->base + QCOM_ICE_REG_BIST_STATUS,
+                                regval, !(regval & QCOM_ICE_BIST_STATUS_MASK),
+                                50, 5000);
+       if (err)
+               dev_err(ice->dev, "Timed out waiting for ICE self-test to complete\n");
+
+       return err;
+}
+
+int qcom_ice_enable(struct qcom_ice *ice)
+{
+       qcom_ice_low_power_mode_enable(ice);
+       qcom_ice_optimization_enable(ice);
+
+       return qcom_ice_wait_bist_status(ice);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_enable);
+
+int qcom_ice_resume(struct qcom_ice *ice)
+{
+       struct device *dev = ice->dev;
+       int err;
+
+       err = clk_prepare_enable(ice->core_clk);
+       if (err) {
+               dev_err(dev, "failed to enable core clock (%d)\n",
+                       err);
+               return err;
+       }
+
+       return qcom_ice_wait_bist_status(ice);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_resume);
+
+int qcom_ice_suspend(struct qcom_ice *ice)
+{
+       clk_disable_unprepare(ice->core_clk);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_suspend);
+
+int qcom_ice_program_key(struct qcom_ice *ice,
+                        u8 algorithm_id, u8 key_size,
+                        const u8 crypto_key[], u8 data_unit_size,
+                        int slot)
+{
+       struct device *dev = ice->dev;
+       union {
+               u8 bytes[AES_256_XTS_KEY_SIZE];
+               u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)];
+       } key;
+       int i;
+       int err;
+
+       /* Only AES-256-XTS has been tested so far. */
+       if (algorithm_id != QCOM_ICE_CRYPTO_ALG_AES_XTS ||
+           key_size != QCOM_ICE_CRYPTO_KEY_SIZE_256) {
+               dev_err_ratelimited(dev,
+                                   "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
+                                   algorithm_id, key_size);
+               return -EINVAL;
+       }
+
+       memcpy(key.bytes, crypto_key, AES_256_XTS_KEY_SIZE);
+
+       /* The SCM call requires that the key words are encoded in big endian */
+       for (i = 0; i < ARRAY_SIZE(key.words); i++)
+               __cpu_to_be32s(&key.words[i]);
+
+       err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
+                                  QCOM_SCM_ICE_CIPHER_AES_256_XTS,
+                                  data_unit_size);
+
+       memzero_explicit(&key, sizeof(key));
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_program_key);
+
+int qcom_ice_evict_key(struct qcom_ice *ice, int slot)
+{
+       return qcom_scm_ice_invalidate_key(slot);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_evict_key);
+
+static struct qcom_ice *qcom_ice_create(struct device *dev,
+                                       void __iomem *base)
+{
+       struct qcom_ice *engine;
+
+       if (!qcom_scm_is_available())
+               return ERR_PTR(-EPROBE_DEFER);
+
+       if (!qcom_scm_ice_available()) {
+               dev_warn(dev, "ICE SCM interface not found\n");
+               return NULL;
+       }
+
+       engine = devm_kzalloc(dev, sizeof(*engine), GFP_KERNEL);
+       if (!engine)
+               return ERR_PTR(-ENOMEM);
+
+       engine->dev = dev;
+       engine->base = base;
+
+       /*
+        * Legacy DT binding uses different clk names for each consumer,
+        * so lets try those first. If none of those are a match, it means
+        * the we only have one clock and it is part of the dedicated DT node.
+        * Also, enable the clock before we check what HW version the driver
+        * supports.
+        */
+       engine->core_clk = devm_clk_get_optional_enabled(dev, "ice_core_clk");
+       if (!engine->core_clk)
+               engine->core_clk = devm_clk_get_optional_enabled(dev, "ice");
+       if (!engine->core_clk)
+               engine->core_clk = devm_clk_get_enabled(dev, NULL);
+       if (IS_ERR(engine->core_clk))
+               return ERR_CAST(engine->core_clk);
+
+       if (!qcom_ice_check_supported(engine))
+               return ERR_PTR(-EOPNOTSUPP);
+
+       dev_dbg(dev, "Registered Qualcomm Inline Crypto Engine\n");
+
+       return engine;
+}
+
+/**
+ * of_qcom_ice_get() - get an ICE instance from a DT node
+ * @dev: device pointer for the consumer device
+ *
+ * This function will provide an ICE instance either by creating one for the
+ * consumer device if its DT node provides the 'ice' reg range and the 'ice'
+ * clock (for legacy DT style). On the other hand, if consumer provides a
+ * phandle via 'qcom,ice' property to an ICE DT, the ICE instance will already
+ * be created and so this function will return that instead.
+ *
+ * Return: ICE pointer on success, NULL if there is no ICE data provided by the
+ * consumer or ERR_PTR() on error.
+ */
+struct qcom_ice *of_qcom_ice_get(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct qcom_ice *ice;
+       struct device_node *node;
+       struct resource *res;
+       void __iomem *base;
+
+       if (!dev || !dev->of_node)
+               return ERR_PTR(-ENODEV);
+
+       /*
+        * In order to support legacy style devicetree bindings, we need
+        * to create the ICE instance using the consumer device and the reg
+        * range called 'ice' it provides.
+        */
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice");
+       if (res) {
+               base = devm_ioremap_resource(&pdev->dev, res);
+               if (IS_ERR(base))
+                       return ERR_CAST(base);
+
+               /* create ICE instance using consumer dev */
+               return qcom_ice_create(&pdev->dev, base);
+       }
+
+       /*
+        * If the consumer node does not provider an 'ice' reg range
+        * (legacy DT binding), then it must at least provide a phandle
+        * to the ICE devicetree node, otherwise ICE is not supported.
+        */
+       node = of_parse_phandle(dev->of_node, "qcom,ice", 0);
+       if (!node)
+               return NULL;
+
+       pdev = of_find_device_by_node(node);
+       if (!pdev) {
+               dev_err(dev, "Cannot find device node %s\n", node->name);
+               ice = ERR_PTR(-EPROBE_DEFER);
+               goto out;
+       }
+
+       ice = platform_get_drvdata(pdev);
+       if (!ice) {
+               dev_err(dev, "Cannot get ice instance from %s\n",
+                       dev_name(&pdev->dev));
+               platform_device_put(pdev);
+               ice = ERR_PTR(-EPROBE_DEFER);
+               goto out;
+       }
+
+       ice->link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
+       if (!ice->link) {
+               dev_err(&pdev->dev,
+                       "Failed to create device link to consumer %s\n",
+                       dev_name(dev));
+               platform_device_put(pdev);
+               ice = ERR_PTR(-EINVAL);
+       }
+
+out:
+       of_node_put(node);
+
+       return ice;
+}
+EXPORT_SYMBOL_GPL(of_qcom_ice_get);
+
+static int qcom_ice_probe(struct platform_device *pdev)
+{
+       struct qcom_ice *engine;
+       void __iomem *base;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base)) {
+               dev_warn(&pdev->dev, "ICE registers not found\n");
+               return PTR_ERR(base);
+       }
+
+       engine = qcom_ice_create(&pdev->dev, base);
+       if (IS_ERR(engine))
+               return PTR_ERR(engine);
+
+       platform_set_drvdata(pdev, engine);
+
+       return 0;
+}
+
+static const struct of_device_id qcom_ice_of_match_table[] = {
+       { .compatible = "qcom,inline-crypto-engine" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, qcom_ice_of_match_table);
+
+static struct platform_driver qcom_ice_driver = {
+       .probe  = qcom_ice_probe,
+       .driver = {
+               .name = "qcom-ice",
+               .of_match_table = qcom_ice_of_match_table,
+       },
+};
+
+module_platform_driver(qcom_ice_driver);
+
+MODULE_DESCRIPTION("Qualcomm Inline Crypto Engine driver");
+MODULE_LICENSE("GPL");
index 26efe12012a0da443ddd21586c03b56381ed1050..67c19ed2219a6d35d0c6927c8b65c81c9c961f92 100644 (file)
@@ -62,8 +62,6 @@
 #define LLCC_TRP_WRSC_CACHEABLE_EN    0x21f2c
 #define LLCC_TRP_ALGO_CFG8           0x21f30
 
-#define BANK_OFFSET_STRIDE           0x80000
-
 #define LLCC_VERSION_2_0_0_0          0x02000000
 #define LLCC_VERSION_2_1_0_0          0x02010000
 #define LLCC_VERSION_4_1_0_0          0x04010000
@@ -122,10 +120,11 @@ struct llcc_slice_config {
 
 struct qcom_llcc_config {
        const struct llcc_slice_config *sct_data;
-       int size;
-       bool need_llcc_cfg;
        const u32 *reg_offset;
        const struct llcc_edac_reg_offset *edac_reg_offset;
+       int size;
+       bool need_llcc_cfg;
+       bool no_edac;
 };
 
 enum llcc_reg_offset {
@@ -227,6 +226,14 @@ static const struct llcc_slice_config sm6350_data[] =  {
        { LLCC_MODPE,    29,  64, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 },
 };
 
+static const struct llcc_slice_config sm7150_data[] =  {
+       { LLCC_CPUSS,    1,  512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 1 },
+       { LLCC_MDM,      8,  128, 2, 0, 0xF, 0x0, 0, 0, 0, 1, 0 },
+       { LLCC_GPUHTW,   11, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 },
+       { LLCC_GPU,      12, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 },
+       { LLCC_NPU,      23, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 0 },
+};
+
 static const struct llcc_slice_config sm8150_data[] =  {
        {  LLCC_CPUSS,    1, 3072, 1, 1, 0xFFF, 0x0,   0, 0, 0, 1, 1 },
        {  LLCC_VIDSC0,   2, 512,  2, 1, 0xFFF, 0x0,   0, 0, 0, 1, 0 },
@@ -454,6 +461,7 @@ static const struct qcom_llcc_config sdm845_cfg = {
        .need_llcc_cfg  = false,
        .reg_offset     = llcc_v1_reg_offset,
        .edac_reg_offset = &llcc_v1_edac_reg_offset,
+       .no_edac        = true,
 };
 
 static const struct qcom_llcc_config sm6350_cfg = {
@@ -464,6 +472,14 @@ static const struct qcom_llcc_config sm6350_cfg = {
        .edac_reg_offset = &llcc_v1_edac_reg_offset,
 };
 
+static const struct qcom_llcc_config sm7150_cfg = {
+       .sct_data       = sm7150_data,
+       .size           = ARRAY_SIZE(sm7150_data),
+       .need_llcc_cfg  = true,
+       .reg_offset     = llcc_v1_reg_offset,
+       .edac_reg_offset = &llcc_v1_edac_reg_offset,
+};
+
 static const struct qcom_llcc_config sm8150_cfg = {
        .sct_data       = sm8150_data,
        .size           = ARRAY_SIZE(sm8150_data),
@@ -898,8 +914,8 @@ static int qcom_llcc_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
-               const char *name)
+static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev, u8 index,
+                                         const char *name)
 {
        void __iomem *base;
        struct regmap_config llcc_regmap_config = {
@@ -909,7 +925,7 @@ static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
                .fast_io = true,
        };
 
-       base = devm_platform_ioremap_resource_byname(pdev, name);
+       base = devm_platform_ioremap_resource(pdev, index);
        if (IS_ERR(base))
                return ERR_CAST(base);
 
@@ -927,6 +943,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
        const struct llcc_slice_config *llcc_cfg;
        u32 sz;
        u32 version;
+       struct regmap *regmap;
 
        drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
        if (!drv_data) {
@@ -934,21 +951,51 @@ static int qcom_llcc_probe(struct platform_device *pdev)
                goto err;
        }
 
-       drv_data->regmap = qcom_llcc_init_mmio(pdev, "llcc_base");
-       if (IS_ERR(drv_data->regmap)) {
-               ret = PTR_ERR(drv_data->regmap);
+       /* Initialize the first LLCC bank regmap */
+       regmap = qcom_llcc_init_mmio(pdev, 0, "llcc0_base");
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               goto err;
+       }
+
+       cfg = of_device_get_match_data(&pdev->dev);
+
+       ret = regmap_read(regmap, cfg->reg_offset[LLCC_COMMON_STATUS0], &num_banks);
+       if (ret)
+               goto err;
+
+       num_banks &= LLCC_LB_CNT_MASK;
+       num_banks >>= LLCC_LB_CNT_SHIFT;
+       drv_data->num_banks = num_banks;
+
+       drv_data->regmaps = devm_kcalloc(dev, num_banks, sizeof(*drv_data->regmaps), GFP_KERNEL);
+       if (!drv_data->regmaps) {
+               ret = -ENOMEM;
                goto err;
        }
 
-       drv_data->bcast_regmap =
-               qcom_llcc_init_mmio(pdev, "llcc_broadcast_base");
+       drv_data->regmaps[0] = regmap;
+
+       /* Initialize rest of LLCC bank regmaps */
+       for (i = 1; i < num_banks; i++) {
+               char *base = kasprintf(GFP_KERNEL, "llcc%d_base", i);
+
+               drv_data->regmaps[i] = qcom_llcc_init_mmio(pdev, i, base);
+               if (IS_ERR(drv_data->regmaps[i])) {
+                       ret = PTR_ERR(drv_data->regmaps[i]);
+                       kfree(base);
+                       goto err;
+               }
+
+               kfree(base);
+       }
+
+       drv_data->bcast_regmap = qcom_llcc_init_mmio(pdev, i, "llcc_broadcast_base");
        if (IS_ERR(drv_data->bcast_regmap)) {
                ret = PTR_ERR(drv_data->bcast_regmap);
                goto err;
        }
 
-       cfg = of_device_get_match_data(&pdev->dev);
-
        /* Extract version of the IP */
        ret = regmap_read(drv_data->bcast_regmap, cfg->reg_offset[LLCC_COMMON_HW_INFO],
                          &version);
@@ -957,15 +1004,6 @@ static int qcom_llcc_probe(struct platform_device *pdev)
 
        drv_data->version = version;
 
-       ret = regmap_read(drv_data->regmap, cfg->reg_offset[LLCC_COMMON_STATUS0],
-                         &num_banks);
-       if (ret)
-               goto err;
-
-       num_banks &= LLCC_LB_CNT_MASK;
-       num_banks >>= LLCC_LB_CNT_SHIFT;
-       drv_data->num_banks = num_banks;
-
        llcc_cfg = cfg->sct_data;
        sz = cfg->size;
 
@@ -973,16 +1011,6 @@ static int qcom_llcc_probe(struct platform_device *pdev)
                if (llcc_cfg[i].slice_id > drv_data->max_slices)
                        drv_data->max_slices = llcc_cfg[i].slice_id;
 
-       drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32),
-                                                       GFP_KERNEL);
-       if (!drv_data->offsets) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       for (i = 0; i < num_banks; i++)
-               drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
-
        drv_data->bitmap = devm_bitmap_zalloc(dev, drv_data->max_slices,
                                              GFP_KERNEL);
        if (!drv_data->bitmap) {
@@ -1001,7 +1029,14 @@ static int qcom_llcc_probe(struct platform_device *pdev)
                goto err;
 
        drv_data->ecc_irq = platform_get_irq_optional(pdev, 0);
-       if (drv_data->ecc_irq >= 0) {
+
+       /*
+        * On some platforms, the access to EDAC registers will be locked by
+        * the bootloader. So probing the EDAC driver will result in a crash.
+        * Hence, disable the creation of EDAC platform device for the
+        * problematic platforms.
+        */
+       if (!cfg->no_edac) {
                llcc_edac = platform_device_register_data(&pdev->dev,
                                                "qcom_llcc_edac", -1, drv_data,
                                                sizeof(*drv_data));
@@ -1022,6 +1057,7 @@ static const struct of_device_id qcom_llcc_of_match[] = {
        { .compatible = "qcom,sc8280xp-llcc", .data = &sc8280xp_cfg },
        { .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfg },
        { .compatible = "qcom,sm6350-llcc", .data = &sm6350_cfg },
+       { .compatible = "qcom,sm7150-llcc", .data = &sm7150_cfg },
        { .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg },
        { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg },
        { .compatible = "qcom,sm8350-llcc", .data = &sm8350_cfg },
index bb3fb57abcc6561ff1933a3066e86c3c48fd8b58..8bf95df0a56ac9f26cf741740d22af40005a0fdc 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2022, Linaro Ltd
  */
 #include <linux/auxiliary_bus.h>
+#include <linux/of_device.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/rpmsg.h>
 #include <linux/soc/qcom/pdr.h>
 #include <linux/soc/qcom/pmic_glink.h>
 
+enum {
+       PMIC_GLINK_CLIENT_BATT = 0,
+       PMIC_GLINK_CLIENT_ALTMODE,
+       PMIC_GLINK_CLIENT_UCSI,
+};
+
+#define PMIC_GLINK_CLIENT_DEFAULT      (BIT(PMIC_GLINK_CLIENT_BATT) |  \
+                                        BIT(PMIC_GLINK_CLIENT_ALTMODE))
+
 struct pmic_glink {
        struct device *dev;
        struct pdr_handle *pdr;
 
        struct rpmsg_endpoint *ept;
 
+       unsigned long client_mask;
+
        struct auxiliary_device altmode_aux;
        struct auxiliary_device ps_aux;
        struct auxiliary_device ucsi_aux;
@@ -233,6 +245,7 @@ static struct rpmsg_driver pmic_glink_rpmsg_driver = {
 
 static int pmic_glink_probe(struct platform_device *pdev)
 {
+       const unsigned long *match_data;
        struct pdr_service *service;
        struct pmic_glink *pg;
        int ret;
@@ -249,12 +262,27 @@ static int pmic_glink_probe(struct platform_device *pdev)
        mutex_init(&pg->client_lock);
        mutex_init(&pg->state_lock);
 
-       ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode");
-       if (ret)
-               return ret;
-       ret = pmic_glink_add_aux_device(pg, &pg->ps_aux, "power-supply");
-       if (ret)
-               goto out_release_altmode_aux;
+       match_data = (unsigned long *)of_device_get_match_data(&pdev->dev);
+       if (match_data)
+               pg->client_mask = *match_data;
+       else
+               pg->client_mask = PMIC_GLINK_CLIENT_DEFAULT;
+
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) {
+               ret = pmic_glink_add_aux_device(pg, &pg->ucsi_aux, "ucsi");
+               if (ret)
+                       return ret;
+       }
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) {
+               ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode");
+               if (ret)
+                       goto out_release_ucsi_aux;
+       }
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) {
+               ret = pmic_glink_add_aux_device(pg, &pg->ps_aux, "power-supply");
+               if (ret)
+                       goto out_release_altmode_aux;
+       }
 
        pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg);
        if (IS_ERR(pg->pdr)) {
@@ -278,9 +306,14 @@ static int pmic_glink_probe(struct platform_device *pdev)
 out_release_pdr_handle:
        pdr_handle_release(pg->pdr);
 out_release_aux_devices:
-       pmic_glink_del_aux_device(pg, &pg->ps_aux);
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT))
+               pmic_glink_del_aux_device(pg, &pg->ps_aux);
 out_release_altmode_aux:
-       pmic_glink_del_aux_device(pg, &pg->altmode_aux);
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE))
+               pmic_glink_del_aux_device(pg, &pg->altmode_aux);
+out_release_ucsi_aux:
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
+               pmic_glink_del_aux_device(pg, &pg->ucsi_aux);
 
        return ret;
 }
@@ -291,8 +324,12 @@ static int pmic_glink_remove(struct platform_device *pdev)
 
        pdr_handle_release(pg->pdr);
 
-       pmic_glink_del_aux_device(pg, &pg->ps_aux);
-       pmic_glink_del_aux_device(pg, &pg->altmode_aux);
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT))
+               pmic_glink_del_aux_device(pg, &pg->ps_aux);
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE))
+               pmic_glink_del_aux_device(pg, &pg->altmode_aux);
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
+               pmic_glink_del_aux_device(pg, &pg->ucsi_aux);
 
        mutex_lock(&__pmic_glink_lock);
        __pmic_glink = NULL;
@@ -301,8 +338,14 @@ static int pmic_glink_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* Do not handle altmode for now on those platforms */
+static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
+                                                          BIT(PMIC_GLINK_CLIENT_UCSI);
+
 static const struct of_device_id pmic_glink_of_match[] = {
-       { .compatible = "qcom,pmic-glink", },
+       { .compatible = "qcom,sm8450-pmic-glink", .data = &pmic_glink_sm8450_client_mask },
+       { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8450_client_mask },
+       { .compatible = "qcom,pmic-glink" },
        {}
 };
 MODULE_DEVICE_TABLE(of, pmic_glink_of_match);
index 18c856056475ce04ef05919367be1fa91b07b7c9..e376c32cc16eb0cfd55d077ec67f34575d1e31bd 100644 (file)
@@ -395,7 +395,7 @@ static int qmp_cooling_devices_register(struct qmp *qmp)
                return -ENOMEM;
 
        for_each_available_child_of_node(np, child) {
-               if (!of_find_property(child, "#cooling-cells", NULL))
+               if (!of_property_present(child, "#cooling-cells"))
                        continue;
                ret = qmp_cooling_device_add(qmp, &qmp->cooling_devs[count++],
                                             child);
index 290bdefbf28aa148013e5a7304ae8672b6e4e3f1..f1742e5bddb9238465af5ed6e449dc46f331f348 100644 (file)
@@ -114,7 +114,7 @@ struct gsbi_info {
        struct regmap *tcsr;
 };
 
-static const struct of_device_id tcsr_dt_match[] = {
+static const struct of_device_id tcsr_dt_match[] __maybe_unused = {
        { .compatible = "qcom,tcsr-ipq8064", .data = &config_ipq8064},
        { .compatible = "qcom,tcsr-apq8064", .data = &config_apq8064},
        { .compatible = "qcom,tcsr-msm8960", .data = &config_msm8960},
index 538fa182169a4171752df2f3c41b0b4cf30b1c1d..0d31377f178d5c69cd886554b999c010ca71830d 100644 (file)
@@ -31,7 +31,7 @@ struct qcom_rmtfs_mem {
 
        unsigned int client_id;
 
-       unsigned int perms;
+       u64 perms;
 };
 
 static ssize_t qcom_rmtfs_mem_show(struct device *dev,
index 0f8b2249f889479d0ee4e31b32c9101307104203..f93544f6d7961a01e18858f9b8cfee42f3da5645 100644 (file)
@@ -1073,7 +1073,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
        drv->ver.minor = rsc_id & (MINOR_VER_MASK << MINOR_VER_SHIFT);
        drv->ver.minor >>= MINOR_VER_SHIFT;
 
-       if (drv->ver.major == 3 && drv->ver.minor == 0)
+       if (drv->ver.major == 3 && drv->ver.minor >= 0)
                drv->regs = rpmh_rsc_reg_offset_ver_3_0;
        else
                drv->regs = rpmh_rsc_reg_offset_ver_2_7;
index 337b1ad1cd3bfecd4119dd417a4676655f9ee7bf..f8397dcb146cf79069282ec62d1cb2d0f7121684 100644 (file)
 
 #define MAX_CORNER_RPMPD_STATE 6
 
-#define DEFINE_RPMPD_PAIR(_platform, _name, _active, r_type, r_key,    \
-                         r_id)                                         \
-       static struct rpmpd _platform##_##_active;                      \
-       static struct rpmpd _platform##_##_name = {                     \
-               .pd = { .name = #_name, },                              \
-               .peer = &_platform##_##_active,                         \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_##r_key,                                     \
-       };                                                              \
-       static struct rpmpd _platform##_##_active = {                   \
-               .pd = { .name = #_active, },                            \
-               .peer = &_platform##_##_name,                           \
-               .active_only = true,                                    \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_##r_key,                                     \
-       }
-
-#define DEFINE_RPMPD_CORNER(_platform, _name, r_type, r_id)            \
-       static struct rpmpd _platform##_##_name = {                     \
-               .pd = { .name = #_name, },                              \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_CORNER,                                      \
-       }
-
-#define DEFINE_RPMPD_LEVEL(_platform, _name, r_type, r_id)             \
-       static struct rpmpd _platform##_##_name = {                     \
-               .pd = { .name = #_name, },                              \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_LEVEL,                                       \
-       }
-
-#define DEFINE_RPMPD_VFC(_platform, _name, r_type, r_id)               \
-       static struct rpmpd _platform##_##_name = {                     \
-               .pd = { .name = #_name, },                              \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_FLOOR_CORNER,                                \
-       }
-
-#define DEFINE_RPMPD_VFL(_platform, _name, r_type, r_id)               \
-       static struct rpmpd _platform##_##_name = {                     \
-               .pd = { .name = #_name, },                              \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_FLOOR_LEVEL,                                 \
-       }
-
 struct rpmpd_req {
        __le32 key;
        __le32 nbytes;
@@ -99,6 +48,7 @@ struct rpmpd_req {
 
 struct rpmpd {
        struct generic_pm_domain pd;
+       struct generic_pm_domain *parent;
        struct rpmpd *peer;
        const bool active_only;
        unsigned int corner;
@@ -118,19 +68,459 @@ struct rpmpd_desc {
 
 static DEFINE_MUTEX(rpmpd_lock);
 
-/* mdm9607 RPM Power Domains */
-DEFINE_RPMPD_PAIR(mdm9607, vddcx, vddcx_ao, SMPA, LEVEL, 3);
-DEFINE_RPMPD_VFL(mdm9607, vddcx_vfl, SMPA, 3);
+/* CX */
+static struct rpmpd cx_rwcx0_lvl_ao;
+static struct rpmpd cx_rwcx0_lvl = {
+       .pd = { .name = "cx", },
+       .peer = &cx_rwcx0_lvl_ao,
+       .res_type = RPMPD_RWCX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_rwcx0_lvl_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_rwcx0_lvl,
+       .active_only = true,
+       .res_type = RPMPD_RWCX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s1a_corner_ao;
+static struct rpmpd cx_s1a_corner = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s1a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s1a_corner_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s1a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s2a_corner_ao;
+static struct rpmpd cx_s2a_corner = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s2a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s2a_corner_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s2a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s2a_lvl_ao;
+static struct rpmpd cx_s2a_lvl = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s2a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s2a_lvl_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s2a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s3a_lvl_ao;
+static struct rpmpd cx_s3a_lvl = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s3a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 3,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s3a_lvl_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s3a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 3,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_rwcx0_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_RWCX,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd cx_rwsc2_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_RWSC,
+       .res_id = 2,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd cx_s1a_vfc = {
+       .pd = { .name = "cx_vfc", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd cx_s2a_vfc = {
+       .pd = { .name = "cx_vfc", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd cx_s2a_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd cx_s3a_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 3,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* G(F)X */
+static struct rpmpd gfx_s2b_corner = {
+       .pd = { .name = "gfx", },
+       .res_type = RPMPD_SMPB,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd gfx_s2b_vfc = {
+       .pd = { .name = "gfx_vfc", },
+       .res_type = RPMPD_SMPB,
+       .res_id = 2,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd mx_rwmx0_lvl;
+static struct rpmpd gx_rwgx0_lvl_ao;
+static struct rpmpd gx_rwgx0_lvl = {
+       .pd = { .name = "gx", },
+       .peer = &gx_rwgx0_lvl_ao,
+       .res_type = RPMPD_RWGX,
+       .parent = &mx_rwmx0_lvl.pd,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_rwmx0_lvl_ao;
+static struct rpmpd gx_rwgx0_lvl_ao = {
+       .pd = { .name = "gx_ao", },
+       .peer = &gx_rwgx0_lvl,
+       .parent = &mx_rwmx0_lvl_ao.pd,
+       .active_only = true,
+       .res_type = RPMPD_RWGX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+/* MX */
+static struct rpmpd mx_l3a_corner_ao;
+static struct rpmpd mx_l3a_corner = {
+       .pd = { .name = "mx", },
+       .peer = &mx_l3a_corner_ao,
+       .res_type = RPMPD_LDOA,
+       .res_id = 3,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_l3a_corner_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_l3a_corner,
+       .active_only = true,
+       .res_type = RPMPD_LDOA,
+       .res_id = 3,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_l12a_lvl_ao;
+static struct rpmpd mx_l12a_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_l12a_lvl_ao,
+       .res_type = RPMPD_LDOA,
+       .res_id = 12,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_l12a_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_l12a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_LDOA,
+       .res_id = 12,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s2a_corner_ao;
+static struct rpmpd mx_s2a_corner = {
+       .pd = { .name = "mx", },
+       .peer = &mx_s2a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_s2a_corner_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_s2a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_rwmx0_lvl_ao;
+static struct rpmpd mx_rwmx0_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_rwmx0_lvl_ao,
+       .res_type = RPMPD_RWMX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_rwmx0_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_rwmx0_lvl,
+       .active_only = true,
+       .res_type = RPMPD_RWMX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s6a_lvl_ao;
+static struct rpmpd mx_s6a_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_s6a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 6,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s6a_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_s6a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 6,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s7a_lvl_ao;
+static struct rpmpd mx_s7a_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_s7a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 7,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s7a_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_s7a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 7,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_l12a_vfl = {
+       .pd = { .name = "mx_vfl", },
+       .res_type = RPMPD_LDOA,
+       .res_id = 12,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd mx_rwmx0_vfl = {
+       .pd = { .name = "mx_vfl", },
+       .res_type = RPMPD_RWMX,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd mx_rwsm6_vfl = {
+       .pd = { .name = "mx_vfl", },
+       .res_type = RPMPD_RWSM,
+       .res_id = 6,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* MD */
+static struct rpmpd md_s1a_corner_ao;
+static struct rpmpd md_s1a_corner = {
+       .pd = { .name = "md", },
+       .peer = &md_s1a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd md_s1a_corner_ao = {
+       .pd = { .name = "md_ao", },
+       .peer = &md_s1a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .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,
+};
+
+static struct rpmpd md_s1a_vfc = {
+       .pd = { .name = "md_vfc", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_FLOOR_CORNER,
+};
+
+/* LPI_CX */
+static struct rpmpd lpi_cx_rwlc0_lvl = {
+       .pd = { .name = "lpi_cx", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd lpi_cx_rwlc0_vfl = {
+       .pd = { .name = "lpi_cx_vfl", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* LPI_MX */
+static struct rpmpd lpi_mx_rwlm0_lvl = {
+       .pd = { .name = "lpi_mx", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd lpi_mx_rwlm0_vfl = {
+       .pd = { .name = "lpi_mx_vfl", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* SSC_CX */
+static struct rpmpd ssc_cx_l26a_corner = {
+       .pd = { .name = "ssc_cx", },
+       .res_type = RPMPD_LDOA,
+       .res_id = 26,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd ssc_cx_rwlc0_lvl = {
+       .pd = { .name = "ssc_cx", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_cx_rwsc0_lvl = {
+       .pd = { .name = "ssc_cx", },
+       .res_type = RPMPD_RWSC,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_cx_l26a_vfc = {
+       .pd = { .name = "ssc_cx_vfc", },
+       .res_type = RPMPD_LDOA,
+       .res_id = 26,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd ssc_cx_rwlc0_vfl = {
+       .pd = { .name = "ssc_cx_vfl", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd ssc_cx_rwsc0_vfl = {
+       .pd = { .name = "ssc_cx_vfl", },
+       .res_type = RPMPD_RWSC,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* SSC_MX */
+static struct rpmpd ssc_mx_rwlm0_lvl = {
+       .pd = { .name = "ssc_mx", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_mx_rwsm0_lvl = {
+       .pd = { .name = "ssc_mx", },
+       .res_type = RPMPD_RWSM,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_mx_rwlm0_vfl = {
+       .pd = { .name = "ssc_mx_vfl", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd ssc_mx_rwsm0_vfl = {
+       .pd = { .name = "ssc_mx_vfl", },
+       .res_type = RPMPD_RWSM,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
 
-DEFINE_RPMPD_PAIR(mdm9607, vddmx, vddmx_ao, LDOA, LEVEL, 12);
-DEFINE_RPMPD_VFL(mdm9607, vddmx_vfl, LDOA, 12);
 static struct rpmpd *mdm9607_rpmpds[] = {
-       [MDM9607_VDDCX] =       &mdm9607_vddcx,
-       [MDM9607_VDDCX_AO] =    &mdm9607_vddcx_ao,
-       [MDM9607_VDDCX_VFL] =   &mdm9607_vddcx_vfl,
-       [MDM9607_VDDMX] =       &mdm9607_vddmx,
-       [MDM9607_VDDMX_AO] =    &mdm9607_vddmx_ao,
-       [MDM9607_VDDMX_VFL] =   &mdm9607_vddmx_vfl,
+       [MDM9607_VDDCX] =       &cx_s3a_lvl,
+       [MDM9607_VDDCX_AO] =    &cx_s3a_lvl_ao,
+       [MDM9607_VDDCX_VFL] =   &cx_s3a_vfl,
+       [MDM9607_VDDMX] =       &mx_l12a_lvl,
+       [MDM9607_VDDMX_AO] =    &mx_l12a_lvl_ao,
+       [MDM9607_VDDMX_VFL] =   &mx_l12a_vfl,
 };
 
 static const struct rpmpd_desc mdm9607_desc = {
@@ -139,14 +529,10 @@ static const struct rpmpd_desc mdm9607_desc = {
        .max_state = RPM_SMD_LEVEL_TURBO,
 };
 
-/* msm8226 RPM Power Domains */
-DEFINE_RPMPD_PAIR(msm8226, vddcx, vddcx_ao, SMPA, CORNER, 1);
-DEFINE_RPMPD_VFC(msm8226, vddcx_vfc, SMPA, 1);
-
 static struct rpmpd *msm8226_rpmpds[] = {
-       [MSM8226_VDDCX] =       &msm8226_vddcx,
-       [MSM8226_VDDCX_AO] =    &msm8226_vddcx_ao,
-       [MSM8226_VDDCX_VFC] =   &msm8226_vddcx_vfc,
+       [MSM8226_VDDCX] =       &cx_s1a_corner,
+       [MSM8226_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8226_VDDCX_VFC] =   &cx_s1a_vfc,
 };
 
 static const struct rpmpd_desc msm8226_desc = {
@@ -155,24 +541,15 @@ static const struct rpmpd_desc msm8226_desc = {
        .max_state = MAX_CORNER_RPMPD_STATE,
 };
 
-/* msm8939 RPM Power Domains */
-DEFINE_RPMPD_PAIR(msm8939, vddmd, vddmd_ao, SMPA, CORNER, 1);
-DEFINE_RPMPD_VFC(msm8939, vddmd_vfc, SMPA, 1);
-
-DEFINE_RPMPD_PAIR(msm8939, vddcx, vddcx_ao, SMPA, CORNER, 2);
-DEFINE_RPMPD_VFC(msm8939, vddcx_vfc, SMPA, 2);
-
-DEFINE_RPMPD_PAIR(msm8939, vddmx, vddmx_ao, LDOA, CORNER, 3);
-
 static struct rpmpd *msm8939_rpmpds[] = {
-       [MSM8939_VDDMDCX] =     &msm8939_vddmd,
-       [MSM8939_VDDMDCX_AO] =  &msm8939_vddmd_ao,
-       [MSM8939_VDDMDCX_VFC] = &msm8939_vddmd_vfc,
-       [MSM8939_VDDCX] =       &msm8939_vddcx,
-       [MSM8939_VDDCX_AO] =    &msm8939_vddcx_ao,
-       [MSM8939_VDDCX_VFC] =   &msm8939_vddcx_vfc,
-       [MSM8939_VDDMX] =       &msm8939_vddmx,
-       [MSM8939_VDDMX_AO] =    &msm8939_vddmx_ao,
+       [MSM8939_VDDMDCX] =     &md_s1a_corner,
+       [MSM8939_VDDMDCX_AO] =  &md_s1a_corner_ao,
+       [MSM8939_VDDMDCX_VFC] = &md_s1a_vfc,
+       [MSM8939_VDDCX] =       &cx_s2a_corner,
+       [MSM8939_VDDCX_AO] =    &cx_s2a_corner_ao,
+       [MSM8939_VDDCX_VFC] =   &cx_s2a_vfc,
+       [MSM8939_VDDMX] =       &mx_l3a_corner,
+       [MSM8939_VDDMX_AO] =    &mx_l3a_corner_ao,
 };
 
 static const struct rpmpd_desc msm8939_desc = {
@@ -181,18 +558,12 @@ static const struct rpmpd_desc msm8939_desc = {
        .max_state = MAX_CORNER_RPMPD_STATE,
 };
 
-/* msm8916 RPM Power Domains */
-DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
-DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
-
-DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
-
 static struct rpmpd *msm8916_rpmpds[] = {
-       [MSM8916_VDDCX] =       &msm8916_vddcx,
-       [MSM8916_VDDCX_AO] =    &msm8916_vddcx_ao,
-       [MSM8916_VDDCX_VFC] =   &msm8916_vddcx_vfc,
-       [MSM8916_VDDMX] =       &msm8916_vddmx,
-       [MSM8916_VDDMX_AO] =    &msm8916_vddmx_ao,
+       [MSM8916_VDDCX] =       &cx_s1a_corner,
+       [MSM8916_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8916_VDDCX_VFC] =   &cx_s1a_vfc,
+       [MSM8916_VDDMX] =       &mx_l3a_corner,
+       [MSM8916_VDDMX_AO] =    &mx_l3a_corner_ao,
 };
 
 static const struct rpmpd_desc msm8916_desc = {
@@ -201,21 +572,14 @@ static const struct rpmpd_desc msm8916_desc = {
        .max_state = MAX_CORNER_RPMPD_STATE,
 };
 
-/* msm8953 RPM Power Domains */
-DEFINE_RPMPD_PAIR(msm8953, vddmd, vddmd_ao, SMPA, LEVEL, 1);
-DEFINE_RPMPD_PAIR(msm8953, vddcx, vddcx_ao, SMPA, LEVEL, 2);
-DEFINE_RPMPD_PAIR(msm8953, vddmx, vddmx_ao, SMPA, LEVEL, 7);
-
-DEFINE_RPMPD_VFL(msm8953, vddcx_vfl, SMPA, 2);
-
 static struct rpmpd *msm8953_rpmpds[] = {
-       [MSM8953_VDDMD] =       &msm8953_vddmd,
-       [MSM8953_VDDMD_AO] =    &msm8953_vddmd_ao,
-       [MSM8953_VDDCX] =       &msm8953_vddcx,
-       [MSM8953_VDDCX_AO] =    &msm8953_vddcx_ao,
-       [MSM8953_VDDCX_VFL] =   &msm8953_vddcx_vfl,
-       [MSM8953_VDDMX] =       &msm8953_vddmx,
-       [MSM8953_VDDMX_AO] =    &msm8953_vddmx_ao,
+       [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,
 };
 
 static const struct rpmpd_desc msm8953_desc = {
@@ -224,20 +588,13 @@ static const struct rpmpd_desc msm8953_desc = {
        .max_state = RPM_SMD_LEVEL_TURBO,
 };
 
-/* msm8976 RPM Power Domains */
-DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
-DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
-
-DEFINE_RPMPD_VFL(msm8976, vddcx_vfl, RWSC, 2);
-DEFINE_RPMPD_VFL(msm8976, vddmx_vfl, RWSM, 6);
-
 static struct rpmpd *msm8976_rpmpds[] = {
-       [MSM8976_VDDCX] =       &msm8976_vddcx,
-       [MSM8976_VDDCX_AO] =    &msm8976_vddcx_ao,
-       [MSM8976_VDDCX_VFL] =   &msm8976_vddcx_vfl,
-       [MSM8976_VDDMX] =       &msm8976_vddmx,
-       [MSM8976_VDDMX_AO] =    &msm8976_vddmx_ao,
-       [MSM8976_VDDMX_VFL] =   &msm8976_vddmx_vfl,
+       [MSM8976_VDDCX] =       &cx_s2a_lvl,
+       [MSM8976_VDDCX_AO] =    &cx_s2a_lvl_ao,
+       [MSM8976_VDDCX_VFL] =   &cx_rwsc2_vfl,
+       [MSM8976_VDDMX] =       &mx_s6a_lvl,
+       [MSM8976_VDDMX_AO] =    &mx_s6a_lvl_ao,
+       [MSM8976_VDDMX_VFL] =   &mx_rwsm6_vfl,
 };
 
 static const struct rpmpd_desc msm8976_desc = {
@@ -246,23 +603,16 @@ static const struct rpmpd_desc msm8976_desc = {
        .max_state = RPM_SMD_LEVEL_TURBO_HIGH,
 };
 
-/* msm8994 RPM Power domains */
-DEFINE_RPMPD_PAIR(msm8994, vddcx, vddcx_ao, SMPA, CORNER, 1);
-DEFINE_RPMPD_PAIR(msm8994, vddmx, vddmx_ao, SMPA, CORNER, 2);
-/* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
-DEFINE_RPMPD_CORNER(msm8994, vddgfx, SMPB, 2);
-
-DEFINE_RPMPD_VFC(msm8994, vddcx_vfc, SMPA, 1);
-DEFINE_RPMPD_VFC(msm8994, vddgfx_vfc, SMPB, 2);
-
 static struct rpmpd *msm8994_rpmpds[] = {
-       [MSM8994_VDDCX] =       &msm8994_vddcx,
-       [MSM8994_VDDCX_AO] =    &msm8994_vddcx_ao,
-       [MSM8994_VDDCX_VFC] =   &msm8994_vddcx_vfc,
-       [MSM8994_VDDMX] =       &msm8994_vddmx,
-       [MSM8994_VDDMX_AO] =    &msm8994_vddmx_ao,
-       [MSM8994_VDDGFX] =      &msm8994_vddgfx,
-       [MSM8994_VDDGFX_VFC] =  &msm8994_vddgfx_vfc,
+       [MSM8994_VDDCX] =       &cx_s1a_corner,
+       [MSM8994_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8994_VDDCX_VFC] =   &cx_s1a_vfc,
+       [MSM8994_VDDMX] =       &mx_s2a_corner,
+       [MSM8994_VDDMX_AO] =    &mx_s2a_corner_ao,
+
+       /* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
+       [MSM8994_VDDGFX] =      &gfx_s2b_corner,
+       [MSM8994_VDDGFX_VFC] =  &gfx_s2b_vfc,
 };
 
 static const struct rpmpd_desc msm8994_desc = {
@@ -271,22 +621,14 @@ static const struct rpmpd_desc msm8994_desc = {
        .max_state = MAX_CORNER_RPMPD_STATE,
 };
 
-/* msm8996 RPM Power domains */
-DEFINE_RPMPD_PAIR(msm8996, vddcx, vddcx_ao, SMPA, CORNER, 1);
-DEFINE_RPMPD_PAIR(msm8996, vddmx, vddmx_ao, SMPA, CORNER, 2);
-DEFINE_RPMPD_CORNER(msm8996, vddsscx, LDOA, 26);
-
-DEFINE_RPMPD_VFC(msm8996, vddcx_vfc, SMPA, 1);
-DEFINE_RPMPD_VFC(msm8996, vddsscx_vfc, LDOA, 26);
-
 static struct rpmpd *msm8996_rpmpds[] = {
-       [MSM8996_VDDCX] =       &msm8996_vddcx,
-       [MSM8996_VDDCX_AO] =    &msm8996_vddcx_ao,
-       [MSM8996_VDDCX_VFC] =   &msm8996_vddcx_vfc,
-       [MSM8996_VDDMX] =       &msm8996_vddmx,
-       [MSM8996_VDDMX_AO] =    &msm8996_vddmx_ao,
-       [MSM8996_VDDSSCX] =     &msm8996_vddsscx,
-       [MSM8996_VDDSSCX_VFC] = &msm8996_vddsscx_vfc,
+       [MSM8996_VDDCX] =       &cx_s1a_corner,
+       [MSM8996_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8996_VDDCX_VFC] =   &cx_s1a_vfc,
+       [MSM8996_VDDMX] =       &mx_s2a_corner,
+       [MSM8996_VDDMX_AO] =    &mx_s2a_corner_ao,
+       [MSM8996_VDDSSCX] =     &ssc_cx_l26a_corner,
+       [MSM8996_VDDSSCX_VFC] = &ssc_cx_l26a_vfc,
 };
 
 static const struct rpmpd_desc msm8996_desc = {
@@ -295,30 +637,17 @@ static const struct rpmpd_desc msm8996_desc = {
        .max_state = MAX_CORNER_RPMPD_STATE,
 };
 
-/* msm8998 RPM Power domains */
-DEFINE_RPMPD_PAIR(msm8998, vddcx, vddcx_ao, RWCX, LEVEL, 0);
-DEFINE_RPMPD_VFL(msm8998, vddcx_vfl, RWCX, 0);
-
-DEFINE_RPMPD_PAIR(msm8998, vddmx, vddmx_ao, RWMX, LEVEL, 0);
-DEFINE_RPMPD_VFL(msm8998, vddmx_vfl, RWMX, 0);
-
-DEFINE_RPMPD_LEVEL(msm8998, vdd_ssccx, RWSC, 0);
-DEFINE_RPMPD_VFL(msm8998, vdd_ssccx_vfl, RWSC, 0);
-
-DEFINE_RPMPD_LEVEL(msm8998, vdd_sscmx, RWSM, 0);
-DEFINE_RPMPD_VFL(msm8998, vdd_sscmx_vfl, RWSM, 0);
-
 static struct rpmpd *msm8998_rpmpds[] = {
-       [MSM8998_VDDCX] =               &msm8998_vddcx,
-       [MSM8998_VDDCX_AO] =            &msm8998_vddcx_ao,
-       [MSM8998_VDDCX_VFL] =           &msm8998_vddcx_vfl,
-       [MSM8998_VDDMX] =               &msm8998_vddmx,
-       [MSM8998_VDDMX_AO] =            &msm8998_vddmx_ao,
-       [MSM8998_VDDMX_VFL] =           &msm8998_vddmx_vfl,
-       [MSM8998_SSCCX] =               &msm8998_vdd_ssccx,
-       [MSM8998_SSCCX_VFL] =           &msm8998_vdd_ssccx_vfl,
-       [MSM8998_SSCMX] =               &msm8998_vdd_sscmx,
-       [MSM8998_SSCMX_VFL] =           &msm8998_vdd_sscmx_vfl,
+       [MSM8998_VDDCX] =       &cx_rwcx0_lvl,
+       [MSM8998_VDDCX_AO] =    &cx_rwcx0_lvl_ao,
+       [MSM8998_VDDCX_VFL] =   &cx_rwcx0_vfl,
+       [MSM8998_VDDMX] =       &mx_rwmx0_lvl,
+       [MSM8998_VDDMX_AO] =    &mx_rwmx0_lvl_ao,
+       [MSM8998_VDDMX_VFL] =   &mx_rwmx0_vfl,
+       [MSM8998_SSCCX] =       &ssc_cx_rwsc0_lvl,
+       [MSM8998_SSCCX_VFL] =   &ssc_cx_rwsc0_vfl,
+       [MSM8998_SSCMX] =       &ssc_mx_rwsm0_lvl,
+       [MSM8998_SSCMX_VFL] =   &ssc_mx_rwsm0_vfl,
 };
 
 static const struct rpmpd_desc msm8998_desc = {
@@ -327,24 +656,14 @@ static const struct rpmpd_desc msm8998_desc = {
        .max_state = RPM_SMD_LEVEL_BINNING,
 };
 
-/* qcs404 RPM Power domains */
-DEFINE_RPMPD_PAIR(qcs404, vddmx, vddmx_ao, RWMX, LEVEL, 0);
-DEFINE_RPMPD_VFL(qcs404, vddmx_vfl, RWMX, 0);
-
-DEFINE_RPMPD_LEVEL(qcs404, vdd_lpicx, RWLC, 0);
-DEFINE_RPMPD_VFL(qcs404, vdd_lpicx_vfl, RWLC, 0);
-
-DEFINE_RPMPD_LEVEL(qcs404, vdd_lpimx, RWLM, 0);
-DEFINE_RPMPD_VFL(qcs404, vdd_lpimx_vfl, RWLM, 0);
-
 static struct rpmpd *qcs404_rpmpds[] = {
-       [QCS404_VDDMX] = &qcs404_vddmx,
-       [QCS404_VDDMX_AO] = &qcs404_vddmx_ao,
-       [QCS404_VDDMX_VFL] = &qcs404_vddmx_vfl,
-       [QCS404_LPICX] = &qcs404_vdd_lpicx,
-       [QCS404_LPICX_VFL] = &qcs404_vdd_lpicx_vfl,
-       [QCS404_LPIMX] = &qcs404_vdd_lpimx,
-       [QCS404_LPIMX_VFL] = &qcs404_vdd_lpimx_vfl,
+       [QCS404_VDDMX] =        &mx_rwmx0_lvl,
+       [QCS404_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [QCS404_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [QCS404_LPICX] =        &lpi_cx_rwlc0_lvl,
+       [QCS404_LPICX_VFL] =    &lpi_cx_rwlc0_vfl,
+       [QCS404_LPIMX] =        &lpi_mx_rwlm0_lvl,
+       [QCS404_LPIMX_VFL] =    &lpi_mx_rwlm0_vfl,
 };
 
 static const struct rpmpd_desc qcs404_desc = {
@@ -353,30 +672,17 @@ static const struct rpmpd_desc qcs404_desc = {
        .max_state = RPM_SMD_LEVEL_BINNING,
 };
 
-/* sdm660 RPM Power domains */
-DEFINE_RPMPD_PAIR(sdm660, vddcx, vddcx_ao, RWCX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sdm660, vddcx_vfl, RWCX, 0);
-
-DEFINE_RPMPD_PAIR(sdm660, vddmx, vddmx_ao, RWMX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sdm660, vddmx_vfl, RWMX, 0);
-
-DEFINE_RPMPD_LEVEL(sdm660, vdd_ssccx, RWLC, 0);
-DEFINE_RPMPD_VFL(sdm660, vdd_ssccx_vfl, RWLC, 0);
-
-DEFINE_RPMPD_LEVEL(sdm660, vdd_sscmx, RWLM, 0);
-DEFINE_RPMPD_VFL(sdm660, vdd_sscmx_vfl, RWLM, 0);
-
 static struct rpmpd *sdm660_rpmpds[] = {
-       [SDM660_VDDCX] =                &sdm660_vddcx,
-       [SDM660_VDDCX_AO] =             &sdm660_vddcx_ao,
-       [SDM660_VDDCX_VFL] =            &sdm660_vddcx_vfl,
-       [SDM660_VDDMX] =                &sdm660_vddmx,
-       [SDM660_VDDMX_AO] =             &sdm660_vddmx_ao,
-       [SDM660_VDDMX_VFL] =            &sdm660_vddmx_vfl,
-       [SDM660_SSCCX] =                &sdm660_vdd_ssccx,
-       [SDM660_SSCCX_VFL] =            &sdm660_vdd_ssccx_vfl,
-       [SDM660_SSCMX] =                &sdm660_vdd_sscmx,
-       [SDM660_SSCMX_VFL] =            &sdm660_vdd_sscmx_vfl,
+       [SDM660_VDDCX] =        &cx_rwcx0_lvl,
+       [SDM660_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SDM660_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SDM660_VDDMX] =        &mx_rwmx0_lvl,
+       [SDM660_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SDM660_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [SDM660_SSCCX] =        &ssc_cx_rwlc0_lvl,
+       [SDM660_SSCCX_VFL] =    &ssc_cx_rwlc0_vfl,
+       [SDM660_SSCMX] =        &ssc_mx_rwlm0_lvl,
+       [SDM660_SSCMX_VFL] =    &ssc_mx_rwlm0_vfl,
 };
 
 static const struct rpmpd_desc sdm660_desc = {
@@ -385,25 +691,15 @@ static const struct rpmpd_desc sdm660_desc = {
        .max_state = RPM_SMD_LEVEL_TURBO,
 };
 
-/* sm4250/6115 RPM Power domains */
-DEFINE_RPMPD_PAIR(sm6115, vddcx, vddcx_ao, RWCX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sm6115, vddcx_vfl, RWCX, 0);
-
-DEFINE_RPMPD_PAIR(sm6115, vddmx, vddmx_ao, RWMX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sm6115, vddmx_vfl, RWMX, 0);
-
-DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_cx, RWLC, 0);
-DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_mx, RWLM, 0);
-
 static struct rpmpd *sm6115_rpmpds[] = {
-       [SM6115_VDDCX] =                &sm6115_vddcx,
-       [SM6115_VDDCX_AO] =             &sm6115_vddcx_ao,
-       [SM6115_VDDCX_VFL] =            &sm6115_vddcx_vfl,
-       [SM6115_VDDMX] =                &sm6115_vddmx,
-       [SM6115_VDDMX_AO] =             &sm6115_vddmx_ao,
-       [SM6115_VDDMX_VFL] =            &sm6115_vddmx_vfl,
-       [SM6115_VDD_LPI_CX] =           &sm6115_vdd_lpi_cx,
-       [SM6115_VDD_LPI_MX] =           &sm6115_vdd_lpi_mx,
+       [SM6115_VDDCX] =        &cx_rwcx0_lvl,
+       [SM6115_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SM6115_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SM6115_VDDMX] =        &mx_rwmx0_lvl,
+       [SM6115_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SM6115_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [SM6115_VDD_LPI_CX] =   &lpi_cx_rwlc0_lvl,
+       [SM6115_VDD_LPI_MX] =   &lpi_mx_rwlm0_lvl,
 };
 
 static const struct rpmpd_desc sm6115_desc = {
@@ -412,20 +708,13 @@ static const struct rpmpd_desc sm6115_desc = {
        .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
 };
 
-/* sm6125 RPM Power domains */
-DEFINE_RPMPD_PAIR(sm6125, vddcx, vddcx_ao, RWCX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sm6125, vddcx_vfl, RWCX, 0);
-
-DEFINE_RPMPD_PAIR(sm6125, vddmx, vddmx_ao, RWMX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sm6125, vddmx_vfl, RWMX, 0);
-
 static struct rpmpd *sm6125_rpmpds[] = {
-       [SM6125_VDDCX] =                &sm6125_vddcx,
-       [SM6125_VDDCX_AO] =             &sm6125_vddcx_ao,
-       [SM6125_VDDCX_VFL] =            &sm6125_vddcx_vfl,
-       [SM6125_VDDMX] =                &sm6125_vddmx,
-       [SM6125_VDDMX_AO] =             &sm6125_vddmx_ao,
-       [SM6125_VDDMX_VFL] =            &sm6125_vddmx_vfl,
+       [SM6125_VDDCX] =        &cx_rwcx0_lvl,
+       [SM6125_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SM6125_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SM6125_VDDMX] =        &mx_rwmx0_lvl,
+       [SM6125_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SM6125_VDDMX_VFL] =    &mx_rwmx0_vfl,
 };
 
 static const struct rpmpd_desc sm6125_desc = {
@@ -434,18 +723,17 @@ static const struct rpmpd_desc sm6125_desc = {
        .max_state = RPM_SMD_LEVEL_BINNING,
 };
 
-DEFINE_RPMPD_PAIR(sm6375, vddgx, vddgx_ao, RWGX, LEVEL, 0);
 static struct rpmpd *sm6375_rpmpds[] = {
-       [SM6375_VDDCX] = &sm6125_vddcx,
-       [SM6375_VDDCX_AO] = &sm6125_vddcx_ao,
-       [SM6375_VDDCX_VFL] = &sm6125_vddcx_vfl,
-       [SM6375_VDDMX] = &sm6125_vddmx,
-       [SM6375_VDDMX_AO] = &sm6125_vddmx_ao,
-       [SM6375_VDDMX_VFL] = &sm6125_vddmx_vfl,
-       [SM6375_VDDGX] = &sm6375_vddgx,
-       [SM6375_VDDGX_AO] = &sm6375_vddgx_ao,
-       [SM6375_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
-       [SM6375_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
+       [SM6375_VDDCX] =        &cx_rwcx0_lvl,
+       [SM6375_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SM6375_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SM6375_VDDMX] =        &mx_rwmx0_lvl,
+       [SM6375_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SM6375_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [SM6375_VDDGX] =        &gx_rwgx0_lvl,
+       [SM6375_VDDGX_AO] =     &gx_rwgx0_lvl_ao,
+       [SM6375_VDD_LPI_CX] =   &lpi_cx_rwlc0_lvl,
+       [SM6375_VDD_LPI_MX] =   &lpi_mx_rwlm0_lvl,
 };
 
 static const struct rpmpd_desc sm6375_desc = {
@@ -455,14 +743,14 @@ static const struct rpmpd_desc sm6375_desc = {
 };
 
 static struct rpmpd *qcm2290_rpmpds[] = {
-       [QCM2290_VDDCX] = &sm6115_vddcx,
-       [QCM2290_VDDCX_AO] = &sm6115_vddcx_ao,
-       [QCM2290_VDDCX_VFL] = &sm6115_vddcx_vfl,
-       [QCM2290_VDDMX] = &sm6115_vddmx,
-       [QCM2290_VDDMX_AO] = &sm6115_vddmx_ao,
-       [QCM2290_VDDMX_VFL] = &sm6115_vddmx_vfl,
-       [QCM2290_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
-       [QCM2290_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
+       [QCM2290_VDDCX] =       &cx_rwcx0_lvl,
+       [QCM2290_VDDCX_AO] =    &cx_rwcx0_lvl_ao,
+       [QCM2290_VDDCX_VFL] =   &cx_rwcx0_vfl,
+       [QCM2290_VDDMX] =       &mx_rwmx0_lvl,
+       [QCM2290_VDDMX_AO] =    &mx_rwmx0_lvl_ao,
+       [QCM2290_VDDMX_VFL] =   &mx_rwmx0_vfl,
+       [QCM2290_VDD_LPI_CX] =  &lpi_cx_rwlc0_lvl,
+       [QCM2290_VDD_LPI_MX] =  &lpi_mx_rwlm0_lvl,
 };
 
 static const struct rpmpd_desc qcm2290_desc = {
@@ -673,6 +961,15 @@ static int rpmpd_probe(struct platform_device *pdev)
                data->domains[i] = &rpmpds[i]->pd;
        }
 
+       /* Add subdomains */
+       for (i = 0; i < num; i++) {
+               if (!rpmpds[i])
+                       continue;
+
+               if (rpmpds[i]->parent)
+                       pm_genpd_add_subdomain(rpmpds[i]->parent, &rpmpds[i]->pd);
+       }
+
        return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
 }
 
index 523627d5d3981424adf9d53ed4251f6d3f3d8e91..0c1aa809cc4e3af206fa7cd639139b8450bbcb27 100644 (file)
@@ -113,7 +113,7 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
        if (WARN_ON(size >= 256))
                return -EINVAL;
 
-       pkt = kmalloc(size, GFP_KERNEL);
+       pkt = kmalloc(size, GFP_ATOMIC);
        if (!pkt)
                return -ENOMEM;
 
index 4f163d62942c1aa580bb54786a6430aa55f6b3f6..6be7ea93c78cfe01777df0fb6f558f90a8f933d8 100644 (file)
@@ -85,7 +85,7 @@
 #define SMEM_GLOBAL_HOST       0xfffe
 
 /* Max number of processors/hosts in a system */
-#define SMEM_HOST_COUNT                15
+#define SMEM_HOST_COUNT                20
 
 /**
   * struct smem_proc_comm - proc_comm communication struct (legacy)
@@ -1045,7 +1045,7 @@ static int qcom_smem_probe(struct platform_device *pdev)
        int i;
 
        num_regions = 1;
-       if (of_find_property(pdev->dev.of_node, "qcom,rpm-msg-ram", NULL))
+       if (of_property_present(pdev->dev.of_node, "qcom,rpm-msg-ram"))
                num_regions++;
 
        array_size = num_regions * sizeof(struct smem_region);
index 3e8994d6110e68ddaa1fcc4a59c8eb4f0b7c62de..c58cfff64856e2b8f27af204ab971820429818cb 100644 (file)
@@ -452,11 +452,10 @@ static int smsm_get_size_info(struct qcom_smsm *smsm)
        } *info;
 
        info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SIZE_INFO, &size);
-       if (IS_ERR(info) && PTR_ERR(info) != -ENOENT) {
-               if (PTR_ERR(info) != -EPROBE_DEFER)
-                       dev_err(smsm->dev, "unable to retrieve smsm size info\n");
-               return PTR_ERR(info);
-       } else if (IS_ERR(info) || size != sizeof(*info)) {
+       if (IS_ERR(info) && PTR_ERR(info) != -ENOENT)
+               return dev_err_probe(smsm->dev, PTR_ERR(info),
+                                    "unable to retrieve smsm size info\n");
+       else if (IS_ERR(info) || size != sizeof(*info)) {
                dev_warn(smsm->dev, "no smsm size info, using defaults\n");
                smsm->num_entries = SMSM_DEFAULT_NUM_ENTRIES;
                smsm->num_hosts = SMSM_DEFAULT_NUM_HOSTS;
@@ -510,7 +509,7 @@ static int qcom_smsm_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        for_each_child_of_node(pdev->dev.of_node, local_node) {
-               if (of_find_property(local_node, "#qcom,smem-state-cells", NULL))
+               if (of_property_present(local_node, "#qcom,smem-state-cells"))
                        break;
        }
        if (!local_node) {
index e9012ca1a87b0ead74bbbd3686a07c1391683a42..c2e4a57dd6665c7f9736f4762e1519c9b2da5222 100644 (file)
@@ -109,15 +109,20 @@ static const char *const pmic_models[] = {
        [32] = "PM8150B",
        [33] = "PMK8002",
        [36] = "PM8009",
+       [37] = "PMI632",
        [38] = "PM8150C",
+       [40] = "PM6150",
        [41] = "SMB2351",
+       [44] = "PM8008",
        [45] = "PM6125",
+       [46] = "PM7250B",
        [47] = "PMK8350",
        [48] = "PM8350",
        [49] = "PM8350C",
        [50] = "PM8350B",
        [51] = "PMR735A",
        [52] = "PMR735B",
+       [55] = "PM2250",
        [58] = "PM8450",
        [65] = "PM8010",
 };
@@ -405,6 +410,7 @@ static const struct soc_id soc_id[] = {
        { qcom_board_id(SA8155) },
        { qcom_board_id(SDA439) },
        { qcom_board_id(SDA429) },
+       { qcom_board_id(SM7150) },
        { qcom_board_id(IPQ8070) },
        { qcom_board_id(IPQ8071) },
        { qcom_board_id(QM215) },
@@ -426,6 +432,7 @@ static const struct soc_id soc_id[] = {
        { qcom_board_id(QCM2150) },
        { qcom_board_id(SDA429W) },
        { qcom_board_id(SM8350) },
+       { qcom_board_id(QCM2290) },
        { qcom_board_id(SM6115) },
        { qcom_board_id(SC8280XP) },
        { qcom_board_id(IPQ6005) },
@@ -441,7 +448,16 @@ static const struct soc_id soc_id[] = {
        { qcom_board_id(SC7280) },
        { qcom_board_id(SC7180P) },
        { qcom_board_id(SM6375) },
+       { qcom_board_id(IPQ9514) },
+       { qcom_board_id(IPQ9550) },
+       { qcom_board_id(IPQ9554) },
+       { qcom_board_id(IPQ9570) },
+       { qcom_board_id(IPQ9574) },
        { qcom_board_id(SM8550) },
+       { qcom_board_id(IPQ9510) },
+       { qcom_board_id(QRB4210) },
+       { qcom_board_id(QRB2210) },
+       { qcom_board_id(SA8775P) },
        { qcom_board_id(QRU1000) },
        { qcom_board_id(QDU1000) },
        { qcom_board_id(QDU1010) },
index 4e8b51ba226614ef1a1e91b47c8a4d249ceff9ac..de31589ed05404a83771d020c0ace184c66efc29 100644 (file)
@@ -206,13 +206,6 @@ config ARCH_R8A77990
          This enables support for the Renesas R-Car E3 SoC.
          This includes different gradings like R-Car E3e.
 
-config ARCH_R8A77950
-       bool "ARM64 Platform support for R-Car H3 ES1.x"
-       select ARCH_RCAR_GEN3
-       select SYSC_R8A7795
-       help
-         This enables support for the Renesas R-Car H3 SoC (revision 1.x).
-
 config ARCH_R8A77951
        bool "ARM64 Platform support for R-Car H3 ES2.0+"
        select ARCH_RCAR_GEN3
index c83bdbdabb64dfe1ac3406b1ef1bf6e9e811e9ce..452cee8d68bee7d04e7acbee6bd90dab457c77c3 100644 (file)
@@ -131,7 +131,7 @@ static struct platform_driver rzv2m_pwc_driver = {
        .probe = rzv2m_pwc_probe,
        .driver = {
                .name = "rzv2m_pwc",
-               .of_match_table = of_match_ptr(rzv2m_pwc_of_match),
+               .of_match_table = rzv2m_pwc_of_match,
        },
 };
 module_platform_driver(rzv2m_pwc_driver);
index 91074411b8cfe48f555ec22ccf36bacbb95ca54b..cbe1ff0fc58393e4d9d6e0ed6030c13119755540 100644 (file)
@@ -38,8 +38,6 @@ static struct rcar_sysc_area r8a7795_areas[] __initdata = {
        { "a3vp",       0x340, 0, R8A7795_PD_A3VP,      R8A7795_PD_ALWAYS_ON },
        { "cr7",        0x240, 0, R8A7795_PD_CR7,       R8A7795_PD_ALWAYS_ON },
        { "a3vc",       0x380, 0, R8A7795_PD_A3VC,      R8A7795_PD_ALWAYS_ON },
-       /* A2VC0 exists on ES1.x only */
-       { "a2vc0",      0x3c0, 0, R8A7795_PD_A2VC0,     R8A7795_PD_A3VC },
        { "a2vc1",      0x3c0, 1, R8A7795_PD_A2VC1,     R8A7795_PD_A3VC },
        { "3dg-a",      0x100, 0, R8A7795_PD_3DG_A,     R8A7795_PD_ALWAYS_ON },
        { "3dg-b",      0x100, 1, R8A7795_PD_3DG_B,     R8A7795_PD_3DG_A },
@@ -54,14 +52,10 @@ static struct rcar_sysc_area r8a7795_areas[] __initdata = {
         * Fixups for R-Car H3 revisions
         */
 
-#define HAS_A2VC0      BIT(0)          /* Power domain A2VC0 is present */
 #define NO_EXTMASK     BIT(1)          /* Missing SYSCEXTMASK register */
 
 static const struct soc_device_attribute r8a7795_quirks_match[] __initconst = {
        {
-               .soc_id = "r8a7795", .revision = "ES1.*",
-               .data = (void *)(HAS_A2VC0 | NO_EXTMASK),
-       }, {
                .soc_id = "r8a7795", .revision = "ES2.*",
                .data = (void *)(NO_EXTMASK),
        },
@@ -77,10 +71,6 @@ static int __init r8a7795_sysc_init(void)
        if (attr)
                quirks = (uintptr_t)attr->data;
 
-       if (!(quirks & HAS_A2VC0))
-               rcar_sysc_nullify(r8a7795_areas, ARRAY_SIZE(r8a7795_areas),
-                                 R8A7795_PD_A2VC0);
-
        if (quirks & NO_EXTMASK)
                r8a7795_sysc_info.extmask_val = 0;
 
index 468ebce1ea88bf61ed364e173279da63ae0dbde0..42af7c09f743340626fc43d7116f5ec890b00fb4 100644 (file)
@@ -269,7 +269,7 @@ static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = {
 };
 
 
-static const struct of_device_id renesas_socs[] __initconst = {
+static const struct of_device_id renesas_socs[] __initconst __maybe_unused = {
 #ifdef CONFIG_ARCH_R7S72100
        { .compatible = "renesas,r7s72100",     .data = &soc_rz_a1h },
 #endif
@@ -330,10 +330,8 @@ static const struct of_device_id renesas_socs[] __initconst = {
 #ifdef CONFIG_ARCH_R8A7794
        { .compatible = "renesas,r8a7794",      .data = &soc_rcar_e2 },
 #endif
-#if defined(CONFIG_ARCH_R8A77950) || defined(CONFIG_ARCH_R8A77951)
-       { .compatible = "renesas,r8a7795",      .data = &soc_rcar_h3 },
-#endif
 #ifdef CONFIG_ARCH_R8A77951
+       { .compatible = "renesas,r8a7795",      .data = &soc_rcar_h3 },
        { .compatible = "renesas,r8a779m0",     .data = &soc_rcar_h3 },
        { .compatible = "renesas,r8a779m1",     .data = &soc_rcar_h3 },
        { .compatible = "renesas,r8a779m8",     .data = &soc_rcar_h3 },
@@ -375,20 +373,20 @@ static const struct of_device_id renesas_socs[] __initconst = {
 #ifdef CONFIG_ARCH_R8A779G0
        { .compatible = "renesas,r8a779g0",     .data = &soc_rcar_v4h },
 #endif
-#if defined(CONFIG_ARCH_R9A07G043)
+#ifdef CONFIG_ARCH_R9A07G043
 #ifdef CONFIG_RISCV
        { .compatible = "renesas,r9a07g043",    .data = &soc_rz_five },
 #else
        { .compatible = "renesas,r9a07g043",    .data = &soc_rz_g2ul },
 #endif
 #endif
-#if defined(CONFIG_ARCH_R9A07G044)
+#ifdef CONFIG_ARCH_R9A07G044
        { .compatible = "renesas,r9a07g044",    .data = &soc_rz_g2l },
 #endif
-#if defined(CONFIG_ARCH_R9A07G054)
+#ifdef CONFIG_ARCH_R9A07G054
        { .compatible = "renesas,r9a07g054",    .data = &soc_rz_v2l },
 #endif
-#if defined(CONFIG_ARCH_R9A09G011)
+#ifdef CONFIG_ARCH_R9A09G011
        { .compatible = "renesas,r9a09g011",    .data = &soc_rz_v2m },
 #endif
 #ifdef CONFIG_ARCH_SH73A0
@@ -471,8 +469,11 @@ static int __init renesas_soc_init(void)
        }
 
        soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
-       if (!soc_dev_attr)
+       if (!soc_dev_attr) {
+               if (chipid)
+                       iounmap(chipid);
                return -ENOMEM;
+       }
 
        np = of_find_node_by_path("/");
        of_property_read_string(np, "model", &soc_dev_attr->machine);
index 204e6135180b919c240f859901d7dc23df7a63b1..728ebac98e14a5cca82555c57b353783b434c370 100644 (file)
@@ -343,7 +343,7 @@ static int __init rmobile_init_pm_domains(void)
                        break;
                }
 
-               fwnode_dev_initialized(&np->fwnode, true);
+               fwnode_dev_initialized(of_fwnode_handle(np), true);
        }
 
        put_special_pds();
index d90e4a264b6f6bfa4ada206c7a7f14bde14856a3..1734da357ca21b249740e089698275507ea98a8a 100644 (file)
@@ -82,7 +82,7 @@ static int sunxi_mbus_notifier(struct notifier_block *nb,
         * Older DTs or SoCs who are not clearly understood need to set
         * that DMA offset though.
         */
-       if (of_find_property(dev->of_node, "interconnects", NULL))
+       if (of_property_present(dev->of_node, "interconnects"))
                return NOTIFY_DONE;
 
        ret = dma_direct_set_offset(dev, PHYS_OFFSET, 0, SZ_4G);
index f09918c5904230a3e10581610f95064f36e0cad3..4c4864cd2342a4b57f7e7a5ac9d8ecdbba9d0259 100644 (file)
@@ -424,4 +424,3 @@ builtin_platform_driver_probe(sunxi_sram_driver, sunxi_sram_probe);
 
 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
 MODULE_DESCRIPTION("Allwinner sunXi SRAM Controller Driver");
-MODULE_LICENSE("GPL");
index a8566b9dd8de4f8179b25763999930d28009c0ab..bd96204a68ee3d035156ba39dae0ba8d0f9c1da7 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/of_address.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/version.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/tegra-cbb.h>
 
index d4112b683f00fdfa1b422a926e41100ebb7dcdb3..54d7ce05c6367da53872f72fd75e65aa69235fcc 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/of_address.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/version.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/tegra-cbb.h>
 
@@ -2191,7 +2190,6 @@ MODULE_DEVICE_TABLE(of, tegra194_cbb_match);
 static int tegra194_cbb_get_bridges(struct tegra194_cbb *cbb, struct device_node *np)
 {
        struct tegra_cbb *entry;
-       struct resource res;
        unsigned long flags;
        unsigned int i;
        int err;
@@ -2211,8 +2209,7 @@ static int tegra194_cbb_get_bridges(struct tegra194_cbb *cbb, struct device_node
        spin_unlock_irqrestore(&cbb_lock, flags);
 
        if (!cbb->bridges) {
-               while (of_address_to_resource(np, cbb->num_bridges, &res) == 0)
-                       cbb->num_bridges++;
+               cbb->num_bridges = of_address_count(np);
 
                cbb->bridges = devm_kcalloc(cbb->base.dev, cbb->num_bridges,
                                            sizeof(*cbb->bridges), GFP_KERNEL);
@@ -2359,4 +2356,3 @@ module_exit(tegra194_cbb_exit);
 
 MODULE_AUTHOR("Sumit Gupta <sumitg@nvidia.com>");
 MODULE_DESCRIPTION("Control Backbone error handling driver for Tegra194");
-MODULE_LICENSE("GPL");
index f33d094e5ea60c28501b960f0952b05ed5a84303..5d16161b2566ec38d39d6d0303b9ed2c500457bd 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/of_address.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/version.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/tegra-cbb.h>
 
@@ -1174,11 +1173,6 @@ static int tegra234_cbb_probe(struct platform_device *pdev)
        return tegra_cbb_register(&cbb->base);
 }
 
-static int tegra234_cbb_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-
 static int __maybe_unused tegra234_cbb_resume_noirq(struct device *dev)
 {
        struct tegra234_cbb *cbb = dev_get_drvdata(dev);
@@ -1196,7 +1190,6 @@ static const struct dev_pm_ops tegra234_cbb_pm = {
 
 static struct platform_driver tegra234_cbb_driver = {
        .probe = tegra234_cbb_probe,
-       .remove = tegra234_cbb_remove,
        .driver = {
                .name = "tegra234-cbb",
                .of_match_table = tegra234_cbb_dt_ids,
@@ -1218,4 +1211,3 @@ static void __exit tegra234_cbb_exit(void)
 module_exit(tegra234_cbb_exit);
 
 MODULE_DESCRIPTION("Control Backbone 2.0 error handling driver for Tegra234");
-MODULE_LICENSE("GPL");
index 5db919d96aba5811f53cb94e532d57693e8374ec..221202db33130c47db456cd0fcfc29b0f7efb48b 100644 (file)
@@ -156,10 +156,8 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
 static int tegra_flowctrl_probe(struct platform_device *pdev)
 {
        void __iomem *base = tegra_flowctrl_base;
-       struct resource *res;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       tegra_flowctrl_base = devm_ioremap_resource(&pdev->dev, res);
+       tegra_flowctrl_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(tegra_flowctrl_base))
                return PTR_ERR(tegra_flowctrl_base);
 
index f02953f793e9e2df6681c28aa7728cbb8a2cd1d2..d7a37f5d45270e405f04ed81b78ae5473279018e 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2013-2022, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2013-2023, NVIDIA CORPORATION.  All rights reserved.
  */
 
 #include <linux/clk.h>
@@ -166,7 +166,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
        nvmem.nkeepout = fuse->soc->num_keepouts;
        nvmem.type = NVMEM_TYPE_OTP;
        nvmem.read_only = true;
-       nvmem.root_only = true;
+       nvmem.root_only = false;
        nvmem.reg_read = tegra_fuse_read;
        nvmem.size = fuse->soc->info->size;
        nvmem.word_size = 4;
index cf4cfbf9f7c5a691fd095e7f7184465ef6e669fb..5d17799524c901ca74ce27828e29c46ce01ac5b7 100644 (file)
@@ -3,7 +3,7 @@
  * drivers/soc/tegra/pmc.c
  *
  * Copyright (c) 2010 Google, Inc
- * Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
  *
  * Author:
  *     Colin Cross <ccross@google.com>
 /* Tegra186 and later */
 #define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2))
 #define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3)
+#define WAKE_AOWAKE_CNTRL_SR_CAPTURE_EN (1 << 1)
 #define WAKE_AOWAKE_MASK_W(x) (0x180 + ((x) << 2))
 #define WAKE_AOWAKE_MASK_R(x) (0x300 + ((x) << 2))
 #define WAKE_AOWAKE_STATUS_W(x) (0x30c + ((x) << 2))
 #define WAKE_AOWAKE_CTRL 0x4f4
 #define  WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
 
+#define SW_WAKE_ID             83 /* wake83 */
+
 /* for secure PMC */
 #define TEGRA_SMC_PMC          0xc2fffe00
 #define  TEGRA_SMC_PMC_READ    0xaa
@@ -355,6 +358,7 @@ struct tegra_pmc_soc {
        void (*setup_irq_polarity)(struct tegra_pmc *pmc,
                                   struct device_node *np,
                                   bool invert);
+       void (*set_wake_filters)(struct tegra_pmc *pmc);
        int (*irq_set_wake)(struct irq_data *data, unsigned int on);
        int (*irq_set_type)(struct irq_data *data, unsigned int type);
        int (*powergate_set)(struct tegra_pmc *pmc, unsigned int id,
@@ -2416,6 +2420,17 @@ static int tegra210_pmc_irq_set_type(struct irq_data *data, unsigned int type)
        return 0;
 }
 
+static void tegra186_pmc_set_wake_filters(struct tegra_pmc *pmc)
+{
+       u32 value;
+
+       /* SW Wake (wake83) needs SR_CAPTURE filter to be enabled */
+       value = readl(pmc->wake + WAKE_AOWAKE_CNTRL(SW_WAKE_ID));
+       value |= WAKE_AOWAKE_CNTRL_SR_CAPTURE_EN;
+       writel(value, pmc->wake + WAKE_AOWAKE_CNTRL(SW_WAKE_ID));
+       dev_dbg(pmc->dev, "WAKE_AOWAKE_CNTRL_83 = 0x%x\n", value);
+}
+
 static int tegra186_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
 {
        struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
@@ -3042,6 +3057,10 @@ static int tegra_pmc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, pmc);
        tegra_pm_init_suspend();
 
+       /* Some wakes require specific filter configuration */
+       if (pmc->soc->set_wake_filters)
+               pmc->soc->set_wake_filters(pmc);
+
        return 0;
 
 cleanup_powergates:
@@ -3938,6 +3957,7 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
        .regs = &tegra186_pmc_regs,
        .init = tegra186_pmc_init,
        .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
+       .set_wake_filters = tegra186_pmc_set_wake_filters,
        .irq_set_wake = tegra186_pmc_irq_set_wake,
        .irq_set_type = tegra186_pmc_irq_set_type,
        .reset_sources = tegra186_reset_sources,
@@ -4122,6 +4142,7 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = {
        .regs = &tegra194_pmc_regs,
        .init = tegra186_pmc_init,
        .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
+       .set_wake_filters = tegra186_pmc_set_wake_filters,
        .irq_set_wake = tegra186_pmc_irq_set_wake,
        .irq_set_type = tegra186_pmc_irq_set_type,
        .reset_sources = tegra194_reset_sources,
@@ -4225,7 +4246,9 @@ static const char * const tegra234_reset_sources[] = {
 };
 
 static const struct tegra_wake_event tegra234_wake_events[] = {
+       TEGRA_WAKE_IRQ("pmu", 24, 209),
        TEGRA_WAKE_GPIO("power", 29, 1, TEGRA234_AON_GPIO(EE, 4)),
+       TEGRA_WAKE_GPIO("mgbe", 56, 0, TEGRA234_MAIN_GPIO(Y, 3)),
        TEGRA_WAKE_IRQ("rtc", 73, 10),
 };
 
@@ -4247,6 +4270,7 @@ static const struct tegra_pmc_soc tegra234_pmc_soc = {
        .regs = &tegra234_pmc_regs,
        .init = tegra186_pmc_init,
        .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
+       .set_wake_filters = tegra186_pmc_set_wake_filters,
        .irq_set_wake = tegra186_pmc_irq_set_wake,
        .irq_set_type = tegra186_pmc_irq_set_type,
        .reset_sources = tegra234_reset_sources,
index 8eaf50d0b6af8e61944b139583f53eb3b1022a90..179ed895c2796b3516647c0024e2e2b5b681eeb3 100644 (file)
@@ -286,7 +286,7 @@ remove:
                tegra_powergate_remove(powergate);
        }
 
-       kfree(genpd->domains);
+       kfree(domains);
        return err;
 }
 
index e01e4d815230af3bccfaad03c96414480db06f3d..8f131368a758621cb6f76eb6e3d26ba7d49f28cb 100644 (file)
@@ -406,6 +406,11 @@ static int k3_dmaring_request_dual_ring(struct k3_ringacc *ringacc, int fwd_id,
 
        mutex_lock(&ringacc->req_lock);
 
+       if (!try_module_get(ringacc->dev->driver->owner)) {
+               ret = -EINVAL;
+               goto err_module_get;
+       }
+
        if (test_bit(fwd_id, ringacc->rings_inuse)) {
                ret = -EBUSY;
                goto error;
@@ -421,6 +426,8 @@ static int k3_dmaring_request_dual_ring(struct k3_ringacc *ringacc, int fwd_id,
        return 0;
 
 error:
+       module_put(ringacc->dev->driver->owner);
+err_module_get:
        mutex_unlock(&ringacc->req_lock);
        return ret;
 }
index d15764e19d968c6eba8dab9f7a4e1155c86c02e8..ad97e08a25f6924816391ee657a4cb5c408c4ba4 100644 (file)
@@ -43,6 +43,7 @@ static const struct k3_soc_id {
        { 0xBB38, "AM64X" },
        { 0xBB75, "J721S2"},
        { 0xBB7E, "AM62X" },
+       { 0xBB80, "J784S4" },
        { 0xBB8D, "AM62AX" },
 };
 
index 84afebd355befc560496837f4f06559ef5316b1e..0fbc37cd5123106c475eb605d489dff6e743e72f 100644 (file)
@@ -666,8 +666,8 @@ static int dma_init(struct device_node *cloud, struct device_node *dma_node)
        dma->rx_priority = DMA_PRIO_DEFAULT;
        dma->tx_priority = DMA_PRIO_DEFAULT;
 
-       dma->enable_all = (of_get_property(node, "ti,enable-all", NULL) != NULL);
-       dma->loopback   = (of_get_property(node, "ti,loop-back",  NULL) != NULL);
+       dma->enable_all = of_property_read_bool(node, "ti,enable-all");
+       dma->loopback   = of_property_read_bool(node, "ti,loop-back");
 
        ret = of_property_read_u32(node, "ti,rx-retry-timeout", &timeout);
        if (ret < 0) {
index fde66e28e046a4aa97897ecf3ee72c09703aaf56..3d388646ed43c359f3d2dd0f8ef538f0818a7bd2 100644 (file)
@@ -521,7 +521,7 @@ int knav_init_acc_range(struct knav_device *kdev,
 
        info->pdsp = pdsp;
        channels = range->num_queues;
-       if (of_get_property(node, "multi-queue", NULL)) {
+       if (of_property_read_bool(node, "multi-queue")) {
                range->flags |= RANGE_MULTI_QUEUE;
                channels = 1;
                if (range->queue_base & (32 - 1)) {
index 8fb76908be7044bfab5ed7bee1ba3974df442d91..0f252c2549ba3148f478412a2a0a3d740b64faf2 100644 (file)
@@ -1264,10 +1264,10 @@ static int knav_setup_queue_range(struct knav_device *kdev,
        if (range->num_irqs)
                range->flags |= RANGE_HAS_IRQ;
 
-       if (of_get_property(node, "qalloc-by-id", NULL))
+       if (of_property_read_bool(node, "qalloc-by-id"))
                range->flags |= RANGE_RESERVED;
 
-       if (of_get_property(node, "accumulator", NULL)) {
+       if (of_property_present(node, "accumulator")) {
                ret = knav_init_acc_range(kdev, node, range);
                if (ret < 0) {
                        devm_kfree(dev, range);
index 913b964374a444092623bf31b309ebf90be368f4..ecd9a8bdd7c0afe43542813d954e59a0158cdd50 100644 (file)
@@ -684,7 +684,7 @@ static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm)
        const char *name;
        int error;
 
-       if (!of_find_property(dev->of_node, "#power-domain-cells", NULL))
+       if (!of_property_present(dev->of_node, "#power-domain-cells"))
                return 0;
 
        of_node_put(dev->of_node);
index ce09c42eaed259df492ccc51b7d5542531435259..f04c21157904bb4a8b901f1373accb22aa540c9d 100644 (file)
@@ -527,7 +527,7 @@ static int am33xx_pm_probe(struct platform_device *pdev)
 
        ret = am33xx_pm_alloc_sram();
        if (ret)
-               return ret;
+               goto err_wkup_m3_ipc_put;
 
        ret = am33xx_pm_rtc_setup();
        if (ret)
@@ -572,13 +572,14 @@ err_pm_runtime_put:
        pm_runtime_put_sync(dev);
 err_pm_runtime_disable:
        pm_runtime_disable(dev);
-       wkup_m3_ipc_put(m3_ipc);
 err_unsetup_rtc:
        iounmap(rtc_base_virt);
        clk_put(rtc_fck);
 err_free_sram:
        am33xx_pm_free_sram();
        pm33xx_dev = NULL;
+err_wkup_m3_ipc_put:
+       wkup_m3_ipc_put(m3_ipc);
        return ret;
 }
 
index 9d9496e0a94c9e59635a8d435fe02a6ebadf095c..da7898239a46ae238b7038551f6573f5ab0ac8f3 100644 (file)
@@ -937,21 +937,8 @@ err_list_del:
 
 static int omap_sr_remove(struct platform_device *pdev)
 {
-       struct omap_sr_data *pdata = pdev->dev.platform_data;
        struct device *dev = &pdev->dev;
-       struct omap_sr *sr_info;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
-               return -EINVAL;
-       }
-
-       sr_info = _sr_lookup(pdata->voltdm);
-       if (IS_ERR(sr_info)) {
-               dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
-                       __func__);
-               return PTR_ERR(sr_info);
-       }
+       struct omap_sr *sr_info = platform_get_drvdata(pdev);
 
        if (sr_info->autocomp_active)
                sr_stop_vddautocomp(sr_info);
@@ -965,20 +952,7 @@ static int omap_sr_remove(struct platform_device *pdev)
 
 static void omap_sr_shutdown(struct platform_device *pdev)
 {
-       struct omap_sr_data *pdata = pdev->dev.platform_data;
-       struct omap_sr *sr_info;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
-               return;
-       }
-
-       sr_info = _sr_lookup(pdata->voltdm);
-       if (IS_ERR(sr_info)) {
-               dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
-                       __func__);
-               return;
-       }
+       struct omap_sr *sr_info = platform_get_drvdata(pdev);
 
        if (sr_info->autocomp_active)
                sr_stop_vddautocomp(sr_info);
index 343c58ed58961044e03d304eeb5596a4a40bac8d..c9197912ec249dfe8acf65421725153f121b858e 100644 (file)
@@ -615,7 +615,6 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
        int irq, ret, temp;
        phandle rproc_phandle;
        struct rproc *m3_rproc;
-       struct resource *res;
        struct task_struct *task;
        struct wkup_m3_ipc *m3_ipc;
        struct device_node *np = dev->of_node;
@@ -624,8 +623,7 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
        if (!m3_ipc)
                return -ENOMEM;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       m3_ipc->ipc_mem_base = devm_ioremap_resource(dev, res);
+       m3_ipc->ipc_mem_base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(m3_ipc->ipc_mem_base))
                return PTR_ERR(m3_ipc->ipc_mem_base);
 
@@ -681,7 +679,7 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
                        dev_warn(dev, "Invalid VTT GPIO(%d) pin\n", temp);
        }
 
-       if (of_find_property(np, "ti,set-io-isolation", NULL))
+       if (of_property_read_bool(np, "ti,set-io-isolation"))
                wkup_m3_set_io_isolation(m3_ipc);
 
        ret = of_property_read_string(np, "firmware-name",
index f121c224e682b0cffccfb49cab1209fd6b2ce536..70898bbd58095951744b8fd0a566ebd9249b8daf 100644 (file)
@@ -7,3 +7,20 @@ config OPTEE
        help
          This implements the OP-TEE Trusted Execution Environment (TEE)
          driver.
+
+config OPTEE_INSECURE_LOAD_IMAGE
+       bool "Load OP-TEE image as firmware"
+       default n
+       depends on OPTEE && ARM64
+       help
+         This loads the BL32 image for OP-TEE as firmware when the driver is
+         probed. This returns -EPROBE_DEFER until the firmware is loadable from
+         the filesystem which is determined by checking the system_state until
+         it is in SYSTEM_RUNNING. This also requires enabling the corresponding
+         option in Trusted Firmware for Arm. The documentation there explains
+         the security threat associated with enabling this as well as
+         mitigations at the firmware and platform level.
+         https://trustedfirmware-a.readthedocs.io/en/latest/threat_model/threat_model.html
+
+         Additional documentation on kernel security risks are at
+         Documentation/staging/tee.rst.
index 70e9cc2ee96b08fa44708b1c1b8547968b003612..e8840a82b98356d21b791cc8f2b305aa9f086fb1 100644 (file)
@@ -241,11 +241,23 @@ struct optee_msg_arg {
  * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b.
  * Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1,
  * OPTEE_MSG_UID_2, OPTEE_MSG_UID_3.
+ *
+ * In the case where the OP-TEE image is loaded by the kernel, this will
+ * initially return an alternate UID to reflect that we are communicating with
+ * the TF-A image loading service at that time instead of OP-TEE. That UID is:
+ * a3fbeab1-1246-315d-c7c4-06b9c03cbea4.
+ * Represented in 4 32-bit words in OPTEE_MSG_IMAGE_LOAD_UID_0,
+ * OPTEE_MSG_IMAGE_LOAD_UID_1, OPTEE_MSG_IMAGE_LOAD_UID_2,
+ * OPTEE_MSG_IMAGE_LOAD_UID_3.
  */
 #define OPTEE_MSG_UID_0                        0x384fb3e0
 #define OPTEE_MSG_UID_1                        0xe7f811e3
 #define OPTEE_MSG_UID_2                        0xaf630002
 #define OPTEE_MSG_UID_3                        0xa5d5c51b
+#define OPTEE_MSG_IMAGE_LOAD_UID_0     0xa3fbeab1
+#define OPTEE_MSG_IMAGE_LOAD_UID_1     0x1246315d
+#define OPTEE_MSG_IMAGE_LOAD_UID_2     0xc7c406b9
+#define OPTEE_MSG_IMAGE_LOAD_UID_3     0xc03cbea4
 #define OPTEE_MSG_FUNCID_CALLS_UID     0xFF01
 
 /*
index 04ae58892608c6b7e2627b156030fb39a3c5b5a2..72685ee0d53f881cbaa8116fec69f465d81f7ca9 100644 (file)
@@ -94,11 +94,35 @@ struct optee_supp {
        struct completion reqs_c;
 };
 
+/*
+ * struct optee_pcpu - per cpu notif private struct passed to work functions
+ * @optee              optee device reference
+ */
+struct optee_pcpu {
+       struct optee *optee;
+};
+
+/*
+ * struct optee_smc - optee smc communication struct
+ * @invoke_fn          handler function to invoke secure monitor
+ * @memremaped_shm     virtual address of memory in shared memory pool
+ * @sec_caps:          secure world capabilities defined by
+ *                     OPTEE_SMC_SEC_CAP_* in optee_smc.h
+ * @notif_irq          interrupt used as async notification by OP-TEE or 0
+ * @optee_pcpu         per_cpu optee instance for per cpu work or NULL
+ * @notif_pcpu_wq      workqueue for per cpu asynchronous notification or NULL
+ * @notif_pcpu_work    work for per cpu asynchronous notification
+ * @notif_cpuhp_state   CPU hotplug state assigned for pcpu interrupt management
+ */
 struct optee_smc {
        optee_invoke_fn *invoke_fn;
        void *memremaped_shm;
        u32 sec_caps;
        unsigned int notif_irq;
+       struct optee_pcpu __percpu *optee_pcpu;
+       struct workqueue_struct *notif_pcpu_wq;
+       struct work_struct notif_pcpu_work;
+       unsigned int notif_cpuhp_state;
 };
 
 /**
index 73b5e7760d102d9e1424dbcece28557c0281c6f0..7d9fa426505ba524f59b541a2059feaa3104b8e0 100644 (file)
@@ -104,6 +104,30 @@ struct optee_smc_call_get_os_revision_result {
        unsigned long reserved1;
 };
 
+/*
+ * Load Trusted OS from optee/tee.bin in the Linux firmware.
+ *
+ * WARNING: Use this cautiously as it could lead to insecure loading of the
+ * Trusted OS.
+ * This SMC instructs EL3 to load a binary and execute it as the Trusted OS.
+ *
+ * Call register usage:
+ * a0 SMC Function ID, OPTEE_SMC_CALL_LOAD_IMAGE
+ * a1 Upper 32bit of a 64bit size for the payload
+ * a2 Lower 32bit of a 64bit size for the payload
+ * a3 Upper 32bit of the physical address for the payload
+ * a4 Lower 32bit of the physical address for the payload
+ *
+ * The payload is in the OP-TEE image format.
+ *
+ * Returns result in a0, 0 on success and an error code otherwise.
+ */
+#define OPTEE_SMC_FUNCID_LOAD_IMAGE 2
+#define OPTEE_SMC_CALL_LOAD_IMAGE \
+       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+                          ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+                          OPTEE_SMC_FUNCID_LOAD_IMAGE)
+
 /*
  * Call with struct optee_msg_arg as argument
  *
index a1c1fa1a9c28a7374337dc571a5a28db575f2317..49702cb08f4fb3a56f28f3bd9f643268b68cba1f 100644 (file)
@@ -7,10 +7,13 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/arm-smccc.h>
+#include <linux/cpuhotplug.h>
 #include <linux/errno.h>
+#include <linux/firmware.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irqdomain.h>
+#include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/of.h>
  */
 #define OPTEE_MIN_STATIC_POOL_ALIGN    9 /* 512 bytes aligned */
 
+/* SMC ABI considers at most a single TEE firmware */
+static unsigned int pcpu_irq_num;
+
+static int optee_cpuhp_enable_pcpu_irq(unsigned int cpu)
+{
+       enable_percpu_irq(pcpu_irq_num, IRQ_TYPE_NONE);
+
+       return 0;
+}
+
+static int optee_cpuhp_disable_pcpu_irq(unsigned int cpu)
+{
+       disable_percpu_irq(pcpu_irq_num);
+
+       return 0;
+}
+
 /*
  * 1. Convert between struct tee_param and struct optee_msg_param
  *
@@ -991,9 +1011,8 @@ static u32 get_async_notif_value(optee_invoke_fn *invoke_fn, bool *value_valid,
        return res.a1;
 }
 
-static irqreturn_t notif_irq_handler(int irq, void *dev_id)
+static irqreturn_t irq_handler(struct optee *optee)
 {
-       struct optee *optee = dev_id;
        bool do_bottom_half = false;
        bool value_valid;
        bool value_pending;
@@ -1016,6 +1035,13 @@ static irqreturn_t notif_irq_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t notif_irq_handler(int irq, void *dev_id)
+{
+       struct optee *optee = dev_id;
+
+       return irq_handler(optee);
+}
+
 static irqreturn_t notif_irq_thread_fn(int irq, void *dev_id)
 {
        struct optee *optee = dev_id;
@@ -1025,7 +1051,7 @@ static irqreturn_t notif_irq_thread_fn(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
+static int init_irq(struct optee *optee, u_int irq)
 {
        int rc;
 
@@ -1040,12 +1066,103 @@ static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
        return 0;
 }
 
+static irqreturn_t notif_pcpu_irq_handler(int irq, void *dev_id)
+{
+       struct optee_pcpu *pcpu = dev_id;
+       struct optee *optee = pcpu->optee;
+
+       if (irq_handler(optee) == IRQ_WAKE_THREAD)
+               queue_work(optee->smc.notif_pcpu_wq,
+                          &optee->smc.notif_pcpu_work);
+
+       return IRQ_HANDLED;
+}
+
+static void notif_pcpu_irq_work_fn(struct work_struct *work)
+{
+       struct optee_smc *optee_smc = container_of(work, struct optee_smc,
+                                                  notif_pcpu_work);
+       struct optee *optee = container_of(optee_smc, struct optee, smc);
+
+       optee_smc_do_bottom_half(optee->ctx);
+}
+
+static int init_pcpu_irq(struct optee *optee, u_int irq)
+{
+       struct optee_pcpu __percpu *optee_pcpu;
+       int cpu, rc;
+
+       optee_pcpu = alloc_percpu(struct optee_pcpu);
+       if (!optee_pcpu)
+               return -ENOMEM;
+
+       for_each_present_cpu(cpu)
+               per_cpu_ptr(optee_pcpu, cpu)->optee = optee;
+
+       rc = request_percpu_irq(irq, notif_pcpu_irq_handler,
+                               "optee_pcpu_notification", optee_pcpu);
+       if (rc)
+               goto err_free_pcpu;
+
+       INIT_WORK(&optee->smc.notif_pcpu_work, notif_pcpu_irq_work_fn);
+       optee->smc.notif_pcpu_wq = create_workqueue("optee_pcpu_notification");
+       if (!optee->smc.notif_pcpu_wq) {
+               rc = -EINVAL;
+               goto err_free_pcpu_irq;
+       }
+
+       optee->smc.optee_pcpu = optee_pcpu;
+       optee->smc.notif_irq = irq;
+
+       pcpu_irq_num = irq;
+       rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "optee/pcpu-notif:starting",
+                              optee_cpuhp_enable_pcpu_irq,
+                              optee_cpuhp_disable_pcpu_irq);
+       if (!rc)
+               rc = -EINVAL;
+       if (rc < 0)
+               goto err_free_pcpu_irq;
+
+       optee->smc.notif_cpuhp_state = rc;
+
+       return 0;
+
+err_free_pcpu_irq:
+       free_percpu_irq(irq, optee_pcpu);
+err_free_pcpu:
+       free_percpu(optee_pcpu);
+
+       return rc;
+}
+
+static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
+{
+       if (irq_is_percpu_devid(irq))
+               return init_pcpu_irq(optee, irq);
+       else
+               return init_irq(optee, irq);
+}
+
+static void uninit_pcpu_irq(struct optee *optee)
+{
+       cpuhp_remove_state(optee->smc.notif_cpuhp_state);
+
+       destroy_workqueue(optee->smc.notif_pcpu_wq);
+
+       free_percpu_irq(optee->smc.notif_irq, optee->smc.optee_pcpu);
+       free_percpu(optee->smc.optee_pcpu);
+}
+
 static void optee_smc_notif_uninit_irq(struct optee *optee)
 {
        if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
                optee_smc_stop_async_notif(optee->ctx);
                if (optee->smc.notif_irq) {
-                       free_irq(optee->smc.notif_irq, optee);
+                       if (irq_is_percpu_devid(optee->smc.notif_irq))
+                               uninit_pcpu_irq(optee);
+                       else
+                               free_irq(optee->smc.notif_irq, optee);
+
                        irq_dispose_mapping(optee->smc.notif_irq);
                }
        }
@@ -1149,6 +1266,22 @@ static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
        return false;
 }
 
+#ifdef CONFIG_OPTEE_INSECURE_LOAD_IMAGE
+static bool optee_msg_api_uid_is_optee_image_load(optee_invoke_fn *invoke_fn)
+{
+       struct arm_smccc_res res;
+
+       invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+       if (res.a0 == OPTEE_MSG_IMAGE_LOAD_UID_0 &&
+           res.a1 == OPTEE_MSG_IMAGE_LOAD_UID_1 &&
+           res.a2 == OPTEE_MSG_IMAGE_LOAD_UID_2 &&
+           res.a3 == OPTEE_MSG_IMAGE_LOAD_UID_3)
+               return true;
+       return false;
+}
+#endif
+
 static void optee_msg_get_os_revision(optee_invoke_fn *invoke_fn)
 {
        union {
@@ -1354,6 +1487,120 @@ static void optee_shutdown(struct platform_device *pdev)
                optee_disable_shm_cache(optee);
 }
 
+#ifdef CONFIG_OPTEE_INSECURE_LOAD_IMAGE
+
+#define OPTEE_FW_IMAGE "optee/tee.bin"
+
+static optee_invoke_fn *cpuhp_invoke_fn;
+
+static int optee_cpuhp_probe(unsigned int cpu)
+{
+       /*
+        * Invoking a call on a CPU will cause OP-TEE to perform the required
+        * setup for that CPU. Just invoke the call to get the UID since that
+        * has no side effects.
+        */
+       if (optee_msg_api_uid_is_optee_api(cpuhp_invoke_fn))
+               return 0;
+       else
+               return -EINVAL;
+}
+
+static int optee_load_fw(struct platform_device *pdev,
+                        optee_invoke_fn *invoke_fn)
+{
+       const struct firmware *fw = NULL;
+       struct arm_smccc_res res;
+       phys_addr_t data_pa;
+       u8 *data_buf = NULL;
+       u64 data_size;
+       u32 data_pa_high, data_pa_low;
+       u32 data_size_high, data_size_low;
+       int rc;
+       int hp_state;
+
+       if (!optee_msg_api_uid_is_optee_image_load(invoke_fn))
+               return 0;
+
+       rc = request_firmware(&fw, OPTEE_FW_IMAGE, &pdev->dev);
+       if (rc) {
+               /*
+                * The firmware in the rootfs will not be accessible until we
+                * are in the SYSTEM_RUNNING state, so return EPROBE_DEFER until
+                * that point.
+                */
+               if (system_state < SYSTEM_RUNNING)
+                       return -EPROBE_DEFER;
+               goto fw_err;
+       }
+
+       data_size = fw->size;
+       /*
+        * This uses the GFP_DMA flag to ensure we are allocated memory in the
+        * 32-bit space since TF-A cannot map memory beyond the 32-bit boundary.
+        */
+       data_buf = kmalloc(fw->size, GFP_KERNEL | GFP_DMA);
+       if (!data_buf) {
+               rc = -ENOMEM;
+               goto fw_err;
+       }
+       memcpy(data_buf, fw->data, fw->size);
+       data_pa = virt_to_phys(data_buf);
+       reg_pair_from_64(&data_pa_high, &data_pa_low, data_pa);
+       reg_pair_from_64(&data_size_high, &data_size_low, data_size);
+       goto fw_load;
+
+fw_err:
+       pr_warn("image loading failed\n");
+       data_pa_high = 0;
+       data_pa_low = 0;
+       data_size_high = 0;
+       data_size_low = 0;
+
+fw_load:
+       /*
+        * Always invoke the SMC, even if loading the image fails, to indicate
+        * to EL3 that we have passed the point where it should allow invoking
+        * this SMC.
+        */
+       pr_warn("OP-TEE image loaded from kernel, this can be insecure");
+       invoke_fn(OPTEE_SMC_CALL_LOAD_IMAGE, data_size_high, data_size_low,
+                 data_pa_high, data_pa_low, 0, 0, 0, &res);
+       if (!rc)
+               rc = res.a0;
+       if (fw)
+               release_firmware(fw);
+       kfree(data_buf);
+
+       if (!rc) {
+               /*
+                * We need to initialize OP-TEE on all other running cores as
+                * well. Any cores that aren't running yet will get initialized
+                * when they are brought up by the power management functions in
+                * TF-A which are registered by the OP-TEE SPD. Due to that we
+                * can un-register the callback right after registering it.
+                */
+               cpuhp_invoke_fn = invoke_fn;
+               hp_state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "optee:probe",
+                                            optee_cpuhp_probe, NULL);
+               if (hp_state < 0) {
+                       pr_warn("Failed with CPU hotplug setup for OP-TEE");
+                       return -EINVAL;
+               }
+               cpuhp_remove_state(hp_state);
+               cpuhp_invoke_fn = NULL;
+       }
+
+       return rc;
+}
+#else
+static inline int optee_load_fw(struct platform_device *pdev,
+                               optee_invoke_fn *invoke_fn)
+{
+       return 0;
+}
+#endif
+
 static int optee_probe(struct platform_device *pdev)
 {
        optee_invoke_fn *invoke_fn;
@@ -1372,6 +1619,10 @@ static int optee_probe(struct platform_device *pdev)
        if (IS_ERR(invoke_fn))
                return PTR_ERR(invoke_fn);
 
+       rc = optee_load_fw(pdev, invoke_fn);
+       if (rc)
+               return rc;
+
        if (!optee_msg_api_uid_is_optee_api(invoke_fn)) {
                pr_warn("api uid mismatch\n");
                return -EINVAL;
index aa95439708dc967a38451506ef611c86dcb38de9..802495b202763cc95d58f886ad32baa7ae76bd4b 100644 (file)
 #define QCOM_ID_SA8155                 362
 #define QCOM_ID_SDA439                 363
 #define QCOM_ID_SDA429                 364
+#define QCOM_ID_SM7150                 365
 #define QCOM_ID_IPQ8070                        375
 #define QCOM_ID_IPQ8071                        376
 #define QCOM_ID_QM215                  386
 #define QCOM_ID_QCM2150                        436
 #define QCOM_ID_SDA429W                        437
 #define QCOM_ID_SM8350                 439
+#define QCOM_ID_QCM2290                        441
 #define QCOM_ID_SM6115                 444
 #define QCOM_ID_SC8280XP               449
 #define QCOM_ID_IPQ6005                        453
 #define QCOM_ID_SC7280                 487
 #define QCOM_ID_SC7180P                        495
 #define QCOM_ID_SM6375                 507
+#define QCOM_ID_IPQ9514                        510
+#define QCOM_ID_IPQ9550                        511
+#define QCOM_ID_IPQ9554                        512
+#define QCOM_ID_IPQ9570                        513
+#define QCOM_ID_IPQ9574                        514
 #define QCOM_ID_SM8550                 519
+#define QCOM_ID_IPQ9510                        521
+#define QCOM_ID_QRB4210                        523
+#define QCOM_ID_QRB2210                        524
+#define QCOM_ID_SA8775P                        534
 #define QCOM_ID_QRU1000                        539
 #define QCOM_ID_QDU1000                        545
 #define QCOM_ID_QDU1010                        587
index eea6ad69f0b07f450500dcbac279331161477887..ff53238585721700fc3276e8f116e8b25fd91fb2 100644 (file)
@@ -30,7 +30,6 @@
 #define R8A7795_PD_CA53_SCU            21
 #define R8A7795_PD_3DG_E               22
 #define R8A7795_PD_A3IR                        24
-#define R8A7795_PD_A2VC0               25      /* ES1.x only */
 #define R8A7795_PD_A2VC1               26
 
 /* Always-on power area */
index 1e449a5d7f5c19d27e4f111b54e2db0fa885dc46..250ea4efb7cb6ab257b03d3df704a598a9e9ff3a 100644 (file)
@@ -94,7 +94,7 @@ extern int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
                                          u32 cp_nonpixel_start,
                                          u32 cp_nonpixel_size);
 extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
-                              unsigned int *src,
+                              u64 *src,
                               const struct qcom_scm_vmperm *newvm,
                               unsigned int dest_cnt);
 
index 2b498f4f394649551ecc0783aa57e566004429bb..649955d2cf5cdd89de731d4b402d7bda22e0f93c 100644 (file)
@@ -27,6 +27,8 @@ struct cmdq_client {
        struct mbox_chan *chan;
 };
 
+#if IS_ENABLED(CONFIG_MTK_CMDQ)
+
 /**
  * cmdq_dev_get_client_reg() - parse cmdq client reg from the device
  *                            node of CMDQ client
@@ -277,4 +279,116 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt);
  */
 int cmdq_pkt_flush_async(struct cmdq_pkt *pkt);
 
+#else /* IS_ENABLED(CONFIG_MTK_CMDQ) */
+
+static inline int cmdq_dev_get_client_reg(struct device *dev,
+                                         struct cmdq_client_reg *client_reg, int idx)
+{
+       return -ENODEV;
+}
+
+static inline struct cmdq_client *cmdq_mbox_create(struct device *dev, int index)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline void cmdq_mbox_destroy(struct cmdq_client *client) { }
+
+static inline  struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline void cmdq_pkt_destroy(struct cmdq_pkt *pkt) { }
+
+static inline int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys,
+                                     u16 offset, u32 value, u32 mask)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
+                                 u16 addr_low, u16 reg_idx)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
+                                  u16 addr_low, u16 src_reg_idx)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
+                                       u16 addr_low, u16 src_reg_idx, u32 mask)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx,
+                                        u16 addr_low, u32 value)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx,
+                                             u16 addr_low, u32 value, u32 mask)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys,
+                               u16 offset, u32 value)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys,
+                                    u16 offset, u32 value, u32 mask)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_flush_async(struct cmdq_pkt *pkt)
+{
+       return -EINVAL;
+}
+
+#endif /* IS_ENABLED(CONFIG_MTK_CMDQ) */
+
 #endif /* __MTK_CMDQ_H__ */
index dc2963a0a0f7ea71def09bf8d0b1b6ba6ed01a1f..37544ea6286d87dcf7f399bf0d413df3bd097774 100644 (file)
@@ -99,4 +99,10 @@ void mtk_mmsys_mixer_in_config(struct device *dev, int idx, bool alpha_sel, u16
 void mtk_mmsys_mixer_in_channel_swap(struct device *dev, int idx, bool channel_swap,
                                     struct cmdq_pkt *cmdq_pkt);
 
+void mtk_mmsys_vpp_rsz_merge_config(struct device *dev, u32 id, bool enable,
+                                   struct cmdq_pkt *cmdq_pkt);
+
+void mtk_mmsys_vpp_rsz_dcm_config(struct device *dev, bool enable,
+                                 struct cmdq_pkt *cmdq_pkt);
+
 #endif /* __MTK_MMSYS_H */
index b335c2837cd8b074503c3d7f67862f4d546b88b6..635218e3ac68a268f5b04fb7ad8e4d2d6eb51484 100644 (file)
@@ -22,6 +22,41 @@ enum mtk_mutex_mod_index {
        MUTEX_MOD_IDX_MDP_CCORR0,
        MUTEX_MOD_IDX_MDP_HDR0,
        MUTEX_MOD_IDX_MDP_COLOR0,
+       MUTEX_MOD_IDX_MDP_RDMA1,
+       MUTEX_MOD_IDX_MDP_RDMA2,
+       MUTEX_MOD_IDX_MDP_RDMA3,
+       MUTEX_MOD_IDX_MDP_STITCH0,
+       MUTEX_MOD_IDX_MDP_FG0,
+       MUTEX_MOD_IDX_MDP_FG1,
+       MUTEX_MOD_IDX_MDP_FG2,
+       MUTEX_MOD_IDX_MDP_FG3,
+       MUTEX_MOD_IDX_MDP_HDR1,
+       MUTEX_MOD_IDX_MDP_HDR2,
+       MUTEX_MOD_IDX_MDP_HDR3,
+       MUTEX_MOD_IDX_MDP_AAL1,
+       MUTEX_MOD_IDX_MDP_AAL2,
+       MUTEX_MOD_IDX_MDP_AAL3,
+       MUTEX_MOD_IDX_MDP_RSZ2,
+       MUTEX_MOD_IDX_MDP_RSZ3,
+       MUTEX_MOD_IDX_MDP_MERGE2,
+       MUTEX_MOD_IDX_MDP_MERGE3,
+       MUTEX_MOD_IDX_MDP_TDSHP1,
+       MUTEX_MOD_IDX_MDP_TDSHP2,
+       MUTEX_MOD_IDX_MDP_TDSHP3,
+       MUTEX_MOD_IDX_MDP_COLOR1,
+       MUTEX_MOD_IDX_MDP_COLOR2,
+       MUTEX_MOD_IDX_MDP_COLOR3,
+       MUTEX_MOD_IDX_MDP_OVL0,
+       MUTEX_MOD_IDX_MDP_OVL1,
+       MUTEX_MOD_IDX_MDP_PAD0,
+       MUTEX_MOD_IDX_MDP_PAD1,
+       MUTEX_MOD_IDX_MDP_PAD2,
+       MUTEX_MOD_IDX_MDP_PAD3,
+       MUTEX_MOD_IDX_MDP_TCC0,
+       MUTEX_MOD_IDX_MDP_TCC1,
+       MUTEX_MOD_IDX_MDP_WROT1,
+       MUTEX_MOD_IDX_MDP_WROT2,
+       MUTEX_MOD_IDX_MDP_WROT3,
 
        MUTEX_MOD_IDX_MAX               /* ALWAYS keep at the end */
 };
index 400213daa461d5998e106871065529c2f87ab92a..c55a0bc8cb0e908f41f04d746fb6d00cf49938e7 100644 (file)
@@ -245,12 +245,22 @@ struct geni_se {
 /* SE_HW_PARAM_0 fields */
 #define TX_FIFO_WIDTH_MSK              GENMASK(29, 24)
 #define TX_FIFO_WIDTH_SHFT             24
+/*
+ * For QUP HW Version >= 3.10 Tx fifo depth support is increased
+ * to 256bytes and corresponding bits are 16 to 23
+ */
+#define TX_FIFO_DEPTH_MSK_256_BYTES    GENMASK(23, 16)
 #define TX_FIFO_DEPTH_MSK              GENMASK(21, 16)
 #define TX_FIFO_DEPTH_SHFT             16
 
 /* SE_HW_PARAM_1 fields */
 #define RX_FIFO_WIDTH_MSK              GENMASK(29, 24)
 #define RX_FIFO_WIDTH_SHFT             24
+/*
+ * For QUP HW Version >= 3.10 Rx fifo depth support is increased
+ * to 256bytes and corresponding bits are 16 to 23
+ */
+#define RX_FIFO_DEPTH_MSK_256_BYTES    GENMASK(23, 16)
 #define RX_FIFO_DEPTH_MSK              GENMASK(21, 16)
 #define RX_FIFO_DEPTH_SHFT             16
 
@@ -391,7 +401,8 @@ static inline void geni_se_abort_s_cmd(struct geni_se *se)
 
 /**
  * geni_se_get_tx_fifo_depth() - Get the TX fifo depth of the serial engine
- * @se:        Pointer to the concerned serial engine.
+ * based on QUP HW version
+ * @se: Pointer to the concerned serial engine.
  *
  * This function is used to get the depth i.e. number of elements in the
  * TX fifo of the serial engine.
@@ -400,11 +411,20 @@ static inline void geni_se_abort_s_cmd(struct geni_se *se)
  */
 static inline u32 geni_se_get_tx_fifo_depth(struct geni_se *se)
 {
-       u32 val;
+       u32 val, hw_version, hw_major, hw_minor, tx_fifo_depth_mask;
+
+       hw_version = geni_se_get_qup_hw_version(se);
+       hw_major = GENI_SE_VERSION_MAJOR(hw_version);
+       hw_minor = GENI_SE_VERSION_MINOR(hw_version);
+
+       if ((hw_major == 3 && hw_minor >= 10) || hw_major > 3)
+               tx_fifo_depth_mask = TX_FIFO_DEPTH_MSK_256_BYTES;
+       else
+               tx_fifo_depth_mask = TX_FIFO_DEPTH_MSK;
 
        val = readl_relaxed(se->base + SE_HW_PARAM_0);
 
-       return (val & TX_FIFO_DEPTH_MSK) >> TX_FIFO_DEPTH_SHFT;
+       return (val & tx_fifo_depth_mask) >> TX_FIFO_DEPTH_SHFT;
 }
 
 /**
@@ -427,7 +447,8 @@ static inline u32 geni_se_get_tx_fifo_width(struct geni_se *se)
 
 /**
  * geni_se_get_rx_fifo_depth() - Get the RX fifo depth of the serial engine
- * @se:        Pointer to the concerned serial engine.
+ * based on QUP HW version
+ * @se: Pointer to the concerned serial engine.
  *
  * This function is used to get the depth i.e. number of elements in the
  * RX fifo of the serial engine.
@@ -436,11 +457,20 @@ static inline u32 geni_se_get_tx_fifo_width(struct geni_se *se)
  */
 static inline u32 geni_se_get_rx_fifo_depth(struct geni_se *se)
 {
-       u32 val;
+       u32 val, hw_version, hw_major, hw_minor, rx_fifo_depth_mask;
+
+       hw_version = geni_se_get_qup_hw_version(se);
+       hw_major = GENI_SE_VERSION_MAJOR(hw_version);
+       hw_minor = GENI_SE_VERSION_MINOR(hw_version);
+
+       if ((hw_major == 3 && hw_minor >= 10) || hw_major > 3)
+               rx_fifo_depth_mask = RX_FIFO_DEPTH_MSK_256_BYTES;
+       else
+               rx_fifo_depth_mask = RX_FIFO_DEPTH_MSK;
 
        val = readl_relaxed(se->base + SE_HW_PARAM_1);
 
-       return (val & RX_FIFO_DEPTH_MSK) >> RX_FIFO_DEPTH_SHFT;
+       return (val & rx_fifo_depth_mask) >> RX_FIFO_DEPTH_SHFT;
 }
 
 void geni_se_init(struct geni_se *se, u32 rx_wm, u32 rx_rfr);
index ad1fd718169d9750fe07b3a05623398c95bfdb19..423220e66026252630bfd065bfd08bd4ab05b457 100644 (file)
@@ -120,7 +120,7 @@ struct llcc_edac_reg_offset {
 
 /**
  * struct llcc_drv_data - Data associated with the llcc driver
- * @regmap: regmap associated with the llcc device
+ * @regmaps: regmaps associated with the llcc device
  * @bcast_regmap: regmap associated with llcc broadcast offset
  * @cfg: pointer to the data structure for slice configuration
  * @edac_reg_offset: Offset of the LLCC EDAC registers
@@ -129,12 +129,11 @@ struct llcc_edac_reg_offset {
  * @max_slices: max slices as read from device tree
  * @num_banks: Number of llcc banks
  * @bitmap: Bit map to track the active slice ids
- * @offsets: Pointer to the bank offsets array
  * @ecc_irq: interrupt for llcc cache error detection and reporting
  * @version: Indicates the LLCC version
  */
 struct llcc_drv_data {
-       struct regmap *regmap;
+       struct regmap **regmaps;
        struct regmap *bcast_regmap;
        const struct llcc_slice_config *cfg;
        const struct llcc_edac_reg_offset *edac_reg_offset;
@@ -143,7 +142,6 @@ struct llcc_drv_data {
        u32 max_slices;
        u32 num_banks;
        unsigned long *bitmap;
-       u32 *offsets;
        int ecc_irq;
        u32 version;
 };
diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
new file mode 100644 (file)
index 0000000..5870a94
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef __QCOM_ICE_H__
+#define __QCOM_ICE_H__
+
+#include <linux/types.h>
+
+struct qcom_ice;
+
+enum qcom_ice_crypto_key_size {
+       QCOM_ICE_CRYPTO_KEY_SIZE_INVALID        = 0x0,
+       QCOM_ICE_CRYPTO_KEY_SIZE_128            = 0x1,
+       QCOM_ICE_CRYPTO_KEY_SIZE_192            = 0x2,
+       QCOM_ICE_CRYPTO_KEY_SIZE_256            = 0x3,
+       QCOM_ICE_CRYPTO_KEY_SIZE_512            = 0x4,
+};
+
+enum qcom_ice_crypto_alg {
+       QCOM_ICE_CRYPTO_ALG_AES_XTS             = 0x0,
+       QCOM_ICE_CRYPTO_ALG_BITLOCKER_AES_CBC   = 0x1,
+       QCOM_ICE_CRYPTO_ALG_AES_ECB             = 0x2,
+       QCOM_ICE_CRYPTO_ALG_ESSIV_AES_CBC       = 0x3,
+};
+
+int qcom_ice_enable(struct qcom_ice *ice);
+int qcom_ice_resume(struct qcom_ice *ice);
+int qcom_ice_suspend(struct qcom_ice *ice);
+int qcom_ice_program_key(struct qcom_ice *ice,
+                        u8 algorithm_id, u8 key_size,
+                        const u8 crypto_key[], u8 data_unit_size,
+                        int slot);
+int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
+struct qcom_ice *of_qcom_ice_get(struct device *dev);
+#endif /* __QCOM_ICE_H__ */