Qualcomm driver updates for v5.19
This converts a wide range of Qualcomm-related DeviceTree bindings to YAML, in order to improve our ability to validate the DeviceTree source. The RPMh power-domain driver gains support for the modem platform SDX65, the compute platform SC8280XP and the automotive platform SA8540p. While LLCC gains support for SC8180X and SC8280XP and gains a MODULE_DEVICE_TABLE() to make it functional as a module. It adds a driver for configuring the SSC bus, providing Linux access to the hardware blocks in the sensor subsystem. The socinfo driver gets confusion related to MSM8974 Pro sorted out and adds new ids for SM8540 and SC7280. The SCM driver gains support for MSM8974. Add missing of_node_put() in smp2p and smsm drivers. Stop using iterator after list_for_each_entry() and define static definitions as such, in the PDR driver. -----BEGIN PGP SIGNATURE----- iQJPBAABCAA5FiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmJ5WsYbHGJqb3JuLmFu ZGVyc3NvbkBsaW5hcm8ub3JnAAoJEAsfOT8Nma3FIo8P+wcc78TQQuG67nqPr2gb QFqVK8U2mz07XW0H1rnGZKsTSrZxFs/YWRBaw+dYC5OZVJHx/uoZM04Njsyy/DFh UaNQgTgsS4+D5+butveh4lBdmk4ja5sreLHw25/azw5VBzeHb9+4HeAd7QMMQ+BO /EvIlykPwsgGIZwabzDHkY8w/xt64CPiajps1qGlFDJedSLsdJ8bKHctvcFD03v3 3utJku3jAc5SZMBQgDttpPwpn7UnHXjCvWxyz8oSFaWDQBROztH0FbiJsZnjMuFI 9RfRqblgb2PkvaG23W7jv68aJf3yQ6siY8ezPPs3/1F6T6tMQaAKEhwrY93ZQiWc gDDx33TvX3YJiRRdC2Gvg1QpL4xMFUERR8o4ooQ0t+b8bG6TkGP44VVg3/n1wrMK Q5xdgDigfrNnVZV1b2flQHc4qke4hNoV23SQ7iFWvtSJO09xklVJhXFGQ6mthEkb PnBFurLyxglKw6afs1/2P8tplS52K0l19lgNJu6vtUzC6fMOg50cX0mmWP8+rkFb njhXlPqCDataECZazyxnn7KORAn3E7zQceJ/LJeV+XZ9i5DJLXup+JkuBCWem4Nd ucEeYtQVRel5FCWZZzkXviPCTlWgTB7ya7pJPCzvZpnNFHeSWSjr9YK6xtWwy9rP CBRXYrz2gJLV/MGkB1piAwkm =/Dqp -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmJ5hB4ACgkQmmx57+YA GNksBxAAj09+d2U1sFSJl3HiHTrXyg3MYoG0dA1QK2CRKucdwMf6KBGpEHTQyL6a Iqan6URrTqEM3WP4suBsZh8vbv1C8u7KGWwDAMqJ18BkigoGHEV1PyvmHYRvPoT2 6DSHAkGbYfDglxXZ4JcxNaQk3+t6rZpe5LcRRgQ7JpoKfzlqKxfSJfPFLzYAvhSV qThiyd3GvfcgkVHL9noh4BrBrnNRj7wMzUwQnhW5aWebN+DqgG8zlzmmZEQx61uR sjMogRZNpGXVAR+4yvPZNoxTGM0plssxlkDQGS4b0XLP1t7ohr22eFPTrWqcsYCi h4fa3nXxUIoTDJXQ7nmU04VXp5xVUtQKKe+zXIvQBT98OkM1f6ep5i7rrEh5DZxJ TWVdRLuIVpHVsVARqq+qpEnwyDeiF3Hgmope3xPYhEIs1WcIOQzWBjHbNTNeiFdy fQMrmAQjirXJBV18ImRSMcAXW+Shc72vnj6fViQcrL5Pzj1HJFMjh/bpPzAhIUYJ w9to8mpNgHUpMwnkfMUqQDV6FANVbYPqancK/z4rEPd8mj6bq1z2GEQq2e9+cAfM imyD30+g7fm7e4mxp53mv/oxqf4NJExE0eIjXAQY53at0TCk+ngsxJd96Wz3aIpB eL9YN5x+y6vXkFC+hsnX2/QdUiVCmfpbrez2QqzoZncSkJ4mjdI= =rjVH -----END PGP SIGNATURE----- Merge tag 'qcom-drivers-for-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/drivers Qualcomm driver updates for v5.19 This converts a wide range of Qualcomm-related DeviceTree bindings to YAML, in order to improve our ability to validate the DeviceTree source. The RPMh power-domain driver gains support for the modem platform SDX65, the compute platform SC8280XP and the automotive platform SA8540p. While LLCC gains support for SC8180X and SC8280XP and gains a MODULE_DEVICE_TABLE() to make it functional as a module. It adds a driver for configuring the SSC bus, providing Linux access to the hardware blocks in the sensor subsystem. The socinfo driver gets confusion related to MSM8974 Pro sorted out and adds new ids for SM8540 and SC7280. The SCM driver gains support for MSM8974. Add missing of_node_put() in smp2p and smsm drivers. Stop using iterator after list_for_each_entry() and define static definitions as such, in the PDR driver. * tag 'qcom-drivers-for-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: (33 commits) soc: qcom: pdr: use static for servreg_* variables soc: qcom: llcc: Add sc8180x and sc8280xp configurations dt-bindings: arm: msm: Add sc8180x and sc8280xp LLCC compatibles soc: qcom: rpmhpd: add sc8280xp & sa8540p rpmh power-domains soc: qcom: rpmhpd: Don't warn about sparse rpmhpd arrays dt-bindings: power: rpmpd: Add sc8280xp RPMh power-domains spi: dt-bindings: qcom,spi-geni-qcom: convert to dtschema soc: qcom: socinfo: Sort out 8974PRO names dt-bindings: soc: qcom,smp2p: convert to dtschema dt-bindings: qcom: geni-se: Update UART schema reference dt-bindings: qcom: geni-se: Update I2C schema reference dt-bindings: soc: qcom,rpmh-rsc: convert to dtschema bus: add driver for initializing the SSC bus on (some) qcom SoCs dt-bindings: bus: add device tree bindings for qcom,ssc-block-bus dt-bindings: qcom: qcom,geni-se: refer to dtschema for SPI dt-bindings: soc: qcom,smd: convert to dtschema firmware: qcom_scm: Add compatible for MSM8976 SoC dt-bindings: firmware: qcom-scm: Document msm8976 bindings soc: qcom: smem: validate fields of shared structures soc: qcom: smem: map only partitions used by local HOST ... Link: https://lore.kernel.org/r/20220509181839.316655-1-bjorn.andersson@linaro.org Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
3f656f2618
|
@ -23,6 +23,8 @@ properties:
|
|||
enum:
|
||||
- qcom,sc7180-llcc
|
||||
- qcom,sc7280-llcc
|
||||
- qcom,sc8180x-llcc
|
||||
- qcom,sc8280xp-llcc
|
||||
- qcom,sdm845-llcc
|
||||
- qcom,sm6350-llcc
|
||||
- qcom,sm8150-llcc
|
||||
|
|
|
@ -39,8 +39,11 @@ description: |
|
|||
msm8994
|
||||
msm8996
|
||||
sa8155p
|
||||
sa8540p
|
||||
sc7180
|
||||
sc7280
|
||||
sc8180x
|
||||
sc8280xp
|
||||
sdm630
|
||||
sdm632
|
||||
sdm660
|
||||
|
@ -225,6 +228,18 @@ properties:
|
|||
- google,senor
|
||||
- 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:
|
||||
- enum:
|
||||
- fairphone,fp3
|
||||
|
@ -258,6 +273,11 @@ properties:
|
|||
- qcom,sa8155p-adp
|
||||
- const: qcom,sa8155p
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sa8295p-adp
|
||||
- const: qcom,sa8540p
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- fairphone,fp4
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
# 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:
|
|||
* "qcom,scm-msm8953"
|
||||
* "qcom,scm-msm8960"
|
||||
* "qcom,scm-msm8974"
|
||||
* "qcom,scm-msm8976"
|
||||
* "qcom,scm-msm8994"
|
||||
* "qcom,scm-msm8996"
|
||||
* "qcom,scm-msm8998"
|
||||
|
@ -37,7 +38,7 @@ Required properties:
|
|||
* core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660" and
|
||||
"qcom,scm-msm8960"
|
||||
* 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 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
|
||||
|
|
|
@ -45,20 +45,20 @@ additionalProperties: false
|
|||
|
||||
examples:
|
||||
# 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";
|
||||
};
|
||||
|
||||
# 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>
|
||||
|
||||
disp_bcm_voter: bcm_voter {
|
||||
disp_bcm_voter: bcm-voter {
|
||||
compatible = "qcom,bcm-voter";
|
||||
qcom,tcs-wait = <QCOM_ICC_TAG_AMC>;
|
||||
};
|
||||
|
|
|
@ -27,12 +27,15 @@ properties:
|
|||
- qcom,msm8998-rpmpd
|
||||
- qcom,qcm2290-rpmpd
|
||||
- qcom,qcs404-rpmpd
|
||||
- qcom,sa8540p-rpmhpd
|
||||
- qcom,sdm660-rpmpd
|
||||
- qcom,sc7180-rpmhpd
|
||||
- qcom,sc7280-rpmhpd
|
||||
- qcom,sc8180x-rpmhpd
|
||||
- qcom,sc8280xp-rpmhpd
|
||||
- qcom,sdm845-rpmhpd
|
||||
- qcom,sdx55-rpmhpd
|
||||
- qcom,sdx65-rpmhpd
|
||||
- qcom,sm6115-rpmpd
|
||||
- qcom,sm6125-rpmpd
|
||||
- qcom,sm6350-rpmhpd
|
||||
|
|
|
@ -12,7 +12,7 @@ description:
|
|||
resides as a subnode of the SMD. As such, the SMD-RPM regulator requires
|
||||
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.
|
||||
|
||||
Please refer to Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
|
||||
|
@ -69,7 +69,8 @@ description:
|
|||
l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22
|
||||
|
||||
maintainers:
|
||||
- Kathiravan T <kathirav@codeaurora.org>
|
||||
- Andy Gross <agross@kernel.org>
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
@ -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
|
||||
"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.
|
||||
|
||||
= EXAMPLE
|
||||
|
|
|
@ -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
|
||||
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
|
||||
The following example describes the resources needed to boot control the WCNSS,
|
||||
|
|
|
@ -64,116 +64,23 @@ required:
|
|||
- ranges
|
||||
|
||||
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]+$":
|
||||
type: object
|
||||
description: GENI serial engine based SPI controller. 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.
|
||||
$ref: /schemas/spi/spi-controller.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"
|
||||
$ref: /schemas/spi/qcom,spi-geni-qcom.yaml#
|
||||
|
||||
"i2c@[0-9a-f]+$":
|
||||
type: object
|
||||
description: GENI serial engine based I2C controller.
|
||||
$ref: /schemas/i2c/i2c-controller.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"
|
||||
$ref: /schemas/i2c/qcom,i2c-geni-qcom.yaml#
|
||||
|
||||
"serial@[0-9a-f]+$":
|
||||
type: object
|
||||
description: GENI Serial Engine based UART Controller.
|
||||
$ref: /schemas/serial.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
|
||||
$ref: /schemas/serial/qcom,serial-geni-qcom.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
QCOM GSBI (General Serial Bus Interface) Driver
|
||||
|
||||
The GSBI controller is modeled as a node with zero or more child nodes, each
|
||||
representing a serial sub-node device that is mux'd as part of the GSBI
|
||||
configuration settings. The mode setting will govern the input/output mode of
|
||||
the 4 GSBI IOs.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should contain "qcom,gsbi-v1.0.0"
|
||||
- cell-index: Should contain the GSBI index
|
||||
- reg: Address range for GSBI registers
|
||||
- clocks: required clock
|
||||
- clock-names: must contain "iface" entry
|
||||
- qcom,mode : indicates MUX value for configuration of the serial interface.
|
||||
Please reference dt-bindings/soc/qcom,gsbi.h for valid mux values.
|
||||
|
||||
Optional properties:
|
||||
- qcom,crci : indicates CRCI MUX value for QUP CRCI ports. Please reference
|
||||
dt-bindings/soc/qcom,gsbi.h for valid CRCI mux values.
|
||||
- syscon-tcsr: indicates phandle of TCSR syscon node. Required if child uses
|
||||
dma.
|
||||
|
||||
Required properties if child node exists:
|
||||
- #address-cells: Must be 1
|
||||
- #size-cells: Must be 1
|
||||
- ranges: Must be present
|
||||
|
||||
Properties for children:
|
||||
|
||||
A GSBI controller node can contain 0 or more child nodes representing serial
|
||||
devices. These serial devices can be a QCOM UART, I2C controller, spi
|
||||
controller, or some combination of aforementioned devices.
|
||||
|
||||
See the following for child node definitions:
|
||||
Documentation/devicetree/bindings/i2c/qcom,i2c-qup.txt
|
||||
Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
|
||||
Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt
|
||||
|
||||
Example for APQ8064:
|
||||
|
||||
#include <dt-bindings/soc/qcom,gsbi.h>
|
||||
|
||||
gsbi4@16300000 {
|
||||
compatible = "qcom,gsbi-v1.0.0";
|
||||
cell-index = <4>;
|
||||
reg = <0x16300000 0x100>;
|
||||
clocks = <&gcc GSBI4_H_CLK>;
|
||||
clock-names = "iface";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
qcom,mode = <GSBI_PROT_I2C_UART>;
|
||||
qcom,crci = <GSBI_CRCI_QUP>;
|
||||
|
||||
syscon-tcsr = <&tcsr>;
|
||||
|
||||
/* child nodes go under here */
|
||||
|
||||
i2c_qup4: i2c@16380000 {
|
||||
compatible = "qcom,i2c-qup-v1.1.1";
|
||||
reg = <0x16380000 0x1000>;
|
||||
interrupts = <0 153 0>;
|
||||
|
||||
clocks = <&gcc GSBI4_QUP_CLK>, <&gcc GSBI4_H_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
|
||||
clock-frequency = <200000>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
};
|
||||
|
||||
uart4: serial@16340000 {
|
||||
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
|
||||
reg = <0x16340000 0x1000>,
|
||||
<0x16300000 0x1000>;
|
||||
interrupts = <0 152 0x0>;
|
||||
clocks = <&gcc GSBI4_UART_CLK>, <&gcc GSBI4_H_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
};
|
||||
};
|
||||
|
||||
tcsr: syscon@1a400000 {
|
||||
compatible = "qcom,apq8064-tcsr", "syscon";
|
||||
reg = <0x1a400000 0x100>;
|
||||
};
|
|
@ -0,0 +1,132 @@
|
|||
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/qcom/qcom,gsbi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm General Serial Bus Interface (GSBI)
|
||||
|
||||
maintainers:
|
||||
- Andy Gross <agross@kernel.org>
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
|
||||
description:
|
||||
The GSBI controller is modeled as a node with zero or more child nodes, each
|
||||
representing a serial sub-node device that is mux'd as part of the GSBI
|
||||
configuration settings. The mode setting will govern the input/output mode
|
||||
of the 4 GSBI IOs.
|
||||
|
||||
A GSBI controller node can contain 0 or more child nodes representing serial
|
||||
devices. These serial devices can be a QCOM UART, I2C controller, spi
|
||||
controller, or some combination of aforementioned devices.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,gsbi-v1.0.0
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
cell-index:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
The GSBI index.
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: iface
|
||||
|
||||
qcom,crci:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
CRCI MUX value for QUP CRCI ports. Please reference
|
||||
include/dt-bindings/soc/qcom,gsbi.h for valid CRCI mux values.
|
||||
|
||||
qcom,mode:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
MUX value for configuration of the serial interface. Please reference
|
||||
include/dt-bindings/soc/qcom,gsbi.h for valid mux values.
|
||||
|
||||
'#size-cells':
|
||||
const: 1
|
||||
|
||||
syscon-tcsr:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle of TCSR syscon node.Required if child uses dma.
|
||||
|
||||
ranges: true
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"spi@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: /schemas/spi/qcom,spi-qup.yaml#
|
||||
|
||||
"i2c@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: /schemas/i2c/qcom,i2c-qup.yaml#
|
||||
|
||||
"serial@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: /schemas/serial/qcom,msm-uartdm.yaml#
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- cell-index
|
||||
- clocks
|
||||
- clock-names
|
||||
- qcom,mode
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8960.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/soc/qcom,gsbi.h>
|
||||
|
||||
gsbi@12440000 {
|
||||
compatible = "qcom,gsbi-v1.0.0";
|
||||
reg = <0x12440000 0x100>;
|
||||
cell-index = <1>;
|
||||
clocks = <&gcc GSBI1_H_CLK>;
|
||||
clock-names = "iface";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
syscon-tcsr = <&tcsr>;
|
||||
qcom,mode = <GSBI_PROT_I2C_UART>;
|
||||
|
||||
serial@12450000 {
|
||||
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
|
||||
reg = <0x12450000 0x100>,
|
||||
<0x12400000 0x03>;
|
||||
interrupts = <0 193 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GSBI1_UART_CLK>, <&gcc GSBI1_H_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
};
|
||||
|
||||
i2c@12460000 {
|
||||
compatible = "qcom,i2c-qup-v1.1.1";
|
||||
reg = <0x12460000 0x1000>;
|
||||
pinctrl-0 = <&i2c1_pins>;
|
||||
pinctrl-1 = <&i2c1_pins_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
interrupts = <0 194 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GSBI1_QUP_CLK>, <&gcc GSBI1_H_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
status = "disabled"; /* UART chosen */
|
||||
};
|
||||
};
|
|
@ -0,0 +1,272 @@
|
|||
# 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: |
|
|||
to vote for state of the system resources, such as clocks, regulators and bus
|
||||
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
|
||||
within the RPM node itself.
|
||||
|
||||
|
@ -25,7 +25,8 @@ description: |
|
|||
rpm_requests.
|
||||
|
||||
maintainers:
|
||||
- Kathiravan T <kathirav@codeaurora.org>
|
||||
- Andy Gross <agross@kernel.org>
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -82,7 +83,7 @@ examples:
|
|||
qcom,ipc = <&apcs 8 0>;
|
||||
qcom,smd-edge = <15>;
|
||||
|
||||
rpm_requests {
|
||||
rpm-requests {
|
||||
compatible = "qcom,rpm-msm8974";
|
||||
qcom,smd-channels = "rpm_requests";
|
||||
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
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";
|
||||
|
||||
...
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,137 @@
|
|||
# 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>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1,110 +0,0 @@
|
|||
Qualcomm Shared Memory Point 2 Point binding
|
||||
|
||||
The Shared Memory Point to Point (SMP2P) protocol facilitates communication of
|
||||
a single 32-bit value between two processors. Each value has a single writer
|
||||
(the local side) and a single reader (the remote side). Values are uniquely
|
||||
identified in the system by the directed edge (local processor ID to remote
|
||||
processor ID) and a string identifier.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: must be one of:
|
||||
"qcom,smp2p"
|
||||
|
||||
- interrupts:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: one entry specifying the smp2p notification interrupt
|
||||
|
||||
- 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 end of the smp2p edge:
|
||||
- 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,smem:
|
||||
Usage: required
|
||||
Value type: <u32 array>
|
||||
Definition: two identifiers of the inbound and outbound smem items used
|
||||
for this edge
|
||||
|
||||
- qcom,local-pid:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: specifies the identifier of the local endpoint of this edge
|
||||
|
||||
- qcom,remote-pid:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: specifies the identifier of the remote endpoint of this edge
|
||||
|
||||
= SUBNODES
|
||||
Each SMP2P pair contain a set of inbound and outbound entries, these are
|
||||
described in subnodes of the smp2p device node. The node names are not
|
||||
important.
|
||||
|
||||
- qcom,entry-name:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: specifies the name of this entry, for inbound entries this
|
||||
will be used to match against the remotely allocated entry
|
||||
and for outbound entries this name is used for allocating
|
||||
entries
|
||||
|
||||
- interrupt-controller:
|
||||
Usage: required for incoming entries
|
||||
Value type: <empty>
|
||||
Definition: marks the entry as inbound; the node should be specified
|
||||
as a two cell interrupt-controller as defined in
|
||||
"../interrupt-controller/interrupts.txt"
|
||||
If not specified this node will denote the outgoing entry
|
||||
|
||||
- #interrupt-cells:
|
||||
Usage: required for incoming entries
|
||||
Value type: <u32>
|
||||
Definition: must be 2 - denoting the bit in the entry and IRQ flags
|
||||
|
||||
- #qcom,smem-state-cells:
|
||||
Usage: required for outgoing entries
|
||||
Value type: <u32>
|
||||
Definition: must be 1 - denoting the bit in the entry
|
||||
|
||||
= EXAMPLE
|
||||
The following example shows the SMP2P setup with the wireless processor,
|
||||
defined from the 8974 apps processor's point-of-view. It encompasses one
|
||||
inbound and one outbound entry:
|
||||
|
||||
wcnss-smp2p {
|
||||
compatible = "qcom,smp2p";
|
||||
qcom,smem = <431>, <451>;
|
||||
|
||||
interrupts = <0 143 1>;
|
||||
|
||||
qcom,ipc = <&apcs 8 18>;
|
||||
|
||||
qcom,local-pid = <0>;
|
||||
qcom,remote-pid = <4>;
|
||||
|
||||
wcnss_smp2p_out: master-kernel {
|
||||
qcom,entry-name = "master-kernel";
|
||||
|
||||
#qcom,smem-state-cells = <1>;
|
||||
};
|
||||
|
||||
wcnss_smp2p_in: slave-kernel {
|
||||
qcom,entry-name = "slave-kernel";
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,145 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/qcom/qcom,smp2p.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Shared Memory Point 2 Point
|
||||
|
||||
maintainers:
|
||||
- Andy Gross <agross@kernel.org>
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
|
||||
description:
|
||||
The Shared Memory Point to Point (SMP2P) protocol facilitates communication
|
||||
of a single 32-bit value between two processors. Each value has a single
|
||||
writer (the local side) and a single reader (the remote side). Values are
|
||||
uniquely identified in the system by the directed edge (local processor ID to
|
||||
remote processor ID) and a string identifier.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,smp2p
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
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 end of the smp2p edge.
|
||||
|
||||
qcom,local-pid:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
The identifier of the local endpoint of this edge.
|
||||
|
||||
qcom,remote-pid:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
The identifier of the remote endpoint of this edge.
|
||||
|
||||
qcom,smem:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
items:
|
||||
maxItems: 2
|
||||
description:
|
||||
Two identifiers of the inbound and outbound smem items used for this edge.
|
||||
|
||||
patternProperties:
|
||||
"^master-kernel|slave-kernel|ipa-ap-to-modem|ipa-modem-to-ap$":
|
||||
type: object
|
||||
description:
|
||||
Each SMP2P pair contain a set of inbound and outbound entries, these are
|
||||
described in subnodes of the smp2p device node. The node names are not
|
||||
important.
|
||||
|
||||
properties:
|
||||
interrupt-controller:
|
||||
description:
|
||||
Marks the entry as inbound; the node should be specified as a two
|
||||
cell interrupt-controller. If not specified this node will denote
|
||||
the outgoing entry.
|
||||
|
||||
'#interrupt-cells':
|
||||
const: 2
|
||||
|
||||
qcom,entry-name:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
The name of this entry, for inbound entries this will be used to
|
||||
match against the remotely allocated entry and for outbound entries
|
||||
this name is used for allocating entries.
|
||||
|
||||
'#qcom,smem-state-cells':
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
const: 1
|
||||
description:
|
||||
Required for outgoing entries.
|
||||
|
||||
required:
|
||||
- qcom,entry-name
|
||||
|
||||
oneOf:
|
||||
- required:
|
||||
- interrupt-controller
|
||||
- '#interrupt-cells'
|
||||
- required:
|
||||
- '#qcom,smem-state-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- interrupts
|
||||
- qcom,local-pid
|
||||
- qcom,remote-pid
|
||||
- qcom,smem
|
||||
|
||||
oneOf:
|
||||
- required:
|
||||
- mboxes
|
||||
- required:
|
||||
- qcom,ipc
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# The following example shows the SMP2P setup with the wireless processor,
|
||||
# defined from the 8974 apps processor's point-of-view. It encompasses one
|
||||
# inbound and one outbound entry.
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
shared-memory {
|
||||
compatible = "qcom,smp2p";
|
||||
qcom,smem = <431>, <451>;
|
||||
interrupts = <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>;
|
||||
qcom,ipc = <&apcs 8 18>;
|
||||
qcom,local-pid = <0>;
|
||||
qcom,remote-pid = <4>;
|
||||
|
||||
wcnss_smp2p_out: master-kernel {
|
||||
qcom,entry-name = "master-kernel";
|
||||
#qcom,smem-state-cells = <1>;
|
||||
};
|
||||
|
||||
wcnss_smp2p_in: slave-kernel {
|
||||
qcom,entry-name = "slave-kernel";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
};
|
|
@ -1,104 +0,0 @@
|
|||
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>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,138 @@
|
|||
# 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>;
|
||||
};
|
||||
};
|
|
@ -1,131 +0,0 @@
|
|||
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";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,137 @@
|
|||
# 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";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1,137 +0,0 @@
|
|||
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>;
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
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>;
|
||||
};
|
|
@ -0,0 +1,116 @@
|
|||
# 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>;
|
||||
};
|
|
@ -152,6 +152,17 @@ config QCOM_EBI2
|
|||
Interface 2, which can be used to connect things like NAND Flash,
|
||||
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
|
||||
bool "Allwinner A64 DE2 Bus Driver"
|
||||
default ARM64
|
||||
|
|
|
@ -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_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_SUNXI_RSB) += sunxi-rsb.o
|
||||
obj-$(CONFIG_OF) += simple-pm-bus.o
|
||||
|
|
|
@ -0,0 +1,389 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright (c) 2021, Michael Srba
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_clock.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
/* AXI Halt Register Offsets */
|
||||
#define AXI_HALTREQ_REG 0x0
|
||||
#define AXI_HALTACK_REG 0x4
|
||||
#define AXI_IDLE_REG 0x8
|
||||
|
||||
#define SSCAON_CONFIG0_CLAMP_EN_OVRD BIT(4)
|
||||
#define SSCAON_CONFIG0_CLAMP_EN_OVRD_VAL BIT(5)
|
||||
|
||||
static const char *const qcom_ssc_block_pd_names[] = {
|
||||
"ssc_cx",
|
||||
"ssc_mx"
|
||||
};
|
||||
|
||||
struct qcom_ssc_block_bus_data {
|
||||
const char *const *pd_names;
|
||||
struct device *pds[ARRAY_SIZE(qcom_ssc_block_pd_names)];
|
||||
char __iomem *reg_mpm_sscaon_config0;
|
||||
char __iomem *reg_mpm_sscaon_config1;
|
||||
struct regmap *halt_map;
|
||||
struct clk *xo_clk;
|
||||
struct clk *aggre2_clk;
|
||||
struct clk *gcc_im_sleep_clk;
|
||||
struct clk *aggre2_north_clk;
|
||||
struct clk *ssc_xo_clk;
|
||||
struct clk *ssc_ahbs_clk;
|
||||
struct reset_control *ssc_bcr;
|
||||
struct reset_control *ssc_reset;
|
||||
u32 ssc_axi_halt;
|
||||
int num_pds;
|
||||
};
|
||||
|
||||
static void reg32_set_bits(char __iomem *reg, u32 value)
|
||||
{
|
||||
u32 tmp = ioread32(reg);
|
||||
|
||||
iowrite32(tmp | value, reg);
|
||||
}
|
||||
|
||||
static void reg32_clear_bits(char __iomem *reg, u32 value)
|
||||
{
|
||||
u32 tmp = ioread32(reg);
|
||||
|
||||
iowrite32(tmp & (~value), reg);
|
||||
}
|
||||
|
||||
static int qcom_ssc_block_bus_init(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct qcom_ssc_block_bus_data *data = dev_get_drvdata(dev);
|
||||
|
||||
ret = clk_prepare_enable(data->xo_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "error enabling xo_clk: %d\n", ret);
|
||||
goto err_xo_clk;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(data->aggre2_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "error enabling aggre2_clk: %d\n", ret);
|
||||
goto err_aggre2_clk;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(data->gcc_im_sleep_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "error enabling gcc_im_sleep_clk: %d\n", ret);
|
||||
goto err_gcc_im_sleep_clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to intervene here because the HW logic driving these signals cannot handle
|
||||
* initialization after power collapse by itself.
|
||||
*/
|
||||
reg32_clear_bits(data->reg_mpm_sscaon_config0,
|
||||
SSCAON_CONFIG0_CLAMP_EN_OVRD | SSCAON_CONFIG0_CLAMP_EN_OVRD_VAL);
|
||||
/* override few_ack/rest_ack */
|
||||
reg32_clear_bits(data->reg_mpm_sscaon_config1, BIT(31));
|
||||
|
||||
ret = clk_prepare_enable(data->aggre2_north_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "error enabling aggre2_north_clk: %d\n", ret);
|
||||
goto err_aggre2_north_clk;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(data->ssc_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "error deasserting ssc_reset: %d\n", ret);
|
||||
goto err_ssc_reset;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(data->ssc_bcr);
|
||||
if (ret) {
|
||||
dev_err(dev, "error deasserting ssc_bcr: %d\n", ret);
|
||||
goto err_ssc_bcr;
|
||||
}
|
||||
|
||||
regmap_write(data->halt_map, data->ssc_axi_halt + AXI_HALTREQ_REG, 0);
|
||||
|
||||
ret = clk_prepare_enable(data->ssc_xo_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "error deasserting ssc_xo_clk: %d\n", ret);
|
||||
goto err_ssc_xo_clk;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(data->ssc_ahbs_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "error deasserting ssc_ahbs_clk: %d\n", ret);
|
||||
goto err_ssc_ahbs_clk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_ssc_ahbs_clk:
|
||||
clk_disable(data->ssc_xo_clk);
|
||||
|
||||
err_ssc_xo_clk:
|
||||
regmap_write(data->halt_map, data->ssc_axi_halt + AXI_HALTREQ_REG, 1);
|
||||
|
||||
reset_control_assert(data->ssc_bcr);
|
||||
|
||||
err_ssc_bcr:
|
||||
reset_control_assert(data->ssc_reset);
|
||||
|
||||
err_ssc_reset:
|
||||
clk_disable(data->aggre2_north_clk);
|
||||
|
||||
err_aggre2_north_clk:
|
||||
reg32_set_bits(data->reg_mpm_sscaon_config0, BIT(4) | BIT(5));
|
||||
reg32_set_bits(data->reg_mpm_sscaon_config1, BIT(31));
|
||||
|
||||
clk_disable(data->gcc_im_sleep_clk);
|
||||
|
||||
err_gcc_im_sleep_clk:
|
||||
clk_disable(data->aggre2_clk);
|
||||
|
||||
err_aggre2_clk:
|
||||
clk_disable(data->xo_clk);
|
||||
|
||||
err_xo_clk:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qcom_ssc_block_bus_deinit(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct qcom_ssc_block_bus_data *data = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable(data->ssc_xo_clk);
|
||||
clk_disable(data->ssc_ahbs_clk);
|
||||
|
||||
ret = reset_control_assert(data->ssc_bcr);
|
||||
if (ret)
|
||||
dev_err(dev, "error asserting ssc_bcr: %d\n", ret);
|
||||
|
||||
regmap_write(data->halt_map, data->ssc_axi_halt + AXI_HALTREQ_REG, 1);
|
||||
|
||||
reg32_set_bits(data->reg_mpm_sscaon_config1, BIT(31));
|
||||
reg32_set_bits(data->reg_mpm_sscaon_config0, BIT(4) | BIT(5));
|
||||
|
||||
ret = reset_control_assert(data->ssc_reset);
|
||||
if (ret)
|
||||
dev_err(dev, "error asserting ssc_reset: %d\n", ret);
|
||||
|
||||
clk_disable(data->gcc_im_sleep_clk);
|
||||
|
||||
clk_disable(data->aggre2_north_clk);
|
||||
|
||||
clk_disable(data->aggre2_clk);
|
||||
clk_disable(data->xo_clk);
|
||||
}
|
||||
|
||||
static int qcom_ssc_block_bus_pds_attach(struct device *dev, struct device **pds,
|
||||
const char *const *pd_names, size_t num_pds)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_pds; i++) {
|
||||
pds[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
|
||||
if (IS_ERR_OR_NULL(pds[i])) {
|
||||
ret = PTR_ERR(pds[i]) ? : -ENODATA;
|
||||
goto unroll_attach;
|
||||
}
|
||||
}
|
||||
|
||||
return num_pds;
|
||||
|
||||
unroll_attach:
|
||||
for (i--; i >= 0; i--)
|
||||
dev_pm_domain_detach(pds[i], false);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
static void qcom_ssc_block_bus_pds_detach(struct device *dev, struct device **pds, size_t num_pds)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_pds; i++)
|
||||
dev_pm_domain_detach(pds[i], false);
|
||||
}
|
||||
|
||||
static int qcom_ssc_block_bus_pds_enable(struct device **pds, size_t num_pds)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_pds; i++) {
|
||||
dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
|
||||
ret = pm_runtime_get_sync(pds[i]);
|
||||
if (ret < 0)
|
||||
goto unroll_pd_votes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
unroll_pd_votes:
|
||||
for (i--; i >= 0; i--) {
|
||||
dev_pm_genpd_set_performance_state(pds[i], 0);
|
||||
pm_runtime_put(pds[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
static void qcom_ssc_block_bus_pds_disable(struct device **pds, size_t num_pds)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_pds; i++) {
|
||||
dev_pm_genpd_set_performance_state(pds[i], 0);
|
||||
pm_runtime_put(pds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int qcom_ssc_block_bus_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_ssc_block_bus_data *data;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct of_phandle_args halt_args;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
data->pd_names = qcom_ssc_block_pd_names;
|
||||
data->num_pds = ARRAY_SIZE(qcom_ssc_block_pd_names);
|
||||
|
||||
/* power domains */
|
||||
ret = qcom_ssc_block_bus_pds_attach(&pdev->dev, data->pds, data->pd_names, data->num_pds);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&pdev->dev, ret, "error when attaching power domains\n");
|
||||
|
||||
ret = qcom_ssc_block_bus_pds_enable(data->pds, data->num_pds);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&pdev->dev, ret, "error when enabling power domains\n");
|
||||
|
||||
/* low level overrides for when the HW logic doesn't "just work" */
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpm_sscaon_config0");
|
||||
data->reg_mpm_sscaon_config0 = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(data->reg_mpm_sscaon_config0))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->reg_mpm_sscaon_config0),
|
||||
"Failed to ioremap mpm_sscaon_config0\n");
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpm_sscaon_config1");
|
||||
data->reg_mpm_sscaon_config1 = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(data->reg_mpm_sscaon_config1))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->reg_mpm_sscaon_config1),
|
||||
"Failed to ioremap mpm_sscaon_config1\n");
|
||||
|
||||
/* resets */
|
||||
data->ssc_bcr = devm_reset_control_get_exclusive(&pdev->dev, "ssc_bcr");
|
||||
if (IS_ERR(data->ssc_bcr))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->ssc_bcr),
|
||||
"Failed to acquire reset: scc_bcr\n");
|
||||
|
||||
data->ssc_reset = devm_reset_control_get_exclusive(&pdev->dev, "ssc_reset");
|
||||
if (IS_ERR(data->ssc_reset))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->ssc_reset),
|
||||
"Failed to acquire reset: ssc_reset:\n");
|
||||
|
||||
/* clocks */
|
||||
data->xo_clk = devm_clk_get(&pdev->dev, "xo");
|
||||
if (IS_ERR(data->xo_clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->xo_clk),
|
||||
"Failed to get clock: xo\n");
|
||||
|
||||
data->aggre2_clk = devm_clk_get(&pdev->dev, "aggre2");
|
||||
if (IS_ERR(data->aggre2_clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->aggre2_clk),
|
||||
"Failed to get clock: aggre2\n");
|
||||
|
||||
data->gcc_im_sleep_clk = devm_clk_get(&pdev->dev, "gcc_im_sleep");
|
||||
if (IS_ERR(data->gcc_im_sleep_clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->gcc_im_sleep_clk),
|
||||
"Failed to get clock: gcc_im_sleep\n");
|
||||
|
||||
data->aggre2_north_clk = devm_clk_get(&pdev->dev, "aggre2_north");
|
||||
if (IS_ERR(data->aggre2_north_clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->aggre2_north_clk),
|
||||
"Failed to get clock: aggre2_north\n");
|
||||
|
||||
data->ssc_xo_clk = devm_clk_get(&pdev->dev, "ssc_xo");
|
||||
if (IS_ERR(data->ssc_xo_clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->ssc_xo_clk),
|
||||
"Failed to get clock: ssc_xo\n");
|
||||
|
||||
data->ssc_ahbs_clk = devm_clk_get(&pdev->dev, "ssc_ahbs");
|
||||
if (IS_ERR(data->ssc_ahbs_clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->ssc_ahbs_clk),
|
||||
"Failed to get clock: ssc_ahbs\n");
|
||||
|
||||
ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, "qcom,halt-regs", 1, 0,
|
||||
&halt_args);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&pdev->dev, ret, "Failed to parse qcom,halt-regs\n");
|
||||
|
||||
data->halt_map = syscon_node_to_regmap(halt_args.np);
|
||||
of_node_put(halt_args.np);
|
||||
if (IS_ERR(data->halt_map))
|
||||
return PTR_ERR(data->halt_map);
|
||||
|
||||
data->ssc_axi_halt = halt_args.args[0];
|
||||
|
||||
qcom_ssc_block_bus_init(&pdev->dev);
|
||||
|
||||
of_platform_populate(np, NULL, NULL, &pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_ssc_block_bus_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_ssc_block_bus_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
qcom_ssc_block_bus_deinit(&pdev->dev);
|
||||
|
||||
iounmap(data->reg_mpm_sscaon_config0);
|
||||
iounmap(data->reg_mpm_sscaon_config1);
|
||||
|
||||
qcom_ssc_block_bus_pds_disable(data->pds, data->num_pds);
|
||||
qcom_ssc_block_bus_pds_detach(&pdev->dev, data->pds, data->num_pds);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_clk_destroy(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_ssc_block_bus_of_match[] = {
|
||||
{ .compatible = "qcom,ssc-block-bus", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_ssc_block_bus_of_match);
|
||||
|
||||
static struct platform_driver qcom_ssc_block_bus_driver = {
|
||||
.probe = qcom_ssc_block_bus_probe,
|
||||
.remove = qcom_ssc_block_bus_remove,
|
||||
.driver = {
|
||||
.name = "qcom-ssc-block-bus",
|
||||
.of_match_table = qcom_ssc_block_bus_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(qcom_ssc_block_bus_driver);
|
||||
|
||||
MODULE_DESCRIPTION("A driver for handling the init sequence needed for accessing the SSC block on (some) qcom SoCs over AHB");
|
||||
MODULE_AUTHOR("Michael Srba <Michael.Srba@seznam.cz>");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -1379,6 +1379,10 @@ static const struct of_device_id qcom_scm_dt_match[] = {
|
|||
SCM_HAS_IFACE_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-msm8996" },
|
||||
{ .compatible = "qcom,scm" },
|
||||
|
|
|
@ -130,6 +130,50 @@ static const struct llcc_slice_config sc7280_data[] = {
|
|||
{ LLCC_MODPE, 29, 64, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
|
||||
};
|
||||
|
||||
static const struct llcc_slice_config sc8180x_data[] = {
|
||||
{ LLCC_CPUSS, 1, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1 },
|
||||
{ LLCC_VIDSC0, 2, 512, 2, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_VIDSC1, 3, 512, 2, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_AUDIO, 6, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_MDMHPGRW, 7, 3072, 1, 1, 0x3ff, 0xc00, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_MDM, 8, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_MODHW, 9, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_CMPT, 10, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_GPU, 12, 5120, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1 },
|
||||
{ LLCC_CMPTDMA, 15, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_DISP, 16, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_VIDFW, 17, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_MDMHPFX, 20, 1024, 2, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_MDMPNG, 21, 1024, 0, 1, 0xc, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_NPU, 23, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_WLHW, 24, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_MODPE, 29, 512, 1, 1, 0xc, 0x0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_APTCM, 30, 512, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0 },
|
||||
{ LLCC_WRCACHE, 31, 128, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static const struct llcc_slice_config sc8280xp_data[] = {
|
||||
{ LLCC_CPUSS, 1, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 },
|
||||
{ LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_AUDIO, 6, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
|
||||
{ LLCC_CMPT, 10, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
|
||||
{ LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_GPU, 12, 4096, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 1 },
|
||||
{ LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_DISP, 16, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_AUDHW, 22, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_DRE, 26, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_CVP, 28, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_WRCACHE, 31, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_CVPFW, 32, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_CPUSS1, 33, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_CPUHWT, 36, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
|
||||
};
|
||||
|
||||
static const struct llcc_slice_config sdm845_data[] = {
|
||||
{ LLCC_CPUSS, 1, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 1 },
|
||||
{ LLCC_VIDSC0, 2, 512, 2, 1, 0x0, 0x0f0, 0, 0, 1, 1, 0 },
|
||||
|
@ -276,6 +320,20 @@ static const struct qcom_llcc_config sc7280_cfg = {
|
|||
.reg_offset = llcc_v1_2_reg_offset,
|
||||
};
|
||||
|
||||
static const struct qcom_llcc_config sc8180x_cfg = {
|
||||
.sct_data = sc8180x_data,
|
||||
.size = ARRAY_SIZE(sc8180x_data),
|
||||
.need_llcc_cfg = true,
|
||||
.reg_offset = llcc_v1_2_reg_offset,
|
||||
};
|
||||
|
||||
static const struct qcom_llcc_config sc8280xp_cfg = {
|
||||
.sct_data = sc8280xp_data,
|
||||
.size = ARRAY_SIZE(sc8280xp_data),
|
||||
.need_llcc_cfg = true,
|
||||
.reg_offset = llcc_v1_2_reg_offset,
|
||||
};
|
||||
|
||||
static const struct qcom_llcc_config sdm845_cfg = {
|
||||
.sct_data = sdm845_data,
|
||||
.size = ARRAY_SIZE(sdm845_data),
|
||||
|
@ -741,6 +799,8 @@ static int qcom_llcc_probe(struct platform_device *pdev)
|
|||
static const struct of_device_id qcom_llcc_of_match[] = {
|
||||
{ .compatible = "qcom,sc7180-llcc", .data = &sc7180_cfg },
|
||||
{ .compatible = "qcom,sc7280-llcc", .data = &sc7280_cfg },
|
||||
{ .compatible = "qcom,sc8180x-llcc", .data = &sc8180x_cfg },
|
||||
{ .compatible = "qcom,sc8280xp-llcc", .data = &sc8280xp_cfg },
|
||||
{ .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfg },
|
||||
{ .compatible = "qcom,sm6350-llcc", .data = &sm6350_cfg },
|
||||
{ .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg },
|
||||
|
@ -749,6 +809,7 @@ static const struct of_device_id qcom_llcc_of_match[] = {
|
|||
{ .compatible = "qcom,sm8450-llcc", .data = &sm8450_cfg },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_llcc_of_match);
|
||||
|
||||
static struct platform_driver qcom_llcc_driver = {
|
||||
.driver = {
|
||||
|
|
|
@ -304,24 +304,23 @@ static void pdr_indication_cb(struct qmi_handle *qmi,
|
|||
notifier_hdl);
|
||||
const struct servreg_state_updated_ind *ind_msg = data;
|
||||
struct pdr_list_node *ind;
|
||||
struct pdr_service *pds;
|
||||
bool found = false;
|
||||
struct pdr_service *pds = NULL, *iter;
|
||||
|
||||
if (!ind_msg || !ind_msg->service_path[0] ||
|
||||
strlen(ind_msg->service_path) > SERVREG_NAME_LENGTH)
|
||||
return;
|
||||
|
||||
mutex_lock(&pdr->list_lock);
|
||||
list_for_each_entry(pds, &pdr->lookups, node) {
|
||||
if (strcmp(pds->service_path, ind_msg->service_path))
|
||||
list_for_each_entry(iter, &pdr->lookups, node) {
|
||||
if (strcmp(iter->service_path, ind_msg->service_path))
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
pds = iter;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&pdr->list_lock);
|
||||
|
||||
if (!found)
|
||||
if (!pds)
|
||||
return;
|
||||
|
||||
pr_info("PDR: Indication received from %s, state: 0x%x, trans-id: %d\n",
|
||||
|
|
|
@ -28,7 +28,7 @@ struct servreg_location_entry {
|
|||
u32 instance;
|
||||
};
|
||||
|
||||
struct qmi_elem_info servreg_location_entry_ei[] = {
|
||||
static struct qmi_elem_info servreg_location_entry_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = SERVREG_NAME_LENGTH + 1,
|
||||
|
@ -74,7 +74,7 @@ struct servreg_get_domain_list_req {
|
|||
u32 domain_offset;
|
||||
};
|
||||
|
||||
struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
|
||||
static struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = SERVREG_NAME_LENGTH + 1,
|
||||
|
@ -116,7 +116,7 @@ struct servreg_get_domain_list_resp {
|
|||
struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
|
||||
};
|
||||
|
||||
struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
|
||||
static struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -199,7 +199,7 @@ struct servreg_register_listener_req {
|
|||
char service_path[SERVREG_NAME_LENGTH + 1];
|
||||
};
|
||||
|
||||
struct qmi_elem_info servreg_register_listener_req_ei[] = {
|
||||
static struct qmi_elem_info servreg_register_listener_req_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -227,7 +227,7 @@ struct servreg_register_listener_resp {
|
|||
enum servreg_service_state curr_state;
|
||||
};
|
||||
|
||||
struct qmi_elem_info servreg_register_listener_resp_ei[] = {
|
||||
static struct qmi_elem_info servreg_register_listener_resp_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -263,7 +263,7 @@ struct servreg_restart_pd_req {
|
|||
char service_path[SERVREG_NAME_LENGTH + 1];
|
||||
};
|
||||
|
||||
struct qmi_elem_info servreg_restart_pd_req_ei[] = {
|
||||
static struct qmi_elem_info servreg_restart_pd_req_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = SERVREG_NAME_LENGTH + 1,
|
||||
|
@ -280,7 +280,7 @@ struct servreg_restart_pd_resp {
|
|||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
|
||||
static struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -300,7 +300,7 @@ struct servreg_state_updated_ind {
|
|||
u16 transaction_id;
|
||||
};
|
||||
|
||||
struct qmi_elem_info servreg_state_updated_ind_ei[] = {
|
||||
static struct qmi_elem_info servreg_state_updated_ind_ei[] = {
|
||||
{
|
||||
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||
.elem_len = 1,
|
||||
|
@ -336,7 +336,7 @@ struct servreg_set_ack_req {
|
|||
u16 transaction_id;
|
||||
};
|
||||
|
||||
struct qmi_elem_info servreg_set_ack_req_ei[] = {
|
||||
static struct qmi_elem_info servreg_set_ack_req_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = SERVREG_NAME_LENGTH + 1,
|
||||
|
@ -362,7 +362,7 @@ struct servreg_set_ack_resp {
|
|||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
struct qmi_elem_info servreg_set_ack_resp_ei[] = {
|
||||
static struct qmi_elem_info servreg_set_ack_resp_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
|
|
@ -180,6 +180,36 @@ static struct rpmhpd mxc_ao = {
|
|||
.res_name = "mxc.lvl",
|
||||
};
|
||||
|
||||
static struct rpmhpd nsp = {
|
||||
.pd = { .name = "nsp", },
|
||||
.res_name = "nsp.lvl",
|
||||
};
|
||||
|
||||
static struct rpmhpd qphy = {
|
||||
.pd = { .name = "qphy", },
|
||||
.res_name = "qphy.lvl",
|
||||
};
|
||||
|
||||
/* SA8540P RPMH powerdomains */
|
||||
static struct rpmhpd *sa8540p_rpmhpds[] = {
|
||||
[SC8280XP_CX] = &cx,
|
||||
[SC8280XP_CX_AO] = &cx_ao,
|
||||
[SC8280XP_EBI] = &ebi,
|
||||
[SC8280XP_GFX] = &gfx,
|
||||
[SC8280XP_LCX] = &lcx,
|
||||
[SC8280XP_LMX] = &lmx,
|
||||
[SC8280XP_MMCX] = &mmcx,
|
||||
[SC8280XP_MMCX_AO] = &mmcx_ao,
|
||||
[SC8280XP_MX] = &mx,
|
||||
[SC8280XP_MX_AO] = &mx_ao,
|
||||
[SC8280XP_NSP] = &nsp,
|
||||
};
|
||||
|
||||
static const struct rpmhpd_desc sa8540p_desc = {
|
||||
.rpmhpds = sa8540p_rpmhpds,
|
||||
.num_pds = ARRAY_SIZE(sa8540p_rpmhpds),
|
||||
};
|
||||
|
||||
/* SDM845 RPMH powerdomains */
|
||||
static struct rpmhpd *sdm845_rpmhpds[] = {
|
||||
[SDM845_CX] = &cx_w_mx_parent,
|
||||
|
@ -210,6 +240,21 @@ static const struct rpmhpd_desc sdx55_desc = {
|
|||
.num_pds = ARRAY_SIZE(sdx55_rpmhpds),
|
||||
};
|
||||
|
||||
/* SDX65 RPMH powerdomains */
|
||||
static struct rpmhpd *sdx65_rpmhpds[] = {
|
||||
[SDX65_CX] = &cx_w_mx_parent,
|
||||
[SDX65_CX_AO] = &cx_ao_w_mx_parent,
|
||||
[SDX65_MSS] = &mss,
|
||||
[SDX65_MX] = &mx,
|
||||
[SDX65_MX_AO] = &mx_ao,
|
||||
[SDX65_MXC] = &mxc,
|
||||
};
|
||||
|
||||
static const struct rpmhpd_desc sdx65_desc = {
|
||||
.rpmhpds = sdx65_rpmhpds,
|
||||
.num_pds = ARRAY_SIZE(sdx65_rpmhpds),
|
||||
};
|
||||
|
||||
/* SM6350 RPMH powerdomains */
|
||||
static struct rpmhpd *sm6350_rpmhpds[] = {
|
||||
[SM6350_CX] = &cx_w_mx_parent,
|
||||
|
@ -363,12 +408,36 @@ static const struct rpmhpd_desc sc8180x_desc = {
|
|||
.num_pds = ARRAY_SIZE(sc8180x_rpmhpds),
|
||||
};
|
||||
|
||||
/* SC8280xp RPMH powerdomains */
|
||||
static struct rpmhpd *sc8280xp_rpmhpds[] = {
|
||||
[SC8280XP_CX] = &cx,
|
||||
[SC8280XP_CX_AO] = &cx_ao,
|
||||
[SC8280XP_EBI] = &ebi,
|
||||
[SC8280XP_GFX] = &gfx,
|
||||
[SC8280XP_LCX] = &lcx,
|
||||
[SC8280XP_LMX] = &lmx,
|
||||
[SC8280XP_MMCX] = &mmcx,
|
||||
[SC8280XP_MMCX_AO] = &mmcx_ao,
|
||||
[SC8280XP_MX] = &mx,
|
||||
[SC8280XP_MX_AO] = &mx_ao,
|
||||
[SC8280XP_NSP] = &nsp,
|
||||
[SC8280XP_QPHY] = &qphy,
|
||||
};
|
||||
|
||||
static const struct rpmhpd_desc sc8280xp_desc = {
|
||||
.rpmhpds = sc8280xp_rpmhpds,
|
||||
.num_pds = ARRAY_SIZE(sc8280xp_rpmhpds),
|
||||
};
|
||||
|
||||
static const struct of_device_id rpmhpd_match_table[] = {
|
||||
{ .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc },
|
||||
{ .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc },
|
||||
{ .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_desc },
|
||||
{ .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc },
|
||||
{ .compatible = "qcom,sc8280xp-rpmhpd", .data = &sc8280xp_desc },
|
||||
{ .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },
|
||||
{ .compatible = "qcom,sdx55-rpmhpd", .data = &sdx55_desc},
|
||||
{ .compatible = "qcom,sdx65-rpmhpd", .data = &sdx65_desc},
|
||||
{ .compatible = "qcom,sm6350-rpmhpd", .data = &sm6350_desc },
|
||||
{ .compatible = "qcom,sm8150-rpmhpd", .data = &sm8150_desc },
|
||||
{ .compatible = "qcom,sm8250-rpmhpd", .data = &sm8250_desc },
|
||||
|
@ -597,10 +666,8 @@ static int rpmhpd_probe(struct platform_device *pdev)
|
|||
data->num_domains = num_pds;
|
||||
|
||||
for (i = 0; i < num_pds; i++) {
|
||||
if (!rpmhpds[i]) {
|
||||
dev_warn(dev, "rpmhpds[%d] is empty\n", i);
|
||||
if (!rpmhpds[i])
|
||||
continue;
|
||||
}
|
||||
|
||||
rpmhpds[i]->dev = dev;
|
||||
rpmhpds[i]->addr = cmd_db_read_addr(rpmhpds[i]->res_name);
|
||||
|
|
|
@ -195,6 +195,20 @@ struct smem_partition_header {
|
|||
__le32 reserved[3];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smem_partition - describes smem partition
|
||||
* @virt_base: starting virtual address of partition
|
||||
* @phys_base: starting physical address of partition
|
||||
* @cacheline: alignment for "cached" entries
|
||||
* @size: size of partition
|
||||
*/
|
||||
struct smem_partition {
|
||||
void __iomem *virt_base;
|
||||
phys_addr_t phys_base;
|
||||
size_t cacheline;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static const u8 SMEM_PART_MAGIC[] = { 0x24, 0x50, 0x52, 0x54 };
|
||||
|
||||
/**
|
||||
|
@ -250,11 +264,9 @@ struct smem_region {
|
|||
* struct qcom_smem - device data for the smem device
|
||||
* @dev: device pointer
|
||||
* @hwlock: reference to a hwspinlock
|
||||
* @global_partition: pointer to global partition when in use
|
||||
* @global_cacheline: cacheline size for global partition
|
||||
* @partitions: list of pointers to partitions affecting the current
|
||||
* processor/host
|
||||
* @cacheline: list of cacheline sizes for each host
|
||||
* @ptable: virtual base of partition table
|
||||
* @global_partition: describes for global partition when in use
|
||||
* @partitions: list of partitions of current processor/host
|
||||
* @item_count: max accepted item number
|
||||
* @socinfo: platform device pointer
|
||||
* @num_regions: number of @regions
|
||||
|
@ -265,12 +277,11 @@ struct qcom_smem {
|
|||
|
||||
struct hwspinlock *hwlock;
|
||||
|
||||
struct smem_partition_header *global_partition;
|
||||
size_t global_cacheline;
|
||||
struct smem_partition_header *partitions[SMEM_HOST_COUNT];
|
||||
size_t cacheline[SMEM_HOST_COUNT];
|
||||
u32 item_count;
|
||||
struct platform_device *socinfo;
|
||||
struct smem_ptable *ptable;
|
||||
struct smem_partition global_partition;
|
||||
struct smem_partition partitions[SMEM_HOST_COUNT];
|
||||
|
||||
unsigned num_regions;
|
||||
struct smem_region regions[];
|
||||
|
@ -348,18 +359,26 @@ static struct qcom_smem *__smem;
|
|||
#define HWSPINLOCK_TIMEOUT 1000
|
||||
|
||||
static int qcom_smem_alloc_private(struct qcom_smem *smem,
|
||||
struct smem_partition_header *phdr,
|
||||
struct smem_partition *part,
|
||||
unsigned item,
|
||||
size_t size)
|
||||
{
|
||||
struct smem_private_entry *hdr, *end;
|
||||
struct smem_partition_header *phdr;
|
||||
size_t alloc_size;
|
||||
void *cached;
|
||||
void *p_end;
|
||||
|
||||
phdr = (struct smem_partition_header __force *)part->virt_base;
|
||||
p_end = (void *)phdr + part->size;
|
||||
|
||||
hdr = phdr_to_first_uncached_entry(phdr);
|
||||
end = phdr_to_last_uncached_entry(phdr);
|
||||
cached = phdr_to_last_cached_entry(phdr);
|
||||
|
||||
if (WARN_ON((void *)end > p_end || cached > p_end))
|
||||
return -EINVAL;
|
||||
|
||||
while (hdr < end) {
|
||||
if (hdr->canary != SMEM_PRIVATE_CANARY)
|
||||
goto bad_canary;
|
||||
|
@ -369,6 +388,9 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
|
|||
hdr = uncached_entry_next(hdr);
|
||||
}
|
||||
|
||||
if (WARN_ON((void *)hdr > p_end))
|
||||
return -EINVAL;
|
||||
|
||||
/* Check that we don't grow into the cached region */
|
||||
alloc_size = sizeof(*hdr) + ALIGN(size, 8);
|
||||
if ((void *)hdr + alloc_size > cached) {
|
||||
|
@ -442,7 +464,7 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
|
|||
*/
|
||||
int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
|
||||
{
|
||||
struct smem_partition_header *phdr;
|
||||
struct smem_partition *part;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
|
@ -464,12 +486,12 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
|
||||
phdr = __smem->partitions[host];
|
||||
ret = qcom_smem_alloc_private(__smem, phdr, item, size);
|
||||
} else if (__smem->global_partition) {
|
||||
phdr = __smem->global_partition;
|
||||
ret = qcom_smem_alloc_private(__smem, phdr, item, size);
|
||||
if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) {
|
||||
part = &__smem->partitions[host];
|
||||
ret = qcom_smem_alloc_private(__smem, part, item, size);
|
||||
} else if (__smem->global_partition.virt_base) {
|
||||
part = &__smem->global_partition;
|
||||
ret = qcom_smem_alloc_private(__smem, part, item, size);
|
||||
} else {
|
||||
ret = qcom_smem_alloc_global(__smem, item, size);
|
||||
}
|
||||
|
@ -487,6 +509,8 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
|
|||
struct smem_header *header;
|
||||
struct smem_region *region;
|
||||
struct smem_global_entry *entry;
|
||||
u64 entry_offset;
|
||||
u32 e_size;
|
||||
u32 aux_base;
|
||||
unsigned i;
|
||||
|
||||
|
@ -501,9 +525,16 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
|
|||
region = &smem->regions[i];
|
||||
|
||||
if ((u32)region->aux_base == aux_base || !aux_base) {
|
||||
e_size = le32_to_cpu(entry->size);
|
||||
entry_offset = le32_to_cpu(entry->offset);
|
||||
|
||||
if (WARN_ON(e_size + entry_offset > region->size))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (size != NULL)
|
||||
*size = le32_to_cpu(entry->size);
|
||||
return region->virt_base + le32_to_cpu(entry->offset);
|
||||
*size = e_size;
|
||||
|
||||
return region->virt_base + entry_offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,12 +542,18 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
|
|||
}
|
||||
|
||||
static void *qcom_smem_get_private(struct qcom_smem *smem,
|
||||
struct smem_partition_header *phdr,
|
||||
size_t cacheline,
|
||||
struct smem_partition *part,
|
||||
unsigned item,
|
||||
size_t *size)
|
||||
{
|
||||
struct smem_private_entry *e, *end;
|
||||
struct smem_partition_header *phdr;
|
||||
void *item_ptr, *p_end;
|
||||
u32 padding_data;
|
||||
u32 e_size;
|
||||
|
||||
phdr = (struct smem_partition_header __force *)part->virt_base;
|
||||
p_end = (void *)phdr + part->size;
|
||||
|
||||
e = phdr_to_first_uncached_entry(phdr);
|
||||
end = phdr_to_last_uncached_entry(phdr);
|
||||
|
@ -526,36 +563,65 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
|
|||
goto invalid_canary;
|
||||
|
||||
if (le16_to_cpu(e->item) == item) {
|
||||
if (size != NULL)
|
||||
*size = le32_to_cpu(e->size) -
|
||||
le16_to_cpu(e->padding_data);
|
||||
if (size != NULL) {
|
||||
e_size = le32_to_cpu(e->size);
|
||||
padding_data = le16_to_cpu(e->padding_data);
|
||||
|
||||
return uncached_entry_to_item(e);
|
||||
if (WARN_ON(e_size > part->size || padding_data > e_size))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
*size = e_size - padding_data;
|
||||
}
|
||||
|
||||
item_ptr = uncached_entry_to_item(e);
|
||||
if (WARN_ON(item_ptr > p_end))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return item_ptr;
|
||||
}
|
||||
|
||||
e = uncached_entry_next(e);
|
||||
}
|
||||
|
||||
if (WARN_ON((void *)e > p_end))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* Item was not found in the uncached list, search the cached list */
|
||||
|
||||
e = phdr_to_first_cached_entry(phdr, cacheline);
|
||||
e = phdr_to_first_cached_entry(phdr, part->cacheline);
|
||||
end = phdr_to_last_cached_entry(phdr);
|
||||
|
||||
if (WARN_ON((void *)e < (void *)phdr || (void *)end > p_end))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
while (e > end) {
|
||||
if (e->canary != SMEM_PRIVATE_CANARY)
|
||||
goto invalid_canary;
|
||||
|
||||
if (le16_to_cpu(e->item) == item) {
|
||||
if (size != NULL)
|
||||
*size = le32_to_cpu(e->size) -
|
||||
le16_to_cpu(e->padding_data);
|
||||
if (size != NULL) {
|
||||
e_size = le32_to_cpu(e->size);
|
||||
padding_data = le16_to_cpu(e->padding_data);
|
||||
|
||||
return cached_entry_to_item(e);
|
||||
if (WARN_ON(e_size > part->size || padding_data > e_size))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
*size = e_size - padding_data;
|
||||
}
|
||||
|
||||
item_ptr = cached_entry_to_item(e);
|
||||
if (WARN_ON(item_ptr < (void *)phdr))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return item_ptr;
|
||||
}
|
||||
|
||||
e = cached_entry_next(e, cacheline);
|
||||
e = cached_entry_next(e, part->cacheline);
|
||||
}
|
||||
|
||||
if (WARN_ON((void *)e < (void *)phdr))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
invalid_canary:
|
||||
|
@ -576,9 +642,8 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
|
|||
*/
|
||||
void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
|
||||
{
|
||||
struct smem_partition_header *phdr;
|
||||
struct smem_partition *part;
|
||||
unsigned long flags;
|
||||
size_t cacheln;
|
||||
int ret;
|
||||
void *ptr = ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
|
@ -594,14 +659,12 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
|
|||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
|
||||
phdr = __smem->partitions[host];
|
||||
cacheln = __smem->cacheline[host];
|
||||
ptr = qcom_smem_get_private(__smem, phdr, cacheln, item, size);
|
||||
} else if (__smem->global_partition) {
|
||||
phdr = __smem->global_partition;
|
||||
cacheln = __smem->global_cacheline;
|
||||
ptr = qcom_smem_get_private(__smem, phdr, cacheln, item, size);
|
||||
if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) {
|
||||
part = &__smem->partitions[host];
|
||||
ptr = qcom_smem_get_private(__smem, part, item, size);
|
||||
} else if (__smem->global_partition.virt_base) {
|
||||
part = &__smem->global_partition;
|
||||
ptr = qcom_smem_get_private(__smem, part, item, size);
|
||||
} else {
|
||||
ptr = qcom_smem_get_global(__smem, item, size);
|
||||
}
|
||||
|
@ -622,6 +685,7 @@ EXPORT_SYMBOL(qcom_smem_get);
|
|||
*/
|
||||
int qcom_smem_get_free_space(unsigned host)
|
||||
{
|
||||
struct smem_partition *part;
|
||||
struct smem_partition_header *phdr;
|
||||
struct smem_header *header;
|
||||
unsigned ret;
|
||||
|
@ -629,23 +693,39 @@ int qcom_smem_get_free_space(unsigned host)
|
|||
if (!__smem)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
|
||||
phdr = __smem->partitions[host];
|
||||
if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) {
|
||||
part = &__smem->partitions[host];
|
||||
phdr = part->virt_base;
|
||||
ret = le32_to_cpu(phdr->offset_free_cached) -
|
||||
le32_to_cpu(phdr->offset_free_uncached);
|
||||
} else if (__smem->global_partition) {
|
||||
phdr = __smem->global_partition;
|
||||
|
||||
if (ret > le32_to_cpu(part->size))
|
||||
return -EINVAL;
|
||||
} else if (__smem->global_partition.virt_base) {
|
||||
part = &__smem->global_partition;
|
||||
phdr = part->virt_base;
|
||||
ret = le32_to_cpu(phdr->offset_free_cached) -
|
||||
le32_to_cpu(phdr->offset_free_uncached);
|
||||
|
||||
if (ret > le32_to_cpu(part->size))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
header = __smem->regions[0].virt_base;
|
||||
ret = le32_to_cpu(header->available);
|
||||
|
||||
if (ret > __smem->regions[0].size)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_smem_get_free_space);
|
||||
|
||||
static bool addr_in_range(void __iomem *base, size_t size, void *addr)
|
||||
{
|
||||
return base && (addr >= base && addr < base + size);
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_smem_virt_to_phys() - return the physical address associated
|
||||
* with an smem item pointer (previously returned by qcom_smem_get()
|
||||
|
@ -655,17 +735,36 @@ EXPORT_SYMBOL(qcom_smem_get_free_space);
|
|||
*/
|
||||
phys_addr_t qcom_smem_virt_to_phys(void *p)
|
||||
{
|
||||
unsigned i;
|
||||
struct smem_partition *part;
|
||||
struct smem_region *area;
|
||||
u64 offset;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < SMEM_HOST_COUNT; i++) {
|
||||
part = &__smem->partitions[i];
|
||||
|
||||
if (addr_in_range(part->virt_base, part->size, p)) {
|
||||
offset = p - part->virt_base;
|
||||
|
||||
return (phys_addr_t)part->phys_base + offset;
|
||||
}
|
||||
}
|
||||
|
||||
part = &__smem->global_partition;
|
||||
|
||||
if (addr_in_range(part->virt_base, part->size, p)) {
|
||||
offset = p - part->virt_base;
|
||||
|
||||
return (phys_addr_t)part->phys_base + offset;
|
||||
}
|
||||
|
||||
for (i = 0; i < __smem->num_regions; i++) {
|
||||
struct smem_region *region = &__smem->regions[i];
|
||||
area = &__smem->regions[i];
|
||||
|
||||
if (p < region->virt_base)
|
||||
continue;
|
||||
if (p < region->virt_base + region->size) {
|
||||
u64 offset = p - region->virt_base;
|
||||
if (addr_in_range(area->virt_base, area->size, p)) {
|
||||
offset = p - area->virt_base;
|
||||
|
||||
return region->aux_base + offset;
|
||||
return (phys_addr_t)area->aux_base + offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -689,7 +788,7 @@ static struct smem_ptable *qcom_smem_get_ptable(struct qcom_smem *smem)
|
|||
struct smem_ptable *ptable;
|
||||
u32 version;
|
||||
|
||||
ptable = smem->regions[0].virt_base + smem->regions[0].size - SZ_4K;
|
||||
ptable = smem->ptable;
|
||||
if (memcmp(ptable->magic, SMEM_PTABLE_MAGIC, sizeof(ptable->magic)))
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
|
@ -728,9 +827,14 @@ qcom_smem_partition_header(struct qcom_smem *smem,
|
|||
struct smem_ptable_entry *entry, u16 host0, u16 host1)
|
||||
{
|
||||
struct smem_partition_header *header;
|
||||
u32 phys_addr;
|
||||
u32 size;
|
||||
|
||||
header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
|
||||
phys_addr = smem->regions[0].aux_base + le32_to_cpu(entry->offset);
|
||||
header = devm_ioremap_wc(smem->dev, phys_addr, le32_to_cpu(entry->size));
|
||||
|
||||
if (!header)
|
||||
return NULL;
|
||||
|
||||
if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) {
|
||||
dev_err(smem->dev, "bad partition magic %4ph\n", header->magic);
|
||||
|
@ -772,7 +876,7 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
|
|||
bool found = false;
|
||||
int i;
|
||||
|
||||
if (smem->global_partition) {
|
||||
if (smem->global_partition.virt_base) {
|
||||
dev_err(smem->dev, "Already found the global partition\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -807,8 +911,11 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
|
|||
if (!header)
|
||||
return -EINVAL;
|
||||
|
||||
smem->global_partition = header;
|
||||
smem->global_cacheline = le32_to_cpu(entry->cacheline);
|
||||
smem->global_partition.virt_base = (void __iomem *)header;
|
||||
smem->global_partition.phys_base = smem->regions[0].aux_base +
|
||||
le32_to_cpu(entry->offset);
|
||||
smem->global_partition.size = le32_to_cpu(entry->size);
|
||||
smem->global_partition.cacheline = le32_to_cpu(entry->cacheline);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -848,7 +955,7 @@ qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (smem->partitions[remote_host]) {
|
||||
if (smem->partitions[remote_host].virt_base) {
|
||||
dev_err(smem->dev, "duplicate host %hu\n", remote_host);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -857,13 +964,47 @@ qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host)
|
|||
if (!header)
|
||||
return -EINVAL;
|
||||
|
||||
smem->partitions[remote_host] = header;
|
||||
smem->cacheline[remote_host] = le32_to_cpu(entry->cacheline);
|
||||
smem->partitions[remote_host].virt_base = (void __iomem *)header;
|
||||
smem->partitions[remote_host].phys_base = smem->regions[0].aux_base +
|
||||
le32_to_cpu(entry->offset);
|
||||
smem->partitions[remote_host].size = le32_to_cpu(entry->size);
|
||||
smem->partitions[remote_host].cacheline = le32_to_cpu(entry->cacheline);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_smem_map_toc(struct qcom_smem *smem, struct smem_region *region)
|
||||
{
|
||||
u32 ptable_start;
|
||||
|
||||
/* map starting 4K for smem header */
|
||||
region->virt_base = devm_ioremap_wc(smem->dev, region->aux_base, SZ_4K);
|
||||
ptable_start = region->aux_base + region->size - SZ_4K;
|
||||
/* map last 4k for toc */
|
||||
smem->ptable = devm_ioremap_wc(smem->dev, ptable_start, SZ_4K);
|
||||
|
||||
if (!region->virt_base || !smem->ptable)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_smem_map_global(struct qcom_smem *smem, u32 size)
|
||||
{
|
||||
u32 phys_addr;
|
||||
|
||||
phys_addr = smem->regions[0].aux_base;
|
||||
|
||||
smem->regions[0].size = size;
|
||||
smem->regions[0].virt_base = devm_ioremap_wc(smem->dev, phys_addr, size);
|
||||
|
||||
if (!smem->regions[0].virt_base)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_smem_resolve_mem(struct qcom_smem *smem, const char *name,
|
||||
struct smem_region *region)
|
||||
{
|
||||
|
@ -894,10 +1035,12 @@ static int qcom_smem_probe(struct platform_device *pdev)
|
|||
struct smem_header *header;
|
||||
struct reserved_mem *rmem;
|
||||
struct qcom_smem *smem;
|
||||
unsigned long flags;
|
||||
size_t array_size;
|
||||
int num_regions;
|
||||
int hwlock_id;
|
||||
u32 version;
|
||||
u32 size;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
|
@ -933,7 +1076,12 @@ static int qcom_smem_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_regions; i++) {
|
||||
|
||||
ret = qcom_smem_map_toc(smem, &smem->regions[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 1; i < num_regions; i++) {
|
||||
smem->regions[i].virt_base = devm_ioremap_wc(&pdev->dev,
|
||||
smem->regions[i].aux_base,
|
||||
smem->regions[i].size);
|
||||
|
@ -950,7 +1098,30 @@ static int qcom_smem_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
|
||||
if (hwlock_id < 0) {
|
||||
if (hwlock_id != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "failed to retrieve hwlock\n");
|
||||
return hwlock_id;
|
||||
}
|
||||
|
||||
smem->hwlock = hwspin_lock_request_specific(hwlock_id);
|
||||
if (!smem->hwlock)
|
||||
return -ENXIO;
|
||||
|
||||
ret = hwspin_lock_timeout_irqsave(smem->hwlock, HWSPINLOCK_TIMEOUT, &flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
size = readl_relaxed(&header->available) + readl_relaxed(&header->free_offset);
|
||||
hwspin_unlock_irqrestore(smem->hwlock, &flags);
|
||||
|
||||
version = qcom_smem_get_sbl_version(smem);
|
||||
/*
|
||||
* smem header mapping is required only in heap version scheme, so unmap
|
||||
* it here. It will be remapped in qcom_smem_map_global() when whole
|
||||
* partition is mapped again.
|
||||
*/
|
||||
devm_iounmap(smem->dev, smem->regions[0].virt_base);
|
||||
switch (version >> 16) {
|
||||
case SMEM_GLOBAL_PART_VERSION:
|
||||
ret = qcom_smem_set_global_partition(smem);
|
||||
|
@ -959,6 +1130,7 @@ static int qcom_smem_probe(struct platform_device *pdev)
|
|||
smem->item_count = qcom_smem_get_item_count(smem);
|
||||
break;
|
||||
case SMEM_GLOBAL_HEAP_VERSION:
|
||||
qcom_smem_map_global(smem, size);
|
||||
smem->item_count = SMEM_ITEM_COUNT;
|
||||
break;
|
||||
default:
|
||||
|
@ -971,17 +1143,6 @@ static int qcom_smem_probe(struct platform_device *pdev)
|
|||
if (ret < 0 && ret != -ENOENT)
|
||||
return ret;
|
||||
|
||||
hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
|
||||
if (hwlock_id < 0) {
|
||||
if (hwlock_id != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "failed to retrieve hwlock\n");
|
||||
return hwlock_id;
|
||||
}
|
||||
|
||||
smem->hwlock = hwspin_lock_request_specific(hwlock_id);
|
||||
if (!smem->hwlock)
|
||||
return -ENXIO;
|
||||
|
||||
__smem = smem;
|
||||
|
||||
smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo",
|
||||
|
|
|
@ -493,6 +493,7 @@ static int smp2p_parse_ipc(struct qcom_smp2p *smp2p)
|
|||
}
|
||||
|
||||
smp2p->ipc_regmap = syscon_node_to_regmap(syscon);
|
||||
of_node_put(syscon);
|
||||
if (IS_ERR(smp2p->ipc_regmap))
|
||||
return PTR_ERR(smp2p->ipc_regmap);
|
||||
|
||||
|
|
|
@ -374,6 +374,7 @@ static int smsm_parse_ipc(struct qcom_smsm *smsm, unsigned host_id)
|
|||
return 0;
|
||||
|
||||
host->ipc_regmap = syscon_node_to_regmap(syscon);
|
||||
of_node_put(syscon);
|
||||
if (IS_ERR(host->ipc_regmap))
|
||||
return PTR_ERR(host->ipc_regmap);
|
||||
|
||||
|
|
|
@ -236,24 +236,24 @@ static const struct soc_id soc_id[] = {
|
|||
{ 184, "APQ8074" },
|
||||
{ 185, "MSM8274" },
|
||||
{ 186, "MSM8674" },
|
||||
{ 194, "MSM8974PRO" },
|
||||
{ 194, "MSM8974PRO-AC" },
|
||||
{ 198, "MSM8126" },
|
||||
{ 199, "APQ8026" },
|
||||
{ 200, "MSM8926" },
|
||||
{ 205, "MSM8326" },
|
||||
{ 206, "MSM8916" },
|
||||
{ 207, "MSM8994" },
|
||||
{ 208, "APQ8074-AA" },
|
||||
{ 209, "APQ8074-AB" },
|
||||
{ 210, "APQ8074PRO" },
|
||||
{ 211, "MSM8274-AA" },
|
||||
{ 212, "MSM8274-AB" },
|
||||
{ 213, "MSM8274PRO" },
|
||||
{ 214, "MSM8674-AA" },
|
||||
{ 215, "MSM8674-AB" },
|
||||
{ 216, "MSM8674PRO" },
|
||||
{ 217, "MSM8974-AA" },
|
||||
{ 218, "MSM8974-AB" },
|
||||
{ 208, "APQ8074PRO-AA" },
|
||||
{ 209, "APQ8074PRO-AB" },
|
||||
{ 210, "APQ8074PRO-AC" },
|
||||
{ 211, "MSM8274PRO-AA" },
|
||||
{ 212, "MSM8274PRO-AB" },
|
||||
{ 213, "MSM8274PRO-AC" },
|
||||
{ 214, "MSM8674PRO-AA" },
|
||||
{ 215, "MSM8674PRO-AB" },
|
||||
{ 216, "MSM8674PRO-AC" },
|
||||
{ 217, "MSM8974PRO-AA" },
|
||||
{ 218, "MSM8974PRO-AB" },
|
||||
{ 219, "APQ8028" },
|
||||
{ 220, "MSM8128" },
|
||||
{ 221, "MSM8228" },
|
||||
|
@ -330,6 +330,8 @@ static const struct soc_id soc_id[] = {
|
|||
{ 459, "SM7225" },
|
||||
{ 460, "SA8540P" },
|
||||
{ 480, "SM8450" },
|
||||
{ 482, "SM8450" },
|
||||
{ 487, "SC7280" },
|
||||
};
|
||||
|
||||
static const char *socinfo_machine(struct device *dev, unsigned int id)
|
||||
|
|
|
@ -20,6 +20,14 @@
|
|||
#define SDX55_MX 1
|
||||
#define SDX55_CX 2
|
||||
|
||||
/* SDX65 Power Domain Indexes */
|
||||
#define SDX65_MSS 0
|
||||
#define SDX65_MX 1
|
||||
#define SDX65_MX_AO 2
|
||||
#define SDX65_CX 3
|
||||
#define SDX65_CX_AO 4
|
||||
#define SDX65_MXC 5
|
||||
|
||||
/* SM6350 Power Domain Indexes */
|
||||
#define SM6350_CX 0
|
||||
#define SM6350_GFX 1
|
||||
|
@ -117,6 +125,24 @@
|
|||
#define SC8180X_MX 9
|
||||
#define SC8180X_MX_AO 10
|
||||
|
||||
/* SC8280XP Power Domain Indexes */
|
||||
#define SC8280XP_CX 0
|
||||
#define SC8280XP_CX_AO 1
|
||||
#define SC8280XP_DDR 2
|
||||
#define SC8280XP_EBI 3
|
||||
#define SC8280XP_GFX 4
|
||||
#define SC8280XP_LCX 5
|
||||
#define SC8280XP_LMX 6
|
||||
#define SC8280XP_MMCX 7
|
||||
#define SC8280XP_MMCX_AO 8
|
||||
#define SC8280XP_MSS 9
|
||||
#define SC8280XP_MX 10
|
||||
#define SC8280XP_MXC 12
|
||||
#define SC8280XP_MX_AO 11
|
||||
#define SC8280XP_NSP 13
|
||||
#define SC8280XP_QPHY 14
|
||||
#define SC8280XP_XO 15
|
||||
|
||||
/* SDM845 Power Domain performance levels */
|
||||
#define RPMH_REGULATOR_LEVEL_RETENTION 16
|
||||
#define RPMH_REGULATOR_LEVEL_MIN_SVS 48
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#define LLCC_AUDHW 22
|
||||
#define LLCC_NPU 23
|
||||
#define LLCC_WLHW 24
|
||||
#define LLCC_PIMEM 25
|
||||
#define LLCC_DRE 26
|
||||
#define LLCC_CVP 28
|
||||
#define LLCC_MODPE 29
|
||||
#define LLCC_APTCM 30
|
||||
|
|
Loading…
Reference in New Issue