Compare commits

...
Sign in to create a new pull request.

129 commits

Author SHA1 Message Date
Dzmitry Sankouski
2b7263cccc fixup: pinctrl: Add driver for Awinic AW9523/B I2C GPIO Expander
This fixes 4a1528ea3c in 6.1 kernel.
Change remove function signature: return void.

Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
2023-02-05 21:34:21 +03:00
Dzmitry Sankouski
22da203ef8 arm64: dts: qcom: sagit: add reserved memory nodes and chassis type
This taken from upstream patch, and fixes wifi.
fix adsp size, slpi size, reorganize reserved memory nodes
2022-11-02 20:30:00 +03:00
Jami Kettunen
4f782f4c3f [WIP] arm64: msm8998-oneplus-common: fix node names for reserved mem 2022-10-31 02:05:05 +02:00
Jami Kettunen
d23c7879c3 msm8998-oneplus-common: Drop GPU down to 257 MHz for better stability 2022-10-31 02:03:17 +02:00
Jami Kettunen
ae7254d494 arm64: msm8998_defconfig: Add for 6.1
Based on allnoconfig msm8998.config pmos.config cleanup.config.
2022-10-31 02:03:17 +02:00
Jami Kettunen
38feeb3074 arm64: oneplus5_defconfig: Add for 6.1
Based on allnoconfig msm8998.config oneplus5.config pmos.config cleanup.config.
2022-10-31 02:03:17 +02:00
Dzmitry Sankouski
a8eef75016 arm64: dts: qcom: sagit: add initial device tree for sagit
New device support - Xiaomi Mi6 phone

Signed-off-by: Degdag Mohamed <degdagmohamed@gmail.com>
2022-10-31 02:03:17 +02:00
Konrad Dybcio
9479a999eb arm64: dts: qcom: msm8998*: Keep MMCC & MMSS_SMMU enabled by default
MMCC is a component of the SoC that should always be configured. It was kept
off due to misconfiguration on clamshell machines. Keep it disabled on these
ones and enable it by default on all the others.

Exactly the same story applies to MMSS_SMMU, which directly depends on MMCC.

Do note, that if a platform doesn't use neither EFIFB (only applies to WoA
devices in this case) or simplefb (applies to precisely 2 msm8998 devices
as of this commit), this will not cause any harm.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2022-10-31 02:03:17 +02:00
Konrad Dybcio
7b4df030bf arm64: dts: qcom: msm8998-yoshino: Fix up SMD regulators formatting
Add a new line between each subnode and make the { } consistent.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2022-10-31 02:03:17 +02:00
Jami Kettunen
48f3cc5f01 arm64: dts: msm8998-oneplus-common: enable SMB2 2022-10-31 02:03:17 +02:00
Jami Kettunen
a106139665 arm64: dts: qcom: msm8998-oneplus-common: enable RRADC 2022-10-31 02:03:17 +02:00
Jami Kettunen
007c711d46 arm64: dts: qcom: msm8998-oneplus-common: add simple-battery 2022-10-31 02:03:14 +02:00
Jami Kettunen
31fcc8d96d arm64: dts: qcom: msm8998-oneplus-common: Add fuel gauge
The OnePlus 5/5T feature a BQ27411 fuel gauge for reading the battery
stats.
2022-10-31 02:03:11 +02:00
Jami Kettunen
fa3def2129 [TEMP] oneplus5: disable all speaker amp stuff
We don't want to blow this up while messing around with audio stuff
early on...
2022-10-31 02:03:11 +02:00
Jami Kettunen
f2922a7943 arm64: dts: msm8998-oneplus-common: Add TFA9890 speaker amp bindings 2022-10-31 02:03:11 +02:00
Jami Kettunen
43f9c1b6df msm8998-oneplus-common: Configure Adreno 540 GPU 2022-10-31 02:03:07 +02:00
Jami Kettunen
705df38a9e arm64: dts: msm8998-oneplus-*: Configure S6E3FA5 & S6E3FC1 panels
These Samsung DSI panels are used on the OnePlus 5/5T respectively.
Additionally disable simplefb until a proper handoff solution can be
found to avoid conflicts between it and the MSM DRM driver.
2022-10-31 02:03:05 +02:00
Jami Kettunen
324c137044 msm8998-oneplus-common: Configure IPA for cellular data 2022-10-31 02:03:05 +02:00
Jami Kettunen
fbfe0bb714 msm8998-oneplus-common: Configure CPUfreq scaling hardware 2022-10-31 02:03:05 +02:00
Jami Kettunen
5c0b2f4545 arm64: dts: msm8998-oneplus-cheeseburger: Configure RMI4 F1A buttons
This allows the capacitive buttons below the touchscreen to be used on
e.g. Android normally :)
2022-10-31 02:03:04 +02:00
Jami Kettunen
3e22a6e8a3 msm8998-oneplus-common: Add remoteproc configuration & enable WLAN 2022-10-31 02:03:02 +02:00
Jami Kettunen
ab047e6597 [DROPME?] msm8998-oneplus-common: Configure blsp1_i2c5_sleep (TS) as no-pull 2022-10-31 02:03:02 +02:00
Jami Kettunen
53da3375c4 dt-bindings: display: panel: Document Samsung S6E3FC1 display panel 2022-10-31 02:02:59 +02:00
Jami Kettunen
246f4d6148 drm/panel: Add panel driver for Samsung S6E3FC1
The S6E3FC1 is 6" 1080x2160 MIPI DSI command mode AMOLED LCD display
found on OnePlus 5T (2017) smartphones.

The panel needs to be enabled from a device tree using the
"samsung,s6e3fc1" compatible.

This driver was generated using the following & includes some minor
cleanup (such as s/to_s6e3fc1/to_s6e3fc1_panel/g):
$ python3 lmdpdg.py dumpling.dtb -r vddio
2022-10-31 02:02:59 +02:00
Jami Kettunen
8b90216819 drm/panel: samsung-s6e3fa5: Implement .get_orientation callback
Other drivers supporting this were already changed as a part of the
following series: https://patchwork.freedesktop.org/series/104807/
2022-10-31 02:02:55 +02:00
Jami Kettunen
7cca9eb36d [SQUASHME?] drm/panel: s6e3fa5: Read panel orientation
The panel is mounted upside down on the OnePlus 5, so we need to handle
this in the driver.
2022-10-31 02:02:41 +02:00
Jami Kettunen
3ea414062d dt-bindings: display: panel: Document Samsung S6E3FA5 display panel 2022-10-31 02:02:37 +02:00
Jami Kettunen
73e0c82858 drm/panel: Add panel driver for Samsung S6E3FA5
The S6E3FA5 is 5.5" 1080x1920 MIPI DSI command mode AMOLED LCD display
found on OnePlus 5 (2017) smartphones.

The panel needs to be enabled from a device tree using the
"samsung,s6e3fa5" compatible.

This driver was generated using the following & includes some minor
cleanup (such as s/to_s6e3fa5/to_s6e3fa5_panel/g):
$ python3 lmdpdg.py cheeseburger.dtb -r vddio

Signed-off-by: Jami Kettunen <jami.kettunen@protonmail.com>
2022-10-31 02:02:37 +02:00
Jami Kettunen
39cd6b976d arm64: dts: qcom: msm8998-oneplus-common: Enable PMI8998 LPG leds
Now the RGB notification LEDs can each be controlled individually :)
2022-10-31 02:02:34 +02:00
Jami Kettunen
b408f19a4f arm64: dts: qcom: msm8998-oneplus-common: Enable PMI8998 haptics
The OnePlus 5 and 5T both have a haptics engine connected to PMI8998.

Signed-off-by: Jami Kettunen <jami.kettunen@somainline.org>
Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2022-10-31 02:02:34 +02:00
Jami Kettunen
35d1ed29cc [ANNOTATION] Apply some F(x)tec Pro1 patches 2022-10-31 02:02:34 +02:00
Danct12
158d9831bf arm64: dts: msm8998-fxtec-pro1: Add remoteproc configuration 2022-10-31 02:02:34 +02:00
Danct12
8535dcd7c2 arm64: dts: msm8998-fxtec-pro1: Enable PMI8998 haptics 2022-10-31 02:02:33 +02:00
Danct12
fdd5838e2b arm64: dts: msm8998-fxtec-pro1: Configure PMI8998 fuel gauge
This will account for battery statistics reporting on the Fxtec Pro1 (QX1000)
2022-10-31 02:02:33 +02:00
Jami Kettunen
b5da4afe50 pinctrl: Fix compilation of Awinic AW9523/B I2C GPIO Expander
Fixes the following link-time error:

    LD      .tmp_vmlinux.kallsyms1
  aarch64-linux-gnu-ld: Unexpected GOT/PLT entries detected!
  aarch64-linux-gnu-ld: Unexpected run-time procedure linkages detected!
  aarch64-linux-gnu-ld: drivers/pinctrl/pinctrl-aw9523.o: in function `aw9523_probe':
  .../drivers/pinctrl/pinctrl-aw9523.c:1004: undefined reference to `__devm_regmap_init_i2c'
  make[1]: *** [.../Makefile:1155: vmlinux] Error 1

Fixes: 96e86abbb4 ("pinctrl: Add driver for Awinic AW9523/B I2C GPIO Expander")
2022-10-31 02:02:33 +02:00
Jami Kettunen
bca8458787 [HACK] pinctrl: aw9523: Add workaround for F(x)tec Pro1 keyboard
This is a hack because the correct interrupt type(s) should should be
defined in msm8998-fxtec-pro1.dts instead of the driver.

(originally from Danct12)

This is a workaround for keyboard not working on Fxtec Pro1.

  genirq: Setting trigger mode 12 for irq 123 failed (aw9523_gpio_irq_type+0x0/0x20)
  gpio-fastmatrix-keyboard gpio-keyboard: Cannot get IRQ for gpio302
2022-10-31 02:02:33 +02:00
Jami Kettunen
c974cc82e4 [ANNOTATION] Apply miscellaneous hacks and patches 2022-10-31 02:02:33 +02:00
Jami Kettunen
37d1583665 [HACK] drm/msm: Always report CTL status as started for MSM8998
This register always appears to read 0 on <SDM845 generations so simply
ignore it to avoid refreshing at ~3 Hz as seen on OnePlus 5 with a
command-mode panel with the following spammed in dmesg every time the
screen refreshes:

  [drm:_dpu_encoder_phys_cmd_wait_for_ctl_start:660] [dpu error]enc31 intf1 ctl start interrupt wait failed
  [drm:dpu_kms_wait_for_commit_done:525] [dpu error]wait for commit done returned -22
  ...
2022-10-31 02:02:33 +02:00
Jami Kettunen
5cdf191d57 module: demote invalid ELF header magic error message to pr_debug
This happens anytime busybox modprobe loads a compressed module and
looks especially ugly on postmarketOS for example (or basically any
initramfs); this error is rather pointless since the module is loaded
anyway afterwards.

Upstream (busybox) has no plans to do anything about this error getting
spammed:
https://www.mail-archive.com/busybox@busybox.net/msg27078.html
2022-10-31 02:02:33 +02:00
Jami Kettunen
b7e8630c76 Input: synaptics-rmi4 - add support for F1A
RMI4 F1A supports the simple capacitive buttons function, it's used for
example on embedded devices such as smartphones for capacitive Android
back and recents buttons.
2022-10-31 02:02:30 +02:00
Jami Kettunen
37df9e8b9c arm64: dts: qcom: msm8998: add IPA information
Add support for the MSM8998 SoC, which includes IPA version 3.1.
2022-10-31 02:02:30 +02:00
Jami Kettunen
f639e1729f [HACK] net: ipa: Disable automatic suspend
1aac309d32 ("net: ipa: use autosuspend") currently causes my device to
enter 900E crashdump mode as soon as IPA is probed :/

With this we at least can run ModemManager once again...
2022-10-31 02:02:30 +02:00
Jami Kettunen
019ec6d0a5 [HACK] ath10k: Fake MSA ready event after event server arrival
This finally allowed me to get past the 2 ath10k_info()'s in qmi.c!

However, this doesn't fix everything; it seems you *have* to run
diag-router from https://github.com/andersson/diag to calm the firmware
down and stop constantly crashing; need to look into a way to get Wi-Fi
working later without needing this debug crap to be running.

This should possible be submitted as a quirk to the ath10k driver as
modem on mainline 8998 should be running now as well...
2022-10-31 02:02:25 +02:00
Jami Kettunen
46f0bbbca4 drm/msm: add missing a540 MODULE_FIRMWARE declarations 2022-10-31 02:02:19 +02:00
Jami Kettunen
4d927cb2d9 drm/msm: Mention DSI 10nm PHY support for MSM8998 2022-10-31 02:02:15 +02:00
Jami Kettunen
72ffd69b45 [HACK] scripts: Stop appending "+" to localversion
This always gets added and doesn't look nice in the version string, so
it's purely for aesthetic reasons :p
2022-10-31 02:02:15 +02:00
Caleb Connolly
dae71dc9a5 arm64: dts: qcom: pmi8998: add charger node
Add a node for the smb2 charger hardware found on the pmi8998.

Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
2022-10-31 02:02:14 +02:00
Caleb Connolly
119430dc18 arm64: dts: qcom: pmi8998: add rradc node
Add a DT node for the Round Robin ADC found in the PMI8998 PMIC.

Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
2022-10-31 02:02:14 +02:00
Caleb Connolly
e2c631ebcf arm64: dts: qcom: pmi8998: introduce spmi haptics
Add bindings for Qualcomm SPMI haptics on platforms using pmi8998.

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
(JAMI: fixup for v6.0-rc2 & v7 of driver patches)
2022-10-31 02:02:14 +02:00
Jami Kettunen
4b341bc463 [ANNOTATION] Import WIP "Qualcomm SPMI Fuel Gauge" driver
https://gitlab.com/sdm845-mainline/linux/-/commits/driver/pmi8998_fg/
+ drop pmi8994 DTS changes though.
+ random pieces from https://gitlab.com/sdm845-mainline/linux/-/commits/sdm845/5.19-release :/
2022-10-31 02:02:14 +02:00
Jami Kettunen
1918745f5f power: supply: qcom_fg: Report online property 2022-10-31 02:02:14 +02:00
Yassine Oudjana
f96cfaff29 power: pmi8998_fg: Rename to qcom_fg and add support for PMI8994/6
This adds support for accessing SRAM. That includes requesting and releasing
access to SRAM by setting some registers and handling the mem-avail IRQ,
configuring access, and reading from/writing to it.

Pre-gen3 fuel gauges require reading from SRAM to get voltage, current
and temperature data. Getting capacity is identical to gen3.

Tested on Xiaomi Mi Note 2 with PMI8996.
2022-10-31 02:02:14 +02:00
Yassine Oudjana
cf062a5c35 power: pmi8998_fg: Remove some trailing spaces and tabs
This should be squashed.
2022-10-31 02:02:14 +02:00
Joel Selvaraj
6ab2aa8358 fg: clean and read charge full and max voltage from dts 2022-10-31 02:02:14 +02:00
Joel Selvaraj
e5f8763d74 power: supply: add battery charging status feature 2022-10-31 02:02:14 +02:00
Caleb Connolly
7214b14a7b arm64: dts: qcom: pmi8998: Add fuel gauge
Add a node for qcom,pmi8998-fg.
2022-10-31 02:02:14 +02:00
Joel Selvaraj
f74131008a power: supply: introduce pmi8998 fuel guage driver 2022-10-31 02:02:14 +02:00
Jami Kettunen
aadef46ad8 [ANNOTATION] Import Qualcomm smb2 charger driver v6 (2022-10-09)
Link: https://patchwork.kernel.org/project/linux-arm-msm/cover/20221008183753.249514-1-caleb.connolly@linaro.org/
2022-10-31 02:02:14 +02:00
Caleb Connolly
ea0538d030 dt-bindings: power: supply: qcom,pmi8998-charger: add bindings for smb2 driver
Add devicetree bindings for the Qualcomm PMI8998/PM660 SMB2 charger
driver.

Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
2022-10-31 02:02:14 +02:00
Caleb Connolly
15864e39c0 power: supply: add Qualcomm PMI8998 SMB2 Charger driver
Add a driver for the SMB2 charger block found in the Qualcomm PMI8998
and PM660.
This driver adds initial support for detecting USB cables and managing
basic battery charging.

Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
2022-10-31 02:02:14 +02:00
Jami Kettunen
e5788ea5dd [ANNOTATION] Import SPMI haptics driver v7 (2022-10-18)
Link: https://patchwork.kernel.org/project/linux-arm-msm/cover/20221015172915.1436236-1-caleb@connolly.tech/
2022-10-31 02:02:14 +02:00
Caleb Connolly
80b7e7d1a0 input: add Qualcomm SPMI haptics driver
Add support for the haptics found in pmi8998 and related PMICs.
Based on the ff-memless interface. Currently this driver provides
a partial implementation of hardware features.

This driver only supports LRAs (Linear Resonant Actuators) in the "buffer"
mode with a single wave pattern.

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2022-10-31 02:02:14 +02:00
Caleb Connolly
cd56ff1567 dt-bindings: input: document Qualcomm PMI8998 haptics driver
Add bindings for qcom PMIC PMI8998 haptics driver.

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
2022-10-31 02:02:14 +02:00
Jami Kettunen
6a627ac6b7 [ANNOTATION] Base @ angelo/5.14-msm8998-audio-working
I also rebased this tree on the linus/v5.18-rc1 tag and while at it
finally dropped changes irrelevant to msm8998.
2022-10-31 02:02:13 +02:00
AngeloGioacchino Del Regno
b1953b7b81 adreno 5xx: TTBR1 extravaganza on MSM8998
(JAMI: fixup for 5.16)
2022-10-31 02:02:13 +02:00
Jami Kettunen
2c83fb4bc9 arm64: dts: qcom: msm8998-xperia: various tests
Originally from: c215a022
2022-10-31 02:02:13 +02:00
Jami Kettunen
a3e55d753a ASoC: wcd9335: various tests
Originally from: c215a022
2022-10-31 02:02:13 +02:00
AngeloGioacchino Del Regno
8720300aa3 iommu/arm-smmu-qcom: Add MSM8998 and SDM660 mss compatibles for identity
Add MSM8998 and SDM660's mss-pil compatibles to switch the default
iommu domain type to IDENTITY, as similarly required by SDM845 and
others.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixup for 6.0-rc2)
2022-10-31 02:02:13 +02:00
AngeloGioacchino Del Regno
1d7018b903 iommu/arm-smmu-qcom: Skip the TTBR1 quirk for MSM8998 and SDM630
Similarly to MSM8996 DragonBoard 820c, MSM8998 and SDM630 are equipped
with Adreno 5xx series, which doesn't have separate pagetables support
at the moment of writing.
Skip the TTBR1 quirk for these two SoCs as to get Adreno in a usable
state.
2022-10-31 02:02:13 +02:00
AngeloGioacchino Del Regno
f2e1fd09d4 arm64: dts: qcom: AUDIO WORKS oon MSM8998 Sony Yoshino platform!!! 2022-10-31 02:02:13 +02:00
AngeloGioacchino Del Regno
e0bb18b783 ASoC: codecs: wcd9335: Fix headphone jack commit for new upstream kernel 2022-10-31 02:02:13 +02:00
Srinivas Kandagatla
c97a787623 ASoC: wcd9335: add mbhc support
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
2022-10-31 02:02:13 +02:00
Jami Kettunen
6944fd8b93 arm64: dts: qcom: Enable audio on MSM8998 Sony Yoshino platform
Originally from: d95b982a
(JAMI: fixup for 6.0-rc2)
2022-10-31 02:02:13 +02:00
Jami Kettunen
df09ff004c arm64: dts: qcom: msm8998: More audio related node changes
Originally from: d95b982a
2022-10-31 02:02:13 +02:00
Jami Kettunen
88f9d846d6 [DROPME?] fixup! arm64: dts: qcom: msm8998: Configure Adreno GPU and related IOMMU 2022-10-31 02:02:08 +02:00
Jami Kettunen
83b748720a mfd: wcd9335: Add support to wcd9335 codec
Qualcomm WCD9335 Codec is a standalone Hi-Fi audio codec IC.

This codec has integrated SoundWire controller, pin controller and
interrupt controller.

Originally from: d95b982a
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
a92cc30ae8 arm64: dts: qcom: msm8998: Add disabled slimbus support
Add generic slimbus configuration to MSM8998 and keep it disabled.
It is expected that this will be enabled in board-specific device
trees when supported, along with the right audio codec.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:33 +02:00
Jami Kettunen
ad7c17af90 ASoC: qcom: lpass-msm8998: Add platform driver for lpass audio
Add platform driver for configuring msm8998 lpass core I2S and
DMA configuration to support playback & capture to external codecs
connected over primary & secondary MI2S interfaces.

(driver originally split from 4d7e1ead3b ("fastmatrix yaml fix"))
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
5be5c146c2 ASoC: qcom: Add MSM8998 sound card support
Add MSM8998 sound support: this driver supports basic functionality
and headphone jack.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixup for 5.17 & 6.0-rc2)
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
08f802d982 arm64: dts: qcom: msm8998-xperia: Enable lpass smmu
To support audio dsp functionality, enable the lpass smmu.
The firmware distributed with the MSM8998 Sony Xperia smartphones
requires us to skip resetting CB12 of this SMMU and to use CB11
as a context bank to emulate bypass streams.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixed up for v5.16-rc1)
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
b32ea4a02e arm64: dts: qcom: msm8998: Add APR services configuration
Add the standard APR Q6 services configuration for MSM8998, used by
boards supporting the audio dsp.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
327e8d1483 arm64: dts: qcom: msm8998: Define fastrpc ADSP compute context banks
If the target board supports ADSP, it is essential to have fastrpc
compute context banks defined. This commit adds the always usable
unsecured context banks only.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
d5b12139e6 arm64: dts: qcom: msm8998: Add disabled support for lpass iommu for q6
Add support for the LPASS (Q6) SMMU and keep it disabled as this is
used only when the audio DSP is present and used, which is not
mandatory to have.
It is expected for board-specific device-trees to enable this node
if supported.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
f2386073b9 clk: qcom: gcc-msm8998: Add LPASS adsp and core GDSCs
As a final step to entirely enable the required clock tree for the
lpass iommu and audio dsp, add the lpass core/adsp GDSCs.

As a side note, it was found out that disabling the lpass core GDSC
at any time would cause a system lockup (and reboot): disabling
this GDSC will leave the lpass iommu completely unclocked, losing
its state entirely - including the secure contexts that have been
previously set-up from the bootloader/TrustZone.
Losing this IOMMU configuration will trigger a hypervisor fault,
which will reboot the system; the only workaround for this issue
is to declare the lpass core gdsc as always-on.

It should also not be forgotten that this is all about firmware and
there may be a version of it that doesn't enable this GDSC at all
before booting Linux, which is the reason why this specific declaration
wasn't simply omitted.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
03cf81d3a0 dt-bindings: clock: gcc-msm8998: Add LPASS adsp/core GDSCs definitions
Add the GDSC definitions for the LPASS_ADSP_GDSC and LPASS_CORE_GDSC
as a final step to enable the required clock tree for the lpass iommu
and for the audio dsp itself.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
190a5aaae0 clk: qcom: gcc-msm8998: Add q6 bimc and lpass core, adsp SMMU clocks
Add the Q6 BIMC, LPASS core/adsp SMMU clocks to support audio related
functionality on MSM8998 and APQ variants. Please note that the Q6 and
the lpass iommu also need GDSCs to be enabled in order to initialize,
which are going to be added in a later commit.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixup for 6.0-rc2)
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
051c715c75 dt-bindings: clock: gcc-msm8998: Add Q6 and LPASS clocks definitions
Add definitions for the Q6 BIMC, LPASS core and adsp smmu clocks,
required to enable audio functionality on MSM8998.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: merge with e122a6a4 for 5.17 & fixup for 6.0-rc1)
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
695a65ac50 arm64: dts: qcom: msm8998: Add imem pil-reloc-info for firmware loading
Firmware loading (mainly the modem) may require IMEM PIL relocation
informations: specify this imem region in dt for qcom_pil_info to
use it.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
0eec71b3b3 arm64: dts: qcom: msm8998: Add qcom,adreno-smmu compatible 2022-10-31 01:55:33 +02:00
Jami Kettunen
4dbc2501ff regulator: qcom-labibb: Always disable interrupts during OCP & SC
Originally from: cd95ecae
2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
2633780796 yoshino: Fix too high overheating backlight, enable all wled strings maple 2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
707f3fc86f drm/msm/dsi_phy_10nm: Fix bad VCO rate calculation 2022-10-31 01:55:33 +02:00
AngeloGioacchino Del Regno
878adc3107 clk: qcom: mmcc-msm8998: Set CLK_GET_RATE_NOCACHE to pixel/byte clks
The pixel and byte clocks rate should not be cached, as a VCO shutdown
may clear the frequency setup and this may not be set again due to the
cached rate being present.
This will also be useful when shadow clocks will be implemented in
the DSI PLL for seamless timing/resolution switch.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
59798e0590 clk: qcom: gcc-msm8998: Set MISC flags, mark hmss/gpu-ahb critical
It is being evaluated whether this commit is really needed.
DONOTUPSTREAM.

(JAMI: fixed up for v5.16-rc1)
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
0dbc76cebe input: keyboard: Add Fast GPIO-driven keyboard/keypad matrix driver
This driver is a reimplementation of matrix_keyboard, on which it
is heavily based: the former was made back in 2009 and then
lightly updated in 2012 to add some support for device-tree / OF.

It turns out that this is not enough, nor OF is fully supported,
as the global (or "clustered") interrupt is never probed, nor it
made usage of the GPIOD API which, nowadays, really simplifies
the job - but not only: it also provides means to set GPIO arrays
for controllers that are supporting this.
The latter is very important when dealing with slow GPIOs such as
I2C and/or SPI expanders (and, again, not only); by using the new
APIs everything fits the new systems, from simplifications of the
probe/remove functions to opening possibility of using expanders
to drive key matrices with or without protection diodes.

But then, why wasn't the old matrix_keyboard driver modified
instead of creating a new one?
The problem there is that the old driver is made to support the
old platform_device style and it's currently still being used by
some PXA boards that are not (yet?) ported to device-tree, so it
would be impossible to modernize it for good, which means that to
support GPIOD (which is - really - required for the aforementioned
reasons) and to fully support DT it would be necessary to wrap the
old GPIO API around the new GPIOD one, creating overhead and also
probably unnecessary memory usage, other than a very big driver
which, at least on embedded devices (having limited resources),
would be simply bad. Leaving the fact that I haven't got any old
board so it's impossible for me to analyze and optimize for them.

Since 98% of the users of the old driver are infact platforms that
have been ported to (or are born with) DT, the introduction of a
new driver that's purely made for them seemed to be the best
choice, also because the expectations are (I think) that all of
the old ARM-based boards will be ported to DT anyway, which will
actually deprecate the good old matrix_keyboard driver.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
f9a159ad15 dt-bindings: input: Add binding for gpio-fastmatrix-keyboard
Add documentation for the gpio-fastmatrix-keyboard driver.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: merge with e7aa905a for 5.17)
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
b540916109 dt-bindings: pinctrl: Add bindings for Awinic AW9523/AW9523B
Add bindings for the Awinic AW9523/AW9523B I2C GPIO Expander driver.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
3809f25c85 pinctrl: Add driver for Awinic AW9523/B I2C GPIO Expander
The Awinic AW9523(B) is a multi-function I2C gpio expander in a
TQFN-24L package, featuring PWM (max 37mA per pin, or total max
power 3.2Watts) for LED driving capability.

It has two ports with 8 pins per port (for a total of 16 pins),
configurable as either PWM with 1/256 stepping or GPIO input/output,
1.8V logic input; each GPIO can be configured as input or output
independently from each other.

This IC also has an internal interrupt controller, which is capable
of generating an interrupt for each GPIO, depending on the
configuration, and will raise an interrupt on the INTN pin to
advertise this to an external interrupt controller.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:32 +02:00
Jami Kettunen
90a10c9650 interconnect: msm8998: Ignore return value of icc_provider_del() in .remove()
A similar fix for sm8450 was done in fa80a2994d, fixes compilation on
v6.1-rc1.
2022-10-31 01:55:32 +02:00
Caleb Connolly
b76ed0ff8e interconnect: qcom: msm8998: fix a typo'd QNODE
Fixes a WARN generated by referencing the same node id multiple times
2022-10-31 01:55:32 +02:00
Konrad Dybcio
0b2c00208c interconnect: qcom: Add MSM8998 interconnect provider driver
Introduce a driver for the Qualcomm interconnect busses found in
the MSM/APQ8998 SoCs.
The topology consists of several NoCs that are controlled by a
remote processor that collects the aggregated bandwidth for each
master-slave pairs.

On a note, these chips are managing the "bus QoS" in a "hybrid"
fashion: some of the paths in the topology are managed through
and by, of course) the RPM uC, while some others are "AP Owned",
meaning that the AP shall do direct writes to the appropriate
QoS registers for the specific paths and ports, instead of sending
an indication to the RPM and leaving the job to that one.

Co-authored-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixup for 5.17)
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
0b98021c39 dt-bindings: interconnect: Add bindings for Qualcomm MSM8998 NoC
Add the bindings for the Qualcomm MSM8998 NoC interconnects.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
e3dd005322 dt-bindings: i2c: qcom,i2c-qup: Document noise rejection properties
Document the new noise rejection properties "qcom,noise-reject-sda"
and "qcom,noise-reject-scl".

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
0615adf07d i2c: qup: Introduce SCL/SDA noise rejection
Some I2C devices may be glitchy due to electrical noise coming
from the device itself or because of possible board design issues.
To overcome this issue, the QUP's I2C in Qualcomm SoCs supports
a noise rejection setting for both SCL and SDA lines.

Introduce a setting for noise rejection through device properties,
"qcom,noise-reject-sda" and "qcom,noise-reject-scl", which will
be used to set the level of noise rejection sensitivity.
If the properties are not specified, noise rejection will not be
enabled.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
da725ffc9e arm64: dts: msm8998: Add SAW, CPRh and CPUFREQ to enable CPU scaling
Add the SAW (SPM), CPR-Hardened, CPUFREQ-HW nodes and relative OPP
tables (and also assign them to the CPU nodes, as required) in order
to enable CPU scaling on the MSM8998 SoC.

The CPR-Hardened and CPUFREQ-HW nodes are disabled by default as to
not change the previous default behavior. Since the drivers are not
yet accounting for speed-binning, these OPPs are referred to the
most common binning for this chip, which I have found on six phones
from Sony and one from FxTec (silver bin0, perf bin2).

At least until speed-binning gets done in the cpufreq-hw and CPR
drivers, users should enable CPR-Hardened and CPUFREQ in their own
board DT.
This is done like that because these drivers are really big, so the
idea is to keep the "base" version easier (but perfectly working),
before adding speed-binning "complications", which may... or may not
be necessary.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
[Fixed up for 5.18 & 6.0-rc2 by Jami]
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
75b6187a2b arm64: dts: msm8998: Wire up interconnects to MDP and GPU
Wire up the interconnects to both the MDP and the Adreno GPU in
order to get the right balance between performance and power
consumption of both devices.
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
4f3aac8982 arm64: dts: qcom: Enable panel etc. on MSM8998 F(x)tec Pro1 QX1000
(JAMI: fixup for 5.16 & 6.0-rc2)
2022-10-31 01:55:32 +02:00
Konrad Dybcio
5633d34633 arm64: dts: qcom: pm8998: Add VREF_1P25 and REF_GND VADC channels
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2022-10-31 01:55:32 +02:00
AngeloGioacchino Del Regno
62b32a6973 arm64: dts: msm8998: Wire up interconnects and OPPs to sdhci port 2
Wire up the OPP table and interconnects to the SDHCI port 2 to
improve performance and power consumption.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
ad14529669 arm64: dts: msm8998: Add interconnect nodes
This SoC features Network-on-Chip (NoC) and Bus Integrated Memory
Controller (BIMC) interconnects: add the required nodes now that
the driver is present.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
7c3825a968 arm64: dts: msm8998: Add disabled configuration for DPU1/DSI
This SoC supports both the MDP5 and DPU1 drivers, but the
latter was chosen as it's more feature-complete;

Configure the DPU1, DSI and related phy and pll in order to
achieve display functionality and keep it disabled.
Enabling it will be done on board specific DT when needed,
as not all boards have a usable display attached to them.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
c48720e33d arm64: dts: qcom: Enable panel etc. on MSM8998 Sony Yoshino platform
(JAMI: fixup for 5.16 & 6.0-rc2)
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
d9a01e884d dt-bindings: soc: qcom: cpr3: Add bindings for CPR3 driver
Add the bindings for the CPR3 driver to the documentation.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Reviewed-by: Rob Herring <robh@kernel.org>
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
8d333acb7b MAINTAINERS: Add entry for Qualcomm CPRv3/v4/Hardened driver
Add maintainers entry for the Qualcomm CPR3/CPR4/CPRh driver.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
9b789ad11d soc: qcom: Add support for Core Power Reduction v3, v4 and Hardened
This commit introduces a new driver, based on the one for cpr v1,
to enable support for the newer Qualcomm Core Power Reduction
hardware, known downstream as CPR3, CPR4 and CPRh, and support
for MSM8998 and SDM630 CPU power reduction.

In these new versions of the hardware, support for various new
features was introduced, including voltage reduction for the GPU,
security hardening and a new way of controlling CPU DVFS,
consisting in internal communication between microcontrollers,
specifically the CPR-Hardened and the Operating State Manager.

The CPR v3, v4 and CPRh are present in a broad range of SoCs,
from the mid-range to the high end ones including, but not limited
to, MSM8953/8996/8998, SDM630/636/660/845.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
b56256fdb4 arm64: qcom: qcs404: Change CPR nvmem-names
The CPR driver's common functions were split and put in another
file in order to support newer CPR revisions: to simplify the
commonization, the expected names of the fuses had to be changed
in order for both new and old support to use the same fuse name
retrieval function and keeping the naming consistent.

The thread id was added to the fuse name and, since CPRv1 does
not support threads, it is expected to always read ID 0, which
means that the expected name here is now "cpr0_(fuse_name)"
instead of "cpr_(fuse_name)": luckily, QCS404 is the only user
so change it accordingly.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
b50e0add79 soc: qcom: cpr: Move common functions to new file
In preparation for implementing a new driver that will be handling
CPRv3, CPRv4 and CPR-Hardened, format out common functions to a new
file.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>

(JAMI: fixup for 5.15 & 5.17)
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
85a644a841 dt-bindings: cpufreq: qcom-hw: Make reg-names a required property
The property reg-names is required after the addition of the OSM
programming sequence, as that mandates specifying different register
domains; to avoid confusion and improve devicetree readability,
specifying the regions names was made mandatory.
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
c53501d155 dt-bindings: cpufreq: qcom-hw: Add bindings for 8998
The OSM programming addition has been done under the
qcom,cpufreq-hw-8998 compatible name: specify the requirement
of two additional register spaces for this functionality.
This implementation, with the same compatible, has been
tested on MSM8998 and SDM630.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
[Fixed up for 5.18 by Jami]
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
b1305a65ab cpufreq: qcom-hw: Allow getting the maximum transition latency for OPPs
In order to fine-tune the frequency scaling from various governors,
allow to set a maximum transition latency from OPPs, which may be
different depending on the SoC.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
[Fixup for 5.18 by Jami]
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
1c85136168 cpufreq: qcom-hw: Implement CPRh aware OSM programming
On new SoCs (SDM845 onwards) the Operating State Manager (OSM) is
being programmed in the bootloader and write-protected by the
hypervisor, leaving to the OS read-only access to some of its
registers (in order to read the Lookup Tables and also some
status registers) and write access to the p-state register, for
for the OS to request a specific performance state to trigger a
DVFS switch on the CPU through the OSM hardware.

On old SoCs though (MSM8998, SDM630/660 and variants), the
bootloader will *not* initialize the OSM (and the CPRh, as it
is a requirement for it) before booting the OS, making any
request to trigger a performance state change ineffective, as
the hardware doesn't have any Lookup Table, nor is storing any
parameter to trigger a DVFS switch. In this case, basically all
of the OSM registers are *not* write protected for the OS, even
though some are - but write access is granted through SCM calls.

This commit introduces support for OSM programming, which has to
be done on these old SoCs that were distributed (almost?) always
with a bootloader that does not do any CPRh nor OSM init before
booting the kernel.
In order to program the OSM on these SoCs, it is necessary to
fullfill a "special" requirement: the Core Power Reduction
Hardened (CPRh) hardware block must be initialized, as the OSM
is "talking" to it in order to perform the Voltage part of DVFS;
here, we are calling initialization of this through Linux generic
power domains, specifically by requesting a genpd attach from the
qcom-cpufreq-hw driver, which will give back voltages associated
to each CPU frequency that has been declared in the OPPs, scaled
and interpolated with the previous one, and will also give us
parameters for the Array Power Mux (APM) and mem-acc, in order
for this driver to be then able to generate the Lookup Tables
that will be finally programmed to the OSM hardware.

After writing the parameters to the OSM and enabling it, all the
programming work will never happen anymore until a OS reboot, so
all of the allocations and "the rest" will be disposed-of: this
is done mainly to leave the code that was referred only to the
new SoCs intact, as to also emphasize on the fact that the OSM
HW is, in the end, the exact same; apart some register offsets
that are slightly different, the entire logic is the same.

This also adds the parameters to support CPU scaling on SDM630
and MSM8998.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
[Fixup for 5.18 & 6.0-rc1 by Jami]
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
67e553ce4b cpufreq: qcom-hw: Add kerneldoc to some functions
Some functions may not be very straightforward to understand:
add kerneldoc to some ones in order to improve readability.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:31 +02:00
Manivannan Sadhasivam
00f981b1fa dt-bindings: arm: cpus: Document 'qcom,freq-domain' property
Add devicetree documentation for 'qcom,freq-domain' property specific
to Qualcomm CPUs. This property is used to reference the CPUFREQ node
along with Domain ID (0/1).

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
2970b7e726 cpufreq: Add MSM8998 to cpufreq-dt-platdev blocklist
Add the MSM8998 to the blocklist since the CPU scaling is handled
out of this.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:31 +02:00
AngeloGioacchino Del Regno
1cfedf9384 iommu/arm-smmu-qcom: Don't modify sACR on hypervisor secured iommus
Avoid modifying the contents of the secure Auxiliary Control Register
on some Qualcomm SoCs: due to a hypervisor configuration on some
firmware versions, this would result in a system crash.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:30 +02:00
AngeloGioacchino Del Regno
fb0b12c66d iommu/arm-smmu-qcom: Avoid disabling secured context banks
Some Qualcomm SoCs' TZ/hypervisor configuration is disallowing the
disablement of some context banks, being them used for tzapps and/or
remote processors; any attempt to disable such CBs will result in
triggering a fault and the system will freeze and/or reset.

For this reason, get a list of context banks that should never get
disabled during smmu initialization through a DT array property
`qcom,reset-nodisable-cbs`.
It was chosen to not hardcode the CBs as this is dependant on the
SoC's firmware, which may vary on different boards.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixup for v6.0-rc1)
2022-10-31 01:55:30 +02:00
AngeloGioacchino Del Regno
047a452f3f iommu/arm-smmu: Allow skipping context bank disable at reset time
On some SoCs some IOMMU context banks are actively used from TZ
during system boot, or some hypervisor configurations will trigger
a system reset upon disabling some protected/secured CBs.

Allow skipping the disablement of such contexts at IOMMU reset time
during initialization with a new implementation detail to work around
this quirk.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-10-31 01:55:30 +02:00
AngeloGioacchino Del Regno
1a7ce19c97 iommu/arm-smmu-qcom: Allow choosing a custom bypass emulation context
It cannot be taken for granted that the last IOMMU context is free
and available for us to use it to emulate bypass streams and, at least
on MSM8998's lpass iommu, using the last one will produce a crash;
please note that this may not be only dependant on the SoC, but also
on the firmware version.

To overcome to this issue, allow specifying a different context for
bypass emulation with the optional DT property "qcom,bypass-cbndx":
if this property is not found this means that we are either booting
with ACPI instead or that we don't want to specify a custom cb because
the default one (the last context bank) is fine.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixup for v6.0-rc1)
2022-10-31 01:55:30 +02:00
Marijn Suijten
2f64669614 leds: ledtrig-pattern: Use last_repeat when applying hw pattern
`last_repeat` holds the actual value requested by the user whereas
`repeat` is a software iteration variable that is unused in hardware
patterns.

Furthermore `last_repeat` is the field returned to the user when reading
the `repeat` sysfs property.  This field is initialized to `-1` which is
- together with `1` - the only valid value in the upcoming Qualcomm LPG
driver.  It is thus unexpected when `repeat` with an initialization
value of `0` is passed into the the driver, when the sysfs property
clearly presents a value of `-1`.

Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org>
2022-10-31 01:55:30 +02:00
94 changed files with 18996 additions and 524 deletions

View file

@ -319,6 +319,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: |

View file

@ -18,6 +18,10 @@ description: |
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
@ -29,19 +33,9 @@ properties:
- qcom,sm8250-cpufreq-epss
- const: qcom,cpufreq-epss
reg:
minItems: 2
items:
- description: Frequency domain 0 register region
- description: Frequency domain 1 register region
- description: Frequency domain 2 register region
reg: {}
reg-names:
minItems: 2
items:
- const: freq-domain0
- const: freq-domain1
- const: freq-domain2
reg-names: {}
clocks:
items:
@ -56,9 +50,52 @@ properties:
'#freq-domain-cells':
const: 1
if:
properties:
compatible:
contains:
const: qcom,cpufreq-hw-8998
then:
properties:
reg:
minItems: 2
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
items:
- const: "osm-domain0"
- const: "freq-domain0"
- const: "osm-domain1"
- const: "freq-domain1"
- const: "osm-acd0"
- const: "osm-acd1"
else:
properties:
reg:
minItems: 2
items:
- description: Frequency domain 0 register region
- description: Frequency domain 1 register region
- description: Frequency domain 2 register region
reg-names:
minItems: 2
items:
- const: "freq-domain0"
- const: "freq-domain1"
- const: "freq-domain2"
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- '#freq-domain-cells'

View file

@ -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>;
};
};

View file

@ -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>;
};
};

View file

@ -55,6 +55,20 @@ properties:
reg:
maxItems: 1
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
- clock-names

View file

@ -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>;
};

View file

@ -0,0 +1,73 @@
# 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,pmi8998-haptics.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm PMI8998/PM660 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,pm660-charger
- qcom,pmi8996-haptics
- qcom,pmi8941-haptics
reg:
maxItems: 1
interrupts:
maxItems: 2
interrupt-names:
items:
- const: short
- const: play
qcom,wave-play-duration-us:
description: |
Wave sample duration in microseconds, 1/f where f
is the resonant frequency of the actuator.
This property is named qcom,wave-play-rate-us in
downstream kernels.
minimum: 0
maximum: 20475
required:
- compatible
- reg
- interrupts
- qcom,wave-play-rate-us
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.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-play-rate-us = <4255>;
};
};

View 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>;
};

View file

@ -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;
};
};
};

View file

@ -0,0 +1,82 @@
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/power/supply/qcom,pmi8998-charger.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm PMI8998/PM660 Switch-Mode Battery Charger "2"
maintainers:
- Caleb Connolly <caleb.connolly@linaro.org>
properties:
compatible:
enum:
- qcom,pmi8998-charger
- qcom,pm660-charger
reg:
maxItems: 1
interrupts:
maxItems: 4
interrupt-names:
items:
- const: usb-plugin
- const: bat-ov
- const: wdog-bark
- const: usbin-icl-change
io-channels:
items:
- description: USB in current in uA
- description: USB in voltage in uV
io-channel-names:
items:
- const: usbin_i
- const: usbin_v
monitored-battery:
description: phandle to the simple-battery node
$ref: /schemas/types.yaml#/definitions/phandle
required:
- compatible
- reg
- interrupts
- interrupt-names
- io-channels
- io-channel-names
- monitored-battery
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
pmic {
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <4>;
charger@1000 {
compatible = "qcom,pmi8998-charger";
reg = <0x1000>;
interrupts = <0x2 0x12 0x2 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x13 0x6 IRQ_TYPE_EDGE_RISING>,
<0x2 0x16 0x1 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "usb-plugin", "bat-ov", "wdog-bark", "usbin-icl-change";
io-channels = <&pmi8998_rradc 3>,
<&pmi8998_rradc 4>;
io-channel-names = "usbin_i",
"usbin_v";
monitored-battery = <&battery>;
};
};

View 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";
};
...

View file

@ -17022,6 +17022,12 @@ S: Maintained
F: Documentation/devicetree/bindings/power/avs/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

View file

@ -49,6 +49,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8998-oneplus-dumpling.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-lilac.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-maple.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-poplar.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-xiaomi-sagit.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb

View file

@ -25,6 +25,15 @@
serial1 = &blsp1_uart3;
};
/* 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.
@ -53,6 +62,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>;
@ -105,6 +116,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";
@ -182,6 +226,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";
@ -241,8 +332,62 @@
status = "okay";
};
&adreno_gpu {
status = "okay";
zap-shader {
memory-region = <&zap_shader_region>;
firmware-name = "qcom/a540_zap.mbn";
};
};
&adreno_smmu {
status = "okay";
};
&apc_cprh {
status = "okay";
};
&blsp1_i2c6 {
status = "okay";
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 = "okay";
qcom,noise-reject-scl = <3>;
qcom,noise-reject-sda = <3>;
touchscreen@14 {
compatible = "goodix,gt9286";
@ -257,6 +402,120 @@
};
};
&cpufreq_hw {
status = "okay";
};
&dsi0 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
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 = "okay";
};
&dsi0_out {
remote-endpoint = <&panel_in>;
data-lanes = <0 1 2 3>;
};
&gcc {
status = "okay";
};
&gpucc {
status = "okay";
};
&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 = "okay";
};
&mdss_mdp {
status = "okay";
};
&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";
};
&etf {
status = "okay";
};
@ -342,7 +601,35 @@
};
};
&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-state {
pins = "gpio5";
function = "normal";
input-enable;
bias-pull-up;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>;
};
vol_up_pin_a: vol-up-active-state {
pins = "gpio6";
function = "normal";
@ -630,6 +917,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";
@ -658,6 +965,13 @@
bias-disable;
drive-strength = <8>;
};
panel_reset_n: panel-rst-n {
pins = "gpio94";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
};
&sdhc2 {

View file

@ -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>;
};

View file

@ -9,12 +9,27 @@
/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 "pm8005.dtsi"
#include "pm8998.dtsi"
#include "pmi8998.dtsi"
/*
* Delete following upstream (msm8998.dtsi) reserved
* memory mappings which are different in this device.
*/
/delete-node/ &adsp_mem;
/delete-node/ &mpss_mem;
/delete-node/ &venus_mem;
/delete-node/ &mba_mem;
/delete-node/ &slpi_mem;
/delete-node/ &ipa_fw_mem;
/delete-node/ &ipa_gsi_mem;
/delete-node/ &gpu_mem;
/delete-node/ &wlan_msa_mem;
/ {
/* Required for bootloader to select correct board */
qcom,msm-id = <292 0x20001>; /* 8998 v2.1 */
@ -45,10 +60,62 @@
<&mmcc MDSS_PCLK0_CLK>,
<&mmcc MDSS_ESC0_CLK>;
power-domains = <&mmcc MDSS_GDSC>;
status = "disabled";
};
};
reserved-memory {
// FIXME: https://patchwork.kernel.org/project/linux-arm-msm/patch/20220617122007.2307726-1-dsankouski@gmail.com/
/*
* OnePlus' ADSP firmware requires 30 MiB in total, so increase the adsp_mem
* region by 4 MiB to account for this while relocating the other now
* conflicting memory nodes accordingly.
*/
adsp_mem: memory@8b200000 {
reg = <0x0 0x8b200000 0x0 0x1e00000>;
no-map;
};
mpss_mem: memory@8d000000 {
reg = <0x0 0x8d000000 0x0 0x7000000>;
no-map;
};
venus_mem: memory@94000000 {
reg = <0x0 0x94000000 0x0 0x500000>;
no-map;
};
mba_mem: memory@94500000 {
reg = <0x0 0x94500000 0x0 0x200000>;
no-map;
};
slpi_mem: memory@94700000 {
reg = <0x0 0x94700000 0x0 0xf00000>;
no-map;
};
ipa_fw_mem: memory@95600000 {
reg = <0x0 0x95600000 0x0 0x10000>;
no-map;
};
ipa_gsi_mem: memory@95610000 {
reg = <0x0 0x95610000 0x0 0x5000>;
no-map;
};
gpu_mem: memory@95615000 {
reg = <0x0 0x95615000 0x0 0x100000>;
no-map;
};
wlan_msa_mem: memory@95715000 {
reg = <0x0 0x95715000 0x0 0x100000>;
no-map;
};
/* Bootloader display framebuffer region */
cont_splash_mem: memory@9d400000 {
reg = <0x0 0x9d400000 0x0 0x2400000>;
@ -80,6 +147,15 @@
reg = <0x0 0xf6900000 0x0 0x2000>;
no-map;
};
blp637_bat: battery {
compatible = "simple-battery";
voltage-max-design-microvolt = <4370000>;
voltage-min-design-microvolt = <3700000>;
charge-full-design-microamp-hours = <3300000>;
energy-full-design-microwatt-hours = <12700000>;
operating-range-celsius = <0 45>;
};
};
gpio-keys {
@ -95,7 +171,7 @@
gpios = <&pm8998_gpio 5 GPIO_ACTIVE_LOW>;
linux,code = <KEY_VOLUMEDOWN>;
debounce-interval = <15>;
wakeup-source;
wakeup-source; // TODO: remove?
};
button-vol-up {
@ -103,7 +179,7 @@
gpios = <&pm8998_gpio 6 GPIO_ACTIVE_LOW>;
linux,code = <KEY_VOLUMEUP>;
debounce-interval = <15>;
wakeup-source;
wakeup-source; // TODO: remove?
};
};
@ -132,43 +208,18 @@
};
};
/*
* OnePlus' ADSP firmware requires 30 MiB in total, so increase the adsp_mem
* region by 4 MiB to account for this while relocating the other now
* conflicting memory nodes accordingly.
*/
&adsp_mem {
reg = <0x0 0x8b200000 0x0 0x1e00000>;
&apc_cprh {
status = "okay";
};
&mpss_mem {
reg = <0x0 0x8d000000 0x0 0x7000000>;
};
&venus_mem {
reg = <0x0 0x94000000 0x0 0x500000>;
};
&mba_mem {
reg = <0x0 0x94500000 0x0 0x200000>;
};
&slpi_mem {
reg = <0x0 0x94700000 0x0 0xf00000>;
};
&ipa_fw_mem {
reg = <0x0 0x95600000 0x0 0x10000>;
};
&ipa_gsi_mem {
reg = <0x0 0x95610000 0x0 0x5000>;
};
&gpu_mem {
reg = <0x0 0x95615000 0x0 0x100000>;
};
&wlan_msa_mem {
reg = <0x0 0x95715000 0x0 0x100000>;
&cpufreq_hw {
status = "okay";
};
&blsp1_i2c5 {
status = "okay";
touchscreen@20 {
rmi4_i2c: touchscreen@20 {
compatible = "syna,rmi4-i2c";
reg = <0x20>;
#address-cells = <1>;
@ -201,6 +252,12 @@
};
};
&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";
@ -254,10 +311,50 @@
};
};
&blsp2_i2c1 {
status = "okay";
fuel-gauge@55 {
compatible = "ti,bq27411";
reg = <0x55>;
/*
* TODO: Adding this appears to not change any reported stats in:
* $ cat /sys/class/power_supply/bq27411-0/uevent
*/
monitored-battery = <&blp637_bat>;
};
};
&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_regulators {
/* VDD_GFX supply */
pm8005_s1: s1 {
@ -279,6 +376,23 @@
};
};
&pmi8998_haptics {
status = "okay";
qcom,wave-play-rate-us = <4255>;
};
&pmi8998_charger {
status = "okay";
monitored-battery = <&blp637_bat>;
};
// cat /sys/bus/iio/devices/iio:device0/in_current0_*
&pmi8998_rradc {
status = "okay";
};
&qusb2phy {
status = "okay";
@ -489,9 +603,139 @@
};
};
&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";
};
&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 = "okay";
};
&gpu_mem {
compatible = "shared-dma-pool";
};
&adreno_gpu {
status = "okay";
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;
/delete-node/ opp-414000000;
/delete-node/ opp-342000000;
};
};
&adreno_smmu {
status = "okay";
};
/*
* 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";
@ -568,7 +812,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>;

View file

@ -24,3 +24,8 @@
&rmi4_f12 {
touchscreen-y-mm = <137>;
};
/* Display */
&panel {
compatible = "samsung,s6e3fc1";
};

View file

@ -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>;

View file

@ -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-state {
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";
};

View file

@ -25,6 +25,11 @@
qcom,soft-start-us = <800>;
};
&wcd9335 {
pinctrl-0 = <&cdc_reset_n &wcd_int_n>;
pinctrl-names = "default";
};
&vreg_l18a_2p85 {
/* Note: Round-down from 2850000 to be a multiple of PLDO step-size 8000 */
regulator-min-microvolt = <2848000>;

View file

@ -8,6 +8,8 @@
#include <dt-bindings/input/input.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>
#include "msm8998.dtsi"
#include "pm8005.dtsi"
#include "pm8998.dtsi"
@ -18,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 {
div1_mclk: divclk1 {
compatible = "gpio-gate-clock";
@ -80,6 +86,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";
@ -188,11 +203,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>;
@ -257,7 +289,10 @@
reg = <0x29>;
interrupt-parent = <&tlmm>;
/* Angelo: not 23? */
interrupts = <22 IRQ_TYPE_EDGE_FALLING>;
//#io-channel-cells = <1>;
//label = "back_camera_tof";
reset-gpios = <&tlmm 27 GPIO_ACTIVE_LOW>;
vdd-supply = <&cam_vio_vreg>;
@ -267,6 +302,62 @@
};
};
&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>;
@ -292,10 +383,34 @@
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";
};
&pm8005_regulators {
/* 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>;
/* Hack until we rig up the gpu consumer */
@ -333,6 +448,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 {
@ -367,6 +489,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";
@ -374,6 +527,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";
@ -410,131 +576,162 @@
regulator-min-microvolt = <1352000>;
regulator-max-microvolt = <1352000>;
};
vreg_s4a_1p8: s4 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-system-load = <100000>;
regulator-allow-set-load;
};
vreg_s5a_2p04: s5 {
regulator-min-microvolt = <1904000>;
regulator-max-microvolt = <2032000>;
};
vreg_s7a_1p025: s7 {
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1028000>;
};
vreg_l1a_0p875: l1 {
regulator-min-microvolt = <880000>;
regulator-max-microvolt = <880000>;
regulator-system-load = <73400>;
regulator-allow-set-load;
};
vreg_l2a_1p2: l2 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-system-load = <12560>;
regulator-allow-set-load;
};
vreg_l3a_1p0: l3 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
};
vreg_l5a_0p8: l5 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <800000>;
};
vreg_l6a_1p8: l6 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
vreg_l7a_1p8: l7 {
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 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
vreg_l13a_2p95: l13 {
regulator-min-microvolt = <1808000>;
regulator-max-microvolt = <2960000>;
regulator-allow-set-load;
};
vreg_l14a_1p85: l14 {
regulator-min-microvolt = <1848000>;
regulator-max-microvolt = <1856000>;
regulator-system-load = <32000>;
regulator-allow-set-load;
};
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 {
regulator-min-microvolt = <1304000>;
regulator-max-microvolt = <1304000>;
};
vreg_l18a_2p85: l18 {};
vreg_l18a_2p85: l18 { };
vreg_l19a_2p7: l19 {
regulator-min-microvolt = <2696000>;
regulator-max-microvolt = <2704000>;
};
vreg_l20a_2p95: l20 {
regulator-min-microvolt = <2960000>;
regulator-max-microvolt = <2960000>;
regulator-system-load = <10000>;
regulator-allow-set-load;
};
vreg_l21a_2p95: l21 {
regulator-min-microvolt = <2960000>;
regulator-max-microvolt = <2960000>;
regulator-system-load = <800000>;
regulator-allow-set-load;
};
vreg_l22a_2p85: l22 { };
vreg_l23a_3p3: l23 {
regulator-min-microvolt = <3312000>;
regulator-max-microvolt = <3312000>;
};
vreg_l24a_3p075: l24 {
regulator-min-microvolt = <3088000>;
regulator-max-microvolt = <3088000>;
};
vreg_l25a_3p3: l25 {
regulator-min-microvolt = <3104000>;
regulator-max-microvolt = <3312000>;
};
vreg_l26a_1p2: l26 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-allow-set-load;
};
vreg_l28_3p0: l28 {
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
};
vreg_lvs1a_1p8: lvs1 { };
vreg_lvs2a_1p8: lvs2 { };
};
@ -562,6 +759,371 @@
pinctrl-1 = <&sdc2_off &sdc2_cd>;
};
/* 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>;
@ -642,6 +1204,67 @@
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 {

View file

@ -0,0 +1,947 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Xiaomi Mi 6 (sagit) device tree source based on msm8998-mtp.dtsi
*
* Copyright (c) 2022, Degdag Mohamed <degdagmohamed@gmail.com>
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
*/
/dts-v1/;
#include "msm8998.dtsi"
#include "pm8005.dtsi"
#include "pm8998.dtsi"
#include "pmi8998.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
/*
* Delete following upstream (msm8998.dtsi) reserved
* memory mappings which are different in this device.
*/
/delete-node/ &adsp_mem;
/delete-node/ &mpss_mem;
/delete-node/ &venus_mem;
/delete-node/ &mba_mem;
/delete-node/ &slpi_mem;
/delete-node/ &ipa_fw_mem;
/delete-node/ &ipa_gsi_mem;
/delete-node/ &gpu_mem;
/delete-node/ &wlan_msa_mem;
/ {
model = "Xiaomi Mi 6";
compatible = "xiaomi,sagit", "qcom,msm8998";
chassis-type = "handset";
/* Required for bootloader to select correct board */
qcom,board-id = <30 0>;
qcom,msm-id = <292 0x20001>; /* 8998 v2.1 */
chosen {
#address-cells = <2>;
#size-cells = <2>;
ranges;
/* Use display framebuffer setup by the UEFI XBL bootloader for simplefb */
framebuffer0: framebuffer@9d400000 {
compatible = "simple-framebuffer";
reg = <0x0 0x9d400000 0x0 0x2400000>;
width = <1080>;
height = <1920>;
stride = <(1080 * 4)>;
format = "a8r8g8b8";
status = "disabled";
};
};
reserved-memory {
/*
* Xiaomi's ADSP firmware requires 30 MiB in total, so increase the adsp_mem
* region by 4 MiB to account for this while relocating the other now
* conflicting memory nodes accordingly.
*/
adsp_mem: memory@8b200000 {
reg = <0x0 0x8b200000 0x0 0x1e00000>;
no-map;
};
mpss_mem: memory@8d000000 {
reg = <0x0 0x8d000000 0x0 0x7000000>;
no-map;
};
venus_mem: memory@94000000 {
reg = <0x0 0x94000000 0x0 0x500000>;
no-map;
};
mba_mem: memory@94500000 {
reg = <0x0 0x94500000 0x0 0x200000>;
no-map;
};
slpi_mem: memory@94700000 {
reg = <0x0 0x94700000 0x0 0xf00000>;
no-map;
};
ipa_fw_mem: memory@95600000 {
reg = <0x0 0x95600000 0x0 0x10000>;
no-map;
};
ipa_gsi_mem: memory@95610000 {
reg = <0x0 0x95610000 0x0 0x5000>;
no-map;
};
gpu_mem: memory@95615000 {
reg = <0x0 0x95615000 0x0 0x100000>;
no-map;
};
wlan_msa_mem: memory@95715000 {
reg = <0x0 0x95715000 0x0 0x100000>;
no-map;
};
/* Bootloader display framebuffer region */
cont_splash_mem: memory@9d400000 {
reg = <0x0 0x9d400000 0x0 0x2400000>;
no-map;
};
/* For getting crash logs using Android downstream kernels */
ramoops@ac000000 {
compatible = "ramoops";
reg = <0x0 0xac000000 0x0 0x200000>;
console-size = <0x80000>;
pmsg-size = <0x40000>;
record-size = <0x8000>;
ftrace-size = <0x20000>;
};
/*
* The following memory regions on downstream are "dynamically allocated"
* but given the same addresses every time. Hard code them as these addresses
* are where the Xiaomi signed firmware expects them to be.
*/
ipa_fws_region: memory@f7800000 {
compatible = "shared-dma-pool";
reg = <0x0 0xf7800000 0x0 0x5000>;
no-map;
};
zap_shader_region: memory@f7900000 {
compatible = "shared-dma-pool";
reg = <0x0 0xf7900000 0x0 0x2000>;
no-map;
};
};
gpio-keys {
compatible = "gpio-keys";
label = "Volume buttons";
autorepeat;
pinctrl-names = "default";
pinctrl-0 = <&vol_up_key_default>;
vol-up {
label = "Volume up";
gpios = <&pm8998_gpio 6 GPIO_ACTIVE_LOW>;
linux,code = <KEY_VOLUMEUP>;
debounce-interval = <15>;
wakeup-source;
};
};
gpio-hall-sensor {
compatible = "gpio-keys";
label = "Hall effect sensor";
pinctrl-names = "default";
pinctrl-0 = <&hall_sensor_default>;
hall-sensor {
label = "Hall Effect Sensor";
gpios = <&tlmm 124 GPIO_ACTIVE_LOW>;
linux,input-type = <EV_SW>;
linux,code = <SW_LID>;
linux,can-disable;
wakeup-source;
};
};
clocks {
div1_mclk: divclk1 {
compatible = "gpio-gate-clock";
pinctrl-0 = <&audio_mclk_pin>;
pinctrl-names = "default";
clocks = <&rpmcc RPM_SMD_DIV_CLK1>;
#clock-cells = <0>;
enable-gpios = <&pm8998_gpio 13 GPIO_ACTIVE_HIGH>;
};
};
vph_pwr: vph-pwr-regulator {
compatible = "regulator-fixed";
regulator-name = "vph_pwr";
regulator-always-on;
regulator-boot-on;
};
disp_vddts_vreg: disp_vddts_vreg {
compatible = "regulator-fixed";
regulator-name = "disp_vddts_vreg";
gpio = <&tlmm 50 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-boot-on;
};
};
&apc_cprh {
status = "okay";
};
&cpufreq_hw {
status = "okay";
};
&blsp1_i2c5 {
pinctrl-names = "default", "sleep";
status = "okay";
synaptics-rmi4-i2c@20 {
compatible = "syna,rmi4-i2c";
reg = <0x20>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&tlmm>;
interrupts = <125 IRQ_TYPE_EDGE_FALLING>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&ts_active>;
pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
vdd-supply = <&disp_vddts_vreg>;
vio-supply = <&vreg_l6a_1p8>;
syna,reset-delay-ms = <20>;
syna,startup-delay-ms = <20>;
rmi4-f01@1 {
reg = <0x01>;
syna,nosleep-mode = <1>;
};
rmi4-f12@12 {
reg = <0x12>;
touchscreen-x-mm = <64>;
touchscreen-y-mm = <114>;
syna,sensor-type = <1>;
syna,rezero-wait-ms = <20>;
};
rmi4-f1a@1a {
reg = <0x1a>;
syna,codes = <KEY_BACK KEY_APPSELECT>;
};
};
};
&blsp1_i2c5_sleep {
/delete-property/ bias-pull-up;
/* Configure a no-pull on TP I2C sleep to match downstream. */
bias-disable;
};
&blsp1_uart3 {
status = "okay";
bluetooth {
compatible = "qcom,wcn3990-bt";
vddio-supply = <&vreg_s4a_1p8>;
vddxo-supply = <&vreg_l7a_1p8>;
vddrf-supply = <&vreg_l17a_1p3>;
vddch0-supply = <&vreg_l25a_3p3>;
max-speed = <3200000>;
};
};
&blsp1_uart3_on {
rx {
/delete-property/ bias-disable;
/*
* Configure a pull-up on 46 (RX). This is needed to
* avoid garbage data when the TX pin of the Bluetooth
* module is in tri-state (module powered off or not
* driving the signal yet).
*/
bias-pull-up;
};
cts {
/delete-property/ bias-disable;
/*
* Configure a pull-down on 47 (CTS) to match the pull
* of the Bluetooth module.
*/
bias-pull-down;
};
};
&blsp2_uart1 {
status = "okay";
};
&ipa {
status = "okay";
memory-region = <&ipa_fws_region>; // ipa_fw_mem? ipa_gsi_mem?
firmware-name = "qcom/msm8998/xiaomi/ipa_fws.mbn";
};
&pm8005_regulators {
/* VDD_GFX supply */
pm8005_s1: s1 {
regulator-min-microvolt = <524000>;
regulator-max-microvolt = <1100000>;
regulator-enable-ramp-delay = <500>;
/* Hack until we rig up the gpu consumer */
regulator-always-on;
};
};
&pm8998_gpio {
vol_up_key_default: vol_up_key_default {
pins = "gpio6";
function = "normal";
bias-pull-up;
input-enable;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
};
audio_mclk_pin: audio-mclk-pin-active {
pins = "gpio13";
function = "func2";
power-source = <0>;
};
};
&pmi8998_fg {
status = "okay";
qcom,max-voltage-uv = <4400000>;
qcom,min-voltage-uv = <3700000>;
qcom,battery-capacity-ua = <3350000>;
};
&pmi8998_lpg {
status = "okay";
notification-led {
color = <LED_COLOR_ID_WHITE>;
function = LED_FUNCTION_STATUS;
reg = <0x5>;
};
};
&pmi8998_haptics {
status = "okay";
qcom,wave-play-rate-us = <5000>;
};
&qusb2phy {
status = "okay";
vdda-pll-supply = <&vreg_l12a_1p8>;
vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
};
&rpm_requests {
pm8998-regulators {
compatible = "qcom,rpm-pm8998-regulators";
vdd_s1-supply = <&vph_pwr>;
vdd_s2-supply = <&vph_pwr>;
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_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_l20_l24-supply = <&vreg_bob>;
vdd_l26-supply = <&vreg_s3a_1p35>;
vdd_lvs1_lvs2-supply = <&vreg_s4a_1p8>;
vreg_s3a_1p35: s3 {
regulator-min-microvolt = <1352000>;
regulator-max-microvolt = <1352000>;
};
vreg_s4a_1p8: s4 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-allow-set-load;
};
vreg_s5a_2p04: s5 {
regulator-min-microvolt = <1904000>;
regulator-max-microvolt = <2040000>;
};
vreg_s7a_1p025: s7 {
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1028000>;
};
vreg_l1a_0p875: l1 {
regulator-min-microvolt = <880000>;
regulator-max-microvolt = <880000>;
};
vreg_l2a_1p2: l2 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
};
vreg_l3a_1p0: l3 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
};
vreg_l5a_0p8: l5 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <800000>;
};
vreg_l6a_1p8: l6 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
vreg_l7a_1p8: l7 {
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 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
vreg_l13a_2p95: l13 {
regulator-min-microvolt = <1808000>;
regulator-max-microvolt = <2960000>;
};
vreg_l14a_1p8: l14 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
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 {
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 {
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-system-load = <800000>;
regulator-allow-set-load;
};
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 {
regulator-min-microvolt = <3088000>;
regulator-max-microvolt = <3088000>;
};
vreg_l25a_3p3: l25 {
regulator-min-microvolt = <3104000>;
regulator-max-microvolt = <3312000>;
};
vreg_l26a_1p2: l26 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-allow-set-load;
};
vreg_l28_3p0: l28 {
regulator-min-microvolt = <3008000>;
regulator-max-microvolt = <3008000>;
};
vreg_lvs1a_1p8: lvs1 { };
vreg_lvs2a_1p8: lvs2 { };
};
pmi8998-regulators {
compatible = "qcom,rpm-pmi8998-regulators";
vdd_bob-supply = <&vph_pwr>;
vreg_bob: bob {
regulator-min-microvolt = <3312000>;
regulator-max-microvolt = <3600000>;
};
};
};
&remoteproc_adsp {
status = "okay";
firmware-name = "qcom/msm8998/xiaomi/adsp.mbn";
};
&remoteproc_mss {
status = "okay";
firmware-name = "qcom/msm8998/xiaomi/mba.mbn", "qcom/msm8998/xiaomi/modem.mbn";
};
&remoteproc_slpi {
status = "okay";
firmware-name = "qcom/msm8998/xiaomi/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 {
compatible = "jdi,fhd-r63452";
reg = <0x0>;
backlight = <&pmi8998_wled>;
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
disp-te-gpios = <&tlmm 10 GPIO_ACTIVE_LOW>;
ibb-supply = <&ibb>;
lab-supply = <&lab>;
vddio-supply = <&vreg_l14a_1p8>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
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>;
};
&ibb {
regulator-min-microvolt = <4600000>;
regulator-max-microvolt = <6000000>;
regulator-min-microamp = <800000>;
regulator-max-microamp = <800000>;
regulator-enable-ramp-delay = <200>;
regulator-over-current-protection;
regulator-pull-down;
regulator-ramp-delay = <1>;
regulator-settling-time-up-us = <600>;
regulator-settling-time-down-us = <1000>;
regulator-soft-start;
qcom,discharge-resistor-kohms = <300>;
regulator-always-on;
};
&lab {
regulator-min-microvolt = <4600000>;
regulator-max-microvolt = <6000000>;
qcom,soft-start-us = <800>;
regulator-min-microamp = <200000>;
regulator-max-microamp = <200000>;
regulator-enable-ramp-delay = <500>;
regulator-over-current-protection;
regulator-pull-down;
regulator-ramp-delay = <1>;
regulator-settling-time-up-us = <50000>;
regulator-settling-time-down-us = <3000>;
regulator-soft-start;
regulator-always-on;
};
&lpass_q6_smmu {
qcom,bypass-cbndx = /bits/ 8 <11>;
qcom,reset-nodisable-cbs = /bits/ 8 <12>;
status = "okay";
};
/* Adreno 540 GPU */
&gpucc {
status = "okay";
};
&gpu_mem {
compatible = "shared-dma-pool";
};
&adreno_gpu {
status = "okay";
zap-shader {
memory-region = <&zap_shader_region>; // gpu_mem?
firmware-name = "qcom/msm8998/xiaomi/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 = "okay";
};
/*
* 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>;
hall_sensor_default: hall-sensor-default {
pins = "gpio124";
function = "gpio";
drive-strength = <2>;
bias-disable;
input-enable;
};
mdss_dsi_active: mdss_dsi_active {
pins = "gpio94";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
mdss_dsi_suspend: mdss_dsi_suspend {
pins = "gpio94";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
mdss_te_active: mdss_te_active {
pins = "gpio10";
function = "mdp_vsync_a";
drive-strength = <2>;
bias-pull-down;
};
mdss_te_suspend: mdss_te_suspend {
pins = "gpio10";
function = "mdp_vsync_a";
drive-strength = <2>;
bias-pull-down;
};
ts_active: ts_active {
pins = "gpio89", "gpio125";
function = "gpio";
drive-strength = <16>;
bias-pull-up;
input-enable;
};
ts_reset_suspend: ts_reset_suspend {
pins = "gpio89";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
ts_int_suspend: ts_int_suspend {
pins = "gpio125";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
nfc_int_active: nfc_int_active {
pins = "gpio92";
function = "gpio";
drive-strength = <6>;
bias-pull-up;
};
nfc_int_suspend: nfc_int_suspend {
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;
};
nfc_enable_suspend: nfc_enable_suspend {
pins = "gpio12", "gpio116";
function = "gpio";
drive-strength = <6>;
bias-disable;
};
msm_mclk0_default: msm-mclk0-active {
pins = "gpio13";
function = "cam_mclk";
drive-strength = <2>;
bias-disable;
};
msm_mclk1_default: msm-mclk1-active {
pins = "gpio14";
function = "cam_mclk";
drive-strength = <2>;
bias-disable;
};
cci1_default: cci1-default {
pins = "gpio18", "gpio19";
function = "cci_i2c";
bias-disable;
drive-strength = <2>;
};
cci1_default: cci1-default {
pins = "gpio19", "gpio20";
function = "cci_i2c";
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;
};
};
&pm8998_pon {
resin {
compatible = "qcom,pm8941-resin";
interrupts = <GIC_SPI 0x8 1 IRQ_TYPE_EDGE_BOTH>;
debounce = <15625>;
bias-pull-up;
linux,code = <KEY_VOLUMEDOWN>;
};
};
&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 = <4>;
qcom,enabled-strings = <0 1 2 3>;
};
&ufshc {
status = "okay";
vcc-supply = <&vreg_l20a_2p95>;
vccq-supply = <&vreg_l26a_1p2>;
vccq2-supply = <&vreg_s4a_1p8>;
vcc-max-microamp = <750000>;
vccq-max-microamp = <560000>;
vccq2-max-microamp = <750000>;
};
&ufsphy {
status = "okay";
vdda-phy-supply = <&vreg_l1a_0p875>;
vdda-pll-supply = <&vreg_l2a_1p2>;
vddp-ref-clk-supply = <&vreg_l26a_1p2>;
vdda-phy-max-microamp = <51400>;
vdda-pll-max-microamp = <14600>;
vddp-ref-clk-max-microamp = <100>;
vddp-ref-clk-always-on;
};
&usb3 {
status = "okay";
/* Disable USB3 clock requirement as the device only supports USB2 */
qcom,select-utmi-as-pipe-clk;
};
&usb3_dwc3 {
/* Drop the unused USB 3 PHY */
phys = <&qusb2phy>;
phy-names = "usb2-phy";
/* Fastest mode for USB 2 */
maximum-speed = "high-speed";
/* Force to peripheral until we can switch modes */
dr_mode = "peripheral";
};
&wifi {
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>;
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
};

File diff suppressed because it is too large Load diff

View file

@ -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";

View file

@ -9,6 +9,23 @@
#address-cells = <1>;
#size-cells = <0>;
pmi8998_charger: charger@1000 {
compatible = "qcom,pmi8998-charger";
reg = <0x1000>;
interrupts = <0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x12 0x2 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x16 0x1 IRQ_TYPE_EDGE_RISING>,
<0x2 0x13 0x6 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "usb-plugin", "bat-ov", "wdog-bark", "usbin-icl-change";
io-channels = <&pmi8998_rradc 3>,
<&pmi8998_rradc 4>;
io-channel-names = "usbin_i", "usbin_v";
status = "disabled";
};
pmi8998_gpio: gpios@c000 {
compatible = "qcom,pmi8998-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
@ -18,6 +35,24 @@
interrupt-controller;
#interrupt-cells = <2>;
};
pmi8998_fg: fuel-gauge@4000 {
compatible = "qcom,pmi8998-fg";
reg = <0x4000>;
interrupts = <0x2 0x40 0x3 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "soc-delta";
status = "disabled";
};
pmi8998_rradc: rradc@4500 {
compatible = "qcom,pmi8998-rradc";
reg = <0x4500>;
#io-channel-cells = <1>;
status = "disabled";
};
};
pmi8998_lsid1: pmic@3 {
@ -62,5 +97,16 @@
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";
status = "disabled";
};
};
};

View file

@ -1185,19 +1185,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 {

View file

@ -0,0 +1,563 @@
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_PREEMPT=y
CONFIG_PSI=y
# CONFIG_CPU_ISOLATION is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_MEMCG=y
CONFIG_BLK_CGROUP=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
# CONFIG_TIME_NS is not set
CONFIG_USER_NS=y
CONFIG_CHECKPOINT_RESTORE=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_ZSTD is not set
# CONFIG_INITRAMFS_PRESERVE_MTIME is not set
CONFIG_PERF_EVENTS=y
CONFIG_ARCH_QCOM=y
# CONFIG_ARM64_ERRATUM_826319 is not set
# CONFIG_ARM64_ERRATUM_827319 is not set
# CONFIG_ARM64_ERRATUM_824069 is not set
# CONFIG_ARM64_ERRATUM_819472 is not set
# CONFIG_ARM64_ERRATUM_832075 is not set
# CONFIG_ARM64_ERRATUM_1742098 is not set
# CONFIG_ARM64_ERRATUM_843419 is not set
# CONFIG_ARM64_ERRATUM_1024718 is not set
# CONFIG_ARM64_ERRATUM_1418040 is not set
# CONFIG_ARM64_ERRATUM_1165522 is not set
# CONFIG_ARM64_ERRATUM_1319367 is not set
# CONFIG_ARM64_ERRATUM_1530923 is not set
# CONFIG_ARM64_ERRATUM_2441007 is not set
# CONFIG_ARM64_ERRATUM_1286807 is not set
# CONFIG_ARM64_ERRATUM_1463225 is not set
# CONFIG_ARM64_ERRATUM_1542419 is not set
# CONFIG_ARM64_ERRATUM_1508412 is not set
# CONFIG_ARM64_ERRATUM_2051678 is not set
# CONFIG_ARM64_ERRATUM_2077057 is not set
# CONFIG_ARM64_ERRATUM_2658417 is not set
# CONFIG_ARM64_ERRATUM_2054223 is not set
# CONFIG_ARM64_ERRATUM_2067961 is not set
# CONFIG_ARM64_ERRATUM_2441009 is not set
# CONFIG_CAVIUM_ERRATUM_22375 is not set
# CONFIG_CAVIUM_ERRATUM_23154 is not set
# CONFIG_CAVIUM_ERRATUM_27456 is not set
# CONFIG_CAVIUM_ERRATUM_30115 is not set
# CONFIG_CAVIUM_TX2_ERRATUM_219 is not set
# CONFIG_FUJITSU_ERRATUM_010001 is not set
# CONFIG_HISILICON_ERRATUM_161600802 is not set
# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set
# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set
# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set
# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set
# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set
# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set
CONFIG_SCHED_MC=y
CONFIG_SCHED_CLUSTER=y
CONFIG_NR_CPUS=8
CONFIG_HOTPLUG_CPU=y
CONFIG_HZ_1000=y
# CONFIG_RODATA_FULL_DEFAULT_ENABLED is not set
# CONFIG_ARM64_TAGGED_ADDR_ABI is not set
CONFIG_COMPAT=y
# CONFIG_ARM64_RAS_EXTN is not set
# CONFIG_ARM64_CNP is not set
# CONFIG_ARM64_PTR_AUTH is not set
# CONFIG_ARM64_AMU_EXTN is not set
# CONFIG_ARM64_TLB_RANGE is not set
# CONFIG_ARM64_BTI is not set
# CONFIG_ARM64_E0PD is not set
# CONFIG_ARM64_EPAN is not set
CONFIG_ARM64_MODULE_PLTS=y
# CONFIG_EFI is not set
# CONFIG_SUSPEND is not set
CONFIG_PM=y
CONFIG_PM_DEBUG=y
CONFIG_PM_ADVANCED_DEBUG=y
CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_ENERGY_MODEL=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_CPU_IDLE_GOV_TEO=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
CONFIG_ARM_QCOM_CPUFREQ_HW=y
CONFIG_JUMP_LABEL=y
# CONFIG_STACKPROTECTOR is not set
CONFIG_SHADOW_CALL_STACK=y
# CONFIG_VMAP_STACK is not set
# CONFIG_GCC_PLUGINS is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_COMPRESS_XZ=y
# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set
CONFIG_BLK_DEV_THROTTLING=y
CONFIG_IOSCHED_BFQ=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=m
CONFIG_ZSMALLOC_STAT=y
# CONFIG_SLAB_MERGE_DEFAULT is not set
# CONFIG_SLUB_CPU_PARTIAL is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_KSM=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_LRU_GEN=y
CONFIG_LRU_GEN_ENABLED=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=y
CONFIG_INET=y
CONFIG_SYN_COOKIES=y
CONFIG_IPV6=m
CONFIG_NETFILTER=y
CONFIG_BRIDGE_NETFILTER=m
CONFIG_NF_CONNTRACK=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=y
CONFIG_NFT_CT=m
CONFIG_NFT_LOG=m
CONFIG_NFT_LIMIT=m
CONFIG_NFT_MASQ=m
CONFIG_NFT_NAT=m
CONFIG_NFT_REJECT=m
CONFIG_NETFILTER_XT_MARK=m
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_IPVS=m
CONFIG_IP_VS=m
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
CONFIG_IP_VS_RR=m
CONFIG_IP_VS_NFCT=y
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_BRIDGE=m
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q=m
CONFIG_NET_SCHED=y
CONFIG_NET_CLS_CGROUP=m
CONFIG_NETLINK_DIAG=y
CONFIG_QRTR=m
CONFIG_QRTR_SMD=m
CONFIG_QRTR_TUN=m
CONFIG_CGROUP_NET_PRIO=y
CONFIG_BT=m
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=m
CONFIG_BT_HS=y
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_QCA=y
CONFIG_CFG80211=m
CONFIG_MAC80211=m
CONFIG_MAC80211_MESH=y
CONFIG_RFKILL=m
CONFIG_NFC=m
CONFIG_NFC_NCI=m
CONFIG_NFC_NXP_NCI=m
CONFIG_NFC_NXP_NCI_I2C=m
CONFIG_UEVENT_HELPER=y
CONFIG_DEVTMPFS=y
CONFIG_QCOM_SSC_BLOCK_BUS=y
# CONFIG_ARM_SMCCC_SOC_ID is not set
CONFIG_ZRAM=m
CONFIG_ZRAM_MEMORY_TRACKING=y
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_QCOM_FASTRPC=m
CONFIG_SCSI=y
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=m
CONFIG_DM_CRYPT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_NETDEVICES=y
CONFIG_DUMMY=m
CONFIG_MACVLAN=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
CONFIG_TUN=m
CONFIG_VETH=m
# CONFIG_NET_VENDOR_ALACRITECH is not set
# CONFIG_NET_VENDOR_AMAZON is not set
# CONFIG_NET_VENDOR_AMD is not set
# CONFIG_NET_VENDOR_AQUANTIA is not set
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_VENDOR_ASIX is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CADENCE is not set
# CONFIG_NET_VENDOR_CAVIUM is not set
# CONFIG_NET_VENDOR_CORTINA is not set
# CONFIG_NET_VENDOR_DAVICOM is not set
# CONFIG_NET_VENDOR_ENGLEDER is not set
# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_FUNGIBLE is not set
# CONFIG_NET_VENDOR_GOOGLE is not set
# CONFIG_NET_VENDOR_HISILICON is not set
# CONFIG_NET_VENDOR_HUAWEI is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_WANGXUN is not set
# CONFIG_NET_VENDOR_LITEX is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MELLANOX is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_MICROSEMI is not set
# CONFIG_NET_VENDOR_MICROSOFT is not set
# CONFIG_NET_VENDOR_NI is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_NETRONOME is not set
# CONFIG_NET_VENDOR_PENSANDO is not set
CONFIG_RMNET=m
# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SOLARFLARE is not set
# CONFIG_NET_VENDOR_SMSC is not set
# CONFIG_NET_VENDOR_SOCIONEXT is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_SYNOPSYS is not set
# CONFIG_NET_VENDOR_VERTEXCOM is not set
# CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_NET_VENDOR_XILINX is not set
CONFIG_QCOM_IPA=m
# CONFIG_WLAN_VENDOR_ADMTEK is not set
CONFIG_ATH10K=m
CONFIG_ATH10K_SNOC=m
# CONFIG_WLAN_VENDOR_ATMEL is not set
# CONFIG_WLAN_VENDOR_BROADCOM is not set
# CONFIG_WLAN_VENDOR_CISCO is not set
# CONFIG_WLAN_VENDOR_INTEL is not set
# CONFIG_WLAN_VENDOR_INTERSIL is not set
# CONFIG_WLAN_VENDOR_MARVELL is not set
# CONFIG_WLAN_VENDOR_MEDIATEK is not set
# CONFIG_WLAN_VENDOR_MICROCHIP is not set
# CONFIG_WLAN_VENDOR_PURELIFI is not set
# CONFIG_WLAN_VENDOR_RALINK is not set
# CONFIG_WLAN_VENDOR_REALTEK is not set
# CONFIG_WLAN_VENDOR_RSI is not set
# CONFIG_WLAN_VENDOR_SILABS is not set
# CONFIG_WLAN_VENDOR_ST is not set
# CONFIG_WLAN_VENDOR_TI is not set
# CONFIG_WLAN_VENDOR_ZYDAS is not set
# CONFIG_WLAN_VENDOR_QUANTENNA is not set
CONFIG_INPUT_FF_MEMLESS=y
CONFIG_INPUT_EVDEV=m
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_GPIO_FASTMATRIX=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_GOODIX=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PM8941_PWRKEY=y
CONFIG_INPUT_QCOM_SPMI_HAPTICS=m
CONFIG_INPUT_UINPUT=m
CONFIG_RMI4_CORE=m
CONFIG_RMI4_I2C=m
CONFIG_RMI4_F12=y
CONFIG_RMI4_F1A=y
# CONFIG_SERIO is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_LDISC_AUTOLOAD is not set
CONFIG_SERIAL_MSM=m
CONFIG_SERIAL_DEV_BUS=y
# CONFIG_HW_RANDOM is not set
# CONFIG_DEVMEM is not set
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QCOM_CCI=m
CONFIG_I2C_QUP=m
CONFIG_SPMI=y
CONFIG_PINCTRL_AW9523=y
CONFIG_PINCTRL_MSM=y
CONFIG_PINCTRL_MSM8998=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_GPIO_WCD934X=m
CONFIG_POWER_RESET_MSM=y
CONFIG_POWER_RESET_QCOM_PON=y
CONFIG_BATTERY_BQ27XXX=m
CONFIG_CHARGER_QCOM_SMB2=m
CONFIG_BATTERY_QCOM_FG=m
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_DEVFREQ_THERMAL=y
CONFIG_QCOM_TSENS=y
CONFIG_QCOM_SPMI_TEMP_ALARM=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_WCD934X=m
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
CONFIG_REGULATOR_QCOM_LABIBB=y
CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_PLATFORM_SUPPORT=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_QCOM_CAMSS=m
CONFIG_VIDEO_IMX355=m
CONFIG_DRM=y
# CONFIG_DRM_USE_DYNAMIC_DEBUG is not set
CONFIG_DRM_MSM=m
# CONFIG_DRM_MSM_MDP4 is not set
# CONFIG_DRM_MSM_MDP5 is not set
# CONFIG_DRM_MSM_DSI_28NM_PHY is not set
# CONFIG_DRM_MSM_DSI_20NM_PHY is not set
# CONFIG_DRM_MSM_DSI_28NM_8960_PHY is not set
# CONFIG_DRM_MSM_DSI_14NM_PHY is not set
# CONFIG_DRM_MSM_DSI_7NM_PHY is not set
CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0=y
CONFIG_DRM_PANEL_JDI_R63452=y
CONFIG_DRM_PANEL_NOVATEK_NT35950=y
CONFIG_DRM_PANEL_SAMSUNG_S6E3FA5=y
CONFIG_DRM_PANEL_SAMSUNG_S6E3FC1=y
CONFIG_FB=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_QCOM_WLED=y
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_SOUND=m
CONFIG_SND=m
# CONFIG_SND_SUPPORT_OLD_API is not set
# CONFIG_SND_VERBOSE_PROCFS is not set
# CONFIG_SND_DRIVERS is not set
CONFIG_SND_SOC=m
CONFIG_SND_SOC_QCOM=m
CONFIG_SND_SOC_MSM8998=m
CONFIG_SND_SOC_WCD9335=m
CONFIG_SND_SOC_WCD934X=m
CONFIG_SND_SOC_LPASS_WSA_MACRO=m
CONFIG_SND_SOC_LPASS_VA_MACRO=m
CONFIG_SND_SOC_LPASS_RX_MACRO=m
CONFIG_SND_SOC_LPASS_TX_MACRO=m
CONFIG_HID_BATTERY_STRENGTH=y
CONFIG_HIDRAW=y
# CONFIG_HID_A4TECH is not set
# CONFIG_HID_APPLE is not set
# CONFIG_HID_BELKIN is not set
# CONFIG_HID_CHERRY is not set
# CONFIG_HID_CHICONY is not set
# CONFIG_HID_CYPRESS is not set
# CONFIG_HID_EZKEY is not set
# CONFIG_HID_ITE is not set
# CONFIG_HID_KENSINGTON is not set
# CONFIG_HID_LOGITECH is not set
# CONFIG_HID_REDRAGON is not set
# CONFIG_HID_MICROSOFT is not set
# CONFIG_HID_MONTEREY is not set
CONFIG_HID_NINTENDO=m
CONFIG_NINTENDO_FF=y
CONFIG_HID_SONY=m
CONFIG_SONY_FF=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_DWC3=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_UVC=y
CONFIG_USB_FUNCTIONFS=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MSM=y
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFS_HPB=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=m
CONFIG_LEDS_CLASS_FLASH=m
CONFIG_LEDS_CLASS_MULTICOLOR=m
CONFIG_LEDS_GPIO=m
CONFIG_LEDS_QCOM_LPG=m
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_ACTIVITY=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_CAMERA=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_LEDS_TRIGGER_NETDEV=y
CONFIG_LEDS_TRIGGER_PATTERN=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_RTC_DRV_PM8XXX=m
CONFIG_DMADEVICES=y
CONFIG_QCOM_BAM_DMA=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
CONFIG_STAGING=y
# CONFIG_SURFACE_PLATFORMS is not set
CONFIG_COMMON_CLK_QCOM=y
CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_MSM_GPUCC_8998=y
CONFIG_MSM_MMCC_8998=y
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=m
# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
# CONFIG_FSL_ERRATUM_A008585 is not set
# CONFIG_HISILICON_ERRATUM_161010101 is not set
# CONFIG_ARM64_ERRATUM_858921 is not set
CONFIG_MAILBOX=y
CONFIG_QCOM_APCS_IPC=y
CONFIG_ARM_SMMU=y
CONFIG_QCOM_IOMMU=y
CONFIG_REMOTEPROC=y
CONFIG_REMOTEPROC_CDEV=y
CONFIG_QCOM_Q6V5_ADSP=m
CONFIG_QCOM_Q6V5_MSS=m
CONFIG_QCOM_Q6V5_PAS=m
CONFIG_QCOM_SYSMON=m
CONFIG_RPMSG_CHAR=m
CONFIG_RPMSG_NS=m
CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_RPMSG_QCOM_GLINK_SMEM=y
CONFIG_RPMSG_QCOM_SMD=m
CONFIG_SOUNDWIRE=m
CONFIG_SOUNDWIRE_QCOM=m
CONFIG_QCOM_CPR3=y
CONFIG_QCOM_RMTFS_MEM=m
CONFIG_QCOM_RPMPD=y
CONFIG_QCOM_SMEM=y
CONFIG_QCOM_SMD_RPM=y
CONFIG_QCOM_SMP2P=m
CONFIG_QCOM_SPM=y
CONFIG_QCOM_STATS=m
CONFIG_QCOM_APR=m
CONFIG_QCOM_ICC_BWMON=y
CONFIG_EXTCON=y
CONFIG_EXTCON_USB_GPIO=y
CONFIG_IIO=y
CONFIG_QCOM_SPMI_VADC=y
CONFIG_QCOM_SPMI_ADC5=y
CONFIG_PWM=y
CONFIG_PHY_QCOM_QMP=y
CONFIG_PHY_QCOM_QUSB2=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDERFS=y
CONFIG_NVMEM_QCOM_QFPROM=y
CONFIG_SLIM_QCOM_CTRL=m
CONFIG_SLIM_QCOM_NGD_CTRL=m
CONFIG_INTERCONNECT=y
CONFIG_INTERCONNECT_QCOM=y
CONFIG_INTERCONNECT_QCOM_MSM8998=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
# CONFIG_DNOTIFY is not set
CONFIG_FANOTIFY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_QFMT_V2=y
CONFIG_FUSE_FS=m
CONFIG_OVERLAY_FS=m
CONFIG_VFAT_FS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON=y
CONFIG_SQUASHFS=m
CONFIG_SQUASHFS_FILE_DIRECT=y
CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_XZ=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_UNICODE=y
CONFIG_KEY_DH_OPERATIONS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_MD5=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
# CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set
CONFIG_CRYPTO_NHPOLY1305_NEON=m
CONFIG_CRYPTO_CHACHA20_NEON=m
CONFIG_CRYPTO_GHASH_ARM64_CE=m
CONFIG_CRYPTO_POLY1305_NEON=m
CONFIG_CRYPTO_SHA1_ARM64_CE=m
CONFIG_CRYPTO_SHA2_ARM64_CE=m
CONFIG_CRYPTO_SHA512_ARM64_CE=m
CONFIG_CRYPTO_POLYVAL_ARM64_CE=m
CONFIG_CRYPTO_AES_ARM64=m
CONFIG_CRYPTO_AES_ARM64_CE_BLK=m
CONFIG_CRYPTO_AES_ARM64_BS=m
CONFIG_CRYPTO_SM4_ARM64_CE_BLK=m
CONFIG_CRYPTO_SM4_ARM64_NEON_BLK=m
CONFIG_CRYPTO_AES_ARM64_CE_CCM=m
CONFIG_PKCS8_PRIVATE_KEY_PARSER=m
CONFIG_FORCE_NR_CPUS=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_RCU_TRACE is not set
# CONFIG_FTRACE is not set
# CONFIG_RUNTIME_TESTING_MENU is not set

View file

@ -0,0 +1,552 @@
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_PREEMPT=y
CONFIG_PSI=y
# CONFIG_CPU_ISOLATION is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_MEMCG=y
CONFIG_BLK_CGROUP=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
# CONFIG_TIME_NS is not set
CONFIG_USER_NS=y
CONFIG_CHECKPOINT_RESTORE=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_ZSTD is not set
# CONFIG_INITRAMFS_PRESERVE_MTIME is not set
CONFIG_PERF_EVENTS=y
CONFIG_ARCH_QCOM=y
# CONFIG_ARM64_ERRATUM_826319 is not set
# CONFIG_ARM64_ERRATUM_827319 is not set
# CONFIG_ARM64_ERRATUM_824069 is not set
# CONFIG_ARM64_ERRATUM_819472 is not set
# CONFIG_ARM64_ERRATUM_832075 is not set
# CONFIG_ARM64_ERRATUM_1742098 is not set
# CONFIG_ARM64_ERRATUM_843419 is not set
# CONFIG_ARM64_ERRATUM_1024718 is not set
# CONFIG_ARM64_ERRATUM_1418040 is not set
# CONFIG_ARM64_ERRATUM_1165522 is not set
# CONFIG_ARM64_ERRATUM_1319367 is not set
# CONFIG_ARM64_ERRATUM_1530923 is not set
# CONFIG_ARM64_ERRATUM_2441007 is not set
# CONFIG_ARM64_ERRATUM_1286807 is not set
# CONFIG_ARM64_ERRATUM_1463225 is not set
# CONFIG_ARM64_ERRATUM_1542419 is not set
# CONFIG_ARM64_ERRATUM_1508412 is not set
# CONFIG_ARM64_ERRATUM_2051678 is not set
# CONFIG_ARM64_ERRATUM_2077057 is not set
# CONFIG_ARM64_ERRATUM_2658417 is not set
# CONFIG_ARM64_ERRATUM_2054223 is not set
# CONFIG_ARM64_ERRATUM_2067961 is not set
# CONFIG_ARM64_ERRATUM_2441009 is not set
# CONFIG_CAVIUM_ERRATUM_22375 is not set
# CONFIG_CAVIUM_ERRATUM_23154 is not set
# CONFIG_CAVIUM_ERRATUM_27456 is not set
# CONFIG_CAVIUM_ERRATUM_30115 is not set
# CONFIG_CAVIUM_TX2_ERRATUM_219 is not set
# CONFIG_FUJITSU_ERRATUM_010001 is not set
# CONFIG_HISILICON_ERRATUM_161600802 is not set
# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set
# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set
# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set
# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set
# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set
# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set
CONFIG_SCHED_MC=y
CONFIG_SCHED_CLUSTER=y
CONFIG_NR_CPUS=8
CONFIG_HOTPLUG_CPU=y
CONFIG_HZ_1000=y
# CONFIG_RODATA_FULL_DEFAULT_ENABLED is not set
# CONFIG_ARM64_TAGGED_ADDR_ABI is not set
CONFIG_COMPAT=y
# CONFIG_ARM64_RAS_EXTN is not set
# CONFIG_ARM64_CNP is not set
# CONFIG_ARM64_PTR_AUTH is not set
# CONFIG_ARM64_AMU_EXTN is not set
# CONFIG_ARM64_TLB_RANGE is not set
# CONFIG_ARM64_BTI is not set
# CONFIG_ARM64_E0PD is not set
# CONFIG_ARM64_EPAN is not set
CONFIG_ARM64_MODULE_PLTS=y
# CONFIG_EFI is not set
# CONFIG_SUSPEND is not set
CONFIG_PM=y
CONFIG_PM_DEBUG=y
CONFIG_PM_ADVANCED_DEBUG=y
CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_ENERGY_MODEL=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_CPU_IDLE_GOV_TEO=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
CONFIG_ARM_QCOM_CPUFREQ_HW=y
CONFIG_JUMP_LABEL=y
# CONFIG_STACKPROTECTOR is not set
CONFIG_SHADOW_CALL_STACK=y
# CONFIG_VMAP_STACK is not set
# CONFIG_GCC_PLUGINS is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_COMPRESS_XZ=y
# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set
CONFIG_BLK_DEV_THROTTLING=y
CONFIG_IOSCHED_BFQ=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=m
CONFIG_ZSMALLOC_STAT=y
# CONFIG_SLAB_MERGE_DEFAULT is not set
# CONFIG_SLUB_CPU_PARTIAL is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_KSM=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_LRU_GEN=y
CONFIG_LRU_GEN_ENABLED=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=y
CONFIG_INET=y
CONFIG_SYN_COOKIES=y
CONFIG_IPV6=m
CONFIG_NETFILTER=y
CONFIG_BRIDGE_NETFILTER=m
CONFIG_NF_CONNTRACK=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=y
CONFIG_NFT_CT=m
CONFIG_NFT_LOG=m
CONFIG_NFT_LIMIT=m
CONFIG_NFT_MASQ=m
CONFIG_NFT_NAT=m
CONFIG_NFT_REJECT=m
CONFIG_NETFILTER_XT_MARK=m
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_IPVS=m
CONFIG_IP_VS=m
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
CONFIG_IP_VS_RR=m
CONFIG_IP_VS_NFCT=y
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_BRIDGE=m
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q=m
CONFIG_NET_SCHED=y
CONFIG_NET_CLS_CGROUP=m
CONFIG_NETLINK_DIAG=y
CONFIG_QRTR=m
CONFIG_QRTR_SMD=m
CONFIG_QRTR_TUN=m
CONFIG_CGROUP_NET_PRIO=y
CONFIG_BT=m
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=m
CONFIG_BT_HS=y
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_QCA=y
CONFIG_CFG80211=m
CONFIG_MAC80211=m
CONFIG_MAC80211_MESH=y
CONFIG_RFKILL=m
CONFIG_NFC=m
CONFIG_NFC_NCI=m
CONFIG_NFC_NXP_NCI=m
CONFIG_NFC_NXP_NCI_I2C=m
CONFIG_UEVENT_HELPER=y
CONFIG_DEVTMPFS=y
CONFIG_QCOM_SSC_BLOCK_BUS=y
# CONFIG_ARM_SMCCC_SOC_ID is not set
CONFIG_ZRAM=m
CONFIG_ZRAM_MEMORY_TRACKING=y
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_QCOM_FASTRPC=m
CONFIG_SCSI=y
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=m
CONFIG_DM_CRYPT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_NETDEVICES=y
CONFIG_DUMMY=m
CONFIG_MACVLAN=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
CONFIG_TUN=m
CONFIG_VETH=m
# CONFIG_NET_VENDOR_ALACRITECH is not set
# CONFIG_NET_VENDOR_AMAZON is not set
# CONFIG_NET_VENDOR_AMD is not set
# CONFIG_NET_VENDOR_AQUANTIA is not set
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_VENDOR_ASIX is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CADENCE is not set
# CONFIG_NET_VENDOR_CAVIUM is not set
# CONFIG_NET_VENDOR_CORTINA is not set
# CONFIG_NET_VENDOR_DAVICOM is not set
# CONFIG_NET_VENDOR_ENGLEDER is not set
# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_FUNGIBLE is not set
# CONFIG_NET_VENDOR_GOOGLE is not set
# CONFIG_NET_VENDOR_HISILICON is not set
# CONFIG_NET_VENDOR_HUAWEI is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_WANGXUN is not set
# CONFIG_NET_VENDOR_LITEX is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MELLANOX is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_MICROSEMI is not set
# CONFIG_NET_VENDOR_MICROSOFT is not set
# CONFIG_NET_VENDOR_NI is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_NETRONOME is not set
# CONFIG_NET_VENDOR_PENSANDO is not set
CONFIG_RMNET=m
# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SOLARFLARE is not set
# CONFIG_NET_VENDOR_SMSC is not set
# CONFIG_NET_VENDOR_SOCIONEXT is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_SYNOPSYS is not set
# CONFIG_NET_VENDOR_VERTEXCOM is not set
# CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_NET_VENDOR_XILINX is not set
CONFIG_QCOM_IPA=m
# CONFIG_WLAN_VENDOR_ADMTEK is not set
CONFIG_ATH10K=m
CONFIG_ATH10K_SNOC=m
# CONFIG_WLAN_VENDOR_ATMEL is not set
# CONFIG_WLAN_VENDOR_BROADCOM is not set
# CONFIG_WLAN_VENDOR_CISCO is not set
# CONFIG_WLAN_VENDOR_INTEL is not set
# CONFIG_WLAN_VENDOR_INTERSIL is not set
# CONFIG_WLAN_VENDOR_MARVELL is not set
# CONFIG_WLAN_VENDOR_MEDIATEK is not set
# CONFIG_WLAN_VENDOR_MICROCHIP is not set
# CONFIG_WLAN_VENDOR_PURELIFI is not set
# CONFIG_WLAN_VENDOR_RALINK is not set
# CONFIG_WLAN_VENDOR_REALTEK is not set
# CONFIG_WLAN_VENDOR_RSI is not set
# CONFIG_WLAN_VENDOR_SILABS is not set
# CONFIG_WLAN_VENDOR_ST is not set
# CONFIG_WLAN_VENDOR_TI is not set
# CONFIG_WLAN_VENDOR_ZYDAS is not set
# CONFIG_WLAN_VENDOR_QUANTENNA is not set
CONFIG_INPUT_FF_MEMLESS=y
CONFIG_INPUT_EVDEV=m
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PM8941_PWRKEY=y
CONFIG_INPUT_QCOM_SPMI_HAPTICS=m
CONFIG_INPUT_UINPUT=m
CONFIG_RMI4_CORE=m
CONFIG_RMI4_I2C=m
CONFIG_RMI4_F12=y
CONFIG_RMI4_F1A=y
# CONFIG_SERIO is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_LDISC_AUTOLOAD is not set
CONFIG_SERIAL_MSM=m
CONFIG_SERIAL_DEV_BUS=y
# CONFIG_HW_RANDOM is not set
# CONFIG_DEVMEM is not set
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QCOM_CCI=m
CONFIG_I2C_QUP=m
CONFIG_SPMI=y
CONFIG_PINCTRL_MSM=y
CONFIG_PINCTRL_MSM8998=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_GPIO_WCD934X=m
CONFIG_POWER_RESET_MSM=y
CONFIG_POWER_RESET_QCOM_PON=y
CONFIG_BATTERY_BQ27XXX=m
CONFIG_CHARGER_QCOM_SMB2=m
CONFIG_BATTERY_QCOM_FG=m
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_DEVFREQ_THERMAL=y
CONFIG_QCOM_TSENS=y
CONFIG_QCOM_SPMI_TEMP_ALARM=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_WCD934X=m
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
CONFIG_REGULATOR_QCOM_LABIBB=y
CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_PLATFORM_SUPPORT=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_QCOM_CAMSS=m
CONFIG_VIDEO_IMX355=m
CONFIG_DRM=y
# CONFIG_DRM_USE_DYNAMIC_DEBUG is not set
CONFIG_DRM_MSM=m
# CONFIG_DRM_MSM_MDP4 is not set
# CONFIG_DRM_MSM_MDP5 is not set
# CONFIG_DRM_MSM_DP is not set
# CONFIG_DRM_MSM_DSI_28NM_PHY is not set
# CONFIG_DRM_MSM_DSI_20NM_PHY is not set
# CONFIG_DRM_MSM_DSI_28NM_8960_PHY is not set
# CONFIG_DRM_MSM_DSI_14NM_PHY is not set
# CONFIG_DRM_MSM_DSI_7NM_PHY is not set
# CONFIG_DRM_MSM_HDMI is not set
CONFIG_DRM_PANEL_SAMSUNG_S6E3FA5=y
CONFIG_DRM_PANEL_SAMSUNG_S6E3FC1=y
CONFIG_FB=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_SOUND=m
CONFIG_SND=m
# CONFIG_SND_SUPPORT_OLD_API is not set
# CONFIG_SND_VERBOSE_PROCFS is not set
# CONFIG_SND_DRIVERS is not set
CONFIG_SND_SOC=m
CONFIG_SND_SOC_QCOM=m
CONFIG_SND_SOC_MSM8998=m
CONFIG_SND_SOC_WCD9335=m
CONFIG_SND_SOC_WCD934X=m
CONFIG_SND_SOC_LPASS_WSA_MACRO=m
CONFIG_SND_SOC_LPASS_VA_MACRO=m
CONFIG_SND_SOC_LPASS_RX_MACRO=m
CONFIG_SND_SOC_LPASS_TX_MACRO=m
CONFIG_HID_BATTERY_STRENGTH=y
CONFIG_HIDRAW=y
# CONFIG_HID_A4TECH is not set
# CONFIG_HID_APPLE is not set
# CONFIG_HID_BELKIN is not set
# CONFIG_HID_CHERRY is not set
# CONFIG_HID_CHICONY is not set
# CONFIG_HID_CYPRESS is not set
# CONFIG_HID_EZKEY is not set
# CONFIG_HID_ITE is not set
# CONFIG_HID_KENSINGTON is not set
# CONFIG_HID_LOGITECH is not set
# CONFIG_HID_REDRAGON is not set
# CONFIG_HID_MICROSOFT is not set
# CONFIG_HID_MONTEREY is not set
CONFIG_HID_NINTENDO=m
CONFIG_NINTENDO_FF=y
CONFIG_HID_SONY=m
CONFIG_SONY_FF=y
CONFIG_USB=m
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_DWC3=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_UVC=y
CONFIG_USB_FUNCTIONFS=m
CONFIG_USB_ROLE_SWITCH=y
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFS_HPB=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=m
CONFIG_LEDS_CLASS_FLASH=m
CONFIG_LEDS_CLASS_MULTICOLOR=m
CONFIG_LEDS_GPIO=m
CONFIG_LEDS_QCOM_LPG=m
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_ACTIVITY=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_CAMERA=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_LEDS_TRIGGER_NETDEV=y
CONFIG_LEDS_TRIGGER_PATTERN=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_RTC_DRV_PM8XXX=m
CONFIG_DMADEVICES=y
CONFIG_QCOM_BAM_DMA=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
CONFIG_STAGING=y
# CONFIG_SURFACE_PLATFORMS is not set
CONFIG_COMMON_CLK_QCOM=y
CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_MSM_GPUCC_8998=y
CONFIG_MSM_MMCC_8998=y
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=m
# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
# CONFIG_FSL_ERRATUM_A008585 is not set
# CONFIG_HISILICON_ERRATUM_161010101 is not set
# CONFIG_ARM64_ERRATUM_858921 is not set
CONFIG_MAILBOX=y
CONFIG_QCOM_APCS_IPC=y
CONFIG_ARM_SMMU=y
CONFIG_QCOM_IOMMU=y
CONFIG_REMOTEPROC=y
CONFIG_REMOTEPROC_CDEV=y
CONFIG_QCOM_Q6V5_ADSP=m
CONFIG_QCOM_Q6V5_MSS=m
CONFIG_QCOM_Q6V5_PAS=m
CONFIG_QCOM_SYSMON=m
CONFIG_RPMSG_CHAR=m
CONFIG_RPMSG_NS=m
CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_RPMSG_QCOM_GLINK_SMEM=y
CONFIG_RPMSG_QCOM_SMD=m
CONFIG_SOUNDWIRE=m
CONFIG_SOUNDWIRE_QCOM=m
CONFIG_QCOM_CPR3=y
CONFIG_QCOM_RMTFS_MEM=m
CONFIG_QCOM_RPMPD=y
CONFIG_QCOM_SMEM=y
CONFIG_QCOM_SMD_RPM=y
CONFIG_QCOM_SMP2P=m
CONFIG_QCOM_SPM=y
CONFIG_QCOM_STATS=m
CONFIG_QCOM_APR=m
CONFIG_QCOM_ICC_BWMON=y
CONFIG_IIO=y
CONFIG_QCOM_SPMI_VADC=y
CONFIG_QCOM_SPMI_ADC5=y
CONFIG_PWM=y
CONFIG_PHY_QCOM_QMP=y
CONFIG_PHY_QCOM_QUSB2=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDERFS=y
CONFIG_NVMEM_QCOM_QFPROM=y
CONFIG_SLIM_QCOM_CTRL=m
CONFIG_SLIM_QCOM_NGD_CTRL=m
CONFIG_INTERCONNECT=y
CONFIG_INTERCONNECT_QCOM=y
CONFIG_INTERCONNECT_QCOM_MSM8998=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
# CONFIG_DNOTIFY is not set
CONFIG_FANOTIFY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_QFMT_V2=y
CONFIG_FUSE_FS=m
CONFIG_OVERLAY_FS=m
CONFIG_VFAT_FS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON=y
CONFIG_SQUASHFS=m
CONFIG_SQUASHFS_FILE_DIRECT=y
CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_XZ=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_UNICODE=y
CONFIG_KEY_DH_OPERATIONS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_MD5=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
# CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set
CONFIG_CRYPTO_NHPOLY1305_NEON=m
CONFIG_CRYPTO_CHACHA20_NEON=m
CONFIG_CRYPTO_GHASH_ARM64_CE=m
CONFIG_CRYPTO_POLY1305_NEON=m
CONFIG_CRYPTO_SHA1_ARM64_CE=m
CONFIG_CRYPTO_SHA2_ARM64_CE=m
CONFIG_CRYPTO_SHA512_ARM64_CE=m
CONFIG_CRYPTO_POLYVAL_ARM64_CE=m
CONFIG_CRYPTO_AES_ARM64=m
CONFIG_CRYPTO_AES_ARM64_CE_BLK=m
CONFIG_CRYPTO_AES_ARM64_BS=m
CONFIG_CRYPTO_SM4_ARM64_CE_BLK=m
CONFIG_CRYPTO_SM4_ARM64_NEON_BLK=m
CONFIG_CRYPTO_AES_ARM64_CE_CCM=m
CONFIG_PKCS8_PRIVATE_KEY_PARSER=m
CONFIG_FORCE_NR_CPUS=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_RCU_TRACE is not set
# CONFIG_FTRACE is not set
# CONFIG_RUNTIME_TESTING_MENU is not set

View file

@ -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,
},
};
@ -2885,6 +2887,43 @@ static struct clk_branch ssc_cnoc_ahbs_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,
@ -2915,6 +2954,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,
@ -3092,12 +3151,17 @@ static struct clk_regmap *gcc_msm8998_clocks[] = {
[AGGRE2_SNOC_NORTH_AXI] = &aggre2_snoc_north_axi_clk.clkr,
[SSC_XO] = &ssc_xo_clk.clkr,
[SSC_CNOC_AHBS_CLK] = &ssc_cnoc_ahbs_clk.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[] = {
@ -3247,6 +3311,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);
}

View file

@ -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,
},
};

View file

@ -138,6 +138,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,sa8540p" },

File diff suppressed because it is too large Load diff

View file

@ -133,7 +133,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

View file

@ -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);
@ -1684,6 +1731,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,
@ -1706,6 +1767,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,

View file

@ -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];

View file

@ -371,6 +371,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/a619_gmu.bin");
MODULE_FIRMWARE("qcom/a630_sqe.fw");
MODULE_FIRMWARE("qcom/a630_gmu.bin");

View file

@ -98,7 +98,7 @@ static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx)
static inline bool dpu_hw_ctl_is_started(struct dpu_hw_ctl *ctx)
{
return !!(DPU_REG_READ(&ctx->hw, CTL_START) & BIT(0));
return true;
}
static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx)

View file

@ -122,7 +122,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);
@ -443,12 +443,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);

View file

@ -484,6 +484,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

View file

@ -47,6 +47,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

View file

@ -0,0 +1,361 @@
// 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;
/*
* TODO: Remove once all drm drivers call
* drm_connector_set_orientation_from_panel()
*/
drm_connector_set_panel_orientation(connector, ctx->orientation);
drm_mode_probed_add(connector, mode);
return 1;
}
static enum drm_panel_orientation s6e3fa5_get_orientation(struct drm_panel *panel)
{
struct s6e3fa5 *ctx = to_s6e3fa5_panel(panel);
return ctx->orientation;
}
static const struct drm_panel_funcs s6e3fa5_panel_funcs = {
.prepare = s6e3fa5_prepare,
.unprepare = s6e3fa5_unprepare,
.get_modes = s6e3fa5_get_modes,
.get_orientation = s6e3fa5_get_orientation,
};
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 void 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);
}
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");

View file

@ -0,0 +1,343 @@
// 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 void 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);
}
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");

View file

@ -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).

View file

@ -246,6 +246,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

View file

@ -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

View 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");

View file

@ -186,6 +186,21 @@ config INPUT_PMIC8XXX_PWRKEY
To compile this driver as a module, choose M here: the
module will be called pmic8xxx-pwrkey.
config INPUT_QCOM_PMI8998_HAPTICS
tristate "Qualcomm SPMI HAPTICS"
depends on ARCH_QCOM || COMPILE_TEST
depends on MFD_PM8XXX || MFD_SPMI_PMIC || COMPILE_TEST
select INPUT_FF_MEMLESS
help
This option enables support for the haptics found in pmi8998 and
related PMICs. Based on the ff-memless interface.
This driver is for hardware too new for the INPUT_PM8XXX_VIBRATOR
driver.
To compile this driver as module, choose M here: the
module will be called qcom_pmi8998_haptics.
config INPUT_SPARCSPKR
tristate "SPARC Speaker support"
depends on PCI && SPARC64

View file

@ -66,6 +66,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_PMI8998_HAPTICS)+= qcom-pmi8998-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

View file

@ -0,0 +1,690 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022, Caleb Connolly <caleb@connolly.tech>
* Qualcomm QPMI haptics driver for pmi8998 and related PMICs.
*/
#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/time.h>
#include <linux/types.h>
// clang-format off
#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 // As CFG2 is the most significant byte
#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
// Actuator types
#define HAP_TYPE_LRA 0
#define HAP_TYPE_ERM 1
// LRA Wave type
#define HAP_WAVE_SINE 0
#define HAP_WAVE_SQUARE 1
// Play modes
#define HAP_PLAY_DIRECT 0
#define HAP_PLAY_BUFFER 1
#define HAP_PLAY_AUDIO 2
#define HAP_PLAY_PWM 3
#define HAP_PLAY_MAX HAP_PLAY_PWM
// Auto resonance type
#define HAP_AUTO_RES_NONE 0
#define HAP_AUTO_RES_ZXD 1
#define HAP_AUTO_RES_QWD 2
#define HAP_AUTO_RES_MAX_QWD 3
#define HAP_AUTO_RES_ZXD_EOP 4
// clang-format on
static const uint8_t default_brake_pattern[] = {
0x3, 0x3, 0x3, 0x3, 0x3,
};
static const uint8_t wave_sample_pattern[] = {
0x7e, 0x7e, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
};
/**
* struct spmi_haptics - struct for spmi haptics data.
*
* @dev: Our device parent.
* @regmap: Register map for the hardware block.
* @input: The input device used to receive events.
* @work: Work struct to play effects.
* @base: Base address of the regmap.
* @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).
* @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.
* @play_lock: Lock to be held when updating the hardware state.
*/
struct spmi_haptics {
struct device *dev;
struct regmap *regmap;
struct input_dev *input;
struct work_struct work;
uint32_t base;
int play_irq;
int sc_irq;
ktime_t last_sc_time;
uint8_t sc_count;
uint8_t actuator_type;
uint8_t wave_shape;
uint8_t play_mode;
uint32_t vmax;
uint32_t current_limit;
uint32_t play_wave_rate;
struct mutex play_lock;
};
static int haptics_write_vmax(struct spmi_haptics *haptics)
{
uint8_t val = 0;
uint32_t vmax_mv = haptics->vmax;
vmax_mv = clamp_t(uint32_t, vmax_mv, HAP_VMAX_MIN_MV, HAP_VMAX_MAX_MV);
vmax_mv = DIV_ROUND_CLOSEST(vmax_mv, HAP_VMAX_MIN_MV);
val = FIELD_PREP(HAP_VMAX_MASK, vmax_mv);
return regmap_update_bits(haptics->regmap,
haptics->base + HAP_VMAX_CFG_REG,
HAP_VMAX_MASK | HAP_WF_OVD_BIT, val);
}
static int haptics_module_enable(struct spmi_haptics *haptics, bool enable)
{
return regmap_update_bits(haptics->regmap,
haptics->base + HAP_EN_CTL_REG, HAP_EN_BIT,
enable ? HAP_EN_BIT : 0);
}
static int haptics_play(struct spmi_haptics *haptics, bool play)
{
return regmap_update_bits(haptics->regmap, haptics->base + HAP_PLAY_REG,
HAP_PLAY_BIT | HAP_PAUSE_BIT,
play ? HAP_PLAY_BIT : 0);
}
static bool is_haptics_module_enabled(struct spmi_haptics *haptics)
{
uint32_t val;
regmap_read(haptics->regmap, haptics->base + HAP_EN_CTL_REG, &val);
return !!val;
}
/*
* 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 haptics_play_irq(int irq, void *data)
{
struct spmi_haptics *haptics = data;
dev_dbg(haptics->dev, "play_irq triggered");
return IRQ_HANDLED;
}
/*
* 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.
*/
static irqreturn_t haptics_sc_irq(int irq, void *data)
{
struct spmi_haptics *haptics = data;
int ret;
uint32_t val;
long sc_delta_time_us;
ktime_t temp;
mutex_lock(&haptics->play_lock);
ret = regmap_read(haptics->regmap, haptics->base + HAP_STATUS_1_REG,
&val);
if (ret)
goto out;
if (!(val & SC_FLAG_BIT)) {
haptics->sc_count = 0;
goto out;
}
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++;
ret = regmap_update_bits(haptics->regmap,
haptics->base + HAP_SC_CLR_REG, SC_CLR_BIT,
SC_CLR_BIT);
if (ret)
goto out;
if (haptics->sc_count > SC_MAX_COUNT) {
cancel_work_sync(&haptics->work);
dev_err(haptics->dev,
"Short circuit persists, disabling haptics\n");
ret = haptics_module_enable(haptics, false);
if (ret)
dev_err(haptics->dev, "Error disabling module, rc=%d\n",
ret);
}
out:
mutex_unlock(&haptics->play_lock);
return IRQ_HANDLED;
}
static int haptics_vibrate(struct spmi_haptics *haptics)
{
int ret;
if (haptics->sc_count > SC_MAX_COUNT) {
dev_err(haptics->dev, "Can't play while in short circuit");
return -EINVAL;
}
ret = haptics_write_vmax(haptics);
if (ret)
return ret;
ret = haptics_module_enable(haptics, true);
if (ret) {
dev_err(haptics->dev, "Error enabling module, ret=%d\n", ret);
return ret;
}
ret = haptics_play(haptics, true);
if (ret) {
dev_err(haptics->dev, "Error enabling play, ret=%d\n", ret);
return ret;
}
return ret;
}
static int haptics_stop_vibrate(struct spmi_haptics *haptics)
{
int ret;
ret = haptics_play(haptics, false);
if (ret) {
dev_err(haptics->dev, "Error disabling play, ret=%d\n", ret);
return ret;
}
ret = haptics_module_enable(haptics, false);
if (ret) {
dev_err(haptics->dev, "Error disabling module, ret=%d\n", ret);
return ret;
}
return ret;
}
static void haptics_play_stop_work(struct work_struct *work)
{
struct spmi_haptics *haptics =
container_of(work, struct spmi_haptics, work);
int ret;
mutex_lock(&haptics->play_lock);
if (!is_haptics_module_enabled(haptics) && haptics->vmax)
ret = haptics_vibrate(haptics);
else
ret = haptics_stop_vibrate(haptics);
if (ret)
dev_err(haptics->dev, "Error setting haptics, ret=%d", ret);
mutex_unlock(&haptics->play_lock);
}
static int spmi_haptics_play_effect(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
struct spmi_haptics *haptics = input_get_drvdata(dev);
uint32_t magnitude;
dev_dbg(haptics->dev, "%s: Rumbling with strong: %d and weak: %d",
__func__, effect->u.rumble.strong_magnitude,
effect->u.rumble.weak_magnitude);
magnitude = effect->u.rumble.strong_magnitude >> 8;
if (!magnitude)
magnitude = effect->u.rumble.weak_magnitude >> 10;
if (!magnitude)
haptics->vmax = 0;
else
haptics->vmax =
((HAP_VMAX_MAX_MV - HAP_VMAX_MIN_MV) * magnitude) /
100 +
HAP_VMAX_MIN_MV;
schedule_work(&haptics->work);
return 0;
}
/**
* 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);
haptics->vmax = 0;
if (is_haptics_module_enabled(haptics))
haptics_stop_vibrate(haptics);
}
static int haptics_write_brake_pattern(struct spmi_haptics *haptics,
const uint8_t *brake_pattern)
{
int ret, i;
uint8_t val = 0;
for (i = HAP_BRAKE_PAT_LEN - 1; i >= 0; i--)
val |= FIELD_PREP(HAP_BRAKE_PAT_MASK, brake_pattern[i])
<< (i * 2);
ret = regmap_update_bits(haptics->regmap, haptics->base + HAP_BRAKE_REG,
0xff, val);
return ret ?:
regmap_update_bits(haptics->regmap,
haptics->base + HAP_EN_CTL2_REG,
BRAKE_EN_BIT, BRAKE_EN_BIT);
}
static int haptics_init(struct spmi_haptics *haptics)
{
int ret;
uint8_t val, mask;
uint16_t play_rate;
ret = regmap_update_bits(haptics->regmap, haptics->base + HAP_CFG1_REG,
HAP_ACT_TYPE_MASK, haptics->actuator_type);
if (ret)
return ret;
/*
* Configure auto resonance
* see qpnp_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 = regmap_update_bits(haptics->regmap,
haptics->base + HAP_LRA_AUTO_RES_REG, mask,
val);
if (ret)
return ret;
val = FIELD_PREP(HAP_WF_SOURCE_MASK, haptics->play_mode);
ret = regmap_update_bits(haptics->regmap, haptics->base + HAP_SEL_REG,
HAP_WF_SOURCE_MASK, val);
if (ret)
return ret;
ret = regmap_update_bits(haptics->regmap,
haptics->base + HAP_ILIM_CFG_REG,
HAP_ILIM_SEL_MASK, haptics->current_limit);
if (ret)
return ret;
/* Configure the debounce for short-circuit detection. */
ret = regmap_update_bits(haptics->regmap,
haptics->base + HAP_SC_DEB_REG,
HAP_SC_DEB_MASK, HAP_SC_DEB_CYCLES_MAX);
if (ret)
return ret;
ret = regmap_update_bits(haptics->regmap, haptics->base + HAP_CFG2_REG,
HAP_LRA_RES_TYPE_MASK, haptics->wave_shape);
if (ret)
return ret;
/*
* Configure RATE_CFG1 and RATE_CFG2 registers.
* Note: For ERM (unsupported) these registers act as play rate and
* for LRA these represent resonance period
*/
play_rate = haptics->play_wave_rate / HAP_RATE_CFG_STEP_US;
val = FIELD_PREP(HAP_RATE_CFG1_MASK, play_rate);
ret = regmap_update_bits(haptics->regmap,
haptics->base + HAP_RATE_CFG1_REG,
HAP_RATE_CFG1_MASK, val);
val = FIELD_PREP(HAP_RATE_CFG2_MASK, play_rate >> 8);
ret = ret ?:
regmap_update_bits(haptics->regmap,
haptics->base + HAP_RATE_CFG2_REG,
HAP_RATE_CFG1_MASK, val);
if (ret)
return ret;
ret = haptics_write_brake_pattern(haptics, default_brake_pattern);
if (ret)
return ret;
/* Currently this is the only supported play mode */
if (haptics->play_mode == HAP_PLAY_BUFFER) {
/* zero repeats and zero sample repeats */
val = FIELD_PREP(WF_REPEAT_MASK, 0) |
FIELD_PREP(WF_S_REPEAT_MASK, 0);
ret = regmap_update_bits(haptics->regmap,
haptics->base + HAP_WF_REPEAT_REG,
WF_REPEAT_MASK | WF_S_REPEAT_MASK,
val);
if (ret)
return ret;
ret = regmap_bulk_write(haptics->regmap,
haptics->base + HAP_WF_S1_REG,
wave_sample_pattern, HAP_WAVE_SAMP_LEN);
if (ret)
return ret;
}
return 0;
}
static int spmi_haptics_probe(struct platform_device *pdev)
{
struct spmi_haptics *haptics;
struct input_dev *input_dev;
int ret, irq;
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;
haptics->dev = &pdev->dev;
platform_set_drvdata(pdev, haptics);
ret = device_property_read_u32(haptics->dev, "reg", &haptics->base);
if (ret)
return dev_err_probe(haptics->dev, ret,
"Couldn't read base address");
/* This is the only currently supported configuration, these values
* are left to allow future additions
*/
haptics->actuator_type = HAP_TYPE_LRA;
haptics->play_mode = HAP_PLAY_BUFFER;
haptics->wave_shape = HAP_WAVE_SINE;
haptics->current_limit = HAP_ILIM_400_MA;
ret = device_property_read_u32(haptics->dev, "qcom,wave-play-rate-us",
&haptics->play_wave_rate);
if (ret)
return dev_err_probe(haptics->dev, ret,
"qcom,wave-play-rate-us is required\n");
INIT_WORK(&haptics->work, haptics_play_stop_work);
ret = haptics_init(haptics);
if (ret)
return ret;
input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev)
return -ENOMEM;
input_dev->name = "spmi_haptics";
input_dev->id.version = 1;
input_dev->close = spmi_haptics_close;
input_set_drvdata(input_dev, haptics);
haptics->input = input_dev;
/* In the future this should become FF_PERIODIC */
input_set_capability(haptics->input, EV_FF, FF_RUMBLE);
ret = input_ff_create_memless(input_dev, NULL,
spmi_haptics_play_effect);
if (ret)
return dev_err_probe(
&pdev->dev, ret,
"Couldn't register haptics as EV_FF device\n");
ret = input_register_device(input_dev);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"Couldn't register input device\n");
/* NOTE: the play IRQ is only used for buffer mode */
irq = platform_get_irq_byname(pdev, "play");
if (irq < 0) {
return dev_err_probe(&pdev->dev, irq,
"Unable to get play irq\n");
}
ret = devm_request_threaded_irq(haptics->dev, irq, NULL,
haptics_play_irq, IRQF_ONESHOT,
"haptics_play_irq", haptics);
if (ret)
return dev_err_probe(haptics->dev, ret,
"Couldn't request play irq\n");
irq = platform_get_irq_byname(pdev, "short");
if (irq < 0)
return dev_err_probe(&pdev->dev, irq,
"Unable to get short circut irq\n");
ret = devm_request_threaded_irq(haptics->dev, irq, NULL, haptics_sc_irq,
IRQF_ONESHOT, "haptics_short_irq",
haptics);
if (ret)
return dev_err_probe(haptics->dev, ret,
"Couldn't request short circuit irq\n");
mutex_init(&haptics->play_lock);
return 0;
}
static int __maybe_unused spmi_haptics_suspend(struct device *dev)
{
struct spmi_haptics *haptics = dev_get_drvdata(dev);
cancel_work_sync(&haptics->work);
haptics_stop_vibrate(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->input);
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);
haptics_stop_vibrate(haptics);
}
static const struct of_device_id spmi_haptics_match_table[] = {
{ .compatible = "qcom,pmi8998-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");
MODULE_AUTHOR("Caleb Connolly <caleb@connolly.tech>");

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View 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,
};

View file

@ -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

View file

@ -8,6 +8,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
@ -32,6 +33,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

View file

@ -0,0 +1,983 @@
// 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);
icc_provider_del(&qp->provider);
return 0;
}
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");

View file

@ -197,11 +197,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;
}
@ -245,12 +247,14 @@ 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,sm8250-mdss" },
{ .compatible = "qcom,sdm660-mss-pil" },
{ .compatible = "qcom,sdm845-mdss" },
{ .compatible = "qcom,sdm845-mss-pil" },
{ }
@ -285,7 +289,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);
@ -377,8 +382,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);
@ -386,11 +398,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,
.tlb_sync = qcom_smmu_tlb_sync,
};
@ -399,6 +420,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,
.tlb_sync = qcom_smmu_tlb_sync,
@ -407,7 +429,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())
@ -419,6 +444,34 @@ static struct arm_smmu_device *qcom_smmu_create(struct arm_smmu_device *smmu,
qsmmu->smmu.impl = impl;
qsmmu->cfg = qcom_smmu_impl_data(smmu);
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;
}

View file

@ -9,6 +9,7 @@
struct qcom_smmu {
struct arm_smmu_device smmu;
const struct qcom_smmu_config *cfg;
DECLARE_BITMAP(reset_cb_nodisable_mask, ARM_SMMU_MAX_CBS);
bool bypass_quirk;
u8 bypass_cbndx;
u32 stall_enabled;

View file

@ -1600,6 +1600,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);
}

View file

@ -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,

View file

@ -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. */

View file

@ -2099,6 +2099,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

View file

@ -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

300
drivers/mfd/wcd9335.c Normal file
View file

@ -0,0 +1,300 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019, Linaro Limited
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/mfd/wcd9335/registers.h>
#include <linux/mfd/wcd9335/wcd9335.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slimbus.h>
#define WCD9335_REGMAP_IRQ_REG(_irq, _off, _mask) \
[_irq] = { \
.reg_offset = (_off), \
.mask = (_mask), \
.type = { \
.type_reg_offset = (_off), \
.types_supported = IRQ_TYPE_EDGE_BOTH, \
.type_reg_mask = (_mask), \
.type_level_low_val = (_mask), \
.type_level_high_val = (_mask), \
.type_falling_val = 0, \
.type_rising_val = 0, \
}, \
}
static const struct mfd_cell wcd9335_devices[] = {
{
.name = "wcd9335-codec",
}, {
.name = "wcd9335-gpio",
.of_compatible = "qcom,wcd9340-gpio",
}, {
.name = "wcd9335-soundwire",
.of_compatible = "qcom,soundwire-v1.3.0",
},
};
static const struct regmap_irq wcd9335_irqs[] = {
WCD9335_REGMAP_IRQ_REG(WCD9335_IRQ_SLIMBUS, 0, BIT(0)),
WCD9335_REGMAP_IRQ_REG(WCD9335_IRQ_HPH_PA_OCPL_FAULT, 0, BIT(2)),
WCD9335_REGMAP_IRQ_REG(WCD9335_IRQ_HPH_PA_OCPR_FAULT, 0, BIT(3)),
WCD9335_REGMAP_IRQ_REG(WCD9335_IRQ_MBHC_SW_DET, 1, BIT(0)),
WCD9335_REGMAP_IRQ_REG(WCD9335_IRQ_MBHC_ELECT_INS_REM_DET, 1, BIT(1)),
WCD9335_REGMAP_IRQ_REG(WCD9335_IRQ_MBHC_BUTTON_PRESS_DET, 1, BIT(2)),
WCD9335_REGMAP_IRQ_REG(WCD9335_IRQ_MBHC_BUTTON_RELEASE_DET, 1, BIT(3)),
WCD9335_REGMAP_IRQ_REG(WCD9335_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 1, BIT(4)),
WCD9335_REGMAP_IRQ_REG(WCD9335_IRQ_SOUNDWIRE, 2, BIT(4)),
};
static const struct regmap_irq_chip wcd9335_regmap_irq_chip = {
.name = "wcd9335_irq",
.status_base = WCD9335_INTR_PIN1_STATUS0,
.mask_base = WCD9335_INTR_PIN1_MASK0,
.ack_base = WCD9335_INTR_PIN1_CLEAR0,
.type_base = WCD9335_INTR_LEVEL0,
.num_type_reg = 4,
.type_in_mask = false,
.num_regs = 4,
.irqs = wcd9335_irqs,
.num_irqs = ARRAY_SIZE(wcd9335_irqs),
};
static bool wcd9335_is_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case WCD9335_INTR_PIN1_STATUS0...WCD9335_INTR_PIN2_CLEAR3:
case WCD9335_SWR_AHB_BRIDGE_RD_DATA_0:
case WCD9335_SWR_AHB_BRIDGE_RD_DATA_1:
case WCD9335_SWR_AHB_BRIDGE_RD_DATA_2:
case WCD9335_SWR_AHB_BRIDGE_RD_DATA_3:
case WCD9335_SWR_AHB_BRIDGE_ACCESS_STATUS:
case WCD9335_ANA_MBHC_RESULT_3:
case WCD9335_ANA_MBHC_RESULT_2:
case WCD9335_ANA_MBHC_RESULT_1:
case WCD9335_ANA_MBHC_MECH:
case WCD9335_ANA_MBHC_ELECT:
case WCD9335_ANA_MBHC_ZDET:
case WCD9335_ANA_MICB2:
case WCD9335_ANA_RCO:
case WCD9335_ANA_BIAS:
return true;
default:
return false;
}
};
static const struct regmap_range_cfg wcd9335_ranges[] = {
{ .name = "WCD9335",
.range_min = 0x0,
.range_max = WCD9335_MAX_REGISTER,
.selector_reg = WCD9335_SEL_REGISTER,
.selector_mask = WCD9335_SEL_MASK,
.selector_shift = WCD9335_SEL_SHIFT,
.window_start = WCD9335_WINDOW_START,
.window_len = WCD9335_WINDOW_LENGTH,
},
};
static struct regmap_config wcd9335_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
.max_register = 0xffff,
.can_multi_write = true,
.ranges = wcd9335_ranges,
.num_ranges = ARRAY_SIZE(wcd9335_ranges),
.volatile_reg = wcd9335_is_volatile_register,
};
static int wcd9335_bring_up(struct wcd9335_ddata *ddata)
{
struct regmap *regmap = ddata->regmap;
u16 id_minor, id_major;
int ret;
ret = regmap_bulk_read(regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
(u8 *)&id_minor, sizeof(u16));
if (ret)
return ret;
ret = regmap_bulk_read(regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE2,
(u8 *)&id_major, sizeof(u16));
if (ret)
return ret;
dev_info(ddata->dev, "WCD934x chip id major 0x%x, minor 0x%x\n",
id_major, id_minor);
regmap_write(regmap, WCD9335_CODEC_RPM_RST_CTL, 0x01);
regmap_write(regmap, WCD9335_SIDO_NEW_VOUT_A_STARTUP, 0x19);
regmap_write(regmap, WCD9335_SIDO_NEW_VOUT_D_STARTUP, 0x15);
/* Add 1msec delay for VOUT to settle */
usleep_range(1000, 1100);
regmap_write(regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
regmap_write(regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7);
regmap_write(regmap, WCD9335_CODEC_RPM_RST_CTL, 0x3);
regmap_write(regmap, WCD9335_CODEC_RPM_RST_CTL, 0x7);
regmap_write(regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
return 0;
}
static int wcd9335_slim_status_up(struct slim_device *sdev)
{
struct device *dev = &sdev->dev;
struct wcd9335_ddata *ddata;
int ret;
ddata = dev_get_drvdata(dev);
ddata->regmap = regmap_init_slimbus(sdev, &wcd9335_regmap_config);
if (IS_ERR(ddata->regmap)) {
dev_err(dev, "Error allocating slim regmap\n");
return PTR_ERR(ddata->regmap);
}
ret = wcd9335_bring_up(ddata);
if (ret) {
dev_err(dev, "Failed to bring up WCD9335: err = %d\n", ret);
return ret;
}
ret = devm_regmap_add_irq_chip(dev, ddata->regmap, ddata->irq,
IRQF_TRIGGER_HIGH, 0,
&wcd9335_regmap_irq_chip,
&ddata->irq_data);
if (ret) {
dev_err(dev, "Failed to add IRQ chip: err = %d\n", ret);
return ret;
}
ret = mfd_add_devices(dev, PLATFORM_DEVID_AUTO, wcd9335_devices,
ARRAY_SIZE(wcd9335_devices), NULL, 0, NULL);
if (ret) {
dev_err(dev, "Failed to add child devices: err = %d\n",
ret);
return ret;
}
return ret;
}
static int wcd9335_slim_status(struct slim_device *sdev,
enum slim_device_status status)
{
switch (status) {
case SLIM_DEVICE_STATUS_UP:
return wcd9335_slim_status_up(sdev);
case SLIM_DEVICE_STATUS_DOWN:
mfd_remove_devices(&sdev->dev);
break;
default:
return -EINVAL;
}
return 0;
}
static int wcd9335_slim_probe(struct slim_device *sdev)
{
struct device *dev = &sdev->dev;
struct device_node *np = dev->of_node;
struct wcd9335_ddata *ddata;
int reset_gpio, ret;
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
ddata->irq = of_irq_get(np, 0);
if (ddata->irq < 0)
return dev_err_probe(ddata->dev, ddata->irq,
"Failed to get IRQ\n");
reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
if (reset_gpio < 0) {
dev_err(dev, "Failed to get reset gpio: err = %d\n",
reset_gpio);
return reset_gpio;
}
ddata->extclk = devm_clk_get(dev, "extclk");
if (IS_ERR(ddata->extclk)) {
dev_err(dev, "Failed to get extclk");
return PTR_ERR(ddata->extclk);
}
ddata->supplies[0].supply = "vdd-buck";
ddata->supplies[1].supply = "vdd-buck-sido";
ddata->supplies[2].supply = "vdd-tx";
ddata->supplies[3].supply = "vdd-rx";
ddata->supplies[4].supply = "vdd-io";
ret = regulator_bulk_get(dev, WCD9335_MAX_SUPPLY, ddata->supplies);
if (ret) {
dev_err(dev, "Failed to get supplies: err = %d\n", ret);
return ret;
}
ret = regulator_bulk_enable(WCD9335_MAX_SUPPLY, ddata->supplies);
if (ret) {
dev_err(dev, "Failed to enable supplies: err = %d\n", ret);
return ret;
}
/*
* For WCD9335, it takes about 600us for the Vout_A and
* Vout_D to be ready after BUCK_SIDO is powered up.
* SYS_RST_N shouldn't be pulled high during this time
*/
usleep_range(600, 650);
gpio_direction_output(reset_gpio, 0);
msleep(20);
gpio_set_value(reset_gpio, 1);
msleep(20);
ddata->dev = dev;
dev_set_drvdata(dev, ddata);
return 0;
}
static void wcd9335_slim_remove(struct slim_device *sdev)
{
struct wcd9335_ddata *ddata = dev_get_drvdata(&sdev->dev);
regulator_bulk_disable(WCD9335_MAX_SUPPLY, ddata->supplies);
mfd_remove_devices(&sdev->dev);
}
static const struct slim_device_id wcd9335_slim_id[] = {
{ SLIM_MANF_ID_QCOM, SLIM_PROD_CODE_WCD9340,
SLIM_DEV_IDX_WCD9340, SLIM_DEV_INSTANCE_ID_WCD9340 },
{}
};
static struct slim_driver wcd9335_slim_driver = {
.driver = {
.name = "wcd9335-slim",
},
.probe = wcd9335_slim_probe,
.remove = wcd9335_slim_remove,
.device_status = wcd9335_slim_status,
.id_table = wcd9335_slim_id,
};
module_slim_driver(wcd9335_slim_driver);
MODULE_DESCRIPTION("WCD9335 slim driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("slim:217:250:*");
MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");

View file

@ -395,6 +395,7 @@ ipa_power_init(struct device *dev, const struct ipa_power_data *data)
pm_runtime_set_autosuspend_delay(dev, IPA_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(dev);
pm_runtime_forbid(dev);
pm_runtime_enable(dev);
return power;

View file

@ -1004,6 +1004,8 @@ static void ath10k_qmi_driver_event_work(struct work_struct *work)
switch (event->type) {
case ATH10K_QMI_EVENT_SERVER_ARRIVE:
ath10k_qmi_event_server_arrive(qmi);
// HACK: Fake MSA being ready
ath10k_qmi_event_msa_ready(qmi);
break;
case ATH10K_QMI_EVENT_SERVER_EXIT:
ath10k_qmi_event_server_exit(qmi);

View file

@ -127,6 +127,23 @@ config PINCTRL_AXP209
selected.
Say Y to enable pinctrl and GPIO support for the AXP209 PMIC.
config PINCTRL_AW9523
bool "Awinic AW9523/AW9523B I2C GPIO expander pinctrl driver"
depends on OF && I2C
select PINMUX
select PINCONF
select GENERIC_PINCONF
select GPIOLIB
select GPIOLIB_IRQCHIP
select REGMAP_I2C
help
The Awinic AW9523/AW9523B is a multi-function I2C GPIO
expander with PWM functionality. This driver bundles a
pinctrl driver to select the function muxing and a GPIO
driver to handle GPIO, when the GPIO function is selected.
Say yes to enable pinctrl and GPIO support for the AW9523(B).
config PINCTRL_BM1880
bool "Bitmain BM1880 Pinctrl driver"
depends on OF && (ARCH_BITMAIN || COMPILE_TEST)

View file

@ -15,6 +15,7 @@ obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl-artpec6.o
obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o
obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o
obj-$(CONFIG_PINCTRL_AW9523) += pinctrl-aw9523.o
obj-$(CONFIG_PINCTRL_AXP209) += pinctrl-axp209.o
obj-$(CONFIG_PINCTRL_BM1880) += pinctrl-bm1880.o
obj-$(CONFIG_PINCTRL_CY8C95X0) += pinctrl-cy8c95x0.o

File diff suppressed because it is too large Load diff

View file

@ -918,4 +918,30 @@ config BATTERY_UG3105
device is off or suspended, the functionality of this driver is
limited to reporting capacity only.
config CHARGER_QCOM_SMB2
tristate "Qualcomm PMI8998 PMIC charger driver"
depends on MFD_SPMI_PMIC
depends on IIO
select QCOM_SPMI_RRADC
help
Driver for the "SMB2" charger block found on Qualcomm PMI8998
and PM660 PMICs.
The charger features automatic power source detection via BC1.2,
automatic input current limiting and reports the realtime voltage
and current via the Round Robin ADC.
Say Y or M here to enable reporting the charger status and rate on
supported platforms such as Snapdragon 845 and 835 based phones.
config BATTERY_QCOM_FG
tristate "Qualcomm PMIC fuel gauge driver"
depends on MFD_SPMI_PMIC
help
Say Y here to enable the Qualcomm PMIC Fuel Gauge driver. This
adds support for battery fuel gauging and state of charge of
battery connected to the fuel gauge. The state of charge is
reported through a BMS power supply property and also sends
uevents when the capacity is updated.
endif # POWER_SUPPLY

View file

@ -83,6 +83,7 @@ obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
obj-$(CONFIG_CHARGER_MP2629) += mp2629_charger.o
obj-$(CONFIG_CHARGER_MT6360) += mt6360_charger.o
obj-$(CONFIG_CHARGER_MT6370) += mt6370-charger.o
obj-$(CONFIG_CHARGER_QCOM_SMB2) += qcom_pmi8998_charger.o
obj-$(CONFIG_CHARGER_QCOM_SMBB) += qcom_smbb.o
obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o
@ -110,3 +111,4 @@ obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o
obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o
obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o
obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o
obj-$(CONFIG_BATTERY_QCOM_FG) += qcom_fg.o

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,176 @@
// #define FG_PARAM_MAX 49
/**** Registers *****/
#define PMIC_SUBTYPE 0x105
#define PMI8994_SUBTYPE 0x0a
#define PMI8996_SUBTYPE 0x13
#define PM8998_SUBTYPE 0x14
#define PMI8998_SUBTYPE 0x15
/* SRAM */
#define MEM_INTF_STS 0x10
#define MEM_INTF_CFG 0x50
#define MEM_INTF_CTL 0x51
#define MEM_INTF_IMA_CFG 0x52
#define MEM_INTF_IMA_OPR_STS 0x54
#define MEM_INTF_IMA_EXP_STS 0x55
#define MEM_INTF_IMA_HW_STS 0x56
#define MEM_INTF_BEAT_COUNT 0x57
#define MEM_INTF_IMA_ERR_STS 0x5f
#define MEM_INTF_IMA_BYTE_EN 0x60
#define MEM_INTF_ADDR_LSB 0x61
#define MEM_INTF_RD_DATA0 0x67
#define MEM_INTF_WR_DATA0 0x63
#define MEM_INTF_AVAIL BIT(0)
#define MEM_INTF_CTL_BURST BIT(7)
#define MEM_INTF_CTL_WR_EN BIT(6)
#define RIF_MEM_ACCESS_REQ BIT(7)
/* Battery info */
#define BATT_INFO_CHARGE_MAX_DESIGN 0x4a
#define BATT_INFO_THERM_C1 0x5c
#define BATT_INFO_VBATT_LSB 0xa0
#define BATT_INFO_VBATT_MSB 0xa1
#define BATT_INFO_IBATT_LSB 0xa2
#define BATT_INFO_IBATT_MSB 0xa3
#define BATT_INFO_BATT_TEMP_LSB 0x50
#define BATT_INFO_BATT_TEMP_MSB 0x51
#define BATT_MONOTONIC_SOC 0x09
#define BATT_TEMP_LSB_MASK GENMASK(7, 0)
#define BATT_TEMP_MSB_MASK GENMASK(2, 0)
/* Base addresses */
#define REG_BASE 0x4000
#define REG_BATT 0x4100
#define REG_MEM 0x4400
/* Interrupt offsets */
#define INT_RT_STS 0x10
#define INT_EN_CLR 0x16
/* Param addresses */
#define PARAM_ADDR_BATT_TEMP 0x50
#define PARAM_ADDR_BATT_VOLTAGE 0xa0
#define PARAM_ADDR_BATT_CURRENT 0xa2
#define MISC_BASE 0x1600
#define USBIN_BASE 0x1300
#define BATT_INFO_JEITA_COLD(chip) (REG_BATT + 0x62)
#define BATT_INFO_JEITA_COOL(chip) (REG_BATT + 0x63)
#define BATT_INFO_JEITA_WARM(chip) (REG_BATT + 0x64)
#define BATT_INFO_JEITA_HOT(chip) (REG_BATT + 0x65)
#define BATT_TEMP_JEITA_COLD 100
#define BATT_TEMP_JEITA_COOL 50
#define BATT_TEMP_JEITA_WARM 400
#define BATT_TEMP_JEITA_HOT 450
#define BATTERY_CHARGER_STATUS_REG(chip) (chip->chg_base + 0x06)
#define BATTERY_HEALTH_STATUS_REG(chip) (chip->chg_base + 0x07)
#define BATTERY_CHARGER_STATUS_MASK GENMASK(2, 0)
#define POWER_PATH_STATUS_REG (MISC_BASE + 0x0B)
#define MEM_IF_TIMEOUT_MS 5000
enum wa_flags {
PMI8998_V1_REV_WA,
PMI8998_V2_REV_WA,
};
enum pmic_rev_offsets {
DIG_MINOR = 0x0,
DIG_MAJOR = 0x1,
ANA_MINOR = 0x2,
ANA_MAJOR = 0x3,
};
enum pmic_rev {
DIG_REV_1 = 0x1,
DIG_REV_2 = 0x2,
DIG_REV_3 = 0x3,
};
enum charger_status{
TRICKLE_CHARGE = 0,
PRE_CHARGE,
FAST_CHARGE,
FULLON_CHARGE,
TAPER_CHARGE,
TERMINATE_CHARGE,
INHIBIT_CHARGE,
DISABLE_CHARGE,
};
static enum power_supply_property fg_properties[] = {
POWER_SUPPLY_PROP_MANUFACTURER,
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_TEMP_MIN,
POWER_SUPPLY_PROP_TEMP_MAX,
POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
};
struct qcom_fg_chip;
struct qcom_fg_ops {
int (*get_capacity)(struct qcom_fg_chip *chip, int *);
int (*get_temperature)(struct qcom_fg_chip *chip, int *);
int (*get_current)(struct qcom_fg_chip *chip, int *);
int (*get_voltage)(struct qcom_fg_chip *chip, int *);
int (*get_batt_status)(struct qcom_fg_chip *chip, int *);
int (*get_health_status)(struct qcom_fg_chip *chip, int *);
int (*get_temp_threshold)(struct qcom_fg_chip *chip,
enum power_supply_property psp, int *);
int (*set_temp_threshold)(struct qcom_fg_chip *chip,
enum power_supply_property psp, int);
};
struct qcom_fg_chip {
struct device *dev;
unsigned int base;
unsigned int chg_base;
struct regmap *regmap;
struct mutex lock;
unsigned int subtype;
const struct qcom_fg_ops *ops;
struct power_supply *bms_psy;
u8 revision[4];
bool ima_supported;
struct completion sram_access_granted;
int batt_cap_uah;
int batt_max_voltage_uv;
int batt_min_voltage_uv;
int health;
int status;
bool online;
};

File diff suppressed because it is too large Load diff

View file

@ -279,12 +279,6 @@ static irqreturn_t qcom_labibb_ocp_isr(int irq, void *chip)
}
vreg->ocp_irq_count++;
/*
* Disable the interrupt temporarily, or it will fire continuously;
* we will re-enable it in the recovery worker function.
*/
disable_irq_nosync(irq);
/* Warn the user for overcurrent */
dev_warn(vreg->dev, "Over-Current interrupt fired!\n");
@ -304,6 +298,12 @@ end:
if (ret)
return IRQ_NONE;
/*
* Disable the interrupt temporarily, or it will fire continuously;
* we will re-enable it in the recovery worker function.
*/
disable_irq_nosync(irq);
return IRQ_HANDLED;
}
@ -316,8 +316,11 @@ static int qcom_labibb_set_ocp(struct regulator_dev *rdev, int lim,
int irq_trig_low, ret;
/*
* labibb supports only protection - and does not support setting
* limit. Furthermore, we don't support disabling protection.
* labibb does not support specifying a current limit that is
* special to over-current protection, but only a global one
* that will be used for both current limiting and protection;
* for this reason, we only support enabling the OCP here.
* Furthermore, we don't support disabling protection.
*/
if (lim || severity != REGULATOR_SEVERITY_PROT || !enable)
return -EINVAL;
@ -540,12 +543,6 @@ static irqreturn_t qcom_labibb_sc_isr(int irq, void *chip)
/* Warn the user for short circuit */
dev_warn(vreg->dev, "Short-Circuit interrupt fired!\n");
/*
* Disable the interrupt temporarily, or it will fire continuously;
* we will re-enable it in the recovery worker function.
*/
disable_irq_nosync(irq);
/* Signal out of regulation event to drivers */
regulator_notifier_call_chain(vreg->rdev,
REGULATOR_EVENT_REGULATION_OUT, NULL);
@ -553,6 +550,13 @@ static irqreturn_t qcom_labibb_sc_isr(int irq, void *chip)
/* Schedule the short-circuit handling as high-priority work */
mod_delayed_work(system_highpri_wq, &vreg->sc_recovery_work,
msecs_to_jiffies(SC_RECOVERY_INTERVAL_MS));
/*
* Disable the interrupt temporarily, or it will fire continuously;
* we will re-enable it in the recovery worker function.
*/
disable_irq_nosync(irq);
return IRQ_HANDLED;
}

View file

@ -42,6 +42,23 @@ config QCOM_CPR
To compile this driver as a module, choose M here: the module will
be called qcom-cpr
config QCOM_CPR3
tristate "QCOM Core Power Reduction (CPR v3/v4/Hardened) support"
depends on ARCH_QCOM && HAS_IOMEM
select PM_OPP
select REGMAP
help
Say Y here to enable support for the CPR hardware found on a broad
variety of Qualcomm SoCs like MSM8996, MSM8998, SDM630, SDM660,
SDM845 and others.
This driver populates OPP tables and makes adjustments to them
based on feedback from the CPR hardware. If you want to do CPU
and/or GPU frequency scaling say Y here.
To compile this driver as a module, choose M here: the module will
be called qcom-cpr3
config QCOM_GENI_SE
tristate "QCOM GENI Serial Engine Driver"
depends on ARCH_QCOM || COMPILE_TEST

View file

@ -3,7 +3,8 @@ CFLAGS_rpmh-rsc.o := -I$(src)
obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o
obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
obj-$(CONFIG_QCOM_CPR) += cpr.o
obj-$(CONFIG_QCOM_CPR) += cpr-common.o cpr.o
obj-$(CONFIG_QCOM_CPR3) += cpr-common.o cpr3.o
obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
obj-$(CONFIG_QCOM_OCMEM) += ocmem.o

View file

@ -0,0 +1,372 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
* Copyright (c) 2019, Linaro Limited
*/
#include <linux/module.h>
#include <linux/err.h>
#include <linux/debugfs.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
#include <linux/interrupt.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
#include <linux/nvmem-consumer.h>
#include "cpr-common.h"
int cpr_populate_ring_osc_idx(struct device *dev,
struct fuse_corner *fuse_corner,
const struct cpr_fuse *cpr_fuse,
int num_fuse_corners)
{
struct fuse_corner *end = fuse_corner + num_fuse_corners;
u32 data;
int ret;
for (; fuse_corner < end; fuse_corner++, cpr_fuse++) {
ret = nvmem_cell_read_variable_le_u32(dev, cpr_fuse->ring_osc, &data);
if (ret)
return ret;
fuse_corner->ring_osc_idx = data;
}
return 0;
}
int cpr_read_fuse_uV(int init_v_width, int step_size_uV, int ref_uV,
int adj, int step_volt, const char *init_v_efuse,
struct device *dev)
{
int steps, uV;
u32 bits = 0;
int ret;
ret = nvmem_cell_read_variable_le_u32(dev, init_v_efuse, &bits);
if (ret)
return ret;
steps = bits & (BIT(init_v_width - 1) - 1);
/* Not two's complement.. instead highest bit is sign bit */
if (bits & BIT(init_v_width - 1))
steps = -steps;
uV = ref_uV + steps * step_size_uV;
/* Apply open-loop fixed adjustments to fused values */
uV += adj;
return DIV_ROUND_UP(uV, step_volt) * step_volt;
}
const struct cpr_fuse *cpr_get_fuses(struct device *dev, int tid,
int num_fuse_corners)
{
struct cpr_fuse *fuses;
int i;
fuses = devm_kcalloc(dev, num_fuse_corners,
sizeof(struct cpr_fuse),
GFP_KERNEL);
if (!fuses)
return ERR_PTR(-ENOMEM);
for (i = 0; i < num_fuse_corners; i++) {
char tbuf[50];
snprintf(tbuf, sizeof(tbuf), "cpr%d_ring_osc%d", tid, i + 1);
fuses[i].ring_osc = devm_kstrdup(dev, tbuf, GFP_KERNEL);
if (!fuses[i].ring_osc)
return ERR_PTR(-ENOMEM);
snprintf(tbuf, sizeof(tbuf),
"cpr%d_init_voltage%d", tid, i + 1);
fuses[i].init_voltage = devm_kstrdup(dev, tbuf,
GFP_KERNEL);
if (!fuses[i].init_voltage)
return ERR_PTR(-ENOMEM);
snprintf(tbuf, sizeof(tbuf), "cpr%d_quotient%d", tid, i + 1);
fuses[i].quotient = devm_kstrdup(dev, tbuf, GFP_KERNEL);
if (!fuses[i].quotient)
return ERR_PTR(-ENOMEM);
snprintf(tbuf, sizeof(tbuf),
"cpr%d_quotient_offset%d", tid, i + 1);
fuses[i].quotient_offset = devm_kstrdup(dev, tbuf,
GFP_KERNEL);
if (!fuses[i].quotient_offset)
return ERR_PTR(-ENOMEM);
}
return fuses;
}
int cpr_populate_fuse_common(struct device *dev,
struct fuse_corner_data *fdata,
const struct cpr_fuse *cpr_fuse,
struct fuse_corner *fuse_corner,
int step_volt, int init_v_width,
int init_v_step)
{
int uV, ret;
/* Populate uV */
uV = cpr_read_fuse_uV(init_v_width, init_v_step,
fdata->ref_uV, fdata->volt_oloop_adjust,
step_volt, cpr_fuse->init_voltage, dev);
if (uV < 0)
return uV;
/*
* Update SoC voltages: platforms might choose a different
* regulators than the one used to characterize the algorithms
* (ie, init_voltage_step).
*/
fdata->min_uV = roundup(fdata->min_uV, step_volt);
fdata->max_uV = roundup(fdata->max_uV, step_volt);
fuse_corner->min_uV = fdata->min_uV;
fuse_corner->max_uV = fdata->max_uV;
fuse_corner->uV = clamp(uV, fuse_corner->min_uV, fuse_corner->max_uV);
/* Populate target quotient by scaling */
ret = nvmem_cell_read_variable_le_u32(dev, cpr_fuse->quotient, &fuse_corner->quot);
if (ret)
return ret;
fuse_corner->quot *= fdata->quot_scale;
fuse_corner->quot += fdata->quot_offset;
fuse_corner->quot += fdata->quot_adjust;
return 0;
}
/*
* Returns: Index of the initial corner or negative number for error.
*/
int cpr_find_initial_corner(struct device *dev, struct clk *cpu_clk,
struct corner *corners, int num_corners)
{
unsigned long rate;
struct corner *iter, *corner;
const struct corner *end;
unsigned int ret = 0;
if (!cpu_clk)
return -EINVAL;
end = &corners[num_corners - 1];
rate = clk_get_rate(cpu_clk);
/*
* Some bootloaders set a CPU clock frequency that is not defined
* in the OPP table. When running at an unlisted frequency,
* cpufreq_online() will change to the OPP which has the lowest
* frequency, at or above the unlisted frequency.
* Since cpufreq_online() always "rounds up" in the case of an
* unlisted frequency, this function always "rounds down" in case
* of an unlisted frequency. That way, when cpufreq_online()
* triggers the first ever call to cpr_set_performance_state(),
* it will correctly determine the direction as UP.
*/
for (iter = corners; iter <= end; iter++) {
if (iter->freq > rate)
break;
ret++;
if (iter->freq == rate) {
corner = iter;
break;
}
if (iter->freq < rate)
corner = iter;
}
if (!corner) {
dev_err(dev, "boot up corner not found\n");
return -EINVAL;
}
dev_dbg(dev, "boot up perf state: %u\n", ret);
return ret;
}
u32 cpr_get_fuse_corner(struct dev_pm_opp *opp, u32 tid)
{
struct device_node *np;
u32 fc;
np = dev_pm_opp_get_of_node(opp);
if (of_property_read_u32_index(np, "qcom,opp-fuse-level", tid, &fc)) {
pr_debug("%s: missing 'qcom,opp-fuse-level' property\n",
__func__);
fc = 0;
}
of_node_put(np);
return fc;
}
void cpr_get_corner_post_vadj(struct dev_pm_opp *opp, u32 tid,
s32 *open_loop, s32 *closed_loop)
{
struct device_node *np;
/*
* There is no of_property_read_s32_index, so we just store the
* result into a s32 variable. After all, the OF API is doing
* the exact same for of_property_read_s32...
*/
np = dev_pm_opp_get_of_node(opp);
if (of_property_read_u32_index(np, "qcom,opp-oloop-vadj", tid,
open_loop))
*open_loop = 0;
if (of_property_read_u32_index(np, "qcom,opp-cloop-vadj", tid,
closed_loop))
*closed_loop = 0;
of_node_put(np);
}
unsigned long cpr_get_opp_hz_for_req(struct dev_pm_opp *ref,
struct device *cpu_dev)
{
u64 rate = 0;
struct device_node *ref_np;
struct device_node *desc_np;
struct device_node *child_np = NULL;
struct device_node *child_req_np = NULL;
desc_np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
if (!desc_np)
return 0;
ref_np = dev_pm_opp_get_of_node(ref);
if (!ref_np)
goto out_ref;
do {
of_node_put(child_req_np);
child_np = of_get_next_available_child(desc_np, child_np);
child_req_np = of_parse_phandle(child_np, "required-opps", 0);
} while (child_np && child_req_np != ref_np);
if (child_np && child_req_np == ref_np)
of_property_read_u64(child_np, "opp-hz", &rate);
of_node_put(child_req_np);
of_node_put(child_np);
of_node_put(ref_np);
out_ref:
of_node_put(desc_np);
return (unsigned long) rate;
}
int cpr_calculate_scaling(const char *quot_offset,
struct device *dev,
const struct fuse_corner_data *fdata,
const struct corner *corner)
{
u64 freq_diff;
const struct fuse_corner *fuse, *prev_fuse;
u32 quot_diff;
int scaling, ret;
fuse = corner->fuse_corner;
prev_fuse = fuse - 1;
if (quot_offset) {
ret = nvmem_cell_read_variable_le_u32(dev, quot_offset, &quot_diff);
if (ret)
return ret;
quot_diff *= fdata->quot_offset_scale;
quot_diff += fdata->quot_offset_adjust;
} else {
quot_diff = fuse->quot - prev_fuse->quot;
}
freq_diff = fuse->max_freq - prev_fuse->max_freq;
freq_diff = div_u64(freq_diff, 1000000); /* Convert to MHz */
scaling = 1000 * quot_diff;
do_div(scaling, freq_diff);
return min(scaling, fdata->max_quot_scale);
}
int cpr_interpolate(const struct corner *corner, int step_volt,
const struct fuse_corner_data *fdata)
{
unsigned long f_high, f_low, f_diff;
int uV_high, uV_low, uV;
u64 temp, temp_limit;
const struct fuse_corner *fuse, *prev_fuse;
fuse = corner->fuse_corner;
prev_fuse = fuse - 1;
f_high = fuse->max_freq;
f_low = prev_fuse->max_freq;
uV_high = fuse->uV;
uV_low = prev_fuse->uV;
f_diff = fuse->max_freq - corner->freq;
/*
* Don't interpolate in the wrong direction. This could happen
* if the adjusted fuse voltage overlaps with the previous fuse's
* adjusted voltage.
*/
if (f_high <= f_low || uV_high <= uV_low || f_high <= corner->freq)
return corner->uV;
temp = f_diff * (uV_high - uV_low);
temp = div64_ul(temp, f_high - f_low);
/*
* max_volt_scale has units of uV/MHz while freq values
* have units of Hz. Divide by 1000000 to convert to.
*/
temp_limit = f_diff * fdata->max_volt_scale;
do_div(temp_limit, 1000000);
uV = uV_high - min(temp, temp_limit);
return roundup(uV, step_volt);
}
int cpr_check_vreg_constraints(struct device *dev, struct regulator *vreg,
struct fuse_corner *f)
{
int ret;
ret = regulator_is_supported_voltage(vreg, f->min_uV, f->min_uV);
if (!ret) {
dev_err(dev, "min uV: %d not supported by regulator\n",
f->min_uV);
return -EINVAL;
}
ret = regulator_is_supported_voltage(vreg, f->max_uV, f->max_uV);
if (!ret) {
dev_err(dev, "max uV: %d not supported by regulator\n",
f->max_uV);
return -EINVAL;
}
return 0;
}

View file

@ -0,0 +1,117 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/regulator/consumer.h>
enum voltage_change_dir {
NO_CHANGE,
DOWN,
UP,
};
struct fuse_corner_data {
int ref_uV;
int max_uV;
int min_uV;
int range_uV;
/* fuse volt: closed/open loop */
int volt_cloop_adjust;
int volt_oloop_adjust;
int max_volt_scale;
int max_quot_scale;
/* fuse quot */
int quot_offset;
int quot_scale;
int quot_adjust;
/* fuse quot_offset */
int quot_offset_scale;
int quot_offset_adjust;
};
struct cpr_fuse {
char *ring_osc;
char *init_voltage;
char *quotient;
char *quotient_offset;
};
struct fuse_corner {
int min_uV;
int max_uV;
int uV;
int quot;
int step_quot;
const struct reg_sequence *accs;
int num_accs;
unsigned long max_freq;
u8 ring_osc_idx;
};
struct corner {
int min_uV;
int max_uV;
int uV;
int last_uV;
int quot_adjust;
u32 save_ctl;
u32 save_irq;
unsigned long freq;
bool is_open_loop;
struct fuse_corner *fuse_corner;
};
struct corner_data {
unsigned int fuse_corner;
unsigned long freq;
int oloop_vadj;
int cloop_vadj;
};
struct acc_desc {
unsigned int enable_reg;
u32 enable_mask;
struct reg_sequence *config;
struct reg_sequence *settings;
int num_regs_per_fuse;
};
struct cpr_acc_desc {
const struct cpr_desc *cpr_desc;
const struct acc_desc *acc_desc;
};
int cpr_read_efuse(struct device *dev, const char *cname, u32 *data);
int cpr_populate_ring_osc_idx(struct device *dev,
struct fuse_corner *fuse_corner,
const struct cpr_fuse *cpr_fuse,
int num_fuse_corners);
int cpr_read_fuse_uV(int init_v_width, int step_size_uV, int ref_uV,
int adj, int step_volt, const char *init_v_efuse,
struct device *dev);
const struct cpr_fuse *cpr_get_fuses(struct device *dev, int tid,
int num_fuse_corners);
int cpr_populate_fuse_common(struct device *dev,
struct fuse_corner_data *fdata,
const struct cpr_fuse *cpr_fuse,
struct fuse_corner *fuse_corner,
int step_volt, int init_v_width,
int init_v_step);
int cpr_find_initial_corner(struct device *dev, struct clk *cpu_clk,
struct corner *corners, int num_corners);
u32 cpr_get_fuse_corner(struct dev_pm_opp *opp, u32 tid);
void cpr_get_corner_post_vadj(struct dev_pm_opp *opp, u32 tid,
s32 *open_loop, s32 *closed_loop);
unsigned long cpr_get_opp_hz_for_req(struct dev_pm_opp *ref,
struct device *cpu_dev);
int cpr_calculate_scaling(const char *quot_offset,
struct device *dev,
const struct fuse_corner_data *fdata,
const struct corner *corner);
int cpr_interpolate(const struct corner *corner, int step_volt,
const struct fuse_corner_data *fdata);
int cpr_check_vreg_constraints(struct device *dev, struct regulator *vreg,
struct fuse_corner *f);

View file

@ -25,6 +25,7 @@
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
#include <linux/nvmem-consumer.h>
#include "cpr-common.h"
/* Register Offsets for RB-CPR and Bit Definitions */
@ -124,45 +125,12 @@
#define FUSE_REVISION_UNKNOWN (-1)
enum voltage_change_dir {
NO_CHANGE,
DOWN,
UP,
};
struct cpr_fuse {
char *ring_osc;
char *init_voltage;
char *quotient;
char *quotient_offset;
};
struct fuse_corner_data {
int ref_uV;
int max_uV;
int min_uV;
int max_volt_scale;
int max_quot_scale;
/* fuse quot */
int quot_offset;
int quot_scale;
int quot_adjust;
/* fuse quot_offset */
int quot_offset_scale;
int quot_offset_adjust;
};
struct cpr_fuses {
int init_voltage_step;
int init_voltage_width;
struct fuse_corner_data *fuse_corner_data;
};
struct corner_data {
unsigned int fuse_corner;
unsigned long freq;
};
struct cpr_desc {
unsigned int num_fuse_corners;
int min_diff_quot;
@ -184,44 +152,6 @@ struct cpr_desc {
bool reduce_to_corner_uV;
};
struct acc_desc {
unsigned int enable_reg;
u32 enable_mask;
struct reg_sequence *config;
struct reg_sequence *settings;
int num_regs_per_fuse;
};
struct cpr_acc_desc {
const struct cpr_desc *cpr_desc;
const struct acc_desc *acc_desc;
};
struct fuse_corner {
int min_uV;
int max_uV;
int uV;
int quot;
int step_quot;
const struct reg_sequence *accs;
int num_accs;
unsigned long max_freq;
u8 ring_osc_idx;
};
struct corner {
int min_uV;
int max_uV;
int uV;
int last_uV;
int quot_adjust;
u32 save_ctl;
u32 save_irq;
unsigned long freq;
struct fuse_corner *fuse_corner;
};
struct cpr_drv {
unsigned int num_corners;
unsigned int ref_clk_khz;
@ -801,62 +731,16 @@ unlock:
return ret;
}
static int
cpr_populate_ring_osc_idx(struct cpr_drv *drv)
{
struct fuse_corner *fuse = drv->fuse_corners;
struct fuse_corner *end = fuse + drv->desc->num_fuse_corners;
const struct cpr_fuse *fuses = drv->cpr_fuses;
u32 data;
int ret;
for (; fuse < end; fuse++, fuses++) {
ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data);
if (ret)
return ret;
fuse->ring_osc_idx = data;
}
return 0;
}
static int cpr_read_fuse_uV(const struct cpr_desc *desc,
const struct fuse_corner_data *fdata,
const char *init_v_efuse,
int step_volt,
struct cpr_drv *drv)
{
int step_size_uV, steps, uV;
u32 bits = 0;
int ret;
ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits);
if (ret)
return ret;
steps = bits & ~BIT(desc->cpr_fuses.init_voltage_width - 1);
/* Not two's complement.. instead highest bit is sign bit */
if (bits & BIT(desc->cpr_fuses.init_voltage_width - 1))
steps = -steps;
step_size_uV = desc->cpr_fuses.init_voltage_step;
uV = fdata->ref_uV + steps * step_size_uV;
return DIV_ROUND_UP(uV, step_volt) * step_volt;
}
static int cpr_fuse_corner_init(struct cpr_drv *drv)
{
const struct cpr_desc *desc = drv->desc;
const struct cpr_fuse *fuses = drv->cpr_fuses;
const struct cpr_fuse *cpr_fuse = drv->cpr_fuses;
const struct acc_desc *acc_desc = drv->acc_desc;
int i;
unsigned int step_volt;
struct fuse_corner_data *fdata;
struct fuse_corner *fuse, *end;
int uV;
const struct reg_sequence *accs;
int ret;
unsigned int step_volt;
int i, ret;
accs = acc_desc->settings;
@ -869,24 +753,16 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
end = &fuse[desc->num_fuse_corners - 1];
fdata = desc->cpr_fuses.fuse_corner_data;
for (i = 0; fuse <= end; fuse++, fuses++, i++, fdata++) {
/*
* Update SoC voltages: platforms might choose a different
* regulators than the one used to characterize the algorithms
* (ie, init_voltage_step).
*/
fdata->min_uV = roundup(fdata->min_uV, step_volt);
fdata->max_uV = roundup(fdata->max_uV, step_volt);
for (i = 0; fuse <= end; fuse++, cpr_fuse++, i++, fdata++) {
ret = cpr_populate_fuse_common(
drv->dev, fdata, cpr_fuse,
fuse, step_volt,
desc->cpr_fuses.init_voltage_width,
desc->cpr_fuses.init_voltage_step);
if (ret)
return ret;
/* Populate uV */
uV = cpr_read_fuse_uV(desc, fdata, fuses->init_voltage,
step_volt, drv);
if (uV < 0)
return uV;
fuse->min_uV = fdata->min_uV;
fuse->max_uV = fdata->max_uV;
fuse->uV = clamp(uV, fuse->min_uV, fuse->max_uV);
fuse->step_quot = desc->step_quot[fuse->ring_osc_idx];
if (fuse == end) {
/*
@ -898,16 +774,6 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
end->max_uV = max(end->max_uV, end->uV);
}
/* Populate target quotient by scaling */
ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot);
if (ret)
return ret;
fuse->quot *= fdata->quot_scale;
fuse->quot += fdata->quot_offset;
fuse->quot += fdata->quot_adjust;
fuse->step_quot = desc->step_quot[fuse->ring_osc_idx];
/* Populate acc settings */
fuse->accs = accs;
fuse->num_accs = acc_desc->num_regs_per_fuse;
@ -924,25 +790,9 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
else if (fuse->uV < fuse->min_uV)
fuse->uV = fuse->min_uV;
ret = regulator_is_supported_voltage(drv->vdd_apc,
fuse->min_uV,
fuse->min_uV);
if (!ret) {
dev_err(drv->dev,
"min uV: %d (fuse corner: %d) not supported by regulator\n",
fuse->min_uV, i);
return -EINVAL;
}
ret = regulator_is_supported_voltage(drv->vdd_apc,
fuse->max_uV,
fuse->max_uV);
if (!ret) {
dev_err(drv->dev,
"max uV: %d (fuse corner: %d) not supported by regulator\n",
fuse->max_uV, i);
return -EINVAL;
}
ret = cpr_check_vreg_constraints(drv->dev, drv->vdd_apc, fuse);
if (ret)
return ret;
dev_dbg(drv->dev,
"fuse corner %d: [%d %d %d] RO%hhu quot %d squot %d\n",
@ -953,126 +803,6 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
return 0;
}
static int cpr_calculate_scaling(const char *quot_offset,
struct cpr_drv *drv,
const struct fuse_corner_data *fdata,
const struct corner *corner)
{
u32 quot_diff = 0;
unsigned long freq_diff;
int scaling;
const struct fuse_corner *fuse, *prev_fuse;
int ret;
fuse = corner->fuse_corner;
prev_fuse = fuse - 1;
if (quot_offset) {
ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, &quot_diff);
if (ret)
return ret;
quot_diff *= fdata->quot_offset_scale;
quot_diff += fdata->quot_offset_adjust;
} else {
quot_diff = fuse->quot - prev_fuse->quot;
}
freq_diff = fuse->max_freq - prev_fuse->max_freq;
freq_diff /= 1000000; /* Convert to MHz */
scaling = 1000 * quot_diff / freq_diff;
return min(scaling, fdata->max_quot_scale);
}
static int cpr_interpolate(const struct corner *corner, int step_volt,
const struct fuse_corner_data *fdata)
{
unsigned long f_high, f_low, f_diff;
int uV_high, uV_low, uV;
u64 temp, temp_limit;
const struct fuse_corner *fuse, *prev_fuse;
fuse = corner->fuse_corner;
prev_fuse = fuse - 1;
f_high = fuse->max_freq;
f_low = prev_fuse->max_freq;
uV_high = fuse->uV;
uV_low = prev_fuse->uV;
f_diff = fuse->max_freq - corner->freq;
/*
* Don't interpolate in the wrong direction. This could happen
* if the adjusted fuse voltage overlaps with the previous fuse's
* adjusted voltage.
*/
if (f_high <= f_low || uV_high <= uV_low || f_high <= corner->freq)
return corner->uV;
temp = f_diff * (uV_high - uV_low);
temp = div64_ul(temp, f_high - f_low);
/*
* max_volt_scale has units of uV/MHz while freq values
* have units of Hz. Divide by 1000000 to convert to.
*/
temp_limit = f_diff * fdata->max_volt_scale;
do_div(temp_limit, 1000000);
uV = uV_high - min(temp, temp_limit);
return roundup(uV, step_volt);
}
static unsigned int cpr_get_fuse_corner(struct dev_pm_opp *opp)
{
struct device_node *np;
unsigned int fuse_corner = 0;
np = dev_pm_opp_get_of_node(opp);
if (of_property_read_u32(np, "qcom,opp-fuse-level", &fuse_corner))
pr_err("%s: missing 'qcom,opp-fuse-level' property\n",
__func__);
of_node_put(np);
return fuse_corner;
}
static unsigned long cpr_get_opp_hz_for_req(struct dev_pm_opp *ref,
struct device *cpu_dev)
{
u64 rate = 0;
struct device_node *ref_np;
struct device_node *desc_np;
struct device_node *child_np = NULL;
struct device_node *child_req_np = NULL;
desc_np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
if (!desc_np)
return 0;
ref_np = dev_pm_opp_get_of_node(ref);
if (!ref_np)
goto out_ref;
do {
of_node_put(child_req_np);
child_np = of_get_next_available_child(desc_np, child_np);
child_req_np = of_parse_phandle(child_np, "required-opps", 0);
} while (child_np && child_req_np != ref_np);
if (child_np && child_req_np == ref_np)
of_property_read_u64(child_np, "opp-hz", &rate);
of_node_put(child_req_np);
of_node_put(child_np);
of_node_put(ref_np);
out_ref:
of_node_put(desc_np);
return (unsigned long) rate;
}
static int cpr_corner_init(struct cpr_drv *drv)
{
const struct cpr_desc *desc = drv->desc;
@ -1110,7 +840,7 @@ static int cpr_corner_init(struct cpr_drv *drv)
opp = dev_pm_opp_find_level_exact(&drv->pd.dev, level);
if (IS_ERR(opp))
return -EINVAL;
fc = cpr_get_fuse_corner(opp);
fc = cpr_get_fuse_corner(opp, 0);
if (!fc) {
dev_pm_opp_put(opp);
return -EINVAL;
@ -1186,7 +916,7 @@ static int cpr_corner_init(struct cpr_drv *drv)
corner->uV = fuse->uV;
if (prev_fuse && cdata[i - 1].freq == prev_fuse->max_freq) {
scaling = cpr_calculate_scaling(quot_offset, drv,
scaling = cpr_calculate_scaling(quot_offset, drv->dev,
fdata, corner);
if (scaling < 0)
return scaling;
@ -1224,47 +954,6 @@ static int cpr_corner_init(struct cpr_drv *drv)
return 0;
}
static const struct cpr_fuse *cpr_get_fuses(struct cpr_drv *drv)
{
const struct cpr_desc *desc = drv->desc;
struct cpr_fuse *fuses;
int i;
fuses = devm_kcalloc(drv->dev, desc->num_fuse_corners,
sizeof(struct cpr_fuse),
GFP_KERNEL);
if (!fuses)
return ERR_PTR(-ENOMEM);
for (i = 0; i < desc->num_fuse_corners; i++) {
char tbuf[32];
snprintf(tbuf, 32, "cpr_ring_osc%d", i + 1);
fuses[i].ring_osc = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL);
if (!fuses[i].ring_osc)
return ERR_PTR(-ENOMEM);
snprintf(tbuf, 32, "cpr_init_voltage%d", i + 1);
fuses[i].init_voltage = devm_kstrdup(drv->dev, tbuf,
GFP_KERNEL);
if (!fuses[i].init_voltage)
return ERR_PTR(-ENOMEM);
snprintf(tbuf, 32, "cpr_quotient%d", i + 1);
fuses[i].quotient = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL);
if (!fuses[i].quotient)
return ERR_PTR(-ENOMEM);
snprintf(tbuf, 32, "cpr_quotient_offset%d", i + 1);
fuses[i].quotient_offset = devm_kstrdup(drv->dev, tbuf,
GFP_KERNEL);
if (!fuses[i].quotient_offset)
return ERR_PTR(-ENOMEM);
}
return fuses;
}
static void cpr_set_loop_allowed(struct cpr_drv *drv)
{
drv->loop_disabled = false;
@ -1296,54 +985,6 @@ static int cpr_init_parameters(struct cpr_drv *drv)
return 0;
}
static int cpr_find_initial_corner(struct cpr_drv *drv)
{
unsigned long rate;
const struct corner *end;
struct corner *iter;
unsigned int i = 0;
if (!drv->cpu_clk) {
dev_err(drv->dev, "cannot get rate from NULL clk\n");
return -EINVAL;
}
end = &drv->corners[drv->num_corners - 1];
rate = clk_get_rate(drv->cpu_clk);
/*
* Some bootloaders set a CPU clock frequency that is not defined
* in the OPP table. When running at an unlisted frequency,
* cpufreq_online() will change to the OPP which has the lowest
* frequency, at or above the unlisted frequency.
* Since cpufreq_online() always "rounds up" in the case of an
* unlisted frequency, this function always "rounds down" in case
* of an unlisted frequency. That way, when cpufreq_online()
* triggers the first ever call to cpr_set_performance_state(),
* it will correctly determine the direction as UP.
*/
for (iter = drv->corners; iter <= end; iter++) {
if (iter->freq > rate)
break;
i++;
if (iter->freq == rate) {
drv->corner = iter;
break;
}
if (iter->freq < rate)
drv->corner = iter;
}
if (!drv->corner) {
dev_err(drv->dev, "boot up corner not found\n");
return -EINVAL;
}
dev_dbg(drv->dev, "boot up perf state: %u\n", i);
return 0;
}
static const struct cpr_desc qcs404_cpr_desc = {
.num_fuse_corners = 3,
.min_diff_quot = CPR_FUSE_MIN_QUOT_DIFF,
@ -1531,8 +1172,9 @@ static int cpr_pd_attach_dev(struct generic_pm_domain *domain,
if (ret)
goto unlock;
ret = cpr_find_initial_corner(drv);
if (ret)
ret = cpr_find_initial_corner(drv->dev, drv->cpu_clk, drv->corners,
drv->num_corners);
if (ret < 0)
goto unlock;
if (acc_desc->config)
@ -1616,6 +1258,7 @@ static int cpr_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct cpr_drv *drv;
const struct cpr_desc *desc;
int irq, ret;
const struct cpr_acc_desc *data;
struct device_node *np;
@ -1631,6 +1274,7 @@ static int cpr_probe(struct platform_device *pdev)
drv->dev = dev;
drv->desc = data->cpr_desc;
drv->acc_desc = data->acc_desc;
desc = drv->desc;
drv->fuse_corners = devm_kcalloc(dev, drv->desc->num_fuse_corners,
sizeof(*drv->fuse_corners),
@ -1670,11 +1314,13 @@ static int cpr_probe(struct platform_device *pdev)
if (ret)
return ret;
drv->cpr_fuses = cpr_get_fuses(drv);
drv->cpr_fuses = cpr_get_fuses(drv->dev, 0, desc->num_fuse_corners);
if (IS_ERR(drv->cpr_fuses))
return PTR_ERR(drv->cpr_fuses);
ret = cpr_populate_ring_osc_idx(drv);
ret = cpr_populate_ring_osc_idx(drv->dev, drv->fuse_corners,
drv->cpr_fuses,
desc->num_fuse_corners);
if (ret)
return ret;

2897
drivers/soc/qcom/cpr3.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -190,10 +190,14 @@
#define AGGRE2_SNOC_NORTH_AXI 181
#define SSC_XO 182
#define SSC_CNOC_AHBS_CLK 183
#define HLOS1_VOTE_LPASS_CORE_SMMU_CLK 184
#define HLOS1_VOTE_LPASS_ADSP_SMMU_CLK 185
#define PCIE_0_GDSC 0
#define UFS_GDSC 1
#define USB_30_GDSC 2
#define LPASS_ADSP_GDSC 3
#define LPASS_CORE_GDSC 4
#define GCC_BLSP1_QUP1_BCR 0
#define GCC_BLSP1_QUP2_BCR 1
@ -304,5 +308,6 @@
#define GCC_QUSB2PHY_PRIM_BCR 106
#define GCC_QUSB2PHY_SEC_BCR 107
#define GCC_MSS_RESTART 108
#define GCC_MSS_Q6_BIMC_AXI_CLK 109
#endif

View file

@ -0,0 +1,128 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* MSM8998 interconnect IDs */
#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_MSM8998_H
#define __DT_BINDINGS_INTERCONNECT_QCOM_MSM8998_H
/* A1NOC */
#define MASTER_PCIE_0 0
#define MASTER_USB3 1
#define MASTER_UFS 2
#define MASTER_BLSP_2 3
#define SLAVE_A1NOC_SNOC 4
/* A2NOC */
#define MASTER_IPA 0
#define MASTER_CNOC_A2NOC 1
#define MASTER_SDCC_2 2
#define MASTER_SDCC_4 3
#define MASTER_TSIF 4
#define MASTER_BLSP_1 5
#define MASTER_CRVIRT_A2NOC 6
#define MASTER_CRYPTO_C0 7
#define SLAVE_A2NOC_SNOC 8
#define SLAVE_CRVIRT_A2NOC 9
/* BIMC */
#define MASTER_GNOC_BIMC 0
#define MASTER_OXILI 1
#define MASTER_MNOC_BIMC 2
#define MASTER_SNOC_BIMC 3
#define SLAVE_EBI 4
#define SLAVE_HMSS_L3 5
#define SLAVE_BIMC_SNOC_0 6
#define SLAVE_BIMC_SNOC_1 7
/* CNOC */
#define MASTER_SNOC_CNOC 0
#define MASTER_QDSS_DAP 1
#define SLAVE_CNOC_A2NOC 2
#define SLAVE_SSC_CFG 3
#define SLAVE_MPM 4
#define SLAVE_PMIC_ARB 5
#define SLAVE_TLMM_NORTH 6
#define SLAVE_PIMEM_CFG 7
#define SLAVE_IMEM_CFG 8
#define SLAVE_MESSAGE_RAM 9
#define SLAVE_SKL 10
#define SLAVE_BIMC_CFG 11
#define SLAVE_PRNG 12
#define SLAVE_A2NOC_CFG 13
#define SLAVE_IPA 14
#define SLAVE_TCSR 15
#define SLAVE_SNOC_CFG 16
#define SLAVE_CLK_CTL 17
#define SLAVE_GLM 18
#define SLAVE_SPDM 19
#define SLAVE_GPUSS_CFG 20
#define SLAVE_CNOC_MNOC_CFG 21
#define SLAVE_QM_CFG 22
#define SLAVE_MSS_CFG 23
#define SLAVE_UFS_CFG 24
#define SLAVE_TLMM_WEST 25
#define SLAVE_A1NOC_CFG 26
#define SLAVE_AHB2PHY 27
#define SLAVE_BLSP_2 28
#define SLAVE_PDM 29
#define SLAVE_USB3_0 30
#define SLAVE_A1NOC_SMMU_CFG 31
#define SLAVE_BLSP_1 32
#define SLAVE_SDCC_2 33
#define SLAVE_SDCC_4 34
#define SLAVE_TSIF 35
#define SLAVE_QDSS_CFG 36
#define SLAVE_TLMM_EAST 37
#define SLAVE_CNOC_MNOC_MMSS_CFG 38
#define SLAVE_SRVC_CNOC 39
/* GNOC */
#define MASTER_APSS_PROC 0
#define SLAVE_GNOC_BIMC 1
/* MNOC */
#define MASTER_CNOC_MNOC_CFG 0
#define MASTER_CPP 1
#define MASTER_JPEG 2
#define MASTER_MDP_P0 3
#define MASTER_MDP_P1 4
#define MASTER_ROTATOR 5
#define MASTER_VENUS 6
#define MASTER_VFE 7
#define MASTER_VENUS_VMEM 8
#define SLAVE_MNOC_BIMC 9
#define SLAVE_VMEM 10
#define SLAVE_SRVC_MNOC 11
#define MASTER_CNOC_MNOC_MMSS_CFG 12
#define SLAVE_CAMERA_CFG 13
#define SLAVE_CAMERA_THROTTLE_CFG 14
#define SLAVE_MISC_CFG 15
#define SLAVE_VENUS_THROTTLE_CFG 16
#define SLAVE_VENUS_CFG 17
#define SLAVE_VMEM_CFG 18
#define SLAVE_MMSS_CLK_XPU_CFG 19
#define SLAVE_MMSS_CLK_CFG 20
#define SLAVE_DISPLAY_CFG 21
#define SLAVE_DISPLAY_THROTTLE_CFG 22
#define SLAVE_SMMU_CFG 23
/* SNOC */
#define MASTER_HMSS 0
#define MASTER_QDSS_BAM 1
#define MASTER_SNOC_CFG 2
#define MASTER_BIMC_SNOC_0 3
#define MASTER_BIMC_SNOC_1 4
#define MASTER_A1NOC_SNOC 5
#define MASTER_A2NOC_SNOC 6
#define MASTER_QDSS_ETR 7
#define SLAVE_HMSS 8
#define SLAVE_LPASS 9
#define SLAVE_WLAN 10
#define SLAVE_SNOC_BIMC 11
#define SLAVE_SNOC_CNOC 12
#define SLAVE_IMEM 13
#define SLAVE_PIMEM 14
#define SLAVE_QDSS_STM 15
#define SLAVE_PCIE_0 16
#define SLAVE_SRVC_SNOC 17
#endif

View file

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __DT_MSM8998_LPASS_H
#define __DT_MSM8998_LPASS_H
#include <dt-bindings/sound/qcom,lpass.h>
/* NOTE: Use qcom,lpass.h to define any AIF ID's for LPASS */
#endif /* __DT_MSM8998_LPASS_H */

17
include/soc/qcom/cpr.h Normal file
View file

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019 Linaro Limited
* Copyright (c) 2021, AngeloGioacchino Del Regno
* <angelogioacchino.delregno@somainline.org>
*/
#ifndef __CPR_H__
#define __CPR_H__
struct cpr_ext_data {
int mem_acc_threshold_uV;
int apm_threshold_uV;
};
#endif /* __CPR_H__ */

View file

@ -1661,7 +1661,7 @@ static int elf_validity_check(struct load_info *info)
}
if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0) {
pr_err("Invalid ELF header magic: != %s\n", ELFMAG);
pr_debug("Invalid ELF header magic: != %s\n", ELFMAG);
goto no_exec;
}
if (info->hdr->e_type != ET_REL) {

View file

@ -139,7 +139,7 @@ elif [ "${LOCALVERSION+set}" != "set" ]; then
# If the variable LOCALVERSION is set (including being set
# to an empty string), we don't want to append a plus sign.
scm=$(scm_version --short)
res="$res${scm:++}"
#res="$res${scm:++}"
fi
echo "$res"

View file

@ -11,6 +11,7 @@
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <sound/jack.h>
#include <linux/kernel.h>
#include <linux/slimbus.h>
#include <sound/soc.h>
@ -88,12 +89,18 @@
#define WCD9335_DEC_PWR_LVL_HP 0x04
#define WCD9335_DEC_PWR_LVL_DF 0x00
#define WCD9335_MBHC_MAX_BUTTONS (8)
#define WCD9335_SLIM_RX_CH(p) \
{.port = p + WCD9335_RX_START, .shift = p,}
#define WCD9335_SLIM_TX_CH(p) \
{.port = p, .shift = p,}
static int btn_mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_BTN_4;
static int hs_jack_mask = SND_JACK_HEADPHONE | SND_JACK_HEADSET;
/* vout step value */
#define WCD9335_CALCULATE_VOUT_D(req_mv) (((req_mv - 650) * 10) / 25)
@ -310,6 +317,16 @@ struct wcd9335_codec {
u32 num_rx_port;
u32 num_tx_port;
struct snd_soc_jack *jack;
bool hphl_jack_type_normally_open;
bool gnd_jack_type_normally_open;
bool mbhc_btn_enabled;
int mbhc_btn0_released;
bool detect_accessory_type;
int accessory_type;
/* Voltage threshold for button detection */
u32 vref_btn[WCD9335_MBHC_MAX_BUTTONS];
int sido_input_src;
enum wcd9335_sido_voltage sido_voltage;
@ -467,7 +484,7 @@ static const struct wcd9335_reg_mask_val wcd9335_codec_reg_init[] = {
{WCD9335_RCO_CTRL_2, 0x0F, 0x08},
{WCD9335_RX_BIAS_FLYB_MID_RST, 0xF0, 0x10},
{WCD9335_FLYBACK_CTRL_1, 0x20, 0x20},
{WCD9335_HPH_OCP_CTL, 0xFF, 0x5A},
{WCD9335_HPH_OCP_CTL, 0xFF, 0x7A}, /*downstream is ff 7a */
{WCD9335_HPH_L_TEST, 0x01, 0x01},
{WCD9335_HPH_R_TEST, 0x01, 0x01},
{WCD9335_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12},
@ -480,6 +497,13 @@ static const struct wcd9335_reg_mask_val wcd9335_codec_reg_init[] = {
{WCD9335_CDC_RX0_RX_PATH_SEC0, 0xFC, 0xF4},
{WCD9335_HPH_REFBUFF_LP_CTL, 0x08, 0x08},
{WCD9335_HPH_REFBUFF_LP_CTL, 0x06, 0x02},
{WCD9335_DIFF_LO_CORE_OUT_PROG, 0xFC, 0xA0},
{WCD9335_SE_LO_COM1, 0xFF, 0xC0},
{WCD9335_CDC_RX3_RX_PATH_SEC0, 0xFC, 0xF4},
{WCD9335_CDC_RX4_RX_PATH_SEC0, 0xFC, 0xF4},
{WCD9335_CDC_RX5_RX_PATH_SEC0, 0xFC, 0xF8},
{WCD9335_CDC_RX6_RX_PATH_SEC0, 0xFC, 0xF8},
};
/* Cutoff frequency for high pass filter */
@ -2805,7 +2829,6 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w,
break;
case SND_SOC_DAPM_POST_PMU:
snd_soc_component_update_bits(comp, hpf_gate_reg, 0x01, 0x00);
if (decimator == 0) {
snd_soc_component_write(comp,
WCD9335_MBHC_ZDET_RAMP_CTL, 0x83);
@ -2816,7 +2839,6 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w,
snd_soc_component_write(comp,
WCD9335_MBHC_ZDET_RAMP_CTL, 0x03);
}
snd_soc_component_update_bits(comp, hpf_gate_reg,
0x01, 0x01);
snd_soc_component_update_bits(comp, tx_vol_ctl_reg,
@ -3729,11 +3751,12 @@ static int wcd9335_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
int hph_mode = wcd->hph_mode;
pr_err("%s\n", __func__);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
break;
case SND_SOC_DAPM_POST_PMU:
pr_err("%s post pmu\n", __func__);
/*
* 7ms sleep is required after PA is enabled as per
* HW requirement
@ -3757,6 +3780,7 @@ static int wcd9335_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
break;
case SND_SOC_DAPM_PRE_PMD:
pr_err("%s pre pmd\n", __func__);
wcd9335_codec_hph_post_pa_config(wcd, hph_mode, event);
break;
case SND_SOC_DAPM_POST_PMD:
@ -3878,7 +3902,7 @@ static int wcd9335_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
int hph_mode = wcd->hph_mode;
pr_err("%s\n", __func__);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
break;
@ -3954,6 +3978,131 @@ static int wcd9335_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
return 0;
}
static irqreturn_t wcd9335_mbhc_sw_irq(int irq, void *data)
{
struct wcd9335_codec *wcd = data;
struct snd_soc_component *component = wcd->component;
bool ins = false;
if (snd_soc_component_read(component, WCD9335_ANA_MBHC_MECH) &
WCD9335_MBHC_MECH_DETECT_TYPE_MASK)
ins = true;
/* Set the detection type appropriately */
snd_soc_component_update_bits(component, WCD9335_ANA_MBHC_MECH,
WCD9335_MBHC_MECH_DETECT_TYPE_MASK,
(!ins << WCD9335_MBHC_MECH_DETECT_TYPE_SHIFT));
if (ins) { /* hs insertion */
u32 btndet_curr_src;
/*
* If no micbias is enabled, then enable 100uA internal
* current source for Button detection
*/
if (snd_soc_component_read(component, WCD9335_ANA_MICB2) &
WCD9335_ANA_MICB2_ENABLE)
btndet_curr_src = WCD9335_ANA_MBHC_BD_ISRC_OFF;
else
btndet_curr_src = WCD9335_ANA_MBHC_BD_ISRC_100UA;
snd_soc_component_update_bits(component,
WCD9335_ANA_MBHC_ELECT,
WCD9335_ANA_MBHC_BD_ISRC_CTL_MASK,
btndet_curr_src);
/*
* if only a btn0 press event is receive just before
* insert event then its a 3 pole headphone else if
* both press and release event received then its
* a headset.
*/
if (wcd->mbhc_btn0_released) {
snd_soc_jack_report(wcd->jack,
SND_JACK_HEADSET, hs_jack_mask);
wcd->accessory_type = SND_JACK_HEADSET;
} else {
snd_soc_jack_report(wcd->jack,
SND_JACK_HEADPHONE, hs_jack_mask);
wcd->accessory_type = SND_JACK_HEADPHONE;
}
wcd->detect_accessory_type = false;
} else { /* removal */
snd_soc_jack_report(wcd->jack, 0, hs_jack_mask);
wcd->detect_accessory_type = true;
wcd->mbhc_btn0_released = false;
}
return IRQ_HANDLED;
}
static irqreturn_t wcd9335_mbhc_btn_press_irq(int irq, void *data)
{
struct wcd9335_codec *wcd = data;
struct snd_soc_component *comp = wcd->component;
u32 btn_result, result;
/* do not handle any button events for headset without buttons */
if (wcd->accessory_type == SND_JACK_HEADPHONE)
return IRQ_HANDLED;
result = snd_soc_component_read(comp, WCD9335_ANA_MBHC_RESULT_3);
btn_result = result & WCD9335_MBHC_BTN_RESULT_MASK;
switch (btn_result) {
case 0xf:
snd_soc_jack_report(wcd->jack, SND_JACK_BTN_4, btn_mask);
break;
case 0x4:
snd_soc_jack_report(wcd->jack, SND_JACK_BTN_4, btn_mask);
break;
case 0x3:
snd_soc_jack_report(wcd->jack, SND_JACK_BTN_3, btn_mask);
break;
case 0x2:
snd_soc_jack_report(wcd->jack, SND_JACK_BTN_2, btn_mask);
break;
case 0x1:
snd_soc_jack_report(wcd->jack, SND_JACK_BTN_1, btn_mask);
break;
case 0x0:
/* handle BTN_0 specially for type detection */
if (!wcd->detect_accessory_type)
snd_soc_jack_report(wcd->jack,
SND_JACK_BTN_0, btn_mask);
break;
default:
dev_err(comp->dev,
"Unexpected button press result (%x)", btn_result);
break;
}
return IRQ_HANDLED;
}
static irqreturn_t wcd9335_mbhc_bt_rel_irq(int irq, void *data)
{
struct wcd9335_codec *wcd = data;
if (wcd->detect_accessory_type) {
u32 result = snd_soc_component_read(wcd->component,
WCD9335_ANA_MBHC_RESULT_3);
/* check if its BTN0 thats released */
if (!(result & WCD9335_MBHC_BTN_RESULT_MASK))
wcd->mbhc_btn0_released = true;
} else {
if (wcd->accessory_type != SND_JACK_HEADPHONE)
snd_soc_jack_report(wcd->jack, 0, btn_mask);
}
return IRQ_HANDLED;
}
static irqreturn_t wcd9335_slimbus_irq(int irq, void *data)
{
struct wcd9335_codec *wcd = data;
@ -4028,11 +4177,95 @@ static irqreturn_t wcd9335_slimbus_irq(int irq, void *data)
return ret;
}
static void wcd9335_program_btn_threshold(struct wcd9335_codec *wcd)
{
int i, vth;
for (i = 0; i < WCD9335_MBHC_MAX_BUTTONS; i++) {
vth = ((wcd->vref_btn[i] * 2) / 25) & 0x3F;
snd_soc_component_update_bits(wcd->component,
WCD9335_ANA_MBHC_BTN0 + i,
0xFC, vth << 2);
}
}
static void wcd9335_mbhc_initialise(struct wcd9335_codec *wcd)
{
struct snd_soc_component *comp = wcd->component;
u32 plug_type = 0;
snd_soc_component_update_bits(comp, WCD9335_MBHC_PLUG_DETECT_CTL,
WCD9335_MBHC_HSDET_PULLUP_CTL_MASK,
WCD9335_MBHC_HSDET_PULLUP_CTL_1_2P0_UA);
if (wcd->hphl_jack_type_normally_open)
plug_type |= WCD9335_MBHC_HPHL_PLUG_TYPE_NO;
if (wcd->gnd_jack_type_normally_open)
plug_type |= WCD9335_MBHC_GND_PLUG_TYPE_NO;
snd_soc_component_write(wcd->component, WCD9335_ANA_MBHC_MECH,
plug_type |
WCD9335_MBHC_L_DET_EN |
WCD9335_MBHC_HSL_PULLUP_COMP_EN |
WCD9335_MBHC_HPHL_100K_TO_GND_EN);
/* Insertion debounce set to 96ms */
snd_soc_component_write(wcd->component,
WCD9335_MBHC_PLUG_DETECT_CTL,
WCD9335_MBHC_DBNC_TIMER_INSREM_DBNC_T_96_MS|
WCD9335_MBHC_HSDET_PULLUP_CTL_1_2P0_UA);
/* Button Debounce set to 16ms */
snd_soc_component_update_bits(wcd->component, WCD9335_MBHC_CTL_1,
WCD9335_MBHC_BTN_DBNC_MASK,
WCD9335_MBHC_BTN_DBNC_T_16_MS);
/* enable bias distribution control */
snd_soc_component_update_bits(comp, WCD9335_ANA_MBHC_ELECT,
WCD9335_ANA_MBHC_BIAS_EN_MASK,
WCD9335_ANA_MBHC_BIAS_EN);
snd_soc_component_update_bits(wcd->component,
WCD9335_ANA_MBHC_ELECT,
WCD9335_ANA_MBHC_BD_ISRC_CTL_MASK,
WCD9335_ANA_MBHC_BD_ISRC_100UA);
/* enable MBHC clock */
snd_soc_component_update_bits(wcd->component, WCD9335_MBHC_CTL_1,
WCD9335_MBHC_CTL_RCO_EN_MASK,
WCD9335_MBHC_CTL_RCO_EN);
snd_soc_component_update_bits(wcd->component, WCD9335_MBHC_CTL_2,
WCD9335_MBHC_HS_VREF_CTL_MASK,
WCD9335_MBHC_HS_VREF_1P5_V);
/* program HS_VREF value */
wcd9335_program_btn_threshold(wcd);
/* Start FSM */
snd_soc_component_update_bits(wcd->component, WCD9335_ANA_MBHC_ELECT,
BIT(7), BIT(7));
wcd->mbhc_btn0_released = false;
wcd->detect_accessory_type = true;
}
static struct wcd9335_irq wcd9335_irqs[] = {
{
.irq = WCD9335_IRQ_SLIMBUS,
.handler = wcd9335_slimbus_irq,
.name = "SLIM Slave",
}, {
.irq = WCD9335_IRQ_MBHC_SW_DET,
.handler = wcd9335_mbhc_sw_irq,
.name = "Headset Mech Insert Removal",
}, {
.irq = WCD9335_IRQ_MBHC_BUTTON_PRESS_DET,
.handler = wcd9335_mbhc_btn_press_irq,
.name = "Headset Button Press",
}, {
.irq = WCD9335_IRQ_MBHC_BUTTON_RELEASE_DET,
.handler = wcd9335_mbhc_bt_rel_irq,
.name = "Headset Button Release",
},
};
@ -4841,6 +5074,7 @@ static void wcd9335_codec_init(struct snd_soc_component *component)
wcd9335_codec_reg_init[i].val);
wcd9335_enable_efuse_sensing(component);
wcd9335_mbhc_initialise(wcd);
}
static int wcd9335_codec_probe(struct snd_soc_component *component)
@ -4905,10 +5139,21 @@ static int wcd9335_codec_set_sysclk(struct snd_soc_component *comp,
return clk_set_rate(wcd->mclk, freq);
}
static int wcd9335_codec_set_jack(struct snd_soc_component *comp,
struct snd_soc_jack *jack, void *data)
{
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
wcd->jack = jack;
return 0;
}
static const struct snd_soc_component_driver wcd9335_component_drv = {
.probe = wcd9335_codec_probe,
.remove = wcd9335_codec_remove,
.set_sysclk = wcd9335_codec_set_sysclk,
.set_jack = wcd9335_codec_set_jack,
.controls = wcd9335_snd_controls,
.num_controls = ARRAY_SIZE(wcd9335_snd_controls),
.dapm_widgets = wcd9335_dapm_widgets,
@ -4918,10 +5163,39 @@ static const struct snd_soc_component_driver wcd9335_component_drv = {
.endianness = 1,
};
static void of_parse_mbhc_data(struct device *dev, struct wcd9335_codec *wcd)
{
int rval;
if (of_property_read_bool(dev->of_node,
"qcom,hphl-jack-type-normally-open"))
wcd->hphl_jack_type_normally_open = true;
else
wcd->hphl_jack_type_normally_open = false;
if (of_property_read_bool(dev->of_node,
"qcom,gnd-jack-type-normally-open"))
wcd->gnd_jack_type_normally_open = true;
else
wcd->gnd_jack_type_normally_open = false;
wcd->mbhc_btn_enabled = true;
rval = of_property_read_u32_array(dev->of_node,
"qcom,mbhc-vthreshold",
&wcd->vref_btn[0],
WCD9335_MBHC_MAX_BUTTONS);
if (rval < 0) {
wcd->mbhc_btn_enabled = false;
dev_err(dev, "MBHC btn detection disabled\n");
}
}
static int wcd9335_probe(struct wcd9335_codec *wcd)
{
struct device *dev = wcd->dev;
of_parse_mbhc_data(dev, wcd);
memcpy(wcd->rx_chs, wcd9335_rx_chs, sizeof(wcd9335_rx_chs));
memcpy(wcd->tx_chs, wcd9335_tx_chs, sizeof(wcd9335_tx_chs));
@ -5009,6 +5283,33 @@ static const struct regmap_irq wcd9335_codec_irqs[] = {
.type_reg_mask = BIT(0),
},
},
[WCD9335_IRQ_MBHC_SW_DET] = {
.reg_offset = 1,
.mask = BIT(0),
.type = {
.type_reg_offset = 1,
.types_supported = IRQ_TYPE_EDGE_BOTH,
.type_reg_mask = BIT(0),
},
},
[WCD9335_IRQ_MBHC_BUTTON_PRESS_DET] = {
.reg_offset = 1,
.mask = BIT(2),
.type = {
.type_reg_offset = 1,
.types_supported = IRQ_TYPE_EDGE_BOTH,
.type_reg_mask = BIT(2),
},
},
[WCD9335_IRQ_MBHC_BUTTON_RELEASE_DET] = {
.reg_offset = 1,
.mask = BIT(3),
.type = {
.type_reg_offset = 1,
.types_supported = IRQ_TYPE_EDGE_BOTH,
.type_reg_mask = BIT(3),
},
}
};
static const unsigned int wcd9335_config_regs[] = {

View file

@ -368,8 +368,10 @@
#define WCD9335_EAR_CMBUFF WCD9335_REG(0x06, 0x0e2)
#define WCD9335_DIFF_LO_LO2_COMPANDER WCD9335_REG(0x06, 0x0ea)
#define WCD9335_DIFF_LO_LO1_COMPANDER WCD9335_REG(0x06, 0x0eb)
#define WCD9335_DIFF_LO_CORE_OUT_PROG WCD9335_REG(0x06, 0x0ef)
#define WCD9335_DIFF_LO_COM_SWCAP_REFBUF_FREQ WCD9335_REG(0x06, 0x0f1)
#define WCD9335_DIFF_LO_COM_PA_FREQ WCD9335_REG(0x06, 0x0f2)
#define WCD9335_SE_LO_COM1 WCD9335_REG(0x06, 0x0f6)
#define WCD9335_SE_LO_LO3_GAIN WCD9335_REG(0x06, 0x0f8)
#define WCD9335_SE_LO_LO3_CTRL WCD9335_REG(0x06, 0x0f9)
#define WCD9335_SE_LO_LO4_GAIN WCD9335_REG(0x06, 0x0fa)
@ -495,6 +497,7 @@
#define WCD9335_CDC_RX3_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x082)
#define WCD9335_CDC_RX3_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x083)
#define WCD9335_CDC_RX3_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x084)
#define WCD9335_CDC_RX3_RX_PATH_SEC0 WCD9335_REG(0x0b, 0x085)
#define WCD9335_CDC_RX4_RX_PATH_CTL WCD9335_REG(0x0b, 0x091)
#define WCD9335_CDC_RX4_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x092)
#define WCD9335_CDC_RX4_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x094)
@ -502,6 +505,7 @@
#define WCD9335_CDC_RX4_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x096)
#define WCD9335_CDC_RX4_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x097)
#define WCD9335_CDC_RX4_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x098)
#define WCD9335_CDC_RX4_RX_PATH_SEC0 WCD9335_REG(0x0b, 0x099)
#define WCD9335_CDC_RX5_RX_PATH_CTL WCD9335_REG(0x0b, 0x0a5)
#define WCD9335_CDC_RX5_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x0a6)
#define WCD9335_CDC_RX5_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x0a8)
@ -509,6 +513,7 @@
#define WCD9335_CDC_RX5_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x0aa)
#define WCD9335_CDC_RX5_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x0ab)
#define WCD9335_CDC_RX5_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x0ac)
#define WCD9335_CDC_RX5_RX_PATH_SEC0 WCD9335_REG(0x0b, 0x0ad)
#define WCD9335_CDC_RX6_RX_PATH_CTL WCD9335_REG(0x0b, 0x0b9)
#define WCD9335_CDC_RX6_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x0ba)
#define WCD9335_CDC_RX6_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x0bc)
@ -516,6 +521,7 @@
#define WCD9335_CDC_RX6_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x0be)
#define WCD9335_CDC_RX6_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x0bf)
#define WCD9335_CDC_RX6_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x0c0)
#define WCD9335_CDC_RX6_RX_PATH_SEC0 WCD9335_REG(0x0b, 0x0c1)
#define WCD9335_CDC_RX7_RX_PATH_CTL WCD9335_REG(0x0b, 0x0cd)
#define WCD9335_CDC_RX7_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x0ce)
#define WCD9335_CDC_RX7_RX_PATH_CFG1 WCD9335_REG(0x0b, 0x0cf)

View file

@ -34,6 +34,12 @@ config SND_SOC_LPASS_APQ8016
select SND_SOC_LPASS_CPU
select SND_SOC_LPASS_PLATFORM
config SND_SOC_LPASS_MSM8998
tristate
select SND_SOC_LPASS_CPU
select SND_SOC_LPASS_PLATFORM
select SND_SOC_LPASS_HDMI
config SND_SOC_LPASS_SC7180
tristate
select SND_SOC_LPASS_CPU
@ -148,6 +154,18 @@ config SND_SOC_MSM8996
APQ8096 SoC-based systems.
Say Y if you want to use audio device on this SoCs
config SND_SOC_MSM8998
tristate "SoC Machine driver for MSM8998 and APQ8098 boards"
depends on QCOM_APR && I2C && SOUNDWIRE
depends on COMMON_CLK
select SND_SOC_QDSP6
select SND_SOC_QCOM_COMMON
select SND_SOC_LPASS_MSM8998
help
To add support for audio on Qualcomm Technologies Inc.
MSM8998 SoC-based systems.
Say Y if you want to use audio device on this SoCs.
config SND_SOC_SDM845
tristate "SoC Machine driver for SDM845 boards"
depends on QCOM_APR && I2C && SOUNDWIRE

View file

@ -6,6 +6,7 @@ snd-soc-lpass-hdmi-objs := lpass-hdmi.o
snd-soc-lpass-platform-objs := lpass-platform.o
snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o
snd-soc-lpass-apq8016-objs := lpass-apq8016.o
snd-soc-lpass-msm8998-objs := lpass-msm8998.o
snd-soc-lpass-sc7180-objs := lpass-sc7180.o
snd-soc-lpass-sc7280-objs := lpass-sc7280.o
@ -15,6 +16,7 @@ obj-$(CONFIG_SND_SOC_LPASS_HDMI) += snd-soc-lpass-hdmi.o
obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o
obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o
obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o
obj-$(CONFIG_SND_SOC_LPASS_MSM8998) += snd-soc-lpass-msm8998.o
obj-$(CONFIG_SND_SOC_LPASS_SC7180) += snd-soc-lpass-sc7180.o
obj-$(CONFIG_SND_SOC_LPASS_SC7280) += snd-soc-lpass-sc7280.o
@ -22,6 +24,7 @@ obj-$(CONFIG_SND_SOC_LPASS_SC7280) += snd-soc-lpass-sc7280.o
snd-soc-storm-objs := storm.o
snd-soc-apq8016-sbc-objs := apq8016_sbc.o
snd-soc-apq8096-objs := apq8096.o
snd-soc-msm8998-objs := msm8998.o
snd-soc-sc7180-objs := sc7180.o
snd-soc-sc7280-objs := sc7280.o
snd-soc-sdm845-objs := sdm845.o
@ -32,6 +35,7 @@ snd-soc-qcom-common-objs := common.o
obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o
obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o
obj-$(CONFIG_SND_SOC_MSM8996) += snd-soc-apq8096.o
obj-$(CONFIG_SND_SOC_MSM8998) += snd-soc-msm8998.o
obj-$(CONFIG_SND_SOC_SC7180) += snd-soc-sc7180.o
obj-$(CONFIG_SND_SOC_SC7280) += snd-soc-sc7280.o
obj-$(CONFIG_SND_SOC_SC8280XP) += snd-soc-sc8280xp.o

View file

@ -0,0 +1,330 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021 AngeloGioacchino Del Regno
* <angelogioacchino.delregno@somainline.org>
*
* lpass-msm8998.c -- ALSA SoC platform-machine driver for QTi LPASS
*/
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <dt-bindings/sound/msm8998-lpass.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include "lpass-lpaif-reg.h"
#include "lpass.h"
static struct snd_soc_dai_driver msm8998_lpass_cpu_dai_driver[] = {
{
.id = MI2S_PRIMARY,
.name = "Primary MI2S",
.playback = {
.stream_name = "Primary Playback",
.formats = SNDRV_PCM_FMTBIT_S16,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
},
.capture = {
.stream_name = "Primary Capture",
.formats = SNDRV_PCM_FMTBIT_S16 |
SNDRV_PCM_FMTBIT_S32,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
},
.probe = &asoc_qcom_lpass_cpu_dai_probe,
.ops = &asoc_qcom_lpass_cpu_dai_ops,
}, {
.id = MI2S_SECONDARY,
.name = "Secondary MI2S",
.playback = {
.stream_name = "Secondary Playback",
.formats = SNDRV_PCM_FMTBIT_S16,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
},
.probe = &asoc_qcom_lpass_cpu_dai_probe,
.ops = &asoc_qcom_lpass_cpu_dai_ops,
}, {
.id = MI2S_TERTIARY,
.name = "Tertiary MI2S",
.playback = {
.stream_name = "Tertiary Playback",
.formats = SNDRV_PCM_FMTBIT_S16,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
},
.probe = &asoc_qcom_lpass_cpu_dai_probe,
.ops = &asoc_qcom_lpass_cpu_dai_ops,
}, {
.id = MI2S_QUATERNARY,
.name = "Quaternary MI2S",
.playback = {
.stream_name = "Quaternary Playback",
.formats = SNDRV_PCM_FMTBIT_S16,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
},
.probe = &asoc_qcom_lpass_cpu_dai_probe,
.ops = &asoc_qcom_lpass_cpu_dai_ops,
}, {
.id = LPASS_DP_RX,
.name = "Hdmi",
.playback = {
.stream_name = "Hdmi Playback",
.formats = SNDRV_PCM_FMTBIT_S24,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
},
.ops = &asoc_qcom_lpass_hdmi_dai_ops,
},
};
static int msm8998_lpass_alloc_dma_channel(struct lpass_data *drvdata,
int direction, unsigned int dai_id)
{
struct lpass_variant *v = drvdata->variant;
int chan = 0;
if (dai_id == LPASS_DP_RX) {
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
chan = find_first_zero_bit(&drvdata->hdmi_dma_ch_bit_map,
v->hdmi_rdma_channels);
if (chan >= v->hdmi_rdma_channels)
return -EBUSY;
}
set_bit(chan, &drvdata->hdmi_dma_ch_bit_map);
} else {
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
chan = find_first_zero_bit(&drvdata->dma_ch_bit_map,
v->rdma_channels);
if (chan >= v->rdma_channels)
return -EBUSY;
} else {
chan = find_next_zero_bit(&drvdata->dma_ch_bit_map,
v->wrdma_channel_start +
v->wrdma_channels,
v->wrdma_channel_start);
if (chan >= v->wrdma_channel_start + v->wrdma_channels)
return -EBUSY;
}
set_bit(chan, &drvdata->dma_ch_bit_map);
}
return chan;
}
static int msm8998_lpass_free_dma_channel(struct lpass_data *drvdata, int chan, unsigned int dai_id)
{
if (dai_id == LPASS_DP_RX)
clear_bit(chan, &drvdata->hdmi_dma_ch_bit_map);
else
clear_bit(chan, &drvdata->dma_ch_bit_map);
return 0;
}
static int msm8998_lpass_init(struct platform_device *pdev)
{
struct lpass_data *drvdata = platform_get_drvdata(pdev);
struct lpass_variant *variant = drvdata->variant;
struct device *dev = &pdev->dev;
int ret, i;
drvdata->clks = devm_kcalloc(dev, variant->num_clks,
sizeof(*drvdata->clks), GFP_KERNEL);
drvdata->num_clks = variant->num_clks;
for (i = 0; i < drvdata->num_clks; i++)
drvdata->clks[i].id = variant->clk_name[i];
ret = devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks);
if (ret) {
dev_err(dev, "Failed to get clocks %d\n", ret);
return ret;
}
ret = clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks);
if (ret) {
dev_err(dev, "msm8998 clk_enable failed\n");
return ret;
}
return 0;
}
static int msm8998_lpass_exit(struct platform_device *pdev)
{
struct lpass_data *drvdata = platform_get_drvdata(pdev);
clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks);
return 0;
}
static struct lpass_variant msm8998_data = {
.i2sctrl_reg_base = 0x1000,
.i2sctrl_reg_stride = 0x1000,
.i2s_ports = 3,
.irq_reg_base = 0xa000,
.irq_reg_stride = 0x1000,
.irq_ports = 3,
.rdma_reg_base = 0xD000,
.rdma_reg_stride = 0x1000,
.rdma_channels = 5,
.hdmi_rdma_reg_base = 0x3000,
.hdmi_rdma_reg_stride = 0x1000,
.hdmi_rdma_channels = 4,
.dmactl_audif_start = 1, /* what's that?? */
.wrdma_reg_base = 0x13000,
.wrdma_reg_stride = 0x1000,
.wrdma_channel_start = 5, /* ?? what's that ?? */
.wrdma_channels = 4,
.loopback = REG_FIELD_ID(0x1000, 15, 15, 4, 0x1000),
.spken = REG_FIELD_ID(0x1000, 14, 14, 4, 0x1000),
.spkmode = REG_FIELD_ID(0x1000, 10, 13, 4, 0x1000),
.spkmono = REG_FIELD_ID(0x1000, 9, 9, 4, 0x1000),
.micen = REG_FIELD_ID(0x1000, 8, 8, 4, 0x1000),
.micmode = REG_FIELD_ID(0x1000, 4, 7, 4, 0x1000),
.micmono = REG_FIELD_ID(0x1000, 3, 3, 4, 0x1000),
.wssrc = REG_FIELD_ID(0x1000, 2, 2, 4, 0x1000),
.bitwidth = REG_FIELD_ID(0x1000, 0, 1, 4, 0x1000),
.rdma_dyncclk = REG_FIELD_ID(0xD000, 14, 14, 4, 0x1000),
.rdma_bursten = REG_FIELD_ID(0xD000, 13, 13, 4, 0x1000),
.rdma_wpscnt = REG_FIELD_ID(0xD000, 10, 12, 4, 0x1000),
.rdma_intf = REG_FIELD_ID(0xD000, 6, 9, 4, 0x1000),
.rdma_fifowm = REG_FIELD_ID(0xD000, 1, 5, 4, 0x1000),
.rdma_enable = REG_FIELD_ID(0xD000, 0, 0, 4, 0x1000),
.wrdma_dyncclk = REG_FIELD_ID(0x13000, 12, 12, 3, 0x1000),
.wrdma_bursten = REG_FIELD_ID(0x13000, 11, 11, 3, 0x1000),
.wrdma_wpscnt = REG_FIELD_ID(0x13000, 8, 10, 3, 0x1000),
.wrdma_intf = REG_FIELD_ID(0x13000, 4, 7, 3, 0x1000),
.wrdma_fifowm = REG_FIELD_ID(0x13000, 1, 3, 3, 0x1000),
.wrdma_enable = REG_FIELD_ID(0x13000, 0, 0, 3, 0x1000),
.hdmi_tx_ctl_addr = 0x1000,
.hdmi_legacy_addr = 0x1008,
.hdmi_vbit_addr = 0xc0,
.hdmi_ch_lsb_addr = 0x48,
.hdmi_ch_msb_addr = 0x4c,
.ch_stride = 0x8,
.hdmi_parity_addr = 0x34,
.hdmi_dmactl_addr = 0x38,
.hdmi_dma_stride = 0x4,
.hdmi_DP_addr = 0xc8,
.hdmi_sstream_addr = 0x1c,
.hdmi_irq_reg_base = 0x63000,
.hdmi_irq_ports = 1,
.hdmi_rdma_dyncclk = REG_FIELD_ID(0x3000, 14, 14, 3, 0x1000),
.hdmi_rdma_bursten = REG_FIELD_ID(0x3000, 13, 13, 3, 0x1000),
.hdmi_rdma_burst8 = REG_FIELD_ID(0x3000, 15, 15, 3, 0x1000),
.hdmi_rdma_burst16 = REG_FIELD_ID(0x3000, 16, 16, 3, 0x1000),
.hdmi_rdma_dynburst = REG_FIELD_ID(0x3000, 18, 18, 3, 0x1000),
.hdmi_rdma_wpscnt = REG_FIELD_ID(0x3000, 10, 12, 3, 0x1000),
.hdmi_rdma_fifowm = REG_FIELD_ID(0x3000, 1, 5, 3, 0x1000),
.hdmi_rdma_enable = REG_FIELD_ID(0x3000, 0, 0, 3, 0x1000),
.sstream_en = REG_FIELD(0x1c, 0, 0),
.dma_sel = REG_FIELD(0x1c, 1, 2),
.auto_bbit_en = REG_FIELD(0x1c, 3, 3),
.layout = REG_FIELD(0x1c, 4, 4),
.layout_sp = REG_FIELD(0x1c, 5, 8),
.set_sp_on_en = REG_FIELD(0x1c, 10, 10),
.dp_audio = REG_FIELD(0x1c, 11, 11),
.dp_staffing_en = REG_FIELD(0x1c, 12, 12),
.dp_sp_b_hw_en = REG_FIELD(0x1c, 13, 13),
.mute = REG_FIELD(0xc8, 0, 0),
.as_sdp_cc = REG_FIELD(0xc8, 1, 3),
.as_sdp_ct = REG_FIELD(0xc8, 4, 7),
.aif_db4 = REG_FIELD(0xc8, 8, 15),
.soft_reset = REG_FIELD(0x1000, 31, 31),
.force_reset = REG_FIELD(0x1000, 30, 30),
.use_hw_chs = REG_FIELD(0x38, 0, 0),
.use_hw_usr = REG_FIELD(0x38, 1, 1),
.hw_chs_sel = REG_FIELD(0x38, 2, 4),
.hw_usr_sel = REG_FIELD(0x38, 5, 6),
.replace_vbit = REG_FIELD(0xc0, 0, 0),
.vbit_stream = REG_FIELD(0xc0, 1, 1),
.legacy_en = REG_FIELD(0x1008, 0, 0),
.calc_en = REG_FIELD(0x34, 0, 0),
.lsb_bits = REG_FIELD(0x48, 0, 31),
.msb_bits = REG_FIELD(0x4c, 0, 16),
.clk_name = (const char*[]) {
"pcnoc-sway-clk",
"audio-core",
"pcnoc-mport-clk",
},
.num_clks = 3,
.dai_driver = msm8998_lpass_cpu_dai_driver,
.num_dai = ARRAY_SIZE(msm8998_lpass_cpu_dai_driver),
.dai_osr_clk_names = (const char *[]) {
"mclk0",
"null",
},
.dai_bit_clk_names = (const char *[]) {
"mi2s-bit-clk0",
"mi2s-bit-clk1",
},
.init = msm8998_lpass_init,
.exit = msm8998_lpass_exit,
.alloc_dma_channel = msm8998_lpass_alloc_dma_channel,
.free_dma_channel = msm8998_lpass_free_dma_channel,
};
static const struct of_device_id msm8998_lpass_cpu_device_id[] __maybe_unused = {
{.compatible = "qcom,msm8998-lpass-cpu", .data = &msm8998_data},
{}
};
MODULE_DEVICE_TABLE(of, msm8998_lpass_cpu_device_id);
static struct platform_driver msm8998_lpass_cpu_platform_driver = {
.driver = {
.name = "msm8998-lpass-cpu",
.of_match_table = of_match_ptr(msm8998_lpass_cpu_device_id),
},
.probe = asoc_qcom_lpass_cpu_platform_probe,
.remove = asoc_qcom_lpass_cpu_platform_remove,
.shutdown = asoc_qcom_lpass_cpu_platform_shutdown,
};
module_platform_driver(msm8998_lpass_cpu_platform_driver);
MODULE_DESCRIPTION("msm8998 LPASS CPU DRIVER");
MODULE_LICENSE("GPL v2");

501
sound/soc/qcom/msm8998.c Normal file
View file

@ -0,0 +1,501 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Based on sdm845.c
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* MSM8998 ASoC driver
* Copyright (c) 2021, AngeloGioacchino Del Regno
* <angelogioacchino.delregno@somainline.org>
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/jack.h>
#include <sound/soc.h>
#include <linux/soundwire/sdw.h>
#include <uapi/linux/input-event-codes.h>
#include "common.h"
#include "qdsp6/q6afe.h"
#define DRIVER_NAME "msm8998"
#define DEFAULT_SAMPLE_RATE_48K 48000
#define DEFAULT_MCLK_RATE 24576000
#define TDM_BCLK_RATE 6144000
#define MI2S_BCLK_RATE 1536000
#define LEFT_SPK_TDM_TX_MASK 0x30
#define RIGHT_SPK_TDM_TX_MASK 0xC0
#define SPK_TDM_RX_MASK 0x03
#define NUM_TDM_SLOTS 8
#define SLIM_MAX_TX_PORTS 17
#define SLIM_MAX_RX_PORTS 14
#define WCD934X_DEFAULT_MCLK_RATE 9600000
struct msm8998_snd_data {
struct snd_soc_jack jack;
bool jack_setup;
bool stream_prepared[SLIM_MAX_RX_PORTS];
struct snd_soc_card *card;
uint32_t quat_tdm_clk_count;
struct sdw_stream_runtime *sruntime[SLIM_MAX_RX_PORTS];
};
static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28};
static int msm8998_slim_snd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai;
struct msm8998_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
struct sdw_stream_runtime *sruntime;
u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
int ret = 0, i;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
sruntime = snd_soc_dai_get_stream(codec_dai,
substream->stream);
if (sruntime != ERR_PTR(-ENOTSUPP))
pdata->sruntime[cpu_dai->id] = sruntime;
ret = snd_soc_dai_get_channel_map(codec_dai,
&tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
if (ret != 0 && ret != -ENOTSUPP) {
pr_err("failed to get codec chan map, err:%d\n", ret);
return ret;
} else if (ret == -ENOTSUPP) {
/* Ignore unsupported */
continue;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
rx_ch_cnt, rx_ch);
else
ret = snd_soc_dai_set_channel_map(cpu_dai, tx_ch_cnt,
tx_ch, 0, NULL);
}
return 0;
}
static int msm8998_tdm_snd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai;
int ret = 0, j;
int channels, slot_width;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
slot_width = 16;
break;
default:
dev_err(rtd->dev, "%s: invalid param format 0x%x\n",
__func__, params_format(params));
return -EINVAL;
}
channels = params_channels(params);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0x3,
8, slot_width);
if (ret < 0) {
dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
__func__, ret);
goto end;
}
ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
channels, tdm_slot_offset);
if (ret < 0) {
dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
__func__, ret);
goto end;
}
} else {
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0,
8, slot_width);
if (ret < 0) {
dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
__func__, ret);
goto end;
}
ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
tdm_slot_offset, 0, NULL);
if (ret < 0) {
dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
__func__, ret);
goto end;
}
}
for_each_rtd_codec_dais(rtd, j, codec_dai) {
if (!strcmp(codec_dai->component->name_prefix, "Left")) {
ret = snd_soc_dai_set_tdm_slot(
codec_dai, LEFT_SPK_TDM_TX_MASK,
SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
slot_width);
if (ret < 0) {
dev_err(rtd->dev,
"DEV0 TDM slot err:%d\n", ret);
return ret;
}
}
if (!strcmp(codec_dai->component->name_prefix, "Right")) {
ret = snd_soc_dai_set_tdm_slot(
codec_dai, RIGHT_SPK_TDM_TX_MASK,
SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
slot_width);
if (ret < 0) {
dev_err(rtd->dev,
"DEV1 TDM slot err:%d\n", ret);
return ret;
}
}
}
end:
return ret;
}
static int msm8998_snd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
int ret = 0;
switch (cpu_dai->id) {
case QUATERNARY_TDM_RX_0:
case QUATERNARY_TDM_TX_0:
ret = msm8998_tdm_snd_hw_params(substream, params);
break;
case SLIMBUS_0_RX...SLIMBUS_6_TX:
ret = msm8998_slim_snd_hw_params(substream, params);
break;
case QUATERNARY_MI2S_RX:
break;
default:
pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
break;
}
return ret;
}
static int msm8998_dai_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct msm8998_snd_data *pdata = snd_soc_card_get_drvdata(card);
struct snd_jack *jack;
/*
* Codec SLIMBUS configuration
* RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13, RX14
* TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13, TX14,
* TX15, TX16
*/
unsigned int rx_ch[SLIM_MAX_RX_PORTS] = {144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155,
156, 157 };
unsigned int tx_ch[SLIM_MAX_TX_PORTS] = {128, 129, 130, 131, 132, 133,
134, 135, 136, 137, 138, 139,
140, 141, 142, 143};
int ret, i;
if (!pdata->jack_setup) {
ret = snd_soc_card_jack_new(card, "Headset Jack",
SND_JACK_HEADSET |
SND_JACK_HEADPHONE |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&pdata->jack);
if (ret < 0) {
dev_err(card->dev, "Unable to add Headphone Jack\n");
return ret;
}
jack = pdata->jack.jack;
snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
pdata->jack_setup = true;
}
switch (cpu_dai->id) {
case SLIMBUS_0_RX...SLIMBUS_6_TX:
for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_channel_map(codec_dai,
ARRAY_SIZE(tx_ch), tx_ch,
ARRAY_SIZE(rx_ch), rx_ch);
if (ret != 0 && ret != -ENOTSUPP)
return ret;
snd_soc_dai_set_sysclk(codec_dai, 0,
WCD934X_DEFAULT_MCLK_RATE,
SNDRV_PCM_STREAM_PLAYBACK);
ret = snd_soc_component_set_jack(codec_dai->component,
&pdata->jack, NULL);
if (ret != 0 && ret != -ENOTSUPP) {
dev_warn(card->dev, "Failed to set jack: %d\n", ret);
return ret;
}
}
break;
default:
break;
}
return 0;
}
static int msm8998_snd_startup(struct snd_pcm_substream *substream)
{
unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct msm8998_snd_data *data = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
int j;
int ret;
switch (cpu_dai->id) {
case QUATERNARY_TDM_RX_0:
case QUATERNARY_TDM_TX_0:
if (++(data->quat_tdm_clk_count) == 1) {
snd_soc_dai_set_sysclk(cpu_dai,
Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
}
codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_B;
for_each_rtd_codec_dais(rtd, j, codec_dai) {
if (!strcmp(codec_dai->component->name_prefix,
"Left")) {
ret = snd_soc_dai_set_fmt(
codec_dai, codec_dai_fmt);
if (ret < 0) {
dev_err(rtd->dev,
"Left TDM fmt err:%d\n", ret);
return ret;
}
}
if (!strcmp(codec_dai->component->name_prefix,
"Right")) {
ret = snd_soc_dai_set_fmt(
codec_dai, codec_dai_fmt);
if (ret < 0) {
dev_err(rtd->dev,
"Right TDM slot err:%d\n", ret);
return ret;
}
}
}
break;
case SLIMBUS_0_RX...SLIMBUS_6_TX:
break;
default:
pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
break;
}
return 0;
}
static void msm8998_snd_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct msm8998_snd_data *data = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
switch (cpu_dai->id) {
case QUATERNARY_TDM_RX_0:
case QUATERNARY_TDM_TX_0:
if (--(data->quat_tdm_clk_count) == 0) {
snd_soc_dai_set_sysclk(cpu_dai,
Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
0, SNDRV_PCM_STREAM_PLAYBACK);
}
break;
case SLIMBUS_0_RX...SLIMBUS_6_TX:
case QUATERNARY_MI2S_RX:
break;
default:
pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
break;
}
}
static int msm8998_snd_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct msm8998_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
int ret;
if (!sruntime)
return 0;
if (data->stream_prepared[cpu_dai->id]) {
sdw_disable_stream(sruntime);
sdw_deprepare_stream(sruntime);
data->stream_prepared[cpu_dai->id] = false;
}
ret = sdw_prepare_stream(sruntime);
if (ret)
return ret;
/**
* NOTE: there is a strict hw requirement about the ordering of port
* enables and actual WSA881x PA enable. PA enable should only happen
* after soundwire ports are enabled if not DC on the line is
* accumulated resulting in Click/Pop Noise
* PA enable/mute are handled as part of codec DAPM and digital mute.
*/
ret = sdw_enable_stream(sruntime);
if (ret) {
sdw_deprepare_stream(sruntime);
return ret;
}
data->stream_prepared[cpu_dai->id] = true;
return ret;
}
static int msm8998_snd_hw_free(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct msm8998_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
if (sruntime && data->stream_prepared[cpu_dai->id]) {
sdw_disable_stream(sruntime);
sdw_deprepare_stream(sruntime);
data->stream_prepared[cpu_dai->id] = false;
}
return 0;
}
static const struct snd_soc_ops msm8998_be_ops = {
.hw_params = msm8998_snd_hw_params,
.hw_free = msm8998_snd_hw_free,
.prepare = msm8998_snd_prepare,
.startup = msm8998_snd_startup,
.shutdown = msm8998_snd_shutdown,
};
static int msm8998_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
rate->min = rate->max = DEFAULT_SAMPLE_RATE_48K;
channels->min = channels->max = 2;
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
return 0;
}
static const struct snd_soc_dapm_widget msm8998_snd_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_SPK("Left Spk", NULL),
SND_SOC_DAPM_SPK("Right Spk", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
};
static void msm8998_add_ops(struct snd_soc_card *card)
{
struct snd_soc_dai_link *link;
int i;
for_each_card_prelinks(card, i, link) {
if (link->no_pcm == 1) {
link->ops = &msm8998_be_ops;
link->be_hw_params_fixup = msm8998_be_hw_params_fixup;
}
link->init = msm8998_dai_init;
}
}
static int msm8998_snd_platform_probe(struct platform_device *pdev)
{
struct snd_soc_card *card;
struct msm8998_snd_data *data;
struct device *dev = &pdev->dev;
int ret;
card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
if (!card)
return -ENOMEM;
/* Allocate the private data */
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
card->driver_name = DRIVER_NAME;
card->dapm_widgets = msm8998_snd_widgets;
card->num_dapm_widgets = ARRAY_SIZE(msm8998_snd_widgets);
card->dev = dev;
card->owner = THIS_MODULE;
dev_set_drvdata(dev, card);
ret = qcom_snd_parse_of(card);
if (ret)
return ret;
data->card = card;
snd_soc_card_set_drvdata(card, data);
msm8998_add_ops(card);
return devm_snd_soc_register_card(dev, card);
}
static const struct of_device_id msm8998_snd_device_id[] = {
{ .compatible = "qcom,msm8998-sndcard" },
{},
};
MODULE_DEVICE_TABLE(of, msm8998_snd_device_id);
static struct platform_driver msm8998_snd_driver = {
.probe = msm8998_snd_platform_probe,
.driver = {
.name = "msm-snd-msm8998",
.of_match_table = msm8998_snd_device_id,
},
};
module_platform_driver(msm8998_snd_driver);
MODULE_DESCRIPTION("msm8998 ASoC Machine Driver");
MODULE_LICENSE("GPL v2");