Commit cc3c470a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arm-drivers-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc

Pull ARM driver updates from Arnd Bergmann:
 "There are minor updates to SoC specific drivers for chips by Rockchip,
  Samsung, NVIDIA, TI, NXP, i.MX, Qualcomm, and Broadcom.

  Noteworthy driver changes include:

   - Several conversions of DT bindings to yaml format.

   - Renesas adds driver support for R-Car V4H, RZ/V2M and RZ/G2UL SoCs.

   - Qualcomm adds a bus driver for the SSC (Snapdragon Sensor Core),
     and support for more chips in the RPMh power domains and the
     soc-id.

   - NXP has a new driver for the HDMI blk-ctrl on i.MX8MP.

   - Apple M1 gains support for the on-chip NVMe controller, making it
     possible to finally use the internal disks. This also includes SoC
     drivers for their RTKit IPC and for the SART DMA address filter.

  For other subsystems that merge their drivers through the SoC tree, we
  have

   - Firmware drivers for the ARM firmware stack including TEE, OP-TEE,
     SCMI and FF-A get a number of smaller updates and cleanups. OP-TEE
     now has a cache for firmware argument structures as an
     optimization, and SCMI now supports the 3.1 version of the
     specification.

   - Reset controller updates to Amlogic, ASpeed, Renesas and ACPI
     drivers

   - Memory controller updates for Tegra, and a few updates for other
     platforms"

* tag 'arm-drivers-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (159 commits)
  memory: tegra: Add MC error logging on Tegra186 onward
  memory: tegra: Add memory controller channels support
  memory: tegra: Add APE memory clients for Tegra234
  memory: tegra: Add Tegra234 support
  nvme-apple: fix sparse endianess warnings
  soc/tegra: pmc: Document core domain fields
  soc: qcom: pdr: use static for servreg_* variables
  soc: imx: fix semicolon.cocci warnings
  soc: renesas: R-Car V3U is R-Car Gen4
  soc: imx: add i.MX8MP HDMI blk-ctrl
  soc: imx: imx8m-blk-ctrl: Add i.MX8MP media blk-ctrl
  soc: imx: add i.MX8MP HSIO blk-ctrl
  soc: imx: imx8m-blk-ctrl: set power device name
  soc: qcom: llcc: Add sc8180x and sc8280xp configurations
  dt-bindings: arm: msm: Add sc8180x and sc8280xp LLCC compatibles
  soc/tegra: pmc: Select REGMAP
  dt-bindings: reset: st,sti-powerdown: Convert to yaml
  dt-bindings: reset: st,sti-picophyreset: Convert to yaml
  dt-bindings: reset: socfpga: Convert to yaml
  dt-bindings: reset: snps,axs10x-reset: Convert to yaml
  ...
