Compare commits
174 commits
master
...
stable/5.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f856d506e7 | ||
|
|
1af0e7a953 | ||
|
|
8515121db0 | ||
|
|
597ef9ed54 | ||
|
|
51ec6fb5ed | ||
|
|
e6d10ac2e6 | ||
|
|
efeefaacc5 | ||
|
|
6e8e56b7f4 | ||
|
|
325024f13a | ||
|
|
ca13592c44 | ||
|
|
49690877c7 | ||
|
|
dd8e0ddd98 | ||
|
|
ff77547634 | ||
|
|
3cba1a0030 | ||
|
|
79802dd6ab | ||
|
|
2ea653f154 | ||
|
|
bb5b766d48 | ||
|
|
8cdfda40c6 | ||
|
|
72a48da166 | ||
|
|
522ad4866d | ||
|
|
7a5876b63a | ||
|
|
2620cc8d7a | ||
|
|
c67fc45041 | ||
|
|
8bb2d2b6b7 | ||
|
|
18b60e1e08 | ||
|
|
9f0b72f7d8 | ||
|
|
28a64dcdc1 | ||
|
|
9cb6c34719 | ||
|
|
4c36b04925 | ||
|
|
b800af63dd | ||
|
|
af1277a488 | ||
|
|
1628ae181f | ||
|
|
51418997ad | ||
|
|
193be10420 | ||
|
|
bdfeaa075c | ||
|
|
88d6e96419 | ||
|
|
8f429d8978 | ||
|
|
34121e6055 | ||
|
|
927111b0f5 | ||
|
|
6c3db94d2e | ||
|
|
ec6f66ad89 | ||
|
|
2eea5fe9f8 | ||
|
|
87e5901e2b | ||
|
|
fff3a97cdc | ||
|
|
f1b6077a13 | ||
|
|
d962bb5d78 | ||
|
|
8a66c540f2 | ||
|
|
0c7a8ce70a | ||
|
|
f780d839de | ||
|
|
6f6f039c9e | ||
|
|
e20414070b | ||
|
|
769df9c28b | ||
|
|
61491d1901 | ||
|
|
c53aa1d6d4 | ||
|
|
e3fa3e3ed1 | ||
|
|
0b49adafb0 | ||
|
|
5b33bb9362 | ||
|
|
0bc0889e02 | ||
|
|
ed0bb1af2a | ||
|
|
ed8cdf8803 | ||
|
|
306b319190 | ||
|
|
b908c27f65 | ||
|
|
c5da981db7 | ||
|
|
be48c36833 | ||
|
|
e7f46aaebe | ||
|
|
ddb5a4ec04 | ||
|
|
2a698c43a6 | ||
|
|
27d473117b | ||
|
|
a8e39acb81 | ||
|
|
41bea9ea58 | ||
|
|
03d8638281 | ||
|
|
ec880e7f42 | ||
|
|
d445d3a0d8 | ||
|
|
b193513789 | ||
|
|
3c59b21e13 | ||
|
|
62de45c5f8 | ||
|
|
18408450a4 | ||
|
|
d98aa89de2 | ||
|
|
67c05fd705 | ||
|
|
d54d3d6a7a | ||
|
|
29fb6d76d3 | ||
|
|
288e9b5162 | ||
|
|
b4524221dc | ||
|
|
4b7ee7c6c1 | ||
|
|
c9f802b140 | ||
|
|
a7333bdc35 | ||
|
|
d9db298685 | ||
|
|
bbe5a5b1a1 | ||
|
|
96e86abbb4 | ||
|
|
c1fcb53c21 | ||
|
|
d4148f80f9 | ||
|
|
728bffed0b | ||
|
|
f7acfd9853 | ||
|
|
1d6a05921e | ||
|
|
d330c5bc8c | ||
|
|
666c6e9851 | ||
|
|
9b043633d2 | ||
|
|
4d6bf1ecf5 | ||
|
|
ddb7db6e7e | ||
|
|
3e04d1024d | ||
|
|
e372ac89aa | ||
|
|
4c86b1ef95 | ||
|
|
6fc76bf252 | ||
|
|
bd9e161cf0 | ||
|
|
df70e2d821 | ||
|
|
ebdfc5be87 | ||
|
|
5ef8905819 | ||
|
|
174914a544 | ||
|
|
71dfa2b623 | ||
|
|
0023cba0a2 | ||
|
|
dffdf15457 | ||
|
|
3b78949610 | ||
|
|
b232c0dfd0 | ||
|
|
f660d49d1a | ||
|
|
62c31274b5 | ||
|
|
40e639041d | ||
|
|
0485ef79b6 | ||
|
|
6ebf835ad5 | ||
|
|
0c034c5ea7 | ||
|
|
8fa5063793 | ||
|
|
bc5d106fe5 | ||
|
|
2dba96237a | ||
|
|
ed38aa4ac2 | ||
|
|
ed5f3ba9c0 | ||
|
|
24aa91f32b | ||
|
|
75b4a47477 | ||
|
|
1d5f57a7c3 | ||
|
|
262f1c68a4 | ||
|
|
562c27df43 | ||
|
|
c1c2f1d842 | ||
|
|
8f64838ebb | ||
|
|
da4fc9a401 | ||
|
|
59db887d13 | ||
|
|
d5ac598705 | ||
|
|
dc9363ece2 | ||
|
|
8f8a8f3ab3 | ||
|
|
b7509a4e81 | ||
|
|
bed07e7ecc | ||
|
|
ba84f9a483 | ||
|
|
6e7baf8414 | ||
|
|
46bb87d406 | ||
|
|
a1ad747fc1 | ||
|
|
cfda62aaf8 | ||
|
|
bff94c57bd | ||
|
|
abc9ad36df | ||
|
|
ae0e10382c | ||
|
|
5f32afca84 | ||
|
|
72deda4b68 | ||
|
|
ef4d3dcd66 | ||
|
|
608d06085d | ||
|
|
0d73a21c48 | ||
|
|
9024419ced | ||
|
|
4006144228 | ||
|
|
afdc3f4b81 | ||
|
|
dd03640529 | ||
|
|
8e8f66882b | ||
|
|
7a378016d6 | ||
|
|
efeffb3029 | ||
|
|
7188dd4d75 | ||
|
|
e7e04e2524 | ||
|
|
5ed8f8e3c4 | ||
|
|
e9d0553225 | ||
|
|
dd2f8c684d | ||
|
|
1bbf82d9f9 | ||
|
|
81b0e6aa90 | ||
|
|
5d2f019b7a | ||
|
|
e3a8cf32be | ||
|
|
d5ec0858e7 | ||
|
|
1e6c2681b5 | ||
|
|
e74a069c6a | ||
|
|
39504539ca | ||
|
|
ef1a6fe356 | ||
|
|
816a512233 | ||
|
|
0d15c66771 |
157 changed files with 19065 additions and 1148 deletions
|
|
@ -313,6 +313,12 @@ properties:
|
|||
|
||||
* arm/msm/qcom,kpss-acc.txt
|
||||
|
||||
qcom,freq-domain:
|
||||
$ref: '/schemas/types.yaml#/definitions/phandle-array'
|
||||
description: |
|
||||
CPUs supporting freq-domain must set their "qcom,freq-domain" property
|
||||
with phandle to a cpufreq_hw node followed by the Domain ID(0/1).
|
||||
|
||||
rockchip,pmu:
|
||||
$ref: '/schemas/types.yaml#/definitions/phandle'
|
||||
description: |
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ description: |
|
|||
sa8155p
|
||||
sc7180
|
||||
sc7280
|
||||
msm8998
|
||||
sdm630
|
||||
sdm660
|
||||
sdm845
|
||||
|
|
@ -210,6 +211,16 @@ properties:
|
|||
- google,senor
|
||||
- const: qcom,sc7280
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- asus,novago-tp370ql
|
||||
- hp,envy-x2
|
||||
- lenovo,miix-630
|
||||
- oneplus,cheeseburger
|
||||
- oneplus,dumpling
|
||||
- qcom,msm8998-mtp
|
||||
- const: qcom,msm8998
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- xiaomi,lavender
|
||||
|
|
|
|||
|
|
@ -1,172 +0,0 @@
|
|||
Qualcomm Technologies, Inc. CPUFREQ Bindings
|
||||
|
||||
CPUFREQ HW is a hardware engine used by some Qualcomm Technologies, Inc. (QTI)
|
||||
SoCs to manage frequency in hardware. It is capable of controlling frequency
|
||||
for multiple clusters.
|
||||
|
||||
Properties:
|
||||
- compatible
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: must be "qcom,cpufreq-hw" or "qcom,cpufreq-epss".
|
||||
|
||||
- clocks
|
||||
Usage: required
|
||||
Value type: <phandle> From common clock binding.
|
||||
Definition: clock handle for XO clock and GPLL0 clock.
|
||||
|
||||
- clock-names
|
||||
Usage: required
|
||||
Value type: <string> From common clock binding.
|
||||
Definition: must be "xo", "alternate".
|
||||
|
||||
- reg
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: Addresses and sizes for the memory of the HW bases in
|
||||
each frequency domain.
|
||||
- reg-names
|
||||
Usage: Optional
|
||||
Value type: <string>
|
||||
Definition: Frequency domain name i.e.
|
||||
"freq-domain0", "freq-domain1".
|
||||
|
||||
- #freq-domain-cells:
|
||||
Usage: required.
|
||||
Definition: Number of cells in a freqency domain specifier.
|
||||
|
||||
* Property qcom,freq-domain
|
||||
Devices supporting freq-domain must set their "qcom,freq-domain" property with
|
||||
phandle to a cpufreq_hw followed by the Domain ID(0/1) in the CPU DT node.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
Example 1: Dual-cluster, Quad-core per cluster. CPUs within a cluster switch
|
||||
DCVS state together.
|
||||
|
||||
/ {
|
||||
cpus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
CPU0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x0>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_0>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_0: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
L3_0: l3-cache {
|
||||
compatible = "cache";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
CPU1: cpu@100 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x100>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_100>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_100: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU2: cpu@200 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x200>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_200>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_200: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU3: cpu@300 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x300>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_300>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_300: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU4: cpu@400 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x400>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_400>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_400: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU5: cpu@500 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x500>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_500>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_500: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU6: cpu@600 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x600>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_600>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_600: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU7: cpu@700 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x700>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_700>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_700: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
cpufreq_hw: cpufreq@17d43000 {
|
||||
compatible = "qcom,cpufreq-hw";
|
||||
reg = <0x17d43000 0x1400>, <0x17d45800 0x1400>;
|
||||
reg-names = "freq-domain0", "freq-domain1";
|
||||
|
||||
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
|
||||
clock-names = "xo", "alternate";
|
||||
|
||||
#freq-domain-cells = <1>;
|
||||
};
|
||||
}
|
||||
242
Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
Normal file
242
Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/cpufreq/cpufreq-qcom-hw.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies, Inc. CPUFREQ
|
||||
|
||||
maintainers:
|
||||
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
|
||||
description: |
|
||||
|
||||
CPUFREQ HW is a hardware engine used by some Qualcomm Technologies, Inc. (QTI)
|
||||
SoCs to manage frequency in hardware. It is capable of controlling frequency
|
||||
for multiple clusters.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- description: Non-secure v1 of CPUFREQ HW
|
||||
items:
|
||||
- const: qcom,cpufreq-hw-8998
|
||||
|
||||
- description: v1 of CPUFREQ HW
|
||||
items:
|
||||
- const: qcom,cpufreq-hw
|
||||
|
||||
- description: v2 of CPUFREQ HW (EPSS)
|
||||
items:
|
||||
- enum:
|
||||
- qcom,sm8250-cpufreq-epss
|
||||
- const: qcom,cpufreq-epss
|
||||
|
||||
reg: {}
|
||||
|
||||
reg-names: {}
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: XO Clock
|
||||
- description: GPLL0 Clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: xo
|
||||
- const: alternate
|
||||
|
||||
'#freq-domain-cells':
|
||||
const: 1
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,cpufreq-hw-8998
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 2
|
||||
maxItems: 6
|
||||
items:
|
||||
- description: Frequency domain 0 register region
|
||||
- description: Operating State Manager domain 0 register region
|
||||
- description: Frequency domain 1 register region
|
||||
- description: Operating State Manager domain 1 register region
|
||||
- description: PLL ACD domain 0 register region (if ACD programming required)
|
||||
- description: PLL ACD domain 1 register region (if ACD programming required)
|
||||
|
||||
reg-names:
|
||||
minItems: 2
|
||||
maxItems: 6
|
||||
items:
|
||||
- const: "osm-domain0"
|
||||
- const: "freq-domain0"
|
||||
- const: "osm-domain1"
|
||||
- const: "freq-domain1"
|
||||
- const: "osm-acd0"
|
||||
- const: "osm-acd1"
|
||||
|
||||
else:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
items:
|
||||
- description: Frequency domain 0 register region
|
||||
- description: Frequency domain 1 register region
|
||||
- description: Frequency domain 2 register region
|
||||
reg-names:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
items:
|
||||
- const: "freq-domain0"
|
||||
- const: "freq-domain1"
|
||||
- const: "freq-domain2"
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#freq-domain-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sdm845.h>
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
|
||||
// Example 1: Dual-cluster, Quad-core per cluster. CPUs within a cluster
|
||||
// switch DCVS state together.
|
||||
cpus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
CPU0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x0>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_0>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_0: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
L3_0: l3-cache {
|
||||
compatible = "cache";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
CPU1: cpu@100 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x100>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_100>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_100: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU2: cpu@200 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x200>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_200>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_200: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU3: cpu@300 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x300>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_300>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_300: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU4: cpu@400 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x400>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_400>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_400: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU5: cpu@500 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x500>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_500>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_500: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU6: cpu@600 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x600>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_600>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_600: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU7: cpu@700 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x700>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_700>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_700: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
cpufreq@17d43000 {
|
||||
compatible = "qcom,cpufreq-hw";
|
||||
reg = <0x17d43000 0x1400>, <0x17d45800 0x1400>;
|
||||
reg-names = "freq-domain0", "freq-domain1";
|
||||
|
||||
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
|
||||
clock-names = "xo", "alternate";
|
||||
|
||||
#freq-domain-cells = <1>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/samsung,s6e3fa5.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Samsung S6E3FA5 AMOLED panel with command mode DSI controller
|
||||
|
||||
maintainers:
|
||||
- Jami Kettunen <jami.kettunen@somainline.org>
|
||||
|
||||
description: |+
|
||||
This panel is found on the OnePlus 3T as well as OnePlus 5,
|
||||
however on the 3T it runs in video mode while this driver
|
||||
currently only support the command mode variant found on the
|
||||
5.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: samsung,s6e3fa5
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
disp-te-gpios: true
|
||||
vddio-supply:
|
||||
description: vddio supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vddio-supply
|
||||
- reset-gpios
|
||||
- disp-te-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
reg = <0>;
|
||||
|
||||
compatible = "samsung,s6e3fa5";
|
||||
|
||||
vddio-supply = <&vreg_l14a_1p88>;
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
|
||||
disp-te-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/samsung,s6e3fc1.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Samsung S6E3FC1 AMOLED panel with command mode DSI controller
|
||||
|
||||
maintainers:
|
||||
- Jami Kettunen <jami.kettunen@somainline.org>
|
||||
|
||||
description: |+
|
||||
This panel is found on the OnePlus 5T and it runs in command mode.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: samsung,s6e3fc1
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
disp-te-gpios: true
|
||||
vddio-supply:
|
||||
description: vddio supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vddio-supply
|
||||
- reset-gpios
|
||||
- disp-te-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
reg = <0>;
|
||||
|
||||
compatible = "samsung,s6e3fc1";
|
||||
|
||||
vddio-supply = <&vreg_l14a_1p88>;
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
|
||||
disp-te-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
Qualcomm Universal Peripheral (QUP) I2C controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be:
|
||||
* "qcom,i2c-qup-v1.1.1" for 8660, 8960 and 8064.
|
||||
* "qcom,i2c-qup-v2.1.1" for 8974 v1.
|
||||
* "qcom,i2c-qup-v2.2.1" for 8974 v2 and later.
|
||||
- reg: Should contain QUP register address and length.
|
||||
- interrupts: Should contain I2C interrupt.
|
||||
|
||||
- clocks: A list of phandles + clock-specifiers, one for each entry in
|
||||
clock-names.
|
||||
- clock-names: Should contain:
|
||||
* "core" for the core clock
|
||||
* "iface" for the AHB clock
|
||||
|
||||
- #address-cells: Should be <1> Address cells for i2c device address
|
||||
- #size-cells: Should be <0> as i2c addresses have no size component
|
||||
|
||||
Optional properties:
|
||||
- clock-frequency: Should specify the desired i2c bus clock frequency in Hz,
|
||||
defaults to 100kHz if omitted.
|
||||
|
||||
Child nodes should conform to i2c bus binding.
|
||||
|
||||
Example:
|
||||
|
||||
i2c@f9924000 {
|
||||
compatible = "qcom,i2c-qup-v2.2.1";
|
||||
reg = <0xf9924000 0x1000>;
|
||||
interrupts = <0 96 0>;
|
||||
|
||||
clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
|
||||
clock-frequency = <355000>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
101
Documentation/devicetree/bindings/i2c/qcom,i2c-qup.yaml
Normal file
101
Documentation/devicetree/bindings/i2c/qcom,i2c-qup.yaml
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
|
||||
$id: http://devicetree.org/schemas/i2c/qcom,i2c-qup.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Universal Peripheral (QUP) I2C controller
|
||||
|
||||
maintainers:
|
||||
- Andy Gross <agross@kernel.org>
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
description: Binding for Qualcomm "QUP" I2C controllers
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/i2c/i2c-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,i2c-qup-v1.1.1
|
||||
- qcom,i2c-qup-v2.1.1
|
||||
- qcom,i2c-qup-v2.2.1
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: QUP I2C register iospace
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Core QUP I2C clock
|
||||
- description: AHB clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: iface
|
||||
|
||||
clock-frequency:
|
||||
minimum: 100000
|
||||
maximum: 1000000
|
||||
default: 100000
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: RX DMA Channel phandle
|
||||
- description: TX DMA Channel phandle
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
qcom,noise-reject-sda:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Noise rejection level for the SDA line.
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
default: 0
|
||||
|
||||
qcom,noise-reject-scl:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Noise rejection level for the SCL line.
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
default: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
- clock-names
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8998.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
i2c@c175000 {
|
||||
compatible = "qcom,i2c-qup-v2.2.1";
|
||||
reg = <0x0c175000 0x600>;
|
||||
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>,
|
||||
<&gcc GCC_BLSP1_AHB_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
clock-frequency = <400000>;
|
||||
dmas = <&blsp_dma 4>, <&blsp_dma 5>;
|
||||
dma-names = "rx", "tx";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/gpio-fastmatrix-keyboard.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Fast modern GPIO-driven keyboard/keypad matrix driver binding
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
description: |
|
||||
A simple common binding for matrix-connected keyboards/keypads, targeted at
|
||||
defining the keys in the scope of linux key codes since that is a stable and
|
||||
standardized interface at this time.
|
||||
This driver uses the GPIOD API in order to support setting (and reading) an
|
||||
entire array of GPIOs which is very fast (if the controller supports it) and
|
||||
a requirement to support full keyboard matrices on slow external GPIO I2C
|
||||
expanders, but also a great latency enhancement for faster GPIO controllers.
|
||||
|
||||
allOf:
|
||||
- $ref: input.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: gpio-fastmatrix-keyboard
|
||||
|
||||
label:
|
||||
description: Descriptive name of the key.
|
||||
|
||||
linux,keymap:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: |
|
||||
An array of packed 1-cell entries containing the equivalent of row,
|
||||
column and linux key-code as specified in dt-bindings/input/input.h
|
||||
|
||||
autorescan-ms:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
Activates auto-rescanning of the matrix after receiving and processing
|
||||
an event for quirky hardware that won't re-send interrupts on fast-press,
|
||||
fast-depress, or multiple keys pressed events.
|
||||
This time is expressed in milliseconds; if not specified, the feature is
|
||||
disabled.
|
||||
|
||||
col-scan-delay-us:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
Time to wait in microseconds for scan after activating a column.
|
||||
If not specified, the default is 0 (no wait).
|
||||
|
||||
debounce-delay-ms:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
Matrix button debouncing interval time in milliseconds.
|
||||
If not specified, debouncing is disabled.
|
||||
|
||||
drive-inactive-cols:
|
||||
type: boolean
|
||||
description: Keep direction of inactive columns as output
|
||||
|
||||
col-gpios:
|
||||
minItems: 2
|
||||
maxItems: 20
|
||||
|
||||
keypad,num-rows:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Number of row lines connected to the keypad controller.
|
||||
|
||||
keypad,num-columns:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Number of column lines connected to the keypad controller.
|
||||
|
||||
pinctrl-0:
|
||||
maxItems: 1
|
||||
|
||||
pinctrl-names:
|
||||
maxItems: 1
|
||||
|
||||
row-gpios:
|
||||
minItems: 2
|
||||
maxItems: 20
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- row-gpios
|
||||
- col-gpios
|
||||
- linux,keymap
|
||||
- keypad,num-rows
|
||||
- keypad,num-columns
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
gpio-keyboard {
|
||||
compatible = "gpio-fastmatrix-keyboard";
|
||||
label = "Keyboard over I2C Expander";
|
||||
row-gpios =
|
||||
<&gpioext0 0 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 1 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 2 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 3 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 4 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 5 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 6 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 7 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
|
||||
col-gpios =
|
||||
<&gpioext0 8 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 9 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 10 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 11 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 12 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 13 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 14 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 15 GPIO_ACTIVE_LOW>;
|
||||
|
||||
linux,keymap = <
|
||||
MATRIX_KEY(0, 0, KEY_F1) MATRIX_KEY(1, 0, KEY_H)
|
||||
MATRIX_KEY(2, 0, KEY_B) MATRIX_KEY(3, 0, KEY_7)
|
||||
/* ... */
|
||||
>;
|
||||
|
||||
keypad,num-rows = <8>;
|
||||
keypad,num-columns = <8>;
|
||||
};
|
||||
123
Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml
Normal file
123
Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright 2020 Unisoc Inc.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/qcom,spmi-haptics.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies Inc PMI8998 spmi haptics
|
||||
|
||||
maintainers:
|
||||
- Caleb Connolly <caleb@connolly.tech>
|
||||
|
||||
description: |
|
||||
Qualcomm SPMI haptics is a peripheral on some QTI PMICs. It supports linear resonant
|
||||
actuators and eccentric rotating mass type haptics commonly found in mobile devices.
|
||||
It supports multiple sources of wave data such as an internal buffer, direct play
|
||||
(from kernel or userspace) as well as an audio output mode.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,pmi8998-haptics
|
||||
- qcom,pmi8996-haptics
|
||||
- qcom,pmi8941-haptics
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: short circuit interrupt
|
||||
- description: play interrupt
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: short
|
||||
- const: play
|
||||
|
||||
qcom,actuator-type:
|
||||
description: |
|
||||
The type of actuator attached to the hardware.
|
||||
Allowed values are,
|
||||
0 - HAP_TYPE_LRA
|
||||
1 - HAP_TYPE_ERM
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
default: 0
|
||||
|
||||
qcom,wave-shape:
|
||||
description: |
|
||||
Selects the wave shape to use.
|
||||
Allowed values are,
|
||||
0 - HAP_WAVE_SINE
|
||||
1 - HAP_WAVE_SQUARE
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
default: 0
|
||||
|
||||
qcom,play-mode:
|
||||
description: |
|
||||
Selects the play mode to use.
|
||||
Allowed values are,
|
||||
0 - HAP_PLAY_DIRECT
|
||||
1 - HAP_PLAY_BUFFER
|
||||
2 - HAP_PLAY_AUDIO
|
||||
3 - HAP_PLAY_PWM
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1, 2, 3 ]
|
||||
default: 2
|
||||
|
||||
qcom,wave-play-rate-us:
|
||||
description: |
|
||||
Wave sample durection in microseconds, 1/f where f
|
||||
is the resonant frequency of the actuator.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 20475
|
||||
|
||||
qcom,brake-pattern:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
description: |
|
||||
The brake pattern are the strengths of the pattern
|
||||
used to brake the haptics. Allowed values are,
|
||||
0 - 0V
|
||||
1 - Vmax/4
|
||||
2 - Vmax/2
|
||||
3 - Vmax
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
default: [0x3, 0x3, 0x2, 0x1]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- qcom,wave-play-rate-us
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/input/qcom,spmi-haptics.h>
|
||||
|
||||
spmi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pmi8998_haptics: haptics@c000 {
|
||||
compatible = "qcom,pmi8998-haptics";
|
||||
reg = <0xc000>;
|
||||
|
||||
interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "short", "play";
|
||||
|
||||
qcom,wave-shape = <HAP_WAVE_SINE>;
|
||||
qcom,play-mode = <HAP_PLAY_BUFFER>;
|
||||
qcom,brake-pattern = <0x3 0x3 0x2 0x1>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
158
Documentation/devicetree/bindings/interconnect/qcom,msm8998.yaml
Normal file
158
Documentation/devicetree/bindings/interconnect/qcom,msm8998.yaml
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/interconnect/qcom,msm8998.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm MSM8998 Network-On-Chip interconnect
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
- Konrad Dybcio <konrad.dybcio@somainline.org>
|
||||
|
||||
description: |
|
||||
The Qualcomm MSM8998 interconnect providers support adjusting the
|
||||
bandwidth requirements between the various NoC fabrics.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,msm8998-a1noc
|
||||
- qcom,msm8998-a2noc
|
||||
- qcom,msm8998-bimc
|
||||
- qcom,msm8998-cnoc
|
||||
- qcom,msm8998-gnoc
|
||||
- qcom,msm8998-mnoc
|
||||
- qcom,msm8998-snoc
|
||||
|
||||
'#interconnect-cells':
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#interconnect-cells'
|
||||
- clock-names
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-mnoc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Bus Clock.
|
||||
- description: Bus A Clock.
|
||||
- description: CPU-NoC High-performance Bus Clock.
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: bus_a
|
||||
- const: iface
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-a2noc
|
||||
- qcom,msm8998-bimc
|
||||
- qcom,msm8998-cnoc
|
||||
- qcom,msm8998-gnoc
|
||||
- qcom,msm8998-snoc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Bus Clock.
|
||||
- description: Bus A Clock.
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: bus_a
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||
#include <dt-bindings/clock/qcom,mmcc-msm8998.h>
|
||||
|
||||
bimc: interconnect@1008000 {
|
||||
compatible = "qcom,msm8998-bimc";
|
||||
reg = <0x01008000 0x78000>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
|
||||
<&rpmcc RPM_SMD_BIMC_A_CLK>;
|
||||
};
|
||||
|
||||
cnoc: interconnect@1500000 {
|
||||
compatible = "qcom,msm8998-cnoc";
|
||||
reg = <0x01500000 0x10000>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_CNOC_CLK>,
|
||||
<&rpmcc RPM_SMD_CNOC_A_CLK>;
|
||||
};
|
||||
|
||||
snoc: interconnect@1625000 {
|
||||
compatible = "qcom,msm8998-snoc";
|
||||
reg = <0x01625000 0x6100>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_SNOC_CLK>,
|
||||
<&rpmcc RPM_SMD_SNOC_A_CLK>;
|
||||
};
|
||||
|
||||
a1noc: interconnect@1669000 {
|
||||
compatible = "qcom,msm8998-a1noc";
|
||||
reg = <0x01669000 0x5020>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_AGGR1_NOC_CLK>,
|
||||
<&rpmcc RPM_SMD_AGGR1_NOC_A_CLK>;
|
||||
};
|
||||
|
||||
a2noc: interconnect@1705000 {
|
||||
compatible = "qcom,msm8998-a2noc";
|
||||
reg = <0x01705000 0xa090>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_AGGR2_NOC_CLK>,
|
||||
<&rpmcc RPM_SMD_AGGR2_NOC_A_CLK>;
|
||||
};
|
||||
|
||||
mnoc: interconnect@1744000 {
|
||||
compatible = "qcom,msm8998-mnoc";
|
||||
reg = <0x01744000 0xb010>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a", "iface";
|
||||
clocks = <&rpmcc RPM_SMD_MMAXI_CLK>,
|
||||
<&rpmcc RPM_SMD_MMAXI_A_CLK>,
|
||||
<&mmcc AHB_CLK_SRC>;
|
||||
};
|
||||
|
||||
gnoc: interconnect@17900000 {
|
||||
compatible = "qcom,msm8998-gnoc";
|
||||
reg = <0x17900000 0xe000>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&xo_board>, <&xo_board>;
|
||||
};
|
||||
158
Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
Normal file
158
Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/leds/leds-qcom-lpg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Light Pulse Generator
|
||||
|
||||
maintainers:
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
description: >
|
||||
The Qualcomm Light Pulse Generator consists of three different hardware blocks;
|
||||
a ramp generator with lookup table, the light pulse generator and a three
|
||||
channel current sink. These blocks are found in a wide range of Qualcomm PMICs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,pm8150b-lpg
|
||||
- qcom,pm8150l-lpg
|
||||
- qcom,pm8916-pwm
|
||||
- qcom,pm8941-lpg
|
||||
- qcom,pm8994-lpg
|
||||
- qcom,pmi8994-lpg
|
||||
- qcom,pmi8998-lpg
|
||||
|
||||
"#pwm-cells":
|
||||
const: 2
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
qcom,power-source:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
power-source used to drive the output, as defined in the datasheet.
|
||||
Should be specified if the TRILED block is present
|
||||
|
||||
qcom,dtest:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: >
|
||||
A list of integer pairs, where each pair represent the dtest line the
|
||||
particular channel should be connected to and the flags denoting how the
|
||||
value should be outputed, as defined in the datasheet. The number of
|
||||
pairs should be the same as the number of channels.
|
||||
|
||||
multi-led:
|
||||
type: object
|
||||
$ref: leds-class-multicolor.yaml#
|
||||
properties:
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
"^led@[0-9a-f]$":
|
||||
type: object
|
||||
$ref: common.yaml#
|
||||
|
||||
patternProperties:
|
||||
"^led@[0-9a-f]$":
|
||||
type: object
|
||||
$ref: common.yaml#
|
||||
|
||||
properties:
|
||||
reg: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
lpg {
|
||||
compatible = "qcom,pmi8994-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
qcom,power-source = <1>;
|
||||
|
||||
qcom,dtest = <0 0
|
||||
0 0
|
||||
0 0
|
||||
4 1>;
|
||||
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
label = "green:user1";
|
||||
};
|
||||
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
label = "green:user0";
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
label = "green:user2";
|
||||
};
|
||||
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
label = "green:user3";
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
lpg {
|
||||
compatible = "qcom,pmi8994-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
qcom,power-source = <1>;
|
||||
|
||||
multi-led {
|
||||
color = <LED_COLOR_ID_MULTI>;
|
||||
label = "rgb:notification";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
};
|
||||
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
};
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
};
|
||||
- |
|
||||
lpg {
|
||||
compatible = "qcom,pm8916-pwm";
|
||||
#pwm-cells = <2>;
|
||||
};
|
||||
...
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/awinic,aw9523-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Awinic AW9523/AW9523B I2C GPIO Expander
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
description: |
|
||||
The Awinic AW9523/AW9523B I2C GPIO Expander featuring 16 multi-function
|
||||
I/O, 256 steps PWM mode and interrupt support.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: awinic,aw9523-pinctrl
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#gpio-cells':
|
||||
description: |
|
||||
Specifying the pin number and flags, as defined in
|
||||
include/dt-bindings/gpio/gpio.h
|
||||
const: 2
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description: Specifies the INTN pin IRQ.
|
||||
|
||||
'#interrupt-cells':
|
||||
description:
|
||||
Specifies the PIN numbers and Flags, as defined in defined in
|
||||
include/dt-bindings/interrupt-controller/irq.h
|
||||
const: 2
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
#PIN CONFIGURATION NODES
|
||||
patternProperties:
|
||||
'-pins$':
|
||||
type: object
|
||||
description:
|
||||
Pinctrl node's client devices use subnodes for desired pin configuration.
|
||||
Client device subnodes use below standard properties.
|
||||
$ref: "/schemas/pinctrl/pincfg-node.yaml"
|
||||
|
||||
properties:
|
||||
pins:
|
||||
description:
|
||||
List of gpio pins affected by the properties specified in
|
||||
this subnode.
|
||||
items:
|
||||
pattern: "^gpio([0-9]|1[0-5])$"
|
||||
minItems: 1
|
||||
maxItems: 16
|
||||
|
||||
function:
|
||||
description:
|
||||
Specify the alternative function to be configured for the
|
||||
specified pins.
|
||||
|
||||
enum: [ gpio, pwm ]
|
||||
|
||||
bias-disable: true
|
||||
bias-pull-down: true
|
||||
bias-pull-up: true
|
||||
drive-open-drain: true
|
||||
drive-push-pull: true
|
||||
input-enable: true
|
||||
input-disable: true
|
||||
output-high: true
|
||||
output-low: true
|
||||
|
||||
required:
|
||||
- pins
|
||||
- function
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- gpio-controller
|
||||
- '#gpio-cells'
|
||||
- gpio-ranges
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Example configuration to drive pins for a keyboard matrix
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
aw9523: gpio-expander@58 {
|
||||
compatible = "awinic,aw9523-pinctrl";
|
||||
reg = <0x58>;
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <50 IRQ_TYPE_EDGE_FALLING>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&tlmm 0 0 16>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
reset-gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
keyboard-matrix-col-pins {
|
||||
pins = "gpio8", "gpio9", "gpio10", "gpio11",
|
||||
"gpio12", "gpio13", "gpio14", "gpio15";
|
||||
function = "gpio";
|
||||
input-disable;
|
||||
output-low;
|
||||
};
|
||||
|
||||
keyboard-matrix-row-pins {
|
||||
pins = "gpio0", "gpio1", "gpio2", "gpio3",
|
||||
"gpio4", "gpio5", "gpio6", "gpio7";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
drive-open-drain;
|
||||
input-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -1,130 +1 @@
|
|||
QCOM CPR (Core Power Reduction)
|
||||
|
||||
CPR (Core Power Reduction) is a technology to reduce core power on a CPU
|
||||
or other device. Each OPP of a device corresponds to a "corner" that has
|
||||
a range of valid voltages for a particular frequency. While the device is
|
||||
running at a particular frequency, CPR monitors dynamic factors such as
|
||||
temperature, etc. and suggests adjustments to the voltage to save power
|
||||
and meet silicon characteristic requirements.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: should be "qcom,qcs404-cpr", "qcom,cpr" for qcs404
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: base address and size of the rbcpr register region
|
||||
|
||||
- interrupts:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: should specify the CPR interrupt
|
||||
|
||||
- clocks:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: phandle to the reference clock
|
||||
|
||||
- clock-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: must be "ref"
|
||||
|
||||
- vdd-apc-supply:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: phandle to the vdd-apc-supply regulator
|
||||
|
||||
- #power-domain-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: should be 0
|
||||
|
||||
- operating-points-v2:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: A phandle to the OPP table containing the
|
||||
performance states supported by the CPR
|
||||
power domain
|
||||
|
||||
- acc-syscon:
|
||||
Usage: optional
|
||||
Value type: <phandle>
|
||||
Definition: phandle to syscon for writing ACC settings
|
||||
|
||||
- nvmem-cells:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: phandle to nvmem cells containing the data
|
||||
that makes up a fuse corner, for each fuse corner.
|
||||
As well as the CPR fuse revision.
|
||||
|
||||
- nvmem-cell-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: should be "cpr_quotient_offset1", "cpr_quotient_offset2",
|
||||
"cpr_quotient_offset3", "cpr_init_voltage1",
|
||||
"cpr_init_voltage2", "cpr_init_voltage3", "cpr_quotient1",
|
||||
"cpr_quotient2", "cpr_quotient3", "cpr_ring_osc1",
|
||||
"cpr_ring_osc2", "cpr_ring_osc3", "cpr_fuse_revision"
|
||||
for qcs404.
|
||||
|
||||
Example:
|
||||
|
||||
cpr_opp_table: cpr-opp-table {
|
||||
compatible = "operating-points-v2-qcom-level";
|
||||
|
||||
cpr_opp1: opp1 {
|
||||
opp-level = <1>;
|
||||
qcom,opp-fuse-level = <1>;
|
||||
};
|
||||
cpr_opp2: opp2 {
|
||||
opp-level = <2>;
|
||||
qcom,opp-fuse-level = <2>;
|
||||
};
|
||||
cpr_opp3: opp3 {
|
||||
opp-level = <3>;
|
||||
qcom,opp-fuse-level = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
power-controller@b018000 {
|
||||
compatible = "qcom,qcs404-cpr", "qcom,cpr";
|
||||
reg = <0x0b018000 0x1000>;
|
||||
interrupts = <0 15 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&xo_board>;
|
||||
clock-names = "ref";
|
||||
vdd-apc-supply = <&pms405_s3>;
|
||||
#power-domain-cells = <0>;
|
||||
operating-points-v2 = <&cpr_opp_table>;
|
||||
acc-syscon = <&tcsr>;
|
||||
|
||||
nvmem-cells = <&cpr_efuse_quot_offset1>,
|
||||
<&cpr_efuse_quot_offset2>,
|
||||
<&cpr_efuse_quot_offset3>,
|
||||
<&cpr_efuse_init_voltage1>,
|
||||
<&cpr_efuse_init_voltage2>,
|
||||
<&cpr_efuse_init_voltage3>,
|
||||
<&cpr_efuse_quot1>,
|
||||
<&cpr_efuse_quot2>,
|
||||
<&cpr_efuse_quot3>,
|
||||
<&cpr_efuse_ring1>,
|
||||
<&cpr_efuse_ring2>,
|
||||
<&cpr_efuse_ring3>,
|
||||
<&cpr_efuse_revision>;
|
||||
nvmem-cell-names = "cpr_quotient_offset1",
|
||||
"cpr_quotient_offset2",
|
||||
"cpr_quotient_offset3",
|
||||
"cpr_init_voltage1",
|
||||
"cpr_init_voltage2",
|
||||
"cpr_init_voltage3",
|
||||
"cpr_quotient1",
|
||||
"cpr_quotient2",
|
||||
"cpr_quotient3",
|
||||
"cpr_ring_osc1",
|
||||
"cpr_ring_osc2",
|
||||
"cpr_ring_osc3",
|
||||
"cpr_fuse_revision";
|
||||
};
|
||||
This file has been moved to ../../soc/qcom/qcom,cpr.yaml
|
||||
|
|
|
|||
167
Documentation/devicetree/bindings/soc/qcom/qcom,cpr.yaml
Normal file
167
Documentation/devicetree/bindings/soc/qcom/qcom,cpr.yaml
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/soc/qcom/qcom,cpr.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm Core Power Reduction (CPR)
|
||||
|
||||
description: |
|
||||
CPR (Core Power Reduction) is a technology to reduce core power on a CPU
|
||||
or other device. Each OPP of a device corresponds to a "corner" that has
|
||||
a range of valid voltages for a particular frequency. While the device is
|
||||
running at a particular frequency, CPR monitors dynamic factors such as
|
||||
temperature, etc. and suggests adjustments to the voltage to save power
|
||||
and meet silicon characteristic requirements.
|
||||
|
||||
maintainers:
|
||||
- Niklas Cassel <nks@flawful.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,qcs404-cpr
|
||||
- const: qcom,cpr
|
||||
|
||||
reg:
|
||||
description: Base address and size of the RBCPR register region
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: CPR reference clock
|
||||
|
||||
vdd-apc-supply:
|
||||
description: Autonomous Phase Control (APC) power supply
|
||||
|
||||
'#power-domain-cells':
|
||||
const: 0
|
||||
|
||||
acc-syscon:
|
||||
description: phandle to syscon for writing ACC settings
|
||||
|
||||
nvmem-cells:
|
||||
minItems: 9
|
||||
maxItems: 32
|
||||
description: Cells containing the fuse corners and revision data
|
||||
|
||||
nvmem-cell-names:
|
||||
minItems: 9
|
||||
maxItems: 32
|
||||
|
||||
operating-points-v2: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clock-names
|
||||
- clocks
|
||||
- vdd-apc-supply
|
||||
- "#power-domain-cells"
|
||||
- nvmem-cells
|
||||
- nvmem-cell-names
|
||||
- operating-points-v2
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@100 {
|
||||
compatible = "arm,cortex-a53";
|
||||
device_type = "cpu";
|
||||
reg = <0x100>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
power-domains = <&cpr>;
|
||||
power-domain-names = "cpr";
|
||||
};
|
||||
};
|
||||
|
||||
cpu_opp_table: cpu-opp-table {
|
||||
compatible = "operating-points-v2-kryo-cpu";
|
||||
opp-shared;
|
||||
|
||||
opp-1094400000 {
|
||||
opp-hz = /bits/ 64 <1094400000>;
|
||||
required-opps = <&cpr_opp1>;
|
||||
};
|
||||
opp-1248000000 {
|
||||
opp-hz = /bits/ 64 <1248000000>;
|
||||
required-opps = <&cpr_opp2>;
|
||||
};
|
||||
opp-1401600000 {
|
||||
opp-hz = /bits/ 64 <1401600000>;
|
||||
required-opps = <&cpr_opp3>;
|
||||
};
|
||||
};
|
||||
|
||||
cpr_opp_table: cpr-opp-table {
|
||||
compatible = "operating-points-v2-qcom-level";
|
||||
|
||||
cpr_opp1: opp1 {
|
||||
opp-level = <1>;
|
||||
qcom,opp-fuse-level = <1>;
|
||||
};
|
||||
cpr_opp2: opp2 {
|
||||
opp-level = <2>;
|
||||
qcom,opp-fuse-level = <2>;
|
||||
};
|
||||
cpr_opp3: opp3 {
|
||||
opp-level = <3>;
|
||||
qcom,opp-fuse-level = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
power-controller@b018000 {
|
||||
compatible = "qcom,qcs404-cpr", "qcom,cpr";
|
||||
reg = <0x0b018000 0x1000>;
|
||||
interrupts = <0 15 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&xo_board>;
|
||||
clock-names = "ref";
|
||||
vdd-apc-supply = <&pms405_s3>;
|
||||
#power-domain-cells = <0>;
|
||||
operating-points-v2 = <&cpr_opp_table>;
|
||||
acc-syscon = <&tcsr>;
|
||||
|
||||
nvmem-cells = <&cpr_efuse_quot_offset1>,
|
||||
<&cpr_efuse_quot_offset2>,
|
||||
<&cpr_efuse_quot_offset3>,
|
||||
<&cpr_efuse_init_voltage1>,
|
||||
<&cpr_efuse_init_voltage2>,
|
||||
<&cpr_efuse_init_voltage3>,
|
||||
<&cpr_efuse_quot1>,
|
||||
<&cpr_efuse_quot2>,
|
||||
<&cpr_efuse_quot3>,
|
||||
<&cpr_efuse_ring1>,
|
||||
<&cpr_efuse_ring2>,
|
||||
<&cpr_efuse_ring3>,
|
||||
<&cpr_efuse_revision>;
|
||||
nvmem-cell-names = "cpr0_quotient_offset1",
|
||||
"cpr0_quotient_offset2",
|
||||
"cpr0_quotient_offset3",
|
||||
"cpr0_init_voltage1",
|
||||
"cpr0_init_voltage2",
|
||||
"cpr0_init_voltage3",
|
||||
"cpr0_quotient1",
|
||||
"cpr0_quotient2",
|
||||
"cpr0_quotient3",
|
||||
"cpr0_ring_osc1",
|
||||
"cpr0_ring_osc2",
|
||||
"cpr0_ring_osc3",
|
||||
"cpr0_fuse_revision";
|
||||
};
|
||||
...
|
||||
241
Documentation/devicetree/bindings/soc/qcom/qcom,cpr3.yaml
Normal file
241
Documentation/devicetree/bindings/soc/qcom/qcom,cpr3.yaml
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/soc/qcom/qcom,cpr3.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm Core Power Reduction v3/v4/Hardened (CPR3, CPR4, CPRh)
|
||||
|
||||
description: |
|
||||
CPR (Core Power Reduction) is a technology to reduce core power on a CPU
|
||||
or other device. Each OPP of a device corresponds to a "corner" that has
|
||||
a range of valid voltages for a particular frequency. While the device is
|
||||
running at a particular frequency, CPR monitors dynamic factors such as
|
||||
temperature, etc. and suggests or, in the CPR-Hardened case performs,
|
||||
adjustments to the voltage to save power and meet silicon characteristic
|
||||
requirements.
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- description: CPRv3 controller
|
||||
items:
|
||||
- const: qcom,cpr3
|
||||
- description: CPRv4 controller
|
||||
items:
|
||||
- const: qcom,cpr4
|
||||
- description: CPRv4-Hardened controller
|
||||
items:
|
||||
- enum:
|
||||
- qcom,msm8998-cprh
|
||||
- qcom,sdm630-cprh
|
||||
- const: qcom,cprh
|
||||
|
||||
reg:
|
||||
description: Base address and size of the CPR controller(s)
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: "ref"
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: CPR reference clock
|
||||
|
||||
vdd-supply:
|
||||
description: Autonomous Phase Control (APC) or other power supply
|
||||
|
||||
'#power-domain-cells':
|
||||
const: 1
|
||||
|
||||
acc-syscon:
|
||||
description: phandle to syscon for writing ACC settings
|
||||
|
||||
nvmem-cells:
|
||||
description: Cells containing the fuse corners and revision data
|
||||
minItems: 10
|
||||
maxItems: 32
|
||||
|
||||
nvmem-cell-names:
|
||||
minItems: 10
|
||||
maxItems: 32
|
||||
|
||||
operating-points-v2: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clock-names
|
||||
- clocks
|
||||
- "#power-domain-cells"
|
||||
- nvmem-cells
|
||||
- nvmem-cell-names
|
||||
- operating-points-v2
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8998.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
cpus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "qcom,kryo280";
|
||||
device_type = "cpu";
|
||||
reg = <0x0 0x0>;
|
||||
operating-points-v2 = <&cpu_gold_opp_table>;
|
||||
power-domains = <&apc_cprh 0>;
|
||||
power-domain-names = "cprh";
|
||||
};
|
||||
|
||||
cpu@100 {
|
||||
compatible = "qcom,kryo280";
|
||||
device_type = "cpu";
|
||||
reg = <0x0 0x0>;
|
||||
operating-points-v2 = <&cpu_silver_opp_table>;
|
||||
power-domains = <&apc_cprh 1>;
|
||||
power-domain-names = "cprh";
|
||||
};
|
||||
};
|
||||
|
||||
cpu_silver_opp_table: cpu-silver-opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-1843200000 {
|
||||
opp-hz = /bits/ 64 <1843200000>;
|
||||
required-opps = <&cprh_opp3>;
|
||||
};
|
||||
opp-1094400000 {
|
||||
opp-hz = /bits/ 64 <1094400000>;
|
||||
required-opps = <&cprh_opp2>;
|
||||
};
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
required-opps = <&cprh_opp1>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu_gold_opp_table: cpu-gold-opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-2208000000 {
|
||||
opp-hz = /bits/ 64 <2208000000>;
|
||||
required-opps = <&cprh_opp3>;
|
||||
};
|
||||
opp-1113600000 {
|
||||
opp-hz = /bits/ 64 <1113600000>;
|
||||
required-opps = <&cprh_opp2>;
|
||||
};
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
required-opps = <&cprh_opp1>;
|
||||
};
|
||||
};
|
||||
|
||||
cprh_opp_table: cpr-hardened-opp-table {
|
||||
compatible = "operating-points-v2-qcom-level";
|
||||
|
||||
cprh_opp1: opp1 {
|
||||
opp-level = <1>;
|
||||
qcom,opp-fuse-level = <1>;
|
||||
};
|
||||
cprh_opp2: opp2 {
|
||||
opp-level = <2>;
|
||||
qcom,opp-fuse-level = <2>;
|
||||
};
|
||||
cprh_opp3: opp3 {
|
||||
opp-level = <3>;
|
||||
qcom,opp-fuse-level = <2 3>;
|
||||
};
|
||||
};
|
||||
|
||||
apc_cprh: power-controller@179c8000 {
|
||||
compatible = "qcom,msm8998-cprh", "qcom,cprh";
|
||||
reg = <0x0179c8000 0x4000>, <0x0179c4000 0x4000>;
|
||||
clocks = <&gcc GCC_HMSS_RBCPR_CLK>;
|
||||
clock-names = "ref";
|
||||
|
||||
#power-domain-cells = <1>;
|
||||
operating-points-v2 = <&cprh_opp_table>;
|
||||
|
||||
nvmem-cells = <&cpr_efuse_speedbin>,
|
||||
<&cpr_fuse_revision>,
|
||||
<&cpr_quot0_pwrcl>,
|
||||
<&cpr_quot1_pwrcl>,
|
||||
<&cpr_quot2_pwrcl>,
|
||||
<&cpr_quot3_pwrcl>,
|
||||
<&cpr_quot_offset1_pwrcl>,
|
||||
<&cpr_quot_offset2_pwrcl>,
|
||||
<&cpr_quot_offset3_pwrcl>,
|
||||
<&cpr_init_voltage0_pwrcl>,
|
||||
<&cpr_init_voltage1_pwrcl>,
|
||||
<&cpr_init_voltage2_pwrcl>,
|
||||
<&cpr_init_voltage3_pwrcl>,
|
||||
<&cpr_ro_sel0_pwrcl>,
|
||||
<&cpr_ro_sel1_pwrcl>,
|
||||
<&cpr_ro_sel2_pwrcl>,
|
||||
<&cpr_ro_sel3_pwrcl>,
|
||||
<&cpr_quot0_perfcl>,
|
||||
<&cpr_quot1_perfcl>,
|
||||
<&cpr_quot2_perfcl>,
|
||||
<&cpr_quot3_perfcl>,
|
||||
<&cpr_quot_offset1_perfcl>,
|
||||
<&cpr_quot_offset2_perfcl>,
|
||||
<&cpr_quot_offset3_perfcl>,
|
||||
<&cpr_init_voltage0_perfcl>,
|
||||
<&cpr_init_voltage1_perfcl>,
|
||||
<&cpr_init_voltage2_perfcl>,
|
||||
<&cpr_init_voltage3_perfcl>,
|
||||
<&cpr_ro_sel0_perfcl>,
|
||||
<&cpr_ro_sel1_perfcl>,
|
||||
<&cpr_ro_sel2_perfcl>,
|
||||
<&cpr_ro_sel3_perfcl>;
|
||||
|
||||
nvmem-cell-names = "cpr_speed_bin",
|
||||
"cpr_fuse_revision",
|
||||
"cpr0_quotient1",
|
||||
"cpr0_quotient2",
|
||||
"cpr0_quotient3",
|
||||
"cpr0_quotient4",
|
||||
"cpr0_quotient_offset2",
|
||||
"cpr0_quotient_offset3",
|
||||
"cpr0_quotient_offset4",
|
||||
"cpr0_init_voltage1",
|
||||
"cpr0_init_voltage2",
|
||||
"cpr0_init_voltage3",
|
||||
"cpr0_init_voltage4",
|
||||
"cpr0_ring_osc1",
|
||||
"cpr0_ring_osc2",
|
||||
"cpr0_ring_osc3",
|
||||
"cpr0_ring_osc4",
|
||||
"cpr1_quotient1",
|
||||
"cpr1_quotient2",
|
||||
"cpr1_quotient3",
|
||||
"cpr1_quotient4",
|
||||
"cpr1_quotient_offset2",
|
||||
"cpr1_quotient_offset3",
|
||||
"cpr1_quotient_offset4",
|
||||
"cpr1_init_voltage1",
|
||||
"cpr1_init_voltage2",
|
||||
"cpr1_init_voltage3",
|
||||
"cpr1_init_voltage4",
|
||||
"cpr1_ring_osc1",
|
||||
"cpr1_ring_osc2",
|
||||
"cpr1_ring_osc3",
|
||||
"cpr1_ring_osc4";
|
||||
};
|
||||
...
|
||||
|
|
@ -15967,9 +15967,15 @@ M: Niklas Cassel <nks@flawful.org>
|
|||
L: linux-pm@vger.kernel.org
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
|
||||
F: Documentation/devicetree/bindings/soc/qcom/qcom,cpr.yaml
|
||||
F: drivers/soc/qcom/cpr.c
|
||||
|
||||
QUALCOMM CORE POWER REDUCTION v3/v4/Hardened AVS DRIVER
|
||||
M: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/soc/qcom/qcom,cpr3.yaml
|
||||
F: drivers/soc/qcom/cpr3.c
|
||||
|
||||
QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
|
||||
M: Ilia Lin <ilia.lin@kernel.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 5
|
||||
PATCHLEVEL = 17
|
||||
SUBLEVEL = 0
|
||||
SUBLEVEL = 1
|
||||
EXTRAVERSION =
|
||||
NAME = Superb Owl
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "pmi8994.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
|
||||
#include <dt-bindings/sound/qcom,q6afe.h>
|
||||
#include <dt-bindings/sound/qcom,q6asm.h>
|
||||
|
|
@ -677,6 +678,54 @@
|
|||
};
|
||||
};
|
||||
|
||||
&pmi8994_lpg {
|
||||
qcom,power-source = <1>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pmi8994_mpp2_userled4>;
|
||||
|
||||
qcom,dtest = <0 0
|
||||
0 0
|
||||
0 0
|
||||
4 1>;
|
||||
|
||||
status = "okay";
|
||||
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
label = "green:user1";
|
||||
|
||||
linux,default-trigger = "heartbeat";
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
label = "green:user0";
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
label = "green:user2";
|
||||
};
|
||||
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
label = "green:user3";
|
||||
};
|
||||
};
|
||||
|
||||
&pmi8994_mpps {
|
||||
pmi8994_mpp2_userled4: mpp2-userled4-state {
|
||||
pins = "mpp2";
|
||||
function = "sink";
|
||||
|
||||
output-low;
|
||||
qcom,dtest = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
&pmi8994_spmi_regulators {
|
||||
vdd_s2-supply = <&vph_pwr>;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,15 @@
|
|||
chassis-type = "handset";
|
||||
qcom,board-id = <0x02000b 0x10>;
|
||||
|
||||
/* This part enables graphical output via bootloader-enabled display */
|
||||
chosen {
|
||||
bootargs = "earlycon=tty0 console=tty0 clk_ignore_unused";
|
||||
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
};
|
||||
|
||||
/*
|
||||
* Until we hook up type-c detection, we
|
||||
* have to stick with this. But it works.
|
||||
|
|
@ -46,6 +55,8 @@
|
|||
gpio-kb-extra-keys {
|
||||
compatible = "gpio-keys";
|
||||
label = "Keyboard extra keys";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio_kb_pins_extra>;
|
||||
|
||||
|
|
@ -98,6 +109,39 @@
|
|||
};
|
||||
};
|
||||
|
||||
gpio_keyboard: gpio-keyboard {
|
||||
compatible = "gpio-fastmatrix-keyboard";
|
||||
label = "F(x)Tec Pro1 Hardware Keyboard";
|
||||
row-gpios =
|
||||
<&gpioext0 0 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 1 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 2 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 3 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 4 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 5 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 6 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 7 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
|
||||
|
||||
col-gpios =
|
||||
<&gpioext0 8 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 9 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 10 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 11 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 12 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 13 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 14 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 15 GPIO_ACTIVE_LOW>;
|
||||
keypad,num-rows = <8>;
|
||||
keypad,num-columns = <8>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&keyboard_pins_col>, <&keyboard_pins_row>;
|
||||
|
||||
autorescan-ms = <5>;
|
||||
debounce-delay-ms = <1>;
|
||||
col-scan-delay-us = <1500>;
|
||||
};
|
||||
|
||||
gpio-keys {
|
||||
compatible = "gpio-keys";
|
||||
label = "Side buttons";
|
||||
|
|
@ -177,6 +221,53 @@
|
|||
};
|
||||
};
|
||||
|
||||
disp_vcc_vreg: disp-vcc-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_vcc";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
disp_vddio_vreg: disp-vddio-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_vddio";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
disp_vci_vreg: disp-vci-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_vci";
|
||||
regulator-min-microvolt = <3000000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
disp_elvdd_vreg: disp-elvdd-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_elvdd";
|
||||
regulator-min-microvolt = <4600000>;
|
||||
regulator-max-microvolt = <4600000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
disp_elvss_vreg: disp-elvss-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_elvss";
|
||||
regulator-min-microvolt = <2400000>;
|
||||
regulator-max-microvolt = <2400000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ts_vio_vreg: ts-vio-vreg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "ts_vio_reg";
|
||||
|
|
@ -189,8 +280,62 @@
|
|||
};
|
||||
};
|
||||
|
||||
&adreno_gpu {
|
||||
status = "ok";
|
||||
|
||||
zap-shader {
|
||||
memory-region = <&zap_shader_region>;
|
||||
firmware-name = "qcom/a540_zap.mbn";
|
||||
};
|
||||
};
|
||||
|
||||
&adreno_smmu {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&apc_cprh {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&blsp1_i2c6 {
|
||||
status = "ok";
|
||||
|
||||
gpioext0: gpio-expander@58 {
|
||||
compatible = "awinic,aw9523-pinctrl";
|
||||
reg = <0x58>;
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <50 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&gpioext0 0 0 16>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
pinctrl-0 = <&gpio_expander_int_n>, <&gpio_expander_rst_n>;
|
||||
pinctrl-names = "default";
|
||||
reset-gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
keyboard_pins_col: keyboard-matrix-col-pins {
|
||||
pins = "gpio8", "gpio9", "gpio10", "gpio11",
|
||||
"gpio12", "gpio13", "gpio14", "gpio15";
|
||||
function = "gpio";
|
||||
output-low;
|
||||
};
|
||||
keyboard_pins_row: keyboard-matrix-row-pins {
|
||||
pins = "gpio0", "gpio1", "gpio2", "gpio3",
|
||||
"gpio4", "gpio5", "gpio6", "gpio7";
|
||||
function = "gpio";
|
||||
drive-open-drain;
|
||||
input-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&blsp2_i2c1 {
|
||||
status = "ok";
|
||||
qcom,noise-reject-scl = <3>;
|
||||
qcom,noise-reject-sda = <3>;
|
||||
|
||||
touchscreen@14 {
|
||||
compatible = "goodix,gt9286";
|
||||
|
|
@ -205,6 +350,120 @@
|
|||
};
|
||||
};
|
||||
|
||||
&cpufreq_hw {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&dsi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "ok";
|
||||
|
||||
vdd-supply = <&vreg_l1a_0p875>;
|
||||
vdda-supply = <&vreg_l2a_1p2>;
|
||||
|
||||
panel: panel@0 {
|
||||
compatible = "boe,bf060y8m-aj0";
|
||||
reg = <0>;
|
||||
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
|
||||
disp-te-gpios = <&tlmm 10 GPIO_ACTIVE_LOW>;
|
||||
no-hpd;
|
||||
|
||||
vcc-supply = <&disp_vcc_vreg>;
|
||||
vddio-supply = <&disp_vddio_vreg>;
|
||||
vci-supply = <&disp_vci_vreg>;
|
||||
elvdd-supply = <&disp_elvdd_vreg>;
|
||||
elvss-supply = <&disp_elvss_vreg>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&panel_reset_n &disp_en_default &mdp_vsync_n>;
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&dsi0_phy {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&dsi0_out {
|
||||
remote-endpoint = <&panel_in>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
|
||||
&gcc {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&gpucc {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&gpio_keyboard {
|
||||
linux,keymap = <
|
||||
MATRIX_KEY(0, 0, KEY_F1) MATRIX_KEY(1, 0, KEY_H)
|
||||
MATRIX_KEY(2, 0, KEY_B) MATRIX_KEY(3, 0, KEY_7)
|
||||
MATRIX_KEY(4, 0, KEY_UP) MATRIX_KEY(5, 0, KEY_ENTER)
|
||||
MATRIX_KEY(6, 0, KEY_Y) MATRIX_KEY(7, 0, KEY_COMMA)
|
||||
MATRIX_KEY(0, 1, KEY_3) MATRIX_KEY(1, 1, KEY_S)
|
||||
MATRIX_KEY(2, 1, KEY_Z) MATRIX_KEY(3, 1, KEY_M)
|
||||
MATRIX_KEY(4, 1, KEY_I) MATRIX_KEY(5, 1, KEY_9)
|
||||
MATRIX_KEY(6, 1, KEY_W) MATRIX_KEY(7, 1, KEY_J)
|
||||
MATRIX_KEY(0, 2, KEY_LEFT) MATRIX_KEY(1, 2, KEY_G)
|
||||
MATRIX_KEY(2, 2, KEY_V) MATRIX_KEY(3, 2, KEY_6)
|
||||
MATRIX_KEY(4, 2, KEY_RIGHT) MATRIX_KEY(5, 2, KEY_DELETE)
|
||||
MATRIX_KEY(6, 2, KEY_T) MATRIX_KEY(7, 2, KEY_DOT)
|
||||
MATRIX_KEY(0, 3, KEY_SLASH) MATRIX_KEY(1, 3, KEY_A)
|
||||
MATRIX_KEY(2, 3, KEY_RIGHTBRACE) MATRIX_KEY(3, 3, KEY_HOMEPAGE)
|
||||
MATRIX_KEY(4, 3, KEY_P) MATRIX_KEY(5, 3, KEY_MINUS)
|
||||
MATRIX_KEY(6, 3, KEY_Q) MATRIX_KEY(7, 3, KEY_L)
|
||||
MATRIX_KEY(0, 4, KEY_BACKSPACE) MATRIX_KEY(1, 4, KEY_D)
|
||||
MATRIX_KEY(2, 4, KEY_X) MATRIX_KEY(3, 4, KEY_K)
|
||||
MATRIX_KEY(4, 4, KEY_SEMICOLON) MATRIX_KEY(5, 4, KEY_EQUAL)
|
||||
MATRIX_KEY(6, 4, KEY_E) MATRIX_KEY(7, 4, KEY_APOSTROPHE)
|
||||
MATRIX_KEY(0, 5, KEY_CAPSLOCK) MATRIX_KEY(1, 5, KEY_BACKSLASH)
|
||||
MATRIX_KEY(2, 5, KEY_LEFTBRACE) MATRIX_KEY(3, 5, KEY_DOWN)
|
||||
MATRIX_KEY(4, 5, KEY_O) MATRIX_KEY(5, 5, KEY_0)
|
||||
MATRIX_KEY(6, 5, KEY_GRAVE) MATRIX_KEY(7, 5, KEY_K)
|
||||
MATRIX_KEY(0, 6, KEY_SPACE) MATRIX_KEY(1, 6, KEY_F)
|
||||
MATRIX_KEY(2, 6, KEY_C) MATRIX_KEY(3, 6, KEY_N)
|
||||
MATRIX_KEY(4, 6, KEY_U) MATRIX_KEY(5, 6, KEY_8)
|
||||
MATRIX_KEY(6, 6, KEY_R) MATRIX_KEY(7, 6, KEY_5)
|
||||
MATRIX_KEY(0, 7, KEY_ESC) MATRIX_KEY(1, 7, KEY_1)
|
||||
MATRIX_KEY(2, 7, KEY_RESERVED) MATRIX_KEY(3, 7, KEY_RESERVED)
|
||||
MATRIX_KEY(4, 7, KEY_2) MATRIX_KEY(5, 7, KEY_4)
|
||||
MATRIX_KEY(6, 7, KEY_TAB) MATRIX_KEY(7, 7, KEY_RESERVED)
|
||||
>;
|
||||
};
|
||||
|
||||
&mdss {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&mdss_mdp {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&remoteproc_adsp {
|
||||
status = "okay";
|
||||
|
||||
firmware-name = "qcom/msm8998/fxtec/adsp.mbn";
|
||||
};
|
||||
|
||||
&remoteproc_mss {
|
||||
firmware-name = "qcom/msm8998/fxtec/mba.mbn", "qcom/msm8998/fxtec/modem.mbn";
|
||||
};
|
||||
|
||||
&remoteproc_slpi {
|
||||
status = "okay";
|
||||
|
||||
firmware-name = "qcom/msm8998/fxtec/slpi_v2.mbn";
|
||||
};
|
||||
|
||||
&mmcc {
|
||||
status = "ok";
|
||||
};
|
||||
|
|
@ -213,7 +472,35 @@
|
|||
status = "ok";
|
||||
};
|
||||
|
||||
&pmi8998_haptics {
|
||||
status = "okay";
|
||||
|
||||
qcom,wave-play-rate-us = <5000>;
|
||||
};
|
||||
|
||||
/* HACK! Push GPU voltage high until GPU CPR is hooked up */
|
||||
&pm8005_s1 {
|
||||
regulator-min-microvolt = <988000>;
|
||||
regulator-max-microvolt = <1100000>;
|
||||
};
|
||||
|
||||
&pmi8998_fg {
|
||||
status = "okay";
|
||||
|
||||
qcom,max-voltage-uv = <4400000>;
|
||||
qcom,min-voltage-uv = <3700000>;
|
||||
qcom,battery-capacity-ua = <3150000>;
|
||||
};
|
||||
|
||||
&pm8998_gpio {
|
||||
unknown_pin_a: unk-active {
|
||||
pins = "gpio5";
|
||||
function = "normal";
|
||||
input-enable;
|
||||
bias-pull-up;
|
||||
qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>;
|
||||
};
|
||||
|
||||
vol_up_pin_a: vol-up-active {
|
||||
pins = "gpio6";
|
||||
function = "normal";
|
||||
|
|
@ -267,6 +554,26 @@
|
|||
bias-pull-up;
|
||||
};
|
||||
|
||||
gpio_expander_int_n: gpio-exp-intn-def {
|
||||
pins = "gpio50";
|
||||
function = "gpio";
|
||||
drive-strength = <2>;
|
||||
input-enable;
|
||||
};
|
||||
|
||||
gpio_expander_rst_n: gpio-exp-rst-def {
|
||||
pins = "gpio51";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
};
|
||||
|
||||
disp_en_default: disp-en {
|
||||
pins = "gpio62";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
ts_vio_default: ts-vio-def {
|
||||
pins = "gpio81";
|
||||
function = "gpio";
|
||||
|
|
@ -295,6 +602,13 @@
|
|||
bias-disable;
|
||||
drive-strength = <8>;
|
||||
};
|
||||
|
||||
panel_reset_n: panel-rst-n {
|
||||
pins = "gpio94";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
&ufshc {
|
||||
|
|
|
|||
|
|
@ -41,3 +41,19 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* Capacitive keypad buttons */
|
||||
&rmi4_i2c {
|
||||
rmi4-f1a@1a {
|
||||
reg = <0x1a>;
|
||||
syna,codes = <KEY_BACK KEY_APPSELECT>;
|
||||
};
|
||||
};
|
||||
|
||||
/* Display */
|
||||
&panel {
|
||||
compatible = "samsung,s6e3fa5";
|
||||
|
||||
/* The panel is mounted upside down on the OnePlus 5 */
|
||||
rotation = <180>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
|
||||
#include "msm8998.dtsi"
|
||||
#include "pm8998.dtsi"
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
height = <1920>;
|
||||
stride = <(1080 * 4)>;
|
||||
format = "a8r8g8b8";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -152,10 +154,18 @@
|
|||
reg = <0x0 0x95715000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
&apc_cprh {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&cpufreq_hw {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&blsp1_i2c5 {
|
||||
status = "okay";
|
||||
|
||||
touchscreen@20 {
|
||||
rmi4_i2c: touchscreen@20 {
|
||||
compatible = "syna,rmi4-i2c";
|
||||
reg = <0x20>;
|
||||
#address-cells = <1>;
|
||||
|
|
@ -188,6 +198,29 @@
|
|||
};
|
||||
};
|
||||
|
||||
&blsp1_i2c5_sleep {
|
||||
/delete-property/ bias-pull-up;
|
||||
/* Configure a no-pull on TP I2C sleep to match downstream. */
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
&blsp1_i2c6 {
|
||||
status = "okay";
|
||||
|
||||
nfc@28 {
|
||||
compatible = "nxp,nxp-nci-i2c";
|
||||
reg = <0x28>;
|
||||
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <92 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
enable-gpios = <&tlmm 116 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&nfc_int_active &nfc_enable_active>;
|
||||
};
|
||||
};
|
||||
|
||||
&blsp1_uart3 {
|
||||
status = "okay";
|
||||
|
||||
|
|
@ -224,10 +257,35 @@
|
|||
};
|
||||
};
|
||||
|
||||
&blsp2_i2c3 {
|
||||
status = "disabled";
|
||||
|
||||
audio-codec@36 {
|
||||
compatible = "nxp,tfa9890";
|
||||
reg = <0x36>;
|
||||
|
||||
/*
|
||||
* vddd-supply = <&vreg_bob>;
|
||||
* vreg_l20a_2p95? 2950000->2960000 mV @ 200->800000 mA?
|
||||
*/
|
||||
|
||||
sound-name-prefix = "Mono Speaker";
|
||||
#sound-dai-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
&blsp2_uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&ipa {
|
||||
status = "okay";
|
||||
|
||||
memory-region = <&ipa_fws_region>; // ipa_fw_mem? ipa_gsi_mem?
|
||||
firmware-name = "qcom/msm8998/oneplus/ipa_fws.mbn";
|
||||
};
|
||||
|
||||
&pm8005_lsid1 {
|
||||
pm8005-regulators {
|
||||
compatible = "qcom,pm8005-regulators";
|
||||
|
|
@ -257,6 +315,49 @@
|
|||
};
|
||||
};
|
||||
|
||||
&pmi8998_fg {
|
||||
status = "okay";
|
||||
|
||||
qcom,max-voltage-uv = <4370000>;
|
||||
qcom,min-voltage-uv = <3700000>;
|
||||
qcom,battery-capacity-ua = <3300000>;
|
||||
};
|
||||
|
||||
&pmi8998_lpg {
|
||||
status = "okay";
|
||||
|
||||
//qcom,power-source = <0>;
|
||||
|
||||
notification-led {
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
};
|
||||
|
||||
led@5 {
|
||||
reg = <5>;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pmi8998_haptics {
|
||||
status = "okay";
|
||||
|
||||
qcom,wave-play-rate-us = <4255>;
|
||||
};
|
||||
|
||||
&qusb2phy {
|
||||
status = "okay";
|
||||
|
||||
|
|
@ -269,30 +370,18 @@
|
|||
pm8998-regulators {
|
||||
compatible = "qcom,rpm-pm8998-regulators";
|
||||
|
||||
vdd_s1-supply = <&vph_pwr>;
|
||||
vdd_s2-supply = <&vph_pwr>;
|
||||
vdd_s1-supply = <&vph_pwr>; /* GPU? */
|
||||
vdd_s3-supply = <&vph_pwr>;
|
||||
vdd_s4-supply = <&vph_pwr>;
|
||||
vdd_s5-supply = <&vph_pwr>;
|
||||
vdd_s6-supply = <&vph_pwr>;
|
||||
vdd_s7-supply = <&vph_pwr>;
|
||||
vdd_s8-supply = <&vph_pwr>;
|
||||
vdd_s9-supply = <&vph_pwr>;
|
||||
vdd_s10-supply = <&vph_pwr>;
|
||||
vdd_s11-supply = <&vph_pwr>;
|
||||
vdd_s12-supply = <&vph_pwr>;
|
||||
vdd_s13-supply = <&vph_pwr>;
|
||||
vdd_l1_l27-supply = <&vreg_s7a_1p025>;
|
||||
vdd_l2_l8_l17-supply = <&vreg_s3a_1p35>;
|
||||
vdd_l3_l11-supply = <&vreg_s7a_1p025>;
|
||||
vdd_l4_l5-supply = <&vreg_s7a_1p025>;
|
||||
vdd_l1-supply = <&vreg_s7a_1p025>;
|
||||
vdd_l2_l17-supply = <&vreg_s3a_1p35>;
|
||||
vdd_l5-supply = <&vreg_s7a_1p025>;
|
||||
vdd_l6-supply = <&vreg_s5a_2p04>;
|
||||
vdd_l7_l12_l14_l15-supply = <&vreg_s5a_2p04>;
|
||||
vdd_l9-supply = <&vreg_bob>;
|
||||
vdd_l10_l23_l25-supply = <&vreg_bob>;
|
||||
vdd_l13_l19_l21-supply = <&vreg_bob>;
|
||||
vdd_l16_l28-supply = <&vreg_bob>;
|
||||
vdd_l18_l22-supply = <&vreg_bob>;
|
||||
vdd_l7_l12_l14-supply = <&vreg_s5a_2p04>;
|
||||
vdd_l25-supply = <&vreg_bob>;
|
||||
vdd_l28-supply = <&vreg_bob>;
|
||||
vdd_l20_l24-supply = <&vreg_bob>;
|
||||
vdd_l26-supply = <&vreg_s3a_1p35>;
|
||||
vdd_lvs1_lvs2-supply = <&vreg_s4a_1p8>;
|
||||
|
|
@ -314,111 +403,57 @@
|
|||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <1028000>;
|
||||
};
|
||||
vreg_l1a_0p875: l1 {
|
||||
vreg_l1a_0p875: l1 { /* UFS PHY */
|
||||
regulator-min-microvolt = <880000>;
|
||||
regulator-max-microvolt = <880000>;
|
||||
};
|
||||
vreg_l2a_1p2: l2 {
|
||||
vreg_l2a_1p2: l2 { /* UFS PHY */
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
};
|
||||
vreg_l3a_1p0: l3 {
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <1000000>;
|
||||
};
|
||||
vreg_l5a_0p8: l5 {
|
||||
vreg_l5a_0p8: l5 { /* Wi-Fi */
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <800000>;
|
||||
};
|
||||
vreg_l6a_1p8: l6 {
|
||||
vreg_l6a_1p8: l6 { /* Touchscreen */
|
||||
regulator-min-microvolt = <1808000>;
|
||||
regulator-max-microvolt = <1808000>;
|
||||
};
|
||||
vreg_l7a_1p8: l7 {
|
||||
vreg_l7a_1p8: l7 { /* Wi-Fi + BT */
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
};
|
||||
vreg_l8a_1p2: l8 {
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
};
|
||||
vreg_l9a_1p8: l9 {
|
||||
regulator-min-microvolt = <1808000>;
|
||||
regulator-max-microvolt = <2960000>;
|
||||
};
|
||||
vreg_l10a_1p8: l10 {
|
||||
regulator-min-microvolt = <1808000>;
|
||||
regulator-max-microvolt = <2960000>;
|
||||
};
|
||||
vreg_l11a_1p0: l11 {
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <1000000>;
|
||||
};
|
||||
vreg_l12a_1p8: l12 {
|
||||
vreg_l12a_1p8: l12 { /* QUSB2 PHY */
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
};
|
||||
vreg_l13a_2p95: l13 {
|
||||
regulator-min-microvolt = <1808000>;
|
||||
regulator-max-microvolt = <2960000>;
|
||||
};
|
||||
vreg_l14a_1p88: l14 {
|
||||
vreg_l14a_1p88: l14 { /* DSI display */
|
||||
regulator-min-microvolt = <1880000>;
|
||||
regulator-max-microvolt = <1880000>;
|
||||
};
|
||||
vreg_l15a_1p8: l15 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
};
|
||||
vreg_l16a_2p7: l16 {
|
||||
regulator-min-microvolt = <2704000>;
|
||||
regulator-max-microvolt = <2704000>;
|
||||
};
|
||||
vreg_l17a_1p3: l17 {
|
||||
vreg_l17a_1p3: l17 { /* Wi-Fi + BT */
|
||||
regulator-min-microvolt = <1304000>;
|
||||
regulator-max-microvolt = <1304000>;
|
||||
};
|
||||
vreg_l18a_2p7: l18 {
|
||||
regulator-min-microvolt = <2704000>;
|
||||
regulator-max-microvolt = <2704000>;
|
||||
};
|
||||
vreg_l19a_3p0: l19 {
|
||||
regulator-min-microvolt = <3008000>;
|
||||
regulator-max-microvolt = <3008000>;
|
||||
};
|
||||
vreg_l20a_2p95: l20 {
|
||||
vreg_l20a_2p95: l20 { /* UFS HC */
|
||||
regulator-min-microvolt = <2960000>;
|
||||
regulator-max-microvolt = <2960000>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
vreg_l21a_2p95: l21 {
|
||||
regulator-min-microvolt = <2960000>;
|
||||
regulator-max-microvolt = <2960000>;
|
||||
regulator-allow-set-load;
|
||||
regulator-system-load = <800000>;
|
||||
};
|
||||
vreg_l22a_2p85: l22 {
|
||||
regulator-min-microvolt = <2864000>;
|
||||
regulator-max-microvolt = <2864000>;
|
||||
};
|
||||
vreg_l23a_3p3: l23 {
|
||||
regulator-min-microvolt = <3312000>;
|
||||
regulator-max-microvolt = <3312000>;
|
||||
};
|
||||
vreg_l24a_3p075: l24 {
|
||||
vreg_l24a_3p075: l24 { /* QUSB2 PHY */
|
||||
regulator-min-microvolt = <3088000>;
|
||||
regulator-max-microvolt = <3088000>;
|
||||
};
|
||||
vreg_l25a_3p3: l25 {
|
||||
vreg_l25a_3p3: l25 { /* Wi-Fi + BT */
|
||||
regulator-min-microvolt = <3104000>;
|
||||
regulator-max-microvolt = <3312000>;
|
||||
};
|
||||
vreg_l26a_1p2: l26 {
|
||||
vreg_l26a_1p2: l26 { /* UFS PHY + HC */
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
vreg_l28_3p0: l28 {
|
||||
vreg_l28_3p0: l28 { /* Touchscreen */
|
||||
regulator-min-microvolt = <3008000>;
|
||||
regulator-max-microvolt = <3008000>;
|
||||
};
|
||||
|
|
@ -438,9 +473,145 @@
|
|||
};
|
||||
};
|
||||
|
||||
&remoteproc_adsp {
|
||||
status = "okay";
|
||||
|
||||
firmware-name = "qcom/msm8998/oneplus/adsp.mbn";
|
||||
};
|
||||
|
||||
&remoteproc_mss {
|
||||
status = "okay";
|
||||
|
||||
firmware-name = "qcom/msm8998/oneplus/mba.mbn", "qcom/msm8998/oneplus/modem.mbn";
|
||||
};
|
||||
|
||||
&remoteproc_slpi {
|
||||
status = "okay";
|
||||
|
||||
firmware-name = "qcom/msm8998/oneplus/slpi_v2.mbn";
|
||||
};
|
||||
|
||||
&mmcc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmss_smmu {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdss {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdss_mdp {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dsi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
|
||||
vdd-supply = <&vreg_l1a_0p875>;
|
||||
vdda-supply = <&vreg_l2a_1p2>;
|
||||
|
||||
panel: panel@0 {
|
||||
reg = <0>;
|
||||
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
|
||||
disp-te-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>;
|
||||
|
||||
vddio-supply = <&vreg_l14a_1p88>; // TODO: Could this be moved under dsi0?
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&panel_reset_n &disp_en_default &mdp_vsync_n>;
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&dsi0_phy {
|
||||
status = "okay";
|
||||
vdds-supply = <&vreg_l1a_0p875>;
|
||||
};
|
||||
|
||||
&dsi0_out {
|
||||
remote-endpoint = <&panel_in>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
|
||||
/* Adreno 540 GPU */
|
||||
&gpucc {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&gpu_mem {
|
||||
compatible = "shared-dma-pool";
|
||||
};
|
||||
|
||||
&adreno_gpu {
|
||||
status = "ok";
|
||||
|
||||
zap-shader {
|
||||
memory-region = <&zap_shader_region>; // gpu_mem?
|
||||
firmware-name = "qcom/msm8998/oneplus/a540_zap.mbn";
|
||||
};
|
||||
|
||||
/*
|
||||
* We are lacking support for the GPU regulator. Hence, disable higher
|
||||
* frequencies for now to prevent the platform from hanging on high
|
||||
* graphics loads. Perhaps the pm8005_s1 voltage below could be
|
||||
* adjusted but I'd rather not touch it.
|
||||
*/
|
||||
opp-table {
|
||||
/delete-node/ opp-710000097;
|
||||
/delete-node/ opp-670000048;
|
||||
/delete-node/ opp-596000097;
|
||||
/delete-node/ opp-515000097;
|
||||
};
|
||||
};
|
||||
|
||||
&adreno_smmu {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
/*
|
||||
* HACK: Shoot GPU voltage high to stabilize Adreno 540 at high frequencies
|
||||
* until the GPU CPR is brought up.
|
||||
*/
|
||||
&pm8005_s1 {
|
||||
regulator-min-microvolt = <988000>; /* 0,524V -> 0,988V */
|
||||
//regulator-max-microvolt = <1100000>;
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
gpio-reserved-ranges = <0 4>, <81 4>;
|
||||
|
||||
disp_en_default: disp-en {
|
||||
pins = "gpio62";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
panel_reset_n: panel-rst-n {
|
||||
pins = "gpio94";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
mdp_vsync_n: mdp-vsync-n {
|
||||
pins = "gpio11";
|
||||
function = "mdp_vsync_a";
|
||||
drive-strength = <2>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
hall_sensor_default: hall-sensor-default {
|
||||
pins = "gpio124";
|
||||
function = "gpio";
|
||||
|
|
@ -462,6 +633,20 @@
|
|||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
nfc_int_active: nfc_int_active {
|
||||
pins = "gpio92";
|
||||
function = "gpio";
|
||||
drive-strength = <6>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
nfc_enable_active: nfc_enable_active {
|
||||
pins = "gpio12", "gpio116";
|
||||
function = "gpio";
|
||||
drive-strength = <6>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
&ufshc {
|
||||
|
|
@ -503,7 +688,7 @@
|
|||
};
|
||||
|
||||
&wifi {
|
||||
/* Leave disabled until MSS is functional */
|
||||
status = "okay";
|
||||
vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
|
||||
vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
|
||||
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
|
||||
|
|
|
|||
|
|
@ -24,3 +24,8 @@
|
|||
&rmi4_f12 {
|
||||
touchscreen-y-mm = <137>;
|
||||
};
|
||||
|
||||
/* Display */
|
||||
&panel {
|
||||
compatible = "samsung,s6e3fc1";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@
|
|||
qcom,soft-start-us = <800>;
|
||||
};
|
||||
|
||||
&wcd9335 {
|
||||
pinctrl-0 = <&cdc_reset_n &wcd_int_n>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
&vreg_l22a_2p85 {
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,28 @@
|
|||
};
|
||||
};
|
||||
|
||||
&dsi0 {
|
||||
qcom,dual-dsi-mode;
|
||||
qcom,master-dsi;
|
||||
};
|
||||
|
||||
&dsi1 {
|
||||
vdd-supply = <&vreg_l1a_0p875>;
|
||||
vdda-supply = <&vreg_l2a_1p2>;
|
||||
qcom,dual-dsi-mode;
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&dsi1_out {
|
||||
remote-endpoint = <&panel_in1>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
|
||||
&dsi1_phy {
|
||||
vdds-supply = <&vreg_l1a_0p875>;
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&ibb {
|
||||
regulator-min-microvolt = <5600000>;
|
||||
regulator-max-microvolt = <5600000>;
|
||||
|
|
@ -37,6 +59,32 @@
|
|||
qcom,soft-start-us = <200>;
|
||||
};
|
||||
|
||||
&panel {
|
||||
compatible = "sharp,ls055d1sx04";
|
||||
|
||||
dvdd-supply = <&disp_dvdd_vreg>;
|
||||
ports {
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
panel_in1: endpoint {
|
||||
remote-endpoint = <&dsi1_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pm8005_gpio {
|
||||
ear_en_default: ear-en-active {
|
||||
pins = "gpio1";
|
||||
function = "normal";
|
||||
bias-disable;
|
||||
drive-push-pull;
|
||||
output-high;
|
||||
power-source = <1>; /* 1.8V */
|
||||
qcom,drive-strength = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
&pmi8998_gpio {
|
||||
disp_dvdd_en: disp-dvdd-en-active {
|
||||
pins = "gpio10";
|
||||
|
|
@ -53,3 +101,17 @@
|
|||
regulator-min-microvolt = <2704000>;
|
||||
regulator-max-microvolt = <2704000>;
|
||||
};
|
||||
|
||||
|
||||
&pmi8998_wled {
|
||||
status = "okay";
|
||||
|
||||
//qcom,auto-string-detection;
|
||||
qcom,num-strings = <3>;
|
||||
qcom,enabled-strings = <0 1 2>;
|
||||
};
|
||||
|
||||
&wcd9335 {
|
||||
pinctrl-0 = <&cdc_reset_n &wcd_int_n &ear_en_default>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@
|
|||
qcom,soft-start-us = <800>;
|
||||
};
|
||||
|
||||
&wcd9335 {
|
||||
pinctrl-0 = <&cdc_reset_n &wcd_int_n>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
&vreg_l18a_2p85 {
|
||||
regulator-min-microvolt = <2850000>;
|
||||
regulator-max-microvolt = <2850000>;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@
|
|||
qcom,msm-id = <0x124 0x20000>, <0x124 0x20001>; /* 8998v2, v2.1 */
|
||||
qcom,board-id = <8 0>;
|
||||
|
||||
chosen {
|
||||
bootargs = "clk_ignore_unused root=/dev/mmcblk0p1";
|
||||
};
|
||||
|
||||
clocks {
|
||||
compatible = "simple-bus";
|
||||
|
||||
|
|
@ -84,6 +88,15 @@
|
|||
pinctrl-0 = <&ts_vddio_en>;
|
||||
};
|
||||
|
||||
/* The gpio-vibrator driver enforces requiring a regulator */
|
||||
vib_vreg: vib-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vib";
|
||||
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
vph_pwr: vph-pwr-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vph_pwr";
|
||||
|
|
@ -184,11 +197,28 @@
|
|||
vibrator {
|
||||
compatible = "gpio-vibrator";
|
||||
enable-gpios = <&pmi8998_gpio 5 GPIO_ACTIVE_HIGH>;
|
||||
vcc-supply = <&vib_vreg>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&vib_default>;
|
||||
};
|
||||
};
|
||||
|
||||
&adreno_gpu {
|
||||
status = "ok";
|
||||
|
||||
zap-shader {
|
||||
memory-region = <&zap_shader_region>;
|
||||
};
|
||||
};
|
||||
|
||||
&adreno_smmu {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&apc_cprh {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&blsp1_i2c5 {
|
||||
status = "okay";
|
||||
clock-frequency = <355000>;
|
||||
|
|
@ -241,10 +271,79 @@
|
|||
};
|
||||
};
|
||||
|
||||
&blsp2_i2c1 {
|
||||
tof-sensor@29 {
|
||||
compatible = "st,vl53l0x";
|
||||
reg = <0x29>;
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
|
||||
#io-channel-cells = <1>;
|
||||
label = "back_camera_tof";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&tof_int_n &tof_rst_n>;
|
||||
};
|
||||
};
|
||||
|
||||
&blsp2_uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&cpufreq_hw {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&dsi0 {
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
vdd-supply = <&vreg_l1a_0p875>;
|
||||
vdda-supply = <&vreg_l2a_1p2>;
|
||||
|
||||
panel: panel@0 {
|
||||
reg = <0>;
|
||||
|
||||
backlight = <&pmi8998_wled>;
|
||||
disp-te-gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
avdd-supply = <&lab>;
|
||||
avee-supply = <&ibb>;
|
||||
vddio-supply = <&vreg_l14a_1p85>;
|
||||
tavdd-supply = <&vreg_l28_3p0>;
|
||||
tvddio-supply = <&touch_vddio_vreg>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&panel_reset_n &mdp_vsync_n>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
panel_in0: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&dsi0_out {
|
||||
remote-endpoint = <&panel_in0>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
|
||||
&dsi0_phy {
|
||||
status = "okay";
|
||||
vdds-supply = <&vreg_l1a_0p875>;
|
||||
};
|
||||
|
||||
&gpucc {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&ibb {
|
||||
regulator-min-microamp = <800000>;
|
||||
regulator-max-microamp = <800000>;
|
||||
|
|
@ -270,6 +369,25 @@
|
|||
regulator-soft-start;
|
||||
};
|
||||
|
||||
&lpass_q6_smmu {
|
||||
qcom,bypass-cbndx = /bits/ 8 <11>;
|
||||
qcom,reset-nodisable-cbs = /bits/ 8 <12>;
|
||||
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&mmcc {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&mmss_smmu {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&mdss {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmcc {
|
||||
status = "ok";
|
||||
};
|
||||
|
|
@ -286,7 +404,12 @@
|
|||
|
||||
/* VDD_GFX supply */
|
||||
pm8005_s1: s1 {
|
||||
regulator-min-microvolt = <524000>;
|
||||
/*
|
||||
* HACK: Set enough voltage for max GPU frequency
|
||||
* and set the regulator always on until the
|
||||
* GPU Core Power Reduction gets available
|
||||
*/
|
||||
regulator-min-microvolt = <988000>;
|
||||
regulator-max-microvolt = <1088000>;
|
||||
regulator-enable-ramp-delay = <500>;
|
||||
regulator-always-on;
|
||||
|
|
@ -324,6 +447,13 @@
|
|||
function = "func2";
|
||||
power-source = <0>;
|
||||
};
|
||||
|
||||
nfc_clk_req_pin: nfc-clk-req-active {
|
||||
pins = "gpio21";
|
||||
function = PMIC_GPIO_FUNC_NORMAL;
|
||||
input-enable;
|
||||
power-source = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
&pmi8998_gpio {
|
||||
|
|
@ -358,6 +488,37 @@
|
|||
};
|
||||
};
|
||||
|
||||
&pmi8998_wled {
|
||||
status = "okay";
|
||||
|
||||
default-brightness = <800>;
|
||||
qcom,switching-freq = <800>;
|
||||
qcom,ovp-millivolt = <29600>;
|
||||
qcom,current-boost-limit = <970>;
|
||||
qcom,current-limit-microamp = <25000>;
|
||||
qcom,num-strings = <2>;
|
||||
qcom,enabled-strings = <0 1>;
|
||||
};
|
||||
|
||||
&q6asmdai {
|
||||
dai@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
dai@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
dai@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
dai@3 {
|
||||
reg = <3>;
|
||||
// direction = <2>;
|
||||
// is-compress-dai;
|
||||
};
|
||||
};
|
||||
|
||||
&qusb2phy {
|
||||
status = "okay";
|
||||
|
||||
|
|
@ -365,6 +526,19 @@
|
|||
vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
|
||||
};
|
||||
|
||||
&remoteproc_adsp {
|
||||
firmware-name = "adsp.mdt";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&remoteproc_mss {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&remoteproc_slpi {
|
||||
firmware-name = "slpi.mdt";
|
||||
};
|
||||
|
||||
&rpm_requests {
|
||||
pm8998-regulators {
|
||||
compatible = "qcom,rpm-pm8998-regulators";
|
||||
|
|
@ -553,6 +727,371 @@
|
|||
pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
|
||||
};
|
||||
|
||||
/* EAR-EN is NXP NX5L2750C */
|
||||
|
||||
/* Downstream example
|
||||
&snd_9335 {
|
||||
qcom,msm-mbhc-hphl-swh = <1>;
|
||||
/delete-property/ qcom,hph-en1-gpio;
|
||||
/delete-property/ qcom,hph-en0-gpio;
|
||||
/delete-property/ qcom,us-euro-gpios;
|
||||
qcom,ear-en-gpios = <&pm8005_gpios 1 0>;
|
||||
qcom,audio-routing =
|
||||
"AIF4 VI", "MCLK",
|
||||
"RX_BIAS", "MCLK",
|
||||
"MADINPUT", "MCLK",
|
||||
"AMIC2", "MIC BIAS2",
|
||||
"MIC BIAS2", "Headset Mic",
|
||||
"MIC BIAS2", "ANCRight Headset Mic",
|
||||
"AMIC3", "MIC BIAS3",
|
||||
"MIC BIAS3", "ANCLeft Headset Mic",
|
||||
"DMIC0", "MIC BIAS1",
|
||||
"MIC BIAS1", "Digital Mic0",
|
||||
"DMIC3", "MIC BIAS4",
|
||||
"MIC BIAS4", "Digital Mic3",
|
||||
"SpkrLeft IN", "SPK1 OUT",
|
||||
"SpkrRight IN", "SPK2 OUT";
|
||||
};
|
||||
*/
|
||||
|
||||
&slimbam {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&slim {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&slim_ngd {
|
||||
tasha_ifd: tas-ifd {
|
||||
compatible = "slim217,1a0";
|
||||
reg = <0 0>;
|
||||
};
|
||||
|
||||
wcd9335: codec@1{
|
||||
compatible = "slim217,1a0";
|
||||
reg = <1 0>;
|
||||
|
||||
clock-names = "mclk", "slimbus";
|
||||
clocks = <&div1_mclk>,
|
||||
<&rpmcc RPM_SMD_LN_BB_CLK1>;
|
||||
#clock-cells = <0>;
|
||||
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <54 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<53 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "intr1", "intr2";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
reset-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
slim-ifc-dev = <&tasha_ifd>;
|
||||
|
||||
vdd-buck-supply = <&vreg_s4a_1p8>;
|
||||
vdd-buck-sido-supply = <&vreg_s4a_1p8>;
|
||||
vdd-tx-supply = <&vreg_s4a_1p8>;
|
||||
vdd-rx-supply = <&vreg_s4a_1p8>;
|
||||
vdd-io-supply = <&vreg_s4a_1p8>;
|
||||
qcom,mbhc-vthreshold = <1700>;
|
||||
|
||||
/* On SoMC Yoshino, HPHL is normally open, GND normally closed */
|
||||
qcom,hphl-jack-type-normally-open;
|
||||
//qcom,gnd-jack-type-normally-open;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#sound-dai-cells = <1>;
|
||||
|
||||
swm: swm@c85 {
|
||||
compatible = "qcom,soundwire-v1.3.0";
|
||||
reg = <0xc85 0x40>;
|
||||
interrupts-extended = <&wcd9335 13>;
|
||||
|
||||
qcom,dout-ports = <6>;
|
||||
qcom,din-ports = <2>;
|
||||
qcom,ports-sinterval-low =/bits/ 8 <0x07 0x1F 0x3F 0x7 0x1F 0x3F 0x0F 0x0F>;
|
||||
qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x0C 0x6 0x12 0x0D 0x07 0x0A >;
|
||||
qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x1F 0x00 0x00 0x1F 0x00 0x00>;
|
||||
/*downstream is <0xFF 0x00 0x1F 0xFF 0x00 0x1F 0x00 0x00>;*/
|
||||
qcom,ports-block-pack-mode = /bits/ 8 <0xFF 0xFF 0x01 0xFF 0xFF 0x01 0xFF 0xFF>;
|
||||
clocks = <&xo>;
|
||||
clock-names = "iface";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
#sound-dai-cells = <1>;
|
||||
|
||||
left_spkr: wsa8810-left {
|
||||
compatible = "sdw10217201000";
|
||||
reg = <0 1>;
|
||||
powerdown-gpios = <&tlmm 65 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-0 = <&wsa_leftspk_pwr_n>;
|
||||
pinctrl-names = "default";
|
||||
#thermal-sensor-cells = <0>;
|
||||
sound-name-prefix = "SpkrRight";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
|
||||
right_spkr: wsa8810-right {
|
||||
compatible = "sdw10217201000";
|
||||
powerdown-gpios = <&tlmm 66 GPIO_ACTIVE_HIGH>;
|
||||
reg = <0 2>;
|
||||
pinctrl-0 = <&wsa_rightspk_pwr_n>;
|
||||
pinctrl-names = "default";
|
||||
#thermal-sensor-cells = <0>;
|
||||
sound-name-prefix = "SpkrLeft";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* NOTES */
|
||||
/*
|
||||
# This is Dragonboard 820C
|
||||
EnableSequence [
|
||||
cset "name='SLIM RX0 MUX' ZERO"
|
||||
cset "name='SLIM RX1 MUX' ZERO"
|
||||
cset "name='SLIM RX2 MUX' ZERO"
|
||||
cset "name='SLIM RX3 MUX' ZERO"
|
||||
cset "name='SLIM RX4 MUX' ZERO"
|
||||
cset "name='SLIM RX5 MUX' AIF4_PB"
|
||||
cset "name='SLIM RX6 MUX' AIF4_PB"
|
||||
cset "name='SLIM RX7 MUX' ZERO"
|
||||
cset "name='RX INT1_2 MUX' RX5"
|
||||
cset "name='RX INT2_2 MUX' RX6"
|
||||
## gain to 0dB
|
||||
cset "name='RX5 Digital Volume' 68"
|
||||
## gain to 0dB
|
||||
cset "name='RX6 Digital Volume' 68"
|
||||
cset "name='SLIMBUS_6_RX Audio Mixer MultiMedia2' 1"
|
||||
cset "name='RX INT1 DEM MUX' CLSH_DSM_OUT"
|
||||
cset "name='RX INT2 DEM MUX' CLSH_DSM_OUT"
|
||||
]
|
||||
|
||||
|
||||
######### WORKS!!!!!! SHE SPEEEEEAKS!!!!!!! #########
|
||||
tinymix set "SLIM RX2 MUX" ZERO
|
||||
tinymix set "SLIM RX3 MUX" ZERO
|
||||
tinymix set "SLIM RX4 MUX" ZERO
|
||||
tinymix set "SLIM RX5 MUX" ZERO
|
||||
tinymix set "SLIM RX6 MUX" ZERO
|
||||
tinymix set "SLIM RX7 MUX" ZERO
|
||||
tinymix set "SLIM RX0 MUX" AIF1_PB
|
||||
tinymix set "SLIM RX1 MUX" AIF1_PB
|
||||
tinymix set "RX INT1_2 MUX" RX0
|
||||
tinymix set "RX INT2_2 MUX" RX1
|
||||
tinymix set "RX INT1_1 MIX1 INP0" RX0
|
||||
tinymix set "RX INT2_1 MIX1 INP0" RX1
|
||||
tinymix set "SLIMBUS_0_RX Audio Mixer MultiMedia1" 1
|
||||
tinymix set "RX INT1 DEM MUX" CLSH_DSM_OUT
|
||||
tinymix set "RX INT2 DEM MUX" CLSH_DSM_OUT
|
||||
tinymix set "SLIM TX0 MUX" DEC0
|
||||
tinymix set "AIF1_CAP Mixer SLIM TX0" 1
|
||||
|
||||
tinymix set "RX INT2_1 MIX1 INP0" RX1
|
||||
tinymix set "RX INT1_1 MIX1 INP0" RX0
|
||||
tinymix set "RX INT1_1 MIX1 INP0" RX2
|
||||
tinymix set "RX INT1_1 MIX1 INP0" RX0
|
||||
tinymix set "RX INT1_1 MIX1 INP0" RX2
|
||||
tinymix set "RX INT2_1 MIX1 INP0" RX2
|
||||
tinymix set "RX INT2_1 MIX1 INP0" RX1
|
||||
tinymix set "RX INT1_1 MIX1 INP0" RX0
|
||||
tinymix set "RX INT0_1 MIX1 INP0" RX0
|
||||
tinymix set "RX INT0_1 MIX1 INP0" RX1
|
||||
tinymix set "RX INT0_1 MIX1 INP0" RX2
|
||||
tinymix set "RX INT0_1 MIX1 INP0" RX0
|
||||
tinymix set "RX INT3_1 MIX1 INP0" RX0
|
||||
tinymix set "RX INT4_1 MIX1 INP0" RX0
|
||||
tinymix set "RX INT5_1 MIX1 INP0" RX0
|
||||
tinymix set "RX INT6_1 MIX1 INP0" RX1
|
||||
tinymix set "RX INT7_1 MIX1 INP0" RX1
|
||||
tinymix set "RX INT7_1 MIX1 INP0" RX1
|
||||
tinymix set "RX INT8_1 MIX1 INP0" RX1
|
||||
tinymix set "RX INT0_1 MIX1 INP1" RX0
|
||||
tinymix set "RX INT0_1 MIX1 INP1" RX2
|
||||
tinymix set "RX INT0_1 MIX1 INP1" RX0
|
||||
tinymix set "RX INT1_1 MIX1 INP1" RX0
|
||||
tinymix set "RX INT2_1 MIX1 INP1" RX0
|
||||
tinymix set "RX INT3_1 MIX1 INP1" RX0
|
||||
tinymix set "RX INT4_1 MIX1 INP1" RX0
|
||||
tinymix set "RX INT5_1 MIX1 INP1" RX0
|
||||
tinymix set "RX INT6_1 MIX1 INP1" RX0
|
||||
tinymix set "RX INT7_1 MIX1 INP1" RX0
|
||||
tinymix set "RX INT8_1 MIX1 INP1" RX0
|
||||
tinymix set "RX INT0_1 MIX1 INP2" RX1
|
||||
tinymix set "RX INT1_1 MIX1 INP2" RX1
|
||||
tinymix set "RX INT2_1 MIX1 INP2" RX1
|
||||
tinymix set "RX INT3_1 MIX1 INP2" RX1
|
||||
tinymix set "RX INT4_1 MIX1 INP2" RX1
|
||||
tinymix set "RX INT5_1 MIX1 INP2" RX1
|
||||
tinymix set "RX INT6_1 MIX1 INP2" RX1
|
||||
tinymix set "RX INT7_1 MIX1 INP2" RX1
|
||||
tinymix set "RX INT8_1 MIX1 INP2" RX1
|
||||
tinymix set "RX INT8_1 MIX1 INP2" RX0
|
||||
tinymix set "RX INT7_1 MIX1 INP2" RX0
|
||||
tinymix set "RX INT6_1 MIX1 INP2" RX0
|
||||
|
||||
tinymix set "RX0 Digital Volume" 80
|
||||
tinymix set "RX1 Digital Volume" 80
|
||||
tinymix set "RX2 Digital Volume" 80
|
||||
|
||||
*/
|
||||
|
||||
&sound {
|
||||
compatible = "qcom,msm8998-sndcard";
|
||||
model = "Sony-Xperia-Yoshino";
|
||||
|
||||
/* Audio routing including WSA amp speakers */
|
||||
/* audio-routing = "RX_BIAS", "MCLK",
|
||||
"AMIC2", "MIC BIAS2",
|
||||
"AMIC3", "MIC BIAS3",
|
||||
"DMIC0", "MIC BIAS1",
|
||||
"DMIC4", "MIC BIAS4",
|
||||
"SpkrLeft IN", "SPK1 OUT",
|
||||
"SpkrRight IN", "SPK2 OUT",
|
||||
"MM_DL1", "MultiMedia1 Playback",
|
||||
"MM_DL2", "MultiMedia2 Playback",
|
||||
"MultiMedia3 Capture", "MM_UL3";
|
||||
*/
|
||||
|
||||
/* Basic routing, 3.5mm jack only */
|
||||
audio-routing = "RX_BIAS", "MCLK",
|
||||
"AMIC2", "MIC BIAS2",
|
||||
"AMIC3", "MIC BIAS3",
|
||||
"DMIC0", "MIC BIAS1",
|
||||
"DMIC4", "MIC BIAS4",
|
||||
"MM_DL1", "MultiMedia1 Playback",
|
||||
"MM_DL2", "MultiMedia2 Playback",
|
||||
"MultiMedia3 Capture", "MM_UL3";
|
||||
|
||||
/*
|
||||
<path name="voicemmode1-call headphones">
|
||||
<ctl name="SLIM_0_RX_Voice Mixer VoiceMMode1" value="1" />
|
||||
<ctl name="VoiceMMode1_Tx Mixer SLIM_0_TX_MMode1" value="1" />
|
||||
</path>
|
||||
|
||||
<path name="sidetone-headphones">
|
||||
<path name="sidetone-iir" />
|
||||
<!-- 45 % of 124 (range 0 - 124) Register: 0x340 -->
|
||||
<ctl name="IIR0 INP0 Volume" value="44" />
|
||||
<ctl name="RX INT1 MIX2 INP" value="SRC0" />
|
||||
<ctl name="RX INT2 MIX2 INP" value="SRC0" />
|
||||
</path>
|
||||
|
||||
<path name="speaker-and-headphones">
|
||||
<path name="speaker" />
|
||||
<ctl name="RX INT1_1 MIX1 INP0" value="RX1" />
|
||||
<ctl name="RX INT2_1 MIX1 INP0" value="RX1" />
|
||||
<ctl name="RX INT1 DEM MUX" value="CLSH_DSM_OUT" />
|
||||
<ctl name="RX INT2 DEM MUX" value="CLSH_DSM_OUT" />
|
||||
<ctl name="RX1 Digital Volume" value="55" />
|
||||
<ctl name="RX2 Digital Volume" value="55" />
|
||||
<path name="headphones-hpf" />
|
||||
<ctl name="Set Custom Stereo" value="Mix" />
|
||||
</path>
|
||||
|
||||
<path name="headphones">
|
||||
<ctl name="SLIM RX0 MUX" value="AIF_MIX1_PB" />
|
||||
<ctl name="SLIM RX1 MUX" value="AIF_MIX1_PB" />
|
||||
<ctl name="SLIM_0_RX Channels" value="Two" />
|
||||
<ctl name="RX INT1_1 MIX1 INP0" value="RX0" />
|
||||
<ctl name="RX INT2_1 MIX1 INP0" value="RX1" />
|
||||
<ctl name="RX INT1 DEM MUX" value="CLSH_DSM_OUT" />
|
||||
<ctl name="RX INT2 DEM MUX" value="CLSH_DSM_OUT" />
|
||||
<ctl name="RX1 Digital Volume" value="80" />
|
||||
<ctl name="RX2 Digital Volume" value="80" />
|
||||
</path>
|
||||
|
||||
<path name="headphones-hpf">
|
||||
<ctl name="RX INT1_1 HPF cut off" value="CF_NEG_3DB_150HZ" />
|
||||
<ctl name="RX INT2_1 HPF cut off" value="CF_NEG_3DB_150HZ" />
|
||||
</path>
|
||||
|
||||
|
||||
<path name="anc-off-headphone">
|
||||
<ctl name="SLIM RX0 MUX" value="AIF_MIX1_PB" />
|
||||
<ctl name="SLIM RX1 MUX" value="AIF_MIX1_PB" />
|
||||
<ctl name="SLIM_0_RX Channels" value="Two" />
|
||||
<ctl name="RX INT1_1 MIX1 INP0" value="RX0" />
|
||||
<ctl name="RX INT2_1 MIX1 INP0" value="RX1" />
|
||||
<ctl name="RX INT1 DEM MUX" value="CLSH_DSM_OUT" />
|
||||
<ctl name="RX INT2 DEM MUX" value="CLSH_DSM_OUT" />
|
||||
<ctl name="COMP1 Switch" value="0" />
|
||||
<ctl name="COMP2 Switch" value="0" />
|
||||
<ctl name="HPHL Volume" value="20" />
|
||||
<ctl name="HPHR Volume" value="20" />
|
||||
<ctl name="RX1 Digital Volume" value="77" />
|
||||
<ctl name="RX2 Digital Volume" value="77" />
|
||||
</path>
|
||||
|
||||
<path name="audio-record">
|
||||
<ctl name="MultiMedia1 Mixer SLIM_0_TX" value="1" />
|
||||
</path>
|
||||
|
||||
<path name="deep-buffer-playback">
|
||||
<ctl name="SLIMBUS_0_RX Audio Mixer MultiMedia1" value="1" />
|
||||
</path>
|
||||
*/
|
||||
|
||||
mm1-dai-link {
|
||||
/* Deep Buffer playback for SLIM{0,7}, BT, USBAUDIO, AFE, DP, HDMI */
|
||||
link-name = "MultiMedia1";
|
||||
cpu {
|
||||
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
|
||||
};
|
||||
};
|
||||
|
||||
mm2-dai-link {
|
||||
/* Multichannel playback for HDMI and DP */
|
||||
link-name = "MultiMedia2";
|
||||
cpu {
|
||||
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
|
||||
};
|
||||
};
|
||||
|
||||
mm3-dai-link {
|
||||
/* Ultra Low Latency playback for SLIM0, HDMI, and DP */
|
||||
link-name = "MultiMedia3";
|
||||
cpu {
|
||||
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
|
||||
};
|
||||
};
|
||||
|
||||
slim-dai-link {
|
||||
link-name = "SLIM Playback";
|
||||
cpu {
|
||||
sound-dai = <&q6afedai SLIMBUS_0_RX>;
|
||||
};
|
||||
|
||||
platform {
|
||||
sound-dai = <&q6routing>;
|
||||
};
|
||||
|
||||
codec {
|
||||
/* Support only sound through 3.5mm for now: soundwire is currently unavailable */
|
||||
//sound-dai = <&left_spkr>, <&right_spkr>, <&swm 0>, <&wcd9335 0>;
|
||||
sound-dai = <&wcd9335 0>;
|
||||
};
|
||||
};
|
||||
|
||||
slimcap-dai-link {
|
||||
link-name = "SLIM Capture";
|
||||
cpu {
|
||||
sound-dai = <&q6afedai SLIMBUS_0_TX>;
|
||||
};
|
||||
|
||||
platform {
|
||||
sound-dai = <&q6routing>;
|
||||
};
|
||||
|
||||
codec {
|
||||
sound-dai = <&wcd9335 1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
gpio-reserved-ranges = <0 4>, <81 4>;
|
||||
|
||||
|
|
@ -606,6 +1145,14 @@
|
|||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
tof_int_n: tof-int-n {
|
||||
pins = "gpio22";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
drive-strength = <2>;
|
||||
input-enable;
|
||||
};
|
||||
|
||||
cam1_vdig_default: cam1-vdig-default {
|
||||
pins = "gpio25";
|
||||
function = "gpio";
|
||||
|
|
@ -613,6 +1160,74 @@
|
|||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
tof_rst_n: tof-rst-n {
|
||||
pins = "gpio27";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
output-low;
|
||||
};
|
||||
|
||||
cam1_rst_default: cam1-rst-n {
|
||||
pins = "gpio28";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
cam0_rst_default: cam0-rst-n {
|
||||
pins = "gpio30";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
wcd_int_n: wcd-int-n {
|
||||
pins = "gpio54";
|
||||
function = "gpio";
|
||||
bias-pull-down;
|
||||
drive-strength = <2>;
|
||||
input-enable;
|
||||
};
|
||||
|
||||
cdc_reset_n: cdc-reset-n {
|
||||
pins = "gpio64";
|
||||
function = "gpio";
|
||||
bias-pull-down;
|
||||
drive-strength = <16>;
|
||||
output-high;
|
||||
};
|
||||
|
||||
wsa_leftspk_pwr_n: wsa-leftspk-pwr-n {
|
||||
pins = "gpio65";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
output-low;
|
||||
};
|
||||
|
||||
wsa_rightspk_pwr_n: wsa-rightspk-pwr-n {
|
||||
pins = "gpio66";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
output-low;
|
||||
};
|
||||
|
||||
ts_reset_n: ts-reset-n {
|
||||
pins = "gpio89";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
drive-strength = <8>;
|
||||
};
|
||||
|
||||
panel_reset_n: panel-rst-n {
|
||||
pins = "gpio94";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
hall_sensor0_default: acc-cover-open {
|
||||
pins = "gpio124";
|
||||
function = "gpio";
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -125,6 +125,14 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pm8916_pwm: pwm {
|
||||
compatible = "qcom,pm8916-pwm";
|
||||
|
||||
#pwm-cells = <2>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pm8916_vib: vibrator@c000 {
|
||||
compatible = "qcom,pm8916-vib";
|
||||
reg = <0xc000>;
|
||||
|
|
|
|||
|
|
@ -135,6 +135,16 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pm8994_lpg: lpg {
|
||||
compatible = "qcom,pm8994-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#pwm-cells = <2>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pm8994_spmi_regulators: regulators {
|
||||
compatible = "qcom,pm8994-regulators";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -78,6 +78,16 @@
|
|||
#size-cells = <0>;
|
||||
#io-channel-cells = <1>;
|
||||
|
||||
adc-chan@0 {
|
||||
reg = <ADC5_REF_GND>;
|
||||
label = "ref_gnd";
|
||||
};
|
||||
|
||||
adc-chan@1 {
|
||||
reg = <ADC5_REF_GND>;
|
||||
label = "vref_1p25";
|
||||
};
|
||||
|
||||
adc-chan@6 {
|
||||
reg = <ADC5_DIE_TEMP>;
|
||||
label = "die_temp";
|
||||
|
|
|
|||
|
|
@ -19,6 +19,18 @@
|
|||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
pmi8994_mpps: mpps@a000 {
|
||||
compatible = "qcom,pmi8994-mpp";
|
||||
reg = <0xa000>;
|
||||
gpio-controller;
|
||||
gpio-ranges = <&pmi8994_mpps 0 0 4>;
|
||||
#gpio-cells = <2>;
|
||||
interrupts = <0 0xa0 0 IRQ_TYPE_NONE>,
|
||||
<0 0xa1 0 IRQ_TYPE_NONE>,
|
||||
<0 0xa2 0 IRQ_TYPE_NONE>,
|
||||
<0 0xa3 0 IRQ_TYPE_NONE>;
|
||||
};
|
||||
};
|
||||
|
||||
pmic@3 {
|
||||
|
|
@ -27,6 +39,16 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmi8994_lpg: lpg {
|
||||
compatible = "qcom,pmi8994-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#pwm-cells = <2>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pmi8994_spmi_regulators: regulators {
|
||||
compatible = "qcom,pmi8994-regulators";
|
||||
#address-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <dt-bindings/input/qcom,spmi-haptics.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/spmi/spmi.h>
|
||||
|
||||
|
|
@ -18,6 +19,17 @@
|
|||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
pmi8998_fg: fuel_guage {
|
||||
compatible = "qcom,pmi8998-fg";
|
||||
status = "disabled";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
//FG //Charger
|
||||
reg = <0x4000 0x1000>;
|
||||
interrupts = <0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "usb-plugin";
|
||||
};
|
||||
};
|
||||
|
||||
pmi8998_lsid1: pmic@3 {
|
||||
|
|
@ -53,5 +65,29 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
pmi8998_lpg: lpg {
|
||||
compatible = "qcom,pmi8998-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#pwm-cells = <2>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pmi8998_haptics: haptics@c000 {
|
||||
compatible = "qcom,pmi8998-haptics";
|
||||
reg = <0xc000>;
|
||||
|
||||
interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "short", "play";
|
||||
|
||||
qcom,wave-shape = <HAP_WAVE_SINE>;
|
||||
qcom,play-mode = <HAP_PLAY_BUFFER>;
|
||||
qcom,brake-pattern = <0x3 0x3 0x2 0x1>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1173,19 +1173,19 @@
|
|||
<&cpr_efuse_ring2>,
|
||||
<&cpr_efuse_ring3>,
|
||||
<&cpr_efuse_revision>;
|
||||
nvmem-cell-names = "cpr_quotient_offset1",
|
||||
"cpr_quotient_offset2",
|
||||
"cpr_quotient_offset3",
|
||||
"cpr_init_voltage1",
|
||||
"cpr_init_voltage2",
|
||||
"cpr_init_voltage3",
|
||||
"cpr_quotient1",
|
||||
"cpr_quotient2",
|
||||
"cpr_quotient3",
|
||||
"cpr_ring_osc1",
|
||||
"cpr_ring_osc2",
|
||||
"cpr_ring_osc3",
|
||||
"cpr_fuse_revision";
|
||||
nvmem-cell-names = "cpr0_quotient_offset1",
|
||||
"cpr0_quotient_offset2",
|
||||
"cpr0_quotient_offset3",
|
||||
"cpr0_init_voltage1",
|
||||
"cpr0_init_voltage2",
|
||||
"cpr0_init_voltage3",
|
||||
"cpr0_quotient1",
|
||||
"cpr0_quotient2",
|
||||
"cpr0_quotient3",
|
||||
"cpr0_ring_osc1",
|
||||
"cpr0_ring_osc2",
|
||||
"cpr0_ring_osc3",
|
||||
"cpr0_fuse_revision";
|
||||
};
|
||||
|
||||
timer@b120000 {
|
||||
|
|
|
|||
|
|
@ -595,6 +595,30 @@
|
|||
};
|
||||
};
|
||||
|
||||
&pmi8998_lpg {
|
||||
status = "okay";
|
||||
|
||||
qcom,power-source = <1>;
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
label = "green:user3";
|
||||
|
||||
linux,default-trigger = "heartbeat";
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
label = "green:user2";
|
||||
};
|
||||
|
||||
led@5 {
|
||||
reg = <5>;
|
||||
label = "green:user1";
|
||||
};
|
||||
};
|
||||
|
||||
/* QUAT I2S Uses 4 I2S SD Lines for audio on LT9611 HDMI Bridge */
|
||||
&q6afedai {
|
||||
qi2s@22 {
|
||||
|
|
|
|||
|
|
@ -450,6 +450,13 @@
|
|||
};
|
||||
};
|
||||
|
||||
&pmi8998_fg {
|
||||
status = "okay";
|
||||
|
||||
qcom,max-voltage-uv = <4400000>;
|
||||
qcom,min-voltage-uv = <3700000>;
|
||||
};
|
||||
|
||||
&qupv3_id_1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
@ -619,7 +626,7 @@
|
|||
pins = "gpio6", "gpio25", "gpio26";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable = <0>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@
|
|||
qcom,board-id = <8 0 17819 22>;
|
||||
};
|
||||
|
||||
&pmi8998_fg {
|
||||
qcom,battery-capacity-ua = <3300000>;
|
||||
};
|
||||
|
||||
&display_panel {
|
||||
status = "okay";
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@
|
|||
compatible = "samsung,s6e3fc2x01";
|
||||
};
|
||||
|
||||
&pmi8998_fg {
|
||||
qcom,battery-capacity-ua = <3700000>;
|
||||
};
|
||||
|
||||
&rmi4_f12 {
|
||||
touchscreen-y-mm = <148>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@
|
|||
#ifndef __ASM_CSKY_UACCESS_H
|
||||
#define __ASM_CSKY_UACCESS_H
|
||||
|
||||
#define user_addr_max() \
|
||||
(uaccess_kernel() ? KERNEL_DS.seg : get_fs().seg)
|
||||
#define user_addr_max() (current_thread_info()->addr_limit.seg)
|
||||
|
||||
static inline int __access_ok(unsigned long addr, unsigned long size)
|
||||
{
|
||||
unsigned long limit = current_thread_info()->addr_limit.seg;
|
||||
unsigned long limit = user_addr_max();
|
||||
|
||||
return ((addr < limit) && ((addr + size) < limit));
|
||||
return (size <= limit) && (addr <= (limit - size));
|
||||
}
|
||||
#define __access_ok __access_ok
|
||||
|
||||
|
|
|
|||
|
|
@ -25,17 +25,17 @@
|
|||
* Returns true (nonzero) if the memory block *may* be valid, false (zero)
|
||||
* if it is definitely invalid.
|
||||
*
|
||||
* User address space in Hexagon, like x86, goes to 0xbfffffff, so the
|
||||
* simple MSB-based tests used by MIPS won't work. Some further
|
||||
* optimization is probably possible here, but for now, keep it
|
||||
* reasonably simple and not *too* slow. After all, we've got the
|
||||
* MMU for backup.
|
||||
*/
|
||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
|
||||
|
||||
#define __access_ok(addr, size) \
|
||||
((get_fs().seg == KERNEL_DS.seg) || \
|
||||
(((unsigned long)addr < get_fs().seg) && \
|
||||
(unsigned long)size < (get_fs().seg - (unsigned long)addr)))
|
||||
static inline int __access_ok(unsigned long addr, unsigned long size)
|
||||
{
|
||||
unsigned long limit = TASK_SIZE;
|
||||
|
||||
return (size <= limit) && (addr <= (limit - size));
|
||||
}
|
||||
#define __access_ok __access_ok
|
||||
|
||||
/*
|
||||
* When a kernel-mode page fault is taken, the faulting instruction
|
||||
|
|
|
|||
|
|
@ -12,14 +12,17 @@
|
|||
#include <asm/extable.h>
|
||||
|
||||
/* We let the MMU do all checking */
|
||||
static inline int access_ok(const void __user *addr,
|
||||
static inline int access_ok(const void __user *ptr,
|
||||
unsigned long size)
|
||||
{
|
||||
/*
|
||||
* XXX: for !CONFIG_CPU_HAS_ADDRESS_SPACES this really needs to check
|
||||
* for TASK_SIZE!
|
||||
*/
|
||||
return 1;
|
||||
unsigned long limit = TASK_SIZE;
|
||||
unsigned long addr = (unsigned long)ptr;
|
||||
|
||||
if (IS_ENABLED(CONFIG_CPU_HAS_ADDRESS_SPACES) ||
|
||||
!IS_ENABLED(CONFIG_MMU))
|
||||
return 1;
|
||||
|
||||
return (size <= limit) && (addr <= (limit - size));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -39,24 +39,13 @@
|
|||
|
||||
# define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
static inline int access_ok(const void __user *addr, unsigned long size)
|
||||
static inline int __access_ok(unsigned long addr, unsigned long size)
|
||||
{
|
||||
if (!size)
|
||||
goto ok;
|
||||
unsigned long limit = user_addr_max();
|
||||
|
||||
if ((get_fs().seg < ((unsigned long)addr)) ||
|
||||
(get_fs().seg < ((unsigned long)addr + size - 1))) {
|
||||
pr_devel("ACCESS fail at 0x%08x (size 0x%x), seg 0x%08x\n",
|
||||
(__force u32)addr, (u32)size,
|
||||
(u32)get_fs().seg);
|
||||
return 0;
|
||||
}
|
||||
ok:
|
||||
pr_devel("ACCESS OK at 0x%08x (size 0x%x), seg 0x%08x\n",
|
||||
(__force u32)addr, (u32)size,
|
||||
(u32)get_fs().seg);
|
||||
return 1;
|
||||
return (size <= limit) && (addr <= (limit - size));
|
||||
}
|
||||
#define access_ok(addr, size) __access_ok((unsigned long)addr, size)
|
||||
|
||||
# define __FIXUP_SECTION ".section .fixup,\"ax\"\n"
|
||||
# define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
|
||||
|
|
|
|||
|
|
@ -70,9 +70,7 @@ static inline void set_fs(mm_segment_t fs)
|
|||
* versions are void (ie, don't return a value as such).
|
||||
*/
|
||||
|
||||
#define get_user __get_user \
|
||||
|
||||
#define __get_user(x, ptr) \
|
||||
#define get_user(x, ptr) \
|
||||
({ \
|
||||
long __gu_err = 0; \
|
||||
__get_user_check((x), (ptr), __gu_err); \
|
||||
|
|
@ -85,6 +83,14 @@ static inline void set_fs(mm_segment_t fs)
|
|||
(void)0; \
|
||||
})
|
||||
|
||||
#define __get_user(x, ptr) \
|
||||
({ \
|
||||
long __gu_err = 0; \
|
||||
const __typeof__(*(ptr)) __user *__p = (ptr); \
|
||||
__get_user_err((x), __p, (__gu_err)); \
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
#define __get_user_check(x, ptr, err) \
|
||||
({ \
|
||||
const __typeof__(*(ptr)) __user *__p = (ptr); \
|
||||
|
|
@ -165,12 +171,18 @@ do { \
|
|||
: "r"(addr), "i"(-EFAULT) \
|
||||
: "cc")
|
||||
|
||||
#define put_user __put_user \
|
||||
#define put_user(x, ptr) \
|
||||
({ \
|
||||
long __pu_err = 0; \
|
||||
__put_user_check((x), (ptr), __pu_err); \
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
#define __put_user(x, ptr) \
|
||||
({ \
|
||||
long __pu_err = 0; \
|
||||
__put_user_err((x), (ptr), __pu_err); \
|
||||
__typeof__(*(ptr)) __user *__p = (ptr); \
|
||||
__put_user_err((x), __p, __pu_err); \
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1328,6 +1328,17 @@ static int __init disable_acpi_pci(const struct dmi_system_id *d)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init disable_acpi_xsdt(const struct dmi_system_id *d)
|
||||
{
|
||||
if (!acpi_force) {
|
||||
pr_notice("%s detected: force use of acpi=rsdt\n", d->ident);
|
||||
acpi_gbl_do_not_use_xsdt = TRUE;
|
||||
} else {
|
||||
pr_notice("Warning: DMI blacklist says broken, but acpi XSDT forced\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init dmi_disable_acpi(const struct dmi_system_id *d)
|
||||
{
|
||||
if (!acpi_force) {
|
||||
|
|
@ -1451,6 +1462,19 @@ static const struct dmi_system_id acpi_dmi_table[] __initconst = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
|
||||
},
|
||||
},
|
||||
/*
|
||||
* Boxes that need ACPI XSDT use disabled due to corrupted tables
|
||||
*/
|
||||
{
|
||||
.callback = disable_acpi_xsdt,
|
||||
.ident = "Advantech DAC-BJ01",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Bearlake CRB Board"),
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "V1.12"),
|
||||
DMI_MATCH(DMI_BIOS_DATE, "02/01/2011"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
|
|||
|
||||
static const struct acpi_device_id battery_device_ids[] = {
|
||||
{"PNP0C0A", 0},
|
||||
|
||||
/* Microsoft Surface Go 3 */
|
||||
{"MSHW0146", 0},
|
||||
|
||||
{"", 0},
|
||||
};
|
||||
|
||||
|
|
@ -1148,6 +1152,14 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
|
|||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Microsoft Surface Go 3 */
|
||||
.callback = battery_notification_delay_quirk,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"),
|
||||
},
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -415,6 +415,81 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "GA503"),
|
||||
},
|
||||
},
|
||||
/*
|
||||
* Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a
|
||||
* working native and video interface. However the default detection
|
||||
* mechanism first registers the video interface before unregistering
|
||||
* it again and switching to the native interface during boot. This
|
||||
* results in a dangling SBIOS request for backlight change for some
|
||||
* reason, causing the backlight to switch to ~2% once per boot on the
|
||||
* first power cord connect or disconnect event. Setting the native
|
||||
* interface explicitly circumvents this buggy behaviour, by avoiding
|
||||
* the unregistering process.
|
||||
*/
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "AURA1501"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xNU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xNU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xNU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Desktops which falsely report a backlight and which our heuristics
|
||||
|
|
|
|||
|
|
@ -405,6 +405,8 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Realtek 8852AE Bluetooth devices */
|
||||
{ USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0bda, 0x385a), .driver_info = BTUSB_REALTEK |
|
||||
|
|
@ -482,6 +484,8 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
/* Additional Realtek 8761BU Bluetooth devices */
|
||||
{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x2550, 0x8761), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Additional Realtek 8821AE Bluetooth devices */
|
||||
{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
|
||||
|
|
@ -2041,6 +2045,8 @@ static int btusb_setup_csr(struct hci_dev *hdev)
|
|||
*/
|
||||
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
|
||||
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
|
||||
set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks);
|
||||
set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks);
|
||||
|
||||
/* Clear the reset quirk since this is not an actual
|
||||
* early Bluetooth 1.1 device from CSR.
|
||||
|
|
@ -2051,7 +2057,7 @@ static int btusb_setup_csr(struct hci_dev *hdev)
|
|||
/*
|
||||
* Special workaround for these BT 4.0 chip clones, and potentially more:
|
||||
*
|
||||
* - 0x0134: a Barrot 8041a02 (HCI rev: 0x1012 sub: 0x0810)
|
||||
* - 0x0134: a Barrot 8041a02 (HCI rev: 0x0810 sub: 0x1012)
|
||||
* - 0x7558: IC markings FR3191AHAL 749H15143 (HCI rev/sub-version: 0x0709)
|
||||
*
|
||||
* These controllers are really messed-up.
|
||||
|
|
@ -2080,7 +2086,7 @@ static int btusb_setup_csr(struct hci_dev *hdev)
|
|||
if (ret >= 0)
|
||||
msleep(200);
|
||||
else
|
||||
bt_dev_err(hdev, "CSR: Failed to suspend the device for our Barrot 8041a02 receive-issue workaround");
|
||||
bt_dev_warn(hdev, "CSR: Couldn't suspend the device for our Barrot 8041a02 receive-issue workaround");
|
||||
|
||||
pm_runtime_forbid(&data->udev->dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -274,14 +274,6 @@ static void tpm_dev_release(struct device *dev)
|
|||
kfree(chip);
|
||||
}
|
||||
|
||||
static void tpm_devs_release(struct device *dev)
|
||||
{
|
||||
struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
|
||||
|
||||
/* release the master device reference */
|
||||
put_device(&chip->dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* tpm_class_shutdown() - prepare the TPM device for loss of power.
|
||||
* @dev: device to which the chip is associated.
|
||||
|
|
@ -344,7 +336,6 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
|
|||
chip->dev_num = rc;
|
||||
|
||||
device_initialize(&chip->dev);
|
||||
device_initialize(&chip->devs);
|
||||
|
||||
chip->dev.class = tpm_class;
|
||||
chip->dev.class->shutdown_pre = tpm_class_shutdown;
|
||||
|
|
@ -352,29 +343,12 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
|
|||
chip->dev.parent = pdev;
|
||||
chip->dev.groups = chip->groups;
|
||||
|
||||
chip->devs.parent = pdev;
|
||||
chip->devs.class = tpmrm_class;
|
||||
chip->devs.release = tpm_devs_release;
|
||||
/* get extra reference on main device to hold on
|
||||
* behalf of devs. This holds the chip structure
|
||||
* while cdevs is in use. The corresponding put
|
||||
* is in the tpm_devs_release (TPM2 only)
|
||||
*/
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
||||
get_device(&chip->dev);
|
||||
|
||||
if (chip->dev_num == 0)
|
||||
chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
|
||||
else
|
||||
chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
|
||||
|
||||
chip->devs.devt =
|
||||
MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
|
||||
|
||||
rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
|
||||
if (rc)
|
||||
goto out;
|
||||
rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
|
@ -382,9 +356,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
|
|||
chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
|
||||
|
||||
cdev_init(&chip->cdev, &tpm_fops);
|
||||
cdev_init(&chip->cdevs, &tpmrm_fops);
|
||||
chip->cdev.owner = THIS_MODULE;
|
||||
chip->cdevs.owner = THIS_MODULE;
|
||||
|
||||
rc = tpm2_init_space(&chip->work_space, TPM2_SPACE_BUFFER_SIZE);
|
||||
if (rc) {
|
||||
|
|
@ -396,7 +368,6 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
|
|||
return chip;
|
||||
|
||||
out:
|
||||
put_device(&chip->devs);
|
||||
put_device(&chip->dev);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
|
@ -445,14 +416,9 @@ static int tpm_add_char_device(struct tpm_chip *chip)
|
|||
}
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip)) {
|
||||
rc = cdev_device_add(&chip->cdevs, &chip->devs);
|
||||
if (rc) {
|
||||
dev_err(&chip->devs,
|
||||
"unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
|
||||
dev_name(&chip->devs), MAJOR(chip->devs.devt),
|
||||
MINOR(chip->devs.devt), rc);
|
||||
return rc;
|
||||
}
|
||||
rc = tpm_devs_add(chip);
|
||||
if (rc)
|
||||
goto err_del_cdev;
|
||||
}
|
||||
|
||||
/* Make the chip available. */
|
||||
|
|
@ -460,6 +426,10 @@ static int tpm_add_char_device(struct tpm_chip *chip)
|
|||
idr_replace(&dev_nums_idr, chip, chip->dev_num);
|
||||
mutex_unlock(&idr_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
err_del_cdev:
|
||||
cdev_device_del(&chip->cdev, &chip->dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -654,7 +624,7 @@ void tpm_chip_unregister(struct tpm_chip *chip)
|
|||
hwrng_unregister(&chip->hwrng);
|
||||
tpm_bios_log_teardown(chip);
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip))
|
||||
cdev_device_del(&chip->cdevs, &chip->devs);
|
||||
tpm_devs_remove(chip);
|
||||
tpm_del_char_device(chip);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_chip_unregister);
|
||||
|
|
|
|||
|
|
@ -69,7 +69,13 @@ static void tpm_dev_async_work(struct work_struct *work)
|
|||
ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer,
|
||||
sizeof(priv->data_buffer));
|
||||
tpm_put_ops(priv->chip);
|
||||
if (ret > 0) {
|
||||
|
||||
/*
|
||||
* If ret is > 0 then tpm_dev_transmit returned the size of the
|
||||
* response. If ret is < 0 then tpm_dev_transmit failed and
|
||||
* returned an error code.
|
||||
*/
|
||||
if (ret != 0) {
|
||||
priv->response_length = ret;
|
||||
mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,6 +234,8 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
|
|||
size_t cmdsiz);
|
||||
int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, void *buf,
|
||||
size_t *bufsiz);
|
||||
int tpm_devs_add(struct tpm_chip *chip);
|
||||
void tpm_devs_remove(struct tpm_chip *chip);
|
||||
|
||||
void tpm_bios_log_setup(struct tpm_chip *chip);
|
||||
void tpm_bios_log_teardown(struct tpm_chip *chip);
|
||||
|
|
|
|||
|
|
@ -58,12 +58,12 @@ int tpm2_init_space(struct tpm_space *space, unsigned int buf_size)
|
|||
|
||||
void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space)
|
||||
{
|
||||
mutex_lock(&chip->tpm_mutex);
|
||||
if (!tpm_chip_start(chip)) {
|
||||
|
||||
if (tpm_try_get_ops(chip) == 0) {
|
||||
tpm2_flush_sessions(chip, space);
|
||||
tpm_chip_stop(chip);
|
||||
tpm_put_ops(chip);
|
||||
}
|
||||
mutex_unlock(&chip->tpm_mutex);
|
||||
|
||||
kfree(space->context_buf);
|
||||
kfree(space->session_buf);
|
||||
}
|
||||
|
|
@ -574,3 +574,68 @@ out:
|
|||
dev_err(&chip->dev, "%s: error %d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the reference to the main device.
|
||||
*/
|
||||
static void tpm_devs_release(struct device *dev)
|
||||
{
|
||||
struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
|
||||
|
||||
/* release the master device reference */
|
||||
put_device(&chip->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the device file for exposed TPM spaces and release the device
|
||||
* reference. This may also release the reference to the master device.
|
||||
*/
|
||||
void tpm_devs_remove(struct tpm_chip *chip)
|
||||
{
|
||||
cdev_device_del(&chip->cdevs, &chip->devs);
|
||||
put_device(&chip->devs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a device file to expose TPM spaces. Also take a reference to the
|
||||
* main device.
|
||||
*/
|
||||
int tpm_devs_add(struct tpm_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
|
||||
device_initialize(&chip->devs);
|
||||
chip->devs.parent = chip->dev.parent;
|
||||
chip->devs.class = tpmrm_class;
|
||||
|
||||
/*
|
||||
* Get extra reference on main device to hold on behalf of devs.
|
||||
* This holds the chip structure while cdevs is in use. The
|
||||
* corresponding put is in the tpm_devs_release.
|
||||
*/
|
||||
get_device(&chip->dev);
|
||||
chip->devs.release = tpm_devs_release;
|
||||
chip->devs.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
|
||||
cdev_init(&chip->cdevs, &tpmrm_fops);
|
||||
chip->cdevs.owner = THIS_MODULE;
|
||||
|
||||
rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
|
||||
if (rc)
|
||||
goto err_put_devs;
|
||||
|
||||
rc = cdev_device_add(&chip->cdevs, &chip->devs);
|
||||
if (rc) {
|
||||
dev_err(&chip->devs,
|
||||
"unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
|
||||
dev_name(&chip->devs), MAJOR(chip->devs.devt),
|
||||
MINOR(chip->devs.devt), rc);
|
||||
goto err_put_devs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_devs:
|
||||
put_device(&chip->devs);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -805,15 +805,20 @@ static const struct rpm_smd_clk_desc rpm_clk_qcs404 = {
|
|||
.num_clks = ARRAY_SIZE(qcs404_clks),
|
||||
};
|
||||
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin,
|
||||
3, 19200000);
|
||||
DEFINE_CLK_SMD_RPM_BRANCH(msm8998, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0,
|
||||
19200000);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk3, ln_bb_clk3_a, 3, 19200000);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin, 3, 19200000);
|
||||
DEFINE_CLK_SMD_RPM(msm8998, aggre1_noc_clk, aggre1_noc_a_clk,
|
||||
QCOM_SMD_RPM_AGGR_CLK, 1);
|
||||
DEFINE_CLK_SMD_RPM(msm8998, aggre2_noc_clk, aggre2_noc_a_clk,
|
||||
QCOM_SMD_RPM_AGGR_CLK, 2);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk3, rf_clk3_a, 6, 19200000);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6, 19200000);
|
||||
|
||||
static struct clk_smd_rpm *msm8998_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
|
||||
[RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk,
|
||||
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
|
||||
|
|
@ -826,12 +831,22 @@ static struct clk_smd_rpm *msm8998_clks[] = {
|
|||
[RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk,
|
||||
[RPM_SMD_DIV_CLK1] = &msm8974_div_clk1,
|
||||
[RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1,
|
||||
[RPM_SMD_DIV_CLK2] = &msm8974_div_clk2,
|
||||
[RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2,
|
||||
[RPM_SMD_DIV_CLK3] = &msm8992_div_clk3,
|
||||
[RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a,
|
||||
[RPM_SMD_IPA_CLK] = &msm8976_ipa_clk,
|
||||
[RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk,
|
||||
[RPM_SMD_LN_BB_CLK1] = &msm8916_bb_clk1,
|
||||
[RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a,
|
||||
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
|
||||
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
|
||||
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
|
||||
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
|
||||
[RPM_SMD_LN_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
|
||||
[RPM_SMD_LN_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
|
||||
[RPM_SMD_LN_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,
|
||||
[RPM_SMD_LN_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,
|
||||
[RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin,
|
||||
[RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin,
|
||||
[RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk,
|
||||
|
|
@ -844,10 +859,14 @@ static struct clk_smd_rpm *msm8998_clks[] = {
|
|||
[RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk,
|
||||
[RPM_SMD_RF_CLK1] = &msm8916_rf_clk1,
|
||||
[RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a,
|
||||
[RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,
|
||||
[RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,
|
||||
[RPM_SMD_RF_CLK2] = &msm8916_rf_clk2,
|
||||
[RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a,
|
||||
[RPM_SMD_RF_CLK3] = &msm8998_rf_clk3,
|
||||
[RPM_SMD_RF_CLK3_A] = &msm8998_rf_clk3_a,
|
||||
[RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,
|
||||
[RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,
|
||||
[RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,
|
||||
[RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,
|
||||
[RPM_SMD_RF_CLK3_PIN] = &msm8998_rf_clk3_pin,
|
||||
[RPM_SMD_RF_CLK3_A_PIN] = &msm8998_rf_clk3_a_pin,
|
||||
};
|
||||
|
|
@ -857,14 +876,9 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8998 = {
|
|||
.num_clks = ARRAY_SIZE(msm8998_clks),
|
||||
};
|
||||
|
||||
DEFINE_CLK_SMD_RPM_BRANCH(sdm660, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0,
|
||||
19200000);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk3, ln_bb_clk3_a, 3, 19200000);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin, ln_bb_clk3_pin_a, 3, 19200000);
|
||||
|
||||
static struct clk_smd_rpm *sdm660_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,
|
||||
[RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk,
|
||||
[RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk,
|
||||
|
|
@ -891,16 +905,16 @@ static struct clk_smd_rpm *sdm660_clks[] = {
|
|||
[RPM_SMD_LN_BB_A_CLK] = &msm8916_bb_clk1_a,
|
||||
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
|
||||
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
|
||||
[RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3,
|
||||
[RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a,
|
||||
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
|
||||
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
|
||||
[RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,
|
||||
[RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,
|
||||
[RPM_SMD_LN_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
|
||||
[RPM_SMD_LN_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
|
||||
[RPM_SMD_LN_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,
|
||||
[RPM_SMD_LN_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,
|
||||
[RPM_SMD_LN_BB_CLK3_PIN] = &sdm660_ln_bb_clk3_pin,
|
||||
[RPM_SMD_LN_BB_CLK3_A_PIN] = &sdm660_ln_bb_clk3_pin_a,
|
||||
[RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin,
|
||||
[RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin,
|
||||
};
|
||||
|
||||
static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
|
||||
|
|
@ -909,8 +923,8 @@ static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
|
|||
};
|
||||
|
||||
static struct clk_smd_rpm *mdm9607_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
|
||||
[RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
|
||||
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
|
||||
|
|
@ -931,8 +945,8 @@ static const struct rpm_smd_clk_desc rpm_clk_mdm9607 = {
|
|||
};
|
||||
|
||||
static struct clk_smd_rpm *msm8953_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
|
||||
[RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
|
||||
[RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,
|
||||
|
|
@ -980,8 +994,8 @@ DEFINE_CLK_SMD_RPM(sm6125, snoc_lpass_clk, snoc_lpass_a_clk,
|
|||
QCOM_SMD_RPM_BUS_CLK, 5);
|
||||
|
||||
static struct clk_smd_rpm *sm6125_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
|
||||
[RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
|
||||
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
|
||||
|
|
@ -1002,8 +1016,8 @@ static struct clk_smd_rpm *sm6125_clks[] = {
|
|||
[RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a,
|
||||
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
|
||||
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
|
||||
[RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3,
|
||||
[RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a,
|
||||
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
|
||||
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
|
||||
[RPM_SMD_QUP_CLK] = &sm6125_qup_clk,
|
||||
[RPM_SMD_QUP_A_CLK] = &sm6125_qup_a_clk,
|
||||
[RPM_SMD_MMRT_CLK] = &sm6125_mmrt_clk,
|
||||
|
|
@ -1023,8 +1037,8 @@ static const struct rpm_smd_clk_desc rpm_clk_sm6125 = {
|
|||
|
||||
/* SM6115 */
|
||||
static struct clk_smd_rpm *sm6115_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
|
||||
[RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
|
||||
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
|
||||
|
|
@ -1075,8 +1089,8 @@ DEFINE_CLK_SMD_RPM(qcm2290, bimc_gpu_clk, bimc_gpu_a_clk,
|
|||
QCOM_SMD_RPM_MEM_CLK, 2);
|
||||
|
||||
static struct clk_smd_rpm *qcm2290_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
|
||||
[RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
|
||||
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
|
||||
|
|
|
|||
|
|
@ -2080,6 +2080,7 @@ static struct clk_branch gcc_bimc_gfx_clk = {
|
|||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gcc_bimc_gfx_clk",
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
|
@ -2220,6 +2221,7 @@ static struct clk_rcg2 hmss_gpll0_clk_src = {
|
|||
.name = "hmss_gpll0_clk_src",
|
||||
.parent_data = gcc_parent_data_1,
|
||||
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
.ops = &clk_rcg2_ops,
|
||||
},
|
||||
};
|
||||
|
|
@ -2833,6 +2835,43 @@ static struct clk_branch gcc_rx1_usb2_clkref_clk = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_branch hlos1_vote_lpass_core_smmu_clk = {
|
||||
.halt_reg = 0x7D010,
|
||||
.clkr = {
|
||||
.enable_reg = 0x7D010,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "hlos1_vote_lpass_core_smmu_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch hlos1_vote_lpass_adsp_smmu_clk = {
|
||||
.halt_reg = 0x7D014,
|
||||
.clkr = {
|
||||
.enable_reg = 0x7D014,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "hlos1_vote_lpass_adsp_smmu_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
|
||||
.halt_reg = 0x8A040,
|
||||
.clkr = {
|
||||
.enable_reg = 0x8A040,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "gcc_mss_q6_bimc_axi_clk",
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct gdsc pcie_0_gdsc = {
|
||||
.gdscr = 0x6b004,
|
||||
.gds_hw_ctrl = 0x0,
|
||||
|
|
@ -2863,6 +2902,26 @@ static struct gdsc usb_30_gdsc = {
|
|||
.flags = VOTABLE,
|
||||
};
|
||||
|
||||
static struct gdsc hlos1_vote_lpass_adsp = {
|
||||
.gdscr = 0x7d034,
|
||||
.gds_hw_ctrl = 0x0,
|
||||
.pd = {
|
||||
.name = "lpass_adsp_gdsc",
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = VOTABLE,
|
||||
};
|
||||
|
||||
static struct gdsc hlos1_vote_lpass_core = {
|
||||
.gdscr = 0x7d038,
|
||||
.gds_hw_ctrl = 0x0,
|
||||
.pd = {
|
||||
.name = "lpass_core_gdsc",
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = ALWAYS_ON,
|
||||
};
|
||||
|
||||
static struct clk_regmap *gcc_msm8998_clocks[] = {
|
||||
[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
|
||||
[BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
|
||||
|
|
@ -3036,12 +3095,17 @@ static struct clk_regmap *gcc_msm8998_clocks[] = {
|
|||
[GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr,
|
||||
[GCC_MMSS_GPLL0_CLK] = &gcc_mmss_gpll0_clk.clkr,
|
||||
[HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
|
||||
[GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr,
|
||||
[HLOS1_VOTE_LPASS_CORE_SMMU_CLK] = &hlos1_vote_lpass_core_smmu_clk.clkr,
|
||||
[HLOS1_VOTE_LPASS_ADSP_SMMU_CLK] = &hlos1_vote_lpass_adsp_smmu_clk.clkr,
|
||||
};
|
||||
|
||||
static struct gdsc *gcc_msm8998_gdscs[] = {
|
||||
[PCIE_0_GDSC] = &pcie_0_gdsc,
|
||||
[UFS_GDSC] = &ufs_gdsc,
|
||||
[USB_30_GDSC] = &usb_30_gdsc,
|
||||
[LPASS_ADSP_GDSC] = &hlos1_vote_lpass_adsp,
|
||||
[LPASS_CORE_GDSC] = &hlos1_vote_lpass_core,
|
||||
};
|
||||
|
||||
static const struct qcom_reset_map gcc_msm8998_resets[] = {
|
||||
|
|
@ -3191,6 +3255,14 @@ static int gcc_msm8998_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* GCC_MMSS_MISC - GCC_GPU_MISC:
|
||||
* 1. Disable the GPLL0 active input to MMSS and GPU
|
||||
* 2. Select clk division 1 (CLK/2)
|
||||
*/
|
||||
regmap_write(regmap, 0x0902C, 0x10003); /* MMSS*/
|
||||
regmap_write(regmap, 0x71028, 0x10003); /* GPU */
|
||||
|
||||
return qcom_cc_really_probe(pdev, &gcc_msm8998_desc, regmap);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -511,7 +511,7 @@ static struct clk_rcg2 byte0_clk_src = {
|
|||
.parent_data = mmss_xo_dsibyte,
|
||||
.num_parents = ARRAY_SIZE(mmss_xo_dsibyte),
|
||||
.ops = &clk_byte2_ops,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -524,7 +524,7 @@ static struct clk_rcg2 byte1_clk_src = {
|
|||
.parent_data = mmss_xo_dsibyte,
|
||||
.num_parents = ARRAY_SIZE(mmss_xo_dsibyte),
|
||||
.ops = &clk_byte2_ops,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -1075,7 +1075,7 @@ static struct clk_rcg2 pclk0_clk_src = {
|
|||
.parent_data = mmss_xo_dsi0pll_dsi1pll,
|
||||
.num_parents = ARRAY_SIZE(mmss_xo_dsi0pll_dsi1pll),
|
||||
.ops = &clk_pixel_ops,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -1089,7 +1089,7 @@ static struct clk_rcg2 pclk1_clk_src = {
|
|||
.parent_data = mmss_xo_dsi0pll_dsi1pll,
|
||||
.num_parents = ARRAY_SIZE(mmss_xo_dsi0pll_dsi1pll),
|
||||
.ops = &clk_pixel_ops,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ static const struct of_device_id blocklist[] __initconst = {
|
|||
|
||||
{ .compatible = "qcom,apq8096", },
|
||||
{ .compatible = "qcom,msm8996", },
|
||||
{ .compatible = "qcom,msm8998", },
|
||||
{ .compatible = "qcom,qcs404", },
|
||||
{ .compatible = "qcom,sa8155p" },
|
||||
{ .compatible = "qcom,sc7180", },
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -75,6 +75,13 @@ static int adf_crypto_dev_config(struct adf_accel_dev *accel_dev)
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* Temporarily set the number of crypto instances to zero to avoid
|
||||
* registering the crypto algorithms.
|
||||
* This will be removed when the algorithms will support the
|
||||
* CRYPTO_TFM_REQ_MAY_BACKLOG flag
|
||||
*/
|
||||
instances = 0;
|
||||
|
||||
for (i = 0; i < instances; i++) {
|
||||
val = i;
|
||||
bank = i * 2;
|
||||
|
|
|
|||
|
|
@ -161,6 +161,13 @@ int qat_crypto_dev_config(struct adf_accel_dev *accel_dev)
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* Temporarily set the number of crypto instances to zero to avoid
|
||||
* registering the crypto algorithms.
|
||||
* This will be removed when the algorithms will support the
|
||||
* CRYPTO_TFM_REQ_MAY_BACKLOG flag
|
||||
*/
|
||||
instances = 0;
|
||||
|
||||
for (i = 0; i < instances; i++) {
|
||||
val = i;
|
||||
snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_BANK_NUM, i);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
|
|||
{
|
||||
int ret;
|
||||
|
||||
WARN_ON(!dev->driver->load && dev->registered && !obj_free_cb);
|
||||
//WARN_ON(!dev->driver->load && dev->registered && !obj_free_cb);
|
||||
|
||||
mutex_lock(&dev->mode_config.idr_mutex);
|
||||
ret = idr_alloc(&dev->mode_config.object_idr, register_obj ? obj : NULL,
|
||||
|
|
@ -237,10 +237,10 @@ void drm_object_attach_property(struct drm_mode_object *obj,
|
|||
|
||||
|
||||
if (obj->type == DRM_MODE_OBJECT_CONNECTOR) {
|
||||
struct drm_connector *connector = obj_to_connector(obj);
|
||||
/*struct drm_connector *connector = obj_to_connector(obj);
|
||||
|
||||
WARN_ON(!dev->driver->load &&
|
||||
connector->registration_state == DRM_CONNECTOR_REGISTERED);
|
||||
connector->registration_state == DRM_CONNECTOR_REGISTERED);*/
|
||||
} else {
|
||||
WARN_ON(!dev->driver->load && dev->registered);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ config DRM_MSM_DSI_14NM_PHY
|
|||
Choose this option if DSI PHY on 8996 is used on the platform.
|
||||
|
||||
config DRM_MSM_DSI_10NM_PHY
|
||||
bool "Enable DSI 10nm PHY driver in MSM DRM (used by SDM845)"
|
||||
bool "Enable DSI 10nm PHY driver in MSM DRM (used by MSM8998/SDM845)"
|
||||
depends on DRM_MSM_DSI
|
||||
default y
|
||||
help
|
||||
|
|
|
|||
|
|
@ -121,6 +121,48 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit
|
|||
msm_gpu_retire(gpu);
|
||||
}
|
||||
|
||||
static void a5xx_set_pagetable(struct a5xx_gpu *a5xx_gpu,
|
||||
struct msm_ringbuffer *ring, struct msm_file_private *ctx)
|
||||
{
|
||||
phys_addr_t ttbr;
|
||||
u32 asid;
|
||||
u64 memptr = rbmemptr(ring, ttbr0);
|
||||
|
||||
if (ctx == a5xx_gpu->cur_ctx)
|
||||
return;
|
||||
|
||||
if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid))
|
||||
return;
|
||||
|
||||
/* Execute the table update */
|
||||
OUT_PKT7(ring, CP_SMMU_TABLE_UPDATE, 3);
|
||||
OUT_RING(ring, CP_SMMU_TABLE_UPDATE_0_TTBR0_LO(lower_32_bits(ttbr)));
|
||||
|
||||
OUT_RING(ring,
|
||||
CP_SMMU_TABLE_UPDATE_1_TTBR0_HI(upper_32_bits(ttbr)) |
|
||||
CP_SMMU_TABLE_UPDATE_1_ASID(asid));
|
||||
OUT_RING(ring, CP_SMMU_TABLE_UPDATE_2_CONTEXTIDR(0));
|
||||
|
||||
/*
|
||||
* Write the new TTBR0 to the memstore. This is good for debugging.
|
||||
*/
|
||||
OUT_PKT7(ring, CP_MEM_WRITE, 4);
|
||||
OUT_RING(ring, CP_MEM_WRITE_0_ADDR_LO(lower_32_bits(memptr)));
|
||||
OUT_RING(ring, CP_MEM_WRITE_1_ADDR_HI(upper_32_bits(memptr)));
|
||||
OUT_RING(ring, lower_32_bits(ttbr));
|
||||
OUT_RING(ring, (asid << 16) | upper_32_bits(ttbr));
|
||||
|
||||
/*
|
||||
* And finally, trigger a uche flush to be sure there isn't anything
|
||||
* lingering in that part of the GPU
|
||||
*/
|
||||
|
||||
OUT_PKT7(ring, CP_EVENT_WRITE, 1);
|
||||
OUT_RING(ring, 0x31);
|
||||
|
||||
a5xx_gpu->cur_ctx = ctx;
|
||||
}
|
||||
|
||||
static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
|
|
@ -151,13 +193,17 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
|||
OUT_RING(ring, 1);
|
||||
|
||||
/* Enable local preemption for finegrain preemption */
|
||||
OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1);
|
||||
OUT_RING(ring, 0x02);
|
||||
//OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1);
|
||||
//OUT_RING(ring, 0x02);
|
||||
OUT_PKT7(ring, CP_PREEMPT_ENABLE_LOCAL, 1);
|
||||
OUT_RING(ring, 0x01);
|
||||
|
||||
/* Allow CP_CONTEXT_SWITCH_YIELD packets in the IB2 */
|
||||
OUT_PKT7(ring, CP_YIELD_ENABLE, 1);
|
||||
OUT_RING(ring, 0x02);
|
||||
|
||||
a5xx_set_pagetable(a5xx_gpu, ring, submit->queue->ctx);
|
||||
|
||||
/* Submit the commands */
|
||||
for (i = 0; i < submit->nr_cmds; i++) {
|
||||
switch (submit->cmd[i].type) {
|
||||
|
|
@ -942,6 +988,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
|
|||
a5xx_preempt_fini(gpu);
|
||||
gpu->nr_rings = 1;
|
||||
}
|
||||
a5xx_gpu->cur_ctx = NULL;
|
||||
|
||||
a5xx_preempt_hw_init(gpu);
|
||||
|
||||
|
|
@ -1697,6 +1744,20 @@ static uint32_t a5xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
|||
return ring->memptrs->rptr = gpu_read(gpu, REG_A5XX_CP_RB_RPTR);
|
||||
}
|
||||
|
||||
static struct msm_gem_address_space *
|
||||
a5xx_create_private_address_space(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_mmu *mmu;
|
||||
|
||||
mmu = msm_iommu_pagetable_create(gpu->aspace->mmu);
|
||||
|
||||
if (IS_ERR(mmu))
|
||||
return ERR_CAST(mmu);
|
||||
|
||||
return msm_gem_address_space_create(mmu,
|
||||
"gpu", 0x100000000ULL, 0x1ffffffffULL);
|
||||
}
|
||||
|
||||
static const struct adreno_gpu_funcs funcs = {
|
||||
.base = {
|
||||
.get_param = adreno_get_param,
|
||||
|
|
@ -1718,6 +1779,7 @@ static const struct adreno_gpu_funcs funcs = {
|
|||
.gpu_state_get = a5xx_gpu_state_get,
|
||||
.gpu_state_put = a5xx_gpu_state_put,
|
||||
.create_address_space = adreno_iommu_create_address_space,
|
||||
.create_private_address_space = a5xx_create_private_address_space,
|
||||
.get_rptr = a5xx_get_rptr,
|
||||
},
|
||||
.get_timestamp = a5xx_get_timestamp,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ struct a5xx_gpu {
|
|||
|
||||
struct msm_ringbuffer *cur_ring;
|
||||
struct msm_ringbuffer *next_ring;
|
||||
struct msm_file_private *cur_ctx;
|
||||
|
||||
struct drm_gem_object *preempt_bo[MSM_GPU_MAX_RINGS];
|
||||
struct drm_gem_object *preempt_counters_bo[MSM_GPU_MAX_RINGS];
|
||||
|
|
|
|||
|
|
@ -356,6 +356,11 @@ MODULE_FIRMWARE("qcom/a530_zap.mdt");
|
|||
MODULE_FIRMWARE("qcom/a530_zap.b00");
|
||||
MODULE_FIRMWARE("qcom/a530_zap.b01");
|
||||
MODULE_FIRMWARE("qcom/a530_zap.b02");
|
||||
MODULE_FIRMWARE("qcom/a540_gpmu.fw2");
|
||||
MODULE_FIRMWARE("qcom/a540_zap.mdt");
|
||||
MODULE_FIRMWARE("qcom/a540_zap.b00");
|
||||
MODULE_FIRMWARE("qcom/a540_zap.b01");
|
||||
MODULE_FIRMWARE("qcom/a540_zap.b02");
|
||||
MODULE_FIRMWARE("qcom/a630_sqe.fw");
|
||||
MODULE_FIRMWARE("qcom/a630_gmu.bin");
|
||||
MODULE_FIRMWARE("qcom/a630_zap.mbn");
|
||||
|
|
|
|||
|
|
@ -682,6 +682,9 @@ static int dpu_encoder_phys_cmd_wait_for_commit_done(
|
|||
if (!dpu_encoder_phys_cmd_is_master(phys_enc))
|
||||
return 0;
|
||||
|
||||
if (phys_enc->hw_ctl->ops.is_started)
|
||||
return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc);
|
||||
|
||||
return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
BIT(DPU_SSPP_CSC_10BIT) | BIT(DPU_SSPP_CDP) |\
|
||||
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_EXCL_RECT))
|
||||
|
||||
#define VIG_MSM8998_MASK \
|
||||
(VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3))
|
||||
|
||||
#define VIG_SDM845_MASK \
|
||||
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3))
|
||||
|
||||
|
|
@ -25,6 +28,11 @@
|
|||
#define VIG_SM8250_MASK \
|
||||
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3LITE))
|
||||
|
||||
#define DMA_MSM8998_MASK \
|
||||
(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\
|
||||
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
|
||||
BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT))
|
||||
|
||||
#define DMA_SDM845_MASK \
|
||||
(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\
|
||||
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
|
||||
|
|
@ -33,6 +41,9 @@
|
|||
#define DMA_CURSOR_SDM845_MASK \
|
||||
(DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR))
|
||||
|
||||
#define DMA_CURSOR_MSM8998_MASK \
|
||||
(DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR))
|
||||
|
||||
#define MIXER_SDM845_MASK \
|
||||
(BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER))
|
||||
|
||||
|
|
@ -49,6 +60,8 @@
|
|||
|
||||
#define MERGE_3D_SM8150_MASK (0)
|
||||
|
||||
#define DSPP_MSM8998_MASK BIT(DPU_DSPP_PCC) | BIT(DPU_DSPP_GC)
|
||||
|
||||
#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC)
|
||||
|
||||
#define INTF_SDM845_MASK (0)
|
||||
|
|
@ -181,6 +194,22 @@ static const uint32_t plane_formats_yuv[] = {
|
|||
* DPU sub blocks config
|
||||
*************************************************************/
|
||||
/* DPU top level caps */
|
||||
static const struct dpu_caps msm8998_dpu_caps = {
|
||||
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.max_mixer_blendstages = 0x7,
|
||||
.qseed_type = DPU_SSPP_SCALER_QSEED3,
|
||||
.smart_dma_rev = DPU_SSPP_SMART_DMA_V1,
|
||||
.ubwc_version = DPU_HW_UBWC_VER_10,
|
||||
.has_src_split = true,
|
||||
.has_dim_layer = true,
|
||||
.has_idle_pc = true,
|
||||
.has_3d_merge = true,
|
||||
.max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
|
||||
.max_hdeci_exp = MAX_HORZ_DECIMATION,
|
||||
.max_vdeci_exp = MAX_VERT_DECIMATION,
|
||||
};
|
||||
|
||||
static const struct dpu_caps sdm845_dpu_caps = {
|
||||
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.max_mixer_blendstages = 0xb,
|
||||
|
|
@ -251,6 +280,35 @@ static const struct dpu_caps sc7280_dpu_caps = {
|
|||
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
|
||||
};
|
||||
|
||||
static const struct dpu_mdp_cfg msm8998_mdp[] = {
|
||||
{
|
||||
.name = "top_0", .id = MDP_TOP,
|
||||
.base = 0x0, .len = 0x458,
|
||||
.features = 0,
|
||||
.highest_bank_bit = 0x2,
|
||||
.clk_ctrls[DPU_CLK_CTRL_VIG0] = {
|
||||
.reg_off = 0x2AC, .bit_off = 0},
|
||||
.clk_ctrls[DPU_CLK_CTRL_VIG1] = {
|
||||
.reg_off = 0x2B4, .bit_off = 0},
|
||||
.clk_ctrls[DPU_CLK_CTRL_VIG2] = {
|
||||
.reg_off = 0x2BC, .bit_off = 0},
|
||||
.clk_ctrls[DPU_CLK_CTRL_VIG3] = {
|
||||
.reg_off = 0x2C4, .bit_off = 0},
|
||||
.clk_ctrls[DPU_CLK_CTRL_DMA0] = {
|
||||
.reg_off = 0x2AC, .bit_off = 8},
|
||||
.clk_ctrls[DPU_CLK_CTRL_DMA1] = {
|
||||
.reg_off = 0x2B4, .bit_off = 8},
|
||||
.clk_ctrls[DPU_CLK_CTRL_DMA2] = {
|
||||
.reg_off = 0x2C4, .bit_off = 8},
|
||||
.clk_ctrls[DPU_CLK_CTRL_DMA3] = {
|
||||
.reg_off = 0x2C4, .bit_off = 12},
|
||||
.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = {
|
||||
.reg_off = 0x3A8, .bit_off = 15},
|
||||
.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = {
|
||||
.reg_off = 0x3B0, .bit_off = 15},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_mdp_cfg sdm845_mdp[] = {
|
||||
{
|
||||
.name = "top_0", .id = MDP_TOP,
|
||||
|
|
@ -339,6 +397,39 @@ static const struct dpu_mdp_cfg sc7280_mdp[] = {
|
|||
/*************************************************************
|
||||
* CTL sub blocks config
|
||||
*************************************************************/
|
||||
static const struct dpu_ctl_cfg msm8998_ctl[] = {
|
||||
{
|
||||
.name = "ctl_0", .id = CTL_0,
|
||||
.base = 0x1000, .len = 0x94,
|
||||
.features = BIT(DPU_CTL_SPLIT_DISPLAY),
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
|
||||
},
|
||||
{
|
||||
.name = "ctl_1", .id = CTL_1,
|
||||
.base = 0x1200, .len = 0x94,
|
||||
.features = 0,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
|
||||
},
|
||||
{
|
||||
.name = "ctl_2", .id = CTL_2,
|
||||
.base = 0x1400, .len = 0x94,
|
||||
.features = BIT(DPU_CTL_SPLIT_DISPLAY),
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
|
||||
},
|
||||
{
|
||||
.name = "ctl_3", .id = CTL_3,
|
||||
.base = 0x1600, .len = 0x94,
|
||||
.features = 0,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
|
||||
},
|
||||
{
|
||||
.name = "ctl_4", .id = CTL_4,
|
||||
.base = 0x1800, .len = 0x94,
|
||||
.features = 0,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_ctl_cfg sdm845_ctl[] = {
|
||||
{
|
||||
.name = "ctl_0", .id = CTL_0,
|
||||
|
|
@ -497,6 +588,15 @@ static const struct dpu_ctl_cfg sc7280_ctl[] = {
|
|||
.virt_num_formats = ARRAY_SIZE(plane_formats), \
|
||||
}
|
||||
|
||||
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_0 =
|
||||
_VIG_SBLK("0", 0, DPU_SSPP_SCALER_QSEED3);
|
||||
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_1 =
|
||||
_VIG_SBLK("1", 0, DPU_SSPP_SCALER_QSEED3);
|
||||
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_2 =
|
||||
_VIG_SBLK("2", 0, DPU_SSPP_SCALER_QSEED3);
|
||||
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_3 =
|
||||
_VIG_SBLK("3", 0, DPU_SSPP_SCALER_QSEED3);
|
||||
|
||||
static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 =
|
||||
_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3);
|
||||
static const struct dpu_sspp_sub_blks sdm845_vig_sblk_1 =
|
||||
|
|
@ -523,6 +623,25 @@ static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK("11", 4);
|
|||
.clk_ctrl = _clkctrl \
|
||||
}
|
||||
|
||||
static const struct dpu_sspp_cfg msm8998_sspp[] = {
|
||||
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_MSM8998_MASK,
|
||||
msm8998_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
|
||||
SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_MSM8998_MASK,
|
||||
msm8998_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1),
|
||||
SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_MSM8998_MASK,
|
||||
msm8998_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2),
|
||||
SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_MSM8998_MASK,
|
||||
msm8998_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3),
|
||||
SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_MSM8998_MASK,
|
||||
sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
|
||||
SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_MSM8998_MASK,
|
||||
sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
|
||||
SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_MSM8998_MASK,
|
||||
sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0),
|
||||
SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_MSM8998_MASK,
|
||||
sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1),
|
||||
};
|
||||
|
||||
static const struct dpu_sspp_cfg sdm845_sspp[] = {
|
||||
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SDM845_MASK,
|
||||
sdm845_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
|
||||
|
|
@ -599,17 +718,6 @@ static const struct dpu_sspp_cfg sc7280_sspp[] = {
|
|||
* MIXER sub blocks config
|
||||
*************************************************************/
|
||||
|
||||
/* SDM845 */
|
||||
|
||||
static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
|
||||
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.maxblendstages = 11, /* excluding base layer */
|
||||
.blendstage_base = { /* offsets relative to mixer base */
|
||||
0x20, 0x38, 0x50, 0x68, 0x80, 0x98,
|
||||
0xb0, 0xc8, 0xe0, 0xf8, 0x110
|
||||
},
|
||||
};
|
||||
|
||||
#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair, _dspp) \
|
||||
{ \
|
||||
.name = _name, .id = _id, \
|
||||
|
|
@ -621,6 +729,43 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
|
|||
.dspp = _dspp \
|
||||
}
|
||||
|
||||
/* MSM8998 */
|
||||
|
||||
static const struct dpu_lm_sub_blks msm8998_lm_sblk = {
|
||||
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.maxblendstages = 7, /* excluding base layer */
|
||||
.blendstage_base = { /* offsets relative to mixer base */
|
||||
0x20, 0x50, 0x80, 0xb0, 0x230,
|
||||
0x260, 0x290
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_lm_cfg msm8998_lm[] = {
|
||||
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_0, LM_2, DSPP_0),
|
||||
LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_1, LM_5, DSPP_1),
|
||||
LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_2, LM_0, 0),
|
||||
LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
|
||||
LM_BLK("lm_4", LM_4, 0x48000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
|
||||
LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_3, LM_1, 0),
|
||||
};
|
||||
|
||||
/* SDM845 */
|
||||
|
||||
static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
|
||||
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.maxblendstages = 11, /* excluding base layer */
|
||||
.blendstage_base = { /* offsets relative to mixer base */
|
||||
0x20, 0x38, 0x50, 0x68, 0x80, 0x98,
|
||||
0xb0, 0xc8, 0xe0, 0xf8, 0x110
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_lm_cfg sdm845_lm[] = {
|
||||
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
|
||||
&sdm845_lm_sblk, PINGPONG_0, LM_1, 0),
|
||||
|
|
@ -682,6 +827,13 @@ static const struct dpu_lm_cfg sc7280_lm[] = {
|
|||
/*************************************************************
|
||||
* DSPP sub blocks config
|
||||
*************************************************************/
|
||||
static const struct dpu_dspp_sub_blks msm8998_dspp_sblk = {
|
||||
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
|
||||
.len = 0x90, .version = 0x10007},
|
||||
.gc = { .id = DPU_DSPP_GC, .base = 0x17c0,
|
||||
.len = 0x90, .version = 0x10007},
|
||||
};
|
||||
|
||||
static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = {
|
||||
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
|
||||
.len = 0x90, .version = 0x10000},
|
||||
|
|
@ -700,6 +852,13 @@ static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = {
|
|||
.sblk = _sblk \
|
||||
}
|
||||
|
||||
static const struct dpu_dspp_cfg msm8998_dspp[] = {
|
||||
DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_MSM8998_MASK,
|
||||
&msm8998_dspp_sblk),
|
||||
DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_MSM8998_MASK,
|
||||
&msm8998_dspp_sblk),
|
||||
};
|
||||
|
||||
static const struct dpu_dspp_cfg sc7180_dspp[] = {
|
||||
DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
|
||||
&sc7180_dspp_sblk),
|
||||
|
|
@ -836,6 +995,13 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
|
|||
.intr_vsync = DPU_IRQ_IDX(_reg, _vsync_bit), \
|
||||
}
|
||||
|
||||
static const struct dpu_intf_cfg msm8998_intf[] = {
|
||||
INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
|
||||
INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
|
||||
INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
|
||||
INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_HDMI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
|
||||
};
|
||||
|
||||
static const struct dpu_intf_cfg sdm845_intf[] = {
|
||||
INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
|
||||
INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
|
||||
|
|
@ -865,9 +1031,55 @@ static const struct dpu_intf_cfg sc7280_intf[] = {
|
|||
* VBIF sub blocks config
|
||||
*************************************************************/
|
||||
/* VBIF QOS remap */
|
||||
static const u32 msm8998_rt_pri_lvl[] = {1, 2, 2, 2};
|
||||
static const u32 msm8998_nrt_pri_lvl[] = {1, 1, 1, 1};
|
||||
static const u32 sdm845_rt_pri_lvl[] = {3, 3, 4, 4, 5, 5, 6, 6};
|
||||
static const u32 sdm845_nrt_pri_lvl[] = {3, 3, 3, 3, 3, 3, 3, 3};
|
||||
|
||||
static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = {
|
||||
{
|
||||
.pps = 1088 * 1920 * 30,
|
||||
.ot_limit = 2,
|
||||
},
|
||||
{
|
||||
.pps = 1088 * 1920 * 60,
|
||||
.ot_limit = 6,
|
||||
},
|
||||
{
|
||||
.pps = 3840 * 2160 * 30,
|
||||
.ot_limit = 16,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_vbif_cfg msm8998_vbif[] = {
|
||||
{
|
||||
.name = "vbif_0", .id = VBIF_0,
|
||||
.base = 0, .len = 0x1040,
|
||||
.default_ot_rd_limit = 32,
|
||||
.default_ot_wr_limit = 32,
|
||||
.features = BIT(DPU_VBIF_QOS_REMAP) | BIT(DPU_VBIF_QOS_OTLIM),
|
||||
.xin_halt_timeout = 0x4000,
|
||||
.dynamic_ot_rd_tbl = {
|
||||
.count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
|
||||
.cfg = msm8998_ot_rdwr_cfg,
|
||||
},
|
||||
.dynamic_ot_wr_tbl = {
|
||||
.count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
|
||||
.cfg = msm8998_ot_rdwr_cfg,
|
||||
},
|
||||
.qos_rt_tbl = {
|
||||
.npriority_lvl = ARRAY_SIZE(msm8998_rt_pri_lvl),
|
||||
.priority_lvl = msm8998_rt_pri_lvl,
|
||||
},
|
||||
.qos_nrt_tbl = {
|
||||
.npriority_lvl = ARRAY_SIZE(msm8998_nrt_pri_lvl),
|
||||
.priority_lvl = msm8998_nrt_pri_lvl,
|
||||
},
|
||||
.memtype_count = 14,
|
||||
.memtype = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_vbif_cfg sdm845_vbif[] = {
|
||||
{
|
||||
.name = "vbif_0", .id = VBIF_0,
|
||||
|
|
@ -908,6 +1120,22 @@ static const struct dpu_reg_dma_cfg sm8250_regdma = {
|
|||
*************************************************************/
|
||||
|
||||
/* SSPP QOS LUTs */
|
||||
static const struct dpu_qos_lut_entry msm8998_qos_linear[] = {
|
||||
{.fl = 4, .lut = 0x1b},
|
||||
{.fl = 5, .lut = 0x5b},
|
||||
{.fl = 6, .lut = 0x15b},
|
||||
{.fl = 7, .lut = 0x55b},
|
||||
{.fl = 8, .lut = 0x155b},
|
||||
{.fl = 9, .lut = 0x555b},
|
||||
{.fl = 10, .lut = 0x1555b},
|
||||
{.fl = 11, .lut = 0x5555b},
|
||||
{.fl = 12, .lut = 0x15555b},
|
||||
{.fl = 13, .lut = 0x55555b},
|
||||
{.fl = 14, .lut = 0},
|
||||
{.fl = 1, .lut = 0x1b},
|
||||
{.fl = 0, .lut = 0}
|
||||
};
|
||||
|
||||
static const struct dpu_qos_lut_entry sdm845_qos_linear[] = {
|
||||
{.fl = 4, .lut = 0x357},
|
||||
{.fl = 5, .lut = 0x3357},
|
||||
|
|
@ -923,6 +1151,15 @@ static const struct dpu_qos_lut_entry sdm845_qos_linear[] = {
|
|||
{.fl = 0, .lut = 0x11222222223357}
|
||||
};
|
||||
|
||||
static const struct dpu_qos_lut_entry msm8998_qos_macrotile[] = {
|
||||
{.fl = 10, .lut = 0x1aaff},
|
||||
{.fl = 11, .lut = 0x5aaff},
|
||||
{.fl = 12, .lut = 0x15aaff},
|
||||
{.fl = 13, .lut = 0x55aaff},
|
||||
{.fl = 1, .lut = 0x1aaff},
|
||||
{.fl = 0, .lut = 0},
|
||||
};
|
||||
|
||||
static const struct dpu_qos_lut_entry sc7180_qos_linear[] = {
|
||||
{.fl = 0, .lut = 0x0011222222335777},
|
||||
};
|
||||
|
|
@ -944,6 +1181,10 @@ static const struct dpu_qos_lut_entry sc7180_qos_macrotile[] = {
|
|||
{.fl = 0, .lut = 0x0011223344556677},
|
||||
};
|
||||
|
||||
static const struct dpu_qos_lut_entry msm8998_qos_nrt[] = {
|
||||
{.fl = 0, .lut = 0x0},
|
||||
};
|
||||
|
||||
static const struct dpu_qos_lut_entry sdm845_qos_nrt[] = {
|
||||
{.fl = 0, .lut = 0x0},
|
||||
};
|
||||
|
|
@ -952,6 +1193,42 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
|
|||
{.fl = 0, .lut = 0x0},
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg msm8998_perf_data = {
|
||||
.max_bw_low = 6700000,
|
||||
.max_bw_high = 6700000,
|
||||
.min_core_ib = 2400000,
|
||||
.min_llcc_ib = 800000,
|
||||
.min_dram_ib = 800000,
|
||||
.undersized_prefill_lines = 2,
|
||||
.xtra_prefill_lines = 2,
|
||||
.dest_scale_prefill_lines = 3,
|
||||
.macrotile_prefill_lines = 4,
|
||||
.yuv_nv12_prefill_lines = 8,
|
||||
.linear_prefill_lines = 1,
|
||||
.downscaling_prefill_lines = 1,
|
||||
.amortizable_threshold = 25,
|
||||
.min_prefill_lines = 25,
|
||||
.danger_lut_tbl = {0xf, 0xffff, 0x0},
|
||||
.safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
|
||||
.qos_lut_tbl = {
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_linear),
|
||||
.entries = msm8998_qos_linear
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
|
||||
.entries = msm8998_qos_macrotile
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_nrt),
|
||||
.entries = msm8998_qos_nrt
|
||||
},
|
||||
},
|
||||
.cdp_cfg = {
|
||||
{.rd_enable = 1, .wr_enable = 1},
|
||||
{.rd_enable = 1, .wr_enable = 0}
|
||||
},
|
||||
.clk_inefficiency_factor = 200,
|
||||
.bw_inefficiency_factor = 120,
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg sdm845_perf_data = {
|
||||
.max_bw_low = 6800000,
|
||||
.max_bw_high = 6800000,
|
||||
|
|
@ -1106,6 +1383,34 @@ static const struct dpu_perf_cfg sc7280_perf_data = {
|
|||
* Hardware catalog init
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
* msm8998_cfg_init(): populate sdm845 dpu sub-blocks reg offsets
|
||||
* and instance counts.
|
||||
*/
|
||||
static void msm8998_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
|
||||
{
|
||||
*dpu_cfg = (struct dpu_mdss_cfg){
|
||||
.caps = &msm8998_dpu_caps,
|
||||
.mdp_count = ARRAY_SIZE(msm8998_mdp),
|
||||
.mdp = msm8998_mdp,
|
||||
.ctl_count = ARRAY_SIZE(msm8998_ctl),
|
||||
.ctl = msm8998_ctl,
|
||||
.sspp_count = ARRAY_SIZE(msm8998_sspp),
|
||||
.sspp = msm8998_sspp,
|
||||
.mixer_count = ARRAY_SIZE(msm8998_lm),
|
||||
.mixer = msm8998_lm,
|
||||
.pingpong_count = ARRAY_SIZE(sdm845_pp),
|
||||
.pingpong = sdm845_pp,
|
||||
.intf_count = ARRAY_SIZE(msm8998_intf),
|
||||
.intf = msm8998_intf,
|
||||
.vbif_count = ARRAY_SIZE(msm8998_vbif),
|
||||
.vbif = msm8998_vbif,
|
||||
.reg_dma_count = 0,
|
||||
.perf = msm8998_perf_data,
|
||||
.mdss_irqs = IRQ_SM8250_MASK,
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* sdm845_cfg_init(): populate sdm845 dpu sub-blocks reg offsets
|
||||
* and instance counts.
|
||||
|
|
@ -1256,6 +1561,8 @@ static void sc7280_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
|
|||
}
|
||||
|
||||
static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = {
|
||||
{ .hw_rev = DPU_HW_VER_300, .cfg_init = msm8998_cfg_init},
|
||||
{ .hw_rev = DPU_HW_VER_301, .cfg_init = msm8998_cfg_init},
|
||||
{ .hw_rev = DPU_HW_VER_400, .cfg_init = sdm845_cfg_init},
|
||||
{ .hw_rev = DPU_HW_VER_401, .cfg_init = sdm845_cfg_init},
|
||||
{ .hw_rev = DPU_HW_VER_500, .cfg_init = sm8150_cfg_init},
|
||||
|
|
|
|||
|
|
@ -435,6 +435,8 @@ enum dpu_clk_ctrl_type {
|
|||
DPU_CLK_CTRL_RGB3,
|
||||
DPU_CLK_CTRL_DMA0,
|
||||
DPU_CLK_CTRL_DMA1,
|
||||
DPU_CLK_CTRL_DMA2,
|
||||
DPU_CLK_CTRL_DMA3,
|
||||
DPU_CLK_CTRL_CURSOR0,
|
||||
DPU_CLK_CTRL_CURSOR1,
|
||||
DPU_CLK_CTRL_INLINE_ROT0_SSPP,
|
||||
|
|
|
|||
|
|
@ -92,6 +92,11 @@ static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx)
|
|||
DPU_REG_WRITE(&ctx->hw, CTL_START, 0x1);
|
||||
}
|
||||
|
||||
static inline bool dpu_hw_ctl_is_started(struct dpu_hw_ctl *ctx)
|
||||
{
|
||||
return !!(DPU_REG_READ(&ctx->hw, CTL_START) & BIT(0));
|
||||
}
|
||||
|
||||
static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx)
|
||||
{
|
||||
trace_dpu_hw_ctl_trigger_prepare(ctx->pending_flush_mask,
|
||||
|
|
@ -587,6 +592,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
|
|||
ops->get_pending_flush = dpu_hw_ctl_get_pending_flush;
|
||||
ops->get_flush_register = dpu_hw_ctl_get_flush_register;
|
||||
ops->trigger_start = dpu_hw_ctl_trigger_start;
|
||||
ops->is_started = dpu_hw_ctl_is_started;
|
||||
ops->trigger_pending = dpu_hw_ctl_trigger_pending;
|
||||
ops->reset = dpu_hw_ctl_reset_control;
|
||||
ops->wait_reset_status = dpu_hw_ctl_wait_reset_status;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,13 @@ struct dpu_hw_ctl_ops {
|
|||
*/
|
||||
void (*trigger_start)(struct dpu_hw_ctl *ctx);
|
||||
|
||||
/**
|
||||
* check if the ctl is started
|
||||
* @ctx : ctl path ctx pointer
|
||||
* @Return: true if started, false if stopped
|
||||
*/
|
||||
bool (*is_started)(struct dpu_hw_ctl *ctx);
|
||||
|
||||
/**
|
||||
* kickoff prepare is in progress hw operation for sw
|
||||
* controlled interfaces: DSI cmd mode and WB interface
|
||||
|
|
|
|||
|
|
@ -1348,6 +1348,7 @@ static const struct dev_pm_ops dpu_pm_ops = {
|
|||
};
|
||||
|
||||
const struct of_device_id dpu_dt_match[] = {
|
||||
{ .compatible = "qcom,msm8998-dpu", },
|
||||
{ .compatible = "qcom,sdm845-dpu", },
|
||||
{ .compatible = "qcom,sc7180-dpu", },
|
||||
{ .compatible = "qcom,sc7280-dpu", },
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_10nm *pll, struct dsi_pll_confi
|
|||
|
||||
pll_freq = pll->vco_current_rate;
|
||||
|
||||
divider = fref * 2;
|
||||
divider = fref;
|
||||
|
||||
multiplier = 1 << FRAC_BITS;
|
||||
dec_multiple = div_u64(pll_freq * multiplier, divider);
|
||||
|
|
@ -428,12 +428,11 @@ static unsigned long dsi_pll_10nm_vco_recalc_rate(struct clk_hw *hw,
|
|||
* 1. Assumes prescaler is disabled
|
||||
*/
|
||||
multiplier = 1 << FRAC_BITS;
|
||||
pll_freq = dec * (ref_clk * 2);
|
||||
tmp64 = (ref_clk * 2 * frac);
|
||||
pll_freq = dec * ref_clk;
|
||||
tmp64 = ref_clk * frac;
|
||||
pll_freq += div_u64(tmp64, multiplier);
|
||||
|
||||
vco_rate = pll_freq;
|
||||
pll_10nm->vco_current_rate = vco_rate;
|
||||
|
||||
DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",
|
||||
pll_10nm->phy->id, (unsigned long)vco_rate, dec, frac);
|
||||
|
|
|
|||
|
|
@ -83,6 +83,12 @@ static struct devfreq_dev_profile msm_devfreq_profile = {
|
|||
static void msm_devfreq_boost_work(struct kthread_work *work);
|
||||
static void msm_devfreq_idle_work(struct kthread_work *work);
|
||||
|
||||
static bool has_devfreq(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
return !!df->devfreq;
|
||||
}
|
||||
|
||||
void msm_devfreq_init(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
|
|
@ -149,6 +155,9 @@ void msm_devfreq_cleanup(struct msm_gpu *gpu)
|
|||
{
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
|
||||
if (!has_devfreq(gpu))
|
||||
return;
|
||||
|
||||
devfreq_cooling_unregister(gpu->cooling);
|
||||
dev_pm_qos_remove_request(&df->boost_freq);
|
||||
dev_pm_qos_remove_request(&df->idle_freq);
|
||||
|
|
@ -156,16 +165,24 @@ void msm_devfreq_cleanup(struct msm_gpu *gpu)
|
|||
|
||||
void msm_devfreq_resume(struct msm_gpu *gpu)
|
||||
{
|
||||
gpu->devfreq.busy_cycles = 0;
|
||||
gpu->devfreq.time = ktime_get();
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
|
||||
devfreq_resume_device(gpu->devfreq.devfreq);
|
||||
if (!has_devfreq(gpu))
|
||||
return;
|
||||
|
||||
df->busy_cycles = 0;
|
||||
df->time = ktime_get();
|
||||
|
||||
devfreq_resume_device(df->devfreq);
|
||||
}
|
||||
|
||||
void msm_devfreq_suspend(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
|
||||
if (!has_devfreq(gpu))
|
||||
return;
|
||||
|
||||
devfreq_suspend_device(df->devfreq);
|
||||
|
||||
cancel_idle_work(df);
|
||||
|
|
@ -185,6 +202,9 @@ void msm_devfreq_boost(struct msm_gpu *gpu, unsigned factor)
|
|||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
uint64_t freq;
|
||||
|
||||
if (!has_devfreq(gpu))
|
||||
return;
|
||||
|
||||
freq = get_freq(gpu);
|
||||
freq *= factor;
|
||||
|
||||
|
|
@ -207,7 +227,7 @@ void msm_devfreq_active(struct msm_gpu *gpu)
|
|||
struct devfreq_dev_status status;
|
||||
unsigned int idle_time;
|
||||
|
||||
if (!df->devfreq)
|
||||
if (!has_devfreq(gpu))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
|
@ -253,7 +273,7 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
|
|||
{
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
|
||||
if (!df->devfreq)
|
||||
if (!has_devfreq(gpu))
|
||||
return;
|
||||
|
||||
msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1),
|
||||
|
|
|
|||
|
|
@ -449,6 +449,36 @@ config DRM_PANEL_SAMSUNG_S6D27A1
|
|||
This panel can be found in Samsung Galaxy Ace 2
|
||||
GT-I8160 mobile phone.
|
||||
|
||||
config DRM_PANEL_SAMSUNG_S6E3FA5
|
||||
tristate "Samsung S6E3FA5 DSI command mode panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select VIDEOMODE_HELPERS
|
||||
help
|
||||
Say Y here if you want to enable support for Samsung S6E3FA5 AMOLED
|
||||
command mode panel as found in OnePlus 5 (2017) devices. The panel has a
|
||||
FHD (1080x1920) resolution and uses 24 bit RGB per pixel. It provides a
|
||||
MIPI DSI interface to the host and has a built-in LED backlight.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called panel-samsung-s6e3fa5.
|
||||
|
||||
config DRM_PANEL_SAMSUNG_S6E3FC1
|
||||
tristate "Samsung S6E3FC1 DSI command mode panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select VIDEOMODE_HELPERS
|
||||
help
|
||||
Say Y here if you want to enable support for Samsung S6E3FC1 AMOLED
|
||||
command mode panel as found in OnePlus 5T (2017) devices. The panel has a
|
||||
FHD (1080x2160) resolution and uses 24 bit RGB per pixel. It provides a
|
||||
MIPI DSI interface to the host and has a built-in LED backlight.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called panel-samsung-s6e3fc1.
|
||||
|
||||
config DRM_PANEL_SAMSUNG_S6E3HA2
|
||||
tristate "Samsung S6E3HA2 DSI video mode panel"
|
||||
depends on OF
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o
|
|||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D27A1) += panel-samsung-s6d27a1.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FA5) += panel-samsung-s6e3fa5.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FC1) += panel-samsung-s6e3fc1.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
|
||||
|
|
|
|||
351
drivers/gpu/drm/panel/panel-samsung-s6e3fa5.c
Normal file
351
drivers/gpu/drm/panel/panel-samsung-s6e3fa5.c
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2021 Jami Kettunen <jami.kettunen@protonmail.com>
|
||||
* Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct s6e3fa5 {
|
||||
struct drm_panel panel;
|
||||
enum drm_panel_orientation orientation;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline struct s6e3fa5 *to_s6e3fa5_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct s6e3fa5, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void s6e3fa5_reset(struct s6e3fa5 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(2000, 3000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
usleep_range(2000, 3000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(2000, 3000);
|
||||
}
|
||||
|
||||
static int s6e3fa5_on(struct s6e3fa5 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set tear on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0x04);
|
||||
dsi_dcs_write_seq(dsi, 0xb4, 0x06, 0x0c, 0x12);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
dsi_dcs_write_seq(dsi, 0xc3, 0x01);
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0x18);
|
||||
dsi_dcs_write_seq(dsi, 0xc3, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fa5_off(struct s6e3fa5 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(40);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(160);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fa5_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct s6e3fa5 *ctx = to_s6e3fa5_panel(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(ctx->supply);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s6e3fa5_reset(ctx);
|
||||
|
||||
ret = s6e3fa5_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_disable(ctx->supply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fa5_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct s6e3fa5 *ctx = to_s6e3fa5_panel(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = s6e3fa5_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_disable(ctx->supply);
|
||||
|
||||
ctx->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode s6e3fa5_mode = {
|
||||
.clock = (1080 + 120 + 19 + 70) * (1920 + 18 + 2 + 4) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 120,
|
||||
.hsync_end = 1080 + 120 + 19,
|
||||
.htotal = 1080 + 120 + 19 + 70,
|
||||
.vdisplay = 1920,
|
||||
.vsync_start = 1920 + 18,
|
||||
.vsync_end = 1920 + 18 + 2,
|
||||
.vtotal = 1920 + 18 + 2 + 4,
|
||||
.width_mm = 68,
|
||||
.height_mm = 122,
|
||||
};
|
||||
|
||||
static int s6e3fa5_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
struct s6e3fa5 *ctx;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &s6e3fa5_mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
ctx = to_s6e3fa5_panel(panel);
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_connector_set_panel_orientation(connector, ctx->orientation);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs s6e3fa5_panel_funcs = {
|
||||
.prepare = s6e3fa5_prepare,
|
||||
.unprepare = s6e3fa5_unprepare,
|
||||
.get_modes = s6e3fa5_get_modes,
|
||||
};
|
||||
|
||||
static int s6e3fa5_bl_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness = backlight_get_brightness(bl);
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fa5_bl_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return brightness & 0xff;
|
||||
}
|
||||
|
||||
static const struct backlight_ops s6e3fa5_bl_ops = {
|
||||
.update_status = s6e3fa5_bl_update_status,
|
||||
.get_brightness = s6e3fa5_bl_get_brightness,
|
||||
};
|
||||
|
||||
static struct backlight_device *
|
||||
s6e3fa5_create_backlight(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
const struct backlight_properties props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.brightness = 255,
|
||||
.max_brightness = 255,
|
||||
};
|
||||
|
||||
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
|
||||
&s6e3fa5_bl_ops, &props);
|
||||
}
|
||||
|
||||
static int s6e3fa5_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct s6e3fa5 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->supply = devm_regulator_get(dev, "vddio");
|
||||
if (IS_ERR(ctx->supply))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->supply),
|
||||
"Failed to get vddio regulator\n");
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ctx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
|
||||
"Failed to get reset-gpios\n");
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_HSE |
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
|
||||
ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to parse rotation property: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &s6e3fa5_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ctx->panel.backlight = s6e3fa5_create_backlight(dsi);
|
||||
if (IS_ERR(ctx->panel.backlight))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
|
||||
"Failed to create backlight\n");
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fa5_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct s6e3fa5 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id s6e3fa5_of_match[] = {
|
||||
{ .compatible = "samsung,s6e3fa5" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, s6e3fa5_of_match);
|
||||
|
||||
static struct mipi_dsi_driver s6e3fa5_driver = {
|
||||
.probe = s6e3fa5_probe,
|
||||
.remove = s6e3fa5_remove,
|
||||
.driver = {
|
||||
.name = "panel-samsung-s6e3fa5",
|
||||
.of_match_table = s6e3fa5_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(s6e3fa5_driver);
|
||||
|
||||
MODULE_AUTHOR("Jami Kettunen <jami.kettunen@protonmail.com>");
|
||||
MODULE_DESCRIPTION("DRM driver for Samsung S6E3FA5 AMOLED DSI cmd mode panel found on OnePlus 5 phones");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
345
drivers/gpu/drm/panel/panel-samsung-s6e3fc1.c
Normal file
345
drivers/gpu/drm/panel/panel-samsung-s6e3fc1.c
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2021 Jami Kettunen <jami.kettunen@protonmail.com>
|
||||
* Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/swab.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct s6e3fc1 {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline struct s6e3fc1 *to_s6e3fc1_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct s6e3fc1, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void s6e3fc1_reset(struct s6e3fc1 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(2000, 3000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
usleep_range(2000, 3000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(2000, 3000);
|
||||
}
|
||||
|
||||
static int s6e3fc1_on(struct s6e3fc1 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(25);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set tear on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xfc, 0x5a, 0x5a);
|
||||
dsi_dcs_write_seq(dsi, 0xe8, 0x64, 0x08, 0x0c);
|
||||
dsi_dcs_write_seq(dsi, 0xfc, 0xa5, 0xa5);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0x01);
|
||||
dsi_dcs_write_seq(dsi, 0xed, 0x04);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fc1_off(struct s6e3fc1 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(160);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fc1_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct s6e3fc1 *ctx = to_s6e3fc1_panel(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(ctx->supply);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s6e3fc1_reset(ctx);
|
||||
|
||||
ret = s6e3fc1_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_disable(ctx->supply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fc1_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct s6e3fc1 *ctx = to_s6e3fc1_panel(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = s6e3fc1_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_disable(ctx->supply);
|
||||
|
||||
ctx->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode s6e3fc1_mode = {
|
||||
.clock = (1080 + 128 + 16 + 64) * (2160 + 18 + 2 + 4) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 128,
|
||||
.hsync_end = 1080 + 128 + 16,
|
||||
.htotal = 1080 + 128 + 16 + 64,
|
||||
.vdisplay = 2160,
|
||||
.vsync_start = 2160 + 18,
|
||||
.vsync_end = 2160 + 18 + 2,
|
||||
.vtotal = 2160 + 18 + 2 + 4,
|
||||
.width_mm = 68,
|
||||
.height_mm = 137,
|
||||
};
|
||||
|
||||
static int s6e3fc1_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &s6e3fc1_mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs s6e3fc1_panel_funcs = {
|
||||
.prepare = s6e3fc1_prepare,
|
||||
.unprepare = s6e3fc1_unprepare,
|
||||
.get_modes = s6e3fc1_get_modes,
|
||||
};
|
||||
|
||||
static int s6e3fc1_bl_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
brightness = (u16)backlight_get_brightness(bl);
|
||||
// This panel needs the high and low bytes swapped for the brightness value
|
||||
brightness = __swab16(brightness);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fc1_bl_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
// This panel needs the high and low bytes swapped for the brightness value
|
||||
brightness = __swab16(brightness);
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return brightness;
|
||||
}
|
||||
|
||||
static const struct backlight_ops s6e3fc1_bl_ops = {
|
||||
.update_status = s6e3fc1_bl_update_status,
|
||||
.get_brightness = s6e3fc1_bl_get_brightness,
|
||||
};
|
||||
|
||||
static struct backlight_device *
|
||||
s6e3fc1_create_backlight(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
const struct backlight_properties props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.brightness = 1023,
|
||||
.max_brightness = 1023,
|
||||
};
|
||||
|
||||
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
|
||||
&s6e3fc1_bl_ops, &props);
|
||||
}
|
||||
|
||||
static int s6e3fc1_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct s6e3fc1 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->supply = devm_regulator_get(dev, "vddio");
|
||||
if (IS_ERR(ctx->supply))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->supply),
|
||||
"Failed to get vddio regulator\n");
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ctx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
|
||||
"Failed to get reset-gpios\n");
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_HSE |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &s6e3fc1_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ctx->panel.backlight = s6e3fc1_create_backlight(dsi);
|
||||
if (IS_ERR(ctx->panel.backlight))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
|
||||
"Failed to create backlight\n");
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fc1_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct s6e3fc1 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id s6e3fc1_of_match[] = {
|
||||
{ .compatible = "samsung,s6e3fc1" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, s6e3fc1_of_match);
|
||||
|
||||
static struct mipi_dsi_driver s6e3fc1_driver = {
|
||||
.probe = s6e3fc1_probe,
|
||||
.remove = s6e3fc1_remove,
|
||||
.driver = {
|
||||
.name = "panel-samsung-s6e3fc1",
|
||||
.of_match_table = s6e3fc1_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(s6e3fc1_driver);
|
||||
|
||||
MODULE_AUTHOR("Jami Kettunen <jami.kettunen@protonmail.com>");
|
||||
MODULE_DESCRIPTION("DRM driver for Samsung S6E3FC1 AMOLED DSI cmd mode panel found on OnePlus 5T phones");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -248,6 +248,9 @@ void virtio_gpu_array_put_free(struct virtio_gpu_object_array *objs)
|
|||
{
|
||||
u32 i;
|
||||
|
||||
if (!objs)
|
||||
return;
|
||||
|
||||
for (i = 0; i < objs->nents; i++)
|
||||
drm_gem_object_put(objs->objs[i]);
|
||||
virtio_gpu_array_free(objs);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@
|
|||
#define QUP_MX_READ_CNT 0x208
|
||||
#define QUP_IN_FIFO_BASE 0x218
|
||||
#define QUP_I2C_CLK_CTL 0x400
|
||||
#define QUP_I2C_CLK_CTL_SDA_NR GENMASK(27, 26)
|
||||
#define QUP_I2C_CLK_CTL_SCL_NR GENMASK(25, 24)
|
||||
#define QUP_I2C_STATUS 0x404
|
||||
#define QUP_I2C_MASTER_GEN 0x408
|
||||
|
||||
|
|
@ -1663,6 +1665,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
|
|||
int ret, fs_div, hs_div;
|
||||
u32 src_clk_freq = DEFAULT_SRC_CLK;
|
||||
u32 clk_freq = DEFAULT_CLK_FREQ;
|
||||
u32 noise_reject_scl = 0, noise_reject_sda = 0;
|
||||
int blocks;
|
||||
bool is_qup_v1;
|
||||
|
||||
|
|
@ -1860,6 +1863,19 @@ nodma:
|
|||
qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff);
|
||||
}
|
||||
|
||||
/* SCL/SDA Noise rejection (optional) */
|
||||
ret = device_property_read_u32(qup->dev, "qcom,noise-reject-scl",
|
||||
&noise_reject_scl);
|
||||
if (ret == 0)
|
||||
qup->clk_ctl |= FIELD_PREP(QUP_I2C_CLK_CTL_SCL_NR,
|
||||
noise_reject_scl);
|
||||
|
||||
ret = device_property_read_u32(qup->dev, "qcom,noise-reject-sda",
|
||||
&noise_reject_sda);
|
||||
if (ret == 0)
|
||||
qup->clk_ctl |= FIELD_PREP(QUP_I2C_CLK_CTL_SDA_NR,
|
||||
noise_reject_sda);
|
||||
|
||||
/*
|
||||
* Time it takes for a byte to be clocked out on the bus.
|
||||
* Each byte takes 9 clock cycles (8 bits + 1 ack).
|
||||
|
|
|
|||
|
|
@ -242,6 +242,19 @@ config KEYBOARD_GPIO
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called gpio_keys.
|
||||
|
||||
config KEYBOARD_GPIO_FASTMATRIX
|
||||
tristate "GPIO Keyboard"
|
||||
depends on GPIOLIB
|
||||
select INPUT_MATRIXKMAP
|
||||
help
|
||||
This driver implements support for matrix keypads and/or
|
||||
keyboards connected directly to GPIO pins of a CPU, made
|
||||
to also perform with slow I2C GPIO expanders and even
|
||||
on matrices with no protection diodes.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called gpio_fastmatrix
|
||||
|
||||
config KEYBOARD_GPIO_POLLED
|
||||
tristate "Polled GPIO buttons"
|
||||
depends on GPIOLIB
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ obj-$(CONFIG_KEYBOARD_DLINK_DIR685) += dlink-dir685-touchkeys.o
|
|||
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_GOLDFISH_EVENTS) += goldfish_events.o
|
||||
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
|
||||
obj-$(CONFIG_KEYBOARD_GPIO_FASTMATRIX) += gpio_fastmatrix.o
|
||||
obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o
|
||||
obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_TCA8418) += tca8418_keypad.o
|
||||
|
|
|
|||
528
drivers/input/keyboard/gpio_fastmatrix.c
Normal file
528
drivers/input/keyboard/gpio_fastmatrix.c
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Fast GPIO driven keyboard/keypad matrix driver
|
||||
*
|
||||
* Copyright (c) 2020 AngeloGioacchino Del Regno
|
||||
* <angelogioacchino.delregno@somainline.org>
|
||||
* Based on matrix_keypad.c
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input/matrix_keypad.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
struct gpio_keyboard {
|
||||
struct device *dev;
|
||||
struct input_dev *input_dev;
|
||||
unsigned int row_shift;
|
||||
|
||||
struct gpio_descs *row_gpios;
|
||||
struct gpio_descs *col_gpios;
|
||||
u32 autorescan_ms;
|
||||
u32 debounce_ms;
|
||||
u32 col_scan_us;
|
||||
int clustered_irq;
|
||||
|
||||
DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS);
|
||||
|
||||
u32 last_key_state[MATRIX_MAX_COLS];
|
||||
struct delayed_work work;
|
||||
struct mutex lock;
|
||||
|
||||
bool drive_inactive_cols;
|
||||
bool gpio_all_disabled;
|
||||
bool scan_pending;
|
||||
bool stopped;
|
||||
};
|
||||
|
||||
static int activate_one_column(struct gpio_keyboard *gkb, int col, bool wait)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpiod_direction_output(gkb->col_gpios->desc[col], 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (wait && gkb->col_scan_us)
|
||||
udelay(gkb->col_scan_us);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: If drive_inactive_cols is false, then the GPIO has to be put into
|
||||
* HiZ when de-activated to cause minmal side effect when scanning other
|
||||
* columns. In that case it is configured here to be input, otherwise it is
|
||||
* driven with the inactive value.
|
||||
*/
|
||||
static int deactivate_one_column(struct gpio_keyboard *gkb, int col)
|
||||
{
|
||||
gpiod_set_value_cansleep(gkb->col_gpios->desc[col], 0);
|
||||
if (!gkb->drive_inactive_cols)
|
||||
return gpiod_direction_input(gkb->col_gpios->desc[col]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int activate_all_cols(struct gpio_keyboard *gkb)
|
||||
{
|
||||
unsigned long val = ULONG_MAX;
|
||||
int ret, col;
|
||||
|
||||
/*
|
||||
* Shortcut! If we don't have to set direction, we can use
|
||||
* the way faster gpiod array setting instead.
|
||||
*/
|
||||
if (gkb->drive_inactive_cols) {
|
||||
return gpiod_set_array_value_cansleep(gkb->col_gpios->ndescs,
|
||||
gkb->col_gpios->desc,
|
||||
gkb->col_gpios->info,
|
||||
&val);
|
||||
}
|
||||
|
||||
for (col = 0; col < gkb->col_gpios->ndescs; col++) {
|
||||
ret = activate_one_column(gkb, col, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int deactivate_all_cols(struct gpio_keyboard *gkb)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
int col, ret;
|
||||
|
||||
/*
|
||||
* If the GPIO controller supports setting all pins at once it
|
||||
* is going to be way faster, otherwise this function will fall
|
||||
* back to setting all pins one at a time.
|
||||
*/
|
||||
ret = gpiod_set_array_value_cansleep(gkb->col_gpios->ndescs,
|
||||
gkb->col_gpios->desc,
|
||||
gkb->col_gpios->info, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!gkb->drive_inactive_cols) {
|
||||
for (col = 0; col < gkb->col_gpios->ndescs; col++)
|
||||
gpiod_direction_input(gkb->col_gpios->desc[col]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void enable_row_irqs(struct gpio_keyboard *gkb)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (gkb->clustered_irq > 0)
|
||||
enable_irq(gkb->clustered_irq);
|
||||
else {
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++)
|
||||
enable_irq(gpiod_to_irq(gkb->row_gpios->desc[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static void disable_row_irqs(struct gpio_keyboard *gkb)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (gkb->clustered_irq > 0)
|
||||
disable_irq_nosync(gkb->clustered_irq);
|
||||
else {
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++)
|
||||
disable_irq_nosync(gpiod_to_irq(gkb->row_gpios->desc[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This gets the keys from keyboard and reports it to input subsystem
|
||||
*/
|
||||
static void gpio_keyboard_scan(struct work_struct *work)
|
||||
{
|
||||
struct gpio_keyboard *gkb =
|
||||
container_of(work, struct gpio_keyboard, work.work);
|
||||
struct input_dev *input_dev = gkb->input_dev;
|
||||
const unsigned short *keycodes = input_dev->keycode;
|
||||
u32 *new_state;
|
||||
unsigned long row_values;
|
||||
int ret, row, col, code;
|
||||
u32 keymask = 0;
|
||||
|
||||
new_state = kzalloc(gkb->col_gpios->ndescs * sizeof(*new_state),
|
||||
GFP_KERNEL);
|
||||
if (!new_state)
|
||||
return;
|
||||
|
||||
/* de-activate all columns for scanning */
|
||||
deactivate_all_cols(gkb);
|
||||
|
||||
/* assert each column and read the row status out */
|
||||
for (col = 0; col < gkb->col_gpios->ndescs; col++) {
|
||||
activate_one_column(gkb, col, true);
|
||||
|
||||
ret = gpiod_get_array_value_cansleep(gkb->row_gpios->ndescs,
|
||||
gkb->row_gpios->desc,
|
||||
gkb->row_gpios->info,
|
||||
&row_values);
|
||||
new_state[col] = row_values;
|
||||
keymask |= new_state[col];
|
||||
|
||||
if (deactivate_one_column(gkb, col)) {
|
||||
activate_all_cols(gkb);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
activate_all_cols(gkb);
|
||||
|
||||
for (col = 0; col < gkb->col_gpios->ndescs; col++) {
|
||||
u32 bits_changed = gkb->last_key_state[col] ^ new_state[col];
|
||||
if (bits_changed == 0)
|
||||
continue;
|
||||
|
||||
for (row = 0; bits_changed; row++, bits_changed >>=1 ) {
|
||||
if (!(bits_changed & BIT(0)))
|
||||
continue;
|
||||
|
||||
code = MATRIX_SCAN_CODE(row, col, gkb->row_shift);
|
||||
input_event(input_dev, EV_MSC, MSC_SCAN, code);
|
||||
input_report_key(input_dev, keycodes[code],
|
||||
new_state[col] & (1 << row));
|
||||
}
|
||||
}
|
||||
input_sync(input_dev);
|
||||
|
||||
memcpy(gkb->last_key_state, new_state, sizeof(gkb->last_key_state));
|
||||
kfree(new_state);
|
||||
|
||||
/* Avoid missing key release events on quirky hardware */
|
||||
if (gkb->autorescan_ms && keymask) {
|
||||
queue_delayed_work(system_highpri_wq, &gkb->work,
|
||||
msecs_to_jiffies(gkb->autorescan_ms));
|
||||
return;
|
||||
}
|
||||
end:
|
||||
/* Enable IRQs again */
|
||||
mutex_lock(&gkb->lock);
|
||||
gkb->scan_pending = false;
|
||||
enable_row_irqs(gkb);
|
||||
mutex_unlock(&gkb->lock);
|
||||
}
|
||||
|
||||
static irqreturn_t gpio_keyboard_interrupt(int irq, void *id)
|
||||
{
|
||||
struct gpio_keyboard *gkb = id;
|
||||
|
||||
/*
|
||||
* See if another IRQ beaten us to it and scheduled the
|
||||
* scan already. In that case we should not try to
|
||||
* disable IRQs again.
|
||||
*/
|
||||
if (unlikely(gkb->scan_pending || gkb->stopped))
|
||||
goto out;
|
||||
|
||||
mutex_lock(&gkb->lock);
|
||||
|
||||
disable_row_irqs(gkb);
|
||||
gkb->scan_pending = true;
|
||||
mod_delayed_work(system_highpri_wq, &gkb->work,
|
||||
msecs_to_jiffies(gkb->debounce_ms));
|
||||
|
||||
out:
|
||||
mutex_unlock(&gkb->lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int gpio_keyboard_start(struct input_dev *dev)
|
||||
{
|
||||
struct gpio_keyboard *gkb = input_get_drvdata(dev);
|
||||
|
||||
gkb->stopped = false;
|
||||
|
||||
/*
|
||||
* Schedule an immediate key scan to capture current key state;
|
||||
* columns will be activated and IRQs be enabled after the scan.
|
||||
*/
|
||||
schedule_delayed_work(&gkb->work, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_keyboard_stop(struct input_dev *dev)
|
||||
{
|
||||
struct gpio_keyboard *gkb = input_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&gkb->lock);
|
||||
gkb->stopped = true;
|
||||
mutex_unlock(&gkb->lock);
|
||||
|
||||
flush_delayed_work(&gkb->work);
|
||||
/*
|
||||
* gpio_keyboard_scan() will leave IRQs enabled;
|
||||
* we should disable them now.
|
||||
*/
|
||||
disable_row_irqs(gkb);
|
||||
}
|
||||
|
||||
static void __maybe_unused gpio_keyboard_wakeup_en(struct gpio_keyboard *gkb)
|
||||
{
|
||||
int irq, i;
|
||||
|
||||
if (gkb->clustered_irq > 0) {
|
||||
if (enable_irq_wake(gkb->clustered_irq) == 0)
|
||||
gkb->gpio_all_disabled = true;
|
||||
} else {
|
||||
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++) {
|
||||
if (!test_bit(i, gkb->disabled_gpios)) {
|
||||
irq = gpiod_to_irq(gkb->row_gpios->desc[i]);
|
||||
|
||||
if (enable_irq_wake(irq) == 0)
|
||||
__set_bit(i, gkb->disabled_gpios);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __maybe_unused gpio_keyboard_wakeup_dis(struct gpio_keyboard *gkb)
|
||||
{
|
||||
int irq, i;
|
||||
|
||||
if (gkb->clustered_irq > 0) {
|
||||
if (gkb->gpio_all_disabled) {
|
||||
disable_irq_wake(gkb->clustered_irq);
|
||||
gkb->gpio_all_disabled = false;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++) {
|
||||
if (test_and_clear_bit(i, gkb->disabled_gpios)) {
|
||||
irq = gpiod_to_irq(gkb->row_gpios->desc[i]);
|
||||
disable_irq_wake(irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __maybe_unused gpio_keyboard_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct gpio_keyboard *gkb = platform_get_drvdata(pdev);
|
||||
|
||||
gpio_keyboard_stop(gkb->input_dev);
|
||||
|
||||
if (device_may_wakeup(&pdev->dev))
|
||||
gpio_keyboard_wakeup_en(gkb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused gpio_keyboard_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct gpio_keyboard *gkb = platform_get_drvdata(pdev);
|
||||
|
||||
if (device_may_wakeup(&pdev->dev))
|
||||
gpio_keyboard_wakeup_dis(gkb);
|
||||
|
||||
gpio_keyboard_start(gkb->input_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static SIMPLE_DEV_PM_OPS(gpio_keyboard_pm_ops,
|
||||
gpio_keyboard_suspend, gpio_keyboard_resume);
|
||||
|
||||
static int gpio_keyboard_init_gpio(struct platform_device *pdev,
|
||||
struct gpio_keyboard *gkb)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
if (gkb->clustered_irq > 0) {
|
||||
ret = devm_request_threaded_irq(gkb->dev, gkb->clustered_irq,
|
||||
NULL, gpio_keyboard_interrupt,
|
||||
IRQF_ONESHOT, "gpio-keyboard", gkb);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot get IRQ %d\n", gkb->clustered_irq);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++) {
|
||||
ret = devm_request_threaded_irq(
|
||||
gkb->dev,
|
||||
gpiod_to_irq(gkb->row_gpios->desc[i]),
|
||||
NULL, gpio_keyboard_interrupt,
|
||||
IRQF_TRIGGER_HIGH |
|
||||
IRQF_TRIGGER_LOW,
|
||||
"gpio-keyboard", gkb);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot get IRQ for gpio%d\n",
|
||||
desc_to_gpio(gkb->row_gpios->desc[i]));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* initialized as disabled - enabled by input->open */
|
||||
disable_row_irqs(gkb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_keyboard_parse_dt(struct gpio_keyboard *gkb)
|
||||
{
|
||||
struct device *dev = gkb->dev;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Get as GPIOD_ASIS to use the configuration that comes from
|
||||
* device-tree. Anyway, in many cases the row is configured as
|
||||
* input, while the column is configured as output-high.
|
||||
*
|
||||
* This may vary depending on the hardware.
|
||||
*/
|
||||
gkb->row_gpios = devm_gpiod_get_array(dev, "row", GPIOD_ASIS);
|
||||
if (IS_ERR(gkb->row_gpios))
|
||||
return PTR_ERR(gkb->row_gpios);
|
||||
|
||||
gkb->col_gpios = devm_gpiod_get_array(dev, "col", GPIOD_ASIS);
|
||||
if (IS_ERR(gkb->col_gpios))
|
||||
return PTR_ERR(gkb->col_gpios);
|
||||
|
||||
/* All of these additional properties are optional */
|
||||
device_property_read_string(dev, "label", &gkb->input_dev->name);
|
||||
|
||||
if (device_property_read_bool(dev, "autorepeat"))
|
||||
__set_bit(EV_REP, gkb->input_dev->evbit);
|
||||
|
||||
gkb->drive_inactive_cols =
|
||||
device_property_read_bool(dev, "drive-inactive-cols");
|
||||
|
||||
rc = device_property_read_u32(dev, "autorescan-ms",
|
||||
&gkb->autorescan_ms);
|
||||
if (rc < 0)
|
||||
gkb->autorescan_ms = 0;
|
||||
|
||||
rc = device_property_read_u32(dev, "debounce-delay-ms",
|
||||
&gkb->debounce_ms);
|
||||
if (rc < 0)
|
||||
gkb->debounce_ms = 0;
|
||||
|
||||
rc = device_property_read_u32(dev, "col-scan-delay-us",
|
||||
&gkb->col_scan_us);
|
||||
if (rc < 0)
|
||||
gkb->col_scan_us = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_keyboard_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_keyboard *gkb;
|
||||
bool wake;
|
||||
int irq, ret;
|
||||
|
||||
gkb = devm_kmalloc(&pdev->dev, sizeof(*gkb), GFP_KERNEL);
|
||||
if (!gkb)
|
||||
return -ENOMEM;
|
||||
|
||||
gkb->dev = &pdev->dev;
|
||||
gkb->input_dev = devm_input_allocate_device(&pdev->dev);
|
||||
if (!gkb->input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = gpio_keyboard_parse_dt(gkb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
irq = platform_get_irq_optional(pdev, 0);
|
||||
gkb->clustered_irq = (irq > 0) ? irq : 0;
|
||||
gkb->row_shift = get_count_order(gkb->col_gpios->ndescs);
|
||||
gkb->stopped = true;
|
||||
INIT_DELAYED_WORK(&gkb->work, gpio_keyboard_scan);
|
||||
memset(gkb->last_key_state, 0, sizeof(gkb->last_key_state));
|
||||
mutex_init(&gkb->lock);
|
||||
|
||||
if (!gkb->input_dev->name)
|
||||
gkb->input_dev->name = pdev->name;
|
||||
gkb->input_dev->id.bustype = BUS_HOST;
|
||||
gkb->input_dev->dev.parent = &pdev->dev;
|
||||
gkb->input_dev->open = gpio_keyboard_start;
|
||||
gkb->input_dev->close = gpio_keyboard_stop;
|
||||
|
||||
ret = matrix_keypad_build_keymap(NULL, NULL,
|
||||
gkb->row_gpios->ndescs,
|
||||
gkb->col_gpios->ndescs,
|
||||
NULL, gkb->input_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to build keymap\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
input_set_capability(gkb->input_dev, EV_MSC, MSC_SCAN);
|
||||
input_set_drvdata(gkb->input_dev, gkb);
|
||||
|
||||
ret = gpio_keyboard_init_gpio(pdev, gkb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = input_register_device(gkb->input_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
wake = device_property_read_bool(&pdev->dev, "wakeup-source");
|
||||
device_init_wakeup(&pdev->dev, wake);
|
||||
|
||||
platform_set_drvdata(pdev, gkb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_keyboard_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_keyboard *gkb = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
if (gkb->clustered_irq > 0) {
|
||||
free_irq(gkb->clustered_irq, gkb);
|
||||
} else {
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++)
|
||||
free_irq(gpiod_to_irq(gkb->row_gpios->desc[i]), gkb);
|
||||
}
|
||||
input_unregister_device(gkb->input_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id gpio_keyboard_dt_match[] = {
|
||||
{ .compatible = "gpio-fastmatrix-keyboard" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, gpio_keyboard_dt_match);
|
||||
|
||||
static struct platform_driver gpio_keyboard_driver = {
|
||||
.probe = gpio_keyboard_probe,
|
||||
.remove = gpio_keyboard_remove,
|
||||
.driver = {
|
||||
.name = "gpio-fastmatrix-keyboard",
|
||||
.pm = &gpio_keyboard_pm_ops,
|
||||
.of_match_table = gpio_keyboard_dt_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(gpio_keyboard_driver);
|
||||
|
||||
MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>");
|
||||
MODULE_DESCRIPTION("Fast GPIO driven keyboard/keypad matrix driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:gpio-fastmatrix-keyboard");
|
||||
|
|
@ -186,6 +186,18 @@ config INPUT_PMIC8XXX_PWRKEY
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called pmic8xxx-pwrkey.
|
||||
|
||||
config INPUT_QCOM_SPMI_HAPTICS
|
||||
tristate "Qualcomm SPMI HAPTICS"
|
||||
depends on ARCH_QCOM
|
||||
depends on SPMI
|
||||
select INPUT_FF_MEMLESS
|
||||
help
|
||||
This option enables support for the haptics found in pmi8998 and
|
||||
related PMICs. Based on the ff-memless interface.
|
||||
|
||||
To compile this driver as module, choose M here: the
|
||||
module will be called qcom_spmi_haptics.
|
||||
|
||||
config INPUT_SPARCSPKR
|
||||
tristate "SPARC Speaker support"
|
||||
depends on PCI && SPARC64
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
|
|||
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
|
||||
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
|
||||
obj-$(CONFIG_INPUT_PWM_VIBRA) += pwm-vibra.o
|
||||
obj-$(CONFIG_INPUT_QCOM_SPMI_HAPTICS) += qcom-spmi-haptics.o
|
||||
obj-$(CONFIG_INPUT_RAVE_SP_PWRBUTTON) += rave-sp-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
|
||||
obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o
|
||||
|
|
|
|||
977
drivers/input/misc/qcom-spmi-haptics.c
Normal file
977
drivers/input/misc/qcom-spmi-haptics.c
Normal file
|
|
@ -0,0 +1,977 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, Caleb Connolly <caleb@connolly.tech>
|
||||
* Qualcomm QPMI haptics driver for pmi8998 and related PMICs.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/input/qcom,spmi-haptics.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
#define HAP_STATUS_1_REG 0x0A
|
||||
#define HAP_BUSY_BIT BIT(1)
|
||||
#define SC_FLAG_BIT BIT(3)
|
||||
#define AUTO_RES_ERROR_BIT BIT(4)
|
||||
|
||||
#define HAP_LRA_AUTO_RES_LO_REG 0x0B
|
||||
#define HAP_LRA_AUTO_RES_HI_REG 0x0C
|
||||
|
||||
#define HAP_EN_CTL_REG 0x46
|
||||
#define HAP_EN_BIT BIT(7)
|
||||
|
||||
#define HAP_EN_CTL2_REG 0x48
|
||||
#define BRAKE_EN_BIT BIT(0)
|
||||
|
||||
#define HAP_AUTO_RES_CTRL_REG 0x4B
|
||||
#define AUTO_RES_EN_BIT BIT(7)
|
||||
#define AUTO_RES_ERR_RECOVERY_BIT BIT(3)
|
||||
#define AUTO_RES_EN_FLAG_BIT BIT(0)
|
||||
|
||||
#define HAP_CFG1_REG 0x4C
|
||||
#define HAP_ACT_TYPE_MASK BIT(0)
|
||||
|
||||
#define HAP_CFG2_REG 0x4D
|
||||
#define HAP_LRA_RES_TYPE_MASK BIT(0)
|
||||
|
||||
#define HAP_SEL_REG 0x4E
|
||||
#define HAP_WF_SOURCE_MASK GENMASK(5, 4)
|
||||
#define HAP_WF_SOURCE_SHIFT 4
|
||||
|
||||
#define HAP_LRA_AUTO_RES_REG 0x4F
|
||||
#define LRA_AUTO_RES_MODE_MASK GENMASK(6, 4)
|
||||
#define LRA_AUTO_RES_MODE_SHIFT 4
|
||||
#define LRA_HIGH_Z_MASK GENMASK(3, 2)
|
||||
#define LRA_HIGH_Z_SHIFT 2
|
||||
#define LRA_RES_CAL_MASK GENMASK(1, 0)
|
||||
#define HAP_RES_CAL_PERIOD_MIN 4
|
||||
#define HAP_RES_CAL_PERIOD_MAX 32
|
||||
|
||||
#define HAP_VMAX_CFG_REG 0x51
|
||||
#define HAP_VMAX_OVD_BIT BIT(6)
|
||||
#define HAP_VMAX_MASK GENMASK(5, 1)
|
||||
#define HAP_VMAX_SHIFT 1
|
||||
|
||||
#define HAP_ILIM_CFG_REG 0x52
|
||||
#define HAP_ILIM_SEL_MASK BIT(0)
|
||||
#define HAP_ILIM_400_MA 0
|
||||
#define HAP_ILIM_800_MA 1
|
||||
|
||||
#define HAP_SC_DEB_REG 0x53
|
||||
#define HAP_SC_DEB_MASK GENMASK(2, 0)
|
||||
#define HAP_SC_DEB_CYCLES_MIN 0
|
||||
#define HAP_DEF_SC_DEB_CYCLES 8
|
||||
#define HAP_SC_DEB_CYCLES_MAX 32
|
||||
|
||||
#define HAP_RATE_CFG1_REG 0x54
|
||||
#define HAP_RATE_CFG1_MASK GENMASK(7, 0)
|
||||
#define HAP_RATE_CFG2_SHIFT 8
|
||||
|
||||
#define HAP_RATE_CFG2_REG 0x55
|
||||
#define HAP_RATE_CFG2_MASK GENMASK(3, 0)
|
||||
|
||||
#define HAP_SC_CLR_REG 0x59
|
||||
#define SC_CLR_BIT BIT(0)
|
||||
|
||||
#define HAP_BRAKE_REG 0x5C
|
||||
#define HAP_BRAKE_PAT_MASK 0x3
|
||||
|
||||
#define HAP_WF_REPEAT_REG 0x5E
|
||||
#define WF_REPEAT_MASK GENMASK(6, 4)
|
||||
#define WF_REPEAT_SHIFT 4
|
||||
#define WF_REPEAT_MIN 1
|
||||
#define WF_REPEAT_MAX 128
|
||||
#define WF_S_REPEAT_MASK GENMASK(1, 0)
|
||||
#define WF_S_REPEAT_MIN 1
|
||||
#define WF_S_REPEAT_MAX 8
|
||||
|
||||
#define HAP_WF_S1_REG 0x60
|
||||
#define HAP_WF_SIGN_BIT BIT(7)
|
||||
#define HAP_WF_OVD_BIT BIT(6)
|
||||
#define HAP_WF_SAMP_MAX GENMASK(5, 1)
|
||||
#define HAP_WF_SAMPLE_LEN 8
|
||||
|
||||
#define HAP_PLAY_REG 0x70
|
||||
#define HAP_PLAY_BIT BIT(7)
|
||||
#define HAP_PAUSE_BIT BIT(0)
|
||||
|
||||
#define HAP_SEC_ACCESS_REG 0xD0
|
||||
#define HAP_SEC_ACCESS_UNLOCK 0xA5
|
||||
|
||||
#define HAP_TEST2_REG 0xE3
|
||||
|
||||
|
||||
#define HAP_VMAX_MIN_MV 116
|
||||
#define HAP_VMAX_MAX_MV 3596
|
||||
#define HAP_VMAX_MAX_MV_STRONG 3596
|
||||
|
||||
#define HAP_WAVE_PLAY_RATE_MIN_US 0
|
||||
#define HAP_WAVE_PLAY_RATE_MAX_US 20475
|
||||
#define HAP_WAVE_PLAY_TIME_MAX_MS 15000
|
||||
|
||||
#define AUTO_RES_ERR_POLL_TIME_NS (20 * NSEC_PER_MSEC)
|
||||
#define HAPTICS_BACK_EMF_DELAY_US 20000
|
||||
|
||||
#define HAP_BRAKE_PAT_LEN 4
|
||||
#define HAP_WAVE_SAMP_LEN 8
|
||||
#define NUM_WF_SET 4
|
||||
#define HAP_WAVE_SAMP_SET_LEN (HAP_WAVE_SAMP_LEN * NUM_WF_SET)
|
||||
#define HAP_RATE_CFG_STEP_US 5
|
||||
|
||||
#define SC_MAX_COUNT 5
|
||||
#define SC_COUNT_RST_DELAY_US 1000000
|
||||
|
||||
enum hap_play_control {
|
||||
HAP_STOP,
|
||||
HAP_PAUSE,
|
||||
HAP_PLAY,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spmi_haptics - struct for spmi haptics data.
|
||||
*
|
||||
* @dev: Our device parent.
|
||||
* @regmap: Register map for the hardware block.
|
||||
* @haptics_input_dev: The input device used to receive events.
|
||||
* @work: Work struct to play effects.
|
||||
* @base: Base address of the regmap.
|
||||
* @active: Atomic value used to track if haptics are currently playing.
|
||||
* @play_irq: Fired to load the next wave pattern.
|
||||
* @sc_irq: Short circuit irq.
|
||||
* @last_sc_time: Time since the short circuit IRQ last fired.
|
||||
* @sc_count: Number of times the short circuit IRQ has fired in this interval.
|
||||
* @actuator_type: The type of actuator in use.
|
||||
* @wave_shape: The shape of the waves to use (sine or square).
|
||||
* @play_mode: The play mode to use (direct, buffer, pwm, audio).
|
||||
* @magnitude: The strength we should be playing at.
|
||||
* @vmax: Max voltage to use when playing.
|
||||
* @current_limit: The current limit for this hardware (400mA or 800mA).
|
||||
* @play_wave_rate: The wave rate to use for this hardware.
|
||||
* @wave_samp: The array of wave samples to write for buffer mode.
|
||||
* @brake_pat: The pattern to apply when braking.
|
||||
* @play_lock: Lock to be held when updating the hardware state.
|
||||
*/
|
||||
struct spmi_haptics {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct input_dev *haptics_input_dev;
|
||||
struct work_struct work;
|
||||
u32 base;
|
||||
|
||||
atomic_t active;
|
||||
|
||||
int play_irq;
|
||||
int sc_irq;
|
||||
ktime_t last_sc_time;
|
||||
u8 sc_count;
|
||||
|
||||
u8 actuator_type;
|
||||
u8 wave_shape;
|
||||
u8 play_mode;
|
||||
int magnitude;
|
||||
u32 vmax;
|
||||
u32 current_limit;
|
||||
u32 play_wave_rate;
|
||||
|
||||
u32 wave_samp[HAP_WAVE_SAMP_SET_LEN];
|
||||
u8 brake_pat[HAP_BRAKE_PAT_LEN];
|
||||
|
||||
struct mutex play_lock;
|
||||
};
|
||||
|
||||
static inline bool is_secure_addr(u16 addr)
|
||||
{
|
||||
return (addr & 0xFF) > 0xD0;
|
||||
}
|
||||
|
||||
static int spmi_haptics_read(struct spmi_haptics *haptics,
|
||||
u16 addr, u8 *val, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(haptics->regmap, addr, val, len);
|
||||
if (ret < 0)
|
||||
dev_err(haptics->dev, "Error reading address: 0x%x, ret %d\n", addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spmi_haptics_write(struct spmi_haptics *haptics,
|
||||
u16 addr, u8 *val, int len)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
if (is_secure_addr(addr)) {
|
||||
for (i = 0; i < len; i++) {
|
||||
dev_dbg(haptics->dev, "%s: unlocking for addr: 0x%x, val: 0x%x", __func__,
|
||||
addr, val[i]);
|
||||
ret = regmap_write(haptics->regmap,
|
||||
haptics->base + HAP_SEC_ACCESS_REG, HAP_SEC_ACCESS_UNLOCK);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error writing unlock code, ret %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(haptics->regmap, addr + i, val[i]);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error writing address 0x%x, ret %d\n",
|
||||
addr + i, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (len > 1)
|
||||
ret = regmap_bulk_write(haptics->regmap, addr, val, len);
|
||||
else
|
||||
ret = regmap_write(haptics->regmap, addr, *val);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(haptics->dev, "%s: Error writing address: 0x%x, ret %d\n",
|
||||
__func__, addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_masked(struct spmi_haptics *haptics,
|
||||
u16 addr, u8 mask, u8 val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (is_secure_addr(addr)) {
|
||||
ret = regmap_write(haptics->regmap,
|
||||
haptics->base + HAP_SEC_ACCESS_REG, HAP_SEC_ACCESS_UNLOCK);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error writing unlock code - ret %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(haptics->regmap, addr, mask, val);
|
||||
if (ret < 0)
|
||||
dev_err(haptics->dev, "Error writing address: 0x%x - ret %d\n", addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool is_haptics_idle(struct spmi_haptics *haptics)
|
||||
{
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
if (haptics->play_mode == HAP_PLAY_DIRECT ||
|
||||
haptics->play_mode == HAP_PLAY_PWM)
|
||||
return true;
|
||||
|
||||
ret = spmi_haptics_read(haptics, haptics->base + HAP_STATUS_1_REG, &val, 1);
|
||||
if (ret < 0 || (val & HAP_BUSY_BIT))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int spmi_haptics_module_enable(struct spmi_haptics *haptics, bool enable)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
dev_dbg(haptics->dev, "Setting module enable: %d", enable);
|
||||
|
||||
val = enable ? HAP_EN_BIT : 0;
|
||||
return spmi_haptics_write(haptics, haptics->base + HAP_EN_CTL_REG, &val, 1);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_vmax(struct spmi_haptics *haptics)
|
||||
{
|
||||
u8 val = 0;
|
||||
u32 vmax_mv = haptics->vmax;
|
||||
|
||||
vmax_mv = clamp_t(u32, vmax_mv, HAP_VMAX_MIN_MV, HAP_VMAX_MAX_MV);
|
||||
|
||||
dev_dbg(haptics->dev, "Setting vmax to: %d", vmax_mv);
|
||||
|
||||
val = DIV_ROUND_CLOSEST(vmax_mv, HAP_VMAX_MIN_MV);
|
||||
val = FIELD_PREP(HAP_VMAX_MASK, val);
|
||||
|
||||
// TODO: pm660 can enable overdrive here
|
||||
|
||||
return spmi_haptics_write_masked(haptics, haptics->base + HAP_VMAX_CFG_REG,
|
||||
HAP_VMAX_MASK | HAP_WF_OVD_BIT, val);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_current_limit(struct spmi_haptics *haptics)
|
||||
{
|
||||
haptics->current_limit = clamp_t(u32, haptics->current_limit,
|
||||
HAP_ILIM_400_MA, HAP_ILIM_800_MA);
|
||||
|
||||
dev_dbg(haptics->dev, "Setting current_limit to: 0x%x", haptics->current_limit);
|
||||
|
||||
return spmi_haptics_write_masked(haptics, haptics->base + HAP_ILIM_CFG_REG,
|
||||
HAP_ILIM_SEL_MASK, haptics->current_limit);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_play_mode(struct spmi_haptics *haptics)
|
||||
{
|
||||
u8 val = 0;
|
||||
|
||||
if (!is_haptics_idle(haptics))
|
||||
return -EBUSY;
|
||||
|
||||
dev_dbg(haptics->dev, "Setting play_mode to: 0x%x", haptics->play_mode);
|
||||
|
||||
val = FIELD_PREP(HAP_WF_SOURCE_MASK, haptics->play_mode);
|
||||
return spmi_haptics_write_masked(haptics, haptics->base + HAP_SEL_REG,
|
||||
HAP_WF_SOURCE_MASK, val);
|
||||
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_play_rate(struct spmi_haptics *haptics, u16 play_rate)
|
||||
{
|
||||
u8 val[2];
|
||||
|
||||
dev_dbg(haptics->dev, "Setting play_rate to: %d", play_rate);
|
||||
|
||||
val[0] = FIELD_PREP(HAP_RATE_CFG1_MASK, play_rate);
|
||||
val[1] = FIELD_PREP(HAP_RATE_CFG2_MASK, play_rate >> HAP_RATE_CFG2_SHIFT);
|
||||
return spmi_haptics_write(haptics, haptics->base + HAP_RATE_CFG1_REG, val, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* spmi_haptics_set_auto_res() - Auto resonance
|
||||
* allows the haptics to automatically adjust the
|
||||
* speed of the oscillation in order to maintain
|
||||
* the resonant frequency.
|
||||
*/
|
||||
static int spmi_haptics_set_auto_res(struct spmi_haptics *haptics, bool enable)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
// LRAs are the only type to support auto res
|
||||
if (haptics->actuator_type != HAP_TYPE_LRA)
|
||||
return 0;
|
||||
|
||||
val = enable ? AUTO_RES_EN_BIT : 0;
|
||||
|
||||
return spmi_haptics_write_masked(haptics, haptics->base + HAP_TEST2_REG,
|
||||
AUTO_RES_EN_BIT, val);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_brake(struct spmi_haptics *haptics)
|
||||
{
|
||||
int ret, i;
|
||||
u8 val;
|
||||
|
||||
dev_dbg(haptics->dev, "Configuring brake pattern");
|
||||
|
||||
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_EN_CTL2_REG,
|
||||
BRAKE_EN_BIT, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (i = HAP_BRAKE_PAT_LEN - 1, val = 0; i >= 0; i--) {
|
||||
u8 p = haptics->brake_pat[i] & HAP_BRAKE_PAT_MASK;
|
||||
|
||||
val |= p << (i * 2);
|
||||
}
|
||||
|
||||
return spmi_haptics_write(haptics, haptics->base + HAP_BRAKE_REG, &val, 1);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_buffer_config(struct spmi_haptics *haptics)
|
||||
{
|
||||
u8 buf[HAP_WAVE_SAMP_LEN];
|
||||
int i;
|
||||
|
||||
dev_dbg(haptics->dev, "Writing buffer config");
|
||||
|
||||
for (i = 0; i < HAP_WAVE_SAMP_LEN; i++)
|
||||
buf[i] = haptics->wave_samp[i];
|
||||
|
||||
return spmi_haptics_write(haptics, haptics->base + HAP_WF_S1_REG, buf,
|
||||
HAP_WAVE_SAMP_LEN);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_wave_repeat(struct spmi_haptics *haptics)
|
||||
{
|
||||
u8 val, mask;
|
||||
|
||||
/* The number of times to repeat each wave */
|
||||
mask = WF_REPEAT_MASK | WF_S_REPEAT_MASK;
|
||||
val = FIELD_PREP(WF_REPEAT_MASK, 0) |
|
||||
FIELD_PREP(WF_S_REPEAT_MASK, 0);
|
||||
|
||||
return spmi_haptics_write_masked(haptics, haptics->base + HAP_WF_REPEAT_REG,
|
||||
mask, val);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_play_control(struct spmi_haptics *haptics,
|
||||
enum hap_play_control ctrl)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
switch (ctrl) {
|
||||
case HAP_STOP:
|
||||
val = 0;
|
||||
break;
|
||||
case HAP_PAUSE:
|
||||
val = HAP_PAUSE_BIT;
|
||||
break;
|
||||
case HAP_PLAY:
|
||||
val = HAP_PLAY_BIT;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_dbg(haptics->dev, "haptics play ctrl: %d\n", ctrl);
|
||||
return spmi_haptics_write(haptics, haptics->base + HAP_PLAY_REG, &val, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This IRQ is fired to tell us to load the next wave sample set.
|
||||
* As we only currently support a single sample set, it's unused.
|
||||
*/
|
||||
static irqreturn_t spmi_haptics_play_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct spmi_haptics *haptics = data;
|
||||
|
||||
dev_dbg(haptics->dev, "play_irq triggered");
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* spmi_haptics_sc_irq_handler() - short circuit irq handler
|
||||
* Fires every ~50ms whilst the haptics are active.
|
||||
* If the SC_FLAG_BIT is set then that means there isn't a short circuit
|
||||
* and we just need to clear the IRQ to indicate that the device should
|
||||
* keep vibrating.
|
||||
*
|
||||
* Otherwise, it means a short circuit situation has occurred.
|
||||
*
|
||||
* @irq: irq number
|
||||
* @data: haptics data
|
||||
* Returns: IRQ_HANDLED
|
||||
*/
|
||||
static irqreturn_t spmi_haptics_sc_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct spmi_haptics *haptics = data;
|
||||
int ret;
|
||||
u8 val;
|
||||
s64 sc_delta_time_us;
|
||||
ktime_t temp;
|
||||
|
||||
ret = spmi_haptics_read(haptics, haptics->base + HAP_STATUS_1_REG, &val, 1);
|
||||
if (ret < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (!(val & SC_FLAG_BIT)) {
|
||||
haptics->sc_count = 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
temp = ktime_get();
|
||||
sc_delta_time_us = ktime_us_delta(temp, haptics->last_sc_time);
|
||||
haptics->last_sc_time = temp;
|
||||
|
||||
if (sc_delta_time_us > SC_COUNT_RST_DELAY_US)
|
||||
haptics->sc_count = 0;
|
||||
else
|
||||
haptics->sc_count++;
|
||||
|
||||
// Clear the interrupt flag
|
||||
val = SC_CLR_BIT;
|
||||
ret = spmi_haptics_write(haptics, haptics->base + HAP_SC_CLR_REG, &val, 1);
|
||||
if (ret < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (haptics->sc_count > SC_MAX_COUNT) {
|
||||
dev_err(haptics->dev, "Short circuit persists, disabling haptics\n");
|
||||
ret = spmi_haptics_module_enable(haptics, false);
|
||||
if (ret < 0)
|
||||
dev_err(haptics->dev, "Error disabling module, rc=%d\n", ret);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* spmi_haptics_init() - Initialise haptics hardware for use
|
||||
* @haptics: haptics device
|
||||
* Returns: 0 on success, < 0 on error
|
||||
*/
|
||||
static int spmi_haptics_init(struct spmi_haptics *haptics)
|
||||
{
|
||||
int ret;
|
||||
u8 val, mask;
|
||||
u16 play_rate;
|
||||
|
||||
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_CFG1_REG,
|
||||
HAP_ACT_TYPE_MASK, haptics->actuator_type);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Configure auto resonance
|
||||
* see spmi_haptics_lra_auto_res_config downstream
|
||||
* This is greatly simplified.
|
||||
*/
|
||||
val = FIELD_PREP(LRA_RES_CAL_MASK, ilog2(32 / HAP_RES_CAL_PERIOD_MIN)) |
|
||||
FIELD_PREP(LRA_AUTO_RES_MODE_MASK, HAP_AUTO_RES_ZXD_EOP) |
|
||||
FIELD_PREP(LRA_HIGH_Z_MASK, 1);
|
||||
|
||||
mask = LRA_AUTO_RES_MODE_MASK | LRA_HIGH_Z_MASK | LRA_RES_CAL_MASK;
|
||||
|
||||
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_LRA_AUTO_RES_REG,
|
||||
mask, val);
|
||||
|
||||
/* Configure the PLAY MODE register */
|
||||
ret = spmi_haptics_write_play_mode(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = spmi_haptics_write_vmax(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Configure the ILIM register */
|
||||
ret = spmi_haptics_write_current_limit(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
// Configure the debounce for short-circuit detection.
|
||||
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_SC_DEB_REG,
|
||||
HAP_SC_DEB_MASK, HAP_SC_DEB_CYCLES_MAX);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
// write the wave shape
|
||||
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_CFG2_REG,
|
||||
HAP_LRA_RES_TYPE_MASK, haptics->wave_shape);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
play_rate = haptics->play_wave_rate / HAP_RATE_CFG_STEP_US;
|
||||
|
||||
/*
|
||||
* Configure RATE_CFG1 and RATE_CFG2 registers.
|
||||
* Note: For ERM these registers act as play rate and
|
||||
* for LRA these represent resonance period
|
||||
*/
|
||||
ret = spmi_haptics_write_play_rate(haptics, play_rate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = spmi_haptics_write_brake(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (haptics->play_mode == HAP_PLAY_BUFFER) {
|
||||
ret = spmi_haptics_write_wave_repeat(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = spmi_haptics_write_buffer_config(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(haptics->dev, "%s: Requesting play IRQ, irq: %d", __func__,
|
||||
haptics->play_irq);
|
||||
ret = devm_request_threaded_irq(haptics->dev, haptics->play_irq,
|
||||
NULL, spmi_haptics_play_irq_handler, IRQF_ONESHOT,
|
||||
"haptics_play_irq", haptics);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Unable to request play IRQ ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* use play_irq only for buffer mode */
|
||||
if (haptics->play_mode != HAP_PLAY_BUFFER)
|
||||
disable_irq(haptics->play_irq);
|
||||
|
||||
dev_dbg(haptics->dev, "%s: Requesting play IRQ, irq: %d", __func__,
|
||||
haptics->play_irq);
|
||||
ret = devm_request_threaded_irq(haptics->dev, haptics->sc_irq,
|
||||
NULL, spmi_haptics_sc_irq_handler, IRQF_ONESHOT,
|
||||
"haptics_sc_irq", haptics);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Unable to request sc IRQ ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* spmi_haptics_enable - handler to start/stop vibration
|
||||
* @haptics: pointer to haptics struct
|
||||
* Returns: 0 on success, < 0 on failure
|
||||
*/
|
||||
static int spmi_haptics_enable(struct spmi_haptics *haptics)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&haptics->play_lock);
|
||||
if (haptics->sc_count > SC_MAX_COUNT) {
|
||||
dev_err(haptics->dev, "Can't play while in short circuit");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
ret = spmi_haptics_set_auto_res(haptics, false);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error disabling auto_res, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = spmi_haptics_module_enable(haptics, true);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error enabling module, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = spmi_haptics_write_play_control(haptics, HAP_PLAY);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error enabling play, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = spmi_haptics_set_auto_res(haptics, true);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error enabling auto_res, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&haptics->play_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* spmi_haptics_enable - handler to start/stop vibration
|
||||
* @haptics: pointer to haptics struct
|
||||
* Returns: 0 on success, < 0 on failure
|
||||
*/
|
||||
static int spmi_haptics_disable(struct spmi_haptics *haptics)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&haptics->play_lock);
|
||||
|
||||
ret = spmi_haptics_write_play_control(haptics, HAP_STOP);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error disabling play, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = spmi_haptics_module_enable(haptics, false);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error disabling module, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&haptics->play_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Threaded function to update the haptics state.
|
||||
*/
|
||||
static void spmi_haptics_work(struct work_struct *work)
|
||||
{
|
||||
struct spmi_haptics *haptics = container_of(work, struct spmi_haptics, work);
|
||||
|
||||
int ret;
|
||||
bool enable;
|
||||
|
||||
enable = atomic_read(&haptics->active);
|
||||
dev_dbg(haptics->dev, "%s: state: %d\n", __func__, enable);
|
||||
|
||||
if (enable)
|
||||
ret = spmi_haptics_enable(haptics);
|
||||
else
|
||||
ret = spmi_haptics_disable(haptics);
|
||||
if (ret < 0)
|
||||
dev_err(haptics->dev, "Error setting haptics, ret=%d", ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* spmi_haptics_close - callback for input device close
|
||||
* @dev: input device pointer
|
||||
*
|
||||
* Turns off the vibrator.
|
||||
*/
|
||||
static void spmi_haptics_close(struct input_dev *dev)
|
||||
{
|
||||
struct spmi_haptics *haptics = input_get_drvdata(dev);
|
||||
|
||||
cancel_work_sync(&haptics->work);
|
||||
if (atomic_read(&haptics->active)) {
|
||||
atomic_set(&haptics->active, 0);
|
||||
schedule_work(&haptics->work);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* spmi_haptics_play_effect - play haptics effects
|
||||
* @dev: input device pointer
|
||||
* @data: data of effect
|
||||
* @effect: effect to play
|
||||
*/
|
||||
static int spmi_haptics_play_effect(struct input_dev *dev, void *data,
|
||||
struct ff_effect *effect)
|
||||
{
|
||||
struct spmi_haptics *haptics = input_get_drvdata(dev);
|
||||
|
||||
dev_dbg(haptics->dev, "%s: Rumbling with strong: %d and weak: %d", __func__,
|
||||
effect->u.rumble.strong_magnitude, effect->u.rumble.weak_magnitude);
|
||||
|
||||
haptics->magnitude = effect->u.rumble.strong_magnitude >> 8;
|
||||
if (!haptics->magnitude)
|
||||
haptics->magnitude = effect->u.rumble.weak_magnitude >> 10;
|
||||
|
||||
if (!haptics->magnitude) {
|
||||
atomic_set(&haptics->active, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
atomic_set(&haptics->active, 1);
|
||||
|
||||
haptics->vmax = ((HAP_VMAX_MAX_MV - HAP_VMAX_MIN_MV) * haptics->magnitude) / 100 +
|
||||
HAP_VMAX_MIN_MV;
|
||||
|
||||
dev_dbg(haptics->dev, "%s: magnitude: %d, vmax: %d", __func__,
|
||||
haptics->magnitude, haptics->vmax);
|
||||
|
||||
spmi_haptics_write_vmax(haptics);
|
||||
|
||||
end:
|
||||
schedule_work(&haptics->work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spmi_haptics_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spmi_haptics *haptics;
|
||||
struct device_node *node;
|
||||
struct input_dev *input_dev;
|
||||
int ret;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
|
||||
if (!haptics)
|
||||
return -ENOMEM;
|
||||
|
||||
haptics->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!haptics->regmap)
|
||||
return -ENODEV;
|
||||
|
||||
node = pdev->dev.of_node;
|
||||
|
||||
haptics->dev = &pdev->dev;
|
||||
|
||||
ret = of_property_read_u32(node, "reg", &haptics->base);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Couldn't find reg in node = %s ret = %d\n",
|
||||
node->full_name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
haptics->play_irq = platform_get_irq_byname(pdev, "play");
|
||||
if (haptics->play_irq < 0) {
|
||||
dev_err(&pdev->dev, "Unable to get play irq\n");
|
||||
ret = haptics->play_irq;
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
haptics->sc_irq = platform_get_irq_byname(pdev, "short");
|
||||
if (haptics->sc_irq < 0) {
|
||||
dev_err(&pdev->dev, "Unable to get sc irq\n");
|
||||
ret = haptics->sc_irq;
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
// We only support LRAs for now
|
||||
haptics->actuator_type = HAP_TYPE_LRA;
|
||||
ret = of_property_read_u32(node, "qcom,actuator-type", &val);
|
||||
if (!ret) {
|
||||
if (val != HAP_TYPE_LRA) {
|
||||
dev_err(&pdev->dev, "qcom,actuator-type (%d) isn't supported\n", val);
|
||||
ret = -EINVAL;
|
||||
goto register_fail;
|
||||
}
|
||||
haptics->actuator_type = val;
|
||||
}
|
||||
|
||||
// Only buffer mode is currently supported
|
||||
haptics->play_mode = HAP_PLAY_BUFFER;
|
||||
ret = of_property_read_u32(node, "qcom,play-mode", &val);
|
||||
if (!ret) {
|
||||
if (val != HAP_PLAY_BUFFER) {
|
||||
dev_err(&pdev->dev, "qcom,play-mode (%d) isn't supported\n", val);
|
||||
ret = -EINVAL;
|
||||
goto register_fail;
|
||||
}
|
||||
haptics->play_mode = val;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "qcom,wave-play-rate-us", &val);
|
||||
if (!ret) {
|
||||
haptics->play_wave_rate = val;
|
||||
} else if (ret != -EINVAL) {
|
||||
dev_err(haptics->dev, "Unable to read play rate ret=%d\n", ret);
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
haptics->play_wave_rate =
|
||||
clamp_t(u32, haptics->play_wave_rate,
|
||||
HAP_WAVE_PLAY_RATE_MIN_US, HAP_WAVE_PLAY_RATE_MAX_US);
|
||||
|
||||
haptics->wave_shape = HAP_WAVE_SINE;
|
||||
ret = of_property_read_u32(node, "qcom,wave-shape", &val);
|
||||
if (!ret) {
|
||||
if (val != HAP_WAVE_SINE && val != HAP_WAVE_SQUARE) {
|
||||
dev_err(&pdev->dev, "qcom,wave-shape is invalid: %d\n", val);
|
||||
ret = -EINVAL;
|
||||
goto register_fail;
|
||||
}
|
||||
haptics->wave_shape = val;
|
||||
}
|
||||
|
||||
haptics->brake_pat[0] = 0x3;
|
||||
haptics->brake_pat[1] = 0x3;
|
||||
haptics->brake_pat[2] = 0x2;
|
||||
haptics->brake_pat[3] = 0x1;
|
||||
|
||||
ret = of_property_read_u8_array(node, "qcom,brake-pattern", haptics->brake_pat, 4);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
dev_err(&pdev->dev, "qcom,brake-pattern is invalid, ret = %d\n", ret);
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
haptics->current_limit = HAP_ILIM_400_MA;
|
||||
|
||||
for (i = 0; i < HAP_WAVE_SAMP_LEN; i++)
|
||||
haptics->wave_samp[i] = HAP_WF_SAMP_MAX;
|
||||
|
||||
ret = spmi_haptics_init(haptics);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Error initialising haptics, ret=%d\n",
|
||||
ret);
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, haptics);
|
||||
|
||||
input_dev = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_WORK(&haptics->work, spmi_haptics_work);
|
||||
haptics->haptics_input_dev = input_dev;
|
||||
|
||||
input_dev->name = "spmi_haptics";
|
||||
input_dev->id.version = 1;
|
||||
input_dev->close = spmi_haptics_close;
|
||||
input_set_drvdata(input_dev, haptics);
|
||||
// Figure out how to make this FF_PERIODIC
|
||||
input_set_capability(haptics->haptics_input_dev, EV_FF, FF_RUMBLE);
|
||||
|
||||
ret = input_ff_create_memless(input_dev, NULL,
|
||||
spmi_haptics_play_effect);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"couldn't register vibrator as FF device\n");
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
ret = input_register_device(input_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "couldn't register input device\n");
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
register_fail:
|
||||
cancel_work_sync(&haptics->work);
|
||||
mutex_destroy(&haptics->play_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused spmi_haptics_suspend(struct device *dev)
|
||||
{
|
||||
struct spmi_haptics *haptics = dev_get_drvdata(dev);
|
||||
|
||||
cancel_work_sync(&haptics->work);
|
||||
spmi_haptics_disable(haptics);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(spmi_haptics_pm_ops, spmi_haptics_suspend, NULL);
|
||||
|
||||
static int spmi_haptics_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spmi_haptics *haptics = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
cancel_work_sync(&haptics->work);
|
||||
mutex_destroy(&haptics->play_lock);
|
||||
input_unregister_device(haptics->haptics_input_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spmi_haptics_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct spmi_haptics *haptics = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
cancel_work_sync(&haptics->work);
|
||||
|
||||
spmi_haptics_disable(haptics);
|
||||
}
|
||||
|
||||
static const struct of_device_id spmi_haptics_match_table[] = {
|
||||
{ .compatible = "qcom,spmi-haptics" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, spmi_haptics_match_table);
|
||||
|
||||
static struct platform_driver spmi_haptics_driver = {
|
||||
.probe = spmi_haptics_probe,
|
||||
.remove = spmi_haptics_remove,
|
||||
.shutdown = spmi_haptics_shutdown,
|
||||
.driver = {
|
||||
.name = "spmi-haptics",
|
||||
.pm = &spmi_haptics_pm_ops,
|
||||
.of_match_table = spmi_haptics_match_table,
|
||||
},
|
||||
};
|
||||
module_platform_driver(spmi_haptics_driver);
|
||||
|
||||
MODULE_DESCRIPTION("spmi haptics driver using ff-memless framework");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Caleb Connolly <caleb@connolly.tech>");
|
||||
|
|
@ -82,6 +82,14 @@ config RMI4_F12
|
|||
touchpads. For sensors that support relative pointing, F12 also
|
||||
provides mouse input.
|
||||
|
||||
config RMI4_F1A
|
||||
bool "RMI4 Function 1A (Simple capacitive buttons)"
|
||||
depends on OF
|
||||
help
|
||||
Say Y here if you want to add support for RMI4 function 1A.
|
||||
|
||||
Function 1A provides GPIO capacitive button support for RMI4 devices.
|
||||
|
||||
config RMI4_F30
|
||||
bool "RMI4 Function 30 (GPIO LED)"
|
||||
help
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ rmi_core-$(CONFIG_RMI4_2D_SENSOR) += rmi_2d_sensor.o
|
|||
rmi_core-$(CONFIG_RMI4_F03) += rmi_f03.o
|
||||
rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
|
||||
rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o
|
||||
rmi_core-$(CONFIG_RMI4_F1A) += rmi_f1a.o
|
||||
rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
|
||||
rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o rmi_f34v7.o
|
||||
rmi_core-$(CONFIG_RMI4_F3A) += rmi_f3a.o
|
||||
|
|
|
|||
|
|
@ -360,6 +360,9 @@ static struct rmi_function_handler *fn_handlers[] = {
|
|||
#ifdef CONFIG_RMI4_F12
|
||||
&rmi_f12_handler,
|
||||
#endif
|
||||
#ifdef CONFIG_RMI4_F1A
|
||||
&rmi_f1a_handler,
|
||||
#endif
|
||||
#ifdef CONFIG_RMI4_F30
|
||||
&rmi_f30_handler,
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ extern struct rmi_function_handler rmi_f01_handler;
|
|||
extern struct rmi_function_handler rmi_f03_handler;
|
||||
extern struct rmi_function_handler rmi_f11_handler;
|
||||
extern struct rmi_function_handler rmi_f12_handler;
|
||||
extern struct rmi_function_handler rmi_f1a_handler;
|
||||
extern struct rmi_function_handler rmi_f30_handler;
|
||||
extern struct rmi_function_handler rmi_f34_handler;
|
||||
extern struct rmi_function_handler rmi_f3a_handler;
|
||||
|
|
|
|||
190
drivers/input/rmi4/rmi_f1a.c
Normal file
190
drivers/input/rmi4/rmi_f1a.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
// FIXME: Too much stuff is hardcoded in currently!
|
||||
#include <linux/input.h>
|
||||
#include <linux/rmi.h>
|
||||
#include <linux/of.h>
|
||||
#include "rmi_driver.h"
|
||||
|
||||
/* Query 1 */
|
||||
//#define F1A_BUTTONS_COUNT 0b00011111 /* BIT(1) */
|
||||
|
||||
#define MAX_NAME_LEN 256
|
||||
#define F1A_MAX_BUTTONS 8
|
||||
|
||||
struct f1a_data {
|
||||
struct rmi_function *fn;
|
||||
|
||||
unsigned char button_count;
|
||||
u32 button_map[F1A_MAX_BUTTONS];
|
||||
struct input_dev *input;
|
||||
char input_name[MAX_NAME_LEN];
|
||||
char input_phys[MAX_NAME_LEN];
|
||||
u8 button_data_buffer;
|
||||
};
|
||||
|
||||
static int rmi_f1a_initialize(struct f1a_data *f1a)
|
||||
{
|
||||
struct rmi_function *fn = f1a->fn;
|
||||
struct device *dev = &fn->dev;
|
||||
//u8 query[2];
|
||||
int error;
|
||||
|
||||
/*error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr, query, 2);
|
||||
if (error) {
|
||||
dev_err(dev, "Failed to read query register (%d).\n", error);
|
||||
return error;
|
||||
}
|
||||
printk("%s: query0: 0x%x, query1: 0x%x\n", __func__, query[0], query[1]);*/
|
||||
|
||||
error = of_property_read_variable_u32_array(dev_of_node(dev),
|
||||
"syna,codes", f1a->button_map, 1, F1A_MAX_BUTTONS);
|
||||
if (error < 0) {
|
||||
dev_err(dev, "Failed to parse syna,codes from OF device tree (%d).\n", error);
|
||||
return error;
|
||||
}
|
||||
// FIXME: button_count = query[1] & F1A_BUTTONS_COUNT;
|
||||
f1a->button_count = 0;
|
||||
for (f1a->button_count = 0; f1a->button_count < F1A_MAX_BUTTONS; f1a->button_count++)
|
||||
if (f1a->button_map[f1a->button_count] == 0)
|
||||
break;
|
||||
rmi_dbg(RMI_DEBUG_FN, dev, "%s: %d button codes defined\n", __func__, f1a->button_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f1a_register_device(struct f1a_data *f1a)
|
||||
{
|
||||
struct rmi_function *fn = f1a->fn;
|
||||
struct device *dev = &fn->dev;
|
||||
struct rmi_device *rmi_dev = fn->rmi_dev;
|
||||
struct input_dev *input_dev;
|
||||
int i, rc;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev) {
|
||||
dev_err(dev, "Failed to allocate input device.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
f1a->input = input_dev;
|
||||
snprintf(f1a->input_name, MAX_NAME_LEN, "%s.fn%02x",
|
||||
dev_name(&rmi_dev->dev), fn->fd.function_number);
|
||||
input_dev->name = f1a->input_name;
|
||||
snprintf(f1a->input_phys, MAX_NAME_LEN, "%s/input0", input_dev->name);
|
||||
input_dev->phys = f1a->input_phys;
|
||||
input_dev->dev.parent = &rmi_dev->dev;
|
||||
input_set_drvdata(input_dev, f1a);
|
||||
|
||||
/* set up any input events */
|
||||
set_bit(EV_SYN, input_dev->evbit);
|
||||
set_bit(EV_KEY, input_dev->evbit);
|
||||
|
||||
/* manage button map using input subsystem */
|
||||
input_dev->keycode = f1a->button_map;
|
||||
input_dev->keycodesize = sizeof(f1a->button_map); /* f1a->button_count */
|
||||
input_dev->keycodemax = f1a->button_count;
|
||||
|
||||
/* set bits for each button */
|
||||
for (i = 0; i < f1a->button_count; i++) {
|
||||
set_bit(f1a->button_map[i], input_dev->keybit);
|
||||
input_set_capability(input_dev, EV_KEY, f1a->button_map[i]);
|
||||
}
|
||||
|
||||
rc = input_register_device(input_dev);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "Failed to register input device.\n");
|
||||
goto error_free_device;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_device:
|
||||
input_free_device(input_dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rmi_f1a_probe(struct rmi_function *fn)
|
||||
{
|
||||
struct device *dev = &fn->dev;
|
||||
struct f1a_data *f1a;
|
||||
int error;
|
||||
|
||||
rmi_dbg(RMI_DEBUG_FN, dev, "%s\n", __func__);
|
||||
|
||||
if (!fn->dev.of_node) {
|
||||
/*
|
||||
* Some quirky devices (e.g. OnePlus 5T) report supporting F1A
|
||||
* (Simple capacitive buttons) despite not having the hardware,
|
||||
* so in case there isn't an associated device-tree node present
|
||||
* just pretend we probed successfully.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
f1a = devm_kzalloc(dev, sizeof(struct f1a_data), GFP_KERNEL);
|
||||
if (!f1a)
|
||||
return -ENOMEM;
|
||||
|
||||
f1a->fn = fn;
|
||||
|
||||
error = rmi_f1a_initialize(f1a);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
error = rmi_f1a_register_device(f1a);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
dev_set_drvdata(dev, f1a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f1a_config(struct rmi_function *fn)
|
||||
{
|
||||
fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t rmi_f1a_attention(int irq, void *ctx)
|
||||
{
|
||||
struct rmi_function *fn = ctx;
|
||||
struct device *dev = &fn->dev;
|
||||
struct rmi_device *rmi_dev = fn->rmi_dev;
|
||||
struct f1a_data *f1a = dev_get_drvdata(dev);
|
||||
int error, button;
|
||||
|
||||
// TODO: use rmi_read_block() to accomodate up to 8 buttons?
|
||||
error = rmi_read(rmi_dev, fn->fd.data_base_addr, &(f1a->button_data_buffer));
|
||||
if (error < 0) {
|
||||
dev_err(dev, "Failed to read button data registers (%d).\n", error);
|
||||
return error;
|
||||
}
|
||||
/*rmi_dbg(RMI_DEBUG_FN, dev, "%s: button_data=0x%x\n", __func__, f1a->button_data_buffer);*/
|
||||
|
||||
/* generate events for buttons that change state */
|
||||
// TODO: Implement button_data_buffer as array + button_reg = button / 8
|
||||
for (button = 0; button < f1a->button_count; button++) {
|
||||
int button_shift;
|
||||
bool button_status;
|
||||
/* bit shift to get button's status */
|
||||
button_shift = button % 8;
|
||||
button_status = ((f1a->button_data_buffer >> button_shift) & 0x01) != 0;
|
||||
|
||||
rmi_dbg(RMI_DEBUG_FN, dev, "button %d (code %d) -> %d\n",
|
||||
button, f1a->button_map[button], button_status);
|
||||
/* generate an event here */
|
||||
input_report_key(f1a->input, f1a->button_map[button], button_status);
|
||||
}
|
||||
input_sync(f1a->input); /* sync after groups of events */
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
struct rmi_function_handler rmi_f1a_handler = {
|
||||
.driver = {
|
||||
.name = "rmi4_f1a",
|
||||
},
|
||||
.func = 0x1a,
|
||||
.probe = rmi_f1a_probe,
|
||||
.config = rmi_f1a_config,
|
||||
.attention = rmi_f1a_attention,
|
||||
};
|
||||
|
|
@ -44,6 +44,15 @@ config INTERCONNECT_QCOM_MSM8996
|
|||
This is a driver for the Qualcomm Network-on-Chip on msm8996-based
|
||||
platforms.
|
||||
|
||||
config INTERCONNECT_QCOM_MSM8998
|
||||
tristate "Qualcomm MSM8998 interconnect driver"
|
||||
depends on INTERCONNECT_QCOM
|
||||
depends on QCOM_SMD_RPM
|
||||
select INTERCONNECT_QCOM_SMD_RPM
|
||||
help
|
||||
This is a driver for the Qualcomm Network-on-Chip on msm8998-based
|
||||
platforms.
|
||||
|
||||
config INTERCONNECT_QCOM_OSM_L3
|
||||
tristate "Qualcomm OSM L3 interconnect driver"
|
||||
depends on INTERCONNECT_QCOM || COMPILE_TEST
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ qnoc-msm8916-objs := msm8916.o
|
|||
qnoc-msm8939-objs := msm8939.o
|
||||
qnoc-msm8974-objs := msm8974.o
|
||||
qnoc-msm8996-objs := msm8996.o
|
||||
qnoc-msm8998-objs := msm8998.o
|
||||
icc-osm-l3-objs := osm-l3.o
|
||||
qnoc-qcm2290-objs := qcm2290.o
|
||||
qnoc-qcs404-objs := qcs404.o
|
||||
|
|
@ -26,6 +27,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o
|
|||
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8939) += qnoc-msm8939.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8996) += qnoc-msm8996.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8998) += qnoc-msm8998.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_QCM2290) += qnoc-qcm2290.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o
|
||||
|
|
|
|||
981
drivers/interconnect/qcom/msm8998.c
Normal file
981
drivers/interconnect/qcom/msm8998.c
Normal file
|
|
@ -0,0 +1,981 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Qualcomm MSM8998 Network-on-Chip (NoC) QoS driver
|
||||
* Copyright (c) 2020, AngeloGioacchino Del Regno
|
||||
* <angelogioacchino.delregno@somainline.org>
|
||||
* Copyright (C) 2020, Konrad Dybcio <konrad.dybcio@somainline.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dt-bindings/interconnect/qcom,msm8998.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "smd-rpm.h"
|
||||
|
||||
#define RPM_BUS_MASTER_REQ 0x73616d62
|
||||
#define RPM_BUS_SLAVE_REQ 0x766c7362
|
||||
|
||||
/* BIMC QoS */
|
||||
#define M_BKE_REG_BASE(n) (0x300 + (0x4000 * n))
|
||||
#define M_BKE_EN_ADDR(n) (M_BKE_REG_BASE(n))
|
||||
#define M_BKE_HEALTH_CFG_ADDR(i, n) (M_BKE_REG_BASE(n) + 0x40 + (0x4 * i))
|
||||
|
||||
#define M_BKE_HEALTH_CFG_LIMITCMDS_MASK 0x80000000
|
||||
#define M_BKE_HEALTH_CFG_AREQPRIO_MASK 0x300
|
||||
#define M_BKE_HEALTH_CFG_PRIOLVL_MASK 0x3
|
||||
#define M_BKE_HEALTH_CFG_AREQPRIO_SHIFT 0x8
|
||||
#define M_BKE_HEALTH_CFG_LIMITCMDS_SHIFT 0x1f
|
||||
|
||||
#define M_BKE_EN_EN_BMASK 0x1
|
||||
|
||||
/* Valid for both NoC and BIMC */
|
||||
#define NOC_QOS_MODE_FIXED 0x0
|
||||
#define NOC_QOS_MODE_LIMITER 0x1
|
||||
#define NOC_QOS_MODE_BYPASS 0x2
|
||||
|
||||
/* NoC QoS */
|
||||
#define NOC_PERM_MODE_FIXED 1
|
||||
#define NOC_PERM_MODE_BYPASS (1 << NOC_QOS_MODE_BYPASS)
|
||||
|
||||
#define NOC_QOS_PRIORITYn_ADDR(n) (0x8 + (n * 0x1000))
|
||||
#define NOC_QOS_PRIORITY_MASK 0xf
|
||||
#define NOC_QOS_PRIORITY_P1_SHIFT 0x2
|
||||
#define NOC_QOS_PRIORITY_P0_SHIFT 0x3
|
||||
|
||||
#define NOC_QOS_MODEn_ADDR(n) (0xc + (n * 0x1000))
|
||||
#define NOC_QOS_MODEn_MASK 0x3
|
||||
|
||||
enum {
|
||||
MSM8998_MASTER_IPA = 1,
|
||||
MSM8998_MASTER_CNOC_A2NOC,
|
||||
MSM8998_MASTER_SDCC_2,
|
||||
MSM8998_MASTER_SDCC_4,
|
||||
MSM8998_MASTER_BLSP_1,
|
||||
MSM8998_MASTER_BLSP_2,
|
||||
MSM8998_MASTER_UFS,
|
||||
MSM8998_MASTER_USB_HS,
|
||||
MSM8998_MASTER_USB3,
|
||||
MSM8998_MASTER_CRYPTO_C0,
|
||||
MSM8998_MASTER_GNOC_BIMC,
|
||||
MSM8998_MASTER_OXILI,
|
||||
MSM8998_MASTER_MNOC_BIMC,
|
||||
MSM8998_MASTER_SNOC_BIMC,
|
||||
MSM8998_MASTER_PIMEM,
|
||||
MSM8998_MASTER_SNOC_CNOC,
|
||||
MSM8998_MASTER_QDSS_DAP,
|
||||
MSM8998_MASTER_APPS_PROC,
|
||||
MSM8998_MASTER_CNOC_MNOC_MMSS_CFG,
|
||||
MSM8998_MASTER_CNOC_MNOC_CFG,
|
||||
MSM8998_MASTER_CPP,
|
||||
MSM8998_MASTER_JPEG,
|
||||
MSM8998_MASTER_MDP_P0,
|
||||
MSM8998_MASTER_MDP_P1,
|
||||
MSM8998_MASTER_VENUS,
|
||||
MSM8998_MASTER_VFE,
|
||||
MSM8998_MASTER_QDSS_ETR,
|
||||
MSM8998_MASTER_QDSS_BAM,
|
||||
MSM8998_MASTER_SNOC_CFG,
|
||||
MSM8998_MASTER_BIMC_SNOC,
|
||||
MSM8998_MASTER_A1NOC_SNOC,
|
||||
MSM8998_MASTER_A2NOC_SNOC,
|
||||
MSM8998_MASTER_GNOC_SNOC,
|
||||
MSM8998_MASTER_PCIE_0,
|
||||
MSM8998_MASTER_A2NOC_TSIF,
|
||||
MSM8998_MASTER_CRVIRT_A2NOC,
|
||||
MSM8998_MASTER_ROTATOR,
|
||||
MSM8998_MASTER_VENUS_VMEM,
|
||||
MSM8998_MASTER_HMSS,
|
||||
MSM8998_MASTER_BIMC_SNOC_0,
|
||||
MSM8998_MASTER_BIMC_SNOC_1,
|
||||
|
||||
MSM8998_SLAVE_A1NOC_SNOC,
|
||||
MSM8998_SLAVE_A2NOC_SNOC,
|
||||
MSM8998_SLAVE_EBI,
|
||||
MSM8998_SLAVE_HMSS_L3,
|
||||
MSM8998_SLAVE_CNOC_A2NOC,
|
||||
MSM8998_SLAVE_MPM,
|
||||
MSM8998_SLAVE_PMIC_ARB,
|
||||
MSM8998_SLAVE_TLMM_NORTH,
|
||||
MSM8998_SLAVE_TCSR,
|
||||
MSM8998_SLAVE_PIMEM_CFG,
|
||||
MSM8998_SLAVE_IMEM_CFG,
|
||||
MSM8998_SLAVE_MESSAGE_RAM,
|
||||
MSM8998_SLAVE_GLM,
|
||||
MSM8998_SLAVE_BIMC_CFG,
|
||||
MSM8998_SLAVE_PRNG,
|
||||
MSM8998_SLAVE_SPDM,
|
||||
MSM8998_SLAVE_QDSS_CFG,
|
||||
MSM8998_SLAVE_CNOC_MNOC_CFG,
|
||||
MSM8998_SLAVE_SNOC_CFG,
|
||||
MSM8998_SLAVE_QM_CFG,
|
||||
MSM8998_SLAVE_CLK_CTL,
|
||||
MSM8998_SLAVE_MSS_CFG,
|
||||
MSM8998_SLAVE_UFS_CFG,
|
||||
MSM8998_SLAVE_A2NOC_CFG,
|
||||
MSM8998_SLAVE_A2NOC_SMMU_CFG,
|
||||
MSM8998_SLAVE_GPUSS_CFG,
|
||||
MSM8998_SLAVE_AHB2PHY,
|
||||
MSM8998_SLAVE_BLSP_1,
|
||||
MSM8998_SLAVE_SDCC_2,
|
||||
MSM8998_SLAVE_SDCC_4,
|
||||
MSM8998_SLAVE_BLSP_2,
|
||||
MSM8998_SLAVE_PDM,
|
||||
MSM8998_SLAVE_CNOC_MNOC_MMSS_CFG,
|
||||
MSM8998_SLAVE_USB_HS,
|
||||
MSM8998_SLAVE_USB3_0,
|
||||
MSM8998_SLAVE_SRVC_CNOC,
|
||||
MSM8998_SLAVE_GNOC_BIMC,
|
||||
MSM8998_SLAVE_GNOC_SNOC,
|
||||
MSM8998_SLAVE_CAMERA_CFG,
|
||||
MSM8998_SLAVE_CAMERA_THROTTLE_CFG,
|
||||
MSM8998_SLAVE_MISC_CFG,
|
||||
MSM8998_SLAVE_VENUS_THROTTLE_CFG,
|
||||
MSM8998_SLAVE_VENUS_CFG,
|
||||
MSM8998_SLAVE_MMSS_CLK_XPU_CFG,
|
||||
MSM8998_SLAVE_MMSS_CLK_CFG,
|
||||
MSM8998_SLAVE_MNOC_MPU_CFG,
|
||||
MSM8998_SLAVE_DISPLAY_CFG,
|
||||
MSM8998_SLAVE_CSI_PHY_CFG,
|
||||
MSM8998_SLAVE_DISPLAY_THROTTLE_CFG,
|
||||
MSM8998_SLAVE_SMMU_CFG,
|
||||
MSM8998_SLAVE_MNOC_BIMC,
|
||||
MSM8998_SLAVE_SRVC_MNOC,
|
||||
MSM8998_SLAVE_HMSS,
|
||||
MSM8998_SLAVE_LPASS,
|
||||
MSM8998_SLAVE_WLAN,
|
||||
MSM8998_SLAVE_CDSP,
|
||||
MSM8998_SLAVE_IPA,
|
||||
MSM8998_SLAVE_SNOC_BIMC,
|
||||
MSM8998_SLAVE_SNOC_CNOC,
|
||||
MSM8998_SLAVE_IMEM,
|
||||
MSM8998_SLAVE_PIMEM,
|
||||
MSM8998_SLAVE_QDSS_STM,
|
||||
MSM8998_SLAVE_SRVC_SNOC,
|
||||
MSM8998_SLAVE_BIMC_SNOC_0,
|
||||
MSM8998_SLAVE_BIMC_SNOC_1,
|
||||
MSM8998_SLAVE_SSC_CFG,
|
||||
MSM8998_SLAVE_SKL,
|
||||
MSM8998_SLAVE_TLMM_WEST,
|
||||
MSM8998_SLAVE_A1NOC_CFG,
|
||||
MSM8998_SLAVE_A1NOC_SMMU_CFG,
|
||||
MSM8998_SLAVE_TSIF,
|
||||
MSM8998_SLAVE_TLMM_EAST,
|
||||
MSM8998_SLAVE_CRVIRT_A2NOC,
|
||||
MSM8998_SLAVE_VMEM_CFG,
|
||||
MSM8998_SLAVE_VMEM,
|
||||
MSM8998_SLAVE_PCIE_0,
|
||||
};
|
||||
|
||||
#define to_qcom_provider(_provider) \
|
||||
container_of(_provider, struct qcom_icc_provider, provider)
|
||||
|
||||
static const struct clk_bulk_data bus_clocks[] = {
|
||||
{ .id = "bus" },
|
||||
{ .id = "bus_a" },
|
||||
};
|
||||
|
||||
static const struct clk_bulk_data bus_mm_clocks[] = {
|
||||
{ .id = "bus" },
|
||||
{ .id = "bus_a" },
|
||||
{ .id = "iface" },
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qcom_icc_provider - Qualcomm specific interconnect provider
|
||||
* @provider: generic interconnect provider
|
||||
* @bus_clks: the clk_bulk_data table of bus clocks
|
||||
* @num_clks: the total number of clk_bulk_data entries
|
||||
* @is_bimc_node: indicates whether to use bimc specific setting
|
||||
* @mmio: NoC base iospace
|
||||
*/
|
||||
struct qcom_icc_provider {
|
||||
struct icc_provider provider;
|
||||
struct clk_bulk_data *bus_clks;
|
||||
int num_clks;
|
||||
bool is_bimc_node;
|
||||
struct regmap *regmap;
|
||||
void __iomem *mmio;
|
||||
};
|
||||
|
||||
#define MSM8998_MAX_LINKS 38
|
||||
|
||||
/**
|
||||
* struct qcom_icc_qos - Qualcomm specific interconnect QoS parameters
|
||||
* @areq_prio: node requests priority
|
||||
* @prio_level: priority level for bus communication
|
||||
* @limit_commands: activate/deactivate limiter mode during runtime
|
||||
* @ap_owned: indicates if the node is owned by the AP or by the RPM
|
||||
* @qos_mode: default qos mode for this node
|
||||
* @qos_port: qos port number for finding qos registers of this node
|
||||
*/
|
||||
struct qcom_icc_qos {
|
||||
u32 areq_prio;
|
||||
u32 prio_level;
|
||||
bool limit_commands;
|
||||
bool ap_owned;
|
||||
int qos_mode;
|
||||
int qos_port;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qcom_icc_node - Qualcomm specific interconnect nodes
|
||||
* @name: the node name used in debugfs
|
||||
* @id: a unique node identifier
|
||||
* @links: an array of nodes where we can go next while traversing
|
||||
* @num_links: the total number of @links
|
||||
* @buswidth: width of the interconnect between a node and the bus (bytes)
|
||||
* @mas_rpm_id: RPM id for devices that are bus masters
|
||||
* @slv_rpm_id: RPM id for devices that are bus slaves
|
||||
* @qos: NoC QoS setting parameters
|
||||
* @rate: current bus clock rate in Hz
|
||||
*/
|
||||
struct qcom_icc_node {
|
||||
unsigned char *name;
|
||||
u16 id;
|
||||
u16 links[MSM8998_MAX_LINKS];
|
||||
u16 num_links;
|
||||
u16 buswidth;
|
||||
int mas_rpm_id;
|
||||
int slv_rpm_id;
|
||||
struct qcom_icc_qos qos;
|
||||
u64 rate;
|
||||
};
|
||||
|
||||
struct qcom_icc_desc {
|
||||
struct qcom_icc_node **nodes;
|
||||
size_t num_nodes;
|
||||
const struct regmap_config *regmap_cfg;
|
||||
};
|
||||
|
||||
#define DEFINE_QNODE(_name, _id, _buswidth, _mas_rpm_id, _slv_rpm_id, \
|
||||
_ap_owned, _qos_mode, _qos_prio, _qos_port, ...) \
|
||||
static struct qcom_icc_node _name = { \
|
||||
.name = #_name, \
|
||||
.id = _id, \
|
||||
.buswidth = _buswidth, \
|
||||
.mas_rpm_id = _mas_rpm_id, \
|
||||
.slv_rpm_id = _slv_rpm_id, \
|
||||
.qos.ap_owned = _ap_owned, \
|
||||
.qos.qos_mode = _qos_mode, \
|
||||
.qos.areq_prio = _qos_prio, \
|
||||
.qos.prio_level = _qos_prio, \
|
||||
.qos.qos_port = _qos_port, \
|
||||
.num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ })), \
|
||||
.links = { __VA_ARGS__ }, \
|
||||
}
|
||||
|
||||
/* masters */
|
||||
DEFINE_QNODE(mas_pcie_0, MSM8998_MASTER_PCIE_0, 16, 45, -1, true, NOC_QOS_MODE_FIXED, 1, 1, MSM8998_SLAVE_A1NOC_SNOC);
|
||||
DEFINE_QNODE(mas_usb3, MSM8998_MASTER_USB3, 16, 32, -1, true, NOC_QOS_MODE_FIXED, 1, 2, MSM8998_SLAVE_A1NOC_SNOC);
|
||||
DEFINE_QNODE(mas_ufs, MSM8998_MASTER_UFS, 16, 68, -1, true, NOC_QOS_MODE_FIXED, 1, 2, MSM8998_SLAVE_A1NOC_SNOC);
|
||||
DEFINE_QNODE(mas_blsp_2, MSM8998_MASTER_BLSP_2, 16, 39, -1, false, NOC_QOS_MODE_FIXED, 0, 4, MSM8998_SLAVE_A1NOC_SNOC);
|
||||
DEFINE_QNODE(mas_cnoc_a2noc, MSM8998_MASTER_CNOC_A2NOC, 8, 146, -1, true, -1, 0, -1, MSM8998_SLAVE_A2NOC_SNOC);
|
||||
DEFINE_QNODE(mas_ipa, MSM8998_MASTER_IPA, 8, 59, -1, true, NOC_QOS_MODE_FIXED, 1, 1, MSM8998_SLAVE_A2NOC_SNOC);
|
||||
DEFINE_QNODE(mas_sdcc_2, MSM8998_MASTER_SDCC_2, 8, 35, -1, false, NOC_QOS_MODE_FIXED, 0, 6, MSM8998_SLAVE_A2NOC_SNOC);
|
||||
DEFINE_QNODE(mas_sdcc_4, MSM8998_MASTER_SDCC_4, 8, 36, -1, false, NOC_QOS_MODE_FIXED, 0, 7, MSM8998_SLAVE_A2NOC_SNOC);
|
||||
DEFINE_QNODE(mas_tsif, MSM8998_MASTER_A2NOC_TSIF, 4, 37, -1, true, -1, 0, -1, MSM8998_SLAVE_A2NOC_SNOC);
|
||||
DEFINE_QNODE(mas_blsp_1, MSM8998_MASTER_BLSP_1, 16, 41, -1, false, NOC_QOS_MODE_FIXED, 0, 8, MSM8998_SLAVE_A2NOC_SNOC);
|
||||
DEFINE_QNODE(mas_crvirt_a2noc, MSM8998_MASTER_CRVIRT_A2NOC, 8, 145, -1, false, NOC_QOS_MODE_FIXED, 0, 9, MSM8998_SLAVE_A2NOC_SNOC);
|
||||
DEFINE_QNODE(mas_gnoc_bimc, MSM8998_MASTER_GNOC_BIMC, 8, 144, -1, true, NOC_QOS_MODE_FIXED, 0, 0, MSM8998_SLAVE_EBI, MSM8998_SLAVE_BIMC_SNOC_0);
|
||||
DEFINE_QNODE(mas_oxili, MSM8998_MASTER_OXILI, 8, 6, -1, true, NOC_QOS_MODE_BYPASS, 0, 1, MSM8998_SLAVE_BIMC_SNOC_1, MSM8998_SLAVE_HMSS_L3, MSM8998_SLAVE_EBI, MSM8998_SLAVE_BIMC_SNOC_0);
|
||||
DEFINE_QNODE(mas_mnoc_bimc, MSM8998_MASTER_MNOC_BIMC, 8, 2, -1, true, NOC_QOS_MODE_BYPASS, 0, 2, MSM8998_SLAVE_BIMC_SNOC_1, MSM8998_SLAVE_HMSS_L3, MSM8998_SLAVE_EBI, MSM8998_SLAVE_BIMC_SNOC_0);
|
||||
DEFINE_QNODE(mas_snoc_bimc, MSM8998_MASTER_SNOC_BIMC, 8, 3, -1, false, NOC_QOS_MODE_BYPASS, 0, 3, MSM8998_SLAVE_HMSS_L3, MSM8998_SLAVE_EBI);
|
||||
DEFINE_QNODE(mas_snoc_cnoc, MSM8998_MASTER_SNOC_CNOC, 8, 52, -1, true, -1, 0, -1, MSM8998_SLAVE_SKL, MSM8998_SLAVE_BLSP_2, MSM8998_SLAVE_MESSAGE_RAM, MSM8998_SLAVE_TLMM_WEST, MSM8998_SLAVE_TSIF, MSM8998_SLAVE_MPM, MSM8998_SLAVE_BIMC_CFG, MSM8998_SLAVE_TLMM_EAST, MSM8998_SLAVE_SPDM, MSM8998_SLAVE_PIMEM_CFG, MSM8998_SLAVE_A1NOC_SMMU_CFG, MSM8998_SLAVE_BLSP_1, MSM8998_SLAVE_CLK_CTL, MSM8998_SLAVE_PRNG, MSM8998_SLAVE_USB3_0, MSM8998_SLAVE_QDSS_CFG, MSM8998_SLAVE_QM_CFG, MSM8998_SLAVE_A2NOC_CFG, MSM8998_SLAVE_PMIC_ARB, MSM8998_SLAVE_UFS_CFG, MSM8998_SLAVE_SRVC_CNOC, MSM8998_SLAVE_AHB2PHY, MSM8998_SLAVE_IPA, MSM8998_SLAVE_GLM, MSM8998_SLAVE_SNOC_CFG, MSM8998_SLAVE_SSC_CFG, MSM8998_SLAVE_SDCC_2, MSM8998_SLAVE_SDCC_4, MSM8998_SLAVE_PDM, MSM8998_SLAVE_CNOC_MNOC_MMSS_CFG, MSM8998_SLAVE_CNOC_MNOC_CFG, MSM8998_SLAVE_MSS_CFG, MSM8998_SLAVE_IMEM_CFG, MSM8998_SLAVE_A1NOC_CFG, MSM8998_SLAVE_GPUSS_CFG, MSM8998_SLAVE_TCSR, MSM8998_SLAVE_TLMM_NORTH);
|
||||
DEFINE_QNODE(mas_qdss_dap, MSM8998_MASTER_QDSS_DAP, 8, 49, -1, true, -1, 0, -1, MSM8998_SLAVE_SKL, MSM8998_SLAVE_BLSP_2, MSM8998_SLAVE_MESSAGE_RAM, MSM8998_SLAVE_TLMM_WEST, MSM8998_SLAVE_TSIF, MSM8998_SLAVE_MPM, MSM8998_SLAVE_BIMC_CFG, MSM8998_SLAVE_TLMM_EAST, MSM8998_SLAVE_SPDM, MSM8998_SLAVE_PIMEM_CFG, MSM8998_SLAVE_A1NOC_SMMU_CFG, MSM8998_SLAVE_BLSP_1, MSM8998_SLAVE_CLK_CTL, MSM8998_SLAVE_PRNG, MSM8998_SLAVE_USB3_0, MSM8998_SLAVE_QDSS_CFG, MSM8998_SLAVE_QM_CFG, MSM8998_SLAVE_A2NOC_CFG, MSM8998_SLAVE_PMIC_ARB, MSM8998_SLAVE_UFS_CFG, MSM8998_SLAVE_SRVC_CNOC, MSM8998_SLAVE_AHB2PHY, MSM8998_SLAVE_IPA, MSM8998_SLAVE_GLM, MSM8998_SLAVE_SNOC_CFG, MSM8998_SLAVE_SDCC_2, MSM8998_SLAVE_SDCC_4, MSM8998_SLAVE_PDM, MSM8998_SLAVE_CNOC_MNOC_MMSS_CFG, MSM8998_SLAVE_CNOC_MNOC_CFG, MSM8998_SLAVE_MSS_CFG, MSM8998_SLAVE_IMEM_CFG, MSM8998_SLAVE_A1NOC_CFG, MSM8998_SLAVE_GPUSS_CFG, MSM8998_SLAVE_SSC_CFG, MSM8998_SLAVE_TCSR, MSM8998_SLAVE_TLMM_NORTH, MSM8998_SLAVE_CNOC_A2NOC);
|
||||
DEFINE_QNODE(mas_crypto, MSM8998_MASTER_CRYPTO_C0, 650, 23, -1, false, -1, 0, -1, MSM8998_MASTER_CRVIRT_A2NOC);
|
||||
DEFINE_QNODE(mas_apss_proc, MSM8998_MASTER_APPS_PROC, 32, 0, -1, true, -1, 0, -1, MSM8998_SLAVE_GNOC_BIMC);
|
||||
DEFINE_QNODE(mas_cnoc_mnoc_mmss_cfg, MSM8998_MASTER_CNOC_MNOC_MMSS_CFG, 8, 4, -1, true, -1, 0, -1, MSM8998_SLAVE_CAMERA_THROTTLE_CFG, MSM8998_SLAVE_VENUS_CFG, MSM8998_SLAVE_MISC_CFG, MSM8998_SLAVE_CAMERA_CFG, MSM8998_SLAVE_DISPLAY_THROTTLE_CFG, MSM8998_SLAVE_VENUS_THROTTLE_CFG, MSM8998_SLAVE_DISPLAY_CFG, MSM8998_SLAVE_MMSS_CLK_CFG, MSM8998_SLAVE_VMEM_CFG, MSM8998_SLAVE_MMSS_CLK_XPU_CFG, MSM8998_SLAVE_SMMU_CFG);
|
||||
DEFINE_QNODE(mas_cnoc_mnoc_cfg, MSM8998_MASTER_CNOC_MNOC_CFG, 8, 5, -1, true, -1, 0, -1, MSM8998_SLAVE_SRVC_MNOC);
|
||||
DEFINE_QNODE(mas_cpp, MSM8998_MASTER_CPP, 32, 115, -1, true, NOC_QOS_MODE_BYPASS, 0, 5, MSM8998_SLAVE_MNOC_BIMC);
|
||||
DEFINE_QNODE(mas_jpeg, MSM8998_MASTER_JPEG, 32, 7, -1, true, NOC_QOS_MODE_BYPASS, 0, 7, MSM8998_SLAVE_MNOC_BIMC);
|
||||
DEFINE_QNODE(mas_mdp_p0, MSM8998_MASTER_MDP_P0, 32, 8, -1, true, NOC_QOS_MODE_BYPASS, 0, 1, MSM8998_SLAVE_MNOC_BIMC); /* vrail-comp???? */
|
||||
DEFINE_QNODE(mas_mdp_p1, MSM8998_MASTER_MDP_P1, 32, 61, -1, true, NOC_QOS_MODE_BYPASS, 0, 2, MSM8998_SLAVE_MNOC_BIMC); /* vrail-comp??? */
|
||||
DEFINE_QNODE(mas_rotator, MSM8998_MASTER_ROTATOR, 32, 120, -1, true, NOC_QOS_MODE_BYPASS, 0, 0, MSM8998_SLAVE_MNOC_BIMC);
|
||||
DEFINE_QNODE(mas_venus, MSM8998_MASTER_VENUS, 32, 9, -1, true, NOC_QOS_MODE_BYPASS, 0, 3, MSM8998_SLAVE_MNOC_BIMC);
|
||||
DEFINE_QNODE(mas_vfe, MSM8998_MASTER_VFE, 32, 11, -1, true, NOC_QOS_MODE_BYPASS, 0, 6, MSM8998_SLAVE_MNOC_BIMC);
|
||||
DEFINE_QNODE(mas_venus_vmem, MSM8998_MASTER_VENUS_VMEM, 32, 121, -1, true, -1, 0, -1, MSM8998_SLAVE_VMEM);
|
||||
DEFINE_QNODE(mas_hmss, MSM8998_MASTER_HMSS, 16, 118, -1, true, NOC_QOS_MODE_FIXED, 1, 3, MSM8998_SLAVE_PIMEM, MSM8998_SLAVE_IMEM, MSM8998_SLAVE_SNOC_BIMC);
|
||||
DEFINE_QNODE(mas_qdss_bam, MSM8998_MASTER_QDSS_BAM, 16, 19, -1, true, NOC_QOS_MODE_FIXED, 1, 1, MSM8998_SLAVE_IMEM, MSM8998_SLAVE_PIMEM, MSM8998_SLAVE_SNOC_CNOC, MSM8998_SLAVE_SNOC_BIMC);
|
||||
DEFINE_QNODE(mas_snoc_cfg, MSM8998_MASTER_SNOC_CFG, 16, 20, -1, false, -1, 0, -1, MSM8998_SLAVE_SRVC_SNOC);
|
||||
DEFINE_QNODE(mas_bimc_snoc_0, MSM8998_MASTER_BIMC_SNOC_0, 16, 21, -1, false, -1, 0, -1, MSM8998_SLAVE_PIMEM, MSM8998_SLAVE_LPASS, MSM8998_SLAVE_HMSS, MSM8998_SLAVE_WLAN, MSM8998_SLAVE_SNOC_CNOC, MSM8998_SLAVE_IMEM, MSM8998_SLAVE_QDSS_STM);
|
||||
DEFINE_QNODE(mas_bimc_snoc_1, MSM8998_MASTER_BIMC_SNOC_1, 16, 109, -1, true, -1, 0, -1, MSM8998_SLAVE_PCIE_0);
|
||||
DEFINE_QNODE(mas_a1noc_snoc, MSM8998_MASTER_A1NOC_SNOC, 16, 111, -1, false, -1, 0, -1, MSM8998_SLAVE_PIMEM, MSM8998_SLAVE_PCIE_0, MSM8998_SLAVE_LPASS, MSM8998_SLAVE_HMSS, MSM8998_SLAVE_SNOC_BIMC, MSM8998_SLAVE_SNOC_CNOC, MSM8998_SLAVE_IMEM, MSM8998_SLAVE_QDSS_STM);
|
||||
DEFINE_QNODE(mas_a2noc_snoc, MSM8998_MASTER_A2NOC_SNOC, 16, 112, -1, false, -1, 0, -1, MSM8998_SLAVE_PIMEM, MSM8998_SLAVE_PCIE_0, MSM8998_SLAVE_LPASS, MSM8998_SLAVE_HMSS, MSM8998_SLAVE_SNOC_BIMC, MSM8998_SLAVE_WLAN, MSM8998_SLAVE_SNOC_CNOC, MSM8998_SLAVE_IMEM, MSM8998_SLAVE_QDSS_STM);
|
||||
DEFINE_QNODE(mas_qdss_etr, MSM8998_MASTER_QDSS_ETR, 16, 31, -1, true, NOC_QOS_MODE_FIXED, 1, 2, MSM8998_SLAVE_IMEM, MSM8998_MASTER_PIMEM, MSM8998_SLAVE_SNOC_CNOC, MSM8998_SLAVE_SNOC_BIMC);
|
||||
|
||||
/* slaves */
|
||||
DEFINE_QNODE(slv_a1noc_snoc, MSM8998_SLAVE_A1NOC_SNOC, 16, -1, 142, false, -1, 0, -1, MSM8998_MASTER_A1NOC_SNOC);
|
||||
DEFINE_QNODE(slv_a2noc_snoc, MSM8998_SLAVE_A2NOC_SNOC, 16, -1, 143, false, -1, 0, -1, MSM8998_MASTER_A2NOC_SNOC);
|
||||
DEFINE_QNODE(slv_ebi, MSM8998_SLAVE_EBI, 8, -1, 0, false, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_hmss_l3, MSM8998_SLAVE_HMSS_L3, 8, -1, 160, false, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_bimc_snoc_0, MSM8998_SLAVE_BIMC_SNOC_0, 8, -1, 2, false, -1, 0, -1, MSM8998_MASTER_BIMC_SNOC_0);
|
||||
DEFINE_QNODE(slv_bimc_snoc_1, MSM8998_SLAVE_BIMC_SNOC_1, 8, -1, 138, true, -1, 0, -1, MSM8998_MASTER_BIMC_SNOC_1);
|
||||
DEFINE_QNODE(slv_cnoc_a2noc, MSM8998_SLAVE_CNOC_A2NOC, 4, -1, 208, true, -1, 0, -1, MSM8998_MASTER_CNOC_A2NOC);
|
||||
DEFINE_QNODE(slv_ssc_cfg, MSM8998_SLAVE_SSC_CFG, 4, -1, 177, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_mpm, MSM8998_SLAVE_MPM, 4, -1, 62, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_pmic_arb, MSM8998_SLAVE_PMIC_ARB, 4, -1, 59, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_tlmm_north, MSM8998_SLAVE_TLMM_NORTH, 4, -1, 214, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_pimem_cfg, MSM8998_SLAVE_PIMEM_CFG, 4, -1, 167, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_imem_cfg, MSM8998_SLAVE_IMEM_CFG, 4, -1, 54, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_message_ram, MSM8998_SLAVE_MESSAGE_RAM, 4, -1, 55, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_skl, MSM8998_SLAVE_SKL, 4, -1, 196, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_bimc_cfg, MSM8998_SLAVE_BIMC_CFG, 4, -1, 56, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_prng, MSM8998_SLAVE_PRNG, 4, -1, 44, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_a2noc_cfg, MSM8998_SLAVE_A2NOC_CFG, 4, -1, 150, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_ipa, MSM8998_SLAVE_IPA, 4, -1, 183, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_tcsr, MSM8998_SLAVE_TCSR, 4, -1, 50, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_snoc_cfg, MSM8998_SLAVE_SNOC_CFG, 4, -1, 70, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_clk_ctl, MSM8998_SLAVE_CLK_CTL, 4, -1, 47, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_glm, MSM8998_SLAVE_GLM, 4, -1, 209, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_spdm, MSM8998_SLAVE_SPDM, 4, -1, 60, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_gpuss_cfg, MSM8998_SLAVE_GPUSS_CFG, 4, -1, 11, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_cnoc_mnoc_cfg, MSM8998_SLAVE_CNOC_MNOC_CFG, 4, -1, 66, true, -1, 0, -1, MSM8998_MASTER_CNOC_MNOC_CFG);
|
||||
DEFINE_QNODE(slv_qm_cfg, MSM8998_SLAVE_QM_CFG, 4, -1, 212, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_mss_cfg, MSM8998_SLAVE_MSS_CFG, 4, -1, 48, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_ufs_cfg, MSM8998_SLAVE_UFS_CFG, 4, -1, 92, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_tlmm_west, MSM8998_SLAVE_TLMM_WEST, 4, -1, 215, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_a1noc_cfg, MSM8998_SLAVE_A1NOC_CFG, 4, -1, 147, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_ahb2phy, MSM8998_SLAVE_AHB2PHY, 4, -1, 163, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_blsp_2, MSM8998_SLAVE_BLSP_2, 4, -1, 37, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_pdm, MSM8998_SLAVE_PDM, 4, -1, 41, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_usb3_0, MSM8998_SLAVE_USB3_0, 4, -1, 22, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_a1noc_smmu_cfg, MSM8998_SLAVE_A1NOC_SMMU_CFG, 8, -1, 149, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_blsp_1, MSM8998_SLAVE_BLSP_1, 4, -1, 39, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_sdcc_2, MSM8998_SLAVE_SDCC_2, 4, -1, 33, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_sdcc_4, MSM8998_SLAVE_SDCC_4, 4, -1, 34, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_tsif, MSM8998_SLAVE_TSIF, 4, -1, 35, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_qdss_cfg, MSM8998_SLAVE_QDSS_CFG, 4, -1, 63, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_tlmm_east, MSM8998_SLAVE_TLMM_EAST, 4, -1, 213, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_cnoc_mnoc_mmss_cfg, MSM8998_SLAVE_CNOC_MNOC_MMSS_CFG, 8, -1, 58, true, -1, 0, -1, MSM8998_MASTER_CNOC_MNOC_MMSS_CFG);
|
||||
DEFINE_QNODE(slv_srvc_cnoc, MSM8998_SLAVE_SRVC_CNOC, 4, -1, 76, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_crvirt_a2noc, MSM8998_SLAVE_CRVIRT_A2NOC, 8, -1, 207, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_gnoc_bimc, MSM8998_SLAVE_GNOC_BIMC, 32, -1, 210, true, -1, 0, -1, MSM8998_MASTER_GNOC_BIMC);
|
||||
DEFINE_QNODE(slv_camera_cfg, MSM8998_SLAVE_CAMERA_CFG, 8, -1, 3, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_camera_throttle_cfg, MSM8998_SLAVE_CAMERA_THROTTLE_CFG, 8, -1, 154, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_misc_cfg, MSM8998_SLAVE_MISC_CFG, 8, -1, 8, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_venus_throttle_cfg, MSM8998_SLAVE_VENUS_THROTTLE_CFG, 8, -1, 178, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_venus_cfg, MSM8998_SLAVE_VENUS_CFG, 8, -1, 10, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_vmem_cfg, MSM8998_SLAVE_VMEM_CFG, 8, -1, 180, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_mmss_clk_xpu_cfg, MSM8998_SLAVE_MMSS_CLK_XPU_CFG, 8, -1, 13, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_mmss_clk_cfg, MSM8998_SLAVE_MMSS_CLK_CFG, 8, -1, 12, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_display_cfg, MSM8998_SLAVE_DISPLAY_CFG, 8, -1, 4, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_display_throttle_cfg, MSM8998_SLAVE_DISPLAY_THROTTLE_CFG, 4, -1, 156, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_smmu_cfg, MSM8998_SLAVE_SMMU_CFG, 8, -1, 205, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_mnoc_bimc, MSM8998_SLAVE_MNOC_BIMC, 32, -1, 16, true, -1, 0, -1, MSM8998_MASTER_MNOC_BIMC);
|
||||
DEFINE_QNODE(slv_vmem, MSM8998_SLAVE_VMEM, 32, -1, 179, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_srvc_mnoc, MSM8998_SLAVE_SRVC_MNOC, 8, -1, 17, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_hmss, MSM8998_SLAVE_HMSS, 16, -1, 20, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_lpass, MSM8998_SLAVE_LPASS, 16, -1, 21, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_wlan, MSM8998_SLAVE_WLAN, 16, -1, 206, false, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_snoc_bimc, MSM8998_SLAVE_SNOC_BIMC, 32, -1, 24, false, -1, 0, -1, MSM8998_MASTER_SNOC_BIMC);
|
||||
DEFINE_QNODE(slv_snoc_cnoc, MSM8998_SLAVE_SNOC_CNOC, 16, -1, 25, false, -1, 0, -1, MSM8998_MASTER_SNOC_CNOC);
|
||||
DEFINE_QNODE(slv_imem, MSM8998_SLAVE_IMEM, 16, -1, 26, false, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_pimem, MSM8998_SLAVE_PIMEM, 16, -1, 166, false, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_qdss_stm, MSM8998_SLAVE_QDSS_STM, 16, -1, 30, false, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_pcie_0, MSM8998_SLAVE_PCIE_0, 16, -1, 84, true, -1, 0, -1, 0);
|
||||
DEFINE_QNODE(slv_srvc_snoc, MSM8998_SLAVE_SRVC_SNOC, 16, -1, 29, false, -1, 0, -1, 0);
|
||||
|
||||
static struct qcom_icc_node *msm8998_a1noc_nodes[] = {
|
||||
[MASTER_PCIE_0] = &mas_pcie_0,
|
||||
[MASTER_USB3] = &mas_usb3,
|
||||
[MASTER_UFS] = &mas_ufs,
|
||||
[MASTER_BLSP_2] = &mas_blsp_2,
|
||||
[SLAVE_A1NOC_SNOC] = &slv_a1noc_snoc,
|
||||
};
|
||||
|
||||
static const struct regmap_config msm8998_a1noc_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = 0x60000,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static struct qcom_icc_desc msm8998_a1noc = {
|
||||
.nodes = msm8998_a1noc_nodes,
|
||||
.num_nodes = ARRAY_SIZE(msm8998_a1noc_nodes),
|
||||
.regmap_cfg = &msm8998_a1noc_regmap_config,
|
||||
};
|
||||
|
||||
static struct qcom_icc_node *msm8998_a2noc_nodes[] = {
|
||||
[MASTER_IPA] = &mas_ipa,
|
||||
[MASTER_CNOC_A2NOC] = &mas_cnoc_a2noc,
|
||||
[MASTER_SDCC_2] = &mas_sdcc_2,
|
||||
[MASTER_SDCC_4] = &mas_sdcc_4,
|
||||
[MASTER_TSIF] = &mas_tsif,
|
||||
[MASTER_BLSP_1] = &mas_blsp_1,
|
||||
[MASTER_CRVIRT_A2NOC] = &mas_crvirt_a2noc,
|
||||
[MASTER_CRYPTO_C0] = &mas_crypto,
|
||||
[SLAVE_A2NOC_SNOC] = &slv_a2noc_snoc,
|
||||
[SLAVE_CRVIRT_A2NOC] = &slv_crvirt_a2noc,
|
||||
};
|
||||
|
||||
static const struct regmap_config msm8998_a2noc_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = 0x60000,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static struct qcom_icc_desc msm8998_a2noc = {
|
||||
.nodes = msm8998_a2noc_nodes,
|
||||
.num_nodes = ARRAY_SIZE(msm8998_a2noc_nodes),
|
||||
.regmap_cfg = &msm8998_a2noc_regmap_config,
|
||||
};
|
||||
|
||||
static struct qcom_icc_node *msm8998_bimc_nodes[] = {
|
||||
[MASTER_GNOC_BIMC] = &mas_gnoc_bimc,
|
||||
[MASTER_OXILI] = &mas_oxili,
|
||||
[MASTER_MNOC_BIMC] = &mas_mnoc_bimc,
|
||||
[MASTER_SNOC_BIMC] = &mas_snoc_bimc,
|
||||
[SLAVE_EBI] = &slv_ebi,
|
||||
[SLAVE_HMSS_L3] = &slv_hmss_l3,
|
||||
[SLAVE_BIMC_SNOC_0] = &slv_bimc_snoc_0,
|
||||
[SLAVE_BIMC_SNOC_1] = &slv_bimc_snoc_1,
|
||||
};
|
||||
|
||||
static const struct regmap_config msm8998_bimc_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = 0x80000,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static struct qcom_icc_desc msm8998_bimc = {
|
||||
.nodes = msm8998_bimc_nodes,
|
||||
.num_nodes = ARRAY_SIZE(msm8998_bimc_nodes),
|
||||
.regmap_cfg = &msm8998_bimc_regmap_config,
|
||||
};
|
||||
|
||||
static struct qcom_icc_node *msm8998_cnoc_nodes[] = {
|
||||
[MASTER_SNOC_CNOC] = &mas_snoc_cnoc,
|
||||
[MASTER_QDSS_DAP] = &mas_qdss_dap,
|
||||
[SLAVE_CNOC_A2NOC] = &slv_cnoc_a2noc,
|
||||
[SLAVE_SSC_CFG] = &slv_ssc_cfg,
|
||||
[SLAVE_MPM] = &slv_mpm,
|
||||
[SLAVE_PMIC_ARB] = &slv_pmic_arb,
|
||||
[SLAVE_TLMM_NORTH] = &slv_tlmm_north,
|
||||
[SLAVE_PIMEM_CFG] = &slv_pimem_cfg,
|
||||
[SLAVE_IMEM_CFG] = &slv_imem_cfg,
|
||||
[SLAVE_MESSAGE_RAM] = &slv_message_ram,
|
||||
[SLAVE_SKL] = &slv_skl,
|
||||
[SLAVE_BIMC_CFG] = &slv_bimc_cfg,
|
||||
[SLAVE_PRNG] = &slv_prng,
|
||||
[SLAVE_A2NOC_CFG] = &slv_a2noc_cfg,
|
||||
[SLAVE_IPA] = &slv_ipa,
|
||||
[SLAVE_TCSR] = &slv_tcsr,
|
||||
[SLAVE_SNOC_CFG] = &slv_snoc_cfg,
|
||||
[SLAVE_CLK_CTL] = &slv_clk_ctl,
|
||||
[SLAVE_GLM] = &slv_glm,
|
||||
[SLAVE_SPDM] = &slv_spdm,
|
||||
[SLAVE_GPUSS_CFG] = &slv_gpuss_cfg,
|
||||
[SLAVE_CNOC_MNOC_CFG] = &slv_cnoc_mnoc_cfg,
|
||||
[SLAVE_QM_CFG] = &slv_qm_cfg,
|
||||
[SLAVE_MSS_CFG] = &slv_mss_cfg,
|
||||
[SLAVE_UFS_CFG] = &slv_ufs_cfg,
|
||||
[SLAVE_TLMM_WEST] = &slv_tlmm_west,
|
||||
[SLAVE_A1NOC_CFG] = &slv_a1noc_cfg,
|
||||
[SLAVE_AHB2PHY] = &slv_ahb2phy,
|
||||
[SLAVE_BLSP_2] = &slv_blsp_2,
|
||||
[SLAVE_PDM] = &slv_pdm,
|
||||
[SLAVE_USB3_0] = &slv_usb3_0,
|
||||
[SLAVE_A1NOC_SMMU_CFG] = &slv_a1noc_smmu_cfg,
|
||||
[SLAVE_BLSP_1] = &slv_blsp_1,
|
||||
[SLAVE_SDCC_2] = &slv_sdcc_2,
|
||||
[SLAVE_SDCC_4] = &slv_sdcc_4,
|
||||
[SLAVE_TSIF] = &slv_tsif,
|
||||
[SLAVE_QDSS_CFG] = &slv_qdss_cfg,
|
||||
[SLAVE_TLMM_EAST] = &slv_tlmm_east,
|
||||
[SLAVE_CNOC_MNOC_MMSS_CFG] = &slv_cnoc_mnoc_mmss_cfg,
|
||||
[SLAVE_SRVC_CNOC] = &slv_srvc_cnoc,
|
||||
};
|
||||
|
||||
static const struct regmap_config msm8998_cnoc_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = 0x10000,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static struct qcom_icc_desc msm8998_cnoc = {
|
||||
.nodes = msm8998_cnoc_nodes,
|
||||
.num_nodes = ARRAY_SIZE(msm8998_cnoc_nodes),
|
||||
.regmap_cfg = &msm8998_cnoc_regmap_config,
|
||||
};
|
||||
|
||||
static struct qcom_icc_node *msm8998_gnoc_nodes[] = {
|
||||
[MASTER_APSS_PROC] = &mas_apss_proc,
|
||||
[SLAVE_GNOC_BIMC] = &slv_gnoc_bimc,
|
||||
};
|
||||
|
||||
static const struct regmap_config msm8998_gnoc_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = 0x10000,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static struct qcom_icc_desc msm8998_gnoc = {
|
||||
.nodes = msm8998_gnoc_nodes,
|
||||
.num_nodes = ARRAY_SIZE(msm8998_gnoc_nodes),
|
||||
.regmap_cfg = &msm8998_gnoc_regmap_config,
|
||||
};
|
||||
|
||||
static struct qcom_icc_node *msm8998_mnoc_nodes[] = {
|
||||
[MASTER_CNOC_MNOC_CFG] = &mas_cnoc_mnoc_cfg,
|
||||
[MASTER_CPP] = &mas_cpp,
|
||||
[MASTER_JPEG] = &mas_jpeg,
|
||||
[MASTER_MDP_P0] = &mas_mdp_p0,
|
||||
[MASTER_MDP_P1] = &mas_mdp_p1,
|
||||
[MASTER_ROTATOR] = &mas_rotator,
|
||||
[MASTER_VENUS] = &mas_venus,
|
||||
[MASTER_VFE] = &mas_vfe,
|
||||
[MASTER_VENUS_VMEM] = &mas_venus_vmem,
|
||||
[SLAVE_MNOC_BIMC] = &slv_mnoc_bimc,
|
||||
[SLAVE_VMEM] = &slv_vmem,
|
||||
[SLAVE_SRVC_MNOC] = &slv_srvc_mnoc,
|
||||
[MASTER_CNOC_MNOC_MMSS_CFG] = &mas_cnoc_mnoc_mmss_cfg,
|
||||
[SLAVE_CAMERA_CFG] = &slv_camera_cfg,
|
||||
[SLAVE_CAMERA_THROTTLE_CFG] = &slv_camera_throttle_cfg,
|
||||
[SLAVE_MISC_CFG] = &slv_misc_cfg,
|
||||
[SLAVE_VENUS_THROTTLE_CFG] = &slv_venus_throttle_cfg,
|
||||
[SLAVE_VENUS_CFG] = &slv_venus_cfg,
|
||||
[SLAVE_VMEM_CFG] = &slv_vmem_cfg,
|
||||
[SLAVE_MMSS_CLK_XPU_CFG] = &slv_mmss_clk_xpu_cfg,
|
||||
[SLAVE_MMSS_CLK_CFG] = &slv_mmss_clk_cfg,
|
||||
[SLAVE_DISPLAY_CFG] = &slv_display_cfg,
|
||||
[SLAVE_DISPLAY_THROTTLE_CFG] = &slv_display_throttle_cfg,
|
||||
[SLAVE_SMMU_CFG] = &slv_smmu_cfg,
|
||||
};
|
||||
|
||||
static const struct regmap_config msm8998_mnoc_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = 0x10000,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static struct qcom_icc_desc msm8998_mnoc = {
|
||||
.nodes = msm8998_mnoc_nodes,
|
||||
.num_nodes = ARRAY_SIZE(msm8998_mnoc_nodes),
|
||||
.regmap_cfg = &msm8998_mnoc_regmap_config,
|
||||
};
|
||||
|
||||
static struct qcom_icc_node *msm8998_snoc_nodes[] = {
|
||||
[MASTER_HMSS] = &mas_hmss,
|
||||
[MASTER_QDSS_BAM] = &mas_qdss_bam,
|
||||
[MASTER_SNOC_CFG] = &mas_snoc_cfg,
|
||||
[MASTER_BIMC_SNOC_0] = &mas_bimc_snoc_0,
|
||||
[MASTER_BIMC_SNOC_1] = &mas_bimc_snoc_1,
|
||||
[MASTER_A1NOC_SNOC] = &mas_a1noc_snoc,
|
||||
[MASTER_A2NOC_SNOC] = &mas_a2noc_snoc,
|
||||
[MASTER_QDSS_ETR] = &mas_qdss_etr,
|
||||
[SLAVE_HMSS] = &slv_hmss,
|
||||
[SLAVE_LPASS] = &slv_lpass,
|
||||
[SLAVE_WLAN] = &slv_wlan,
|
||||
[SLAVE_SNOC_BIMC] = &slv_snoc_bimc,
|
||||
[SLAVE_SNOC_CNOC] = &slv_snoc_cnoc,
|
||||
[SLAVE_IMEM] = &slv_imem,
|
||||
[SLAVE_PIMEM] = &slv_pimem,
|
||||
[SLAVE_QDSS_STM] = &slv_qdss_stm,
|
||||
[SLAVE_PCIE_0] = &slv_pcie_0,
|
||||
[SLAVE_SRVC_SNOC] = &slv_srvc_snoc,
|
||||
};
|
||||
|
||||
static const struct regmap_config msm8998_snoc_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = 0x40000,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static struct qcom_icc_desc msm8998_snoc = {
|
||||
.nodes = msm8998_snoc_nodes,
|
||||
.num_nodes = ARRAY_SIZE(msm8998_snoc_nodes),
|
||||
.regmap_cfg = &msm8998_snoc_regmap_config,
|
||||
};
|
||||
|
||||
static int qcom_icc_bimc_set_qos_health(struct regmap *rmap,
|
||||
struct qcom_icc_qos *qos,
|
||||
int regnum)
|
||||
{
|
||||
u32 val;
|
||||
u32 mask;
|
||||
|
||||
val = qos->prio_level;
|
||||
mask = M_BKE_HEALTH_CFG_PRIOLVL_MASK;
|
||||
|
||||
val |= qos->areq_prio << M_BKE_HEALTH_CFG_AREQPRIO_SHIFT;
|
||||
mask |= M_BKE_HEALTH_CFG_AREQPRIO_MASK;
|
||||
|
||||
/* LIMITCMDS is not present on M_BKE_HEALTH_3 */
|
||||
if (regnum != 3) {
|
||||
val |= qos->limit_commands << M_BKE_HEALTH_CFG_LIMITCMDS_SHIFT;
|
||||
mask |= M_BKE_HEALTH_CFG_LIMITCMDS_MASK;
|
||||
}
|
||||
|
||||
return regmap_update_bits(rmap,
|
||||
M_BKE_HEALTH_CFG_ADDR(regnum, qos->qos_port),
|
||||
mask, val);
|
||||
}
|
||||
|
||||
static int qcom_icc_set_bimc_qos(struct icc_node *src, u64 max_bw,
|
||||
bool bypass_mode)
|
||||
{
|
||||
struct qcom_icc_provider *qp;
|
||||
struct qcom_icc_node *qn;
|
||||
struct icc_provider *provider;
|
||||
u32 mode = NOC_QOS_MODE_BYPASS;
|
||||
u32 val = 0;
|
||||
int i, rc = 0;
|
||||
|
||||
qn = src->data;
|
||||
provider = src->provider;
|
||||
qp = to_qcom_provider(provider);
|
||||
|
||||
if (qn->qos.qos_mode != -1)
|
||||
mode = qn->qos.qos_mode;
|
||||
|
||||
/*
|
||||
* QoS Priority: The QoS Health parameters are getting considered
|
||||
* only if we are NOT in Bypass Mode.
|
||||
*/
|
||||
if (mode != NOC_QOS_MODE_BYPASS) {
|
||||
for (i = 3; i >= 0; i--) {
|
||||
rc = qcom_icc_bimc_set_qos_health(qp->regmap,
|
||||
&qn->qos, i);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Set BKE_EN to 1 when Fixed, Regulator or Limiter Mode */
|
||||
val = 1;
|
||||
}
|
||||
|
||||
return regmap_update_bits(qp->regmap, M_BKE_EN_ADDR(qn->qos.qos_port),
|
||||
M_BKE_EN_EN_BMASK, val);
|
||||
}
|
||||
|
||||
static int qcom_icc_noc_set_qos_priority(struct regmap *rmap,
|
||||
struct qcom_icc_qos *qos)
|
||||
{
|
||||
u32 val;
|
||||
int rc;
|
||||
|
||||
/* Must be updated one at a time, P1 first, P0 last */
|
||||
val = qos->areq_prio << NOC_QOS_PRIORITY_P1_SHIFT;
|
||||
rc = regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port),
|
||||
NOC_QOS_PRIORITY_MASK, val);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
val = qos->prio_level << NOC_QOS_PRIORITY_P0_SHIFT;
|
||||
return regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port),
|
||||
NOC_QOS_PRIORITY_MASK, val);
|
||||
}
|
||||
|
||||
static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw)
|
||||
{
|
||||
struct qcom_icc_provider *qp;
|
||||
struct qcom_icc_node *qn;
|
||||
struct icc_provider *provider;
|
||||
u32 mode = NOC_QOS_MODE_BYPASS;
|
||||
int rc = 0;
|
||||
|
||||
qn = src->data;
|
||||
provider = src->provider;
|
||||
qp = to_qcom_provider(provider);
|
||||
|
||||
if (qn->qos.qos_port < 0) {
|
||||
dev_dbg(src->provider->dev,
|
||||
"NoC QoS: Skipping %s: vote aggregated on parent.\n",
|
||||
qn->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (qn->qos.qos_mode != -1)
|
||||
mode = qn->qos.qos_mode;
|
||||
|
||||
if (mode == NOC_QOS_MODE_FIXED) {
|
||||
dev_dbg(src->provider->dev, "NoC QoS: %s: Set Fixed mode\n",
|
||||
qn->name);
|
||||
rc = qcom_icc_noc_set_qos_priority(qp->regmap, &qn->qos);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (mode == NOC_QOS_MODE_BYPASS) {
|
||||
dev_dbg(src->provider->dev, "NoC QoS: %s: Set Bypass mode\n",
|
||||
qn->name);
|
||||
}
|
||||
|
||||
return regmap_update_bits(qp->regmap,
|
||||
NOC_QOS_MODEn_ADDR(qn->qos.qos_port),
|
||||
NOC_QOS_MODEn_MASK, mode);
|
||||
}
|
||||
|
||||
static int qcom_icc_qos_set(struct icc_node *node, u64 sum_bw)
|
||||
{
|
||||
struct qcom_icc_provider *qp = to_qcom_provider(node->provider);
|
||||
struct qcom_icc_node *qn = node->data;
|
||||
|
||||
dev_dbg(node->provider->dev, "Setting QoS for %s\n", qn->name);
|
||||
|
||||
if (qp->is_bimc_node)
|
||||
return qcom_icc_set_bimc_qos(node, sum_bw,
|
||||
(qn->qos.qos_mode == NOC_QOS_MODE_BYPASS));
|
||||
|
||||
return qcom_icc_set_noc_qos(node, sum_bw);
|
||||
}
|
||||
|
||||
static int qcom_icc_rpm_set(int mas_rpm_id, int slv_rpm_id, u64 sum_bw)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (mas_rpm_id != -1) {
|
||||
ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE,
|
||||
RPM_BUS_MASTER_REQ,
|
||||
mas_rpm_id,
|
||||
sum_bw);
|
||||
if (ret) {
|
||||
pr_err("qcom_icc_rpm_smd_send mas %d error %d\n",
|
||||
mas_rpm_id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (slv_rpm_id != -1) {
|
||||
ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE,
|
||||
RPM_BUS_SLAVE_REQ,
|
||||
slv_rpm_id,
|
||||
sum_bw);
|
||||
if (ret) {
|
||||
pr_err("qcom_icc_rpm_smd_send slv %d error %d\n",
|
||||
slv_rpm_id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
struct qcom_icc_provider *qp;
|
||||
struct qcom_icc_node *qn;
|
||||
struct icc_provider *provider;
|
||||
struct icc_node *n;
|
||||
u64 sum_bw;
|
||||
u64 max_peak_bw;
|
||||
u64 rate;
|
||||
u32 agg_avg = 0;
|
||||
u32 agg_peak = 0;
|
||||
int ret, i;
|
||||
|
||||
qn = src->data;
|
||||
provider = src->provider;
|
||||
qp = to_qcom_provider(provider);
|
||||
|
||||
list_for_each_entry(n, &provider->nodes, node_list)
|
||||
provider->aggregate(n, 0, n->avg_bw, n->peak_bw,
|
||||
&agg_avg, &agg_peak);
|
||||
|
||||
sum_bw = icc_units_to_bps(agg_avg);
|
||||
max_peak_bw = icc_units_to_bps(agg_peak);
|
||||
|
||||
if (!qn->qos.ap_owned) {
|
||||
/* send bandwidth request message to the RPM processor */
|
||||
ret = qcom_icc_rpm_set(qn->mas_rpm_id, qn->slv_rpm_id, sum_bw);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else if (qn->qos.qos_mode != -1) {
|
||||
/* set bandwidth directly from the AP */
|
||||
ret = qcom_icc_qos_set(src, sum_bw);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
rate = max(sum_bw, max_peak_bw);
|
||||
|
||||
do_div(rate, qn->buswidth);
|
||||
|
||||
if (qn->rate == rate)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < qp->num_clks; i++) {
|
||||
ret = clk_set_rate(qp->bus_clks[i].clk, rate);
|
||||
if (ret) {
|
||||
pr_err("%s clk_set_rate error: %d\n",
|
||||
qp->bus_clks[i].id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
qn->rate = rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qnoc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct qcom_icc_desc *desc;
|
||||
struct icc_onecell_data *data;
|
||||
struct icc_provider *provider;
|
||||
struct qcom_icc_node **qnodes;
|
||||
struct qcom_icc_provider *qp;
|
||||
struct icc_node *node;
|
||||
struct resource *res;
|
||||
size_t num_nodes, i;
|
||||
int ret;
|
||||
|
||||
/* wait for the RPM proxy */
|
||||
if (!qcom_icc_rpm_smd_available())
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
desc = of_device_get_match_data(dev);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
qnodes = desc->nodes;
|
||||
num_nodes = desc->num_nodes;
|
||||
|
||||
qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
|
||||
if (!qp)
|
||||
return -ENOMEM;
|
||||
|
||||
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_device_is_compatible(dev->of_node, "qcom,msm8998-mnoc")) {
|
||||
qp->bus_clks = devm_kmemdup(dev, bus_mm_clocks,
|
||||
sizeof(bus_mm_clocks), GFP_KERNEL);
|
||||
qp->num_clks = ARRAY_SIZE(bus_mm_clocks);
|
||||
} else {
|
||||
if (of_device_is_compatible(dev->of_node, "qcom,msm8998-bimc"))
|
||||
qp->is_bimc_node = true;
|
||||
|
||||
qp->bus_clks = devm_kmemdup(dev, bus_clocks, sizeof(bus_clocks),
|
||||
GFP_KERNEL);
|
||||
qp->num_clks = ARRAY_SIZE(bus_clocks);
|
||||
}
|
||||
if (!qp->bus_clks)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
|
||||
qp->mmio = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(qp->mmio)) {
|
||||
dev_err(dev, "Cannot ioremap interconnect bus resource\n");
|
||||
return PTR_ERR(qp->mmio);
|
||||
}
|
||||
|
||||
qp->regmap = devm_regmap_init_mmio(dev, qp->mmio, desc->regmap_cfg);
|
||||
if (IS_ERR(qp->regmap)) {
|
||||
dev_err(dev, "Cannot regmap interconnect bus resource\n");
|
||||
return PTR_ERR(qp->regmap);
|
||||
}
|
||||
|
||||
ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
provider = &qp->provider;
|
||||
INIT_LIST_HEAD(&provider->nodes);
|
||||
provider->dev = dev;
|
||||
provider->set = qcom_icc_set;
|
||||
provider->aggregate = icc_std_aggregate;
|
||||
provider->xlate = of_icc_xlate_onecell;
|
||||
provider->data = data;
|
||||
|
||||
ret = icc_provider_add(provider);
|
||||
if (ret) {
|
||||
dev_err(dev, "error adding interconnect provider: %d\n", ret);
|
||||
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
size_t j;
|
||||
|
||||
node = icc_node_create(qnodes[i]->id);
|
||||
if (IS_ERR(node)) {
|
||||
ret = PTR_ERR(node);
|
||||
goto err;
|
||||
}
|
||||
|
||||
node->name = qnodes[i]->name;
|
||||
node->data = qnodes[i];
|
||||
icc_node_add(node, provider);
|
||||
|
||||
for (j = 0; j < qnodes[i]->num_links; j++)
|
||||
icc_link_create(node, qnodes[i]->links[j]);
|
||||
|
||||
data->nodes[i] = node;
|
||||
}
|
||||
data->num_nodes = num_nodes;
|
||||
platform_set_drvdata(pdev, qp);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
icc_nodes_remove(provider);
|
||||
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
|
||||
icc_provider_del(provider);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qnoc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
|
||||
|
||||
icc_nodes_remove(&qp->provider);
|
||||
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
|
||||
return icc_provider_del(&qp->provider);
|
||||
}
|
||||
|
||||
static const struct of_device_id msm8998_noc_of_match[] = {
|
||||
{ .compatible = "qcom,msm8998-a1noc", .data = &msm8998_a1noc },
|
||||
{ .compatible = "qcom,msm8998-a2noc", .data = &msm8998_a2noc },
|
||||
{ .compatible = "qcom,msm8998-bimc", .data = &msm8998_bimc },
|
||||
{ .compatible = "qcom,msm8998-cnoc", .data = &msm8998_cnoc },
|
||||
{ .compatible = "qcom,msm8998-gnoc", .data = &msm8998_gnoc },
|
||||
{ .compatible = "qcom,msm8998-mnoc", .data = &msm8998_mnoc },
|
||||
{ .compatible = "qcom,msm8998-snoc", .data = &msm8998_snoc },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, msm8998_noc_of_match);
|
||||
|
||||
static struct platform_driver msm8998_noc_driver = {
|
||||
.probe = qnoc_probe,
|
||||
.remove = qnoc_remove,
|
||||
.driver = {
|
||||
.name = "qnoc-msm8998",
|
||||
.of_match_table = msm8998_noc_of_match,
|
||||
.sync_state = icc_sync_state,
|
||||
},
|
||||
};
|
||||
module_platform_driver(msm8998_noc_driver);
|
||||
MODULE_DESCRIPTION("Qualcomm msm8998 NoC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/adreno-smmu-priv.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/qcom_scm.h>
|
||||
|
||||
|
|
@ -12,6 +13,7 @@
|
|||
|
||||
struct qcom_smmu {
|
||||
struct arm_smmu_device smmu;
|
||||
DECLARE_BITMAP(reset_cb_nodisable_mask, ARM_SMMU_MAX_CBS);
|
||||
bool bypass_quirk;
|
||||
u8 bypass_cbndx;
|
||||
u32 stall_enabled;
|
||||
|
|
@ -180,11 +182,13 @@ static int qcom_adreno_smmu_alloc_context_bank(struct arm_smmu_domain *smmu_doma
|
|||
|
||||
static bool qcom_adreno_can_do_ttbr1(struct arm_smmu_device *smmu)
|
||||
{
|
||||
/*
|
||||
const struct device_node *np = smmu->dev->of_node;
|
||||
|
||||
if (of_device_is_compatible(np, "qcom,msm8996-smmu-v2"))
|
||||
if (of_device_is_compatible(np, "qcom,msm8996-smmu-v2") ||
|
||||
of_device_is_compatible(np, "qcom,msm8998-smmu-v2") ||
|
||||
of_device_is_compatible(np, "qcom,sdm630-smmu-v2"))
|
||||
return false;
|
||||
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -228,11 +232,13 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
|
|||
{ .compatible = "qcom,adreno" },
|
||||
{ .compatible = "qcom,mdp4" },
|
||||
{ .compatible = "qcom,mdss" },
|
||||
{ .compatible = "qcom,msm8998-mss-pil" },
|
||||
{ .compatible = "qcom,sc7180-mdss" },
|
||||
{ .compatible = "qcom,sc7180-mss-pil" },
|
||||
{ .compatible = "qcom,sc7280-mdss" },
|
||||
{ .compatible = "qcom,sc7280-mss-pil" },
|
||||
{ .compatible = "qcom,sc8180x-mdss" },
|
||||
{ .compatible = "qcom,sdm660-mss-pil" },
|
||||
{ .compatible = "qcom,sdm845-mdss" },
|
||||
{ .compatible = "qcom,sdm845-mss-pil" },
|
||||
{ }
|
||||
|
|
@ -267,7 +273,8 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
|
|||
reg = arm_smmu_gr0_read(smmu, last_s2cr);
|
||||
if (FIELD_GET(ARM_SMMU_S2CR_TYPE, reg) != S2CR_TYPE_BYPASS) {
|
||||
qsmmu->bypass_quirk = true;
|
||||
qsmmu->bypass_cbndx = smmu->num_context_banks - 1;
|
||||
if (qsmmu->bypass_cbndx == 0xff)
|
||||
qsmmu->bypass_cbndx = smmu->num_context_banks - 1;
|
||||
|
||||
set_bit(qsmmu->bypass_cbndx, smmu->context_map);
|
||||
|
||||
|
|
@ -359,8 +366,15 @@ static int qcom_sdm845_smmu500_reset(struct arm_smmu_device *smmu)
|
|||
static int qcom_smmu500_reset(struct arm_smmu_device *smmu)
|
||||
{
|
||||
const struct device_node *np = smmu->dev->of_node;
|
||||
struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
|
||||
|
||||
arm_mmu500_reset(smmu);
|
||||
/*
|
||||
* Execute the mmu-500 reset implementation detail only if there
|
||||
* are no secured untouchable contexts in this iommu, otherwise
|
||||
* the system will crash.
|
||||
*/
|
||||
if (bitmap_empty(qsmmu->reset_cb_nodisable_mask, ARM_SMMU_MAX_CBS))
|
||||
arm_mmu500_reset(smmu);
|
||||
|
||||
if (of_device_is_compatible(np, "qcom,sdm845-smmu-500"))
|
||||
return qcom_sdm845_smmu500_reset(smmu);
|
||||
|
|
@ -368,11 +382,20 @@ static int qcom_smmu500_reset(struct arm_smmu_device *smmu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool qcom_smmu500_reset_cb_nodisable(struct arm_smmu_device *smmu,
|
||||
int cbndx)
|
||||
{
|
||||
struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
|
||||
|
||||
return test_bit(cbndx, qsmmu->reset_cb_nodisable_mask);
|
||||
}
|
||||
|
||||
static const struct arm_smmu_impl qcom_smmu_impl = {
|
||||
.init_context = qcom_smmu_init_context,
|
||||
.cfg_probe = qcom_smmu_cfg_probe,
|
||||
.def_domain_type = qcom_smmu_def_domain_type,
|
||||
.reset = qcom_smmu500_reset,
|
||||
.reset_cb_nodisable = qcom_smmu500_reset_cb_nodisable,
|
||||
.write_s2cr = qcom_smmu_write_s2cr,
|
||||
};
|
||||
|
||||
|
|
@ -380,6 +403,7 @@ static const struct arm_smmu_impl qcom_adreno_smmu_impl = {
|
|||
.init_context = qcom_adreno_smmu_init_context,
|
||||
.def_domain_type = qcom_smmu_def_domain_type,
|
||||
.reset = qcom_smmu500_reset,
|
||||
.reset_cb_nodisable = qcom_smmu500_reset_cb_nodisable,
|
||||
.alloc_context_bank = qcom_adreno_smmu_alloc_context_bank,
|
||||
.write_sctlr = qcom_adreno_smmu_write_sctlr,
|
||||
};
|
||||
|
|
@ -387,7 +411,10 @@ static const struct arm_smmu_impl qcom_adreno_smmu_impl = {
|
|||
static struct arm_smmu_device *qcom_smmu_create(struct arm_smmu_device *smmu,
|
||||
const struct arm_smmu_impl *impl)
|
||||
{
|
||||
const struct device_node *np = smmu->dev->of_node;
|
||||
struct qcom_smmu *qsmmu;
|
||||
u8 reset_nodisable_cbs[ARM_SMMU_MAX_CBS];
|
||||
int i, sz;
|
||||
|
||||
/* Check to make sure qcom_scm has finished probing */
|
||||
if (!qcom_scm_is_available())
|
||||
|
|
@ -398,6 +425,34 @@ static struct arm_smmu_device *qcom_smmu_create(struct arm_smmu_device *smmu,
|
|||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
qsmmu->smmu.impl = impl;
|
||||
qsmmu->bypass_cbndx = 0xff;
|
||||
bitmap_zero(qsmmu->reset_cb_nodisable_mask, ARM_SMMU_MAX_CBS);
|
||||
|
||||
if (np != NULL) {
|
||||
/*
|
||||
* This property is optional and we expect to fail finding it if:
|
||||
* - Using the default bypass_cbndx (in the .cfg_probe cb) is fine; or
|
||||
* - We are booting on ACPI
|
||||
*/
|
||||
of_property_read_u8(np, "qcom,bypass-cbndx", &qsmmu->bypass_cbndx);
|
||||
|
||||
/*
|
||||
* Some context banks may not be disabled because they are
|
||||
* secured: read from DT a list of secured contexts that cannot
|
||||
* be disabled without crashing the system.
|
||||
* This list is optional, as not all firmware configurations do
|
||||
* require us skipping disablement of context banks.
|
||||
*/
|
||||
sz = of_property_read_variable_u8_array(np, "qcom,reset-nodisable-cbs",
|
||||
reset_nodisable_cbs,
|
||||
1, ARM_SMMU_MAX_CBS);
|
||||
if (sz > 0) {
|
||||
for (i = 0; i < sz; i++) {
|
||||
__set_bit(reset_nodisable_cbs[i],
|
||||
qsmmu->reset_cb_nodisable_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &qsmmu->smmu;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1622,6 +1622,16 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
|
|||
|
||||
/* Make sure all context banks are disabled and clear CB_FSR */
|
||||
for (i = 0; i < smmu->num_context_banks; ++i) {
|
||||
/*
|
||||
* Some context banks cannot be disabled due to hypervisor
|
||||
* configuration on some systems; if this is the case,
|
||||
* skip disabling and writing FAULT on the CB FSR in order
|
||||
* to avoid a system crash.
|
||||
*/
|
||||
if (smmu->impl && smmu->impl->reset_cb_nodisable &&
|
||||
smmu->impl->reset_cb_nodisable(smmu, i)) {
|
||||
continue;
|
||||
}
|
||||
arm_smmu_write_context_bank(smmu, i);
|
||||
arm_smmu_cb_write(smmu, i, ARM_SMMU_CB_FSR, ARM_SMMU_FSR_FAULT);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -430,6 +430,7 @@ struct arm_smmu_impl {
|
|||
u64 val);
|
||||
int (*cfg_probe)(struct arm_smmu_device *smmu);
|
||||
int (*reset)(struct arm_smmu_device *smmu);
|
||||
bool (*reset_cb_nodisable)(struct arm_smmu_device *smmu, int cbndx);
|
||||
int (*init_context)(struct arm_smmu_domain *smmu_domain,
|
||||
struct io_pgtable_cfg *cfg, struct device *dev);
|
||||
void (*tlb_sync)(struct arm_smmu_device *smmu, int page, int sync,
|
||||
|
|
|
|||
|
|
@ -869,6 +869,18 @@ source "drivers/leds/blink/Kconfig"
|
|||
comment "Flash and Torch LED drivers"
|
||||
source "drivers/leds/flash/Kconfig"
|
||||
|
||||
#comment "RGB LED drivers"
|
||||
#source "drivers/leds/rgb/Kconfig"
|
||||
|
||||
config LEDS_QCOM_LPG
|
||||
tristate "LED support for Qualcomm LPG"
|
||||
depends on LEDS_CLASS_MULTICOLOR
|
||||
depends on OF
|
||||
depends on SPMI
|
||||
help
|
||||
This option enables support for the Light Pulse Generator found in a
|
||||
wide variety of Qualcomm PMICs.
|
||||
|
||||
comment "LED Triggers"
|
||||
source "drivers/leds/trigger/Kconfig"
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,11 @@ obj-$(CONFIG_LEDS_USER) += uleds.o
|
|||
# Flash and Torch LED Drivers
|
||||
obj-$(CONFIG_LEDS_CLASS_FLASH) += flash/
|
||||
|
||||
# RGB LED Drivers
|
||||
# obj-$(CONFIG_LEDS_CLASS_MULTICOLOR) += rgb/
|
||||
|
||||
obj-$(CONFIG_LEDS_QCOM_LPG) += rgb/leds-qcom-lpg.o
|
||||
|
||||
# LED Triggers
|
||||
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
|
||||
|
||||
|
|
|
|||
1286
drivers/leds/rgb/leds-qcom-lpg.c
Normal file
1286
drivers/leds/rgb/leds-qcom-lpg.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -126,7 +126,8 @@ static int pattern_trig_start_pattern(struct led_classdev *led_cdev)
|
|||
|
||||
if (data->is_hw_pattern) {
|
||||
return led_cdev->pattern_set(led_cdev, data->patterns,
|
||||
data->npatterns, data->repeat);
|
||||
data->npatterns,
|
||||
data->last_repeat);
|
||||
}
|
||||
|
||||
/* At least 2 tuples for software pattern. */
|
||||
|
|
|
|||
|
|
@ -2032,6 +2032,18 @@ config MFD_WCD934X
|
|||
This driver provides common support WCD934x audio codec and its
|
||||
associated Pin Controller, Soundwire Controller and Audio codec.
|
||||
|
||||
config MFD_WCD9335
|
||||
tristate "Support for WCD9335 Codec"
|
||||
depends on SLIMBUS
|
||||
select REGMAP
|
||||
select REGMAP_SLIMBUS
|
||||
select REGMAP_IRQ
|
||||
select MFD_CORE
|
||||
help
|
||||
Support for the Qualcomm WCD9335 Codec.
|
||||
This driver provides common support WCD9335 audio codec and its
|
||||
associated Pin Controller, Soundwire Controller and Audio codec.
|
||||
|
||||
config MFD_ATC260X
|
||||
tristate
|
||||
select MFD_CORE
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ ifeq ($(CONFIG_MFD_CS47L24),y)
|
|||
arizona-objs += cs47l24-tables.o
|
||||
endif
|
||||
obj-$(CONFIG_MFD_WCD934X) += wcd934x.o
|
||||
obj-$(CONFIG_MFD_WCD9335) += wcd9335.o
|
||||
obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
|
||||
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
|
||||
wm831x-objs += wm831x-auxadc.o
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue