Compare commits

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

174 commits

Author SHA1 Message Date
Caleb Connolly
f856d506e7 interconnect: qcom: msm8998: fix a typo'd QNODE
Fixes a WARN generated by referencing the same node id multiple times
2022-03-30 04:00:55 +03:00
Jami Kettunen
1af0e7a953 pinctrl: aw9523: Add workaround for F(x)tec Pro1 keyboard
(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-03-30 03:29:25 +03:00
Jami Kettunen
8515121db0 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-03-30 03:21:11 +03:00
Jami Kettunen
597ef9ed54 [HACK] drm: Don't WARN_ON() drm_connector_set_panel_orientation() call
This method is used by OnePlus 5 (cheeseburger) during
s6e3fa5_get_modes() and calling it here (which is what all other panel
drivers seem to do as well) causes a massively long 140-line stacktrace
for the 2 hit WARN_ON()s:

  ------------[ cut here ]------------
  WARNING: CPU: 5 PID: 103 at drivers/gpu/drm/drm_mode_object.c:45 drm_mode_object_add+0x80/0x90
  Modules linked in: hci_uart apr fastrpc msm pdr_interface qrtr_smd btqca bluetooth gpu_sched nxp_nci_i2c nxp_nci nci drm_kms_helper nfc rmi_i2c rmi_core ecdh_generic ecc libaes ath10k_snoc ath10k_core cfbfillrect syscopyarea cfbimgblt sysfillrect sysimgblt fb_sys_fops cfbcopyarea ath i2c_qup msm_serial serial_core mac80211 libarc4 sha256_generic libsha256 leds_qcom_lpg cfg80211 led_class_multicolor qcom_fg rtc_pm8xxx ipa qrtr qcom_q6v5_mss qcom_q6v5_pas qcom_stats qcom_pil_info qcom_q6v5 qcom_sysmon qcom_common qcom_smd mdt_loader qmi_helpers smp2p rpmsg_char leds_gpio evdev led_class rmtfs_mem qcom_hwspinlock rfkill dm_mod uinput loop
  CPU: 5 PID: 103 Comm: kworker/u16:5 Tainted: G        W         5.17.0-rc5-msm8998 #7
  Hardware name: OnePlus 5 (DT)
  Workqueue: events_unbound deferred_probe_work_func
  pstate: 40000005 (nZcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
  pc : drm_mode_object_add+0x80/0x90
  lr : drm_property_create+0xd4/0x190
  sp : ffffff808193b210
  x29: ffffff808193b210 x28: 0000000000000020 x27: 0000000000001000
  x26: 0000000000001000 x25: 0000000000000001 x24: ffffffc0087f1f78
  x23: ffffffc008833928 x22: 0000000000000004 x21: 00000000b0b0b0b0
  x20: ffffff8088570b90 x19: ffffff8084b26000 x18: 00000000fffffffb
  x17: 0000007a00440000 x16: 0000000000000000 x15: 0000000000000020
  x14: ffffffffffffffff x13: ffffff8088570b70 x12: ffffff8088570b55
  x11: 0000000000000000 x10: 0000000000000078 x9 : 0000000000000000
  x8 : ffffff8088570c80 x7 : 0000000000000000 x6 : 000000000000003f
  x5 : 0000000000000040 x4 : 0000000000000000 x3 : 0000000000000004
  x2 : 00000000b0b0b0b0 x1 : ffffff8088570b90 x0 : 0000000000000001
  Call trace:
   drm_mode_object_add+0x80/0x90
   drm_property_create+0xd4/0x190
   drm_property_create_enum+0x28/0x90
   drm_connector_set_panel_orientation+0x8c/0xb0
   s6e3fa5_get_modes+0x64/0x80
   drm_panel_get_modes+0x20/0x40
   dsi_mgr_connector_get_modes+0x28/0x40 [msm]
   drm_helper_probe_single_connector_modes+0x19c/0x770 [drm_kms_helper]
   drm_client_modeset_probe+0x1a4/0x1144
   __drm_fb_helper_initial_config_and_unlock+0x30/0x500 [drm_kms_helper]
   drm_fb_helper_initial_config+0x44/0x50 [drm_kms_helper]
   msm_fbdev_init+0x84/0xec [msm]
   msm_drm_bind+0x51c/0x5e0 [msm]
   try_to_bring_up_master+0x218/0x300
   __component_add+0x9c/0x180
   component_add+0x10/0x1c
   dsi_dev_attach+0x1c/0x24 [msm]
   dsi_host_attach+0x90/0x140 [msm]
   mipi_dsi_attach+0x24/0x34
   s6e3fa5_probe+0x10c/0x1cc
   mipi_dsi_drv_probe+0x1c/0x24
   really_probe+0x1b0/0x430
   __driver_probe_device+0x10c/0x180
   driver_probe_device+0x3c/0xf0
   __device_attach_driver+0x94/0x120
   bus_for_each_drv+0x64/0xa0
   __device_attach+0xa8/0x19c
   device_initial_probe+0x10/0x20
   bus_probe_device+0x90/0xa0
   device_add+0x364/0x83c
   mipi_dsi_device_register_full+0xc4/0x150
   mipi_dsi_host_register+0xb8/0x14c
   msm_dsi_host_register+0x3c/0x54 [msm]
   msm_dsi_manager_register+0x144/0x260 [msm]
   dsi_dev_probe+0x124/0x1a4 [msm]
   platform_probe+0x64/0xcc
   really_probe+0x1b0/0x430
   __driver_probe_device+0x10c/0x180
   driver_probe_device+0x3c/0xf0
   __device_attach_driver+0x94/0x120
   bus_for_each_drv+0x64/0xa0
   __device_attach+0xa8/0x19c
   device_initial_probe+0x10/0x20
   bus_probe_device+0x90/0xa0
   deferred_probe_work_func+0x9c/0xf0
   process_one_work+0x1d0/0x350
   worker_thread+0x134/0x450
   kthread+0x104/0x10c
   ret_from_fork+0x10/0x20
  ---[ end trace 0000000000000000 ]---
  ------------[ cut here ]------------
  WARNING: CPU: 5 PID: 103 at drivers/gpu/drm/drm_mode_object.c:242 drm_object_attach_property+0x6c/0xb0
  Modules linked in: hci_uart apr fastrpc msm pdr_interface qrtr_smd btqca bluetooth gpu_sched nxp_nci_i2c nxp_nci nci drm_kms_helper nfc rmi_i2c rmi_core ecdh_generic ecc libaes ath10k_snoc ath10k_core cfbfillrect syscopyarea cfbimgblt sysfillrect sysimgblt fb_sys_fops cfbcopyarea ath i2c_qup msm_serial serial_core mac80211 libarc4 sha256_generic libsha256 leds_qcom_lpg cfg80211 led_class_multicolor qcom_fg rtc_pm8xxx ipa qrtr qcom_q6v5_mss qcom_q6v5_pas qcom_stats qcom_pil_info qcom_q6v5 qcom_sysmon qcom_common qcom_smd mdt_loader qmi_helpers smp2p rpmsg_char leds_gpio evdev led_class rmtfs_mem qcom_hwspinlock rfkill dm_mod uinput loop
  CPU: 5 PID: 103 Comm: kworker/u16:5 Tainted: G        W         5.17.0-rc5-msm8998 #7
  Hardware name: OnePlus 5 (DT)
  Workqueue: events_unbound deferred_probe_work_func
  pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
  pc : drm_object_attach_property+0x6c/0xb0
  lr : drm_connector_set_panel_orientation+0x54/0xb0
  sp : ffffff808193b2b0
  x29: ffffff808193b2b0 x28: 0000000000000020 x27: 0000000000001000
  x26: 0000000000001000 x25: 0000000000000001 x24: ffffffc0087f1f78
  x23: 0000000000000000 x22: 0000000000000000 x21: ffffff8084b26000
  x20: ffffff8088570b00 x19: ffffff8084b90800 x18: 00000000fffffffb
  x17: 0000007a00440000 x16: 0000000000000000 x15: 0000000000000020
  x14: ffffffffffffffff x13: ffffff8088570b70 x12: ffffff8088570b55
  x11: 0000000000000000 x10: 0000000000000078 x9 : ffffff8088570e20
  x8 : ffffff8088570e38 x7 : 00000000c0c0c0c0 x6 : 00000000c0c0c0c0
  x5 : 0000000000000000 x4 : 0000000000000001 x3 : 0000000000000006
  x2 : 0000000000000001 x1 : ffffff8088570b80 x0 : ffffff8084b90840
  Call trace:
   drm_object_attach_property+0x6c/0xb0
   s6e3fa5_get_modes+0x64/0x80
   drm_panel_get_modes+0x20/0x40
   dsi_mgr_connector_get_modes+0x28/0x40 [msm]
   drm_helper_probe_single_connector_modes+0x19c/0x770 [drm_kms_helper]
   drm_client_modeset_probe+0x1a4/0x1144
   __drm_fb_helper_initial_config_and_unlock+0x30/0x500 [drm_kms_helper]
   drm_fb_helper_initial_config+0x44/0x50 [drm_kms_helper]
   msm_fbdev_init+0x84/0xec [msm]
   msm_drm_bind+0x51c/0x5e0 [msm]
   try_to_bring_up_master+0x218/0x300
   __component_add+0x9c/0x180
   component_add+0x10/0x1c
   dsi_dev_attach+0x1c/0x24 [msm]
   dsi_host_attach+0x90/0x140 [msm]
   mipi_dsi_attach+0x24/0x34
   s6e3fa5_probe+0x10c/0x1cc
   mipi_dsi_drv_probe+0x1c/0x24
   really_probe+0x1b0/0x430
   __driver_probe_device+0x10c/0x180
   driver_probe_device+0x3c/0xf0
   __device_attach_driver+0x94/0x120
   bus_for_each_drv+0x64/0xa0
   __device_attach+0xa8/0x19c
   device_initial_probe+0x10/0x20
   bus_probe_device+0x90/0xa0
   device_add+0x364/0x83c
   mipi_dsi_device_register_full+0xc4/0x150
   mipi_dsi_host_register+0xb8/0x14c
   msm_dsi_host_register+0x3c/0x54 [msm]
   msm_dsi_manager_register+0x144/0x260 [msm]
   dsi_dev_probe+0x124/0x1a4 [msm]
   platform_probe+0x64/0xcc
   really_probe+0x1b0/0x430
   __driver_probe_device+0x10c/0x180
   driver_probe_device+0x3c/0xf0
   __device_attach_driver+0x94/0x120
   bus_for_each_drv+0x64/0xa0
   __device_attach+0xa8/0x19c
   device_initial_probe+0x10/0x20
   bus_probe_device+0x90/0xa0
   deferred_probe_work_func+0x9c/0xf0
   process_one_work+0x1d0/0x350
   worker_thread+0x134/0x450
   kthread+0x104/0x10c
   ret_from_fork+0x10/0x20
  ---[ end trace 0000000000000000 ]---
2022-03-29 22:52:48 +03:00
Jami Kettunen
51ec6fb5ed Input: synaptics-rmi4 - suppress F1A probe error on OP5T
In case the DT node doesn't exist don't actually attempt probing.
2022-03-29 22:52:48 +03:00
Jami Kettunen
e6d10ac2e6 [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-03-29 22:52:48 +03:00
Jami Kettunen
efeefaacc5 TEMP: oneplus5: disable all speaker amp stuff
We don't want to blow this up while messing around with audio stuff
early on...
2022-03-29 22:52:48 +03:00
Jami Kettunen
6e8e56b7f4 arm64: dts: msm8998-oneplus-common: Add TFA9890 speaker amp bindings 2022-03-29 22:52:48 +03:00
Jami Kettunen
325024f13a arm64: dts: qcom: msm8998-oneplus-common: Enable PMI8998 LPG leds
Now the RGB notification LEDs can each be controlled individually :)
2022-03-29 22:52:48 +03:00
Jami Kettunen
ca13592c44 arm64: dts: msm8998-oneplus-common: Cap GPU @ 414 MHz max
If it reaches any higher the device has a chance of freezing under high
load; use this as a temp hack until the GPU CPR regulator driver is up.
2022-03-29 22:52:47 +03:00
Jami Kettunen
49690877c7 msm8998-oneplus-common: Configure Adreno 540 GPU 2022-03-29 22:52:47 +03:00
Jami Kettunen
dd8e0ddd98 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-03-29 22:52:47 +03:00
Jami Kettunen
ff77547634 msm8998-oneplus-common: Configure IPA for cellular data 2022-03-29 22:52:47 +03:00
Jami Kettunen
3cba1a0030 msm8998-oneplus-common: Configure PMI8998 fuel gauge for battery info 2022-03-29 22:52:47 +03:00
Jami Kettunen
79802dd6ab msm8998-oneplus-common: Configure CPUfreq scaling hardware 2022-03-29 22:52:47 +03:00
Jami Kettunen
2ea653f154 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-03-29 22:52:47 +03:00
Jami Kettunen
bb5b766d48 msm8998-oneplus-common: Add remoteproc configuration & enable WLAN 2022-03-29 22:52:47 +03:00
Jami Kettunen
8cdfda40c6 msm8998-oneplus-common: Configure blsp1_i2c5_sleep (TS) as no-pull 2022-03-29 22:52:47 +03:00
Jami Kettunen
72a48da166 dt-bindings: display: panel: Document Samsung S6E3FC1 display panel 2022-03-29 22:52:47 +03:00
Jami Kettunen
522ad4866d 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-03-29 22:52:47 +03:00
Jami Kettunen
7a5876b63a 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-03-29 22:52:47 +03:00
Jami Kettunen
2620cc8d7a arm64: dts: msm8998-oneplus-common: Drop unused regulators
Also comment the used ones.
2022-03-29 22:52:47 +03:00
Jami Kettunen
c67fc45041 dt-bindings: display: panel: Document Samsung S6E3FA5 display panel 2022-03-29 22:52:47 +03:00
Jami Kettunen
8bb2d2b6b7 arm64: qcom: msm8998-oneplus-common: Enable NFC 2022-03-29 22:52:47 +03:00
Jami Kettunen
18b60e1e08 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-03-29 22:52:47 +03:00
Jami Kettunen
9f0b72f7d8 [ANNOTATION] Apply some F(x)tec Pro1 patches 2022-03-29 22:52:47 +03:00
Danct12
28a64dcdc1 arm64: dts: msm8998-fxtec-pro1: Add remoteproc configuration 2022-03-29 22:52:47 +03:00
Danct12
9cb6c34719 arm64: dts: msm8998-fxtec-pro1: Enable PMI8998 haptics 2022-03-29 22:52:46 +03:00
Danct12
4c36b04925 arm64: dts: msm8998-fxtec-pro1: Configure PMI8998 fuel gauge
This will account for battery statistics reporting on the Fxtec Pro1 (QX1000)
2022-03-29 22:52:46 +03:00
Jami Kettunen
b800af63dd [ANNOTATION] Apply miscellaneous hacks and patches 2022-03-29 22:52:46 +03:00
Jami Kettunen
af1277a488 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-03-29 22:52:46 +03:00
Jami Kettunen
1628ae181f ASoC: codecs: tfa989x: Add support for tfa9890
This speaker amp model appears to be rather popular on phones and is
used for example by the OnePlus 5/5T.
2022-03-29 22:52:46 +03:00
Jami Kettunen
51418997ad 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-03-29 22:52:46 +03:00
Jami Kettunen
193be10420 drm/msm: Add A540 device support 2022-03-29 22:52:46 +03:00
Jami Kettunen
bdfeaa075c arm64: dts: qcom: msm8998: add IPA information
Add support for the MSM8998 SoC, which includes IPA version 3.1.
2022-03-29 22:52:46 +03:00
Jami Kettunen
88d6e96419 power: supply: qcom_fg: Report online property 2022-03-29 22:52:46 +03:00
Jami Kettunen
8f429d8978 drm/msm: Mention DSI 10nm PHY support for MSM8998 2022-03-29 22:52:46 +03:00
Jami Kettunen
34121e6055 dt-bindings: Document bindings for all MSM8998 devices 2022-03-29 22:52:46 +03:00
Jami Kettunen
927111b0f5 [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.
2022-03-29 22:52:46 +03:00
Jami Kettunen
6c3db94d2e [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-03-29 22:52:46 +03:00
Jami Kettunen
ec6f66ad89 [ANNOTATION] Import WIP "Qualcomm SPMI Fuel Gauge" driver
Drop pmi8994 DTS changes though.

https://gitlab.com/sdm845-mainline/linux/-/commits/driver/pmi8998_fg/
2022-03-29 22:52:46 +03:00
Yassine Oudjana
2eea5fe9f8 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-03-29 22:52:46 +03:00
Yassine Oudjana
87e5901e2b power: pmi8998_fg: Remove some trailing spaces and tabs
This should be squashed.
2022-03-29 22:52:46 +03:00
Joel Selvaraj
fff3a97cdc arm64: dts: qcom: sdm845-oneplus: enable pmi8998 fuel guage
Enable the new pmi8998 fuel gauge

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2022-03-29 22:52:46 +03:00
Joel Selvaraj
f1b6077a13 fg: clean and read charge full and max voltage from dts 2022-03-29 22:52:45 +03:00
Joel Selvaraj
d962bb5d78 power: supply: add battery charging status feature 2022-03-29 22:52:45 +03:00
Joel Selvaraj
8a66c540f2 arm64: dts: qcom: pmi8998: Add nodes for pmi8998 fuel guage 2022-03-29 22:52:45 +03:00
Joel Selvaraj
0c7a8ce70a power: supply: introduce pmi8998 fuel guage driver 2022-03-29 22:52:45 +03:00
Jami Kettunen
f780d839de [ANNOTATION] Import SPMI haptics driver v4
Drop SDM845 DTS changes though.

Link: https://patchwork.kernel.org/project/linux-arm-msm/cover/20211210022639.2779173-1-caleb@connolly.tech/
2022-03-29 22:52:45 +03:00
Jami Kettunen
6f6f039c9e 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-03-29 22:52:45 +03:00
Caleb Connolly
e20414070b 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>
2022-03-29 22:52:45 +03:00
Caleb Connolly
769df9c28b 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-03-29 22:52:45 +03:00
Caleb Connolly
61491d1901 dt-bindings: input: add Qualcomm SPMI haptics driver
Add bindings for qcom PMIC SPMI haptics driver.

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2022-03-29 22:52:45 +03:00
Jami Kettunen
c53aa1d6d4 [ANNOTATION] Base @ angelo/5.14-msm8998-audio-working
I also rebased this tree on the linus/v5.17-rc1 tag and while at it
finally dropped changes irrelevant to msm8998.
2022-03-29 22:52:45 +03:00
AngeloGioacchino Del Regno
e3fa3e3ed1 adreno 5xx: TTBR1 extravaganza on MSM8998
(JAMI: fixup for 5.16)
2022-03-29 22:52:45 +03:00
Jami Kettunen
0b49adafb0 arm64: dts: qcom: msm8998-xperia: various tests
Originally from: c215a022
2022-03-29 22:52:45 +03:00
Jami Kettunen
5b33bb9362 ASoC: wcd9335: various tests
Originally from: c215a022
2022-03-29 22:52:45 +03:00
AngeloGioacchino Del Regno
0bc0889e02 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>
2022-03-29 22:52:45 +03:00
AngeloGioacchino Del Regno
ed0bb1af2a 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-03-29 22:52:45 +03:00
AngeloGioacchino Del Regno
ed8cdf8803 arm64: dts: qcom: AUDIO WORKS oon MSM8998 Sony Yoshino platform!!! 2022-03-29 22:52:45 +03:00
AngeloGioacchino Del Regno
306b319190 ASoC: codecs: wcd9335: Fix headphone jack commit for new upstream kernel 2022-03-29 22:52:45 +03:00
Srinivas Kandagatla
b908c27f65 ASoC: wcd9335: add mbhc support
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
2022-03-29 22:52:45 +03:00
Jami Kettunen
c5da981db7 arm64: dts: qcom: Enable audio on MSM8998 Sony Yoshino platform
Originally from: d95b982a
2022-03-29 22:52:44 +03:00
Jami Kettunen
be48c36833 arm64: dts: qcom: msm8998: More audio related node changes
Originally from: d95b982a
2022-03-29 22:52:44 +03:00
Jami Kettunen
e7f46aaebe fixup! arm64: dts: qcom: msm8998: Configure Adreno GPU and related IOMMU 2022-03-29 22:52:44 +03:00
Jami Kettunen
ddb5a4ec04 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-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
2a698c43a6 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-03-29 22:52:44 +03:00
Jami Kettunen
27d473117b 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-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
a8e39acb81 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)
2022-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
41bea9ea58 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-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
03d8638281 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-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
ec880e7f42 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-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
d445d3a0d8 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-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
b193513789 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-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
3c59b21e13 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-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
62de45c5f8 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>
2022-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
18408450a4 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)
2022-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
d98aa89de2 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-03-29 22:52:44 +03:00
AngeloGioacchino Del Regno
67c05fd705 arm64: dts: qcom: msm8998: Add qcom,adreno-smmu compatible 2022-03-29 22:52:44 +03:00
Jami Kettunen
d54d3d6a7a regulator: qcom-labibb: Always disable interrupts during OCP & SC
Originally from: cd95ecae
2022-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
29fb6d76d3 yoshino: Fix too high overheating backlight, enable all wled strings maple 2022-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
288e9b5162 drm/msm/dsi_phy_10nm: Fix bad VCO rate calculation 2022-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
b4524221dc 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-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
4b7ee7c6c1 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-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
c9f802b140 drm/msm/dpu1: Add DMA2, DMA3 clock control to enum
The enum dpu_clk_ctrl_type misses DPU_CLK_CTRL_DMA{2,3} even though
this driver does actually handle both, if present: add the two in
preparation for adding support for SoCs having them.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
a7333bdc35 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-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
d9db298685 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-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
bbe5a5b1a1 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-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
96e86abbb4 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-03-29 22:52:43 +03:00
Konrad Dybcio
c1fcb53c21 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-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
d4148f80f9 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-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
728bffed0b 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-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
f7acfd9853 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-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
1d6a05921e dt-bindings: i2c: qcom,i2c-qup: Convert txt to YAML schema
Convert the qcom,i2c-qup binding to YAML schema.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
d330c5bc8c drm/msm/dpu1: Add MSM8998 to hw catalog
Bringup functionality for MSM8998 in the DPU, driver which is mostly
the same as SDM845 (just a few variations).

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixup for 5.17)
2022-03-29 22:52:43 +03:00
Konrad Dybcio
666c6e9851 clk: qcom: smd: Add missing MSM8998 RPM clocks
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
JAMI: fixed for a0384ecfe2 ("clk: qcom: smd-rpm: De-duplicate identical entries")
JAMI: fixed for 36354c32bd ("clk: qcom: smd-rpm: Add .recalc_rate hook for clk_smd_rpm_branch_ops")
2022-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
9b043633d2 drm/msm/dpu: Fix timeout issues on command mode panels
In function dpu_encoder_phys_cmd_wait_for_commit_done we are always
checking if the relative CTL is started by waiting for an interrupt
to fire: it is fine to do that, but then sometimes we call this
function while the CTL is up and has never been put down, but that
interrupt gets raised only when the CTL gets a state change from
0 to 1 (disabled to enabled), so we're going to wait for something
that will never happen on its own.

Solving this while avoiding to restart the CTL is actually possible
and can be done by just checking if it is already up and running
when the wait_for_commit_done function is called: in this case, so,
if the CTL was already running, we can say that the commit is done
if the command transmission is complete (in other terms, if the
interface has been flushed).

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-03-29 22:52:43 +03:00
AngeloGioacchino Del Regno
4d6bf1ecf5 drm/msm/dpu: Add a function to retrieve the current CTL status
Add a function that returns whether the requested CTL is active or not:
this will be used in a later commit to fix command mode panel issues.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
ddb7db6e7e 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>
2022-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
3e04d1024d 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-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
e372ac89aa arm64: dts: qcom: Enable panel etc. on MSM8998 F(x)tec Pro1 QX1000
(JAMI: fixup for 5.16)
2022-03-29 22:52:42 +03:00
Konrad Dybcio
4c86b1ef95 arm64: dts: qcom: pm8998: Add VREF_1P25 and REF_GND VADC channels
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2022-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
6fc76bf252 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-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
bd9e161cf0 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-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
df70e2d821 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-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
ebdfc5be87 arm64: dts: qcom: Enable panel etc. on MSM8998 Sony Yoshino platform
(JAMI: fixup for 5.16)
2022-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
5ef8905819 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-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
174914a544 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-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
71dfa2b623 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-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
0023cba0a2 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-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
dffdf15457 dt-bindings: avs: cpr: Convert binding to YAML schema
Convert the qcom,cpr.txt document to YAML schema and place it in the
appropriate directory, since this driver was moved from power/avs
to soc/qcom, but forgets to move the documentation.

Fixes: a7305e684f ("PM: AVS: qcom-cpr: Move the driver to the qcom specific drivers")
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
3b78949610 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-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
b232c0dfd0 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-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
f660d49d1a 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>
2022-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
62c31274b5 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.15 by Jami]
2022-03-29 22:52:42 +03:00
AngeloGioacchino Del Regno
40e639041d 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.15 by Jami]
2022-03-29 22:52:41 +03:00
AngeloGioacchino Del Regno
0485ef79b6 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-03-29 22:52:41 +03:00
Manivannan Sadhasivam
6ebf835ad5 dt-bindings: cpufreq: cpufreq-qcom-hw: Convert to YAML bindings
Convert Qualcomm cpufreq devicetree binding to YAML.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2022-03-29 22:52:41 +03:00
Manivannan Sadhasivam
0c034c5ea7 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-03-29 22:52:41 +03:00
AngeloGioacchino Del Regno
8fa5063793 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-03-29 22:52:41 +03:00
AngeloGioacchino Del Regno
bc5d106fe5 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-03-29 22:52:41 +03:00
AngeloGioacchino Del Regno
2dba96237a 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>
2022-03-29 22:52:41 +03:00
AngeloGioacchino Del Regno
ed38aa4ac2 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-03-29 22:52:41 +03:00
AngeloGioacchino Del Regno
ed5f3ba9c0 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>
2022-03-29 22:52:41 +03:00
Jami Kettunen
24aa91f32b leds: qcom-lpg: Review fixups! 2022-03-29 22:52:41 +03:00
Bjorn Andersson
75b4a47477 arm64: dts: qcom: db820c: Add user LEDs
The db820c has 4 "user LEDs", all connected to the PMI8994. The first
three are connected to the three current sinks provided by the TRILED
and the fourth is connected to MPP2.

By utilizing the DTEST bus the MPP is fed the control signal from the
fourth LPG block, providing a consistent interface to the user.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
(JAMI: fixed up for v5.16-rc1)
2022-03-29 22:52:41 +03:00
Bjorn Andersson
1d5f57a7c3 arm64: dts: qcom: pmi8994: Define MPP block
The pmi8994 has 4 multi-purpose-pins, add these to the definition.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2022-03-29 22:52:41 +03:00
Bjorn Andersson
262f1c68a4 arm64: dts: qcom: sdm845: Enable user LEDs on DB845c
The DB845c has 4 "user LEDs", the last one is already supported as it's
just wired to a gpio. Now that the LPG binding is in place we can wire
up the other 3 LEDs as well.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2022-03-29 22:52:41 +03:00
Bjorn Andersson
562c27df43 arm64: dts: qcom: Add LPG to pm8916, pm8994, pmi8994 and pmi8998
Add PWM/LPG nodes to the PMICs currently supported by the binding.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
(JAMI: fixed up for v5.16-rc1)
2022-03-29 22:52:41 +03:00
Bjorn Andersson
c1c2f1d842 leds: Add driver for Qualcomm LPG
The Light Pulse Generator (LPG) is a PWM-block found in a wide range of
PMICs from Qualcomm. It can operate on fixed parameters or based on a
lookup-table, altering the duty cycle over time - which provides the
means for e.g. hardware assisted transitions of LED brightness.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2022-03-29 22:52:41 +03:00
Bjorn Andersson
8f64838ebb dt-bindings: leds: Add Qualcomm Light Pulse Generator binding
This adds the binding document describing the three hardware blocks
related to the Light Pulse Generator found in a wide range of Qualcomm
PMICs.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2022-03-29 22:52:41 +03:00
Marijn Suijten
da4fc9a401 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-03-29 22:52:41 +03:00
Greg Kroah-Hartman
59db887d13 Linux 5.17.1
Link: https://lore.kernel.org/r/20220325150420.245733653@linuxfoundation.org
Tested-by: Ronald Warsow <rwarsow@gmx.de>
Tested-by: Shuah Khan <skhan@linuxfoundation.org>
Tested-by: Fox Chen <foxhlchen@gmail.com>
Tested-by: Rudi Heitbaum <rudi@heitbaum.com>
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Tested-by: Bagas Sanjaya <bagasdotme@gmail.com>
Tested-by: Fenil Jain <fkjainco@gmail.com>
Tested-by: Ron Economos <re@w6rz.net>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Justin M. Forbes <jforbes@fedoraproject.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:22 +02:00
Eric Dumazet
d5ac598705 llc: only change llc->dev when bind() succeeds
commit 2d327a79ee upstream.

My latest patch, attempting to fix the refcount leak in a minimal
way turned out to add a new bug.

Whenever the bind operation fails before we attempt to grab
a reference count on a device, we might release the device refcount
of a prior successful bind() operation.

syzbot was not happy about this [1].

Note to stable teams:

Make sure commit b37a466837 ("netdevice: add the case if dev is NULL")
is already present in your trees.

[1]
general protection fault, probably for non-canonical address 0xdffffc0000000070: 0000 [#1] PREEMPT SMP KASAN
KASAN: null-ptr-deref in range [0x0000000000000380-0x0000000000000387]
CPU: 1 PID: 3590 Comm: syz-executor361 Tainted: G        W         5.17.0-syzkaller-04796-g169e77764adc #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
RIP: 0010:llc_ui_connect+0x400/0xcb0 net/llc/af_llc.c:500
Code: 80 3c 02 00 0f 85 fc 07 00 00 4c 8b a5 38 05 00 00 48 b8 00 00 00 00 00 fc ff df 49 8d bc 24 80 03 00 00 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 a9 07 00 00 49 8b b4 24 80 03 00 00 4c 89 f2 48
RSP: 0018:ffffc900038cfcc0 EFLAGS: 00010202
RAX: dffffc0000000000 RBX: ffff8880756eb600 RCX: 0000000000000000
RDX: 0000000000000070 RSI: ffffc900038cfe3e RDI: 0000000000000380
RBP: ffff888015ee5000 R08: 0000000000000001 R09: ffff888015ee5535
R10: ffffed1002bdcaa6 R11: 0000000000000000 R12: 0000000000000000
R13: ffffc900038cfe37 R14: ffffc900038cfe38 R15: ffff888015ee5012
FS:  0000555555acd300(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000020000280 CR3: 0000000077db6000 CR4: 00000000003506e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
 <TASK>
 __sys_connect_file+0x155/0x1a0 net/socket.c:1900
 __sys_connect+0x161/0x190 net/socket.c:1917
 __do_sys_connect net/socket.c:1927 [inline]
 __se_sys_connect net/socket.c:1924 [inline]
 __x64_sys_connect+0x6f/0xb0 net/socket.c:1924
 do_syscall_x64 arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x44/0xae
RIP: 0033:0x7f016acb90b9
Code: 28 c3 e8 2a 14 00 00 66 2e 0f 1f 84 00 00 00 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffd417947f8 EFLAGS: 00000246 ORIG_RAX: 000000000000002a
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f016acb90b9
RDX: 0000000000000010 RSI: 0000000020000140 RDI: 0000000000000003
RBP: 00007f016ac7d0a0 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f016ac7d130
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
 </TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:llc_ui_connect+0x400/0xcb0 net/llc/af_llc.c:500

Fixes: 764f4eb684 ("llc: fix netdevice reference leaks in llc_ui_bind()")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Cc: 赵子轩 <beraphin@gmail.com>
Cc: Stoyan Manolov <smanolov@suse.de>
Link: https://lore.kernel.org/r/20220325035827.360418-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:22 +02:00
Rob Clark
dc9363ece2 drm/msm/gpu: Fix crash on devices without devfreq support (v2)
commit 05afd57f4d upstream.

Avoid going down devfreq paths on devices where devfreq is not
initialized.

v2: Change has_devfreq() logic [Dmitry]

Reported-by: Linux Kernel Functional Testing <lkft@linaro.org>
Reported-by: Anders Roxell <anders.roxell@linaro.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>
Fixes: 6aa89ae1fb ("drm/msm/gpu: Cancel idle/boost work on suspend")
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20220308184844.1121029-1-robdclark@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:22 +02:00
Arnd Bergmann
8f8a8f3ab3 nds32: fix access_ok() checks in get/put_user
commit 8926d88ced upstream.

The get_user()/put_user() functions are meant to check for
access_ok(), while the __get_user()/__put_user() functions
don't.

This broke in 4.19 for nds32, when it gained an extraneous
check in __get_user(), but lost the check it needs in
__put_user().

Fixes: 487913ab18 ("nds32: Extract the checking and getting pointer to a macro")
Cc: stable@vger.kernel.org @ v4.19+
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:22 +02:00
Arnd Bergmann
b7509a4e81 m68k: fix access_ok for coldfire
commit 26509034be upstream.

While most m68k platforms use separate address spaces for user
and kernel space, at least coldfire does not, and the other
ones have a TASK_SIZE that is less than the entire 4GB address
range.

Using the default implementation of __access_ok() stops coldfire
user space from trivially accessing kernel memory.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Cc: stable@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:22 +02:00
Bryan O'Donoghue
bed07e7ecc wcn36xx: Differentiate wcn3660 from wcn3620
commit 98d504a82c upstream.

The spread of capability between the three WiFi silicon parts wcn36xx
supports is:

wcn3620 - 802.11 a/b/g
wcn3660 - 802.11 a/b/g/n
wcn3680 - 802.11 a/b/g/n/ac

We currently treat wcn3660 as wcn3620 thus limiting it to 2GHz channels.
Fix this regression by ensuring we differentiate between all three parts.

Fixes: 8490987bdb ("wcn36xx: Hook and identify RF_IRIS_WCN3680")
Cc: stable@vger.kernel.org
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Loic Poulain <loic.poulain@linaro.org>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220125004046.4058284-1-bryan.odonoghue@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:21 +02:00
James Bottomley
ba84f9a483 tpm: use try_get_ops() in tpm-space.c
commit fb5abce6b2 upstream.

As part of the series conversion to remove nested TPM operations:

https://lore.kernel.org/all/20190205224723.19671-1-jarkko.sakkinen@linux.intel.com/

exposure of the chip->tpm_mutex was removed from much of the upper
level code.  In this conversion, tpm2_del_space() was missed.  This
didn't matter much because it's usually called closely after a
converted operation, so there's only a very tiny race window where the
chip can be removed before the space flushing is done which causes a
NULL deref on the mutex.  However, there are reports of this window
being hit in practice, so fix this by converting tpm2_del_space() to
use tpm_try_get_ops(), which performs all the teardown checks before
acquring the mutex.

Cc: stable@vger.kernel.org # 5.4.x
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:21 +02:00
Lino Sanfilippo
6e7baf8414 tpm: fix reference counting for struct tpm_chip
commit 7e0438f83d upstream.

The following sequence of operations results in a refcount warning:

1. Open device /dev/tpmrm.
2. Remove module tpm_tis_spi.
3. Write a TPM command to the file descriptor opened at step 1.

------------[ cut here ]------------
WARNING: CPU: 3 PID: 1161 at lib/refcount.c:25 kobject_get+0xa0/0xa4
refcount_t: addition on 0; use-after-free.
Modules linked in: tpm_tis_spi tpm_tis_core tpm mdio_bcm_unimac brcmfmac
sha256_generic libsha256 sha256_arm hci_uart btbcm bluetooth cfg80211 vc4
brcmutil ecdh_generic ecc snd_soc_core crc32_arm_ce libaes
raspberrypi_hwmon ac97_bus snd_pcm_dmaengine bcm2711_thermal snd_pcm
snd_timer genet snd phy_generic soundcore [last unloaded: spi_bcm2835]
CPU: 3 PID: 1161 Comm: hold_open Not tainted 5.10.0ls-main-dirty #2
Hardware name: BCM2711
[<c0410c3c>] (unwind_backtrace) from [<c040b580>] (show_stack+0x10/0x14)
[<c040b580>] (show_stack) from [<c1092174>] (dump_stack+0xc4/0xd8)
[<c1092174>] (dump_stack) from [<c0445a30>] (__warn+0x104/0x108)
[<c0445a30>] (__warn) from [<c0445aa8>] (warn_slowpath_fmt+0x74/0xb8)
[<c0445aa8>] (warn_slowpath_fmt) from [<c08435d0>] (kobject_get+0xa0/0xa4)
[<c08435d0>] (kobject_get) from [<bf0a715c>] (tpm_try_get_ops+0x14/0x54 [tpm])
[<bf0a715c>] (tpm_try_get_ops [tpm]) from [<bf0a7d6c>] (tpm_common_write+0x38/0x60 [tpm])
[<bf0a7d6c>] (tpm_common_write [tpm]) from [<c05a7ac0>] (vfs_write+0xc4/0x3c0)
[<c05a7ac0>] (vfs_write) from [<c05a7ee4>] (ksys_write+0x58/0xcc)
[<c05a7ee4>] (ksys_write) from [<c04001a0>] (ret_fast_syscall+0x0/0x4c)
Exception stack(0xc226bfa8 to 0xc226bff0)
bfa0:                   00000000 000105b4 00000003 beafe664 00000014 00000000
bfc0: 00000000 000105b4 000103f8 00000004 00000000 00000000 b6f9c000 beafe684
bfe0: 0000006c beafe648 0001056c b6eb6944
---[ end trace d4b8409def9b8b1f ]---

The reason for this warning is the attempt to get the chip->dev reference
in tpm_common_write() although the reference counter is already zero.

Since commit 8979b02aaf ("tpm: Fix reference count to main device") the
extra reference used to prevent a premature zero counter is never taken,
because the required TPM_CHIP_FLAG_TPM2 flag is never set.

Fix this by moving the TPM 2 character device handling from
tpm_chip_alloc() to tpm_add_char_device() which is called at a later point
in time when the flag has been set in case of TPM2.

Commit fdc915f7f7 ("tpm: expose spaces via a device link /dev/tpmrm<n>")
already introduced function tpm_devs_release() to release the extra
reference but did not implement the required put on chip->devs that results
in the call of this function.

Fix this by putting chip->devs in tpm_chip_unregister().

Finally move the new implementation for the TPM 2 handling into a new
function to avoid multiple checks for the TPM_CHIP_FLAG_TPM2 flag in the
good case and error cases.

Cc: stable@vger.kernel.org
Fixes: fdc915f7f7 ("tpm: expose spaces via a device link /dev/tpmrm<n>")
Fixes: 8979b02aaf ("tpm: Fix reference count to main device")
Co-developed-by: Jason Gunthorpe <jgg@ziepe.ca>
Signed-off-by: Jason Gunthorpe <jgg@ziepe.ca>
Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:21 +02:00
Linus Lüssing
46bb87d406 mac80211: fix potential double free on mesh join
commit 4a2d4496e1 upstream.

While commit 6a01afcf84 ("mac80211: mesh: Free ie data when leaving
mesh") fixed a memory leak on mesh leave / teardown it introduced a
potential memory corruption caused by a double free when rejoining the
mesh:

  ieee80211_leave_mesh()
  -> kfree(sdata->u.mesh.ie);
  ...
  ieee80211_join_mesh()
  -> copy_mesh_setup()
     -> old_ie = ifmsh->ie;
     -> kfree(old_ie);

This double free / kernel panics can be reproduced by using wpa_supplicant
with an encrypted mesh (if set up without encryption via "iw" then
ifmsh->ie is always NULL, which avoids this issue). And then calling:

  $ iw dev mesh0 mesh leave
  $ iw dev mesh0 mesh join my-mesh

Note that typically these commands are not used / working when using
wpa_supplicant. And it seems that wpa_supplicant or wpa_cli are going
through a NETDEV_DOWN/NETDEV_UP cycle between a mesh leave and mesh join
where the NETDEV_UP resets the mesh.ie to NULL via a memcpy of
default_mesh_setup in cfg80211_netdev_notifier_call, which then avoids
the memory corruption, too.

The issue was first observed in an application which was not using
wpa_supplicant but "Senf" instead, which implements its own calls to
nl80211.

Fixing the issue by removing the kfree()'ing of the mesh IE in the mesh
join function and leaving it solely up to the mesh leave to free the
mesh IE.

Cc: stable@vger.kernel.org
Fixes: 6a01afcf84 ("mac80211: mesh: Free ie data when leaving mesh")
Reported-by: Matthias Kretschmer <mathias.kretschmer@fit.fraunhofer.de>
Signed-off-by: Linus Lüssing <ll@simonwunderlich.de>
Tested-by: Mathias Kretschmer <mathias.kretschmer@fit.fraunhofer.de>
Link: https://lore.kernel.org/r/20220310183513.28589-1-linus.luessing@c0d3.blue
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:21 +02:00
Arnd Bergmann
a1ad747fc1 uaccess: fix integer overflow on access_ok()
commit 222ca305c9 upstream.

Three architectures check the end of a user access against the
address limit without taking a possible overflow into account.
Passing a negative length or another overflow in here returns
success when it should not.

Use the most common correct implementation here, which optimizes
for a constant 'size' argument, and turns the common case into a
single comparison.

Cc: stable@vger.kernel.org
Fixes: da55128194 ("csky: User access")
Fixes: f663b60f52 ("microblaze: Fix uaccess_ok macro")
Fixes: 7567746e1c ("Hexagon: Add user access functions")
Reported-by: David Laight <David.Laight@aculab.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:21 +02:00
Paul E. McKenney
cfda62aaf8 rcu: Don't deboost before reporting expedited quiescent state
commit 10c5357874 upstream.

Currently rcu_preempt_deferred_qs_irqrestore() releases rnp->boost_mtx
before reporting the expedited quiescent state.  Under heavy real-time
load, this can result in this function being preempted before the
quiescent state is reported, which can in turn prevent the expedited grace
period from completing.  Tim Murray reports that the resulting expedited
grace periods can take hundreds of milliseconds and even more than one
second, when they should normally complete in less than a millisecond.

This was fine given that there were no particular response-time
constraints for synchronize_rcu_expedited(), as it was designed
for throughput rather than latency.  However, some users now need
sub-100-millisecond response-time constratints.

This patch therefore follows Neeraj's suggestion (seconded by Tim and
by Uladzislau Rezki) of simply reversing the two operations.

Reported-by: Tim Murray <timmurray@google.com>
Reported-by: Joel Fernandes <joelaf@google.com>
Reported-by: Neeraj Upadhyay <quic_neeraju@quicinc.com>
Reviewed-by: Neeraj Upadhyay <quic_neeraju@quicinc.com>
Reviewed-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
Tested-by: Tim Murray <timmurray@google.com>
Cc: Todd Kjos <tkjos@google.com>
Cc: Sandeep Patil <sspatil@google.com>
Cc: <stable@vger.kernel.org> # 5.4.x
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:21 +02:00
Ritesh Harjani
bff94c57bd jbd2: fix use-after-free of transaction_t race
commit cc16eecae6 upstream.

jbd2_journal_wait_updates() is called with j_state_lock held. But if
there is a commit in progress, then this transaction might get committed
and freed via jbd2_journal_commit_transaction() ->
jbd2_journal_free_transaction(), when we release j_state_lock.
So check for journal->j_running_transaction everytime we release and
acquire j_state_lock to avoid use-after-free issue.

Link: https://lore.kernel.org/r/948c2fed518ae739db6a8f7f83f1d58b504f87d0.1644497105.git.ritesh.list@gmail.com
Fixes: 4f98186848 ("jbd2: refactor wait logic for transaction updates into a common function")
Cc: stable@kernel.org
Reported-and-tested-by: syzbot+afa2ca5171d93e44b348@syzkaller.appspotmail.com
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Ritesh Harjani <riteshh@linux.ibm.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:21 +02:00
Roberto Sassu
abc9ad36df drm/virtio: Ensure that objs is not NULL in virtio_gpu_array_put_free()
commit 6b79f96f4a upstream.

If virtio_gpu_object_shmem_init() fails (e.g. due to fault injection, as it
happened in the bug report by syzbot), virtio_gpu_array_put_free() could be
called with objs equal to NULL.

Ensure that objs is not NULL in virtio_gpu_array_put_free(), or otherwise
return from the function.

Cc: stable@vger.kernel.org # 5.13.x
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Reported-by: syzbot+e9072e90624a31dfa85f@syzkaller.appspotmail.com
Fixes: 377f8331d0 ("drm/virtio: fix possible leak/unlock virtio_gpu_object_array")
Link: http://patchwork.freedesktop.org/patch/msgid/20211213183122.838119-1-roberto.sassu@huawei.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:21 +02:00
Brian Norris
ae0e10382c Revert "ath: add support for special 0x0 regulatory domain"
commit 1ec7ed5163 upstream.

This reverts commit 2dc016599c.

Users are reporting regressions in regulatory domain detection and
channel availability.

The problem this was trying to resolve was fixed in firmware anyway:

    QCA6174 hw3.0: sdio-4.4.1: add firmware.bin_WLAN.RMH.4.4.1-00042
    4d382787f0

Link: https://bbs.archlinux.org/viewtopic.php?id=254535
Link: http://lists.infradead.org/pipermail/ath10k/2020-April/014871.html
Link: http://lists.infradead.org/pipermail/ath10k/2020-May/015152.html
Link: https://lore.kernel.org/all/1c160dfb-6ccc-b4d6-76f6-4364e0adb6dd@reox.at/
Fixes: 2dc016599c ("ath: add support for special 0x0 regulatory domain")
Cc: <stable@vger.kernel.org>
Cc: Wen Gong <wgong@codeaurora.org>
Signed-off-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20200527165718.129307-1-briannorris@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:21 +02:00
Ismael Ferreras Morezuelas
5f32afca84 Bluetooth: btusb: Use quirk to skip HCI_FLT_CLEAR_ALL on fake CSR controllers
commit b3cf94c8b6 upstream.

Another subset of the more recent batch of Chinese clones aren't
specs-compliant and seem to lock up whenever they receive a
HCI_OP_SET_EVENT_FLT with flt_type set to zero/HCI_FLT_CLEAR_ALL,
which on Linux (until the recent HCI state-machine refactor) happened
right at BR/EDR setup. As there are other less-straightforward ways
of reaching those operations, this patch is still relevant.

So, while all the previous efforts to wrangle the herd of fake CSRs
seem to be paying off (and these also get detected as such) we
still need to take care of this quirk; testers seem to agree
that these dongles tend to work well enough afterwards.

From some cursory USB packet capture on Windows it seems like
that driver doesn't appear to use this clear-all functionality at all.

This patch was tested on some really popular AliExpress-style
dongles, in my case marked as "V5.0". Chip markings: UG8413,
the backside of the PCB says "USB Dangel" (sic).

Here is the `hciconfig -a` output; for completeness:

hci0:	Type: Primary  Bus: USB
	BD Address: 00:1A:7D:DA:7X:XX  ACL MTU: 679:8  SCO MTU: 48:16
	UP RUNNING PSCAN ISCAN
	Features: 0xbf 0x3e 0x4d 0xfa 0xdb 0x3d 0x7b 0xc7
	Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
	Link policy: RSWITCH SNIFF
	Link mode: PERIPHERAL ACCEPT
	Name: 'CSR8510 A10.'
	Class: 0x7c0104
	Service Classes: Rendering, Capturing, Object Transfer, Audio, Telephony
	Device Class: Computer, Desktop workstation
	HCI Version: 4.0 (0x6)  Revision: 0x3120
	LMP Version: 4.0 (0x6)  Subversion: 0x22bb
	Manufacturer: Cambridge Silicon Radio (10)

As well as the `lsusb -vv -d 0a12:0001`:

ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          224 Wireless
  bDeviceSubClass         1 Radio Frequency
  bDeviceProtocol         1 Bluetooth
  bMaxPacketSize0        64
  idVendor           0x0a12 Cambridge Silicon Radio, Ltd
  idProduct          0x0001 Bluetooth Dongle (HCI mode)
  bcdDevice           88.91
  iManufacturer           0
  iProduct                2 BT DONGLE10
  iSerial                 0
  bNumConfigurations      1

Also, changed the benign dmesg print that shows up whenever the
generic force-suspend fails from bt_dev_err to bt_dev_warn;
it's okay and done on a best-effort basis, not a problem
if that does not work.

Also, swapped the HCI subver and LMP subver numbers for the Barrot
in the comment, which I copied wrong the last time around.

Fixes: 81cac64ba2 ("Bluetooth: Deal with USB devices that are faking CSR vendor")
Fixes: cde1a8a992 ("Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers")
Fixes: d74e0ae7e0 ("Bluetooth: btusb: Fix detection of some fake CSR controllers with a bcdDevice val of 0x0134")
Fixes: 0671c06623 ("Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers")
Fixes: f4292e2faf ("Bluetooth: btusb: Make the CSR clone chip force-suspend workaround more generic")

Link: https://bugzilla.kernel.org/show_bug.cgi?id=60824
Link: https://gist.github.com/nevack/6b36b82d715dc025163d9e9124840a07

Cc: stable@vger.kernel.org
Cc: Hans de Goede <hdegoede@redhat.com>
Tested-by: Gonzalo Tornaría <tornaria@cmat.edu.uy>
Tested-by: Mateus Lemos <lemonsmateus@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:21 +02:00
Ismael Ferreras Morezuelas
72deda4b68 Bluetooth: hci_sync: Add a new quirk to skip HCI_FLT_CLEAR_ALL
commit 0eaecfb2e4 upstream.

Some controllers have problems with being sent a command to clear
all filtering. While the HCI code does not unconditionally
send a clear-all anymore at BR/EDR setup (after the state machine
refactor), there might be more ways of hitting these codepaths
in the future as the kernel develops.

Cc: stable@vger.kernel.org
Cc: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:20 +02:00
Larry Finger
ef4d3dcd66 Bluetooth: btusb: Add one more Bluetooth part for the Realtek RTL8852AE
commit 2e7b4a328e upstream.

This Realtek device has both wifi and BT components. The latter reports
a USB ID of 0bda:2852, which is not in the table.

BT device description in /sys/kernel/debug/usb/devices contains the following entries:

T: Bus=01 Lev=01 Prnt=01 Port=03 Cnt=02 Dev#= 3 Spd=12 MxCh= 0
D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0bda ProdID=2852 Rev= 0.00
S: Manufacturer=Realtek
S: Product=Bluetooth Radio
S: SerialNumber=00e04c000001
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms

The missing USB_ID was reported by user trius65 at https://github.com/lwfinger/rtw89/issues/122

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: stable@vger.kernel.org
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:20 +02:00
Giovanni Cabiddu
608d06085d crypto: qat - disable registration of algorithms
commit 8893d27ffc upstream.

The implementations of aead and skcipher in the QAT driver do not
support properly requests with the CRYPTO_TFM_REQ_MAY_BACKLOG flag set.
If the HW queue is full, the driver returns -EBUSY but does not enqueue
the request.
This can result in applications like dm-crypt waiting indefinitely for a
completion of a request that was never submitted to the hardware.

To avoid this problem, disable the registration of all crypto algorithms
in the QAT driver by setting the number of crypto instances to 0 at
configuration time.

Cc: stable@vger.kernel.org
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:20 +02:00
Werner Sembach
0d73a21c48 ACPI: video: Force backlight native for Clevo NL5xRU and NL5xNU
commit c844d22fe0 upstream.

Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a working
native and video interface. However the default detection mechanism first
registers the video interface before unregistering it again and switching
to the native interface during boot. This results in a dangling SBIOS
request for backlight change for some reason, causing the backlight to
switch to ~2% once per boot on the first power cord connect or disconnect
event. Setting the native interface explicitly circumvents this buggy
behaviour by avoiding the unregistering process.

Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
Cc: All applicable <stable@vger.kernel.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:20 +02:00
Maximilian Luz
9024419ced ACPI: battery: Add device HID and quirk for Microsoft Surface Go 3
commit 7dacee0b9e upstream.

For some reason, the Microsoft Surface Go 3 uses the standard ACPI
interface for battery information, but does not use the standard PNP0C0A
HID. Instead it uses MSHW0146 as identifier. Add that ID to the driver
as this seems to work well.

Additionally, the power state is not updated immediately after the AC
has been (un-)plugged, so add the respective quirk for that.

Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Cc: All applicable <stable@vger.kernel.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:20 +02:00
Mark Cilissen
4006144228 ACPI / x86: Work around broken XSDT on Advantech DAC-BJ01 board
commit e702196bf8 upstream.

On this board the ACPI RSDP structure points to both a RSDT and an XSDT,
but the XSDT points to a truncated FADT. This causes all sorts of trouble
and usually a complete failure to boot after the following error occurs:

  ACPI Error: Unsupported address space: 0x20 (*/hwregs-*)
  ACPI Error: AE_SUPPORT, Unable to initialize fixed events (*/evevent-*)
  ACPI: Unable to start ACPI Interpreter

This leaves the ACPI implementation in such a broken state that subsequent
kernel subsystem initialisations go wrong, resulting in among others
mismapped PCI memory, SATA and USB enumeration failures, and freezes.

As this is an older embedded platform that will likely never see any BIOS
updates to address this issue and its default shipping OS only complies to
ACPI 1.0, work around this by forcing `acpi=rsdt`. This patch, applied on
top of Linux 5.10.102, was confirmed on real hardware to fix the issue.

Signed-off-by: Mark Cilissen <mark@yotsuba.nl>
Cc: All applicable <stable@vger.kernel.org>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:20 +02:00
Pablo Neira Ayuso
afdc3f4b81 netfilter: nf_tables: validate registers coming from userspace.
commit 6e1acfa387 upstream.

Bail out in case userspace uses unsupported registers.

Fixes: 49499c3e6e ("netfilter: nf_tables: switch registers to 32 bit addressing")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:20 +02:00
Pablo Neira Ayuso
dd03640529 netfilter: nf_tables: initialize registers in nft_do_chain()
commit 4c905f6740 upstream.

Initialize registers to avoid stack leak into userspace.

Fixes: 96518518cc ("netfilter: add nftables")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:20 +02:00
Stephane Graber
8e8f66882b drivers: net: xgene: Fix regression in CRC stripping
commit e9e6faeafa upstream.

All packets on ingress (except for jumbo) are terminated with a 4-bytes
CRC checksum. It's the responsability of the driver to strip those 4
bytes. Unfortunately a change dating back to March 2017 re-shuffled some
code and made the CRC stripping code effectively dead.

This change re-orders that part a bit such that the datalen is
immediately altered if needed.

Fixes: 4902a92270 ("drivers: net: xgene: Add workaround for errata 10GE_8/ENET_11")
Cc: stable@vger.kernel.org
Signed-off-by: Stephane Graber <stgraber@ubuntu.com>
Tested-by: Stephane Graber <stgraber@ubuntu.com>
Link: https://lore.kernel.org/r/20220322224205.752795-1-stgraber@ubuntu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:20 +02:00
Giacomo Guiduzzi
7a378016d6 ALSA: pci: fix reading of swapped values from pcmreg in AC97 codec
commit 17aaf01933 upstream.

Tests 72 and 78 for ALSA in kselftest fail due to reading
inconsistent values from some devices on a VirtualBox
Virtual Machine using the snd_intel8x0 driver for the AC'97
Audio Controller device.
Taking for example test number 72, this is what the test reports:
"Surround Playback Volume.0 expected 1 but read 0, is_volatile 0"
"Surround Playback Volume.1 expected 0 but read 1, is_volatile 0"
These errors repeat for each value from 0 to 31.

Taking a look at these error messages it is possible to notice
that the written values are read back swapped.
When the write is performed, these values are initially stored in
an array used to sanity-check them and write them in the pcmreg
array. To write them, the two one-byte values are packed together
in a two-byte variable through bitwise operations: the first
value is shifted left by one byte and the second value is stored in the
right byte through a bitwise OR. When reading the values back,
right shifts are performed to retrieve the previously stored
bytes. These shifts are executed in the wrong order, thus
reporting the values swapped as shown above.

This patch fixes this mistake by reversing the read
operations' order.

Signed-off-by: Giacomo Guiduzzi <guiduzzi.giacomo@gmail.com>
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20220322200653.15862-1-guiduzzi.giacomo@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:20 +02:00
Jonathan Teh
efeffb3029 ALSA: cmipci: Restore aux vol on suspend/resume
commit c14231cc04 upstream.

Save and restore CM_REG_AUX_VOL instead of register 0x24 twice on
suspend/resume.

Tested on CMI8738LX.

Fixes: cb60e5f5b2 ("[ALSA] cmipci - Add PM support")
Signed-off-by: Jonathan Teh <jonathan.teh@outlook.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/DBAPR04MB7366CB3EA9C8521C35C56E8B920E9@DBAPR04MB7366.eurprd04.prod.outlook.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:19 +02:00
Lars-Peter Clausen
7188dd4d75 ALSA: usb-audio: Add mute TLV for playback volumes on RODE NT-USB
commit 0f306cca42 upstream.

For the RODE NT-USB the lowest Playback mixer volume setting mutes the
audio output. But it is not reported as such causing e.g. PulseAudio to
accidentally mute the device when selecting a low volume.

Fix this by applying the existing quirk for this kind of issue when the
device is detected.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20220311201400.235892-1-lars@metafoo.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:19 +02:00
Takashi Iwai
e7e04e2524 ALSA: pcm: Add stream lock during PCM reset ioctl operations
commit 1f68915b2e upstream.

snd_pcm_reset() is a non-atomic operation, and it's allowed to run
during the PCM stream running.  It implies that the manipulation of
hw_ptr and other parameters might be racy.

This patch adds the PCM stream lock at appropriate places in
snd_pcm_*_reset() actions for covering that.

Cc: <stable@vger.kernel.org>
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20220322171325.4355-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:19 +02:00
Takashi Iwai
5ed8f8e3c4 ALSA: pcm: Fix races among concurrent prealloc proc writes
commit 69534c48ba upstream.

We have no protection against concurrent PCM buffer preallocation
changes via proc files, and it may potentially lead to UAF or some
weird problem.  This patch applies the PCM open_mutex to the proc
write operation for avoiding the racy proc writes and the PCM stream
open (and further operations).

Cc: <stable@vger.kernel.org>
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20220322170720.3529-5-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:19 +02:00
Takashi Iwai
e9d0553225 ALSA: pcm: Fix races among concurrent prepare and hw_params/hw_free calls
commit 3c3201f8c7 upstream.

Like the previous fixes to hw_params and hw_free ioctl races, we need
to paper over the concurrent prepare ioctl calls against hw_params and
hw_free, too.

This patch implements the locking with the existing
runtime->buffer_mutex for prepare ioctls.  Unlike the previous case
for snd_pcm_hw_hw_params() and snd_pcm_hw_free(), snd_pcm_prepare() is
performed to the linked streams, hence the lock can't be applied
simply on the top.  For tracking the lock in each linked substream, we
modify snd_pcm_action_group() slightly and apply the buffer_mutex for
the case stream_lock=false (formerly there was no lock applied)
there.

Cc: <stable@vger.kernel.org>
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20220322170720.3529-4-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:19 +02:00
Takashi Iwai
dd2f8c684d ALSA: pcm: Fix races among concurrent read/write and buffer changes
commit dca947d4d2 upstream.

In the current PCM design, the read/write syscalls (as well as the
equivalent ioctls) are allowed before the PCM stream is running, that
is, at PCM PREPARED state.  Meanwhile, we also allow to re-issue
hw_params and hw_free ioctl calls at the PREPARED state that may
change or free the buffers, too.  The problem is that there is no
protection against those mix-ups.

This patch applies the previously introduced runtime->buffer_mutex to
the read/write operations so that the concurrent hw_params or hw_free
call can no longer interfere during the operation.  The mutex is
unlocked before scheduling, so we don't take it too long.

Cc: <stable@vger.kernel.org>
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20220322170720.3529-3-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:19 +02:00
Takashi Iwai
1bbf82d9f9 ALSA: pcm: Fix races among concurrent hw_params and hw_free calls
commit 92ee3c60ec upstream.

Currently we have neither proper check nor protection against the
concurrent calls of PCM hw_params and hw_free ioctls, which may result
in a UAF.  Since the existing PCM stream lock can't be used for
protecting the whole ioctl operations, we need a new mutex to protect
those racy calls.

This patch introduced a new mutex, runtime->buffer_mutex, and applies
it to both hw_params and hw_free ioctl code paths.  Along with it, the
both functions are slightly modified (the mmap_count check is moved
into the state-check block) for code simplicity.

Reported-by: Hu Jiahui <kirin.say@gmail.com>
Cc: <stable@vger.kernel.org>
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20220322170720.3529-2-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:19 +02:00
Jason Zheng
81b0e6aa90 ALSA: hda/realtek: Add quirk for ASUS GA402
commit b7557267c2 upstream.

ASUS GA402 requires a workaround to manage the routing of its 4 speakers
like the other ASUS models. Add a corresponding quirk entry to fix it.

Signed-off-by: Jason Zheng <jasonzheng2004@gmail.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20220313092216.29858-1-jasonzheng2004@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:19 +02:00
huangwenhui
5d2f019b7a ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc671
commit 882bd07f56 upstream.

On a HP 288 Pro G8, the front mic could not be detected.In order to
get it working, the pin configuration needs to be set correctly, and
the ALC671_FIXUP_HP_HEADSET_MIC2 fixup needs to be applied.

Signed-off-by: huangwenhui <huangwenhuia@uniontech.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20220311093836.20754-1-huangwenhuia@uniontech.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:19 +02:00
Tim Crawford
e3a8cf32be ALSA: hda/realtek: Add quirk for Clevo NP50PNJ
commit 9cb7275067 upstream.

Fixes headset detection on Clevo NP50PNJ.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20220307193229.5141-1-tcrawford@system76.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:19 +02:00
Tim Crawford
d5ec0858e7 ALSA: hda/realtek: Add quirk for Clevo NP70PNJ
commit 0c20fce13e upstream.

Fixes headset detection on Clevo NP70PNJ.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20220304170840.3351-1-tcrawford@system76.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:18 +02:00
Reza Jahanbakhshi
1e6c2681b5 ALSA: usb-audio: add mapping for new Corsair Virtuoso SE
commit cd94df1795 upstream.

New device id for Corsair Virtuoso SE RGB Wireless that currently is not
in the mixer_map. This entry in the mixer_map is necessary in order to
label its mixer appropriately and allow userspace to pick the correct
volume controls. For instance, my own Corsair Virtuoso SE RGB Wireless
headset has this new ID and consequently, the sidetone and volume are not
 working correctly without this change.
> sudo lsusb -v | grep -i corsair
Bus 007 Device 011: ID 1b1c:0a40 Corsair CORSAIR VIRTUOSO SE Wireless Gam
  idVendor           0x1b1c Corsair
  iManufacturer           1 Corsair
  iProduct                2 CORSAIR VIRTUOSO SE Wireless Gaming Headset

Signed-off-by: Reza Jahanbakhshi <reza.jahanbakhshi@gmail.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20220304212303.195949-1-reza.jahanbakhshi@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:18 +02:00
Takashi Iwai
e74a069c6a ALSA: oss: Fix PCM OSS buffer allocation overflow
commit efb6402c3c upstream.

We've got syzbot reports hitting INT_MAX overflow at vmalloc()
allocation that is called from snd_pcm_plug_alloc().  Although we
apply the restrictions to input parameters, it's based only on the
hw_params of the underlying PCM device.  Since the PCM OSS layer
allocates a temporary buffer for the data conversion, the size may
become unexpectedly large when more channels or higher rates is given;
in the reported case, it went over INT_MAX, hence it hits WARN_ON().

This patch is an attempt to avoid such an overflow and an allocation
for too large buffers.  First off, it adds the limit of 1MB as the
upper bound for period bytes.  This must be large enough for all use
cases, and we really don't want to handle a larger temporary buffer
than this size.  The size check is performed at two places, where the
original period bytes is calculated and where the plugin buffer size
is calculated.

In addition, the driver uses array_size() and array3_size() for
multiplications to catch overflows for the converted period size and
buffer bytes.

Reported-by: syzbot+72732c532ac1454eeee9@syzkaller.appspotmail.com
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/00000000000085b1b305da5a66f3@google.com
Link: https://lore.kernel.org/r/20220318082036.29699-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:18 +02:00
Takashi Iwai
39504539ca ASoC: sti: Fix deadlock via snd_pcm_stop_xrun() call
commit 455c5653f5 upstream.

This is essentially a revert of the commit dc865fb9e7 ("ASoC: sti:
Use snd_pcm_stop_xrun() helper"), which converted the manual
snd_pcm_stop() calls with snd_pcm_stop_xrun().

The commit above introduced a deadlock as snd_pcm_stop_xrun() itself
takes the PCM stream lock while the caller already holds it.  Since
the conversion was done only for consistency reason and the open-call
with snd_pcm_stop() to the XRUN state is a correct usage, let's revert
the commit back as the fix.

Fixes: dc865fb9e7 ("ASoC: sti: Use snd_pcm_stop_xrun() helper")
Reported-by: Daniel Palmer <daniel@0x0f.com>
Cc: Arnaud POULIQUEN <arnaud.pouliquen@st.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20220315091319.3351522-1-daniel@0x0f.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Reviewed-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
Link: https://lore.kernel.org/r/20220315164158.19804-1-tiwai@suse.de
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:18 +02:00
Eric Dumazet
ef1a6fe356 llc: fix netdevice reference leaks in llc_ui_bind()
commit 764f4eb684 upstream.

Whenever llc_ui_bind() and/or llc_ui_autobind()
took a reference on a netdevice but subsequently fail,
they must properly release their reference
or risk the infamous message from unregister_netdevice()
at device dismantle.

unregister_netdevice: waiting for eth0 to become free. Usage count = 3

Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: 赵子轩 <beraphin@gmail.com>
Reported-by: Stoyan Manolov <smanolov@suse.de>
Link: https://lore.kernel.org/r/20220323004147.1990845-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:18 +02:00
Helmut Grohne
816a512233 Bluetooth: btusb: Add another Realtek 8761BU
commit 6dfbe29f45 upstream.

This device is sometimes wrapped with a label "EDUP".

T:  Bus=01 Lev=02 Prnt=02 Port=02 Cnt=03 Dev#=107 Spd=12   MxCh= 0
D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=2550 ProdID=8761 Rev= 2.00
S:  Manufacturer=Realtek
S:  Product=Bluetooth Radio
S:  SerialNumber=00E04C239987
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=81(I) Atr=03(Int.) MxPS=  16 Ivl=1ms
E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=   0 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=   0 Ivl=1ms
I:  If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=   9 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=   9 Ivl=1ms
I:  If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  17 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  17 Ivl=1ms
I:  If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  25 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  25 Ivl=1ms
I:  If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  33 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  33 Ivl=1ms
I:  If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  49 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  49 Ivl=1ms

Signed-off-by: Helmut Grohne <helmut@subdivi.de>
Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1955351
Cc: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:18 +02:00
Tadeusz Struk
0d15c66771 tpm: Fix error handling in async work
commit 2e8e4c8f66 upstream.

When an invalid (non existing) handle is used in a TPM command,
that uses the resource manager interface (/dev/tpmrm0) the resource
manager tries to load it from its internal cache, but fails and
the tpm_dev_transmit returns an -EINVAL error to the caller.
The existing async handler doesn't handle these error cases
currently and the condition in the poll handler never returns
mask with EPOLLIN set.
The result is that the poll call blocks and the application gets stuck
until the user_read_timer wakes it up after 120 sec.
Change the tpm_dev_async_work function to handle error conditions
returned from tpm_dev_transmit they are also reflected in the poll mask
and a correct error code could passed back to the caller.

Cc: Jarkko Sakkinen <jarkko@kernel.org>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: <linux-integrity@vger.kernel.org>
Cc: <stable@vger.kernel.org>
Cc: <linux-kernel@vger.kernel.org>

Fixes: 9e1b74a63f ("tpm: add support for nonblocking operation")
Tested-by: Jarkko Sakkinen<jarkko@kernel.org>
Signed-off-by: Tadeusz Struk <tstruk@gmail.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Cc: Tadeusz Struk <tadeusz.struk@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-28 10:03:18 +02:00
157 changed files with 19065 additions and 1148 deletions

View file

@ -313,6 +313,12 @@ properties:
* arm/msm/qcom,kpss-acc.txt
qcom,freq-domain:
$ref: '/schemas/types.yaml#/definitions/phandle-array'
description: |
CPUs supporting freq-domain must set their "qcom,freq-domain" property
with phandle to a cpufreq_hw node followed by the Domain ID(0/1).
rockchip,pmu:
$ref: '/schemas/types.yaml#/definitions/phandle'
description: |

View file

@ -41,6 +41,7 @@ description: |
sa8155p
sc7180
sc7280
msm8998
sdm630
sdm660
sdm845
@ -210,6 +211,16 @@ properties:
- google,senor
- const: qcom,sc7280
- items:
- enum:
- asus,novago-tp370ql
- hp,envy-x2
- lenovo,miix-630
- oneplus,cheeseburger
- oneplus,dumpling
- qcom,msm8998-mtp
- const: qcom,msm8998
- items:
- enum:
- xiaomi,lavender

View file

@ -1,172 +0,0 @@
Qualcomm Technologies, Inc. CPUFREQ Bindings
CPUFREQ HW is a hardware engine used by some Qualcomm Technologies, Inc. (QTI)
SoCs to manage frequency in hardware. It is capable of controlling frequency
for multiple clusters.
Properties:
- compatible
Usage: required
Value type: <string>
Definition: must be "qcom,cpufreq-hw" or "qcom,cpufreq-epss".
- clocks
Usage: required
Value type: <phandle> From common clock binding.
Definition: clock handle for XO clock and GPLL0 clock.
- clock-names
Usage: required
Value type: <string> From common clock binding.
Definition: must be "xo", "alternate".
- reg
Usage: required
Value type: <prop-encoded-array>
Definition: Addresses and sizes for the memory of the HW bases in
each frequency domain.
- reg-names
Usage: Optional
Value type: <string>
Definition: Frequency domain name i.e.
"freq-domain0", "freq-domain1".
- #freq-domain-cells:
Usage: required.
Definition: Number of cells in a freqency domain specifier.
* Property qcom,freq-domain
Devices supporting freq-domain must set their "qcom,freq-domain" property with
phandle to a cpufreq_hw followed by the Domain ID(0/1) in the CPU DT node.
Example:
Example 1: Dual-cluster, Quad-core per cluster. CPUs within a cluster switch
DCVS state together.
/ {
cpus {
#address-cells = <2>;
#size-cells = <0>;
CPU0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x0>;
enable-method = "psci";
next-level-cache = <&L2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
L2_0: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
L3_0: l3-cache {
compatible = "cache";
};
};
};
CPU1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x100>;
enable-method = "psci";
next-level-cache = <&L2_100>;
qcom,freq-domain = <&cpufreq_hw 0>;
L2_100: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x200>;
enable-method = "psci";
next-level-cache = <&L2_200>;
qcom,freq-domain = <&cpufreq_hw 0>;
L2_200: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x300>;
enable-method = "psci";
next-level-cache = <&L2_300>;
qcom,freq-domain = <&cpufreq_hw 0>;
L2_300: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x400>;
enable-method = "psci";
next-level-cache = <&L2_400>;
qcom,freq-domain = <&cpufreq_hw 1>;
L2_400: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x500>;
enable-method = "psci";
next-level-cache = <&L2_500>;
qcom,freq-domain = <&cpufreq_hw 1>;
L2_500: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x600>;
enable-method = "psci";
next-level-cache = <&L2_600>;
qcom,freq-domain = <&cpufreq_hw 1>;
L2_600: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x700>;
enable-method = "psci";
next-level-cache = <&L2_700>;
qcom,freq-domain = <&cpufreq_hw 1>;
L2_700: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
};
soc {
cpufreq_hw: cpufreq@17d43000 {
compatible = "qcom,cpufreq-hw";
reg = <0x17d43000 0x1400>, <0x17d45800 0x1400>;
reg-names = "freq-domain0", "freq-domain1";
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
clock-names = "xo", "alternate";
#freq-domain-cells = <1>;
};
}

View file

@ -0,0 +1,242 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/cpufreq/cpufreq-qcom-hw.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. CPUFREQ
maintainers:
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
description: |
CPUFREQ HW is a hardware engine used by some Qualcomm Technologies, Inc. (QTI)
SoCs to manage frequency in hardware. It is capable of controlling frequency
for multiple clusters.
properties:
compatible:
oneOf:
- description: Non-secure v1 of CPUFREQ HW
items:
- const: qcom,cpufreq-hw-8998
- description: v1 of CPUFREQ HW
items:
- const: qcom,cpufreq-hw
- description: v2 of CPUFREQ HW (EPSS)
items:
- enum:
- qcom,sm8250-cpufreq-epss
- const: qcom,cpufreq-epss
reg: {}
reg-names: {}
clocks:
items:
- description: XO Clock
- description: GPLL0 Clock
clock-names:
items:
- const: xo
- const: alternate
'#freq-domain-cells':
const: 1
if:
properties:
compatible:
contains:
const: qcom,cpufreq-hw-8998
then:
properties:
reg:
minItems: 2
maxItems: 6
items:
- description: Frequency domain 0 register region
- description: Operating State Manager domain 0 register region
- description: Frequency domain 1 register region
- description: Operating State Manager domain 1 register region
- description: PLL ACD domain 0 register region (if ACD programming required)
- description: PLL ACD domain 1 register region (if ACD programming required)
reg-names:
minItems: 2
maxItems: 6
items:
- const: "osm-domain0"
- const: "freq-domain0"
- const: "osm-domain1"
- const: "freq-domain1"
- const: "osm-acd0"
- const: "osm-acd1"
else:
properties:
reg:
minItems: 2
maxItems: 3
items:
- description: Frequency domain 0 register region
- description: Frequency domain 1 register region
- description: Frequency domain 2 register region
reg-names:
minItems: 2
maxItems: 3
items:
- const: "freq-domain0"
- const: "freq-domain1"
- const: "freq-domain2"
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- '#freq-domain-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-sdm845.h>
#include <dt-bindings/clock/qcom,rpmh.h>
// Example 1: Dual-cluster, Quad-core per cluster. CPUs within a cluster
// switch DCVS state together.
cpus {
#address-cells = <2>;
#size-cells = <0>;
CPU0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x0>;
enable-method = "psci";
next-level-cache = <&L2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
L2_0: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
L3_0: l3-cache {
compatible = "cache";
};
};
};
CPU1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x100>;
enable-method = "psci";
next-level-cache = <&L2_100>;
qcom,freq-domain = <&cpufreq_hw 0>;
L2_100: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x200>;
enable-method = "psci";
next-level-cache = <&L2_200>;
qcom,freq-domain = <&cpufreq_hw 0>;
L2_200: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x300>;
enable-method = "psci";
next-level-cache = <&L2_300>;
qcom,freq-domain = <&cpufreq_hw 0>;
L2_300: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x400>;
enable-method = "psci";
next-level-cache = <&L2_400>;
qcom,freq-domain = <&cpufreq_hw 1>;
L2_400: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x500>;
enable-method = "psci";
next-level-cache = <&L2_500>;
qcom,freq-domain = <&cpufreq_hw 1>;
L2_500: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x600>;
enable-method = "psci";
next-level-cache = <&L2_600>;
qcom,freq-domain = <&cpufreq_hw 1>;
L2_600: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
CPU7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x700>;
enable-method = "psci";
next-level-cache = <&L2_700>;
qcom,freq-domain = <&cpufreq_hw 1>;
L2_700: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
};
};
};
soc {
#address-cells = <1>;
#size-cells = <1>;
cpufreq@17d43000 {
compatible = "qcom,cpufreq-hw";
reg = <0x17d43000 0x1400>, <0x17d45800 0x1400>;
reg-names = "freq-domain0", "freq-domain1";
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
clock-names = "xo", "alternate";
#freq-domain-cells = <1>;
};
};
...

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

@ -1,40 +0,0 @@
Qualcomm Universal Peripheral (QUP) I2C controller
Required properties:
- compatible: Should be:
* "qcom,i2c-qup-v1.1.1" for 8660, 8960 and 8064.
* "qcom,i2c-qup-v2.1.1" for 8974 v1.
* "qcom,i2c-qup-v2.2.1" for 8974 v2 and later.
- reg: Should contain QUP register address and length.
- interrupts: Should contain I2C interrupt.
- clocks: A list of phandles + clock-specifiers, one for each entry in
clock-names.
- clock-names: Should contain:
* "core" for the core clock
* "iface" for the AHB clock
- #address-cells: Should be <1> Address cells for i2c device address
- #size-cells: Should be <0> as i2c addresses have no size component
Optional properties:
- clock-frequency: Should specify the desired i2c bus clock frequency in Hz,
defaults to 100kHz if omitted.
Child nodes should conform to i2c bus binding.
Example:
i2c@f9924000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0xf9924000 0x1000>;
interrupts = <0 96 0>;
clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
clock-names = "core", "iface";
clock-frequency = <355000>;
#address-cells = <1>;
#size-cells = <0>;
};

View file

@ -0,0 +1,101 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/qcom,i2c-qup.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Universal Peripheral (QUP) I2C controller
maintainers:
- Andy Gross <agross@kernel.org>
- Bjorn Andersson <bjorn.andersson@linaro.org>
description: Binding for Qualcomm "QUP" I2C controllers
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties:
compatible:
enum:
- qcom,i2c-qup-v1.1.1
- qcom,i2c-qup-v2.1.1
- qcom,i2c-qup-v2.2.1
reg:
items:
- description: QUP I2C register iospace
clocks:
items:
- description: Core QUP I2C clock
- description: AHB clock
clock-names:
items:
- const: core
- const: iface
clock-frequency:
minimum: 100000
maximum: 1000000
default: 100000
dmas:
items:
- description: RX DMA Channel phandle
- description: TX DMA Channel phandle
dma-names:
items:
- const: rx
- const: tx
'#address-cells':
const: 1
'#size-cells':
const: 0
qcom,noise-reject-sda:
$ref: /schemas/types.yaml#/definitions/uint32
description: Noise rejection level for the SDA line.
minimum: 0
maximum: 3
default: 0
qcom,noise-reject-scl:
$ref: /schemas/types.yaml#/definitions/uint32
description: Noise rejection level for the SCL line.
minimum: 0
maximum: 3
default: 0
required:
- compatible
- clocks
- clock-names
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-msm8998.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
i2c@c175000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x0c175000 0x600>;
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>,
<&gcc GCC_BLSP1_AHB_CLK>;
clock-names = "core", "iface";
clock-frequency = <400000>;
dmas = <&blsp_dma 4>, <&blsp_dma 5>;
dma-names = "rx", "tx";
#address-cells = <1>;
#size-cells = <0>;
};

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,123 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright 2020 Unisoc Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/qcom,spmi-haptics.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies Inc PMI8998 spmi haptics
maintainers:
- Caleb Connolly <caleb@connolly.tech>
description: |
Qualcomm SPMI haptics is a peripheral on some QTI PMICs. It supports linear resonant
actuators and eccentric rotating mass type haptics commonly found in mobile devices.
It supports multiple sources of wave data such as an internal buffer, direct play
(from kernel or userspace) as well as an audio output mode.
properties:
compatible:
items:
- enum:
- qcom,pmi8998-haptics
- qcom,pmi8996-haptics
- qcom,pmi8941-haptics
reg:
maxItems: 1
interrupts:
items:
- description: short circuit interrupt
- description: play interrupt
interrupt-names:
items:
- const: short
- const: play
qcom,actuator-type:
description: |
The type of actuator attached to the hardware.
Allowed values are,
0 - HAP_TYPE_LRA
1 - HAP_TYPE_ERM
$ref: /schemas/types.yaml#/definitions/uint32
enum: [ 0, 1 ]
default: 0
qcom,wave-shape:
description: |
Selects the wave shape to use.
Allowed values are,
0 - HAP_WAVE_SINE
1 - HAP_WAVE_SQUARE
$ref: /schemas/types.yaml#/definitions/uint32
enum: [ 0, 1 ]
default: 0
qcom,play-mode:
description: |
Selects the play mode to use.
Allowed values are,
0 - HAP_PLAY_DIRECT
1 - HAP_PLAY_BUFFER
2 - HAP_PLAY_AUDIO
3 - HAP_PLAY_PWM
$ref: /schemas/types.yaml#/definitions/uint32
enum: [ 0, 1, 2, 3 ]
default: 2
qcom,wave-play-rate-us:
description: |
Wave sample durection in microseconds, 1/f where f
is the resonant frequency of the actuator.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 20475
qcom,brake-pattern:
minItems: 4
maxItems: 4
description: |
The brake pattern are the strengths of the pattern
used to brake the haptics. Allowed values are,
0 - 0V
1 - Vmax/4
2 - Vmax/2
3 - Vmax
$ref: /schemas/types.yaml#/definitions/uint32-array
default: [0x3, 0x3, 0x2, 0x1]
required:
- compatible
- reg
- interrupts
- qcom,wave-play-rate-us
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/input/qcom,spmi-haptics.h>
spmi {
#address-cells = <1>;
#size-cells = <0>;
pmi8998_haptics: haptics@c000 {
compatible = "qcom,pmi8998-haptics";
reg = <0xc000>;
interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
<0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "short", "play";
qcom,wave-shape = <HAP_WAVE_SINE>;
qcom,play-mode = <HAP_PLAY_BUFFER>;
qcom,brake-pattern = <0x3 0x3 0x2 0x1>;
status = "disabled";
};
};

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,158 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/leds/leds-qcom-lpg.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Light Pulse Generator
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
description: >
The Qualcomm Light Pulse Generator consists of three different hardware blocks;
a ramp generator with lookup table, the light pulse generator and a three
channel current sink. These blocks are found in a wide range of Qualcomm PMICs.
properties:
compatible:
enum:
- qcom,pm8150b-lpg
- qcom,pm8150l-lpg
- qcom,pm8916-pwm
- qcom,pm8941-lpg
- qcom,pm8994-lpg
- qcom,pmi8994-lpg
- qcom,pmi8998-lpg
"#pwm-cells":
const: 2
"#address-cells":
const: 1
"#size-cells":
const: 0
qcom,power-source:
$ref: /schemas/types.yaml#/definitions/uint32
description:
power-source used to drive the output, as defined in the datasheet.
Should be specified if the TRILED block is present
qcom,dtest:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: >
A list of integer pairs, where each pair represent the dtest line the
particular channel should be connected to and the flags denoting how the
value should be outputed, as defined in the datasheet. The number of
pairs should be the same as the number of channels.
multi-led:
type: object
$ref: leds-class-multicolor.yaml#
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
"^led@[0-9a-f]$":
type: object
$ref: common.yaml#
patternProperties:
"^led@[0-9a-f]$":
type: object
$ref: common.yaml#
properties:
reg: true
required:
- reg
required:
- compatible
additionalProperties: false
examples:
- |
#include <dt-bindings/leds/common.h>
lpg {
compatible = "qcom,pmi8994-lpg";
#address-cells = <1>;
#size-cells = <0>;
qcom,power-source = <1>;
qcom,dtest = <0 0
0 0
0 0
4 1>;
led@1 {
reg = <1>;
label = "green:user1";
};
led@2 {
reg = <2>;
label = "green:user0";
default-state = "on";
};
led@3 {
reg = <3>;
label = "green:user2";
};
led@4 {
reg = <4>;
label = "green:user3";
};
};
- |
#include <dt-bindings/leds/common.h>
lpg {
compatible = "qcom,pmi8994-lpg";
#address-cells = <1>;
#size-cells = <0>;
qcom,power-source = <1>;
multi-led {
color = <LED_COLOR_ID_MULTI>;
label = "rgb:notification";
#address-cells = <1>;
#size-cells = <0>;
led@1 {
reg = <1>;
color = <LED_COLOR_ID_RED>;
};
led@2 {
reg = <2>;
color = <LED_COLOR_ID_GREEN>;
};
led@3 {
reg = <3>;
color = <LED_COLOR_ID_BLUE>;
};
};
};
- |
lpg {
compatible = "qcom,pm8916-pwm";
#pwm-cells = <2>;
};
...

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

@ -1,130 +1 @@
QCOM CPR (Core Power Reduction)
CPR (Core Power Reduction) is a technology to reduce core power on a CPU
or other device. Each OPP of a device corresponds to a "corner" that has
a range of valid voltages for a particular frequency. While the device is
running at a particular frequency, CPR monitors dynamic factors such as
temperature, etc. and suggests adjustments to the voltage to save power
and meet silicon characteristic requirements.
- compatible:
Usage: required
Value type: <string>
Definition: should be "qcom,qcs404-cpr", "qcom,cpr" for qcs404
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: base address and size of the rbcpr register region
- interrupts:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify the CPR interrupt
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: phandle to the reference clock
- clock-names:
Usage: required
Value type: <stringlist>
Definition: must be "ref"
- vdd-apc-supply:
Usage: required
Value type: <phandle>
Definition: phandle to the vdd-apc-supply regulator
- #power-domain-cells:
Usage: required
Value type: <u32>
Definition: should be 0
- operating-points-v2:
Usage: required
Value type: <phandle>
Definition: A phandle to the OPP table containing the
performance states supported by the CPR
power domain
- acc-syscon:
Usage: optional
Value type: <phandle>
Definition: phandle to syscon for writing ACC settings
- nvmem-cells:
Usage: required
Value type: <phandle>
Definition: phandle to nvmem cells containing the data
that makes up a fuse corner, for each fuse corner.
As well as the CPR fuse revision.
- nvmem-cell-names:
Usage: required
Value type: <stringlist>
Definition: should be "cpr_quotient_offset1", "cpr_quotient_offset2",
"cpr_quotient_offset3", "cpr_init_voltage1",
"cpr_init_voltage2", "cpr_init_voltage3", "cpr_quotient1",
"cpr_quotient2", "cpr_quotient3", "cpr_ring_osc1",
"cpr_ring_osc2", "cpr_ring_osc3", "cpr_fuse_revision"
for qcs404.
Example:
cpr_opp_table: cpr-opp-table {
compatible = "operating-points-v2-qcom-level";
cpr_opp1: opp1 {
opp-level = <1>;
qcom,opp-fuse-level = <1>;
};
cpr_opp2: opp2 {
opp-level = <2>;
qcom,opp-fuse-level = <2>;
};
cpr_opp3: opp3 {
opp-level = <3>;
qcom,opp-fuse-level = <3>;
};
};
power-controller@b018000 {
compatible = "qcom,qcs404-cpr", "qcom,cpr";
reg = <0x0b018000 0x1000>;
interrupts = <0 15 IRQ_TYPE_EDGE_RISING>;
clocks = <&xo_board>;
clock-names = "ref";
vdd-apc-supply = <&pms405_s3>;
#power-domain-cells = <0>;
operating-points-v2 = <&cpr_opp_table>;
acc-syscon = <&tcsr>;
nvmem-cells = <&cpr_efuse_quot_offset1>,
<&cpr_efuse_quot_offset2>,
<&cpr_efuse_quot_offset3>,
<&cpr_efuse_init_voltage1>,
<&cpr_efuse_init_voltage2>,
<&cpr_efuse_init_voltage3>,
<&cpr_efuse_quot1>,
<&cpr_efuse_quot2>,
<&cpr_efuse_quot3>,
<&cpr_efuse_ring1>,
<&cpr_efuse_ring2>,
<&cpr_efuse_ring3>,
<&cpr_efuse_revision>;
nvmem-cell-names = "cpr_quotient_offset1",
"cpr_quotient_offset2",
"cpr_quotient_offset3",
"cpr_init_voltage1",
"cpr_init_voltage2",
"cpr_init_voltage3",
"cpr_quotient1",
"cpr_quotient2",
"cpr_quotient3",
"cpr_ring_osc1",
"cpr_ring_osc2",
"cpr_ring_osc3",
"cpr_fuse_revision";
};
This file has been moved to ../../soc/qcom/qcom,cpr.yaml

View file

@ -0,0 +1,167 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/soc/qcom/qcom,cpr.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm Core Power Reduction (CPR)
description: |
CPR (Core Power Reduction) is a technology to reduce core power on a CPU
or other device. Each OPP of a device corresponds to a "corner" that has
a range of valid voltages for a particular frequency. While the device is
running at a particular frequency, CPR monitors dynamic factors such as
temperature, etc. and suggests adjustments to the voltage to save power
and meet silicon characteristic requirements.
maintainers:
- Niklas Cassel <nks@flawful.org>
properties:
compatible:
items:
- enum:
- qcom,qcs404-cpr
- const: qcom,cpr
reg:
description: Base address and size of the RBCPR register region
maxItems: 1
interrupts:
maxItems: 1
clock-names:
items:
- const: ref
clocks:
items:
- description: CPR reference clock
vdd-apc-supply:
description: Autonomous Phase Control (APC) power supply
'#power-domain-cells':
const: 0
acc-syscon:
description: phandle to syscon for writing ACC settings
nvmem-cells:
minItems: 9
maxItems: 32
description: Cells containing the fuse corners and revision data
nvmem-cell-names:
minItems: 9
maxItems: 32
operating-points-v2: true
required:
- compatible
- reg
- interrupts
- clock-names
- clocks
- vdd-apc-supply
- "#power-domain-cells"
- nvmem-cells
- nvmem-cell-names
- operating-points-v2
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@100 {
compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <0x100>;
operating-points-v2 = <&cpu_opp_table>;
power-domains = <&cpr>;
power-domain-names = "cpr";
};
};
cpu_opp_table: cpu-opp-table {
compatible = "operating-points-v2-kryo-cpu";
opp-shared;
opp-1094400000 {
opp-hz = /bits/ 64 <1094400000>;
required-opps = <&cpr_opp1>;
};
opp-1248000000 {
opp-hz = /bits/ 64 <1248000000>;
required-opps = <&cpr_opp2>;
};
opp-1401600000 {
opp-hz = /bits/ 64 <1401600000>;
required-opps = <&cpr_opp3>;
};
};
cpr_opp_table: cpr-opp-table {
compatible = "operating-points-v2-qcom-level";
cpr_opp1: opp1 {
opp-level = <1>;
qcom,opp-fuse-level = <1>;
};
cpr_opp2: opp2 {
opp-level = <2>;
qcom,opp-fuse-level = <2>;
};
cpr_opp3: opp3 {
opp-level = <3>;
qcom,opp-fuse-level = <3>;
};
};
power-controller@b018000 {
compatible = "qcom,qcs404-cpr", "qcom,cpr";
reg = <0x0b018000 0x1000>;
interrupts = <0 15 IRQ_TYPE_EDGE_RISING>;
clocks = <&xo_board>;
clock-names = "ref";
vdd-apc-supply = <&pms405_s3>;
#power-domain-cells = <0>;
operating-points-v2 = <&cpr_opp_table>;
acc-syscon = <&tcsr>;
nvmem-cells = <&cpr_efuse_quot_offset1>,
<&cpr_efuse_quot_offset2>,
<&cpr_efuse_quot_offset3>,
<&cpr_efuse_init_voltage1>,
<&cpr_efuse_init_voltage2>,
<&cpr_efuse_init_voltage3>,
<&cpr_efuse_quot1>,
<&cpr_efuse_quot2>,
<&cpr_efuse_quot3>,
<&cpr_efuse_ring1>,
<&cpr_efuse_ring2>,
<&cpr_efuse_ring3>,
<&cpr_efuse_revision>;
nvmem-cell-names = "cpr0_quotient_offset1",
"cpr0_quotient_offset2",
"cpr0_quotient_offset3",
"cpr0_init_voltage1",
"cpr0_init_voltage2",
"cpr0_init_voltage3",
"cpr0_quotient1",
"cpr0_quotient2",
"cpr0_quotient3",
"cpr0_ring_osc1",
"cpr0_ring_osc2",
"cpr0_ring_osc3",
"cpr0_fuse_revision";
};
...

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

@ -15967,9 +15967,15 @@ M: Niklas Cassel <nks@flawful.org>
L: linux-pm@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
F: Documentation/devicetree/bindings/soc/qcom/qcom,cpr.yaml
F: drivers/soc/qcom/cpr.c
QUALCOMM CORE POWER REDUCTION v3/v4/Hardened AVS DRIVER
M: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
S: Maintained
F: Documentation/devicetree/bindings/soc/qcom/qcom,cpr3.yaml
F: drivers/soc/qcom/cpr3.c
QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
M: Ilia Lin <ilia.lin@kernel.org>
L: linux-pm@vger.kernel.org

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 17
SUBLEVEL = 0
SUBLEVEL = 1
EXTRAVERSION =
NAME = Superb Owl

View file

@ -10,6 +10,7 @@
#include "pmi8994.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
@ -677,6 +678,54 @@
};
};
&pmi8994_lpg {
qcom,power-source = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pmi8994_mpp2_userled4>;
qcom,dtest = <0 0
0 0
0 0
4 1>;
status = "okay";
led@1 {
reg = <1>;
label = "green:user1";
linux,default-trigger = "heartbeat";
default-state = "on";
};
led@2 {
reg = <2>;
label = "green:user0";
default-state = "on";
};
led@3 {
reg = <3>;
label = "green:user2";
};
led@4 {
reg = <4>;
label = "green:user3";
};
};
&pmi8994_mpps {
pmi8994_mpp2_userled4: mpp2-userled4-state {
pins = "mpp2";
function = "sink";
output-low;
qcom,dtest = <4>;
};
};
&pmi8994_spmi_regulators {
vdd_s2-supply = <&vph_pwr>;

View file

@ -18,6 +18,15 @@
chassis-type = "handset";
qcom,board-id = <0x02000b 0x10>;
/* This part enables graphical output via bootloader-enabled display */
chosen {
bootargs = "earlycon=tty0 console=tty0 clk_ignore_unused";
#address-cells = <2>;
#size-cells = <2>;
ranges;
};
/*
* Until we hook up type-c detection, we
* have to stick with this. But it works.
@ -46,6 +55,8 @@
gpio-kb-extra-keys {
compatible = "gpio-keys";
label = "Keyboard extra keys";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&gpio_kb_pins_extra>;
@ -98,6 +109,39 @@
};
};
gpio_keyboard: gpio-keyboard {
compatible = "gpio-fastmatrix-keyboard";
label = "F(x)Tec Pro1 Hardware Keyboard";
row-gpios =
<&gpioext0 0 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 1 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 2 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 3 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 4 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 5 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 6 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 7 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
col-gpios =
<&gpioext0 8 GPIO_ACTIVE_LOW>,
<&gpioext0 9 GPIO_ACTIVE_LOW>,
<&gpioext0 10 GPIO_ACTIVE_LOW>,
<&gpioext0 11 GPIO_ACTIVE_LOW>,
<&gpioext0 12 GPIO_ACTIVE_LOW>,
<&gpioext0 13 GPIO_ACTIVE_LOW>,
<&gpioext0 14 GPIO_ACTIVE_LOW>,
<&gpioext0 15 GPIO_ACTIVE_LOW>;
keypad,num-rows = <8>;
keypad,num-columns = <8>;
pinctrl-names = "default";
pinctrl-0 = <&keyboard_pins_col>, <&keyboard_pins_row>;
autorescan-ms = <5>;
debounce-delay-ms = <1>;
col-scan-delay-us = <1500>;
};
gpio-keys {
compatible = "gpio-keys";
label = "Side buttons";
@ -177,6 +221,53 @@
};
};
disp_vcc_vreg: disp-vcc-regulator {
compatible = "regulator-fixed";
regulator-name = "disp_vcc";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
disp_vddio_vreg: disp-vddio-regulator {
compatible = "regulator-fixed";
regulator-name = "disp_vddio";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
regulator-allow-set-load;
};
disp_vci_vreg: disp-vci-regulator {
compatible = "regulator-fixed";
regulator-name = "disp_vci";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-boot-on;
regulator-always-on;
regulator-allow-set-load;
};
disp_elvdd_vreg: disp-elvdd-regulator {
compatible = "regulator-fixed";
regulator-name = "disp_elvdd";
regulator-min-microvolt = <4600000>;
regulator-max-microvolt = <4600000>;
regulator-boot-on;
regulator-always-on;
};
disp_elvss_vreg: disp-elvss-regulator {
compatible = "regulator-fixed";
regulator-name = "disp_elvss";
regulator-min-microvolt = <2400000>;
regulator-max-microvolt = <2400000>;
regulator-boot-on;
regulator-always-on;
};
ts_vio_vreg: ts-vio-vreg {
compatible = "regulator-fixed";
regulator-name = "ts_vio_reg";
@ -189,8 +280,62 @@
};
};
&adreno_gpu {
status = "ok";
zap-shader {
memory-region = <&zap_shader_region>;
firmware-name = "qcom/a540_zap.mbn";
};
};
&adreno_smmu {
status = "ok";
};
&apc_cprh {
status = "ok";
};
&blsp1_i2c6 {
status = "ok";
gpioext0: gpio-expander@58 {
compatible = "awinic,aw9523-pinctrl";
reg = <0x58>;
interrupt-parent = <&tlmm>;
interrupts = <50 IRQ_TYPE_EDGE_FALLING>;
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&gpioext0 0 0 16>;
interrupt-controller;
#interrupt-cells = <2>;
pinctrl-0 = <&gpio_expander_int_n>, <&gpio_expander_rst_n>;
pinctrl-names = "default";
reset-gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>;
keyboard_pins_col: keyboard-matrix-col-pins {
pins = "gpio8", "gpio9", "gpio10", "gpio11",
"gpio12", "gpio13", "gpio14", "gpio15";
function = "gpio";
output-low;
};
keyboard_pins_row: keyboard-matrix-row-pins {
pins = "gpio0", "gpio1", "gpio2", "gpio3",
"gpio4", "gpio5", "gpio6", "gpio7";
function = "gpio";
drive-open-drain;
input-enable;
};
};
};
&blsp2_i2c1 {
status = "ok";
qcom,noise-reject-scl = <3>;
qcom,noise-reject-sda = <3>;
touchscreen@14 {
compatible = "goodix,gt9286";
@ -205,6 +350,120 @@
};
};
&cpufreq_hw {
status = "ok";
};
&dsi0 {
#address-cells = <1>;
#size-cells = <0>;
status = "ok";
vdd-supply = <&vreg_l1a_0p875>;
vdda-supply = <&vreg_l2a_1p2>;
panel: panel@0 {
compatible = "boe,bf060y8m-aj0";
reg = <0>;
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
disp-te-gpios = <&tlmm 10 GPIO_ACTIVE_LOW>;
no-hpd;
vcc-supply = <&disp_vcc_vreg>;
vddio-supply = <&disp_vddio_vreg>;
vci-supply = <&disp_vci_vreg>;
elvdd-supply = <&disp_elvdd_vreg>;
elvss-supply = <&disp_elvss_vreg>;
pinctrl-names = "default";
pinctrl-0 = <&panel_reset_n &disp_en_default &mdp_vsync_n>;
port {
panel_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
&dsi0_phy {
status = "ok";
};
&dsi0_out {
remote-endpoint = <&panel_in>;
data-lanes = <0 1 2 3>;
};
&gcc {
status = "ok";
};
&gpucc {
status = "ok";
};
&gpio_keyboard {
linux,keymap = <
MATRIX_KEY(0, 0, KEY_F1) MATRIX_KEY(1, 0, KEY_H)
MATRIX_KEY(2, 0, KEY_B) MATRIX_KEY(3, 0, KEY_7)
MATRIX_KEY(4, 0, KEY_UP) MATRIX_KEY(5, 0, KEY_ENTER)
MATRIX_KEY(6, 0, KEY_Y) MATRIX_KEY(7, 0, KEY_COMMA)
MATRIX_KEY(0, 1, KEY_3) MATRIX_KEY(1, 1, KEY_S)
MATRIX_KEY(2, 1, KEY_Z) MATRIX_KEY(3, 1, KEY_M)
MATRIX_KEY(4, 1, KEY_I) MATRIX_KEY(5, 1, KEY_9)
MATRIX_KEY(6, 1, KEY_W) MATRIX_KEY(7, 1, KEY_J)
MATRIX_KEY(0, 2, KEY_LEFT) MATRIX_KEY(1, 2, KEY_G)
MATRIX_KEY(2, 2, KEY_V) MATRIX_KEY(3, 2, KEY_6)
MATRIX_KEY(4, 2, KEY_RIGHT) MATRIX_KEY(5, 2, KEY_DELETE)
MATRIX_KEY(6, 2, KEY_T) MATRIX_KEY(7, 2, KEY_DOT)
MATRIX_KEY(0, 3, KEY_SLASH) MATRIX_KEY(1, 3, KEY_A)
MATRIX_KEY(2, 3, KEY_RIGHTBRACE) MATRIX_KEY(3, 3, KEY_HOMEPAGE)
MATRIX_KEY(4, 3, KEY_P) MATRIX_KEY(5, 3, KEY_MINUS)
MATRIX_KEY(6, 3, KEY_Q) MATRIX_KEY(7, 3, KEY_L)
MATRIX_KEY(0, 4, KEY_BACKSPACE) MATRIX_KEY(1, 4, KEY_D)
MATRIX_KEY(2, 4, KEY_X) MATRIX_KEY(3, 4, KEY_K)
MATRIX_KEY(4, 4, KEY_SEMICOLON) MATRIX_KEY(5, 4, KEY_EQUAL)
MATRIX_KEY(6, 4, KEY_E) MATRIX_KEY(7, 4, KEY_APOSTROPHE)
MATRIX_KEY(0, 5, KEY_CAPSLOCK) MATRIX_KEY(1, 5, KEY_BACKSLASH)
MATRIX_KEY(2, 5, KEY_LEFTBRACE) MATRIX_KEY(3, 5, KEY_DOWN)
MATRIX_KEY(4, 5, KEY_O) MATRIX_KEY(5, 5, KEY_0)
MATRIX_KEY(6, 5, KEY_GRAVE) MATRIX_KEY(7, 5, KEY_K)
MATRIX_KEY(0, 6, KEY_SPACE) MATRIX_KEY(1, 6, KEY_F)
MATRIX_KEY(2, 6, KEY_C) MATRIX_KEY(3, 6, KEY_N)
MATRIX_KEY(4, 6, KEY_U) MATRIX_KEY(5, 6, KEY_8)
MATRIX_KEY(6, 6, KEY_R) MATRIX_KEY(7, 6, KEY_5)
MATRIX_KEY(0, 7, KEY_ESC) MATRIX_KEY(1, 7, KEY_1)
MATRIX_KEY(2, 7, KEY_RESERVED) MATRIX_KEY(3, 7, KEY_RESERVED)
MATRIX_KEY(4, 7, KEY_2) MATRIX_KEY(5, 7, KEY_4)
MATRIX_KEY(6, 7, KEY_TAB) MATRIX_KEY(7, 7, KEY_RESERVED)
>;
};
&mdss {
status = "ok";
};
&mdss_mdp {
status = "ok";
};
&remoteproc_adsp {
status = "okay";
firmware-name = "qcom/msm8998/fxtec/adsp.mbn";
};
&remoteproc_mss {
firmware-name = "qcom/msm8998/fxtec/mba.mbn", "qcom/msm8998/fxtec/modem.mbn";
};
&remoteproc_slpi {
status = "okay";
firmware-name = "qcom/msm8998/fxtec/slpi_v2.mbn";
};
&mmcc {
status = "ok";
};
@ -213,7 +472,35 @@
status = "ok";
};
&pmi8998_haptics {
status = "okay";
qcom,wave-play-rate-us = <5000>;
};
/* HACK! Push GPU voltage high until GPU CPR is hooked up */
&pm8005_s1 {
regulator-min-microvolt = <988000>;
regulator-max-microvolt = <1100000>;
};
&pmi8998_fg {
status = "okay";
qcom,max-voltage-uv = <4400000>;
qcom,min-voltage-uv = <3700000>;
qcom,battery-capacity-ua = <3150000>;
};
&pm8998_gpio {
unknown_pin_a: unk-active {
pins = "gpio5";
function = "normal";
input-enable;
bias-pull-up;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>;
};
vol_up_pin_a: vol-up-active {
pins = "gpio6";
function = "normal";
@ -267,6 +554,26 @@
bias-pull-up;
};
gpio_expander_int_n: gpio-exp-intn-def {
pins = "gpio50";
function = "gpio";
drive-strength = <2>;
input-enable;
};
gpio_expander_rst_n: gpio-exp-rst-def {
pins = "gpio51";
function = "gpio";
drive-strength = <8>;
};
disp_en_default: disp-en {
pins = "gpio62";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
ts_vio_default: ts-vio-def {
pins = "gpio81";
function = "gpio";
@ -295,6 +602,13 @@
bias-disable;
drive-strength = <8>;
};
panel_reset_n: panel-rst-n {
pins = "gpio94";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
};
&ufshc {

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,6 +9,7 @@
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include "msm8998.dtsi"
#include "pm8998.dtsi"
@ -32,6 +33,7 @@
height = <1920>;
stride = <(1080 * 4)>;
format = "a8r8g8b8";
status = "disabled";
};
};
@ -152,10 +154,18 @@
reg = <0x0 0x95715000 0x0 0x100000>;
};
&apc_cprh {
status = "ok";
};
&cpufreq_hw {
status = "ok";
};
&blsp1_i2c5 {
status = "okay";
touchscreen@20 {
rmi4_i2c: touchscreen@20 {
compatible = "syna,rmi4-i2c";
reg = <0x20>;
#address-cells = <1>;
@ -188,6 +198,29 @@
};
};
&blsp1_i2c5_sleep {
/delete-property/ bias-pull-up;
/* Configure a no-pull on TP I2C sleep to match downstream. */
bias-disable;
};
&blsp1_i2c6 {
status = "okay";
nfc@28 {
compatible = "nxp,nxp-nci-i2c";
reg = <0x28>;
interrupt-parent = <&tlmm>;
interrupts = <92 IRQ_TYPE_LEVEL_HIGH>;
enable-gpios = <&tlmm 116 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&nfc_int_active &nfc_enable_active>;
};
};
&blsp1_uart3 {
status = "okay";
@ -224,10 +257,35 @@
};
};
&blsp2_i2c3 {
status = "disabled";
audio-codec@36 {
compatible = "nxp,tfa9890";
reg = <0x36>;
/*
* vddd-supply = <&vreg_bob>;
* vreg_l20a_2p95? 2950000->2960000 mV @ 200->800000 mA?
*/
sound-name-prefix = "Mono Speaker";
#sound-dai-cells = <0>;
status = "disabled";
};
};
&blsp2_uart1 {
status = "okay";
};
&ipa {
status = "okay";
memory-region = <&ipa_fws_region>; // ipa_fw_mem? ipa_gsi_mem?
firmware-name = "qcom/msm8998/oneplus/ipa_fws.mbn";
};
&pm8005_lsid1 {
pm8005-regulators {
compatible = "qcom,pm8005-regulators";
@ -257,6 +315,49 @@
};
};
&pmi8998_fg {
status = "okay";
qcom,max-voltage-uv = <4370000>;
qcom,min-voltage-uv = <3700000>;
qcom,battery-capacity-ua = <3300000>;
};
&pmi8998_lpg {
status = "okay";
//qcom,power-source = <0>;
notification-led {
color = <LED_COLOR_ID_RGB>;
function = LED_FUNCTION_STATUS;
#address-cells = <1>;
#size-cells = <0>;
led@3 {
reg = <3>;
color = <LED_COLOR_ID_BLUE>;
};
led@4 {
reg = <4>;
color = <LED_COLOR_ID_GREEN>;
};
led@5 {
reg = <5>;
color = <LED_COLOR_ID_RED>;
};
};
};
&pmi8998_haptics {
status = "okay";
qcom,wave-play-rate-us = <4255>;
};
&qusb2phy {
status = "okay";
@ -269,30 +370,18 @@
pm8998-regulators {
compatible = "qcom,rpm-pm8998-regulators";
vdd_s1-supply = <&vph_pwr>;
vdd_s2-supply = <&vph_pwr>;
vdd_s1-supply = <&vph_pwr>; /* GPU? */
vdd_s3-supply = <&vph_pwr>;
vdd_s4-supply = <&vph_pwr>;
vdd_s5-supply = <&vph_pwr>;
vdd_s6-supply = <&vph_pwr>;
vdd_s7-supply = <&vph_pwr>;
vdd_s8-supply = <&vph_pwr>;
vdd_s9-supply = <&vph_pwr>;
vdd_s10-supply = <&vph_pwr>;
vdd_s11-supply = <&vph_pwr>;
vdd_s12-supply = <&vph_pwr>;
vdd_s13-supply = <&vph_pwr>;
vdd_l1_l27-supply = <&vreg_s7a_1p025>;
vdd_l2_l8_l17-supply = <&vreg_s3a_1p35>;
vdd_l3_l11-supply = <&vreg_s7a_1p025>;
vdd_l4_l5-supply = <&vreg_s7a_1p025>;
vdd_l1-supply = <&vreg_s7a_1p025>;
vdd_l2_l17-supply = <&vreg_s3a_1p35>;
vdd_l5-supply = <&vreg_s7a_1p025>;
vdd_l6-supply = <&vreg_s5a_2p04>;
vdd_l7_l12_l14_l15-supply = <&vreg_s5a_2p04>;
vdd_l9-supply = <&vreg_bob>;
vdd_l10_l23_l25-supply = <&vreg_bob>;
vdd_l13_l19_l21-supply = <&vreg_bob>;
vdd_l16_l28-supply = <&vreg_bob>;
vdd_l18_l22-supply = <&vreg_bob>;
vdd_l7_l12_l14-supply = <&vreg_s5a_2p04>;
vdd_l25-supply = <&vreg_bob>;
vdd_l28-supply = <&vreg_bob>;
vdd_l20_l24-supply = <&vreg_bob>;
vdd_l26-supply = <&vreg_s3a_1p35>;
vdd_lvs1_lvs2-supply = <&vreg_s4a_1p8>;
@ -314,111 +403,57 @@
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1028000>;
};
vreg_l1a_0p875: l1 {
vreg_l1a_0p875: l1 { /* UFS PHY */
regulator-min-microvolt = <880000>;
regulator-max-microvolt = <880000>;
};
vreg_l2a_1p2: l2 {
vreg_l2a_1p2: l2 { /* UFS PHY */
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
};
vreg_l3a_1p0: l3 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
};
vreg_l5a_0p8: l5 {
vreg_l5a_0p8: l5 { /* Wi-Fi */
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <800000>;
};
vreg_l6a_1p8: l6 {
vreg_l6a_1p8: l6 { /* Touchscreen */
regulator-min-microvolt = <1808000>;
regulator-max-microvolt = <1808000>;
};
vreg_l7a_1p8: l7 {
vreg_l7a_1p8: l7 { /* Wi-Fi + BT */
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
vreg_l8a_1p2: l8 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
};
vreg_l9a_1p8: l9 {
regulator-min-microvolt = <1808000>;
regulator-max-microvolt = <2960000>;
};
vreg_l10a_1p8: l10 {
regulator-min-microvolt = <1808000>;
regulator-max-microvolt = <2960000>;
};
vreg_l11a_1p0: l11 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
};
vreg_l12a_1p8: l12 {
vreg_l12a_1p8: l12 { /* QUSB2 PHY */
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
vreg_l13a_2p95: l13 {
regulator-min-microvolt = <1808000>;
regulator-max-microvolt = <2960000>;
};
vreg_l14a_1p88: l14 {
vreg_l14a_1p88: l14 { /* DSI display */
regulator-min-microvolt = <1880000>;
regulator-max-microvolt = <1880000>;
};
vreg_l15a_1p8: l15 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
vreg_l16a_2p7: l16 {
regulator-min-microvolt = <2704000>;
regulator-max-microvolt = <2704000>;
};
vreg_l17a_1p3: l17 {
vreg_l17a_1p3: l17 { /* Wi-Fi + BT */
regulator-min-microvolt = <1304000>;
regulator-max-microvolt = <1304000>;
};
vreg_l18a_2p7: l18 {
regulator-min-microvolt = <2704000>;
regulator-max-microvolt = <2704000>;
};
vreg_l19a_3p0: l19 {
regulator-min-microvolt = <3008000>;
regulator-max-microvolt = <3008000>;
};
vreg_l20a_2p95: l20 {
vreg_l20a_2p95: l20 { /* UFS HC */
regulator-min-microvolt = <2960000>;
regulator-max-microvolt = <2960000>;
regulator-allow-set-load;
};
vreg_l21a_2p95: l21 {
regulator-min-microvolt = <2960000>;
regulator-max-microvolt = <2960000>;
regulator-allow-set-load;
regulator-system-load = <800000>;
};
vreg_l22a_2p85: l22 {
regulator-min-microvolt = <2864000>;
regulator-max-microvolt = <2864000>;
};
vreg_l23a_3p3: l23 {
regulator-min-microvolt = <3312000>;
regulator-max-microvolt = <3312000>;
};
vreg_l24a_3p075: l24 {
vreg_l24a_3p075: l24 { /* QUSB2 PHY */
regulator-min-microvolt = <3088000>;
regulator-max-microvolt = <3088000>;
};
vreg_l25a_3p3: l25 {
vreg_l25a_3p3: l25 { /* Wi-Fi + BT */
regulator-min-microvolt = <3104000>;
regulator-max-microvolt = <3312000>;
};
vreg_l26a_1p2: l26 {
vreg_l26a_1p2: l26 { /* UFS PHY + HC */
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-allow-set-load;
};
vreg_l28_3p0: l28 {
vreg_l28_3p0: l28 { /* Touchscreen */
regulator-min-microvolt = <3008000>;
regulator-max-microvolt = <3008000>;
};
@ -438,9 +473,145 @@
};
};
&remoteproc_adsp {
status = "okay";
firmware-name = "qcom/msm8998/oneplus/adsp.mbn";
};
&remoteproc_mss {
status = "okay";
firmware-name = "qcom/msm8998/oneplus/mba.mbn", "qcom/msm8998/oneplus/modem.mbn";
};
&remoteproc_slpi {
status = "okay";
firmware-name = "qcom/msm8998/oneplus/slpi_v2.mbn";
};
&mmcc {
status = "okay";
};
&mmss_smmu {
status = "okay";
};
&mdss {
status = "okay";
};
&mdss_mdp {
status = "okay";
};
&dsi0 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
vdd-supply = <&vreg_l1a_0p875>;
vdda-supply = <&vreg_l2a_1p2>;
panel: panel@0 {
reg = <0>;
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
disp-te-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>;
vddio-supply = <&vreg_l14a_1p88>; // TODO: Could this be moved under dsi0?
pinctrl-names = "default";
pinctrl-0 = <&panel_reset_n &disp_en_default &mdp_vsync_n>;
port {
panel_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
&dsi0_phy {
status = "okay";
vdds-supply = <&vreg_l1a_0p875>;
};
&dsi0_out {
remote-endpoint = <&panel_in>;
data-lanes = <0 1 2 3>;
};
/* Adreno 540 GPU */
&gpucc {
status = "ok";
};
&gpu_mem {
compatible = "shared-dma-pool";
};
&adreno_gpu {
status = "ok";
zap-shader {
memory-region = <&zap_shader_region>; // gpu_mem?
firmware-name = "qcom/msm8998/oneplus/a540_zap.mbn";
};
/*
* We are lacking support for the GPU regulator. Hence, disable higher
* frequencies for now to prevent the platform from hanging on high
* graphics loads. Perhaps the pm8005_s1 voltage below could be
* adjusted but I'd rather not touch it.
*/
opp-table {
/delete-node/ opp-710000097;
/delete-node/ opp-670000048;
/delete-node/ opp-596000097;
/delete-node/ opp-515000097;
};
};
&adreno_smmu {
status = "ok";
};
/*
* HACK: Shoot GPU voltage high to stabilize Adreno 540 at high frequencies
* until the GPU CPR is brought up.
*/
&pm8005_s1 {
regulator-min-microvolt = <988000>; /* 0,524V -> 0,988V */
//regulator-max-microvolt = <1100000>;
};
&tlmm {
gpio-reserved-ranges = <0 4>, <81 4>;
disp_en_default: disp-en {
pins = "gpio62";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
panel_reset_n: panel-rst-n {
pins = "gpio94";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
mdp_vsync_n: mdp-vsync-n {
pins = "gpio11";
function = "mdp_vsync_a";
drive-strength = <2>;
bias-pull-down;
};
hall_sensor_default: hall-sensor-default {
pins = "gpio124";
function = "gpio";
@ -462,6 +633,20 @@
drive-strength = <8>;
bias-pull-up;
};
nfc_int_active: nfc_int_active {
pins = "gpio92";
function = "gpio";
drive-strength = <6>;
bias-pull-up;
};
nfc_enable_active: nfc_enable_active {
pins = "gpio12", "gpio116";
function = "gpio";
drive-strength = <6>;
bias-pull-up;
};
};
&ufshc {
@ -503,7 +688,7 @@
};
&wifi {
/* Leave disabled until MSS is functional */
status = "okay";
vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;

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 {
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 {
regulator-min-microvolt = <2850000>;
regulator-max-microvolt = <2850000>;

View file

@ -20,6 +20,10 @@
qcom,msm-id = <0x124 0x20000>, <0x124 0x20001>; /* 8998v2, v2.1 */
qcom,board-id = <8 0>;
chosen {
bootargs = "clk_ignore_unused root=/dev/mmcblk0p1";
};
clocks {
compatible = "simple-bus";
@ -84,6 +88,15 @@
pinctrl-0 = <&ts_vddio_en>;
};
/* The gpio-vibrator driver enforces requiring a regulator */
vib_vreg: vib-regulator {
compatible = "regulator-fixed";
regulator-name = "vib";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
vph_pwr: vph-pwr-regulator {
compatible = "regulator-fixed";
regulator-name = "vph_pwr";
@ -184,11 +197,28 @@
vibrator {
compatible = "gpio-vibrator";
enable-gpios = <&pmi8998_gpio 5 GPIO_ACTIVE_HIGH>;
vcc-supply = <&vib_vreg>;
pinctrl-names = "default";
pinctrl-0 = <&vib_default>;
};
};
&adreno_gpu {
status = "ok";
zap-shader {
memory-region = <&zap_shader_region>;
};
};
&adreno_smmu {
status = "ok";
};
&apc_cprh {
status = "ok";
};
&blsp1_i2c5 {
status = "okay";
clock-frequency = <355000>;
@ -241,10 +271,79 @@
};
};
&blsp2_i2c1 {
tof-sensor@29 {
compatible = "st,vl53l0x";
reg = <0x29>;
interrupt-parent = <&tlmm>;
interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
#io-channel-cells = <1>;
label = "back_camera_tof";
pinctrl-names = "default";
pinctrl-0 = <&tof_int_n &tof_rst_n>;
};
};
&blsp2_uart1 {
status = "okay";
};
&cpufreq_hw {
status = "ok";
};
&dsi0 {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
vdd-supply = <&vreg_l1a_0p875>;
vdda-supply = <&vreg_l2a_1p2>;
panel: panel@0 {
reg = <0>;
backlight = <&pmi8998_wled>;
disp-te-gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>;
reset-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
avdd-supply = <&lab>;
avee-supply = <&ibb>;
vddio-supply = <&vreg_l14a_1p85>;
tavdd-supply = <&vreg_l28_3p0>;
tvddio-supply = <&touch_vddio_vreg>;
pinctrl-names = "default";
pinctrl-0 = <&panel_reset_n &mdp_vsync_n>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
panel_in0: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
};
&dsi0_out {
remote-endpoint = <&panel_in0>;
data-lanes = <0 1 2 3>;
};
&dsi0_phy {
status = "okay";
vdds-supply = <&vreg_l1a_0p875>;
};
&gpucc {
status = "ok";
};
&ibb {
regulator-min-microamp = <800000>;
regulator-max-microamp = <800000>;
@ -270,6 +369,25 @@
regulator-soft-start;
};
&lpass_q6_smmu {
qcom,bypass-cbndx = /bits/ 8 <11>;
qcom,reset-nodisable-cbs = /bits/ 8 <12>;
status = "ok";
};
&mmcc {
status = "ok";
};
&mmss_smmu {
status = "ok";
};
&mdss {
status = "okay";
};
&mmcc {
status = "ok";
};
@ -286,7 +404,12 @@
/* VDD_GFX supply */
pm8005_s1: s1 {
regulator-min-microvolt = <524000>;
/*
* HACK: Set enough voltage for max GPU frequency
* and set the regulator always on until the
* GPU Core Power Reduction gets available
*/
regulator-min-microvolt = <988000>;
regulator-max-microvolt = <1088000>;
regulator-enable-ramp-delay = <500>;
regulator-always-on;
@ -324,6 +447,13 @@
function = "func2";
power-source = <0>;
};
nfc_clk_req_pin: nfc-clk-req-active {
pins = "gpio21";
function = PMIC_GPIO_FUNC_NORMAL;
input-enable;
power-source = <1>;
};
};
&pmi8998_gpio {
@ -358,6 +488,37 @@
};
};
&pmi8998_wled {
status = "okay";
default-brightness = <800>;
qcom,switching-freq = <800>;
qcom,ovp-millivolt = <29600>;
qcom,current-boost-limit = <970>;
qcom,current-limit-microamp = <25000>;
qcom,num-strings = <2>;
qcom,enabled-strings = <0 1>;
};
&q6asmdai {
dai@0 {
reg = <0>;
};
dai@1 {
reg = <1>;
};
dai@2 {
reg = <2>;
};
dai@3 {
reg = <3>;
// direction = <2>;
// is-compress-dai;
};
};
&qusb2phy {
status = "okay";
@ -365,6 +526,19 @@
vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
};
&remoteproc_adsp {
firmware-name = "adsp.mdt";
status = "okay";
};
&remoteproc_mss {
status = "disabled";
};
&remoteproc_slpi {
firmware-name = "slpi.mdt";
};
&rpm_requests {
pm8998-regulators {
compatible = "qcom,rpm-pm8998-regulators";
@ -553,6 +727,371 @@
pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
};
/* EAR-EN is NXP NX5L2750C */
/* Downstream example
&snd_9335 {
qcom,msm-mbhc-hphl-swh = <1>;
/delete-property/ qcom,hph-en1-gpio;
/delete-property/ qcom,hph-en0-gpio;
/delete-property/ qcom,us-euro-gpios;
qcom,ear-en-gpios = <&pm8005_gpios 1 0>;
qcom,audio-routing =
"AIF4 VI", "MCLK",
"RX_BIAS", "MCLK",
"MADINPUT", "MCLK",
"AMIC2", "MIC BIAS2",
"MIC BIAS2", "Headset Mic",
"MIC BIAS2", "ANCRight Headset Mic",
"AMIC3", "MIC BIAS3",
"MIC BIAS3", "ANCLeft Headset Mic",
"DMIC0", "MIC BIAS1",
"MIC BIAS1", "Digital Mic0",
"DMIC3", "MIC BIAS4",
"MIC BIAS4", "Digital Mic3",
"SpkrLeft IN", "SPK1 OUT",
"SpkrRight IN", "SPK2 OUT";
};
*/
&slimbam {
status = "okay";
};
&slim {
status = "okay";
};
&slim_ngd {
tasha_ifd: tas-ifd {
compatible = "slim217,1a0";
reg = <0 0>;
};
wcd9335: codec@1{
compatible = "slim217,1a0";
reg = <1 0>;
clock-names = "mclk", "slimbus";
clocks = <&div1_mclk>,
<&rpmcc RPM_SMD_LN_BB_CLK1>;
#clock-cells = <0>;
interrupt-parent = <&tlmm>;
interrupts = <54 IRQ_TYPE_LEVEL_HIGH>,
<53 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "intr1", "intr2";
interrupt-controller;
#interrupt-cells = <1>;
reset-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>;
slim-ifc-dev = <&tasha_ifd>;
vdd-buck-supply = <&vreg_s4a_1p8>;
vdd-buck-sido-supply = <&vreg_s4a_1p8>;
vdd-tx-supply = <&vreg_s4a_1p8>;
vdd-rx-supply = <&vreg_s4a_1p8>;
vdd-io-supply = <&vreg_s4a_1p8>;
qcom,mbhc-vthreshold = <1700>;
/* On SoMC Yoshino, HPHL is normally open, GND normally closed */
qcom,hphl-jack-type-normally-open;
//qcom,gnd-jack-type-normally-open;
#address-cells = <1>;
#size-cells = <1>;
#sound-dai-cells = <1>;
swm: swm@c85 {
compatible = "qcom,soundwire-v1.3.0";
reg = <0xc85 0x40>;
interrupts-extended = <&wcd9335 13>;
qcom,dout-ports = <6>;
qcom,din-ports = <2>;
qcom,ports-sinterval-low =/bits/ 8 <0x07 0x1F 0x3F 0x7 0x1F 0x3F 0x0F 0x0F>;
qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x0C 0x6 0x12 0x0D 0x07 0x0A >;
qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x1F 0x00 0x00 0x1F 0x00 0x00>;
/*downstream is <0xFF 0x00 0x1F 0xFF 0x00 0x1F 0x00 0x00>;*/
qcom,ports-block-pack-mode = /bits/ 8 <0xFF 0xFF 0x01 0xFF 0xFF 0x01 0xFF 0xFF>;
clocks = <&xo>;
clock-names = "iface";
#address-cells = <2>;
#size-cells = <0>;
#sound-dai-cells = <1>;
left_spkr: wsa8810-left {
compatible = "sdw10217201000";
reg = <0 1>;
powerdown-gpios = <&tlmm 65 GPIO_ACTIVE_HIGH>;
pinctrl-0 = <&wsa_leftspk_pwr_n>;
pinctrl-names = "default";
#thermal-sensor-cells = <0>;
sound-name-prefix = "SpkrRight";
#sound-dai-cells = <0>;
};
right_spkr: wsa8810-right {
compatible = "sdw10217201000";
powerdown-gpios = <&tlmm 66 GPIO_ACTIVE_HIGH>;
reg = <0 2>;
pinctrl-0 = <&wsa_rightspk_pwr_n>;
pinctrl-names = "default";
#thermal-sensor-cells = <0>;
sound-name-prefix = "SpkrLeft";
#sound-dai-cells = <0>;
};
};
};
};
/* NOTES */
/*
# This is Dragonboard 820C
EnableSequence [
cset "name='SLIM RX0 MUX' ZERO"
cset "name='SLIM RX1 MUX' ZERO"
cset "name='SLIM RX2 MUX' ZERO"
cset "name='SLIM RX3 MUX' ZERO"
cset "name='SLIM RX4 MUX' ZERO"
cset "name='SLIM RX5 MUX' AIF4_PB"
cset "name='SLIM RX6 MUX' AIF4_PB"
cset "name='SLIM RX7 MUX' ZERO"
cset "name='RX INT1_2 MUX' RX5"
cset "name='RX INT2_2 MUX' RX6"
## gain to 0dB
cset "name='RX5 Digital Volume' 68"
## gain to 0dB
cset "name='RX6 Digital Volume' 68"
cset "name='SLIMBUS_6_RX Audio Mixer MultiMedia2' 1"
cset "name='RX INT1 DEM MUX' CLSH_DSM_OUT"
cset "name='RX INT2 DEM MUX' CLSH_DSM_OUT"
]
######### WORKS!!!!!! SHE SPEEEEEAKS!!!!!!! #########
tinymix set "SLIM RX2 MUX" ZERO
tinymix set "SLIM RX3 MUX" ZERO
tinymix set "SLIM RX4 MUX" ZERO
tinymix set "SLIM RX5 MUX" ZERO
tinymix set "SLIM RX6 MUX" ZERO
tinymix set "SLIM RX7 MUX" ZERO
tinymix set "SLIM RX0 MUX" AIF1_PB
tinymix set "SLIM RX1 MUX" AIF1_PB
tinymix set "RX INT1_2 MUX" RX0
tinymix set "RX INT2_2 MUX" RX1
tinymix set "RX INT1_1 MIX1 INP0" RX0
tinymix set "RX INT2_1 MIX1 INP0" RX1
tinymix set "SLIMBUS_0_RX Audio Mixer MultiMedia1" 1
tinymix set "RX INT1 DEM MUX" CLSH_DSM_OUT
tinymix set "RX INT2 DEM MUX" CLSH_DSM_OUT
tinymix set "SLIM TX0 MUX" DEC0
tinymix set "AIF1_CAP Mixer SLIM TX0" 1
tinymix set "RX INT2_1 MIX1 INP0" RX1
tinymix set "RX INT1_1 MIX1 INP0" RX0
tinymix set "RX INT1_1 MIX1 INP0" RX2
tinymix set "RX INT1_1 MIX1 INP0" RX0
tinymix set "RX INT1_1 MIX1 INP0" RX2
tinymix set "RX INT2_1 MIX1 INP0" RX2
tinymix set "RX INT2_1 MIX1 INP0" RX1
tinymix set "RX INT1_1 MIX1 INP0" RX0
tinymix set "RX INT0_1 MIX1 INP0" RX0
tinymix set "RX INT0_1 MIX1 INP0" RX1
tinymix set "RX INT0_1 MIX1 INP0" RX2
tinymix set "RX INT0_1 MIX1 INP0" RX0
tinymix set "RX INT3_1 MIX1 INP0" RX0
tinymix set "RX INT4_1 MIX1 INP0" RX0
tinymix set "RX INT5_1 MIX1 INP0" RX0
tinymix set "RX INT6_1 MIX1 INP0" RX1
tinymix set "RX INT7_1 MIX1 INP0" RX1
tinymix set "RX INT7_1 MIX1 INP0" RX1
tinymix set "RX INT8_1 MIX1 INP0" RX1
tinymix set "RX INT0_1 MIX1 INP1" RX0
tinymix set "RX INT0_1 MIX1 INP1" RX2
tinymix set "RX INT0_1 MIX1 INP1" RX0
tinymix set "RX INT1_1 MIX1 INP1" RX0
tinymix set "RX INT2_1 MIX1 INP1" RX0
tinymix set "RX INT3_1 MIX1 INP1" RX0
tinymix set "RX INT4_1 MIX1 INP1" RX0
tinymix set "RX INT5_1 MIX1 INP1" RX0
tinymix set "RX INT6_1 MIX1 INP1" RX0
tinymix set "RX INT7_1 MIX1 INP1" RX0
tinymix set "RX INT8_1 MIX1 INP1" RX0
tinymix set "RX INT0_1 MIX1 INP2" RX1
tinymix set "RX INT1_1 MIX1 INP2" RX1
tinymix set "RX INT2_1 MIX1 INP2" RX1
tinymix set "RX INT3_1 MIX1 INP2" RX1
tinymix set "RX INT4_1 MIX1 INP2" RX1
tinymix set "RX INT5_1 MIX1 INP2" RX1
tinymix set "RX INT6_1 MIX1 INP2" RX1
tinymix set "RX INT7_1 MIX1 INP2" RX1
tinymix set "RX INT8_1 MIX1 INP2" RX1
tinymix set "RX INT8_1 MIX1 INP2" RX0
tinymix set "RX INT7_1 MIX1 INP2" RX0
tinymix set "RX INT6_1 MIX1 INP2" RX0
tinymix set "RX0 Digital Volume" 80
tinymix set "RX1 Digital Volume" 80
tinymix set "RX2 Digital Volume" 80
*/
&sound {
compatible = "qcom,msm8998-sndcard";
model = "Sony-Xperia-Yoshino";
/* Audio routing including WSA amp speakers */
/* audio-routing = "RX_BIAS", "MCLK",
"AMIC2", "MIC BIAS2",
"AMIC3", "MIC BIAS3",
"DMIC0", "MIC BIAS1",
"DMIC4", "MIC BIAS4",
"SpkrLeft IN", "SPK1 OUT",
"SpkrRight IN", "SPK2 OUT",
"MM_DL1", "MultiMedia1 Playback",
"MM_DL2", "MultiMedia2 Playback",
"MultiMedia3 Capture", "MM_UL3";
*/
/* Basic routing, 3.5mm jack only */
audio-routing = "RX_BIAS", "MCLK",
"AMIC2", "MIC BIAS2",
"AMIC3", "MIC BIAS3",
"DMIC0", "MIC BIAS1",
"DMIC4", "MIC BIAS4",
"MM_DL1", "MultiMedia1 Playback",
"MM_DL2", "MultiMedia2 Playback",
"MultiMedia3 Capture", "MM_UL3";
/*
<path name="voicemmode1-call headphones">
<ctl name="SLIM_0_RX_Voice Mixer VoiceMMode1" value="1" />
<ctl name="VoiceMMode1_Tx Mixer SLIM_0_TX_MMode1" value="1" />
</path>
<path name="sidetone-headphones">
<path name="sidetone-iir" />
<!-- 45 % of 124 (range 0 - 124) Register: 0x340 -->
<ctl name="IIR0 INP0 Volume" value="44" />
<ctl name="RX INT1 MIX2 INP" value="SRC0" />
<ctl name="RX INT2 MIX2 INP" value="SRC0" />
</path>
<path name="speaker-and-headphones">
<path name="speaker" />
<ctl name="RX INT1_1 MIX1 INP0" value="RX1" />
<ctl name="RX INT2_1 MIX1 INP0" value="RX1" />
<ctl name="RX INT1 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="RX INT2 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="RX1 Digital Volume" value="55" />
<ctl name="RX2 Digital Volume" value="55" />
<path name="headphones-hpf" />
<ctl name="Set Custom Stereo" value="Mix" />
</path>
<path name="headphones">
<ctl name="SLIM RX0 MUX" value="AIF_MIX1_PB" />
<ctl name="SLIM RX1 MUX" value="AIF_MIX1_PB" />
<ctl name="SLIM_0_RX Channels" value="Two" />
<ctl name="RX INT1_1 MIX1 INP0" value="RX0" />
<ctl name="RX INT2_1 MIX1 INP0" value="RX1" />
<ctl name="RX INT1 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="RX INT2 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="RX1 Digital Volume" value="80" />
<ctl name="RX2 Digital Volume" value="80" />
</path>
<path name="headphones-hpf">
<ctl name="RX INT1_1 HPF cut off" value="CF_NEG_3DB_150HZ" />
<ctl name="RX INT2_1 HPF cut off" value="CF_NEG_3DB_150HZ" />
</path>
<path name="anc-off-headphone">
<ctl name="SLIM RX0 MUX" value="AIF_MIX1_PB" />
<ctl name="SLIM RX1 MUX" value="AIF_MIX1_PB" />
<ctl name="SLIM_0_RX Channels" value="Two" />
<ctl name="RX INT1_1 MIX1 INP0" value="RX0" />
<ctl name="RX INT2_1 MIX1 INP0" value="RX1" />
<ctl name="RX INT1 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="RX INT2 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="COMP1 Switch" value="0" />
<ctl name="COMP2 Switch" value="0" />
<ctl name="HPHL Volume" value="20" />
<ctl name="HPHR Volume" value="20" />
<ctl name="RX1 Digital Volume" value="77" />
<ctl name="RX2 Digital Volume" value="77" />
</path>
<path name="audio-record">
<ctl name="MultiMedia1 Mixer SLIM_0_TX" value="1" />
</path>
<path name="deep-buffer-playback">
<ctl name="SLIMBUS_0_RX Audio Mixer MultiMedia1" value="1" />
</path>
*/
mm1-dai-link {
/* Deep Buffer playback for SLIM{0,7}, BT, USBAUDIO, AFE, DP, HDMI */
link-name = "MultiMedia1";
cpu {
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
};
};
mm2-dai-link {
/* Multichannel playback for HDMI and DP */
link-name = "MultiMedia2";
cpu {
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
};
};
mm3-dai-link {
/* Ultra Low Latency playback for SLIM0, HDMI, and DP */
link-name = "MultiMedia3";
cpu {
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
};
};
slim-dai-link {
link-name = "SLIM Playback";
cpu {
sound-dai = <&q6afedai SLIMBUS_0_RX>;
};
platform {
sound-dai = <&q6routing>;
};
codec {
/* Support only sound through 3.5mm for now: soundwire is currently unavailable */
//sound-dai = <&left_spkr>, <&right_spkr>, <&swm 0>, <&wcd9335 0>;
sound-dai = <&wcd9335 0>;
};
};
slimcap-dai-link {
link-name = "SLIM Capture";
cpu {
sound-dai = <&q6afedai SLIMBUS_0_TX>;
};
platform {
sound-dai = <&q6routing>;
};
codec {
sound-dai = <&wcd9335 1>;
};
};
};
&tlmm {
gpio-reserved-ranges = <0 4>, <81 4>;
@ -606,6 +1145,14 @@
drive-strength = <2>;
};
tof_int_n: tof-int-n {
pins = "gpio22";
function = "gpio";
bias-pull-up;
drive-strength = <2>;
input-enable;
};
cam1_vdig_default: cam1-vdig-default {
pins = "gpio25";
function = "gpio";
@ -613,6 +1160,74 @@
drive-strength = <2>;
};
tof_rst_n: tof-rst-n {
pins = "gpio27";
function = "gpio";
bias-disable;
drive-strength = <2>;
output-low;
};
cam1_rst_default: cam1-rst-n {
pins = "gpio28";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
cam0_rst_default: cam0-rst-n {
pins = "gpio30";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
wcd_int_n: wcd-int-n {
pins = "gpio54";
function = "gpio";
bias-pull-down;
drive-strength = <2>;
input-enable;
};
cdc_reset_n: cdc-reset-n {
pins = "gpio64";
function = "gpio";
bias-pull-down;
drive-strength = <16>;
output-high;
};
wsa_leftspk_pwr_n: wsa-leftspk-pwr-n {
pins = "gpio65";
function = "gpio";
bias-disable;
drive-strength = <2>;
output-low;
};
wsa_rightspk_pwr_n: wsa-rightspk-pwr-n {
pins = "gpio66";
function = "gpio";
bias-disable;
drive-strength = <2>;
output-low;
};
ts_reset_n: ts-reset-n {
pins = "gpio89";
function = "gpio";
bias-pull-up;
drive-strength = <8>;
};
panel_reset_n: panel-rst-n {
pins = "gpio94";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
hall_sensor0_default: acc-cover-open {
pins = "gpio124";
function = "gpio";

File diff suppressed because it is too large Load diff

View file

@ -125,6 +125,14 @@
#address-cells = <1>;
#size-cells = <0>;
pm8916_pwm: pwm {
compatible = "qcom,pm8916-pwm";
#pwm-cells = <2>;
status = "disabled";
};
pm8916_vib: vibrator@c000 {
compatible = "qcom,pm8916-vib";
reg = <0xc000>;

View file

@ -135,6 +135,16 @@
#address-cells = <1>;
#size-cells = <0>;
pm8994_lpg: lpg {
compatible = "qcom,pm8994-lpg";
#address-cells = <1>;
#size-cells = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pm8994_spmi_regulators: regulators {
compatible = "qcom,pm8994-regulators";
};

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

@ -19,6 +19,18 @@
interrupt-controller;
#interrupt-cells = <2>;
};
pmi8994_mpps: mpps@a000 {
compatible = "qcom,pmi8994-mpp";
reg = <0xa000>;
gpio-controller;
gpio-ranges = <&pmi8994_mpps 0 0 4>;
#gpio-cells = <2>;
interrupts = <0 0xa0 0 IRQ_TYPE_NONE>,
<0 0xa1 0 IRQ_TYPE_NONE>,
<0 0xa2 0 IRQ_TYPE_NONE>,
<0 0xa3 0 IRQ_TYPE_NONE>;
};
};
pmic@3 {
@ -27,6 +39,16 @@
#address-cells = <1>;
#size-cells = <0>;
pmi8994_lpg: lpg {
compatible = "qcom,pmi8994-lpg";
#address-cells = <1>;
#size-cells = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pmi8994_spmi_regulators: regulators {
compatible = "qcom,pmi8994-regulators";
#address-cells = <1>;

View file

@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include <dt-bindings/input/qcom,spmi-haptics.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
@ -18,6 +19,17 @@
interrupt-controller;
#interrupt-cells = <2>;
};
pmi8998_fg: fuel_guage {
compatible = "qcom,pmi8998-fg";
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
//FG //Charger
reg = <0x4000 0x1000>;
interrupts = <0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "usb-plugin";
};
};
pmi8998_lsid1: pmic@3 {
@ -53,5 +65,29 @@
status = "disabled";
};
pmi8998_lpg: lpg {
compatible = "qcom,pmi8998-lpg";
#address-cells = <1>;
#size-cells = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pmi8998_haptics: haptics@c000 {
compatible = "qcom,pmi8998-haptics";
reg = <0xc000>;
interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
<0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "short", "play";
qcom,wave-shape = <HAP_WAVE_SINE>;
qcom,play-mode = <HAP_PLAY_BUFFER>;
qcom,brake-pattern = <0x3 0x3 0x2 0x1>;
status = "disabled";
};
};
};

View file

@ -1173,19 +1173,19 @@
<&cpr_efuse_ring2>,
<&cpr_efuse_ring3>,
<&cpr_efuse_revision>;
nvmem-cell-names = "cpr_quotient_offset1",
"cpr_quotient_offset2",
"cpr_quotient_offset3",
"cpr_init_voltage1",
"cpr_init_voltage2",
"cpr_init_voltage3",
"cpr_quotient1",
"cpr_quotient2",
"cpr_quotient3",
"cpr_ring_osc1",
"cpr_ring_osc2",
"cpr_ring_osc3",
"cpr_fuse_revision";
nvmem-cell-names = "cpr0_quotient_offset1",
"cpr0_quotient_offset2",
"cpr0_quotient_offset3",
"cpr0_init_voltage1",
"cpr0_init_voltage2",
"cpr0_init_voltage3",
"cpr0_quotient1",
"cpr0_quotient2",
"cpr0_quotient3",
"cpr0_ring_osc1",
"cpr0_ring_osc2",
"cpr0_ring_osc3",
"cpr0_fuse_revision";
};
timer@b120000 {

View file

@ -595,6 +595,30 @@
};
};
&pmi8998_lpg {
status = "okay";
qcom,power-source = <1>;
led@3 {
reg = <3>;
label = "green:user3";
linux,default-trigger = "heartbeat";
default-state = "on";
};
led@4 {
reg = <4>;
label = "green:user2";
};
led@5 {
reg = <5>;
label = "green:user1";
};
};
/* QUAT I2S Uses 4 I2S SD Lines for audio on LT9611 HDMI Bridge */
&q6afedai {
qi2s@22 {

View file

@ -450,6 +450,13 @@
};
};
&pmi8998_fg {
status = "okay";
qcom,max-voltage-uv = <4400000>;
qcom,min-voltage-uv = <3700000>;
};
&qupv3_id_1 {
status = "okay";
};
@ -619,7 +626,7 @@
pins = "gpio6", "gpio25", "gpio26";
function = "gpio";
drive-strength = <8>;
bias-disable = <0>;
bias-disable;
};
};

View file

@ -15,6 +15,10 @@
qcom,board-id = <8 0 17819 22>;
};
&pmi8998_fg {
qcom,battery-capacity-ua = <3300000>;
};
&display_panel {
status = "okay";

View file

@ -21,6 +21,10 @@
compatible = "samsung,s6e3fc2x01";
};
&pmi8998_fg {
qcom,battery-capacity-ua = <3700000>;
};
&rmi4_f12 {
touchscreen-y-mm = <148>;
};

View file

@ -3,14 +3,13 @@
#ifndef __ASM_CSKY_UACCESS_H
#define __ASM_CSKY_UACCESS_H
#define user_addr_max() \
(uaccess_kernel() ? KERNEL_DS.seg : get_fs().seg)
#define user_addr_max() (current_thread_info()->addr_limit.seg)
static inline int __access_ok(unsigned long addr, unsigned long size)
{
unsigned long limit = current_thread_info()->addr_limit.seg;
unsigned long limit = user_addr_max();
return ((addr < limit) && ((addr + size) < limit));
return (size <= limit) && (addr <= (limit - size));
}
#define __access_ok __access_ok

View file

@ -25,17 +25,17 @@
* Returns true (nonzero) if the memory block *may* be valid, false (zero)
* if it is definitely invalid.
*
* User address space in Hexagon, like x86, goes to 0xbfffffff, so the
* simple MSB-based tests used by MIPS won't work. Some further
* optimization is probably possible here, but for now, keep it
* reasonably simple and not *too* slow. After all, we've got the
* MMU for backup.
*/
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
#define __access_ok(addr, size) \
((get_fs().seg == KERNEL_DS.seg) || \
(((unsigned long)addr < get_fs().seg) && \
(unsigned long)size < (get_fs().seg - (unsigned long)addr)))
static inline int __access_ok(unsigned long addr, unsigned long size)
{
unsigned long limit = TASK_SIZE;
return (size <= limit) && (addr <= (limit - size));
}
#define __access_ok __access_ok
/*
* When a kernel-mode page fault is taken, the faulting instruction

View file

@ -12,14 +12,17 @@
#include <asm/extable.h>
/* We let the MMU do all checking */
static inline int access_ok(const void __user *addr,
static inline int access_ok(const void __user *ptr,
unsigned long size)
{
/*
* XXX: for !CONFIG_CPU_HAS_ADDRESS_SPACES this really needs to check
* for TASK_SIZE!
*/
return 1;
unsigned long limit = TASK_SIZE;
unsigned long addr = (unsigned long)ptr;
if (IS_ENABLED(CONFIG_CPU_HAS_ADDRESS_SPACES) ||
!IS_ENABLED(CONFIG_MMU))
return 1;
return (size <= limit) && (addr <= (limit - size));
}
/*

View file

@ -39,24 +39,13 @@
# define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
static inline int access_ok(const void __user *addr, unsigned long size)
static inline int __access_ok(unsigned long addr, unsigned long size)
{
if (!size)
goto ok;
unsigned long limit = user_addr_max();
if ((get_fs().seg < ((unsigned long)addr)) ||
(get_fs().seg < ((unsigned long)addr + size - 1))) {
pr_devel("ACCESS fail at 0x%08x (size 0x%x), seg 0x%08x\n",
(__force u32)addr, (u32)size,
(u32)get_fs().seg);
return 0;
}
ok:
pr_devel("ACCESS OK at 0x%08x (size 0x%x), seg 0x%08x\n",
(__force u32)addr, (u32)size,
(u32)get_fs().seg);
return 1;
return (size <= limit) && (addr <= (limit - size));
}
#define access_ok(addr, size) __access_ok((unsigned long)addr, size)
# define __FIXUP_SECTION ".section .fixup,\"ax\"\n"
# define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"

View file

@ -70,9 +70,7 @@ static inline void set_fs(mm_segment_t fs)
* versions are void (ie, don't return a value as such).
*/
#define get_user __get_user \
#define __get_user(x, ptr) \
#define get_user(x, ptr) \
({ \
long __gu_err = 0; \
__get_user_check((x), (ptr), __gu_err); \
@ -85,6 +83,14 @@ static inline void set_fs(mm_segment_t fs)
(void)0; \
})
#define __get_user(x, ptr) \
({ \
long __gu_err = 0; \
const __typeof__(*(ptr)) __user *__p = (ptr); \
__get_user_err((x), __p, (__gu_err)); \
__gu_err; \
})
#define __get_user_check(x, ptr, err) \
({ \
const __typeof__(*(ptr)) __user *__p = (ptr); \
@ -165,12 +171,18 @@ do { \
: "r"(addr), "i"(-EFAULT) \
: "cc")
#define put_user __put_user \
#define put_user(x, ptr) \
({ \
long __pu_err = 0; \
__put_user_check((x), (ptr), __pu_err); \
__pu_err; \
})
#define __put_user(x, ptr) \
({ \
long __pu_err = 0; \
__put_user_err((x), (ptr), __pu_err); \
__typeof__(*(ptr)) __user *__p = (ptr); \
__put_user_err((x), __p, __pu_err); \
__pu_err; \
})

View file

@ -1328,6 +1328,17 @@ static int __init disable_acpi_pci(const struct dmi_system_id *d)
return 0;
}
static int __init disable_acpi_xsdt(const struct dmi_system_id *d)
{
if (!acpi_force) {
pr_notice("%s detected: force use of acpi=rsdt\n", d->ident);
acpi_gbl_do_not_use_xsdt = TRUE;
} else {
pr_notice("Warning: DMI blacklist says broken, but acpi XSDT forced\n");
}
return 0;
}
static int __init dmi_disable_acpi(const struct dmi_system_id *d)
{
if (!acpi_force) {
@ -1451,6 +1462,19 @@ static const struct dmi_system_id acpi_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
},
},
/*
* Boxes that need ACPI XSDT use disabled due to corrupted tables
*/
{
.callback = disable_acpi_xsdt,
.ident = "Advantech DAC-BJ01",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
DMI_MATCH(DMI_PRODUCT_NAME, "Bearlake CRB Board"),
DMI_MATCH(DMI_BIOS_VERSION, "V1.12"),
DMI_MATCH(DMI_BIOS_DATE, "02/01/2011"),
},
},
{}
};

View file

@ -59,6 +59,10 @@ MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
static const struct acpi_device_id battery_device_ids[] = {
{"PNP0C0A", 0},
/* Microsoft Surface Go 3 */
{"MSHW0146", 0},
{"", 0},
};
@ -1148,6 +1152,14 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"),
},
},
{
/* Microsoft Surface Go 3 */
.callback = battery_notification_delay_quirk,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"),
},
},
{},
};

View file

@ -415,6 +415,81 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "GA503"),
},
},
/*
* Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a
* working native and video interface. However the default detection
* mechanism first registers the video interface before unregistering
* it again and switching to the native interface during boot. This
* results in a dangling SBIOS request for backlight change for some
* reason, causing the backlight to switch to ~2% once per boot on the
* first power cord connect or disconnect event. Setting the native
* interface explicitly circumvents this buggy behaviour, by avoiding
* the unregistering process.
*/
{
.callback = video_detect_force_native,
.ident = "Clevo NL5xRU",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
},
},
{
.callback = video_detect_force_native,
.ident = "Clevo NL5xRU",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
},
},
{
.callback = video_detect_force_native,
.ident = "Clevo NL5xRU",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
},
},
{
.callback = video_detect_force_native,
.ident = "Clevo NL5xRU",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_MATCH(DMI_BOARD_NAME, "AURA1501"),
},
},
{
.callback = video_detect_force_native,
.ident = "Clevo NL5xRU",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"),
},
},
{
.callback = video_detect_force_native,
.ident = "Clevo NL5xNU",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
},
},
{
.callback = video_detect_force_native,
.ident = "Clevo NL5xNU",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
},
},
{
.callback = video_detect_force_native,
.ident = "Clevo NL5xNU",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
},
},
/*
* Desktops which falsely report a backlight and which our heuristics

View file

@ -405,6 +405,8 @@ static const struct usb_device_id blacklist_table[] = {
BTUSB_WIDEBAND_SPEECH },
/* Realtek 8852AE Bluetooth devices */
{ USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0bda, 0x385a), .driver_info = BTUSB_REALTEK |
@ -482,6 +484,8 @@ static const struct usb_device_id blacklist_table[] = {
/* Additional Realtek 8761BU Bluetooth devices */
{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x2550, 0x8761), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
/* Additional Realtek 8821AE Bluetooth devices */
{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
@ -2041,6 +2045,8 @@ static int btusb_setup_csr(struct hci_dev *hdev)
*/
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks);
set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks);
/* Clear the reset quirk since this is not an actual
* early Bluetooth 1.1 device from CSR.
@ -2051,7 +2057,7 @@ static int btusb_setup_csr(struct hci_dev *hdev)
/*
* Special workaround for these BT 4.0 chip clones, and potentially more:
*
* - 0x0134: a Barrot 8041a02 (HCI rev: 0x1012 sub: 0x0810)
* - 0x0134: a Barrot 8041a02 (HCI rev: 0x0810 sub: 0x1012)
* - 0x7558: IC markings FR3191AHAL 749H15143 (HCI rev/sub-version: 0x0709)
*
* These controllers are really messed-up.
@ -2080,7 +2086,7 @@ static int btusb_setup_csr(struct hci_dev *hdev)
if (ret >= 0)
msleep(200);
else
bt_dev_err(hdev, "CSR: Failed to suspend the device for our Barrot 8041a02 receive-issue workaround");
bt_dev_warn(hdev, "CSR: Couldn't suspend the device for our Barrot 8041a02 receive-issue workaround");
pm_runtime_forbid(&data->udev->dev);

View file

@ -274,14 +274,6 @@ static void tpm_dev_release(struct device *dev)
kfree(chip);
}
static void tpm_devs_release(struct device *dev)
{
struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
/* release the master device reference */
put_device(&chip->dev);
}
/**
* tpm_class_shutdown() - prepare the TPM device for loss of power.
* @dev: device to which the chip is associated.
@ -344,7 +336,6 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
chip->dev_num = rc;
device_initialize(&chip->dev);
device_initialize(&chip->devs);
chip->dev.class = tpm_class;
chip->dev.class->shutdown_pre = tpm_class_shutdown;
@ -352,29 +343,12 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
chip->dev.parent = pdev;
chip->dev.groups = chip->groups;
chip->devs.parent = pdev;
chip->devs.class = tpmrm_class;
chip->devs.release = tpm_devs_release;
/* get extra reference on main device to hold on
* behalf of devs. This holds the chip structure
* while cdevs is in use. The corresponding put
* is in the tpm_devs_release (TPM2 only)
*/
if (chip->flags & TPM_CHIP_FLAG_TPM2)
get_device(&chip->dev);
if (chip->dev_num == 0)
chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
else
chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
chip->devs.devt =
MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
if (rc)
goto out;
rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
if (rc)
goto out;
@ -382,9 +356,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
cdev_init(&chip->cdev, &tpm_fops);
cdev_init(&chip->cdevs, &tpmrm_fops);
chip->cdev.owner = THIS_MODULE;
chip->cdevs.owner = THIS_MODULE;
rc = tpm2_init_space(&chip->work_space, TPM2_SPACE_BUFFER_SIZE);
if (rc) {
@ -396,7 +368,6 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
return chip;
out:
put_device(&chip->devs);
put_device(&chip->dev);
return ERR_PTR(rc);
}
@ -445,14 +416,9 @@ static int tpm_add_char_device(struct tpm_chip *chip)
}
if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip)) {
rc = cdev_device_add(&chip->cdevs, &chip->devs);
if (rc) {
dev_err(&chip->devs,
"unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
dev_name(&chip->devs), MAJOR(chip->devs.devt),
MINOR(chip->devs.devt), rc);
return rc;
}
rc = tpm_devs_add(chip);
if (rc)
goto err_del_cdev;
}
/* Make the chip available. */
@ -460,6 +426,10 @@ static int tpm_add_char_device(struct tpm_chip *chip)
idr_replace(&dev_nums_idr, chip, chip->dev_num);
mutex_unlock(&idr_lock);
return 0;
err_del_cdev:
cdev_device_del(&chip->cdev, &chip->dev);
return rc;
}
@ -654,7 +624,7 @@ void tpm_chip_unregister(struct tpm_chip *chip)
hwrng_unregister(&chip->hwrng);
tpm_bios_log_teardown(chip);
if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip))
cdev_device_del(&chip->cdevs, &chip->devs);
tpm_devs_remove(chip);
tpm_del_char_device(chip);
}
EXPORT_SYMBOL_GPL(tpm_chip_unregister);

View file

@ -69,7 +69,13 @@ static void tpm_dev_async_work(struct work_struct *work)
ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer,
sizeof(priv->data_buffer));
tpm_put_ops(priv->chip);
if (ret > 0) {
/*
* If ret is > 0 then tpm_dev_transmit returned the size of the
* response. If ret is < 0 then tpm_dev_transmit failed and
* returned an error code.
*/
if (ret != 0) {
priv->response_length = ret;
mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
}

View file

@ -234,6 +234,8 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
size_t cmdsiz);
int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, void *buf,
size_t *bufsiz);
int tpm_devs_add(struct tpm_chip *chip);
void tpm_devs_remove(struct tpm_chip *chip);
void tpm_bios_log_setup(struct tpm_chip *chip);
void tpm_bios_log_teardown(struct tpm_chip *chip);

View file

@ -58,12 +58,12 @@ int tpm2_init_space(struct tpm_space *space, unsigned int buf_size)
void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space)
{
mutex_lock(&chip->tpm_mutex);
if (!tpm_chip_start(chip)) {
if (tpm_try_get_ops(chip) == 0) {
tpm2_flush_sessions(chip, space);
tpm_chip_stop(chip);
tpm_put_ops(chip);
}
mutex_unlock(&chip->tpm_mutex);
kfree(space->context_buf);
kfree(space->session_buf);
}
@ -574,3 +574,68 @@ out:
dev_err(&chip->dev, "%s: error %d\n", __func__, rc);
return rc;
}
/*
* Put the reference to the main device.
*/
static void tpm_devs_release(struct device *dev)
{
struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
/* release the master device reference */
put_device(&chip->dev);
}
/*
* Remove the device file for exposed TPM spaces and release the device
* reference. This may also release the reference to the master device.
*/
void tpm_devs_remove(struct tpm_chip *chip)
{
cdev_device_del(&chip->cdevs, &chip->devs);
put_device(&chip->devs);
}
/*
* Add a device file to expose TPM spaces. Also take a reference to the
* main device.
*/
int tpm_devs_add(struct tpm_chip *chip)
{
int rc;
device_initialize(&chip->devs);
chip->devs.parent = chip->dev.parent;
chip->devs.class = tpmrm_class;
/*
* Get extra reference on main device to hold on behalf of devs.
* This holds the chip structure while cdevs is in use. The
* corresponding put is in the tpm_devs_release.
*/
get_device(&chip->dev);
chip->devs.release = tpm_devs_release;
chip->devs.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
cdev_init(&chip->cdevs, &tpmrm_fops);
chip->cdevs.owner = THIS_MODULE;
rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
if (rc)
goto err_put_devs;
rc = cdev_device_add(&chip->cdevs, &chip->devs);
if (rc) {
dev_err(&chip->devs,
"unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
dev_name(&chip->devs), MAJOR(chip->devs.devt),
MINOR(chip->devs.devt), rc);
goto err_put_devs;
}
return 0;
err_put_devs:
put_device(&chip->devs);
return rc;
}

View file

@ -805,15 +805,20 @@ static const struct rpm_smd_clk_desc rpm_clk_qcs404 = {
.num_clks = ARRAY_SIZE(qcs404_clks),
};
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin,
3, 19200000);
DEFINE_CLK_SMD_RPM_BRANCH(msm8998, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0,
19200000);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk3, ln_bb_clk3_a, 3, 19200000);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin, 3, 19200000);
DEFINE_CLK_SMD_RPM(msm8998, aggre1_noc_clk, aggre1_noc_a_clk,
QCOM_SMD_RPM_AGGR_CLK, 1);
DEFINE_CLK_SMD_RPM(msm8998, aggre2_noc_clk, aggre2_noc_a_clk,
QCOM_SMD_RPM_AGGR_CLK, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk3, rf_clk3_a, 6, 19200000);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6, 19200000);
static struct clk_smd_rpm *msm8998_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
[RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk,
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
@ -826,12 +831,22 @@ static struct clk_smd_rpm *msm8998_clks[] = {
[RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk,
[RPM_SMD_DIV_CLK1] = &msm8974_div_clk1,
[RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1,
[RPM_SMD_DIV_CLK2] = &msm8974_div_clk2,
[RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2,
[RPM_SMD_DIV_CLK3] = &msm8992_div_clk3,
[RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a,
[RPM_SMD_IPA_CLK] = &msm8976_ipa_clk,
[RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk,
[RPM_SMD_LN_BB_CLK1] = &msm8916_bb_clk1,
[RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a,
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
[RPM_SMD_LN_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
[RPM_SMD_LN_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
[RPM_SMD_LN_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,
[RPM_SMD_LN_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,
[RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin,
[RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin,
[RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk,
@ -844,10 +859,14 @@ static struct clk_smd_rpm *msm8998_clks[] = {
[RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk,
[RPM_SMD_RF_CLK1] = &msm8916_rf_clk1,
[RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a,
[RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,
[RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,
[RPM_SMD_RF_CLK2] = &msm8916_rf_clk2,
[RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a,
[RPM_SMD_RF_CLK3] = &msm8998_rf_clk3,
[RPM_SMD_RF_CLK3_A] = &msm8998_rf_clk3_a,
[RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,
[RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,
[RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,
[RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,
[RPM_SMD_RF_CLK3_PIN] = &msm8998_rf_clk3_pin,
[RPM_SMD_RF_CLK3_A_PIN] = &msm8998_rf_clk3_a_pin,
};
@ -857,14 +876,9 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8998 = {
.num_clks = ARRAY_SIZE(msm8998_clks),
};
DEFINE_CLK_SMD_RPM_BRANCH(sdm660, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0,
19200000);
DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk3, ln_bb_clk3_a, 3, 19200000);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin, ln_bb_clk3_pin_a, 3, 19200000);
static struct clk_smd_rpm *sdm660_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk,
[RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk,
@ -891,16 +905,16 @@ static struct clk_smd_rpm *sdm660_clks[] = {
[RPM_SMD_LN_BB_A_CLK] = &msm8916_bb_clk1_a,
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
[RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a,
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
[RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,
[RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,
[RPM_SMD_LN_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
[RPM_SMD_LN_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
[RPM_SMD_LN_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,
[RPM_SMD_LN_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,
[RPM_SMD_LN_BB_CLK3_PIN] = &sdm660_ln_bb_clk3_pin,
[RPM_SMD_LN_BB_CLK3_A_PIN] = &sdm660_ln_bb_clk3_pin_a,
[RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin,
[RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin,
};
static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
@ -909,8 +923,8 @@ static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
};
static struct clk_smd_rpm *mdm9607_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
[RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
@ -931,8 +945,8 @@ static const struct rpm_smd_clk_desc rpm_clk_mdm9607 = {
};
static struct clk_smd_rpm *msm8953_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
[RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
[RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,
@ -980,8 +994,8 @@ DEFINE_CLK_SMD_RPM(sm6125, snoc_lpass_clk, snoc_lpass_a_clk,
QCOM_SMD_RPM_BUS_CLK, 5);
static struct clk_smd_rpm *sm6125_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
@ -1002,8 +1016,8 @@ static struct clk_smd_rpm *sm6125_clks[] = {
[RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a,
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
[RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a,
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
[RPM_SMD_QUP_CLK] = &sm6125_qup_clk,
[RPM_SMD_QUP_A_CLK] = &sm6125_qup_a_clk,
[RPM_SMD_MMRT_CLK] = &sm6125_mmrt_clk,
@ -1023,8 +1037,8 @@ static const struct rpm_smd_clk_desc rpm_clk_sm6125 = {
/* SM6115 */
static struct clk_smd_rpm *sm6115_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
@ -1075,8 +1089,8 @@ DEFINE_CLK_SMD_RPM(qcm2290, bimc_gpu_clk, bimc_gpu_a_clk,
QCOM_SMD_RPM_MEM_CLK, 2);
static struct clk_smd_rpm *qcm2290_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,

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,
},
};
@ -2833,6 +2835,43 @@ static struct clk_branch gcc_rx1_usb2_clkref_clk = {
},
};
static struct clk_branch hlos1_vote_lpass_core_smmu_clk = {
.halt_reg = 0x7D010,
.clkr = {
.enable_reg = 0x7D010,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data) {
.name = "hlos1_vote_lpass_core_smmu_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch hlos1_vote_lpass_adsp_smmu_clk = {
.halt_reg = 0x7D014,
.clkr = {
.enable_reg = 0x7D014,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data) {
.name = "hlos1_vote_lpass_adsp_smmu_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
.halt_reg = 0x8A040,
.clkr = {
.enable_reg = 0x8A040,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data) {
.name = "gcc_mss_q6_bimc_axi_clk",
.flags = CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
};
static struct gdsc pcie_0_gdsc = {
.gdscr = 0x6b004,
.gds_hw_ctrl = 0x0,
@ -2863,6 +2902,26 @@ static struct gdsc usb_30_gdsc = {
.flags = VOTABLE,
};
static struct gdsc hlos1_vote_lpass_adsp = {
.gdscr = 0x7d034,
.gds_hw_ctrl = 0x0,
.pd = {
.name = "lpass_adsp_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
.flags = VOTABLE,
};
static struct gdsc hlos1_vote_lpass_core = {
.gdscr = 0x7d038,
.gds_hw_ctrl = 0x0,
.pd = {
.name = "lpass_core_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
.flags = ALWAYS_ON,
};
static struct clk_regmap *gcc_msm8998_clocks[] = {
[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
[BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
@ -3036,12 +3095,17 @@ static struct clk_regmap *gcc_msm8998_clocks[] = {
[GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr,
[GCC_MMSS_GPLL0_CLK] = &gcc_mmss_gpll0_clk.clkr,
[HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
[GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr,
[HLOS1_VOTE_LPASS_CORE_SMMU_CLK] = &hlos1_vote_lpass_core_smmu_clk.clkr,
[HLOS1_VOTE_LPASS_ADSP_SMMU_CLK] = &hlos1_vote_lpass_adsp_smmu_clk.clkr,
};
static struct gdsc *gcc_msm8998_gdscs[] = {
[PCIE_0_GDSC] = &pcie_0_gdsc,
[UFS_GDSC] = &ufs_gdsc,
[USB_30_GDSC] = &usb_30_gdsc,
[LPASS_ADSP_GDSC] = &hlos1_vote_lpass_adsp,
[LPASS_CORE_GDSC] = &hlos1_vote_lpass_core,
};
static const struct qcom_reset_map gcc_msm8998_resets[] = {
@ -3191,6 +3255,14 @@ static int gcc_msm8998_probe(struct platform_device *pdev)
if (ret)
return ret;
/*
* GCC_MMSS_MISC - GCC_GPU_MISC:
* 1. Disable the GPLL0 active input to MMSS and GPU
* 2. Select clk division 1 (CLK/2)
*/
regmap_write(regmap, 0x0902C, 0x10003); /* MMSS*/
regmap_write(regmap, 0x71028, 0x10003); /* GPU */
return qcom_cc_really_probe(pdev, &gcc_msm8998_desc, regmap);
}

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

@ -136,6 +136,7 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "qcom,apq8096", },
{ .compatible = "qcom,msm8996", },
{ .compatible = "qcom,msm8998", },
{ .compatible = "qcom,qcs404", },
{ .compatible = "qcom,sa8155p" },
{ .compatible = "qcom,sc7180", },

File diff suppressed because it is too large Load diff

View file

@ -75,6 +75,13 @@ static int adf_crypto_dev_config(struct adf_accel_dev *accel_dev)
if (ret)
goto err;
/* Temporarily set the number of crypto instances to zero to avoid
* registering the crypto algorithms.
* This will be removed when the algorithms will support the
* CRYPTO_TFM_REQ_MAY_BACKLOG flag
*/
instances = 0;
for (i = 0; i < instances; i++) {
val = i;
bank = i * 2;

View file

@ -161,6 +161,13 @@ int qat_crypto_dev_config(struct adf_accel_dev *accel_dev)
if (ret)
goto err;
/* Temporarily set the number of crypto instances to zero to avoid
* registering the crypto algorithms.
* This will be removed when the algorithms will support the
* CRYPTO_TFM_REQ_MAY_BACKLOG flag
*/
instances = 0;
for (i = 0; i < instances; i++) {
val = i;
snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_BANK_NUM, i);

View file

@ -42,7 +42,7 @@ int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
{
int ret;
WARN_ON(!dev->driver->load && dev->registered && !obj_free_cb);
//WARN_ON(!dev->driver->load && dev->registered && !obj_free_cb);
mutex_lock(&dev->mode_config.idr_mutex);
ret = idr_alloc(&dev->mode_config.object_idr, register_obj ? obj : NULL,
@ -237,10 +237,10 @@ void drm_object_attach_property(struct drm_mode_object *obj,
if (obj->type == DRM_MODE_OBJECT_CONNECTOR) {
struct drm_connector *connector = obj_to_connector(obj);
/*struct drm_connector *connector = obj_to_connector(obj);
WARN_ON(!dev->driver->load &&
connector->registration_state == DRM_CONNECTOR_REGISTERED);
connector->registration_state == DRM_CONNECTOR_REGISTERED);*/
} else {
WARN_ON(!dev->driver->load && dev->registered);
}

View file

@ -112,7 +112,7 @@ config DRM_MSM_DSI_14NM_PHY
Choose this option if DSI PHY on 8996 is used on the platform.
config DRM_MSM_DSI_10NM_PHY
bool "Enable DSI 10nm PHY driver in MSM DRM (used by SDM845)"
bool "Enable DSI 10nm PHY driver in MSM DRM (used by MSM8998/SDM845)"
depends on DRM_MSM_DSI
default y
help

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);
@ -1697,6 +1744,20 @@ static uint32_t a5xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
return ring->memptrs->rptr = gpu_read(gpu, REG_A5XX_CP_RB_RPTR);
}
static struct msm_gem_address_space *
a5xx_create_private_address_space(struct msm_gpu *gpu)
{
struct msm_mmu *mmu;
mmu = msm_iommu_pagetable_create(gpu->aspace->mmu);
if (IS_ERR(mmu))
return ERR_CAST(mmu);
return msm_gem_address_space_create(mmu,
"gpu", 0x100000000ULL, 0x1ffffffffULL);
}
static const struct adreno_gpu_funcs funcs = {
.base = {
.get_param = adreno_get_param,
@ -1718,6 +1779,7 @@ static const struct adreno_gpu_funcs funcs = {
.gpu_state_get = a5xx_gpu_state_get,
.gpu_state_put = a5xx_gpu_state_put,
.create_address_space = adreno_iommu_create_address_space,
.create_private_address_space = a5xx_create_private_address_space,
.get_rptr = a5xx_get_rptr,
},
.get_timestamp = a5xx_get_timestamp,

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

@ -356,6 +356,11 @@ MODULE_FIRMWARE("qcom/a530_zap.mdt");
MODULE_FIRMWARE("qcom/a530_zap.b00");
MODULE_FIRMWARE("qcom/a530_zap.b01");
MODULE_FIRMWARE("qcom/a530_zap.b02");
MODULE_FIRMWARE("qcom/a540_gpmu.fw2");
MODULE_FIRMWARE("qcom/a540_zap.mdt");
MODULE_FIRMWARE("qcom/a540_zap.b00");
MODULE_FIRMWARE("qcom/a540_zap.b01");
MODULE_FIRMWARE("qcom/a540_zap.b02");
MODULE_FIRMWARE("qcom/a630_sqe.fw");
MODULE_FIRMWARE("qcom/a630_gmu.bin");
MODULE_FIRMWARE("qcom/a630_zap.mbn");

View file

@ -682,6 +682,9 @@ static int dpu_encoder_phys_cmd_wait_for_commit_done(
if (!dpu_encoder_phys_cmd_is_master(phys_enc))
return 0;
if (phys_enc->hw_ctl->ops.is_started)
return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc);
return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc);
}

View file

@ -16,6 +16,9 @@
BIT(DPU_SSPP_CSC_10BIT) | BIT(DPU_SSPP_CDP) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_EXCL_RECT))
#define VIG_MSM8998_MASK \
(VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3))
#define VIG_SDM845_MASK \
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3))
@ -25,6 +28,11 @@
#define VIG_SM8250_MASK \
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3LITE))
#define DMA_MSM8998_MASK \
(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT))
#define DMA_SDM845_MASK \
(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
@ -33,6 +41,9 @@
#define DMA_CURSOR_SDM845_MASK \
(DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR))
#define DMA_CURSOR_MSM8998_MASK \
(DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR))
#define MIXER_SDM845_MASK \
(BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER))
@ -49,6 +60,8 @@
#define MERGE_3D_SM8150_MASK (0)
#define DSPP_MSM8998_MASK BIT(DPU_DSPP_PCC) | BIT(DPU_DSPP_GC)
#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC)
#define INTF_SDM845_MASK (0)
@ -181,6 +194,22 @@ static const uint32_t plane_formats_yuv[] = {
* DPU sub blocks config
*************************************************************/
/* DPU top level caps */
static const struct dpu_caps msm8998_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0x7,
.qseed_type = DPU_SSPP_SCALER_QSEED3,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V1,
.ubwc_version = DPU_HW_UBWC_VER_10,
.has_src_split = true,
.has_dim_layer = true,
.has_idle_pc = true,
.has_3d_merge = true,
.max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
.max_hdeci_exp = MAX_HORZ_DECIMATION,
.max_vdeci_exp = MAX_VERT_DECIMATION,
};
static const struct dpu_caps sdm845_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
@ -251,6 +280,35 @@ static const struct dpu_caps sc7280_dpu_caps = {
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
};
static const struct dpu_mdp_cfg msm8998_mdp[] = {
{
.name = "top_0", .id = MDP_TOP,
.base = 0x0, .len = 0x458,
.features = 0,
.highest_bank_bit = 0x2,
.clk_ctrls[DPU_CLK_CTRL_VIG0] = {
.reg_off = 0x2AC, .bit_off = 0},
.clk_ctrls[DPU_CLK_CTRL_VIG1] = {
.reg_off = 0x2B4, .bit_off = 0},
.clk_ctrls[DPU_CLK_CTRL_VIG2] = {
.reg_off = 0x2BC, .bit_off = 0},
.clk_ctrls[DPU_CLK_CTRL_VIG3] = {
.reg_off = 0x2C4, .bit_off = 0},
.clk_ctrls[DPU_CLK_CTRL_DMA0] = {
.reg_off = 0x2AC, .bit_off = 8},
.clk_ctrls[DPU_CLK_CTRL_DMA1] = {
.reg_off = 0x2B4, .bit_off = 8},
.clk_ctrls[DPU_CLK_CTRL_DMA2] = {
.reg_off = 0x2C4, .bit_off = 8},
.clk_ctrls[DPU_CLK_CTRL_DMA3] = {
.reg_off = 0x2C4, .bit_off = 12},
.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = {
.reg_off = 0x3A8, .bit_off = 15},
.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = {
.reg_off = 0x3B0, .bit_off = 15},
},
};
static const struct dpu_mdp_cfg sdm845_mdp[] = {
{
.name = "top_0", .id = MDP_TOP,
@ -339,6 +397,39 @@ static const struct dpu_mdp_cfg sc7280_mdp[] = {
/*************************************************************
* CTL sub blocks config
*************************************************************/
static const struct dpu_ctl_cfg msm8998_ctl[] = {
{
.name = "ctl_0", .id = CTL_0,
.base = 0x1000, .len = 0x94,
.features = BIT(DPU_CTL_SPLIT_DISPLAY),
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
},
{
.name = "ctl_1", .id = CTL_1,
.base = 0x1200, .len = 0x94,
.features = 0,
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
},
{
.name = "ctl_2", .id = CTL_2,
.base = 0x1400, .len = 0x94,
.features = BIT(DPU_CTL_SPLIT_DISPLAY),
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
},
{
.name = "ctl_3", .id = CTL_3,
.base = 0x1600, .len = 0x94,
.features = 0,
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
},
{
.name = "ctl_4", .id = CTL_4,
.base = 0x1800, .len = 0x94,
.features = 0,
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
},
};
static const struct dpu_ctl_cfg sdm845_ctl[] = {
{
.name = "ctl_0", .id = CTL_0,
@ -497,6 +588,15 @@ static const struct dpu_ctl_cfg sc7280_ctl[] = {
.virt_num_formats = ARRAY_SIZE(plane_formats), \
}
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_0 =
_VIG_SBLK("0", 0, DPU_SSPP_SCALER_QSEED3);
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_1 =
_VIG_SBLK("1", 0, DPU_SSPP_SCALER_QSEED3);
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_2 =
_VIG_SBLK("2", 0, DPU_SSPP_SCALER_QSEED3);
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_3 =
_VIG_SBLK("3", 0, DPU_SSPP_SCALER_QSEED3);
static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 =
_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3);
static const struct dpu_sspp_sub_blks sdm845_vig_sblk_1 =
@ -523,6 +623,25 @@ static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK("11", 4);
.clk_ctrl = _clkctrl \
}
static const struct dpu_sspp_cfg msm8998_sspp[] = {
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_MSM8998_MASK,
msm8998_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_MSM8998_MASK,
msm8998_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1),
SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_MSM8998_MASK,
msm8998_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2),
SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_MSM8998_MASK,
msm8998_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3),
SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_MSM8998_MASK,
sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_MSM8998_MASK,
sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_MSM8998_MASK,
sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0),
SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_MSM8998_MASK,
sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1),
};
static const struct dpu_sspp_cfg sdm845_sspp[] = {
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SDM845_MASK,
sdm845_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
@ -599,17 +718,6 @@ static const struct dpu_sspp_cfg sc7280_sspp[] = {
* MIXER sub blocks config
*************************************************************/
/* SDM845 */
static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.maxblendstages = 11, /* excluding base layer */
.blendstage_base = { /* offsets relative to mixer base */
0x20, 0x38, 0x50, 0x68, 0x80, 0x98,
0xb0, 0xc8, 0xe0, 0xf8, 0x110
},
};
#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair, _dspp) \
{ \
.name = _name, .id = _id, \
@ -621,6 +729,43 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
.dspp = _dspp \
}
/* MSM8998 */
static const struct dpu_lm_sub_blks msm8998_lm_sblk = {
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.maxblendstages = 7, /* excluding base layer */
.blendstage_base = { /* offsets relative to mixer base */
0x20, 0x50, 0x80, 0xb0, 0x230,
0x260, 0x290
},
};
static const struct dpu_lm_cfg msm8998_lm[] = {
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
&msm8998_lm_sblk, PINGPONG_0, LM_2, DSPP_0),
LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
&msm8998_lm_sblk, PINGPONG_1, LM_5, DSPP_1),
LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
&msm8998_lm_sblk, PINGPONG_2, LM_0, 0),
LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK,
&msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
LM_BLK("lm_4", LM_4, 0x48000, MIXER_SDM845_MASK,
&msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
&msm8998_lm_sblk, PINGPONG_3, LM_1, 0),
};
/* SDM845 */
static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.maxblendstages = 11, /* excluding base layer */
.blendstage_base = { /* offsets relative to mixer base */
0x20, 0x38, 0x50, 0x68, 0x80, 0x98,
0xb0, 0xc8, 0xe0, 0xf8, 0x110
},
};
static const struct dpu_lm_cfg sdm845_lm[] = {
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
&sdm845_lm_sblk, PINGPONG_0, LM_1, 0),
@ -682,6 +827,13 @@ static const struct dpu_lm_cfg sc7280_lm[] = {
/*************************************************************
* DSPP sub blocks config
*************************************************************/
static const struct dpu_dspp_sub_blks msm8998_dspp_sblk = {
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
.len = 0x90, .version = 0x10007},
.gc = { .id = DPU_DSPP_GC, .base = 0x17c0,
.len = 0x90, .version = 0x10007},
};
static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = {
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
.len = 0x90, .version = 0x10000},
@ -700,6 +852,13 @@ static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = {
.sblk = _sblk \
}
static const struct dpu_dspp_cfg msm8998_dspp[] = {
DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_MSM8998_MASK,
&msm8998_dspp_sblk),
DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_MSM8998_MASK,
&msm8998_dspp_sblk),
};
static const struct dpu_dspp_cfg sc7180_dspp[] = {
DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
&sc7180_dspp_sblk),
@ -836,6 +995,13 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
.intr_vsync = DPU_IRQ_IDX(_reg, _vsync_bit), \
}
static const struct dpu_intf_cfg msm8998_intf[] = {
INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_HDMI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
};
static const struct dpu_intf_cfg sdm845_intf[] = {
INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
@ -865,9 +1031,55 @@ static const struct dpu_intf_cfg sc7280_intf[] = {
* VBIF sub blocks config
*************************************************************/
/* VBIF QOS remap */
static const u32 msm8998_rt_pri_lvl[] = {1, 2, 2, 2};
static const u32 msm8998_nrt_pri_lvl[] = {1, 1, 1, 1};
static const u32 sdm845_rt_pri_lvl[] = {3, 3, 4, 4, 5, 5, 6, 6};
static const u32 sdm845_nrt_pri_lvl[] = {3, 3, 3, 3, 3, 3, 3, 3};
static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = {
{
.pps = 1088 * 1920 * 30,
.ot_limit = 2,
},
{
.pps = 1088 * 1920 * 60,
.ot_limit = 6,
},
{
.pps = 3840 * 2160 * 30,
.ot_limit = 16,
},
};
static const struct dpu_vbif_cfg msm8998_vbif[] = {
{
.name = "vbif_0", .id = VBIF_0,
.base = 0, .len = 0x1040,
.default_ot_rd_limit = 32,
.default_ot_wr_limit = 32,
.features = BIT(DPU_VBIF_QOS_REMAP) | BIT(DPU_VBIF_QOS_OTLIM),
.xin_halt_timeout = 0x4000,
.dynamic_ot_rd_tbl = {
.count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
.cfg = msm8998_ot_rdwr_cfg,
},
.dynamic_ot_wr_tbl = {
.count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
.cfg = msm8998_ot_rdwr_cfg,
},
.qos_rt_tbl = {
.npriority_lvl = ARRAY_SIZE(msm8998_rt_pri_lvl),
.priority_lvl = msm8998_rt_pri_lvl,
},
.qos_nrt_tbl = {
.npriority_lvl = ARRAY_SIZE(msm8998_nrt_pri_lvl),
.priority_lvl = msm8998_nrt_pri_lvl,
},
.memtype_count = 14,
.memtype = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
},
};
static const struct dpu_vbif_cfg sdm845_vbif[] = {
{
.name = "vbif_0", .id = VBIF_0,
@ -908,6 +1120,22 @@ static const struct dpu_reg_dma_cfg sm8250_regdma = {
*************************************************************/
/* SSPP QOS LUTs */
static const struct dpu_qos_lut_entry msm8998_qos_linear[] = {
{.fl = 4, .lut = 0x1b},
{.fl = 5, .lut = 0x5b},
{.fl = 6, .lut = 0x15b},
{.fl = 7, .lut = 0x55b},
{.fl = 8, .lut = 0x155b},
{.fl = 9, .lut = 0x555b},
{.fl = 10, .lut = 0x1555b},
{.fl = 11, .lut = 0x5555b},
{.fl = 12, .lut = 0x15555b},
{.fl = 13, .lut = 0x55555b},
{.fl = 14, .lut = 0},
{.fl = 1, .lut = 0x1b},
{.fl = 0, .lut = 0}
};
static const struct dpu_qos_lut_entry sdm845_qos_linear[] = {
{.fl = 4, .lut = 0x357},
{.fl = 5, .lut = 0x3357},
@ -923,6 +1151,15 @@ static const struct dpu_qos_lut_entry sdm845_qos_linear[] = {
{.fl = 0, .lut = 0x11222222223357}
};
static const struct dpu_qos_lut_entry msm8998_qos_macrotile[] = {
{.fl = 10, .lut = 0x1aaff},
{.fl = 11, .lut = 0x5aaff},
{.fl = 12, .lut = 0x15aaff},
{.fl = 13, .lut = 0x55aaff},
{.fl = 1, .lut = 0x1aaff},
{.fl = 0, .lut = 0},
};
static const struct dpu_qos_lut_entry sc7180_qos_linear[] = {
{.fl = 0, .lut = 0x0011222222335777},
};
@ -944,6 +1181,10 @@ static const struct dpu_qos_lut_entry sc7180_qos_macrotile[] = {
{.fl = 0, .lut = 0x0011223344556677},
};
static const struct dpu_qos_lut_entry msm8998_qos_nrt[] = {
{.fl = 0, .lut = 0x0},
};
static const struct dpu_qos_lut_entry sdm845_qos_nrt[] = {
{.fl = 0, .lut = 0x0},
};
@ -952,6 +1193,42 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
{.fl = 0, .lut = 0x0},
};
static const struct dpu_perf_cfg msm8998_perf_data = {
.max_bw_low = 6700000,
.max_bw_high = 6700000,
.min_core_ib = 2400000,
.min_llcc_ib = 800000,
.min_dram_ib = 800000,
.undersized_prefill_lines = 2,
.xtra_prefill_lines = 2,
.dest_scale_prefill_lines = 3,
.macrotile_prefill_lines = 4,
.yuv_nv12_prefill_lines = 8,
.linear_prefill_lines = 1,
.downscaling_prefill_lines = 1,
.amortizable_threshold = 25,
.min_prefill_lines = 25,
.danger_lut_tbl = {0xf, 0xffff, 0x0},
.safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
.qos_lut_tbl = {
{.nentry = ARRAY_SIZE(msm8998_qos_linear),
.entries = msm8998_qos_linear
},
{.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
.entries = msm8998_qos_macrotile
},
{.nentry = ARRAY_SIZE(msm8998_qos_nrt),
.entries = msm8998_qos_nrt
},
},
.cdp_cfg = {
{.rd_enable = 1, .wr_enable = 1},
{.rd_enable = 1, .wr_enable = 0}
},
.clk_inefficiency_factor = 200,
.bw_inefficiency_factor = 120,
};
static const struct dpu_perf_cfg sdm845_perf_data = {
.max_bw_low = 6800000,
.max_bw_high = 6800000,
@ -1106,6 +1383,34 @@ static const struct dpu_perf_cfg sc7280_perf_data = {
* Hardware catalog init
*************************************************************/
/*
* msm8998_cfg_init(): populate sdm845 dpu sub-blocks reg offsets
* and instance counts.
*/
static void msm8998_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
{
*dpu_cfg = (struct dpu_mdss_cfg){
.caps = &msm8998_dpu_caps,
.mdp_count = ARRAY_SIZE(msm8998_mdp),
.mdp = msm8998_mdp,
.ctl_count = ARRAY_SIZE(msm8998_ctl),
.ctl = msm8998_ctl,
.sspp_count = ARRAY_SIZE(msm8998_sspp),
.sspp = msm8998_sspp,
.mixer_count = ARRAY_SIZE(msm8998_lm),
.mixer = msm8998_lm,
.pingpong_count = ARRAY_SIZE(sdm845_pp),
.pingpong = sdm845_pp,
.intf_count = ARRAY_SIZE(msm8998_intf),
.intf = msm8998_intf,
.vbif_count = ARRAY_SIZE(msm8998_vbif),
.vbif = msm8998_vbif,
.reg_dma_count = 0,
.perf = msm8998_perf_data,
.mdss_irqs = IRQ_SM8250_MASK,
};
}
/*
* sdm845_cfg_init(): populate sdm845 dpu sub-blocks reg offsets
* and instance counts.
@ -1256,6 +1561,8 @@ static void sc7280_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
}
static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = {
{ .hw_rev = DPU_HW_VER_300, .cfg_init = msm8998_cfg_init},
{ .hw_rev = DPU_HW_VER_301, .cfg_init = msm8998_cfg_init},
{ .hw_rev = DPU_HW_VER_400, .cfg_init = sdm845_cfg_init},
{ .hw_rev = DPU_HW_VER_401, .cfg_init = sdm845_cfg_init},
{ .hw_rev = DPU_HW_VER_500, .cfg_init = sm8150_cfg_init},

View file

@ -435,6 +435,8 @@ enum dpu_clk_ctrl_type {
DPU_CLK_CTRL_RGB3,
DPU_CLK_CTRL_DMA0,
DPU_CLK_CTRL_DMA1,
DPU_CLK_CTRL_DMA2,
DPU_CLK_CTRL_DMA3,
DPU_CLK_CTRL_CURSOR0,
DPU_CLK_CTRL_CURSOR1,
DPU_CLK_CTRL_INLINE_ROT0_SSPP,

View file

@ -92,6 +92,11 @@ static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx)
DPU_REG_WRITE(&ctx->hw, CTL_START, 0x1);
}
static inline bool dpu_hw_ctl_is_started(struct dpu_hw_ctl *ctx)
{
return !!(DPU_REG_READ(&ctx->hw, CTL_START) & BIT(0));
}
static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx)
{
trace_dpu_hw_ctl_trigger_prepare(ctx->pending_flush_mask,
@ -587,6 +592,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->get_pending_flush = dpu_hw_ctl_get_pending_flush;
ops->get_flush_register = dpu_hw_ctl_get_flush_register;
ops->trigger_start = dpu_hw_ctl_trigger_start;
ops->is_started = dpu_hw_ctl_is_started;
ops->trigger_pending = dpu_hw_ctl_trigger_pending;
ops->reset = dpu_hw_ctl_reset_control;
ops->wait_reset_status = dpu_hw_ctl_wait_reset_status;

View file

@ -61,6 +61,13 @@ struct dpu_hw_ctl_ops {
*/
void (*trigger_start)(struct dpu_hw_ctl *ctx);
/**
* check if the ctl is started
* @ctx : ctl path ctx pointer
* @Return: true if started, false if stopped
*/
bool (*is_started)(struct dpu_hw_ctl *ctx);
/**
* kickoff prepare is in progress hw operation for sw
* controlled interfaces: DSI cmd mode and WB interface

View file

@ -1348,6 +1348,7 @@ static const struct dev_pm_ops dpu_pm_ops = {
};
const struct of_device_id dpu_dt_match[] = {
{ .compatible = "qcom,msm8998-dpu", },
{ .compatible = "qcom,sdm845-dpu", },
{ .compatible = "qcom,sc7180-dpu", },
{ .compatible = "qcom,sc7280-dpu", },

View file

@ -110,7 +110,7 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_10nm *pll, struct dsi_pll_confi
pll_freq = pll->vco_current_rate;
divider = fref * 2;
divider = fref;
multiplier = 1 << FRAC_BITS;
dec_multiple = div_u64(pll_freq * multiplier, divider);
@ -428,12 +428,11 @@ static unsigned long dsi_pll_10nm_vco_recalc_rate(struct clk_hw *hw,
* 1. Assumes prescaler is disabled
*/
multiplier = 1 << FRAC_BITS;
pll_freq = dec * (ref_clk * 2);
tmp64 = (ref_clk * 2 * frac);
pll_freq = dec * ref_clk;
tmp64 = ref_clk * frac;
pll_freq += div_u64(tmp64, multiplier);
vco_rate = pll_freq;
pll_10nm->vco_current_rate = vco_rate;
DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",
pll_10nm->phy->id, (unsigned long)vco_rate, dec, frac);

View file

@ -83,6 +83,12 @@ static struct devfreq_dev_profile msm_devfreq_profile = {
static void msm_devfreq_boost_work(struct kthread_work *work);
static void msm_devfreq_idle_work(struct kthread_work *work);
static bool has_devfreq(struct msm_gpu *gpu)
{
struct msm_gpu_devfreq *df = &gpu->devfreq;
return !!df->devfreq;
}
void msm_devfreq_init(struct msm_gpu *gpu)
{
struct msm_gpu_devfreq *df = &gpu->devfreq;
@ -149,6 +155,9 @@ void msm_devfreq_cleanup(struct msm_gpu *gpu)
{
struct msm_gpu_devfreq *df = &gpu->devfreq;
if (!has_devfreq(gpu))
return;
devfreq_cooling_unregister(gpu->cooling);
dev_pm_qos_remove_request(&df->boost_freq);
dev_pm_qos_remove_request(&df->idle_freq);
@ -156,16 +165,24 @@ void msm_devfreq_cleanup(struct msm_gpu *gpu)
void msm_devfreq_resume(struct msm_gpu *gpu)
{
gpu->devfreq.busy_cycles = 0;
gpu->devfreq.time = ktime_get();
struct msm_gpu_devfreq *df = &gpu->devfreq;
devfreq_resume_device(gpu->devfreq.devfreq);
if (!has_devfreq(gpu))
return;
df->busy_cycles = 0;
df->time = ktime_get();
devfreq_resume_device(df->devfreq);
}
void msm_devfreq_suspend(struct msm_gpu *gpu)
{
struct msm_gpu_devfreq *df = &gpu->devfreq;
if (!has_devfreq(gpu))
return;
devfreq_suspend_device(df->devfreq);
cancel_idle_work(df);
@ -185,6 +202,9 @@ void msm_devfreq_boost(struct msm_gpu *gpu, unsigned factor)
struct msm_gpu_devfreq *df = &gpu->devfreq;
uint64_t freq;
if (!has_devfreq(gpu))
return;
freq = get_freq(gpu);
freq *= factor;
@ -207,7 +227,7 @@ void msm_devfreq_active(struct msm_gpu *gpu)
struct devfreq_dev_status status;
unsigned int idle_time;
if (!df->devfreq)
if (!has_devfreq(gpu))
return;
/*
@ -253,7 +273,7 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
{
struct msm_gpu_devfreq *df = &gpu->devfreq;
if (!df->devfreq)
if (!has_devfreq(gpu))
return;
msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1),

View file

@ -449,6 +449,36 @@ config DRM_PANEL_SAMSUNG_S6D27A1
This panel can be found in Samsung Galaxy Ace 2
GT-I8160 mobile phone.
config DRM_PANEL_SAMSUNG_S6E3FA5
tristate "Samsung S6E3FA5 DSI command mode panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
Say Y here if you want to enable support for Samsung S6E3FA5 AMOLED
command mode panel as found in OnePlus 5 (2017) devices. The panel has a
FHD (1080x1920) resolution and uses 24 bit RGB per pixel. It provides a
MIPI DSI interface to the host and has a built-in LED backlight.
To compile this driver as a module, choose M here: the module
will be called panel-samsung-s6e3fa5.
config DRM_PANEL_SAMSUNG_S6E3FC1
tristate "Samsung S6E3FC1 DSI command mode panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
Say Y here if you want to enable support for Samsung S6E3FC1 AMOLED
command mode panel as found in OnePlus 5T (2017) devices. The panel has a
FHD (1080x2160) resolution and uses 24 bit RGB per pixel. It provides a
MIPI DSI interface to the host and has a built-in LED backlight.
To compile this driver as a module, choose M here: the module
will be called panel-samsung-s6e3fc1.
config DRM_PANEL_SAMSUNG_S6E3HA2
tristate "Samsung S6E3HA2 DSI video mode panel"
depends on OF

View file

@ -44,6 +44,8 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D27A1) += panel-samsung-s6d27a1.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FA5) += panel-samsung-s6e3fa5.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FC1) += panel-samsung-s6e3fc1.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o

View file

@ -0,0 +1,351 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2021 Jami Kettunen <jami.kettunen@protonmail.com>
* Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/backlight.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
#include <drm/drm_connector.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
struct s6e3fa5 {
struct drm_panel panel;
enum drm_panel_orientation orientation;
struct mipi_dsi_device *dsi;
struct regulator *supply;
struct gpio_desc *reset_gpio;
bool prepared;
};
static inline struct s6e3fa5 *to_s6e3fa5_panel(struct drm_panel *panel)
{
return container_of(panel, struct s6e3fa5, panel);
}
#define dsi_dcs_write_seq(dsi, seq...) do { \
static const u8 d[] = { seq }; \
int ret; \
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
if (ret < 0) \
return ret; \
} while (0)
static void s6e3fa5_reset(struct s6e3fa5 *ctx)
{
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
usleep_range(2000, 3000);
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
usleep_range(2000, 3000);
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
usleep_range(2000, 3000);
}
static int s6e3fa5_on(struct s6e3fa5 *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
struct device *dev = &dsi->dev;
int ret;
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
if (ret < 0) {
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
return ret;
}
msleep(20);
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
if (ret < 0) {
dev_err(dev, "Failed to set tear on: %d\n", ret);
return ret;
}
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
dsi_dcs_write_seq(dsi, 0xb0, 0x04);
dsi_dcs_write_seq(dsi, 0xb4, 0x06, 0x0c, 0x12);
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
dsi_dcs_write_seq(dsi, 0xc3, 0x01);
dsi_dcs_write_seq(dsi, 0xb0, 0x18);
dsi_dcs_write_seq(dsi, 0xc3, 0x00);
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
ret = mipi_dsi_dcs_set_display_on(dsi);
if (ret < 0) {
dev_err(dev, "Failed to set display on: %d\n", ret);
return ret;
}
return 0;
}
static int s6e3fa5_off(struct s6e3fa5 *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
struct device *dev = &dsi->dev;
int ret;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0) {
dev_err(dev, "Failed to set display off: %d\n", ret);
return ret;
}
msleep(40);
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
if (ret < 0) {
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
return ret;
}
msleep(160);
return 0;
}
static int s6e3fa5_prepare(struct drm_panel *panel)
{
struct s6e3fa5 *ctx = to_s6e3fa5_panel(panel);
struct device *dev = &ctx->dsi->dev;
int ret;
if (ctx->prepared)
return 0;
ret = regulator_enable(ctx->supply);
if (ret < 0) {
dev_err(dev, "Failed to enable regulator: %d\n", ret);
return ret;
}
s6e3fa5_reset(ctx);
ret = s6e3fa5_on(ctx);
if (ret < 0) {
dev_err(dev, "Failed to initialize panel: %d\n", ret);
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
regulator_disable(ctx->supply);
return ret;
}
ctx->prepared = true;
return 0;
}
static int s6e3fa5_unprepare(struct drm_panel *panel)
{
struct s6e3fa5 *ctx = to_s6e3fa5_panel(panel);
struct device *dev = &ctx->dsi->dev;
int ret;
if (!ctx->prepared)
return 0;
ret = s6e3fa5_off(ctx);
if (ret < 0)
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
regulator_disable(ctx->supply);
ctx->prepared = false;
return 0;
}
static const struct drm_display_mode s6e3fa5_mode = {
.clock = (1080 + 120 + 19 + 70) * (1920 + 18 + 2 + 4) * 60 / 1000,
.hdisplay = 1080,
.hsync_start = 1080 + 120,
.hsync_end = 1080 + 120 + 19,
.htotal = 1080 + 120 + 19 + 70,
.vdisplay = 1920,
.vsync_start = 1920 + 18,
.vsync_end = 1920 + 18 + 2,
.vtotal = 1920 + 18 + 2 + 4,
.width_mm = 68,
.height_mm = 122,
};
static int s6e3fa5_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
struct drm_display_mode *mode;
struct s6e3fa5 *ctx;
mode = drm_mode_duplicate(connector->dev, &s6e3fa5_mode);
if (!mode)
return -ENOMEM;
ctx = to_s6e3fa5_panel(panel);
drm_mode_set_name(mode);
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
connector->display_info.width_mm = mode->width_mm;
connector->display_info.height_mm = mode->height_mm;
drm_connector_set_panel_orientation(connector, ctx->orientation);
drm_mode_probed_add(connector, mode);
return 1;
}
static const struct drm_panel_funcs s6e3fa5_panel_funcs = {
.prepare = s6e3fa5_prepare,
.unprepare = s6e3fa5_unprepare,
.get_modes = s6e3fa5_get_modes,
};
static int s6e3fa5_bl_update_status(struct backlight_device *bl)
{
struct mipi_dsi_device *dsi = bl_get_data(bl);
u16 brightness = backlight_get_brightness(bl);
int ret;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
if (ret < 0)
return ret;
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
return 0;
}
static int s6e3fa5_bl_get_brightness(struct backlight_device *bl)
{
struct mipi_dsi_device *dsi = bl_get_data(bl);
u16 brightness;
int ret;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
if (ret < 0)
return ret;
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
return brightness & 0xff;
}
static const struct backlight_ops s6e3fa5_bl_ops = {
.update_status = s6e3fa5_bl_update_status,
.get_brightness = s6e3fa5_bl_get_brightness,
};
static struct backlight_device *
s6e3fa5_create_backlight(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
const struct backlight_properties props = {
.type = BACKLIGHT_RAW,
.brightness = 255,
.max_brightness = 255,
};
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
&s6e3fa5_bl_ops, &props);
}
static int s6e3fa5_probe(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
struct s6e3fa5 *ctx;
int ret;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->supply = devm_regulator_get(dev, "vddio");
if (IS_ERR(ctx->supply))
return dev_err_probe(dev, PTR_ERR(ctx->supply),
"Failed to get vddio regulator\n");
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ctx->reset_gpio))
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
"Failed to get reset-gpios\n");
ctx->dsi = dsi;
mipi_dsi_set_drvdata(dsi, ctx);
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_HSE |
MIPI_DSI_MODE_NO_EOT_PACKET |
MIPI_DSI_CLOCK_NON_CONTINUOUS;
ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
if (ret < 0) {
dev_err(dev, "Failed to parse rotation property: %d\n", ret);
return ret;
}
drm_panel_init(&ctx->panel, dev, &s6e3fa5_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
ctx->panel.backlight = s6e3fa5_create_backlight(dsi);
if (IS_ERR(ctx->panel.backlight))
return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
"Failed to create backlight\n");
drm_panel_add(&ctx->panel);
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
drm_panel_remove(&ctx->panel);
return ret;
}
return 0;
}
static int s6e3fa5_remove(struct mipi_dsi_device *dsi)
{
struct s6e3fa5 *ctx = mipi_dsi_get_drvdata(dsi);
int ret;
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
drm_panel_remove(&ctx->panel);
return 0;
}
static const struct of_device_id s6e3fa5_of_match[] = {
{ .compatible = "samsung,s6e3fa5" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, s6e3fa5_of_match);
static struct mipi_dsi_driver s6e3fa5_driver = {
.probe = s6e3fa5_probe,
.remove = s6e3fa5_remove,
.driver = {
.name = "panel-samsung-s6e3fa5",
.of_match_table = s6e3fa5_of_match,
},
};
module_mipi_dsi_driver(s6e3fa5_driver);
MODULE_AUTHOR("Jami Kettunen <jami.kettunen@protonmail.com>");
MODULE_DESCRIPTION("DRM driver for Samsung S6E3FA5 AMOLED DSI cmd mode panel found on OnePlus 5 phones");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,345 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2021 Jami Kettunen <jami.kettunen@protonmail.com>
* Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/backlight.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/swab.h>
#include <video/mipi_display.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
struct s6e3fc1 {
struct drm_panel panel;
struct mipi_dsi_device *dsi;
struct regulator *supply;
struct gpio_desc *reset_gpio;
bool prepared;
};
static inline struct s6e3fc1 *to_s6e3fc1_panel(struct drm_panel *panel)
{
return container_of(panel, struct s6e3fc1, panel);
}
#define dsi_dcs_write_seq(dsi, seq...) do { \
static const u8 d[] = { seq }; \
int ret; \
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
if (ret < 0) \
return ret; \
} while (0)
static void s6e3fc1_reset(struct s6e3fc1 *ctx)
{
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
usleep_range(2000, 3000);
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
usleep_range(2000, 3000);
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
usleep_range(2000, 3000);
}
static int s6e3fc1_on(struct s6e3fc1 *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
struct device *dev = &dsi->dev;
int ret;
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
if (ret < 0) {
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
return ret;
}
msleep(25);
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
if (ret < 0) {
dev_err(dev, "Failed to set tear on: %d\n", ret);
return ret;
}
dsi_dcs_write_seq(dsi, 0xfc, 0x5a, 0x5a);
dsi_dcs_write_seq(dsi, 0xe8, 0x64, 0x08, 0x0c);
dsi_dcs_write_seq(dsi, 0xfc, 0xa5, 0xa5);
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
dsi_dcs_write_seq(dsi, 0xb0, 0x01);
dsi_dcs_write_seq(dsi, 0xed, 0x04);
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
ret = mipi_dsi_dcs_set_display_on(dsi);
if (ret < 0) {
dev_err(dev, "Failed to set display on: %d\n", ret);
return ret;
}
return 0;
}
static int s6e3fc1_off(struct s6e3fc1 *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
struct device *dev = &dsi->dev;
int ret;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0) {
dev_err(dev, "Failed to set display off: %d\n", ret);
return ret;
}
usleep_range(10000, 11000);
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
if (ret < 0) {
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
return ret;
}
msleep(160);
return 0;
}
static int s6e3fc1_prepare(struct drm_panel *panel)
{
struct s6e3fc1 *ctx = to_s6e3fc1_panel(panel);
struct device *dev = &ctx->dsi->dev;
int ret;
if (ctx->prepared)
return 0;
ret = regulator_enable(ctx->supply);
if (ret < 0) {
dev_err(dev, "Failed to enable regulator: %d\n", ret);
return ret;
}
s6e3fc1_reset(ctx);
ret = s6e3fc1_on(ctx);
if (ret < 0) {
dev_err(dev, "Failed to initialize panel: %d\n", ret);
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
regulator_disable(ctx->supply);
return ret;
}
ctx->prepared = true;
return 0;
}
static int s6e3fc1_unprepare(struct drm_panel *panel)
{
struct s6e3fc1 *ctx = to_s6e3fc1_panel(panel);
struct device *dev = &ctx->dsi->dev;
int ret;
if (!ctx->prepared)
return 0;
ret = s6e3fc1_off(ctx);
if (ret < 0)
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
regulator_disable(ctx->supply);
ctx->prepared = false;
return 0;
}
static const struct drm_display_mode s6e3fc1_mode = {
.clock = (1080 + 128 + 16 + 64) * (2160 + 18 + 2 + 4) * 60 / 1000,
.hdisplay = 1080,
.hsync_start = 1080 + 128,
.hsync_end = 1080 + 128 + 16,
.htotal = 1080 + 128 + 16 + 64,
.vdisplay = 2160,
.vsync_start = 2160 + 18,
.vsync_end = 2160 + 18 + 2,
.vtotal = 2160 + 18 + 2 + 4,
.width_mm = 68,
.height_mm = 137,
};
static int s6e3fc1_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
struct drm_display_mode *mode;
mode = drm_mode_duplicate(connector->dev, &s6e3fc1_mode);
if (!mode)
return -ENOMEM;
drm_mode_set_name(mode);
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
connector->display_info.width_mm = mode->width_mm;
connector->display_info.height_mm = mode->height_mm;
drm_mode_probed_add(connector, mode);
return 1;
}
static const struct drm_panel_funcs s6e3fc1_panel_funcs = {
.prepare = s6e3fc1_prepare,
.unprepare = s6e3fc1_unprepare,
.get_modes = s6e3fc1_get_modes,
};
static int s6e3fc1_bl_update_status(struct backlight_device *bl)
{
struct mipi_dsi_device *dsi = bl_get_data(bl);
u16 brightness;
int ret;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
brightness = (u16)backlight_get_brightness(bl);
// This panel needs the high and low bytes swapped for the brightness value
brightness = __swab16(brightness);
ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
if (ret < 0)
return ret;
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
return 0;
}
static int s6e3fc1_bl_get_brightness(struct backlight_device *bl)
{
struct mipi_dsi_device *dsi = bl_get_data(bl);
u16 brightness;
int ret;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
if (ret < 0)
return ret;
// This panel needs the high and low bytes swapped for the brightness value
brightness = __swab16(brightness);
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
return brightness;
}
static const struct backlight_ops s6e3fc1_bl_ops = {
.update_status = s6e3fc1_bl_update_status,
.get_brightness = s6e3fc1_bl_get_brightness,
};
static struct backlight_device *
s6e3fc1_create_backlight(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
const struct backlight_properties props = {
.type = BACKLIGHT_RAW,
.brightness = 1023,
.max_brightness = 1023,
};
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
&s6e3fc1_bl_ops, &props);
}
static int s6e3fc1_probe(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
struct s6e3fc1 *ctx;
int ret;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->supply = devm_regulator_get(dev, "vddio");
if (IS_ERR(ctx->supply))
return dev_err_probe(dev, PTR_ERR(ctx->supply),
"Failed to get vddio regulator\n");
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ctx->reset_gpio))
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
"Failed to get reset-gpios\n");
ctx->dsi = dsi;
mipi_dsi_set_drvdata(dsi, ctx);
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_HSE |
MIPI_DSI_CLOCK_NON_CONTINUOUS;
drm_panel_init(&ctx->panel, dev, &s6e3fc1_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
ctx->panel.backlight = s6e3fc1_create_backlight(dsi);
if (IS_ERR(ctx->panel.backlight))
return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
"Failed to create backlight\n");
drm_panel_add(&ctx->panel);
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
drm_panel_remove(&ctx->panel);
return ret;
}
return 0;
}
static int s6e3fc1_remove(struct mipi_dsi_device *dsi)
{
struct s6e3fc1 *ctx = mipi_dsi_get_drvdata(dsi);
int ret;
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
drm_panel_remove(&ctx->panel);
return 0;
}
static const struct of_device_id s6e3fc1_of_match[] = {
{ .compatible = "samsung,s6e3fc1" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, s6e3fc1_of_match);
static struct mipi_dsi_driver s6e3fc1_driver = {
.probe = s6e3fc1_probe,
.remove = s6e3fc1_remove,
.driver = {
.name = "panel-samsung-s6e3fc1",
.of_match_table = s6e3fc1_of_match,
},
};
module_mipi_dsi_driver(s6e3fc1_driver);
MODULE_AUTHOR("Jami Kettunen <jami.kettunen@protonmail.com>");
MODULE_DESCRIPTION("DRM driver for Samsung S6E3FC1 AMOLED DSI cmd mode panel found on OnePlus 5T phones");
MODULE_LICENSE("GPL v2");

View file

@ -248,6 +248,9 @@ void virtio_gpu_array_put_free(struct virtio_gpu_object_array *objs)
{
u32 i;
if (!objs)
return;
for (i = 0; i < objs->nents; i++)
drm_gem_object_put(objs->objs[i]);
virtio_gpu_array_free(objs);

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

@ -242,6 +242,19 @@ config KEYBOARD_GPIO
To compile this driver as a module, choose M here: the
module will be called gpio_keys.
config KEYBOARD_GPIO_FASTMATRIX
tristate "GPIO Keyboard"
depends on GPIOLIB
select INPUT_MATRIXKMAP
help
This driver implements support for matrix keypads and/or
keyboards connected directly to GPIO pins of a CPU, made
to also perform with slow I2C GPIO expanders and even
on matrices with no protection diodes.
To compile this driver as a module, choose M here: the
module will be called gpio_fastmatrix
config KEYBOARD_GPIO_POLLED
tristate "Polled GPIO buttons"
depends on GPIOLIB

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,18 @@ config INPUT_PMIC8XXX_PWRKEY
To compile this driver as a module, choose M here: the
module will be called pmic8xxx-pwrkey.
config INPUT_QCOM_SPMI_HAPTICS
tristate "Qualcomm SPMI HAPTICS"
depends on ARCH_QCOM
depends on SPMI
select INPUT_FF_MEMLESS
help
This option enables support for the haptics found in pmi8998 and
related PMICs. Based on the ff-memless interface.
To compile this driver as module, choose M here: the
module will be called qcom_spmi_haptics.
config INPUT_SPARCSPKR
tristate "SPARC Speaker support"
depends on PCI && SPARC64

View file

@ -64,6 +64,7 @@ obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
obj-$(CONFIG_INPUT_PWM_VIBRA) += pwm-vibra.o
obj-$(CONFIG_INPUT_QCOM_SPMI_HAPTICS) += qcom-spmi-haptics.o
obj-$(CONFIG_INPUT_RAVE_SP_PWRBUTTON) += rave-sp-pwrbutton.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o

View file

@ -0,0 +1,977 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021, Caleb Connolly <caleb@connolly.tech>
* Qualcomm QPMI haptics driver for pmi8998 and related PMICs.
*/
#include <dt-bindings/input/qcom,spmi-haptics.h>
#include <linux/atomic.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/types.h>
#define HAP_STATUS_1_REG 0x0A
#define HAP_BUSY_BIT BIT(1)
#define SC_FLAG_BIT BIT(3)
#define AUTO_RES_ERROR_BIT BIT(4)
#define HAP_LRA_AUTO_RES_LO_REG 0x0B
#define HAP_LRA_AUTO_RES_HI_REG 0x0C
#define HAP_EN_CTL_REG 0x46
#define HAP_EN_BIT BIT(7)
#define HAP_EN_CTL2_REG 0x48
#define BRAKE_EN_BIT BIT(0)
#define HAP_AUTO_RES_CTRL_REG 0x4B
#define AUTO_RES_EN_BIT BIT(7)
#define AUTO_RES_ERR_RECOVERY_BIT BIT(3)
#define AUTO_RES_EN_FLAG_BIT BIT(0)
#define HAP_CFG1_REG 0x4C
#define HAP_ACT_TYPE_MASK BIT(0)
#define HAP_CFG2_REG 0x4D
#define HAP_LRA_RES_TYPE_MASK BIT(0)
#define HAP_SEL_REG 0x4E
#define HAP_WF_SOURCE_MASK GENMASK(5, 4)
#define HAP_WF_SOURCE_SHIFT 4
#define HAP_LRA_AUTO_RES_REG 0x4F
#define LRA_AUTO_RES_MODE_MASK GENMASK(6, 4)
#define LRA_AUTO_RES_MODE_SHIFT 4
#define LRA_HIGH_Z_MASK GENMASK(3, 2)
#define LRA_HIGH_Z_SHIFT 2
#define LRA_RES_CAL_MASK GENMASK(1, 0)
#define HAP_RES_CAL_PERIOD_MIN 4
#define HAP_RES_CAL_PERIOD_MAX 32
#define HAP_VMAX_CFG_REG 0x51
#define HAP_VMAX_OVD_BIT BIT(6)
#define HAP_VMAX_MASK GENMASK(5, 1)
#define HAP_VMAX_SHIFT 1
#define HAP_ILIM_CFG_REG 0x52
#define HAP_ILIM_SEL_MASK BIT(0)
#define HAP_ILIM_400_MA 0
#define HAP_ILIM_800_MA 1
#define HAP_SC_DEB_REG 0x53
#define HAP_SC_DEB_MASK GENMASK(2, 0)
#define HAP_SC_DEB_CYCLES_MIN 0
#define HAP_DEF_SC_DEB_CYCLES 8
#define HAP_SC_DEB_CYCLES_MAX 32
#define HAP_RATE_CFG1_REG 0x54
#define HAP_RATE_CFG1_MASK GENMASK(7, 0)
#define HAP_RATE_CFG2_SHIFT 8
#define HAP_RATE_CFG2_REG 0x55
#define HAP_RATE_CFG2_MASK GENMASK(3, 0)
#define HAP_SC_CLR_REG 0x59
#define SC_CLR_BIT BIT(0)
#define HAP_BRAKE_REG 0x5C
#define HAP_BRAKE_PAT_MASK 0x3
#define HAP_WF_REPEAT_REG 0x5E
#define WF_REPEAT_MASK GENMASK(6, 4)
#define WF_REPEAT_SHIFT 4
#define WF_REPEAT_MIN 1
#define WF_REPEAT_MAX 128
#define WF_S_REPEAT_MASK GENMASK(1, 0)
#define WF_S_REPEAT_MIN 1
#define WF_S_REPEAT_MAX 8
#define HAP_WF_S1_REG 0x60
#define HAP_WF_SIGN_BIT BIT(7)
#define HAP_WF_OVD_BIT BIT(6)
#define HAP_WF_SAMP_MAX GENMASK(5, 1)
#define HAP_WF_SAMPLE_LEN 8
#define HAP_PLAY_REG 0x70
#define HAP_PLAY_BIT BIT(7)
#define HAP_PAUSE_BIT BIT(0)
#define HAP_SEC_ACCESS_REG 0xD0
#define HAP_SEC_ACCESS_UNLOCK 0xA5
#define HAP_TEST2_REG 0xE3
#define HAP_VMAX_MIN_MV 116
#define HAP_VMAX_MAX_MV 3596
#define HAP_VMAX_MAX_MV_STRONG 3596
#define HAP_WAVE_PLAY_RATE_MIN_US 0
#define HAP_WAVE_PLAY_RATE_MAX_US 20475
#define HAP_WAVE_PLAY_TIME_MAX_MS 15000
#define AUTO_RES_ERR_POLL_TIME_NS (20 * NSEC_PER_MSEC)
#define HAPTICS_BACK_EMF_DELAY_US 20000
#define HAP_BRAKE_PAT_LEN 4
#define HAP_WAVE_SAMP_LEN 8
#define NUM_WF_SET 4
#define HAP_WAVE_SAMP_SET_LEN (HAP_WAVE_SAMP_LEN * NUM_WF_SET)
#define HAP_RATE_CFG_STEP_US 5
#define SC_MAX_COUNT 5
#define SC_COUNT_RST_DELAY_US 1000000
enum hap_play_control {
HAP_STOP,
HAP_PAUSE,
HAP_PLAY,
};
/**
* struct spmi_haptics - struct for spmi haptics data.
*
* @dev: Our device parent.
* @regmap: Register map for the hardware block.
* @haptics_input_dev: The input device used to receive events.
* @work: Work struct to play effects.
* @base: Base address of the regmap.
* @active: Atomic value used to track if haptics are currently playing.
* @play_irq: Fired to load the next wave pattern.
* @sc_irq: Short circuit irq.
* @last_sc_time: Time since the short circuit IRQ last fired.
* @sc_count: Number of times the short circuit IRQ has fired in this interval.
* @actuator_type: The type of actuator in use.
* @wave_shape: The shape of the waves to use (sine or square).
* @play_mode: The play mode to use (direct, buffer, pwm, audio).
* @magnitude: The strength we should be playing at.
* @vmax: Max voltage to use when playing.
* @current_limit: The current limit for this hardware (400mA or 800mA).
* @play_wave_rate: The wave rate to use for this hardware.
* @wave_samp: The array of wave samples to write for buffer mode.
* @brake_pat: The pattern to apply when braking.
* @play_lock: Lock to be held when updating the hardware state.
*/
struct spmi_haptics {
struct device *dev;
struct regmap *regmap;
struct input_dev *haptics_input_dev;
struct work_struct work;
u32 base;
atomic_t active;
int play_irq;
int sc_irq;
ktime_t last_sc_time;
u8 sc_count;
u8 actuator_type;
u8 wave_shape;
u8 play_mode;
int magnitude;
u32 vmax;
u32 current_limit;
u32 play_wave_rate;
u32 wave_samp[HAP_WAVE_SAMP_SET_LEN];
u8 brake_pat[HAP_BRAKE_PAT_LEN];
struct mutex play_lock;
};
static inline bool is_secure_addr(u16 addr)
{
return (addr & 0xFF) > 0xD0;
}
static int spmi_haptics_read(struct spmi_haptics *haptics,
u16 addr, u8 *val, int len)
{
int ret;
ret = regmap_bulk_read(haptics->regmap, addr, val, len);
if (ret < 0)
dev_err(haptics->dev, "Error reading address: 0x%x, ret %d\n", addr, ret);
return ret;
}
static int spmi_haptics_write(struct spmi_haptics *haptics,
u16 addr, u8 *val, int len)
{
int ret, i;
if (is_secure_addr(addr)) {
for (i = 0; i < len; i++) {
dev_dbg(haptics->dev, "%s: unlocking for addr: 0x%x, val: 0x%x", __func__,
addr, val[i]);
ret = regmap_write(haptics->regmap,
haptics->base + HAP_SEC_ACCESS_REG, HAP_SEC_ACCESS_UNLOCK);
if (ret < 0) {
dev_err(haptics->dev, "Error writing unlock code, ret %d\n",
ret);
return ret;
}
ret = regmap_write(haptics->regmap, addr + i, val[i]);
if (ret < 0) {
dev_err(haptics->dev, "Error writing address 0x%x, ret %d\n",
addr + i, ret);
return ret;
}
}
} else {
if (len > 1)
ret = regmap_bulk_write(haptics->regmap, addr, val, len);
else
ret = regmap_write(haptics->regmap, addr, *val);
}
if (ret < 0)
dev_err(haptics->dev, "%s: Error writing address: 0x%x, ret %d\n",
__func__, addr, ret);
return ret;
}
static int spmi_haptics_write_masked(struct spmi_haptics *haptics,
u16 addr, u8 mask, u8 val)
{
int ret;
if (is_secure_addr(addr)) {
ret = regmap_write(haptics->regmap,
haptics->base + HAP_SEC_ACCESS_REG, HAP_SEC_ACCESS_UNLOCK);
if (ret < 0) {
dev_err(haptics->dev, "Error writing unlock code - ret %d\n", ret);
return ret;
}
}
ret = regmap_update_bits(haptics->regmap, addr, mask, val);
if (ret < 0)
dev_err(haptics->dev, "Error writing address: 0x%x - ret %d\n", addr, ret);
return ret;
}
static bool is_haptics_idle(struct spmi_haptics *haptics)
{
int ret;
u8 val;
if (haptics->play_mode == HAP_PLAY_DIRECT ||
haptics->play_mode == HAP_PLAY_PWM)
return true;
ret = spmi_haptics_read(haptics, haptics->base + HAP_STATUS_1_REG, &val, 1);
if (ret < 0 || (val & HAP_BUSY_BIT))
return false;
return true;
}
static int spmi_haptics_module_enable(struct spmi_haptics *haptics, bool enable)
{
u8 val;
dev_dbg(haptics->dev, "Setting module enable: %d", enable);
val = enable ? HAP_EN_BIT : 0;
return spmi_haptics_write(haptics, haptics->base + HAP_EN_CTL_REG, &val, 1);
}
static int spmi_haptics_write_vmax(struct spmi_haptics *haptics)
{
u8 val = 0;
u32 vmax_mv = haptics->vmax;
vmax_mv = clamp_t(u32, vmax_mv, HAP_VMAX_MIN_MV, HAP_VMAX_MAX_MV);
dev_dbg(haptics->dev, "Setting vmax to: %d", vmax_mv);
val = DIV_ROUND_CLOSEST(vmax_mv, HAP_VMAX_MIN_MV);
val = FIELD_PREP(HAP_VMAX_MASK, val);
// TODO: pm660 can enable overdrive here
return spmi_haptics_write_masked(haptics, haptics->base + HAP_VMAX_CFG_REG,
HAP_VMAX_MASK | HAP_WF_OVD_BIT, val);
}
static int spmi_haptics_write_current_limit(struct spmi_haptics *haptics)
{
haptics->current_limit = clamp_t(u32, haptics->current_limit,
HAP_ILIM_400_MA, HAP_ILIM_800_MA);
dev_dbg(haptics->dev, "Setting current_limit to: 0x%x", haptics->current_limit);
return spmi_haptics_write_masked(haptics, haptics->base + HAP_ILIM_CFG_REG,
HAP_ILIM_SEL_MASK, haptics->current_limit);
}
static int spmi_haptics_write_play_mode(struct spmi_haptics *haptics)
{
u8 val = 0;
if (!is_haptics_idle(haptics))
return -EBUSY;
dev_dbg(haptics->dev, "Setting play_mode to: 0x%x", haptics->play_mode);
val = FIELD_PREP(HAP_WF_SOURCE_MASK, haptics->play_mode);
return spmi_haptics_write_masked(haptics, haptics->base + HAP_SEL_REG,
HAP_WF_SOURCE_MASK, val);
}
static int spmi_haptics_write_play_rate(struct spmi_haptics *haptics, u16 play_rate)
{
u8 val[2];
dev_dbg(haptics->dev, "Setting play_rate to: %d", play_rate);
val[0] = FIELD_PREP(HAP_RATE_CFG1_MASK, play_rate);
val[1] = FIELD_PREP(HAP_RATE_CFG2_MASK, play_rate >> HAP_RATE_CFG2_SHIFT);
return spmi_haptics_write(haptics, haptics->base + HAP_RATE_CFG1_REG, val, 2);
}
/*
* spmi_haptics_set_auto_res() - Auto resonance
* allows the haptics to automatically adjust the
* speed of the oscillation in order to maintain
* the resonant frequency.
*/
static int spmi_haptics_set_auto_res(struct spmi_haptics *haptics, bool enable)
{
u8 val;
// LRAs are the only type to support auto res
if (haptics->actuator_type != HAP_TYPE_LRA)
return 0;
val = enable ? AUTO_RES_EN_BIT : 0;
return spmi_haptics_write_masked(haptics, haptics->base + HAP_TEST2_REG,
AUTO_RES_EN_BIT, val);
}
static int spmi_haptics_write_brake(struct spmi_haptics *haptics)
{
int ret, i;
u8 val;
dev_dbg(haptics->dev, "Configuring brake pattern");
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_EN_CTL2_REG,
BRAKE_EN_BIT, 1);
if (ret < 0)
return ret;
for (i = HAP_BRAKE_PAT_LEN - 1, val = 0; i >= 0; i--) {
u8 p = haptics->brake_pat[i] & HAP_BRAKE_PAT_MASK;
val |= p << (i * 2);
}
return spmi_haptics_write(haptics, haptics->base + HAP_BRAKE_REG, &val, 1);
}
static int spmi_haptics_write_buffer_config(struct spmi_haptics *haptics)
{
u8 buf[HAP_WAVE_SAMP_LEN];
int i;
dev_dbg(haptics->dev, "Writing buffer config");
for (i = 0; i < HAP_WAVE_SAMP_LEN; i++)
buf[i] = haptics->wave_samp[i];
return spmi_haptics_write(haptics, haptics->base + HAP_WF_S1_REG, buf,
HAP_WAVE_SAMP_LEN);
}
static int spmi_haptics_write_wave_repeat(struct spmi_haptics *haptics)
{
u8 val, mask;
/* The number of times to repeat each wave */
mask = WF_REPEAT_MASK | WF_S_REPEAT_MASK;
val = FIELD_PREP(WF_REPEAT_MASK, 0) |
FIELD_PREP(WF_S_REPEAT_MASK, 0);
return spmi_haptics_write_masked(haptics, haptics->base + HAP_WF_REPEAT_REG,
mask, val);
}
static int spmi_haptics_write_play_control(struct spmi_haptics *haptics,
enum hap_play_control ctrl)
{
u8 val;
switch (ctrl) {
case HAP_STOP:
val = 0;
break;
case HAP_PAUSE:
val = HAP_PAUSE_BIT;
break;
case HAP_PLAY:
val = HAP_PLAY_BIT;
break;
default:
return 0;
}
dev_dbg(haptics->dev, "haptics play ctrl: %d\n", ctrl);
return spmi_haptics_write(haptics, haptics->base + HAP_PLAY_REG, &val, 1);
}
/*
* This IRQ is fired to tell us to load the next wave sample set.
* As we only currently support a single sample set, it's unused.
*/
static irqreturn_t spmi_haptics_play_irq_handler(int irq, void *data)
{
struct spmi_haptics *haptics = data;
dev_dbg(haptics->dev, "play_irq triggered");
return IRQ_HANDLED;
}
/**
* spmi_haptics_sc_irq_handler() - short circuit irq handler
* Fires every ~50ms whilst the haptics are active.
* If the SC_FLAG_BIT is set then that means there isn't a short circuit
* and we just need to clear the IRQ to indicate that the device should
* keep vibrating.
*
* Otherwise, it means a short circuit situation has occurred.
*
* @irq: irq number
* @data: haptics data
* Returns: IRQ_HANDLED
*/
static irqreturn_t spmi_haptics_sc_irq_handler(int irq, void *data)
{
struct spmi_haptics *haptics = data;
int ret;
u8 val;
s64 sc_delta_time_us;
ktime_t temp;
ret = spmi_haptics_read(haptics, haptics->base + HAP_STATUS_1_REG, &val, 1);
if (ret < 0)
return IRQ_HANDLED;
if (!(val & SC_FLAG_BIT)) {
haptics->sc_count = 0;
return IRQ_HANDLED;
}
temp = ktime_get();
sc_delta_time_us = ktime_us_delta(temp, haptics->last_sc_time);
haptics->last_sc_time = temp;
if (sc_delta_time_us > SC_COUNT_RST_DELAY_US)
haptics->sc_count = 0;
else
haptics->sc_count++;
// Clear the interrupt flag
val = SC_CLR_BIT;
ret = spmi_haptics_write(haptics, haptics->base + HAP_SC_CLR_REG, &val, 1);
if (ret < 0)
return IRQ_HANDLED;
if (haptics->sc_count > SC_MAX_COUNT) {
dev_err(haptics->dev, "Short circuit persists, disabling haptics\n");
ret = spmi_haptics_module_enable(haptics, false);
if (ret < 0)
dev_err(haptics->dev, "Error disabling module, rc=%d\n", ret);
}
return IRQ_HANDLED;
}
/**
* spmi_haptics_init() - Initialise haptics hardware for use
* @haptics: haptics device
* Returns: 0 on success, < 0 on error
*/
static int spmi_haptics_init(struct spmi_haptics *haptics)
{
int ret;
u8 val, mask;
u16 play_rate;
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_CFG1_REG,
HAP_ACT_TYPE_MASK, haptics->actuator_type);
if (ret < 0)
return ret;
/*
* Configure auto resonance
* see spmi_haptics_lra_auto_res_config downstream
* This is greatly simplified.
*/
val = FIELD_PREP(LRA_RES_CAL_MASK, ilog2(32 / HAP_RES_CAL_PERIOD_MIN)) |
FIELD_PREP(LRA_AUTO_RES_MODE_MASK, HAP_AUTO_RES_ZXD_EOP) |
FIELD_PREP(LRA_HIGH_Z_MASK, 1);
mask = LRA_AUTO_RES_MODE_MASK | LRA_HIGH_Z_MASK | LRA_RES_CAL_MASK;
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_LRA_AUTO_RES_REG,
mask, val);
/* Configure the PLAY MODE register */
ret = spmi_haptics_write_play_mode(haptics);
if (ret < 0)
return ret;
ret = spmi_haptics_write_vmax(haptics);
if (ret < 0)
return ret;
/* Configure the ILIM register */
ret = spmi_haptics_write_current_limit(haptics);
if (ret < 0)
return ret;
// Configure the debounce for short-circuit detection.
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_SC_DEB_REG,
HAP_SC_DEB_MASK, HAP_SC_DEB_CYCLES_MAX);
if (ret < 0)
return ret;
// write the wave shape
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_CFG2_REG,
HAP_LRA_RES_TYPE_MASK, haptics->wave_shape);
if (ret < 0)
return ret;
play_rate = haptics->play_wave_rate / HAP_RATE_CFG_STEP_US;
/*
* Configure RATE_CFG1 and RATE_CFG2 registers.
* Note: For ERM these registers act as play rate and
* for LRA these represent resonance period
*/
ret = spmi_haptics_write_play_rate(haptics, play_rate);
if (ret < 0)
return ret;
ret = spmi_haptics_write_brake(haptics);
if (ret < 0)
return ret;
if (haptics->play_mode == HAP_PLAY_BUFFER) {
ret = spmi_haptics_write_wave_repeat(haptics);
if (ret < 0)
return ret;
ret = spmi_haptics_write_buffer_config(haptics);
if (ret < 0)
return ret;
}
dev_dbg(haptics->dev, "%s: Requesting play IRQ, irq: %d", __func__,
haptics->play_irq);
ret = devm_request_threaded_irq(haptics->dev, haptics->play_irq,
NULL, spmi_haptics_play_irq_handler, IRQF_ONESHOT,
"haptics_play_irq", haptics);
if (ret < 0) {
dev_err(haptics->dev, "Unable to request play IRQ ret=%d\n", ret);
return ret;
}
/* use play_irq only for buffer mode */
if (haptics->play_mode != HAP_PLAY_BUFFER)
disable_irq(haptics->play_irq);
dev_dbg(haptics->dev, "%s: Requesting play IRQ, irq: %d", __func__,
haptics->play_irq);
ret = devm_request_threaded_irq(haptics->dev, haptics->sc_irq,
NULL, spmi_haptics_sc_irq_handler, IRQF_ONESHOT,
"haptics_sc_irq", haptics);
if (ret < 0) {
dev_err(haptics->dev, "Unable to request sc IRQ ret=%d\n", ret);
return ret;
}
return 0;
}
/**
* spmi_haptics_enable - handler to start/stop vibration
* @haptics: pointer to haptics struct
* Returns: 0 on success, < 0 on failure
*/
static int spmi_haptics_enable(struct spmi_haptics *haptics)
{
int ret;
mutex_lock(&haptics->play_lock);
if (haptics->sc_count > SC_MAX_COUNT) {
dev_err(haptics->dev, "Can't play while in short circuit");
ret = -1;
goto out;
}
ret = spmi_haptics_set_auto_res(haptics, false);
if (ret < 0) {
dev_err(haptics->dev, "Error disabling auto_res, ret=%d\n", ret);
goto out;
}
ret = spmi_haptics_module_enable(haptics, true);
if (ret < 0) {
dev_err(haptics->dev, "Error enabling module, ret=%d\n", ret);
goto out;
}
ret = spmi_haptics_write_play_control(haptics, HAP_PLAY);
if (ret < 0) {
dev_err(haptics->dev, "Error enabling play, ret=%d\n", ret);
goto out;
}
ret = spmi_haptics_set_auto_res(haptics, true);
if (ret < 0) {
dev_err(haptics->dev, "Error enabling auto_res, ret=%d\n", ret);
goto out;
}
out:
mutex_unlock(&haptics->play_lock);
return ret;
}
/**
* spmi_haptics_enable - handler to start/stop vibration
* @haptics: pointer to haptics struct
* Returns: 0 on success, < 0 on failure
*/
static int spmi_haptics_disable(struct spmi_haptics *haptics)
{
int ret;
mutex_lock(&haptics->play_lock);
ret = spmi_haptics_write_play_control(haptics, HAP_STOP);
if (ret < 0) {
dev_err(haptics->dev, "Error disabling play, ret=%d\n", ret);
goto out;
}
ret = spmi_haptics_module_enable(haptics, false);
if (ret < 0) {
dev_err(haptics->dev, "Error disabling module, ret=%d\n", ret);
goto out;
}
out:
mutex_unlock(&haptics->play_lock);
return ret;
}
/*
* Threaded function to update the haptics state.
*/
static void spmi_haptics_work(struct work_struct *work)
{
struct spmi_haptics *haptics = container_of(work, struct spmi_haptics, work);
int ret;
bool enable;
enable = atomic_read(&haptics->active);
dev_dbg(haptics->dev, "%s: state: %d\n", __func__, enable);
if (enable)
ret = spmi_haptics_enable(haptics);
else
ret = spmi_haptics_disable(haptics);
if (ret < 0)
dev_err(haptics->dev, "Error setting haptics, ret=%d", ret);
}
/**
* spmi_haptics_close - callback for input device close
* @dev: input device pointer
*
* Turns off the vibrator.
*/
static void spmi_haptics_close(struct input_dev *dev)
{
struct spmi_haptics *haptics = input_get_drvdata(dev);
cancel_work_sync(&haptics->work);
if (atomic_read(&haptics->active)) {
atomic_set(&haptics->active, 0);
schedule_work(&haptics->work);
}
}
/**
* spmi_haptics_play_effect - play haptics effects
* @dev: input device pointer
* @data: data of effect
* @effect: effect to play
*/
static int spmi_haptics_play_effect(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
struct spmi_haptics *haptics = input_get_drvdata(dev);
dev_dbg(haptics->dev, "%s: Rumbling with strong: %d and weak: %d", __func__,
effect->u.rumble.strong_magnitude, effect->u.rumble.weak_magnitude);
haptics->magnitude = effect->u.rumble.strong_magnitude >> 8;
if (!haptics->magnitude)
haptics->magnitude = effect->u.rumble.weak_magnitude >> 10;
if (!haptics->magnitude) {
atomic_set(&haptics->active, 0);
goto end;
}
atomic_set(&haptics->active, 1);
haptics->vmax = ((HAP_VMAX_MAX_MV - HAP_VMAX_MIN_MV) * haptics->magnitude) / 100 +
HAP_VMAX_MIN_MV;
dev_dbg(haptics->dev, "%s: magnitude: %d, vmax: %d", __func__,
haptics->magnitude, haptics->vmax);
spmi_haptics_write_vmax(haptics);
end:
schedule_work(&haptics->work);
return 0;
}
static int spmi_haptics_probe(struct platform_device *pdev)
{
struct spmi_haptics *haptics;
struct device_node *node;
struct input_dev *input_dev;
int ret;
u32 val;
int i;
haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
if (!haptics)
return -ENOMEM;
haptics->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!haptics->regmap)
return -ENODEV;
node = pdev->dev.of_node;
haptics->dev = &pdev->dev;
ret = of_property_read_u32(node, "reg", &haptics->base);
if (ret < 0) {
dev_err(haptics->dev, "Couldn't find reg in node = %s ret = %d\n",
node->full_name, ret);
return ret;
}
haptics->play_irq = platform_get_irq_byname(pdev, "play");
if (haptics->play_irq < 0) {
dev_err(&pdev->dev, "Unable to get play irq\n");
ret = haptics->play_irq;
goto register_fail;
}
haptics->sc_irq = platform_get_irq_byname(pdev, "short");
if (haptics->sc_irq < 0) {
dev_err(&pdev->dev, "Unable to get sc irq\n");
ret = haptics->sc_irq;
goto register_fail;
}
// We only support LRAs for now
haptics->actuator_type = HAP_TYPE_LRA;
ret = of_property_read_u32(node, "qcom,actuator-type", &val);
if (!ret) {
if (val != HAP_TYPE_LRA) {
dev_err(&pdev->dev, "qcom,actuator-type (%d) isn't supported\n", val);
ret = -EINVAL;
goto register_fail;
}
haptics->actuator_type = val;
}
// Only buffer mode is currently supported
haptics->play_mode = HAP_PLAY_BUFFER;
ret = of_property_read_u32(node, "qcom,play-mode", &val);
if (!ret) {
if (val != HAP_PLAY_BUFFER) {
dev_err(&pdev->dev, "qcom,play-mode (%d) isn't supported\n", val);
ret = -EINVAL;
goto register_fail;
}
haptics->play_mode = val;
}
ret = of_property_read_u32(node, "qcom,wave-play-rate-us", &val);
if (!ret) {
haptics->play_wave_rate = val;
} else if (ret != -EINVAL) {
dev_err(haptics->dev, "Unable to read play rate ret=%d\n", ret);
goto register_fail;
}
haptics->play_wave_rate =
clamp_t(u32, haptics->play_wave_rate,
HAP_WAVE_PLAY_RATE_MIN_US, HAP_WAVE_PLAY_RATE_MAX_US);
haptics->wave_shape = HAP_WAVE_SINE;
ret = of_property_read_u32(node, "qcom,wave-shape", &val);
if (!ret) {
if (val != HAP_WAVE_SINE && val != HAP_WAVE_SQUARE) {
dev_err(&pdev->dev, "qcom,wave-shape is invalid: %d\n", val);
ret = -EINVAL;
goto register_fail;
}
haptics->wave_shape = val;
}
haptics->brake_pat[0] = 0x3;
haptics->brake_pat[1] = 0x3;
haptics->brake_pat[2] = 0x2;
haptics->brake_pat[3] = 0x1;
ret = of_property_read_u8_array(node, "qcom,brake-pattern", haptics->brake_pat, 4);
if (ret < 0 && ret != -EINVAL) {
dev_err(&pdev->dev, "qcom,brake-pattern is invalid, ret = %d\n", ret);
goto register_fail;
}
haptics->current_limit = HAP_ILIM_400_MA;
for (i = 0; i < HAP_WAVE_SAMP_LEN; i++)
haptics->wave_samp[i] = HAP_WF_SAMP_MAX;
ret = spmi_haptics_init(haptics);
if (ret < 0) {
dev_err(&pdev->dev, "Error initialising haptics, ret=%d\n",
ret);
goto register_fail;
}
platform_set_drvdata(pdev, haptics);
input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev)
return -ENOMEM;
INIT_WORK(&haptics->work, spmi_haptics_work);
haptics->haptics_input_dev = input_dev;
input_dev->name = "spmi_haptics";
input_dev->id.version = 1;
input_dev->close = spmi_haptics_close;
input_set_drvdata(input_dev, haptics);
// Figure out how to make this FF_PERIODIC
input_set_capability(haptics->haptics_input_dev, EV_FF, FF_RUMBLE);
ret = input_ff_create_memless(input_dev, NULL,
spmi_haptics_play_effect);
if (ret) {
dev_err(&pdev->dev,
"couldn't register vibrator as FF device\n");
goto register_fail;
}
ret = input_register_device(input_dev);
if (ret) {
dev_err(&pdev->dev, "couldn't register input device\n");
goto register_fail;
}
return 0;
register_fail:
cancel_work_sync(&haptics->work);
mutex_destroy(&haptics->play_lock);
return ret;
}
static int __maybe_unused spmi_haptics_suspend(struct device *dev)
{
struct spmi_haptics *haptics = dev_get_drvdata(dev);
cancel_work_sync(&haptics->work);
spmi_haptics_disable(haptics);
return 0;
}
static SIMPLE_DEV_PM_OPS(spmi_haptics_pm_ops, spmi_haptics_suspend, NULL);
static int spmi_haptics_remove(struct platform_device *pdev)
{
struct spmi_haptics *haptics = dev_get_drvdata(&pdev->dev);
cancel_work_sync(&haptics->work);
mutex_destroy(&haptics->play_lock);
input_unregister_device(haptics->haptics_input_dev);
return 0;
}
static void spmi_haptics_shutdown(struct platform_device *pdev)
{
struct spmi_haptics *haptics = dev_get_drvdata(&pdev->dev);
cancel_work_sync(&haptics->work);
spmi_haptics_disable(haptics);
}
static const struct of_device_id spmi_haptics_match_table[] = {
{ .compatible = "qcom,spmi-haptics" },
{ }
};
MODULE_DEVICE_TABLE(of, spmi_haptics_match_table);
static struct platform_driver spmi_haptics_driver = {
.probe = spmi_haptics_probe,
.remove = spmi_haptics_remove,
.shutdown = spmi_haptics_shutdown,
.driver = {
.name = "spmi-haptics",
.pm = &spmi_haptics_pm_ops,
.of_match_table = spmi_haptics_match_table,
},
};
module_platform_driver(spmi_haptics_driver);
MODULE_DESCRIPTION("spmi haptics driver using ff-memless framework");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Caleb Connolly <caleb@connolly.tech>");

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

@ -5,6 +5,7 @@ qnoc-msm8916-objs := msm8916.o
qnoc-msm8939-objs := msm8939.o
qnoc-msm8974-objs := msm8974.o
qnoc-msm8996-objs := msm8996.o
qnoc-msm8998-objs := msm8998.o
icc-osm-l3-objs := osm-l3.o
qnoc-qcm2290-objs := qcm2290.o
qnoc-qcs404-objs := qcs404.o
@ -26,6 +27,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8939) += qnoc-msm8939.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8996) += qnoc-msm8996.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8998) += qnoc-msm8998.o
obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCM2290) += qnoc-qcm2290.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o

View file

@ -0,0 +1,981 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Qualcomm MSM8998 Network-on-Chip (NoC) QoS driver
* Copyright (c) 2020, AngeloGioacchino Del Regno
* <angelogioacchino.delregno@somainline.org>
* Copyright (C) 2020, Konrad Dybcio <konrad.dybcio@somainline.org>
*
*/
#include <dt-bindings/interconnect/qcom,msm8998.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interconnect-provider.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include "smd-rpm.h"
#define RPM_BUS_MASTER_REQ 0x73616d62
#define RPM_BUS_SLAVE_REQ 0x766c7362
/* BIMC QoS */
#define M_BKE_REG_BASE(n) (0x300 + (0x4000 * n))
#define M_BKE_EN_ADDR(n) (M_BKE_REG_BASE(n))
#define M_BKE_HEALTH_CFG_ADDR(i, n) (M_BKE_REG_BASE(n) + 0x40 + (0x4 * i))
#define M_BKE_HEALTH_CFG_LIMITCMDS_MASK 0x80000000
#define M_BKE_HEALTH_CFG_AREQPRIO_MASK 0x300
#define M_BKE_HEALTH_CFG_PRIOLVL_MASK 0x3
#define M_BKE_HEALTH_CFG_AREQPRIO_SHIFT 0x8
#define M_BKE_HEALTH_CFG_LIMITCMDS_SHIFT 0x1f
#define M_BKE_EN_EN_BMASK 0x1
/* Valid for both NoC and BIMC */
#define NOC_QOS_MODE_FIXED 0x0
#define NOC_QOS_MODE_LIMITER 0x1
#define NOC_QOS_MODE_BYPASS 0x2
/* NoC QoS */
#define NOC_PERM_MODE_FIXED 1
#define NOC_PERM_MODE_BYPASS (1 << NOC_QOS_MODE_BYPASS)
#define NOC_QOS_PRIORITYn_ADDR(n) (0x8 + (n * 0x1000))
#define NOC_QOS_PRIORITY_MASK 0xf
#define NOC_QOS_PRIORITY_P1_SHIFT 0x2
#define NOC_QOS_PRIORITY_P0_SHIFT 0x3
#define NOC_QOS_MODEn_ADDR(n) (0xc + (n * 0x1000))
#define NOC_QOS_MODEn_MASK 0x3
enum {
MSM8998_MASTER_IPA = 1,
MSM8998_MASTER_CNOC_A2NOC,
MSM8998_MASTER_SDCC_2,
MSM8998_MASTER_SDCC_4,
MSM8998_MASTER_BLSP_1,
MSM8998_MASTER_BLSP_2,
MSM8998_MASTER_UFS,
MSM8998_MASTER_USB_HS,
MSM8998_MASTER_USB3,
MSM8998_MASTER_CRYPTO_C0,
MSM8998_MASTER_GNOC_BIMC,
MSM8998_MASTER_OXILI,
MSM8998_MASTER_MNOC_BIMC,
MSM8998_MASTER_SNOC_BIMC,
MSM8998_MASTER_PIMEM,
MSM8998_MASTER_SNOC_CNOC,
MSM8998_MASTER_QDSS_DAP,
MSM8998_MASTER_APPS_PROC,
MSM8998_MASTER_CNOC_MNOC_MMSS_CFG,
MSM8998_MASTER_CNOC_MNOC_CFG,
MSM8998_MASTER_CPP,
MSM8998_MASTER_JPEG,
MSM8998_MASTER_MDP_P0,
MSM8998_MASTER_MDP_P1,
MSM8998_MASTER_VENUS,
MSM8998_MASTER_VFE,
MSM8998_MASTER_QDSS_ETR,
MSM8998_MASTER_QDSS_BAM,
MSM8998_MASTER_SNOC_CFG,
MSM8998_MASTER_BIMC_SNOC,
MSM8998_MASTER_A1NOC_SNOC,
MSM8998_MASTER_A2NOC_SNOC,
MSM8998_MASTER_GNOC_SNOC,
MSM8998_MASTER_PCIE_0,
MSM8998_MASTER_A2NOC_TSIF,
MSM8998_MASTER_CRVIRT_A2NOC,
MSM8998_MASTER_ROTATOR,
MSM8998_MASTER_VENUS_VMEM,
MSM8998_MASTER_HMSS,
MSM8998_MASTER_BIMC_SNOC_0,
MSM8998_MASTER_BIMC_SNOC_1,
MSM8998_SLAVE_A1NOC_SNOC,
MSM8998_SLAVE_A2NOC_SNOC,
MSM8998_SLAVE_EBI,
MSM8998_SLAVE_HMSS_L3,
MSM8998_SLAVE_CNOC_A2NOC,
MSM8998_SLAVE_MPM,
MSM8998_SLAVE_PMIC_ARB,
MSM8998_SLAVE_TLMM_NORTH,
MSM8998_SLAVE_TCSR,
MSM8998_SLAVE_PIMEM_CFG,
MSM8998_SLAVE_IMEM_CFG,
MSM8998_SLAVE_MESSAGE_RAM,
MSM8998_SLAVE_GLM,
MSM8998_SLAVE_BIMC_CFG,
MSM8998_SLAVE_PRNG,
MSM8998_SLAVE_SPDM,
MSM8998_SLAVE_QDSS_CFG,
MSM8998_SLAVE_CNOC_MNOC_CFG,
MSM8998_SLAVE_SNOC_CFG,
MSM8998_SLAVE_QM_CFG,
MSM8998_SLAVE_CLK_CTL,
MSM8998_SLAVE_MSS_CFG,
MSM8998_SLAVE_UFS_CFG,
MSM8998_SLAVE_A2NOC_CFG,
MSM8998_SLAVE_A2NOC_SMMU_CFG,
MSM8998_SLAVE_GPUSS_CFG,
MSM8998_SLAVE_AHB2PHY,
MSM8998_SLAVE_BLSP_1,
MSM8998_SLAVE_SDCC_2,
MSM8998_SLAVE_SDCC_4,
MSM8998_SLAVE_BLSP_2,
MSM8998_SLAVE_PDM,
MSM8998_SLAVE_CNOC_MNOC_MMSS_CFG,
MSM8998_SLAVE_USB_HS,
MSM8998_SLAVE_USB3_0,
MSM8998_SLAVE_SRVC_CNOC,
MSM8998_SLAVE_GNOC_BIMC,
MSM8998_SLAVE_GNOC_SNOC,
MSM8998_SLAVE_CAMERA_CFG,
MSM8998_SLAVE_CAMERA_THROTTLE_CFG,
MSM8998_SLAVE_MISC_CFG,
MSM8998_SLAVE_VENUS_THROTTLE_CFG,
MSM8998_SLAVE_VENUS_CFG,
MSM8998_SLAVE_MMSS_CLK_XPU_CFG,
MSM8998_SLAVE_MMSS_CLK_CFG,
MSM8998_SLAVE_MNOC_MPU_CFG,
MSM8998_SLAVE_DISPLAY_CFG,
MSM8998_SLAVE_CSI_PHY_CFG,
MSM8998_SLAVE_DISPLAY_THROTTLE_CFG,
MSM8998_SLAVE_SMMU_CFG,
MSM8998_SLAVE_MNOC_BIMC,
MSM8998_SLAVE_SRVC_MNOC,
MSM8998_SLAVE_HMSS,
MSM8998_SLAVE_LPASS,
MSM8998_SLAVE_WLAN,
MSM8998_SLAVE_CDSP,
MSM8998_SLAVE_IPA,
MSM8998_SLAVE_SNOC_BIMC,
MSM8998_SLAVE_SNOC_CNOC,
MSM8998_SLAVE_IMEM,
MSM8998_SLAVE_PIMEM,
MSM8998_SLAVE_QDSS_STM,
MSM8998_SLAVE_SRVC_SNOC,
MSM8998_SLAVE_BIMC_SNOC_0,
MSM8998_SLAVE_BIMC_SNOC_1,
MSM8998_SLAVE_SSC_CFG,
MSM8998_SLAVE_SKL,
MSM8998_SLAVE_TLMM_WEST,
MSM8998_SLAVE_A1NOC_CFG,
MSM8998_SLAVE_A1NOC_SMMU_CFG,
MSM8998_SLAVE_TSIF,
MSM8998_SLAVE_TLMM_EAST,
MSM8998_SLAVE_CRVIRT_A2NOC,
MSM8998_SLAVE_VMEM_CFG,
MSM8998_SLAVE_VMEM,
MSM8998_SLAVE_PCIE_0,
};
#define to_qcom_provider(_provider) \
container_of(_provider, struct qcom_icc_provider, provider)
static const struct clk_bulk_data bus_clocks[] = {
{ .id = "bus" },
{ .id = "bus_a" },
};
static const struct clk_bulk_data bus_mm_clocks[] = {
{ .id = "bus" },
{ .id = "bus_a" },
{ .id = "iface" },
};
/**
* struct qcom_icc_provider - Qualcomm specific interconnect provider
* @provider: generic interconnect provider
* @bus_clks: the clk_bulk_data table of bus clocks
* @num_clks: the total number of clk_bulk_data entries
* @is_bimc_node: indicates whether to use bimc specific setting
* @mmio: NoC base iospace
*/
struct qcom_icc_provider {
struct icc_provider provider;
struct clk_bulk_data *bus_clks;
int num_clks;
bool is_bimc_node;
struct regmap *regmap;
void __iomem *mmio;
};
#define MSM8998_MAX_LINKS 38
/**
* struct qcom_icc_qos - Qualcomm specific interconnect QoS parameters
* @areq_prio: node requests priority
* @prio_level: priority level for bus communication
* @limit_commands: activate/deactivate limiter mode during runtime
* @ap_owned: indicates if the node is owned by the AP or by the RPM
* @qos_mode: default qos mode for this node
* @qos_port: qos port number for finding qos registers of this node
*/
struct qcom_icc_qos {
u32 areq_prio;
u32 prio_level;
bool limit_commands;
bool ap_owned;
int qos_mode;
int qos_port;
};
/**
* struct qcom_icc_node - Qualcomm specific interconnect nodes
* @name: the node name used in debugfs
* @id: a unique node identifier
* @links: an array of nodes where we can go next while traversing
* @num_links: the total number of @links
* @buswidth: width of the interconnect between a node and the bus (bytes)
* @mas_rpm_id: RPM id for devices that are bus masters
* @slv_rpm_id: RPM id for devices that are bus slaves
* @qos: NoC QoS setting parameters
* @rate: current bus clock rate in Hz
*/
struct qcom_icc_node {
unsigned char *name;
u16 id;
u16 links[MSM8998_MAX_LINKS];
u16 num_links;
u16 buswidth;
int mas_rpm_id;
int slv_rpm_id;
struct qcom_icc_qos qos;
u64 rate;
};
struct qcom_icc_desc {
struct qcom_icc_node **nodes;
size_t num_nodes;
const struct regmap_config *regmap_cfg;
};
#define DEFINE_QNODE(_name, _id, _buswidth, _mas_rpm_id, _slv_rpm_id, \
_ap_owned, _qos_mode, _qos_prio, _qos_port, ...) \
static struct qcom_icc_node _name = { \
.name = #_name, \
.id = _id, \
.buswidth = _buswidth, \
.mas_rpm_id = _mas_rpm_id, \
.slv_rpm_id = _slv_rpm_id, \
.qos.ap_owned = _ap_owned, \
.qos.qos_mode = _qos_mode, \
.qos.areq_prio = _qos_prio, \
.qos.prio_level = _qos_prio, \
.qos.qos_port = _qos_port, \
.num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ })), \
.links = { __VA_ARGS__ }, \
}
/* masters */
DEFINE_QNODE(mas_pcie_0, MSM8998_MASTER_PCIE_0, 16, 45, -1, true, NOC_QOS_MODE_FIXED, 1, 1, MSM8998_SLAVE_A1NOC_SNOC);
DEFINE_QNODE(mas_usb3, MSM8998_MASTER_USB3, 16, 32, -1, true, NOC_QOS_MODE_FIXED, 1, 2, MSM8998_SLAVE_A1NOC_SNOC);
DEFINE_QNODE(mas_ufs, MSM8998_MASTER_UFS, 16, 68, -1, true, NOC_QOS_MODE_FIXED, 1, 2, MSM8998_SLAVE_A1NOC_SNOC);
DEFINE_QNODE(mas_blsp_2, MSM8998_MASTER_BLSP_2, 16, 39, -1, false, NOC_QOS_MODE_FIXED, 0, 4, MSM8998_SLAVE_A1NOC_SNOC);
DEFINE_QNODE(mas_cnoc_a2noc, MSM8998_MASTER_CNOC_A2NOC, 8, 146, -1, true, -1, 0, -1, MSM8998_SLAVE_A2NOC_SNOC);
DEFINE_QNODE(mas_ipa, MSM8998_MASTER_IPA, 8, 59, -1, true, NOC_QOS_MODE_FIXED, 1, 1, MSM8998_SLAVE_A2NOC_SNOC);
DEFINE_QNODE(mas_sdcc_2, MSM8998_MASTER_SDCC_2, 8, 35, -1, false, NOC_QOS_MODE_FIXED, 0, 6, MSM8998_SLAVE_A2NOC_SNOC);
DEFINE_QNODE(mas_sdcc_4, MSM8998_MASTER_SDCC_4, 8, 36, -1, false, NOC_QOS_MODE_FIXED, 0, 7, MSM8998_SLAVE_A2NOC_SNOC);
DEFINE_QNODE(mas_tsif, MSM8998_MASTER_A2NOC_TSIF, 4, 37, -1, true, -1, 0, -1, MSM8998_SLAVE_A2NOC_SNOC);
DEFINE_QNODE(mas_blsp_1, MSM8998_MASTER_BLSP_1, 16, 41, -1, false, NOC_QOS_MODE_FIXED, 0, 8, MSM8998_SLAVE_A2NOC_SNOC);
DEFINE_QNODE(mas_crvirt_a2noc, MSM8998_MASTER_CRVIRT_A2NOC, 8, 145, -1, false, NOC_QOS_MODE_FIXED, 0, 9, MSM8998_SLAVE_A2NOC_SNOC);
DEFINE_QNODE(mas_gnoc_bimc, MSM8998_MASTER_GNOC_BIMC, 8, 144, -1, true, NOC_QOS_MODE_FIXED, 0, 0, MSM8998_SLAVE_EBI, MSM8998_SLAVE_BIMC_SNOC_0);
DEFINE_QNODE(mas_oxili, MSM8998_MASTER_OXILI, 8, 6, -1, true, NOC_QOS_MODE_BYPASS, 0, 1, MSM8998_SLAVE_BIMC_SNOC_1, MSM8998_SLAVE_HMSS_L3, MSM8998_SLAVE_EBI, MSM8998_SLAVE_BIMC_SNOC_0);
DEFINE_QNODE(mas_mnoc_bimc, MSM8998_MASTER_MNOC_BIMC, 8, 2, -1, true, NOC_QOS_MODE_BYPASS, 0, 2, MSM8998_SLAVE_BIMC_SNOC_1, MSM8998_SLAVE_HMSS_L3, MSM8998_SLAVE_EBI, MSM8998_SLAVE_BIMC_SNOC_0);
DEFINE_QNODE(mas_snoc_bimc, MSM8998_MASTER_SNOC_BIMC, 8, 3, -1, false, NOC_QOS_MODE_BYPASS, 0, 3, MSM8998_SLAVE_HMSS_L3, MSM8998_SLAVE_EBI);
DEFINE_QNODE(mas_snoc_cnoc, MSM8998_MASTER_SNOC_CNOC, 8, 52, -1, true, -1, 0, -1, MSM8998_SLAVE_SKL, MSM8998_SLAVE_BLSP_2, MSM8998_SLAVE_MESSAGE_RAM, MSM8998_SLAVE_TLMM_WEST, MSM8998_SLAVE_TSIF, MSM8998_SLAVE_MPM, MSM8998_SLAVE_BIMC_CFG, MSM8998_SLAVE_TLMM_EAST, MSM8998_SLAVE_SPDM, MSM8998_SLAVE_PIMEM_CFG, MSM8998_SLAVE_A1NOC_SMMU_CFG, MSM8998_SLAVE_BLSP_1, MSM8998_SLAVE_CLK_CTL, MSM8998_SLAVE_PRNG, MSM8998_SLAVE_USB3_0, MSM8998_SLAVE_QDSS_CFG, MSM8998_SLAVE_QM_CFG, MSM8998_SLAVE_A2NOC_CFG, MSM8998_SLAVE_PMIC_ARB, MSM8998_SLAVE_UFS_CFG, MSM8998_SLAVE_SRVC_CNOC, MSM8998_SLAVE_AHB2PHY, MSM8998_SLAVE_IPA, MSM8998_SLAVE_GLM, MSM8998_SLAVE_SNOC_CFG, MSM8998_SLAVE_SSC_CFG, MSM8998_SLAVE_SDCC_2, MSM8998_SLAVE_SDCC_4, MSM8998_SLAVE_PDM, MSM8998_SLAVE_CNOC_MNOC_MMSS_CFG, MSM8998_SLAVE_CNOC_MNOC_CFG, MSM8998_SLAVE_MSS_CFG, MSM8998_SLAVE_IMEM_CFG, MSM8998_SLAVE_A1NOC_CFG, MSM8998_SLAVE_GPUSS_CFG, MSM8998_SLAVE_TCSR, MSM8998_SLAVE_TLMM_NORTH);
DEFINE_QNODE(mas_qdss_dap, MSM8998_MASTER_QDSS_DAP, 8, 49, -1, true, -1, 0, -1, MSM8998_SLAVE_SKL, MSM8998_SLAVE_BLSP_2, MSM8998_SLAVE_MESSAGE_RAM, MSM8998_SLAVE_TLMM_WEST, MSM8998_SLAVE_TSIF, MSM8998_SLAVE_MPM, MSM8998_SLAVE_BIMC_CFG, MSM8998_SLAVE_TLMM_EAST, MSM8998_SLAVE_SPDM, MSM8998_SLAVE_PIMEM_CFG, MSM8998_SLAVE_A1NOC_SMMU_CFG, MSM8998_SLAVE_BLSP_1, MSM8998_SLAVE_CLK_CTL, MSM8998_SLAVE_PRNG, MSM8998_SLAVE_USB3_0, MSM8998_SLAVE_QDSS_CFG, MSM8998_SLAVE_QM_CFG, MSM8998_SLAVE_A2NOC_CFG, MSM8998_SLAVE_PMIC_ARB, MSM8998_SLAVE_UFS_CFG, MSM8998_SLAVE_SRVC_CNOC, MSM8998_SLAVE_AHB2PHY, MSM8998_SLAVE_IPA, MSM8998_SLAVE_GLM, MSM8998_SLAVE_SNOC_CFG, MSM8998_SLAVE_SDCC_2, MSM8998_SLAVE_SDCC_4, MSM8998_SLAVE_PDM, MSM8998_SLAVE_CNOC_MNOC_MMSS_CFG, MSM8998_SLAVE_CNOC_MNOC_CFG, MSM8998_SLAVE_MSS_CFG, MSM8998_SLAVE_IMEM_CFG, MSM8998_SLAVE_A1NOC_CFG, MSM8998_SLAVE_GPUSS_CFG, MSM8998_SLAVE_SSC_CFG, MSM8998_SLAVE_TCSR, MSM8998_SLAVE_TLMM_NORTH, MSM8998_SLAVE_CNOC_A2NOC);
DEFINE_QNODE(mas_crypto, MSM8998_MASTER_CRYPTO_C0, 650, 23, -1, false, -1, 0, -1, MSM8998_MASTER_CRVIRT_A2NOC);
DEFINE_QNODE(mas_apss_proc, MSM8998_MASTER_APPS_PROC, 32, 0, -1, true, -1, 0, -1, MSM8998_SLAVE_GNOC_BIMC);
DEFINE_QNODE(mas_cnoc_mnoc_mmss_cfg, MSM8998_MASTER_CNOC_MNOC_MMSS_CFG, 8, 4, -1, true, -1, 0, -1, MSM8998_SLAVE_CAMERA_THROTTLE_CFG, MSM8998_SLAVE_VENUS_CFG, MSM8998_SLAVE_MISC_CFG, MSM8998_SLAVE_CAMERA_CFG, MSM8998_SLAVE_DISPLAY_THROTTLE_CFG, MSM8998_SLAVE_VENUS_THROTTLE_CFG, MSM8998_SLAVE_DISPLAY_CFG, MSM8998_SLAVE_MMSS_CLK_CFG, MSM8998_SLAVE_VMEM_CFG, MSM8998_SLAVE_MMSS_CLK_XPU_CFG, MSM8998_SLAVE_SMMU_CFG);
DEFINE_QNODE(mas_cnoc_mnoc_cfg, MSM8998_MASTER_CNOC_MNOC_CFG, 8, 5, -1, true, -1, 0, -1, MSM8998_SLAVE_SRVC_MNOC);
DEFINE_QNODE(mas_cpp, MSM8998_MASTER_CPP, 32, 115, -1, true, NOC_QOS_MODE_BYPASS, 0, 5, MSM8998_SLAVE_MNOC_BIMC);
DEFINE_QNODE(mas_jpeg, MSM8998_MASTER_JPEG, 32, 7, -1, true, NOC_QOS_MODE_BYPASS, 0, 7, MSM8998_SLAVE_MNOC_BIMC);
DEFINE_QNODE(mas_mdp_p0, MSM8998_MASTER_MDP_P0, 32, 8, -1, true, NOC_QOS_MODE_BYPASS, 0, 1, MSM8998_SLAVE_MNOC_BIMC); /* vrail-comp???? */
DEFINE_QNODE(mas_mdp_p1, MSM8998_MASTER_MDP_P1, 32, 61, -1, true, NOC_QOS_MODE_BYPASS, 0, 2, MSM8998_SLAVE_MNOC_BIMC); /* vrail-comp??? */
DEFINE_QNODE(mas_rotator, MSM8998_MASTER_ROTATOR, 32, 120, -1, true, NOC_QOS_MODE_BYPASS, 0, 0, MSM8998_SLAVE_MNOC_BIMC);
DEFINE_QNODE(mas_venus, MSM8998_MASTER_VENUS, 32, 9, -1, true, NOC_QOS_MODE_BYPASS, 0, 3, MSM8998_SLAVE_MNOC_BIMC);
DEFINE_QNODE(mas_vfe, MSM8998_MASTER_VFE, 32, 11, -1, true, NOC_QOS_MODE_BYPASS, 0, 6, MSM8998_SLAVE_MNOC_BIMC);
DEFINE_QNODE(mas_venus_vmem, MSM8998_MASTER_VENUS_VMEM, 32, 121, -1, true, -1, 0, -1, MSM8998_SLAVE_VMEM);
DEFINE_QNODE(mas_hmss, MSM8998_MASTER_HMSS, 16, 118, -1, true, NOC_QOS_MODE_FIXED, 1, 3, MSM8998_SLAVE_PIMEM, MSM8998_SLAVE_IMEM, MSM8998_SLAVE_SNOC_BIMC);
DEFINE_QNODE(mas_qdss_bam, MSM8998_MASTER_QDSS_BAM, 16, 19, -1, true, NOC_QOS_MODE_FIXED, 1, 1, MSM8998_SLAVE_IMEM, MSM8998_SLAVE_PIMEM, MSM8998_SLAVE_SNOC_CNOC, MSM8998_SLAVE_SNOC_BIMC);
DEFINE_QNODE(mas_snoc_cfg, MSM8998_MASTER_SNOC_CFG, 16, 20, -1, false, -1, 0, -1, MSM8998_SLAVE_SRVC_SNOC);
DEFINE_QNODE(mas_bimc_snoc_0, MSM8998_MASTER_BIMC_SNOC_0, 16, 21, -1, false, -1, 0, -1, MSM8998_SLAVE_PIMEM, MSM8998_SLAVE_LPASS, MSM8998_SLAVE_HMSS, MSM8998_SLAVE_WLAN, MSM8998_SLAVE_SNOC_CNOC, MSM8998_SLAVE_IMEM, MSM8998_SLAVE_QDSS_STM);
DEFINE_QNODE(mas_bimc_snoc_1, MSM8998_MASTER_BIMC_SNOC_1, 16, 109, -1, true, -1, 0, -1, MSM8998_SLAVE_PCIE_0);
DEFINE_QNODE(mas_a1noc_snoc, MSM8998_MASTER_A1NOC_SNOC, 16, 111, -1, false, -1, 0, -1, MSM8998_SLAVE_PIMEM, MSM8998_SLAVE_PCIE_0, MSM8998_SLAVE_LPASS, MSM8998_SLAVE_HMSS, MSM8998_SLAVE_SNOC_BIMC, MSM8998_SLAVE_SNOC_CNOC, MSM8998_SLAVE_IMEM, MSM8998_SLAVE_QDSS_STM);
DEFINE_QNODE(mas_a2noc_snoc, MSM8998_MASTER_A2NOC_SNOC, 16, 112, -1, false, -1, 0, -1, MSM8998_SLAVE_PIMEM, MSM8998_SLAVE_PCIE_0, MSM8998_SLAVE_LPASS, MSM8998_SLAVE_HMSS, MSM8998_SLAVE_SNOC_BIMC, MSM8998_SLAVE_WLAN, MSM8998_SLAVE_SNOC_CNOC, MSM8998_SLAVE_IMEM, MSM8998_SLAVE_QDSS_STM);
DEFINE_QNODE(mas_qdss_etr, MSM8998_MASTER_QDSS_ETR, 16, 31, -1, true, NOC_QOS_MODE_FIXED, 1, 2, MSM8998_SLAVE_IMEM, MSM8998_MASTER_PIMEM, MSM8998_SLAVE_SNOC_CNOC, MSM8998_SLAVE_SNOC_BIMC);
/* slaves */
DEFINE_QNODE(slv_a1noc_snoc, MSM8998_SLAVE_A1NOC_SNOC, 16, -1, 142, false, -1, 0, -1, MSM8998_MASTER_A1NOC_SNOC);
DEFINE_QNODE(slv_a2noc_snoc, MSM8998_SLAVE_A2NOC_SNOC, 16, -1, 143, false, -1, 0, -1, MSM8998_MASTER_A2NOC_SNOC);
DEFINE_QNODE(slv_ebi, MSM8998_SLAVE_EBI, 8, -1, 0, false, -1, 0, -1, 0);
DEFINE_QNODE(slv_hmss_l3, MSM8998_SLAVE_HMSS_L3, 8, -1, 160, false, -1, 0, -1, 0);
DEFINE_QNODE(slv_bimc_snoc_0, MSM8998_SLAVE_BIMC_SNOC_0, 8, -1, 2, false, -1, 0, -1, MSM8998_MASTER_BIMC_SNOC_0);
DEFINE_QNODE(slv_bimc_snoc_1, MSM8998_SLAVE_BIMC_SNOC_1, 8, -1, 138, true, -1, 0, -1, MSM8998_MASTER_BIMC_SNOC_1);
DEFINE_QNODE(slv_cnoc_a2noc, MSM8998_SLAVE_CNOC_A2NOC, 4, -1, 208, true, -1, 0, -1, MSM8998_MASTER_CNOC_A2NOC);
DEFINE_QNODE(slv_ssc_cfg, MSM8998_SLAVE_SSC_CFG, 4, -1, 177, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_mpm, MSM8998_SLAVE_MPM, 4, -1, 62, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_pmic_arb, MSM8998_SLAVE_PMIC_ARB, 4, -1, 59, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_tlmm_north, MSM8998_SLAVE_TLMM_NORTH, 4, -1, 214, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_pimem_cfg, MSM8998_SLAVE_PIMEM_CFG, 4, -1, 167, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_imem_cfg, MSM8998_SLAVE_IMEM_CFG, 4, -1, 54, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_message_ram, MSM8998_SLAVE_MESSAGE_RAM, 4, -1, 55, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_skl, MSM8998_SLAVE_SKL, 4, -1, 196, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_bimc_cfg, MSM8998_SLAVE_BIMC_CFG, 4, -1, 56, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_prng, MSM8998_SLAVE_PRNG, 4, -1, 44, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_a2noc_cfg, MSM8998_SLAVE_A2NOC_CFG, 4, -1, 150, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_ipa, MSM8998_SLAVE_IPA, 4, -1, 183, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_tcsr, MSM8998_SLAVE_TCSR, 4, -1, 50, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_snoc_cfg, MSM8998_SLAVE_SNOC_CFG, 4, -1, 70, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_clk_ctl, MSM8998_SLAVE_CLK_CTL, 4, -1, 47, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_glm, MSM8998_SLAVE_GLM, 4, -1, 209, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_spdm, MSM8998_SLAVE_SPDM, 4, -1, 60, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_gpuss_cfg, MSM8998_SLAVE_GPUSS_CFG, 4, -1, 11, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_cnoc_mnoc_cfg, MSM8998_SLAVE_CNOC_MNOC_CFG, 4, -1, 66, true, -1, 0, -1, MSM8998_MASTER_CNOC_MNOC_CFG);
DEFINE_QNODE(slv_qm_cfg, MSM8998_SLAVE_QM_CFG, 4, -1, 212, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_mss_cfg, MSM8998_SLAVE_MSS_CFG, 4, -1, 48, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_ufs_cfg, MSM8998_SLAVE_UFS_CFG, 4, -1, 92, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_tlmm_west, MSM8998_SLAVE_TLMM_WEST, 4, -1, 215, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_a1noc_cfg, MSM8998_SLAVE_A1NOC_CFG, 4, -1, 147, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_ahb2phy, MSM8998_SLAVE_AHB2PHY, 4, -1, 163, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_blsp_2, MSM8998_SLAVE_BLSP_2, 4, -1, 37, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_pdm, MSM8998_SLAVE_PDM, 4, -1, 41, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_usb3_0, MSM8998_SLAVE_USB3_0, 4, -1, 22, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_a1noc_smmu_cfg, MSM8998_SLAVE_A1NOC_SMMU_CFG, 8, -1, 149, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_blsp_1, MSM8998_SLAVE_BLSP_1, 4, -1, 39, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_sdcc_2, MSM8998_SLAVE_SDCC_2, 4, -1, 33, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_sdcc_4, MSM8998_SLAVE_SDCC_4, 4, -1, 34, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_tsif, MSM8998_SLAVE_TSIF, 4, -1, 35, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_qdss_cfg, MSM8998_SLAVE_QDSS_CFG, 4, -1, 63, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_tlmm_east, MSM8998_SLAVE_TLMM_EAST, 4, -1, 213, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_cnoc_mnoc_mmss_cfg, MSM8998_SLAVE_CNOC_MNOC_MMSS_CFG, 8, -1, 58, true, -1, 0, -1, MSM8998_MASTER_CNOC_MNOC_MMSS_CFG);
DEFINE_QNODE(slv_srvc_cnoc, MSM8998_SLAVE_SRVC_CNOC, 4, -1, 76, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_crvirt_a2noc, MSM8998_SLAVE_CRVIRT_A2NOC, 8, -1, 207, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_gnoc_bimc, MSM8998_SLAVE_GNOC_BIMC, 32, -1, 210, true, -1, 0, -1, MSM8998_MASTER_GNOC_BIMC);
DEFINE_QNODE(slv_camera_cfg, MSM8998_SLAVE_CAMERA_CFG, 8, -1, 3, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_camera_throttle_cfg, MSM8998_SLAVE_CAMERA_THROTTLE_CFG, 8, -1, 154, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_misc_cfg, MSM8998_SLAVE_MISC_CFG, 8, -1, 8, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_venus_throttle_cfg, MSM8998_SLAVE_VENUS_THROTTLE_CFG, 8, -1, 178, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_venus_cfg, MSM8998_SLAVE_VENUS_CFG, 8, -1, 10, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_vmem_cfg, MSM8998_SLAVE_VMEM_CFG, 8, -1, 180, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_mmss_clk_xpu_cfg, MSM8998_SLAVE_MMSS_CLK_XPU_CFG, 8, -1, 13, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_mmss_clk_cfg, MSM8998_SLAVE_MMSS_CLK_CFG, 8, -1, 12, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_display_cfg, MSM8998_SLAVE_DISPLAY_CFG, 8, -1, 4, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_display_throttle_cfg, MSM8998_SLAVE_DISPLAY_THROTTLE_CFG, 4, -1, 156, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_smmu_cfg, MSM8998_SLAVE_SMMU_CFG, 8, -1, 205, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_mnoc_bimc, MSM8998_SLAVE_MNOC_BIMC, 32, -1, 16, true, -1, 0, -1, MSM8998_MASTER_MNOC_BIMC);
DEFINE_QNODE(slv_vmem, MSM8998_SLAVE_VMEM, 32, -1, 179, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_srvc_mnoc, MSM8998_SLAVE_SRVC_MNOC, 8, -1, 17, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_hmss, MSM8998_SLAVE_HMSS, 16, -1, 20, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_lpass, MSM8998_SLAVE_LPASS, 16, -1, 21, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_wlan, MSM8998_SLAVE_WLAN, 16, -1, 206, false, -1, 0, -1, 0);
DEFINE_QNODE(slv_snoc_bimc, MSM8998_SLAVE_SNOC_BIMC, 32, -1, 24, false, -1, 0, -1, MSM8998_MASTER_SNOC_BIMC);
DEFINE_QNODE(slv_snoc_cnoc, MSM8998_SLAVE_SNOC_CNOC, 16, -1, 25, false, -1, 0, -1, MSM8998_MASTER_SNOC_CNOC);
DEFINE_QNODE(slv_imem, MSM8998_SLAVE_IMEM, 16, -1, 26, false, -1, 0, -1, 0);
DEFINE_QNODE(slv_pimem, MSM8998_SLAVE_PIMEM, 16, -1, 166, false, -1, 0, -1, 0);
DEFINE_QNODE(slv_qdss_stm, MSM8998_SLAVE_QDSS_STM, 16, -1, 30, false, -1, 0, -1, 0);
DEFINE_QNODE(slv_pcie_0, MSM8998_SLAVE_PCIE_0, 16, -1, 84, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_srvc_snoc, MSM8998_SLAVE_SRVC_SNOC, 16, -1, 29, false, -1, 0, -1, 0);
static struct qcom_icc_node *msm8998_a1noc_nodes[] = {
[MASTER_PCIE_0] = &mas_pcie_0,
[MASTER_USB3] = &mas_usb3,
[MASTER_UFS] = &mas_ufs,
[MASTER_BLSP_2] = &mas_blsp_2,
[SLAVE_A1NOC_SNOC] = &slv_a1noc_snoc,
};
static const struct regmap_config msm8998_a1noc_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x60000,
.fast_io = true,
};
static struct qcom_icc_desc msm8998_a1noc = {
.nodes = msm8998_a1noc_nodes,
.num_nodes = ARRAY_SIZE(msm8998_a1noc_nodes),
.regmap_cfg = &msm8998_a1noc_regmap_config,
};
static struct qcom_icc_node *msm8998_a2noc_nodes[] = {
[MASTER_IPA] = &mas_ipa,
[MASTER_CNOC_A2NOC] = &mas_cnoc_a2noc,
[MASTER_SDCC_2] = &mas_sdcc_2,
[MASTER_SDCC_4] = &mas_sdcc_4,
[MASTER_TSIF] = &mas_tsif,
[MASTER_BLSP_1] = &mas_blsp_1,
[MASTER_CRVIRT_A2NOC] = &mas_crvirt_a2noc,
[MASTER_CRYPTO_C0] = &mas_crypto,
[SLAVE_A2NOC_SNOC] = &slv_a2noc_snoc,
[SLAVE_CRVIRT_A2NOC] = &slv_crvirt_a2noc,
};
static const struct regmap_config msm8998_a2noc_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x60000,
.fast_io = true,
};
static struct qcom_icc_desc msm8998_a2noc = {
.nodes = msm8998_a2noc_nodes,
.num_nodes = ARRAY_SIZE(msm8998_a2noc_nodes),
.regmap_cfg = &msm8998_a2noc_regmap_config,
};
static struct qcom_icc_node *msm8998_bimc_nodes[] = {
[MASTER_GNOC_BIMC] = &mas_gnoc_bimc,
[MASTER_OXILI] = &mas_oxili,
[MASTER_MNOC_BIMC] = &mas_mnoc_bimc,
[MASTER_SNOC_BIMC] = &mas_snoc_bimc,
[SLAVE_EBI] = &slv_ebi,
[SLAVE_HMSS_L3] = &slv_hmss_l3,
[SLAVE_BIMC_SNOC_0] = &slv_bimc_snoc_0,
[SLAVE_BIMC_SNOC_1] = &slv_bimc_snoc_1,
};
static const struct regmap_config msm8998_bimc_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x80000,
.fast_io = true,
};
static struct qcom_icc_desc msm8998_bimc = {
.nodes = msm8998_bimc_nodes,
.num_nodes = ARRAY_SIZE(msm8998_bimc_nodes),
.regmap_cfg = &msm8998_bimc_regmap_config,
};
static struct qcom_icc_node *msm8998_cnoc_nodes[] = {
[MASTER_SNOC_CNOC] = &mas_snoc_cnoc,
[MASTER_QDSS_DAP] = &mas_qdss_dap,
[SLAVE_CNOC_A2NOC] = &slv_cnoc_a2noc,
[SLAVE_SSC_CFG] = &slv_ssc_cfg,
[SLAVE_MPM] = &slv_mpm,
[SLAVE_PMIC_ARB] = &slv_pmic_arb,
[SLAVE_TLMM_NORTH] = &slv_tlmm_north,
[SLAVE_PIMEM_CFG] = &slv_pimem_cfg,
[SLAVE_IMEM_CFG] = &slv_imem_cfg,
[SLAVE_MESSAGE_RAM] = &slv_message_ram,
[SLAVE_SKL] = &slv_skl,
[SLAVE_BIMC_CFG] = &slv_bimc_cfg,
[SLAVE_PRNG] = &slv_prng,
[SLAVE_A2NOC_CFG] = &slv_a2noc_cfg,
[SLAVE_IPA] = &slv_ipa,
[SLAVE_TCSR] = &slv_tcsr,
[SLAVE_SNOC_CFG] = &slv_snoc_cfg,
[SLAVE_CLK_CTL] = &slv_clk_ctl,
[SLAVE_GLM] = &slv_glm,
[SLAVE_SPDM] = &slv_spdm,
[SLAVE_GPUSS_CFG] = &slv_gpuss_cfg,
[SLAVE_CNOC_MNOC_CFG] = &slv_cnoc_mnoc_cfg,
[SLAVE_QM_CFG] = &slv_qm_cfg,
[SLAVE_MSS_CFG] = &slv_mss_cfg,
[SLAVE_UFS_CFG] = &slv_ufs_cfg,
[SLAVE_TLMM_WEST] = &slv_tlmm_west,
[SLAVE_A1NOC_CFG] = &slv_a1noc_cfg,
[SLAVE_AHB2PHY] = &slv_ahb2phy,
[SLAVE_BLSP_2] = &slv_blsp_2,
[SLAVE_PDM] = &slv_pdm,
[SLAVE_USB3_0] = &slv_usb3_0,
[SLAVE_A1NOC_SMMU_CFG] = &slv_a1noc_smmu_cfg,
[SLAVE_BLSP_1] = &slv_blsp_1,
[SLAVE_SDCC_2] = &slv_sdcc_2,
[SLAVE_SDCC_4] = &slv_sdcc_4,
[SLAVE_TSIF] = &slv_tsif,
[SLAVE_QDSS_CFG] = &slv_qdss_cfg,
[SLAVE_TLMM_EAST] = &slv_tlmm_east,
[SLAVE_CNOC_MNOC_MMSS_CFG] = &slv_cnoc_mnoc_mmss_cfg,
[SLAVE_SRVC_CNOC] = &slv_srvc_cnoc,
};
static const struct regmap_config msm8998_cnoc_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x10000,
.fast_io = true,
};
static struct qcom_icc_desc msm8998_cnoc = {
.nodes = msm8998_cnoc_nodes,
.num_nodes = ARRAY_SIZE(msm8998_cnoc_nodes),
.regmap_cfg = &msm8998_cnoc_regmap_config,
};
static struct qcom_icc_node *msm8998_gnoc_nodes[] = {
[MASTER_APSS_PROC] = &mas_apss_proc,
[SLAVE_GNOC_BIMC] = &slv_gnoc_bimc,
};
static const struct regmap_config msm8998_gnoc_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x10000,
.fast_io = true,
};
static struct qcom_icc_desc msm8998_gnoc = {
.nodes = msm8998_gnoc_nodes,
.num_nodes = ARRAY_SIZE(msm8998_gnoc_nodes),
.regmap_cfg = &msm8998_gnoc_regmap_config,
};
static struct qcom_icc_node *msm8998_mnoc_nodes[] = {
[MASTER_CNOC_MNOC_CFG] = &mas_cnoc_mnoc_cfg,
[MASTER_CPP] = &mas_cpp,
[MASTER_JPEG] = &mas_jpeg,
[MASTER_MDP_P0] = &mas_mdp_p0,
[MASTER_MDP_P1] = &mas_mdp_p1,
[MASTER_ROTATOR] = &mas_rotator,
[MASTER_VENUS] = &mas_venus,
[MASTER_VFE] = &mas_vfe,
[MASTER_VENUS_VMEM] = &mas_venus_vmem,
[SLAVE_MNOC_BIMC] = &slv_mnoc_bimc,
[SLAVE_VMEM] = &slv_vmem,
[SLAVE_SRVC_MNOC] = &slv_srvc_mnoc,
[MASTER_CNOC_MNOC_MMSS_CFG] = &mas_cnoc_mnoc_mmss_cfg,
[SLAVE_CAMERA_CFG] = &slv_camera_cfg,
[SLAVE_CAMERA_THROTTLE_CFG] = &slv_camera_throttle_cfg,
[SLAVE_MISC_CFG] = &slv_misc_cfg,
[SLAVE_VENUS_THROTTLE_CFG] = &slv_venus_throttle_cfg,
[SLAVE_VENUS_CFG] = &slv_venus_cfg,
[SLAVE_VMEM_CFG] = &slv_vmem_cfg,
[SLAVE_MMSS_CLK_XPU_CFG] = &slv_mmss_clk_xpu_cfg,
[SLAVE_MMSS_CLK_CFG] = &slv_mmss_clk_cfg,
[SLAVE_DISPLAY_CFG] = &slv_display_cfg,
[SLAVE_DISPLAY_THROTTLE_CFG] = &slv_display_throttle_cfg,
[SLAVE_SMMU_CFG] = &slv_smmu_cfg,
};
static const struct regmap_config msm8998_mnoc_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x10000,
.fast_io = true,
};
static struct qcom_icc_desc msm8998_mnoc = {
.nodes = msm8998_mnoc_nodes,
.num_nodes = ARRAY_SIZE(msm8998_mnoc_nodes),
.regmap_cfg = &msm8998_mnoc_regmap_config,
};
static struct qcom_icc_node *msm8998_snoc_nodes[] = {
[MASTER_HMSS] = &mas_hmss,
[MASTER_QDSS_BAM] = &mas_qdss_bam,
[MASTER_SNOC_CFG] = &mas_snoc_cfg,
[MASTER_BIMC_SNOC_0] = &mas_bimc_snoc_0,
[MASTER_BIMC_SNOC_1] = &mas_bimc_snoc_1,
[MASTER_A1NOC_SNOC] = &mas_a1noc_snoc,
[MASTER_A2NOC_SNOC] = &mas_a2noc_snoc,
[MASTER_QDSS_ETR] = &mas_qdss_etr,
[SLAVE_HMSS] = &slv_hmss,
[SLAVE_LPASS] = &slv_lpass,
[SLAVE_WLAN] = &slv_wlan,
[SLAVE_SNOC_BIMC] = &slv_snoc_bimc,
[SLAVE_SNOC_CNOC] = &slv_snoc_cnoc,
[SLAVE_IMEM] = &slv_imem,
[SLAVE_PIMEM] = &slv_pimem,
[SLAVE_QDSS_STM] = &slv_qdss_stm,
[SLAVE_PCIE_0] = &slv_pcie_0,
[SLAVE_SRVC_SNOC] = &slv_srvc_snoc,
};
static const struct regmap_config msm8998_snoc_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x40000,
.fast_io = true,
};
static struct qcom_icc_desc msm8998_snoc = {
.nodes = msm8998_snoc_nodes,
.num_nodes = ARRAY_SIZE(msm8998_snoc_nodes),
.regmap_cfg = &msm8998_snoc_regmap_config,
};
static int qcom_icc_bimc_set_qos_health(struct regmap *rmap,
struct qcom_icc_qos *qos,
int regnum)
{
u32 val;
u32 mask;
val = qos->prio_level;
mask = M_BKE_HEALTH_CFG_PRIOLVL_MASK;
val |= qos->areq_prio << M_BKE_HEALTH_CFG_AREQPRIO_SHIFT;
mask |= M_BKE_HEALTH_CFG_AREQPRIO_MASK;
/* LIMITCMDS is not present on M_BKE_HEALTH_3 */
if (regnum != 3) {
val |= qos->limit_commands << M_BKE_HEALTH_CFG_LIMITCMDS_SHIFT;
mask |= M_BKE_HEALTH_CFG_LIMITCMDS_MASK;
}
return regmap_update_bits(rmap,
M_BKE_HEALTH_CFG_ADDR(regnum, qos->qos_port),
mask, val);
}
static int qcom_icc_set_bimc_qos(struct icc_node *src, u64 max_bw,
bool bypass_mode)
{
struct qcom_icc_provider *qp;
struct qcom_icc_node *qn;
struct icc_provider *provider;
u32 mode = NOC_QOS_MODE_BYPASS;
u32 val = 0;
int i, rc = 0;
qn = src->data;
provider = src->provider;
qp = to_qcom_provider(provider);
if (qn->qos.qos_mode != -1)
mode = qn->qos.qos_mode;
/*
* QoS Priority: The QoS Health parameters are getting considered
* only if we are NOT in Bypass Mode.
*/
if (mode != NOC_QOS_MODE_BYPASS) {
for (i = 3; i >= 0; i--) {
rc = qcom_icc_bimc_set_qos_health(qp->regmap,
&qn->qos, i);
if (rc)
return rc;
}
/* Set BKE_EN to 1 when Fixed, Regulator or Limiter Mode */
val = 1;
}
return regmap_update_bits(qp->regmap, M_BKE_EN_ADDR(qn->qos.qos_port),
M_BKE_EN_EN_BMASK, val);
}
static int qcom_icc_noc_set_qos_priority(struct regmap *rmap,
struct qcom_icc_qos *qos)
{
u32 val;
int rc;
/* Must be updated one at a time, P1 first, P0 last */
val = qos->areq_prio << NOC_QOS_PRIORITY_P1_SHIFT;
rc = regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port),
NOC_QOS_PRIORITY_MASK, val);
if (rc)
return rc;
val = qos->prio_level << NOC_QOS_PRIORITY_P0_SHIFT;
return regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port),
NOC_QOS_PRIORITY_MASK, val);
}
static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw)
{
struct qcom_icc_provider *qp;
struct qcom_icc_node *qn;
struct icc_provider *provider;
u32 mode = NOC_QOS_MODE_BYPASS;
int rc = 0;
qn = src->data;
provider = src->provider;
qp = to_qcom_provider(provider);
if (qn->qos.qos_port < 0) {
dev_dbg(src->provider->dev,
"NoC QoS: Skipping %s: vote aggregated on parent.\n",
qn->name);
return 0;
}
if (qn->qos.qos_mode != -1)
mode = qn->qos.qos_mode;
if (mode == NOC_QOS_MODE_FIXED) {
dev_dbg(src->provider->dev, "NoC QoS: %s: Set Fixed mode\n",
qn->name);
rc = qcom_icc_noc_set_qos_priority(qp->regmap, &qn->qos);
if (rc)
return rc;
} else if (mode == NOC_QOS_MODE_BYPASS) {
dev_dbg(src->provider->dev, "NoC QoS: %s: Set Bypass mode\n",
qn->name);
}
return regmap_update_bits(qp->regmap,
NOC_QOS_MODEn_ADDR(qn->qos.qos_port),
NOC_QOS_MODEn_MASK, mode);
}
static int qcom_icc_qos_set(struct icc_node *node, u64 sum_bw)
{
struct qcom_icc_provider *qp = to_qcom_provider(node->provider);
struct qcom_icc_node *qn = node->data;
dev_dbg(node->provider->dev, "Setting QoS for %s\n", qn->name);
if (qp->is_bimc_node)
return qcom_icc_set_bimc_qos(node, sum_bw,
(qn->qos.qos_mode == NOC_QOS_MODE_BYPASS));
return qcom_icc_set_noc_qos(node, sum_bw);
}
static int qcom_icc_rpm_set(int mas_rpm_id, int slv_rpm_id, u64 sum_bw)
{
int ret = 0;
if (mas_rpm_id != -1) {
ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE,
RPM_BUS_MASTER_REQ,
mas_rpm_id,
sum_bw);
if (ret) {
pr_err("qcom_icc_rpm_smd_send mas %d error %d\n",
mas_rpm_id, ret);
return ret;
}
}
if (slv_rpm_id != -1) {
ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE,
RPM_BUS_SLAVE_REQ,
slv_rpm_id,
sum_bw);
if (ret) {
pr_err("qcom_icc_rpm_smd_send slv %d error %d\n",
slv_rpm_id, ret);
return ret;
}
}
return ret;
}
static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
{
struct qcom_icc_provider *qp;
struct qcom_icc_node *qn;
struct icc_provider *provider;
struct icc_node *n;
u64 sum_bw;
u64 max_peak_bw;
u64 rate;
u32 agg_avg = 0;
u32 agg_peak = 0;
int ret, i;
qn = src->data;
provider = src->provider;
qp = to_qcom_provider(provider);
list_for_each_entry(n, &provider->nodes, node_list)
provider->aggregate(n, 0, n->avg_bw, n->peak_bw,
&agg_avg, &agg_peak);
sum_bw = icc_units_to_bps(agg_avg);
max_peak_bw = icc_units_to_bps(agg_peak);
if (!qn->qos.ap_owned) {
/* send bandwidth request message to the RPM processor */
ret = qcom_icc_rpm_set(qn->mas_rpm_id, qn->slv_rpm_id, sum_bw);
if (ret)
return ret;
} else if (qn->qos.qos_mode != -1) {
/* set bandwidth directly from the AP */
ret = qcom_icc_qos_set(src, sum_bw);
if (ret)
return ret;
}
rate = max(sum_bw, max_peak_bw);
do_div(rate, qn->buswidth);
if (qn->rate == rate)
return 0;
for (i = 0; i < qp->num_clks; i++) {
ret = clk_set_rate(qp->bus_clks[i].clk, rate);
if (ret) {
pr_err("%s clk_set_rate error: %d\n",
qp->bus_clks[i].id, ret);
return ret;
}
}
qn->rate = rate;
return 0;
}
static int qnoc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct qcom_icc_desc *desc;
struct icc_onecell_data *data;
struct icc_provider *provider;
struct qcom_icc_node **qnodes;
struct qcom_icc_provider *qp;
struct icc_node *node;
struct resource *res;
size_t num_nodes, i;
int ret;
/* wait for the RPM proxy */
if (!qcom_icc_rpm_smd_available())
return -EPROBE_DEFER;
desc = of_device_get_match_data(dev);
if (!desc)
return -EINVAL;
qnodes = desc->nodes;
num_nodes = desc->num_nodes;
qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
if (!qp)
return -ENOMEM;
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
GFP_KERNEL);
if (!data)
return -ENOMEM;
if (of_device_is_compatible(dev->of_node, "qcom,msm8998-mnoc")) {
qp->bus_clks = devm_kmemdup(dev, bus_mm_clocks,
sizeof(bus_mm_clocks), GFP_KERNEL);
qp->num_clks = ARRAY_SIZE(bus_mm_clocks);
} else {
if (of_device_is_compatible(dev->of_node, "qcom,msm8998-bimc"))
qp->is_bimc_node = true;
qp->bus_clks = devm_kmemdup(dev, bus_clocks, sizeof(bus_clocks),
GFP_KERNEL);
qp->num_clks = ARRAY_SIZE(bus_clocks);
}
if (!qp->bus_clks)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
qp->mmio = devm_ioremap_resource(dev, res);
if (IS_ERR(qp->mmio)) {
dev_err(dev, "Cannot ioremap interconnect bus resource\n");
return PTR_ERR(qp->mmio);
}
qp->regmap = devm_regmap_init_mmio(dev, qp->mmio, desc->regmap_cfg);
if (IS_ERR(qp->regmap)) {
dev_err(dev, "Cannot regmap interconnect bus resource\n");
return PTR_ERR(qp->regmap);
}
ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks);
if (ret)
return ret;
ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks);
if (ret)
return ret;
provider = &qp->provider;
INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev;
provider->set = qcom_icc_set;
provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell;
provider->data = data;
ret = icc_provider_add(provider);
if (ret) {
dev_err(dev, "error adding interconnect provider: %d\n", ret);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return ret;
}
for (i = 0; i < num_nodes; i++) {
size_t j;
node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) {
ret = PTR_ERR(node);
goto err;
}
node->name = qnodes[i]->name;
node->data = qnodes[i];
icc_node_add(node, provider);
for (j = 0; j < qnodes[i]->num_links; j++)
icc_link_create(node, qnodes[i]->links[j]);
data->nodes[i] = node;
}
data->num_nodes = num_nodes;
platform_set_drvdata(pdev, qp);
return 0;
err:
icc_nodes_remove(provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
icc_provider_del(provider);
return ret;
}
static int qnoc_remove(struct platform_device *pdev)
{
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
icc_nodes_remove(&qp->provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return icc_provider_del(&qp->provider);
}
static const struct of_device_id msm8998_noc_of_match[] = {
{ .compatible = "qcom,msm8998-a1noc", .data = &msm8998_a1noc },
{ .compatible = "qcom,msm8998-a2noc", .data = &msm8998_a2noc },
{ .compatible = "qcom,msm8998-bimc", .data = &msm8998_bimc },
{ .compatible = "qcom,msm8998-cnoc", .data = &msm8998_cnoc },
{ .compatible = "qcom,msm8998-gnoc", .data = &msm8998_gnoc },
{ .compatible = "qcom,msm8998-mnoc", .data = &msm8998_mnoc },
{ .compatible = "qcom,msm8998-snoc", .data = &msm8998_snoc },
{ },
};
MODULE_DEVICE_TABLE(of, msm8998_noc_of_match);
static struct platform_driver msm8998_noc_driver = {
.probe = qnoc_probe,
.remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8998",
.of_match_table = msm8998_noc_of_match,
.sync_state = icc_sync_state,
},
};
module_platform_driver(msm8998_noc_driver);
MODULE_DESCRIPTION("Qualcomm msm8998 NoC driver");
MODULE_LICENSE("GPL v2");

View file

@ -5,6 +5,7 @@
#include <linux/acpi.h>
#include <linux/adreno-smmu-priv.h>
#include <linux/bitmap.h>
#include <linux/of_device.h>
#include <linux/qcom_scm.h>
@ -12,6 +13,7 @@
struct qcom_smmu {
struct arm_smmu_device smmu;
DECLARE_BITMAP(reset_cb_nodisable_mask, ARM_SMMU_MAX_CBS);
bool bypass_quirk;
u8 bypass_cbndx;
u32 stall_enabled;
@ -180,11 +182,13 @@ static int qcom_adreno_smmu_alloc_context_bank(struct arm_smmu_domain *smmu_doma
static bool qcom_adreno_can_do_ttbr1(struct arm_smmu_device *smmu)
{
/*
const struct device_node *np = smmu->dev->of_node;
if (of_device_is_compatible(np, "qcom,msm8996-smmu-v2"))
if (of_device_is_compatible(np, "qcom,msm8996-smmu-v2") ||
of_device_is_compatible(np, "qcom,msm8998-smmu-v2") ||
of_device_is_compatible(np, "qcom,sdm630-smmu-v2"))
return false;
*/
return true;
}
@ -228,11 +232,13 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
{ .compatible = "qcom,adreno" },
{ .compatible = "qcom,mdp4" },
{ .compatible = "qcom,mdss" },
{ .compatible = "qcom,msm8998-mss-pil" },
{ .compatible = "qcom,sc7180-mdss" },
{ .compatible = "qcom,sc7180-mss-pil" },
{ .compatible = "qcom,sc7280-mdss" },
{ .compatible = "qcom,sc7280-mss-pil" },
{ .compatible = "qcom,sc8180x-mdss" },
{ .compatible = "qcom,sdm660-mss-pil" },
{ .compatible = "qcom,sdm845-mdss" },
{ .compatible = "qcom,sdm845-mss-pil" },
{ }
@ -267,7 +273,8 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
reg = arm_smmu_gr0_read(smmu, last_s2cr);
if (FIELD_GET(ARM_SMMU_S2CR_TYPE, reg) != S2CR_TYPE_BYPASS) {
qsmmu->bypass_quirk = true;
qsmmu->bypass_cbndx = smmu->num_context_banks - 1;
if (qsmmu->bypass_cbndx == 0xff)
qsmmu->bypass_cbndx = smmu->num_context_banks - 1;
set_bit(qsmmu->bypass_cbndx, smmu->context_map);
@ -359,8 +366,15 @@ static int qcom_sdm845_smmu500_reset(struct arm_smmu_device *smmu)
static int qcom_smmu500_reset(struct arm_smmu_device *smmu)
{
const struct device_node *np = smmu->dev->of_node;
struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
arm_mmu500_reset(smmu);
/*
* Execute the mmu-500 reset implementation detail only if there
* are no secured untouchable contexts in this iommu, otherwise
* the system will crash.
*/
if (bitmap_empty(qsmmu->reset_cb_nodisable_mask, ARM_SMMU_MAX_CBS))
arm_mmu500_reset(smmu);
if (of_device_is_compatible(np, "qcom,sdm845-smmu-500"))
return qcom_sdm845_smmu500_reset(smmu);
@ -368,11 +382,20 @@ static int qcom_smmu500_reset(struct arm_smmu_device *smmu)
return 0;
}
static bool qcom_smmu500_reset_cb_nodisable(struct arm_smmu_device *smmu,
int cbndx)
{
struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
return test_bit(cbndx, qsmmu->reset_cb_nodisable_mask);
}
static const struct arm_smmu_impl qcom_smmu_impl = {
.init_context = qcom_smmu_init_context,
.cfg_probe = qcom_smmu_cfg_probe,
.def_domain_type = qcom_smmu_def_domain_type,
.reset = qcom_smmu500_reset,
.reset_cb_nodisable = qcom_smmu500_reset_cb_nodisable,
.write_s2cr = qcom_smmu_write_s2cr,
};
@ -380,6 +403,7 @@ static const struct arm_smmu_impl qcom_adreno_smmu_impl = {
.init_context = qcom_adreno_smmu_init_context,
.def_domain_type = qcom_smmu_def_domain_type,
.reset = qcom_smmu500_reset,
.reset_cb_nodisable = qcom_smmu500_reset_cb_nodisable,
.alloc_context_bank = qcom_adreno_smmu_alloc_context_bank,
.write_sctlr = qcom_adreno_smmu_write_sctlr,
};
@ -387,7 +411,10 @@ static const struct arm_smmu_impl qcom_adreno_smmu_impl = {
static struct arm_smmu_device *qcom_smmu_create(struct arm_smmu_device *smmu,
const struct arm_smmu_impl *impl)
{
const struct device_node *np = smmu->dev->of_node;
struct qcom_smmu *qsmmu;
u8 reset_nodisable_cbs[ARM_SMMU_MAX_CBS];
int i, sz;
/* Check to make sure qcom_scm has finished probing */
if (!qcom_scm_is_available())
@ -398,6 +425,34 @@ static struct arm_smmu_device *qcom_smmu_create(struct arm_smmu_device *smmu,
return ERR_PTR(-ENOMEM);
qsmmu->smmu.impl = impl;
qsmmu->bypass_cbndx = 0xff;
bitmap_zero(qsmmu->reset_cb_nodisable_mask, ARM_SMMU_MAX_CBS);
if (np != NULL) {
/*
* This property is optional and we expect to fail finding it if:
* - Using the default bypass_cbndx (in the .cfg_probe cb) is fine; or
* - We are booting on ACPI
*/
of_property_read_u8(np, "qcom,bypass-cbndx", &qsmmu->bypass_cbndx);
/*
* Some context banks may not be disabled because they are
* secured: read from DT a list of secured contexts that cannot
* be disabled without crashing the system.
* This list is optional, as not all firmware configurations do
* require us skipping disablement of context banks.
*/
sz = of_property_read_variable_u8_array(np, "qcom,reset-nodisable-cbs",
reset_nodisable_cbs,
1, ARM_SMMU_MAX_CBS);
if (sz > 0) {
for (i = 0; i < sz; i++) {
__set_bit(reset_nodisable_cbs[i],
qsmmu->reset_cb_nodisable_mask);
}
}
}
return &qsmmu->smmu;
}

View file

@ -1622,6 +1622,16 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
/* Make sure all context banks are disabled and clear CB_FSR */
for (i = 0; i < smmu->num_context_banks; ++i) {
/*
* Some context banks cannot be disabled due to hypervisor
* configuration on some systems; if this is the case,
* skip disabling and writing FAULT on the CB FSR in order
* to avoid a system crash.
*/
if (smmu->impl && smmu->impl->reset_cb_nodisable &&
smmu->impl->reset_cb_nodisable(smmu, i)) {
continue;
}
arm_smmu_write_context_bank(smmu, i);
arm_smmu_cb_write(smmu, i, ARM_SMMU_CB_FSR, ARM_SMMU_FSR_FAULT);
}

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

@ -869,6 +869,18 @@ source "drivers/leds/blink/Kconfig"
comment "Flash and Torch LED drivers"
source "drivers/leds/flash/Kconfig"
#comment "RGB LED drivers"
#source "drivers/leds/rgb/Kconfig"
config LEDS_QCOM_LPG
tristate "LED support for Qualcomm LPG"
depends on LEDS_CLASS_MULTICOLOR
depends on OF
depends on SPMI
help
This option enables support for the Light Pulse Generator found in a
wide variety of Qualcomm PMICs.
comment "LED Triggers"
source "drivers/leds/trigger/Kconfig"

View file

@ -99,6 +99,11 @@ obj-$(CONFIG_LEDS_USER) += uleds.o
# Flash and Torch LED Drivers
obj-$(CONFIG_LEDS_CLASS_FLASH) += flash/
# RGB LED Drivers
# obj-$(CONFIG_LEDS_CLASS_MULTICOLOR) += rgb/
obj-$(CONFIG_LEDS_QCOM_LPG) += rgb/leds-qcom-lpg.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/

File diff suppressed because it is too large Load diff

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

@ -2032,6 +2032,18 @@ config MFD_WCD934X
This driver provides common support WCD934x audio codec and its
associated Pin Controller, Soundwire Controller and Audio codec.
config MFD_WCD9335
tristate "Support for WCD9335 Codec"
depends on SLIMBUS
select REGMAP
select REGMAP_SLIMBUS
select REGMAP_IRQ
select MFD_CORE
help
Support for the Qualcomm WCD9335 Codec.
This driver provides common support WCD9335 audio codec and its
associated Pin Controller, Soundwire Controller and Audio codec.
config MFD_ATC260X
tristate
select MFD_CORE

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

Some files were not shown because too many files have changed in this diff Show more