parents ae862183 d4a3b442
...@@ -23,6 +23,8 @@ properties: ...@@ -23,6 +23,8 @@ properties:
enum: enum:
- qcom,sc7180-llcc - qcom,sc7180-llcc
- qcom,sc7280-llcc - qcom,sc7280-llcc
- qcom,sc8180x-llcc
- qcom,sc8280xp-llcc
- qcom,sdm845-llcc - qcom,sdm845-llcc
- qcom,sm6350-llcc - qcom,sm6350-llcc
- qcom,sm8150-llcc - qcom,sm8150-llcc
......
...@@ -39,8 +39,11 @@ description: | ...@@ -39,8 +39,11 @@ description: |
msm8994 msm8994
msm8996 msm8996
sa8155p sa8155p
sa8540p
sc7180 sc7180
sc7280 sc7280
sc8180x
sc8280xp
sdm630 sdm630
sdm632 sdm632
sdm660 sdm660
...@@ -226,6 +229,18 @@ properties: ...@@ -226,6 +229,18 @@ properties:
- google,senor - google,senor
- const: qcom,sc7280 - const: qcom,sc7280
- items:
- enum:
- lenovo,flex-5g
- microsoft,surface-prox
- qcom,sc8180x-primus
- const: qcom,sc8180x
- items:
- enum:
- qcom,sc8280xp-qrd
- const: qcom,sc8280xp
- items: - items:
- enum: - enum:
- fairphone,fp3 - fairphone,fp3
...@@ -259,6 +274,11 @@ properties: ...@@ -259,6 +274,11 @@ properties:
- qcom,sa8155p-adp - qcom,sa8155p-adp
- const: qcom,sa8155p - const: qcom,sa8155p
- items:
- enum:
- qcom,sa8295p-adp
- const: qcom,sa8540p
- items: - items:
- enum: - enum:
- fairphone,fp4 - fairphone,fp4
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/bus/qcom,ssc-block-bus.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: The AHB Bus Providing a Global View of the SSC Block on (some) qcom SoCs
maintainers:
- Michael Srba <Michael.Srba@seznam.cz>
description: |
This binding describes the dependencies (clocks, resets, power domains) which
need to be turned on in a sequence before communication over the AHB bus
becomes possible.
Additionally, the reg property is used to pass to the driver the location of
two sadly undocumented registers which need to be poked as part of the sequence.
The SSC (Snapdragon Sensor Core) block contains a gpio controller, i2c/spi/uart
controllers, a hexagon core, and a clock controller which provides clocks for
the above.
properties:
compatible:
items:
- const: qcom,msm8998-ssc-block-bus
- const: qcom,ssc-block-bus
reg:
description: |
Shall contain the addresses of the SSCAON_CONFIG0 and SSCAON_CONFIG1
registers
minItems: 2
maxItems: 2
reg-names:
items:
- const: mpm_sscaon_config0
- const: mpm_sscaon_config1
'#address-cells':
enum: [ 1, 2 ]
'#size-cells':
enum: [ 1, 2 ]
ranges: true
clocks:
minItems: 6
maxItems: 6
clock-names:
items:
- const: xo
- const: aggre2
- const: gcc_im_sleep
- const: aggre2_north
- const: ssc_xo
- const: ssc_ahbs
power-domains:
description: Power domain phandles for the ssc_cx and ssc_mx power domains
minItems: 2
maxItems: 2
power-domain-names:
items:
- const: ssc_cx
- const: ssc_mx
resets:
description: |
Reset phandles for the ssc_reset and ssc_bcr resets (note: ssc_bcr is the
branch control register associated with the ssc_xo and ssc_ahbs clocks)
minItems: 2
maxItems: 2
reset-names:
items:
- const: ssc_reset
- const: ssc_bcr
qcom,halt-regs:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: describes how to locate the ssc AXI halt register
items:
- items:
- description: Phandle reference to a syscon representing TCSR
- description: offset for the ssc AXI halt register
required:
- compatible
- reg
- reg-names
- '#address-cells'
- '#size-cells'
- ranges
- clocks
- clock-names
- power-domains
- power-domain-names
- resets
- reset-names
- qcom,halt-regs
additionalProperties:
type: object
examples:
- |
#include <dt-bindings/clock/qcom,gcc-msm8998.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/power/qcom-rpmpd.h>
soc {
#address-cells = <1>;
#size-cells = <1>;
// devices under this node are physically located in the SSC block, connected to an ssc-internal bus;
ssc_ahb_slave: bus@10ac008 {
#address-cells = <1>;
#size-cells = <1>;
ranges;
compatible = "qcom,msm8998-ssc-block-bus", "qcom,ssc-block-bus";
reg = <0x10ac008 0x4>, <0x10ac010 0x4>;
reg-names = "mpm_sscaon_config0", "mpm_sscaon_config1";
clocks = <&xo>,
<&rpmcc RPM_SMD_AGGR2_NOC_CLK>,
<&gcc GCC_IM_SLEEP>,
<&gcc AGGRE2_SNOC_NORTH_AXI>,
<&gcc SSC_XO>,
<&gcc SSC_CNOC_AHBS_CLK>;
clock-names = "xo", "aggre2", "gcc_im_sleep", "aggre2_north", "ssc_xo", "ssc_ahbs";
resets = <&gcc GCC_SSC_RESET>, <&gcc GCC_SSC_BCR>;
reset-names = "ssc_reset", "ssc_bcr";
power-domains = <&rpmpd MSM8998_SSCCX>, <&rpmpd MSM8998_SSCMX>;
power-domain-names = "ssc_cx", "ssc_mx";
qcom,halt-regs = <&tcsr_mutex_regs 0x26000>;
};
};
...@@ -19,6 +19,7 @@ Required properties: ...@@ -19,6 +19,7 @@ Required properties:
* "qcom,scm-msm8953" * "qcom,scm-msm8953"
* "qcom,scm-msm8960" * "qcom,scm-msm8960"
* "qcom,scm-msm8974" * "qcom,scm-msm8974"
* "qcom,scm-msm8976"
* "qcom,scm-msm8994" * "qcom,scm-msm8994"
* "qcom,scm-msm8996" * "qcom,scm-msm8996"
* "qcom,scm-msm8998" * "qcom,scm-msm8998"
...@@ -37,7 +38,7 @@ Required properties: ...@@ -37,7 +38,7 @@ Required properties:
* core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660" and * core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660" and
"qcom,scm-msm8960" "qcom,scm-msm8960"
* core, iface and bus clocks required for "qcom,scm-apq8084", * core, iface and bus clocks required for "qcom,scm-apq8084",
"qcom,scm-msm8916", "qcom,scm-msm8953" and "qcom,scm-msm8974" "qcom,scm-msm8916", "qcom,scm-msm8953", "qcom,scm-msm8974" and "qcom,scm-msm8976"
- clock-names: Must contain "core" for the core clock, "iface" for the interface - clock-names: Must contain "core" for the core clock, "iface" for the interface
clock and "bus" for the bus clock per the requirements of the compatible. clock and "bus" for the bus clock per the requirements of the compatible.
- qcom,dload-mode: phandle to the TCSR hardware block and offset of the - qcom,dload-mode: phandle to the TCSR hardware block and offset of the
......
...@@ -45,20 +45,20 @@ additionalProperties: false ...@@ -45,20 +45,20 @@ additionalProperties: false
examples: examples:
# Example 1: apps bcm_voter on SDM845 SoC should be defined inside &apps_rsc node # Example 1: apps bcm_voter on SDM845 SoC should be defined inside &apps_rsc node
# as defined in Documentation/devicetree/bindings/soc/qcom/rpmh-rsc.txt # as defined in Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml
- | - |
apps_bcm_voter: bcm_voter { apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter"; compatible = "qcom,bcm-voter";
}; };
# Example 2: disp bcm_voter on SDM845 should be defined inside &disp_rsc node # Example 2: disp bcm_voter on SDM845 should be defined inside &disp_rsc node
# as defined in Documentation/devicetree/bindings/soc/qcom/rpmh-rsc.txt # as defined in Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml
- | - |
#include <dt-bindings/interconnect/qcom,icc.h> #include <dt-bindings/interconnect/qcom,icc.h>
disp_bcm_voter: bcm_voter { disp_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter"; compatible = "qcom,bcm-voter";
qcom,tcs-wait = <QCOM_ICC_TAG_AMC>; qcom,tcs-wait = <QCOM_ICC_TAG_AMC>;
}; };
......
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/iommu/apple,sart.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Apple SART DMA address filter
maintainers:
- Sven Peter <sven@svenpeter.dev>
description:
Apple SART is a simple address filter for DMA transactions. Regions of
physical memory must be added to the SART's allow list before any
DMA can target these. Unlike a proper IOMMU no remapping can be done and
special support in the consumer driver is required since not all DMA
transactions of a single device are subject to SART filtering.
SART1 has first been used since at least the A11 (iPhone 8 and iPhone X)
and allows 36 bit of physical address space and filter entries with sizes
up to 24 bit.
SART2, first seen in A14 and M1, allows 36 bit of physical address space
and filter entry size up to 36 bit.
SART3, first seen in M1 Pro/Max, extends both the address space and filter
entry size to 42 bit.
properties:
compatible:
enum:
- apple,t6000-sart
- apple,t8103-sart
reg:
maxItems: 1
power-domains:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
iommu@7bc50000 {
compatible = "apple,t8103-sart";
reg = <0x7bc50000 0x4000>;
};
...@@ -31,8 +31,13 @@ properties: ...@@ -31,8 +31,13 @@ properties:
- renesas,r8a774b1-rpc-if # RZ/G2N - renesas,r8a774b1-rpc-if # RZ/G2N
- renesas,r8a774c0-rpc-if # RZ/G2E - renesas,r8a774c0-rpc-if # RZ/G2E
- renesas,r8a774e1-rpc-if # RZ/G2H - renesas,r8a774e1-rpc-if # RZ/G2H
- renesas,r8a7795-rpc-if # R-Car H3
- renesas,r8a7796-rpc-if # R-Car M3-W
- renesas,r8a77961-rpc-if # R-Car M3-W+
- renesas,r8a77965-rpc-if # R-Car M3-N
- renesas,r8a77970-rpc-if # R-Car V3M - renesas,r8a77970-rpc-if # R-Car V3M
- renesas,r8a77980-rpc-if # R-Car V3H - renesas,r8a77980-rpc-if # R-Car V3H
- renesas,r8a77990-rpc-if # R-Car E3
- renesas,r8a77995-rpc-if # R-Car D3 - renesas,r8a77995-rpc-if # R-Car D3
- renesas,r8a779a0-rpc-if # R-Car V3U - renesas,r8a779a0-rpc-if # R-Car V3U
- const: renesas,rcar-gen3-rpc-if # a generic R-Car gen3 or RZ/G2{E,H,M,N} device - const: renesas,rcar-gen3-rpc-if # a generic R-Car gen3 or RZ/G2{E,H,M,N} device
......
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/nvme/apple,nvme-ans.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Apple ANS NVM Express host controller
maintainers:
- Sven Peter <sven@svenpeter.dev>
properties:
compatible:
items:
- enum:
- apple,t8103-nvme-ans2
- apple,t6000-nvme-ans2
- const: apple,nvme-ans2
reg:
items:
- description: NVMe and NVMMU registers
- description: ANS2 co-processor control registers
reg-names:
items:
- const: nvme
- const: ans
resets:
maxItems: 1
power-domains:
# two domains for t8103, three for t6000
minItems: 2
items:
- description: power domain for the NVMe controller.
- description: power domain for the first PCIe bus connecting the NVMe
controller to the storage modules.
- description: optional power domain for the second PCIe bus
connecting the NVMe controller to the storage modules.
power-domain-names:
minItems: 2
items:
- const: ans
- const: apcie0
- const: apcie1
mboxes:
maxItems: 1
description: Mailbox of the ANS2 co-processor
interrupts:
maxItems: 1
apple,sart:
maxItems: 1
$ref: /schemas/types.yaml#/definitions/phandle
description: |
Reference to the SART address filter.
The SART address filter is documented in iommu/apple,sart.yaml.
if:
properties:
compatible:
contains:
const: apple,t8103-nvme-ans2
then:
properties:
power-domains:
maxItems: 2
power-domain-names:
maxItems: 2
else:
properties:
power-domains:
minItems: 3
power-domain-names:
minItems: 3
required:
- compatible
- reg
- reg-names
- resets
- power-domains
- power-domain-names
- mboxes
- interrupts
- apple,sart
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/apple-aic.h>
#include <dt-bindings/interrupt-controller/irq.h>
nvme@7bcc0000 {
compatible = "apple,t8103-nvme-ans2", "apple,nvme-ans2";
reg = <0x7bcc0000 0x40000>, <0x77400000 0x4000>;
reg-names = "nvme", "ans";
interrupts = <AIC_IRQ 590 IRQ_TYPE_LEVEL_HIGH>;
mboxes = <&ans>;
apple,sart = <&sart>;
power-domains = <&ps_ans2>, <&ps_apcie_st>;
power-domain-names = "ans", "apcie0";
resets = <&ps_ans2>;
};
...@@ -27,12 +27,15 @@ properties: ...@@ -27,12 +27,15 @@ properties:
- qcom,msm8998-rpmpd - qcom,msm8998-rpmpd
- qcom,qcm2290-rpmpd - qcom,qcm2290-rpmpd
- qcom,qcs404-rpmpd - qcom,qcs404-rpmpd
- qcom,sa8540p-rpmhpd
- qcom,sdm660-rpmpd - qcom,sdm660-rpmpd
- qcom,sc7180-rpmhpd - qcom,sc7180-rpmhpd
- qcom,sc7280-rpmhpd - qcom,sc7280-rpmhpd
- qcom,sc8180x-rpmhpd - qcom,sc8180x-rpmhpd
- qcom,sc8280xp-rpmhpd
- qcom,sdm845-rpmhpd - qcom,sdm845-rpmhpd
- qcom,sdx55-rpmhpd - qcom,sdx55-rpmhpd
- qcom,sdx65-rpmhpd
- qcom,sm6115-rpmpd - qcom,sm6115-rpmpd
- qcom,sm6125-rpmpd - qcom,sm6125-rpmpd
- qcom,sm6350-rpmhpd - qcom,sm6350-rpmhpd
......
...@@ -12,7 +12,7 @@ description: ...@@ -12,7 +12,7 @@ description:
resides as a subnode of the SMD. As such, the SMD-RPM regulator requires resides as a subnode of the SMD. As such, the SMD-RPM regulator requires
that the SMD and RPM nodes be present. that the SMD and RPM nodes be present.
Please refer to Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt for Please refer to Documentation/devicetree/bindings/soc/qcom/qcom,smd.yaml for
information pertaining to the SMD node. information pertaining to the SMD node.
Please refer to Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml Please refer to Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
...@@ -69,7 +69,8 @@ description: ...@@ -69,7 +69,8 @@ description:
l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22 l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22
maintainers: maintainers:
- Kathiravan T <kathirav@codeaurora.org> - Andy Gross <agross@kernel.org>
- Bjorn Andersson <bjorn.andersson@linaro.org>
properties: properties:
compatible: compatible:
......
...@@ -250,7 +250,7 @@ the memory regions used by the Hexagon firmware. Each sub-node must contain: ...@@ -250,7 +250,7 @@ the memory regions used by the Hexagon firmware. Each sub-node must contain:
The Hexagon node may also have an subnode named either "smd-edge" or The Hexagon node may also have an subnode named either "smd-edge" or
"glink-edge" that describes the communication edge, channels and devices "glink-edge" that describes the communication edge, channels and devices
related to the Hexagon. See ../soc/qcom/qcom,smd.txt and related to the Hexagon. See ../soc/qcom/qcom,smd.yaml and
../soc/qcom/qcom,glink.txt for details on how to describe these. ../soc/qcom/qcom,glink.txt for details on how to describe these.
= EXAMPLE = EXAMPLE
......
...@@ -111,7 +111,7 @@ and its resource dependencies. It is described by the following properties: ...@@ -111,7 +111,7 @@ and its resource dependencies. It is described by the following properties:
The wcnss node can also have an subnode named "smd-edge" that describes the SMD The wcnss node can also have an subnode named "smd-edge" that describes the SMD
edge, channels and devices related to the WCNSS. edge, channels and devices related to the WCNSS.
See ../soc/qcom/qcom,smd.txt for details on how to describe the SMD edge. See ../soc/qcom/qcom,smd.yaml for details on how to describe the SMD edge.
= EXAMPLE = EXAMPLE
The following example describes the resources needed to boot control the WCNSS, The following example describes the resources needed to boot control the WCNSS,
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/altr,rst-mgr.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Altera SOCFPGA Reset Manager
maintainers:
- Dinh Nguyen <dinguyen@altera.com>
properties:
compatible:
oneOf:
- description: Cyclone5/Arria5/Arria10
const: altr,rst-mgr
- description: Stratix10 ARM64 SoC
items:
- const: altr,stratix10-rst-mgr
- const: altr,rst-mgr
reg:
maxItems: 1
altr,modrst-offset:
$ref: /schemas/types.yaml#/definitions/uint32
description: Offset of the first modrst register
'#reset-cells':
const: 1
required:
- compatible
- reg
- altr,modrst-offset
- '#reset-cells'
additionalProperties: false
examples:
- |
rstmgr@ffd05000 {
compatible = "altr,rst-mgr";
reg = <0xffd05000 0x1000>;
altr,modrst-offset = <0x10>;
#reset-cells = <1>;
};
* Amlogic audio memory arbiter controller
The Amlogic Audio ARB is a simple device which enables or
disables the access of Audio FIFOs to DDR on AXG based SoC.
Required properties:
- compatible: 'amlogic,meson-axg-audio-arb' or
'amlogic,meson-sm1-audio-arb'
- reg: physical base address of the controller and length of memory
mapped region.
- clocks: phandle to the fifo peripheral clock provided by the audio
clock controller.
- #reset-cells: must be 1.
Example on the A113 SoC:
arb: reset-controller@280 {
compatible = "amlogic,meson-axg-audio-arb";
reg = <0x0 0x280 0x0 0x4>;
#reset-cells = <1>;
clocks = <&clkc_audio AUD_CLKID_DDR_ARB>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2019 BayLibre, SAS
%YAML 1.2
---
$id: "http://devicetree.org/schemas/reset/amlogic,meson-axg-audio-arb.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Amlogic audio memory arbiter controller
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
description: The Amlogic Audio ARB is a simple device which enables or disables
the access of Audio FIFOs to DDR on AXG based SoC.
properties:
compatible:
enum:
- amlogic,meson-axg-audio-arb
- amlogic,meson-sm1-audio-arb
reg:
maxItems: 1
clocks:
maxItems: 1
description: |
phandle to the fifo peripheral clock provided by the audio clock
controller.
"#reset-cells":
const: 1
required:
- compatible
- reg
- clocks
- "#reset-cells"
additionalProperties: false
examples:
- |
// on the A113 SoC:
#include <dt-bindings/clock/axg-audio-clkc.h>
bus {
#address-cells = <2>;
#size-cells = <2>;
arb: reset-controller@280 {
compatible = "amlogic,meson-axg-audio-arb";
reg = <0x0 0x280 0x0 0x4>;
#reset-cells = <1>;
clocks = <&clkc_audio AUD_CLKID_DDR_ARB>;
};
};
...@@ -17,6 +17,7 @@ properties: ...@@ -17,6 +17,7 @@ properties:
- amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs - amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs
- amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs - amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs
- amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs - amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs
- amlogic,meson-s4-reset # Reset Controller on S4 and compatible SoCs
reg: reg:
maxItems: 1 maxItems: 1
......
Binding for Qualcomm Atheros AR7xxx/AR9XXX reset controller
Please also refer to reset.txt in this directory for common reset
controller binding usage.
Required Properties:
- compatible: has to be "qca,<soctype>-reset", "qca,ar7100-reset"
as fallback
- reg: Base address and size of the controllers memory area
- #reset-cells : Specifies the number of cells needed to encode reset
line, should be 1
Example:
reset-controller@1806001c {
compatible = "qca,ar9132-reset", "qca,ar7100-reset";
reg = <0x1806001c 0x4>;
#reset-cells = <1>;
};
Marvell Berlin reset controller
===============================
Please also refer to reset.txt in this directory for common reset
controller binding usage.
The reset controller node must be a sub-node of the chip controller
node on Berlin SoCs.
Required properties:
- compatible: should be "marvell,berlin2-reset"
- #reset-cells: must be set to 2
Example:
chip_rst: reset {
compatible = "marvell,berlin2-reset";
#reset-cells = <2>;
};
&usb_phy0 {
resets = <&chip_rst 0x104 12>;
};
Bitmain BM1880 SoC Reset Controller
===================================
Please also refer to reset.txt in this directory for common reset
controller binding usage.
Required properties:
- compatible: Should be "bitmain,bm1880-reset"
- reg: Offset and length of reset controller space in SCTRL.
- #reset-cells: Must be 1.
Example:
rst: reset-controller@c00 {
compatible = "bitmain,bm1880-reset";
reg = <0xc00 0x8>;
#reset-cells = <1>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2019 Manivannan Sadhasivam <mani@kernel.org>
%YAML 1.2
---
$id: "http://devicetree.org/schemas/reset/bitmain,bm1880-reset.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Bitmain BM1880 SoC Reset Controller
maintainers:
- Manivannan Sadhasivam <mani@kernel.org>
properties:
compatible:
const: bitmain,bm1880-reset
reg:
maxItems: 1
"#reset-cells":
const: 1
required:
- compatible
- reg
- "#reset-cells"
additionalProperties: false
examples:
- |
rst: reset-controller@c00 {
compatible = "bitmain,bm1880-reset";
reg = <0xc00 0x8>;
#reset-cells = <1>;
};
Lantiq XWAY SoC RCU reset controller binding
============================================
This binding describes a reset-controller found on the RCU module on Lantiq
XWAY SoCs.
This node has to be a sub node of the Lantiq RCU block.
-------------------------------------------------------------------------------
Required properties:
- compatible : Should be one of
"lantiq,danube-reset"
"lantiq,xrx200-reset"
- reg : Defines the following sets of registers in the parent
syscon device
- Offset of the reset set register
- Offset of the reset status register
- #reset-cells : Specifies the number of cells needed to encode the
reset line, should be 2.
The first cell takes the reset set bit and the
second cell takes the status bit.
-------------------------------------------------------------------------------
Example for the reset-controllers on the xRX200 SoCs:
reset0: reset-controller@10 {
compatible = "lantiq,xrx200-reset";
reg <0x10 0x04>, <0x14 0x04>;
#reset-cells = <2>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/lantiq,reset.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Lantiq XWAY SoC RCU reset controller
maintainers:
- Martin Blumenstingl <martin.blumenstingl@googlemail.com>
description: |
This binding describes a reset-controller found on the RCU module on Lantiq
XWAY SoCs. This node has to be a sub node of the Lantiq RCU block.
properties:
compatible:
enum:
- lantiq,danube-reset
- lantiq,xrx200-reset
reg:
description: |
Defines the following sets of registers in the parent syscon device
Offset of the reset set register
Offset of the reset status register
maxItems: 2
'#reset-cells':
description: |
The first cell takes the reset set bit and the second cell takes the
status bit.
const: 2
required:
- compatible
- reg
- '#reset-cells'
additionalProperties: false
examples:
- |
// On the xRX200 SoCs:
reset0: reset-controller@10 {
compatible = "lantiq,xrx200-reset";
reg = <0x10 0x04>, <0x14 0x04>;
#reset-cells = <2>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2015 Antoine Tenart <atenart@kernel.org>
%YAML 1.2
---
$id: "http://devicetree.org/schemas/reset/marvell,berlin2-reset.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Marvell Berlin reset controller
maintainers:
- Antoine Tenart <atenart@kernel.org>
description: The reset controller node must be a sub-node of the chip
controller node on Berlin SoCs.
properties:
compatible:
const: marvell,berlin2-reset
"#reset-cells":
const: 2
required:
- compatible
- "#reset-cells"
additionalProperties: false
examples:
- |
chip: chip-control@ea0000 {
reg = <0xea0000 0x400>;
chip_rst: reset {
compatible = "marvell,berlin2-reset";
#reset-cells = <2>;
};
};
Nuvoton NPCM Reset controller
Required properties:
- compatible : "nuvoton,npcm750-reset" for NPCM7XX BMC
- reg : specifies physical base address and size of the register.
- #reset-cells: must be set to 2
Optional property:
- nuvoton,sw-reset-number - Contains the software reset number to restart the SoC.
NPCM7xx contain four software reset that represent numbers 1 to 4.
If 'nuvoton,sw-reset-number' is not specified software reset is disabled.
Example:
rstc: rstc@f0801000 {
compatible = "nuvoton,npcm750-reset";
reg = <0xf0801000 0x70>;
#reset-cells = <2>;
nuvoton,sw-reset-number = <2>;
};
Specifying reset lines connected to IP NPCM7XX modules
======================================================
example:
spi0: spi@..... {
...
resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_PSPI1>;
...
};
The index could be found in <dt-bindings/reset/nuvoton,npcm7xx-reset.h>.
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/nuvoton,npcm750-reset.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Nuvoton NPCM Reset controller
maintainers:
- Tomer Maimon <tmaimon77@gmail.com>
properties:
compatible:
const: nuvoton,npcm750-reset
reg:
maxItems: 1
'#reset-cells':
const: 2
nuvoton,sw-reset-number:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1
maximum: 4
description: |
Contains the software reset number to restart the SoC.
If not specified, software reset is disabled.
required:
- compatible
- reg
- '#reset-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/reset/nuvoton,npcm7xx-reset.h>
rstc: rstc@f0801000 {
compatible = "nuvoton,npcm750-reset";
reg = <0xf0801000 0x70>;
#reset-cells = <2>;
nuvoton,sw-reset-number = <2>;
};
// Specifying reset lines connected to IP NPCM7XX modules
spi0: spi {
resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_PSPI1>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2015 Alban Bedel <albeu@free.fr>
%YAML 1.2
---
$id: "http://devicetree.org/schemas/reset/qca,ar7100-reset.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm Atheros AR7xxx/AR9XXX reset controller
maintainers:
- Alban Bedel <albeu@free.fr>
properties:
compatible:
items:
- enum:
- qca,ar9132-reset
- qca,ar9331-reset
- const: qca,ar7100-reset
reg:
maxItems: 1
"#reset-cells":
const: 1
required:
- compatible
- reg
- "#reset-cells"
additionalProperties: false
examples:
- |
reset-controller@1806001c {
compatible = "qca,ar9132-reset", "qca,ar7100-reset";
reg = <0x1806001c 0x4>;
#reset-cells = <1>;
};
Binding for the AXS10x reset controller
This binding describes the ARC AXS10x boards custom IP-block which allows
to control reset signals of selected peripherals. For example DW GMAC, etc...
This block is controlled via memory-mapped register (AKA CREG) which
represents up-to 32 reset lines.
As of today only the following lines are used:
- DW GMAC - line 5
This binding uses the common reset binding[1].
[1] Documentation/devicetree/bindings/reset/reset.txt
Required properties:
- compatible: should be "snps,axs10x-reset".
- reg: should always contain pair address - length: for creg reset
bits register.
- #reset-cells: from common reset binding; Should always be set to 1.
Example:
reset: reset-controller@11220 {
compatible = "snps,axs10x-reset";
#reset-cells = <1>;
reg = <0x11220 0x4>;
};
Specifying reset lines connected to IP modules:
ethernet@.... {
....
resets = <&reset 5>;
....
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/snps,axs10x-reset.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: AXS10x reset controller
maintainers:
- Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
description: |
This binding describes the ARC AXS10x boards custom IP-block which allows
to control reset signals of selected peripherals. For example DW GMAC, etc...
This block is controlled via memory-mapped register (AKA CREG) which
represents up-to 32 reset lines.
As of today only the following lines are used:
- DW GMAC - line 5
properties:
compatible:
const: snps,axs10x-reset
reg:
maxItems: 1
'#reset-cells':
const: 1
required:
- compatible
- reg
- '#reset-cells'
additionalProperties: false
examples:
- |
reset: reset-controller@11220 {
compatible = "snps,axs10x-reset";
#reset-cells = <1>;
reg = <0x11220 0x4>;
};
// Specifying reset lines connected to IP modules:
ethernet {
resets = <&reset 5>;
};
Altera SOCFPGA Reset Manager
Required properties:
- compatible : "altr,rst-mgr" for (Cyclone5/Arria5/Arria10)
"altr,stratix10-rst-mgr","altr,rst-mgr" for Stratix10 ARM64 SoC
- reg : Should contain 1 register ranges(address and length)
- altr,modrst-offset : Should contain the offset of the first modrst register.
- #reset-cells: 1
Example:
rstmgr@ffd05000 {
#reset-cells = <1>;
compatible = "altr,rst-mgr";
reg = <0xffd05000 0x1000>;
altr,modrst-offset = <0x10>;
};
...@@ -38,25 +38,49 @@ properties: ...@@ -38,25 +38,49 @@ properties:
minItems: 1 minItems: 1
maxItems: 2 maxItems: 2
clock-names: clock-names: true
oneOf:
- items: # for Pro4, Pro5
- const: gio
- const: link
- items: # for others
- const: link
resets: resets:
minItems: 1 minItems: 1
maxItems: 2 maxItems: 2
reset-names: reset-names: true
oneOf:
- items: # for Pro4, Pro5 allOf:
- const: gio - if:
- const: link properties:
- items: # for others compatible:
- const: link contains:
enum:
- socionext,uniphier-pro4-usb3-reset
- socionext,uniphier-pro5-usb3-reset
- socionext,uniphier-pro4-ahci-reset
then:
properties:
clocks:
minItems: 2
maxItems: 2
clock-names:
items:
- const: gio
- const: link
resets:
minItems: 2
maxItems: 2
reset-names:
items:
- const: gio
- const: link
else:
properties:
clocks:
maxItems: 1
clock-names:
const: link
resets:
maxItems: 1
reset-names:
const: link
additionalProperties: false additionalProperties: false
......
STMicroelectronics STi family Sysconfig Picophy SoftReset Controller
=============================================================================
This binding describes a reset controller device that is used to enable and
disable on-chip PicoPHY USB2 phy(s) using "softreset" control bits found in
the STi family SoC system configuration registers.
The actual action taken when softreset is asserted is hardware dependent.
However, when asserted it may not be possible to access the hardware's
registers and after an assert/deassert sequence the hardware's previous state
may no longer be valid.
Please refer to Documentation/devicetree/bindings/reset/reset.txt
for common reset controller binding usage.
Required properties:
- compatible: Should be "st,stih407-picophyreset"
- #reset-cells: 1, see below
Example:
picophyreset: picophyreset-controller {
compatible = "st,stih407-picophyreset";
#reset-cells = <1>;
};
Specifying picophyreset control of devices
=======================================
Device nodes should specify the reset channel required in their "resets"
property, containing a phandle to the picophyreset device node and an
index specifying which channel to use, as described in
Documentation/devicetree/bindings/reset/reset.txt.
Example:
usb2_picophy0: usbpicophy@0 {
resets = <&picophyreset STIH407_PICOPHY0_RESET>;
};
Macro definitions for the supported reset channels can be found in:
include/dt-bindings/reset/stih407-resets.h
STMicroelectronics STi family Sysconfig Peripheral Powerdown Reset Controller
=============================================================================
This binding describes a reset controller device that is used to enable and
disable on-chip peripheral controllers such as USB and SATA, using
"powerdown" control bits found in the STi family SoC system configuration
registers. These have been grouped together into a single reset controller
device for convenience.
The actual action taken when powerdown is asserted is hardware dependent.
However, when asserted it may not be possible to access the hardware's
registers and after an assert/deassert sequence the hardware's previous state
may no longer be valid.
Please refer to reset.txt in this directory for common reset
controller binding usage.
Required properties:
- compatible: Should be "st,stih407-powerdown"
- #reset-cells: 1, see below
example:
powerdown: powerdown-controller {
compatible = "st,stih407-powerdown";
#reset-cells = <1>;
};
Specifying powerdown control of devices
=======================================
Device nodes should specify the reset channel required in their "resets"
property, containing a phandle to the powerdown device node and an
index specifying which channel to use, as described in reset.txt
example:
st_dwc3: dwc3@8f94000 {
resets = <&powerdown STIH407_USB3_POWERDOWN>,
};
Macro definitions for the supported reset channels can be found in:
include/dt-bindings/reset/stih407-resets.h
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/st,stih407-picophyreset.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: STMicroelectronics STi family Sysconfig Picophy SoftReset Controller
maintainers:
- Peter Griffin <peter.griffin@linaro.org>
description: |
This binding describes a reset controller device that is used to enable and
disable on-chip PicoPHY USB2 phy(s) using "softreset" control bits found in
the STi family SoC system configuration registers.
The actual action taken when softreset is asserted is hardware dependent.
However, when asserted it may not be possible to access the hardware's
registers and after an assert/deassert sequence the hardware's previous state
may no longer be valid.
properties:
compatible:
const: st,stih407-picophyreset
'#reset-cells':
const: 1
required:
- compatible
- '#reset-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/reset/stih407-resets.h>
picophyreset: picophyreset-controller {
compatible = "st,stih407-picophyreset";
#reset-cells = <1>;
};
// Specifying picophyreset control of devices
usb2_picophy0: usbpicophy {
resets = <&picophyreset STIH407_PICOPHY0_RESET>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/st,stih407-powerdown.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: STMicroelectronics STi family Sysconfig Peripheral Powerdown Reset Controller
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@st.com>
description: |
This binding describes a reset controller device that is used to enable and
disable on-chip peripheral controllers such as USB and SATA, using
"powerdown" control bits found in the STi family SoC system configuration
registers. These have been grouped together into a single reset controller
device for convenience.
The actual action taken when powerdown is asserted is hardware dependent.
However, when asserted it may not be possible to access the hardware's
registers and after an assert/deassert sequence the hardware's previous state
may no longer be valid.
properties:
compatible:
const: st,stih407-powerdown
'#reset-cells':
const: 1
required:
- compatible
- '#reset-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/reset/stih407-resets.h>
powerdown: powerdown-controller {
compatible = "st,stih407-powerdown";
#reset-cells = <1>;
};
// Specifying powerdown control of devices:
st_dwc3: dwc3 {
resets = <&powerdown STIH407_USB3_POWERDOWN>;
};
...@@ -63,116 +63,23 @@ required: ...@@ -63,116 +63,23 @@ required:
- ranges - ranges
patternProperties: patternProperties:
"^.*@[0-9a-f]+$":
type: object
description: Common properties for GENI Serial Engine based I2C, SPI and
UART controller.
properties:
reg:
description: GENI Serial Engine register address and length.
maxItems: 1
clock-names:
const: se
clocks:
description: Serial engine core clock needed by the device.
maxItems: 1
interconnects:
minItems: 2
maxItems: 3
interconnect-names:
minItems: 2
items:
- const: qup-core
- const: qup-config
- const: qup-memory
required:
- reg
- clock-names
- clocks
"spi@[0-9a-f]+$": "spi@[0-9a-f]+$":
type: object type: object
description: GENI serial engine based SPI controller. SPI in master mode description: GENI serial engine based SPI controller. SPI in master mode
supports up to 50MHz, up to four chip selects, programmable supports up to 50MHz, up to four chip selects, programmable
data path from 4 bits to 32 bits and numerous protocol data path from 4 bits to 32 bits and numerous protocol
variants. variants.
$ref: /schemas/spi/spi-controller.yaml# $ref: /schemas/spi/qcom,spi-geni-qcom.yaml#
properties:
compatible:
enum:
- qcom,geni-spi
interrupts:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 0
required:
- compatible
- interrupts
- "#address-cells"
- "#size-cells"
"i2c@[0-9a-f]+$": "i2c@[0-9a-f]+$":
type: object type: object
description: GENI serial engine based I2C controller. description: GENI serial engine based I2C controller.
$ref: /schemas/i2c/i2c-controller.yaml# $ref: /schemas/i2c/qcom,i2c-geni-qcom.yaml#
properties:
compatible:
enum:
- qcom,geni-i2c
interrupts:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 0
clock-frequency:
description: Desired I2C bus clock frequency in Hz.
default: 100000
required:
- compatible
- interrupts
- "#address-cells"
- "#size-cells"
"serial@[0-9a-f]+$": "serial@[0-9a-f]+$":
type: object type: object
description: GENI Serial Engine based UART Controller. description: GENI Serial Engine based UART Controller.
$ref: /schemas/serial.yaml# $ref: /schemas/serial/qcom,serial-geni-qcom.yaml#
properties:
compatible:
enum:
- qcom,geni-uart
- qcom,geni-debug-uart
interrupts:
minItems: 1
items:
- description: UART core irq
- description: Wakeup irq (RX GPIO)
required:
- compatible
- interrupts
additionalProperties: false additionalProperties: false
......
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/qcom/qcom,rpmh-rsc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm RPMH RSC
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
description: |
Resource Power Manager Hardened (RPMH) is the mechanism for communicating
with the hardened resource accelerators on Qualcomm SoCs. Requests to the
resources can be written to the Trigger Command Set (TCS) registers and
using a (addr, val) pair and triggered. Messages in the TCS are then sent in
sequence over an internal bus.
The hardware block (Direct Resource Voter or DRV) is a part of the h/w entity
(Resource State Coordinator a.k.a RSC) that can handle multiple sleep and
active/wake resource requests. Multiple such DRVs can exist in a SoC and can
be written to from Linux. The structure of each DRV follows the same template
with a few variations that are captured by the properties here.
A TCS may be triggered from Linux or triggered by the F/W after all the CPUs
have powered off to facilitate idle power saving. TCS could be classified as::
ACTIVE - Triggered by Linux
SLEEP - Triggered by F/W
WAKE - Triggered by F/W
CONTROL - Triggered by F/W
See also:: <dt-bindings/soc/qcom,rpmh-rsc.h>
The order in which they are described in the DT, should match the hardware
configuration.
Requests can be made for the state of a resource, when the subsystem is
active or idle. When all subsystems like Modem, GPU, CPU are idle, the
resource state will be an aggregate of the sleep votes from each of those
subsystems. Clients may request a sleep value for their shared resources in
addition to the active mode requests.
Drivers that want to use the RSC to communicate with RPMH must specify their
bindings as child nodes of the RSC controllers they wish to communicate with.
properties:
compatible:
const: qcom,rpmh-rsc
interrupts:
minItems: 1
maxItems: 4
description:
The interrupt that trips when a message complete/response is received for
this DRV from the accelerators.
Number of interrupts must match number of DRV blocks.
label:
description:
Name for the RSC. The name would be used in trace logs.
qcom,drv-id:
$ref: /schemas/types.yaml#/definitions/uint32
description:
The ID of the DRV in the RSC block that will be used by this controller.
qcom,tcs-config:
$ref: /schemas/types.yaml#/definitions/uint32-matrix
items:
- items:
- description: TCS type
enum: [ 0, 1, 2, 3 ]
- description: Number of TCS
- items:
- description: TCS type
enum: [ 0, 1, 2, 3 ]
- description: Number of TCS
- items:
- description: TCS type
enum: [ 0, 1, 2, 3]
- description: Numbe r of TCS
- items:
- description: TCS type
enum: [ 0, 1, 2, 3 ]
- description: Number of TCS
description: |
The tuple defining the configuration of TCS. Must have two cells which
describe each TCS type. The order of the TCS must match the hardware
configuration.
Cell 1 (TCS Type):: TCS types to be specified::
- ACTIVE_TCS
- SLEEP_TCS
- WAKE_TCS
- CONTROL_TCS
Cell 2 (Number of TCS):: <u32>
qcom,tcs-offset:
$ref: /schemas/types.yaml#/definitions/uint32
description:
The offset of the TCS blocks.
reg:
minItems: 1
maxItems: 4
reg-names:
minItems: 1
items:
- const: drv-0
- const: drv-1
- const: drv-2
- const: drv-3
bcm-voter:
$ref: /schemas/interconnect/qcom,bcm-voter.yaml#
clock-controller:
$ref: /schemas/clock/qcom,rpmhcc.yaml#
power-controller:
$ref: /schemas/power/qcom,rpmpd.yaml#
patternProperties:
'-regulators$':
$ref: /schemas/regulator/qcom,rpmh-regulator.yaml#
required:
- compatible
- interrupts
- qcom,drv-id
- qcom,tcs-config
- qcom,tcs-offset
- reg
- reg-names
additionalProperties: false
examples:
- |
// For a TCS whose RSC base address is 0x179C0000 and is at a DRV id of
// 2, the register offsets for DRV2 start at 0D00, the register
// calculations are like this::
// DRV0: 0x179C0000
// DRV2: 0x179C0000 + 0x10000 = 0x179D0000
// DRV2: 0x179C0000 + 0x10000 * 2 = 0x179E0000
// TCS-OFFSET: 0xD00
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
rsc@179c0000 {
compatible = "qcom,rpmh-rsc";
reg = <0x179c0000 0x10000>,
<0x179d0000 0x10000>,
<0x179e0000 0x10000>;
reg-names = "drv-0", "drv-1", "drv-2";
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
label = "apps_rsc";
qcom,tcs-offset = <0xd00>;
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 2>,
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
};
- |
// For a TCS whose RSC base address is 0xAF20000 and is at DRV id of 0, the
// register offsets for DRV0 start at 01C00, the register calculations are
// like this::
// DRV0: 0xAF20000
// TCS-OFFSET: 0x1C00
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
rsc@af20000 {
compatible = "qcom,rpmh-rsc";
reg = <0xaf20000 0x10000>;
reg-names = "drv-0";
interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>;
label = "disp_rsc";
qcom,tcs-offset = <0x1c00>;
qcom,drv-id = <0>;
qcom,tcs-config = <ACTIVE_TCS 0>,
<SLEEP_TCS 1>,
<WAKE_TCS 1>,
<CONTROL_TCS 0>;
};
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
#include <dt-bindings/power/qcom-rpmpd.h>
rsc@18200000 {
compatible = "qcom,rpmh-rsc";
reg = <0x18200000 0x10000>,
<0x18210000 0x10000>,
<0x18220000 0x10000>;
reg-names = "drv-0", "drv-1", "drv-2";
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
label = "apps_rsc";
qcom,tcs-offset = <0xd00>;
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 2>,
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 0>;
clock-controller {
compatible = "qcom,sm8350-rpmh-clk";
#clock-cells = <1>;
clock-names = "xo";
clocks = <&xo_board>;
};
power-controller {
compatible = "qcom,sm8350-rpmhpd";
#power-domain-cells = <1>;
operating-points-v2 = <&rpmhpd_opp_table>;
rpmhpd_opp_table: opp-table {
compatible = "operating-points-v2";
rpmhpd_opp_ret: opp1 {
opp-level = <RPMH_REGULATOR_LEVEL_RETENTION>;
};
rpmhpd_opp_min_svs: opp2 {
opp-level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
};
rpmhpd_opp_low_svs: opp3 {
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
};
rpmhpd_opp_svs: opp4 {
opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
};
rpmhpd_opp_svs_l1: opp5 {
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
};
rpmhpd_opp_nom: opp6 {
opp-level = <RPMH_REGULATOR_LEVEL_NOM>;
};
rpmhpd_opp_nom_l1: opp7 {
opp-level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
};
rpmhpd_opp_nom_l2: opp8 {
opp-level = <RPMH_REGULATOR_LEVEL_NOM_L2>;
};
rpmhpd_opp_turbo: opp9 {
opp-level = <RPMH_REGULATOR_LEVEL_TURBO>;
};
rpmhpd_opp_turbo_l1: opp10 {
opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
};
};
};
bcm-voter {
compatible = "qcom,bcm-voter";
};
};
...@@ -12,7 +12,7 @@ description: | ...@@ -12,7 +12,7 @@ description: |
to vote for state of the system resources, such as clocks, regulators and bus to vote for state of the system resources, such as clocks, regulators and bus
frequencies. frequencies.
The SMD information for the RPM edge should be filled out. See qcom,smd.txt The SMD information for the RPM edge should be filled out. See qcom,smd.yaml
for the required edge properties. All SMD related properties will reside for the required edge properties. All SMD related properties will reside
within the RPM node itself. within the RPM node itself.
...@@ -25,7 +25,8 @@ description: | ...@@ -25,7 +25,8 @@ description: |
rpm_requests. rpm_requests.
maintainers: maintainers:
- Kathiravan T <kathirav@codeaurora.org> - Andy Gross <agross@kernel.org>
- Bjorn Andersson <bjorn.andersson@linaro.org>
properties: properties:
compatible: compatible:
...@@ -83,7 +84,7 @@ examples: ...@@ -83,7 +84,7 @@ examples:
qcom,ipc = <&apcs 8 0>; qcom,ipc = <&apcs 8 0>;
qcom,smd-edge = <15>; qcom,smd-edge = <15>;
rpm_requests { rpm-requests {
compatible = "qcom,rpm-msm8974"; compatible = "qcom,rpm-msm8974";
qcom,smd-channels = "rpm_requests"; qcom,smd-channels = "rpm_requests";
......
Qualcomm Shared Memory Driver (SMD) binding
This binding describes the Qualcomm Shared Memory Driver, a fifo based
communication channel for sending data between the various subsystems in
Qualcomm platforms.
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,smd"
= EDGES
Each subnode of the SMD node represents a remote subsystem or a remote
processor of some sort - or in SMD language an "edge". The name of the edges
are not important.
The edge is described by the following properties:
- interrupts:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify the IRQ used by the remote processor to
signal this processor about communication related updates
- mboxes:
Usage: required
Value type: <prop-encoded-array>
Definition: reference to the associated doorbell in APCS, as described
in mailbox/mailbox.txt
- qcom,ipc:
Usage: required, unless mboxes is specified
Value type: <prop-encoded-array>
Definition: three entries specifying the outgoing ipc bit used for
signaling the remote processor:
- phandle to a syscon node representing the apcs registers
- u32 representing offset to the register within the syscon
- u32 representing the ipc bit within the register
- qcom,smd-edge:
Usage: required
Value type: <u32>
Definition: the identifier of the remote processor in the smd channel
allocation table
- qcom,remote-pid:
Usage: optional
Value type: <u32>
Definition: the identifier for the remote processor as known by the rest
of the system.
- label:
Usage: optional
Value type: <string>
Definition: name of the edge, used for debugging and identification
purposes. The node name will be used if this is not
present.
= SMD DEVICES
In turn, subnodes of the "edges" represent devices tied to SMD channels on that
"edge". The names of the devices are not important. The properties of these
nodes are defined by the individual bindings for the SMD devices - but must
contain the following property:
- qcom,smd-channels:
Usage: required
Value type: <stringlist>
Definition: a list of channels tied to this device, used for matching
the device to channels
= EXAMPLE
The following example represents a smd node, with one edge representing the
"rpm" subsystem. For the "rpm" subsystem we have a device tied to the
"rpm_request" channel.
apcs: syscon@f9011000 {
compatible = "syscon";
reg = <0xf9011000 0x1000>;
};
smd {
compatible = "qcom,smd";
rpm {
interrupts = <0 168 1>;
qcom,ipc = <&apcs 8 0>;
qcom,smd-edge = <15>;
rpm_requests {
compatible = "qcom,rpm-msm8974";
qcom,smd-channels = "rpm_requests";
...
};
};
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/qcom/qcom,smd.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Shared Memory Driver
maintainers:
- Andy Gross <agross@kernel.org>
- Bjorn Andersson <bjorn.andersson@linaro.org>
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
description:
The Qualcomm Shared Memory Driver is a FIFO based communication channel for
sending data between the various subsystems in Qualcomm platforms.
properties:
compatible:
const: qcom,smd
patternProperties:
"^.*-edge|rpm$":
type: object
description:
Each subnode of the SMD node represents a remote subsystem or a remote
processor of some sort - or in SMD language an "edge". The name of the
edges are not important.
properties:
interrupts:
maxItems: 1
label:
$ref: /schemas/types.yaml#/definitions/string
description:
Name of the edge, used for debugging and identification purposes. The
node name will be used if this is not present.
mboxes:
maxItems: 1
description:
Reference to the mailbox representing the outgoing doorbell in APCS for
this client.
qcom,ipc:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- description: phandle to a syscon node representing the APCS registers
- description: u32 representing offset to the register within the syscon
- description: u32 representing the ipc bit within the register
description:
Three entries specifying the outgoing ipc bit used for signaling the
remote processor.
qcom,smd-edge:
$ref: /schemas/types.yaml#/definitions/uint32
description:
The identifier of the remote processor in the smd channel allocation
table.
qcom,remote-pid:
$ref: /schemas/types.yaml#/definitions/uint32
description:
The identifier for the remote processor as known by the rest of the
system.
# Binding for edge subnodes is not complete
patternProperties:
"^rpm-requests$":
type: object
description:
In turn, subnodes of the "edges" represent devices tied to SMD
channels on that "edge". The names of the devices are not
important. The properties of these nodes are defined by the
individual bindings for the SMD devices.
properties:
qcom,smd-channels:
$ref: /schemas/types.yaml#/definitions/string-array
minItems: 1
maxItems: 32
description:
A list of channels tied to this device, used for matching the
device to channels.
required:
- compatible
- qcom,smd-channels
additionalProperties: true
required:
- interrupts
- qcom,smd-edge
oneOf:
- required:
- mboxes
- required:
- qcom,ipc
additionalProperties: false
required:
- compatible
additionalProperties: false
examples:
# The following example represents a smd node, with one edge representing the
# "rpm" subsystem. For the "rpm" subsystem we have a device tied to the
# "rpm_request" channel.
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
shared-memory {
compatible = "qcom,smd";
rpm {
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
qcom,ipc = <&apcs 8 0>;
qcom,smd-edge = <15>;
rpm-requests {
compatible = "qcom,rpm-msm8974";
qcom,smd-channels = "rpm_requests";
clock-controller {
compatible = "qcom,rpmcc-msm8974", "qcom,rpmcc";
#clock-cells = <1>;
};
};
};
};
Qualcomm Shared Memory State Machine
The Shared Memory State Machine facilitates broadcasting of single bit state
information between the processors in a Qualcomm SoC. Each processor is
assigned 32 bits of state that can be modified. A processor can through a
matrix of bitmaps signal subscription of notifications upon changes to a
certain bit owned by a certain remote processor.
- compatible:
Usage: required
Value type: <string>
Definition: must be one of:
"qcom,smsm"
- qcom,ipc-N:
Usage: required
Value type: <prop-encoded-array>
Definition: three entries specifying the outgoing ipc bit used for
signaling the N:th remote processor
- phandle to a syscon node representing the apcs registers
- u32 representing offset to the register within the syscon
- u32 representing the ipc bit within the register
- qcom,local-host:
Usage: optional
Value type: <u32>
Definition: identifier of the local processor in the list of hosts, or
in other words specifier of the column in the subscription
matrix representing the local processor
defaults to host 0
- #address-cells:
Usage: required
Value type: <u32>
Definition: must be 1
- #size-cells:
Usage: required
Value type: <u32>
Definition: must be 0
= SUBNODES
Each processor's state bits are described by a subnode of the smsm device node.
Nodes can either be flagged as an interrupt-controller to denote a remote
processor's state bits or the local processors bits. The node names are not
important.
- reg:
Usage: required
Value type: <u32>
Definition: specifies the offset, in words, of the first bit for this
entry
- #qcom,smem-state-cells:
Usage: required for local entry
Value type: <u32>
Definition: must be 1 - denotes bit number
- interrupt-controller:
Usage: required for remote entries
Value type: <empty>
Definition: marks the entry as a interrupt-controller and the state bits
to belong to a remote processor
- #interrupt-cells:
Usage: required for remote entries
Value type: <u32>
Definition: must be 2 - denotes bit number and IRQ flags
- interrupts:
Usage: required for remote entries
Value type: <prop-encoded-array>
Definition: one entry specifying remote IRQ used by the remote processor
to signal changes of its state bits
= EXAMPLE
The following example shows the SMEM setup for controlling properties of the
wireless processor, defined from the 8974 apps processor's point-of-view. It
encompasses one outbound entry and the outgoing interrupt for the wireless
processor.
smsm {
compatible = "qcom,smsm";
#address-cells = <1>;
#size-cells = <0>;
qcom,ipc-3 = <&apcs 8 19>;
apps_smsm: apps@0 {
reg = <0>;
#qcom,smem-state-cells = <1>;
};
wcnss_smsm: wcnss@7 {
reg = <7>;
interrupts = <0 144 1>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/qcom/qcom,smsm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Shared Memory State Machine
maintainers:
- Andy Gross <agross@kernel.org>
- Bjorn Andersson <bjorn.andersson@linaro.org>
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
description:
The Shared Memory State Machine facilitates broadcasting of single bit state
information between the processors in a Qualcomm SoC. Each processor is
assigned 32 bits of state that can be modified. A processor can through a
matrix of bitmaps signal subscription of notifications upon changes to a
certain bit owned by a certain remote processor.
properties:
compatible:
const: qcom,smsm
'#address-cells':
const: 1
qcom,local-host:
$ref: /schemas/types.yaml#/definitions/uint32
default: 0
description:
Identifier of the local processor in the list of hosts, or in other words
specifier of the column in the subscription matrix representing the local
processor.
'#size-cells':
const: 0
patternProperties:
"^qcom,ipc-[1-4]$":
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- description: phandle to a syscon node representing the APCS registers
- description: u32 representing offset to the register within the syscon
- description: u32 representing the ipc bit within the register
description:
Three entries specifying the outgoing ipc bit used for signaling the N:th
remote processor.
"@[0-9a-f]$":
type: object
description:
Each processor's state bits are described by a subnode of the SMSM device
node. Nodes can either be flagged as an interrupt-controller to denote a
remote processor's state bits or the local processors bits. The node
names are not important.
properties:
reg:
maxItems: 1
interrupt-controller:
description:
Marks the entry as a interrupt-controller and the state bits to
belong to a remote processor.
'#interrupt-cells':
const: 2
interrupts:
maxItems: 1
description:
One entry specifying remote IRQ used by the remote processor to
signal changes of its state bits.
'#qcom,smem-state-cells':
$ref: /schemas/types.yaml#/definitions/uint32
const: 1
description:
Required for local entry. Denotes bit number.
required:
- reg
oneOf:
- required:
- '#qcom,smem-state-cells'
- required:
- interrupt-controller
- '#interrupt-cells'
- interrupts
additionalProperties: false
required:
- compatible
- '#address-cells'
- '#size-cells'
anyOf:
- required:
- qcom,ipc-1
- required:
- qcom,ipc-2
- required:
- qcom,ipc-3
- required:
- qcom,ipc-4
additionalProperties: false
examples:
# The following example shows the SMEM setup for controlling properties of
# the wireless processor, defined from the 8974 apps processor's
# point-of-view. It encompasses one outbound entry and the outgoing interrupt
# for the wireless processor.
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
shared-memory {
compatible = "qcom,smsm";
#address-cells = <1>;
#size-cells = <0>;
qcom,ipc-3 = <&apcs 8 19>;
apps_smsm: apps@0 {
reg = <0>;
#qcom,smem-state-cells = <1>;
};
wcnss_smsm: wcnss@7 {
reg = <7>;
interrupts = <GIC_SPI 144 IRQ_TYPE_EDGE_RISING>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
Qualcomm WCNSS Binding
This binding describes the Qualcomm WCNSS hardware. It consists of control
block and a BT, WiFi and FM radio block, all using SMD as command channels.
- compatible:
Usage: required
Value type: <string>
Definition: must be: "qcom,wcnss",
- qcom,smd-channel:
Usage: required
Value type: <string>
Definition: standard SMD property specifying the SMD channel used for
communication with the WiFi firmware.
Should be "WCNSS_CTRL".
- qcom,mmio:
Usage: required
Value type: <prop-encoded-array>
Definition: reference to a node specifying the wcnss "ccu" and "dxe"
register blocks. The node must be compatible with one of
the following:
"qcom,riva",
"qcom,pronto"
- firmware-name:
Usage: optional
Value type: <string>
Definition: specifies the relative firmware image path for the WLAN NV
blob. Defaults to "wlan/prima/WCNSS_qcom_wlan_nv.bin" if
not specified.
= SUBNODES
The subnodes of the wcnss node are optional and describe the individual blocks in
the WCNSS.
== Bluetooth
The following properties are defined to the bluetooth node:
- compatible:
Usage: required
Value type: <string>
Definition: must be:
"qcom,wcnss-bt"
- local-bd-address:
Usage: optional
Value type: <u8 array>
Definition: see Documentation/devicetree/bindings/net/bluetooth.txt
== WiFi
The following properties are defined to the WiFi node:
- compatible:
Usage: required
Value type: <string>
Definition: must be one of:
"qcom,wcnss-wlan",
- interrupts:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify the "rx" and "tx" interrupts
- interrupt-names:
Usage: required
Value type: <stringlist>
Definition: must contain "rx" and "tx"
- qcom,smem-state:
Usage: required
Value type: <prop-encoded-array>
Definition: should reference the tx-enable and tx-rings-empty SMEM states
- qcom,smem-state-names:
Usage: required
Value type: <stringlist>
Definition: must contain "tx-enable" and "tx-rings-empty"
= EXAMPLE
The following example represents a SMD node, with one edge representing the
"pronto" subsystem, with the wcnss device and its wcn3680 BT and WiFi blocks
described; as found on the 8974 platform.
smd {
compatible = "qcom,smd";
pronto-edge {
interrupts = <0 142 1>;
qcom,ipc = <&apcs 8 17>;
qcom,smd-edge = <6>;
wcnss {
compatible = "qcom,wcnss";
qcom,smd-channels = "WCNSS_CTRL";
#address-cells = <1>;
#size-cells = <1>;
qcom,mmio = <&pronto>;
bt {
compatible = "qcom,wcnss-bt";
/* BD address 00:11:22:33:44:55 */
local-bd-address = [ 55 44 33 22 11 00 ];
};
wlan {
compatible = "qcom,wcnss-wlan";
interrupts = <0 145 0>, <0 146 0>;
interrupt-names = "tx", "rx";
qcom,smem-state = <&apps_smsm 10>, <&apps_smsm 9>;
qcom,smem-state-names = "tx-enable", "tx-rings-empty";
};
};
};
};
soc {
pronto: pronto {
compatible = "qcom,pronto";
reg = <0xfb204000 0x2000>, <0xfb202000 0x1000>, <0xfb21b000 0x3000>;
reg-names = "ccu", "dxe", "pmu";
};
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/qcom/qcom,wcnss.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm WCNSS
maintainers:
- Andy Gross <agross@kernel.org>
- Bjorn Andersson <bjorn.andersson@linaro.org>
description:
The Qualcomm WCNSS hardware consists of control block and a BT, WiFi and FM
radio block, all using SMD as command channels.
properties:
compatible:
const: qcom,wcnss
firmware-name:
$ref: /schemas/types.yaml#/definitions/string
default: "wlan/prima/WCNSS_qcom_wlan_nv.bin"
description:
Relative firmware image path for the WLAN NV blob.
qcom,mmio:
$ref: /schemas/types.yaml#/definitions/phandle
description: |
Reference to a node specifying the wcnss "ccu" and "dxe" register blocks.
The node must be compatible with one of the following::
- qcom,riva"
- qcom,pronto"
qcom,smd-channels:
$ref: /schemas/types.yaml#/definitions/string
const: WCNSS_CTRL
description:
Standard SMD property specifying the SMD channel used for communication
with the WiFi firmware.
bluetooth:
type: object
additionalProperties: false
properties:
compatible:
const: qcom,wcnss-bt
local-bd-address:
$ref: /schemas/types.yaml#/definitions/uint8-array
maxItems: 6
description:
See Documentation/devicetree/bindings/net/bluetooth.txt
required:
- compatible
wifi:
additionalProperties: false
type: object
properties:
compatible:
const: qcom,wcnss-wlan
interrupts:
maxItems: 2
interrupt-names:
items:
- const: tx
- const: rx
qcom,smem-states:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 2
description:
Should reference the tx-enable and tx-rings-empty SMEM states.
qcom,smem-state-names:
$ref: /schemas/types.yaml#/definitions/string-array
items:
- const: tx-enable
- const: tx-rings-empty
description:
Names of SMEM states.
required:
- compatible
- interrupts
- interrupt-names
- qcom,smem-states
- qcom,smem-state-names
required:
- compatible
- qcom,mmio
- qcom,smd-channels
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
smd-edge {
interrupts = <GIC_SPI 142 IRQ_TYPE_EDGE_RISING>;
qcom,ipc = <&apcs 8 17>;
qcom,smd-edge = <6>;
qcom,remote-pid = <4>;
label = "pronto";
wcnss {
compatible = "qcom,wcnss";
qcom,smd-channels = "WCNSS_CTRL";
qcom,mmio = <&pronto>;
bluetooth {
compatible = "qcom,wcnss-bt";
/* BD address 00:11:22:33:44:55 */
local-bd-address = [ 55 44 33 22 11 00 ];
};
wifi {
compatible = "qcom,wcnss-wlan";
interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "tx", "rx";
qcom,smem-states = <&apps_smsm 10>, <&apps_smsm 9>;
qcom,smem-state-names = "tx-enable", "tx-rings-empty";
};
};
};
RPMH RSC:
------------
Resource Power Manager Hardened (RPMH) is the mechanism for communicating with
the hardened resource accelerators on Qualcomm SoCs. Requests to the resources
can be written to the Trigger Command Set (TCS) registers and using a (addr,
val) pair and triggered. Messages in the TCS are then sent in sequence over an
internal bus.
The hardware block (Direct Resource Voter or DRV) is a part of the h/w entity
(Resource State Coordinator a.k.a RSC) that can handle multiple sleep and
active/wake resource requests. Multiple such DRVs can exist in a SoC and can
be written to from Linux. The structure of each DRV follows the same template
with a few variations that are captured by the properties here.
A TCS may be triggered from Linux or triggered by the F/W after all the CPUs
have powered off to facilitate idle power saving. TCS could be classified as -
ACTIVE /* Triggered by Linux */
SLEEP /* Triggered by F/W */
WAKE /* Triggered by F/W */
CONTROL /* Triggered by F/W */
The order in which they are described in the DT, should match the hardware
configuration.
Requests can be made for the state of a resource, when the subsystem is active
or idle. When all subsystems like Modem, GPU, CPU are idle, the resource state
will be an aggregate of the sleep votes from each of those subsystems. Clients
may request a sleep value for their shared resources in addition to the active
mode requests.
Properties:
- compatible:
Usage: required
Value type: <string>
Definition: Should be "qcom,rpmh-rsc".
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: The first register specifies the base address of the
DRV(s). The number of DRVs in the dependent on the RSC.
The tcs-offset specifies the start address of the
TCS in the DRVs.
- reg-names:
Usage: required
Value type: <string>
Definition: Maps the register specified in the reg property. Must be
"drv-0", "drv-1", "drv-2" etc and "tcs-offset". The
- interrupts:
Usage: required
Value type: <prop-encoded-interrupt>
Definition: The interrupt that trips when a message complete/response
is received for this DRV from the accelerators.
- qcom,drv-id:
Usage: required
Value type: <u32>
Definition: The id of the DRV in the RSC block that will be used by
this controller.
- qcom,tcs-config:
Usage: required
Value type: <prop-encoded-array>
Definition: The tuple defining the configuration of TCS.
Must have 2 cells which describe each TCS type.
<type number_of_tcs>.
The order of the TCS must match the hardware
configuration.
- Cell #1 (TCS Type): TCS types to be specified -
ACTIVE_TCS
SLEEP_TCS
WAKE_TCS
CONTROL_TCS
- Cell #2 (Number of TCS): <u32>
- label:
Usage: optional
Value type: <string>
Definition: Name for the RSC. The name would be used in trace logs.
Drivers that want to use the RSC to communicate with RPMH must specify their
bindings as child nodes of the RSC controllers they wish to communicate with.
Example 1:
For a TCS whose RSC base address is is 0x179C0000 and is at a DRV id of 2, the
register offsets for DRV2 start at 0D00, the register calculations are like
this -
DRV0: 0x179C0000
DRV2: 0x179C0000 + 0x10000 = 0x179D0000
DRV2: 0x179C0000 + 0x10000 * 2 = 0x179E0000
TCS-OFFSET: 0xD00
apps_rsc: rsc@179c0000 {
label = "apps_rsc";
compatible = "qcom,rpmh-rsc";
reg = <0x179c0000 0x10000>,
<0x179d0000 0x10000>,
<0x179e0000 0x10000>;
reg-names = "drv-0", "drv-1", "drv-2";
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
qcom,tcs-offset = <0xd00>;
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 2>,
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
};
Example 2:
For a TCS whose RSC base address is 0xAF20000 and is at DRV id of 0, the
register offsets for DRV0 start at 01C00, the register calculations are like
this -
DRV0: 0xAF20000
TCS-OFFSET: 0x1C00
disp_rsc: rsc@af20000 {
label = "disp_rsc";
compatible = "qcom,rpmh-rsc";
reg = <0xaf20000 0x10000>;
reg-names = "drv-0";
interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>;
qcom,tcs-offset = <0x1c00>;
qcom,drv-id = <0>;
qcom,tcs-config = <ACTIVE_TCS 0>,
<SLEEP_TCS 1>,
<WAKE_TCS 1>,
<CONTROL_TCS 0>;
};
...@@ -15,6 +15,9 @@ properties: ...@@ -15,6 +15,9 @@ properties:
- items: - items:
- enum: - enum:
- rockchip,rk3288-sgrf - rockchip,rk3288-sgrf
- rockchip,rk3566-pipe-grf
- rockchip,rk3568-pipe-grf
- rockchip,rk3568-pipe-phy-grf
- rockchip,rk3568-usb2phy-grf - rockchip,rk3568-usb2phy-grf
- rockchip,rv1108-usbgrf - rockchip,rv1108-usbgrf
- const: syscon - const: syscon
......
...@@ -77,7 +77,7 @@ patternProperties: ...@@ -77,7 +77,7 @@ patternProperties:
description: Child node describing underlying UART/serial description: Child node describing underlying UART/serial
"^spi@[0-9a-f]+$": "^spi@[0-9a-f]+$":
type: object $ref: /schemas/spi/samsung,spi.yaml
description: Child node describing underlying SPI description: Child node describing underlying SPI
required: required:
......
GENI based Qualcomm Universal Peripheral (QUP) Serial Peripheral Interface (SPI)
The QUP v3 core is a GENI based AHB slave that provides a common data path
(an output FIFO and an input FIFO) for serial peripheral interface (SPI)
mini-core.
SPI in master mode supports up to 50MHz, up to four chip selects, programmable
data path from 4 bits to 32 bits and numerous protocol variants.
Required properties:
- compatible: Must contain "qcom,geni-spi".
- reg: Must contain SPI register location and length.
- interrupts: Must contain SPI controller interrupts.
- clock-names: Must contain "se".
- clocks: Serial engine core clock needed by the device.
- #address-cells: Must be <1> to define a chip select address on
the SPI bus.
- #size-cells: Must be <0>.
SPI Controller nodes must be child of GENI based Qualcomm Universal
Peripharal. Please refer GENI based QUP wrapper controller node bindings
described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml.
SPI slave nodes must be children of the SPI master node and conform to SPI bus
binding as described in Documentation/devicetree/bindings/spi/spi-bus.txt.
Example:
spi0: spi@a84000 {
compatible = "qcom,geni-spi";
reg = <0xa84000 0x4000>;
interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "se";
clocks = <&clock_gcc GCC_QUPV3_WRAP0_S0_CLK>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&qup_1_spi_2_active>;
pinctrl-1 = <&qup_1_spi_2_sleep>;
#address-cells = <1>;
#size-cells = <0>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/qcom,spi-geni-qcom.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: GENI based Qualcomm Universal Peripheral (QUP) Serial Peripheral Interface (SPI)
maintainers:
- Andy Gross <agross@kernel.org>
- Bjorn Andersson <bjorn.andersson@linaro.org>
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
description:
The QUP v3 core is a GENI based AHB slave that provides a common data path
(an output FIFO and an input FIFO) for serial peripheral interface (SPI)
mini-core.
SPI in master mode supports up to 50MHz, up to four chip selects,
programmable data path from 4 bits to 32 bits and numerous protocol variants.
SPI Controller nodes must be child of GENI based Qualcomm Universal
Peripharal. Please refer GENI based QUP wrapper controller node bindings
described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml.
allOf:
- $ref: /schemas/spi/spi-controller.yaml#
properties:
compatible:
const: qcom,geni-spi
clocks:
maxItems: 1
clock-names:
const: se
dmas:
maxItems: 2
dma-names:
items:
- const: tx
- const: rx
interconnects:
maxItems: 2
interconnect-names:
items:
- const: qup-core
- const: qup-config
interrupts:
maxItems: 1
operating-points-v2: true
power-domains:
maxItems: 1
reg:
maxItems: 1
required:
- compatible
- clocks
- clock-names
- interrupts
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-sc7180.h>
#include <dt-bindings/interconnect/qcom,sc7180.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/qcom-rpmpd.h>
spi@880000 {
compatible = "qcom,geni-spi";
reg = <0x00880000 0x4000>;
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
pinctrl-names = "default";
pinctrl-0 = <&qup_spi0_default>;
interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&rpmhpd SC7180_CX>;
operating-points-v2 = <&qup_opp_table>;
interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_0 0>;
interconnect-names = "qup-core", "qup-config";
};
- |
#include <dt-bindings/dma/qcom-gpi.h>
spi@884000 {
compatible = "qcom,geni-spi";
reg = <0x00884000 0x4000>;
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
dmas = <&gpi_dma0 0 1 QCOM_GPI_SPI>,
<&gpi_dma0 1 1 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&qup_spi1_default>;
interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
spi-max-frequency = <50000000>;
#address-cells = <1>;
#size-cells = <0>;
};
...@@ -19,9 +19,20 @@ description: |+ ...@@ -19,9 +19,20 @@ description: |+
properties: properties:
compatible: compatible:
enum: oneOf:
- samsung,exynos4210-mct - enum:
- samsung,exynos4412-mct - samsung,exynos4210-mct
- samsung,exynos4412-mct
- items:
- enum:
- samsung,exynos3250-mct
- samsung,exynos5250-mct
- samsung,exynos5260-mct
- samsung,exynos5420-mct
- samsung,exynos5433-mct
- samsung,exynos850-mct
- tesla,fsd-mct
- const: samsung,exynos4210-mct
clocks: clocks:
maxItems: 2 maxItems: 2
...@@ -62,6 +73,56 @@ required: ...@@ -62,6 +73,56 @@ required:
- interrupts - interrupts
- reg - reg
allOf:
- if:
properties:
compatible:
contains:
const: samsung,exynos3250-mct
then:
properties:
interrupts:
minItems: 8
maxItems: 8
- if:
properties:
compatible:
contains:
const: samsung,exynos5250-mct
then:
properties:
interrupts:
minItems: 6
maxItems: 6
- if:
properties:
compatible:
contains:
enum:
- samsung,exynos5260-mct
- samsung,exynos5420-mct
- samsung,exynos5433-mct
- samsung,exynos850-mct
then:
properties:
interrupts:
minItems: 12
maxItems: 12
- if:
properties:
compatible:
contains:
enum:
- tesla,fsd-mct
then:
properties:
interrupts:
minItems: 16
maxItems: 16
additionalProperties: false additionalProperties: false
examples: examples:
......
...@@ -1837,7 +1837,9 @@ F: Documentation/devicetree/bindings/arm/apple/* ...@@ -1837,7 +1837,9 @@ F: Documentation/devicetree/bindings/arm/apple/*
F: Documentation/devicetree/bindings/clock/apple,nco.yaml F: Documentation/devicetree/bindings/clock/apple,nco.yaml
F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml
F: Documentation/devicetree/bindings/interrupt-controller/apple,* F: Documentation/devicetree/bindings/interrupt-controller/apple,*
F: Documentation/devicetree/bindings/iommu/apple,sart.yaml
F: Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml F: Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml
F: Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml
F: Documentation/devicetree/bindings/pci/apple,pcie.yaml F: Documentation/devicetree/bindings/pci/apple,pcie.yaml
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
F: Documentation/devicetree/bindings/power/apple* F: Documentation/devicetree/bindings/power/apple*
...@@ -1848,12 +1850,14 @@ F: drivers/i2c/busses/i2c-pasemi-core.c ...@@ -1848,12 +1850,14 @@ F: drivers/i2c/busses/i2c-pasemi-core.c
F: drivers/i2c/busses/i2c-pasemi-platform.c F: drivers/i2c/busses/i2c-pasemi-platform.c
F: drivers/irqchip/irq-apple-aic.c F: drivers/irqchip/irq-apple-aic.c
F: drivers/mailbox/apple-mailbox.c F: drivers/mailbox/apple-mailbox.c
F: drivers/nvme/host/apple.c
F: drivers/pinctrl/pinctrl-apple-gpio.c F: drivers/pinctrl/pinctrl-apple-gpio.c
F: drivers/soc/apple/* F: drivers/soc/apple/*
F: drivers/watchdog/apple_wdt.c F: drivers/watchdog/apple_wdt.c
F: include/dt-bindings/interrupt-controller/apple-aic.h F: include/dt-bindings/interrupt-controller/apple-aic.h
F: include/dt-bindings/pinctrl/apple.h F: include/dt-bindings/pinctrl/apple.h
F: include/linux/apple-mailbox.h F: include/linux/apple-mailbox.h
F: include/linux/soc/apple/*
ARM/ARTPEC MACHINE SUPPORT ARM/ARTPEC MACHINE SUPPORT
M: Jesper Nilsson <jesper.nilsson@axis.com> M: Jesper Nilsson <jesper.nilsson@axis.com>
......
...@@ -152,6 +152,17 @@ config QCOM_EBI2 ...@@ -152,6 +152,17 @@ config QCOM_EBI2
Interface 2, which can be used to connect things like NAND Flash, Interface 2, which can be used to connect things like NAND Flash,
SRAM, ethernet adapters, FPGAs and LCD displays. SRAM, ethernet adapters, FPGAs and LCD displays.
config QCOM_SSC_BLOCK_BUS
bool "Qualcomm SSC Block Bus Init Driver"
depends on ARCH_QCOM
help
Say y here to enable support for initializing the bus that connects
the SSC block's internal bus to the cNoC (configurantion NoC) on
(some) qcom SoCs.
The SSC (Snapdragon Sensor Core) block contains a gpio controller,
i2c/spi/uart controllers, a hexagon core, and a clock controller
which provides clocks for the above.
config SUN50I_DE2_BUS config SUN50I_DE2_BUS
bool "Allwinner A64 DE2 Bus Driver" bool "Allwinner A64 DE2 Bus Driver"
default ARM64 default ARM64
......
...@@ -25,6 +25,7 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o ...@@ -25,6 +25,7 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o
obj-$(CONFIG_QCOM_SSC_BLOCK_BUS) += qcom-ssc-block-bus.o
obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_OF) += simple-pm-bus.o obj-$(CONFIG_OF) += simple-pm-bus.o
......
...@@ -536,7 +536,6 @@ static struct platform_driver brcmstb_gisb_arb_driver = { ...@@ -536,7 +536,6 @@ static struct platform_driver brcmstb_gisb_arb_driver = {
.name = "brcm-gisb-arb", .name = "brcm-gisb-arb",
.of_match_table = brcmstb_gisb_arb_of_match, .of_match_table = brcmstb_gisb_arb_of_match,
.pm = &brcmstb_gisb_arb_pm_ops, .pm = &brcmstb_gisb_arb_pm_ops,
.suppress_bind_attrs = true,
}, },
}; };
......
This diff is collapsed.
...@@ -3049,7 +3049,7 @@ static const struct soc_device_attribute sysc_soc_match[] = { ...@@ -3049,7 +3049,7 @@ static const struct soc_device_attribute sysc_soc_match[] = {
SOC_FLAG("AM43*", SOC_AM4), SOC_FLAG("AM43*", SOC_AM4),
SOC_FLAG("DRA7*", SOC_DRA7), SOC_FLAG("DRA7*", SOC_DRA7),
{ /* sentinel */ }, { /* sentinel */ }
}; };
/* /*
...@@ -3070,7 +3070,7 @@ static const struct soc_device_attribute sysc_soc_feat_match[] = { ...@@ -3070,7 +3070,7 @@ static const struct soc_device_attribute sysc_soc_feat_match[] = {
SOC_FLAG("OMAP3615/AM3715", DIS_IVA), SOC_FLAG("OMAP3615/AM3715", DIS_IVA),
SOC_FLAG("OMAP3621", DIS_ISP), SOC_FLAG("OMAP3621", DIS_ISP),
{ /* sentinel */ }, { /* sentinel */ }
}; };
static int sysc_add_disabled(unsigned long base) static int sysc_add_disabled(unsigned long base)
......
...@@ -398,11 +398,15 @@ static int ffa_mem_first_frag(u32 func_id, phys_addr_t buf, u32 buf_sz, ...@@ -398,11 +398,15 @@ static int ffa_mem_first_frag(u32 func_id, phys_addr_t buf, u32 buf_sz,
if (ret.a0 == FFA_ERROR) if (ret.a0 == FFA_ERROR)
return ffa_to_linux_errno((int)ret.a2); return ffa_to_linux_errno((int)ret.a2);
if (ret.a0 != FFA_SUCCESS) if (ret.a0 == FFA_SUCCESS) {
if (handle)
*handle = PACK_HANDLE(ret.a2, ret.a3);
} else if (ret.a0 == FFA_MEM_FRAG_RX) {
if (handle)
*handle = PACK_HANDLE(ret.a1, ret.a2);
} else {
return -EOPNOTSUPP; return -EOPNOTSUPP;
}
if (handle)
*handle = PACK_HANDLE(ret.a2, ret.a3);
return frag_len; return frag_len;
} }
...@@ -426,10 +430,12 @@ static int ffa_mem_next_frag(u64 handle, u32 frag_len) ...@@ -426,10 +430,12 @@ static int ffa_mem_next_frag(u64 handle, u32 frag_len)
if (ret.a0 == FFA_ERROR) if (ret.a0 == FFA_ERROR)
return ffa_to_linux_errno((int)ret.a2); return ffa_to_linux_errno((int)ret.a2);
if (ret.a0 != FFA_MEM_FRAG_RX) if (ret.a0 == FFA_MEM_FRAG_RX)
return -EOPNOTSUPP; return ret.a3;
else if (ret.a0 == FFA_SUCCESS)
return 0;
return ret.a3; return -EOPNOTSUPP;
} }
static int static int
...@@ -582,7 +588,7 @@ static int ffa_partition_info_get(const char *uuid_str, ...@@ -582,7 +588,7 @@ static int ffa_partition_info_get(const char *uuid_str,
return -ENODEV; return -ENODEV;
} }
count = ffa_partition_probe(&uuid_null, &pbuf); count = ffa_partition_probe(&uuid, &pbuf);
if (count <= 0) if (count <= 0)
return -ENOENT; return -ENOENT;
...@@ -688,8 +694,6 @@ static void ffa_setup_partitions(void) ...@@ -688,8 +694,6 @@ static void ffa_setup_partitions(void)
__func__, tpbuf->id); __func__, tpbuf->id);
continue; continue;
} }
ffa_dev_set_drvdata(ffa_dev, drv_info);
} }
kfree(pbuf); kfree(pbuf);
} }
......
...@@ -59,6 +59,7 @@ config ARM_SCMI_TRANSPORT_OPTEE ...@@ -59,6 +59,7 @@ config ARM_SCMI_TRANSPORT_OPTEE
depends on OPTEE=y || OPTEE=ARM_SCMI_PROTOCOL depends on OPTEE=y || OPTEE=ARM_SCMI_PROTOCOL
select ARM_SCMI_HAVE_TRANSPORT select ARM_SCMI_HAVE_TRANSPORT
select ARM_SCMI_HAVE_SHMEM select ARM_SCMI_HAVE_SHMEM
select ARM_SCMI_HAVE_MSG
default y default y
help help
This enables the OP-TEE service based transport for SCMI. This enables the OP-TEE service based transport for SCMI.
......
...@@ -178,6 +178,7 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph, ...@@ -178,6 +178,7 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph,
__le32 *num_skip, *num_ret; __le32 *num_skip, *num_ret;
u32 tot_num_ret = 0, loop_num_ret; u32 tot_num_ret = 0, loop_num_ret;
struct device *dev = ph->dev; struct device *dev = ph->dev;
struct scmi_revision_info *rev = ph->get_priv(ph);
ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_LIST_PROTOCOLS, ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_LIST_PROTOCOLS,
sizeof(*num_skip), 0, &t); sizeof(*num_skip), 0, &t);
...@@ -189,6 +190,9 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph, ...@@ -189,6 +190,9 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph,
list = t->rx.buf + sizeof(*num_ret); list = t->rx.buf + sizeof(*num_ret);
do { do {
size_t real_list_sz;
u32 calc_list_sz;
/* Set the number of protocols to be skipped/already read */ /* Set the number of protocols to be skipped/already read */
*num_skip = cpu_to_le32(tot_num_ret); *num_skip = cpu_to_le32(tot_num_ret);
...@@ -197,8 +201,30 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph, ...@@ -197,8 +201,30 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph,
break; break;
loop_num_ret = le32_to_cpu(*num_ret); loop_num_ret = le32_to_cpu(*num_ret);
if (tot_num_ret + loop_num_ret > MAX_PROTOCOLS_IMP) { if (!loop_num_ret)
dev_err(dev, "No. of Protocol > MAX_PROTOCOLS_IMP"); break;
if (loop_num_ret > rev->num_protocols - tot_num_ret) {
dev_err(dev,
"No. Returned protocols > Total protocols.\n");
break;
}
if (t->rx.len < (sizeof(u32) * 2)) {
dev_err(dev, "Truncated reply - rx.len:%zd\n",
t->rx.len);
ret = -EPROTO;
break;
}
real_list_sz = t->rx.len - sizeof(u32);
calc_list_sz = (1 + (loop_num_ret - 1) / sizeof(u32)) *
sizeof(u32);
if (calc_list_sz != real_list_sz) {
dev_err(dev,
"Malformed reply - real_sz:%zd calc_sz:%u\n",
real_list_sz, calc_list_sz);
ret = -EPROTO;
break; break;
} }
...@@ -208,7 +234,7 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph, ...@@ -208,7 +234,7 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph,
tot_num_ret += loop_num_ret; tot_num_ret += loop_num_ret;
ph->xops->reset_rx_to_maxsz(ph, t); ph->xops->reset_rx_to_maxsz(ph, t);
} while (loop_num_ret); } while (tot_num_ret < rev->num_protocols);
ph->xops->xfer_put(ph, t); ph->xops->xfer_put(ph, t);
...@@ -351,15 +377,19 @@ static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph) ...@@ -351,15 +377,19 @@ static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)
if (ret) if (ret)
return ret; return ret;
prot_imp = devm_kcalloc(dev, MAX_PROTOCOLS_IMP, sizeof(u8), GFP_KERNEL);
if (!prot_imp)
return -ENOMEM;
rev->major_ver = PROTOCOL_REV_MAJOR(version), rev->major_ver = PROTOCOL_REV_MAJOR(version),
rev->minor_ver = PROTOCOL_REV_MINOR(version); rev->minor_ver = PROTOCOL_REV_MINOR(version);
ph->set_priv(ph, rev); ph->set_priv(ph, rev);
scmi_base_attributes_get(ph); ret = scmi_base_attributes_get(ph);
if (ret)
return ret;
prot_imp = devm_kcalloc(dev, rev->num_protocols, sizeof(u8),
GFP_KERNEL);
if (!prot_imp)
return -ENOMEM;
scmi_base_vendor_id_get(ph, false); scmi_base_vendor_id_get(ph, false);
scmi_base_vendor_id_get(ph, true); scmi_base_vendor_id_get(ph, true);
scmi_base_implementation_version_get(ph); scmi_base_implementation_version_get(ph);
......
This diff is collapsed.
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* driver common header file containing some definitions, structures * driver common header file containing some definitions, structures
* and function prototypes used in all the different SCMI protocols. * and function prototypes used in all the different SCMI protocols.
* *
* Copyright (C) 2018-2021 ARM Ltd. * Copyright (C) 2018-2022 ARM Ltd.
*/ */
#ifndef _SCMI_COMMON_H #ifndef _SCMI_COMMON_H
#define _SCMI_COMMON_H #define _SCMI_COMMON_H
...@@ -24,38 +24,9 @@ ...@@ -24,38 +24,9 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "protocols.h"
#include "notify.h" #include "notify.h"
#define PROTOCOL_REV_MINOR_MASK GENMASK(15, 0)
#define PROTOCOL_REV_MAJOR_MASK GENMASK(31, 16)
#define PROTOCOL_REV_MAJOR(x) (u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x)))
#define PROTOCOL_REV_MINOR(x) (u16)(FIELD_GET(PROTOCOL_REV_MINOR_MASK, (x)))
#define MAX_PROTOCOLS_IMP 16
#define MAX_OPPS 16
enum scmi_common_cmd {
PROTOCOL_VERSION = 0x0,
PROTOCOL_ATTRIBUTES = 0x1,
PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
};
/**
* struct scmi_msg_resp_prot_version - Response for a message
*
* @minor_version: Minor version of the ABI that firmware supports
* @major_version: Major version of the ABI that firmware supports
*
* In general, ABI version changes follow the rule that minor version increments
* are backward compatible. Major revision changes in ABI may not be
* backward compatible.
*
* Response to a generic message with message type SCMI_MSG_VERSION
*/
struct scmi_msg_resp_prot_version {
__le16 minor_version;
__le16 major_version;
};
#define MSG_ID_MASK GENMASK(7, 0) #define MSG_ID_MASK GENMASK(7, 0)
#define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr)) #define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr))
#define MSG_TYPE_MASK GENMASK(9, 8) #define MSG_TYPE_MASK GENMASK(9, 8)
...@@ -79,28 +50,6 @@ struct scmi_msg_resp_prot_version { ...@@ -79,28 +50,6 @@ struct scmi_msg_resp_prot_version {
*/ */
#define SCMI_PENDING_XFERS_HT_ORDER_SZ 9 #define SCMI_PENDING_XFERS_HT_ORDER_SZ 9
/**
* struct scmi_msg_hdr - Message(Tx/Rx) header
*
* @id: The identifier of the message being sent
* @protocol_id: The identifier of the protocol used to send @id message
* @type: The SCMI type for this message
* @seq: The token to identify the message. When a message returns, the
* platform returns the whole message header unmodified including the
* token
* @status: Status of the transfer once it's complete
* @poll_completion: Indicate if the transfer needs to be polled for
* completion or interrupt mode is used
*/
struct scmi_msg_hdr {
u8 id;
u8 protocol_id;
u8 type;
u16 seq;
u32 status;
bool poll_completion;
};
/** /**
* pack_scmi_header() - packs and returns 32-bit header * pack_scmi_header() - packs and returns 32-bit header
* *
...@@ -130,72 +79,6 @@ static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr) ...@@ -130,72 +79,6 @@ static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr)
hdr->type = MSG_XTRACT_TYPE(msg_hdr); hdr->type = MSG_XTRACT_TYPE(msg_hdr);
} }
/**
* struct scmi_msg - Message(Tx/Rx) structure
*
* @buf: Buffer pointer
* @len: Length of data in the Buffer
*/
struct scmi_msg {
void *buf;
size_t len;
};
/**
* struct scmi_xfer - Structure representing a message flow
*
* @transfer_id: Unique ID for debug & profiling purpose
* @hdr: Transmit message header
* @tx: Transmit message
* @rx: Receive message, the buffer should be pre-allocated to store
* message. If request-ACK protocol is used, we can reuse the same
* buffer for the rx path as we use for the tx path.
* @done: command message transmit completion event
* @async_done: pointer to delayed response message received event completion
* @pending: True for xfers added to @pending_xfers hashtable
* @node: An hlist_node reference used to store this xfer, alternatively, on
* the free list @free_xfers or in the @pending_xfers hashtable
* @users: A refcount to track the active users for this xfer.
* This is meant to protect against the possibility that, when a command
* transaction times out concurrently with the reception of a valid
* response message, the xfer could be finally put on the TX path, and
* so vanish, while on the RX path scmi_rx_callback() is still
* processing it: in such a case this refcounting will ensure that, even
* though the timed-out transaction will anyway cause the command
* request to be reported as failed by time-out, the underlying xfer
* cannot be discarded and possibly reused until the last one user on
* the RX path has released it.
* @busy: An atomic flag to ensure exclusive write access to this xfer
* @state: The current state of this transfer, with states transitions deemed
* valid being:
* - SCMI_XFER_SENT_OK -> SCMI_XFER_RESP_OK [ -> SCMI_XFER_DRESP_OK ]
* - SCMI_XFER_SENT_OK -> SCMI_XFER_DRESP_OK
* (Missing synchronous response is assumed OK and ignored)
* @lock: A spinlock to protect state and busy fields.
* @priv: A pointer for transport private usage.
*/
struct scmi_xfer {
int transfer_id;
struct scmi_msg_hdr hdr;
struct scmi_msg tx;
struct scmi_msg rx;
struct completion done;
struct completion *async_done;
bool pending;
struct hlist_node node;
refcount_t users;
#define SCMI_XFER_FREE 0
#define SCMI_XFER_BUSY 1
atomic_t busy;
#define SCMI_XFER_SENT_OK 0
#define SCMI_XFER_RESP_OK 1
#define SCMI_XFER_DRESP_OK 2
int state;
/* A lock to protect state and busy fields */
spinlock_t lock;
void *priv;
};
/* /*
* An helper macro to lookup an xfer from the @pending_xfers hashtable * An helper macro to lookup an xfer from the @pending_xfers hashtable
* using the message sequence number token as a key. * using the message sequence number token as a key.
...@@ -211,64 +94,6 @@ struct scmi_xfer { ...@@ -211,64 +94,6 @@ struct scmi_xfer {
xfer_; \ xfer_; \
}) })
struct scmi_xfer_ops;
/**
* struct scmi_protocol_handle - Reference to an initialized protocol instance
*
* @dev: A reference to the associated SCMI instance device (handle->dev).
* @xops: A reference to a struct holding refs to the core xfer operations that
* can be used by the protocol implementation to generate SCMI messages.
* @set_priv: A method to set protocol private data for this instance.
* @get_priv: A method to get protocol private data previously set.
*
* This structure represents a protocol initialized against specific SCMI
* instance and it will be used as follows:
* - as a parameter fed from the core to the protocol initialization code so
* that it can access the core xfer operations to build and generate SCMI
* messages exclusively for the specific underlying protocol instance.
* - as an opaque handle fed by an SCMI driver user when it tries to access
* this protocol through its own protocol operations.
* In this case this handle will be returned as an opaque object together
* with the related protocol operations when the SCMI driver tries to access
* the protocol.
*/
struct scmi_protocol_handle {
struct device *dev;
const struct scmi_xfer_ops *xops;
int (*set_priv)(const struct scmi_protocol_handle *ph, void *priv);
void *(*get_priv)(const struct scmi_protocol_handle *ph);
};
/**
* struct scmi_xfer_ops - References to the core SCMI xfer operations.
* @version_get: Get this version protocol.
* @xfer_get_init: Initialize one struct xfer if any xfer slot is free.
* @reset_rx_to_maxsz: Reset rx size to max transport size.
* @do_xfer: Do the SCMI transfer.
* @do_xfer_with_response: Do the SCMI transfer waiting for a response.
* @xfer_put: Free the xfer slot.
*
* Note that all this operations expect a protocol handle as first parameter;
* they then internally use it to infer the underlying protocol number: this
* way is not possible for a protocol implementation to forge messages for
* another protocol.
*/
struct scmi_xfer_ops {
int (*version_get)(const struct scmi_protocol_handle *ph, u32 *version);
int (*xfer_get_init)(const struct scmi_protocol_handle *ph, u8 msg_id,
size_t tx_size, size_t rx_size,
struct scmi_xfer **p);
void (*reset_rx_to_maxsz)(const struct scmi_protocol_handle *ph,
struct scmi_xfer *xfer);
int (*do_xfer)(const struct scmi_protocol_handle *ph,
struct scmi_xfer *xfer);
int (*do_xfer_with_response)(const struct scmi_protocol_handle *ph,
struct scmi_xfer *xfer);
void (*xfer_put)(const struct scmi_protocol_handle *ph,
struct scmi_xfer *xfer);
};
struct scmi_revision_info * struct scmi_revision_info *
scmi_revision_area_get(const struct scmi_protocol_handle *ph); scmi_revision_area_get(const struct scmi_protocol_handle *ph);
int scmi_handle_put(const struct scmi_handle *handle); int scmi_handle_put(const struct scmi_handle *handle);
...@@ -277,55 +102,9 @@ void scmi_set_handle(struct scmi_device *scmi_dev); ...@@ -277,55 +102,9 @@ void scmi_set_handle(struct scmi_device *scmi_dev);
void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph, void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph,
u8 *prot_imp); u8 *prot_imp);
typedef int (*scmi_prot_init_ph_fn_t)(const struct scmi_protocol_handle *);
/**
* struct scmi_protocol - Protocol descriptor
* @id: Protocol ID.
* @owner: Module reference if any.
* @instance_init: Mandatory protocol initialization function.
* @instance_deinit: Optional protocol de-initialization function.
* @ops: Optional reference to the operations provided by the protocol and
* exposed in scmi_protocol.h.
* @events: An optional reference to the events supported by this protocol.
*/
struct scmi_protocol {
const u8 id;
struct module *owner;
const scmi_prot_init_ph_fn_t instance_init;
const scmi_prot_init_ph_fn_t instance_deinit;
const void *ops;
const struct scmi_protocol_events *events;
};
int __init scmi_bus_init(void); int __init scmi_bus_init(void);
void __exit scmi_bus_exit(void); void __exit scmi_bus_exit(void);
#define DECLARE_SCMI_REGISTER_UNREGISTER(func) \
int __init scmi_##func##_register(void); \
void __exit scmi_##func##_unregister(void)
DECLARE_SCMI_REGISTER_UNREGISTER(base);
DECLARE_SCMI_REGISTER_UNREGISTER(clock);
DECLARE_SCMI_REGISTER_UNREGISTER(perf);
DECLARE_SCMI_REGISTER_UNREGISTER(power);
DECLARE_SCMI_REGISTER_UNREGISTER(reset);
DECLARE_SCMI_REGISTER_UNREGISTER(sensors);
DECLARE_SCMI_REGISTER_UNREGISTER(voltage);
DECLARE_SCMI_REGISTER_UNREGISTER(system);
#define DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(name, proto) \
static const struct scmi_protocol *__this_proto = &(proto); \
\
int __init scmi_##name##_register(void) \
{ \
return scmi_protocol_register(__this_proto); \
} \
\
void __exit scmi_##name##_unregister(void) \
{ \
scmi_protocol_unregister(__this_proto); \
}
const struct scmi_protocol *scmi_protocol_get(int protocol_id); const struct scmi_protocol *scmi_protocol_get(int protocol_id);
void scmi_protocol_put(int protocol_id); void scmi_protocol_put(int protocol_id);
......
...@@ -128,7 +128,8 @@ struct scmi_protocol_instance { ...@@ -128,7 +128,8 @@ struct scmi_protocol_instance {
* usage. * usage.
* @protocols_mtx: A mutex to protect protocols instances initialization. * @protocols_mtx: A mutex to protect protocols instances initialization.
* @protocols_imp: List of protocols implemented, currently maximum of * @protocols_imp: List of protocols implemented, currently maximum of
* MAX_PROTOCOLS_IMP elements allocated by the base protocol * scmi_revision_info.num_protocols elements allocated by the
* base protocol
* @active_protocols: IDR storing device_nodes for protocols actually defined * @active_protocols: IDR storing device_nodes for protocols actually defined
* in the DT and confirmed as implemented by fw. * in the DT and confirmed as implemented by fw.
* @atomic_threshold: Optional system wide DT-configured threshold, expressed * @atomic_threshold: Optional system wide DT-configured threshold, expressed
...@@ -1102,6 +1103,167 @@ static const struct scmi_xfer_ops xfer_ops = { ...@@ -1102,6 +1103,167 @@ static const struct scmi_xfer_ops xfer_ops = {
.xfer_put = xfer_put, .xfer_put = xfer_put,
}; };
struct scmi_msg_resp_domain_name_get {
__le32 flags;
u8 name[SCMI_MAX_STR_SIZE];
};
/**
* scmi_common_extended_name_get - Common helper to get extended resources name
* @ph: A protocol handle reference.
* @cmd_id: The specific command ID to use.
* @res_id: The specific resource ID to use.
* @name: A pointer to the preallocated area where the retrieved name will be
* stored as a NULL terminated string.
* @len: The len in bytes of the @name char array.
*
* Return: 0 on Succcess
*/
static int scmi_common_extended_name_get(const struct scmi_protocol_handle *ph,
u8 cmd_id, u32 res_id, char *name,
size_t len)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_resp_domain_name_get *resp;
ret = ph->xops->xfer_get_init(ph, cmd_id, sizeof(res_id),
sizeof(*resp), &t);
if (ret)
goto out;
put_unaligned_le32(res_id, t->tx.buf);
resp = t->rx.buf;
ret = ph->xops->do_xfer(ph, t);
if (!ret)
strscpy(name, resp->name, len);
ph->xops->xfer_put(ph, t);
out:
if (ret)
dev_warn(ph->dev,
"Failed to get extended name - id:%u (ret:%d). Using %s\n",
res_id, ret, name);
return ret;
}
/**
* struct scmi_iterator - Iterator descriptor
* @msg: A reference to the message TX buffer; filled by @prepare_message with
* a proper custom command payload for each multi-part command request.
* @resp: A reference to the response RX buffer; used by @update_state and
* @process_response to parse the multi-part replies.
* @t: A reference to the underlying xfer initialized and used transparently by
* the iterator internal routines.
* @ph: A reference to the associated protocol handle to be used.
* @ops: A reference to the custom provided iterator operations.
* @state: The current iterator state; used and updated in turn by the iterators
* internal routines and by the caller-provided @scmi_iterator_ops.
* @priv: A reference to optional private data as provided by the caller and
* passed back to the @@scmi_iterator_ops.
*/
struct scmi_iterator {
void *msg;
void *resp;
struct scmi_xfer *t;
const struct scmi_protocol_handle *ph;
struct scmi_iterator_ops *ops;
struct scmi_iterator_state state;
void *priv;
};
static void *scmi_iterator_init(const struct scmi_protocol_handle *ph,
struct scmi_iterator_ops *ops,
unsigned int max_resources, u8 msg_id,
size_t tx_size, void *priv)
{
int ret;
struct scmi_iterator *i;
i = devm_kzalloc(ph->dev, sizeof(*i), GFP_KERNEL);
if (!i)
return ERR_PTR(-ENOMEM);
i->ph = ph;
i->ops = ops;
i->priv = priv;
ret = ph->xops->xfer_get_init(ph, msg_id, tx_size, 0, &i->t);
if (ret) {
devm_kfree(ph->dev, i);
return ERR_PTR(ret);
}
i->state.max_resources = max_resources;
i->msg = i->t->tx.buf;
i->resp = i->t->rx.buf;
return i;
}
static int scmi_iterator_run(void *iter)
{
int ret = -EINVAL;
struct scmi_iterator_ops *iops;
const struct scmi_protocol_handle *ph;
struct scmi_iterator_state *st;
struct scmi_iterator *i = iter;
if (!i || !i->ops || !i->ph)
return ret;
iops = i->ops;
ph = i->ph;
st = &i->state;
do {
iops->prepare_message(i->msg, st->desc_index, i->priv);
ret = ph->xops->do_xfer(ph, i->t);
if (ret)
break;
ret = iops->update_state(st, i->resp, i->priv);
if (ret)
break;
if (st->num_returned > st->max_resources - st->desc_index) {
dev_err(ph->dev,
"No. of resources can't exceed %d\n",
st->max_resources);
ret = -EINVAL;
break;
}
for (st->loop_idx = 0; st->loop_idx < st->num_returned;
st->loop_idx++) {
ret = iops->process_response(ph, i->resp, st, i->priv);
if (ret)
goto out;
}
st->desc_index += st->num_returned;
ph->xops->reset_rx_to_maxsz(ph, i->t);
/*
* check for both returned and remaining to avoid infinite
* loop due to buggy firmware
*/
} while (st->num_returned && st->num_remaining);
out:
/* Finalize and destroy iterator */
ph->xops->xfer_put(ph, i->t);
devm_kfree(ph->dev, i);
return ret;
}
static const struct scmi_proto_helpers_ops helpers_ops = {
.extended_name_get = scmi_common_extended_name_get,
.iter_response_init = scmi_iterator_init,
.iter_response_run = scmi_iterator_run,
};
/** /**
* scmi_revision_area_get - Retrieve version memory area. * scmi_revision_area_get - Retrieve version memory area.
* *
...@@ -1162,6 +1324,7 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info, ...@@ -1162,6 +1324,7 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,
pi->handle = handle; pi->handle = handle;
pi->ph.dev = handle->dev; pi->ph.dev = handle->dev;
pi->ph.xops = &xfer_ops; pi->ph.xops = &xfer_ops;
pi->ph.hops = &helpers_ops;
pi->ph.set_priv = scmi_set_protocol_priv; pi->ph.set_priv = scmi_set_protocol_priv;
pi->ph.get_priv = scmi_get_protocol_priv; pi->ph.get_priv = scmi_get_protocol_priv;
refcount_set(&pi->users, 1); refcount_set(&pi->users, 1);
...@@ -1310,11 +1473,12 @@ scmi_is_protocol_implemented(const struct scmi_handle *handle, u8 prot_id) ...@@ -1310,11 +1473,12 @@ scmi_is_protocol_implemented(const struct scmi_handle *handle, u8 prot_id)
{ {
int i; int i;
struct scmi_info *info = handle_to_scmi_info(handle); struct scmi_info *info = handle_to_scmi_info(handle);
struct scmi_revision_info *rev = handle->version;
if (!info->protocols_imp) if (!info->protocols_imp)
return false; return false;
for (i = 0; i < MAX_PROTOCOLS_IMP; i++) for (i = 0; i < rev->num_protocols; i++)
if (info->protocols_imp[i] == prot_id) if (info->protocols_imp[i] == prot_id)
return true; return true;
return false; return false;
......
...@@ -64,6 +64,22 @@ enum scmi_optee_pta_cmd { ...@@ -64,6 +64,22 @@ enum scmi_optee_pta_cmd {
* [in] value[0].b: Requested capabilities mask (enum pta_scmi_caps) * [in] value[0].b: Requested capabilities mask (enum pta_scmi_caps)
*/ */
PTA_SCMI_CMD_GET_CHANNEL = 3, PTA_SCMI_CMD_GET_CHANNEL = 3,
/*
* PTA_SCMI_CMD_PROCESS_MSG_CHANNEL - Process SCMI message in a MSG
* buffer pointed by memref parameters
*
* [in] value[0].a: Channel handle
* [in] memref[1]: Message buffer (MSG and SCMI payload)
* [out] memref[2]: Response buffer (MSG and SCMI payload)
*
* Shared memories used for SCMI message/response are MSG buffers
* referenced by param[1] and param[2]. MSG transport protocol
* uses a 32bit header to carry SCMI meta-data (protocol ID and
* protocol message ID) followed by the effective SCMI message
* payload.
*/
PTA_SCMI_CMD_PROCESS_MSG_CHANNEL = 4,
}; };
/* /*
...@@ -72,9 +88,17 @@ enum scmi_optee_pta_cmd { ...@@ -72,9 +88,17 @@ enum scmi_optee_pta_cmd {
* PTA_SCMI_CAPS_SMT_HEADER * PTA_SCMI_CAPS_SMT_HEADER
* When set, OP-TEE supports command using SMT header protocol (SCMI shmem) in * When set, OP-TEE supports command using SMT header protocol (SCMI shmem) in
* shared memory buffers to carry SCMI protocol synchronisation information. * shared memory buffers to carry SCMI protocol synchronisation information.
*
* PTA_SCMI_CAPS_MSG_HEADER
* When set, OP-TEE supports command using MSG header protocol in an OP-TEE
* shared memory to carry SCMI protocol synchronisation information and SCMI
* message payload.
*/ */
#define PTA_SCMI_CAPS_NONE 0 #define PTA_SCMI_CAPS_NONE 0
#define PTA_SCMI_CAPS_SMT_HEADER BIT(0) #define PTA_SCMI_CAPS_SMT_HEADER BIT(0)
#define PTA_SCMI_CAPS_MSG_HEADER BIT(1)
#define PTA_SCMI_CAPS_MASK (PTA_SCMI_CAPS_SMT_HEADER | \
PTA_SCMI_CAPS_MSG_HEADER)
/** /**
* struct scmi_optee_channel - Description of an OP-TEE SCMI channel * struct scmi_optee_channel - Description of an OP-TEE SCMI channel
...@@ -85,7 +109,8 @@ enum scmi_optee_pta_cmd { ...@@ -85,7 +109,8 @@ enum scmi_optee_pta_cmd {
* @mu: Mutex protection on channel access * @mu: Mutex protection on channel access
* @cinfo: SCMI channel information * @cinfo: SCMI channel information
* @shmem: Virtual base address of the shared memory * @shmem: Virtual base address of the shared memory
* @tee_shm: Reference to TEE shared memory or NULL if using static shmem * @req: Shared memory protocol handle for SCMI request and synchronous response
* @tee_shm: TEE shared memory handle @req or NULL if using IOMEM shmem
* @link: Reference in agent's channel list * @link: Reference in agent's channel list
*/ */
struct scmi_optee_channel { struct scmi_optee_channel {
...@@ -94,7 +119,10 @@ struct scmi_optee_channel { ...@@ -94,7 +119,10 @@ struct scmi_optee_channel {
u32 caps; u32 caps;
struct mutex mu; struct mutex mu;
struct scmi_chan_info *cinfo; struct scmi_chan_info *cinfo;
struct scmi_shared_mem __iomem *shmem; union {
struct scmi_shared_mem __iomem *shmem;
struct scmi_msg_payld *msg;
} req;
struct tee_shm *tee_shm; struct tee_shm *tee_shm;
struct list_head link; struct list_head link;
}; };
...@@ -178,8 +206,8 @@ static int get_capabilities(struct scmi_optee_agent *agent) ...@@ -178,8 +206,8 @@ static int get_capabilities(struct scmi_optee_agent *agent)
caps = param[0].u.value.a; caps = param[0].u.value.a;
if (!(caps & PTA_SCMI_CAPS_SMT_HEADER)) { if (!(caps & (PTA_SCMI_CAPS_SMT_HEADER | PTA_SCMI_CAPS_MSG_HEADER))) {
dev_err(agent->dev, "OP-TEE SCMI PTA doesn't support SMT\n"); dev_err(agent->dev, "OP-TEE SCMI PTA doesn't support SMT and MSG\n");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -193,9 +221,14 @@ static int get_channel(struct scmi_optee_channel *channel) ...@@ -193,9 +221,14 @@ static int get_channel(struct scmi_optee_channel *channel)
struct device *dev = scmi_optee_private->dev; struct device *dev = scmi_optee_private->dev;
struct tee_ioctl_invoke_arg arg = { }; struct tee_ioctl_invoke_arg arg = { };
struct tee_param param[1] = { }; struct tee_param param[1] = { };
unsigned int caps = PTA_SCMI_CAPS_SMT_HEADER; unsigned int caps = 0;
int ret; int ret;
if (channel->tee_shm)
caps = PTA_SCMI_CAPS_MSG_HEADER;
else
caps = PTA_SCMI_CAPS_SMT_HEADER;
arg.func = PTA_SCMI_CMD_GET_CHANNEL; arg.func = PTA_SCMI_CMD_GET_CHANNEL;
arg.session = channel->tee_session; arg.session = channel->tee_session;
arg.num_params = 1; arg.num_params = 1;
...@@ -220,25 +253,48 @@ static int get_channel(struct scmi_optee_channel *channel) ...@@ -220,25 +253,48 @@ static int get_channel(struct scmi_optee_channel *channel)
static int invoke_process_smt_channel(struct scmi_optee_channel *channel) static int invoke_process_smt_channel(struct scmi_optee_channel *channel)
{ {
struct tee_ioctl_invoke_arg arg = { }; struct tee_ioctl_invoke_arg arg = {
struct tee_param param[2] = { }; .func = PTA_SCMI_CMD_PROCESS_SMT_CHANNEL,
.session = channel->tee_session,
.num_params = 1,
};
struct tee_param param[1] = { };
int ret; int ret;
arg.session = channel->tee_session;
param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
param[0].u.value.a = channel->channel_id; param[0].u.value.a = channel->channel_id;
if (channel->tee_shm) { ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param);
param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; if (ret < 0 || arg.ret) {
param[1].u.memref.shm = channel->tee_shm; dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n",
param[1].u.memref.size = SCMI_OPTEE_MAX_MSG_SIZE; channel->channel_id, ret, arg.ret);
arg.num_params = 2; return -EIO;
arg.func = PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE;
} else {
arg.num_params = 1;
arg.func = PTA_SCMI_CMD_PROCESS_SMT_CHANNEL;
} }
return 0;
}
static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t msg_size)
{
struct tee_ioctl_invoke_arg arg = {
.func = PTA_SCMI_CMD_PROCESS_MSG_CHANNEL,
.session = channel->tee_session,
.num_params = 3,
};
struct tee_param param[3] = { };
int ret;
param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
param[0].u.value.a = channel->channel_id;
param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
param[1].u.memref.shm = channel->tee_shm;
param[1].u.memref.size = msg_size;
param[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
param[2].u.memref.shm = channel->tee_shm;
param[2].u.memref.size = SCMI_OPTEE_MAX_MSG_SIZE;
ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param); ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param);
if (ret < 0 || arg.ret) { if (ret < 0 || arg.ret) {
dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n", dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n",
...@@ -279,7 +335,26 @@ static void scmi_optee_clear_channel(struct scmi_chan_info *cinfo) ...@@ -279,7 +335,26 @@ static void scmi_optee_clear_channel(struct scmi_chan_info *cinfo)
{ {
struct scmi_optee_channel *channel = cinfo->transport_info; struct scmi_optee_channel *channel = cinfo->transport_info;
shmem_clear_channel(channel->shmem); if (!channel->tee_shm)
shmem_clear_channel(channel->req.shmem);
}
static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *channel)
{
const size_t msg_size = SCMI_OPTEE_MAX_MSG_SIZE;
void *shbuf;
channel->tee_shm = tee_shm_alloc_kernel_buf(scmi_optee_private->tee_ctx, msg_size);
if (IS_ERR(channel->tee_shm)) {
dev_err(channel->cinfo->dev, "shmem allocation failed\n");
return -ENOMEM;
}
shbuf = tee_shm_get_va(channel->tee_shm, 0);
memset(shbuf, 0, msg_size);
channel->req.msg = shbuf;
return 0;
} }
static int setup_static_shmem(struct device *dev, struct scmi_chan_info *cinfo, static int setup_static_shmem(struct device *dev, struct scmi_chan_info *cinfo,
...@@ -304,8 +379,8 @@ static int setup_static_shmem(struct device *dev, struct scmi_chan_info *cinfo, ...@@ -304,8 +379,8 @@ static int setup_static_shmem(struct device *dev, struct scmi_chan_info *cinfo,
size = resource_size(&res); size = resource_size(&res);
channel->shmem = devm_ioremap(dev, res.start, size); channel->req.shmem = devm_ioremap(dev, res.start, size);
if (!channel->shmem) { if (!channel->req.shmem) {
dev_err(dev, "Failed to ioremap SCMI Tx shared memory\n"); dev_err(dev, "Failed to ioremap SCMI Tx shared memory\n");
ret = -EADDRNOTAVAIL; ret = -EADDRNOTAVAIL;
goto out; goto out;
...@@ -325,7 +400,7 @@ static int setup_shmem(struct device *dev, struct scmi_chan_info *cinfo, ...@@ -325,7 +400,7 @@ static int setup_shmem(struct device *dev, struct scmi_chan_info *cinfo,
if (of_find_property(cinfo->dev->of_node, "shmem", NULL)) if (of_find_property(cinfo->dev->of_node, "shmem", NULL))
return setup_static_shmem(dev, cinfo, channel); return setup_static_shmem(dev, cinfo, channel);
else else
return -ENOMEM; return setup_dynamic_shmem(dev, channel);
} }
static int scmi_optee_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, bool tx) static int scmi_optee_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, bool tx)
...@@ -405,27 +480,22 @@ static int scmi_optee_chan_free(int id, void *p, void *data) ...@@ -405,27 +480,22 @@ static int scmi_optee_chan_free(int id, void *p, void *data)
return 0; return 0;
} }
static struct scmi_shared_mem __iomem *
get_channel_shm(struct scmi_optee_channel *chan, struct scmi_xfer *xfer)
{
if (!chan)
return NULL;
return chan->shmem;
}
static int scmi_optee_send_message(struct scmi_chan_info *cinfo, static int scmi_optee_send_message(struct scmi_chan_info *cinfo,
struct scmi_xfer *xfer) struct scmi_xfer *xfer)
{ {
struct scmi_optee_channel *channel = cinfo->transport_info; struct scmi_optee_channel *channel = cinfo->transport_info;
struct scmi_shared_mem __iomem *shmem = get_channel_shm(channel, xfer);
int ret; int ret;
mutex_lock(&channel->mu); mutex_lock(&channel->mu);
shmem_tx_prepare(shmem, xfer);
ret = invoke_process_smt_channel(channel); if (channel->tee_shm) {
msg_tx_prepare(channel->req.msg, xfer);
ret = invoke_process_msg_channel(channel, msg_command_size(xfer));
} else {
shmem_tx_prepare(channel->req.shmem, xfer);
ret = invoke_process_smt_channel(channel);
}
if (ret) if (ret)
mutex_unlock(&channel->mu); mutex_unlock(&channel->mu);
...@@ -436,9 +506,11 @@ static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo, ...@@ -436,9 +506,11 @@ static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo,
struct scmi_xfer *xfer) struct scmi_xfer *xfer)
{ {
struct scmi_optee_channel *channel = cinfo->transport_info; struct scmi_optee_channel *channel = cinfo->transport_info;
struct scmi_shared_mem __iomem *shmem = get_channel_shm(channel, xfer);
shmem_fetch_response(shmem, xfer); if (channel->tee_shm)
msg_fetch_response(channel->req.msg, SCMI_OPTEE_MAX_MSG_SIZE, xfer);
else
shmem_fetch_response(channel->req.shmem, xfer);
} }
static void scmi_optee_mark_txdone(struct scmi_chan_info *cinfo, int ret, static void scmi_optee_mark_txdone(struct scmi_chan_info *cinfo, int ret,
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* /*
* System Control and Management Interface (SCMI) Performance Protocol * System Control and Management Interface (SCMI) Performance Protocol
* *
* Copyright (C) 2018-2021 ARM Ltd. * Copyright (C) 2018-2022 ARM Ltd.
*/ */
#define pr_fmt(fmt) "SCMI Notifications PERF - " fmt #define pr_fmt(fmt) "SCMI Notifications PERF - " fmt
...@@ -17,9 +17,11 @@ ...@@ -17,9 +17,11 @@
#include <linux/scmi_protocol.h> #include <linux/scmi_protocol.h>
#include <linux/sort.h> #include <linux/sort.h>
#include "common.h" #include "protocols.h"
#include "notify.h" #include "notify.h"
#define MAX_OPPS 16
enum scmi_performance_protocol_cmd { enum scmi_performance_protocol_cmd {
PERF_DOMAIN_ATTRIBUTES = 0x3, PERF_DOMAIN_ATTRIBUTES = 0x3,
PERF_DESCRIBE_LEVELS = 0x4, PERF_DESCRIBE_LEVELS = 0x4,
...@@ -30,6 +32,7 @@ enum scmi_performance_protocol_cmd { ...@@ -30,6 +32,7 @@ enum scmi_performance_protocol_cmd {
PERF_NOTIFY_LIMITS = 0x9, PERF_NOTIFY_LIMITS = 0x9,
PERF_NOTIFY_LEVEL = 0xa, PERF_NOTIFY_LEVEL = 0xa,
PERF_DESCRIBE_FASTCHANNEL = 0xb, PERF_DESCRIBE_FASTCHANNEL = 0xb,
PERF_DOMAIN_NAME_GET = 0xc,
}; };
struct scmi_opp { struct scmi_opp {
...@@ -42,6 +45,7 @@ struct scmi_msg_resp_perf_attributes { ...@@ -42,6 +45,7 @@ struct scmi_msg_resp_perf_attributes {
__le16 num_domains; __le16 num_domains;
__le16 flags; __le16 flags;
#define POWER_SCALE_IN_MILLIWATT(x) ((x) & BIT(0)) #define POWER_SCALE_IN_MILLIWATT(x) ((x) & BIT(0))
#define POWER_SCALE_IN_MICROWATT(x) ((x) & BIT(1))
__le32 stats_addr_low; __le32 stats_addr_low;
__le32 stats_addr_high; __le32 stats_addr_high;
__le32 stats_size; __le32 stats_size;
...@@ -54,10 +58,11 @@ struct scmi_msg_resp_perf_domain_attributes { ...@@ -54,10 +58,11 @@ struct scmi_msg_resp_perf_domain_attributes {
#define SUPPORTS_PERF_LIMIT_NOTIFY(x) ((x) & BIT(29)) #define SUPPORTS_PERF_LIMIT_NOTIFY(x) ((x) & BIT(29))
#define SUPPORTS_PERF_LEVEL_NOTIFY(x) ((x) & BIT(28)) #define SUPPORTS_PERF_LEVEL_NOTIFY(x) ((x) & BIT(28))
#define SUPPORTS_PERF_FASTCHANNELS(x) ((x) & BIT(27)) #define SUPPORTS_PERF_FASTCHANNELS(x) ((x) & BIT(27))
#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(26))
__le32 rate_limit_us; __le32 rate_limit_us;
__le32 sustained_freq_khz; __le32 sustained_freq_khz;
__le32 sustained_perf_level; __le32 sustained_perf_level;
u8 name[SCMI_MAX_STR_SIZE]; u8 name[SCMI_SHORT_NAME_MAX_SIZE];
}; };
struct scmi_msg_perf_describe_levels { struct scmi_msg_perf_describe_levels {
...@@ -166,6 +171,7 @@ struct scmi_perf_info { ...@@ -166,6 +171,7 @@ struct scmi_perf_info {
u32 version; u32 version;
int num_domains; int num_domains;
bool power_scale_mw; bool power_scale_mw;
bool power_scale_uw;
u64 stats_addr; u64 stats_addr;
u32 stats_size; u32 stats_size;
struct perf_dom_info *dom_info; struct perf_dom_info *dom_info;
...@@ -196,6 +202,8 @@ static int scmi_perf_attributes_get(const struct scmi_protocol_handle *ph, ...@@ -196,6 +202,8 @@ static int scmi_perf_attributes_get(const struct scmi_protocol_handle *ph,
pi->num_domains = le16_to_cpu(attr->num_domains); pi->num_domains = le16_to_cpu(attr->num_domains);
pi->power_scale_mw = POWER_SCALE_IN_MILLIWATT(flags); pi->power_scale_mw = POWER_SCALE_IN_MILLIWATT(flags);
if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3)
pi->power_scale_uw = POWER_SCALE_IN_MICROWATT(flags);
pi->stats_addr = le32_to_cpu(attr->stats_addr_low) | pi->stats_addr = le32_to_cpu(attr->stats_addr_low) |
(u64)le32_to_cpu(attr->stats_addr_high) << 32; (u64)le32_to_cpu(attr->stats_addr_high) << 32;
pi->stats_size = le32_to_cpu(attr->stats_size); pi->stats_size = le32_to_cpu(attr->stats_size);
...@@ -207,9 +215,11 @@ static int scmi_perf_attributes_get(const struct scmi_protocol_handle *ph, ...@@ -207,9 +215,11 @@ static int scmi_perf_attributes_get(const struct scmi_protocol_handle *ph,
static int static int
scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph, scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
u32 domain, struct perf_dom_info *dom_info) u32 domain, struct perf_dom_info *dom_info,
u32 version)
{ {
int ret; int ret;
u32 flags;
struct scmi_xfer *t; struct scmi_xfer *t;
struct scmi_msg_resp_perf_domain_attributes *attr; struct scmi_msg_resp_perf_domain_attributes *attr;
...@@ -223,7 +233,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph, ...@@ -223,7 +233,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
ret = ph->xops->do_xfer(ph, t); ret = ph->xops->do_xfer(ph, t);
if (!ret) { if (!ret) {
u32 flags = le32_to_cpu(attr->flags); flags = le32_to_cpu(attr->flags);
dom_info->set_limits = SUPPORTS_SET_LIMITS(flags); dom_info->set_limits = SUPPORTS_SET_LIMITS(flags);
dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags); dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags);
...@@ -246,6 +256,16 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph, ...@@ -246,6 +256,16 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
} }
ph->xops->xfer_put(ph, t); ph->xops->xfer_put(ph, t);
/*
* If supported overwrite short name with the extended one;
* on error just carry on and use already provided short name.
*/
if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 &&
SUPPORTS_EXTENDED_NAMES(flags))
ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET, domain,
dom_info->name, SCMI_MAX_STR_SIZE);
return ret; return ret;
} }
...@@ -256,66 +276,87 @@ static int opp_cmp_func(const void *opp1, const void *opp2) ...@@ -256,66 +276,87 @@ static int opp_cmp_func(const void *opp1, const void *opp2)
return t1->perf - t2->perf; return t1->perf - t2->perf;
} }
static int struct scmi_perf_ipriv {
scmi_perf_describe_levels_get(const struct scmi_protocol_handle *ph, u32 domain, u32 domain;
struct perf_dom_info *perf_dom) struct perf_dom_info *perf_dom;
};
static void iter_perf_levels_prepare_message(void *message,
unsigned int desc_index,
const void *priv)
{ {
int ret, cnt; struct scmi_msg_perf_describe_levels *msg = message;
u32 tot_opp_cnt = 0; const struct scmi_perf_ipriv *p = priv;
u16 num_returned, num_remaining;
struct scmi_xfer *t;
struct scmi_opp *opp;
struct scmi_msg_perf_describe_levels *dom_info;
struct scmi_msg_resp_perf_describe_levels *level_info;
ret = ph->xops->xfer_get_init(ph, PERF_DESCRIBE_LEVELS, msg->domain = cpu_to_le32(p->domain);
sizeof(*dom_info), 0, &t); /* Set the number of OPPs to be skipped/already read */
if (ret) msg->level_index = cpu_to_le32(desc_index);
return ret; }
dom_info = t->tx.buf; static int iter_perf_levels_update_state(struct scmi_iterator_state *st,
level_info = t->rx.buf; const void *response, void *priv)
{
const struct scmi_msg_resp_perf_describe_levels *r = response;
do { st->num_returned = le16_to_cpu(r->num_returned);
dom_info->domain = cpu_to_le32(domain); st->num_remaining = le16_to_cpu(r->num_remaining);
/* Set the number of OPPs to be skipped/already read */
dom_info->level_index = cpu_to_le32(tot_opp_cnt);
ret = ph->xops->do_xfer(ph, t); return 0;
if (ret) }
break;
num_returned = le16_to_cpu(level_info->num_returned); static int
num_remaining = le16_to_cpu(level_info->num_remaining); iter_perf_levels_process_response(const struct scmi_protocol_handle *ph,
if (tot_opp_cnt + num_returned > MAX_OPPS) { const void *response,
dev_err(ph->dev, "No. of OPPs exceeded MAX_OPPS"); struct scmi_iterator_state *st, void *priv)
break; {
} struct scmi_opp *opp;
const struct scmi_msg_resp_perf_describe_levels *r = response;
struct scmi_perf_ipriv *p = priv;
opp = &perf_dom->opp[tot_opp_cnt]; opp = &p->perf_dom->opp[st->desc_index + st->loop_idx];
for (cnt = 0; cnt < num_returned; cnt++, opp++) { opp->perf = le32_to_cpu(r->opp[st->loop_idx].perf_val);
opp->perf = le32_to_cpu(level_info->opp[cnt].perf_val); opp->power = le32_to_cpu(r->opp[st->loop_idx].power);
opp->power = le32_to_cpu(level_info->opp[cnt].power); opp->trans_latency_us =
opp->trans_latency_us = le16_to_cpu le16_to_cpu(r->opp[st->loop_idx].transition_latency_us);
(level_info->opp[cnt].transition_latency_us); p->perf_dom->opp_count++;
dev_dbg(ph->dev, "Level %d Power %d Latency %dus\n", dev_dbg(ph->dev, "Level %d Power %d Latency %dus\n",
opp->perf, opp->power, opp->trans_latency_us); opp->perf, opp->power, opp->trans_latency_us);
}
tot_opp_cnt += num_returned; return 0;
}
ph->xops->reset_rx_to_maxsz(ph, t); static int
/* scmi_perf_describe_levels_get(const struct scmi_protocol_handle *ph, u32 domain,
* check for both returned and remaining to avoid infinite struct perf_dom_info *perf_dom)
* loop due to buggy firmware {
*/ int ret;
} while (num_returned && num_remaining); void *iter;
struct scmi_msg_perf_describe_levels *msg;
struct scmi_iterator_ops ops = {
.prepare_message = iter_perf_levels_prepare_message,
.update_state = iter_perf_levels_update_state,
.process_response = iter_perf_levels_process_response,
};
struct scmi_perf_ipriv ppriv = {
.domain = domain,
.perf_dom = perf_dom,
};
iter = ph->hops->iter_response_init(ph, &ops, MAX_OPPS,
PERF_DESCRIBE_LEVELS,
sizeof(*msg), &ppriv);
if (IS_ERR(iter))
return PTR_ERR(iter);
ret = ph->hops->iter_response_run(iter);
if (ret)
return ret;
perf_dom->opp_count = tot_opp_cnt; if (perf_dom->opp_count)
ph->xops->xfer_put(ph, t); sort(perf_dom->opp, perf_dom->opp_count,
sizeof(struct scmi_opp), opp_cmp_func, NULL);
sort(perf_dom->opp, tot_opp_cnt, sizeof(*opp), opp_cmp_func, NULL);
return ret; return ret;
} }
...@@ -382,6 +423,9 @@ static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph, ...@@ -382,6 +423,9 @@ static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph,
struct scmi_perf_info *pi = ph->get_priv(ph); struct scmi_perf_info *pi = ph->get_priv(ph);
struct perf_dom_info *dom = pi->dom_info + domain; struct perf_dom_info *dom = pi->dom_info + domain;
if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3 && !max_perf && !min_perf)
return -EINVAL;
if (dom->fc_info && dom->fc_info->limit_set_addr) { if (dom->fc_info && dom->fc_info->limit_set_addr) {
iowrite32(max_perf, dom->fc_info->limit_set_addr); iowrite32(max_perf, dom->fc_info->limit_set_addr);
iowrite32(min_perf, dom->fc_info->limit_set_addr + 4); iowrite32(min_perf, dom->fc_info->limit_set_addr + 4);
...@@ -873,11 +917,13 @@ static const struct scmi_protocol_events perf_protocol_events = { ...@@ -873,11 +917,13 @@ static const struct scmi_protocol_events perf_protocol_events = {
static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph) static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
{ {
int domain; int domain, ret;
u32 version; u32 version;
struct scmi_perf_info *pinfo; struct scmi_perf_info *pinfo;
ph->xops->version_get(ph, &version); ret = ph->xops->version_get(ph, &version);
if (ret)
return ret;
dev_dbg(ph->dev, "Performance Version %d.%d\n", dev_dbg(ph->dev, "Performance Version %d.%d\n",
PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
...@@ -886,7 +932,9 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph) ...@@ -886,7 +932,9 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
if (!pinfo) if (!pinfo)
return -ENOMEM; return -ENOMEM;
scmi_perf_attributes_get(ph, pinfo); ret = scmi_perf_attributes_get(ph, pinfo);
if (ret)
return ret;
pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains, pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
sizeof(*pinfo->dom_info), GFP_KERNEL); sizeof(*pinfo->dom_info), GFP_KERNEL);
...@@ -896,7 +944,7 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph) ...@@ -896,7 +944,7 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
for (domain = 0; domain < pinfo->num_domains; domain++) { for (domain = 0; domain < pinfo->num_domains; domain++) {
struct perf_dom_info *dom = pinfo->dom_info + domain; struct perf_dom_info *dom = pinfo->dom_info + domain;
scmi_perf_domain_attributes_get(ph, domain, dom); scmi_perf_domain_attributes_get(ph, domain, dom, version);
scmi_perf_describe_levels_get(ph, domain, dom); scmi_perf_describe_levels_get(ph, domain, dom);
if (dom->perf_fastchannels) if (dom->perf_fastchannels)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* /*
* System Control and Management Interface (SCMI) Power Protocol * System Control and Management Interface (SCMI) Power Protocol
* *
* Copyright (C) 2018-2021 ARM Ltd. * Copyright (C) 2018-2022 ARM Ltd.
*/ */
#define pr_fmt(fmt) "SCMI Notifications POWER - " fmt #define pr_fmt(fmt) "SCMI Notifications POWER - " fmt
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/scmi_protocol.h> #include <linux/scmi_protocol.h>
#include "common.h" #include "protocols.h"
#include "notify.h" #include "notify.h"
enum scmi_power_protocol_cmd { enum scmi_power_protocol_cmd {
...@@ -18,6 +18,7 @@ enum scmi_power_protocol_cmd { ...@@ -18,6 +18,7 @@ enum scmi_power_protocol_cmd {
POWER_STATE_SET = 0x4, POWER_STATE_SET = 0x4,
POWER_STATE_GET = 0x5, POWER_STATE_GET = 0x5,
POWER_STATE_NOTIFY = 0x6, POWER_STATE_NOTIFY = 0x6,
POWER_DOMAIN_NAME_GET = 0x8,
}; };
struct scmi_msg_resp_power_attributes { struct scmi_msg_resp_power_attributes {
...@@ -33,7 +34,8 @@ struct scmi_msg_resp_power_domain_attributes { ...@@ -33,7 +34,8 @@ struct scmi_msg_resp_power_domain_attributes {
#define SUPPORTS_STATE_SET_NOTIFY(x) ((x) & BIT(31)) #define SUPPORTS_STATE_SET_NOTIFY(x) ((x) & BIT(31))
#define SUPPORTS_STATE_SET_ASYNC(x) ((x) & BIT(30)) #define SUPPORTS_STATE_SET_ASYNC(x) ((x) & BIT(30))
#define SUPPORTS_STATE_SET_SYNC(x) ((x) & BIT(29)) #define SUPPORTS_STATE_SET_SYNC(x) ((x) & BIT(29))
u8 name[SCMI_MAX_STR_SIZE]; #define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(27))
u8 name[SCMI_SHORT_NAME_MAX_SIZE];
}; };
struct scmi_power_set_state { struct scmi_power_set_state {
...@@ -97,9 +99,11 @@ static int scmi_power_attributes_get(const struct scmi_protocol_handle *ph, ...@@ -97,9 +99,11 @@ static int scmi_power_attributes_get(const struct scmi_protocol_handle *ph,
static int static int
scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph, scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
u32 domain, struct power_dom_info *dom_info) u32 domain, struct power_dom_info *dom_info,
u32 version)
{ {
int ret; int ret;
u32 flags;
struct scmi_xfer *t; struct scmi_xfer *t;
struct scmi_msg_resp_power_domain_attributes *attr; struct scmi_msg_resp_power_domain_attributes *attr;
...@@ -113,15 +117,26 @@ scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph, ...@@ -113,15 +117,26 @@ scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
ret = ph->xops->do_xfer(ph, t); ret = ph->xops->do_xfer(ph, t);
if (!ret) { if (!ret) {
u32 flags = le32_to_cpu(attr->flags); flags = le32_to_cpu(attr->flags);
dom_info->state_set_notify = SUPPORTS_STATE_SET_NOTIFY(flags); dom_info->state_set_notify = SUPPORTS_STATE_SET_NOTIFY(flags);
dom_info->state_set_async = SUPPORTS_STATE_SET_ASYNC(flags); dom_info->state_set_async = SUPPORTS_STATE_SET_ASYNC(flags);
dom_info->state_set_sync = SUPPORTS_STATE_SET_SYNC(flags); dom_info->state_set_sync = SUPPORTS_STATE_SET_SYNC(flags);
strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
} }
ph->xops->xfer_put(ph, t); ph->xops->xfer_put(ph, t);
/*
* If supported overwrite short name with the extended one;
* on error just carry on and use already provided short name.
*/
if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 &&
SUPPORTS_EXTENDED_NAMES(flags)) {
ph->hops->extended_name_get(ph, POWER_DOMAIN_NAME_GET,
domain, dom_info->name,
SCMI_MAX_STR_SIZE);
}
return ret; return ret;
} }
...@@ -174,8 +189,9 @@ static int scmi_power_num_domains_get(const struct scmi_protocol_handle *ph) ...@@ -174,8 +189,9 @@ static int scmi_power_num_domains_get(const struct scmi_protocol_handle *ph)
return pi->num_domains; return pi->num_domains;
} }
static char *scmi_power_name_get(const struct scmi_protocol_handle *ph, static const char *
u32 domain) scmi_power_name_get(const struct scmi_protocol_handle *ph,
u32 domain)
{ {
struct scmi_power_info *pi = ph->get_priv(ph); struct scmi_power_info *pi = ph->get_priv(ph);
struct power_dom_info *dom = pi->dom_info + domain; struct power_dom_info *dom = pi->dom_info + domain;
...@@ -280,11 +296,13 @@ static const struct scmi_protocol_events power_protocol_events = { ...@@ -280,11 +296,13 @@ static const struct scmi_protocol_events power_protocol_events = {
static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph) static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
{ {
int domain; int domain, ret;
u32 version; u32 version;
struct scmi_power_info *pinfo; struct scmi_power_info *pinfo;
ph->xops->version_get(ph, &version); ret = ph->xops->version_get(ph, &version);
if (ret)
return ret;
dev_dbg(ph->dev, "Power Version %d.%d\n", dev_dbg(ph->dev, "Power Version %d.%d\n",
PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
...@@ -293,7 +311,9 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph) ...@@ -293,7 +311,9 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
if (!pinfo) if (!pinfo)
return -ENOMEM; return -ENOMEM;
scmi_power_attributes_get(ph, pinfo); ret = scmi_power_attributes_get(ph, pinfo);
if (ret)
return ret;
pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains, pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
sizeof(*pinfo->dom_info), GFP_KERNEL); sizeof(*pinfo->dom_info), GFP_KERNEL);
...@@ -303,7 +323,7 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph) ...@@ -303,7 +323,7 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
for (domain = 0; domain < pinfo->num_domains; domain++) { for (domain = 0; domain < pinfo->num_domains; domain++) {
struct power_dom_info *dom = pinfo->dom_info + domain; struct power_dom_info *dom = pinfo->dom_info + domain;
scmi_power_domain_attributes_get(ph, domain, dom); scmi_power_domain_attributes_get(ph, domain, dom, version);
} }
pinfo->version = version; pinfo->version = version;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* /*
* System Control and Management Interface (SCMI) System Power Protocol * System Control and Management Interface (SCMI) System Power Protocol
* *
* Copyright (C) 2020-2021 ARM Ltd. * Copyright (C) 2020-2022 ARM Ltd.
*/ */
#define pr_fmt(fmt) "SCMI Notifications SYSTEM - " fmt #define pr_fmt(fmt) "SCMI Notifications SYSTEM - " fmt
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/scmi_protocol.h> #include <linux/scmi_protocol.h>
#include "common.h" #include "protocols.h"
#include "notify.h" #include "notify.h"
#define SCMI_SYSTEM_NUM_SOURCES 1 #define SCMI_SYSTEM_NUM_SOURCES 1
...@@ -113,10 +113,13 @@ static const struct scmi_protocol_events system_protocol_events = { ...@@ -113,10 +113,13 @@ static const struct scmi_protocol_events system_protocol_events = {
static int scmi_system_protocol_init(const struct scmi_protocol_handle *ph) static int scmi_system_protocol_init(const struct scmi_protocol_handle *ph)
{ {
int ret;
u32 version; u32 version;
struct scmi_system_info *pinfo; struct scmi_system_info *pinfo;
ph->xops->version_get(ph, &version); ret = ph->xops->version_get(ph, &version);
if (ret)
return ret;
dev_dbg(ph->dev, "System Power Version %d.%d\n", dev_dbg(ph->dev, "System Power Version %d.%d\n",
PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
......
This diff is collapsed.
...@@ -1379,6 +1379,10 @@ static const struct of_device_id qcom_scm_dt_match[] = { ...@@ -1379,6 +1379,10 @@ static const struct of_device_id qcom_scm_dt_match[] = {
SCM_HAS_IFACE_CLK | SCM_HAS_IFACE_CLK |
SCM_HAS_BUS_CLK) SCM_HAS_BUS_CLK)
}, },
{ .compatible = "qcom,scm-msm8976", .data = (void *)(SCM_HAS_CORE_CLK |
SCM_HAS_IFACE_CLK |
SCM_HAS_BUS_CLK)
},
{ .compatible = "qcom,scm-msm8994" }, { .compatible = "qcom,scm-msm8994" },
{ .compatible = "qcom,scm-msm8996" }, { .compatible = "qcom,scm-msm8996" },
{ .compatible = "qcom,scm" }, { .compatible = "qcom,scm" },
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment