Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull ARM SoC driver updates from Arnd Bergmann:
"As usual, there are lots of minor driver changes across SoC platforms
from NXP, Amlogic, AMD Zynq, Mediatek, Qualcomm, Apple and Samsung.
These usually add support for additional chip variations in existing
drivers, but also add features or bugfixes.

The SCMI firmware subsystem gains a unified raw userspace interface
through debugfs, which can be used for validation purposes.

Newly added drivers include:

- New power management drivers for StarFive JH7110, Allwinner D1 and
Renesas RZ/V2M

- A driver for Qualcomm battery and power supply status

- A SoC device driver for identifying Nuvoton WPCM450 chips

- A regulator coupler driver for Mediatek MT81xxv"

* tag 'soc-drivers-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (165 commits)
power: supply: Introduce Qualcomm PMIC GLINK power supply
soc: apple: rtkit: Do not copy the reg state structure to the stack
soc: sunxi: SUN20I_PPU should depend on PM
memory: renesas-rpc-if: Remove redundant division of dummy
soc: qcom: socinfo: Add IDs for IPQ5332 and its variant
dt-bindings: arm: qcom,ids: Add IDs for IPQ5332 and its variant
dt-bindings: power: qcom,rpmpd: add RPMH_REGULATOR_LEVEL_LOW_SVS_L1
firmware: qcom_scm: Move qcom_scm.h to include/linux/firmware/qcom/
MAINTAINERS: Update qcom CPR maintainer entry
dt-bindings: firmware: document Qualcomm SM8550 SCM
dt-bindings: firmware: qcom,scm: add qcom,scm-sa8775p compatible
soc: qcom: socinfo: Add Soc IDs for IPQ8064 and variants
dt-bindings: arm: qcom,ids: Add Soc IDs for IPQ8064 and variants
soc: qcom: socinfo: Add support for new field in revision 17
soc: qcom: smd-rpm: Add IPQ9574 compatible
soc: qcom: pmic_glink: remove redundant calculation of svid
soc: qcom: stats: Populate all subsystem debugfs files
dt-bindings: soc: qcom,rpmh-rsc: Update to allow for generic nodes
soc: qcom: pmic_glink: add CONFIG_NET/CONFIG_OF dependencies
soc: qcom: pmic_glink: Introduce altmode support
...

+10107 -1389
+127
Documentation/ABI/testing/debugfs-driver-dcc
··· 1 + What: /sys/kernel/debug/dcc/.../ready 2 + Date: December 2022 3 + Contact: Souradeep Chowdhury <quic_schowdhu@quicinc.com> 4 + Description: 5 + This file is used to check the status of the dcc 6 + hardware if it's ready to receive user configurations. 7 + A 'Y' here indicates dcc is ready. 8 + 9 + What: /sys/kernel/debug/dcc/.../trigger 10 + Date: December 2022 11 + Contact: Souradeep Chowdhury <quic_schowdhu@quicinc.com> 12 + Description: 13 + This is the debugfs interface for manual software 14 + triggers. The trigger can be invoked by writing '1' 15 + to the file. 16 + 17 + What: /sys/kernel/debug/dcc/.../config_reset 18 + Date: December 2022 19 + Contact: Souradeep Chowdhury <quic_schowdhu@quicinc.com> 20 + Description: 21 + This file is used to reset the configuration of 22 + a dcc driver to the default configuration. When '1' 23 + is written to the file, all the previous addresses 24 + stored in the driver gets removed and users need to 25 + reconfigure addresses again. 26 + 27 + What: /sys/kernel/debug/dcc/.../[list-number]/config 28 + Date: December 2022 29 + Contact: Souradeep Chowdhury <quic_schowdhu@quicinc.com> 30 + Description: 31 + This stores the addresses of the registers which 32 + can be read in case of a hardware crash or manual 33 + software triggers. The input addresses type 34 + can be one of following dcc instructions: read, 35 + write, read-write, and loop type. The lists need to 36 + be configured sequentially and not in a overlapping 37 + manner; e.g. users can jump to list x only after 38 + list y is configured and enabled. The input format for 39 + each type is as follows: 40 + 41 + i) Read instruction 42 + 43 + :: 44 + 45 + echo R <addr> <n> <bus> >/sys/kernel/debug/dcc/../[list-number]/config 46 + 47 + where: 48 + 49 + <addr> 50 + The address to be read. 51 + 52 + <n> 53 + The addresses word count, starting from address <1>. 54 + Each word is 32 bits (4 bytes). If omitted, defaulted 55 + to 1. 56 + 57 + <bus type> 58 + The bus type, which can be either 'apb' or 'ahb'. 59 + The default is 'ahb' if leaved out. 60 + 61 + ii) Write instruction 62 + 63 + :: 64 + 65 + echo W <addr> <n> <bus type> > /sys/kernel/debug/dcc/../[list-number]/config 66 + 67 + where: 68 + 69 + <addr> 70 + The address to be written. 71 + 72 + <n> 73 + The value to be written at <addr>. 74 + 75 + <bus type> 76 + The bus type, which can be either 'apb' or 'ahb'. 77 + 78 + iii) Read-write instruction 79 + 80 + :: 81 + 82 + echo RW <addr> <n> <mask> > /sys/kernel/debug/dcc/../[list-number]/config 83 + 84 + where: 85 + 86 + <addr> 87 + The address to be read and written. 88 + 89 + <n> 90 + The value to be written at <addr>. 91 + 92 + <mask> 93 + The value mask. 94 + 95 + iv) Loop instruction 96 + 97 + :: 98 + 99 + echo L <loop count> <address count> <address>... > /sys/kernel/debug/dcc/../[list-number]/config 100 + 101 + where: 102 + 103 + <loop count> 104 + Number of iterations 105 + 106 + <address count> 107 + total number of addresses to be written 108 + 109 + <address> 110 + Space-separated list of addresses. 111 + 112 + What: /sys/kernel/debug/dcc/.../[list-number]/enable 113 + Date: December 2022 114 + Contact: Souradeep Chowdhury <quic_schowdhu@quicinc.com> 115 + Description: 116 + This debugfs interface is used for enabling the 117 + the dcc hardware. A file named "enable" is in the 118 + directory list number where users can enable/disable 119 + the specific list by writing boolean (1 or 0) to the 120 + file. 121 + 122 + On enabling the dcc, all the addresses specified 123 + by the user for the corresponding list is written 124 + into dcc sram which is read by the dcc hardware 125 + on manual or crash induced triggers. Lists must 126 + be configured and enabled sequentially, e.g. list 127 + 2 can only be enabled when list 1 have so.
+70
Documentation/ABI/testing/debugfs-scmi
··· 1 + What: /sys/kernel/debug/scmi/<n>/instance_name 2 + Date: March 2023 3 + KernelVersion: 6.3 4 + Contact: cristian.marussi@arm.com 5 + Description: The name of the underlying SCMI instance <n> described by 6 + all the debugfs accessors rooted at /sys/kernel/debug/scmi/<n>, 7 + expressed as the full name of the top DT SCMI node under which 8 + this SCMI instance is rooted. 9 + Users: Debugging, any userspace test suite 10 + 11 + What: /sys/kernel/debug/scmi/<n>/atomic_threshold_us 12 + Date: March 2023 13 + KernelVersion: 6.3 14 + Contact: cristian.marussi@arm.com 15 + Description: An optional time value, expressed in microseconds, representing, 16 + on this SCMI instance <n>, the threshold above which any SCMI 17 + command, advertised to have an higher-than-threshold execution 18 + latency, should not be considered for atomic mode of operation, 19 + even if requested. 20 + Users: Debugging, any userspace test suite 21 + 22 + What: /sys/kernel/debug/scmi/<n>/transport/type 23 + Date: March 2023 24 + KernelVersion: 6.3 25 + Contact: cristian.marussi@arm.com 26 + Description: A string representing the type of transport configured for this 27 + SCMI instance <n>. 28 + Users: Debugging, any userspace test suite 29 + 30 + What: /sys/kernel/debug/scmi/<n>/transport/is_atomic 31 + Date: March 2023 32 + KernelVersion: 6.3 33 + Contact: cristian.marussi@arm.com 34 + Description: A boolean stating if the transport configured on the underlying 35 + SCMI instance <n> is capable of atomic mode of operation. 36 + Users: Debugging, any userspace test suite 37 + 38 + What: /sys/kernel/debug/scmi/<n>/transport/max_rx_timeout_ms 39 + Date: March 2023 40 + KernelVersion: 6.3 41 + Contact: cristian.marussi@arm.com 42 + Description: Timeout in milliseconds allowed for SCMI synchronous replies 43 + for the currently configured SCMI transport for instance <n>. 44 + Users: Debugging, any userspace test suite 45 + 46 + What: /sys/kernel/debug/scmi/<n>/transport/max_msg_size 47 + Date: March 2023 48 + KernelVersion: 6.3 49 + Contact: cristian.marussi@arm.com 50 + Description: Max message size of allowed SCMI messages for the currently 51 + configured SCMI transport for instance <n>. 52 + Users: Debugging, any userspace test suite 53 + 54 + What: /sys/kernel/debug/scmi/<n>/transport/tx_max_msg 55 + Date: March 2023 56 + KernelVersion: 6.3 57 + Contact: cristian.marussi@arm.com 58 + Description: Max number of concurrently allowed in-flight SCMI messages for 59 + the currently configured SCMI transport for instance <n> on the 60 + TX channels. 61 + Users: Debugging, any userspace test suite 62 + 63 + What: /sys/kernel/debug/scmi/<n>/transport/rx_max_msg 64 + Date: March 2023 65 + KernelVersion: 6.3 66 + Contact: cristian.marussi@arm.com 67 + Description: Max number of concurrently allowed in-flight SCMI messages for 68 + the currently configured SCMI transport for instance <n> on the 69 + RX channels. 70 + Users: Debugging, any userspace test suite
+117
Documentation/ABI/testing/debugfs-scmi-raw
··· 1 + What: /sys/kernel/debug/scmi/<n>/raw/message 2 + Date: March 2023 3 + KernelVersion: 6.3 4 + Contact: cristian.marussi@arm.com 5 + Description: SCMI Raw synchronous message injection/snooping facility; write 6 + a complete SCMI synchronous command message (header included) 7 + in little-endian binary format to have it sent to the configured 8 + backend SCMI server for instance <n>. 9 + Any subsequently received response can be read from this same 10 + entry if it arrived within the configured timeout. 11 + Each write to the entry causes one command request to be built 12 + and sent while the replies are read back one message at time 13 + (receiving an EOF at each message boundary). 14 + Users: Debugging, any userspace test suite 15 + 16 + What: /sys/kernel/debug/scmi/<n>/raw/message_async 17 + Date: March 2023 18 + KernelVersion: 6.3 19 + Contact: cristian.marussi@arm.com 20 + Description: SCMI Raw asynchronous message injection/snooping facility; write 21 + a complete SCMI asynchronous command message (header included) 22 + in little-endian binary format to have it sent to the configured 23 + backend SCMI server for instance <n>. 24 + Any subsequently received response can be read from this same 25 + entry if it arrived within the configured timeout. 26 + Any additional delayed response received afterwards can be read 27 + from this same entry too if it arrived within the configured 28 + timeout. 29 + Each write to the entry causes one command request to be built 30 + and sent while the replies are read back one message at time 31 + (receiving an EOF at each message boundary). 32 + Users: Debugging, any userspace test suite 33 + 34 + What: /sys/kernel/debug/scmi/<n>/raw/errors 35 + Date: March 2023 36 + KernelVersion: 6.3 37 + Contact: cristian.marussi@arm.com 38 + Description: SCMI Raw message errors facility; any kind of timed-out or 39 + generally unexpectedly received SCMI message, for instance <n>, 40 + can be read from this entry. 41 + Each read gives back one message at time (receiving an EOF at 42 + each message boundary). 43 + Users: Debugging, any userspace test suite 44 + 45 + What: /sys/kernel/debug/scmi/<n>/raw/notification 46 + Date: March 2023 47 + KernelVersion: 6.3 48 + Contact: cristian.marussi@arm.com 49 + Description: SCMI Raw notification snooping facility; any notification 50 + emitted by the backend SCMI server, for instance <n>, can be 51 + read from this entry. 52 + Each read gives back one message at time (receiving an EOF at 53 + each message boundary). 54 + Users: Debugging, any userspace test suite 55 + 56 + What: /sys/kernel/debug/scmi/<n>/raw/reset 57 + Date: March 2023 58 + KernelVersion: 6.3 59 + Contact: cristian.marussi@arm.com 60 + Description: SCMI Raw stack reset facility; writing a value to this entry 61 + causes the internal queues of any kind of received message, 62 + still pending to be read out for instance <n>, to be immediately 63 + flushed. 64 + Can be used to reset and clean the SCMI Raw stack between to 65 + different test-run. 66 + Users: Debugging, any userspace test suite 67 + 68 + What: /sys/kernel/debug/scmi/<n>/raw/channels/<m>/message 69 + Date: March 2023 70 + KernelVersion: 6.3 71 + Contact: cristian.marussi@arm.com 72 + Description: SCMI Raw synchronous message injection/snooping facility; write 73 + a complete SCMI synchronous command message (header included) 74 + in little-endian binary format to have it sent to the configured 75 + backend SCMI server for instance <n> through the <m> transport 76 + channel. 77 + Any subsequently received response can be read from this same 78 + entry if it arrived on channel <m> within the configured 79 + timeout. 80 + Each write to the entry causes one command request to be built 81 + and sent while the replies are read back one message at time 82 + (receiving an EOF at each message boundary). 83 + Channel identifier <m> matches the SCMI protocol number which 84 + has been associated with this transport channel in the DT 85 + description, with base protocol number 0x10 being the default 86 + channel for this instance. 87 + Note that these per-channel entries rooted at <..>/channels 88 + exist only if the transport is configured to have more than 89 + one default channel. 90 + Users: Debugging, any userspace test suite 91 + 92 + What: /sys/kernel/debug/scmi/<n>/raw/channels/<m>/message_async 93 + Date: March 2023 94 + KernelVersion: 6.3 95 + Contact: cristian.marussi@arm.com 96 + Description: SCMI Raw asynchronous message injection/snooping facility; write 97 + a complete SCMI asynchronous command message (header included) 98 + in little-endian binary format to have it sent to the configured 99 + backend SCMI server for instance <n> through the <m> transport 100 + channel. 101 + Any subsequently received response can be read from this same 102 + entry if it arrived on channel <m> within the configured 103 + timeout. 104 + Any additional delayed response received afterwards can be read 105 + from this same entry too if it arrived within the configured 106 + timeout. 107 + Each write to the entry causes one command request to be built 108 + and sent while the replies are read back one message at time 109 + (receiving an EOF at each message boundary). 110 + Channel identifier <m> matches the SCMI protocol number which 111 + has been associated with this transport channel in the DT 112 + description, with base protocol number 0x10 being the default 113 + channel for this instance. 114 + Note that these per-channel entries rooted at <..>/channels 115 + exist only if the transport is configured to have more than 116 + one default channel. 117 + Users: Debugging, any userspace test suite
+4
Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
··· 31 31 - mediatek,mt8173-mmsys 32 32 - mediatek,mt8183-mmsys 33 33 - mediatek,mt8186-mmsys 34 + - mediatek,mt8188-vdosys0 34 35 - mediatek,mt8192-mmsys 36 + - mediatek,mt8195-vdosys1 37 + - mediatek,mt8195-vppsys0 38 + - mediatek,mt8195-vppsys1 35 39 - mediatek,mt8365-mmsys 36 40 - const: syscon 37 41
+39
Documentation/devicetree/bindings/firmware/amlogic,meson-gxbb-sm.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/firmware/amlogic,meson-gxbb-sm.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Amlogic Secure Monitor (SM) 8 + 9 + description: 10 + In the Amlogic SoCs the Secure Monitor code is used to provide access to the 11 + NVMEM, enable JTAG, set USB boot, etc... 12 + 13 + maintainers: 14 + - Neil Armstrong <neil.armstrong@linaro.org> 15 + 16 + properties: 17 + compatible: 18 + oneOf: 19 + - const: amlogic,meson-gxbb-sm 20 + - items: 21 + - const: amlogic,meson-gx-sm 22 + - const: amlogic,meson-gxbb-sm 23 + 24 + power-controller: 25 + type: object 26 + $ref: /schemas/power/amlogic,meson-sec-pwrc.yaml# 27 + 28 + required: 29 + - compatible 30 + 31 + additionalProperties: false 32 + 33 + examples: 34 + - | 35 + firmware { 36 + secure-monitor { 37 + compatible = "amlogic,meson-gxbb-sm"; 38 + }; 39 + };
-15
Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
··· 1 - * Amlogic Secure Monitor 2 - 3 - In the Amlogic SoCs the Secure Monitor code is used to provide access to the 4 - NVMEM, enable JTAG, set USB boot, etc... 5 - 6 - Required properties for the secure monitor node: 7 - - compatible: Should be "amlogic,meson-gxbb-sm" 8 - 9 - Example: 10 - 11 - firmware { 12 - sm: secure-monitor { 13 - compatible = "amlogic,meson-gxbb-sm"; 14 - }; 15 - };
+61 -7
Documentation/devicetree/bindings/firmware/qcom,scm.yaml
··· 38 38 - qcom,scm-msm8994 39 39 - qcom,scm-msm8996 40 40 - qcom,scm-msm8998 41 + - qcom,scm-qdu1000 42 + - qcom,scm-sa8775p 41 43 - qcom,scm-sc7180 42 44 - qcom,scm-sc7280 43 45 - qcom,scm-sc8280xp ··· 55 53 - qcom,scm-sm8250 56 54 - qcom,scm-sm8350 57 55 - qcom,scm-sm8450 56 + - qcom,scm-sm8550 58 57 - qcom,scm-qcs404 59 58 - const: qcom,scm 60 59 ··· 76 73 '#reset-cells': 77 74 const: 1 78 75 76 + interrupts: 77 + description: 78 + The wait-queue interrupt that firmware raises as part of handshake 79 + protocol to handle sleeping SCM calls. 80 + maxItems: 1 81 + 79 82 qcom,dload-mode: 80 83 $ref: /schemas/types.yaml#/definitions/phandle-array 81 84 items: ··· 91 82 description: TCSR hardware block 92 83 93 84 allOf: 85 + # Clocks 86 + - if: 87 + properties: 88 + compatible: 89 + contains: 90 + enum: 91 + - qcom,scm-apq8064 92 + - qcom,scm-apq8084 93 + - qcom,scm-mdm9607 94 + - qcom,scm-msm8226 95 + - qcom,scm-msm8660 96 + - qcom,scm-msm8916 97 + - qcom,scm-msm8953 98 + - qcom,scm-msm8960 99 + - qcom,scm-msm8974 100 + - qcom,scm-msm8976 101 + - qcom,scm-sm6375 102 + then: 103 + required: 104 + - clocks 105 + - clock-names 106 + else: 107 + properties: 108 + clock-names: false 109 + clocks: false 110 + 94 111 - if: 95 112 properties: 96 113 compatible: ··· 135 100 clocks: 136 101 maxItems: 1 137 102 138 - required: 139 - - clocks 140 - - clock-names 141 - 142 103 - if: 143 104 properties: 144 105 compatible: ··· 142 111 enum: 143 112 - qcom,scm-apq8084 144 113 - qcom,scm-mdm9607 114 + - qcom,scm-msm8226 145 115 - qcom,scm-msm8916 146 116 - qcom,scm-msm8953 147 117 - qcom,scm-msm8974 ··· 159 127 minItems: 3 160 128 maxItems: 3 161 129 162 - required: 163 - - clocks 164 - - clock-names 130 + # Interconnects 131 + - if: 132 + not: 133 + properties: 134 + compatible: 135 + contains: 136 + enum: 137 + - qcom,scm-sm8450 138 + - qcom,scm-sm8550 139 + then: 140 + properties: 141 + interconnects: false 142 + 143 + # Interrupts 144 + - if: 145 + not: 146 + properties: 147 + compatible: 148 + contains: 149 + enum: 150 + - qcom,scm-sm8450 151 + - qcom,scm-sm8550 152 + then: 153 + properties: 154 + interrupts: false 165 155 166 156 required: 167 157 - compatible
+1
Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
··· 26 26 enum: 27 27 - mediatek,mt6323-keys 28 28 - mediatek,mt6331-keys 29 + - mediatek,mt6357-keys 29 30 - mediatek,mt6358-keys 30 31 - mediatek,mt6397-keys 31 32
+1 -1
Documentation/devicetree/bindings/leds/leds-mt6323.txt
··· 9 9 For MT6323 MFD bindings see: 10 10 Documentation/devicetree/bindings/mfd/mt6397.txt 11 11 For MediaTek PMIC wrapper bindings see: 12 - Documentation/devicetree/bindings/soc/mediatek/pwrap.txt 12 + Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml 13 13 14 14 Required properties: 15 15 - compatible : Must be "mediatek,mt6323-led"
+111
Documentation/devicetree/bindings/mfd/mediatek,mt6357.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mfd/mediatek,mt6357.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: MediaTek MT6357 PMIC 8 + 9 + maintainers: 10 + - Flora Fu <flora.fu@mediatek.com> 11 + - Alexandre Mergnat <amergnat@baylibre.com> 12 + 13 + description: | 14 + MT6357 is a power management system chip containing 5 buck 15 + converters and 29 LDOs. Supported features are audio codec, 16 + USB battery charging, fuel gauge, RTC 17 + 18 + This is a multifunction device with the following sub modules: 19 + - Regulator 20 + - RTC 21 + - Keys 22 + 23 + It is interfaced to host controller using SPI interface by a proprietary hardware 24 + called PMIC wrapper or pwrap. This MFD is a child device of pwrap. 25 + See the following for pwrap node definitions: 26 + Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml 27 + 28 + properties: 29 + compatible: 30 + const: mediatek,mt6357 31 + 32 + interrupts: 33 + maxItems: 1 34 + 35 + interrupt-controller: true 36 + 37 + "#interrupt-cells": 38 + const: 2 39 + 40 + regulators: 41 + type: object 42 + $ref: /schemas/regulator/mediatek,mt6357-regulator.yaml 43 + description: 44 + List of MT6357 BUCKs and LDOs regulators. 45 + 46 + rtc: 47 + type: object 48 + $ref: /schemas/rtc/rtc.yaml# 49 + description: 50 + MT6357 Real Time Clock. 51 + properties: 52 + compatible: 53 + const: mediatek,mt6357-rtc 54 + start-year: true 55 + required: 56 + - compatible 57 + 58 + keys: 59 + type: object 60 + $ref: /schemas/input/mediatek,pmic-keys.yaml 61 + description: 62 + MT6357 power and home keys. 63 + 64 + required: 65 + - compatible 66 + - regulators 67 + 68 + additionalProperties: false 69 + 70 + examples: 71 + - | 72 + #include <dt-bindings/interrupt-controller/arm-gic.h> 73 + 74 + pwrap { 75 + pmic { 76 + compatible = "mediatek,mt6357"; 77 + 78 + interrupt-parent = <&pio>; 79 + interrupts = <145 IRQ_TYPE_LEVEL_HIGH>; 80 + interrupt-controller; 81 + #interrupt-cells = <2>; 82 + 83 + regulators { 84 + mt6357_vproc_reg: buck-vproc { 85 + regulator-name = "vproc"; 86 + regulator-min-microvolt = <518750>; 87 + regulator-max-microvolt = <1312500>; 88 + regulator-ramp-delay = <6250>; 89 + regulator-enable-ramp-delay = <220>; 90 + regulator-always-on; 91 + }; 92 + 93 + // ... 94 + 95 + mt6357_vusb33_reg: ldo-vusb33 { 96 + regulator-name = "vusb33"; 97 + regulator-min-microvolt = <3000000>; 98 + regulator-max-microvolt = <3100000>; 99 + regulator-enable-ramp-delay = <264>; 100 + }; 101 + }; 102 + 103 + rtc { 104 + compatible = "mediatek,mt6357-rtc"; 105 + }; 106 + 107 + keys { 108 + compatible = "mediatek,mt6357-keys"; 109 + }; 110 + }; 111 + };
+1 -1
Documentation/devicetree/bindings/mfd/mt6397.txt
··· 13 13 It is interfaced to host controller using SPI interface by a proprietary hardware 14 14 called PMIC wrapper or pwrap. MT6397/MT6323 MFD is a child device of pwrap. 15 15 See the following for pwarp node definitions: 16 - ../soc/mediatek/pwrap.txt 16 + ../soc/mediatek/mediatek,pwrap.yaml 17 17 18 18 This document describes the binding for MFD device and its sub module. 19 19
-283
Documentation/devicetree/bindings/mfd/qcom-rpm.txt
··· 1 - Qualcomm Resource Power Manager (RPM) 2 - 3 - This driver is used to interface with the Resource Power Manager (RPM) found in 4 - various Qualcomm platforms. The RPM allows each component in the system to vote 5 - for state of the system resources, such as clocks, regulators and bus 6 - frequencies. 7 - 8 - - compatible: 9 - Usage: required 10 - Value type: <string> 11 - Definition: must be one of: 12 - "qcom,rpm-apq8064" 13 - "qcom,rpm-msm8660" 14 - "qcom,rpm-msm8960" 15 - "qcom,rpm-ipq8064" 16 - "qcom,rpm-mdm9615" 17 - 18 - - reg: 19 - Usage: required 20 - Value type: <prop-encoded-array> 21 - Definition: base address and size of the RPM's message ram 22 - 23 - - interrupts: 24 - Usage: required 25 - Value type: <prop-encoded-array> 26 - Definition: three entries specifying the RPM's: 27 - 1. acknowledgement interrupt 28 - 2. error interrupt 29 - 3. wakeup interrupt 30 - 31 - - interrupt-names: 32 - Usage: required 33 - Value type: <string-array> 34 - Definition: must be the three strings "ack", "err" and "wakeup", in order 35 - 36 - - qcom,ipc: 37 - Usage: required 38 - Value type: <prop-encoded-array> 39 - 40 - Definition: three entries specifying the outgoing ipc bit used for 41 - signaling the RPM: 42 - - phandle to a syscon node representing the apcs registers 43 - - u32 representing offset to the register within the syscon 44 - - u32 representing the ipc bit within the register 45 - 46 - 47 - = SUBNODES 48 - 49 - The RPM exposes resources to its subnodes. The below bindings specify the set 50 - of valid subnodes that can operate on these resources. 51 - 52 - == Regulators 53 - 54 - Regulator nodes are identified by their compatible: 55 - 56 - - compatible: 57 - Usage: required 58 - Value type: <string> 59 - Definition: must be one of: 60 - "qcom,rpm-pm8058-regulators" 61 - "qcom,rpm-pm8901-regulators" 62 - "qcom,rpm-pm8921-regulators" 63 - "qcom,rpm-pm8018-regulators" 64 - "qcom,rpm-smb208-regulators" 65 - 66 - - vdd_l0_l1_lvs-supply: 67 - - vdd_l2_l11_l12-supply: 68 - - vdd_l3_l4_l5-supply: 69 - - vdd_l6_l7-supply: 70 - - vdd_l8-supply: 71 - - vdd_l9-supply: 72 - - vdd_l10-supply: 73 - - vdd_l13_l16-supply: 74 - - vdd_l14_l15-supply: 75 - - vdd_l17_l18-supply: 76 - - vdd_l19_l20-supply: 77 - - vdd_l21-supply: 78 - - vdd_l22-supply: 79 - - vdd_l23_l24_l25-supply: 80 - - vdd_ncp-supply: 81 - - vdd_s0-supply: 82 - - vdd_s1-supply: 83 - - vdd_s2-supply: 84 - - vdd_s3-supply: 85 - - vdd_s4-supply: 86 - Usage: optional (pm8058 only) 87 - Value type: <phandle> 88 - Definition: reference to regulator supplying the input pin, as 89 - described in the data sheet 90 - 91 - - lvs0_in-supply: 92 - - lvs1_in-supply: 93 - - lvs2_in-supply: 94 - - lvs3_in-supply: 95 - - mvs_in-supply: 96 - - vdd_l0-supply: 97 - - vdd_l1-supply: 98 - - vdd_l2-supply: 99 - - vdd_l3-supply: 100 - - vdd_l4-supply: 101 - - vdd_l5-supply: 102 - - vdd_l6-supply: 103 - - vdd_s0-supply: 104 - - vdd_s1-supply: 105 - - vdd_s2-supply: 106 - - vdd_s3-supply: 107 - - vdd_s4-supply: 108 - Usage: optional (pm8901 only) 109 - Value type: <phandle> 110 - Definition: reference to regulator supplying the input pin, as 111 - described in the data sheet 112 - 113 - - vdd_l1_l2_l12_l18-supply: 114 - - vdd_l3_l15_l17-supply: 115 - - vdd_l4_l14-supply: 116 - - vdd_l5_l8_l16-supply: 117 - - vdd_l6_l7-supply: 118 - - vdd_l9_l11-supply: 119 - - vdd_l10_l22-supply: 120 - - vdd_l21_l23_l29-supply: 121 - - vdd_l24-supply: 122 - - vdd_l25-supply: 123 - - vdd_l26-supply: 124 - - vdd_l27-supply: 125 - - vdd_l28-supply: 126 - - vdd_ncp-supply: 127 - - vdd_s1-supply: 128 - - vdd_s2-supply: 129 - - vdd_s4-supply: 130 - - vdd_s5-supply: 131 - - vdd_s6-supply: 132 - - vdd_s7-supply: 133 - - vdd_s8-supply: 134 - - vin_5vs-supply: 135 - - vin_lvs1_3_6-supply: 136 - - vin_lvs2-supply: 137 - - vin_lvs4_5_7-supply: 138 - Usage: optional (pm8921 only) 139 - Value type: <phandle> 140 - Definition: reference to regulator supplying the input pin, as 141 - described in the data sheet 142 - 143 - - vin_lvs1-supply: 144 - - vdd_l7-supply: 145 - - vdd_l8-supply: 146 - - vdd_l9_l10_l11_l12-supply: 147 - Usage: optional (pm8018 only) 148 - Value type: <phandle> 149 - Definition: reference to regulator supplying the input pin, as 150 - described in the data sheet 151 - 152 - The regulator node houses sub-nodes for each regulator within the device. Each 153 - sub-node is identified using the node's name, with valid values listed for each 154 - of the pmics below. 155 - 156 - pm8058: 157 - l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, 158 - l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, s0, s1, s2, s3, s4, 159 - lvs0, lvs1, ncp 160 - 161 - pm8901: 162 - l0, l1, l2, l3, l4, l5, l6, s0, s1, s2, s3, s4, lvs0, lvs1, lvs2, lvs3, 163 - mvs 164 - 165 - pm8921: 166 - s1, s2, s3, s4, s7, s8, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, 167 - l12, l14, l15, l16, l17, l18, l21, l22, l23, l24, l25, l26, l27, l28, 168 - l29, lvs1, lvs2, lvs3, lvs4, lvs5, lvs6, lvs7, usb-switch, hdmi-switch, 169 - ncp 170 - 171 - pm8018: 172 - s1, s2, s3, s4, s5, , l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, 173 - l12, l14, lvs1 174 - 175 - smb208: 176 - s1a, s1b, s2a, s2b 177 - 178 - The content of each sub-node is defined by the standard binding for regulators - 179 - see regulator.txt - with additional custom properties described below: 180 - 181 - === Switch-mode Power Supply regulator custom properties 182 - 183 - - bias-pull-down: 184 - Usage: optional 185 - Value type: <empty> 186 - Definition: enable pull down of the regulator when inactive 187 - 188 - - qcom,switch-mode-frequency: 189 - Usage: required 190 - Value type: <u32> 191 - Definition: Frequency (Hz) of the switch-mode power supply; 192 - must be one of: 193 - 19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 194 - 2740000, 2400000, 2130000, 1920000, 1750000, 1600000, 195 - 1480000, 1370000, 1280000, 1200000 196 - 197 - - qcom,force-mode: 198 - Usage: optional (default if no other qcom,force-mode is specified) 199 - Value type: <u32> 200 - Definition: indicates that the regulator should be forced to a 201 - particular mode, valid values are: 202 - QCOM_RPM_FORCE_MODE_NONE - do not force any mode 203 - QCOM_RPM_FORCE_MODE_LPM - force into low power mode 204 - QCOM_RPM_FORCE_MODE_HPM - force into high power mode 205 - QCOM_RPM_FORCE_MODE_AUTO - allow regulator to automatically 206 - select its own mode based on 207 - realtime current draw, only for: 208 - pm8921 smps and ftsmps 209 - 210 - - qcom,power-mode-hysteretic: 211 - Usage: optional 212 - Value type: <empty> 213 - Definition: select that the power supply should operate in hysteretic 214 - mode, instead of the default pwm mode 215 - 216 - === Low-dropout regulator custom properties 217 - 218 - - bias-pull-down: 219 - Usage: optional 220 - Value type: <empty> 221 - Definition: enable pull down of the regulator when inactive 222 - 223 - - qcom,force-mode: 224 - Usage: optional 225 - Value type: <u32> 226 - Definition: indicates that the regulator should not be forced to any 227 - particular mode, valid values are: 228 - QCOM_RPM_FORCE_MODE_NONE - do not force any mode 229 - QCOM_RPM_FORCE_MODE_LPM - force into low power mode 230 - QCOM_RPM_FORCE_MODE_HPM - force into high power mode 231 - QCOM_RPM_FORCE_MODE_BYPASS - set regulator to use bypass 232 - mode, i.e. to act as a switch 233 - and not regulate, only for: 234 - pm8921 pldo, nldo and nldo1200 235 - 236 - === Negative Charge Pump custom properties 237 - 238 - - qcom,switch-mode-frequency: 239 - Usage: required 240 - Value type: <u32> 241 - Definition: Frequency (Hz) of the switch mode power supply; 242 - must be one of: 243 - 19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 244 - 2740000, 2400000, 2130000, 1920000, 1750000, 1600000, 245 - 1480000, 1370000, 1280000, 1200000 246 - 247 - = EXAMPLE 248 - 249 - #include <dt-bindings/mfd/qcom-rpm.h> 250 - 251 - rpm@108000 { 252 - compatible = "qcom,rpm-msm8960"; 253 - reg = <0x108000 0x1000>; 254 - qcom,ipc = <&apcs 0x8 2>; 255 - 256 - interrupts = <0 19 0>, <0 21 0>, <0 22 0>; 257 - interrupt-names = "ack", "err", "wakeup"; 258 - 259 - regulators { 260 - compatible = "qcom,rpm-pm8921-regulators"; 261 - vdd_l1_l2_l12_l18-supply = <&pm8921_s4>; 262 - 263 - s1 { 264 - regulator-min-microvolt = <1225000>; 265 - regulator-max-microvolt = <1225000>; 266 - 267 - bias-pull-down; 268 - 269 - qcom,switch-mode-frequency = <3200000>; 270 - }; 271 - 272 - pm8921_s4: s4 { 273 - regulator-min-microvolt = <1800000>; 274 - regulator-max-microvolt = <1800000>; 275 - 276 - qcom,switch-mode-frequency = <1600000>; 277 - bias-pull-down; 278 - 279 - qcom,force-mode = <QCOM_RPM_FORCE_MODE_AUTO>; 280 - }; 281 - }; 282 - }; 283 -
+2 -3
Documentation/devicetree/bindings/phy/samsung,dp-video-phy.yaml
··· 22 22 23 23 samsung,pmu-syscon: 24 24 $ref: /schemas/types.yaml#/definitions/phandle 25 + deprecated: true 25 26 description: 26 - Phandle to PMU system controller interface. 27 + Phandle to PMU system controller interface (if not a child of PMU). 27 28 28 29 required: 29 30 - compatible 30 31 - "#phy-cells" 31 - - samsung,pmu-syscon 32 32 33 33 additionalProperties: false 34 34 ··· 36 36 - | 37 37 phy { 38 38 compatible = "samsung,exynos5420-dp-video-phy"; 39 - samsung,pmu-syscon = <&pmu_system_controller>; 40 39 #phy-cells = <0>; 41 40 };
+5 -6
Documentation/devicetree/bindings/phy/samsung,mipi-video-phy.yaml
··· 35 35 36 36 syscon: 37 37 $ref: /schemas/types.yaml#/definitions/phandle 38 + deprecated: true 38 39 description: 39 40 Phandle to PMU system controller interface, valid only for 40 - samsung,s5pv210-mipi-video-phy and samsung,exynos5420-mipi-video-phy. 41 + samsung,s5pv210-mipi-video-phy and samsung,exynos5420-mipi-video-phy (if 42 + not a child of PMU). 41 43 42 44 samsung,pmu-syscon: 43 45 $ref: /schemas/types.yaml#/definitions/phandle 46 + deprecated: true 44 47 description: 45 48 Phandle to PMU system controller interface, valid for 46 - samsung,exynos5433-mipi-video-phy. 49 + samsung,exynos5433-mipi-video-phy (if not a child of PMU). 47 50 48 51 samsung,disp-sysreg: 49 52 $ref: /schemas/types.yaml#/definitions/phandle ··· 84 81 samsung,disp-sysreg: false 85 82 samsung,cam0-sysreg: false 86 83 samsung,cam1-sysreg: false 87 - required: 88 - - syscon 89 84 else: 90 85 properties: 91 86 syscon: false 92 87 required: 93 - - samsung,pmu-syscon 94 88 - samsung,disp-sysreg 95 89 - samsung,cam0-sysreg 96 90 - samsung,cam1-sysreg ··· 99 99 phy { 100 100 compatible = "samsung,exynos5433-mipi-video-phy"; 101 101 #phy-cells = <1>; 102 - samsung,pmu-syscon = <&pmu_system_controller>; 103 102 samsung,cam0-sysreg = <&syscon_cam0>; 104 103 samsung,cam1-sysreg = <&syscon_cam1>; 105 104 samsung,disp-sysreg = <&syscon_disp>;
+54
Documentation/devicetree/bindings/power/allwinner,sun20i-d1-ppu.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/power/allwinner,sun20i-d1-ppu.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Allwinner SoCs PPU power domain controller 8 + 9 + maintainers: 10 + - Samuel Holland <samuel@sholland.org> 11 + 12 + description: 13 + D1 and related SoCs contain a power domain controller for the CPUs, GPU, and 14 + video-related hardware. 15 + 16 + properties: 17 + compatible: 18 + enum: 19 + - allwinner,sun20i-d1-ppu 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + clocks: 25 + description: Bus Clock 26 + maxItems: 1 27 + 28 + resets: 29 + maxItems: 1 30 + 31 + '#power-domain-cells': 32 + const: 1 33 + 34 + required: 35 + - compatible 36 + - reg 37 + - clocks 38 + - resets 39 + - '#power-domain-cells' 40 + 41 + additionalProperties: false 42 + 43 + examples: 44 + - | 45 + #include <dt-bindings/clock/sun20i-d1-r-ccu.h> 46 + #include <dt-bindings/reset/sun20i-d1-r-ccu.h> 47 + 48 + ppu: power-controller@7001000 { 49 + compatible = "allwinner,sun20i-d1-ppu"; 50 + reg = <0x7001000 0x1000>; 51 + clocks = <&r_ccu CLK_BUS_R_PPU>; 52 + resets = <&r_ccu RST_BUS_R_PPU>; 53 + #power-domain-cells = <1>; 54 + };
+2 -2
Documentation/devicetree/bindings/power/amlogic,meson-gx-pwrc.txt
··· 1 - Amlogic Meson Power Controller 2 - ============================== 1 + Amlogic Meson Power Controller (deprecated) 2 + =========================================== 3 3 4 4 The Amlogic Meson SoCs embeds an internal Power domain controller. 5 5
+2
Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
··· 28 28 - mediatek,mt8173-power-controller 29 29 - mediatek,mt8183-power-controller 30 30 - mediatek,mt8186-power-controller 31 + - mediatek,mt8188-power-controller 31 32 - mediatek,mt8192-power-controller 32 33 - mediatek,mt8195-power-controller 33 34 ··· 85 84 "include/dt-bindings/power/mt8167-power.h" - for MT8167 type power domain. 86 85 "include/dt-bindings/power/mt8173-power.h" - for MT8173 type power domain. 87 86 "include/dt-bindings/power/mt8183-power.h" - for MT8183 type power domain. 87 + "include/dt-bindings/power/mediatek,mt8188-power.h" - for MT8188 type power domain. 88 88 "include/dt-bindings/power/mt8192-power.h" - for MT8192 type power domain. 89 89 "include/dt-bindings/power/mt8195-power.h" - for MT8195 type power domain. 90 90 maxItems: 1
+1 -1
Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
··· 30 30 - qcom,qcs404-rpmpd 31 31 - qcom,qdu1000-rpmhpd 32 32 - qcom,sa8540p-rpmhpd 33 + - qcom,sa8775p-rpmhpd 33 34 - qcom,sdm660-rpmpd 34 35 - qcom,sc7180-rpmhpd 35 36 - qcom,sc7280-rpmhpd ··· 40 39 - qcom,sdm845-rpmhpd 41 40 - qcom,sdx55-rpmhpd 42 41 - qcom,sdx65-rpmhpd 43 - - qcom,sm4250-rpmpd 44 42 - qcom,sm6115-rpmpd 45 43 - qcom,sm6125-rpmpd 46 44 - qcom,sm6350-rpmhpd
+45
Documentation/devicetree/bindings/power/starfive,jh7110-pmu.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/power/starfive,jh7110-pmu.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: StarFive JH7110 Power Management Unit 8 + 9 + maintainers: 10 + - Walker Chen <walker.chen@starfivetech.com> 11 + 12 + description: | 13 + StarFive JH7110 SoC includes support for multiple power domains which can be 14 + powered on/off by software based on different application scenes to save power. 15 + 16 + properties: 17 + compatible: 18 + enum: 19 + - starfive,jh7110-pmu 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + interrupts: 25 + maxItems: 1 26 + 27 + "#power-domain-cells": 28 + const: 1 29 + 30 + required: 31 + - compatible 32 + - reg 33 + - interrupts 34 + - "#power-domain-cells" 35 + 36 + additionalProperties: false 37 + 38 + examples: 39 + - | 40 + pwrc: power-controller@17030000 { 41 + compatible = "starfive,jh7110-pmu"; 42 + reg = <0x17030000 0x10000>; 43 + interrupts = <111>; 44 + #power-domain-cells = <1>; 45 + };
+4 -2
Documentation/devicetree/bindings/reserved-memory/qcom,rmtfs-mem.yaml
··· 27 27 identifier of the client to use this region for buffers 28 28 29 29 qcom,vmid: 30 - $ref: /schemas/types.yaml#/definitions/uint32 30 + $ref: /schemas/types.yaml#/definitions/uint32-array 31 31 description: > 32 - vmid of the remote processor, to set up memory protection 32 + Array of vmids of the remote processors, to set up memory protection 33 + minItems: 1 34 + maxItems: 2 33 35 34 36 required: 35 37 - qcom,client-id
+8 -1
Documentation/devicetree/bindings/riscv/sifive,ccache0.yaml
··· 38 38 - sifive,fu740-c000-ccache 39 39 - const: cache 40 40 - items: 41 + - const: starfive,jh7110-ccache 42 + - const: sifive,ccache0 43 + - const: cache 44 + - items: 41 45 - const: microchip,mpfs-ccache 42 46 - const: sifive,fu540-c000-ccache 43 47 - const: cache ··· 88 84 contains: 89 85 enum: 90 86 - sifive,fu740-c000-ccache 87 + - starfive,jh7110-ccache 91 88 - microchip,mpfs-ccache 92 89 93 90 then: ··· 109 104 properties: 110 105 compatible: 111 106 contains: 112 - const: sifive,fu740-c000-ccache 107 + enum: 108 + - sifive,fu740-c000-ccache 109 + - starfive,jh7110-ccache 113 110 114 111 then: 115 112 properties:
+1
Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
··· 32 32 - mediatek,mt8183-disp-mutex 33 33 - mediatek,mt8186-disp-mutex 34 34 - mediatek,mt8186-mdp3-mutex 35 + - mediatek,mt8188-disp-mutex 35 36 - mediatek,mt8192-disp-mutex 36 37 - mediatek,mt8195-disp-mutex 37 38
+147
Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/soc/mediatek/mediatek,pwrap.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Mediatek PMIC Wrapper 8 + 9 + maintainers: 10 + - Flora Fu <flora.fu@mediatek.com> 11 + - Alexandre Mergnat <amergnat@baylibre.com> 12 + 13 + description: 14 + On MediaTek SoCs the PMIC is connected via SPI. The SPI master interface 15 + is not directly visible to the CPU, but only through the PMIC wrapper 16 + inside the SoC. The communication between the SoC and the PMIC can 17 + optionally be encrypted. Also a non standard Dual IO SPI mode can be 18 + used to increase speed. 19 + 20 + IP Pairing 21 + 22 + On MT8135 the pins of some SoC internal peripherals can be on the PMIC. 23 + The signals of these pins are routed over the SPI bus using the pwrap 24 + bridge. In the binding description below the properties needed for bridging 25 + are marked with "IP Pairing". These are optional on SoCs which do not support 26 + IP Pairing 27 + 28 + properties: 29 + compatible: 30 + oneOf: 31 + - items: 32 + - enum: 33 + - mediatek,mt2701-pwrap 34 + - mediatek,mt6765-pwrap 35 + - mediatek,mt6779-pwrap 36 + - mediatek,mt6797-pwrap 37 + - mediatek,mt6873-pwrap 38 + - mediatek,mt7622-pwrap 39 + - mediatek,mt8135-pwrap 40 + - mediatek,mt8173-pwrap 41 + - mediatek,mt8183-pwrap 42 + - mediatek,mt8186-pwrap 43 + - mediatek,mt8188-pwrap 44 + - mediatek,mt8195-pwrap 45 + - mediatek,mt8365-pwrap 46 + - mediatek,mt8516-pwrap 47 + - items: 48 + - enum: 49 + - mediatek,mt8186-pwrap 50 + - mediatek,mt8195-pwrap 51 + - const: syscon 52 + 53 + reg: 54 + minItems: 1 55 + items: 56 + - description: PMIC wrapper registers 57 + - description: IP pairing registers 58 + 59 + reg-names: 60 + minItems: 1 61 + items: 62 + - const: pwrap 63 + - const: pwrap-bridge 64 + 65 + interrupts: 66 + maxItems: 1 67 + 68 + clocks: 69 + minItems: 2 70 + items: 71 + - description: SPI bus clock 72 + - description: Main module clock 73 + - description: System module clock 74 + - description: Timer module clock 75 + 76 + clock-names: 77 + minItems: 2 78 + items: 79 + - const: spi 80 + - const: wrap 81 + - const: sys 82 + - const: tmr 83 + 84 + resets: 85 + minItems: 1 86 + items: 87 + - description: PMIC wrapper reset 88 + - description: IP pairing reset 89 + 90 + reset-names: 91 + minItems: 1 92 + items: 93 + - const: pwrap 94 + - const: pwrap-bridge 95 + 96 + pmic: 97 + type: object 98 + 99 + required: 100 + - compatible 101 + - reg 102 + - reg-names 103 + - interrupts 104 + - clocks 105 + - clock-names 106 + 107 + dependentRequired: 108 + resets: [reset-names] 109 + 110 + allOf: 111 + - if: 112 + properties: 113 + compatible: 114 + contains: 115 + const: mediatek,mt8365-pwrap 116 + then: 117 + properties: 118 + clocks: 119 + minItems: 4 120 + 121 + clock-names: 122 + minItems: 4 123 + 124 + additionalProperties: false 125 + 126 + examples: 127 + - | 128 + #include <dt-bindings/interrupt-controller/irq.h> 129 + #include <dt-bindings/interrupt-controller/arm-gic.h> 130 + #include <dt-bindings/reset/mt8135-resets.h> 131 + 132 + soc { 133 + #address-cells = <2>; 134 + #size-cells = <2>; 135 + pwrap@1000f000 { 136 + compatible = "mediatek,mt8135-pwrap"; 137 + reg = <0 0x1000f000 0 0x1000>, 138 + <0 0x11017000 0 0x1000>; 139 + reg-names = "pwrap", "pwrap-bridge"; 140 + interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>; 141 + clocks = <&clk26m>, <&clk26m>; 142 + clock-names = "spi", "wrap"; 143 + resets = <&infracfg MT8135_INFRA_PMIC_WRAP_RST>, 144 + <&pericfg MT8135_PERI_PWRAP_BRIDGE_SW_RST>; 145 + reset-names = "pwrap", "pwrap-bridge"; 146 + }; 147 + };
-75
Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
··· 1 - MediaTek PMIC Wrapper Driver 2 - 3 - This document describes the binding for the MediaTek PMIC wrapper. 4 - 5 - On MediaTek SoCs the PMIC is connected via SPI. The SPI master interface 6 - is not directly visible to the CPU, but only through the PMIC wrapper 7 - inside the SoC. The communication between the SoC and the PMIC can 8 - optionally be encrypted. Also a non standard Dual IO SPI mode can be 9 - used to increase speed. 10 - 11 - IP Pairing 12 - 13 - on MT8135 the pins of some SoC internal peripherals can be on the PMIC. 14 - The signals of these pins are routed over the SPI bus using the pwrap 15 - bridge. In the binding description below the properties needed for bridging 16 - are marked with "IP Pairing". These are optional on SoCs which do not support 17 - IP Pairing 18 - 19 - Required properties in pwrap device node. 20 - - compatible: 21 - "mediatek,mt2701-pwrap" for MT2701/7623 SoCs 22 - "mediatek,mt6765-pwrap" for MT6765 SoCs 23 - "mediatek,mt6779-pwrap" for MT6779 SoCs 24 - "mediatek,mt6797-pwrap" for MT6797 SoCs 25 - "mediatek,mt6873-pwrap" for MT6873/8192 SoCs 26 - "mediatek,mt7622-pwrap" for MT7622 SoCs 27 - "mediatek,mt8135-pwrap" for MT8135 SoCs 28 - "mediatek,mt8173-pwrap" for MT8173 SoCs 29 - "mediatek,mt8183-pwrap" for MT8183 SoCs 30 - "mediatek,mt8186-pwrap" for MT8186 SoCs 31 - "mediatek,mt8188-pwrap", "mediatek,mt8195-pwrap" for MT8188 SoCs 32 - "mediatek,mt8195-pwrap" for MT8195 SoCs 33 - "mediatek,mt8365-pwrap" for MT8365 SoCs 34 - "mediatek,mt8516-pwrap" for MT8516 SoCs 35 - - interrupts: IRQ for pwrap in SOC 36 - - reg-names: "pwrap" is required; "pwrap-bridge" is optional. 37 - "pwrap": Main registers base 38 - "pwrap-bridge": bridge base (IP Pairing) 39 - - reg: Must contain an entry for each entry in reg-names. 40 - - clock-names: Must include the following entries: 41 - "spi": SPI bus clock 42 - "wrap": Main module clock 43 - "sys": Optional system module clock 44 - "tmr": Optional timer module clock 45 - - clocks: Must contain an entry for each entry in clock-names. 46 - 47 - Optional properities: 48 - - reset-names: Some SoCs include the following entries: 49 - "pwrap" 50 - "pwrap-bridge" (IP Pairing) 51 - - resets: Must contain an entry for each entry in reset-names. 52 - - pmic: Using either MediaTek PMIC MFD as the child device of pwrap 53 - See the following for child node definitions: 54 - Documentation/devicetree/bindings/mfd/mt6397.txt 55 - or the regulator-only device as the child device of pwrap, such as MT6380. 56 - See the following definitions for such kinds of devices. 57 - Documentation/devicetree/bindings/regulator/mt6380-regulator.txt 58 - 59 - Example: 60 - pwrap: pwrap@1000f000 { 61 - compatible = "mediatek,mt8135-pwrap"; 62 - reg = <0 0x1000f000 0 0x1000>, 63 - <0 0x11017000 0 0x1000>; 64 - reg-names = "pwrap", "pwrap-bridge"; 65 - interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>; 66 - resets = <&infracfg MT8135_INFRA_PMIC_WRAP_RST>, 67 - <&pericfg MT8135_PERI_PWRAP_BRIDGE_SW_RST>; 68 - reset-names = "pwrap", "pwrap-bridge"; 69 - clocks = <&clk26m>, <&clk26m>; 70 - clock-names = "spi", "wrap"; 71 - 72 - pmic { 73 - compatible = "mediatek,mt6397"; 74 - }; 75 - };
+44
Documentation/devicetree/bindings/soc/qcom/qcom,dcc.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/soc/qcom/qcom,dcc.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Data Capture and Compare 8 + 9 + maintainers: 10 + - Souradeep Chowdhury <quic_schowdhu@quicinc.com> 11 + 12 + description: | 13 + DCC (Data Capture and Compare) is a DMA engine which is used to save 14 + configuration data or system memory contents during catastrophic failure 15 + or SW trigger. DCC is used to capture and store data for debugging purpose 16 + 17 + properties: 18 + compatible: 19 + items: 20 + - enum: 21 + - qcom,sm8150-dcc 22 + - qcom,sc7280-dcc 23 + - qcom,sc7180-dcc 24 + - qcom,sdm845-dcc 25 + - const: qcom,dcc 26 + 27 + reg: 28 + items: 29 + - description: DCC base 30 + - description: DCC RAM base 31 + 32 + required: 33 + - compatible 34 + - reg 35 + 36 + additionalProperties: false 37 + 38 + examples: 39 + - | 40 + dma@10a2000{ 41 + compatible = "qcom,sm8150-dcc", "qcom,dcc"; 42 + reg = <0x010a2000 0x1000>, 43 + <0x010ad000 0x2000>; 44 + };
+36
Documentation/devicetree/bindings/soc/qcom/qcom,msm8976-ramp-controller.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/soc/qcom/qcom,msm8976-ramp-controller.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm Ramp Controller 8 + 9 + maintainers: 10 + - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 11 + 12 + description: 13 + The Ramp Controller is used to program the sequence ID for pulse 14 + swallowing, enable sequences and link Sequence IDs (SIDs) for the 15 + CPU cores on some Qualcomm SoCs. 16 + 17 + properties: 18 + compatible: 19 + enum: 20 + - qcom,msm8976-ramp-controller 21 + 22 + reg: 23 + maxItems: 1 24 + 25 + required: 26 + - compatible 27 + - reg 28 + 29 + additionalProperties: false 30 + 31 + examples: 32 + - | 33 + cpu-power-controller@b014000 { 34 + compatible = "qcom,msm8976-ramp-controller"; 35 + reg = <0x0b014000 0x68>; 36 + };
+95
Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/soc/qcom/qcom,pmic-glink.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm PMIC GLINK firmware interface for battery management, USB 8 + Type-C and other things. 9 + 10 + maintainers: 11 + - Bjorn Andersson <andersson@kernel.org> 12 + 13 + description: 14 + The PMIC GLINK service, running on a coprocessor on some modern Qualcomm 15 + platforms and implement USB Type-C handling and battery management. This 16 + binding describes the component in the OS used to communicate with the 17 + firmware and connect it's resources to those described in the Devicetree, 18 + particularly the USB Type-C controllers relationship with USB and DisplayPort 19 + components. 20 + 21 + properties: 22 + compatible: 23 + items: 24 + - enum: 25 + - qcom,sc8180x-pmic-glink 26 + - qcom,sc8280xp-pmic-glink 27 + - qcom,sm8350-pmic-glink 28 + - const: qcom,pmic-glink 29 + 30 + '#address-cells': 31 + const: 1 32 + 33 + '#size-cells': 34 + const: 0 35 + 36 + patternProperties: 37 + '^connector@\d$': 38 + $ref: /schemas/connector/usb-connector.yaml# 39 + 40 + properties: 41 + reg: true 42 + 43 + required: 44 + - reg 45 + 46 + unevaluatedProperties: false 47 + 48 + required: 49 + - compatible 50 + 51 + additionalProperties: false 52 + 53 + examples: 54 + - |+ 55 + pmic-glink { 56 + compatible = "qcom,sc8280xp-pmic-glink", "qcom,pmic-glink"; 57 + 58 + #address-cells = <1>; 59 + #size-cells = <0>; 60 + 61 + connector@0 { 62 + compatible = "usb-c-connector"; 63 + reg = <0>; 64 + power-role = "dual"; 65 + data-role = "dual"; 66 + 67 + ports { 68 + #address-cells = <1>; 69 + #size-cells = <0>; 70 + 71 + port@0 { 72 + reg = <0>; 73 + endpoint { 74 + remote-endpoint = <&usb_role>; 75 + }; 76 + }; 77 + 78 + port@1 { 79 + reg = <1>; 80 + endpoint { 81 + remote-endpoint = <&ss_phy_out>; 82 + }; 83 + }; 84 + 85 + port@2 { 86 + reg = <2>; 87 + endpoint { 88 + remote-endpoint = <&sbu_mux>; 89 + }; 90 + }; 91 + }; 92 + }; 93 + }; 94 + ... 95 +
+101
Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/soc/qcom/qcom,rpm.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm Resource Power Manager (RPM) 8 + 9 + description: 10 + This driver is used to interface with the Resource Power Manager (RPM) found 11 + in various Qualcomm platforms. The RPM allows each component in the system 12 + to vote for state of the system resources, such as clocks, regulators and bus 13 + frequencies. 14 + 15 + maintainers: 16 + - Bjorn Andersson <andersson@kernel.org> 17 + 18 + properties: 19 + compatible: 20 + enum: 21 + - qcom,rpm-apq8064 22 + - qcom,rpm-msm8660 23 + - qcom,rpm-msm8960 24 + - qcom,rpm-ipq8064 25 + - qcom,rpm-mdm9615 26 + 27 + reg: 28 + maxItems: 1 29 + 30 + interrupts: 31 + maxItems: 3 32 + 33 + interrupt-names: 34 + items: 35 + - const: ack 36 + - const: err 37 + - const: wakeup 38 + 39 + qcom,ipc: 40 + $ref: /schemas/types.yaml#/definitions/phandle-array 41 + items: 42 + - items: 43 + - description: phandle to a syscon node representing the APCS registers 44 + - description: u32 representing offset to the register within the syscon 45 + - description: u32 representing the ipc bit within the register 46 + description: 47 + Three entries specifying the outgoing ipc bit used for signaling the RPM. 48 + 49 + patternProperties: 50 + "^regulators(-[01])?$": 51 + type: object 52 + $ref: /schemas/regulator/qcom,rpm-regulator.yaml# 53 + unevaluatedProperties: false 54 + 55 + required: 56 + - compatible 57 + - reg 58 + - interrupts 59 + - interrupt-names 60 + - qcom,ipc 61 + 62 + additionalProperties: false 63 + 64 + examples: 65 + - | 66 + #include <dt-bindings/interrupt-controller/arm-gic.h> 67 + #include <dt-bindings/interrupt-controller/irq.h> 68 + #include <dt-bindings/mfd/qcom-rpm.h> 69 + 70 + rpm@108000 { 71 + compatible = "qcom,rpm-msm8960"; 72 + reg = <0x108000 0x1000>; 73 + qcom,ipc = <&apcs 0x8 2>; 74 + 75 + interrupts = <GIC_SPI 19 IRQ_TYPE_NONE>, <GIC_SPI 21 IRQ_TYPE_NONE>, <GIC_SPI 22 IRQ_TYPE_NONE>; 76 + interrupt-names = "ack", "err", "wakeup"; 77 + 78 + regulators { 79 + compatible = "qcom,rpm-pm8921-regulators"; 80 + vdd_l1_l2_l12_l18-supply = <&pm8921_s4>; 81 + 82 + s1 { 83 + regulator-min-microvolt = <1225000>; 84 + regulator-max-microvolt = <1225000>; 85 + 86 + bias-pull-down; 87 + 88 + qcom,switch-mode-frequency = <3200000>; 89 + }; 90 + 91 + pm8921_s4: s4 { 92 + regulator-min-microvolt = <1800000>; 93 + regulator-max-microvolt = <1800000>; 94 + 95 + qcom,switch-mode-frequency = <1600000>; 96 + bias-pull-down; 97 + 98 + qcom,force-mode = <QCOM_RPM_FORCE_MODE_AUTO>; 99 + }; 100 + }; 101 + };
+2 -1
Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml
··· 112 112 $ref: /schemas/power/qcom,rpmpd.yaml# 113 113 114 114 patternProperties: 115 - '-regulators$': 115 + '^regulators(-[0-9])?$': 116 116 $ref: /schemas/regulator/qcom,rpmh-regulator.yaml# 117 + unevaluatedProperties: false 117 118 118 119 required: 119 120 - compatible
+1
Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
··· 80 80 enum: 81 81 - qcom,rpm-apq8084 82 82 - qcom,rpm-msm8916 83 + - qcom,rpm-msm8936 83 84 - qcom,rpm-msm8974 84 85 - qcom,rpm-msm8976 85 86 - qcom,rpm-msm8953
+15 -1
MAINTAINERS
··· 17253 17253 F: include/dt-bindings/clock/qcom,* 17254 17254 17255 17255 QUALCOMM CORE POWER REDUCTION (CPR) AVS DRIVER 17256 - M: Niklas Cassel <nks@flawful.org> 17256 + M: Bjorn Andersson <andersson@kernel.org> 17257 + M: Konrad Dybcio <konrad.dybcio@linaro.org> 17257 17258 L: linux-pm@vger.kernel.org 17258 17259 L: linux-arm-msm@vger.kernel.org 17259 17260 S: Maintained ··· 19947 19946 F: Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml 19948 19947 F: drivers/reset/reset-starfive-jh7100.c 19949 19948 F: include/dt-bindings/reset/starfive-jh7100.h 19949 + 19950 + STARFIVE JH71XX PMU CONTROLLER DRIVER 19951 + M: Walker Chen <walker.chen@starfivetech.com> 19952 + S: Supported 19953 + F: Documentation/devicetree/bindings/power/starfive* 19954 + F: drivers/soc/starfive/jh71xx_pmu.c 19955 + F: include/dt-bindings/power/starfive,jh7110-pmu.h 19956 + 19957 + STARFIVE SOC DRIVERS 19958 + M: Conor Dooley <conor@kernel.org> 19959 + S: Maintained 19960 + T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/ 19961 + F: drivers/soc/starfive/ 19950 19962 19951 19963 STARFIVE TRNG DRIVER 19952 19964 M: Jia Jie Ho <jiajie.ho@starfivetech.com>
+1 -1
arch/arm/mach-qcom/platsmp.c
··· 14 14 #include <linux/of_address.h> 15 15 #include <linux/smp.h> 16 16 #include <linux/io.h> 17 - #include <linux/qcom_scm.h> 17 + #include <linux/firmware/qcom/qcom_scm.h> 18 18 19 19 #include <asm/smp_plat.h> 20 20
+1 -3
drivers/bus/imx-weim.c
··· 263 263 static int weim_probe(struct platform_device *pdev) 264 264 { 265 265 struct weim_priv *priv; 266 - struct resource *res; 267 266 struct clk *clk; 268 267 void __iomem *base; 269 268 int ret; ··· 272 273 return -ENOMEM; 273 274 274 275 /* get the resource */ 275 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 276 - base = devm_ioremap_resource(&pdev->dev, res); 276 + base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 277 277 if (IS_ERR(base)) 278 278 return PTR_ERR(base); 279 279
+1 -1
drivers/cpuidle/cpuidle-qcom-spm.c
··· 17 17 #include <linux/platform_device.h> 18 18 #include <linux/cpuidle.h> 19 19 #include <linux/cpu_pm.h> 20 - #include <linux/qcom_scm.h> 20 + #include <linux/firmware/qcom/qcom_scm.h> 21 21 #include <soc/qcom/spm.h> 22 22 23 23 #include <asm/proc-fns.h>
+32
drivers/firmware/arm_scmi/Kconfig
··· 23 23 24 24 if ARM_SCMI_PROTOCOL 25 25 26 + config ARM_SCMI_NEED_DEBUGFS 27 + bool 28 + help 29 + This declares whether at least one SCMI facility is configured 30 + which needs debugfs support. When selected causess the creation 31 + of a common SCMI debugfs root directory. 32 + 33 + config ARM_SCMI_RAW_MODE_SUPPORT 34 + bool "Enable support for SCMI Raw transmission mode" 35 + depends on DEBUG_FS 36 + select ARM_SCMI_NEED_DEBUGFS 37 + help 38 + Enable support for SCMI Raw transmission mode. 39 + 40 + If enabled allows the direct injection and snooping of SCMI bare 41 + messages through a dedicated debugfs interface. 42 + It is meant to be used by SCMI compliance/testing suites. 43 + 44 + When enabled regular SCMI drivers interactions are inhibited in 45 + order to avoid unexpected interactions with the SCMI Raw message 46 + flow. If unsure say N. 47 + 48 + config ARM_SCMI_RAW_MODE_SUPPORT_COEX 49 + bool "Allow SCMI Raw mode coexistence with normal SCMI stack" 50 + depends on ARM_SCMI_RAW_MODE_SUPPORT 51 + help 52 + Allow SCMI Raw transmission mode to coexist with normal SCMI stack. 53 + 54 + This will allow regular SCMI drivers to register with the core and 55 + operate normally, thing which could make an SCMI test suite using the 56 + SCMI Raw mode support unreliable. If unsure, say N. 57 + 26 58 config ARM_SCMI_HAVE_TRANSPORT 27 59 bool 28 60 help
+7 -2
drivers/firmware/arm_scmi/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 scmi-bus-y = bus.o 3 + scmi-core-objs := $(scmi-bus-y) 4 + 3 5 scmi-driver-y = driver.o notify.o 6 + scmi-driver-$(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT) += raw_mode.o 4 7 scmi-transport-$(CONFIG_ARM_SCMI_HAVE_SHMEM) = shmem.o 5 8 scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_MAILBOX) += mailbox.o 6 9 scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_SMC) += smc.o ··· 11 8 scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO) += virtio.o 12 9 scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += optee.o 13 10 scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o powercap.o 14 - scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \ 15 - $(scmi-transport-y) 11 + scmi-module-objs := $(scmi-driver-y) $(scmi-protocols-y) $(scmi-transport-y) 12 + 13 + obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-core.o 16 14 obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o 15 + 17 16 obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o 18 17 obj-$(CONFIG_ARM_SCMI_POWER_CONTROL) += scmi_power_control.o 19 18
+300 -91
drivers/firmware/arm_scmi/bus.c
··· 7 7 8 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 9 10 + #include <linux/atomic.h> 10 11 #include <linux/types.h> 11 12 #include <linux/module.h> 13 + #include <linux/of.h> 12 14 #include <linux/kernel.h> 13 15 #include <linux/slab.h> 14 16 #include <linux/device.h> ··· 18 16 19 17 #include "common.h" 20 18 19 + BLOCKING_NOTIFIER_HEAD(scmi_requested_devices_nh); 20 + EXPORT_SYMBOL_GPL(scmi_requested_devices_nh); 21 + 21 22 static DEFINE_IDA(scmi_bus_id); 22 - static DEFINE_IDR(scmi_protocols); 23 - static DEFINE_SPINLOCK(protocol_lock); 23 + 24 + static DEFINE_IDR(scmi_requested_devices); 25 + /* Protect access to scmi_requested_devices */ 26 + static DEFINE_MUTEX(scmi_requested_devices_mtx); 27 + 28 + struct scmi_requested_dev { 29 + const struct scmi_device_id *id_table; 30 + struct list_head node; 31 + }; 32 + 33 + /* Track globally the creation of SCMI SystemPower related devices */ 34 + static atomic_t scmi_syspower_registered = ATOMIC_INIT(0); 35 + 36 + /** 37 + * scmi_protocol_device_request - Helper to request a device 38 + * 39 + * @id_table: A protocol/name pair descriptor for the device to be created. 40 + * 41 + * This helper let an SCMI driver request specific devices identified by the 42 + * @id_table to be created for each active SCMI instance. 43 + * 44 + * The requested device name MUST NOT be already existent for any protocol; 45 + * at first the freshly requested @id_table is annotated in the IDR table 46 + * @scmi_requested_devices and then the requested device is advertised to any 47 + * registered party via the @scmi_requested_devices_nh notification chain. 48 + * 49 + * Return: 0 on Success 50 + */ 51 + static int scmi_protocol_device_request(const struct scmi_device_id *id_table) 52 + { 53 + int ret = 0; 54 + unsigned int id = 0; 55 + struct list_head *head, *phead = NULL; 56 + struct scmi_requested_dev *rdev; 57 + 58 + pr_debug("Requesting SCMI device (%s) for protocol %x\n", 59 + id_table->name, id_table->protocol_id); 60 + 61 + if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT) && 62 + !IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX)) { 63 + pr_warn("SCMI Raw mode active. Rejecting '%s'/0x%02X\n", 64 + id_table->name, id_table->protocol_id); 65 + return -EINVAL; 66 + } 67 + 68 + /* 69 + * Search for the matching protocol rdev list and then search 70 + * of any existent equally named device...fails if any duplicate found. 71 + */ 72 + mutex_lock(&scmi_requested_devices_mtx); 73 + idr_for_each_entry(&scmi_requested_devices, head, id) { 74 + if (!phead) { 75 + /* A list found registered in the IDR is never empty */ 76 + rdev = list_first_entry(head, struct scmi_requested_dev, 77 + node); 78 + if (rdev->id_table->protocol_id == 79 + id_table->protocol_id) 80 + phead = head; 81 + } 82 + list_for_each_entry(rdev, head, node) { 83 + if (!strcmp(rdev->id_table->name, id_table->name)) { 84 + pr_err("Ignoring duplicate request [%d] %s\n", 85 + rdev->id_table->protocol_id, 86 + rdev->id_table->name); 87 + ret = -EINVAL; 88 + goto out; 89 + } 90 + } 91 + } 92 + 93 + /* 94 + * No duplicate found for requested id_table, so let's create a new 95 + * requested device entry for this new valid request. 96 + */ 97 + rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 98 + if (!rdev) { 99 + ret = -ENOMEM; 100 + goto out; 101 + } 102 + rdev->id_table = id_table; 103 + 104 + /* 105 + * Append the new requested device table descriptor to the head of the 106 + * related protocol list, eventually creating such head if not already 107 + * there. 108 + */ 109 + if (!phead) { 110 + phead = kzalloc(sizeof(*phead), GFP_KERNEL); 111 + if (!phead) { 112 + kfree(rdev); 113 + ret = -ENOMEM; 114 + goto out; 115 + } 116 + INIT_LIST_HEAD(phead); 117 + 118 + ret = idr_alloc(&scmi_requested_devices, (void *)phead, 119 + id_table->protocol_id, 120 + id_table->protocol_id + 1, GFP_KERNEL); 121 + if (ret != id_table->protocol_id) { 122 + pr_err("Failed to save SCMI device - ret:%d\n", ret); 123 + kfree(rdev); 124 + kfree(phead); 125 + ret = -EINVAL; 126 + goto out; 127 + } 128 + ret = 0; 129 + } 130 + list_add(&rdev->node, phead); 131 + 132 + out: 133 + mutex_unlock(&scmi_requested_devices_mtx); 134 + 135 + if (!ret) 136 + blocking_notifier_call_chain(&scmi_requested_devices_nh, 137 + SCMI_BUS_NOTIFY_DEVICE_REQUEST, 138 + (void *)rdev->id_table); 139 + 140 + return ret; 141 + } 142 + 143 + /** 144 + * scmi_protocol_device_unrequest - Helper to unrequest a device 145 + * 146 + * @id_table: A protocol/name pair descriptor for the device to be unrequested. 147 + * 148 + * The unrequested device, described by the provided id_table, is at first 149 + * removed from the IDR @scmi_requested_devices and then the removal is 150 + * advertised to any registered party via the @scmi_requested_devices_nh 151 + * notification chain. 152 + */ 153 + static void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table) 154 + { 155 + struct list_head *phead; 156 + 157 + pr_debug("Unrequesting SCMI device (%s) for protocol %x\n", 158 + id_table->name, id_table->protocol_id); 159 + 160 + mutex_lock(&scmi_requested_devices_mtx); 161 + phead = idr_find(&scmi_requested_devices, id_table->protocol_id); 162 + if (phead) { 163 + struct scmi_requested_dev *victim, *tmp; 164 + 165 + list_for_each_entry_safe(victim, tmp, phead, node) { 166 + if (!strcmp(victim->id_table->name, id_table->name)) { 167 + list_del(&victim->node); 168 + 169 + mutex_unlock(&scmi_requested_devices_mtx); 170 + blocking_notifier_call_chain(&scmi_requested_devices_nh, 171 + SCMI_BUS_NOTIFY_DEVICE_UNREQUEST, 172 + (void *)victim->id_table); 173 + kfree(victim); 174 + mutex_lock(&scmi_requested_devices_mtx); 175 + break; 176 + } 177 + } 178 + 179 + if (list_empty(phead)) { 180 + idr_remove(&scmi_requested_devices, 181 + id_table->protocol_id); 182 + kfree(phead); 183 + } 184 + } 185 + mutex_unlock(&scmi_requested_devices_mtx); 186 + } 24 187 25 188 static const struct scmi_device_id * 26 189 scmi_dev_match_id(struct scmi_device *scmi_dev, struct scmi_driver *scmi_drv) ··· 225 58 struct scmi_device_id *id_table = data; 226 59 227 60 return sdev->protocol_id == id_table->protocol_id && 228 - !strcmp(sdev->name, id_table->name); 61 + (id_table->name && !strcmp(sdev->name, id_table->name)); 229 62 } 230 63 231 - struct scmi_device *scmi_child_dev_find(struct device *parent, 232 - int prot_id, const char *name) 64 + static struct scmi_device *scmi_child_dev_find(struct device *parent, 65 + int prot_id, const char *name) 233 66 { 234 67 struct scmi_device_id id_table; 235 68 struct device *dev; ··· 242 75 return NULL; 243 76 244 77 return to_scmi_dev(dev); 245 - } 246 - 247 - const struct scmi_protocol *scmi_protocol_get(int protocol_id) 248 - { 249 - const struct scmi_protocol *proto; 250 - 251 - proto = idr_find(&scmi_protocols, protocol_id); 252 - if (!proto || !try_module_get(proto->owner)) { 253 - pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id); 254 - return NULL; 255 - } 256 - 257 - pr_debug("Found SCMI Protocol 0x%x\n", protocol_id); 258 - 259 - return proto; 260 - } 261 - 262 - void scmi_protocol_put(int protocol_id) 263 - { 264 - const struct scmi_protocol *proto; 265 - 266 - proto = idr_find(&scmi_protocols, protocol_id); 267 - if (proto) 268 - module_put(proto->owner); 269 78 } 270 79 271 80 static int scmi_dev_probe(struct device *dev) ··· 264 121 scmi_drv->remove(scmi_dev); 265 122 } 266 123 267 - static struct bus_type scmi_bus_type = { 124 + struct bus_type scmi_bus_type = { 268 125 .name = "scmi_protocol", 269 126 .match = scmi_dev_match, 270 127 .probe = scmi_dev_probe, 271 128 .remove = scmi_dev_remove, 272 129 }; 130 + EXPORT_SYMBOL_GPL(scmi_bus_type); 273 131 274 132 int scmi_driver_register(struct scmi_driver *driver, struct module *owner, 275 133 const char *mod_name) ··· 291 147 292 148 retval = driver_register(&driver->driver); 293 149 if (!retval) 294 - pr_debug("registered new scmi driver %s\n", driver->name); 150 + pr_debug("Registered new scmi driver %s\n", driver->name); 295 151 296 152 return retval; 297 153 } ··· 309 165 kfree(to_scmi_dev(dev)); 310 166 } 311 167 312 - struct scmi_device * 313 - scmi_device_create(struct device_node *np, struct device *parent, int protocol, 314 - const char *name) 168 + static void __scmi_device_destroy(struct scmi_device *scmi_dev) 169 + { 170 + pr_debug("(%s) Destroying SCMI device '%s' for protocol 0x%x (%s)\n", 171 + of_node_full_name(scmi_dev->dev.parent->of_node), 172 + dev_name(&scmi_dev->dev), scmi_dev->protocol_id, 173 + scmi_dev->name); 174 + 175 + if (scmi_dev->protocol_id == SCMI_PROTOCOL_SYSTEM) 176 + atomic_set(&scmi_syspower_registered, 0); 177 + 178 + kfree_const(scmi_dev->name); 179 + ida_free(&scmi_bus_id, scmi_dev->id); 180 + device_unregister(&scmi_dev->dev); 181 + } 182 + 183 + static struct scmi_device * 184 + __scmi_device_create(struct device_node *np, struct device *parent, 185 + int protocol, const char *name) 315 186 { 316 187 int id, retval; 317 188 struct scmi_device *scmi_dev; 189 + 190 + /* 191 + * If the same protocol/name device already exist under the same parent 192 + * (i.e. SCMI instance) just return the existent device. 193 + * This avoids any race between the SCMI driver, creating devices for 194 + * each DT defined protocol at probe time, and the concurrent 195 + * registration of SCMI drivers. 196 + */ 197 + scmi_dev = scmi_child_dev_find(parent, protocol, name); 198 + if (scmi_dev) 199 + return scmi_dev; 200 + 201 + /* 202 + * Ignore any possible subsequent failures while creating the device 203 + * since we are doomed anyway at that point; not using a mutex which 204 + * spans across this whole function to keep things simple and to avoid 205 + * to serialize all the __scmi_device_create calls across possibly 206 + * different SCMI server instances (parent) 207 + */ 208 + if (protocol == SCMI_PROTOCOL_SYSTEM && 209 + atomic_cmpxchg(&scmi_syspower_registered, 0, 1)) { 210 + dev_warn(parent, 211 + "SCMI SystemPower protocol device must be unique !\n"); 212 + return NULL; 213 + } 318 214 319 215 scmi_dev = kzalloc(sizeof(*scmi_dev), GFP_KERNEL); 320 216 if (!scmi_dev) ··· 385 201 if (retval) 386 202 goto put_dev; 387 203 204 + pr_debug("(%s) Created SCMI device '%s' for protocol 0x%x (%s)\n", 205 + of_node_full_name(parent->of_node), 206 + dev_name(&scmi_dev->dev), protocol, name); 207 + 388 208 return scmi_dev; 389 209 put_dev: 390 210 kfree_const(scmi_dev->name); ··· 397 209 return NULL; 398 210 } 399 211 400 - void scmi_device_destroy(struct scmi_device *scmi_dev) 212 + /** 213 + * scmi_device_create - A method to create one or more SCMI devices 214 + * 215 + * @np: A reference to the device node to use for the new device(s) 216 + * @parent: The parent device to use identifying a specific SCMI instance 217 + * @protocol: The SCMI protocol to be associated with this device 218 + * @name: The requested-name of the device to be created; this is optional 219 + * and if no @name is provided, all the devices currently known to 220 + * be requested on the SCMI bus for @protocol will be created. 221 + * 222 + * This method can be invoked to create a single well-defined device (like 223 + * a transport device or a device requested by an SCMI driver loaded after 224 + * the core SCMI stack has been probed), or to create all the devices currently 225 + * known to have been requested by the loaded SCMI drivers for a specific 226 + * protocol (typically during SCMI core protocol enumeration at probe time). 227 + * 228 + * Return: The created device (or one of them if @name was NOT provided and 229 + * multiple devices were created) or NULL if no device was created; 230 + * note that NULL indicates an error ONLY in case a specific @name 231 + * was provided: when @name param was not provided, a number of devices 232 + * could have been potentially created for a whole protocol, unless no 233 + * device was found to have been requested for that specific protocol. 234 + */ 235 + struct scmi_device *scmi_device_create(struct device_node *np, 236 + struct device *parent, int protocol, 237 + const char *name) 401 238 { 402 - kfree_const(scmi_dev->name); 403 - scmi_handle_put(scmi_dev->handle); 404 - ida_free(&scmi_bus_id, scmi_dev->id); 405 - device_unregister(&scmi_dev->dev); 406 - } 239 + struct list_head *phead; 240 + struct scmi_requested_dev *rdev; 241 + struct scmi_device *scmi_dev = NULL; 407 242 408 - void scmi_device_link_add(struct device *consumer, struct device *supplier) 409 - { 410 - struct device_link *link; 243 + if (name) 244 + return __scmi_device_create(np, parent, protocol, name); 411 245 412 - link = device_link_add(consumer, supplier, DL_FLAG_AUTOREMOVE_CONSUMER); 413 - 414 - WARN_ON(!link); 415 - } 416 - 417 - void scmi_set_handle(struct scmi_device *scmi_dev) 418 - { 419 - scmi_dev->handle = scmi_handle_get(&scmi_dev->dev); 420 - if (scmi_dev->handle) 421 - scmi_device_link_add(&scmi_dev->dev, scmi_dev->handle->dev); 422 - } 423 - 424 - int scmi_protocol_register(const struct scmi_protocol *proto) 425 - { 426 - int ret; 427 - 428 - if (!proto) { 429 - pr_err("invalid protocol\n"); 430 - return -EINVAL; 246 + mutex_lock(&scmi_requested_devices_mtx); 247 + phead = idr_find(&scmi_requested_devices, protocol); 248 + /* Nothing to do. */ 249 + if (!phead) { 250 + mutex_unlock(&scmi_requested_devices_mtx); 251 + return scmi_dev; 431 252 } 432 253 433 - if (!proto->instance_init) { 434 - pr_err("missing init for protocol 0x%x\n", proto->id); 435 - return -EINVAL; 254 + /* Walk the list of requested devices for protocol and create them */ 255 + list_for_each_entry(rdev, phead, node) { 256 + struct scmi_device *sdev; 257 + 258 + sdev = __scmi_device_create(np, parent, 259 + rdev->id_table->protocol_id, 260 + rdev->id_table->name); 261 + /* Report errors and carry on... */ 262 + if (sdev) 263 + scmi_dev = sdev; 264 + else 265 + pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n", 266 + of_node_full_name(parent->of_node), 267 + rdev->id_table->protocol_id, 268 + rdev->id_table->name); 436 269 } 270 + mutex_unlock(&scmi_requested_devices_mtx); 437 271 438 - spin_lock(&protocol_lock); 439 - ret = idr_alloc(&scmi_protocols, (void *)proto, 440 - proto->id, proto->id + 1, GFP_ATOMIC); 441 - spin_unlock(&protocol_lock); 442 - if (ret != proto->id) { 443 - pr_err("unable to allocate SCMI idr slot for 0x%x - err %d\n", 444 - proto->id, ret); 445 - return ret; 446 - } 447 - 448 - pr_debug("Registered SCMI Protocol 0x%x\n", proto->id); 449 - 450 - return 0; 272 + return scmi_dev; 451 273 } 452 - EXPORT_SYMBOL_GPL(scmi_protocol_register); 274 + EXPORT_SYMBOL_GPL(scmi_device_create); 453 275 454 - void scmi_protocol_unregister(const struct scmi_protocol *proto) 276 + void scmi_device_destroy(struct device *parent, int protocol, const char *name) 455 277 { 456 - spin_lock(&protocol_lock); 457 - idr_remove(&scmi_protocols, proto->id); 458 - spin_unlock(&protocol_lock); 278 + struct scmi_device *scmi_dev; 459 279 460 - pr_debug("Unregistered SCMI Protocol 0x%x\n", proto->id); 461 - 462 - return; 280 + scmi_dev = scmi_child_dev_find(parent, protocol, name); 281 + if (scmi_dev) 282 + __scmi_device_destroy(scmi_dev); 463 283 } 464 - EXPORT_SYMBOL_GPL(scmi_protocol_unregister); 284 + EXPORT_SYMBOL_GPL(scmi_device_destroy); 465 285 466 286 static int __scmi_devices_unregister(struct device *dev, void *data) 467 287 { 468 288 struct scmi_device *scmi_dev = to_scmi_dev(dev); 469 289 470 - scmi_device_destroy(scmi_dev); 290 + __scmi_device_destroy(scmi_dev); 471 291 return 0; 472 292 } 473 293 ··· 484 288 bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister); 485 289 } 486 290 487 - int __init scmi_bus_init(void) 291 + static int __init scmi_bus_init(void) 488 292 { 489 293 int retval; 490 294 491 295 retval = bus_register(&scmi_bus_type); 492 296 if (retval) 493 - pr_err("scmi protocol bus register failed (%d)\n", retval); 297 + pr_err("SCMI protocol bus register failed (%d)\n", retval); 298 + 299 + pr_info("SCMI protocol bus registered\n"); 494 300 495 301 return retval; 496 302 } 303 + subsys_initcall(scmi_bus_init); 497 304 498 - void __exit scmi_bus_exit(void) 305 + static void __exit scmi_bus_exit(void) 499 306 { 307 + /* 308 + * Destroy all remaining devices: just in case the drivers were 309 + * manually unbound and at first and then the modules unloaded. 310 + */ 500 311 scmi_devices_unregister(); 501 312 bus_unregister(&scmi_bus_type); 502 313 ida_destroy(&scmi_bus_id); 503 314 } 315 + module_exit(scmi_bus_exit); 316 + 317 + MODULE_ALIAS("scmi-core"); 318 + MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>"); 319 + MODULE_DESCRIPTION("ARM SCMI protocol bus"); 320 + MODULE_LICENSE("GPL");
+85 -15
drivers/firmware/arm_scmi/common.h
··· 27 27 #include "protocols.h" 28 28 #include "notify.h" 29 29 30 + #define SCMI_MAX_CHANNELS 256 31 + 32 + #define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC) 33 + 34 + enum scmi_error_codes { 35 + SCMI_SUCCESS = 0, /* Success */ 36 + SCMI_ERR_SUPPORT = -1, /* Not supported */ 37 + SCMI_ERR_PARAMS = -2, /* Invalid Parameters */ 38 + SCMI_ERR_ACCESS = -3, /* Invalid access/permission denied */ 39 + SCMI_ERR_ENTRY = -4, /* Not found */ 40 + SCMI_ERR_RANGE = -5, /* Value out of range */ 41 + SCMI_ERR_BUSY = -6, /* Device busy */ 42 + SCMI_ERR_COMMS = -7, /* Communication Error */ 43 + SCMI_ERR_GENERIC = -8, /* Generic Error */ 44 + SCMI_ERR_HARDWARE = -9, /* Hardware Error */ 45 + SCMI_ERR_PROTOCOL = -10,/* Protocol Error */ 46 + }; 47 + 48 + static const int scmi_linux_errmap[] = { 49 + /* better than switch case as long as return value is continuous */ 50 + 0, /* SCMI_SUCCESS */ 51 + -EOPNOTSUPP, /* SCMI_ERR_SUPPORT */ 52 + -EINVAL, /* SCMI_ERR_PARAM */ 53 + -EACCES, /* SCMI_ERR_ACCESS */ 54 + -ENOENT, /* SCMI_ERR_ENTRY */ 55 + -ERANGE, /* SCMI_ERR_RANGE */ 56 + -EBUSY, /* SCMI_ERR_BUSY */ 57 + -ECOMM, /* SCMI_ERR_COMMS */ 58 + -EIO, /* SCMI_ERR_GENERIC */ 59 + -EREMOTEIO, /* SCMI_ERR_HARDWARE */ 60 + -EPROTO, /* SCMI_ERR_PROTOCOL */ 61 + }; 62 + 63 + static inline int scmi_to_linux_errno(int errno) 64 + { 65 + int err_idx = -errno; 66 + 67 + if (err_idx >= SCMI_SUCCESS && err_idx < ARRAY_SIZE(scmi_linux_errmap)) 68 + return scmi_linux_errmap[err_idx]; 69 + return -EIO; 70 + } 71 + 30 72 #define MSG_ID_MASK GENMASK(7, 0) 31 73 #define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr)) 32 74 #define MSG_TYPE_MASK GENMASK(9, 8) ··· 138 96 139 97 struct scmi_revision_info * 140 98 scmi_revision_area_get(const struct scmi_protocol_handle *ph); 141 - int scmi_handle_put(const struct scmi_handle *handle); 142 - void scmi_device_link_add(struct device *consumer, struct device *supplier); 143 - struct scmi_handle *scmi_handle_get(struct device *dev); 144 - void scmi_set_handle(struct scmi_device *scmi_dev); 145 99 void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph, 146 100 u8 *prot_imp); 147 101 148 - int __init scmi_bus_init(void); 149 - void __exit scmi_bus_exit(void); 102 + extern struct bus_type scmi_bus_type; 150 103 151 - const struct scmi_protocol *scmi_protocol_get(int protocol_id); 152 - void scmi_protocol_put(int protocol_id); 104 + #define SCMI_BUS_NOTIFY_DEVICE_REQUEST 0 105 + #define SCMI_BUS_NOTIFY_DEVICE_UNREQUEST 1 106 + extern struct blocking_notifier_head scmi_requested_devices_nh; 107 + 108 + struct scmi_device *scmi_device_create(struct device_node *np, 109 + struct device *parent, int protocol, 110 + const char *name); 111 + void scmi_device_destroy(struct device *parent, int protocol, const char *name); 153 112 154 113 int scmi_protocol_acquire(const struct scmi_handle *handle, u8 protocol_id); 155 114 void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id); ··· 159 116 /** 160 117 * struct scmi_chan_info - Structure representing a SCMI channel information 161 118 * 119 + * @id: An identifier for this channel: this matches the protocol number 120 + * used to initialize this channel 162 121 * @dev: Reference to device in the SCMI hierarchy corresponding to this 163 122 * channel 164 123 * @rx_timeout_ms: The configured RX timeout in milliseconds. ··· 172 127 * @transport_info: Transport layer related information 173 128 */ 174 129 struct scmi_chan_info { 130 + int id; 175 131 struct device *dev; 176 132 unsigned int rx_timeout_ms; 177 133 struct scmi_handle *handle; ··· 199 153 */ 200 154 struct scmi_transport_ops { 201 155 int (*link_supplier)(struct device *dev); 202 - bool (*chan_available)(struct device *dev, int idx); 156 + bool (*chan_available)(struct device_node *of_node, int idx); 203 157 int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev, 204 158 bool tx); 205 159 int (*chan_free)(int id, void *p, void *data); ··· 215 169 void (*clear_channel)(struct scmi_chan_info *cinfo); 216 170 bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer); 217 171 }; 218 - 219 - int scmi_protocol_device_request(const struct scmi_device_id *id_table); 220 - void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table); 221 - struct scmi_device *scmi_child_dev_find(struct device *parent, 222 - int prot_id, const char *name); 223 172 224 173 /** 225 174 * struct scmi_desc - Description of SoC integration ··· 256 215 const bool atomic_enabled; 257 216 }; 258 217 218 + static inline bool is_polling_required(struct scmi_chan_info *cinfo, 219 + const struct scmi_desc *desc) 220 + { 221 + return cinfo->no_completion_irq || desc->force_polling; 222 + } 223 + 224 + static inline bool is_transport_polling_capable(const struct scmi_desc *desc) 225 + { 226 + return desc->ops->poll_done || desc->sync_cmds_completed_on_ret; 227 + } 228 + 229 + static inline bool is_polling_enabled(struct scmi_chan_info *cinfo, 230 + const struct scmi_desc *desc) 231 + { 232 + return is_polling_required(cinfo, desc) && 233 + is_transport_polling_capable(desc); 234 + } 235 + 236 + void scmi_xfer_raw_put(const struct scmi_handle *handle, 237 + struct scmi_xfer *xfer); 238 + struct scmi_xfer *scmi_xfer_raw_get(const struct scmi_handle *handle); 239 + struct scmi_chan_info * 240 + scmi_xfer_raw_channel_get(const struct scmi_handle *handle, u8 protocol_id); 241 + 242 + int scmi_xfer_raw_inflight_register(const struct scmi_handle *handle, 243 + struct scmi_xfer *xfer); 244 + 245 + int scmi_xfer_raw_wait_for_message_response(struct scmi_chan_info *cinfo, 246 + struct scmi_xfer *xfer, 247 + unsigned int timeout_ms); 259 248 #ifdef CONFIG_ARM_SCMI_TRANSPORT_MAILBOX 260 249 extern const struct scmi_desc scmi_mailbox_desc; 261 250 #endif ··· 300 229 #endif 301 230 302 231 void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr, void *priv); 303 - void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id); 304 232 305 233 /* shmem related declarations */ 306 234 struct scmi_shared_mem;
+831 -476
drivers/firmware/arm_scmi/driver.c
··· 14 14 * Copyright (C) 2018-2021 ARM Ltd. 15 15 */ 16 16 17 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 + 17 19 #include <linux/bitmap.h> 20 + #include <linux/debugfs.h> 18 21 #include <linux/device.h> 19 22 #include <linux/export.h> 20 23 #include <linux/idr.h> ··· 37 34 #include "common.h" 38 35 #include "notify.h" 39 36 37 + #include "raw_mode.h" 38 + 40 39 #define CREATE_TRACE_POINTS 41 40 #include <trace/events/scmi.h> 42 41 43 - enum scmi_error_codes { 44 - SCMI_SUCCESS = 0, /* Success */ 45 - SCMI_ERR_SUPPORT = -1, /* Not supported */ 46 - SCMI_ERR_PARAMS = -2, /* Invalid Parameters */ 47 - SCMI_ERR_ACCESS = -3, /* Invalid access/permission denied */ 48 - SCMI_ERR_ENTRY = -4, /* Not found */ 49 - SCMI_ERR_RANGE = -5, /* Value out of range */ 50 - SCMI_ERR_BUSY = -6, /* Device busy */ 51 - SCMI_ERR_COMMS = -7, /* Communication Error */ 52 - SCMI_ERR_GENERIC = -8, /* Generic Error */ 53 - SCMI_ERR_HARDWARE = -9, /* Hardware Error */ 54 - SCMI_ERR_PROTOCOL = -10,/* Protocol Error */ 55 - }; 42 + static DEFINE_IDA(scmi_id); 43 + 44 + static DEFINE_IDR(scmi_protocols); 45 + static DEFINE_SPINLOCK(protocol_lock); 56 46 57 47 /* List of all SCMI devices active in system */ 58 48 static LIST_HEAD(scmi_list); ··· 54 58 /* Track the unique id for the transfers for debug & profiling purpose */ 55 59 static atomic_t transfer_last_id; 56 60 57 - static DEFINE_IDR(scmi_requested_devices); 58 - static DEFINE_MUTEX(scmi_requested_devices_mtx); 59 - 60 - /* Track globally the creation of SCMI SystemPower related devices */ 61 - static bool scmi_syspower_registered; 62 - /* Protect access to scmi_syspower_registered */ 63 - static DEFINE_MUTEX(scmi_syspower_mtx); 64 - 65 - struct scmi_requested_dev { 66 - const struct scmi_device_id *id_table; 67 - struct list_head node; 68 - }; 61 + static struct dentry *scmi_top_dentry; 69 62 70 63 /** 71 64 * struct scmi_xfers_info - Structure to manage transfer information ··· 103 118 #define ph_to_pi(h) container_of(h, struct scmi_protocol_instance, ph) 104 119 105 120 /** 121 + * struct scmi_debug_info - Debug common info 122 + * @top_dentry: A reference to the top debugfs dentry 123 + * @name: Name of this SCMI instance 124 + * @type: Type of this SCMI instance 125 + * @is_atomic: Flag to state if the transport of this instance is atomic 126 + */ 127 + struct scmi_debug_info { 128 + struct dentry *top_dentry; 129 + const char *name; 130 + const char *type; 131 + bool is_atomic; 132 + }; 133 + 134 + /** 106 135 * struct scmi_info - Structure representing a SCMI instance 107 136 * 137 + * @id: A sequence number starting from zero identifying this instance 108 138 * @dev: Device pointer 109 139 * @desc: SoC description for this instance 110 140 * @version: SCMI revision information containing protocol version, ··· 147 147 * @notify_priv: Pointer to private data structure specific to notifications. 148 148 * @node: List head 149 149 * @users: Number of users of this instance 150 + * @bus_nb: A notifier to listen for device bind/unbind on the scmi bus 151 + * @dev_req_nb: A notifier to listen for device request/unrequest on the scmi 152 + * bus 153 + * @devreq_mtx: A mutex to serialize device creation for this SCMI instance 154 + * @dbg: A pointer to debugfs related data (if any) 155 + * @raw: An opaque reference handle used by SCMI Raw mode. 150 156 */ 151 157 struct scmi_info { 158 + int id; 152 159 struct device *dev; 153 160 const struct scmi_desc *desc; 154 161 struct scmi_revision_info version; ··· 173 166 void *notify_priv; 174 167 struct list_head node; 175 168 int users; 169 + struct notifier_block bus_nb; 170 + struct notifier_block dev_req_nb; 171 + /* Serialize device creation process for this instance */ 172 + struct mutex devreq_mtx; 173 + struct scmi_debug_info *dbg; 174 + void *raw; 176 175 }; 177 176 178 177 #define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle) 178 + #define bus_nb_to_scmi_info(nb) container_of(nb, struct scmi_info, bus_nb) 179 + #define req_nb_to_scmi_info(nb) container_of(nb, struct scmi_info, dev_req_nb) 179 180 180 - static const int scmi_linux_errmap[] = { 181 - /* better than switch case as long as return value is continuous */ 182 - 0, /* SCMI_SUCCESS */ 183 - -EOPNOTSUPP, /* SCMI_ERR_SUPPORT */ 184 - -EINVAL, /* SCMI_ERR_PARAM */ 185 - -EACCES, /* SCMI_ERR_ACCESS */ 186 - -ENOENT, /* SCMI_ERR_ENTRY */ 187 - -ERANGE, /* SCMI_ERR_RANGE */ 188 - -EBUSY, /* SCMI_ERR_BUSY */ 189 - -ECOMM, /* SCMI_ERR_COMMS */ 190 - -EIO, /* SCMI_ERR_GENERIC */ 191 - -EREMOTEIO, /* SCMI_ERR_HARDWARE */ 192 - -EPROTO, /* SCMI_ERR_PROTOCOL */ 193 - }; 194 - 195 - static inline int scmi_to_linux_errno(int errno) 181 + static const struct scmi_protocol *scmi_protocol_get(int protocol_id) 196 182 { 197 - int err_idx = -errno; 183 + const struct scmi_protocol *proto; 198 184 199 - if (err_idx >= SCMI_SUCCESS && err_idx < ARRAY_SIZE(scmi_linux_errmap)) 200 - return scmi_linux_errmap[err_idx]; 201 - return -EIO; 185 + proto = idr_find(&scmi_protocols, protocol_id); 186 + if (!proto || !try_module_get(proto->owner)) { 187 + pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id); 188 + return NULL; 189 + } 190 + 191 + pr_debug("Found SCMI Protocol 0x%x\n", protocol_id); 192 + 193 + return proto; 194 + } 195 + 196 + static void scmi_protocol_put(int protocol_id) 197 + { 198 + const struct scmi_protocol *proto; 199 + 200 + proto = idr_find(&scmi_protocols, protocol_id); 201 + if (proto) 202 + module_put(proto->owner); 203 + } 204 + 205 + int scmi_protocol_register(const struct scmi_protocol *proto) 206 + { 207 + int ret; 208 + 209 + if (!proto) { 210 + pr_err("invalid protocol\n"); 211 + return -EINVAL; 212 + } 213 + 214 + if (!proto->instance_init) { 215 + pr_err("missing init for protocol 0x%x\n", proto->id); 216 + return -EINVAL; 217 + } 218 + 219 + spin_lock(&protocol_lock); 220 + ret = idr_alloc(&scmi_protocols, (void *)proto, 221 + proto->id, proto->id + 1, GFP_ATOMIC); 222 + spin_unlock(&protocol_lock); 223 + if (ret != proto->id) { 224 + pr_err("unable to allocate SCMI idr slot for 0x%x - err %d\n", 225 + proto->id, ret); 226 + return ret; 227 + } 228 + 229 + pr_debug("Registered SCMI Protocol 0x%x\n", proto->id); 230 + 231 + return 0; 232 + } 233 + EXPORT_SYMBOL_GPL(scmi_protocol_register); 234 + 235 + void scmi_protocol_unregister(const struct scmi_protocol *proto) 236 + { 237 + spin_lock(&protocol_lock); 238 + idr_remove(&scmi_protocols, proto->id); 239 + spin_unlock(&protocol_lock); 240 + 241 + pr_debug("Unregistered SCMI Protocol 0x%x\n", proto->id); 242 + } 243 + EXPORT_SYMBOL_GPL(scmi_protocol_unregister); 244 + 245 + /** 246 + * scmi_create_protocol_devices - Create devices for all pending requests for 247 + * this SCMI instance. 248 + * 249 + * @np: The device node describing the protocol 250 + * @info: The SCMI instance descriptor 251 + * @prot_id: The protocol ID 252 + * @name: The optional name of the device to be created: if not provided this 253 + * call will lead to the creation of all the devices currently requested 254 + * for the specified protocol. 255 + */ 256 + static void scmi_create_protocol_devices(struct device_node *np, 257 + struct scmi_info *info, 258 + int prot_id, const char *name) 259 + { 260 + struct scmi_device *sdev; 261 + 262 + mutex_lock(&info->devreq_mtx); 263 + sdev = scmi_device_create(np, info->dev, prot_id, name); 264 + if (name && !sdev) 265 + dev_err(info->dev, 266 + "failed to create device for protocol 0x%X (%s)\n", 267 + prot_id, name); 268 + mutex_unlock(&info->devreq_mtx); 269 + } 270 + 271 + static void scmi_destroy_protocol_devices(struct scmi_info *info, 272 + int prot_id, const char *name) 273 + { 274 + mutex_lock(&info->devreq_mtx); 275 + scmi_device_destroy(info->dev, prot_id, name); 276 + mutex_unlock(&info->devreq_mtx); 202 277 } 203 278 204 279 void scmi_notification_instance_data_set(const struct scmi_handle *handle, ··· 400 311 if (xfer_id != next_token) 401 312 atomic_add((int)(xfer_id - next_token), &transfer_last_id); 402 313 403 - /* Set in-flight */ 404 - set_bit(xfer_id, minfo->xfer_alloc_table); 405 314 xfer->hdr.seq = (u16)xfer_id; 406 315 407 316 return 0; ··· 418 331 } 419 332 420 333 /** 334 + * scmi_xfer_inflight_register_unlocked - Register the xfer as in-flight 335 + * 336 + * @xfer: The xfer to register 337 + * @minfo: Pointer to Tx/Rx Message management info based on channel type 338 + * 339 + * Note that this helper assumes that the xfer to be registered as in-flight 340 + * had been built using an xfer sequence number which still corresponds to a 341 + * free slot in the xfer_alloc_table. 342 + * 343 + * Context: Assumes to be called with @xfer_lock already acquired. 344 + */ 345 + static inline void 346 + scmi_xfer_inflight_register_unlocked(struct scmi_xfer *xfer, 347 + struct scmi_xfers_info *minfo) 348 + { 349 + /* Set in-flight */ 350 + set_bit(xfer->hdr.seq, minfo->xfer_alloc_table); 351 + hash_add(minfo->pending_xfers, &xfer->node, xfer->hdr.seq); 352 + xfer->pending = true; 353 + } 354 + 355 + /** 356 + * scmi_xfer_inflight_register - Try to register an xfer as in-flight 357 + * 358 + * @xfer: The xfer to register 359 + * @minfo: Pointer to Tx/Rx Message management info based on channel type 360 + * 361 + * Note that this helper does NOT assume anything about the sequence number 362 + * that was baked into the provided xfer, so it checks at first if it can 363 + * be mapped to a free slot and fails with an error if another xfer with the 364 + * same sequence number is currently still registered as in-flight. 365 + * 366 + * Return: 0 on Success or -EBUSY if sequence number embedded in the xfer 367 + * could not rbe mapped to a free slot in the xfer_alloc_table. 368 + */ 369 + static int scmi_xfer_inflight_register(struct scmi_xfer *xfer, 370 + struct scmi_xfers_info *minfo) 371 + { 372 + int ret = 0; 373 + unsigned long flags; 374 + 375 + spin_lock_irqsave(&minfo->xfer_lock, flags); 376 + if (!test_bit(xfer->hdr.seq, minfo->xfer_alloc_table)) 377 + scmi_xfer_inflight_register_unlocked(xfer, minfo); 378 + else 379 + ret = -EBUSY; 380 + spin_unlock_irqrestore(&minfo->xfer_lock, flags); 381 + 382 + return ret; 383 + } 384 + 385 + /** 386 + * scmi_xfer_raw_inflight_register - An helper to register the given xfer as in 387 + * flight on the TX channel, if possible. 388 + * 389 + * @handle: Pointer to SCMI entity handle 390 + * @xfer: The xfer to register 391 + * 392 + * Return: 0 on Success, error otherwise 393 + */ 394 + int scmi_xfer_raw_inflight_register(const struct scmi_handle *handle, 395 + struct scmi_xfer *xfer) 396 + { 397 + struct scmi_info *info = handle_to_scmi_info(handle); 398 + 399 + return scmi_xfer_inflight_register(xfer, &info->tx_minfo); 400 + } 401 + 402 + /** 403 + * scmi_xfer_pending_set - Pick a proper sequence number and mark the xfer 404 + * as pending in-flight 405 + * 406 + * @xfer: The xfer to act upon 407 + * @minfo: Pointer to Tx/Rx Message management info based on channel type 408 + * 409 + * Return: 0 on Success or error otherwise 410 + */ 411 + static inline int scmi_xfer_pending_set(struct scmi_xfer *xfer, 412 + struct scmi_xfers_info *minfo) 413 + { 414 + int ret; 415 + unsigned long flags; 416 + 417 + spin_lock_irqsave(&minfo->xfer_lock, flags); 418 + /* Set a new monotonic token as the xfer sequence number */ 419 + ret = scmi_xfer_token_set(minfo, xfer); 420 + if (!ret) 421 + scmi_xfer_inflight_register_unlocked(xfer, minfo); 422 + spin_unlock_irqrestore(&minfo->xfer_lock, flags); 423 + 424 + return ret; 425 + } 426 + 427 + /** 421 428 * scmi_xfer_get() - Allocate one message 422 429 * 423 430 * @handle: Pointer to SCMI entity handle 424 431 * @minfo: Pointer to Tx/Rx Message management info based on channel type 425 - * @set_pending: If true a monotonic token is picked and the xfer is added to 426 - * the pending hash table. 427 432 * 428 433 * Helper function which is used by various message functions that are 429 434 * exposed to clients of this driver for allocating a message traffic event. 430 435 * 431 - * Picks an xfer from the free list @free_xfers (if any available) and, if 432 - * required, sets a monotonically increasing token and stores the inflight xfer 433 - * into the @pending_xfers hashtable for later retrieval. 436 + * Picks an xfer from the free list @free_xfers (if any available) and perform 437 + * a basic initialization. 438 + * 439 + * Note that, at this point, still no sequence number is assigned to the 440 + * allocated xfer, nor it is registered as a pending transaction. 434 441 * 435 442 * The successfully initialized xfer is refcounted. 436 443 * 437 - * Context: Holds @xfer_lock while manipulating @xfer_alloc_table and 438 - * @free_xfers. 444 + * Context: Holds @xfer_lock while manipulating @free_xfers. 439 445 * 440 - * Return: 0 if all went fine, else corresponding error. 446 + * Return: An initialized xfer if all went fine, else pointer error. 441 447 */ 442 448 static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle, 443 - struct scmi_xfers_info *minfo, 444 - bool set_pending) 449 + struct scmi_xfers_info *minfo) 445 450 { 446 - int ret; 447 451 unsigned long flags; 448 452 struct scmi_xfer *xfer; 449 453 ··· 554 376 */ 555 377 xfer->transfer_id = atomic_inc_return(&transfer_last_id); 556 378 557 - if (set_pending) { 558 - /* Pick and set monotonic token */ 559 - ret = scmi_xfer_token_set(minfo, xfer); 560 - if (!ret) { 561 - hash_add(minfo->pending_xfers, &xfer->node, 562 - xfer->hdr.seq); 563 - xfer->pending = true; 564 - } else { 565 - dev_err(handle->dev, 566 - "Failed to get monotonic token %d\n", ret); 567 - hlist_add_head(&xfer->node, &minfo->free_xfers); 568 - xfer = ERR_PTR(ret); 569 - } 570 - } 571 - 572 - if (!IS_ERR(xfer)) { 573 - refcount_set(&xfer->users, 1); 574 - atomic_set(&xfer->busy, SCMI_XFER_FREE); 575 - } 379 + refcount_set(&xfer->users, 1); 380 + atomic_set(&xfer->busy, SCMI_XFER_FREE); 576 381 spin_unlock_irqrestore(&minfo->xfer_lock, flags); 577 382 578 383 return xfer; 384 + } 385 + 386 + /** 387 + * scmi_xfer_raw_get - Helper to get a bare free xfer from the TX channel 388 + * 389 + * @handle: Pointer to SCMI entity handle 390 + * 391 + * Note that xfer is taken from the TX channel structures. 392 + * 393 + * Return: A valid xfer on Success, or an error-pointer otherwise 394 + */ 395 + struct scmi_xfer *scmi_xfer_raw_get(const struct scmi_handle *handle) 396 + { 397 + struct scmi_xfer *xfer; 398 + struct scmi_info *info = handle_to_scmi_info(handle); 399 + 400 + xfer = scmi_xfer_get(handle, &info->tx_minfo); 401 + if (!IS_ERR(xfer)) 402 + xfer->flags |= SCMI_XFER_FLAG_IS_RAW; 403 + 404 + return xfer; 405 + } 406 + 407 + /** 408 + * scmi_xfer_raw_channel_get - Helper to get a reference to the proper channel 409 + * to use for a specific protocol_id Raw transaction. 410 + * 411 + * @handle: Pointer to SCMI entity handle 412 + * @protocol_id: Identifier of the protocol 413 + * 414 + * Note that in a regular SCMI stack, usually, a protocol has to be defined in 415 + * the DT to have an associated channel and be usable; but in Raw mode any 416 + * protocol in range is allowed, re-using the Base channel, so as to enable 417 + * fuzzing on any protocol without the need of a fully compiled DT. 418 + * 419 + * Return: A reference to the channel to use, or an ERR_PTR 420 + */ 421 + struct scmi_chan_info * 422 + scmi_xfer_raw_channel_get(const struct scmi_handle *handle, u8 protocol_id) 423 + { 424 + struct scmi_chan_info *cinfo; 425 + struct scmi_info *info = handle_to_scmi_info(handle); 426 + 427 + cinfo = idr_find(&info->tx_idr, protocol_id); 428 + if (!cinfo) { 429 + if (protocol_id == SCMI_PROTOCOL_BASE) 430 + return ERR_PTR(-EINVAL); 431 + /* Use Base channel for protocols not defined for DT */ 432 + cinfo = idr_find(&info->tx_idr, SCMI_PROTOCOL_BASE); 433 + if (!cinfo) 434 + return ERR_PTR(-EINVAL); 435 + dev_warn_once(handle->dev, 436 + "Using Base channel for protocol 0x%X\n", 437 + protocol_id); 438 + } 439 + 440 + return cinfo; 579 441 } 580 442 581 443 /** ··· 644 426 hlist_add_head(&xfer->node, &minfo->free_xfers); 645 427 } 646 428 spin_unlock_irqrestore(&minfo->xfer_lock, flags); 429 + } 430 + 431 + /** 432 + * scmi_xfer_raw_put - Release an xfer that was taken by @scmi_xfer_raw_get 433 + * 434 + * @handle: Pointer to SCMI entity handle 435 + * @xfer: A reference to the xfer to put 436 + * 437 + * Note that as with other xfer_put() handlers the xfer is really effectively 438 + * released only if there are no more users on the system. 439 + */ 440 + void scmi_xfer_raw_put(const struct scmi_handle *handle, struct scmi_xfer *xfer) 441 + { 442 + struct scmi_info *info = handle_to_scmi_info(handle); 443 + 444 + xfer->flags &= ~SCMI_XFER_FLAG_IS_RAW; 445 + xfer->flags &= ~SCMI_XFER_FLAG_CHAN_SET; 446 + return __scmi_xfer_put(&info->tx_minfo, xfer); 647 447 } 648 448 649 449 /** ··· 859 623 info->desc->ops->clear_channel(cinfo); 860 624 } 861 625 862 - static inline bool is_polling_required(struct scmi_chan_info *cinfo, 863 - struct scmi_info *info) 864 - { 865 - return cinfo->no_completion_irq || info->desc->force_polling; 866 - } 867 - 868 - static inline bool is_transport_polling_capable(struct scmi_info *info) 869 - { 870 - return info->desc->ops->poll_done || 871 - info->desc->sync_cmds_completed_on_ret; 872 - } 873 - 874 - static inline bool is_polling_enabled(struct scmi_chan_info *cinfo, 875 - struct scmi_info *info) 876 - { 877 - return is_polling_required(cinfo, info) && 878 - is_transport_polling_capable(info); 879 - } 880 - 881 626 static void scmi_handle_notification(struct scmi_chan_info *cinfo, 882 627 u32 msg_hdr, void *priv) 883 628 { ··· 869 652 ktime_t ts; 870 653 871 654 ts = ktime_get_boottime(); 872 - xfer = scmi_xfer_get(cinfo->handle, minfo, false); 655 + xfer = scmi_xfer_get(cinfo->handle, minfo); 873 656 if (IS_ERR(xfer)) { 874 657 dev_err(dev, "failed to get free message slot (%ld)\n", 875 658 PTR_ERR(xfer)); ··· 884 667 info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size, 885 668 xfer); 886 669 887 - trace_scmi_msg_dump(xfer->hdr.protocol_id, xfer->hdr.id, "NOTI", 888 - xfer->hdr.seq, xfer->hdr.status, 889 - xfer->rx.buf, xfer->rx.len); 670 + trace_scmi_msg_dump(info->id, cinfo->id, xfer->hdr.protocol_id, 671 + xfer->hdr.id, "NOTI", xfer->hdr.seq, 672 + xfer->hdr.status, xfer->rx.buf, xfer->rx.len); 890 673 891 674 scmi_notify(cinfo->handle, xfer->hdr.protocol_id, 892 675 xfer->hdr.id, xfer->rx.buf, xfer->rx.len, ts); ··· 894 677 trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id, 895 678 xfer->hdr.protocol_id, xfer->hdr.seq, 896 679 MSG_TYPE_NOTIFICATION); 680 + 681 + if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { 682 + xfer->hdr.seq = MSG_XTRACT_TOKEN(msg_hdr); 683 + scmi_raw_message_report(info->raw, xfer, SCMI_RAW_NOTIF_QUEUE, 684 + cinfo->id); 685 + } 897 686 898 687 __scmi_xfer_put(minfo, xfer); 899 688 ··· 914 691 915 692 xfer = scmi_xfer_command_acquire(cinfo, msg_hdr); 916 693 if (IS_ERR(xfer)) { 694 + if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) 695 + scmi_raw_error_report(info->raw, cinfo, msg_hdr, priv); 696 + 917 697 if (MSG_XTRACT_TYPE(msg_hdr) == MSG_TYPE_DELAYED_RESP) 918 698 scmi_clear_channel(info, cinfo); 919 699 return; ··· 931 705 smp_store_mb(xfer->priv, priv); 932 706 info->desc->ops->fetch_response(cinfo, xfer); 933 707 934 - trace_scmi_msg_dump(xfer->hdr.protocol_id, xfer->hdr.id, 708 + trace_scmi_msg_dump(info->id, cinfo->id, xfer->hdr.protocol_id, 709 + xfer->hdr.id, 935 710 xfer->hdr.type == MSG_TYPE_DELAYED_RESP ? 936 - "DLYD" : "RESP", 711 + (!SCMI_XFER_IS_RAW(xfer) ? "DLYD" : "dlyd") : 712 + (!SCMI_XFER_IS_RAW(xfer) ? "RESP" : "resp"), 937 713 xfer->hdr.seq, xfer->hdr.status, 938 714 xfer->rx.buf, xfer->rx.len); 939 715 ··· 948 720 complete(xfer->async_done); 949 721 } else { 950 722 complete(&xfer->done); 723 + } 724 + 725 + if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { 726 + /* 727 + * When in polling mode avoid to queue the Raw xfer on the IRQ 728 + * RX path since it will be already queued at the end of the TX 729 + * poll loop. 730 + */ 731 + if (!xfer->hdr.poll_completion) 732 + scmi_raw_message_report(info->raw, xfer, 733 + SCMI_RAW_REPLY_QUEUE, 734 + cinfo->id); 951 735 } 952 736 953 737 scmi_xfer_command_release(info, xfer); ··· 1025 785 ktime_after(ktime_get(), stop); 1026 786 } 1027 787 1028 - /** 1029 - * scmi_wait_for_message_response - An helper to group all the possible ways of 1030 - * waiting for a synchronous message response. 1031 - * 1032 - * @cinfo: SCMI channel info 1033 - * @xfer: Reference to the transfer being waited for. 1034 - * 1035 - * Chooses waiting strategy (sleep-waiting vs busy-waiting) depending on 1036 - * configuration flags like xfer->hdr.poll_completion. 1037 - * 1038 - * Return: 0 on Success, error otherwise. 1039 - */ 1040 - static int scmi_wait_for_message_response(struct scmi_chan_info *cinfo, 1041 - struct scmi_xfer *xfer) 788 + static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc, 789 + struct scmi_chan_info *cinfo, 790 + struct scmi_xfer *xfer, unsigned int timeout_ms) 1042 791 { 1043 - struct scmi_info *info = handle_to_scmi_info(cinfo->handle); 1044 - struct device *dev = info->dev; 1045 - int ret = 0, timeout_ms = info->desc->max_rx_timeout_ms; 1046 - 1047 - trace_scmi_xfer_response_wait(xfer->transfer_id, xfer->hdr.id, 1048 - xfer->hdr.protocol_id, xfer->hdr.seq, 1049 - timeout_ms, 1050 - xfer->hdr.poll_completion); 792 + int ret = 0; 1051 793 1052 794 if (xfer->hdr.poll_completion) { 1053 795 /* 1054 796 * Real polling is needed only if transport has NOT declared 1055 797 * itself to support synchronous commands replies. 1056 798 */ 1057 - if (!info->desc->sync_cmds_completed_on_ret) { 799 + if (!desc->sync_cmds_completed_on_ret) { 1058 800 /* 1059 801 * Poll on xfer using transport provided .poll_done(); 1060 802 * assumes no completion interrupt was available. ··· 1055 833 1056 834 if (!ret) { 1057 835 unsigned long flags; 836 + struct scmi_info *info = 837 + handle_to_scmi_info(cinfo->handle); 1058 838 1059 839 /* 1060 840 * Do not fetch_response if an out-of-order delayed ··· 1064 840 */ 1065 841 spin_lock_irqsave(&xfer->lock, flags); 1066 842 if (xfer->state == SCMI_XFER_SENT_OK) { 1067 - info->desc->ops->fetch_response(cinfo, xfer); 843 + desc->ops->fetch_response(cinfo, xfer); 1068 844 xfer->state = SCMI_XFER_RESP_OK; 1069 845 } 1070 846 spin_unlock_irqrestore(&xfer->lock, flags); 1071 847 1072 848 /* Trace polled replies. */ 1073 - trace_scmi_msg_dump(xfer->hdr.protocol_id, xfer->hdr.id, 1074 - "RESP", 849 + trace_scmi_msg_dump(info->id, cinfo->id, 850 + xfer->hdr.protocol_id, xfer->hdr.id, 851 + !SCMI_XFER_IS_RAW(xfer) ? 852 + "RESP" : "resp", 1075 853 xfer->hdr.seq, xfer->hdr.status, 1076 854 xfer->rx.buf, xfer->rx.len); 855 + 856 + if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { 857 + struct scmi_info *info = 858 + handle_to_scmi_info(cinfo->handle); 859 + 860 + scmi_raw_message_report(info->raw, xfer, 861 + SCMI_RAW_REPLY_QUEUE, 862 + cinfo->id); 863 + } 1077 864 } 1078 865 } else { 1079 866 /* And we wait for the response. */ ··· 1095 860 ret = -ETIMEDOUT; 1096 861 } 1097 862 } 863 + 864 + return ret; 865 + } 866 + 867 + /** 868 + * scmi_wait_for_message_response - An helper to group all the possible ways of 869 + * waiting for a synchronous message response. 870 + * 871 + * @cinfo: SCMI channel info 872 + * @xfer: Reference to the transfer being waited for. 873 + * 874 + * Chooses waiting strategy (sleep-waiting vs busy-waiting) depending on 875 + * configuration flags like xfer->hdr.poll_completion. 876 + * 877 + * Return: 0 on Success, error otherwise. 878 + */ 879 + static int scmi_wait_for_message_response(struct scmi_chan_info *cinfo, 880 + struct scmi_xfer *xfer) 881 + { 882 + struct scmi_info *info = handle_to_scmi_info(cinfo->handle); 883 + struct device *dev = info->dev; 884 + 885 + trace_scmi_xfer_response_wait(xfer->transfer_id, xfer->hdr.id, 886 + xfer->hdr.protocol_id, xfer->hdr.seq, 887 + info->desc->max_rx_timeout_ms, 888 + xfer->hdr.poll_completion); 889 + 890 + return scmi_wait_for_reply(dev, info->desc, cinfo, xfer, 891 + info->desc->max_rx_timeout_ms); 892 + } 893 + 894 + /** 895 + * scmi_xfer_raw_wait_for_message_response - An helper to wait for a message 896 + * reply to an xfer raw request on a specific channel for the required timeout. 897 + * 898 + * @cinfo: SCMI channel info 899 + * @xfer: Reference to the transfer being waited for. 900 + * @timeout_ms: The maximum timeout in milliseconds 901 + * 902 + * Return: 0 on Success, error otherwise. 903 + */ 904 + int scmi_xfer_raw_wait_for_message_response(struct scmi_chan_info *cinfo, 905 + struct scmi_xfer *xfer, 906 + unsigned int timeout_ms) 907 + { 908 + int ret; 909 + struct scmi_info *info = handle_to_scmi_info(cinfo->handle); 910 + struct device *dev = info->dev; 911 + 912 + ret = scmi_wait_for_reply(dev, info->desc, cinfo, xfer, timeout_ms); 913 + if (ret) 914 + dev_dbg(dev, "timed out in RAW response - HDR:%08X\n", 915 + pack_scmi_header(&xfer->hdr)); 1098 916 1099 917 return ret; 1100 918 } ··· 1172 884 struct scmi_chan_info *cinfo; 1173 885 1174 886 /* Check for polling request on custom command xfers at first */ 1175 - if (xfer->hdr.poll_completion && !is_transport_polling_capable(info)) { 887 + if (xfer->hdr.poll_completion && 888 + !is_transport_polling_capable(info->desc)) { 1176 889 dev_warn_once(dev, 1177 890 "Polling mode is not supported by transport.\n"); 1178 891 return -EINVAL; ··· 1184 895 return -EINVAL; 1185 896 1186 897 /* True ONLY if also supported by transport. */ 1187 - if (is_polling_enabled(cinfo, info)) 898 + if (is_polling_enabled(cinfo, info->desc)) 1188 899 xfer->hdr.poll_completion = true; 1189 900 1190 901 /* ··· 1217 928 return ret; 1218 929 } 1219 930 1220 - trace_scmi_msg_dump(xfer->hdr.protocol_id, xfer->hdr.id, "CMND", 1221 - xfer->hdr.seq, xfer->hdr.status, 1222 - xfer->tx.buf, xfer->tx.len); 931 + trace_scmi_msg_dump(info->id, cinfo->id, xfer->hdr.protocol_id, 932 + xfer->hdr.id, "CMND", xfer->hdr.seq, 933 + xfer->hdr.status, xfer->tx.buf, xfer->tx.len); 1223 934 1224 935 ret = scmi_wait_for_message_response(cinfo, xfer); 1225 936 if (!ret && xfer->hdr.status) ··· 1242 953 1243 954 xfer->rx.len = info->desc->max_msg_size; 1244 955 } 1245 - 1246 - #define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC) 1247 956 1248 957 /** 1249 958 * do_xfer_with_response() - Do one transfer and wait until the delayed ··· 1330 1043 tx_size > info->desc->max_msg_size) 1331 1044 return -ERANGE; 1332 1045 1333 - xfer = scmi_xfer_get(pi->handle, minfo, true); 1046 + xfer = scmi_xfer_get(pi->handle, minfo); 1334 1047 if (IS_ERR(xfer)) { 1335 1048 ret = PTR_ERR(xfer); 1336 1049 dev_err(dev, "failed to get free message slot(%d)\n", ret); 1050 + return ret; 1051 + } 1052 + 1053 + /* Pick a sequence number and register this xfer as in-flight */ 1054 + ret = scmi_xfer_pending_set(xfer, minfo); 1055 + if (ret) { 1056 + dev_err(pi->handle->dev, 1057 + "Failed to get monotonic token %d\n", ret); 1058 + __scmi_xfer_put(minfo, xfer); 1337 1059 return ret; 1338 1060 } 1339 1061 ··· 2118 1822 bool ret; 2119 1823 struct scmi_info *info = handle_to_scmi_info(handle); 2120 1824 2121 - ret = info->desc->atomic_enabled && is_transport_polling_capable(info); 1825 + ret = info->desc->atomic_enabled && 1826 + is_transport_polling_capable(info->desc); 2122 1827 if (ret && atomic_threshold) 2123 1828 *atomic_threshold = info->atomic_threshold; 2124 1829 2125 1830 return ret; 2126 - } 2127 - 2128 - static inline 2129 - struct scmi_handle *scmi_handle_get_from_info_unlocked(struct scmi_info *info) 2130 - { 2131 - info->users++; 2132 - return &info->handle; 2133 1831 } 2134 1832 2135 1833 /** ··· 2137 1847 * 2138 1848 * Return: pointer to handle if successful, NULL on error 2139 1849 */ 2140 - struct scmi_handle *scmi_handle_get(struct device *dev) 1850 + static struct scmi_handle *scmi_handle_get(struct device *dev) 2141 1851 { 2142 1852 struct list_head *p; 2143 1853 struct scmi_info *info; ··· 2147 1857 list_for_each(p, &scmi_list) { 2148 1858 info = list_entry(p, struct scmi_info, node); 2149 1859 if (dev->parent == info->dev) { 2150 - handle = scmi_handle_get_from_info_unlocked(info); 1860 + info->users++; 1861 + handle = &info->handle; 2151 1862 break; 2152 1863 } 2153 1864 } ··· 2169 1878 * Return: 0 is successfully released 2170 1879 * if null was passed, it returns -EINVAL; 2171 1880 */ 2172 - int scmi_handle_put(const struct scmi_handle *handle) 1881 + static int scmi_handle_put(const struct scmi_handle *handle) 2173 1882 { 2174 1883 struct scmi_info *info; 2175 1884 ··· 2183 1892 mutex_unlock(&scmi_list_mutex); 2184 1893 2185 1894 return 0; 1895 + } 1896 + 1897 + static void scmi_device_link_add(struct device *consumer, 1898 + struct device *supplier) 1899 + { 1900 + struct device_link *link; 1901 + 1902 + link = device_link_add(consumer, supplier, DL_FLAG_AUTOREMOVE_CONSUMER); 1903 + 1904 + WARN_ON(!link); 1905 + } 1906 + 1907 + static void scmi_set_handle(struct scmi_device *scmi_dev) 1908 + { 1909 + scmi_dev->handle = scmi_handle_get(&scmi_dev->dev); 1910 + if (scmi_dev->handle) 1911 + scmi_device_link_add(&scmi_dev->dev, scmi_dev->handle->dev); 2186 1912 } 2187 1913 2188 1914 static int __scmi_xfer_info_init(struct scmi_info *sinfo, ··· 2295 1987 return ret; 2296 1988 } 2297 1989 2298 - static int scmi_chan_setup(struct scmi_info *info, struct device *dev, 1990 + static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node, 2299 1991 int prot_id, bool tx) 2300 1992 { 2301 1993 int ret, idx; 1994 + char name[32]; 2302 1995 struct scmi_chan_info *cinfo; 2303 1996 struct idr *idr; 1997 + struct scmi_device *tdev = NULL; 2304 1998 2305 1999 /* Transmit channel is first entry i.e. index 0 */ 2306 2000 idx = tx ? 0 : 1; 2307 2001 idr = tx ? &info->tx_idr : &info->rx_idr; 2308 2002 2309 - /* check if already allocated, used for multiple device per protocol */ 2310 - cinfo = idr_find(idr, prot_id); 2311 - if (cinfo) 2312 - return 0; 2313 - 2314 - if (!info->desc->ops->chan_available(dev, idx)) { 2003 + if (!info->desc->ops->chan_available(of_node, idx)) { 2315 2004 cinfo = idr_find(idr, SCMI_PROTOCOL_BASE); 2316 2005 if (unlikely(!cinfo)) /* Possible only if platform has no Rx */ 2317 2006 return -EINVAL; ··· 2319 2014 if (!cinfo) 2320 2015 return -ENOMEM; 2321 2016 2322 - cinfo->dev = dev; 2323 2017 cinfo->rx_timeout_ms = info->desc->max_rx_timeout_ms; 2324 2018 2325 - ret = info->desc->ops->chan_setup(cinfo, info->dev, tx); 2326 - if (ret) 2327 - return ret; 2019 + /* Create a unique name for this transport device */ 2020 + snprintf(name, 32, "__scmi_transport_device_%s_%02X", 2021 + idx ? "rx" : "tx", prot_id); 2022 + /* Create a uniquely named, dedicated transport device for this chan */ 2023 + tdev = scmi_device_create(of_node, info->dev, prot_id, name); 2024 + if (!tdev) { 2025 + dev_err(info->dev, 2026 + "failed to create transport device (%s)\n", name); 2027 + devm_kfree(info->dev, cinfo); 2028 + return -EINVAL; 2029 + } 2030 + of_node_get(of_node); 2328 2031 2329 - if (tx && is_polling_required(cinfo, info)) { 2330 - if (is_transport_polling_capable(info)) 2331 - dev_info(dev, 2032 + cinfo->id = prot_id; 2033 + cinfo->dev = &tdev->dev; 2034 + ret = info->desc->ops->chan_setup(cinfo, info->dev, tx); 2035 + if (ret) { 2036 + of_node_put(of_node); 2037 + scmi_device_destroy(info->dev, prot_id, name); 2038 + devm_kfree(info->dev, cinfo); 2039 + return ret; 2040 + } 2041 + 2042 + if (tx && is_polling_required(cinfo, info->desc)) { 2043 + if (is_transport_polling_capable(info->desc)) 2044 + dev_info(&tdev->dev, 2332 2045 "Enabled polling mode TX channel - prot_id:%d\n", 2333 2046 prot_id); 2334 2047 else 2335 - dev_warn(dev, 2048 + dev_warn(&tdev->dev, 2336 2049 "Polling mode NOT supported by transport.\n"); 2337 2050 } 2338 2051 2339 2052 idr_alloc: 2340 2053 ret = idr_alloc(idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL); 2341 2054 if (ret != prot_id) { 2342 - dev_err(dev, "unable to allocate SCMI idr slot err %d\n", ret); 2055 + dev_err(info->dev, 2056 + "unable to allocate SCMI idr slot err %d\n", ret); 2057 + /* Destroy channel and device only if created by this call. */ 2058 + if (tdev) { 2059 + of_node_put(of_node); 2060 + scmi_device_destroy(info->dev, prot_id, name); 2061 + devm_kfree(info->dev, cinfo); 2062 + } 2343 2063 return ret; 2344 2064 } 2345 2065 ··· 2373 2043 } 2374 2044 2375 2045 static inline int 2376 - scmi_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id) 2046 + scmi_txrx_setup(struct scmi_info *info, struct device_node *of_node, 2047 + int prot_id) 2377 2048 { 2378 - int ret = scmi_chan_setup(info, dev, prot_id, true); 2049 + int ret = scmi_chan_setup(info, of_node, prot_id, true); 2379 2050 2380 2051 if (!ret) { 2381 2052 /* Rx is optional, report only memory errors */ 2382 - ret = scmi_chan_setup(info, dev, prot_id, false); 2053 + ret = scmi_chan_setup(info, of_node, prot_id, false); 2383 2054 if (ret && ret != -ENOMEM) 2384 2055 ret = 0; 2385 2056 } ··· 2389 2058 } 2390 2059 2391 2060 /** 2392 - * scmi_get_protocol_device - Helper to get/create an SCMI device. 2061 + * scmi_channels_setup - Helper to initialize all required channels 2393 2062 * 2394 - * @np: A device node representing a valid active protocols for the referred 2395 - * SCMI instance. 2396 - * @info: The referred SCMI instance for which we are getting/creating this 2397 - * device. 2398 - * @prot_id: The protocol ID. 2399 - * @name: The device name. 2063 + * @info: The SCMI instance descriptor. 2400 2064 * 2401 - * Referring to the specific SCMI instance identified by @info, this helper 2402 - * takes care to return a properly initialized device matching the requested 2403 - * @proto_id and @name: if device was still not existent it is created as a 2404 - * child of the specified SCMI instance @info and its transport properly 2405 - * initialized as usual. 2065 + * Initialize all the channels found described in the DT against the underlying 2066 + * configured transport using custom defined dedicated devices instead of 2067 + * borrowing devices from the SCMI drivers; this way channels are initialized 2068 + * upfront during core SCMI stack probing and are no more coupled with SCMI 2069 + * devices used by SCMI drivers. 2406 2070 * 2407 - * Return: A properly initialized scmi device, NULL otherwise. 2408 - */ 2409 - static inline struct scmi_device * 2410 - scmi_get_protocol_device(struct device_node *np, struct scmi_info *info, 2411 - int prot_id, const char *name) 2412 - { 2413 - struct scmi_device *sdev; 2414 - 2415 - /* Already created for this parent SCMI instance ? */ 2416 - sdev = scmi_child_dev_find(info->dev, prot_id, name); 2417 - if (sdev) 2418 - return sdev; 2419 - 2420 - mutex_lock(&scmi_syspower_mtx); 2421 - if (prot_id == SCMI_PROTOCOL_SYSTEM && scmi_syspower_registered) { 2422 - dev_warn(info->dev, 2423 - "SCMI SystemPower protocol device must be unique !\n"); 2424 - mutex_unlock(&scmi_syspower_mtx); 2425 - 2426 - return NULL; 2427 - } 2428 - 2429 - pr_debug("Creating SCMI device (%s) for protocol %x\n", name, prot_id); 2430 - 2431 - sdev = scmi_device_create(np, info->dev, prot_id, name); 2432 - if (!sdev) { 2433 - dev_err(info->dev, "failed to create %d protocol device\n", 2434 - prot_id); 2435 - mutex_unlock(&scmi_syspower_mtx); 2436 - 2437 - return NULL; 2438 - } 2439 - 2440 - if (scmi_txrx_setup(info, &sdev->dev, prot_id)) { 2441 - dev_err(&sdev->dev, "failed to setup transport\n"); 2442 - scmi_device_destroy(sdev); 2443 - mutex_unlock(&scmi_syspower_mtx); 2444 - 2445 - return NULL; 2446 - } 2447 - 2448 - if (prot_id == SCMI_PROTOCOL_SYSTEM) 2449 - scmi_syspower_registered = true; 2450 - 2451 - mutex_unlock(&scmi_syspower_mtx); 2452 - 2453 - return sdev; 2454 - } 2455 - 2456 - static inline void 2457 - scmi_create_protocol_device(struct device_node *np, struct scmi_info *info, 2458 - int prot_id, const char *name) 2459 - { 2460 - struct scmi_device *sdev; 2461 - 2462 - sdev = scmi_get_protocol_device(np, info, prot_id, name); 2463 - if (!sdev) 2464 - return; 2465 - 2466 - /* setup handle now as the transport is ready */ 2467 - scmi_set_handle(sdev); 2468 - } 2469 - 2470 - /** 2471 - * scmi_create_protocol_devices - Create devices for all pending requests for 2472 - * this SCMI instance. 2473 - * 2474 - * @np: The device node describing the protocol 2475 - * @info: The SCMI instance descriptor 2476 - * @prot_id: The protocol ID 2477 - * 2478 - * All devices previously requested for this instance (if any) are found and 2479 - * created by scanning the proper @&scmi_requested_devices entry. 2480 - */ 2481 - static void scmi_create_protocol_devices(struct device_node *np, 2482 - struct scmi_info *info, int prot_id) 2483 - { 2484 - struct list_head *phead; 2485 - 2486 - mutex_lock(&scmi_requested_devices_mtx); 2487 - phead = idr_find(&scmi_requested_devices, prot_id); 2488 - if (phead) { 2489 - struct scmi_requested_dev *rdev; 2490 - 2491 - list_for_each_entry(rdev, phead, node) 2492 - scmi_create_protocol_device(np, info, prot_id, 2493 - rdev->id_table->name); 2494 - } 2495 - mutex_unlock(&scmi_requested_devices_mtx); 2496 - } 2497 - 2498 - /** 2499 - * scmi_protocol_device_request - Helper to request a device 2500 - * 2501 - * @id_table: A protocol/name pair descriptor for the device to be created. 2502 - * 2503 - * This helper let an SCMI driver request specific devices identified by the 2504 - * @id_table to be created for each active SCMI instance. 2505 - * 2506 - * The requested device name MUST NOT be already existent for any protocol; 2507 - * at first the freshly requested @id_table is annotated in the IDR table 2508 - * @scmi_requested_devices, then a matching device is created for each already 2509 - * active SCMI instance. (if any) 2510 - * 2511 - * This way the requested device is created straight-away for all the already 2512 - * initialized(probed) SCMI instances (handles) and it remains also annotated 2513 - * as pending creation if the requesting SCMI driver was loaded before some 2514 - * SCMI instance and related transports were available: when such late instance 2515 - * is probed, its probe will take care to scan the list of pending requested 2516 - * devices and create those on its own (see @scmi_create_protocol_devices and 2517 - * its enclosing loop) 2071 + * Note that, even though a pair of TX/RX channels is associated to each 2072 + * protocol defined in the DT, a distinct freshly initialized channel is 2073 + * created only if the DT node for the protocol at hand describes a dedicated 2074 + * channel: in all the other cases the common BASE protocol channel is reused. 2518 2075 * 2519 2076 * Return: 0 on Success 2520 2077 */ 2521 - int scmi_protocol_device_request(const struct scmi_device_id *id_table) 2522 - { 2523 - int ret = 0; 2524 - unsigned int id = 0; 2525 - struct list_head *head, *phead = NULL; 2526 - struct scmi_requested_dev *rdev; 2527 - struct scmi_info *info; 2528 - 2529 - pr_debug("Requesting SCMI device (%s) for protocol %x\n", 2530 - id_table->name, id_table->protocol_id); 2531 - 2532 - /* 2533 - * Search for the matching protocol rdev list and then search 2534 - * of any existent equally named device...fails if any duplicate found. 2535 - */ 2536 - mutex_lock(&scmi_requested_devices_mtx); 2537 - idr_for_each_entry(&scmi_requested_devices, head, id) { 2538 - if (!phead) { 2539 - /* A list found registered in the IDR is never empty */ 2540 - rdev = list_first_entry(head, struct scmi_requested_dev, 2541 - node); 2542 - if (rdev->id_table->protocol_id == 2543 - id_table->protocol_id) 2544 - phead = head; 2545 - } 2546 - list_for_each_entry(rdev, head, node) { 2547 - if (!strcmp(rdev->id_table->name, id_table->name)) { 2548 - pr_err("Ignoring duplicate request [%d] %s\n", 2549 - rdev->id_table->protocol_id, 2550 - rdev->id_table->name); 2551 - ret = -EINVAL; 2552 - goto out; 2553 - } 2554 - } 2555 - } 2556 - 2557 - /* 2558 - * No duplicate found for requested id_table, so let's create a new 2559 - * requested device entry for this new valid request. 2560 - */ 2561 - rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 2562 - if (!rdev) { 2563 - ret = -ENOMEM; 2564 - goto out; 2565 - } 2566 - rdev->id_table = id_table; 2567 - 2568 - /* 2569 - * Append the new requested device table descriptor to the head of the 2570 - * related protocol list, eventually creating such head if not already 2571 - * there. 2572 - */ 2573 - if (!phead) { 2574 - phead = kzalloc(sizeof(*phead), GFP_KERNEL); 2575 - if (!phead) { 2576 - kfree(rdev); 2577 - ret = -ENOMEM; 2578 - goto out; 2579 - } 2580 - INIT_LIST_HEAD(phead); 2581 - 2582 - ret = idr_alloc(&scmi_requested_devices, (void *)phead, 2583 - id_table->protocol_id, 2584 - id_table->protocol_id + 1, GFP_KERNEL); 2585 - if (ret != id_table->protocol_id) { 2586 - pr_err("Failed to save SCMI device - ret:%d\n", ret); 2587 - kfree(rdev); 2588 - kfree(phead); 2589 - ret = -EINVAL; 2590 - goto out; 2591 - } 2592 - ret = 0; 2593 - } 2594 - list_add(&rdev->node, phead); 2595 - 2596 - /* 2597 - * Now effectively create and initialize the requested device for every 2598 - * already initialized SCMI instance which has registered the requested 2599 - * protocol as a valid active one: i.e. defined in DT and supported by 2600 - * current platform FW. 2601 - */ 2602 - mutex_lock(&scmi_list_mutex); 2603 - list_for_each_entry(info, &scmi_list, node) { 2604 - struct device_node *child; 2605 - 2606 - child = idr_find(&info->active_protocols, 2607 - id_table->protocol_id); 2608 - if (child) { 2609 - struct scmi_device *sdev; 2610 - 2611 - sdev = scmi_get_protocol_device(child, info, 2612 - id_table->protocol_id, 2613 - id_table->name); 2614 - if (sdev) { 2615 - /* Set handle if not already set: device existed */ 2616 - if (!sdev->handle) 2617 - sdev->handle = 2618 - scmi_handle_get_from_info_unlocked(info); 2619 - /* Relink consumer and suppliers */ 2620 - if (sdev->handle) 2621 - scmi_device_link_add(&sdev->dev, 2622 - sdev->handle->dev); 2623 - } 2624 - } else { 2625 - dev_err(info->dev, 2626 - "Failed. SCMI protocol %d not active.\n", 2627 - id_table->protocol_id); 2628 - } 2629 - } 2630 - mutex_unlock(&scmi_list_mutex); 2631 - 2632 - out: 2633 - mutex_unlock(&scmi_requested_devices_mtx); 2634 - 2635 - return ret; 2636 - } 2637 - 2638 - /** 2639 - * scmi_protocol_device_unrequest - Helper to unrequest a device 2640 - * 2641 - * @id_table: A protocol/name pair descriptor for the device to be unrequested. 2642 - * 2643 - * An helper to let an SCMI driver release its request about devices; note that 2644 - * devices are created and initialized once the first SCMI driver request them 2645 - * but they destroyed only on SCMI core unloading/unbinding. 2646 - * 2647 - * The current SCMI transport layer uses such devices as internal references and 2648 - * as such they could be shared as same transport between multiple drivers so 2649 - * that cannot be safely destroyed till the whole SCMI stack is removed. 2650 - * (unless adding further burden of refcounting.) 2651 - */ 2652 - void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table) 2653 - { 2654 - struct list_head *phead; 2655 - 2656 - pr_debug("Unrequesting SCMI device (%s) for protocol %x\n", 2657 - id_table->name, id_table->protocol_id); 2658 - 2659 - mutex_lock(&scmi_requested_devices_mtx); 2660 - phead = idr_find(&scmi_requested_devices, id_table->protocol_id); 2661 - if (phead) { 2662 - struct scmi_requested_dev *victim, *tmp; 2663 - 2664 - list_for_each_entry_safe(victim, tmp, phead, node) { 2665 - if (!strcmp(victim->id_table->name, id_table->name)) { 2666 - list_del(&victim->node); 2667 - kfree(victim); 2668 - break; 2669 - } 2670 - } 2671 - 2672 - if (list_empty(phead)) { 2673 - idr_remove(&scmi_requested_devices, 2674 - id_table->protocol_id); 2675 - kfree(phead); 2676 - } 2677 - } 2678 - mutex_unlock(&scmi_requested_devices_mtx); 2679 - } 2680 - 2681 - static int scmi_cleanup_txrx_channels(struct scmi_info *info) 2078 + static int scmi_channels_setup(struct scmi_info *info) 2682 2079 { 2683 2080 int ret; 2684 - struct idr *idr = &info->tx_idr; 2081 + struct device_node *child, *top_np = info->dev->of_node; 2685 2082 2686 - ret = idr_for_each(idr, info->desc->ops->chan_free, idr); 2687 - idr_destroy(&info->tx_idr); 2083 + /* Initialize a common generic channel at first */ 2084 + ret = scmi_txrx_setup(info, top_np, SCMI_PROTOCOL_BASE); 2085 + if (ret) 2086 + return ret; 2688 2087 2689 - idr = &info->rx_idr; 2690 - ret = idr_for_each(idr, info->desc->ops->chan_free, idr); 2691 - idr_destroy(&info->rx_idr); 2088 + for_each_available_child_of_node(top_np, child) { 2089 + u32 prot_id; 2090 + 2091 + if (of_property_read_u32(child, "reg", &prot_id)) 2092 + continue; 2093 + 2094 + if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) 2095 + dev_err(info->dev, 2096 + "Out of range protocol %d\n", prot_id); 2097 + 2098 + ret = scmi_txrx_setup(info, child, prot_id); 2099 + if (ret) { 2100 + of_node_put(child); 2101 + return ret; 2102 + } 2103 + } 2104 + 2105 + return 0; 2106 + } 2107 + 2108 + static int scmi_chan_destroy(int id, void *p, void *idr) 2109 + { 2110 + struct scmi_chan_info *cinfo = p; 2111 + 2112 + if (cinfo->dev) { 2113 + struct scmi_info *info = handle_to_scmi_info(cinfo->handle); 2114 + struct scmi_device *sdev = to_scmi_dev(cinfo->dev); 2115 + 2116 + of_node_put(cinfo->dev->of_node); 2117 + scmi_device_destroy(info->dev, id, sdev->name); 2118 + cinfo->dev = NULL; 2119 + } 2120 + 2121 + idr_remove(idr, id); 2122 + 2123 + return 0; 2124 + } 2125 + 2126 + static void scmi_cleanup_channels(struct scmi_info *info, struct idr *idr) 2127 + { 2128 + /* At first free all channels at the transport layer ... */ 2129 + idr_for_each(idr, info->desc->ops->chan_free, idr); 2130 + 2131 + /* ...then destroy all underlying devices */ 2132 + idr_for_each(idr, scmi_chan_destroy, idr); 2133 + 2134 + idr_destroy(idr); 2135 + } 2136 + 2137 + static void scmi_cleanup_txrx_channels(struct scmi_info *info) 2138 + { 2139 + scmi_cleanup_channels(info, &info->tx_idr); 2140 + 2141 + scmi_cleanup_channels(info, &info->rx_idr); 2142 + } 2143 + 2144 + static int scmi_bus_notifier(struct notifier_block *nb, 2145 + unsigned long action, void *data) 2146 + { 2147 + struct scmi_info *info = bus_nb_to_scmi_info(nb); 2148 + struct scmi_device *sdev = to_scmi_dev(data); 2149 + 2150 + /* Skip transport devices and devices of different SCMI instances */ 2151 + if (!strncmp(sdev->name, "__scmi_transport_device", 23) || 2152 + sdev->dev.parent != info->dev) 2153 + return NOTIFY_DONE; 2154 + 2155 + switch (action) { 2156 + case BUS_NOTIFY_BIND_DRIVER: 2157 + /* setup handle now as the transport is ready */ 2158 + scmi_set_handle(sdev); 2159 + break; 2160 + case BUS_NOTIFY_UNBOUND_DRIVER: 2161 + scmi_handle_put(sdev->handle); 2162 + sdev->handle = NULL; 2163 + break; 2164 + default: 2165 + return NOTIFY_DONE; 2166 + } 2167 + 2168 + dev_dbg(info->dev, "Device %s (%s) is now %s\n", dev_name(&sdev->dev), 2169 + sdev->name, action == BUS_NOTIFY_BIND_DRIVER ? 2170 + "about to be BOUND." : "UNBOUND."); 2171 + 2172 + return NOTIFY_OK; 2173 + } 2174 + 2175 + static int scmi_device_request_notifier(struct notifier_block *nb, 2176 + unsigned long action, void *data) 2177 + { 2178 + struct device_node *np; 2179 + struct scmi_device_id *id_table = data; 2180 + struct scmi_info *info = req_nb_to_scmi_info(nb); 2181 + 2182 + np = idr_find(&info->active_protocols, id_table->protocol_id); 2183 + if (!np) 2184 + return NOTIFY_DONE; 2185 + 2186 + dev_dbg(info->dev, "%sRequested device (%s) for protocol 0x%x\n", 2187 + action == SCMI_BUS_NOTIFY_DEVICE_REQUEST ? "" : "UN-", 2188 + id_table->name, id_table->protocol_id); 2189 + 2190 + switch (action) { 2191 + case SCMI_BUS_NOTIFY_DEVICE_REQUEST: 2192 + scmi_create_protocol_devices(np, info, id_table->protocol_id, 2193 + id_table->name); 2194 + break; 2195 + case SCMI_BUS_NOTIFY_DEVICE_UNREQUEST: 2196 + scmi_destroy_protocol_devices(info, id_table->protocol_id, 2197 + id_table->name); 2198 + break; 2199 + default: 2200 + return NOTIFY_DONE; 2201 + } 2202 + 2203 + return NOTIFY_OK; 2204 + } 2205 + 2206 + static void scmi_debugfs_common_cleanup(void *d) 2207 + { 2208 + struct scmi_debug_info *dbg = d; 2209 + 2210 + if (!dbg) 2211 + return; 2212 + 2213 + debugfs_remove_recursive(dbg->top_dentry); 2214 + kfree(dbg->name); 2215 + kfree(dbg->type); 2216 + } 2217 + 2218 + static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info) 2219 + { 2220 + char top_dir[16]; 2221 + struct dentry *trans, *top_dentry; 2222 + struct scmi_debug_info *dbg; 2223 + const char *c_ptr = NULL; 2224 + 2225 + dbg = devm_kzalloc(info->dev, sizeof(*dbg), GFP_KERNEL); 2226 + if (!dbg) 2227 + return NULL; 2228 + 2229 + dbg->name = kstrdup(of_node_full_name(info->dev->of_node), GFP_KERNEL); 2230 + if (!dbg->name) { 2231 + devm_kfree(info->dev, dbg); 2232 + return NULL; 2233 + } 2234 + 2235 + of_property_read_string(info->dev->of_node, "compatible", &c_ptr); 2236 + dbg->type = kstrdup(c_ptr, GFP_KERNEL); 2237 + if (!dbg->type) { 2238 + kfree(dbg->name); 2239 + devm_kfree(info->dev, dbg); 2240 + return NULL; 2241 + } 2242 + 2243 + snprintf(top_dir, 16, "%d", info->id); 2244 + top_dentry = debugfs_create_dir(top_dir, scmi_top_dentry); 2245 + trans = debugfs_create_dir("transport", top_dentry); 2246 + 2247 + dbg->is_atomic = info->desc->atomic_enabled && 2248 + is_transport_polling_capable(info->desc); 2249 + 2250 + debugfs_create_str("instance_name", 0400, top_dentry, 2251 + (char **)&dbg->name); 2252 + 2253 + debugfs_create_u32("atomic_threshold_us", 0400, top_dentry, 2254 + &info->atomic_threshold); 2255 + 2256 + debugfs_create_str("type", 0400, trans, (char **)&dbg->type); 2257 + 2258 + debugfs_create_bool("is_atomic", 0400, trans, &dbg->is_atomic); 2259 + 2260 + debugfs_create_u32("max_rx_timeout_ms", 0400, trans, 2261 + (u32 *)&info->desc->max_rx_timeout_ms); 2262 + 2263 + debugfs_create_u32("max_msg_size", 0400, trans, 2264 + (u32 *)&info->desc->max_msg_size); 2265 + 2266 + debugfs_create_u32("tx_max_msg", 0400, trans, 2267 + (u32 *)&info->tx_minfo.max_msg); 2268 + 2269 + debugfs_create_u32("rx_max_msg", 0400, trans, 2270 + (u32 *)&info->rx_minfo.max_msg); 2271 + 2272 + dbg->top_dentry = top_dentry; 2273 + 2274 + if (devm_add_action_or_reset(info->dev, 2275 + scmi_debugfs_common_cleanup, dbg)) { 2276 + scmi_debugfs_common_cleanup(dbg); 2277 + return NULL; 2278 + } 2279 + 2280 + return dbg; 2281 + } 2282 + 2283 + static int scmi_debugfs_raw_mode_setup(struct scmi_info *info) 2284 + { 2285 + int id, num_chans = 0, ret = 0; 2286 + struct scmi_chan_info *cinfo; 2287 + u8 channels[SCMI_MAX_CHANNELS] = {}; 2288 + DECLARE_BITMAP(protos, SCMI_MAX_CHANNELS) = {}; 2289 + 2290 + if (!info->dbg) 2291 + return -EINVAL; 2292 + 2293 + /* Enumerate all channels to collect their ids */ 2294 + idr_for_each_entry(&info->tx_idr, cinfo, id) { 2295 + /* 2296 + * Cannot happen, but be defensive. 2297 + * Zero as num_chans is ok, warn and carry on. 2298 + */ 2299 + if (num_chans >= SCMI_MAX_CHANNELS || !cinfo) { 2300 + dev_warn(info->dev, 2301 + "SCMI RAW - Error enumerating channels\n"); 2302 + break; 2303 + } 2304 + 2305 + if (!test_bit(cinfo->id, protos)) { 2306 + channels[num_chans++] = cinfo->id; 2307 + set_bit(cinfo->id, protos); 2308 + } 2309 + } 2310 + 2311 + info->raw = scmi_raw_mode_init(&info->handle, info->dbg->top_dentry, 2312 + info->id, channels, num_chans, 2313 + info->desc, info->tx_minfo.max_msg); 2314 + if (IS_ERR(info->raw)) { 2315 + dev_err(info->dev, "Failed to initialize SCMI RAW Mode !\n"); 2316 + ret = PTR_ERR(info->raw); 2317 + info->raw = NULL; 2318 + } 2692 2319 2693 2320 return ret; 2694 2321 } ··· 2668 2379 if (!info) 2669 2380 return -ENOMEM; 2670 2381 2382 + info->id = ida_alloc_min(&scmi_id, 0, GFP_KERNEL); 2383 + if (info->id < 0) 2384 + return info->id; 2385 + 2671 2386 info->dev = dev; 2672 2387 info->desc = desc; 2388 + info->bus_nb.notifier_call = scmi_bus_notifier; 2389 + info->dev_req_nb.notifier_call = scmi_device_request_notifier; 2673 2390 INIT_LIST_HEAD(&info->node); 2674 2391 idr_init(&info->protocols); 2675 2392 mutex_init(&info->protocols_mtx); 2676 2393 idr_init(&info->active_protocols); 2394 + mutex_init(&info->devreq_mtx); 2677 2395 2678 2396 platform_set_drvdata(pdev, info); 2679 2397 idr_init(&info->tx_idr); ··· 2704 2408 if (desc->ops->link_supplier) { 2705 2409 ret = desc->ops->link_supplier(dev); 2706 2410 if (ret) 2707 - return ret; 2411 + goto clear_ida; 2708 2412 } 2709 2413 2710 - ret = scmi_txrx_setup(info, dev, SCMI_PROTOCOL_BASE); 2414 + /* Setup all channels described in the DT at first */ 2415 + ret = scmi_channels_setup(info); 2711 2416 if (ret) 2712 - return ret; 2417 + goto clear_ida; 2418 + 2419 + ret = bus_register_notifier(&scmi_bus_type, &info->bus_nb); 2420 + if (ret) 2421 + goto clear_txrx_setup; 2422 + 2423 + ret = blocking_notifier_chain_register(&scmi_requested_devices_nh, 2424 + &info->dev_req_nb); 2425 + if (ret) 2426 + goto clear_bus_notifier; 2713 2427 2714 2428 ret = scmi_xfer_info_init(info); 2715 2429 if (ret) 2716 - goto clear_txrx_setup; 2430 + goto clear_dev_req_notifier; 2431 + 2432 + if (scmi_top_dentry) { 2433 + info->dbg = scmi_debugfs_common_setup(info); 2434 + if (!info->dbg) 2435 + dev_warn(dev, "Failed to setup SCMI debugfs.\n"); 2436 + 2437 + if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { 2438 + bool coex = 2439 + IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX); 2440 + 2441 + ret = scmi_debugfs_raw_mode_setup(info); 2442 + if (!coex) { 2443 + if (ret) 2444 + goto clear_dev_req_notifier; 2445 + 2446 + /* Bail out anyway when coex enabled */ 2447 + return ret; 2448 + } 2449 + 2450 + /* Coex enabled, carry on in any case. */ 2451 + dev_info(dev, "SCMI RAW Mode COEX enabled !\n"); 2452 + } 2453 + } 2717 2454 2718 2455 if (scmi_notification_init(handle)) 2719 2456 dev_err(dev, "SCMI Notifications NOT available.\n"); 2720 2457 2721 - if (info->desc->atomic_enabled && !is_transport_polling_capable(info)) 2458 + if (info->desc->atomic_enabled && 2459 + !is_transport_polling_capable(info->desc)) 2722 2460 dev_err(dev, 2723 2461 "Transport is not polling capable. Atomic mode not supported.\n"); 2724 2462 ··· 2799 2469 } 2800 2470 2801 2471 of_node_get(child); 2802 - scmi_create_protocol_devices(child, info, prot_id); 2472 + scmi_create_protocol_devices(child, info, prot_id, NULL); 2803 2473 } 2804 2474 2805 2475 return 0; 2806 2476 2807 2477 notification_exit: 2478 + if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) 2479 + scmi_raw_mode_cleanup(info->raw); 2808 2480 scmi_notification_exit(&info->handle); 2481 + clear_dev_req_notifier: 2482 + blocking_notifier_chain_unregister(&scmi_requested_devices_nh, 2483 + &info->dev_req_nb); 2484 + clear_bus_notifier: 2485 + bus_unregister_notifier(&scmi_bus_type, &info->bus_nb); 2809 2486 clear_txrx_setup: 2810 2487 scmi_cleanup_txrx_channels(info); 2488 + clear_ida: 2489 + ida_free(&scmi_id, info->id); 2811 2490 return ret; 2812 - } 2813 - 2814 - void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id) 2815 - { 2816 - idr_remove(idr, id); 2817 2491 } 2818 2492 2819 2493 static int scmi_remove(struct platform_device *pdev) 2820 2494 { 2821 - int ret, id; 2495 + int id; 2822 2496 struct scmi_info *info = platform_get_drvdata(pdev); 2823 2497 struct device_node *child; 2498 + 2499 + if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) 2500 + scmi_raw_mode_cleanup(info->raw); 2824 2501 2825 2502 mutex_lock(&scmi_list_mutex); 2826 2503 if (info->users) ··· 2846 2509 of_node_put(child); 2847 2510 idr_destroy(&info->active_protocols); 2848 2511 2512 + blocking_notifier_chain_unregister(&scmi_requested_devices_nh, 2513 + &info->dev_req_nb); 2514 + bus_unregister_notifier(&scmi_bus_type, &info->bus_nb); 2515 + 2849 2516 /* Safe to free channels since no more users */ 2850 - ret = scmi_cleanup_txrx_channels(info); 2851 - if (ret) 2852 - dev_warn(&pdev->dev, "Failed to cleanup SCMI channels.\n"); 2517 + scmi_cleanup_txrx_channels(info); 2518 + 2519 + ida_free(&scmi_id, info->id); 2853 2520 2854 2521 return 0; 2855 2522 } ··· 2982 2641 __scmi_transports_setup(false); 2983 2642 } 2984 2643 2644 + static struct dentry *scmi_debugfs_init(void) 2645 + { 2646 + struct dentry *d; 2647 + 2648 + d = debugfs_create_dir("scmi", NULL); 2649 + if (IS_ERR(d)) { 2650 + pr_err("Could NOT create SCMI top dentry.\n"); 2651 + return NULL; 2652 + } 2653 + 2654 + return d; 2655 + } 2656 + 2985 2657 static int __init scmi_driver_init(void) 2986 2658 { 2987 2659 int ret; ··· 3003 2649 if (WARN_ON(!IS_ENABLED(CONFIG_ARM_SCMI_HAVE_TRANSPORT))) 3004 2650 return -EINVAL; 3005 2651 3006 - scmi_bus_init(); 3007 - 3008 2652 /* Initialize any compiled-in transport which provided an init/exit */ 3009 2653 ret = scmi_transports_init(); 3010 2654 if (ret) 3011 2655 return ret; 2656 + 2657 + if (IS_ENABLED(CONFIG_ARM_SCMI_NEED_DEBUGFS)) 2658 + scmi_top_dentry = scmi_debugfs_init(); 3012 2659 3013 2660 scmi_base_register(); 3014 2661 ··· 3024 2669 3025 2670 return platform_driver_register(&scmi_driver); 3026 2671 } 3027 - subsys_initcall(scmi_driver_init); 2672 + module_init(scmi_driver_init); 3028 2673 3029 2674 static void __exit scmi_driver_exit(void) 3030 2675 { ··· 3039 2684 scmi_system_unregister(); 3040 2685 scmi_powercap_unregister(); 3041 2686 3042 - scmi_bus_exit(); 3043 - 3044 2687 scmi_transports_exit(); 3045 2688 3046 2689 platform_driver_unregister(&scmi_driver); 2690 + 2691 + debugfs_remove_recursive(scmi_top_dentry); 3047 2692 } 3048 2693 module_exit(scmi_driver_exit); 3049 2694
+2 -4
drivers/firmware/arm_scmi/mailbox.c
··· 46 46 scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem), NULL); 47 47 } 48 48 49 - static bool mailbox_chan_available(struct device *dev, int idx) 49 + static bool mailbox_chan_available(struct device_node *of_node, int idx) 50 50 { 51 - return !of_parse_phandle_with_args(dev->of_node, "mboxes", 51 + return !of_parse_phandle_with_args(of_node, "mboxes", 52 52 "#mbox-cells", idx, NULL); 53 53 } 54 54 ··· 119 119 smbox->chan = NULL; 120 120 smbox->cinfo = NULL; 121 121 } 122 - 123 - scmi_free_channel(cinfo, data, id); 124 122 125 123 return 0; 126 124 }
+2 -4
drivers/firmware/arm_scmi/optee.c
··· 328 328 return 0; 329 329 } 330 330 331 - static bool scmi_optee_chan_available(struct device *dev, int idx) 331 + static bool scmi_optee_chan_available(struct device_node *of_node, int idx) 332 332 { 333 333 u32 channel_id; 334 334 335 - return !of_property_read_u32_index(dev->of_node, "linaro,optee-channel-id", 335 + return !of_property_read_u32_index(of_node, "linaro,optee-channel-id", 336 336 idx, &channel_id); 337 337 } 338 338 ··· 480 480 481 481 cinfo->transport_info = NULL; 482 482 channel->cinfo = NULL; 483 - 484 - scmi_free_channel(cinfo, data, id); 485 483 486 484 return 0; 487 485 }
+7
drivers/firmware/arm_scmi/protocols.h
··· 115 115 * - SCMI_XFER_SENT_OK -> SCMI_XFER_RESP_OK [ -> SCMI_XFER_DRESP_OK ] 116 116 * - SCMI_XFER_SENT_OK -> SCMI_XFER_DRESP_OK 117 117 * (Missing synchronous response is assumed OK and ignored) 118 + * @flags: Optional flags associated to this xfer. 118 119 * @lock: A spinlock to protect state and busy fields. 119 120 * @priv: A pointer for transport private usage. 120 121 */ ··· 136 135 #define SCMI_XFER_RESP_OK 1 137 136 #define SCMI_XFER_DRESP_OK 2 138 137 int state; 138 + #define SCMI_XFER_FLAG_IS_RAW BIT(0) 139 + #define SCMI_XFER_IS_RAW(x) ((x)->flags & SCMI_XFER_FLAG_IS_RAW) 140 + #define SCMI_XFER_FLAG_CHAN_SET BIT(1) 141 + #define SCMI_XFER_IS_CHAN_SET(x) \ 142 + ((x)->flags & SCMI_XFER_FLAG_CHAN_SET) 143 + int flags; 139 144 /* A lock to protect state and busy fields */ 140 145 spinlock_t lock; 141 146 void *priv;
+1443
drivers/firmware/arm_scmi/raw_mode.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * System Control and Management Interface (SCMI) Raw mode support 4 + * 5 + * Copyright (C) 2022 ARM Ltd. 6 + */ 7 + /** 8 + * DOC: Theory of operation 9 + * 10 + * When enabled the SCMI Raw mode support exposes a userspace API which allows 11 + * to send and receive SCMI commands, replies and notifications from a user 12 + * application through injection and snooping of bare SCMI messages in binary 13 + * little-endian format. 14 + * 15 + * Such injected SCMI transactions will then be routed through the SCMI core 16 + * stack towards the SCMI backend server using whatever SCMI transport is 17 + * currently configured on the system under test. 18 + * 19 + * It is meant to help in running any sort of SCMI backend server testing, no 20 + * matter where the server is placed, as long as it is normally reachable via 21 + * the transport configured on the system. 22 + * 23 + * It is activated by a Kernel configuration option since it is NOT meant to 24 + * be used in production but only during development and in CI deployments. 25 + * 26 + * In order to avoid possible interferences between the SCMI Raw transactions 27 + * originated from a test-suite and the normal operations of the SCMI drivers, 28 + * when Raw mode is enabled, by default, all the regular SCMI drivers are 29 + * inhibited, unless CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX is enabled: in this 30 + * latter case the regular SCMI stack drivers will be loaded as usual and it is 31 + * up to the user of this interface to take care of manually inhibiting the 32 + * regular SCMI drivers in order to avoid interferences during the test runs. 33 + * 34 + * The exposed API is as follows. 35 + * 36 + * All SCMI Raw entries are rooted under a common top /raw debugfs top directory 37 + * which in turn is rooted under the corresponding underlying SCMI instance. 38 + * 39 + * /sys/kernel/debug/scmi/ 40 + * `-- 0 41 + * |-- atomic_threshold_us 42 + * |-- instance_name 43 + * |-- raw 44 + * | |-- channels 45 + * | | |-- 0x10 46 + * | | | |-- message 47 + * | | | `-- message_async 48 + * | | `-- 0x13 49 + * | | |-- message 50 + * | | `-- message_async 51 + * | |-- errors 52 + * | |-- message 53 + * | |-- message_async 54 + * | |-- notification 55 + * | `-- reset 56 + * `-- transport 57 + * |-- is_atomic 58 + * |-- max_msg_size 59 + * |-- max_rx_timeout_ms 60 + * |-- rx_max_msg 61 + * |-- tx_max_msg 62 + * `-- type 63 + * 64 + * where: 65 + * 66 + * - errors: used to read back timed-out and unexpected replies 67 + * - message*: used to send sync/async commands and read back immediate and 68 + * delayed reponses (if any) 69 + * - notification: used to read any notification being emitted by the system 70 + * (if previously enabled by the user app) 71 + * - reset: used to flush the queues of messages (of any kind) still pending 72 + * to be read; this is useful at test-suite start/stop to get 73 + * rid of any unread messages from the previous run. 74 + * 75 + * with the per-channel entries rooted at /channels being present only on a 76 + * system where multiple transport channels have been configured. 77 + * 78 + * Such per-channel entries can be used to explicitly choose a specific channel 79 + * for SCMI bare message injection, in contrast with the general entries above 80 + * where, instead, the selection of the proper channel to use is automatically 81 + * performed based the protocol embedded in the injected message and on how the 82 + * transport is configured on the system. 83 + * 84 + * Note that other common general entries are available under transport/ to let 85 + * the user applications properly make up their expectations in terms of 86 + * timeouts and message characteristics. 87 + * 88 + * Each write to the message* entries causes one command request to be built 89 + * and sent while the replies or delayed response are read back from those same 90 + * entries one message at time (receiving an EOF at each message boundary). 91 + * 92 + * The user application running the test is in charge of handling timeouts 93 + * on replies and properly choosing SCMI sequence numbers for the outgoing 94 + * requests (using the same sequence number is supported but discouraged). 95 + * 96 + * Injection of multiple in-flight requests is supported as long as the user 97 + * application uses properly distinct sequence numbers for concurrent requests 98 + * and takes care to properly manage all the related issues about concurrency 99 + * and command/reply pairing. Keep in mind that, anyway, the real level of 100 + * parallelism attainable in such scenario is dependent on the characteristics 101 + * of the underlying transport being used. 102 + * 103 + * Since the SCMI core regular stack is partially used to deliver and collect 104 + * the messages, late replies arrived after timeouts and any other sort of 105 + * unexpected message can be identified by the SCMI core as usual and they will 106 + * be reported as messages under "errors" for later analysis. 107 + */ 108 + 109 + #include <linux/bitmap.h> 110 + #include <linux/debugfs.h> 111 + #include <linux/delay.h> 112 + #include <linux/device.h> 113 + #include <linux/export.h> 114 + #include <linux/io.h> 115 + #include <linux/kernel.h> 116 + #include <linux/fs.h> 117 + #include <linux/list.h> 118 + #include <linux/module.h> 119 + #include <linux/poll.h> 120 + #include <linux/of.h> 121 + #include <linux/slab.h> 122 + #include <linux/xarray.h> 123 + 124 + #include "common.h" 125 + 126 + #include "raw_mode.h" 127 + 128 + #include <trace/events/scmi.h> 129 + 130 + #define SCMI_XFER_RAW_MAX_RETRIES 10 131 + 132 + /** 133 + * struct scmi_raw_queue - Generic Raw queue descriptor 134 + * 135 + * @free_bufs: A freelists listhead used to keep unused raw buffers 136 + * @free_bufs_lock: Spinlock used to protect access to @free_bufs 137 + * @msg_q: A listhead to a queue of snooped messages waiting to be read out 138 + * @msg_q_lock: Spinlock used to protect access to @msg_q 139 + * @wq: A waitqueue used to wait and poll on related @msg_q 140 + */ 141 + struct scmi_raw_queue { 142 + struct list_head free_bufs; 143 + /* Protect free_bufs[] lists */ 144 + spinlock_t free_bufs_lock; 145 + struct list_head msg_q; 146 + /* Protect msg_q[] lists */ 147 + spinlock_t msg_q_lock; 148 + wait_queue_head_t wq; 149 + }; 150 + 151 + /** 152 + * struct scmi_raw_mode_info - Structure holding SCMI Raw instance data 153 + * 154 + * @id: Sequential Raw instance ID. 155 + * @handle: Pointer to SCMI entity handle to use 156 + * @desc: Pointer to the transport descriptor to use 157 + * @tx_max_msg: Maximum number of concurrent TX in-flight messages 158 + * @q: An array of Raw queue descriptors 159 + * @chans_q: An XArray mapping optional additional per-channel queues 160 + * @free_waiters: Head of freelist for unused waiters 161 + * @free_mtx: A mutex to protect the waiters freelist 162 + * @active_waiters: Head of list for currently active and used waiters 163 + * @active_mtx: A mutex to protect the active waiters list 164 + * @waiters_work: A work descriptor to be used with the workqueue machinery 165 + * @wait_wq: A workqueue reference to the created workqueue 166 + * @dentry: Top debugfs root dentry for SCMI Raw 167 + * @gid: A group ID used for devres accounting 168 + * 169 + * Note that this descriptor is passed back to the core after SCMI Raw is 170 + * initialized as an opaque handle to use by subsequent SCMI Raw call hooks. 171 + * 172 + */ 173 + struct scmi_raw_mode_info { 174 + unsigned int id; 175 + const struct scmi_handle *handle; 176 + const struct scmi_desc *desc; 177 + int tx_max_msg; 178 + struct scmi_raw_queue *q[SCMI_RAW_MAX_QUEUE]; 179 + struct xarray chans_q; 180 + struct list_head free_waiters; 181 + /* Protect free_waiters list */ 182 + struct mutex free_mtx; 183 + struct list_head active_waiters; 184 + /* Protect active_waiters list */ 185 + struct mutex active_mtx; 186 + struct work_struct waiters_work; 187 + struct workqueue_struct *wait_wq; 188 + struct dentry *dentry; 189 + void *gid; 190 + }; 191 + 192 + /** 193 + * struct scmi_xfer_raw_waiter - Structure to describe an xfer to be waited for 194 + * 195 + * @start_jiffies: The timestamp in jiffies of when this structure was queued. 196 + * @cinfo: A reference to the channel to use for this transaction 197 + * @xfer: A reference to the xfer to be waited for 198 + * @async_response: A completion to be, optionally, used for async waits: it 199 + * will be setup by @scmi_do_xfer_raw_start, if needed, to be 200 + * pointed at by xfer->async_done. 201 + * @node: A list node. 202 + */ 203 + struct scmi_xfer_raw_waiter { 204 + unsigned long start_jiffies; 205 + struct scmi_chan_info *cinfo; 206 + struct scmi_xfer *xfer; 207 + struct completion async_response; 208 + struct list_head node; 209 + }; 210 + 211 + /** 212 + * struct scmi_raw_buffer - Structure to hold a full SCMI message 213 + * 214 + * @max_len: The maximum allowed message size (header included) that can be 215 + * stored into @msg 216 + * @msg: A message buffer used to collect a full message grabbed from an xfer. 217 + * @node: A list node. 218 + */ 219 + struct scmi_raw_buffer { 220 + size_t max_len; 221 + struct scmi_msg msg; 222 + struct list_head node; 223 + }; 224 + 225 + /** 226 + * struct scmi_dbg_raw_data - Structure holding data needed by the debugfs 227 + * layer 228 + * 229 + * @chan_id: The preferred channel to use: if zero the channel is automatically 230 + * selected based on protocol. 231 + * @raw: A reference to the Raw instance. 232 + * @tx: A message buffer used to collect TX message on write. 233 + * @tx_size: The effective size of the TX message. 234 + * @tx_req_size: The final expected size of the complete TX message. 235 + * @rx: A message buffer to collect RX message on read. 236 + * @rx_size: The effective size of the RX message. 237 + */ 238 + struct scmi_dbg_raw_data { 239 + u8 chan_id; 240 + struct scmi_raw_mode_info *raw; 241 + struct scmi_msg tx; 242 + size_t tx_size; 243 + size_t tx_req_size; 244 + struct scmi_msg rx; 245 + size_t rx_size; 246 + }; 247 + 248 + static struct scmi_raw_queue * 249 + scmi_raw_queue_select(struct scmi_raw_mode_info *raw, unsigned int idx, 250 + unsigned int chan_id) 251 + { 252 + if (!chan_id) 253 + return raw->q[idx]; 254 + 255 + return xa_load(&raw->chans_q, chan_id); 256 + } 257 + 258 + static struct scmi_raw_buffer *scmi_raw_buffer_get(struct scmi_raw_queue *q) 259 + { 260 + unsigned long flags; 261 + struct scmi_raw_buffer *rb = NULL; 262 + struct list_head *head = &q->free_bufs; 263 + 264 + spin_lock_irqsave(&q->free_bufs_lock, flags); 265 + if (!list_empty(head)) { 266 + rb = list_first_entry(head, struct scmi_raw_buffer, node); 267 + list_del_init(&rb->node); 268 + } 269 + spin_unlock_irqrestore(&q->free_bufs_lock, flags); 270 + 271 + return rb; 272 + } 273 + 274 + static void scmi_raw_buffer_put(struct scmi_raw_queue *q, 275 + struct scmi_raw_buffer *rb) 276 + { 277 + unsigned long flags; 278 + 279 + /* Reset to full buffer length */ 280 + rb->msg.len = rb->max_len; 281 + 282 + spin_lock_irqsave(&q->free_bufs_lock, flags); 283 + list_add_tail(&rb->node, &q->free_bufs); 284 + spin_unlock_irqrestore(&q->free_bufs_lock, flags); 285 + } 286 + 287 + static void scmi_raw_buffer_enqueue(struct scmi_raw_queue *q, 288 + struct scmi_raw_buffer *rb) 289 + { 290 + unsigned long flags; 291 + 292 + spin_lock_irqsave(&q->msg_q_lock, flags); 293 + list_add_tail(&rb->node, &q->msg_q); 294 + spin_unlock_irqrestore(&q->msg_q_lock, flags); 295 + 296 + wake_up_interruptible(&q->wq); 297 + } 298 + 299 + static struct scmi_raw_buffer* 300 + scmi_raw_buffer_dequeue_unlocked(struct scmi_raw_queue *q) 301 + { 302 + struct scmi_raw_buffer *rb = NULL; 303 + 304 + if (!list_empty(&q->msg_q)) { 305 + rb = list_first_entry(&q->msg_q, struct scmi_raw_buffer, node); 306 + list_del_init(&rb->node); 307 + } 308 + 309 + return rb; 310 + } 311 + 312 + static struct scmi_raw_buffer *scmi_raw_buffer_dequeue(struct scmi_raw_queue *q) 313 + { 314 + unsigned long flags; 315 + struct scmi_raw_buffer *rb; 316 + 317 + spin_lock_irqsave(&q->msg_q_lock, flags); 318 + rb = scmi_raw_buffer_dequeue_unlocked(q); 319 + spin_unlock_irqrestore(&q->msg_q_lock, flags); 320 + 321 + return rb; 322 + } 323 + 324 + static void scmi_raw_buffer_queue_flush(struct scmi_raw_queue *q) 325 + { 326 + struct scmi_raw_buffer *rb; 327 + 328 + do { 329 + rb = scmi_raw_buffer_dequeue(q); 330 + if (rb) 331 + scmi_raw_buffer_put(q, rb); 332 + } while (rb); 333 + } 334 + 335 + static struct scmi_xfer_raw_waiter * 336 + scmi_xfer_raw_waiter_get(struct scmi_raw_mode_info *raw, struct scmi_xfer *xfer, 337 + struct scmi_chan_info *cinfo, bool async) 338 + { 339 + struct scmi_xfer_raw_waiter *rw = NULL; 340 + 341 + mutex_lock(&raw->free_mtx); 342 + if (!list_empty(&raw->free_waiters)) { 343 + rw = list_first_entry(&raw->free_waiters, 344 + struct scmi_xfer_raw_waiter, node); 345 + list_del_init(&rw->node); 346 + 347 + if (async) { 348 + reinit_completion(&rw->async_response); 349 + xfer->async_done = &rw->async_response; 350 + } 351 + 352 + rw->cinfo = cinfo; 353 + rw->xfer = xfer; 354 + } 355 + mutex_unlock(&raw->free_mtx); 356 + 357 + return rw; 358 + } 359 + 360 + static void scmi_xfer_raw_waiter_put(struct scmi_raw_mode_info *raw, 361 + struct scmi_xfer_raw_waiter *rw) 362 + { 363 + if (rw->xfer) { 364 + rw->xfer->async_done = NULL; 365 + rw->xfer = NULL; 366 + } 367 + 368 + mutex_lock(&raw->free_mtx); 369 + list_add_tail(&rw->node, &raw->free_waiters); 370 + mutex_unlock(&raw->free_mtx); 371 + } 372 + 373 + static void scmi_xfer_raw_waiter_enqueue(struct scmi_raw_mode_info *raw, 374 + struct scmi_xfer_raw_waiter *rw) 375 + { 376 + /* A timestamp for the deferred worker to know how much this has aged */ 377 + rw->start_jiffies = jiffies; 378 + 379 + trace_scmi_xfer_response_wait(rw->xfer->transfer_id, rw->xfer->hdr.id, 380 + rw->xfer->hdr.protocol_id, 381 + rw->xfer->hdr.seq, 382 + raw->desc->max_rx_timeout_ms, 383 + rw->xfer->hdr.poll_completion); 384 + 385 + mutex_lock(&raw->active_mtx); 386 + list_add_tail(&rw->node, &raw->active_waiters); 387 + mutex_unlock(&raw->active_mtx); 388 + 389 + /* kick waiter work */ 390 + queue_work(raw->wait_wq, &raw->waiters_work); 391 + } 392 + 393 + static struct scmi_xfer_raw_waiter * 394 + scmi_xfer_raw_waiter_dequeue(struct scmi_raw_mode_info *raw) 395 + { 396 + struct scmi_xfer_raw_waiter *rw = NULL; 397 + 398 + mutex_lock(&raw->active_mtx); 399 + if (!list_empty(&raw->active_waiters)) { 400 + rw = list_first_entry(&raw->active_waiters, 401 + struct scmi_xfer_raw_waiter, node); 402 + list_del_init(&rw->node); 403 + } 404 + mutex_unlock(&raw->active_mtx); 405 + 406 + return rw; 407 + } 408 + 409 + /** 410 + * scmi_xfer_raw_worker - Work function to wait for Raw xfers completions 411 + * 412 + * @work: A reference to the work. 413 + * 414 + * In SCMI Raw mode, once a user-provided injected SCMI message is sent, we 415 + * cannot wait to receive its response (if any) in the context of the injection 416 + * routines so as not to leave the userspace write syscall, which delivered the 417 + * SCMI message to send, pending till eventually a reply is received. 418 + * Userspace should and will poll/wait instead on the read syscalls which will 419 + * be in charge of reading a received reply (if any). 420 + * 421 + * Even though reply messages are collected and reported into the SCMI Raw layer 422 + * on the RX path, nonetheless we have to properly wait for their completion as 423 + * usual (and async_completion too if needed) in order to properly release the 424 + * xfer structure at the end: to do this out of the context of the write/send 425 + * these waiting jobs are delegated to this deferred worker. 426 + * 427 + * Any sent xfer, to be waited for, is timestamped and queued for later 428 + * consumption by this worker: queue aging is accounted for while choosing a 429 + * timeout for the completion, BUT we do not really care here if we end up 430 + * accidentally waiting for a bit too long. 431 + */ 432 + static void scmi_xfer_raw_worker(struct work_struct *work) 433 + { 434 + struct scmi_raw_mode_info *raw; 435 + struct device *dev; 436 + unsigned long max_tmo; 437 + 438 + raw = container_of(work, struct scmi_raw_mode_info, waiters_work); 439 + dev = raw->handle->dev; 440 + max_tmo = msecs_to_jiffies(raw->desc->max_rx_timeout_ms); 441 + 442 + do { 443 + int ret = 0; 444 + unsigned int timeout_ms; 445 + unsigned long aging; 446 + struct scmi_xfer *xfer; 447 + struct scmi_xfer_raw_waiter *rw; 448 + struct scmi_chan_info *cinfo; 449 + 450 + rw = scmi_xfer_raw_waiter_dequeue(raw); 451 + if (!rw) 452 + return; 453 + 454 + cinfo = rw->cinfo; 455 + xfer = rw->xfer; 456 + /* 457 + * Waiters are queued by wait-deadline at the end, so some of 458 + * them could have been already expired when processed, BUT we 459 + * have to check the completion status anyway just in case a 460 + * virtually expired (aged) transaction was indeed completed 461 + * fine and we'll have to wait for the asynchronous part (if 462 + * any): for this reason a 1 ms timeout is used for already 463 + * expired/aged xfers. 464 + */ 465 + aging = jiffies - rw->start_jiffies; 466 + timeout_ms = max_tmo > aging ? 467 + jiffies_to_msecs(max_tmo - aging) : 1; 468 + 469 + ret = scmi_xfer_raw_wait_for_message_response(cinfo, xfer, 470 + timeout_ms); 471 + if (!ret && xfer->hdr.status) 472 + ret = scmi_to_linux_errno(xfer->hdr.status); 473 + 474 + if (raw->desc->ops->mark_txdone) 475 + raw->desc->ops->mark_txdone(rw->cinfo, ret, xfer); 476 + 477 + trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id, 478 + xfer->hdr.protocol_id, xfer->hdr.seq, ret); 479 + 480 + /* Wait also for an async delayed response if needed */ 481 + if (!ret && xfer->async_done) { 482 + unsigned long tmo = msecs_to_jiffies(SCMI_MAX_RESPONSE_TIMEOUT); 483 + 484 + if (!wait_for_completion_timeout(xfer->async_done, tmo)) 485 + dev_err(dev, 486 + "timed out in RAW delayed resp - HDR:%08X\n", 487 + pack_scmi_header(&xfer->hdr)); 488 + } 489 + 490 + /* Release waiter and xfer */ 491 + scmi_xfer_raw_put(raw->handle, xfer); 492 + scmi_xfer_raw_waiter_put(raw, rw); 493 + } while (1); 494 + } 495 + 496 + static void scmi_xfer_raw_reset(struct scmi_raw_mode_info *raw) 497 + { 498 + int i; 499 + 500 + dev_info(raw->handle->dev, "Resetting SCMI Raw stack.\n"); 501 + 502 + for (i = 0; i < SCMI_RAW_MAX_QUEUE; i++) 503 + scmi_raw_buffer_queue_flush(raw->q[i]); 504 + } 505 + 506 + /** 507 + * scmi_xfer_raw_get_init - An helper to build a valid xfer from the provided 508 + * bare SCMI message. 509 + * 510 + * @raw: A reference to the Raw instance. 511 + * @buf: A buffer containing the whole SCMI message to send (including the 512 + * header) in little-endian binary formmat. 513 + * @len: Length of the message in @buf. 514 + * @p: A pointer to return the initialized Raw xfer. 515 + * 516 + * After an xfer is picked from the TX pool and filled in with the message 517 + * content, the xfer is registered as pending with the core in the usual way 518 + * using the original sequence number provided by the user with the message. 519 + * 520 + * Note that, in case the testing user application is NOT using distinct 521 + * sequence-numbers between successive SCMI messages such registration could 522 + * fail temporarily if the previous message, using the same sequence number, 523 + * had still not released; in such a case we just wait and retry. 524 + * 525 + * Return: 0 on Success 526 + */ 527 + static int scmi_xfer_raw_get_init(struct scmi_raw_mode_info *raw, void *buf, 528 + size_t len, struct scmi_xfer **p) 529 + { 530 + u32 msg_hdr; 531 + size_t tx_size; 532 + struct scmi_xfer *xfer; 533 + int ret, retry = SCMI_XFER_RAW_MAX_RETRIES; 534 + struct device *dev = raw->handle->dev; 535 + 536 + if (!buf || len < sizeof(u32)) 537 + return -EINVAL; 538 + 539 + tx_size = len - sizeof(u32); 540 + /* Ensure we have sane transfer sizes */ 541 + if (tx_size > raw->desc->max_msg_size) 542 + return -ERANGE; 543 + 544 + xfer = scmi_xfer_raw_get(raw->handle); 545 + if (IS_ERR(xfer)) { 546 + dev_warn(dev, "RAW - Cannot get a free RAW xfer !\n"); 547 + return PTR_ERR(xfer); 548 + } 549 + 550 + /* Build xfer from the provided SCMI bare LE message */ 551 + msg_hdr = le32_to_cpu(*((__le32 *)buf)); 552 + unpack_scmi_header(msg_hdr, &xfer->hdr); 553 + xfer->hdr.seq = (u16)MSG_XTRACT_TOKEN(msg_hdr); 554 + /* Polling not supported */ 555 + xfer->hdr.poll_completion = false; 556 + xfer->hdr.status = SCMI_SUCCESS; 557 + xfer->tx.len = tx_size; 558 + xfer->rx.len = raw->desc->max_msg_size; 559 + /* Clear the whole TX buffer */ 560 + memset(xfer->tx.buf, 0x00, raw->desc->max_msg_size); 561 + if (xfer->tx.len) 562 + memcpy(xfer->tx.buf, (u8 *)buf + sizeof(msg_hdr), xfer->tx.len); 563 + *p = xfer; 564 + 565 + /* 566 + * In flight registration can temporarily fail in case of Raw messages 567 + * if the user injects messages without using monotonically increasing 568 + * sequence numbers since, in Raw mode, the xfer (and the token) is 569 + * finally released later by a deferred worker. Just retry for a while. 570 + */ 571 + do { 572 + ret = scmi_xfer_raw_inflight_register(raw->handle, xfer); 573 + if (ret) { 574 + dev_dbg(dev, 575 + "...retrying[%d] inflight registration\n", 576 + retry); 577 + msleep(raw->desc->max_rx_timeout_ms / 578 + SCMI_XFER_RAW_MAX_RETRIES); 579 + } 580 + } while (ret && --retry); 581 + 582 + if (ret) { 583 + dev_warn(dev, 584 + "RAW - Could NOT register xfer %d in-flight HDR:0x%08X\n", 585 + xfer->hdr.seq, msg_hdr); 586 + scmi_xfer_raw_put(raw->handle, xfer); 587 + } 588 + 589 + return ret; 590 + } 591 + 592 + /** 593 + * scmi_do_xfer_raw_start - An helper to send a valid raw xfer 594 + * 595 + * @raw: A reference to the Raw instance. 596 + * @xfer: The xfer to send 597 + * @chan_id: The channel ID to use, if zero the channels is automatically 598 + * selected based on the protocol used. 599 + * @async: A flag stating if an asynchronous command is required. 600 + * 601 + * This function send a previously built raw xfer using an appropriate channel 602 + * and queues the related waiting work. 603 + * 604 + * Note that we need to know explicitly if the required command is meant to be 605 + * asynchronous in kind since we have to properly setup the waiter. 606 + * (and deducing this from the payload is weak and do not scale given there is 607 + * NOT a common header-flag stating if the command is asynchronous or not) 608 + * 609 + * Return: 0 on Success 610 + */ 611 + static int scmi_do_xfer_raw_start(struct scmi_raw_mode_info *raw, 612 + struct scmi_xfer *xfer, u8 chan_id, 613 + bool async) 614 + { 615 + int ret; 616 + struct scmi_chan_info *cinfo; 617 + struct scmi_xfer_raw_waiter *rw; 618 + struct device *dev = raw->handle->dev; 619 + 620 + if (!chan_id) 621 + chan_id = xfer->hdr.protocol_id; 622 + else 623 + xfer->flags |= SCMI_XFER_FLAG_CHAN_SET; 624 + 625 + cinfo = scmi_xfer_raw_channel_get(raw->handle, chan_id); 626 + if (IS_ERR(cinfo)) 627 + return PTR_ERR(cinfo); 628 + 629 + rw = scmi_xfer_raw_waiter_get(raw, xfer, cinfo, async); 630 + if (!rw) { 631 + dev_warn(dev, "RAW - Cannot get a free waiter !\n"); 632 + return -ENOMEM; 633 + } 634 + 635 + /* True ONLY if also supported by transport. */ 636 + if (is_polling_enabled(cinfo, raw->desc)) 637 + xfer->hdr.poll_completion = true; 638 + 639 + reinit_completion(&xfer->done); 640 + /* Make sure xfer state update is visible before sending */ 641 + smp_store_mb(xfer->state, SCMI_XFER_SENT_OK); 642 + 643 + trace_scmi_xfer_begin(xfer->transfer_id, xfer->hdr.id, 644 + xfer->hdr.protocol_id, xfer->hdr.seq, 645 + xfer->hdr.poll_completion); 646 + 647 + ret = raw->desc->ops->send_message(rw->cinfo, xfer); 648 + if (ret) { 649 + dev_err(dev, "Failed to send RAW message %d\n", ret); 650 + scmi_xfer_raw_waiter_put(raw, rw); 651 + return ret; 652 + } 653 + 654 + trace_scmi_msg_dump(raw->id, cinfo->id, xfer->hdr.protocol_id, 655 + xfer->hdr.id, "cmnd", xfer->hdr.seq, 656 + xfer->hdr.status, 657 + xfer->tx.buf, xfer->tx.len); 658 + 659 + scmi_xfer_raw_waiter_enqueue(raw, rw); 660 + 661 + return ret; 662 + } 663 + 664 + /** 665 + * scmi_raw_message_send - An helper to build and send an SCMI command using 666 + * the provided SCMI bare message buffer 667 + * 668 + * @raw: A reference to the Raw instance. 669 + * @buf: A buffer containing the whole SCMI message to send (including the 670 + * header) in little-endian binary format. 671 + * @len: Length of the message in @buf. 672 + * @chan_id: The channel ID to use. 673 + * @async: A flag stating if an asynchronous command is required. 674 + * 675 + * Return: 0 on Success 676 + */ 677 + static int scmi_raw_message_send(struct scmi_raw_mode_info *raw, 678 + void *buf, size_t len, u8 chan_id, bool async) 679 + { 680 + int ret; 681 + struct scmi_xfer *xfer; 682 + 683 + ret = scmi_xfer_raw_get_init(raw, buf, len, &xfer); 684 + if (ret) 685 + return ret; 686 + 687 + ret = scmi_do_xfer_raw_start(raw, xfer, chan_id, async); 688 + if (ret) 689 + scmi_xfer_raw_put(raw->handle, xfer); 690 + 691 + return ret; 692 + } 693 + 694 + static struct scmi_raw_buffer * 695 + scmi_raw_message_dequeue(struct scmi_raw_queue *q, bool o_nonblock) 696 + { 697 + unsigned long flags; 698 + struct scmi_raw_buffer *rb; 699 + 700 + spin_lock_irqsave(&q->msg_q_lock, flags); 701 + while (list_empty(&q->msg_q)) { 702 + spin_unlock_irqrestore(&q->msg_q_lock, flags); 703 + 704 + if (o_nonblock) 705 + return ERR_PTR(-EAGAIN); 706 + 707 + if (wait_event_interruptible(q->wq, !list_empty(&q->msg_q))) 708 + return ERR_PTR(-ERESTARTSYS); 709 + 710 + spin_lock_irqsave(&q->msg_q_lock, flags); 711 + } 712 + 713 + rb = scmi_raw_buffer_dequeue_unlocked(q); 714 + 715 + spin_unlock_irqrestore(&q->msg_q_lock, flags); 716 + 717 + return rb; 718 + } 719 + 720 + /** 721 + * scmi_raw_message_receive - An helper to dequeue and report the next 722 + * available enqueued raw message payload that has been collected. 723 + * 724 + * @raw: A reference to the Raw instance. 725 + * @buf: A buffer to get hold of the whole SCMI message received and represented 726 + * in little-endian binary format. 727 + * @len: Length of @buf. 728 + * @size: The effective size of the message copied into @buf 729 + * @idx: The index of the queue to pick the next queued message from. 730 + * @chan_id: The channel ID to use. 731 + * @o_nonblock: A flag to request a non-blocking message dequeue. 732 + * 733 + * Return: 0 on Success 734 + */ 735 + static int scmi_raw_message_receive(struct scmi_raw_mode_info *raw, 736 + void *buf, size_t len, size_t *size, 737 + unsigned int idx, unsigned int chan_id, 738 + bool o_nonblock) 739 + { 740 + int ret = 0; 741 + struct scmi_raw_buffer *rb; 742 + struct scmi_raw_queue *q; 743 + 744 + q = scmi_raw_queue_select(raw, idx, chan_id); 745 + if (!q) 746 + return -ENODEV; 747 + 748 + rb = scmi_raw_message_dequeue(q, o_nonblock); 749 + if (IS_ERR(rb)) { 750 + dev_dbg(raw->handle->dev, "RAW - No message available!\n"); 751 + return PTR_ERR(rb); 752 + } 753 + 754 + if (rb->msg.len <= len) { 755 + memcpy(buf, rb->msg.buf, rb->msg.len); 756 + *size = rb->msg.len; 757 + } else { 758 + ret = -ENOSPC; 759 + } 760 + 761 + scmi_raw_buffer_put(q, rb); 762 + 763 + return ret; 764 + } 765 + 766 + /* SCMI Raw debugfs helpers */ 767 + 768 + static ssize_t scmi_dbg_raw_mode_common_read(struct file *filp, 769 + char __user *buf, 770 + size_t count, loff_t *ppos, 771 + unsigned int idx) 772 + { 773 + ssize_t cnt; 774 + struct scmi_dbg_raw_data *rd = filp->private_data; 775 + 776 + if (!rd->rx_size) { 777 + int ret; 778 + 779 + ret = scmi_raw_message_receive(rd->raw, rd->rx.buf, rd->rx.len, 780 + &rd->rx_size, idx, rd->chan_id, 781 + filp->f_flags & O_NONBLOCK); 782 + if (ret) { 783 + rd->rx_size = 0; 784 + return ret; 785 + } 786 + 787 + /* Reset any previous filepos change, including writes */ 788 + *ppos = 0; 789 + } else if (*ppos == rd->rx_size) { 790 + /* Return EOF once all the message has been read-out */ 791 + rd->rx_size = 0; 792 + return 0; 793 + } 794 + 795 + cnt = simple_read_from_buffer(buf, count, ppos, 796 + rd->rx.buf, rd->rx_size); 797 + 798 + return cnt; 799 + } 800 + 801 + static ssize_t scmi_dbg_raw_mode_common_write(struct file *filp, 802 + const char __user *buf, 803 + size_t count, loff_t *ppos, 804 + bool async) 805 + { 806 + int ret; 807 + struct scmi_dbg_raw_data *rd = filp->private_data; 808 + 809 + if (count > rd->tx.len - rd->tx_size) 810 + return -ENOSPC; 811 + 812 + /* On first write attempt @count carries the total full message size. */ 813 + if (!rd->tx_size) 814 + rd->tx_req_size = count; 815 + 816 + /* 817 + * Gather a full message, possibly across multiple interrupted wrrtes, 818 + * before sending it with a single RAW xfer. 819 + */ 820 + if (rd->tx_size < rd->tx_req_size) { 821 + size_t cnt; 822 + 823 + cnt = simple_write_to_buffer(rd->tx.buf, rd->tx.len, ppos, 824 + buf, count); 825 + rd->tx_size += cnt; 826 + if (cnt < count) 827 + return cnt; 828 + } 829 + 830 + ret = scmi_raw_message_send(rd->raw, rd->tx.buf, rd->tx_size, 831 + rd->chan_id, async); 832 + 833 + /* Reset ppos for next message ... */ 834 + rd->tx_size = 0; 835 + *ppos = 0; 836 + 837 + return ret ?: count; 838 + } 839 + 840 + static __poll_t scmi_test_dbg_raw_common_poll(struct file *filp, 841 + struct poll_table_struct *wait, 842 + unsigned int idx) 843 + { 844 + unsigned long flags; 845 + struct scmi_dbg_raw_data *rd = filp->private_data; 846 + struct scmi_raw_queue *q; 847 + __poll_t mask = 0; 848 + 849 + q = scmi_raw_queue_select(rd->raw, idx, rd->chan_id); 850 + if (!q) 851 + return mask; 852 + 853 + poll_wait(filp, &q->wq, wait); 854 + 855 + spin_lock_irqsave(&q->msg_q_lock, flags); 856 + if (!list_empty(&q->msg_q)) 857 + mask = EPOLLIN | EPOLLRDNORM; 858 + spin_unlock_irqrestore(&q->msg_q_lock, flags); 859 + 860 + return mask; 861 + } 862 + 863 + static ssize_t scmi_dbg_raw_mode_message_read(struct file *filp, 864 + char __user *buf, 865 + size_t count, loff_t *ppos) 866 + { 867 + return scmi_dbg_raw_mode_common_read(filp, buf, count, ppos, 868 + SCMI_RAW_REPLY_QUEUE); 869 + } 870 + 871 + static ssize_t scmi_dbg_raw_mode_message_write(struct file *filp, 872 + const char __user *buf, 873 + size_t count, loff_t *ppos) 874 + { 875 + return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, false); 876 + } 877 + 878 + static __poll_t scmi_dbg_raw_mode_message_poll(struct file *filp, 879 + struct poll_table_struct *wait) 880 + { 881 + return scmi_test_dbg_raw_common_poll(filp, wait, SCMI_RAW_REPLY_QUEUE); 882 + } 883 + 884 + static int scmi_dbg_raw_mode_open(struct inode *inode, struct file *filp) 885 + { 886 + u8 id; 887 + struct scmi_raw_mode_info *raw; 888 + struct scmi_dbg_raw_data *rd; 889 + const char *id_str = filp->f_path.dentry->d_parent->d_name.name; 890 + 891 + if (!inode->i_private) 892 + return -ENODEV; 893 + 894 + raw = inode->i_private; 895 + rd = kzalloc(sizeof(*rd), GFP_KERNEL); 896 + if (!rd) 897 + return -ENOMEM; 898 + 899 + rd->rx.len = raw->desc->max_msg_size + sizeof(u32); 900 + rd->rx.buf = kzalloc(rd->rx.len, GFP_KERNEL); 901 + if (!rd->rx.buf) { 902 + kfree(rd); 903 + return -ENOMEM; 904 + } 905 + 906 + rd->tx.len = raw->desc->max_msg_size + sizeof(u32); 907 + rd->tx.buf = kzalloc(rd->tx.len, GFP_KERNEL); 908 + if (!rd->tx.buf) { 909 + kfree(rd->rx.buf); 910 + kfree(rd); 911 + return -ENOMEM; 912 + } 913 + 914 + /* Grab channel ID from debugfs entry naming if any */ 915 + if (!kstrtou8(id_str, 16, &id)) 916 + rd->chan_id = id; 917 + 918 + rd->raw = raw; 919 + filp->private_data = rd; 920 + 921 + return 0; 922 + } 923 + 924 + static int scmi_dbg_raw_mode_release(struct inode *inode, struct file *filp) 925 + { 926 + struct scmi_dbg_raw_data *rd = filp->private_data; 927 + 928 + kfree(rd->rx.buf); 929 + kfree(rd->tx.buf); 930 + kfree(rd); 931 + 932 + return 0; 933 + } 934 + 935 + static ssize_t scmi_dbg_raw_mode_reset_write(struct file *filp, 936 + const char __user *buf, 937 + size_t count, loff_t *ppos) 938 + { 939 + struct scmi_dbg_raw_data *rd = filp->private_data; 940 + 941 + scmi_xfer_raw_reset(rd->raw); 942 + 943 + return count; 944 + } 945 + 946 + static const struct file_operations scmi_dbg_raw_mode_reset_fops = { 947 + .open = scmi_dbg_raw_mode_open, 948 + .release = scmi_dbg_raw_mode_release, 949 + .write = scmi_dbg_raw_mode_reset_write, 950 + .owner = THIS_MODULE, 951 + }; 952 + 953 + static const struct file_operations scmi_dbg_raw_mode_message_fops = { 954 + .open = scmi_dbg_raw_mode_open, 955 + .release = scmi_dbg_raw_mode_release, 956 + .read = scmi_dbg_raw_mode_message_read, 957 + .write = scmi_dbg_raw_mode_message_write, 958 + .poll = scmi_dbg_raw_mode_message_poll, 959 + .owner = THIS_MODULE, 960 + }; 961 + 962 + static ssize_t scmi_dbg_raw_mode_message_async_write(struct file *filp, 963 + const char __user *buf, 964 + size_t count, loff_t *ppos) 965 + { 966 + return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, true); 967 + } 968 + 969 + static const struct file_operations scmi_dbg_raw_mode_message_async_fops = { 970 + .open = scmi_dbg_raw_mode_open, 971 + .release = scmi_dbg_raw_mode_release, 972 + .read = scmi_dbg_raw_mode_message_read, 973 + .write = scmi_dbg_raw_mode_message_async_write, 974 + .poll = scmi_dbg_raw_mode_message_poll, 975 + .owner = THIS_MODULE, 976 + }; 977 + 978 + static ssize_t scmi_test_dbg_raw_mode_notif_read(struct file *filp, 979 + char __user *buf, 980 + size_t count, loff_t *ppos) 981 + { 982 + return scmi_dbg_raw_mode_common_read(filp, buf, count, ppos, 983 + SCMI_RAW_NOTIF_QUEUE); 984 + } 985 + 986 + static __poll_t 987 + scmi_test_dbg_raw_mode_notif_poll(struct file *filp, 988 + struct poll_table_struct *wait) 989 + { 990 + return scmi_test_dbg_raw_common_poll(filp, wait, SCMI_RAW_NOTIF_QUEUE); 991 + } 992 + 993 + static const struct file_operations scmi_dbg_raw_mode_notification_fops = { 994 + .open = scmi_dbg_raw_mode_open, 995 + .release = scmi_dbg_raw_mode_release, 996 + .read = scmi_test_dbg_raw_mode_notif_read, 997 + .poll = scmi_test_dbg_raw_mode_notif_poll, 998 + .owner = THIS_MODULE, 999 + }; 1000 + 1001 + static ssize_t scmi_test_dbg_raw_mode_errors_read(struct file *filp, 1002 + char __user *buf, 1003 + size_t count, loff_t *ppos) 1004 + { 1005 + return scmi_dbg_raw_mode_common_read(filp, buf, count, ppos, 1006 + SCMI_RAW_ERRS_QUEUE); 1007 + } 1008 + 1009 + static __poll_t 1010 + scmi_test_dbg_raw_mode_errors_poll(struct file *filp, 1011 + struct poll_table_struct *wait) 1012 + { 1013 + return scmi_test_dbg_raw_common_poll(filp, wait, SCMI_RAW_ERRS_QUEUE); 1014 + } 1015 + 1016 + static const struct file_operations scmi_dbg_raw_mode_errors_fops = { 1017 + .open = scmi_dbg_raw_mode_open, 1018 + .release = scmi_dbg_raw_mode_release, 1019 + .read = scmi_test_dbg_raw_mode_errors_read, 1020 + .poll = scmi_test_dbg_raw_mode_errors_poll, 1021 + .owner = THIS_MODULE, 1022 + }; 1023 + 1024 + static struct scmi_raw_queue * 1025 + scmi_raw_queue_init(struct scmi_raw_mode_info *raw) 1026 + { 1027 + int i; 1028 + struct scmi_raw_buffer *rb; 1029 + struct device *dev = raw->handle->dev; 1030 + struct scmi_raw_queue *q; 1031 + 1032 + q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL); 1033 + if (!q) 1034 + return ERR_PTR(-ENOMEM); 1035 + 1036 + rb = devm_kcalloc(dev, raw->tx_max_msg, sizeof(*rb), GFP_KERNEL); 1037 + if (!rb) 1038 + return ERR_PTR(-ENOMEM); 1039 + 1040 + spin_lock_init(&q->free_bufs_lock); 1041 + INIT_LIST_HEAD(&q->free_bufs); 1042 + for (i = 0; i < raw->tx_max_msg; i++, rb++) { 1043 + rb->max_len = raw->desc->max_msg_size + sizeof(u32); 1044 + rb->msg.buf = devm_kzalloc(dev, rb->max_len, GFP_KERNEL); 1045 + if (!rb->msg.buf) 1046 + return ERR_PTR(-ENOMEM); 1047 + scmi_raw_buffer_put(q, rb); 1048 + } 1049 + 1050 + spin_lock_init(&q->msg_q_lock); 1051 + INIT_LIST_HEAD(&q->msg_q); 1052 + init_waitqueue_head(&q->wq); 1053 + 1054 + return q; 1055 + } 1056 + 1057 + static int scmi_xfer_raw_worker_init(struct scmi_raw_mode_info *raw) 1058 + { 1059 + int i; 1060 + struct scmi_xfer_raw_waiter *rw; 1061 + struct device *dev = raw->handle->dev; 1062 + 1063 + rw = devm_kcalloc(dev, raw->tx_max_msg, sizeof(*rw), GFP_KERNEL); 1064 + if (!rw) 1065 + return -ENOMEM; 1066 + 1067 + raw->wait_wq = alloc_workqueue("scmi-raw-wait-wq-%d", 1068 + WQ_UNBOUND | WQ_FREEZABLE | 1069 + WQ_HIGHPRI, WQ_SYSFS, raw->id); 1070 + if (!raw->wait_wq) 1071 + return -ENOMEM; 1072 + 1073 + mutex_init(&raw->free_mtx); 1074 + INIT_LIST_HEAD(&raw->free_waiters); 1075 + mutex_init(&raw->active_mtx); 1076 + INIT_LIST_HEAD(&raw->active_waiters); 1077 + 1078 + for (i = 0; i < raw->tx_max_msg; i++, rw++) { 1079 + init_completion(&rw->async_response); 1080 + scmi_xfer_raw_waiter_put(raw, rw); 1081 + } 1082 + INIT_WORK(&raw->waiters_work, scmi_xfer_raw_worker); 1083 + 1084 + return 0; 1085 + } 1086 + 1087 + static int scmi_raw_mode_setup(struct scmi_raw_mode_info *raw, 1088 + u8 *channels, int num_chans) 1089 + { 1090 + int ret, idx; 1091 + void *gid; 1092 + struct device *dev = raw->handle->dev; 1093 + 1094 + gid = devres_open_group(dev, NULL, GFP_KERNEL); 1095 + if (!gid) 1096 + return -ENOMEM; 1097 + 1098 + for (idx = 0; idx < SCMI_RAW_MAX_QUEUE; idx++) { 1099 + raw->q[idx] = scmi_raw_queue_init(raw); 1100 + if (IS_ERR(raw->q[idx])) { 1101 + ret = PTR_ERR(raw->q[idx]); 1102 + goto err; 1103 + } 1104 + } 1105 + 1106 + xa_init(&raw->chans_q); 1107 + if (num_chans > 1) { 1108 + int i; 1109 + 1110 + for (i = 0; i < num_chans; i++) { 1111 + void *xret; 1112 + struct scmi_raw_queue *q; 1113 + 1114 + q = scmi_raw_queue_init(raw); 1115 + if (IS_ERR(q)) { 1116 + ret = PTR_ERR(q); 1117 + goto err_xa; 1118 + } 1119 + 1120 + xret = xa_store(&raw->chans_q, channels[i], q, 1121 + GFP_KERNEL); 1122 + if (xa_err(xret)) { 1123 + dev_err(dev, 1124 + "Fail to allocate Raw queue 0x%02X\n", 1125 + channels[i]); 1126 + ret = xa_err(xret); 1127 + goto err_xa; 1128 + } 1129 + } 1130 + } 1131 + 1132 + ret = scmi_xfer_raw_worker_init(raw); 1133 + if (ret) 1134 + goto err_xa; 1135 + 1136 + devres_close_group(dev, gid); 1137 + raw->gid = gid; 1138 + 1139 + return 0; 1140 + 1141 + err_xa: 1142 + xa_destroy(&raw->chans_q); 1143 + err: 1144 + devres_release_group(dev, gid); 1145 + return ret; 1146 + } 1147 + 1148 + /** 1149 + * scmi_raw_mode_init - Function to initialize the SCMI Raw stack 1150 + * 1151 + * @handle: Pointer to SCMI entity handle 1152 + * @top_dentry: A reference to the top Raw debugfs dentry 1153 + * @instance_id: The ID of the underlying SCMI platform instance represented by 1154 + * this Raw instance 1155 + * @channels: The list of the existing channels 1156 + * @num_chans: The number of entries in @channels 1157 + * @desc: Reference to the transport operations 1158 + * @tx_max_msg: Max number of in-flight messages allowed by the transport 1159 + * 1160 + * This function prepare the SCMI Raw stack and creates the debugfs API. 1161 + * 1162 + * Return: An opaque handle to the Raw instance on Success, an ERR_PTR otherwise 1163 + */ 1164 + void *scmi_raw_mode_init(const struct scmi_handle *handle, 1165 + struct dentry *top_dentry, int instance_id, 1166 + u8 *channels, int num_chans, 1167 + const struct scmi_desc *desc, int tx_max_msg) 1168 + { 1169 + int ret; 1170 + struct scmi_raw_mode_info *raw; 1171 + struct device *dev; 1172 + 1173 + if (!handle || !desc) 1174 + return ERR_PTR(-EINVAL); 1175 + 1176 + dev = handle->dev; 1177 + raw = devm_kzalloc(dev, sizeof(*raw), GFP_KERNEL); 1178 + if (!raw) 1179 + return ERR_PTR(-ENOMEM); 1180 + 1181 + raw->handle = handle; 1182 + raw->desc = desc; 1183 + raw->tx_max_msg = tx_max_msg; 1184 + raw->id = instance_id; 1185 + 1186 + ret = scmi_raw_mode_setup(raw, channels, num_chans); 1187 + if (ret) { 1188 + devm_kfree(dev, raw); 1189 + return ERR_PTR(ret); 1190 + } 1191 + 1192 + raw->dentry = debugfs_create_dir("raw", top_dentry); 1193 + 1194 + debugfs_create_file("reset", 0200, raw->dentry, raw, 1195 + &scmi_dbg_raw_mode_reset_fops); 1196 + 1197 + debugfs_create_file("message", 0600, raw->dentry, raw, 1198 + &scmi_dbg_raw_mode_message_fops); 1199 + 1200 + debugfs_create_file("message_async", 0600, raw->dentry, raw, 1201 + &scmi_dbg_raw_mode_message_async_fops); 1202 + 1203 + debugfs_create_file("notification", 0400, raw->dentry, raw, 1204 + &scmi_dbg_raw_mode_notification_fops); 1205 + 1206 + debugfs_create_file("errors", 0400, raw->dentry, raw, 1207 + &scmi_dbg_raw_mode_errors_fops); 1208 + 1209 + /* 1210 + * Expose per-channel entries if multiple channels available. 1211 + * Just ignore errors while setting up these interfaces since we 1212 + * have anyway already a working core Raw support. 1213 + */ 1214 + if (num_chans > 1) { 1215 + int i; 1216 + struct dentry *top_chans; 1217 + 1218 + top_chans = debugfs_create_dir("channels", raw->dentry); 1219 + 1220 + for (i = 0; i < num_chans; i++) { 1221 + char cdir[8]; 1222 + struct dentry *chd; 1223 + 1224 + snprintf(cdir, 8, "0x%02X", channels[i]); 1225 + chd = debugfs_create_dir(cdir, top_chans); 1226 + 1227 + debugfs_create_file("message", 0600, chd, raw, 1228 + &scmi_dbg_raw_mode_message_fops); 1229 + 1230 + debugfs_create_file("message_async", 0600, chd, raw, 1231 + &scmi_dbg_raw_mode_message_async_fops); 1232 + } 1233 + } 1234 + 1235 + dev_info(dev, "SCMI RAW Mode initialized for instance %d\n", raw->id); 1236 + 1237 + return raw; 1238 + } 1239 + 1240 + /** 1241 + * scmi_raw_mode_cleanup - Function to cleanup the SCMI Raw stack 1242 + * 1243 + * @r: An opaque handle to an initialized SCMI Raw instance 1244 + */ 1245 + void scmi_raw_mode_cleanup(void *r) 1246 + { 1247 + struct scmi_raw_mode_info *raw = r; 1248 + 1249 + if (!raw) 1250 + return; 1251 + 1252 + debugfs_remove_recursive(raw->dentry); 1253 + 1254 + cancel_work_sync(&raw->waiters_work); 1255 + destroy_workqueue(raw->wait_wq); 1256 + xa_destroy(&raw->chans_q); 1257 + } 1258 + 1259 + static int scmi_xfer_raw_collect(void *msg, size_t *msg_len, 1260 + struct scmi_xfer *xfer) 1261 + { 1262 + __le32 *m; 1263 + size_t msg_size; 1264 + 1265 + if (!xfer || !msg || !msg_len) 1266 + return -EINVAL; 1267 + 1268 + /* Account for hdr ...*/ 1269 + msg_size = xfer->rx.len + sizeof(u32); 1270 + /* ... and status if needed */ 1271 + if (xfer->hdr.type != MSG_TYPE_NOTIFICATION) 1272 + msg_size += sizeof(u32); 1273 + 1274 + if (msg_size > *msg_len) 1275 + return -ENOSPC; 1276 + 1277 + m = msg; 1278 + *m = cpu_to_le32(pack_scmi_header(&xfer->hdr)); 1279 + if (xfer->hdr.type != MSG_TYPE_NOTIFICATION) 1280 + *++m = cpu_to_le32(xfer->hdr.status); 1281 + 1282 + memcpy(++m, xfer->rx.buf, xfer->rx.len); 1283 + 1284 + *msg_len = msg_size; 1285 + 1286 + return 0; 1287 + } 1288 + 1289 + /** 1290 + * scmi_raw_message_report - Helper to report back valid reponses/notifications 1291 + * to raw message requests. 1292 + * 1293 + * @r: An opaque reference to the raw instance configuration 1294 + * @xfer: The xfer containing the message to be reported 1295 + * @idx: The index of the queue. 1296 + * @chan_id: The channel ID to use. 1297 + * 1298 + * If Raw mode is enabled, this is called from the SCMI core on the regular RX 1299 + * path to save and enqueue the response/notification payload carried by this 1300 + * xfer into a dedicated scmi_raw_buffer for later consumption by the user. 1301 + * 1302 + * This way the caller can free the related xfer immediately afterwards and the 1303 + * user can read back the raw message payload at its own pace (if ever) without 1304 + * holding an xfer for too long. 1305 + */ 1306 + void scmi_raw_message_report(void *r, struct scmi_xfer *xfer, 1307 + unsigned int idx, unsigned int chan_id) 1308 + { 1309 + int ret; 1310 + unsigned long flags; 1311 + struct scmi_raw_buffer *rb; 1312 + struct device *dev; 1313 + struct scmi_raw_queue *q; 1314 + struct scmi_raw_mode_info *raw = r; 1315 + 1316 + if (!raw || (idx == SCMI_RAW_REPLY_QUEUE && !SCMI_XFER_IS_RAW(xfer))) 1317 + return; 1318 + 1319 + dev = raw->handle->dev; 1320 + q = scmi_raw_queue_select(raw, idx, 1321 + SCMI_XFER_IS_CHAN_SET(xfer) ? chan_id : 0); 1322 + 1323 + /* 1324 + * Grab the msg_q_lock upfront to avoid a possible race between 1325 + * realizing the free list was empty and effectively picking the next 1326 + * buffer to use from the oldest one enqueued and still unread on this 1327 + * msg_q. 1328 + * 1329 + * Note that nowhere else these locks are taken together, so no risk of 1330 + * deadlocks du eto inversion. 1331 + */ 1332 + spin_lock_irqsave(&q->msg_q_lock, flags); 1333 + rb = scmi_raw_buffer_get(q); 1334 + if (!rb) { 1335 + /* 1336 + * Immediate and delayed replies to previously injected Raw 1337 + * commands MUST be read back from userspace to free the buffers: 1338 + * if this is not happening something is seriously broken and 1339 + * must be fixed at the application level: complain loudly. 1340 + */ 1341 + if (idx == SCMI_RAW_REPLY_QUEUE) { 1342 + spin_unlock_irqrestore(&q->msg_q_lock, flags); 1343 + dev_warn(dev, 1344 + "RAW[%d] - Buffers exhausted. Dropping report.\n", 1345 + idx); 1346 + return; 1347 + } 1348 + 1349 + /* 1350 + * Notifications and errors queues are instead handled in a 1351 + * circular manner: unread old buffers are just overwritten by 1352 + * newer ones. 1353 + * 1354 + * The main reason for this is that notifications originated 1355 + * by Raw requests cannot be distinguished from normal ones, so 1356 + * your Raw buffers queues risk to be flooded and depleted by 1357 + * notifications if you left it mistakenly enabled or when in 1358 + * coexistence mode. 1359 + */ 1360 + rb = scmi_raw_buffer_dequeue_unlocked(q); 1361 + if (WARN_ON(!rb)) { 1362 + spin_unlock_irqrestore(&q->msg_q_lock, flags); 1363 + return; 1364 + } 1365 + 1366 + /* Reset to full buffer length */ 1367 + rb->msg.len = rb->max_len; 1368 + 1369 + dev_warn_once(dev, 1370 + "RAW[%d] - Buffers exhausted. Re-using oldest.\n", 1371 + idx); 1372 + } 1373 + spin_unlock_irqrestore(&q->msg_q_lock, flags); 1374 + 1375 + ret = scmi_xfer_raw_collect(rb->msg.buf, &rb->msg.len, xfer); 1376 + if (ret) { 1377 + dev_warn(dev, "RAW - Cannot collect xfer into buffer !\n"); 1378 + scmi_raw_buffer_put(q, rb); 1379 + return; 1380 + } 1381 + 1382 + scmi_raw_buffer_enqueue(q, rb); 1383 + } 1384 + 1385 + static void scmi_xfer_raw_fill(struct scmi_raw_mode_info *raw, 1386 + struct scmi_chan_info *cinfo, 1387 + struct scmi_xfer *xfer, u32 msg_hdr) 1388 + { 1389 + /* Unpack received HDR as it is */ 1390 + unpack_scmi_header(msg_hdr, &xfer->hdr); 1391 + xfer->hdr.seq = MSG_XTRACT_TOKEN(msg_hdr); 1392 + 1393 + memset(xfer->rx.buf, 0x00, xfer->rx.len); 1394 + 1395 + raw->desc->ops->fetch_response(cinfo, xfer); 1396 + } 1397 + 1398 + /** 1399 + * scmi_raw_error_report - Helper to report back timed-out or generally 1400 + * unexpected replies. 1401 + * 1402 + * @r: An opaque reference to the raw instance configuration 1403 + * @cinfo: A reference to the channel to use to retrieve the broken xfer 1404 + * @msg_hdr: The SCMI message header of the message to fetch and report 1405 + * @priv: Any private data related to the xfer. 1406 + * 1407 + * If Raw mode is enabled, this is called from the SCMI core on the RX path in 1408 + * case of errors to save and enqueue the bad message payload carried by the 1409 + * message that has just been received. 1410 + * 1411 + * Note that we have to manually fetch any available payload into a temporary 1412 + * xfer to be able to save and enqueue the message, since the regular RX error 1413 + * path which had called this would have not fetched the message payload having 1414 + * classified it as an error. 1415 + */ 1416 + void scmi_raw_error_report(void *r, struct scmi_chan_info *cinfo, 1417 + u32 msg_hdr, void *priv) 1418 + { 1419 + struct scmi_xfer xfer; 1420 + struct scmi_raw_mode_info *raw = r; 1421 + 1422 + if (!raw) 1423 + return; 1424 + 1425 + xfer.rx.len = raw->desc->max_msg_size; 1426 + xfer.rx.buf = kzalloc(xfer.rx.len, GFP_ATOMIC); 1427 + if (!xfer.rx.buf) { 1428 + dev_info(raw->handle->dev, 1429 + "Cannot report Raw error for HDR:0x%X - ENOMEM\n", 1430 + msg_hdr); 1431 + return; 1432 + } 1433 + 1434 + /* Any transport-provided priv must be passed back down to transport */ 1435 + if (priv) 1436 + /* Ensure priv is visible */ 1437 + smp_store_mb(xfer.priv, priv); 1438 + 1439 + scmi_xfer_raw_fill(raw, cinfo, &xfer, msg_hdr); 1440 + scmi_raw_message_report(raw, &xfer, SCMI_RAW_ERRS_QUEUE, 0); 1441 + 1442 + kfree(xfer.rx.buf); 1443 + }
+31
drivers/firmware/arm_scmi/raw_mode.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * System Control and Management Interface (SCMI) Message Protocol 4 + * Raw mode support header. 5 + * 6 + * Copyright (C) 2022 ARM Ltd. 7 + */ 8 + #ifndef _SCMI_RAW_MODE_H 9 + #define _SCMI_RAW_MODE_H 10 + 11 + #include "common.h" 12 + 13 + enum { 14 + SCMI_RAW_REPLY_QUEUE, 15 + SCMI_RAW_NOTIF_QUEUE, 16 + SCMI_RAW_ERRS_QUEUE, 17 + SCMI_RAW_MAX_QUEUE 18 + }; 19 + 20 + void *scmi_raw_mode_init(const struct scmi_handle *handle, 21 + struct dentry *top_dentry, int instance_id, 22 + u8 *channels, int num_chans, 23 + const struct scmi_desc *desc, int tx_max_msg); 24 + void scmi_raw_mode_cleanup(void *raw); 25 + 26 + void scmi_raw_message_report(void *raw, struct scmi_xfer *xfer, 27 + unsigned int idx, unsigned int chan_id); 28 + void scmi_raw_error_report(void *raw, struct scmi_chan_info *cinfo, 29 + u32 msg_hdr, void *priv); 30 + 31 + #endif /* _SCMI_RAW_MODE_H */
+2 -4
drivers/firmware/arm_scmi/smc.c
··· 52 52 return IRQ_HANDLED; 53 53 } 54 54 55 - static bool smc_chan_available(struct device *dev, int idx) 55 + static bool smc_chan_available(struct device_node *of_node, int idx) 56 56 { 57 - struct device_node *np = of_parse_phandle(dev->of_node, "shmem", 0); 57 + struct device_node *np = of_parse_phandle(of_node, "shmem", 0); 58 58 if (!np) 59 59 return false; 60 60 ··· 170 170 171 171 cinfo->transport_info = NULL; 172 172 scmi_info->cinfo = NULL; 173 - 174 - scmi_free_channel(cinfo, data, id); 175 173 176 174 return 0; 177 175 }
+1 -3
drivers/firmware/arm_scmi/virtio.c
··· 385 385 return 0; 386 386 } 387 387 388 - static bool virtio_chan_available(struct device *dev, int idx) 388 + static bool virtio_chan_available(struct device_node *of_node, int idx) 389 389 { 390 390 struct scmi_vio_channel *channels, *vioch = NULL; 391 391 ··· 488 488 */ 489 489 virtio_break_device(vioch->vqueue->vdev); 490 490 scmi_vio_channel_cleanup_sync(vioch); 491 - 492 - scmi_free_channel(cinfo, data, id); 493 491 494 492 return 0; 495 493 }
+1 -1
drivers/firmware/meson/meson_sm.c
··· 82 82 83 83 sm_phy_base = __meson_sm_call(cmd_shmem, 0, 0, 0, 0, 0); 84 84 if (!sm_phy_base) 85 - return 0; 85 + return NULL; 86 86 87 87 return ioremap_cache(sm_phy_base, size); 88 88 }
+1 -1
drivers/firmware/qcom_scm-legacy.c
··· 9 9 #include <linux/mutex.h> 10 10 #include <linux/errno.h> 11 11 #include <linux/err.h> 12 - #include <linux/qcom_scm.h> 12 + #include <linux/firmware/qcom/qcom_scm.h> 13 13 #include <linux/arm-smccc.h> 14 14 #include <linux/dma-mapping.h> 15 15
+80 -8
drivers/firmware/qcom_scm-smc.c
··· 8 8 #include <linux/mutex.h> 9 9 #include <linux/slab.h> 10 10 #include <linux/types.h> 11 - #include <linux/qcom_scm.h> 11 + #include <linux/firmware/qcom/qcom_scm.h> 12 12 #include <linux/arm-smccc.h> 13 13 #include <linux/dma-mapping.h> 14 14 ··· 52 52 } while (res->a0 == QCOM_SCM_INTERRUPTED); 53 53 } 54 54 55 - static void __scm_smc_do(const struct arm_smccc_args *smc, 56 - struct arm_smccc_res *res, bool atomic) 55 + static void fill_wq_resume_args(struct arm_smccc_args *resume, u32 smc_call_ctx) 57 56 { 58 - int retry_count = 0; 57 + memset(resume->args, 0, sizeof(resume->args[0]) * ARRAY_SIZE(resume->args)); 58 + 59 + resume->args[0] = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, 60 + ARM_SMCCC_SMC_64, ARM_SMCCC_OWNER_SIP, 61 + SCM_SMC_FNID(QCOM_SCM_SVC_WAITQ, QCOM_SCM_WAITQ_RESUME)); 62 + 63 + resume->args[1] = QCOM_SCM_ARGS(1); 64 + 65 + resume->args[2] = smc_call_ctx; 66 + } 67 + 68 + int scm_get_wq_ctx(u32 *wq_ctx, u32 *flags, u32 *more_pending) 69 + { 70 + int ret; 71 + struct arm_smccc_res get_wq_res; 72 + struct arm_smccc_args get_wq_ctx = {0}; 73 + 74 + get_wq_ctx.args[0] = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, 75 + ARM_SMCCC_SMC_64, ARM_SMCCC_OWNER_SIP, 76 + SCM_SMC_FNID(QCOM_SCM_SVC_WAITQ, QCOM_SCM_WAITQ_GET_WQ_CTX)); 77 + 78 + /* Guaranteed to return only success or error, no WAITQ_* */ 79 + __scm_smc_do_quirk(&get_wq_ctx, &get_wq_res); 80 + ret = get_wq_res.a0; 81 + if (ret) 82 + return ret; 83 + 84 + *wq_ctx = get_wq_res.a1; 85 + *flags = get_wq_res.a2; 86 + *more_pending = get_wq_res.a3; 87 + 88 + return 0; 89 + } 90 + 91 + static int __scm_smc_do_quirk_handle_waitq(struct device *dev, struct arm_smccc_args *waitq, 92 + struct arm_smccc_res *res) 93 + { 94 + int ret; 95 + u32 wq_ctx, smc_call_ctx; 96 + struct arm_smccc_args resume; 97 + struct arm_smccc_args *smc = waitq; 98 + 99 + do { 100 + __scm_smc_do_quirk(smc, res); 101 + 102 + if (res->a0 == QCOM_SCM_WAITQ_SLEEP) { 103 + wq_ctx = res->a1; 104 + smc_call_ctx = res->a2; 105 + 106 + ret = qcom_scm_wait_for_wq_completion(wq_ctx); 107 + if (ret) 108 + return ret; 109 + 110 + fill_wq_resume_args(&resume, smc_call_ctx); 111 + smc = &resume; 112 + } 113 + } while (res->a0 == QCOM_SCM_WAITQ_SLEEP); 114 + 115 + return 0; 116 + } 117 + 118 + static int __scm_smc_do(struct device *dev, struct arm_smccc_args *smc, 119 + struct arm_smccc_res *res, bool atomic) 120 + { 121 + int ret, retry_count = 0; 59 122 60 123 if (atomic) { 61 124 __scm_smc_do_quirk(smc, res); 62 - return; 125 + return 0; 63 126 } 64 127 65 128 do { 66 129 mutex_lock(&qcom_scm_lock); 67 130 68 - __scm_smc_do_quirk(smc, res); 131 + ret = __scm_smc_do_quirk_handle_waitq(dev, smc, res); 69 132 70 133 mutex_unlock(&qcom_scm_lock); 134 + 135 + if (ret) 136 + return ret; 71 137 72 138 if (res->a0 == QCOM_SCM_V2_EBUSY) { 73 139 if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY) ··· 141 75 msleep(QCOM_SCM_EBUSY_WAIT_MS); 142 76 } 143 77 } while (res->a0 == QCOM_SCM_V2_EBUSY); 78 + 79 + return 0; 144 80 } 145 81 146 82 ··· 151 83 struct qcom_scm_res *res, bool atomic) 152 84 { 153 85 int arglen = desc->arginfo & 0xf; 154 - int i; 86 + int i, ret; 155 87 dma_addr_t args_phys = 0; 156 88 void *args_virt = NULL; 157 89 size_t alloc_len; ··· 203 135 smc.args[SCM_SMC_LAST_REG_IDX] = args_phys; 204 136 } 205 137 206 - __scm_smc_do(&smc, &smc_res, atomic); 138 + /* ret error check follows after args_virt cleanup*/ 139 + ret = __scm_smc_do(dev, &smc, &smc_res, atomic); 207 140 208 141 if (args_virt) { 209 142 dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE); 210 143 kfree(args_virt); 211 144 } 145 + 146 + if (ret) 147 + return ret; 212 148 213 149 if (res) { 214 150 res->result[0] = smc_res.a1;
+90 -2
drivers/firmware/qcom_scm.c
··· 4 4 */ 5 5 #include <linux/platform_device.h> 6 6 #include <linux/init.h> 7 + #include <linux/interrupt.h> 8 + #include <linux/completion.h> 7 9 #include <linux/cpumask.h> 8 10 #include <linux/export.h> 9 11 #include <linux/dma-mapping.h> 10 12 #include <linux/interconnect.h> 11 13 #include <linux/module.h> 12 14 #include <linux/types.h> 13 - #include <linux/qcom_scm.h> 15 + #include <linux/firmware/qcom/qcom_scm.h> 14 16 #include <linux/of.h> 15 17 #include <linux/of_address.h> 18 + #include <linux/of_irq.h> 16 19 #include <linux/of_platform.h> 17 20 #include <linux/clk.h> 18 21 #include <linux/reset-controller.h> ··· 36 33 struct clk *iface_clk; 37 34 struct clk *bus_clk; 38 35 struct icc_path *path; 36 + struct completion waitq_comp; 39 37 struct reset_controller_dev reset; 40 38 41 39 /* control access to the interconnect path */ ··· 66 62 static const u8 qcom_scm_cpu_warm_bits[QCOM_SCM_BOOT_MAX_CPUS] = { 67 63 BIT(2), BIT(1), BIT(4), BIT(6) 68 64 }; 65 + 66 + #define QCOM_SMC_WAITQ_FLAG_WAKE_ONE BIT(0) 67 + #define QCOM_SMC_WAITQ_FLAG_WAKE_ALL BIT(1) 69 68 70 69 static const char * const qcom_scm_convention_names[] = { 71 70 [SMC_CONVENTION_UNKNOWN] = "unknown", ··· 1332 1325 } 1333 1326 EXPORT_SYMBOL(qcom_scm_is_available); 1334 1327 1328 + static int qcom_scm_assert_valid_wq_ctx(u32 wq_ctx) 1329 + { 1330 + /* FW currently only supports a single wq_ctx (zero). 1331 + * TODO: Update this logic to include dynamic allocation and lookup of 1332 + * completion structs when FW supports more wq_ctx values. 1333 + */ 1334 + if (wq_ctx != 0) { 1335 + dev_err(__scm->dev, "Firmware unexpectedly passed non-zero wq_ctx\n"); 1336 + return -EINVAL; 1337 + } 1338 + 1339 + return 0; 1340 + } 1341 + 1342 + int qcom_scm_wait_for_wq_completion(u32 wq_ctx) 1343 + { 1344 + int ret; 1345 + 1346 + ret = qcom_scm_assert_valid_wq_ctx(wq_ctx); 1347 + if (ret) 1348 + return ret; 1349 + 1350 + wait_for_completion(&__scm->waitq_comp); 1351 + 1352 + return 0; 1353 + } 1354 + 1355 + static int qcom_scm_waitq_wakeup(struct qcom_scm *scm, unsigned int wq_ctx) 1356 + { 1357 + int ret; 1358 + 1359 + ret = qcom_scm_assert_valid_wq_ctx(wq_ctx); 1360 + if (ret) 1361 + return ret; 1362 + 1363 + complete(&__scm->waitq_comp); 1364 + 1365 + return 0; 1366 + } 1367 + 1368 + static irqreturn_t qcom_scm_irq_handler(int irq, void *data) 1369 + { 1370 + int ret; 1371 + struct qcom_scm *scm = data; 1372 + u32 wq_ctx, flags, more_pending = 0; 1373 + 1374 + do { 1375 + ret = scm_get_wq_ctx(&wq_ctx, &flags, &more_pending); 1376 + if (ret) { 1377 + dev_err(scm->dev, "GET_WQ_CTX SMC call failed: %d\n", ret); 1378 + goto out; 1379 + } 1380 + 1381 + if (flags != QCOM_SMC_WAITQ_FLAG_WAKE_ONE && 1382 + flags != QCOM_SMC_WAITQ_FLAG_WAKE_ALL) { 1383 + dev_err(scm->dev, "Invalid flags found for wq_ctx: %u\n", flags); 1384 + goto out; 1385 + } 1386 + 1387 + ret = qcom_scm_waitq_wakeup(scm, wq_ctx); 1388 + if (ret) 1389 + goto out; 1390 + } while (more_pending); 1391 + 1392 + out: 1393 + return IRQ_HANDLED; 1394 + } 1395 + 1335 1396 static int qcom_scm_probe(struct platform_device *pdev) 1336 1397 { 1337 1398 struct qcom_scm *scm; 1338 1399 unsigned long clks; 1339 - int ret; 1400 + int irq, ret; 1340 1401 1341 1402 scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL); 1342 1403 if (!scm) ··· 1476 1401 1477 1402 __scm = scm; 1478 1403 __scm->dev = &pdev->dev; 1404 + 1405 + init_completion(&__scm->waitq_comp); 1406 + 1407 + irq = platform_get_irq(pdev, 0); 1408 + if (irq < 0) { 1409 + if (irq != -ENXIO) 1410 + return irq; 1411 + } else { 1412 + ret = devm_request_threaded_irq(__scm->dev, irq, NULL, qcom_scm_irq_handler, 1413 + IRQF_ONESHOT, "qcom-scm", __scm); 1414 + if (ret < 0) 1415 + return dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n"); 1416 + } 1479 1417 1480 1418 __get_convention(); 1481 1419
+8
drivers/firmware/qcom_scm.h
··· 60 60 u64 result[MAX_QCOM_SCM_RETS]; 61 61 }; 62 62 63 + int qcom_scm_wait_for_wq_completion(u32 wq_ctx); 64 + int scm_get_wq_ctx(u32 *wq_ctx, u32 *flags, u32 *more_pending); 65 + 63 66 #define SCM_SMC_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF)) 64 67 extern int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc, 65 68 enum qcom_scm_convention qcom_convention, ··· 132 129 #define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x03 133 130 #define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x02 134 131 132 + #define QCOM_SCM_SVC_WAITQ 0x24 133 + #define QCOM_SCM_WAITQ_RESUME 0x02 134 + #define QCOM_SCM_WAITQ_GET_WQ_CTX 0x03 135 + 135 136 /* common error codes */ 136 137 #define QCOM_SCM_V2_EBUSY -12 137 138 #define QCOM_SCM_ENOMEM -5 ··· 144 137 #define QCOM_SCM_EINVAL_ARG -2 145 138 #define QCOM_SCM_ERROR -1 146 139 #define QCOM_SCM_INTERRUPTED 1 140 + #define QCOM_SCM_WAITQ_SLEEP 2 147 141 148 142 static inline int qcom_scm_remap_error(int err) 149 143 {
+25 -2
drivers/firmware/xilinx/zynqmp.c
··· 738 738 */ 739 739 int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value) 740 740 { 741 - return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY, 742 - type, value, NULL); 741 + u32 reg = (type == PM_TAPDELAY_INPUT) ? SD_ITAPDLY : SD_OTAPDLYSEL; 742 + u32 mask = (node_id == NODE_SD_0) ? GENMASK(15, 0) : GENMASK(31, 16); 743 + 744 + if (value) { 745 + return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, 746 + IOCTL_SET_SD_TAPDELAY, 747 + type, value, NULL); 748 + } 749 + 750 + /* 751 + * Work around completely misdesigned firmware API on Xilinx ZynqMP. 752 + * The IOCTL_SET_SD_TAPDELAY firmware call allows the caller to only 753 + * ever set IOU_SLCR SD_ITAPDLY Register SD0_ITAPDLYENA/SD1_ITAPDLYENA 754 + * bits, but there is no matching call to clear those bits. If those 755 + * bits are not cleared, SDMMC tuning may fail. 756 + * 757 + * Luckily, there are PM_MMIO_READ/PM_MMIO_WRITE calls which seem to 758 + * allow complete unrestricted access to all address space, including 759 + * IOU_SLCR SD_ITAPDLY Register and all the other registers, access 760 + * to which was supposed to be protected by the current firmware API. 761 + * 762 + * Use PM_MMIO_READ/PM_MMIO_WRITE to re-implement the missing counter 763 + * part of IOCTL_SET_SD_TAPDELAY which clears SDx_ITAPDLYENA bits. 764 + */ 765 + return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, reg, mask, 0, 0, NULL); 743 766 } 744 767 EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay); 745 768
+1 -1
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
··· 5 5 #include <linux/kernel.h> 6 6 #include <linux/types.h> 7 7 #include <linux/cpumask.h> 8 - #include <linux/qcom_scm.h> 8 + #include <linux/firmware/qcom/qcom_scm.h> 9 9 #include <linux/pm_opp.h> 10 10 #include <linux/nvmem-consumer.h> 11 11 #include <linux/slab.h>
+1 -1
drivers/gpu/drm/msm/adreno/adreno_gpu.c
··· 8 8 9 9 #include <linux/ascii85.h> 10 10 #include <linux/interconnect.h> 11 - #include <linux/qcom_scm.h> 11 + #include <linux/firmware/qcom/qcom_scm.h> 12 12 #include <linux/kernel.h> 13 13 #include <linux/of_address.h> 14 14 #include <linux/pm_opp.h>
+1 -1
drivers/gpu/drm/msm/hdmi/hdmi_hdcp.c
··· 3 3 */ 4 4 5 5 #include "hdmi.h" 6 - #include <linux/qcom_scm.h> 6 + #include <linux/firmware/qcom/qcom_scm.h> 7 7 8 8 #define HDCP_REG_ENABLE 0x01 9 9 #define HDCP_REG_DISABLE 0x00
+17
drivers/input/keyboard/mtk-pmic-keys.c
··· 10 10 #include <linux/kernel.h> 11 11 #include <linux/mfd/mt6323/registers.h> 12 12 #include <linux/mfd/mt6331/registers.h> 13 + #include <linux/mfd/mt6357/registers.h> 13 14 #include <linux/mfd/mt6358/registers.h> 14 15 #include <linux/mfd/mt6397/core.h> 15 16 #include <linux/mfd/mt6397/registers.h> ··· 89 88 MTK_PMIC_MT6331_HOMEKEY_RST), 90 89 .pmic_rst_reg = MT6331_TOP_RST_MISC, 91 90 .rst_lprst_mask = MTK_PMIC_MT6331_RST_DU_MASK, 91 + }; 92 + 93 + static const struct mtk_pmic_regs mt6357_regs = { 94 + .keys_regs[MTK_PMIC_PWRKEY_INDEX] = 95 + MTK_PMIC_KEYS_REGS(MT6357_TOPSTATUS, 96 + 0x2, MT6357_PSC_TOP_INT_CON0, 0x5, 97 + MTK_PMIC_PWRKEY_RST), 98 + .keys_regs[MTK_PMIC_HOMEKEY_INDEX] = 99 + MTK_PMIC_KEYS_REGS(MT6357_TOPSTATUS, 100 + 0x8, MT6357_PSC_TOP_INT_CON0, 0xa, 101 + MTK_PMIC_HOMEKEY_INDEX), 102 + .pmic_rst_reg = MT6357_TOP_RST_MISC, 103 + .rst_lprst_mask = MTK_PMIC_RST_DU_MASK, 92 104 }; 93 105 94 106 static const struct mtk_pmic_regs mt6358_regs = { ··· 290 276 }, { 291 277 .compatible = "mediatek,mt6331-keys", 292 278 .data = &mt6331_regs, 279 + }, { 280 + .compatible = "mediatek,mt6357-keys", 281 + .data = &mt6357_regs, 293 282 }, { 294 283 .compatible = "mediatek,mt6358-keys", 295 284 .data = &mt6358_regs,
+1 -1
drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
··· 4 4 */ 5 5 6 6 #include <linux/of_device.h> 7 - #include <linux/qcom_scm.h> 7 + #include <linux/firmware/qcom/qcom_scm.h> 8 8 #include <linux/ratelimit.h> 9 9 10 10 #include "arm-smmu.h"
+1 -1
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
··· 7 7 #include <linux/adreno-smmu-priv.h> 8 8 #include <linux/delay.h> 9 9 #include <linux/of_device.h> 10 - #include <linux/qcom_scm.h> 10 + #include <linux/firmware/qcom/qcom_scm.h> 11 11 12 12 #include "arm-smmu.h" 13 13 #include "arm-smmu-qcom.h"
+1 -1
drivers/iommu/arm/arm-smmu/qcom_iommu.c
··· 27 27 #include <linux/platform_device.h> 28 28 #include <linux/pm.h> 29 29 #include <linux/pm_runtime.h> 30 - #include <linux/qcom_scm.h> 30 + #include <linux/firmware/qcom/qcom_scm.h> 31 31 #include <linux/slab.h> 32 32 #include <linux/spinlock.h> 33 33
+1 -1
drivers/media/platform/qcom/venus/firmware.c
··· 12 12 #include <linux/of_address.h> 13 13 #include <linux/platform_device.h> 14 14 #include <linux/of_device.h> 15 - #include <linux/qcom_scm.h> 15 + #include <linux/firmware/qcom/qcom_scm.h> 16 16 #include <linux/sizes.h> 17 17 #include <linux/soc/qcom/mdt_loader.h> 18 18
+99 -56
drivers/memory/renesas-rpc-if.c
··· 163 163 .n_yes_ranges = ARRAY_SIZE(rpcif_volatile_ranges), 164 164 }; 165 165 166 + struct rpcif_priv { 167 + struct device *dev; 168 + void __iomem *base; 169 + void __iomem *dirmap; 170 + struct regmap *regmap; 171 + struct reset_control *rstc; 172 + struct platform_device *vdev; 173 + size_t size; 174 + enum rpcif_type type; 175 + enum rpcif_data_dir dir; 176 + u8 bus_size; 177 + u8 xfer_size; 178 + void *buffer; 179 + u32 xferlen; 180 + u32 smcr; 181 + u32 smadr; 182 + u32 command; /* DRCMR or SMCMR */ 183 + u32 option; /* DROPR or SMOPR */ 184 + u32 enable; /* DRENR or SMENR */ 185 + u32 dummy; /* DRDMCR or SMDMCR */ 186 + u32 ddr; /* DRDRENR or SMDRENR */ 187 + }; 166 188 167 189 /* 168 190 * Custom accessor functions to ensure SM[RW]DR[01] are always accessed with 169 - * proper width. Requires rpcif.xfer_size to be correctly set before! 191 + * proper width. Requires rpcif_priv.xfer_size to be correctly set before! 170 192 */ 171 193 static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val) 172 194 { 173 - struct rpcif *rpc = context; 195 + struct rpcif_priv *rpc = context; 174 196 175 197 switch (reg) { 176 198 case RPCIF_SMRDR0: ··· 228 206 229 207 static int rpcif_reg_write(void *context, unsigned int reg, unsigned int val) 230 208 { 231 - struct rpcif *rpc = context; 209 + struct rpcif_priv *rpc = context; 232 210 233 211 switch (reg) { 234 212 case RPCIF_SMWDR0: ··· 275 253 .volatile_table = &rpcif_volatile_table, 276 254 }; 277 255 278 - int rpcif_sw_init(struct rpcif *rpc, struct device *dev) 256 + int rpcif_sw_init(struct rpcif *rpcif, struct device *dev) 279 257 { 280 - struct platform_device *pdev = to_platform_device(dev); 281 - struct resource *res; 258 + struct rpcif_priv *rpc = dev_get_drvdata(dev); 282 259 283 - rpc->dev = dev; 284 - 285 - rpc->base = devm_platform_ioremap_resource_byname(pdev, "regs"); 286 - if (IS_ERR(rpc->base)) 287 - return PTR_ERR(rpc->base); 288 - 289 - rpc->regmap = devm_regmap_init(&pdev->dev, NULL, rpc, &rpcif_regmap_config); 290 - if (IS_ERR(rpc->regmap)) { 291 - dev_err(&pdev->dev, 292 - "failed to init regmap for rpcif, error %ld\n", 293 - PTR_ERR(rpc->regmap)); 294 - return PTR_ERR(rpc->regmap); 295 - } 296 - 297 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap"); 298 - rpc->dirmap = devm_ioremap_resource(&pdev->dev, res); 299 - if (IS_ERR(rpc->dirmap)) 300 - return PTR_ERR(rpc->dirmap); 301 - rpc->size = resource_size(res); 302 - 303 - rpc->type = (uintptr_t)of_device_get_match_data(dev); 304 - rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); 305 - 306 - return PTR_ERR_OR_ZERO(rpc->rstc); 260 + rpcif->dev = dev; 261 + rpcif->dirmap = rpc->dirmap; 262 + rpcif->size = rpc->size; 263 + return 0; 307 264 } 308 265 EXPORT_SYMBOL(rpcif_sw_init); 309 266 310 - static void rpcif_rzg2l_timing_adjust_sdr(struct rpcif *rpc) 267 + static void rpcif_rzg2l_timing_adjust_sdr(struct rpcif_priv *rpc) 311 268 { 312 269 regmap_write(rpc->regmap, RPCIF_PHYWR, 0xa5390000); 313 270 regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000000); ··· 300 299 regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000032); 301 300 } 302 301 303 - int rpcif_hw_init(struct rpcif *rpc, bool hyperflash) 302 + int rpcif_hw_init(struct device *dev, bool hyperflash) 304 303 { 304 + struct rpcif_priv *rpc = dev_get_drvdata(dev); 305 305 u32 dummy; 306 + int ret; 306 307 307 - pm_runtime_get_sync(rpc->dev); 308 + ret = pm_runtime_resume_and_get(dev); 309 + if (ret) 310 + return ret; 308 311 309 312 if (rpc->type == RPCIF_RZ_G2L) { 310 - int ret; 311 - 312 313 ret = reset_control_reset(rpc->rstc); 313 314 if (ret) 314 315 return ret; ··· 359 356 regmap_write(rpc->regmap, RPCIF_SSLDR, RPCIF_SSLDR_SPNDL(7) | 360 357 RPCIF_SSLDR_SLNDL(7) | RPCIF_SSLDR_SCKDL(7)); 361 358 362 - pm_runtime_put(rpc->dev); 359 + pm_runtime_put(dev); 363 360 364 361 rpc->bus_size = hyperflash ? 2 : 1; 365 362 ··· 367 364 } 368 365 EXPORT_SYMBOL(rpcif_hw_init); 369 366 370 - static int wait_msg_xfer_end(struct rpcif *rpc) 367 + static int wait_msg_xfer_end(struct rpcif_priv *rpc) 371 368 { 372 369 u32 sts; 373 370 ··· 376 373 USEC_PER_SEC); 377 374 } 378 375 379 - static u8 rpcif_bits_set(struct rpcif *rpc, u32 nbytes) 376 + static u8 rpcif_bits_set(struct rpcif_priv *rpc, u32 nbytes) 380 377 { 381 378 if (rpc->bus_size == 2) 382 379 nbytes /= 2; ··· 389 386 return buswidth > 4 ? 2 : ilog2(buswidth); 390 387 } 391 388 392 - void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs, 389 + void rpcif_prepare(struct device *dev, const struct rpcif_op *op, u64 *offs, 393 390 size_t *len) 394 391 { 392 + struct rpcif_priv *rpc = dev_get_drvdata(dev); 393 + 395 394 rpc->smcr = 0; 396 395 rpc->smadr = 0; 397 396 rpc->enable = 0; ··· 435 430 436 431 if (op->dummy.buswidth) { 437 432 rpc->enable |= RPCIF_SMENR_DME; 438 - rpc->dummy = RPCIF_SMDMCR_DMCYC(op->dummy.ncycles / 439 - op->dummy.buswidth); 433 + rpc->dummy = RPCIF_SMDMCR_DMCYC(op->dummy.ncycles); 440 434 } 441 435 442 436 if (op->option.buswidth) { ··· 476 472 } 477 473 EXPORT_SYMBOL(rpcif_prepare); 478 474 479 - int rpcif_manual_xfer(struct rpcif *rpc) 475 + int rpcif_manual_xfer(struct device *dev) 480 476 { 477 + struct rpcif_priv *rpc = dev_get_drvdata(dev); 481 478 u32 smenr, smcr, pos = 0, max = rpc->bus_size == 2 ? 8 : 4; 482 479 int ret = 0; 483 480 484 - pm_runtime_get_sync(rpc->dev); 481 + ret = pm_runtime_resume_and_get(dev); 482 + if (ret < 0) 483 + return ret; 485 484 486 485 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, 487 486 RPCIF_PHYCNT_CAL, RPCIF_PHYCNT_CAL); ··· 594 587 } 595 588 596 589 exit: 597 - pm_runtime_put(rpc->dev); 590 + pm_runtime_put(dev); 598 591 return ret; 599 592 600 593 err_out: 601 594 if (reset_control_reset(rpc->rstc)) 602 - dev_err(rpc->dev, "Failed to reset HW\n"); 603 - rpcif_hw_init(rpc, rpc->bus_size == 2); 595 + dev_err(dev, "Failed to reset HW\n"); 596 + rpcif_hw_init(dev, rpc->bus_size == 2); 604 597 goto exit; 605 598 } 606 599 EXPORT_SYMBOL(rpcif_manual_xfer); ··· 647 640 } 648 641 } 649 642 650 - ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf) 643 + ssize_t rpcif_dirmap_read(struct device *dev, u64 offs, size_t len, void *buf) 651 644 { 645 + struct rpcif_priv *rpc = dev_get_drvdata(dev); 652 646 loff_t from = offs & (rpc->size - 1); 653 647 size_t size = rpc->size - from; 648 + int ret; 654 649 655 650 if (len > size) 656 651 len = size; 657 652 658 - pm_runtime_get_sync(rpc->dev); 653 + ret = pm_runtime_resume_and_get(dev); 654 + if (ret < 0) 655 + return ret; 659 656 660 657 regmap_update_bits(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_MD, 0); 661 658 regmap_write(rpc->regmap, RPCIF_DRCR, 0); ··· 677 666 else 678 667 memcpy_fromio(buf, rpc->dirmap + from, len); 679 668 680 - pm_runtime_put(rpc->dev); 669 + pm_runtime_put(dev); 681 670 682 671 return len; 683 672 } ··· 685 674 686 675 static int rpcif_probe(struct platform_device *pdev) 687 676 { 677 + struct device *dev = &pdev->dev; 688 678 struct platform_device *vdev; 689 679 struct device_node *flash; 680 + struct rpcif_priv *rpc; 681 + struct resource *res; 690 682 const char *name; 691 683 int ret; 692 684 693 - flash = of_get_next_child(pdev->dev.of_node, NULL); 685 + flash = of_get_next_child(dev->of_node, NULL); 694 686 if (!flash) { 695 - dev_warn(&pdev->dev, "no flash node found\n"); 687 + dev_warn(dev, "no flash node found\n"); 696 688 return -ENODEV; 697 689 } 698 690 ··· 705 691 name = "rpc-if-hyperflash"; 706 692 } else { 707 693 of_node_put(flash); 708 - dev_warn(&pdev->dev, "unknown flash type\n"); 694 + dev_warn(dev, "unknown flash type\n"); 709 695 return -ENODEV; 710 696 } 711 697 of_node_put(flash); 712 698 699 + rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL); 700 + if (!rpc) 701 + return -ENOMEM; 702 + 703 + rpc->base = devm_platform_ioremap_resource_byname(pdev, "regs"); 704 + if (IS_ERR(rpc->base)) 705 + return PTR_ERR(rpc->base); 706 + 707 + rpc->regmap = devm_regmap_init(dev, NULL, rpc, &rpcif_regmap_config); 708 + if (IS_ERR(rpc->regmap)) { 709 + dev_err(dev, "failed to init regmap for rpcif, error %ld\n", 710 + PTR_ERR(rpc->regmap)); 711 + return PTR_ERR(rpc->regmap); 712 + } 713 + 714 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap"); 715 + rpc->dirmap = devm_ioremap_resource(dev, res); 716 + if (IS_ERR(rpc->dirmap)) 717 + return PTR_ERR(rpc->dirmap); 718 + rpc->size = resource_size(res); 719 + 720 + rpc->type = (uintptr_t)of_device_get_match_data(dev); 721 + rpc->rstc = devm_reset_control_get_exclusive(dev, NULL); 722 + if (IS_ERR(rpc->rstc)) 723 + return PTR_ERR(rpc->rstc); 724 + 713 725 vdev = platform_device_alloc(name, pdev->id); 714 726 if (!vdev) 715 727 return -ENOMEM; 716 - vdev->dev.parent = &pdev->dev; 717 - platform_set_drvdata(pdev, vdev); 728 + vdev->dev.parent = dev; 729 + 730 + rpc->dev = dev; 731 + rpc->vdev = vdev; 732 + platform_set_drvdata(pdev, rpc); 718 733 719 734 ret = platform_device_add(vdev); 720 735 if (ret) { ··· 756 713 757 714 static int rpcif_remove(struct platform_device *pdev) 758 715 { 759 - struct platform_device *vdev = platform_get_drvdata(pdev); 716 + struct rpcif_priv *rpc = platform_get_drvdata(pdev); 760 717 761 - platform_device_unregister(vdev); 718 + platform_device_unregister(rpc->vdev); 762 719 763 720 return 0; 764 721 }
+1 -6
drivers/memory/ti-emif-pm.c
··· 277 277 int ret; 278 278 struct resource *res; 279 279 struct device *dev = &pdev->dev; 280 - const struct of_device_id *match; 281 280 struct ti_emif_data *emif_data; 282 281 283 282 emif_data = devm_kzalloc(dev, sizeof(*emif_data), GFP_KERNEL); 284 283 if (!emif_data) 285 284 return -ENOMEM; 286 285 287 - match = of_match_device(ti_emif_of_match, &pdev->dev); 288 - if (!match) 289 - return -ENODEV; 290 - 291 - emif_data->pm_data.ti_emif_sram_config = (unsigned long)match->data; 286 + emif_data->pm_data.ti_emif_sram_config = (unsigned long) device_get_match_data(&pdev->dev); 292 287 293 288 emif_data->pm_data.ti_emif_base_addr_virt = devm_platform_get_and_ioremap_resource(pdev, 294 289 0,
+1 -1
drivers/misc/fastrpc.c
··· 18 18 #include <linux/rpmsg.h> 19 19 #include <linux/scatterlist.h> 20 20 #include <linux/slab.h> 21 - #include <linux/qcom_scm.h> 21 + #include <linux/firmware/qcom/qcom_scm.h> 22 22 #include <uapi/misc/fastrpc.h> 23 23 #include <linux/of_reserved_mem.h> 24 24
+1 -1
drivers/mmc/host/sdhci-msm.c
··· 13 13 #include <linux/pm_opp.h> 14 14 #include <linux/slab.h> 15 15 #include <linux/iopoll.h> 16 - #include <linux/qcom_scm.h> 16 + #include <linux/firmware/qcom/qcom_scm.h> 17 17 #include <linux/regulator/consumer.h> 18 18 #include <linux/interconnect.h> 19 19 #include <linux/pinctrl/consumer.h>
+9 -9
drivers/mtd/hyperbus/rpc-if.c
··· 56 56 op.data.nbytes = len; 57 57 op.data.buf.in = to; 58 58 59 - rpcif_prepare(rpc, &op, NULL, NULL); 59 + rpcif_prepare(rpc->dev, &op, NULL, NULL); 60 60 } 61 61 62 62 static void rpcif_hb_prepare_write(struct rpcif *rpc, unsigned long to, ··· 70 70 op.data.nbytes = len; 71 71 op.data.buf.out = from; 72 72 73 - rpcif_prepare(rpc, &op, NULL, NULL); 73 + rpcif_prepare(rpc->dev, &op, NULL, NULL); 74 74 } 75 75 76 76 static u16 rpcif_hb_read16(struct hyperbus_device *hbdev, unsigned long addr) ··· 81 81 82 82 rpcif_hb_prepare_read(&hyperbus->rpc, &data, addr, 2); 83 83 84 - rpcif_manual_xfer(&hyperbus->rpc); 84 + rpcif_manual_xfer(hyperbus->rpc.dev); 85 85 86 86 return data.x[0]; 87 87 } ··· 94 94 95 95 rpcif_hb_prepare_write(&hyperbus->rpc, addr, &data, 2); 96 96 97 - rpcif_manual_xfer(&hyperbus->rpc); 97 + rpcif_manual_xfer(hyperbus->rpc.dev); 98 98 } 99 99 100 100 static void rpcif_hb_copy_from(struct hyperbus_device *hbdev, void *to, ··· 105 105 106 106 rpcif_hb_prepare_read(&hyperbus->rpc, to, from, len); 107 107 108 - rpcif_dirmap_read(&hyperbus->rpc, from, len, to); 108 + rpcif_dirmap_read(hyperbus->rpc.dev, from, len, to); 109 109 } 110 110 111 111 static const struct hyperbus_ops rpcif_hb_ops = { ··· 130 130 131 131 platform_set_drvdata(pdev, hyperbus); 132 132 133 - rpcif_enable_rpm(&hyperbus->rpc); 133 + pm_runtime_enable(hyperbus->rpc.dev); 134 134 135 - error = rpcif_hw_init(&hyperbus->rpc, true); 135 + error = rpcif_hw_init(hyperbus->rpc.dev, true); 136 136 if (error) 137 137 goto out_disable_rpm; 138 138 ··· 150 150 return 0; 151 151 152 152 out_disable_rpm: 153 - rpcif_disable_rpm(&hyperbus->rpc); 153 + pm_runtime_disable(hyperbus->rpc.dev); 154 154 return error; 155 155 } 156 156 ··· 160 160 161 161 hyperbus_unregister_device(&hyperbus->hbdev); 162 162 163 - rpcif_disable_rpm(&hyperbus->rpc); 163 + pm_runtime_disable(hyperbus->rpc.dev); 164 164 165 165 return 0; 166 166 }
+1 -1
drivers/net/ipa/ipa_main.c
··· 16 16 #include <linux/of_device.h> 17 17 #include <linux/of_address.h> 18 18 #include <linux/pm_runtime.h> 19 - #include <linux/qcom_scm.h> 19 + #include <linux/firmware/qcom/qcom_scm.h> 20 20 #include <linux/soc/qcom/mdt_loader.h> 21 21 22 22 #include "ipa.h"
+1 -1
drivers/net/wireless/ath/ath10k/qmi.c
··· 13 13 #include <linux/module.h> 14 14 #include <linux/net.h> 15 15 #include <linux/platform_device.h> 16 - #include <linux/qcom_scm.h> 16 + #include <linux/firmware/qcom/qcom_scm.h> 17 17 #include <linux/soc/qcom/smem.h> 18 18 #include <linux/string.h> 19 19 #include <net/sock.h>
+5 -2
drivers/phy/samsung/phy-exynos-dp-video.c
··· 83 83 if (!state) 84 84 return -ENOMEM; 85 85 86 - state->regs = syscon_regmap_lookup_by_phandle(dev->of_node, 87 - "samsung,pmu-syscon"); 86 + state->regs = syscon_node_to_regmap(dev->parent->of_node); 87 + if (IS_ERR(state->regs)) 88 + /* Backwards compatible way */ 89 + state->regs = syscon_regmap_lookup_by_phandle(dev->of_node, 90 + "samsung,pmu-syscon"); 88 91 if (IS_ERR(state->regs)) { 89 92 dev_err(dev, "Failed to lookup PMU regmap\n"); 90 93 return PTR_ERR(state->regs);
+5 -2
drivers/phy/samsung/phy-exynos-mipi-video.c
··· 298 298 struct device *dev = &pdev->dev; 299 299 struct device_node *np = dev->of_node; 300 300 struct phy_provider *phy_provider; 301 - unsigned int i; 301 + unsigned int i = 0; 302 302 303 303 phy_dev = of_device_get_match_data(dev); 304 304 if (!phy_dev) ··· 308 308 if (!state) 309 309 return -ENOMEM; 310 310 311 - for (i = 0; i < phy_dev->num_regmaps; i++) { 311 + state->regmaps[i] = syscon_node_to_regmap(dev->parent->of_node); 312 + if (!IS_ERR(state->regmaps[i])) 313 + i++; 314 + for (; i < phy_dev->num_regmaps; i++) { 312 315 state->regmaps[i] = syscon_regmap_lookup_by_phandle(np, 313 316 phy_dev->regmap_names[i]); 314 317 if (IS_ERR(state->regmaps[i]))
+1 -1
drivers/pinctrl/qcom/pinctrl-msm.c
··· 14 14 #include <linux/of.h> 15 15 #include <linux/platform_device.h> 16 16 #include <linux/pm.h> 17 - #include <linux/qcom_scm.h> 17 + #include <linux/firmware/qcom/qcom_scm.h> 18 18 #include <linux/reboot.h> 19 19 #include <linux/seq_file.h> 20 20 #include <linux/slab.h>
+9
drivers/power/supply/Kconfig
··· 174 174 Say Y here to expose battery information on Apple machines 175 175 through the generic battery class. 176 176 177 + config BATTERY_QCOM_BATTMGR 178 + tristate "Qualcomm PMIC GLINK battery manager support" 179 + depends on QCOM_PMIC_GLINK 180 + select AUXILIARY_BUS 181 + help 182 + Say Y here to enable the Qualcomm PMIC GLINK power supply driver, 183 + which is used on modern Qualcomm platforms to provide battery and 184 + power supply information. 185 + 177 186 config BATTERY_OLPC 178 187 tristate "One Laptop Per Child battery" 179 188 depends on OLPC_EC
+1
drivers/power/supply/Makefile
··· 33 33 obj-$(CONFIG_BATTERY_GOLDFISH) += goldfish_battery.o 34 34 obj-$(CONFIG_BATTERY_LEGO_EV3) += lego_ev3_battery.o 35 35 obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o 36 + obj-$(CONFIG_BATTERY_QCOM_BATTMGR) += qcom_battmgr.o 36 37 obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o 37 38 obj-$(CONFIG_BATTERY_SAMSUNG_SDI) += samsung-sdi-battery.o 38 39 obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o
+1411
drivers/power/supply/qcom_battmgr.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. 4 + * Copyright (c) 2022, Linaro Ltd 5 + */ 6 + #include <linux/auxiliary_bus.h> 7 + #include <linux/module.h> 8 + #include <linux/mutex.h> 9 + #include <linux/of_device.h> 10 + #include <linux/power_supply.h> 11 + #include <linux/soc/qcom/pdr.h> 12 + #include <linux/soc/qcom/pmic_glink.h> 13 + #include <linux/math.h> 14 + #include <linux/units.h> 15 + 16 + #define BATTMGR_CHEMISTRY_LEN 4 17 + #define BATTMGR_STRING_LEN 128 18 + 19 + enum qcom_battmgr_variant { 20 + QCOM_BATTMGR_SM8350, 21 + QCOM_BATTMGR_SC8280XP, 22 + }; 23 + 24 + #define BATTMGR_BAT_STATUS 0x1 25 + 26 + #define BATTMGR_REQUEST_NOTIFICATION 0x4 27 + 28 + #define BATTMGR_NOTIFICATION 0x7 29 + #define NOTIF_BAT_PROPERTY 0x30 30 + #define NOTIF_USB_PROPERTY 0x32 31 + #define NOTIF_WLS_PROPERTY 0x34 32 + #define NOTIF_BAT_INFO 0x81 33 + #define NOTIF_BAT_STATUS 0x80 34 + 35 + #define BATTMGR_BAT_INFO 0x9 36 + 37 + #define BATTMGR_BAT_DISCHARGE_TIME 0xc 38 + 39 + #define BATTMGR_BAT_CHARGE_TIME 0xd 40 + 41 + #define BATTMGR_BAT_PROPERTY_GET 0x30 42 + #define BATTMGR_BAT_PROPERTY_SET 0x31 43 + #define BATT_STATUS 0 44 + #define BATT_HEALTH 1 45 + #define BATT_PRESENT 2 46 + #define BATT_CHG_TYPE 3 47 + #define BATT_CAPACITY 4 48 + #define BATT_SOH 5 49 + #define BATT_VOLT_OCV 6 50 + #define BATT_VOLT_NOW 7 51 + #define BATT_VOLT_MAX 8 52 + #define BATT_CURR_NOW 9 53 + #define BATT_CHG_CTRL_LIM 10 54 + #define BATT_CHG_CTRL_LIM_MAX 11 55 + #define BATT_TEMP 12 56 + #define BATT_TECHNOLOGY 13 57 + #define BATT_CHG_COUNTER 14 58 + #define BATT_CYCLE_COUNT 15 59 + #define BATT_CHG_FULL_DESIGN 16 60 + #define BATT_CHG_FULL 17 61 + #define BATT_MODEL_NAME 18 62 + #define BATT_TTF_AVG 19 63 + #define BATT_TTE_AVG 20 64 + #define BATT_RESISTANCE 21 65 + #define BATT_POWER_NOW 22 66 + #define BATT_POWER_AVG 23 67 + 68 + #define BATTMGR_USB_PROPERTY_GET 0x32 69 + #define BATTMGR_USB_PROPERTY_SET 0x33 70 + #define USB_ONLINE 0 71 + #define USB_VOLT_NOW 1 72 + #define USB_VOLT_MAX 2 73 + #define USB_CURR_NOW 3 74 + #define USB_CURR_MAX 4 75 + #define USB_INPUT_CURR_LIMIT 5 76 + #define USB_TYPE 6 77 + #define USB_ADAP_TYPE 7 78 + #define USB_MOISTURE_DET_EN 8 79 + #define USB_MOISTURE_DET_STS 9 80 + 81 + #define BATTMGR_WLS_PROPERTY_GET 0x34 82 + #define BATTMGR_WLS_PROPERTY_SET 0x35 83 + #define WLS_ONLINE 0 84 + #define WLS_VOLT_NOW 1 85 + #define WLS_VOLT_MAX 2 86 + #define WLS_CURR_NOW 3 87 + #define WLS_CURR_MAX 4 88 + #define WLS_TYPE 5 89 + #define WLS_BOOST_EN 6 90 + 91 + struct qcom_battmgr_enable_request { 92 + struct pmic_glink_hdr hdr; 93 + __le32 battery_id; 94 + __le32 power_state; 95 + __le32 low_capacity; 96 + __le32 high_capacity; 97 + }; 98 + 99 + struct qcom_battmgr_property_request { 100 + struct pmic_glink_hdr hdr; 101 + __le32 battery; 102 + __le32 property; 103 + __le32 value; 104 + }; 105 + 106 + struct qcom_battmgr_update_request { 107 + struct pmic_glink_hdr hdr; 108 + u32 battery_id; 109 + }; 110 + 111 + struct qcom_battmgr_charge_time_request { 112 + struct pmic_glink_hdr hdr; 113 + __le32 battery_id; 114 + __le32 percent; 115 + __le32 reserved; 116 + }; 117 + 118 + struct qcom_battmgr_discharge_time_request { 119 + struct pmic_glink_hdr hdr; 120 + __le32 battery_id; 121 + __le32 rate; /* 0 for current rate */ 122 + __le32 reserved; 123 + }; 124 + 125 + struct qcom_battmgr_message { 126 + struct pmic_glink_hdr hdr; 127 + union { 128 + struct { 129 + __le32 property; 130 + __le32 value; 131 + __le32 result; 132 + } intval; 133 + struct { 134 + __le32 property; 135 + char model[BATTMGR_STRING_LEN]; 136 + } strval; 137 + struct { 138 + /* 139 + * 0: mWh 140 + * 1: mAh 141 + */ 142 + __le32 power_unit; 143 + __le32 design_capacity; 144 + __le32 last_full_capacity; 145 + /* 146 + * 0 nonrechargable 147 + * 1 rechargable 148 + */ 149 + __le32 battery_tech; 150 + __le32 design_voltage; /* mV */ 151 + __le32 capacity_low; 152 + __le32 capacity_warning; 153 + __le32 cycle_count; 154 + /* thousandth of persent */ 155 + __le32 accuracy; 156 + __le32 max_sample_time_ms; 157 + __le32 min_sample_time_ms; 158 + __le32 max_average_interval_ms; 159 + __le32 min_average_interval_ms; 160 + /* granularity between low and warning */ 161 + __le32 capacity_granularity1; 162 + /* granularity between warning and full */ 163 + __le32 capacity_granularity2; 164 + /* 165 + * 0: no 166 + * 1: cold 167 + * 2: hot 168 + */ 169 + __le32 swappable; 170 + __le32 capabilities; 171 + char model_number[BATTMGR_STRING_LEN]; 172 + char serial_number[BATTMGR_STRING_LEN]; 173 + char battery_type[BATTMGR_STRING_LEN]; 174 + char oem_info[BATTMGR_STRING_LEN]; 175 + char battery_chemistry[BATTMGR_CHEMISTRY_LEN]; 176 + char uid[BATTMGR_STRING_LEN]; 177 + __le32 critical_bias; 178 + u8 day; 179 + u8 month; 180 + __le16 year; 181 + __le32 battery_id; 182 + } info; 183 + struct { 184 + /* 185 + * BIT(0) discharging 186 + * BIT(1) charging 187 + * BIT(2) critical low 188 + */ 189 + __le32 battery_state; 190 + /* mWh or mAh, based on info->power_unit */ 191 + __le32 capacity; 192 + __le32 rate; 193 + /* mv */ 194 + __le32 battery_voltage; 195 + /* 196 + * BIT(0) power online 197 + * BIT(1) discharging 198 + * BIT(2) charging 199 + * BIT(3) battery critical 200 + */ 201 + __le32 power_state; 202 + /* 203 + * 1: AC 204 + * 2: USB 205 + * 3: Wireless 206 + */ 207 + __le32 charging_source; 208 + __le32 temperature; 209 + } status; 210 + __le32 time; 211 + __le32 notification; 212 + }; 213 + }; 214 + 215 + #define BATTMGR_CHARGING_SOURCE_AC 1 216 + #define BATTMGR_CHARGING_SOURCE_USB 2 217 + #define BATTMGR_CHARGING_SOURCE_WIRELESS 3 218 + 219 + enum qcom_battmgr_unit { 220 + QCOM_BATTMGR_UNIT_mWh = 0, 221 + QCOM_BATTMGR_UNIT_mAh = 1 222 + }; 223 + 224 + struct qcom_battmgr_info { 225 + bool valid; 226 + 227 + bool present; 228 + unsigned int charge_type; 229 + unsigned int design_capacity; 230 + unsigned int last_full_capacity; 231 + unsigned int voltage_max_design; 232 + unsigned int voltage_max; 233 + unsigned int capacity_low; 234 + unsigned int capacity_warning; 235 + unsigned int cycle_count; 236 + unsigned int charge_count; 237 + char model_number[BATTMGR_STRING_LEN]; 238 + char serial_number[BATTMGR_STRING_LEN]; 239 + char oem_info[BATTMGR_STRING_LEN]; 240 + unsigned char technology; 241 + unsigned char day; 242 + unsigned char month; 243 + unsigned short year; 244 + }; 245 + 246 + struct qcom_battmgr_status { 247 + unsigned int status; 248 + unsigned int health; 249 + unsigned int capacity; 250 + unsigned int percent; 251 + int current_now; 252 + int power_now; 253 + unsigned int voltage_now; 254 + unsigned int voltage_ocv; 255 + unsigned int temperature; 256 + 257 + unsigned int discharge_time; 258 + unsigned int charge_time; 259 + }; 260 + 261 + struct qcom_battmgr_ac { 262 + bool online; 263 + }; 264 + 265 + struct qcom_battmgr_usb { 266 + bool online; 267 + unsigned int voltage_now; 268 + unsigned int voltage_max; 269 + unsigned int current_now; 270 + unsigned int current_max; 271 + unsigned int current_limit; 272 + unsigned int usb_type; 273 + }; 274 + 275 + struct qcom_battmgr_wireless { 276 + bool online; 277 + unsigned int voltage_now; 278 + unsigned int voltage_max; 279 + unsigned int current_now; 280 + unsigned int current_max; 281 + }; 282 + 283 + struct qcom_battmgr { 284 + struct device *dev; 285 + struct pmic_glink_client *client; 286 + 287 + enum qcom_battmgr_variant variant; 288 + 289 + struct power_supply *ac_psy; 290 + struct power_supply *bat_psy; 291 + struct power_supply *usb_psy; 292 + struct power_supply *wls_psy; 293 + 294 + enum qcom_battmgr_unit unit; 295 + 296 + int error; 297 + struct completion ack; 298 + 299 + bool service_up; 300 + 301 + struct qcom_battmgr_info info; 302 + struct qcom_battmgr_status status; 303 + struct qcom_battmgr_ac ac; 304 + struct qcom_battmgr_usb usb; 305 + struct qcom_battmgr_wireless wireless; 306 + 307 + struct work_struct enable_work; 308 + 309 + /* 310 + * @lock is used to prevent concurrent power supply requests to the 311 + * firmware, as it then stops responding. 312 + */ 313 + struct mutex lock; 314 + }; 315 + 316 + static int qcom_battmgr_request(struct qcom_battmgr *battmgr, void *data, size_t len) 317 + { 318 + unsigned long left; 319 + int ret; 320 + 321 + reinit_completion(&battmgr->ack); 322 + 323 + battmgr->error = 0; 324 + 325 + ret = pmic_glink_send(battmgr->client, data, len); 326 + if (ret < 0) 327 + return ret; 328 + 329 + left = wait_for_completion_timeout(&battmgr->ack, HZ); 330 + if (!left) 331 + return -ETIMEDOUT; 332 + 333 + return battmgr->error; 334 + } 335 + 336 + static int qcom_battmgr_request_property(struct qcom_battmgr *battmgr, int opcode, 337 + int property, u32 value) 338 + { 339 + struct qcom_battmgr_property_request request = { 340 + .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_BATTMGR), 341 + .hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP), 342 + .hdr.opcode = cpu_to_le32(opcode), 343 + .battery = cpu_to_le32(0), 344 + .property = cpu_to_le32(property), 345 + .value = cpu_to_le32(value), 346 + }; 347 + 348 + return qcom_battmgr_request(battmgr, &request, sizeof(request)); 349 + } 350 + 351 + static int qcom_battmgr_update_status(struct qcom_battmgr *battmgr) 352 + { 353 + struct qcom_battmgr_update_request request = { 354 + .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_BATTMGR), 355 + .hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP), 356 + .hdr.opcode = cpu_to_le32(BATTMGR_BAT_STATUS), 357 + .battery_id = cpu_to_le32(0), 358 + }; 359 + 360 + return qcom_battmgr_request(battmgr, &request, sizeof(request)); 361 + } 362 + 363 + static int qcom_battmgr_update_info(struct qcom_battmgr *battmgr) 364 + { 365 + struct qcom_battmgr_update_request request = { 366 + .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_BATTMGR), 367 + .hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP), 368 + .hdr.opcode = cpu_to_le32(BATTMGR_BAT_INFO), 369 + .battery_id = cpu_to_le32(0), 370 + }; 371 + 372 + return qcom_battmgr_request(battmgr, &request, sizeof(request)); 373 + } 374 + 375 + static int qcom_battmgr_update_charge_time(struct qcom_battmgr *battmgr) 376 + { 377 + struct qcom_battmgr_charge_time_request request = { 378 + .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_BATTMGR), 379 + .hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP), 380 + .hdr.opcode = cpu_to_le32(BATTMGR_BAT_CHARGE_TIME), 381 + .battery_id = cpu_to_le32(0), 382 + .percent = cpu_to_le32(100), 383 + }; 384 + 385 + return qcom_battmgr_request(battmgr, &request, sizeof(request)); 386 + } 387 + 388 + static int qcom_battmgr_update_discharge_time(struct qcom_battmgr *battmgr) 389 + { 390 + struct qcom_battmgr_discharge_time_request request = { 391 + .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_BATTMGR), 392 + .hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP), 393 + .hdr.opcode = cpu_to_le32(BATTMGR_BAT_DISCHARGE_TIME), 394 + .battery_id = cpu_to_le32(0), 395 + .rate = cpu_to_le32(0), 396 + }; 397 + 398 + return qcom_battmgr_request(battmgr, &request, sizeof(request)); 399 + } 400 + 401 + static const u8 sm8350_bat_prop_map[] = { 402 + [POWER_SUPPLY_PROP_STATUS] = BATT_STATUS, 403 + [POWER_SUPPLY_PROP_HEALTH] = BATT_HEALTH, 404 + [POWER_SUPPLY_PROP_PRESENT] = BATT_PRESENT, 405 + [POWER_SUPPLY_PROP_CHARGE_TYPE] = BATT_CHG_TYPE, 406 + [POWER_SUPPLY_PROP_CAPACITY] = BATT_CAPACITY, 407 + [POWER_SUPPLY_PROP_VOLTAGE_OCV] = BATT_VOLT_OCV, 408 + [POWER_SUPPLY_PROP_VOLTAGE_NOW] = BATT_VOLT_NOW, 409 + [POWER_SUPPLY_PROP_VOLTAGE_MAX] = BATT_VOLT_MAX, 410 + [POWER_SUPPLY_PROP_CURRENT_NOW] = BATT_CURR_NOW, 411 + [POWER_SUPPLY_PROP_TEMP] = BATT_TEMP, 412 + [POWER_SUPPLY_PROP_TECHNOLOGY] = BATT_TECHNOLOGY, 413 + [POWER_SUPPLY_PROP_CHARGE_COUNTER] = BATT_CHG_COUNTER, 414 + [POWER_SUPPLY_PROP_CYCLE_COUNT] = BATT_CYCLE_COUNT, 415 + [POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN] = BATT_CHG_FULL_DESIGN, 416 + [POWER_SUPPLY_PROP_CHARGE_FULL] = BATT_CHG_FULL, 417 + [POWER_SUPPLY_PROP_MODEL_NAME] = BATT_MODEL_NAME, 418 + [POWER_SUPPLY_PROP_TIME_TO_FULL_AVG] = BATT_TTF_AVG, 419 + [POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG] = BATT_TTE_AVG, 420 + [POWER_SUPPLY_PROP_POWER_NOW] = BATT_POWER_NOW, 421 + }; 422 + 423 + static int qcom_battmgr_bat_sm8350_update(struct qcom_battmgr *battmgr, 424 + enum power_supply_property psp) 425 + { 426 + unsigned int prop; 427 + int ret; 428 + 429 + if (psp >= ARRAY_SIZE(sm8350_bat_prop_map)) 430 + return -EINVAL; 431 + 432 + prop = sm8350_bat_prop_map[psp]; 433 + 434 + mutex_lock(&battmgr->lock); 435 + ret = qcom_battmgr_request_property(battmgr, BATTMGR_BAT_PROPERTY_GET, prop, 0); 436 + mutex_unlock(&battmgr->lock); 437 + 438 + return ret; 439 + } 440 + 441 + static int qcom_battmgr_bat_sc8280xp_update(struct qcom_battmgr *battmgr, 442 + enum power_supply_property psp) 443 + { 444 + int ret; 445 + 446 + mutex_lock(&battmgr->lock); 447 + 448 + if (!battmgr->info.valid) { 449 + ret = qcom_battmgr_update_info(battmgr); 450 + if (ret < 0) 451 + goto out_unlock; 452 + battmgr->info.valid = true; 453 + } 454 + 455 + ret = qcom_battmgr_update_status(battmgr); 456 + if (ret < 0) 457 + goto out_unlock; 458 + 459 + if (psp == POWER_SUPPLY_PROP_TIME_TO_FULL_AVG) { 460 + ret = qcom_battmgr_update_charge_time(battmgr); 461 + if (ret < 0) { 462 + ret = -ENODATA; 463 + goto out_unlock; 464 + } 465 + } 466 + 467 + if (psp == POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG) { 468 + ret = qcom_battmgr_update_discharge_time(battmgr); 469 + if (ret < 0) { 470 + ret = -ENODATA; 471 + goto out_unlock; 472 + } 473 + } 474 + 475 + out_unlock: 476 + mutex_unlock(&battmgr->lock); 477 + return ret; 478 + } 479 + 480 + static int qcom_battmgr_bat_get_property(struct power_supply *psy, 481 + enum power_supply_property psp, 482 + union power_supply_propval *val) 483 + { 484 + struct qcom_battmgr *battmgr = power_supply_get_drvdata(psy); 485 + enum qcom_battmgr_unit unit = battmgr->unit; 486 + int ret; 487 + 488 + if (!battmgr->service_up) 489 + return -ENODEV; 490 + 491 + if (battmgr->variant == QCOM_BATTMGR_SC8280XP) 492 + ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); 493 + else 494 + ret = qcom_battmgr_bat_sm8350_update(battmgr, psp); 495 + if (ret < 0) 496 + return ret; 497 + 498 + switch (psp) { 499 + case POWER_SUPPLY_PROP_STATUS: 500 + val->intval = battmgr->status.status; 501 + break; 502 + case POWER_SUPPLY_PROP_CHARGE_TYPE: 503 + val->intval = battmgr->info.charge_type; 504 + break; 505 + case POWER_SUPPLY_PROP_HEALTH: 506 + val->intval = battmgr->status.health; 507 + break; 508 + case POWER_SUPPLY_PROP_PRESENT: 509 + val->intval = battmgr->info.present; 510 + break; 511 + case POWER_SUPPLY_PROP_TECHNOLOGY: 512 + val->intval = battmgr->info.technology; 513 + break; 514 + case POWER_SUPPLY_PROP_CYCLE_COUNT: 515 + val->intval = battmgr->info.cycle_count; 516 + break; 517 + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 518 + val->intval = battmgr->info.voltage_max_design; 519 + break; 520 + case POWER_SUPPLY_PROP_VOLTAGE_MAX: 521 + val->intval = battmgr->info.voltage_max; 522 + break; 523 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 524 + val->intval = battmgr->status.voltage_now; 525 + break; 526 + case POWER_SUPPLY_PROP_VOLTAGE_OCV: 527 + val->intval = battmgr->status.voltage_ocv; 528 + break; 529 + case POWER_SUPPLY_PROP_CURRENT_NOW: 530 + val->intval = battmgr->status.current_now; 531 + break; 532 + case POWER_SUPPLY_PROP_POWER_NOW: 533 + val->intval = battmgr->status.power_now; 534 + break; 535 + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 536 + if (unit != QCOM_BATTMGR_UNIT_mAh) 537 + return -ENODATA; 538 + val->intval = battmgr->info.design_capacity; 539 + break; 540 + case POWER_SUPPLY_PROP_CHARGE_FULL: 541 + if (unit != QCOM_BATTMGR_UNIT_mAh) 542 + return -ENODATA; 543 + val->intval = battmgr->info.last_full_capacity; 544 + break; 545 + case POWER_SUPPLY_PROP_CHARGE_EMPTY: 546 + if (unit != QCOM_BATTMGR_UNIT_mAh) 547 + return -ENODATA; 548 + val->intval = battmgr->info.capacity_low; 549 + break; 550 + case POWER_SUPPLY_PROP_CHARGE_NOW: 551 + if (unit != QCOM_BATTMGR_UNIT_mAh) 552 + return -ENODATA; 553 + val->intval = battmgr->status.capacity; 554 + break; 555 + case POWER_SUPPLY_PROP_CHARGE_COUNTER: 556 + val->intval = battmgr->info.charge_count; 557 + break; 558 + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 559 + if (unit != QCOM_BATTMGR_UNIT_mWh) 560 + return -ENODATA; 561 + val->intval = battmgr->info.design_capacity; 562 + break; 563 + case POWER_SUPPLY_PROP_ENERGY_FULL: 564 + if (unit != QCOM_BATTMGR_UNIT_mWh) 565 + return -ENODATA; 566 + val->intval = battmgr->info.last_full_capacity; 567 + break; 568 + case POWER_SUPPLY_PROP_ENERGY_EMPTY: 569 + if (unit != QCOM_BATTMGR_UNIT_mWh) 570 + return -ENODATA; 571 + val->intval = battmgr->info.capacity_low; 572 + break; 573 + case POWER_SUPPLY_PROP_ENERGY_NOW: 574 + if (unit != QCOM_BATTMGR_UNIT_mWh) 575 + return -ENODATA; 576 + val->intval = battmgr->status.capacity; 577 + break; 578 + case POWER_SUPPLY_PROP_CAPACITY: 579 + val->intval = battmgr->status.percent; 580 + break; 581 + case POWER_SUPPLY_PROP_TEMP: 582 + val->intval = battmgr->status.temperature; 583 + break; 584 + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 585 + val->intval = battmgr->status.discharge_time; 586 + break; 587 + case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: 588 + val->intval = battmgr->status.charge_time; 589 + break; 590 + case POWER_SUPPLY_PROP_MANUFACTURE_YEAR: 591 + val->intval = battmgr->info.year; 592 + break; 593 + case POWER_SUPPLY_PROP_MANUFACTURE_MONTH: 594 + val->intval = battmgr->info.month; 595 + break; 596 + case POWER_SUPPLY_PROP_MANUFACTURE_DAY: 597 + val->intval = battmgr->info.day; 598 + break; 599 + case POWER_SUPPLY_PROP_MODEL_NAME: 600 + val->strval = battmgr->info.model_number; 601 + break; 602 + case POWER_SUPPLY_PROP_MANUFACTURER: 603 + val->strval = battmgr->info.oem_info; 604 + break; 605 + case POWER_SUPPLY_PROP_SERIAL_NUMBER: 606 + val->strval = battmgr->info.serial_number; 607 + break; 608 + default: 609 + return -EINVAL; 610 + } 611 + 612 + return 0; 613 + } 614 + 615 + static const enum power_supply_property sc8280xp_bat_props[] = { 616 + POWER_SUPPLY_PROP_STATUS, 617 + POWER_SUPPLY_PROP_PRESENT, 618 + POWER_SUPPLY_PROP_TECHNOLOGY, 619 + POWER_SUPPLY_PROP_CYCLE_COUNT, 620 + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 621 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 622 + POWER_SUPPLY_PROP_POWER_NOW, 623 + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 624 + POWER_SUPPLY_PROP_CHARGE_FULL, 625 + POWER_SUPPLY_PROP_CHARGE_EMPTY, 626 + POWER_SUPPLY_PROP_CHARGE_NOW, 627 + POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 628 + POWER_SUPPLY_PROP_ENERGY_FULL, 629 + POWER_SUPPLY_PROP_ENERGY_EMPTY, 630 + POWER_SUPPLY_PROP_ENERGY_NOW, 631 + POWER_SUPPLY_PROP_TEMP, 632 + POWER_SUPPLY_PROP_MANUFACTURE_YEAR, 633 + POWER_SUPPLY_PROP_MANUFACTURE_MONTH, 634 + POWER_SUPPLY_PROP_MANUFACTURE_DAY, 635 + POWER_SUPPLY_PROP_MODEL_NAME, 636 + POWER_SUPPLY_PROP_MANUFACTURER, 637 + POWER_SUPPLY_PROP_SERIAL_NUMBER, 638 + }; 639 + 640 + static const struct power_supply_desc sc8280xp_bat_psy_desc = { 641 + .name = "qcom-battmgr-bat", 642 + .type = POWER_SUPPLY_TYPE_BATTERY, 643 + .properties = sc8280xp_bat_props, 644 + .num_properties = ARRAY_SIZE(sc8280xp_bat_props), 645 + .get_property = qcom_battmgr_bat_get_property, 646 + }; 647 + 648 + static const enum power_supply_property sm8350_bat_props[] = { 649 + POWER_SUPPLY_PROP_STATUS, 650 + POWER_SUPPLY_PROP_HEALTH, 651 + POWER_SUPPLY_PROP_PRESENT, 652 + POWER_SUPPLY_PROP_CHARGE_TYPE, 653 + POWER_SUPPLY_PROP_CAPACITY, 654 + POWER_SUPPLY_PROP_VOLTAGE_OCV, 655 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 656 + POWER_SUPPLY_PROP_VOLTAGE_MAX, 657 + POWER_SUPPLY_PROP_CURRENT_NOW, 658 + POWER_SUPPLY_PROP_TEMP, 659 + POWER_SUPPLY_PROP_TECHNOLOGY, 660 + POWER_SUPPLY_PROP_CHARGE_COUNTER, 661 + POWER_SUPPLY_PROP_CYCLE_COUNT, 662 + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 663 + POWER_SUPPLY_PROP_CHARGE_FULL, 664 + POWER_SUPPLY_PROP_MODEL_NAME, 665 + POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 666 + POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 667 + POWER_SUPPLY_PROP_POWER_NOW, 668 + }; 669 + 670 + static const struct power_supply_desc sm8350_bat_psy_desc = { 671 + .name = "qcom-battmgr-bat", 672 + .type = POWER_SUPPLY_TYPE_BATTERY, 673 + .properties = sm8350_bat_props, 674 + .num_properties = ARRAY_SIZE(sm8350_bat_props), 675 + .get_property = qcom_battmgr_bat_get_property, 676 + }; 677 + 678 + static int qcom_battmgr_ac_get_property(struct power_supply *psy, 679 + enum power_supply_property psp, 680 + union power_supply_propval *val) 681 + { 682 + struct qcom_battmgr *battmgr = power_supply_get_drvdata(psy); 683 + int ret; 684 + 685 + if (!battmgr->service_up) 686 + return -ENODEV; 687 + 688 + ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); 689 + if (ret) 690 + return ret; 691 + 692 + switch (psp) { 693 + case POWER_SUPPLY_PROP_ONLINE: 694 + val->intval = battmgr->ac.online; 695 + break; 696 + default: 697 + return -EINVAL; 698 + } 699 + 700 + return 0; 701 + } 702 + 703 + static const enum power_supply_property sc8280xp_ac_props[] = { 704 + POWER_SUPPLY_PROP_ONLINE, 705 + }; 706 + 707 + static const struct power_supply_desc sc8280xp_ac_psy_desc = { 708 + .name = "qcom-battmgr-ac", 709 + .type = POWER_SUPPLY_TYPE_MAINS, 710 + .properties = sc8280xp_ac_props, 711 + .num_properties = ARRAY_SIZE(sc8280xp_ac_props), 712 + .get_property = qcom_battmgr_ac_get_property, 713 + }; 714 + 715 + static const u8 sm8350_usb_prop_map[] = { 716 + [POWER_SUPPLY_PROP_ONLINE] = USB_ONLINE, 717 + [POWER_SUPPLY_PROP_VOLTAGE_NOW] = USB_VOLT_NOW, 718 + [POWER_SUPPLY_PROP_VOLTAGE_MAX] = USB_VOLT_MAX, 719 + [POWER_SUPPLY_PROP_CURRENT_NOW] = USB_CURR_NOW, 720 + [POWER_SUPPLY_PROP_CURRENT_MAX] = USB_CURR_MAX, 721 + [POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT] = USB_INPUT_CURR_LIMIT, 722 + [POWER_SUPPLY_PROP_USB_TYPE] = USB_TYPE, 723 + }; 724 + 725 + static int qcom_battmgr_usb_sm8350_update(struct qcom_battmgr *battmgr, 726 + enum power_supply_property psp) 727 + { 728 + unsigned int prop; 729 + int ret; 730 + 731 + if (psp >= ARRAY_SIZE(sm8350_usb_prop_map)) 732 + return -EINVAL; 733 + 734 + prop = sm8350_usb_prop_map[psp]; 735 + 736 + mutex_lock(&battmgr->lock); 737 + ret = qcom_battmgr_request_property(battmgr, BATTMGR_USB_PROPERTY_GET, prop, 0); 738 + mutex_unlock(&battmgr->lock); 739 + 740 + return ret; 741 + } 742 + 743 + static int qcom_battmgr_usb_get_property(struct power_supply *psy, 744 + enum power_supply_property psp, 745 + union power_supply_propval *val) 746 + { 747 + struct qcom_battmgr *battmgr = power_supply_get_drvdata(psy); 748 + int ret; 749 + 750 + if (!battmgr->service_up) 751 + return -ENODEV; 752 + 753 + if (battmgr->variant == QCOM_BATTMGR_SC8280XP) 754 + ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); 755 + else 756 + ret = qcom_battmgr_usb_sm8350_update(battmgr, psp); 757 + if (ret) 758 + return ret; 759 + 760 + switch (psp) { 761 + case POWER_SUPPLY_PROP_ONLINE: 762 + val->intval = battmgr->usb.online; 763 + break; 764 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 765 + val->intval = battmgr->usb.voltage_now; 766 + break; 767 + case POWER_SUPPLY_PROP_VOLTAGE_MAX: 768 + val->intval = battmgr->usb.voltage_max; 769 + break; 770 + case POWER_SUPPLY_PROP_CURRENT_NOW: 771 + val->intval = battmgr->usb.current_now; 772 + break; 773 + case POWER_SUPPLY_PROP_CURRENT_MAX: 774 + val->intval = battmgr->usb.current_max; 775 + break; 776 + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 777 + val->intval = battmgr->usb.current_limit; 778 + break; 779 + case POWER_SUPPLY_PROP_USB_TYPE: 780 + val->intval = battmgr->usb.usb_type; 781 + break; 782 + default: 783 + return -EINVAL; 784 + } 785 + 786 + return 0; 787 + } 788 + 789 + static const enum power_supply_usb_type usb_psy_supported_types[] = { 790 + POWER_SUPPLY_USB_TYPE_UNKNOWN, 791 + POWER_SUPPLY_USB_TYPE_SDP, 792 + POWER_SUPPLY_USB_TYPE_DCP, 793 + POWER_SUPPLY_USB_TYPE_CDP, 794 + POWER_SUPPLY_USB_TYPE_ACA, 795 + POWER_SUPPLY_USB_TYPE_C, 796 + POWER_SUPPLY_USB_TYPE_PD, 797 + POWER_SUPPLY_USB_TYPE_PD_DRP, 798 + POWER_SUPPLY_USB_TYPE_PD_PPS, 799 + POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID, 800 + }; 801 + 802 + static const enum power_supply_property sc8280xp_usb_props[] = { 803 + POWER_SUPPLY_PROP_ONLINE, 804 + }; 805 + 806 + static const struct power_supply_desc sc8280xp_usb_psy_desc = { 807 + .name = "qcom-battmgr-usb", 808 + .type = POWER_SUPPLY_TYPE_USB, 809 + .properties = sc8280xp_usb_props, 810 + .num_properties = ARRAY_SIZE(sc8280xp_usb_props), 811 + .get_property = qcom_battmgr_usb_get_property, 812 + .usb_types = usb_psy_supported_types, 813 + .num_usb_types = ARRAY_SIZE(usb_psy_supported_types), 814 + }; 815 + 816 + static const enum power_supply_property sm8350_usb_props[] = { 817 + POWER_SUPPLY_PROP_ONLINE, 818 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 819 + POWER_SUPPLY_PROP_VOLTAGE_MAX, 820 + POWER_SUPPLY_PROP_CURRENT_NOW, 821 + POWER_SUPPLY_PROP_CURRENT_MAX, 822 + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 823 + POWER_SUPPLY_PROP_USB_TYPE, 824 + }; 825 + 826 + static const struct power_supply_desc sm8350_usb_psy_desc = { 827 + .name = "qcom-battmgr-usb", 828 + .type = POWER_SUPPLY_TYPE_USB, 829 + .properties = sm8350_usb_props, 830 + .num_properties = ARRAY_SIZE(sm8350_usb_props), 831 + .get_property = qcom_battmgr_usb_get_property, 832 + .usb_types = usb_psy_supported_types, 833 + .num_usb_types = ARRAY_SIZE(usb_psy_supported_types), 834 + }; 835 + 836 + static const u8 sm8350_wls_prop_map[] = { 837 + [POWER_SUPPLY_PROP_ONLINE] = WLS_ONLINE, 838 + [POWER_SUPPLY_PROP_VOLTAGE_NOW] = WLS_VOLT_NOW, 839 + [POWER_SUPPLY_PROP_VOLTAGE_MAX] = WLS_VOLT_MAX, 840 + [POWER_SUPPLY_PROP_CURRENT_NOW] = WLS_CURR_NOW, 841 + [POWER_SUPPLY_PROP_CURRENT_MAX] = WLS_CURR_MAX, 842 + }; 843 + 844 + static int qcom_battmgr_wls_sm8350_update(struct qcom_battmgr *battmgr, 845 + enum power_supply_property psp) 846 + { 847 + unsigned int prop; 848 + int ret; 849 + 850 + if (psp >= ARRAY_SIZE(sm8350_wls_prop_map)) 851 + return -EINVAL; 852 + 853 + prop = sm8350_wls_prop_map[psp]; 854 + 855 + mutex_lock(&battmgr->lock); 856 + ret = qcom_battmgr_request_property(battmgr, BATTMGR_WLS_PROPERTY_GET, prop, 0); 857 + mutex_unlock(&battmgr->lock); 858 + 859 + return ret; 860 + } 861 + 862 + static int qcom_battmgr_wls_get_property(struct power_supply *psy, 863 + enum power_supply_property psp, 864 + union power_supply_propval *val) 865 + { 866 + struct qcom_battmgr *battmgr = power_supply_get_drvdata(psy); 867 + int ret; 868 + 869 + if (!battmgr->service_up) 870 + return -ENODEV; 871 + 872 + if (battmgr->variant == QCOM_BATTMGR_SC8280XP) 873 + ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); 874 + else 875 + ret = qcom_battmgr_wls_sm8350_update(battmgr, psp); 876 + if (ret < 0) 877 + return ret; 878 + 879 + switch (psp) { 880 + case POWER_SUPPLY_PROP_ONLINE: 881 + val->intval = battmgr->wireless.online; 882 + break; 883 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 884 + val->intval = battmgr->wireless.voltage_now; 885 + break; 886 + case POWER_SUPPLY_PROP_VOLTAGE_MAX: 887 + val->intval = battmgr->wireless.voltage_max; 888 + break; 889 + case POWER_SUPPLY_PROP_CURRENT_NOW: 890 + val->intval = battmgr->wireless.current_now; 891 + break; 892 + case POWER_SUPPLY_PROP_CURRENT_MAX: 893 + val->intval = battmgr->wireless.current_max; 894 + break; 895 + default: 896 + return -EINVAL; 897 + } 898 + 899 + return 0; 900 + } 901 + 902 + static const enum power_supply_property sc8280xp_wls_props[] = { 903 + POWER_SUPPLY_PROP_ONLINE, 904 + }; 905 + 906 + static const struct power_supply_desc sc8280xp_wls_psy_desc = { 907 + .name = "qcom-battmgr-wls", 908 + .type = POWER_SUPPLY_TYPE_WIRELESS, 909 + .properties = sc8280xp_wls_props, 910 + .num_properties = ARRAY_SIZE(sc8280xp_wls_props), 911 + .get_property = qcom_battmgr_wls_get_property, 912 + }; 913 + 914 + static const enum power_supply_property sm8350_wls_props[] = { 915 + POWER_SUPPLY_PROP_ONLINE, 916 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 917 + POWER_SUPPLY_PROP_VOLTAGE_MAX, 918 + POWER_SUPPLY_PROP_CURRENT_NOW, 919 + POWER_SUPPLY_PROP_CURRENT_MAX, 920 + }; 921 + 922 + static const struct power_supply_desc sm8350_wls_psy_desc = { 923 + .name = "qcom-battmgr-wls", 924 + .type = POWER_SUPPLY_TYPE_WIRELESS, 925 + .properties = sm8350_wls_props, 926 + .num_properties = ARRAY_SIZE(sm8350_wls_props), 927 + .get_property = qcom_battmgr_wls_get_property, 928 + }; 929 + 930 + static void qcom_battmgr_notification(struct qcom_battmgr *battmgr, 931 + const struct qcom_battmgr_message *msg, 932 + int len) 933 + { 934 + size_t payload_len = len - sizeof(struct pmic_glink_hdr); 935 + unsigned int notification; 936 + 937 + if (payload_len != sizeof(msg->notification)) { 938 + dev_warn(battmgr->dev, "ignoring notification with invalid length\n"); 939 + return; 940 + } 941 + 942 + notification = le32_to_cpu(msg->notification); 943 + switch (notification) { 944 + case NOTIF_BAT_INFO: 945 + battmgr->info.valid = false; 946 + fallthrough; 947 + case NOTIF_BAT_STATUS: 948 + case NOTIF_BAT_PROPERTY: 949 + power_supply_changed(battmgr->bat_psy); 950 + break; 951 + case NOTIF_USB_PROPERTY: 952 + power_supply_changed(battmgr->usb_psy); 953 + break; 954 + case NOTIF_WLS_PROPERTY: 955 + power_supply_changed(battmgr->wls_psy); 956 + break; 957 + default: 958 + dev_err(battmgr->dev, "unknown notification: %#x\n", notification); 959 + break; 960 + } 961 + } 962 + 963 + static void qcom_battmgr_sc8280xp_strcpy(char *dest, const char *src) 964 + { 965 + size_t len = src[0]; 966 + 967 + /* Some firmware versions return Pascal-style strings */ 968 + if (len < BATTMGR_STRING_LEN && len == strnlen(src + 1, BATTMGR_STRING_LEN - 1)) { 969 + memcpy(dest, src + 1, len); 970 + dest[len] = '\0'; 971 + } else { 972 + memcpy(dest, src, BATTMGR_STRING_LEN); 973 + } 974 + } 975 + 976 + static unsigned int qcom_battmgr_sc8280xp_parse_technology(const char *chemistry) 977 + { 978 + if (!strncmp(chemistry, "LIO", BATTMGR_CHEMISTRY_LEN)) 979 + return POWER_SUPPLY_TECHNOLOGY_LION; 980 + 981 + pr_err("Unknown battery technology '%s'\n", chemistry); 982 + return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; 983 + } 984 + 985 + static unsigned int qcom_battmgr_sc8280xp_convert_temp(unsigned int temperature) 986 + { 987 + return DIV_ROUND_CLOSEST(temperature, 10); 988 + } 989 + 990 + static void qcom_battmgr_sc8280xp_callback(struct qcom_battmgr *battmgr, 991 + const struct qcom_battmgr_message *resp, 992 + size_t len) 993 + { 994 + unsigned int opcode = le32_to_cpu(resp->hdr.opcode); 995 + unsigned int source; 996 + unsigned int state; 997 + size_t payload_len = len - sizeof(struct pmic_glink_hdr); 998 + 999 + if (payload_len < sizeof(__le32)) { 1000 + dev_warn(battmgr->dev, "invalid payload length for %#x: %zd\n", 1001 + opcode, len); 1002 + return; 1003 + } 1004 + 1005 + switch (opcode) { 1006 + case BATTMGR_REQUEST_NOTIFICATION: 1007 + battmgr->error = 0; 1008 + break; 1009 + case BATTMGR_BAT_INFO: 1010 + if (payload_len != sizeof(resp->info)) { 1011 + dev_warn(battmgr->dev, 1012 + "invalid payload length for battery information request: %zd\n", 1013 + payload_len); 1014 + battmgr->error = -ENODATA; 1015 + return; 1016 + } 1017 + 1018 + battmgr->unit = le32_to_cpu(resp->info.power_unit); 1019 + 1020 + battmgr->info.present = true; 1021 + battmgr->info.design_capacity = le32_to_cpu(resp->info.design_capacity) * 1000; 1022 + battmgr->info.last_full_capacity = le32_to_cpu(resp->info.last_full_capacity) * 1000; 1023 + battmgr->info.voltage_max_design = le32_to_cpu(resp->info.design_voltage) * 1000; 1024 + battmgr->info.capacity_low = le32_to_cpu(resp->info.capacity_low) * 1000; 1025 + battmgr->info.cycle_count = le32_to_cpu(resp->info.cycle_count); 1026 + qcom_battmgr_sc8280xp_strcpy(battmgr->info.model_number, resp->info.model_number); 1027 + qcom_battmgr_sc8280xp_strcpy(battmgr->info.serial_number, resp->info.serial_number); 1028 + battmgr->info.technology = qcom_battmgr_sc8280xp_parse_technology(resp->info.battery_chemistry); 1029 + qcom_battmgr_sc8280xp_strcpy(battmgr->info.oem_info, resp->info.oem_info); 1030 + battmgr->info.day = resp->info.day; 1031 + battmgr->info.month = resp->info.month; 1032 + battmgr->info.year = le16_to_cpu(resp->info.year); 1033 + break; 1034 + case BATTMGR_BAT_STATUS: 1035 + if (payload_len != sizeof(resp->status)) { 1036 + dev_warn(battmgr->dev, 1037 + "invalid payload length for battery status request: %zd\n", 1038 + payload_len); 1039 + battmgr->error = -ENODATA; 1040 + return; 1041 + } 1042 + 1043 + state = le32_to_cpu(resp->status.battery_state); 1044 + if (state & BIT(0)) 1045 + battmgr->status.status = POWER_SUPPLY_STATUS_DISCHARGING; 1046 + else if (state & BIT(1)) 1047 + battmgr->status.status = POWER_SUPPLY_STATUS_CHARGING; 1048 + else 1049 + battmgr->status.status = POWER_SUPPLY_STATUS_NOT_CHARGING; 1050 + 1051 + battmgr->status.capacity = le32_to_cpu(resp->status.capacity) * 1000; 1052 + battmgr->status.power_now = le32_to_cpu(resp->status.rate) * 1000; 1053 + battmgr->status.voltage_now = le32_to_cpu(resp->status.battery_voltage) * 1000; 1054 + battmgr->status.temperature = qcom_battmgr_sc8280xp_convert_temp(le32_to_cpu(resp->status.temperature)); 1055 + 1056 + source = le32_to_cpu(resp->status.charging_source); 1057 + battmgr->ac.online = source == BATTMGR_CHARGING_SOURCE_AC; 1058 + battmgr->usb.online = source == BATTMGR_CHARGING_SOURCE_USB; 1059 + battmgr->wireless.online = source == BATTMGR_CHARGING_SOURCE_WIRELESS; 1060 + break; 1061 + case BATTMGR_BAT_DISCHARGE_TIME: 1062 + battmgr->status.discharge_time = le32_to_cpu(resp->time); 1063 + break; 1064 + case BATTMGR_BAT_CHARGE_TIME: 1065 + battmgr->status.charge_time = le32_to_cpu(resp->time); 1066 + break; 1067 + default: 1068 + dev_warn(battmgr->dev, "unknown message %#x\n", opcode); 1069 + break; 1070 + } 1071 + 1072 + complete(&battmgr->ack); 1073 + } 1074 + 1075 + static void qcom_battmgr_sm8350_callback(struct qcom_battmgr *battmgr, 1076 + const struct qcom_battmgr_message *resp, 1077 + size_t len) 1078 + { 1079 + unsigned int property; 1080 + unsigned int opcode = le32_to_cpu(resp->hdr.opcode); 1081 + size_t payload_len = len - sizeof(struct pmic_glink_hdr); 1082 + unsigned int val; 1083 + 1084 + if (payload_len < sizeof(__le32)) { 1085 + dev_warn(battmgr->dev, "invalid payload length for %#x: %zd\n", 1086 + opcode, len); 1087 + return; 1088 + } 1089 + 1090 + switch (opcode) { 1091 + case BATTMGR_BAT_PROPERTY_GET: 1092 + property = le32_to_cpu(resp->intval.property); 1093 + if (property == BATT_MODEL_NAME) { 1094 + if (payload_len != sizeof(resp->strval)) { 1095 + dev_warn(battmgr->dev, 1096 + "invalid payload length for BATT_MODEL_NAME request: %zd\n", 1097 + payload_len); 1098 + battmgr->error = -ENODATA; 1099 + return; 1100 + } 1101 + } else { 1102 + if (payload_len != sizeof(resp->intval)) { 1103 + dev_warn(battmgr->dev, 1104 + "invalid payload length for %#x request: %zd\n", 1105 + property, payload_len); 1106 + battmgr->error = -ENODATA; 1107 + return; 1108 + } 1109 + 1110 + battmgr->error = le32_to_cpu(resp->intval.result); 1111 + if (battmgr->error) 1112 + goto out_complete; 1113 + } 1114 + 1115 + switch (property) { 1116 + case BATT_STATUS: 1117 + battmgr->status.status = le32_to_cpu(resp->intval.value); 1118 + break; 1119 + case BATT_HEALTH: 1120 + battmgr->status.health = le32_to_cpu(resp->intval.value); 1121 + break; 1122 + case BATT_PRESENT: 1123 + battmgr->info.present = le32_to_cpu(resp->intval.value); 1124 + break; 1125 + case BATT_CHG_TYPE: 1126 + battmgr->info.charge_type = le32_to_cpu(resp->intval.value); 1127 + break; 1128 + case BATT_CAPACITY: 1129 + battmgr->status.percent = le32_to_cpu(resp->intval.value); 1130 + do_div(battmgr->status.percent, 100); 1131 + break; 1132 + case BATT_VOLT_OCV: 1133 + battmgr->status.voltage_ocv = le32_to_cpu(resp->intval.value); 1134 + break; 1135 + case BATT_VOLT_NOW: 1136 + battmgr->status.voltage_now = le32_to_cpu(resp->intval.value); 1137 + break; 1138 + case BATT_VOLT_MAX: 1139 + battmgr->info.voltage_max = le32_to_cpu(resp->intval.value); 1140 + break; 1141 + case BATT_CURR_NOW: 1142 + battmgr->status.current_now = le32_to_cpu(resp->intval.value); 1143 + break; 1144 + case BATT_TEMP: 1145 + val = le32_to_cpu(resp->intval.value); 1146 + battmgr->status.temperature = DIV_ROUND_CLOSEST(val, 10); 1147 + break; 1148 + case BATT_TECHNOLOGY: 1149 + battmgr->info.technology = le32_to_cpu(resp->intval.value); 1150 + break; 1151 + case BATT_CHG_COUNTER: 1152 + battmgr->info.charge_count = le32_to_cpu(resp->intval.value); 1153 + break; 1154 + case BATT_CYCLE_COUNT: 1155 + battmgr->info.cycle_count = le32_to_cpu(resp->intval.value); 1156 + break; 1157 + case BATT_CHG_FULL_DESIGN: 1158 + battmgr->info.design_capacity = le32_to_cpu(resp->intval.value); 1159 + break; 1160 + case BATT_CHG_FULL: 1161 + battmgr->info.last_full_capacity = le32_to_cpu(resp->intval.value); 1162 + break; 1163 + case BATT_MODEL_NAME: 1164 + strscpy(battmgr->info.model_number, resp->strval.model, BATTMGR_STRING_LEN); 1165 + break; 1166 + case BATT_TTF_AVG: 1167 + battmgr->status.charge_time = le32_to_cpu(resp->intval.value); 1168 + break; 1169 + case BATT_TTE_AVG: 1170 + battmgr->status.discharge_time = le32_to_cpu(resp->intval.value); 1171 + break; 1172 + case BATT_POWER_NOW: 1173 + battmgr->status.power_now = le32_to_cpu(resp->intval.value); 1174 + break; 1175 + default: 1176 + dev_warn(battmgr->dev, "unknown property %#x\n", property); 1177 + break; 1178 + } 1179 + break; 1180 + case BATTMGR_USB_PROPERTY_GET: 1181 + property = le32_to_cpu(resp->intval.property); 1182 + if (payload_len != sizeof(resp->intval)) { 1183 + dev_warn(battmgr->dev, 1184 + "invalid payload length for %#x request: %zd\n", 1185 + property, payload_len); 1186 + battmgr->error = -ENODATA; 1187 + return; 1188 + } 1189 + 1190 + battmgr->error = le32_to_cpu(resp->intval.result); 1191 + if (battmgr->error) 1192 + goto out_complete; 1193 + 1194 + switch (property) { 1195 + case USB_ONLINE: 1196 + battmgr->usb.online = le32_to_cpu(resp->intval.value); 1197 + break; 1198 + case USB_VOLT_NOW: 1199 + battmgr->usb.voltage_now = le32_to_cpu(resp->intval.value); 1200 + break; 1201 + case USB_VOLT_MAX: 1202 + battmgr->usb.voltage_max = le32_to_cpu(resp->intval.value); 1203 + break; 1204 + case USB_CURR_NOW: 1205 + battmgr->usb.current_now = le32_to_cpu(resp->intval.value); 1206 + break; 1207 + case USB_CURR_MAX: 1208 + battmgr->usb.current_max = le32_to_cpu(resp->intval.value); 1209 + break; 1210 + case USB_INPUT_CURR_LIMIT: 1211 + battmgr->usb.current_limit = le32_to_cpu(resp->intval.value); 1212 + break; 1213 + case USB_TYPE: 1214 + battmgr->usb.usb_type = le32_to_cpu(resp->intval.value); 1215 + break; 1216 + default: 1217 + dev_warn(battmgr->dev, "unknown property %#x\n", property); 1218 + break; 1219 + } 1220 + break; 1221 + case BATTMGR_WLS_PROPERTY_GET: 1222 + property = le32_to_cpu(resp->intval.property); 1223 + if (payload_len != sizeof(resp->intval)) { 1224 + dev_warn(battmgr->dev, 1225 + "invalid payload length for %#x request: %zd\n", 1226 + property, payload_len); 1227 + battmgr->error = -ENODATA; 1228 + return; 1229 + } 1230 + 1231 + battmgr->error = le32_to_cpu(resp->intval.result); 1232 + if (battmgr->error) 1233 + goto out_complete; 1234 + 1235 + switch (property) { 1236 + case WLS_ONLINE: 1237 + battmgr->wireless.online = le32_to_cpu(resp->intval.value); 1238 + break; 1239 + case WLS_VOLT_NOW: 1240 + battmgr->wireless.voltage_now = le32_to_cpu(resp->intval.value); 1241 + break; 1242 + case WLS_VOLT_MAX: 1243 + battmgr->wireless.voltage_max = le32_to_cpu(resp->intval.value); 1244 + break; 1245 + case WLS_CURR_NOW: 1246 + battmgr->wireless.current_now = le32_to_cpu(resp->intval.value); 1247 + break; 1248 + case WLS_CURR_MAX: 1249 + battmgr->wireless.current_max = le32_to_cpu(resp->intval.value); 1250 + break; 1251 + default: 1252 + dev_warn(battmgr->dev, "unknown property %#x\n", property); 1253 + break; 1254 + } 1255 + break; 1256 + case BATTMGR_REQUEST_NOTIFICATION: 1257 + battmgr->error = 0; 1258 + break; 1259 + default: 1260 + dev_warn(battmgr->dev, "unknown message %#x\n", opcode); 1261 + break; 1262 + } 1263 + 1264 + out_complete: 1265 + complete(&battmgr->ack); 1266 + } 1267 + 1268 + static void qcom_battmgr_callback(const void *data, size_t len, void *priv) 1269 + { 1270 + const struct pmic_glink_hdr *hdr = data; 1271 + struct qcom_battmgr *battmgr = priv; 1272 + unsigned int opcode = le32_to_cpu(hdr->opcode); 1273 + 1274 + if (opcode == BATTMGR_NOTIFICATION) 1275 + qcom_battmgr_notification(battmgr, data, len); 1276 + else if (battmgr->variant == QCOM_BATTMGR_SC8280XP) 1277 + qcom_battmgr_sc8280xp_callback(battmgr, data, len); 1278 + else 1279 + qcom_battmgr_sm8350_callback(battmgr, data, len); 1280 + } 1281 + 1282 + static void qcom_battmgr_enable_worker(struct work_struct *work) 1283 + { 1284 + struct qcom_battmgr *battmgr = container_of(work, struct qcom_battmgr, enable_work); 1285 + struct qcom_battmgr_enable_request req = { 1286 + .hdr.owner = PMIC_GLINK_OWNER_BATTMGR, 1287 + .hdr.type = PMIC_GLINK_NOTIFY, 1288 + .hdr.opcode = BATTMGR_REQUEST_NOTIFICATION, 1289 + }; 1290 + int ret; 1291 + 1292 + ret = qcom_battmgr_request(battmgr, &req, sizeof(req)); 1293 + if (ret) 1294 + dev_err(battmgr->dev, "failed to request power notifications\n"); 1295 + } 1296 + 1297 + static void qcom_battmgr_pdr_notify(void *priv, int state) 1298 + { 1299 + struct qcom_battmgr *battmgr = priv; 1300 + 1301 + if (state == SERVREG_SERVICE_STATE_UP) { 1302 + battmgr->service_up = true; 1303 + schedule_work(&battmgr->enable_work); 1304 + } else { 1305 + battmgr->service_up = false; 1306 + } 1307 + } 1308 + 1309 + static const struct of_device_id qcom_battmgr_of_variants[] = { 1310 + { .compatible = "qcom,sc8180x-pmic-glink", .data = (void *)QCOM_BATTMGR_SC8280XP }, 1311 + { .compatible = "qcom,sc8280xp-pmic-glink", .data = (void *)QCOM_BATTMGR_SC8280XP }, 1312 + /* Unmatched devices falls back to QCOM_BATTMGR_SM8350 */ 1313 + {} 1314 + }; 1315 + 1316 + static char *qcom_battmgr_battery[] = { "battery" }; 1317 + 1318 + static int qcom_battmgr_probe(struct auxiliary_device *adev, 1319 + const struct auxiliary_device_id *id) 1320 + { 1321 + struct power_supply_config psy_cfg_supply = {}; 1322 + struct power_supply_config psy_cfg = {}; 1323 + const struct of_device_id *match; 1324 + struct qcom_battmgr *battmgr; 1325 + struct device *dev = &adev->dev; 1326 + 1327 + battmgr = devm_kzalloc(dev, sizeof(*battmgr), GFP_KERNEL); 1328 + if (!battmgr) 1329 + return -ENOMEM; 1330 + 1331 + battmgr->dev = dev; 1332 + 1333 + psy_cfg.drv_data = battmgr; 1334 + psy_cfg.of_node = adev->dev.of_node; 1335 + 1336 + psy_cfg_supply.drv_data = battmgr; 1337 + psy_cfg_supply.of_node = adev->dev.of_node; 1338 + psy_cfg_supply.supplied_to = qcom_battmgr_battery; 1339 + psy_cfg_supply.num_supplicants = 1; 1340 + 1341 + INIT_WORK(&battmgr->enable_work, qcom_battmgr_enable_worker); 1342 + mutex_init(&battmgr->lock); 1343 + init_completion(&battmgr->ack); 1344 + 1345 + match = of_match_device(qcom_battmgr_of_variants, dev->parent); 1346 + if (match) 1347 + battmgr->variant = (unsigned long)match->data; 1348 + else 1349 + battmgr->variant = QCOM_BATTMGR_SM8350; 1350 + 1351 + if (battmgr->variant == QCOM_BATTMGR_SC8280XP) { 1352 + battmgr->bat_psy = devm_power_supply_register(dev, &sc8280xp_bat_psy_desc, &psy_cfg); 1353 + if (IS_ERR(battmgr->bat_psy)) 1354 + return dev_err_probe(dev, PTR_ERR(battmgr->bat_psy), 1355 + "failed to register battery power supply\n"); 1356 + 1357 + battmgr->ac_psy = devm_power_supply_register(dev, &sc8280xp_ac_psy_desc, &psy_cfg_supply); 1358 + if (IS_ERR(battmgr->ac_psy)) 1359 + return dev_err_probe(dev, PTR_ERR(battmgr->ac_psy), 1360 + "failed to register AC power supply\n"); 1361 + 1362 + battmgr->usb_psy = devm_power_supply_register(dev, &sc8280xp_usb_psy_desc, &psy_cfg_supply); 1363 + if (IS_ERR(battmgr->usb_psy)) 1364 + return dev_err_probe(dev, PTR_ERR(battmgr->usb_psy), 1365 + "failed to register USB power supply\n"); 1366 + 1367 + battmgr->wls_psy = devm_power_supply_register(dev, &sc8280xp_wls_psy_desc, &psy_cfg_supply); 1368 + if (IS_ERR(battmgr->wls_psy)) 1369 + return dev_err_probe(dev, PTR_ERR(battmgr->wls_psy), 1370 + "failed to register wireless charing power supply\n"); 1371 + } else { 1372 + battmgr->bat_psy = devm_power_supply_register(dev, &sm8350_bat_psy_desc, &psy_cfg); 1373 + if (IS_ERR(battmgr->bat_psy)) 1374 + return dev_err_probe(dev, PTR_ERR(battmgr->bat_psy), 1375 + "failed to register battery power supply\n"); 1376 + 1377 + battmgr->usb_psy = devm_power_supply_register(dev, &sm8350_usb_psy_desc, &psy_cfg_supply); 1378 + if (IS_ERR(battmgr->usb_psy)) 1379 + return dev_err_probe(dev, PTR_ERR(battmgr->usb_psy), 1380 + "failed to register USB power supply\n"); 1381 + 1382 + battmgr->wls_psy = devm_power_supply_register(dev, &sm8350_wls_psy_desc, &psy_cfg_supply); 1383 + if (IS_ERR(battmgr->wls_psy)) 1384 + return dev_err_probe(dev, PTR_ERR(battmgr->wls_psy), 1385 + "failed to register wireless charing power supply\n"); 1386 + } 1387 + 1388 + battmgr->client = devm_pmic_glink_register_client(dev, 1389 + PMIC_GLINK_OWNER_BATTMGR, 1390 + qcom_battmgr_callback, 1391 + qcom_battmgr_pdr_notify, 1392 + battmgr); 1393 + return PTR_ERR_OR_ZERO(battmgr->client); 1394 + } 1395 + 1396 + static const struct auxiliary_device_id qcom_battmgr_id_table[] = { 1397 + { .name = "pmic_glink.power-supply", }, 1398 + {}, 1399 + }; 1400 + MODULE_DEVICE_TABLE(auxiliary, qcom_battmgr_id_table); 1401 + 1402 + static struct auxiliary_driver qcom_battmgr_driver = { 1403 + .name = "pmic_glink_power_supply", 1404 + .probe = qcom_battmgr_probe, 1405 + .id_table = qcom_battmgr_id_table, 1406 + }; 1407 + 1408 + module_auxiliary_driver(qcom_battmgr_driver); 1409 + 1410 + MODULE_DESCRIPTION("Qualcomm PMIC GLINK battery manager driver"); 1411 + MODULE_LICENSE("GPL");
+1 -1
drivers/remoteproc/qcom_q6v5_mss.c
··· 34 34 #include "qcom_pil_info.h" 35 35 #include "qcom_q6v5.h" 36 36 37 - #include <linux/qcom_scm.h> 37 + #include <linux/firmware/qcom/qcom_scm.h> 38 38 39 39 #define MPSS_CRASH_REASON_SMEM 421 40 40
+1 -1
drivers/remoteproc/qcom_q6v5_pas.c
··· 18 18 #include <linux/platform_device.h> 19 19 #include <linux/pm_domain.h> 20 20 #include <linux/pm_runtime.h> 21 - #include <linux/qcom_scm.h> 21 + #include <linux/firmware/qcom/qcom_scm.h> 22 22 #include <linux/regulator/consumer.h> 23 23 #include <linux/remoteproc.h> 24 24 #include <linux/soc/qcom/mdt_loader.h>
+1 -1
drivers/remoteproc/qcom_wcnss.c
··· 19 19 #include <linux/platform_device.h> 20 20 #include <linux/pm_domain.h> 21 21 #include <linux/pm_runtime.h> 22 - #include <linux/qcom_scm.h> 22 + #include <linux/firmware/qcom/qcom_scm.h> 23 23 #include <linux/regulator/consumer.h> 24 24 #include <linux/remoteproc.h> 25 25 #include <linux/soc/qcom/mdt_loader.h>
+2
drivers/soc/Kconfig
··· 16 16 source "drivers/soc/loongson/Kconfig" 17 17 source "drivers/soc/mediatek/Kconfig" 18 18 source "drivers/soc/microchip/Kconfig" 19 + source "drivers/soc/nuvoton/Kconfig" 19 20 source "drivers/soc/pxa/Kconfig" 20 21 source "drivers/soc/qcom/Kconfig" 21 22 source "drivers/soc/renesas/Kconfig" 22 23 source "drivers/soc/rockchip/Kconfig" 23 24 source "drivers/soc/samsung/Kconfig" 24 25 source "drivers/soc/sifive/Kconfig" 26 + source "drivers/soc/starfive/Kconfig" 25 27 source "drivers/soc/sunxi/Kconfig" 26 28 source "drivers/soc/tegra/Kconfig" 27 29 source "drivers/soc/ti/Kconfig"
+3 -1
drivers/soc/Makefile
··· 21 21 obj-y += loongson/ 22 22 obj-y += mediatek/ 23 23 obj-y += microchip/ 24 + obj-y += nuvoton/ 24 25 obj-y += pxa/ 25 26 obj-y += amlogic/ 26 27 obj-y += qcom/ 27 28 obj-y += renesas/ 28 29 obj-y += rockchip/ 29 30 obj-$(CONFIG_SOC_SAMSUNG) += samsung/ 30 - obj-$(CONFIG_SOC_SIFIVE) += sifive/ 31 + obj-y += sifive/ 32 + obj-$(CONFIG_SOC_STARFIVE) += starfive/ 31 33 obj-y += sunxi/ 32 34 obj-$(CONFIG_ARCH_TEGRA) += tegra/ 33 35 obj-y += ti/
+17
drivers/soc/amlogic/meson-ee-pwrc.c
··· 46 46 #define HHI_NANOQ_MEM_PD_REG1 (0x47 << 2) 47 47 #define HHI_VPU_MEM_PD_REG2 (0x4d << 2) 48 48 49 + #define G12A_HHI_NANOQ_MEM_PD_REG0 (0x43 << 2) 50 + #define G12A_HHI_NANOQ_MEM_PD_REG1 (0x44 << 2) 51 + 49 52 struct meson_ee_pwrc; 50 53 struct meson_ee_pwrc_domain; 51 54 ··· 108 105 static struct meson_ee_pwrc_top_domain sm1_pwrc_usb = SM1_EE_PD(17); 109 106 static struct meson_ee_pwrc_top_domain sm1_pwrc_pci = SM1_EE_PD(18); 110 107 static struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19); 108 + 109 + static struct meson_ee_pwrc_top_domain g12a_pwrc_nna = { 110 + .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0, 111 + .sleep_mask = BIT(16) | BIT(17), 112 + .iso_reg = GX_AO_RTI_GEN_PWR_ISO0, 113 + .iso_mask = BIT(16) | BIT(17), 114 + }; 111 115 112 116 /* Memory PD Domains */ 113 117 ··· 227 217 { HHI_AUDIO_MEM_PD_REG0, GENMASK(27, 26) }, 228 218 }; 229 219 220 + static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_nna[] = { 221 + { G12A_HHI_NANOQ_MEM_PD_REG0, GENMASK(31, 0) }, 222 + { G12A_HHI_NANOQ_MEM_PD_REG1, GENMASK(23, 0) }, 223 + }; 224 + 230 225 #define VPU_PD(__name, __top_pd, __mem, __is_pwr_off, __resets, __clks) \ 231 226 { \ 232 227 .name = __name, \ ··· 268 253 [PWRC_G12A_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, g12a_pwrc_mem_vpu, 269 254 pwrc_ee_is_powered_off, 11, 2), 270 255 [PWRC_G12A_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth), 256 + [PWRC_G12A_NNA_ID] = TOP_PD("NNA", &g12a_pwrc_nna, g12a_pwrc_mem_nna, 257 + pwrc_ee_is_powered_off), 271 258 }; 272 259 273 260 static struct meson_ee_pwrc_domain_desc gxbb_pwrc_domains[] = {
+7 -4
drivers/soc/apple/apple-pmgr-pwrstate.c
··· 116 116 static int apple_pmgr_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) 117 117 { 118 118 struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); 119 + unsigned long flags; 119 120 120 - mutex_lock(&ps->genpd.mlock); 121 + spin_lock_irqsave(&ps->genpd.slock, flags); 121 122 122 123 if (ps->genpd.status == GENPD_STATE_OFF) 123 124 dev_err(ps->dev, "PS 0x%x: asserting RESET while powered down\n", ps->offset); ··· 130 129 regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, 131 130 APPLE_PMGR_RESET); 132 131 133 - mutex_unlock(&ps->genpd.mlock); 132 + spin_unlock_irqrestore(&ps->genpd.slock, flags); 134 133 135 134 return 0; 136 135 } ··· 138 137 static int apple_pmgr_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) 139 138 { 140 139 struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); 140 + unsigned long flags; 141 141 142 - mutex_lock(&ps->genpd.mlock); 142 + spin_lock_irqsave(&ps->genpd.slock, flags); 143 143 144 144 dev_dbg(ps->dev, "PS 0x%x: deassert reset\n", ps->offset); 145 145 regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, 0); ··· 149 147 if (ps->genpd.status == GENPD_STATE_OFF) 150 148 dev_err(ps->dev, "PS 0x%x: RESET was deasserted while powered down\n", ps->offset); 151 149 152 - mutex_unlock(&ps->genpd.mlock); 150 + spin_unlock_irqrestore(&ps->genpd.slock, flags); 153 151 154 152 return 0; 155 153 } ··· 224 222 return ret; 225 223 } 226 224 225 + ps->genpd.flags |= GENPD_FLAG_IRQ_SAFE; 227 226 ps->genpd.name = name; 228 227 ps->genpd.power_on = apple_pmgr_ps_power_on; 229 228 ps->genpd.power_off = apple_pmgr_ps_power_off;
+93
drivers/soc/apple/rtkit-crashlog.c
··· 13 13 #define APPLE_RTKIT_CRASHLOG_VERSION FOURCC('C', 'v', 'e', 'r') 14 14 #define APPLE_RTKIT_CRASHLOG_MBOX FOURCC('C', 'm', 'b', 'x') 15 15 #define APPLE_RTKIT_CRASHLOG_TIME FOURCC('C', 't', 'i', 'm') 16 + #define APPLE_RTKIT_CRASHLOG_REGS FOURCC('C', 'r', 'g', '8') 17 + 18 + /* For COMPILE_TEST on non-ARM64 architectures */ 19 + #ifndef PSR_MODE_EL0t 20 + #define PSR_MODE_EL0t 0x00000000 21 + #define PSR_MODE_EL1t 0x00000004 22 + #define PSR_MODE_EL1h 0x00000005 23 + #define PSR_MODE_EL2t 0x00000008 24 + #define PSR_MODE_EL2h 0x00000009 25 + #define PSR_MODE_MASK 0x0000000f 26 + #endif 16 27 17 28 struct apple_rtkit_crashlog_header { 18 29 u32 fourcc; ··· 41 30 u8 _unk[4]; 42 31 }; 43 32 static_assert(sizeof(struct apple_rtkit_crashlog_mbox_entry) == 0x18); 33 + 34 + struct apple_rtkit_crashlog_regs { 35 + u32 unk_0; 36 + u32 unk_4; 37 + u64 regs[31]; 38 + u64 sp; 39 + u64 pc; 40 + u64 psr; 41 + u64 cpacr; 42 + u64 fpsr; 43 + u64 fpcr; 44 + u64 unk[64]; 45 + u64 far; 46 + u64 unk_X; 47 + u64 esr; 48 + u64 unk_Z; 49 + } __packed; 50 + static_assert(sizeof(struct apple_rtkit_crashlog_regs) == 0x350); 44 51 45 52 static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr, 46 53 size_t size) ··· 123 94 } 124 95 } 125 96 97 + static void apple_rtkit_crashlog_dump_regs(struct apple_rtkit *rtk, u8 *bfr, 98 + size_t size) 99 + { 100 + struct apple_rtkit_crashlog_regs *regs; 101 + const char *el; 102 + int i; 103 + 104 + if (size < sizeof(*regs)) { 105 + dev_warn(rtk->dev, "RTKit: Regs section too small: 0x%zx", size); 106 + return; 107 + } 108 + 109 + regs = (struct apple_rtkit_crashlog_regs *)bfr; 110 + 111 + switch (regs->psr & PSR_MODE_MASK) { 112 + case PSR_MODE_EL0t: 113 + el = "EL0t"; 114 + break; 115 + case PSR_MODE_EL1t: 116 + el = "EL1t"; 117 + break; 118 + case PSR_MODE_EL1h: 119 + el = "EL1h"; 120 + break; 121 + case PSR_MODE_EL2t: 122 + el = "EL2t"; 123 + break; 124 + case PSR_MODE_EL2h: 125 + el = "EL2h"; 126 + break; 127 + default: 128 + el = "unknown"; 129 + break; 130 + } 131 + 132 + dev_warn(rtk->dev, "RTKit: Exception dump:"); 133 + dev_warn(rtk->dev, " == Exception taken from %s ==", el); 134 + dev_warn(rtk->dev, " PSR = 0x%llx", regs->psr); 135 + dev_warn(rtk->dev, " PC = 0x%llx\n", regs->pc); 136 + dev_warn(rtk->dev, " ESR = 0x%llx\n", regs->esr); 137 + dev_warn(rtk->dev, " FAR = 0x%llx\n", regs->far); 138 + dev_warn(rtk->dev, " SP = 0x%llx\n", regs->sp); 139 + dev_warn(rtk->dev, "\n"); 140 + 141 + for (i = 0; i < 31; i += 4) { 142 + if (i < 28) 143 + dev_warn(rtk->dev, 144 + " x%02d-x%02d = %016llx %016llx %016llx %016llx\n", 145 + i, i + 3, 146 + regs->regs[i], regs->regs[i + 1], 147 + regs->regs[i + 2], regs->regs[i + 3]); 148 + else 149 + dev_warn(rtk->dev, 150 + " x%02d-x%02d = %016llx %016llx %016llx\n", i, i + 3, 151 + regs->regs[i], regs->regs[i + 1], regs->regs[i + 2]); 152 + } 153 + 154 + dev_warn(rtk->dev, "\n"); 155 + } 156 + 126 157 void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size) 127 158 { 128 159 size_t offset; ··· 227 138 break; 228 139 case APPLE_RTKIT_CRASHLOG_TIME: 229 140 apple_rtkit_crashlog_dump_time(rtk, bfr + offset + 16, 141 + section_size); 142 + break; 143 + case APPLE_RTKIT_CRASHLOG_REGS: 144 + apple_rtkit_crashlog_dump_regs(rtk, bfr + offset + 16, 230 145 section_size); 231 146 break; 232 147 default:
+31 -5
drivers/soc/apple/rtkit.c
··· 9 9 enum { 10 10 APPLE_RTKIT_PWR_STATE_OFF = 0x00, /* power off, cannot be restarted */ 11 11 APPLE_RTKIT_PWR_STATE_SLEEP = 0x01, /* sleeping, can be restarted */ 12 + APPLE_RTKIT_PWR_STATE_IDLE = 0x201, /* sleeping, retain state */ 12 13 APPLE_RTKIT_PWR_STATE_QUIESCED = 0x10, /* running but no communication */ 13 14 APPLE_RTKIT_PWR_STATE_ON = 0x20, /* normal operating state */ 14 15 }; ··· 699 698 return 0; 700 699 } 701 700 702 - static struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie, 701 + struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie, 703 702 const char *mbox_name, int mbox_idx, 704 703 const struct apple_rtkit_ops *ops) 705 704 { ··· 751 750 kfree(rtk); 752 751 return ERR_PTR(ret); 753 752 } 753 + EXPORT_SYMBOL_GPL(apple_rtkit_init); 754 754 755 755 static int apple_rtkit_wait_for_completion(struct completion *c) 756 756 { ··· 883 881 } 884 882 EXPORT_SYMBOL_GPL(apple_rtkit_shutdown); 885 883 884 + int apple_rtkit_idle(struct apple_rtkit *rtk) 885 + { 886 + int ret; 887 + 888 + /* if OFF is used here the co-processor will not wake up again */ 889 + ret = apple_rtkit_set_ap_power_state(rtk, 890 + APPLE_RTKIT_PWR_STATE_IDLE); 891 + if (ret) 892 + return ret; 893 + 894 + ret = apple_rtkit_set_iop_power_state(rtk, APPLE_RTKIT_PWR_STATE_IDLE); 895 + if (ret) 896 + return ret; 897 + 898 + rtk->iop_power_state = APPLE_RTKIT_PWR_STATE_IDLE; 899 + rtk->ap_power_state = APPLE_RTKIT_PWR_STATE_IDLE; 900 + return 0; 901 + } 902 + EXPORT_SYMBOL_GPL(apple_rtkit_idle); 903 + 886 904 int apple_rtkit_quiesce(struct apple_rtkit *rtk) 887 905 { 888 906 int ret; ··· 948 926 } 949 927 EXPORT_SYMBOL_GPL(apple_rtkit_wake); 950 928 951 - static void apple_rtkit_free(void *data) 929 + void apple_rtkit_free(struct apple_rtkit *rtk) 952 930 { 953 - struct apple_rtkit *rtk = data; 954 - 955 931 mbox_free_channel(rtk->mbox_chan); 956 932 destroy_workqueue(rtk->wq); 957 933 ··· 959 939 960 940 kfree(rtk->syslog_msg_buffer); 961 941 kfree(rtk); 942 + } 943 + EXPORT_SYMBOL_GPL(apple_rtkit_free); 944 + 945 + static void apple_rtkit_free_wrapper(void *data) 946 + { 947 + apple_rtkit_free(data); 962 948 } 963 949 964 950 struct apple_rtkit *devm_apple_rtkit_init(struct device *dev, void *cookie, ··· 978 952 if (IS_ERR(rtk)) 979 953 return rtk; 980 954 981 - ret = devm_add_action_or_reset(dev, apple_rtkit_free, rtk); 955 + ret = devm_add_action_or_reset(dev, apple_rtkit_free_wrapper, rtk); 982 956 if (ret) 983 957 return ERR_PTR(ret); 984 958
-6
drivers/soc/bcm/bcm2835-power.c
··· 701 701 return ret; 702 702 } 703 703 704 - static int bcm2835_power_remove(struct platform_device *pdev) 705 - { 706 - return 0; 707 - } 708 - 709 704 static struct platform_driver bcm2835_power_driver = { 710 705 .probe = bcm2835_power_probe, 711 - .remove = bcm2835_power_remove, 712 706 .driver = { 713 707 .name = "bcm2835-power", 714 708 },
+11
drivers/soc/imx/Kconfig
··· 28 28 help 29 29 If you say yes here, you get support for the NXP i.MX9 family 30 30 31 + config IMX8M_BLK_CTRL 32 + bool 33 + default SOC_IMX8M && IMX_GPCV2_PM_DOMAINS 34 + depends on PM_GENERIC_DOMAINS 35 + depends on COMMON_CLK 36 + 37 + config IMX9_BLK_CTRL 38 + bool 39 + default SOC_IMX9 && IMX_GPCV2_PM_DOMAINS 40 + depends on PM_GENERIC_DOMAINS 41 + 31 42 endmenu
+3 -3
drivers/soc/imx/Makefile
··· 5 5 obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o 6 6 obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o 7 7 obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o 8 - obj-$(CONFIG_SOC_IMX8M) += imx8m-blk-ctrl.o 9 - obj-$(CONFIG_SOC_IMX8M) += imx8mp-blk-ctrl.o 8 + obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o 9 + obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8mp-blk-ctrl.o 10 10 obj-$(CONFIG_SOC_IMX9) += imx93-src.o imx93-pd.o 11 - obj-$(CONFIG_SOC_IMX9) += imx93-blk-ctrl.o 11 + obj-$(CONFIG_IMX9_BLK_CTRL) += imx93-blk-ctrl.o
+21 -6
drivers/soc/imx/imx8m-blk-ctrl.c
··· 4 4 * Copyright 2021 Pengutronix, Lucas Stach <kernel@pengutronix.de> 5 5 */ 6 6 7 + #include <linux/bitfield.h> 7 8 #include <linux/device.h> 8 9 #include <linux/interconnect.h> 9 10 #include <linux/module.h> ··· 655 654 .num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data), 656 655 }; 657 656 657 + #define LCDIF_ARCACHE_CTRL 0x4c 658 + #define LCDIF_1_RD_HURRY GENMASK(15, 13) 659 + #define LCDIF_0_RD_HURRY GENMASK(12, 10) 660 + 658 661 static int imx8mp_media_power_notifier(struct notifier_block *nb, 659 662 unsigned long action, void *data) 660 663 { ··· 672 667 regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8)); 673 668 regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8)); 674 669 675 - /* 676 - * On power up we have no software backchannel to the GPC to 677 - * wait for the ADB handshake to happen, so we just delay for a 678 - * bit. On power down the GPC driver waits for the handshake. 679 - */ 680 - if (action == GENPD_NOTIFY_ON) 670 + if (action == GENPD_NOTIFY_ON) { 671 + /* 672 + * On power up we have no software backchannel to the GPC to 673 + * wait for the ADB handshake to happen, so we just delay for a 674 + * bit. On power down the GPC driver waits for the handshake. 675 + */ 681 676 udelay(5); 677 + 678 + /* 679 + * Set panic read hurry level for both LCDIF interfaces to 680 + * maximum priority to minimize chances of display FIFO 681 + * underflow. 682 + */ 683 + regmap_set_bits(bc->regmap, LCDIF_ARCACHE_CTRL, 684 + FIELD_PREP(LCDIF_1_RD_HURRY, 7) | 685 + FIELD_PREP(LCDIF_0_RD_HURRY, 7)); 686 + } 682 687 683 688 return NOTIFY_OK; 684 689 }
+108
drivers/soc/imx/imx8mp-blk-ctrl.c
··· 4 4 * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de> 5 5 */ 6 6 7 + #include <linux/bitfield.h> 7 8 #include <linux/clk.h> 9 + #include <linux/clk-provider.h> 8 10 #include <linux/device.h> 9 11 #include <linux/interconnect.h> 10 12 #include <linux/module.h> ··· 23 21 #define USB_CLOCK_MODULE_EN BIT(1) 24 22 #define PCIE_PHY_APB_RST BIT(4) 25 23 #define PCIE_PHY_INIT_RST BIT(5) 24 + #define GPR_REG1 0x4 25 + #define PLL_LOCK BIT(13) 26 + #define GPR_REG2 0x8 27 + #define P_PLL_MASK GENMASK(5, 0) 28 + #define M_PLL_MASK GENMASK(15, 6) 29 + #define S_PLL_MASK GENMASK(18, 16) 30 + #define GPR_REG3 0xc 31 + #define PLL_CKE BIT(17) 32 + #define PLL_RST BIT(31) 26 33 27 34 struct imx8mp_blk_ctrl_domain; 28 35 ··· 71 60 72 61 struct imx8mp_blk_ctrl_data { 73 62 int max_reg; 63 + int (*probe) (struct imx8mp_blk_ctrl *bc); 74 64 notifier_fn_t power_notifier_fn; 75 65 void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain); 76 66 void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain); ··· 83 71 to_imx8mp_blk_ctrl_domain(struct generic_pm_domain *genpd) 84 72 { 85 73 return container_of(genpd, struct imx8mp_blk_ctrl_domain, genpd); 74 + } 75 + 76 + struct clk_hsio_pll { 77 + struct clk_hw hw; 78 + struct regmap *regmap; 79 + }; 80 + 81 + static inline struct clk_hsio_pll *to_clk_hsio_pll(struct clk_hw *hw) 82 + { 83 + return container_of(hw, struct clk_hsio_pll, hw); 84 + } 85 + 86 + static int clk_hsio_pll_prepare(struct clk_hw *hw) 87 + { 88 + struct clk_hsio_pll *clk = to_clk_hsio_pll(hw); 89 + u32 val; 90 + 91 + /* set the PLL configuration */ 92 + regmap_update_bits(clk->regmap, GPR_REG2, 93 + P_PLL_MASK | M_PLL_MASK | S_PLL_MASK, 94 + FIELD_PREP(P_PLL_MASK, 12) | 95 + FIELD_PREP(M_PLL_MASK, 800) | 96 + FIELD_PREP(S_PLL_MASK, 4)); 97 + 98 + /* de-assert PLL reset */ 99 + regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST, PLL_RST); 100 + 101 + /* enable PLL */ 102 + regmap_update_bits(clk->regmap, GPR_REG3, PLL_CKE, PLL_CKE); 103 + 104 + return regmap_read_poll_timeout(clk->regmap, GPR_REG1, val, 105 + val & PLL_LOCK, 10, 100); 106 + } 107 + 108 + static void clk_hsio_pll_unprepare(struct clk_hw *hw) 109 + { 110 + struct clk_hsio_pll *clk = to_clk_hsio_pll(hw); 111 + 112 + regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST | PLL_CKE, 0); 113 + } 114 + 115 + static int clk_hsio_pll_is_prepared(struct clk_hw *hw) 116 + { 117 + struct clk_hsio_pll *clk = to_clk_hsio_pll(hw); 118 + 119 + return regmap_test_bits(clk->regmap, GPR_REG1, PLL_LOCK); 120 + } 121 + 122 + static unsigned long clk_hsio_pll_recalc_rate(struct clk_hw *hw, 123 + unsigned long parent_rate) 124 + { 125 + return 100000000; 126 + } 127 + 128 + static const struct clk_ops clk_hsio_pll_ops = { 129 + .prepare = clk_hsio_pll_prepare, 130 + .unprepare = clk_hsio_pll_unprepare, 131 + .is_prepared = clk_hsio_pll_is_prepared, 132 + .recalc_rate = clk_hsio_pll_recalc_rate, 133 + }; 134 + 135 + static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc) 136 + { 137 + struct clk_hsio_pll *clk_hsio_pll; 138 + struct clk_hw *hw; 139 + struct clk_init_data init = {}; 140 + int ret; 141 + 142 + clk_hsio_pll = devm_kzalloc(bc->dev, sizeof(*clk_hsio_pll), GFP_KERNEL); 143 + if (!clk_hsio_pll) 144 + return -ENOMEM; 145 + 146 + init.name = "hsio_pll"; 147 + init.ops = &clk_hsio_pll_ops; 148 + init.parent_names = (const char *[]){"osc_24m"}; 149 + init.num_parents = 1; 150 + 151 + clk_hsio_pll->regmap = bc->regmap; 152 + clk_hsio_pll->hw.init = &init; 153 + 154 + hw = &clk_hsio_pll->hw; 155 + ret = devm_clk_hw_register(bc->dev, hw); 156 + if (ret) 157 + return ret; 158 + 159 + return devm_of_clk_add_hw_provider(bc->dev, of_clk_hw_simple_get, hw); 86 160 } 87 161 88 162 static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc, ··· 285 187 286 188 static const struct imx8mp_blk_ctrl_data imx8mp_hsio_blk_ctl_dev_data = { 287 189 .max_reg = 0x24, 190 + .probe = imx8mp_hsio_blk_ctrl_probe, 288 191 .power_on = imx8mp_hsio_blk_ctrl_power_on, 289 192 .power_off = imx8mp_hsio_blk_ctrl_power_off, 290 193 .power_notifier_fn = imx8mp_hsio_power_notifier, ··· 300 201 #define HDMI_RTX_CLK_CTL3 0x70 301 202 #define HDMI_RTX_CLK_CTL4 0x80 302 203 #define HDMI_TX_CONTROL0 0x200 204 + #define HDMI_LCDIF_NOC_HURRY_MASK GENMASK(14, 12) 303 205 304 206 static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc, 305 207 struct imx8mp_blk_ctrl_domain *domain) ··· 317 217 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11)); 318 218 regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, 319 219 BIT(4) | BIT(5) | BIT(6)); 220 + regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, 221 + FIELD_PREP(HDMI_LCDIF_NOC_HURRY_MASK, 7)); 320 222 break; 321 223 case IMX8MP_HDMIBLK_PD_PAI: 322 224 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17)); ··· 735 633 if (ret) { 736 634 dev_err_probe(dev, ret, "failed to add power notifier\n"); 737 635 goto cleanup_provider; 636 + } 637 + 638 + if (bc_data->probe) { 639 + ret = bc_data->probe(bc); 640 + if (ret) 641 + goto cleanup_provider; 738 642 } 739 643 740 644 dev_set_drvdata(dev, bc);
-1
drivers/soc/imx/imx93-pd.c
··· 164 164 static struct platform_driver imx93_power_domain_driver = { 165 165 .driver = { 166 166 .name = "imx93_power_domain", 167 - .owner = THIS_MODULE, 168 167 .of_match_table = imx93_pd_ids, 169 168 }, 170 169 .probe = imx93_pd_probe,
-1
drivers/soc/imx/imx93-src.c
··· 21 21 static struct platform_driver imx93_src_driver = { 22 22 .driver = { 23 23 .name = "imx93_src", 24 - .owner = THIS_MODULE, 25 24 .of_match_table = imx93_src_ids, 26 25 }, 27 26 .probe = imx93_src_probe,
+6 -1
drivers/soc/mediatek/Kconfig
··· 44 44 on different MediaTek SoCs. The PMIC wrapper is a proprietary 45 45 hardware to connect the PMIC. 46 46 47 + config MTK_REGULATOR_COUPLER 48 + bool "MediaTek SoC Regulator Coupler" if COMPILE_TEST 49 + default ARCH_MEDIATEK 50 + depends on REGULATOR 51 + 47 52 config MTK_SCPSYS 48 53 bool "MediaTek SCPSYS Support" 49 54 default ARCH_MEDIATEK ··· 73 68 tasks in the system. 74 69 75 70 config MTK_MMSYS 76 - bool "MediaTek MMSYS Support" 71 + tristate "MediaTek MMSYS Support" 77 72 default ARCH_MEDIATEK 78 73 depends on HAS_IOMEM 79 74 help
+1
drivers/soc/mediatek/Makefile
··· 3 3 obj-$(CONFIG_MTK_DEVAPC) += mtk-devapc.o 4 4 obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o 5 5 obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o 6 + obj-$(CONFIG_MTK_REGULATOR_COUPLER) += mtk-regulator-coupler.o 6 7 obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o 7 8 obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS) += mtk-pm-domains.o 8 9 obj-$(CONFIG_MTK_MMSYS) += mtk-mmsys.o
+1 -3
drivers/soc/mediatek/mt8186-pm-domains.h
··· 304 304 .ctl_offs = 0x9FC, 305 305 .pwr_sta_offs = 0x16C, 306 306 .pwr_sta2nd_offs = 0x170, 307 - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 308 307 }, 309 308 [MT8186_POWER_DOMAIN_ADSP_INFRA] = { 310 309 .name = "adsp_infra", ··· 311 312 .ctl_offs = 0x9F8, 312 313 .pwr_sta_offs = 0x16C, 313 314 .pwr_sta2nd_offs = 0x170, 314 - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 315 315 }, 316 316 [MT8186_POWER_DOMAIN_ADSP_TOP] = { 317 317 .name = "adsp_top", ··· 330 332 MT8186_TOP_AXI_PROT_EN_3_CLR, 331 333 MT8186_TOP_AXI_PROT_EN_3_STA), 332 334 }, 333 - .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, 335 + .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP, 334 336 }, 335 337 }; 336 338
+149
drivers/soc/mediatek/mt8188-mmsys.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef __SOC_MEDIATEK_MT8188_MMSYS_H 4 + #define __SOC_MEDIATEK_MT8188_MMSYS_H 5 + 6 + #define MT8188_VDO0_OVL_MOUT_EN 0xf14 7 + #define MT8188_MOUT_DISP_OVL0_TO_DISP_RDMA0 BIT(0) 8 + #define MT8188_MOUT_DISP_OVL0_TO_DISP_WDMA0 BIT(1) 9 + #define MT8188_MOUT_DISP_OVL0_TO_DISP_OVL1 BIT(2) 10 + #define MT8188_MOUT_DISP_OVL1_TO_DISP_RDMA1 BIT(4) 11 + #define MT8188_MOUT_DISP_OVL1_TO_DISP_WDMA1 BIT(5) 12 + #define MT8188_MOUT_DISP_OVL1_TO_DISP_OVL0 BIT(6) 13 + 14 + #define MT8188_VDO0_SEL_IN 0xf34 15 + #define MT8188_VDO0_SEL_OUT 0xf38 16 + 17 + #define MT8188_VDO0_DISP_RDMA_SEL 0xf40 18 + #define MT8188_SOUT_DISP_RDMA0_TO_MASK GENMASK(2, 0) 19 + #define MT8188_SOUT_DISP_RDMA0_TO_DISP_COLOR0 (0 << 0) 20 + #define MT8188_SOUT_DISP_RDMA0_TO_DISP_DSI0 (1 << 0) 21 + #define MT8188_SOUT_DISP_RDMA0_TO_DISP_DP_INTF0 (5 << 0) 22 + #define MT8188_SEL_IN_DISP_RDMA0_FROM_MASK GENMASK(8, 8) 23 + #define MT8188_SEL_IN_DISP_RDMA0_FROM_DISP_OVL0 (0 << 8) 24 + #define MT8188_SEL_IN_DISP_RDMA0_FROM_DISP_RSZ0 (1 << 8) 25 + 26 + 27 + #define MT8188_VDO0_DSI0_SEL_IN 0xf44 28 + #define MT8188_SEL_IN_DSI0_FROM_MASK BIT(0) 29 + #define MT8188_SEL_IN_DSI0_FROM_DSC_WRAP0_OUT (0 << 0) 30 + #define MT8188_SEL_IN_DSI0_FROM_DISP_DITHER0 (1 << 0) 31 + 32 + #define MT8188_VDO0_DP_INTF0_SEL_IN 0xf4C 33 + #define MT8188_SEL_IN_DP_INTF0_FROM_MASK GENMASK(2, 0) 34 + #define MT8188_SEL_IN_DP_INTF0_FROM_DSC_WRAP0C1_OUT (0 << 0) 35 + #define MT8188_SEL_IN_DP_INTF0_FROM_VPP_MERGE (1 << 0) 36 + #define MT8188_SEL_IN_DP_INTF0_FROM_DISP_DITHER0 (3 << 0) 37 + 38 + #define MT8188_VDO0_DISP_DITHER0_SEL_OUT 0xf58 39 + #define MT8188_SOUT_DISP_DITHER0_TO_MASK GENMASK(2, 0) 40 + #define MT8188_SOUT_DISP_DITHER0_TO_DSC_WRAP0_IN (0 << 0) 41 + #define MT8188_SOUT_DISP_DITHER0_TO_DSI0 (1 << 0) 42 + #define MT8188_SOUT_DISP_DITHER0_TO_VPP_MERGE0 (6 << 0) 43 + #define MT8188_SOUT_DISP_DITHER0_TO_DP_INTF0 (7 << 0) 44 + 45 + #define MT8188_VDO0_VPP_MERGE_SEL 0xf60 46 + #define MT8188_SEL_IN_VPP_MERGE_FROM_MASK GENMASK(1, 0) 47 + #define MT8188_SEL_IN_VPP_MERGE_FROM_DSC_WRAP0_OUT (0 << 0) 48 + #define MT8188_SEL_IN_VPP_MERGE_FROM_DITHER0_OUT (3 << 0) 49 + 50 + #define MT8188_SOUT_VPP_MERGE_TO_MASK GENMASK(6, 4) 51 + #define MT8188_SOUT_VPP_MERGE_TO_DSI1 (0 << 4) 52 + #define MT8188_SOUT_VPP_MERGE_TO_DP_INTF0 (1 << 4) 53 + #define MT8188_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0 (2 << 4) 54 + #define MT8188_SOUT_VPP_MERGE_TO_DISP_WDMA1 (3 << 4) 55 + #define MT8188_SOUT_VPP_MERGE_TO_DSC_WRAP0_IN (4 << 4) 56 + #define MT8188_SOUT_VPP_MERGE_TO_DISP_WDMA0 (5 << 4) 57 + #define MT8188_SOUT_VPP_MERGE_TO_DSC_WRAP1_IN_MASK GENMASK(11, 11) 58 + #define MT8188_SOUT_VPP_MERGE_TO_DSC_WRAP1_IN (0 << 11) 59 + 60 + #define MT8188_VDO0_DSC_WARP_SEL 0xf64 61 + #define MT8188_SEL_IN_DSC_WRAP0C0_IN_FROM_MASK GENMASK(0, 0) 62 + #define MT8188_SEL_IN_DSC_WRAP0C0_IN_FROM_DISP_DITHER0 (0 << 0) 63 + #define MT8188_SEL_IN_DSC_WRAP0C0_IN_FROM_VPP_MERGE (1 << 0) 64 + #define MT8188_SOUT_DSC_WRAP0_OUT_TO_MASK GENMASK(19, 16) 65 + #define MT8188_SOUT_DSC_WRAP0_OUT_TO_DSI0 BIT(16) 66 + #define MT8188_SOUT_DSC_WRAP0_OUT_TO_SINB_VIRTUAL0 BIT(17) 67 + #define MT8188_SOUT_DSC_WRAP0_OUT_TO_VPP_MERGE BIT(18) 68 + #define MT8188_SOUT_DSC_WRAP0_OUT_TO_DISP_WDMA0 BIT(19) 69 + 70 + static const struct mtk_mmsys_routes mmsys_mt8188_routing_table[] = { 71 + { 72 + DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, 73 + MT8188_VDO0_OVL_MOUT_EN, MT8188_MOUT_DISP_OVL0_TO_DISP_RDMA0, 74 + MT8188_MOUT_DISP_OVL0_TO_DISP_RDMA0 75 + }, { 76 + DDP_COMPONENT_OVL0, DDP_COMPONENT_WDMA0, 77 + MT8188_VDO0_OVL_MOUT_EN, MT8188_MOUT_DISP_OVL0_TO_DISP_WDMA0, 78 + MT8188_MOUT_DISP_OVL0_TO_DISP_WDMA0 79 + }, { 80 + DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, 81 + MT8188_VDO0_DISP_RDMA_SEL, MT8188_SEL_IN_DISP_RDMA0_FROM_MASK, 82 + MT8188_SEL_IN_DISP_RDMA0_FROM_DISP_OVL0 83 + }, { 84 + DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0, 85 + MT8188_VDO0_DSI0_SEL_IN, MT8188_SEL_IN_DSI0_FROM_MASK, 86 + MT8188_SEL_IN_DSI0_FROM_DISP_DITHER0 87 + }, { 88 + DDP_COMPONENT_DITHER0, DDP_COMPONENT_MERGE0, 89 + MT8188_VDO0_VPP_MERGE_SEL, MT8188_SEL_IN_VPP_MERGE_FROM_MASK, 90 + MT8188_SEL_IN_VPP_MERGE_FROM_DITHER0_OUT 91 + }, { 92 + DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSC0, 93 + MT8188_VDO0_DSC_WARP_SEL, 94 + MT8188_SEL_IN_DSC_WRAP0C0_IN_FROM_MASK, 95 + MT8188_SEL_IN_DSC_WRAP0C0_IN_FROM_DISP_DITHER0 96 + }, { 97 + DDP_COMPONENT_DITHER0, DDP_COMPONENT_DP_INTF0, 98 + MT8188_VDO0_DP_INTF0_SEL_IN, MT8188_SEL_IN_DP_INTF0_FROM_MASK, 99 + MT8188_SEL_IN_DP_INTF0_FROM_DISP_DITHER0 100 + }, { 101 + DDP_COMPONENT_DSC0, DDP_COMPONENT_MERGE0, 102 + MT8188_VDO0_VPP_MERGE_SEL, MT8188_SEL_IN_VPP_MERGE_FROM_MASK, 103 + MT8188_SEL_IN_VPP_MERGE_FROM_DSC_WRAP0_OUT 104 + }, { 105 + DDP_COMPONENT_DSC0, DDP_COMPONENT_DSI0, 106 + MT8188_VDO0_DSI0_SEL_IN, MT8188_SEL_IN_DSI0_FROM_MASK, 107 + MT8188_SEL_IN_DSI0_FROM_DSC_WRAP0_OUT 108 + }, { 109 + DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0, 110 + MT8188_VDO0_DISP_RDMA_SEL, MT8188_SOUT_DISP_RDMA0_TO_MASK, 111 + MT8188_SOUT_DISP_RDMA0_TO_DISP_COLOR0 112 + }, { 113 + DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0, 114 + MT8188_VDO0_DISP_DITHER0_SEL_OUT, 115 + MT8188_SOUT_DISP_DITHER0_TO_MASK, 116 + MT8188_SOUT_DISP_DITHER0_TO_DSI0 117 + }, { 118 + DDP_COMPONENT_DITHER0, DDP_COMPONENT_DP_INTF0, 119 + MT8188_VDO0_DISP_DITHER0_SEL_OUT, 120 + MT8188_SOUT_DISP_DITHER0_TO_MASK, 121 + MT8188_SOUT_DISP_DITHER0_TO_DP_INTF0 122 + }, { 123 + DDP_COMPONENT_MERGE0, DDP_COMPONENT_DP_INTF0, 124 + MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK, 125 + MT8188_SOUT_VPP_MERGE_TO_DP_INTF0 126 + }, { 127 + DDP_COMPONENT_MERGE0, DDP_COMPONENT_DPI0, 128 + MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK, 129 + MT8188_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0 130 + }, { 131 + DDP_COMPONENT_MERGE0, DDP_COMPONENT_WDMA0, 132 + MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK, 133 + MT8188_SOUT_VPP_MERGE_TO_DISP_WDMA0 134 + }, { 135 + DDP_COMPONENT_MERGE0, DDP_COMPONENT_DSC0, 136 + MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK, 137 + MT8188_SOUT_VPP_MERGE_TO_DSC_WRAP0_IN 138 + }, { 139 + DDP_COMPONENT_DSC0, DDP_COMPONENT_DSI0, 140 + MT8188_VDO0_DSC_WARP_SEL, MT8188_SOUT_DSC_WRAP0_OUT_TO_MASK, 141 + MT8188_SOUT_DSC_WRAP0_OUT_TO_DSI0 142 + }, { 143 + DDP_COMPONENT_DSC0, DDP_COMPONENT_MERGE0, 144 + MT8188_VDO0_DSC_WARP_SEL, MT8188_SOUT_DSC_WRAP0_OUT_TO_MASK, 145 + MT8188_SOUT_DSC_WRAP0_OUT_TO_VPP_MERGE 146 + }, 147 + }; 148 + 149 + #endif /* __SOC_MEDIATEK_MT8188_MMSYS_H */
+623
drivers/soc/mediatek/mt8188-pm-domains.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2022 MediaTek Inc. 4 + * Author: Garmin Chang <garmin.chang@mediatek.com> 5 + */ 6 + 7 + #ifndef __SOC_MEDIATEK_MT8188_PM_DOMAINS_H 8 + #define __SOC_MEDIATEK_MT8188_PM_DOMAINS_H 9 + 10 + #include "mtk-pm-domains.h" 11 + #include <dt-bindings/power/mediatek,mt8188-power.h> 12 + 13 + /* 14 + * MT8188 power domain support 15 + */ 16 + 17 + static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = { 18 + [MT8188_POWER_DOMAIN_MFG0] = { 19 + .name = "mfg0", 20 + .sta_mask = BIT(1), 21 + .ctl_offs = 0x300, 22 + .pwr_sta_offs = 0x174, 23 + .pwr_sta2nd_offs = 0x178, 24 + .sram_pdn_bits = BIT(8), 25 + .sram_pdn_ack_bits = BIT(12), 26 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, 27 + }, 28 + [MT8188_POWER_DOMAIN_MFG1] = { 29 + .name = "mfg1", 30 + .sta_mask = BIT(2), 31 + .ctl_offs = 0x304, 32 + .pwr_sta_offs = 0x174, 33 + .pwr_sta2nd_offs = 0x178, 34 + .sram_pdn_bits = BIT(8), 35 + .sram_pdn_ack_bits = BIT(12), 36 + .bp_infracfg = { 37 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MFG1_STEP1, 38 + MT8188_TOP_AXI_PROT_EN_SET, 39 + MT8188_TOP_AXI_PROT_EN_CLR, 40 + MT8188_TOP_AXI_PROT_EN_STA), 41 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP2, 42 + MT8188_TOP_AXI_PROT_EN_2_SET, 43 + MT8188_TOP_AXI_PROT_EN_2_CLR, 44 + MT8188_TOP_AXI_PROT_EN_2_STA), 45 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_1_MFG1_STEP3, 46 + MT8188_TOP_AXI_PROT_EN_1_SET, 47 + MT8188_TOP_AXI_PROT_EN_1_CLR, 48 + MT8188_TOP_AXI_PROT_EN_1_STA), 49 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP4, 50 + MT8188_TOP_AXI_PROT_EN_2_SET, 51 + MT8188_TOP_AXI_PROT_EN_2_CLR, 52 + MT8188_TOP_AXI_PROT_EN_2_STA), 53 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MFG1_STEP5, 54 + MT8188_TOP_AXI_PROT_EN_SET, 55 + MT8188_TOP_AXI_PROT_EN_CLR, 56 + MT8188_TOP_AXI_PROT_EN_STA), 57 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1_STEP6, 58 + MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, 59 + MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, 60 + MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA), 61 + }, 62 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, 63 + }, 64 + [MT8188_POWER_DOMAIN_MFG2] = { 65 + .name = "mfg2", 66 + .sta_mask = BIT(3), 67 + .ctl_offs = 0x308, 68 + .pwr_sta_offs = 0x174, 69 + .pwr_sta2nd_offs = 0x178, 70 + .sram_pdn_bits = BIT(8), 71 + .sram_pdn_ack_bits = BIT(12), 72 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 73 + }, 74 + [MT8188_POWER_DOMAIN_MFG3] = { 75 + .name = "mfg3", 76 + .sta_mask = BIT(4), 77 + .ctl_offs = 0x30C, 78 + .pwr_sta_offs = 0x174, 79 + .pwr_sta2nd_offs = 0x178, 80 + .sram_pdn_bits = BIT(8), 81 + .sram_pdn_ack_bits = BIT(12), 82 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 83 + }, 84 + [MT8188_POWER_DOMAIN_MFG4] = { 85 + .name = "mfg4", 86 + .sta_mask = BIT(5), 87 + .ctl_offs = 0x310, 88 + .pwr_sta_offs = 0x174, 89 + .pwr_sta2nd_offs = 0x178, 90 + .sram_pdn_bits = BIT(8), 91 + .sram_pdn_ack_bits = BIT(12), 92 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 93 + }, 94 + [MT8188_POWER_DOMAIN_PEXTP_MAC_P0] = { 95 + .name = "pextp_mac_p0", 96 + .sta_mask = BIT(10), 97 + .ctl_offs = 0x324, 98 + .pwr_sta_offs = 0x174, 99 + .pwr_sta2nd_offs = 0x178, 100 + .sram_pdn_bits = BIT(8), 101 + .sram_pdn_ack_bits = BIT(12), 102 + .bp_infracfg = { 103 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_PEXTP_MAC_P0_STEP1, 104 + MT8188_TOP_AXI_PROT_EN_SET, 105 + MT8188_TOP_AXI_PROT_EN_CLR, 106 + MT8188_TOP_AXI_PROT_EN_STA), 107 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_PEXTP_MAC_P0_STEP2, 108 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET, 109 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR, 110 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA), 111 + }, 112 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 113 + }, 114 + [MT8188_POWER_DOMAIN_PEXTP_PHY_TOP] = { 115 + .name = "pextp_phy_top", 116 + .sta_mask = BIT(12), 117 + .ctl_offs = 0x328, 118 + .pwr_sta_offs = 0x174, 119 + .pwr_sta2nd_offs = 0x178, 120 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 121 + }, 122 + [MT8188_POWER_DOMAIN_CSIRX_TOP] = { 123 + .name = "pextp_csirx_top", 124 + .sta_mask = BIT(17), 125 + .ctl_offs = 0x3C4, 126 + .pwr_sta_offs = 0x174, 127 + .pwr_sta2nd_offs = 0x178, 128 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 129 + }, 130 + [MT8188_POWER_DOMAIN_ETHER] = { 131 + .name = "ether", 132 + .sta_mask = BIT(1), 133 + .ctl_offs = 0x338, 134 + .pwr_sta_offs = 0x16C, 135 + .pwr_sta2nd_offs = 0x170, 136 + .sram_pdn_bits = BIT(8), 137 + .sram_pdn_ack_bits = BIT(12), 138 + .bp_infracfg = { 139 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_ETHER_STEP1, 140 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET, 141 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR, 142 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA), 143 + }, 144 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, 145 + }, 146 + [MT8188_POWER_DOMAIN_HDMI_TX] = { 147 + .name = "hdmi_tx", 148 + .sta_mask = BIT(18), 149 + .ctl_offs = 0x37C, 150 + .pwr_sta_offs = 0x16C, 151 + .pwr_sta2nd_offs = 0x170, 152 + .sram_pdn_bits = BIT(8), 153 + .sram_pdn_ack_bits = BIT(12), 154 + .bp_infracfg = { 155 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_HDMI_TX_STEP1, 156 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET, 157 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR, 158 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA), 159 + }, 160 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, 161 + }, 162 + [MT8188_POWER_DOMAIN_ADSP_AO] = { 163 + .name = "adsp_ao", 164 + .sta_mask = BIT(10), 165 + .ctl_offs = 0x35C, 166 + .pwr_sta_offs = 0x16C, 167 + .pwr_sta2nd_offs = 0x170, 168 + .bp_infracfg = { 169 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP1, 170 + MT8188_TOP_AXI_PROT_EN_2_SET, 171 + MT8188_TOP_AXI_PROT_EN_2_CLR, 172 + MT8188_TOP_AXI_PROT_EN_2_STA), 173 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP2, 174 + MT8188_TOP_AXI_PROT_EN_2_SET, 175 + MT8188_TOP_AXI_PROT_EN_2_CLR, 176 + MT8188_TOP_AXI_PROT_EN_2_STA), 177 + }, 178 + .caps = MTK_SCPD_ALWAYS_ON, 179 + }, 180 + [MT8188_POWER_DOMAIN_ADSP_INFRA] = { 181 + .name = "adsp_infra", 182 + .sta_mask = BIT(9), 183 + .ctl_offs = 0x358, 184 + .pwr_sta_offs = 0x16C, 185 + .pwr_sta2nd_offs = 0x170, 186 + .sram_pdn_bits = BIT(8), 187 + .sram_pdn_ack_bits = BIT(12), 188 + .bp_infracfg = { 189 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP1, 190 + MT8188_TOP_AXI_PROT_EN_2_SET, 191 + MT8188_TOP_AXI_PROT_EN_2_CLR, 192 + MT8188_TOP_AXI_PROT_EN_2_STA), 193 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP2, 194 + MT8188_TOP_AXI_PROT_EN_2_SET, 195 + MT8188_TOP_AXI_PROT_EN_2_CLR, 196 + MT8188_TOP_AXI_PROT_EN_2_STA), 197 + }, 198 + .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ALWAYS_ON, 199 + }, 200 + [MT8188_POWER_DOMAIN_ADSP] = { 201 + .name = "adsp", 202 + .sta_mask = BIT(8), 203 + .ctl_offs = 0x354, 204 + .pwr_sta_offs = 0x16C, 205 + .pwr_sta2nd_offs = 0x170, 206 + .sram_pdn_bits = BIT(8), 207 + .sram_pdn_ack_bits = BIT(12), 208 + .bp_infracfg = { 209 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP1, 210 + MT8188_TOP_AXI_PROT_EN_2_SET, 211 + MT8188_TOP_AXI_PROT_EN_2_CLR, 212 + MT8188_TOP_AXI_PROT_EN_2_STA), 213 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP2, 214 + MT8188_TOP_AXI_PROT_EN_2_SET, 215 + MT8188_TOP_AXI_PROT_EN_2_CLR, 216 + MT8188_TOP_AXI_PROT_EN_2_STA), 217 + }, 218 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP, 219 + }, 220 + [MT8188_POWER_DOMAIN_AUDIO] = { 221 + .name = "audio", 222 + .sta_mask = BIT(6), 223 + .ctl_offs = 0x34C, 224 + .pwr_sta_offs = 0x16C, 225 + .pwr_sta2nd_offs = 0x170, 226 + .sram_pdn_bits = BIT(8), 227 + .sram_pdn_ack_bits = BIT(12), 228 + .bp_infracfg = { 229 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1, 230 + MT8188_TOP_AXI_PROT_EN_2_SET, 231 + MT8188_TOP_AXI_PROT_EN_2_CLR, 232 + MT8188_TOP_AXI_PROT_EN_2_STA), 233 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2, 234 + MT8188_TOP_AXI_PROT_EN_2_SET, 235 + MT8188_TOP_AXI_PROT_EN_2_CLR, 236 + MT8188_TOP_AXI_PROT_EN_2_STA), 237 + }, 238 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, 239 + }, 240 + [MT8188_POWER_DOMAIN_AUDIO_ASRC] = { 241 + .name = "audio_asrc", 242 + .sta_mask = BIT(7), 243 + .ctl_offs = 0x350, 244 + .pwr_sta_offs = 0x16C, 245 + .pwr_sta2nd_offs = 0x170, 246 + .sram_pdn_bits = BIT(8), 247 + .sram_pdn_ack_bits = BIT(12), 248 + .bp_infracfg = { 249 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP1, 250 + MT8188_TOP_AXI_PROT_EN_2_SET, 251 + MT8188_TOP_AXI_PROT_EN_2_CLR, 252 + MT8188_TOP_AXI_PROT_EN_2_STA), 253 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP2, 254 + MT8188_TOP_AXI_PROT_EN_2_SET, 255 + MT8188_TOP_AXI_PROT_EN_2_CLR, 256 + MT8188_TOP_AXI_PROT_EN_2_STA), 257 + }, 258 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 259 + }, 260 + [MT8188_POWER_DOMAIN_VPPSYS0] = { 261 + .name = "vppsys0", 262 + .sta_mask = BIT(11), 263 + .ctl_offs = 0x360, 264 + .pwr_sta_offs = 0x16C, 265 + .pwr_sta2nd_offs = 0x170, 266 + .sram_pdn_bits = BIT(8), 267 + .sram_pdn_ack_bits = BIT(12), 268 + .bp_infracfg = { 269 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP1, 270 + MT8188_TOP_AXI_PROT_EN_SET, 271 + MT8188_TOP_AXI_PROT_EN_CLR, 272 + MT8188_TOP_AXI_PROT_EN_STA), 273 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP2, 274 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 275 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 276 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 277 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP3, 278 + MT8188_TOP_AXI_PROT_EN_SET, 279 + MT8188_TOP_AXI_PROT_EN_CLR, 280 + MT8188_TOP_AXI_PROT_EN_STA), 281 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP4, 282 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 283 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 284 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 285 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0_STEP5, 286 + MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, 287 + MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, 288 + MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA), 289 + }, 290 + }, 291 + [MT8188_POWER_DOMAIN_VDOSYS0] = { 292 + .name = "vdosys0", 293 + .sta_mask = BIT(13), 294 + .ctl_offs = 0x368, 295 + .pwr_sta_offs = 0x16C, 296 + .pwr_sta2nd_offs = 0x170, 297 + .sram_pdn_bits = BIT(8), 298 + .sram_pdn_ack_bits = BIT(12), 299 + .bp_infracfg = { 300 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS0_STEP1, 301 + MT8188_TOP_AXI_PROT_EN_MM_SET, 302 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 303 + MT8188_TOP_AXI_PROT_EN_MM_STA), 304 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VDOSYS0_STEP2, 305 + MT8188_TOP_AXI_PROT_EN_SET, 306 + MT8188_TOP_AXI_PROT_EN_CLR, 307 + MT8188_TOP_AXI_PROT_EN_STA), 308 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0_STEP3, 309 + MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, 310 + MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, 311 + MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA), 312 + }, 313 + }, 314 + [MT8188_POWER_DOMAIN_VDOSYS1] = { 315 + .name = "vdosys1", 316 + .sta_mask = BIT(14), 317 + .ctl_offs = 0x36C, 318 + .pwr_sta_offs = 0x16C, 319 + .pwr_sta2nd_offs = 0x170, 320 + .sram_pdn_bits = BIT(8), 321 + .sram_pdn_ack_bits = BIT(12), 322 + .bp_infracfg = { 323 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP1, 324 + MT8188_TOP_AXI_PROT_EN_MM_SET, 325 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 326 + MT8188_TOP_AXI_PROT_EN_MM_STA), 327 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP2, 328 + MT8188_TOP_AXI_PROT_EN_MM_SET, 329 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 330 + MT8188_TOP_AXI_PROT_EN_MM_STA), 331 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VDOSYS1_STEP3, 332 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 333 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 334 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 335 + }, 336 + }, 337 + [MT8188_POWER_DOMAIN_DP_TX] = { 338 + .name = "dp_tx", 339 + .sta_mask = BIT(16), 340 + .ctl_offs = 0x374, 341 + .pwr_sta_offs = 0x16C, 342 + .pwr_sta2nd_offs = 0x170, 343 + .sram_pdn_bits = BIT(8), 344 + .sram_pdn_ack_bits = BIT(12), 345 + .bp_infracfg = { 346 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_DP_TX_STEP1, 347 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET, 348 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR, 349 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA), 350 + }, 351 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 352 + }, 353 + [MT8188_POWER_DOMAIN_EDP_TX] = { 354 + .name = "edp_tx", 355 + .sta_mask = BIT(17), 356 + .ctl_offs = 0x378, 357 + .pwr_sta_offs = 0x16C, 358 + .pwr_sta2nd_offs = 0x170, 359 + .sram_pdn_bits = BIT(8), 360 + .sram_pdn_ack_bits = BIT(12), 361 + .bp_infracfg = { 362 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_EDP_TX_STEP1, 363 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET, 364 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR, 365 + MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA), 366 + }, 367 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 368 + }, 369 + [MT8188_POWER_DOMAIN_VPPSYS1] = { 370 + .name = "vppsys1", 371 + .sta_mask = BIT(12), 372 + .ctl_offs = 0x364, 373 + .pwr_sta_offs = 0x16C, 374 + .pwr_sta2nd_offs = 0x170, 375 + .sram_pdn_bits = BIT(8), 376 + .sram_pdn_ack_bits = BIT(12), 377 + .bp_infracfg = { 378 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP1, 379 + MT8188_TOP_AXI_PROT_EN_MM_SET, 380 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 381 + MT8188_TOP_AXI_PROT_EN_MM_STA), 382 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP2, 383 + MT8188_TOP_AXI_PROT_EN_MM_SET, 384 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 385 + MT8188_TOP_AXI_PROT_EN_MM_STA), 386 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS1_STEP3, 387 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 388 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 389 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 390 + }, 391 + }, 392 + [MT8188_POWER_DOMAIN_WPE] = { 393 + .name = "wpe", 394 + .sta_mask = BIT(15), 395 + .ctl_offs = 0x370, 396 + .pwr_sta_offs = 0x16C, 397 + .pwr_sta2nd_offs = 0x170, 398 + .sram_pdn_bits = BIT(8), 399 + .sram_pdn_ack_bits = BIT(12), 400 + .bp_infracfg = { 401 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP1, 402 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 403 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 404 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 405 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP2, 406 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 407 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 408 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 409 + }, 410 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 411 + }, 412 + [MT8188_POWER_DOMAIN_VDEC0] = { 413 + .name = "vdec0", 414 + .sta_mask = BIT(19), 415 + .ctl_offs = 0x380, 416 + .pwr_sta_offs = 0x16C, 417 + .pwr_sta2nd_offs = 0x170, 418 + .sram_pdn_bits = BIT(8), 419 + .sram_pdn_ack_bits = BIT(12), 420 + .bp_infracfg = { 421 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC0_STEP1, 422 + MT8188_TOP_AXI_PROT_EN_MM_SET, 423 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 424 + MT8188_TOP_AXI_PROT_EN_MM_STA), 425 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VDEC0_STEP2, 426 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 427 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 428 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 429 + }, 430 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 431 + }, 432 + [MT8188_POWER_DOMAIN_VDEC1] = { 433 + .name = "vdec1", 434 + .sta_mask = BIT(20), 435 + .ctl_offs = 0x384, 436 + .pwr_sta_offs = 0x16C, 437 + .pwr_sta2nd_offs = 0x170, 438 + .sram_pdn_bits = BIT(8), 439 + .sram_pdn_ack_bits = BIT(12), 440 + .bp_infracfg = { 441 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP1, 442 + MT8188_TOP_AXI_PROT_EN_MM_SET, 443 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 444 + MT8188_TOP_AXI_PROT_EN_MM_STA), 445 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP2, 446 + MT8188_TOP_AXI_PROT_EN_MM_SET, 447 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 448 + MT8188_TOP_AXI_PROT_EN_MM_STA), 449 + }, 450 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 451 + }, 452 + [MT8188_POWER_DOMAIN_VENC] = { 453 + .name = "venc", 454 + .sta_mask = BIT(22), 455 + .ctl_offs = 0x38C, 456 + .pwr_sta_offs = 0x16C, 457 + .pwr_sta2nd_offs = 0x170, 458 + .sram_pdn_bits = BIT(8), 459 + .sram_pdn_ack_bits = BIT(12), 460 + .bp_infracfg = { 461 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP1, 462 + MT8188_TOP_AXI_PROT_EN_MM_SET, 463 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 464 + MT8188_TOP_AXI_PROT_EN_MM_STA), 465 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP2, 466 + MT8188_TOP_AXI_PROT_EN_MM_SET, 467 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 468 + MT8188_TOP_AXI_PROT_EN_MM_STA), 469 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VENC_STEP3, 470 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 471 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 472 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 473 + }, 474 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 475 + }, 476 + [MT8188_POWER_DOMAIN_IMG_VCORE] = { 477 + .name = "vcore", 478 + .sta_mask = BIT(28), 479 + .ctl_offs = 0x3A4, 480 + .pwr_sta_offs = 0x16C, 481 + .pwr_sta2nd_offs = 0x170, 482 + .bp_infracfg = { 483 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP1, 484 + MT8188_TOP_AXI_PROT_EN_MM_SET, 485 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 486 + MT8188_TOP_AXI_PROT_EN_MM_STA), 487 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP2, 488 + MT8188_TOP_AXI_PROT_EN_MM_SET, 489 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 490 + MT8188_TOP_AXI_PROT_EN_MM_STA), 491 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_VCORE_STEP3, 492 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 493 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 494 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 495 + }, 496 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, 497 + }, 498 + [MT8188_POWER_DOMAIN_IMG_MAIN] = { 499 + .name = "img_main", 500 + .sta_mask = BIT(29), 501 + .ctl_offs = 0x3A8, 502 + .pwr_sta_offs = 0x16C, 503 + .pwr_sta2nd_offs = 0x170, 504 + .sram_pdn_bits = BIT(8), 505 + .sram_pdn_ack_bits = BIT(12), 506 + .bp_infracfg = { 507 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP1, 508 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 509 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 510 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 511 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP2, 512 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 513 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 514 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 515 + }, 516 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 517 + }, 518 + [MT8188_POWER_DOMAIN_DIP] = { 519 + .name = "dip", 520 + .sta_mask = BIT(30), 521 + .ctl_offs = 0x3AC, 522 + .pwr_sta_offs = 0x16C, 523 + .pwr_sta2nd_offs = 0x170, 524 + .sram_pdn_bits = BIT(8), 525 + .sram_pdn_ack_bits = BIT(12), 526 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 527 + }, 528 + [MT8188_POWER_DOMAIN_IPE] = { 529 + .name = "ipe", 530 + .sta_mask = BIT(31), 531 + .ctl_offs = 0x3B0, 532 + .pwr_sta_offs = 0x16C, 533 + .pwr_sta2nd_offs = 0x170, 534 + .sram_pdn_bits = BIT(8), 535 + .sram_pdn_ack_bits = BIT(12), 536 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 537 + }, 538 + [MT8188_POWER_DOMAIN_CAM_VCORE] = { 539 + .name = "cam_vcore", 540 + .sta_mask = BIT(27), 541 + .ctl_offs = 0x3A0, 542 + .pwr_sta_offs = 0x16C, 543 + .pwr_sta2nd_offs = 0x170, 544 + .bp_infracfg = { 545 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP1, 546 + MT8188_TOP_AXI_PROT_EN_MM_SET, 547 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 548 + MT8188_TOP_AXI_PROT_EN_MM_STA), 549 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_VCORE_STEP2, 550 + MT8188_TOP_AXI_PROT_EN_2_SET, 551 + MT8188_TOP_AXI_PROT_EN_2_CLR, 552 + MT8188_TOP_AXI_PROT_EN_2_STA), 553 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_1_CAM_VCORE_STEP3, 554 + MT8188_TOP_AXI_PROT_EN_1_SET, 555 + MT8188_TOP_AXI_PROT_EN_1_CLR, 556 + MT8188_TOP_AXI_PROT_EN_1_STA), 557 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP4, 558 + MT8188_TOP_AXI_PROT_EN_MM_SET, 559 + MT8188_TOP_AXI_PROT_EN_MM_CLR, 560 + MT8188_TOP_AXI_PROT_EN_MM_STA), 561 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_VCORE_STEP5, 562 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 563 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 564 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 565 + }, 566 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, 567 + }, 568 + [MT8188_POWER_DOMAIN_CAM_MAIN] = { 569 + .name = "cam_main", 570 + .sta_mask = BIT(24), 571 + .ctl_offs = 0x394, 572 + .pwr_sta_offs = 0x16C, 573 + .pwr_sta2nd_offs = 0x170, 574 + .sram_pdn_bits = BIT(8), 575 + .sram_pdn_ack_bits = BIT(12), 576 + .bp_infracfg = { 577 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP1, 578 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 579 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 580 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 581 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP2, 582 + MT8188_TOP_AXI_PROT_EN_2_SET, 583 + MT8188_TOP_AXI_PROT_EN_2_CLR, 584 + MT8188_TOP_AXI_PROT_EN_2_STA), 585 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP3, 586 + MT8188_TOP_AXI_PROT_EN_MM_2_SET, 587 + MT8188_TOP_AXI_PROT_EN_MM_2_CLR, 588 + MT8188_TOP_AXI_PROT_EN_MM_2_STA), 589 + BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP4, 590 + MT8188_TOP_AXI_PROT_EN_2_SET, 591 + MT8188_TOP_AXI_PROT_EN_2_CLR, 592 + MT8188_TOP_AXI_PROT_EN_2_STA), 593 + }, 594 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 595 + }, 596 + [MT8188_POWER_DOMAIN_CAM_SUBA] = { 597 + .name = "cam_suba", 598 + .sta_mask = BIT(25), 599 + .ctl_offs = 0x398, 600 + .pwr_sta_offs = 0x16C, 601 + .pwr_sta2nd_offs = 0x170, 602 + .sram_pdn_bits = BIT(8), 603 + .sram_pdn_ack_bits = BIT(12), 604 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 605 + }, 606 + [MT8188_POWER_DOMAIN_CAM_SUBB] = { 607 + .name = "cam_subb", 608 + .sta_mask = BIT(26), 609 + .ctl_offs = 0x39C, 610 + .pwr_sta_offs = 0x16C, 611 + .pwr_sta2nd_offs = 0x170, 612 + .sram_pdn_bits = BIT(8), 613 + .sram_pdn_ack_bits = BIT(12), 614 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 615 + }, 616 + }; 617 + 618 + static const struct scpsys_soc_data mt8188_scpsys_data = { 619 + .domains_data = scpsys_domain_data_mt8188, 620 + .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8188), 621 + }; 622 + 623 + #endif /* __SOC_MEDIATEK_MT8188_PM_DOMAINS_H */
+146
drivers/soc/mediatek/mt8195-mmsys.h
··· 75 75 #define MT8195_SOUT_DSC_WRAP1_OUT_TO_SINA_VIRTUAL0 (2 << 16) 76 76 #define MT8195_SOUT_DSC_WRAP1_OUT_TO_VPP_MERGE (3 << 16) 77 77 78 + #define MT8195_VDO1_SW0_RST_B 0x1d0 79 + #define MT8195_VDO1_MERGE0_ASYNC_CFG_WD 0xe30 80 + #define MT8195_VDO1_HDRBE_ASYNC_CFG_WD 0xe70 81 + #define MT8195_VDO1_HDR_TOP_CFG 0xd00 82 + #define MT8195_VDO1_MIXER_IN1_ALPHA 0xd30 83 + #define MT8195_VDO1_MIXER_IN1_PAD 0xd40 84 + 85 + #define MT8195_VDO1_VPP_MERGE0_P0_SEL_IN 0xf04 86 + #define MT8195_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0 1 87 + 88 + #define MT8195_VDO1_VPP_MERGE0_P1_SEL_IN 0xf08 89 + #define MT8195_VPP_MERGE0_P1_SEL_IN_FROM_MDP_RDMA1 1 90 + 91 + #define MT8195_VDO1_DISP_DPI1_SEL_IN 0xf10 92 + #define MT8195_DISP_DPI1_SEL_IN_FROM_VPP_MERGE4_MOUT 0 93 + 94 + #define MT8195_VDO1_DISP_DP_INTF0_SEL_IN 0xf14 95 + #define MT8195_DISP_DP_INTF0_SEL_IN_FROM_VPP_MERGE4_MOUT 0 96 + 97 + #define MT8195_VDO1_MERGE4_SOUT_SEL 0xf18 98 + #define MT8195_MERGE4_SOUT_TO_DPI1_SEL 2 99 + #define MT8195_MERGE4_SOUT_TO_DP_INTF0_SEL 3 100 + 101 + #define MT8195_VDO1_MIXER_IN1_SEL_IN 0xf24 102 + #define MT8195_MIXER_IN1_SEL_IN_FROM_MERGE0_ASYNC_SOUT 1 103 + 104 + #define MT8195_VDO1_MIXER_IN2_SEL_IN 0xf28 105 + #define MT8195_MIXER_IN2_SEL_IN_FROM_MERGE1_ASYNC_SOUT 1 106 + 107 + #define MT8195_VDO1_MIXER_IN3_SEL_IN 0xf2c 108 + #define MT8195_MIXER_IN3_SEL_IN_FROM_MERGE2_ASYNC_SOUT 1 109 + 110 + #define MT8195_VDO1_MIXER_IN4_SEL_IN 0xf30 111 + #define MT8195_MIXER_IN4_SEL_IN_FROM_MERGE3_ASYNC_SOUT 1 112 + 113 + #define MT8195_VDO1_MIXER_OUT_SOUT_SEL 0xf34 114 + #define MT8195_MIXER_SOUT_TO_MERGE4_ASYNC_SEL 1 115 + 116 + #define MT8195_VDO1_VPP_MERGE1_P0_SEL_IN 0xf3c 117 + #define MT8195_VPP_MERGE1_P0_SEL_IN_FROM_MDP_RDMA2 1 118 + 119 + #define MT8195_VDO1_MERGE0_ASYNC_SOUT_SEL 0xf40 120 + #define MT8195_SOUT_TO_MIXER_IN1_SEL 1 121 + 122 + #define MT8195_VDO1_MERGE1_ASYNC_SOUT_SEL 0xf44 123 + #define MT8195_SOUT_TO_MIXER_IN2_SEL 1 124 + 125 + #define MT8195_VDO1_MERGE2_ASYNC_SOUT_SEL 0xf48 126 + #define MT8195_SOUT_TO_MIXER_IN3_SEL 1 127 + 128 + #define MT8195_VDO1_MERGE3_ASYNC_SOUT_SEL 0xf4c 129 + #define MT8195_SOUT_TO_MIXER_IN4_SEL 1 130 + 131 + #define MT8195_VDO1_MERGE4_ASYNC_SEL_IN 0xf50 132 + #define MT8195_MERGE4_ASYNC_SEL_IN_FROM_MIXER_OUT_SOUT 1 133 + 134 + #define MT8195_VDO1_MIXER_IN1_SOUT_SEL 0xf58 135 + #define MT8195_MIXER_IN1_SOUT_TO_DISP_MIXER 0 136 + 137 + #define MT8195_VDO1_MIXER_IN2_SOUT_SEL 0xf5c 138 + #define MT8195_MIXER_IN2_SOUT_TO_DISP_MIXER 0 139 + 140 + #define MT8195_VDO1_MIXER_IN3_SOUT_SEL 0xf60 141 + #define MT8195_MIXER_IN3_SOUT_TO_DISP_MIXER 0 142 + 143 + #define MT8195_VDO1_MIXER_IN4_SOUT_SEL 0xf64 144 + #define MT8195_MIXER_IN4_SOUT_TO_DISP_MIXER 0 145 + 146 + #define MT8195_VDO1_MIXER_SOUT_SEL_IN 0xf68 147 + #define MT8195_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER 0 148 + 78 149 static const struct mtk_mmsys_routes mmsys_mt8195_routing_table[] = { 79 150 { 80 151 DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, ··· 438 367 } 439 368 }; 440 369 370 + static const struct mtk_mmsys_routes mmsys_mt8195_vdo1_routing_table[] = { 371 + { 372 + DDP_COMPONENT_MDP_RDMA0, DDP_COMPONENT_MERGE1, 373 + MT8195_VDO1_VPP_MERGE0_P0_SEL_IN, GENMASK(0, 0), 374 + MT8195_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0 375 + }, { 376 + DDP_COMPONENT_MDP_RDMA1, DDP_COMPONENT_MERGE1, 377 + MT8195_VDO1_VPP_MERGE0_P1_SEL_IN, GENMASK(0, 0), 378 + MT8195_VPP_MERGE0_P1_SEL_IN_FROM_MDP_RDMA1 379 + }, { 380 + DDP_COMPONENT_MDP_RDMA2, DDP_COMPONENT_MERGE2, 381 + MT8195_VDO1_VPP_MERGE1_P0_SEL_IN, GENMASK(0, 0), 382 + MT8195_VPP_MERGE1_P0_SEL_IN_FROM_MDP_RDMA2 383 + }, { 384 + DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER, 385 + MT8195_VDO1_MERGE0_ASYNC_SOUT_SEL, GENMASK(1, 0), 386 + MT8195_SOUT_TO_MIXER_IN1_SEL 387 + }, { 388 + DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER, 389 + MT8195_VDO1_MERGE1_ASYNC_SOUT_SEL, GENMASK(1, 0), 390 + MT8195_SOUT_TO_MIXER_IN2_SEL 391 + }, { 392 + DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER, 393 + MT8195_VDO1_MERGE2_ASYNC_SOUT_SEL, GENMASK(1, 0), 394 + MT8195_SOUT_TO_MIXER_IN3_SEL 395 + }, { 396 + DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER, 397 + MT8195_VDO1_MERGE3_ASYNC_SOUT_SEL, GENMASK(1, 0), 398 + MT8195_SOUT_TO_MIXER_IN4_SEL 399 + }, { 400 + DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5, 401 + MT8195_VDO1_MIXER_OUT_SOUT_SEL, GENMASK(0, 0), 402 + MT8195_MIXER_SOUT_TO_MERGE4_ASYNC_SEL 403 + }, { 404 + DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER, 405 + MT8195_VDO1_MIXER_IN1_SEL_IN, GENMASK(0, 0), 406 + MT8195_MIXER_IN1_SEL_IN_FROM_MERGE0_ASYNC_SOUT 407 + }, { 408 + DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER, 409 + MT8195_VDO1_MIXER_IN2_SEL_IN, GENMASK(0, 0), 410 + MT8195_MIXER_IN2_SEL_IN_FROM_MERGE1_ASYNC_SOUT 411 + }, { 412 + DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER, 413 + MT8195_VDO1_MIXER_IN3_SEL_IN, GENMASK(0, 0), 414 + MT8195_MIXER_IN3_SEL_IN_FROM_MERGE2_ASYNC_SOUT 415 + }, { 416 + DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER, 417 + MT8195_VDO1_MIXER_IN4_SEL_IN, GENMASK(0, 0), 418 + MT8195_MIXER_IN4_SEL_IN_FROM_MERGE3_ASYNC_SOUT 419 + }, { 420 + DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5, 421 + MT8195_VDO1_MIXER_SOUT_SEL_IN, GENMASK(2, 0), 422 + MT8195_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER 423 + }, { 424 + DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5, 425 + MT8195_VDO1_MERGE4_ASYNC_SEL_IN, GENMASK(2, 0), 426 + MT8195_MERGE4_ASYNC_SEL_IN_FROM_MIXER_OUT_SOUT 427 + }, { 428 + DDP_COMPONENT_MERGE5, DDP_COMPONENT_DPI1, 429 + MT8195_VDO1_DISP_DPI1_SEL_IN, GENMASK(1, 0), 430 + MT8195_DISP_DPI1_SEL_IN_FROM_VPP_MERGE4_MOUT 431 + }, { 432 + DDP_COMPONENT_MERGE5, DDP_COMPONENT_DPI1, 433 + MT8195_VDO1_MERGE4_SOUT_SEL, GENMASK(1, 0), 434 + MT8195_MERGE4_SOUT_TO_DPI1_SEL 435 + }, { 436 + DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF1, 437 + MT8195_VDO1_DISP_DP_INTF0_SEL_IN, GENMASK(1, 0), 438 + MT8195_DISP_DP_INTF0_SEL_IN_FROM_VPP_MERGE4_MOUT 439 + }, { 440 + DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF1, 441 + MT8195_VDO1_MERGE4_SOUT_SEL, GENMASK(1, 0), 442 + MT8195_MERGE4_SOUT_TO_DP_INTF0_SEL 443 + } 444 + }; 441 445 #endif /* __SOC_MEDIATEK_MT8195_MMSYS_H */
+2 -9
drivers/soc/mediatek/mtk-devapc.c
··· 276 276 if (!devapc_irq) 277 277 return -EINVAL; 278 278 279 - ctx->infra_clk = devm_clk_get(&pdev->dev, "devapc-infra-clock"); 279 + ctx->infra_clk = devm_clk_get_enabled(&pdev->dev, "devapc-infra-clock"); 280 280 if (IS_ERR(ctx->infra_clk)) 281 - return -EINVAL; 282 - 283 - if (clk_prepare_enable(ctx->infra_clk)) 284 281 return -EINVAL; 285 282 286 283 ret = devm_request_irq(&pdev->dev, devapc_irq, devapc_violation_irq, 287 284 IRQF_TRIGGER_NONE, "devapc", ctx); 288 - if (ret) { 289 - clk_disable_unprepare(ctx->infra_clk); 285 + if (ret) 290 286 return ret; 291 - } 292 287 293 288 platform_set_drvdata(pdev, ctx); 294 289 ··· 297 302 struct mtk_devapc_context *ctx = platform_get_drvdata(pdev); 298 303 299 304 stop_devapc(ctx); 300 - 301 - clk_disable_unprepare(ctx->infra_clk); 302 305 303 306 return 0; 304 307 }
+162 -40
drivers/soc/mediatek/mtk-mmsys.c
··· 7 7 #include <linux/delay.h> 8 8 #include <linux/device.h> 9 9 #include <linux/io.h> 10 + #include <linux/module.h> 10 11 #include <linux/of_device.h> 11 12 #include <linux/platform_device.h> 12 13 #include <linux/reset-controller.h> ··· 17 16 #include "mt8167-mmsys.h" 18 17 #include "mt8183-mmsys.h" 19 18 #include "mt8186-mmsys.h" 19 + #include "mt8188-mmsys.h" 20 20 #include "mt8192-mmsys.h" 21 21 #include "mt8195-mmsys.h" 22 22 #include "mt8365-mmsys.h" 23 + 24 + #define MMSYS_SW_RESET_PER_REG 32 23 25 24 26 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = { 25 27 .clk_driver = "clk-mt2701-mm", ··· 55 51 .routes = mmsys_default_routing_table, 56 52 .num_routes = ARRAY_SIZE(mmsys_default_routing_table), 57 53 .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B, 54 + .num_resets = 32, 58 55 }; 59 56 60 57 static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = { ··· 63 58 .routes = mmsys_mt8183_routing_table, 64 59 .num_routes = ARRAY_SIZE(mmsys_mt8183_routing_table), 65 60 .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B, 61 + .num_resets = 32, 66 62 }; 67 63 68 64 static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = { ··· 71 65 .routes = mmsys_mt8186_routing_table, 72 66 .num_routes = ARRAY_SIZE(mmsys_mt8186_routing_table), 73 67 .sw0_rst_offset = MT8186_MMSYS_SW0_RST_B, 68 + .num_resets = 32, 69 + }; 70 + 71 + static const struct mtk_mmsys_driver_data mt8188_vdosys0_driver_data = { 72 + .clk_driver = "clk-mt8188-vdo0", 73 + .routes = mmsys_mt8188_routing_table, 74 + .num_routes = ARRAY_SIZE(mmsys_mt8188_routing_table), 74 75 }; 75 76 76 77 static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = { ··· 85 72 .routes = mmsys_mt8192_routing_table, 86 73 .num_routes = ARRAY_SIZE(mmsys_mt8192_routing_table), 87 74 .sw0_rst_offset = MT8186_MMSYS_SW0_RST_B, 75 + .num_resets = 32, 88 76 }; 89 77 90 78 static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = { 91 79 .clk_driver = "clk-mt8195-vdo0", 92 80 .routes = mmsys_mt8195_routing_table, 93 81 .num_routes = ARRAY_SIZE(mmsys_mt8195_routing_table), 82 + }; 83 + 84 + static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = { 85 + .clk_driver = "clk-mt8195-vdo1", 86 + .routes = mmsys_mt8195_vdo1_routing_table, 87 + .num_routes = ARRAY_SIZE(mmsys_mt8195_vdo1_routing_table), 88 + .sw0_rst_offset = MT8195_VDO1_SW0_RST_B, 89 + .num_resets = 64, 90 + }; 91 + 92 + static const struct mtk_mmsys_driver_data mt8195_vppsys0_driver_data = { 93 + .clk_driver = "clk-mt8195-vpp0", 94 + .is_vppsys = true, 95 + }; 96 + 97 + static const struct mtk_mmsys_driver_data mt8195_vppsys1_driver_data = { 98 + .clk_driver = "clk-mt8195-vpp1", 99 + .is_vppsys = true, 94 100 }; 95 101 96 102 static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = { ··· 123 91 const struct mtk_mmsys_driver_data *data; 124 92 spinlock_t lock; /* protects mmsys_sw_rst_b reg */ 125 93 struct reset_controller_dev rcdev; 94 + struct cmdq_client_reg cmdq_base; 126 95 }; 96 + 97 + static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask, u32 val, 98 + struct cmdq_pkt *cmdq_pkt) 99 + { 100 + u32 tmp; 101 + 102 + #if IS_REACHABLE(CONFIG_MTK_CMDQ) 103 + if (cmdq_pkt) { 104 + if (mmsys->cmdq_base.size == 0) { 105 + pr_err("mmsys lose gce property, failed to update mmsys bits with cmdq"); 106 + return; 107 + } 108 + cmdq_pkt_write_mask(cmdq_pkt, mmsys->cmdq_base.subsys, 109 + mmsys->cmdq_base.offset + offset, val, 110 + mask); 111 + return; 112 + } 113 + #endif 114 + 115 + tmp = readl_relaxed(mmsys->regs + offset); 116 + tmp = (tmp & ~mask) | (val & mask); 117 + writel_relaxed(tmp, mmsys->regs + offset); 118 + } 127 119 128 120 void mtk_mmsys_ddp_connect(struct device *dev, 129 121 enum mtk_ddp_comp_id cur, ··· 155 99 { 156 100 struct mtk_mmsys *mmsys = dev_get_drvdata(dev); 157 101 const struct mtk_mmsys_routes *routes = mmsys->data->routes; 158 - u32 reg; 159 102 int i; 160 103 161 104 for (i = 0; i < mmsys->data->num_routes; i++) 162 - if (cur == routes[i].from_comp && next == routes[i].to_comp) { 163 - reg = readl_relaxed(mmsys->regs + routes[i].addr); 164 - reg &= ~routes[i].mask; 165 - reg |= routes[i].val; 166 - writel_relaxed(reg, mmsys->regs + routes[i].addr); 167 - } 105 + if (cur == routes[i].from_comp && next == routes[i].to_comp) 106 + mtk_mmsys_update_bits(mmsys, routes[i].addr, routes[i].mask, 107 + routes[i].val, NULL); 168 108 } 169 109 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_connect); 170 110 ··· 170 118 { 171 119 struct mtk_mmsys *mmsys = dev_get_drvdata(dev); 172 120 const struct mtk_mmsys_routes *routes = mmsys->data->routes; 173 - u32 reg; 174 121 int i; 175 122 176 123 for (i = 0; i < mmsys->data->num_routes; i++) 177 - if (cur == routes[i].from_comp && next == routes[i].to_comp) { 178 - reg = readl_relaxed(mmsys->regs + routes[i].addr); 179 - reg &= ~routes[i].mask; 180 - writel_relaxed(reg, mmsys->regs + routes[i].addr); 181 - } 124 + if (cur == routes[i].from_comp && next == routes[i].to_comp) 125 + mtk_mmsys_update_bits(mmsys, routes[i].addr, routes[i].mask, 0, NULL); 182 126 } 183 127 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect); 184 128 185 - static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask, u32 val) 129 + void mtk_mmsys_merge_async_config(struct device *dev, int idx, int width, int height, 130 + struct cmdq_pkt *cmdq_pkt) 186 131 { 187 - u32 tmp; 188 - 189 - tmp = readl_relaxed(mmsys->regs + offset); 190 - tmp = (tmp & ~mask) | val; 191 - writel_relaxed(tmp, mmsys->regs + offset); 132 + mtk_mmsys_update_bits(dev_get_drvdata(dev), MT8195_VDO1_MERGE0_ASYNC_CFG_WD + 0x10 * idx, 133 + ~0, height << 16 | width, cmdq_pkt); 192 134 } 135 + EXPORT_SYMBOL_GPL(mtk_mmsys_merge_async_config); 136 + 137 + void mtk_mmsys_hdr_config(struct device *dev, int be_width, int be_height, 138 + struct cmdq_pkt *cmdq_pkt) 139 + { 140 + mtk_mmsys_update_bits(dev_get_drvdata(dev), MT8195_VDO1_HDRBE_ASYNC_CFG_WD, ~0, 141 + be_height << 16 | be_width, cmdq_pkt); 142 + } 143 + EXPORT_SYMBOL_GPL(mtk_mmsys_hdr_config); 144 + 145 + void mtk_mmsys_mixer_in_config(struct device *dev, int idx, bool alpha_sel, u16 alpha, 146 + u8 mode, u32 biwidth, struct cmdq_pkt *cmdq_pkt) 147 + { 148 + struct mtk_mmsys *mmsys = dev_get_drvdata(dev); 149 + 150 + mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_ALPHA + (idx - 1) * 4, ~0, 151 + alpha << 16 | alpha, cmdq_pkt); 152 + mtk_mmsys_update_bits(mmsys, MT8195_VDO1_HDR_TOP_CFG, BIT(19 + idx), 153 + alpha_sel << (19 + idx), cmdq_pkt); 154 + mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_PAD + (idx - 1) * 4, 155 + GENMASK(31, 16) | GENMASK(1, 0), biwidth << 16 | mode, cmdq_pkt); 156 + } 157 + EXPORT_SYMBOL_GPL(mtk_mmsys_mixer_in_config); 158 + 159 + void mtk_mmsys_mixer_in_channel_swap(struct device *dev, int idx, bool channel_swap, 160 + struct cmdq_pkt *cmdq_pkt) 161 + { 162 + mtk_mmsys_update_bits(dev_get_drvdata(dev), MT8195_VDO1_MIXER_IN1_PAD + (idx - 1) * 4, 163 + BIT(4), channel_swap << 4, cmdq_pkt); 164 + } 165 + EXPORT_SYMBOL_GPL(mtk_mmsys_mixer_in_channel_swap); 193 166 194 167 void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val) 195 168 { ··· 223 146 switch (val) { 224 147 case MTK_DPI_RGB888_SDR_CON: 225 148 mtk_mmsys_update_bits(mmsys, MT8186_MMSYS_DPI_OUTPUT_FORMAT, 226 - MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB888_SDR_CON); 149 + MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB888_SDR_CON, NULL); 227 150 break; 228 151 case MTK_DPI_RGB565_SDR_CON: 229 152 mtk_mmsys_update_bits(mmsys, MT8186_MMSYS_DPI_OUTPUT_FORMAT, 230 - MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB565_SDR_CON); 153 + MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB565_SDR_CON, NULL); 231 154 break; 232 155 case MTK_DPI_RGB565_DDR_CON: 233 156 mtk_mmsys_update_bits(mmsys, MT8186_MMSYS_DPI_OUTPUT_FORMAT, 234 - MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB565_DDR_CON); 157 + MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB565_DDR_CON, NULL); 235 158 break; 236 159 case MTK_DPI_RGB888_DDR_CON: 237 160 default: 238 161 mtk_mmsys_update_bits(mmsys, MT8186_MMSYS_DPI_OUTPUT_FORMAT, 239 - MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB888_DDR_CON); 162 + MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB888_DDR_CON, NULL); 240 163 break; 241 164 } 242 165 } ··· 247 170 { 248 171 struct mtk_mmsys *mmsys = container_of(rcdev, struct mtk_mmsys, rcdev); 249 172 unsigned long flags; 173 + u32 offset; 250 174 u32 reg; 175 + 176 + offset = (id / MMSYS_SW_RESET_PER_REG) * sizeof(u32); 177 + id = id % MMSYS_SW_RESET_PER_REG; 178 + reg = mmsys->data->sw0_rst_offset + offset; 251 179 252 180 spin_lock_irqsave(&mmsys->lock, flags); 253 181 254 - reg = readl_relaxed(mmsys->regs + mmsys->data->sw0_rst_offset); 255 - 256 182 if (assert) 257 - reg &= ~BIT(id); 183 + mtk_mmsys_update_bits(mmsys, reg, BIT(id), 0, NULL); 258 184 else 259 - reg |= BIT(id); 260 - 261 - writel_relaxed(reg, mmsys->regs + mmsys->data->sw0_rst_offset); 185 + mtk_mmsys_update_bits(mmsys, reg, BIT(id), BIT(id), NULL); 262 186 263 187 spin_unlock_irqrestore(&mmsys->lock, flags); 264 188 ··· 314 236 return ret; 315 237 } 316 238 317 - spin_lock_init(&mmsys->lock); 239 + mmsys->data = of_device_get_match_data(&pdev->dev); 318 240 319 - mmsys->rcdev.owner = THIS_MODULE; 320 - mmsys->rcdev.nr_resets = 32; 321 - mmsys->rcdev.ops = &mtk_mmsys_reset_ops; 322 - mmsys->rcdev.of_node = pdev->dev.of_node; 323 - ret = devm_reset_controller_register(&pdev->dev, &mmsys->rcdev); 324 - if (ret) { 325 - dev_err(&pdev->dev, "Couldn't register mmsys reset controller: %d\n", ret); 326 - return ret; 241 + if (mmsys->data->num_resets > 0) { 242 + spin_lock_init(&mmsys->lock); 243 + 244 + mmsys->rcdev.owner = THIS_MODULE; 245 + mmsys->rcdev.nr_resets = mmsys->data->num_resets; 246 + mmsys->rcdev.ops = &mtk_mmsys_reset_ops; 247 + mmsys->rcdev.of_node = pdev->dev.of_node; 248 + ret = devm_reset_controller_register(&pdev->dev, &mmsys->rcdev); 249 + if (ret) { 250 + dev_err(&pdev->dev, "Couldn't register mmsys reset controller: %d\n", ret); 251 + return ret; 252 + } 327 253 } 328 254 329 - mmsys->data = of_device_get_match_data(&pdev->dev); 255 + #if IS_REACHABLE(CONFIG_MTK_CMDQ) 256 + ret = cmdq_dev_get_client_reg(dev, &mmsys->cmdq_base, 0); 257 + if (ret) 258 + dev_dbg(dev, "No mediatek,gce-client-reg!\n"); 259 + #endif 260 + 330 261 platform_set_drvdata(pdev, mmsys); 331 262 332 263 clks = platform_device_register_data(&pdev->dev, mmsys->data->clk_driver, 333 264 PLATFORM_DEVID_AUTO, NULL, 0); 334 265 if (IS_ERR(clks)) 335 266 return PTR_ERR(clks); 267 + 268 + if (mmsys->data->is_vppsys) 269 + goto out_probe_done; 336 270 337 271 drm = platform_device_register_data(&pdev->dev, "mediatek-drm", 338 272 PLATFORM_DEVID_AUTO, NULL, 0); ··· 353 263 return PTR_ERR(drm); 354 264 } 355 265 266 + out_probe_done: 356 267 return 0; 357 268 } 358 269 ··· 391 300 .data = &mt8186_mmsys_driver_data, 392 301 }, 393 302 { 303 + .compatible = "mediatek,mt8188-vdosys0", 304 + .data = &mt8188_vdosys0_driver_data, 305 + }, 306 + { 394 307 .compatible = "mediatek,mt8192-mmsys", 395 308 .data = &mt8192_mmsys_driver_data, 396 309 }, ··· 405 310 { 406 311 .compatible = "mediatek,mt8195-vdosys0", 407 312 .data = &mt8195_vdosys0_driver_data, 313 + }, 314 + { 315 + .compatible = "mediatek,mt8195-vdosys1", 316 + .data = &mt8195_vdosys1_driver_data, 317 + }, 318 + { 319 + .compatible = "mediatek,mt8195-vppsys0", 320 + .data = &mt8195_vppsys0_driver_data, 321 + }, 322 + { 323 + .compatible = "mediatek,mt8195-vppsys1", 324 + .data = &mt8195_vppsys1_driver_data, 408 325 }, 409 326 { 410 327 .compatible = "mediatek,mt8365-mmsys", ··· 433 326 .probe = mtk_mmsys_probe, 434 327 }; 435 328 436 - builtin_platform_driver(mtk_mmsys_drv); 329 + static int __init mtk_mmsys_init(void) 330 + { 331 + return platform_driver_register(&mtk_mmsys_drv); 332 + } 333 + 334 + static void __exit mtk_mmsys_exit(void) 335 + { 336 + platform_driver_unregister(&mtk_mmsys_drv); 337 + } 338 + 339 + module_init(mtk_mmsys_init); 340 + module_exit(mtk_mmsys_exit); 341 + 342 + MODULE_AUTHOR("Yongqiang Niu <yongqiang.niu@mediatek.com>"); 343 + MODULE_DESCRIPTION("MediaTek SoC MMSYS driver"); 344 + MODULE_LICENSE("GPL");
+2
drivers/soc/mediatek/mtk-mmsys.h
··· 91 91 const struct mtk_mmsys_routes *routes; 92 92 const unsigned int num_routes; 93 93 const u16 sw0_rst_offset; 94 + const u32 num_resets; 95 + const bool is_vppsys; 94 96 }; 95 97 96 98 /*
+106 -7
drivers/soc/mediatek/mtk-mutex.c
··· 116 116 #define MT8173_MUTEX_MOD_DISP_PWM1 24 117 117 #define MT8173_MUTEX_MOD_DISP_OD 25 118 118 119 + #define MT8188_MUTEX_MOD_DISP_OVL0 0 120 + #define MT8188_MUTEX_MOD_DISP_WDMA0 1 121 + #define MT8188_MUTEX_MOD_DISP_RDMA0 2 122 + #define MT8188_MUTEX_MOD_DISP_COLOR0 3 123 + #define MT8188_MUTEX_MOD_DISP_CCORR0 4 124 + #define MT8188_MUTEX_MOD_DISP_AAL0 5 125 + #define MT8188_MUTEX_MOD_DISP_GAMMA0 6 126 + #define MT8188_MUTEX_MOD_DISP_DITHER0 7 127 + #define MT8188_MUTEX_MOD_DISP_DSI0 8 128 + #define MT8188_MUTEX_MOD_DISP_DSC_WRAP0_CORE0 9 129 + #define MT8188_MUTEX_MOD_DISP_VPP_MERGE 20 130 + #define MT8188_MUTEX_MOD_DISP_DP_INTF0 21 131 + #define MT8188_MUTEX_MOD_DISP_POSTMASK0 24 132 + #define MT8188_MUTEX_MOD2_DISP_PWM0 33 133 + 119 134 #define MT8195_MUTEX_MOD_DISP_OVL0 0 120 135 #define MT8195_MUTEX_MOD_DISP_WDMA0 1 121 136 #define MT8195_MUTEX_MOD_DISP_RDMA0 2 ··· 144 129 #define MT8195_MUTEX_MOD_DISP_VPP_MERGE 20 145 130 #define MT8195_MUTEX_MOD_DISP_DP_INTF0 21 146 131 #define MT8195_MUTEX_MOD_DISP_PWM0 27 132 + 133 + #define MT8195_MUTEX_MOD_DISP1_MDP_RDMA0 0 134 + #define MT8195_MUTEX_MOD_DISP1_MDP_RDMA1 1 135 + #define MT8195_MUTEX_MOD_DISP1_MDP_RDMA2 2 136 + #define MT8195_MUTEX_MOD_DISP1_MDP_RDMA3 3 137 + #define MT8195_MUTEX_MOD_DISP1_MDP_RDMA4 4 138 + #define MT8195_MUTEX_MOD_DISP1_MDP_RDMA5 5 139 + #define MT8195_MUTEX_MOD_DISP1_MDP_RDMA6 6 140 + #define MT8195_MUTEX_MOD_DISP1_MDP_RDMA7 7 141 + #define MT8195_MUTEX_MOD_DISP1_VPP_MERGE0 8 142 + #define MT8195_MUTEX_MOD_DISP1_VPP_MERGE1 9 143 + #define MT8195_MUTEX_MOD_DISP1_VPP_MERGE2 10 144 + #define MT8195_MUTEX_MOD_DISP1_VPP_MERGE3 11 145 + #define MT8195_MUTEX_MOD_DISP1_VPP_MERGE4 12 146 + #define MT8195_MUTEX_MOD_DISP1_DISP_MIXER 18 147 + #define MT8195_MUTEX_MOD_DISP1_DPI0 25 148 + #define MT8195_MUTEX_MOD_DISP1_DPI1 26 149 + #define MT8195_MUTEX_MOD_DISP1_DP_INTF0 27 147 150 148 151 #define MT8365_MUTEX_MOD_DISP_OVL0 7 149 152 #define MT8365_MUTEX_MOD_DISP_OVL0_2L 8 ··· 213 180 #define MT8167_MUTEX_SOF_DPI1 3 214 181 #define MT8183_MUTEX_SOF_DSI0 1 215 182 #define MT8183_MUTEX_SOF_DPI0 2 183 + #define MT8188_MUTEX_SOF_DSI0 1 184 + #define MT8188_MUTEX_SOF_DP_INTF0 3 216 185 #define MT8195_MUTEX_SOF_DSI0 1 217 186 #define MT8195_MUTEX_SOF_DSI1 2 218 187 #define MT8195_MUTEX_SOF_DP_INTF0 3 ··· 224 189 225 190 #define MT8183_MUTEX_EOF_DSI0 (MT8183_MUTEX_SOF_DSI0 << 6) 226 191 #define MT8183_MUTEX_EOF_DPI0 (MT8183_MUTEX_SOF_DPI0 << 6) 192 + #define MT8188_MUTEX_EOF_DSI0 (MT8188_MUTEX_SOF_DSI0 << 7) 193 + #define MT8188_MUTEX_EOF_DP_INTF0 (MT8188_MUTEX_SOF_DP_INTF0 << 7) 227 194 #define MT8195_MUTEX_EOF_DSI0 (MT8195_MUTEX_SOF_DSI0 << 7) 228 195 #define MT8195_MUTEX_EOF_DSI1 (MT8195_MUTEX_SOF_DSI1 << 7) 229 196 #define MT8195_MUTEX_EOF_DP_INTF0 (MT8195_MUTEX_SOF_DP_INTF0 << 7) ··· 381 344 [MUTEX_MOD_IDX_MDP_COLOR0] = MT8186_MUTEX_MOD_MDP_COLOR0, 382 345 }; 383 346 347 + static const unsigned int mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = { 348 + [DDP_COMPONENT_OVL0] = MT8188_MUTEX_MOD_DISP_OVL0, 349 + [DDP_COMPONENT_WDMA0] = MT8188_MUTEX_MOD_DISP_WDMA0, 350 + [DDP_COMPONENT_RDMA0] = MT8188_MUTEX_MOD_DISP_RDMA0, 351 + [DDP_COMPONENT_COLOR0] = MT8188_MUTEX_MOD_DISP_COLOR0, 352 + [DDP_COMPONENT_CCORR] = MT8188_MUTEX_MOD_DISP_CCORR0, 353 + [DDP_COMPONENT_AAL0] = MT8188_MUTEX_MOD_DISP_AAL0, 354 + [DDP_COMPONENT_GAMMA] = MT8188_MUTEX_MOD_DISP_GAMMA0, 355 + [DDP_COMPONENT_POSTMASK0] = MT8188_MUTEX_MOD_DISP_POSTMASK0, 356 + [DDP_COMPONENT_DITHER0] = MT8188_MUTEX_MOD_DISP_DITHER0, 357 + [DDP_COMPONENT_MERGE0] = MT8188_MUTEX_MOD_DISP_VPP_MERGE, 358 + [DDP_COMPONENT_DSC0] = MT8188_MUTEX_MOD_DISP_DSC_WRAP0_CORE0, 359 + [DDP_COMPONENT_DSI0] = MT8188_MUTEX_MOD_DISP_DSI0, 360 + [DDP_COMPONENT_PWM0] = MT8188_MUTEX_MOD2_DISP_PWM0, 361 + [DDP_COMPONENT_DP_INTF0] = MT8188_MUTEX_MOD_DISP_DP_INTF0, 362 + }; 363 + 384 364 static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = { 385 365 [DDP_COMPONENT_AAL0] = MT8192_MUTEX_MOD_DISP_AAL0, 386 366 [DDP_COMPONENT_CCORR] = MT8192_MUTEX_MOD_DISP_CCORR0, ··· 426 372 [DDP_COMPONENT_DSI0] = MT8195_MUTEX_MOD_DISP_DSI0, 427 373 [DDP_COMPONENT_PWM0] = MT8195_MUTEX_MOD_DISP_PWM0, 428 374 [DDP_COMPONENT_DP_INTF0] = MT8195_MUTEX_MOD_DISP_DP_INTF0, 375 + [DDP_COMPONENT_MDP_RDMA0] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA0, 376 + [DDP_COMPONENT_MDP_RDMA1] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA1, 377 + [DDP_COMPONENT_MDP_RDMA2] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA2, 378 + [DDP_COMPONENT_MDP_RDMA3] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA3, 379 + [DDP_COMPONENT_MDP_RDMA4] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA4, 380 + [DDP_COMPONENT_MDP_RDMA5] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA5, 381 + [DDP_COMPONENT_MDP_RDMA6] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA6, 382 + [DDP_COMPONENT_MDP_RDMA7] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA7, 383 + [DDP_COMPONENT_MERGE1] = MT8195_MUTEX_MOD_DISP1_VPP_MERGE0, 384 + [DDP_COMPONENT_MERGE2] = MT8195_MUTEX_MOD_DISP1_VPP_MERGE1, 385 + [DDP_COMPONENT_MERGE3] = MT8195_MUTEX_MOD_DISP1_VPP_MERGE2, 386 + [DDP_COMPONENT_MERGE4] = MT8195_MUTEX_MOD_DISP1_VPP_MERGE3, 387 + [DDP_COMPONENT_ETHDR_MIXER] = MT8195_MUTEX_MOD_DISP1_DISP_MIXER, 388 + [DDP_COMPONENT_MERGE5] = MT8195_MUTEX_MOD_DISP1_VPP_MERGE4, 389 + [DDP_COMPONENT_DP_INTF1] = MT8195_MUTEX_MOD_DISP1_DP_INTF0, 429 390 }; 430 391 431 392 static const unsigned int mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = { ··· 504 435 * but also detect the error at end of frame(EAEOF) when EOF signal 505 436 * arrives. 506 437 */ 438 + static const unsigned int mt8188_mutex_sof[DDP_MUTEX_SOF_MAX] = { 439 + [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, 440 + [MUTEX_SOF_DSI0] = 441 + MT8188_MUTEX_SOF_DSI0 | MT8188_MUTEX_EOF_DSI0, 442 + [MUTEX_SOF_DP_INTF0] = 443 + MT8188_MUTEX_SOF_DP_INTF0 | MT8188_MUTEX_EOF_DP_INTF0, 444 + }; 445 + 507 446 static const unsigned int mt8195_mutex_sof[DDP_MUTEX_SOF_MAX] = { 508 447 [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, 509 448 [MUTEX_SOF_DSI0] = MT8195_MUTEX_SOF_DSI0 | MT8195_MUTEX_EOF_DSI0, ··· 578 501 static const struct mtk_mutex_data mt8186_mutex_driver_data = { 579 502 .mutex_mod = mt8186_mutex_mod, 580 503 .mutex_sof = mt8186_mutex_sof, 504 + .mutex_mod_reg = MT8183_MUTEX0_MOD0, 505 + .mutex_sof_reg = MT8183_MUTEX0_SOF0, 506 + }; 507 + 508 + static const struct mtk_mutex_data mt8188_mutex_driver_data = { 509 + .mutex_mod = mt8188_mutex_mod, 510 + .mutex_sof = mt8188_mutex_sof, 581 511 .mutex_mod_reg = MT8183_MUTEX0_MOD0, 582 512 .mutex_sof_reg = MT8183_MUTEX0_SOF0, 583 513 }; ··· 686 602 case DDP_COMPONENT_DP_INTF0: 687 603 sof_id = MUTEX_SOF_DP_INTF0; 688 604 break; 605 + case DDP_COMPONENT_DP_INTF1: 606 + sof_id = MUTEX_SOF_DP_INTF1; 607 + break; 689 608 default: 690 609 if (mtx->data->mutex_mod[id] < 32) { 691 610 offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg, ··· 729 642 case DDP_COMPONENT_DPI0: 730 643 case DDP_COMPONENT_DPI1: 731 644 case DDP_COMPONENT_DP_INTF0: 645 + case DDP_COMPONENT_DP_INTF1: 732 646 writel_relaxed(MUTEX_SOF_SINGLE_MODE, 733 647 mtx->regs + 734 648 DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, ··· 920 832 return 0; 921 833 } 922 834 923 - static int mtk_mutex_remove(struct platform_device *pdev) 924 - { 925 - return 0; 926 - } 927 - 928 835 static const struct of_device_id mutex_driver_dt_match[] = { 929 836 { .compatible = "mediatek,mt2701-disp-mutex", 930 837 .data = &mt2701_mutex_driver_data}, ··· 937 854 .data = &mt8186_mutex_driver_data}, 938 855 { .compatible = "mediatek,mt8186-mdp3-mutex", 939 856 .data = &mt8186_mdp_mutex_driver_data}, 857 + { .compatible = "mediatek,mt8188-disp-mutex", 858 + .data = &mt8188_mutex_driver_data}, 940 859 { .compatible = "mediatek,mt8192-disp-mutex", 941 860 .data = &mt8192_mutex_driver_data}, 942 861 { .compatible = "mediatek,mt8195-disp-mutex", ··· 951 866 952 867 static struct platform_driver mtk_mutex_driver = { 953 868 .probe = mtk_mutex_probe, 954 - .remove = mtk_mutex_remove, 955 869 .driver = { 956 870 .name = "mediatek-mutex", 957 871 .owner = THIS_MODULE, ··· 958 874 }, 959 875 }; 960 876 961 - builtin_platform_driver(mtk_mutex_driver); 877 + static int __init mtk_mutex_init(void) 878 + { 879 + return platform_driver_register(&mtk_mutex_driver); 880 + } 881 + 882 + static void __exit mtk_mutex_exit(void) 883 + { 884 + platform_driver_unregister(&mtk_mutex_driver); 885 + } 886 + 887 + module_init(mtk_mutex_init); 888 + module_exit(mtk_mutex_exit); 889 + 890 + MODULE_AUTHOR("Yongqiang Niu <yongqiang.niu@mediatek.com>"); 891 + MODULE_DESCRIPTION("MediaTek SoC MUTEX driver"); 892 + MODULE_LICENSE("GPL");
+13
drivers/soc/mediatek/mtk-pm-domains.c
··· 21 21 #include "mt8173-pm-domains.h" 22 22 #include "mt8183-pm-domains.h" 23 23 #include "mt8186-pm-domains.h" 24 + #include "mt8188-pm-domains.h" 24 25 #include "mt8192-pm-domains.h" 25 26 #include "mt8195-pm-domains.h" 26 27 ··· 219 218 if (ret) 220 219 goto err_reg; 221 220 221 + if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO)) 222 + regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs, 223 + pd->data->ext_buck_iso_mask); 224 + 222 225 /* subsys power on */ 223 226 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); 224 227 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); ··· 276 271 ret = scpsys_sram_disable(pd); 277 272 if (ret < 0) 278 273 return ret; 274 + 275 + if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO)) 276 + regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs, 277 + pd->data->ext_buck_iso_mask); 279 278 280 279 clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks); 281 280 ··· 587 578 { 588 579 .compatible = "mediatek,mt8186-power-controller", 589 580 .data = &mt8186_scpsys_data, 581 + }, 582 + { 583 + .compatible = "mediatek,mt8188-power-controller", 584 + .data = &mt8188_scpsys_data, 590 585 }, 591 586 { 592 587 .compatible = "mediatek,mt8192-power-controller",
+5
drivers/soc/mediatek/mtk-pm-domains.h
··· 10 10 #define MTK_SCPD_DOMAIN_SUPPLY BIT(4) 11 11 /* can't set MTK_SCPD_KEEP_DEFAULT_OFF at the same time */ 12 12 #define MTK_SCPD_ALWAYS_ON BIT(5) 13 + #define MTK_SCPD_EXT_BUCK_ISO BIT(6) 13 14 #define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x)) 14 15 15 16 #define SPM_VDE_PWR_CON 0x0210 ··· 82 81 * @ctl_offs: The offset for main power control register. 83 82 * @sram_pdn_bits: The mask for sram power control bits. 84 83 * @sram_pdn_ack_bits: The mask for sram power control acked bits. 84 + * @ext_buck_iso_offs: The offset for external buck isolation 85 + * @ext_buck_iso_mask: The mask for external buck isolation 85 86 * @caps: The flag for active wake-up action. 86 87 * @bp_infracfg: bus protection for infracfg subsystem 87 88 * @bp_smi: bus protection for smi subsystem ··· 94 91 int ctl_offs; 95 92 u32 sram_pdn_bits; 96 93 u32 sram_pdn_ack_bits; 94 + int ext_buck_iso_offs; 95 + u32 ext_buck_iso_mask; 97 96 u8 caps; 98 97 const struct scpsys_bus_prot_data bp_infracfg[SPM_MAX_BUS_PROT_DATA]; 99 98 const struct scpsys_bus_prot_data bp_smi[SPM_MAX_BUS_PROT_DATA];
+159
drivers/soc/mediatek/mtk-regulator-coupler.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Voltage regulators coupler for MediaTek SoCs 4 + * 5 + * Copyright (C) 2022 Collabora, Ltd. 6 + * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 7 + */ 8 + 9 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 + 11 + #include <linux/init.h> 12 + #include <linux/kernel.h> 13 + #include <linux/of.h> 14 + #include <linux/regulator/coupler.h> 15 + #include <linux/regulator/driver.h> 16 + #include <linux/regulator/machine.h> 17 + #include <linux/suspend.h> 18 + 19 + #define to_mediatek_coupler(x) container_of(x, struct mediatek_regulator_coupler, coupler) 20 + 21 + struct mediatek_regulator_coupler { 22 + struct regulator_coupler coupler; 23 + struct regulator_dev *vsram_rdev; 24 + }; 25 + 26 + /* 27 + * We currently support only couples of not more than two vregs and 28 + * modify the vsram voltage only when changing voltage of vgpu. 29 + * 30 + * This function is limited to the GPU<->SRAM voltages relationships. 31 + */ 32 + static int mediatek_regulator_balance_voltage(struct regulator_coupler *coupler, 33 + struct regulator_dev *rdev, 34 + suspend_state_t state) 35 + { 36 + struct mediatek_regulator_coupler *mrc = to_mediatek_coupler(coupler); 37 + int max_spread = rdev->constraints->max_spread[0]; 38 + int vsram_min_uV = mrc->vsram_rdev->constraints->min_uV; 39 + int vsram_max_uV = mrc->vsram_rdev->constraints->max_uV; 40 + int vsram_target_min_uV, vsram_target_max_uV; 41 + int min_uV = 0; 42 + int max_uV = INT_MAX; 43 + int ret; 44 + 45 + /* 46 + * If the target device is on, setting the SRAM voltage directly 47 + * is not supported as it scales through its coupled supply voltage. 48 + * 49 + * An exception is made in case the use_count is zero: this means 50 + * that this is the first time we power up the SRAM regulator, which 51 + * implies that the target device has yet to perform initialization 52 + * and setting a voltage at that time is harmless. 53 + */ 54 + if (rdev == mrc->vsram_rdev) { 55 + if (rdev->use_count == 0) 56 + return regulator_do_balance_voltage(rdev, state, true); 57 + 58 + return -EPERM; 59 + } 60 + 61 + ret = regulator_check_consumers(rdev, &min_uV, &max_uV, state); 62 + if (ret < 0) 63 + return ret; 64 + 65 + if (min_uV == 0) { 66 + ret = regulator_get_voltage_rdev(rdev); 67 + if (ret < 0) 68 + return ret; 69 + min_uV = ret; 70 + } 71 + 72 + ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 73 + if (ret < 0) 74 + return ret; 75 + 76 + /* 77 + * If we're asked to set a voltage less than VSRAM min_uV, set 78 + * the minimum allowed voltage on VSRAM, as in this case it is 79 + * safe to ignore the max_spread parameter. 80 + */ 81 + vsram_target_min_uV = max(vsram_min_uV, min_uV + max_spread); 82 + vsram_target_max_uV = min(vsram_max_uV, vsram_target_min_uV + max_spread); 83 + 84 + /* Make sure we're not out of range */ 85 + vsram_target_min_uV = min(vsram_target_min_uV, vsram_max_uV); 86 + 87 + pr_debug("Setting voltage %d-%duV on %s (minuV %d)\n", 88 + vsram_target_min_uV, vsram_target_max_uV, 89 + rdev_get_name(mrc->vsram_rdev), min_uV); 90 + 91 + ret = regulator_set_voltage_rdev(mrc->vsram_rdev, vsram_target_min_uV, 92 + vsram_target_max_uV, state); 93 + if (ret) 94 + return ret; 95 + 96 + /* The sram voltage is now balanced: update the target vreg voltage */ 97 + return regulator_do_balance_voltage(rdev, state, true); 98 + } 99 + 100 + static int mediatek_regulator_attach(struct regulator_coupler *coupler, 101 + struct regulator_dev *rdev) 102 + { 103 + struct mediatek_regulator_coupler *mrc = to_mediatek_coupler(coupler); 104 + const char *rdev_name = rdev_get_name(rdev); 105 + 106 + /* 107 + * If we're getting a coupling of more than two regulators here and 108 + * this means that this is surely not a GPU<->SRAM couple: in that 109 + * case, we may want to use another coupler implementation, if any, 110 + * or the generic one: the regulator core will keep walking through 111 + * the list of couplers when any .attach_regulator() cb returns 1. 112 + */ 113 + if (rdev->coupling_desc.n_coupled > 2) 114 + return 1; 115 + 116 + if (strstr(rdev_name, "sram")) { 117 + if (mrc->vsram_rdev) 118 + return -EINVAL; 119 + mrc->vsram_rdev = rdev; 120 + } else if (!strstr(rdev_name, "vgpu") && !strstr(rdev_name, "Vgpu")) { 121 + return 1; 122 + } 123 + 124 + return 0; 125 + } 126 + 127 + static int mediatek_regulator_detach(struct regulator_coupler *coupler, 128 + struct regulator_dev *rdev) 129 + { 130 + struct mediatek_regulator_coupler *mrc = to_mediatek_coupler(coupler); 131 + 132 + if (rdev == mrc->vsram_rdev) 133 + mrc->vsram_rdev = NULL; 134 + 135 + return 0; 136 + } 137 + 138 + static struct mediatek_regulator_coupler mediatek_coupler = { 139 + .coupler = { 140 + .attach_regulator = mediatek_regulator_attach, 141 + .detach_regulator = mediatek_regulator_detach, 142 + .balance_voltage = mediatek_regulator_balance_voltage, 143 + }, 144 + }; 145 + 146 + static int mediatek_regulator_coupler_init(void) 147 + { 148 + if (!of_machine_is_compatible("mediatek,mt8183") && 149 + !of_machine_is_compatible("mediatek,mt8186") && 150 + !of_machine_is_compatible("mediatek,mt8192")) 151 + return 0; 152 + 153 + return regulator_coupler_register(&mediatek_coupler.coupler); 154 + } 155 + arch_initcall(mediatek_regulator_coupler_init); 156 + 157 + MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>"); 158 + MODULE_DESCRIPTION("MediaTek Regulator Coupler driver"); 159 + MODULE_LICENSE("GPL");
+92 -85
drivers/soc/mediatek/mtk-svs.c
··· 138 138 139 139 static DEFINE_SPINLOCK(svs_lock); 140 140 141 + #ifdef CONFIG_DEBUG_FS 141 142 #define debug_fops_ro(name) \ 142 143 static int svs_##name##_debug_open(struct inode *inode, \ 143 144 struct file *filp) \ ··· 171 170 } 172 171 173 172 #define svs_dentry_data(name) {__stringify(name), &svs_##name##_debug_fops} 173 + #endif 174 174 175 175 /** 176 176 * enum svsb_phase - svs bank phase enumeration ··· 313 311 314 312 /** 315 313 * struct svs_platform - svs platform control 316 - * @name: svs platform name 317 314 * @base: svs platform register base 318 315 * @dev: svs platform device 319 316 * @main_clk: main clock for svs bank 320 317 * @pbank: svs bank pointer needing to be protected by spin_lock section 321 318 * @banks: svs banks that svs platform supports 322 319 * @rst: svs platform reset control 323 - * @efuse_parsing: svs platform efuse parsing function pointer 324 - * @probe: svs platform probe function pointer 325 320 * @efuse_max: total number of svs efuse 326 321 * @tefuse_max: total number of thermal efuse 327 322 * @regs: svs platform registers map ··· 327 328 * @tefuse: thermal efuse data received from NVMEM framework 328 329 */ 329 330 struct svs_platform { 330 - char *name; 331 331 void __iomem *base; 332 332 struct device *dev; 333 333 struct clk *main_clk; 334 334 struct svs_bank *pbank; 335 335 struct svs_bank *banks; 336 336 struct reset_control *rst; 337 - bool (*efuse_parsing)(struct svs_platform *svsp); 338 - int (*probe)(struct svs_platform *svsp); 339 337 size_t efuse_max; 340 338 size_t tefuse_max; 341 339 const u32 *regs; ··· 624 628 return ret; 625 629 } 626 630 631 + #ifdef CONFIG_DEBUG_FS 627 632 static int svs_dump_debug_show(struct seq_file *m, void *p) 628 633 { 629 634 struct svs_platform *svsp = (struct svs_platform *)m->private; ··· 840 843 841 844 return 0; 842 845 } 846 + #endif /* CONFIG_DEBUG_FS */ 843 847 844 848 static u32 interpolate(u32 f0, u32 f1, u32 v0, u32 v1, u32 fx) 845 849 { ··· 1322 1324 svsb->pm_runtime_enabled_count++; 1323 1325 } 1324 1326 1325 - ret = pm_runtime_get_sync(svsb->opp_dev); 1327 + ret = pm_runtime_resume_and_get(svsb->opp_dev); 1326 1328 if (ret < 0) { 1327 1329 dev_err(svsb->dev, "mtcmos on fail: %d\n", ret); 1328 1330 goto svs_init01_resume_cpuidle; ··· 1459 1461 { 1460 1462 struct svs_bank *svsb; 1461 1463 unsigned long flags, time_left; 1464 + int ret; 1462 1465 u32 idx; 1463 1466 1464 1467 for (idx = 0; idx < svsp->bank_max; idx++) { ··· 1478 1479 msecs_to_jiffies(5000)); 1479 1480 if (!time_left) { 1480 1481 dev_err(svsb->dev, "init02 completion timeout\n"); 1481 - return -EBUSY; 1482 + ret = -EBUSY; 1483 + goto out_of_init02; 1482 1484 } 1483 1485 } 1484 1486 ··· 1497 1497 if (svsb->type == SVSB_HIGH || svsb->type == SVSB_LOW) { 1498 1498 if (svs_sync_bank_volts_from_opp(svsb)) { 1499 1499 dev_err(svsb->dev, "sync volt fail\n"); 1500 - return -EPERM; 1500 + ret = -EPERM; 1501 + goto out_of_init02; 1501 1502 } 1502 1503 } 1503 1504 } 1504 1505 1505 1506 return 0; 1507 + 1508 + out_of_init02: 1509 + for (idx = 0; idx < svsp->bank_max; idx++) { 1510 + svsb = &svsp->banks[idx]; 1511 + 1512 + spin_lock_irqsave(&svs_lock, flags); 1513 + svsp->pbank = svsb; 1514 + svs_switch_bank(svsp); 1515 + svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN); 1516 + svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS); 1517 + spin_unlock_irqrestore(&svs_lock, flags); 1518 + 1519 + svsb->phase = SVSB_PHASE_ERROR; 1520 + svs_adjust_pm_opp_volts(svsb); 1521 + } 1522 + 1523 + return ret; 1506 1524 } 1507 1525 1508 1526 static void svs_mon_mode(struct svs_platform *svsp) ··· 1612 1594 1613 1595 ret = svs_init02(svsp); 1614 1596 if (ret) 1615 - goto out_of_resume; 1597 + goto svs_resume_reset_assert; 1616 1598 1617 1599 svs_mon_mode(svsp); 1618 1600 1619 1601 return 0; 1602 + 1603 + svs_resume_reset_assert: 1604 + dev_err(svsp->dev, "assert reset: %d\n", 1605 + reset_control_assert(svsp->rst)); 1620 1606 1621 1607 out_of_resume: 1622 1608 clk_disable_unprepare(svsp->main_clk); ··· 1921 1899 o_slope_sign = (svsp->tefuse[0] >> 7) & BIT(0); 1922 1900 1923 1901 ts_id = (svsp->tefuse[1] >> 9) & BIT(0); 1924 - o_slope = (svsp->tefuse[0] >> 26) & GENMASK(5, 0); 1925 - 1926 - if (adc_cali_en_t == 1) { 1927 - if (!ts_id) 1928 - o_slope = 0; 1929 - 1930 - if (adc_ge_t < 265 || adc_ge_t > 758 || 1931 - adc_oe_t < 265 || adc_oe_t > 758 || 1932 - o_vtsmcu[0] < -8 || o_vtsmcu[0] > 484 || 1933 - o_vtsmcu[1] < -8 || o_vtsmcu[1] > 484 || 1934 - o_vtsmcu[2] < -8 || o_vtsmcu[2] > 484 || 1935 - o_vtsmcu[3] < -8 || o_vtsmcu[3] > 484 || 1936 - o_vtsmcu[4] < -8 || o_vtsmcu[4] > 484 || 1937 - o_vtsabb < -8 || o_vtsabb > 484 || 1938 - degc_cali < 1 || degc_cali > 63) { 1939 - dev_err(svsp->dev, "bad thermal efuse, no mon mode\n"); 1940 - goto remove_mt8183_svsb_mon_mode; 1941 - } 1902 + if (!ts_id) { 1903 + o_slope = 1534; 1942 1904 } else { 1943 - dev_err(svsp->dev, "no thermal efuse, no mon mode\n"); 1905 + o_slope = (svsp->tefuse[0] >> 26) & GENMASK(5, 0); 1906 + if (!o_slope_sign) 1907 + o_slope = 1534 + o_slope * 10; 1908 + else 1909 + o_slope = 1534 - o_slope * 10; 1910 + } 1911 + 1912 + if (adc_cali_en_t == 0 || 1913 + adc_ge_t < 265 || adc_ge_t > 758 || 1914 + adc_oe_t < 265 || adc_oe_t > 758 || 1915 + o_vtsmcu[0] < -8 || o_vtsmcu[0] > 484 || 1916 + o_vtsmcu[1] < -8 || o_vtsmcu[1] > 484 || 1917 + o_vtsmcu[2] < -8 || o_vtsmcu[2] > 484 || 1918 + o_vtsmcu[3] < -8 || o_vtsmcu[3] > 484 || 1919 + o_vtsmcu[4] < -8 || o_vtsmcu[4] > 484 || 1920 + o_vtsabb < -8 || o_vtsabb > 484 || 1921 + degc_cali < 1 || degc_cali > 63) { 1922 + dev_err(svsp->dev, "bad thermal efuse, no mon mode\n"); 1944 1923 goto remove_mt8183_svsb_mon_mode; 1945 1924 } 1946 1925 ··· 1960 1937 x_roomt[i] = (((format[i] * 10000) / 4096) * 10000) / gain; 1961 1938 1962 1939 temp0 = (10000 * 100000 / gain) * 15 / 18; 1963 - 1964 - if (!o_slope_sign) 1965 - mts = (temp0 * 10) / (1534 + o_slope * 10); 1966 - else 1967 - mts = (temp0 * 10) / (1534 - o_slope * 10); 1940 + mts = (temp0 * 10) / o_slope; 1968 1941 1969 1942 for (idx = 0; idx < svsp->bank_max; idx++) { 1970 1943 svsb = &svsp->banks[idx]; ··· 1987 1968 temp0 = (degc_cali * 10 / 2); 1988 1969 temp1 = ((10000 * 100000 / 4096 / gain) * 1989 1970 oe + tb_roomt * 10) * 15 / 18; 1990 - 1991 - if (!o_slope_sign) 1992 - temp2 = temp1 * 100 / (1534 + o_slope * 10); 1993 - else 1994 - temp2 = temp1 * 100 / (1534 - o_slope * 10); 1971 + temp2 = temp1 * 100 / o_slope; 1995 1972 1996 1973 svsb->bts = (temp0 + temp2 - 250) * 4 / 10; 1997 1974 } ··· 2026 2011 svsp->efuse_max /= sizeof(u32); 2027 2012 nvmem_cell_put(cell); 2028 2013 2029 - return svsp->efuse_parsing(svsp); 2014 + return true; 2030 2015 } 2031 2016 2032 2017 static struct device *svs_get_subsys_device(struct svs_platform *svsp, ··· 2341 2326 /* Sentinel */ 2342 2327 }, 2343 2328 }; 2344 - 2345 - static struct svs_platform *svs_platform_probe(struct platform_device *pdev) 2346 - { 2347 - struct svs_platform *svsp; 2348 - const struct svs_platform_data *svsp_data; 2349 - int ret; 2350 - 2351 - svsp_data = of_device_get_match_data(&pdev->dev); 2352 - if (!svsp_data) { 2353 - dev_err(&pdev->dev, "no svs platform data?\n"); 2354 - return ERR_PTR(-EPERM); 2355 - } 2356 - 2357 - svsp = devm_kzalloc(&pdev->dev, sizeof(*svsp), GFP_KERNEL); 2358 - if (!svsp) 2359 - return ERR_PTR(-ENOMEM); 2360 - 2361 - svsp->dev = &pdev->dev; 2362 - svsp->name = svsp_data->name; 2363 - svsp->banks = svsp_data->banks; 2364 - svsp->efuse_parsing = svsp_data->efuse_parsing; 2365 - svsp->probe = svsp_data->probe; 2366 - svsp->regs = svsp_data->regs; 2367 - svsp->bank_max = svsp_data->bank_max; 2368 - 2369 - ret = svsp->probe(svsp); 2370 - if (ret) 2371 - return ERR_PTR(ret); 2372 - 2373 - return svsp; 2374 - } 2329 + MODULE_DEVICE_TABLE(of, svs_of_match); 2375 2330 2376 2331 static int svs_probe(struct platform_device *pdev) 2377 2332 { 2378 2333 struct svs_platform *svsp; 2379 - int svsp_irq, ret; 2334 + const struct svs_platform_data *svsp_data; 2335 + int ret, svsp_irq; 2380 2336 2381 - svsp = svs_platform_probe(pdev); 2382 - if (IS_ERR(svsp)) 2383 - return PTR_ERR(svsp); 2337 + svsp_data = of_device_get_match_data(&pdev->dev); 2338 + 2339 + svsp = devm_kzalloc(&pdev->dev, sizeof(*svsp), GFP_KERNEL); 2340 + if (!svsp) 2341 + return -ENOMEM; 2342 + 2343 + svsp->dev = &pdev->dev; 2344 + svsp->banks = svsp_data->banks; 2345 + svsp->regs = svsp_data->regs; 2346 + svsp->bank_max = svsp_data->bank_max; 2347 + 2348 + ret = svsp_data->probe(svsp); 2349 + if (ret) 2350 + return ret; 2384 2351 2385 2352 if (!svs_is_efuse_data_correct(svsp)) { 2386 2353 dev_notice(svsp->dev, "efuse data isn't correct\n"); 2354 + ret = -EPERM; 2355 + goto svs_probe_free_efuse; 2356 + } 2357 + 2358 + if (!svsp_data->efuse_parsing(svsp)) { 2359 + dev_err(svsp->dev, "efuse data parsing failed\n"); 2387 2360 ret = -EPERM; 2388 2361 goto svs_probe_free_resource; 2389 2362 } ··· 2385 2382 svsp_irq = platform_get_irq(pdev, 0); 2386 2383 if (svsp_irq < 0) { 2387 2384 ret = svsp_irq; 2388 - goto svs_probe_free_resource; 2389 - } 2390 - 2391 - ret = devm_request_threaded_irq(svsp->dev, svsp_irq, NULL, svs_isr, 2392 - IRQF_ONESHOT, svsp->name, svsp); 2393 - if (ret) { 2394 - dev_err(svsp->dev, "register irq(%d) failed: %d\n", 2395 - svsp_irq, ret); 2396 2385 goto svs_probe_free_resource; 2397 2386 } 2398 2387 ··· 2409 2414 goto svs_probe_clk_disable; 2410 2415 } 2411 2416 2417 + ret = devm_request_threaded_irq(svsp->dev, svsp_irq, NULL, svs_isr, 2418 + IRQF_ONESHOT, svsp_data->name, svsp); 2419 + if (ret) { 2420 + dev_err(svsp->dev, "register irq(%d) failed: %d\n", 2421 + svsp_irq, ret); 2422 + goto svs_probe_iounmap; 2423 + } 2424 + 2412 2425 ret = svs_start(svsp); 2413 2426 if (ret) { 2414 2427 dev_err(svsp->dev, "svs start fail: %d\n", ret); 2415 2428 goto svs_probe_iounmap; 2416 2429 } 2417 2430 2431 + #ifdef CONFIG_DEBUG_FS 2418 2432 ret = svs_create_debug_cmds(svsp); 2419 2433 if (ret) { 2420 2434 dev_err(svsp->dev, "svs create debug cmds fail: %d\n", ret); 2421 2435 goto svs_probe_iounmap; 2422 2436 } 2437 + #endif 2423 2438 2424 2439 return 0; 2425 2440 ··· 2440 2435 clk_disable_unprepare(svsp->main_clk); 2441 2436 2442 2437 svs_probe_free_resource: 2443 - if (!IS_ERR_OR_NULL(svsp->efuse)) 2444 - kfree(svsp->efuse); 2445 2438 if (!IS_ERR_OR_NULL(svsp->tefuse)) 2446 2439 kfree(svsp->tefuse); 2440 + 2441 + svs_probe_free_efuse: 2442 + if (!IS_ERR_OR_NULL(svsp->efuse)) 2443 + kfree(svsp->efuse); 2447 2444 2448 2445 return ret; 2449 2446 }
+11
drivers/soc/nuvoton/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + menuconfig WPCM450_SOC 3 + tristate "Nuvoton WPCM450 SoC driver" 4 + default y if ARCH_WPCM450 5 + select SOC_BUS 6 + help 7 + Say Y here to compile the SoC information driver for Nuvoton 8 + WPCM450 SoCs. 9 + 10 + This driver provides information such as the SoC model and 11 + revision.
+2
drivers/soc/nuvoton/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + obj-$(CONFIG_WPCM450_SOC) += wpcm450-soc.o
+109
drivers/soc/nuvoton/wpcm450-soc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Nuvoton WPCM450 SoC Identification 4 + * 5 + * Copyright (C) 2022 Jonathan Neuschäfer 6 + */ 7 + 8 + #include <linux/mfd/syscon.h> 9 + #include <linux/of.h> 10 + #include <linux/regmap.h> 11 + #include <linux/slab.h> 12 + #include <linux/sys_soc.h> 13 + 14 + #define GCR_PDID 0 15 + #define PDID_CHIP(x) ((x) & 0x00ffffff) 16 + #define CHIP_WPCM450 0x926450 17 + #define PDID_REV(x) ((x) >> 24) 18 + 19 + struct revision { 20 + u8 number; 21 + const char *name; 22 + }; 23 + 24 + static const struct revision revisions[] __initconst = { 25 + { 0x00, "Z1" }, 26 + { 0x03, "Z2" }, 27 + { 0x04, "Z21" }, 28 + { 0x08, "A1" }, 29 + { 0x09, "A2" }, 30 + { 0x0a, "A3" }, 31 + {} 32 + }; 33 + 34 + static const char * __init get_revision(unsigned int rev) 35 + { 36 + int i; 37 + 38 + for (i = 0; revisions[i].name; i++) 39 + if (revisions[i].number == rev) 40 + return revisions[i].name; 41 + return NULL; 42 + } 43 + 44 + static struct soc_device_attribute *wpcm450_attr; 45 + static struct soc_device *wpcm450_soc; 46 + 47 + static int __init wpcm450_soc_init(void) 48 + { 49 + struct soc_device_attribute *attr; 50 + struct soc_device *soc; 51 + const char *revision; 52 + struct regmap *gcr; 53 + u32 pdid; 54 + int ret; 55 + 56 + if (!of_machine_is_compatible("nuvoton,wpcm450")) 57 + return 0; 58 + 59 + gcr = syscon_regmap_lookup_by_compatible("nuvoton,wpcm450-gcr"); 60 + if (IS_ERR(gcr)) 61 + return PTR_ERR(gcr); 62 + ret = regmap_read(gcr, GCR_PDID, &pdid); 63 + if (ret) 64 + return ret; 65 + 66 + if (PDID_CHIP(pdid) != CHIP_WPCM450) { 67 + pr_warn("Unknown chip ID in GCR.PDID: 0x%06x\n", PDID_CHIP(pdid)); 68 + return -ENODEV; 69 + } 70 + 71 + revision = get_revision(PDID_REV(pdid)); 72 + if (!revision) { 73 + pr_warn("Unknown chip revision in GCR.PDID: 0x%02x\n", PDID_REV(pdid)); 74 + return -ENODEV; 75 + } 76 + 77 + attr = kzalloc(sizeof(*attr), GFP_KERNEL); 78 + if (!attr) 79 + return -ENOMEM; 80 + 81 + attr->family = "Nuvoton NPCM"; 82 + attr->soc_id = "WPCM450"; 83 + attr->revision = revision; 84 + soc = soc_device_register(attr); 85 + if (IS_ERR(soc)) { 86 + kfree(attr); 87 + pr_warn("Could not register SoC device\n"); 88 + return PTR_ERR(soc); 89 + } 90 + 91 + wpcm450_soc = soc; 92 + wpcm450_attr = attr; 93 + return 0; 94 + } 95 + module_init(wpcm450_soc_init); 96 + 97 + static void __exit wpcm450_soc_exit(void) 98 + { 99 + if (wpcm450_soc) { 100 + soc_device_unregister(wpcm450_soc); 101 + wpcm450_soc = NULL; 102 + kfree(wpcm450_attr); 103 + } 104 + } 105 + module_exit(wpcm450_soc_exit); 106 + 107 + MODULE_LICENSE("GPL"); 108 + MODULE_AUTHOR("Jonathan Neuschäfer"); 109 + MODULE_DESCRIPTION("Nuvoton WPCM450 SoC Identification driver");
+27
drivers/soc/qcom/Kconfig
··· 91 91 config QCOM_PDR_HELPERS 92 92 tristate 93 93 select QCOM_QMI_HELPERS 94 + depends on NET 95 + 96 + config QCOM_PMIC_GLINK 97 + tristate "Qualcomm PMIC GLINK driver" 98 + depends on RPMSG 99 + depends on TYPEC 100 + depends on DRM 101 + depends on NET 102 + depends on OF 103 + select AUXILIARY_BUS 104 + select QCOM_PDR_HELPERS 105 + help 106 + The Qualcomm PMIC GLINK driver provides access, over GLINK, to the 107 + USB and battery firmware running on one of the coprocessors in 108 + several modern Qualcomm platforms. 109 + 110 + Say yes here to support USB-C and battery status on modern Qualcomm 111 + platforms. 94 112 95 113 config QCOM_QMI_HELPERS 96 114 tristate 97 115 depends on NET 116 + 117 + config QCOM_RAMP_CTRL 118 + tristate "Qualcomm Ramp Controller driver" 119 + depends on ARCH_QCOM || COMPILE_TEST 120 + help 121 + The Ramp Controller is used to program the sequence ID for pulse 122 + swallowing, enable sequence and link sequence IDs for the CPU 123 + cores on some Qualcomm SoCs. 124 + Say y here to enable support for the ramp controller. 98 125 99 126 config QCOM_RMTFS_MEM 100 127 tristate "Qualcomm Remote Filesystem memory driver"
+3
drivers/soc/qcom/Makefile
··· 8 8 obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o 9 9 obj-$(CONFIG_QCOM_OCMEM) += ocmem.o 10 10 obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o 11 + obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o 12 + obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o 11 13 obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o 12 14 qmi_helpers-y += qmi_encdec.o qmi_interface.o 15 + obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o 13 16 obj-$(CONFIG_QCOM_RMTFS_MEM) += rmtfs_mem.o 14 17 obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o 15 18 qcom_rpmh-y += rpmh-rsc.o
+1 -1
drivers/soc/qcom/mdt_loader.c
··· 12 12 #include <linux/firmware.h> 13 13 #include <linux/kernel.h> 14 14 #include <linux/module.h> 15 - #include <linux/qcom_scm.h> 15 + #include <linux/firmware/qcom/qcom_scm.h> 16 16 #include <linux/sizes.h> 17 17 #include <linux/slab.h> 18 18 #include <linux/soc/qcom/mdt_loader.h>
+1 -1
drivers/soc/qcom/ocmem.c
··· 16 16 #include <linux/module.h> 17 17 #include <linux/of_device.h> 18 18 #include <linux/platform_device.h> 19 - #include <linux/qcom_scm.h> 19 + #include <linux/firmware/qcom/qcom_scm.h> 20 20 #include <linux/sizes.h> 21 21 #include <linux/slab.h> 22 22 #include <linux/types.h>
+336
drivers/soc/qcom/pmic_glink.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. 4 + * Copyright (c) 2022, Linaro Ltd 5 + */ 6 + #include <linux/auxiliary_bus.h> 7 + #include <linux/module.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/rpmsg.h> 10 + #include <linux/slab.h> 11 + #include <linux/soc/qcom/pdr.h> 12 + #include <linux/soc/qcom/pmic_glink.h> 13 + 14 + struct pmic_glink { 15 + struct device *dev; 16 + struct pdr_handle *pdr; 17 + 18 + struct rpmsg_endpoint *ept; 19 + 20 + struct auxiliary_device altmode_aux; 21 + struct auxiliary_device ps_aux; 22 + struct auxiliary_device ucsi_aux; 23 + 24 + /* serializing client_state and pdr_state updates */ 25 + struct mutex state_lock; 26 + unsigned int client_state; 27 + unsigned int pdr_state; 28 + 29 + /* serializing clients list updates */ 30 + struct mutex client_lock; 31 + struct list_head clients; 32 + }; 33 + 34 + static struct pmic_glink *__pmic_glink; 35 + static DEFINE_MUTEX(__pmic_glink_lock); 36 + 37 + struct pmic_glink_client { 38 + struct list_head node; 39 + 40 + struct pmic_glink *pg; 41 + unsigned int id; 42 + 43 + void (*cb)(const void *data, size_t len, void *priv); 44 + void (*pdr_notify)(void *priv, int state); 45 + void *priv; 46 + }; 47 + 48 + static void _devm_pmic_glink_release_client(struct device *dev, void *res) 49 + { 50 + struct pmic_glink_client *client = (struct pmic_glink_client *)res; 51 + struct pmic_glink *pg = client->pg; 52 + 53 + mutex_lock(&pg->client_lock); 54 + list_del(&client->node); 55 + mutex_unlock(&pg->client_lock); 56 + } 57 + 58 + struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev, 59 + unsigned int id, 60 + void (*cb)(const void *, size_t, void *), 61 + void (*pdr)(void *, int), 62 + void *priv) 63 + { 64 + struct pmic_glink_client *client; 65 + struct pmic_glink *pg = dev_get_drvdata(dev->parent); 66 + 67 + client = devres_alloc(_devm_pmic_glink_release_client, sizeof(*client), GFP_KERNEL); 68 + if (!client) 69 + return ERR_PTR(-ENOMEM); 70 + 71 + client->pg = pg; 72 + client->id = id; 73 + client->cb = cb; 74 + client->pdr_notify = pdr; 75 + client->priv = priv; 76 + 77 + mutex_lock(&pg->client_lock); 78 + list_add(&client->node, &pg->clients); 79 + mutex_unlock(&pg->client_lock); 80 + 81 + devres_add(dev, client); 82 + 83 + return client; 84 + } 85 + EXPORT_SYMBOL_GPL(devm_pmic_glink_register_client); 86 + 87 + int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len) 88 + { 89 + struct pmic_glink *pg = client->pg; 90 + 91 + return rpmsg_send(pg->ept, data, len); 92 + } 93 + EXPORT_SYMBOL_GPL(pmic_glink_send); 94 + 95 + static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data, 96 + int len, void *priv, u32 addr) 97 + { 98 + struct pmic_glink_client *client; 99 + struct pmic_glink_hdr *hdr; 100 + struct pmic_glink *pg = dev_get_drvdata(&rpdev->dev); 101 + 102 + if (len < sizeof(*hdr)) { 103 + dev_warn(pg->dev, "ignoring truncated message\n"); 104 + return 0; 105 + } 106 + 107 + hdr = data; 108 + 109 + list_for_each_entry(client, &pg->clients, node) { 110 + if (client->id == le32_to_cpu(hdr->owner)) 111 + client->cb(data, len, client->priv); 112 + } 113 + 114 + return 0; 115 + } 116 + 117 + static void pmic_glink_aux_release(struct device *dev) {} 118 + 119 + static int pmic_glink_add_aux_device(struct pmic_glink *pg, 120 + struct auxiliary_device *aux, 121 + const char *name) 122 + { 123 + struct device *parent = pg->dev; 124 + int ret; 125 + 126 + aux->name = name; 127 + aux->dev.parent = parent; 128 + aux->dev.release = pmic_glink_aux_release; 129 + device_set_of_node_from_dev(&aux->dev, parent); 130 + ret = auxiliary_device_init(aux); 131 + if (ret) 132 + return ret; 133 + 134 + ret = auxiliary_device_add(aux); 135 + if (ret) 136 + auxiliary_device_uninit(aux); 137 + 138 + return ret; 139 + } 140 + 141 + static void pmic_glink_del_aux_device(struct pmic_glink *pg, 142 + struct auxiliary_device *aux) 143 + { 144 + auxiliary_device_delete(aux); 145 + auxiliary_device_uninit(aux); 146 + } 147 + 148 + static void pmic_glink_state_notify_clients(struct pmic_glink *pg) 149 + { 150 + struct pmic_glink_client *client; 151 + unsigned int new_state = pg->client_state; 152 + 153 + if (pg->client_state != SERVREG_SERVICE_STATE_UP) { 154 + if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept) 155 + new_state = SERVREG_SERVICE_STATE_UP; 156 + } else { 157 + if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept) 158 + new_state = SERVREG_SERVICE_STATE_DOWN; 159 + } 160 + 161 + if (new_state != pg->client_state) { 162 + list_for_each_entry(client, &pg->clients, node) 163 + client->pdr_notify(client->priv, new_state); 164 + pg->client_state = new_state; 165 + } 166 + } 167 + 168 + static void pmic_glink_pdr_callback(int state, char *svc_path, void *priv) 169 + { 170 + struct pmic_glink *pg = priv; 171 + 172 + mutex_lock(&pg->state_lock); 173 + pg->pdr_state = state; 174 + 175 + pmic_glink_state_notify_clients(pg); 176 + mutex_unlock(&pg->state_lock); 177 + } 178 + 179 + static int pmic_glink_rpmsg_probe(struct rpmsg_device *rpdev) 180 + { 181 + struct pmic_glink *pg = __pmic_glink; 182 + int ret = 0; 183 + 184 + mutex_lock(&__pmic_glink_lock); 185 + if (!pg) { 186 + ret = dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n"); 187 + goto out_unlock; 188 + } 189 + 190 + dev_set_drvdata(&rpdev->dev, pg); 191 + 192 + mutex_lock(&pg->state_lock); 193 + pg->ept = rpdev->ept; 194 + pmic_glink_state_notify_clients(pg); 195 + mutex_unlock(&pg->state_lock); 196 + 197 + out_unlock: 198 + mutex_unlock(&__pmic_glink_lock); 199 + return ret; 200 + } 201 + 202 + static void pmic_glink_rpmsg_remove(struct rpmsg_device *rpdev) 203 + { 204 + struct pmic_glink *pg; 205 + 206 + mutex_lock(&__pmic_glink_lock); 207 + pg = __pmic_glink; 208 + if (!pg) 209 + goto out_unlock; 210 + 211 + mutex_lock(&pg->state_lock); 212 + pg->ept = NULL; 213 + pmic_glink_state_notify_clients(pg); 214 + mutex_unlock(&pg->state_lock); 215 + out_unlock: 216 + mutex_unlock(&__pmic_glink_lock); 217 + } 218 + 219 + static const struct rpmsg_device_id pmic_glink_rpmsg_id_match[] = { 220 + { "PMIC_RTR_ADSP_APPS" }, 221 + {} 222 + }; 223 + 224 + static struct rpmsg_driver pmic_glink_rpmsg_driver = { 225 + .probe = pmic_glink_rpmsg_probe, 226 + .remove = pmic_glink_rpmsg_remove, 227 + .callback = pmic_glink_rpmsg_callback, 228 + .id_table = pmic_glink_rpmsg_id_match, 229 + .drv = { 230 + .name = "qcom_pmic_glink_rpmsg", 231 + }, 232 + }; 233 + 234 + static int pmic_glink_probe(struct platform_device *pdev) 235 + { 236 + struct pdr_service *service; 237 + struct pmic_glink *pg; 238 + int ret; 239 + 240 + pg = devm_kzalloc(&pdev->dev, sizeof(*pg), GFP_KERNEL); 241 + if (!pg) 242 + return -ENOMEM; 243 + 244 + dev_set_drvdata(&pdev->dev, pg); 245 + 246 + pg->dev = &pdev->dev; 247 + 248 + INIT_LIST_HEAD(&pg->clients); 249 + mutex_init(&pg->client_lock); 250 + mutex_init(&pg->state_lock); 251 + 252 + ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode"); 253 + if (ret) 254 + return ret; 255 + ret = pmic_glink_add_aux_device(pg, &pg->ps_aux, "power-supply"); 256 + if (ret) 257 + goto out_release_altmode_aux; 258 + 259 + pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg); 260 + if (IS_ERR(pg->pdr)) { 261 + ret = dev_err_probe(&pdev->dev, PTR_ERR(pg->pdr), "failed to initialize pdr\n"); 262 + goto out_release_aux_devices; 263 + } 264 + 265 + service = pdr_add_lookup(pg->pdr, "tms/servreg", "msm/adsp/charger_pd"); 266 + if (IS_ERR(service)) { 267 + ret = dev_err_probe(&pdev->dev, PTR_ERR(service), 268 + "failed adding pdr lookup for charger_pd\n"); 269 + goto out_release_pdr_handle; 270 + } 271 + 272 + mutex_lock(&__pmic_glink_lock); 273 + __pmic_glink = pg; 274 + mutex_unlock(&__pmic_glink_lock); 275 + 276 + return 0; 277 + 278 + out_release_pdr_handle: 279 + pdr_handle_release(pg->pdr); 280 + out_release_aux_devices: 281 + pmic_glink_del_aux_device(pg, &pg->ps_aux); 282 + out_release_altmode_aux: 283 + pmic_glink_del_aux_device(pg, &pg->altmode_aux); 284 + 285 + return ret; 286 + } 287 + 288 + static int pmic_glink_remove(struct platform_device *pdev) 289 + { 290 + struct pmic_glink *pg = dev_get_drvdata(&pdev->dev); 291 + 292 + pdr_handle_release(pg->pdr); 293 + 294 + pmic_glink_del_aux_device(pg, &pg->ps_aux); 295 + pmic_glink_del_aux_device(pg, &pg->altmode_aux); 296 + 297 + mutex_lock(&__pmic_glink_lock); 298 + __pmic_glink = NULL; 299 + mutex_unlock(&__pmic_glink_lock); 300 + 301 + return 0; 302 + } 303 + 304 + static const struct of_device_id pmic_glink_of_match[] = { 305 + { .compatible = "qcom,pmic-glink", }, 306 + {} 307 + }; 308 + MODULE_DEVICE_TABLE(of, pmic_glink_of_match); 309 + 310 + static struct platform_driver pmic_glink_driver = { 311 + .probe = pmic_glink_probe, 312 + .remove = pmic_glink_remove, 313 + .driver = { 314 + .name = "qcom_pmic_glink", 315 + .of_match_table = pmic_glink_of_match, 316 + }, 317 + }; 318 + 319 + static int pmic_glink_init(void) 320 + { 321 + platform_driver_register(&pmic_glink_driver); 322 + register_rpmsg_driver(&pmic_glink_rpmsg_driver); 323 + 324 + return 0; 325 + }; 326 + module_init(pmic_glink_init); 327 + 328 + static void pmic_glink_exit(void) 329 + { 330 + unregister_rpmsg_driver(&pmic_glink_rpmsg_driver); 331 + platform_driver_unregister(&pmic_glink_driver); 332 + }; 333 + module_exit(pmic_glink_exit); 334 + 335 + MODULE_DESCRIPTION("Qualcomm PMIC GLINK driver"); 336 + MODULE_LICENSE("GPL");
+2 -8
drivers/soc/qcom/qcom_stats.c
··· 92 92 /* Items are allocated lazily, so lookup pointer each time */ 93 93 stat = qcom_smem_get(subsystem->pid, subsystem->smem_item, NULL); 94 94 if (IS_ERR(stat)) 95 - return -EIO; 95 + return 0; 96 96 97 97 qcom_print_stats(s, stat); 98 98 ··· 170 170 static void qcom_create_subsystem_stat_files(struct dentry *root, 171 171 const struct stats_config *config) 172 172 { 173 - const struct sleep_stats *stat; 174 173 int i; 175 174 176 175 if (!config->subsystem_stats_in_smem) 177 176 return; 178 177 179 - for (i = 0; i < ARRAY_SIZE(subsystems); i++) { 180 - stat = qcom_smem_get(subsystems[i].pid, subsystems[i].smem_item, NULL); 181 - if (IS_ERR(stat)) 182 - continue; 183 - 178 + for (i = 0; i < ARRAY_SIZE(subsystems); i++) 184 179 debugfs_create_file(subsystems[i].name, 0400, root, (void *)&subsystems[i], 185 180 &qcom_subsystem_sleep_stats_fops); 186 - } 187 181 } 188 182 189 183 static int qcom_stats_probe(struct platform_device *pdev)
+343
drivers/soc/qcom/ramp_controller.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Qualcomm Ramp Controller driver 4 + * Copyright (c) 2022, AngeloGioacchino Del Regno 5 + * <angelogioacchino.delregno@collabora.com> 6 + */ 7 + 8 + #include <linux/bitfield.h> 9 + #include <linux/kernel.h> 10 + #include <linux/module.h> 11 + #include <linux/of.h> 12 + #include <linux/of_platform.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/regmap.h> 15 + #include <linux/types.h> 16 + 17 + #define RC_UPDATE_EN BIT(0) 18 + #define RC_ROOT_EN BIT(1) 19 + 20 + #define RC_REG_CFG_UPDATE 0x60 21 + #define RC_CFG_UPDATE_EN BIT(8) 22 + #define RC_CFG_ACK GENMASK(31, 16) 23 + 24 + #define RC_DCVS_CFG_SID 2 25 + #define RC_LINK_SID 3 26 + #define RC_LMH_SID 6 27 + #define RC_DFS_SID 14 28 + 29 + #define RC_UPDATE_TIMEOUT_US 500 30 + 31 + /** 32 + * struct qcom_ramp_controller_desc - SoC specific parameters 33 + * @cfg_dfs_sid: Dynamic Frequency Scaling SID configuration 34 + * @cfg_link_sid: Link SID configuration 35 + * @cfg_lmh_sid: Limits Management hardware SID configuration 36 + * @cfg_ramp_en: Ramp Controller enable sequence 37 + * @cfg_ramp_dis: Ramp Controller disable sequence 38 + * @cmd_reg: Command register offset 39 + * @num_dfs_sids: Number of DFS SIDs (max 8) 40 + * @num_link_sids: Number of Link SIDs (max 3) 41 + * @num_lmh_sids: Number of LMh SIDs (max 8) 42 + * @num_ramp_en: Number of entries in enable sequence 43 + * @num_ramp_dis: Number of entries in disable sequence 44 + */ 45 + struct qcom_ramp_controller_desc { 46 + const struct reg_sequence *cfg_dfs_sid; 47 + const struct reg_sequence *cfg_link_sid; 48 + const struct reg_sequence *cfg_lmh_sid; 49 + const struct reg_sequence *cfg_ramp_en; 50 + const struct reg_sequence *cfg_ramp_dis; 51 + u8 cmd_reg; 52 + u8 num_dfs_sids; 53 + u8 num_link_sids; 54 + u8 num_lmh_sids; 55 + u8 num_ramp_en; 56 + u8 num_ramp_dis; 57 + }; 58 + 59 + /** 60 + * struct qcom_ramp_controller - Main driver structure 61 + * @regmap: Regmap handle 62 + * @desc: SoC specific parameters 63 + */ 64 + struct qcom_ramp_controller { 65 + struct regmap *regmap; 66 + const struct qcom_ramp_controller_desc *desc; 67 + }; 68 + 69 + /** 70 + * rc_wait_for_update() - Wait for Ramp Controller root update 71 + * @qrc: Main driver structure 72 + * 73 + * Return: Zero for success or negative number for failure 74 + */ 75 + static int rc_wait_for_update(struct qcom_ramp_controller *qrc) 76 + { 77 + const struct qcom_ramp_controller_desc *d = qrc->desc; 78 + struct regmap *r = qrc->regmap; 79 + u32 val; 80 + int ret; 81 + 82 + ret = regmap_set_bits(r, d->cmd_reg, RC_ROOT_EN); 83 + if (ret) 84 + return ret; 85 + 86 + return regmap_read_poll_timeout(r, d->cmd_reg, val, !(val & RC_UPDATE_EN), 87 + 1, RC_UPDATE_TIMEOUT_US); 88 + } 89 + 90 + /** 91 + * rc_set_cfg_update() - Ramp Controller configuration update 92 + * @qrc: Main driver structure 93 + * @ce: Configuration entry to update 94 + * 95 + * Return: Zero for success or negative number for failure 96 + */ 97 + static int rc_set_cfg_update(struct qcom_ramp_controller *qrc, u8 ce) 98 + { 99 + const struct qcom_ramp_controller_desc *d = qrc->desc; 100 + struct regmap *r = qrc->regmap; 101 + u32 ack, val; 102 + int ret; 103 + 104 + /* The ack bit is between bits 16-31 of RC_REG_CFG_UPDATE */ 105 + ack = FIELD_PREP(RC_CFG_ACK, BIT(ce)); 106 + 107 + /* Write the configuration type first... */ 108 + ret = regmap_set_bits(r, d->cmd_reg + RC_REG_CFG_UPDATE, ce); 109 + if (ret) 110 + return ret; 111 + 112 + /* ...and after that, enable the update bit to sync the changes */ 113 + ret = regmap_set_bits(r, d->cmd_reg + RC_REG_CFG_UPDATE, RC_CFG_UPDATE_EN); 114 + if (ret) 115 + return ret; 116 + 117 + /* Wait for the changes to go through */ 118 + ret = regmap_read_poll_timeout(r, d->cmd_reg + RC_REG_CFG_UPDATE, val, 119 + val & ack, 1, RC_UPDATE_TIMEOUT_US); 120 + if (ret) 121 + return ret; 122 + 123 + /* 124 + * Configuration update success! The CFG_UPDATE register will not be 125 + * cleared automatically upon applying the configuration, so we have 126 + * to do that manually in order to leave the ramp controller in a 127 + * predictable and clean state. 128 + */ 129 + ret = regmap_write(r, d->cmd_reg + RC_REG_CFG_UPDATE, 0); 130 + if (ret) 131 + return ret; 132 + 133 + /* Wait for the update bit cleared ack */ 134 + return regmap_read_poll_timeout(r, d->cmd_reg + RC_REG_CFG_UPDATE, 135 + val, !(val & RC_CFG_ACK), 1, 136 + RC_UPDATE_TIMEOUT_US); 137 + } 138 + 139 + /** 140 + * rc_write_cfg - Send configuration sequence 141 + * @qrc: Main driver structure 142 + * @seq: Register sequence to send before asking for update 143 + * @ce: Configuration SID 144 + * @nsids: Total number of SIDs 145 + * 146 + * Returns: Zero for success or negative number for error 147 + */ 148 + static int rc_write_cfg(struct qcom_ramp_controller *qrc, 149 + const struct reg_sequence *seq, 150 + u16 ce, u8 nsids) 151 + { 152 + int ret; 153 + u8 i; 154 + 155 + /* Check if, and wait until the ramp controller is ready */ 156 + ret = rc_wait_for_update(qrc); 157 + if (ret) 158 + return ret; 159 + 160 + /* Write the sequence */ 161 + ret = regmap_multi_reg_write(qrc->regmap, seq, nsids); 162 + if (ret) 163 + return ret; 164 + 165 + /* Pull the trigger: do config update starting from the last sid */ 166 + for (i = 0; i < nsids; i++) { 167 + ret = rc_set_cfg_update(qrc, (u8)ce - i); 168 + if (ret) 169 + return ret; 170 + } 171 + 172 + return 0; 173 + } 174 + 175 + /** 176 + * rc_ramp_ctrl_enable() - Enable Ramp up/down Control 177 + * @qrc: Main driver structure 178 + * 179 + * Return: Zero for success or negative number for error 180 + */ 181 + static int rc_ramp_ctrl_enable(struct qcom_ramp_controller *qrc) 182 + { 183 + const struct qcom_ramp_controller_desc *d = qrc->desc; 184 + int i, ret; 185 + 186 + for (i = 0; i < d->num_ramp_en; i++) { 187 + ret = rc_write_cfg(qrc, &d->cfg_ramp_en[i], RC_DCVS_CFG_SID, 1); 188 + if (ret) 189 + return ret; 190 + } 191 + 192 + return 0; 193 + } 194 + 195 + /** 196 + * qcom_ramp_controller_start() - Initialize and start the ramp controller 197 + * @qrc: Main driver structure 198 + * 199 + * The Ramp Controller needs to be initialized by programming the relevant 200 + * registers with SoC-specific configuration: once programming is done, 201 + * the hardware will take care of the rest (no further handling required). 202 + * 203 + * Return: Zero for success or negative number for error 204 + */ 205 + static int qcom_ramp_controller_start(struct qcom_ramp_controller *qrc) 206 + { 207 + const struct qcom_ramp_controller_desc *d = qrc->desc; 208 + int ret; 209 + 210 + /* Program LMH, DFS, Link SIDs */ 211 + ret = rc_write_cfg(qrc, d->cfg_lmh_sid, RC_LMH_SID, d->num_lmh_sids); 212 + if (ret) 213 + return ret; 214 + 215 + ret = rc_write_cfg(qrc, d->cfg_dfs_sid, RC_DFS_SID, d->num_dfs_sids); 216 + if (ret) 217 + return ret; 218 + 219 + ret = rc_write_cfg(qrc, d->cfg_link_sid, RC_LINK_SID, d->num_link_sids); 220 + if (ret) 221 + return ret; 222 + 223 + /* Everything is ready! Enable the ramp up/down control */ 224 + return rc_ramp_ctrl_enable(qrc); 225 + } 226 + 227 + static const struct regmap_config qrc_regmap_config = { 228 + .reg_bits = 32, 229 + .reg_stride = 4, 230 + .val_bits = 32, 231 + .max_register = 0x68, 232 + .fast_io = true, 233 + }; 234 + 235 + static const struct reg_sequence msm8976_cfg_dfs_sid[] = { 236 + { 0x10, 0xfefebff7 }, 237 + { 0x14, 0xfdff7fef }, 238 + { 0x18, 0xfbffdefb }, 239 + { 0x1c, 0xb69b5555 }, 240 + { 0x20, 0x24929249 }, 241 + { 0x24, 0x49241112 }, 242 + { 0x28, 0x11112111 }, 243 + { 0x2c, 0x8102 } 244 + }; 245 + 246 + static const struct reg_sequence msm8976_cfg_link_sid[] = { 247 + { 0x40, 0xfc987 } 248 + }; 249 + 250 + static const struct reg_sequence msm8976_cfg_lmh_sid[] = { 251 + { 0x30, 0x77706db }, 252 + { 0x34, 0x5550249 }, 253 + { 0x38, 0x111 } 254 + }; 255 + 256 + static const struct reg_sequence msm8976_cfg_ramp_en[] = { 257 + { 0x50, 0x800 }, /* pre_en */ 258 + { 0x50, 0xc00 }, /* en */ 259 + { 0x50, 0x400 } /* post_en */ 260 + }; 261 + 262 + static const struct reg_sequence msm8976_cfg_ramp_dis[] = { 263 + { 0x50, 0x0 } 264 + }; 265 + 266 + static const struct qcom_ramp_controller_desc msm8976_rc_cfg = { 267 + .cfg_dfs_sid = msm8976_cfg_dfs_sid, 268 + .num_dfs_sids = ARRAY_SIZE(msm8976_cfg_dfs_sid), 269 + 270 + .cfg_link_sid = msm8976_cfg_link_sid, 271 + .num_link_sids = ARRAY_SIZE(msm8976_cfg_link_sid), 272 + 273 + .cfg_lmh_sid = msm8976_cfg_lmh_sid, 274 + .num_lmh_sids = ARRAY_SIZE(msm8976_cfg_lmh_sid), 275 + 276 + .cfg_ramp_en = msm8976_cfg_ramp_en, 277 + .num_ramp_en = ARRAY_SIZE(msm8976_cfg_ramp_en), 278 + 279 + .cfg_ramp_dis = msm8976_cfg_ramp_dis, 280 + .num_ramp_dis = ARRAY_SIZE(msm8976_cfg_ramp_dis), 281 + 282 + .cmd_reg = 0x0, 283 + }; 284 + 285 + static int qcom_ramp_controller_probe(struct platform_device *pdev) 286 + { 287 + struct qcom_ramp_controller *qrc; 288 + void __iomem *base; 289 + 290 + base = devm_platform_ioremap_resource(pdev, 0); 291 + if (IS_ERR(base)) 292 + return PTR_ERR(base); 293 + 294 + qrc = devm_kmalloc(&pdev->dev, sizeof(*qrc), GFP_KERNEL); 295 + if (!qrc) 296 + return -ENOMEM; 297 + 298 + qrc->desc = device_get_match_data(&pdev->dev); 299 + if (!qrc) 300 + return -EINVAL; 301 + 302 + qrc->regmap = devm_regmap_init_mmio(&pdev->dev, base, &qrc_regmap_config); 303 + if (IS_ERR(qrc->regmap)) 304 + return PTR_ERR(qrc->regmap); 305 + 306 + platform_set_drvdata(pdev, qrc); 307 + 308 + return qcom_ramp_controller_start(qrc); 309 + } 310 + 311 + static int qcom_ramp_controller_remove(struct platform_device *pdev) 312 + { 313 + struct qcom_ramp_controller *qrc = platform_get_drvdata(pdev); 314 + 315 + return rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis, 316 + RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis); 317 + } 318 + 319 + static const struct of_device_id qcom_ramp_controller_match_table[] = { 320 + { .compatible = "qcom,msm8976-ramp-controller", .data = &msm8976_rc_cfg }, 321 + { /* sentinel */ } 322 + }; 323 + MODULE_DEVICE_TABLE(of, qcom_ramp_controller_match_table); 324 + 325 + static struct platform_driver qcom_ramp_controller_driver = { 326 + .driver = { 327 + .name = "qcom-ramp-controller", 328 + .of_match_table = qcom_ramp_controller_match_table, 329 + .suppress_bind_attrs = true, 330 + }, 331 + .probe = qcom_ramp_controller_probe, 332 + .remove = qcom_ramp_controller_remove, 333 + }; 334 + 335 + static int __init qcom_ramp_controller_init(void) 336 + { 337 + return platform_driver_register(&qcom_ramp_controller_driver); 338 + } 339 + arch_initcall(qcom_ramp_controller_init); 340 + 341 + MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>"); 342 + MODULE_DESCRIPTION("Qualcomm Ramp Controller driver"); 343 + MODULE_LICENSE("GPL");
+23 -8
drivers/soc/qcom/rmtfs_mem.c
··· 14 14 #include <linux/slab.h> 15 15 #include <linux/uaccess.h> 16 16 #include <linux/io.h> 17 - #include <linux/qcom_scm.h> 17 + #include <linux/firmware/qcom/qcom_scm.h> 18 18 19 19 #define QCOM_RMTFS_MEM_DEV_MAX (MINORMASK + 1) 20 + #define NUM_MAX_VMIDS 2 20 21 21 22 static dev_t qcom_rmtfs_mem_major; 22 23 ··· 172 171 static int qcom_rmtfs_mem_probe(struct platform_device *pdev) 173 172 { 174 173 struct device_node *node = pdev->dev.of_node; 175 - struct qcom_scm_vmperm perms[2]; 174 + struct qcom_scm_vmperm perms[NUM_MAX_VMIDS + 1]; 176 175 struct reserved_mem *rmem; 177 176 struct qcom_rmtfs_mem *rmtfs_mem; 178 177 u32 client_id; 179 - u32 vmid; 180 - int ret; 178 + u32 num_vmids, vmid[NUM_MAX_VMIDS]; 179 + int ret, i; 181 180 182 181 rmem = of_reserved_mem_lookup(node); 183 182 if (!rmem) { ··· 227 226 goto put_device; 228 227 } 229 228 230 - ret = of_property_read_u32(node, "qcom,vmid", &vmid); 229 + num_vmids = of_property_count_u32_elems(node, "qcom,vmid"); 230 + if (num_vmids < 0) { 231 + dev_err(&pdev->dev, "failed to count qcom,vmid elements: %d\n", ret); 232 + goto remove_cdev; 233 + } else if (num_vmids > NUM_MAX_VMIDS) { 234 + dev_warn(&pdev->dev, 235 + "too many VMIDs (%d) specified! Only mapping first %d entries\n", 236 + num_vmids, NUM_MAX_VMIDS); 237 + num_vmids = NUM_MAX_VMIDS; 238 + } 239 + 240 + ret = of_property_read_u32_array(node, "qcom,vmid", vmid, num_vmids); 231 241 if (ret < 0 && ret != -EINVAL) { 232 242 dev_err(&pdev->dev, "failed to parse qcom,vmid\n"); 233 243 goto remove_cdev; ··· 250 238 251 239 perms[0].vmid = QCOM_SCM_VMID_HLOS; 252 240 perms[0].perm = QCOM_SCM_PERM_RW; 253 - perms[1].vmid = vmid; 254 - perms[1].perm = QCOM_SCM_PERM_RW; 241 + 242 + for (i = 0; i < num_vmids; i++) { 243 + perms[i + 1].vmid = vmid[i]; 244 + perms[i + 1].perm = QCOM_SCM_PERM_RW; 245 + } 255 246 256 247 rmtfs_mem->perms = BIT(QCOM_SCM_VMID_HLOS); 257 248 ret = qcom_scm_assign_mem(rmtfs_mem->addr, rmtfs_mem->size, 258 - &rmtfs_mem->perms, perms, 2); 249 + &rmtfs_mem->perms, perms, num_vmids + 1); 259 250 if (ret < 0) { 260 251 dev_err(&pdev->dev, "assign memory failed\n"); 261 252 goto remove_cdev;
+34
drivers/soc/qcom/rpmhpd.c
··· 187 187 .res_name = "nsp.lvl", 188 188 }; 189 189 190 + static struct rpmhpd nsp0 = { 191 + .pd = { .name = "nsp0", }, 192 + .res_name = "nsp0.lvl", 193 + }; 194 + 195 + static struct rpmhpd nsp1 = { 196 + .pd = { .name = "nsp1", }, 197 + .res_name = "nsp1.lvl", 198 + }; 199 + 190 200 static struct rpmhpd qphy = { 191 201 .pd = { .name = "qphy", }, 192 202 .res_name = "qphy.lvl", ··· 220 210 static const struct rpmhpd_desc sa8540p_desc = { 221 211 .rpmhpds = sa8540p_rpmhpds, 222 212 .num_pds = ARRAY_SIZE(sa8540p_rpmhpds), 213 + }; 214 + 215 + /* SA8775P RPMH power domains */ 216 + static struct rpmhpd *sa8775p_rpmhpds[] = { 217 + [SA8775P_CX] = &cx, 218 + [SA8775P_CX_AO] = &cx_ao, 219 + [SA8775P_EBI] = &ebi, 220 + [SA8775P_GFX] = &gfx, 221 + [SA8775P_LCX] = &lcx, 222 + [SA8775P_LMX] = &lmx, 223 + [SA8775P_MMCX] = &mmcx, 224 + [SA8775P_MMCX_AO] = &mmcx_ao, 225 + [SA8775P_MXC] = &mxc, 226 + [SA8775P_MXC_AO] = &mxc_ao, 227 + [SA8775P_MX] = &mx, 228 + [SA8775P_MX_AO] = &mx_ao, 229 + [SA8775P_NSP0] = &nsp0, 230 + [SA8775P_NSP1] = &nsp1, 231 + }; 232 + 233 + static const struct rpmhpd_desc sa8775p_desc = { 234 + .rpmhpds = sa8775p_rpmhpds, 235 + .num_pds = ARRAY_SIZE(sa8775p_rpmhpds), 223 236 }; 224 237 225 238 /* SDM670 RPMH powerdomains */ ··· 520 487 static const struct of_device_id rpmhpd_match_table[] = { 521 488 { .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc }, 522 489 { .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc }, 490 + { .compatible = "qcom,sa8775p-rpmhpd", .data = &sa8775p_desc }, 523 491 { .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc }, 524 492 { .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_desc }, 525 493 { .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc },
-18
drivers/soc/qcom/rpmpd.c
··· 471 471 .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, 472 472 }; 473 473 474 - static struct rpmpd *sm4250_rpmpds[] = { 475 - [SM4250_VDDCX] = &sm6115_vddcx, 476 - [SM4250_VDDCX_AO] = &sm6115_vddcx_ao, 477 - [SM4250_VDDCX_VFL] = &sm6115_vddcx_vfl, 478 - [SM4250_VDDMX] = &sm6115_vddmx, 479 - [SM4250_VDDMX_AO] = &sm6115_vddmx_ao, 480 - [SM4250_VDDMX_VFL] = &sm6115_vddmx_vfl, 481 - [SM4250_VDD_LPI_CX] = &sm6115_vdd_lpi_cx, 482 - [SM4250_VDD_LPI_MX] = &sm6115_vdd_lpi_mx, 483 - }; 484 - 485 - static const struct rpmpd_desc sm4250_desc = { 486 - .rpmpds = sm4250_rpmpds, 487 - .num_pds = ARRAY_SIZE(sm4250_rpmpds), 488 - .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, 489 - }; 490 - 491 474 static const struct of_device_id rpmpd_match_table[] = { 492 475 { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc }, 493 476 { .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc }, ··· 485 502 { .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc }, 486 503 { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc }, 487 504 { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc }, 488 - { .compatible = "qcom,sm4250-rpmpd", .data = &sm4250_desc }, 489 505 { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc }, 490 506 { .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc }, 491 507 { .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc },
+1
drivers/soc/qcom/smd-rpm.c
··· 233 233 static const struct of_device_id qcom_smd_rpm_of_match[] = { 234 234 { .compatible = "qcom,rpm-apq8084" }, 235 235 { .compatible = "qcom,rpm-ipq6018" }, 236 + { .compatible = "qcom,rpm-ipq9574" }, 236 237 { .compatible = "qcom,rpm-msm8226" }, 237 238 { .compatible = "qcom,rpm-msm8909" }, 238 239 { .compatible = "qcom,rpm-msm8916" },
+109 -3
drivers/soc/qcom/socinfo.c
··· 169 169 __le32 ndefective_parts_array_offset; 170 170 /* Version 15 */ 171 171 __le32 nmodem_supported; 172 + /* Version 16 */ 173 + __le32 feature_code; 174 + __le32 pcode; 175 + __le32 npartnamemap_offset; 176 + __le32 nnum_partname_mapping; 177 + /* Version 17 */ 178 + __le32 oem_variant; 172 179 }; 173 180 174 181 #ifdef CONFIG_DEBUG_FS ··· 196 189 u32 num_defective_parts; 197 190 u32 ndefective_parts_array_offset; 198 191 u32 nmodem_supported; 192 + u32 feature_code; 193 + u32 pcode; 194 + u32 oem_variant; 199 195 }; 200 196 201 197 struct smem_image_version { ··· 224 214 }; 225 215 226 216 static const struct soc_id soc_id[] = { 217 + { qcom_board_id(MSM8260) }, 218 + { qcom_board_id(MSM8660) }, 219 + { qcom_board_id(APQ8060) }, 227 220 { qcom_board_id(MSM8960) }, 228 221 { qcom_board_id(APQ8064) }, 222 + { qcom_board_id(MSM8930) }, 223 + { qcom_board_id(MSM8630) }, 224 + { qcom_board_id(MSM8230) }, 225 + { qcom_board_id(APQ8030) }, 226 + { qcom_board_id(MSM8627) }, 227 + { qcom_board_id(MSM8227) }, 229 228 { qcom_board_id(MSM8660A) }, 230 229 { qcom_board_id(MSM8260A) }, 231 230 { qcom_board_id(APQ8060A) }, 232 231 { qcom_board_id(MSM8974) }, 232 + { qcom_board_id(MSM8225) }, 233 + { qcom_board_id(MSM8625) }, 233 234 { qcom_board_id(MPQ8064) }, 234 235 { qcom_board_id(MSM8960AB) }, 235 236 { qcom_board_id(APQ8060AB) }, 236 237 { qcom_board_id(MSM8260AB) }, 237 238 { qcom_board_id(MSM8660AB) }, 239 + { qcom_board_id(MSM8930AA) }, 240 + { qcom_board_id(MSM8630AA) }, 241 + { qcom_board_id(MSM8230AA) }, 238 242 { qcom_board_id(MSM8626) }, 239 243 { qcom_board_id(MSM8610) }, 240 244 { qcom_board_id(APQ8064AB) }, 245 + { qcom_board_id(MSM8930AB) }, 246 + { qcom_board_id(MSM8630AB) }, 247 + { qcom_board_id(MSM8230AB) }, 248 + { qcom_board_id(APQ8030AB) }, 241 249 { qcom_board_id(MSM8226) }, 242 250 { qcom_board_id(MSM8526) }, 251 + { qcom_board_id(APQ8030AA) }, 243 252 { qcom_board_id(MSM8110) }, 244 253 { qcom_board_id(MSM8210) }, 245 254 { qcom_board_id(MSM8810) }, 246 255 { qcom_board_id(MSM8212) }, 247 256 { qcom_board_id(MSM8612) }, 248 257 { qcom_board_id(MSM8112) }, 258 + { qcom_board_id(MSM8125) }, 249 259 { qcom_board_id(MSM8225Q) }, 250 260 { qcom_board_id(MSM8625Q) }, 251 261 { qcom_board_id(MSM8125Q) }, 252 262 { qcom_board_id(APQ8064AA) }, 253 263 { qcom_board_id(APQ8084) }, 264 + { qcom_board_id(MSM8130) }, 265 + { qcom_board_id(MSM8130AA) }, 266 + { qcom_board_id(MSM8130AB) }, 267 + { qcom_board_id(MSM8627AA) }, 268 + { qcom_board_id(MSM8227AA) }, 254 269 { qcom_board_id(APQ8074) }, 255 270 { qcom_board_id(MSM8274) }, 256 271 { qcom_board_id(MSM8674) }, 272 + { qcom_board_id(MDM9635) }, 257 273 { qcom_board_id_named(MSM8974PRO_AC, "MSM8974PRO-AC") }, 258 274 { qcom_board_id(MSM8126) }, 259 275 { qcom_board_id(APQ8026) }, 260 276 { qcom_board_id(MSM8926) }, 277 + { qcom_board_id(IPQ8062) }, 278 + { qcom_board_id(IPQ8064) }, 279 + { qcom_board_id(IPQ8066) }, 280 + { qcom_board_id(IPQ8068) }, 261 281 { qcom_board_id(MSM8326) }, 262 282 { qcom_board_id(MSM8916) }, 263 - { qcom_board_id(MSM8956) }, 264 - { qcom_board_id(MSM8976) }, 265 283 { qcom_board_id(MSM8994) }, 266 284 { qcom_board_id_named(APQ8074PRO_AA, "APQ8074PRO-AA") }, 267 285 { qcom_board_id_named(APQ8074PRO_AB, "APQ8074PRO-AB") }, ··· 311 273 { qcom_board_id(MSM8510) }, 312 274 { qcom_board_id(MSM8512) }, 313 275 { qcom_board_id(MSM8936) }, 276 + { qcom_board_id(MDM9640) }, 314 277 { qcom_board_id(MSM8939) }, 315 278 { qcom_board_id(APQ8036) }, 316 279 { qcom_board_id(APQ8039) }, 280 + { qcom_board_id(MSM8236) }, 281 + { qcom_board_id(MSM8636) }, 282 + { qcom_board_id(MSM8909) }, 317 283 { qcom_board_id(MSM8996) }, 318 284 { qcom_board_id(APQ8016) }, 319 285 { qcom_board_id(MSM8216) }, 320 286 { qcom_board_id(MSM8116) }, 321 287 { qcom_board_id(MSM8616) }, 322 288 { qcom_board_id(MSM8992) }, 289 + { qcom_board_id(APQ8092) }, 323 290 { qcom_board_id(APQ8094) }, 291 + { qcom_board_id(MSM8209) }, 292 + { qcom_board_id(MSM8208) }, 293 + { qcom_board_id(MDM9209) }, 294 + { qcom_board_id(MDM9309) }, 295 + { qcom_board_id(MDM9609) }, 296 + { qcom_board_id(MSM8239) }, 297 + { qcom_board_id(MSM8952) }, 298 + { qcom_board_id(APQ8009) }, 299 + { qcom_board_id(MSM8956) }, 300 + { qcom_board_id(MSM8929) }, 301 + { qcom_board_id(MSM8629) }, 302 + { qcom_board_id(MSM8229) }, 303 + { qcom_board_id(APQ8029) }, 304 + { qcom_board_id(APQ8056) }, 305 + { qcom_board_id(MSM8609) }, 306 + { qcom_board_id(APQ8076) }, 307 + { qcom_board_id(MSM8976) }, 308 + { qcom_board_id(IPQ8065) }, 309 + { qcom_board_id(IPQ8069) }, 310 + { qcom_board_id(MDM9650) }, 311 + { qcom_board_id(MDM9655) }, 312 + { qcom_board_id(MDM9250) }, 313 + { qcom_board_id(MDM9255) }, 314 + { qcom_board_id(MDM9350) }, 315 + { qcom_board_id(APQ8052) }, 324 316 { qcom_board_id(MDM9607) }, 325 317 { qcom_board_id(APQ8096) }, 326 318 { qcom_board_id(MSM8998) }, 327 319 { qcom_board_id(MSM8953) }, 320 + { qcom_board_id(MSM8937) }, 321 + { qcom_board_id(APQ8037) }, 328 322 { qcom_board_id(MDM8207) }, 329 323 { qcom_board_id(MDM9207) }, 330 324 { qcom_board_id(MDM9307) }, 331 325 { qcom_board_id(MDM9628) }, 326 + { qcom_board_id(MSM8909W) }, 327 + { qcom_board_id(APQ8009W) }, 328 + { qcom_board_id(MSM8996L) }, 329 + { qcom_board_id(MSM8917) }, 332 330 { qcom_board_id(APQ8053) }, 333 331 { qcom_board_id(MSM8996SG) }, 332 + { qcom_board_id(APQ8017) }, 333 + { qcom_board_id(MSM8217) }, 334 + { qcom_board_id(MSM8617) }, 334 335 { qcom_board_id(MSM8996AU) }, 335 336 { qcom_board_id(APQ8096AU) }, 336 337 { qcom_board_id(APQ8096SG) }, 338 + { qcom_board_id(MSM8940) }, 339 + { qcom_board_id(SDX201) }, 337 340 { qcom_board_id(SDM660) }, 338 341 { qcom_board_id(SDM630) }, 339 342 { qcom_board_id(APQ8098) }, 343 + { qcom_board_id(MSM8920) }, 340 344 { qcom_board_id(SDM845) }, 341 345 { qcom_board_id(MDM9206) }, 342 346 { qcom_board_id(IPQ8074) }, ··· 386 306 { qcom_board_id(SDM658) }, 387 307 { qcom_board_id(SDA658) }, 388 308 { qcom_board_id(SDA630) }, 309 + { qcom_board_id(MSM8905) }, 310 + { qcom_board_id(SDX202) }, 389 311 { qcom_board_id(SDM450) }, 390 312 { qcom_board_id(SM8150) }, 391 313 { qcom_board_id(SDA845) }, ··· 399 317 { qcom_board_id(SDM632) }, 400 318 { qcom_board_id(SDA632) }, 401 319 { qcom_board_id(SDA450) }, 320 + { qcom_board_id(SDM439) }, 321 + { qcom_board_id(SDM429) }, 402 322 { qcom_board_id(SM8250) }, 403 323 { qcom_board_id(SA8155) }, 324 + { qcom_board_id(SDA439) }, 325 + { qcom_board_id(SDA429) }, 404 326 { qcom_board_id(IPQ8070) }, 405 327 { qcom_board_id(IPQ8071) }, 328 + { qcom_board_id(QM215) }, 406 329 { qcom_board_id(IPQ8072A) }, 407 330 { qcom_board_id(IPQ8074A) }, 408 331 { qcom_board_id(IPQ8076A) }, ··· 417 330 { qcom_board_id(IPQ8071A) }, 418 331 { qcom_board_id(IPQ6018) }, 419 332 { qcom_board_id(IPQ6028) }, 333 + { qcom_board_id(SDM429W) }, 420 334 { qcom_board_id(SM4250) }, 421 335 { qcom_board_id(IPQ6000) }, 422 336 { qcom_board_id(IPQ6010) }, 423 337 { qcom_board_id(SC7180) }, 424 338 { qcom_board_id(SM6350) }, 339 + { qcom_board_id(QCM2150) }, 340 + { qcom_board_id(SDA429W) }, 425 341 { qcom_board_id(SM8350) }, 426 342 { qcom_board_id(SM6115) }, 427 343 { qcom_board_id(SC8280XP) }, 428 344 { qcom_board_id(IPQ6005) }, 429 345 { qcom_board_id(QRB5165) }, 430 346 { qcom_board_id(SM8450) }, 431 - { qcom_board_id(SM8550) }, 432 347 { qcom_board_id(SM7225) }, 433 348 { qcom_board_id(SA8295P) }, 434 349 { qcom_board_id(SA8540P) }, ··· 441 352 { qcom_board_id(SC7280) }, 442 353 { qcom_board_id(SC7180P) }, 443 354 { qcom_board_id(SM6375) }, 355 + { qcom_board_id(SM8550) }, 444 356 { qcom_board_id(QRU1000) }, 445 357 { qcom_board_id(QDU1000) }, 446 358 { qcom_board_id(QDU1010) }, 447 359 { qcom_board_id(QRU1032) }, 448 360 { qcom_board_id(QRU1052) }, 449 361 { qcom_board_id(QRU1062) }, 362 + { qcom_board_id(IPQ5332) }, 363 + { qcom_board_id(IPQ5322) }, 450 364 }; 451 365 452 366 static const char *socinfo_machine(struct device *dev, unsigned int id) ··· 604 512 &qcom_socinfo->info.fmt); 605 513 606 514 switch (qcom_socinfo->info.fmt) { 515 + case SOCINFO_VERSION(0, 17): 516 + qcom_socinfo->info.oem_variant = __le32_to_cpu(info->oem_variant); 517 + debugfs_create_u32("oem_variant", 0444, qcom_socinfo->dbg_root, 518 + &qcom_socinfo->info.oem_variant); 519 + fallthrough; 520 + case SOCINFO_VERSION(0, 16): 521 + qcom_socinfo->info.feature_code = __le32_to_cpu(info->feature_code); 522 + qcom_socinfo->info.pcode = __le32_to_cpu(info->pcode); 523 + 524 + debugfs_create_u32("feature_code", 0444, qcom_socinfo->dbg_root, 525 + &qcom_socinfo->info.feature_code); 526 + debugfs_create_u32("pcode", 0444, qcom_socinfo->dbg_root, 527 + &qcom_socinfo->info.pcode); 528 + fallthrough; 607 529 case SOCINFO_VERSION(0, 15): 608 530 qcom_socinfo->info.nmodem_supported = __le32_to_cpu(info->nmodem_supported); 609 531
+4
drivers/soc/renesas/Kconfig
··· 330 330 bool "ARM64 Platform support for RZ/V2M" 331 331 select PM 332 332 select PM_GENERIC_DOMAINS 333 + select PWC_RZV2M 333 334 help 334 335 This enables support for the Renesas RZ/V2M SoC. 335 336 ··· 345 344 This enables support for the Renesas RZ/Five SoC. 346 345 347 346 endif # RISCV 347 + 348 + config PWC_RZV2M 349 + bool "Renesas RZ/V2M PWC support" if COMPILE_TEST 348 350 349 351 config RST_RCAR 350 352 bool "Reset Controller support for R-Car" if COMPILE_TEST
+1
drivers/soc/renesas/Makefile
··· 32 32 endif 33 33 34 34 # Family 35 + obj-$(CONFIG_PWC_RZV2M) += pwc-rzv2m.o 35 36 obj-$(CONFIG_RST_RCAR) += rcar-rst.o 36 37 obj-$(CONFIG_SYSC_RCAR) += rcar-sysc.o 37 38 obj-$(CONFIG_SYSC_RCAR_GEN4) += rcar-gen4-sysc.o
+141
drivers/soc/renesas/pwc-rzv2m.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2023 Renesas Electronics Corporation 4 + */ 5 + 6 + #include <linux/delay.h> 7 + #include <linux/gpio/driver.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/reboot.h> 10 + 11 + #define PWC_PWCRST 0x00 12 + #define PWC_PWCCKEN 0x04 13 + #define PWC_PWCCTL 0x50 14 + #define PWC_GPIO 0x80 15 + 16 + #define PWC_PWCRST_RSTSOFTAX 0x1 17 + #define PWC_PWCCKEN_ENGCKMAIN 0x1 18 + #define PWC_PWCCTL_PWOFF 0x1 19 + 20 + struct rzv2m_pwc_priv { 21 + void __iomem *base; 22 + struct device *dev; 23 + struct gpio_chip gp; 24 + DECLARE_BITMAP(ch_en_bits, 2); 25 + }; 26 + 27 + static void rzv2m_pwc_gpio_set(struct gpio_chip *chip, unsigned int offset, 28 + int value) 29 + { 30 + struct rzv2m_pwc_priv *priv = gpiochip_get_data(chip); 31 + u32 reg; 32 + 33 + /* BIT 16 enables write to BIT 0, and BIT 17 enables write to BIT 1 */ 34 + reg = BIT(offset + 16); 35 + if (value) 36 + reg |= BIT(offset); 37 + 38 + writel(reg, priv->base + PWC_GPIO); 39 + 40 + assign_bit(offset, priv->ch_en_bits, value); 41 + } 42 + 43 + static int rzv2m_pwc_gpio_get(struct gpio_chip *chip, unsigned int offset) 44 + { 45 + struct rzv2m_pwc_priv *priv = gpiochip_get_data(chip); 46 + 47 + return test_bit(offset, priv->ch_en_bits); 48 + } 49 + 50 + static int rzv2m_pwc_gpio_direction_output(struct gpio_chip *gc, 51 + unsigned int nr, int value) 52 + { 53 + if (nr > 1) 54 + return -EINVAL; 55 + 56 + rzv2m_pwc_gpio_set(gc, nr, value); 57 + 58 + return 0; 59 + } 60 + 61 + static const struct gpio_chip rzv2m_pwc_gc = { 62 + .label = "gpio_rzv2m_pwc", 63 + .owner = THIS_MODULE, 64 + .get = rzv2m_pwc_gpio_get, 65 + .set = rzv2m_pwc_gpio_set, 66 + .direction_output = rzv2m_pwc_gpio_direction_output, 67 + .can_sleep = false, 68 + .ngpio = 2, 69 + .base = -1, 70 + }; 71 + 72 + static int rzv2m_pwc_poweroff(struct sys_off_data *data) 73 + { 74 + struct rzv2m_pwc_priv *priv = data->cb_data; 75 + 76 + writel(PWC_PWCRST_RSTSOFTAX, priv->base + PWC_PWCRST); 77 + writel(PWC_PWCCKEN_ENGCKMAIN, priv->base + PWC_PWCCKEN); 78 + writel(PWC_PWCCTL_PWOFF, priv->base + PWC_PWCCTL); 79 + 80 + mdelay(150); 81 + 82 + dev_err(priv->dev, "Failed to power off the system"); 83 + 84 + return NOTIFY_DONE; 85 + } 86 + 87 + static int rzv2m_pwc_probe(struct platform_device *pdev) 88 + { 89 + struct rzv2m_pwc_priv *priv; 90 + int ret; 91 + 92 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 93 + if (!priv) 94 + return -ENOMEM; 95 + 96 + priv->base = devm_platform_ioremap_resource(pdev, 0); 97 + if (IS_ERR(priv->base)) 98 + return PTR_ERR(priv->base); 99 + 100 + /* 101 + * The register used by this driver cannot be read, therefore set the 102 + * outputs to their default values and initialize priv->ch_en_bits 103 + * accordingly. BIT 16 enables write to BIT 0, BIT 17 enables write to 104 + * BIT 1, and the default value of both BIT 0 and BIT 1 is 0. 105 + */ 106 + writel(BIT(17) | BIT(16), priv->base + PWC_GPIO); 107 + bitmap_zero(priv->ch_en_bits, 2); 108 + 109 + priv->gp = rzv2m_pwc_gc; 110 + priv->gp.parent = pdev->dev.parent; 111 + priv->gp.fwnode = dev_fwnode(&pdev->dev); 112 + 113 + ret = devm_gpiochip_add_data(&pdev->dev, &priv->gp, priv); 114 + if (ret) 115 + return ret; 116 + 117 + if (device_property_read_bool(&pdev->dev, "renesas,rzv2m-pwc-power")) 118 + ret = devm_register_power_off_handler(&pdev->dev, 119 + rzv2m_pwc_poweroff, priv); 120 + 121 + return ret; 122 + } 123 + 124 + static const struct of_device_id rzv2m_pwc_of_match[] = { 125 + { .compatible = "renesas,rzv2m-pwc" }, 126 + { /* sentinel */ } 127 + }; 128 + MODULE_DEVICE_TABLE(of, rzv2m_pwc_of_match); 129 + 130 + static struct platform_driver rzv2m_pwc_driver = { 131 + .probe = rzv2m_pwc_probe, 132 + .driver = { 133 + .name = "rzv2m_pwc", 134 + .of_match_table = of_match_ptr(rzv2m_pwc_of_match), 135 + }, 136 + }; 137 + module_platform_driver(rzv2m_pwc_driver); 138 + 139 + MODULE_LICENSE("GPL"); 140 + MODULE_AUTHOR("Fabrizio Castro <castro.fabrizio.jz@renesas.com>"); 141 + MODULE_DESCRIPTION("Renesas RZ/V2M PWC driver");
+1
drivers/soc/renesas/r8a779g0-sysc.c
··· 37 37 { "a3vip0", R8A779G0_PD_A3VIP0, R8A779G0_PD_ALWAYS_ON }, 38 38 { "a3vip1", R8A779G0_PD_A3VIP1, R8A779G0_PD_ALWAYS_ON }, 39 39 { "a3vip2", R8A779G0_PD_A3VIP2, R8A779G0_PD_ALWAYS_ON }, 40 + { "a3dul", R8A779G0_PD_A3DUL, R8A779G0_PD_ALWAYS_ON }, 40 41 { "a3isp0", R8A779G0_PD_A3ISP0, R8A779G0_PD_ALWAYS_ON }, 41 42 { "a3isp1", R8A779G0_PD_A3ISP1, R8A779G0_PD_ALWAYS_ON }, 42 43 { "a3ir", R8A779G0_PD_A3IR, R8A779G0_PD_ALWAYS_ON },
+1 -1
drivers/soc/sifive/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 - if SOC_SIFIVE 3 + if SOC_SIFIVE || SOC_STARFIVE 4 4 5 5 config SIFIVE_CCACHE 6 6 bool "Sifive Composable Cache controller"
+12
drivers/soc/starfive/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + config JH71XX_PMU 4 + bool "Support PMU for StarFive JH71XX Soc" 5 + depends on PM 6 + depends on SOC_STARFIVE || COMPILE_TEST 7 + default SOC_STARFIVE 8 + select PM_GENERIC_DOMAINS 9 + help 10 + Say 'y' here to enable support power domain support. 11 + In order to meet low power requirements, a Power Management Unit (PMU) 12 + is designed for controlling power resources in StarFive JH71XX SoCs.
+3
drivers/soc/starfive/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + obj-$(CONFIG_JH71XX_PMU) += jh71xx_pmu.o
+383
drivers/soc/starfive/jh71xx_pmu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * StarFive JH71XX PMU (Power Management Unit) Controller Driver 4 + * 5 + * Copyright (C) 2022 StarFive Technology Co., Ltd. 6 + */ 7 + 8 + #include <linux/interrupt.h> 9 + #include <linux/io.h> 10 + #include <linux/iopoll.h> 11 + #include <linux/module.h> 12 + #include <linux/of.h> 13 + #include <linux/of_device.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/pm_domain.h> 16 + #include <dt-bindings/power/starfive,jh7110-pmu.h> 17 + 18 + /* register offset */ 19 + #define JH71XX_PMU_SW_TURN_ON_POWER 0x0C 20 + #define JH71XX_PMU_SW_TURN_OFF_POWER 0x10 21 + #define JH71XX_PMU_SW_ENCOURAGE 0x44 22 + #define JH71XX_PMU_TIMER_INT_MASK 0x48 23 + #define JH71XX_PMU_CURR_POWER_MODE 0x80 24 + #define JH71XX_PMU_EVENT_STATUS 0x88 25 + #define JH71XX_PMU_INT_STATUS 0x8C 26 + 27 + /* sw encourage cfg */ 28 + #define JH71XX_PMU_SW_ENCOURAGE_EN_LO 0x05 29 + #define JH71XX_PMU_SW_ENCOURAGE_EN_HI 0x50 30 + #define JH71XX_PMU_SW_ENCOURAGE_DIS_LO 0x0A 31 + #define JH71XX_PMU_SW_ENCOURAGE_DIS_HI 0xA0 32 + #define JH71XX_PMU_SW_ENCOURAGE_ON 0xFF 33 + 34 + /* pmu int status */ 35 + #define JH71XX_PMU_INT_SEQ_DONE BIT(0) 36 + #define JH71XX_PMU_INT_HW_REQ BIT(1) 37 + #define JH71XX_PMU_INT_SW_FAIL GENMASK(3, 2) 38 + #define JH71XX_PMU_INT_HW_FAIL GENMASK(5, 4) 39 + #define JH71XX_PMU_INT_PCH_FAIL GENMASK(8, 6) 40 + #define JH71XX_PMU_INT_ALL_MASK GENMASK(8, 0) 41 + 42 + /* 43 + * The time required for switching power status is based on the time 44 + * to turn on the largest domain's power, which is at microsecond level 45 + */ 46 + #define JH71XX_PMU_TIMEOUT_US 100 47 + 48 + struct jh71xx_domain_info { 49 + const char * const name; 50 + unsigned int flags; 51 + u8 bit; 52 + }; 53 + 54 + struct jh71xx_pmu_match_data { 55 + const struct jh71xx_domain_info *domain_info; 56 + int num_domains; 57 + }; 58 + 59 + struct jh71xx_pmu { 60 + struct device *dev; 61 + const struct jh71xx_pmu_match_data *match_data; 62 + void __iomem *base; 63 + struct generic_pm_domain **genpd; 64 + struct genpd_onecell_data genpd_data; 65 + int irq; 66 + spinlock_t lock; /* protects pmu reg */ 67 + }; 68 + 69 + struct jh71xx_pmu_dev { 70 + const struct jh71xx_domain_info *domain_info; 71 + struct jh71xx_pmu *pmu; 72 + struct generic_pm_domain genpd; 73 + }; 74 + 75 + static int jh71xx_pmu_get_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool *is_on) 76 + { 77 + struct jh71xx_pmu *pmu = pmd->pmu; 78 + 79 + if (!mask) 80 + return -EINVAL; 81 + 82 + *is_on = readl(pmu->base + JH71XX_PMU_CURR_POWER_MODE) & mask; 83 + 84 + return 0; 85 + } 86 + 87 + static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on) 88 + { 89 + struct jh71xx_pmu *pmu = pmd->pmu; 90 + unsigned long flags; 91 + u32 val; 92 + u32 mode; 93 + u32 encourage_lo; 94 + u32 encourage_hi; 95 + bool is_on; 96 + int ret; 97 + 98 + ret = jh71xx_pmu_get_state(pmd, mask, &is_on); 99 + if (ret) { 100 + dev_dbg(pmu->dev, "unable to get current state for %s\n", 101 + pmd->genpd.name); 102 + return ret; 103 + } 104 + 105 + if (is_on == on) { 106 + dev_dbg(pmu->dev, "pm domain [%s] is already %sable status.\n", 107 + pmd->genpd.name, on ? "en" : "dis"); 108 + return 0; 109 + } 110 + 111 + spin_lock_irqsave(&pmu->lock, flags); 112 + 113 + /* 114 + * The PMU accepts software encourage to switch power mode in the following 2 steps: 115 + * 116 + * 1.Configure the register SW_TURN_ON_POWER (offset 0x0c) by writing 1 to 117 + * the bit corresponding to the power domain that will be turned on 118 + * and writing 0 to the others. 119 + * Likewise, configure the register SW_TURN_OFF_POWER (offset 0x10) by 120 + * writing 1 to the bit corresponding to the power domain that will be 121 + * turned off and writing 0 to the others. 122 + */ 123 + if (on) { 124 + mode = JH71XX_PMU_SW_TURN_ON_POWER; 125 + encourage_lo = JH71XX_PMU_SW_ENCOURAGE_EN_LO; 126 + encourage_hi = JH71XX_PMU_SW_ENCOURAGE_EN_HI; 127 + } else { 128 + mode = JH71XX_PMU_SW_TURN_OFF_POWER; 129 + encourage_lo = JH71XX_PMU_SW_ENCOURAGE_DIS_LO; 130 + encourage_hi = JH71XX_PMU_SW_ENCOURAGE_DIS_HI; 131 + } 132 + 133 + writel(mask, pmu->base + mode); 134 + 135 + /* 136 + * 2.Write SW encourage command sequence to the Software Encourage Reg (offset 0x44) 137 + * First write SW_MODE_ENCOURAGE_ON to JH71XX_PMU_SW_ENCOURAGE. This will reset 138 + * the state machine which parses the command sequence. This register must be 139 + * written every time software wants to power on/off a domain. 140 + * Then write the lower bits of the command sequence, followed by the upper 141 + * bits. The sequence differs between powering on & off a domain. 142 + */ 143 + writel(JH71XX_PMU_SW_ENCOURAGE_ON, pmu->base + JH71XX_PMU_SW_ENCOURAGE); 144 + writel(encourage_lo, pmu->base + JH71XX_PMU_SW_ENCOURAGE); 145 + writel(encourage_hi, pmu->base + JH71XX_PMU_SW_ENCOURAGE); 146 + 147 + spin_unlock_irqrestore(&pmu->lock, flags); 148 + 149 + /* Wait for the power domain bit to be enabled / disabled */ 150 + if (on) { 151 + ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE, 152 + val, val & mask, 153 + 1, JH71XX_PMU_TIMEOUT_US); 154 + } else { 155 + ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE, 156 + val, !(val & mask), 157 + 1, JH71XX_PMU_TIMEOUT_US); 158 + } 159 + 160 + if (ret) { 161 + dev_err(pmu->dev, "%s: failed to power %s\n", 162 + pmd->genpd.name, on ? "on" : "off"); 163 + return -ETIMEDOUT; 164 + } 165 + 166 + return 0; 167 + } 168 + 169 + static int jh71xx_pmu_on(struct generic_pm_domain *genpd) 170 + { 171 + struct jh71xx_pmu_dev *pmd = container_of(genpd, 172 + struct jh71xx_pmu_dev, genpd); 173 + u32 pwr_mask = BIT(pmd->domain_info->bit); 174 + 175 + return jh71xx_pmu_set_state(pmd, pwr_mask, true); 176 + } 177 + 178 + static int jh71xx_pmu_off(struct generic_pm_domain *genpd) 179 + { 180 + struct jh71xx_pmu_dev *pmd = container_of(genpd, 181 + struct jh71xx_pmu_dev, genpd); 182 + u32 pwr_mask = BIT(pmd->domain_info->bit); 183 + 184 + return jh71xx_pmu_set_state(pmd, pwr_mask, false); 185 + } 186 + 187 + static void jh71xx_pmu_int_enable(struct jh71xx_pmu *pmu, u32 mask, bool enable) 188 + { 189 + u32 val; 190 + unsigned long flags; 191 + 192 + spin_lock_irqsave(&pmu->lock, flags); 193 + val = readl(pmu->base + JH71XX_PMU_TIMER_INT_MASK); 194 + 195 + if (enable) 196 + val &= ~mask; 197 + else 198 + val |= mask; 199 + 200 + writel(val, pmu->base + JH71XX_PMU_TIMER_INT_MASK); 201 + spin_unlock_irqrestore(&pmu->lock, flags); 202 + } 203 + 204 + static irqreturn_t jh71xx_pmu_interrupt(int irq, void *data) 205 + { 206 + struct jh71xx_pmu *pmu = data; 207 + u32 val; 208 + 209 + val = readl(pmu->base + JH71XX_PMU_INT_STATUS); 210 + 211 + if (val & JH71XX_PMU_INT_SEQ_DONE) 212 + dev_dbg(pmu->dev, "sequence done.\n"); 213 + if (val & JH71XX_PMU_INT_HW_REQ) 214 + dev_dbg(pmu->dev, "hardware encourage requestion.\n"); 215 + if (val & JH71XX_PMU_INT_SW_FAIL) 216 + dev_err(pmu->dev, "software encourage fail.\n"); 217 + if (val & JH71XX_PMU_INT_HW_FAIL) 218 + dev_err(pmu->dev, "hardware encourage fail.\n"); 219 + if (val & JH71XX_PMU_INT_PCH_FAIL) 220 + dev_err(pmu->dev, "p-channel fail event.\n"); 221 + 222 + /* clear interrupts */ 223 + writel(val, pmu->base + JH71XX_PMU_INT_STATUS); 224 + writel(val, pmu->base + JH71XX_PMU_EVENT_STATUS); 225 + 226 + return IRQ_HANDLED; 227 + } 228 + 229 + static int jh71xx_pmu_init_domain(struct jh71xx_pmu *pmu, int index) 230 + { 231 + struct jh71xx_pmu_dev *pmd; 232 + u32 pwr_mask; 233 + int ret; 234 + bool is_on = false; 235 + 236 + pmd = devm_kzalloc(pmu->dev, sizeof(*pmd), GFP_KERNEL); 237 + if (!pmd) 238 + return -ENOMEM; 239 + 240 + pmd->domain_info = &pmu->match_data->domain_info[index]; 241 + pmd->pmu = pmu; 242 + pwr_mask = BIT(pmd->domain_info->bit); 243 + 244 + pmd->genpd.name = pmd->domain_info->name; 245 + pmd->genpd.flags = pmd->domain_info->flags; 246 + 247 + ret = jh71xx_pmu_get_state(pmd, pwr_mask, &is_on); 248 + if (ret) 249 + dev_warn(pmu->dev, "unable to get current state for %s\n", 250 + pmd->genpd.name); 251 + 252 + pmd->genpd.power_on = jh71xx_pmu_on; 253 + pmd->genpd.power_off = jh71xx_pmu_off; 254 + pm_genpd_init(&pmd->genpd, NULL, !is_on); 255 + 256 + pmu->genpd_data.domains[index] = &pmd->genpd; 257 + 258 + return 0; 259 + } 260 + 261 + static int jh71xx_pmu_probe(struct platform_device *pdev) 262 + { 263 + struct device *dev = &pdev->dev; 264 + struct device_node *np = dev->of_node; 265 + const struct jh71xx_pmu_match_data *match_data; 266 + struct jh71xx_pmu *pmu; 267 + unsigned int i; 268 + int ret; 269 + 270 + pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL); 271 + if (!pmu) 272 + return -ENOMEM; 273 + 274 + pmu->base = devm_platform_ioremap_resource(pdev, 0); 275 + if (IS_ERR(pmu->base)) 276 + return PTR_ERR(pmu->base); 277 + 278 + pmu->irq = platform_get_irq(pdev, 0); 279 + if (pmu->irq < 0) 280 + return pmu->irq; 281 + 282 + ret = devm_request_irq(dev, pmu->irq, jh71xx_pmu_interrupt, 283 + 0, pdev->name, pmu); 284 + if (ret) 285 + dev_err(dev, "failed to request irq\n"); 286 + 287 + match_data = of_device_get_match_data(dev); 288 + if (!match_data) 289 + return -EINVAL; 290 + 291 + pmu->genpd = devm_kcalloc(dev, match_data->num_domains, 292 + sizeof(struct generic_pm_domain *), 293 + GFP_KERNEL); 294 + if (!pmu->genpd) 295 + return -ENOMEM; 296 + 297 + pmu->dev = dev; 298 + pmu->match_data = match_data; 299 + pmu->genpd_data.domains = pmu->genpd; 300 + pmu->genpd_data.num_domains = match_data->num_domains; 301 + 302 + for (i = 0; i < match_data->num_domains; i++) { 303 + ret = jh71xx_pmu_init_domain(pmu, i); 304 + if (ret) { 305 + dev_err(dev, "failed to initialize power domain\n"); 306 + return ret; 307 + } 308 + } 309 + 310 + spin_lock_init(&pmu->lock); 311 + jh71xx_pmu_int_enable(pmu, JH71XX_PMU_INT_ALL_MASK & ~JH71XX_PMU_INT_PCH_FAIL, true); 312 + 313 + ret = of_genpd_add_provider_onecell(np, &pmu->genpd_data); 314 + if (ret) { 315 + dev_err(dev, "failed to register genpd driver: %d\n", ret); 316 + return ret; 317 + } 318 + 319 + dev_dbg(dev, "registered %u power domains\n", i); 320 + 321 + return 0; 322 + } 323 + 324 + static const struct jh71xx_domain_info jh7110_power_domains[] = { 325 + [JH7110_PD_SYSTOP] = { 326 + .name = "SYSTOP", 327 + .bit = 0, 328 + .flags = GENPD_FLAG_ALWAYS_ON, 329 + }, 330 + [JH7110_PD_CPU] = { 331 + .name = "CPU", 332 + .bit = 1, 333 + .flags = GENPD_FLAG_ALWAYS_ON, 334 + }, 335 + [JH7110_PD_GPUA] = { 336 + .name = "GPUA", 337 + .bit = 2, 338 + }, 339 + [JH7110_PD_VDEC] = { 340 + .name = "VDEC", 341 + .bit = 3, 342 + }, 343 + [JH7110_PD_VOUT] = { 344 + .name = "VOUT", 345 + .bit = 4, 346 + }, 347 + [JH7110_PD_ISP] = { 348 + .name = "ISP", 349 + .bit = 5, 350 + }, 351 + [JH7110_PD_VENC] = { 352 + .name = "VENC", 353 + .bit = 6, 354 + }, 355 + }; 356 + 357 + static const struct jh71xx_pmu_match_data jh7110_pmu = { 358 + .num_domains = ARRAY_SIZE(jh7110_power_domains), 359 + .domain_info = jh7110_power_domains, 360 + }; 361 + 362 + static const struct of_device_id jh71xx_pmu_of_match[] = { 363 + { 364 + .compatible = "starfive,jh7110-pmu", 365 + .data = (void *)&jh7110_pmu, 366 + }, { 367 + /* sentinel */ 368 + } 369 + }; 370 + 371 + static struct platform_driver jh71xx_pmu_driver = { 372 + .probe = jh71xx_pmu_probe, 373 + .driver = { 374 + .name = "jh71xx-pmu", 375 + .of_match_table = jh71xx_pmu_of_match, 376 + .suppress_bind_attrs = true, 377 + }, 378 + }; 379 + builtin_platform_driver(jh71xx_pmu_driver); 380 + 381 + MODULE_AUTHOR("Walker Chen <walker.chen@starfivetech.com>"); 382 + MODULE_DESCRIPTION("StarFive JH71XX PMU Driver"); 383 + MODULE_LICENSE("GPL");
+9
drivers/soc/sunxi/Kconfig
··· 19 19 Say y here to enable the SRAM controller support. This 20 20 device is responsible on mapping the SRAM in the sunXi SoCs 21 21 whether to the CPU/DMA, or to the devices. 22 + 23 + config SUN20I_PPU 24 + bool "Allwinner D1 PPU power domain driver" 25 + depends on ARCH_SUNXI || COMPILE_TEST 26 + depends on PM 27 + select PM_GENERIC_DOMAINS 28 + help 29 + Say y to enable the PPU power domain driver. This saves power 30 + when certain peripherals, such as the video engine, are idle.
+1
drivers/soc/sunxi/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 obj-$(CONFIG_SUNXI_MBUS) += sunxi_mbus.o 3 3 obj-$(CONFIG_SUNXI_SRAM) += sunxi_sram.o 4 + obj-$(CONFIG_SUN20I_PPU) += sun20i-ppu.o
+207
drivers/soc/sunxi/sun20i-ppu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/bitfield.h> 4 + #include <linux/clk.h> 5 + #include <linux/io.h> 6 + #include <linux/iopoll.h> 7 + #include <linux/module.h> 8 + #include <linux/of_device.h> 9 + #include <linux/platform_device.h> 10 + #include <linux/pm_domain.h> 11 + #include <linux/reset.h> 12 + 13 + #define PD_STATE_ON 1 14 + #define PD_STATE_OFF 2 15 + 16 + #define PD_RSTN_REG 0x00 17 + #define PD_CLK_GATE_REG 0x04 18 + #define PD_PWROFF_GATE_REG 0x08 19 + #define PD_PSW_ON_REG 0x0c 20 + #define PD_PSW_OFF_REG 0x10 21 + #define PD_PSW_DELAY_REG 0x14 22 + #define PD_OFF_DELAY_REG 0x18 23 + #define PD_ON_DELAY_REG 0x1c 24 + #define PD_COMMAND_REG 0x20 25 + #define PD_STATUS_REG 0x24 26 + #define PD_STATUS_COMPLETE BIT(1) 27 + #define PD_STATUS_BUSY BIT(3) 28 + #define PD_STATUS_STATE GENMASK(17, 16) 29 + #define PD_ACTIVE_CTRL_REG 0x2c 30 + #define PD_GATE_STATUS_REG 0x30 31 + #define PD_RSTN_STATUS BIT(0) 32 + #define PD_CLK_GATE_STATUS BIT(1) 33 + #define PD_PWROFF_GATE_STATUS BIT(2) 34 + #define PD_PSW_STATUS_REG 0x34 35 + 36 + #define PD_REGS_SIZE 0x80 37 + 38 + struct sun20i_ppu_desc { 39 + const char *const *names; 40 + unsigned int num_domains; 41 + }; 42 + 43 + struct sun20i_ppu_pd { 44 + struct generic_pm_domain genpd; 45 + void __iomem *base; 46 + }; 47 + 48 + #define to_sun20i_ppu_pd(_genpd) \ 49 + container_of(_genpd, struct sun20i_ppu_pd, genpd) 50 + 51 + static bool sun20i_ppu_pd_is_on(const struct sun20i_ppu_pd *pd) 52 + { 53 + u32 status = readl(pd->base + PD_STATUS_REG); 54 + 55 + return FIELD_GET(PD_STATUS_STATE, status) == PD_STATE_ON; 56 + } 57 + 58 + static int sun20i_ppu_pd_set_power(const struct sun20i_ppu_pd *pd, bool power_on) 59 + { 60 + u32 state, status; 61 + int ret; 62 + 63 + if (sun20i_ppu_pd_is_on(pd) == power_on) 64 + return 0; 65 + 66 + /* Wait for the power controller to be idle. */ 67 + ret = readl_poll_timeout(pd->base + PD_STATUS_REG, status, 68 + !(status & PD_STATUS_BUSY), 100, 1000); 69 + if (ret) 70 + return ret; 71 + 72 + state = power_on ? PD_STATE_ON : PD_STATE_OFF; 73 + writel(state, pd->base + PD_COMMAND_REG); 74 + 75 + /* Wait for the state transition to complete. */ 76 + ret = readl_poll_timeout(pd->base + PD_STATUS_REG, status, 77 + FIELD_GET(PD_STATUS_STATE, status) == state && 78 + (status & PD_STATUS_COMPLETE), 100, 1000); 79 + if (ret) 80 + return ret; 81 + 82 + /* Clear the completion flag. */ 83 + writel(status, pd->base + PD_STATUS_REG); 84 + 85 + return 0; 86 + } 87 + 88 + static int sun20i_ppu_pd_power_on(struct generic_pm_domain *genpd) 89 + { 90 + const struct sun20i_ppu_pd *pd = to_sun20i_ppu_pd(genpd); 91 + 92 + return sun20i_ppu_pd_set_power(pd, true); 93 + } 94 + 95 + static int sun20i_ppu_pd_power_off(struct generic_pm_domain *genpd) 96 + { 97 + const struct sun20i_ppu_pd *pd = to_sun20i_ppu_pd(genpd); 98 + 99 + return sun20i_ppu_pd_set_power(pd, false); 100 + } 101 + 102 + static int sun20i_ppu_probe(struct platform_device *pdev) 103 + { 104 + const struct sun20i_ppu_desc *desc; 105 + struct device *dev = &pdev->dev; 106 + struct genpd_onecell_data *ppu; 107 + struct sun20i_ppu_pd *pds; 108 + struct reset_control *rst; 109 + void __iomem *base; 110 + struct clk *clk; 111 + int ret; 112 + 113 + desc = of_device_get_match_data(dev); 114 + if (!desc) 115 + return -EINVAL; 116 + 117 + pds = devm_kcalloc(dev, desc->num_domains, sizeof(*pds), GFP_KERNEL); 118 + if (!pds) 119 + return -ENOMEM; 120 + 121 + ppu = devm_kzalloc(dev, sizeof(*ppu), GFP_KERNEL); 122 + if (!ppu) 123 + return -ENOMEM; 124 + 125 + ppu->domains = devm_kcalloc(dev, desc->num_domains, 126 + sizeof(*ppu->domains), GFP_KERNEL); 127 + if (!ppu->domains) 128 + return -ENOMEM; 129 + 130 + ppu->num_domains = desc->num_domains; 131 + platform_set_drvdata(pdev, ppu); 132 + 133 + base = devm_platform_ioremap_resource(pdev, 0); 134 + if (IS_ERR(base)) 135 + return PTR_ERR(base); 136 + 137 + clk = devm_clk_get_enabled(dev, NULL); 138 + if (IS_ERR(clk)) 139 + return PTR_ERR(clk); 140 + 141 + rst = devm_reset_control_get_exclusive(dev, NULL); 142 + if (IS_ERR(rst)) 143 + return PTR_ERR(rst); 144 + 145 + ret = reset_control_deassert(rst); 146 + if (ret) 147 + return ret; 148 + 149 + for (unsigned int i = 0; i < ppu->num_domains; ++i) { 150 + struct sun20i_ppu_pd *pd = &pds[i]; 151 + 152 + pd->genpd.name = desc->names[i]; 153 + pd->genpd.power_off = sun20i_ppu_pd_power_off; 154 + pd->genpd.power_on = sun20i_ppu_pd_power_on; 155 + pd->base = base + PD_REGS_SIZE * i; 156 + 157 + ret = pm_genpd_init(&pd->genpd, NULL, sun20i_ppu_pd_is_on(pd)); 158 + if (ret) { 159 + dev_warn(dev, "Failed to add '%s' domain: %d\n", 160 + pd->genpd.name, ret); 161 + continue; 162 + } 163 + 164 + ppu->domains[i] = &pd->genpd; 165 + } 166 + 167 + ret = of_genpd_add_provider_onecell(dev->of_node, ppu); 168 + if (ret) 169 + dev_warn(dev, "Failed to add provider: %d\n", ret); 170 + 171 + return 0; 172 + } 173 + 174 + static const char *const sun20i_d1_ppu_pd_names[] = { 175 + "CPU", 176 + "VE", 177 + "DSP", 178 + }; 179 + 180 + static const struct sun20i_ppu_desc sun20i_d1_ppu_desc = { 181 + .names = sun20i_d1_ppu_pd_names, 182 + .num_domains = ARRAY_SIZE(sun20i_d1_ppu_pd_names), 183 + }; 184 + 185 + static const struct of_device_id sun20i_ppu_of_match[] = { 186 + { 187 + .compatible = "allwinner,sun20i-d1-ppu", 188 + .data = &sun20i_d1_ppu_desc, 189 + }, 190 + { } 191 + }; 192 + MODULE_DEVICE_TABLE(of, sun20i_ppu_of_match); 193 + 194 + static struct platform_driver sun20i_ppu_driver = { 195 + .probe = sun20i_ppu_probe, 196 + .driver = { 197 + .name = "sun20i-ppu", 198 + .of_match_table = sun20i_ppu_of_match, 199 + /* Power domains cannot be removed while they are in use. */ 200 + .suppress_bind_attrs = true, 201 + }, 202 + }; 203 + module_platform_driver(sun20i_ppu_driver); 204 + 205 + MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>"); 206 + MODULE_DESCRIPTION("Allwinner D1 PPU power domain driver"); 207 + MODULE_LICENSE("GPL");
+3
drivers/soc/sunxi/sunxi_sram.c
··· 120 120 seq_puts(s, "--------------------\n\n"); 121 121 122 122 for_each_child_of_node(sram_dev->of_node, sram_node) { 123 + if (!of_device_is_compatible(sram_node, "mmio-sram")) 124 + continue; 125 + 123 126 sram_addr_p = of_get_address(sram_node, 0, NULL, NULL); 124 127 125 128 seq_printf(s, "sram@%08x\n",
+3 -1
drivers/soc/xilinx/xlnx_event_manager.c
··· 116 116 INIT_LIST_HEAD(&eve_data->cb_list_head); 117 117 118 118 cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL); 119 - if (!cb_data) 119 + if (!cb_data) { 120 + kfree(eve_data); 120 121 return -ENOMEM; 122 + } 121 123 cb_data->eve_cb = cb_fun; 122 124 cb_data->agent_data = data; 123 125
+1 -1
drivers/soc/xilinx/zynqmp_pm_domains.c
··· 227 227 goto done; 228 228 } 229 229 230 - /** 230 + /* 231 231 * Add index in empty node_id of power domain list as no existing 232 232 * power domain found for current index. 233 233 */
+7 -7
drivers/spi/spi-rpc-if.c
··· 58 58 rpc_op.data.dir = RPCIF_NO_DATA; 59 59 } 60 60 61 - rpcif_prepare(rpc, &rpc_op, offs, len); 61 + rpcif_prepare(rpc->dev, &rpc_op, offs, len); 62 62 } 63 63 64 64 static bool rpcif_spi_mem_supports_op(struct spi_mem *mem, ··· 86 86 87 87 rpcif_spi_mem_prepare(desc->mem->spi, &desc->info.op_tmpl, &offs, &len); 88 88 89 - return rpcif_dirmap_read(rpc, offs, len, buf); 89 + return rpcif_dirmap_read(rpc->dev, offs, len, buf); 90 90 } 91 91 92 92 static int rpcif_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc) ··· 117 117 118 118 rpcif_spi_mem_prepare(mem->spi, op, NULL, NULL); 119 119 120 - return rpcif_manual_xfer(rpc); 120 + return rpcif_manual_xfer(rpc->dev); 121 121 } 122 122 123 123 static const struct spi_controller_mem_ops rpcif_spi_mem_ops = { ··· 147 147 148 148 ctlr->dev.of_node = parent->of_node; 149 149 150 - rpcif_enable_rpm(rpc); 150 + pm_runtime_enable(rpc->dev); 151 151 152 152 ctlr->num_chipselect = 1; 153 153 ctlr->mem_ops = &rpcif_spi_mem_ops; ··· 156 156 ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_QUAD | SPI_RX_QUAD; 157 157 ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX; 158 158 159 - error = rpcif_hw_init(rpc, false); 159 + error = rpcif_hw_init(rpc->dev, false); 160 160 if (error) 161 161 goto out_disable_rpm; 162 162 ··· 169 169 return 0; 170 170 171 171 out_disable_rpm: 172 - rpcif_disable_rpm(rpc); 172 + pm_runtime_disable(rpc->dev); 173 173 return error; 174 174 } 175 175 ··· 179 179 struct rpcif *rpc = spi_controller_get_devdata(ctlr); 180 180 181 181 spi_unregister_controller(ctlr); 182 - rpcif_disable_rpm(rpc); 182 + pm_runtime_disable(rpc->dev); 183 183 184 184 return 0; 185 185 }
+1 -1
drivers/thermal/qcom/lmh.c
··· 10 10 #include <linux/platform_device.h> 11 11 #include <linux/of_platform.h> 12 12 #include <linux/slab.h> 13 - #include <linux/qcom_scm.h> 13 + #include <linux/firmware/qcom/qcom_scm.h> 14 14 15 15 #define LMH_NODE_DCVS 0x44435653 16 16 #define LMH_CLUSTER0_NODE_ID 0x6370302D
+1 -1
drivers/ufs/host/ufs-qcom-ice.c
··· 8 8 9 9 #include <linux/delay.h> 10 10 #include <linux/platform_device.h> 11 - #include <linux/qcom_scm.h> 11 + #include <linux/firmware/qcom/qcom_scm.h> 12 12 13 13 #include "ufs-qcom.h" 14 14
+1
fs/debugfs/file.c
··· 899 899 900 900 return ret; 901 901 } 902 + EXPORT_SYMBOL_GPL(debugfs_create_str); 902 903 903 904 static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf, 904 905 size_t count, loff_t *ppos)
+83
include/dt-bindings/arm/qcom,ids.h
··· 11 11 * The MSM chipset and hardware revision used by Qualcomm bootloaders, DTS for 12 12 * older chipsets (qcom,msm-id) and in socinfo driver: 13 13 */ 14 + #define QCOM_ID_MSM8260 70 15 + #define QCOM_ID_MSM8660 71 16 + #define QCOM_ID_APQ8060 86 14 17 #define QCOM_ID_MSM8960 87 15 18 #define QCOM_ID_APQ8064 109 19 + #define QCOM_ID_MSM8930 116 20 + #define QCOM_ID_MSM8630 117 21 + #define QCOM_ID_MSM8230 118 22 + #define QCOM_ID_APQ8030 119 23 + #define QCOM_ID_MSM8627 120 24 + #define QCOM_ID_MSM8227 121 16 25 #define QCOM_ID_MSM8660A 122 17 26 #define QCOM_ID_MSM8260A 123 18 27 #define QCOM_ID_APQ8060A 124 19 28 #define QCOM_ID_MSM8974 126 29 + #define QCOM_ID_MSM8225 127 30 + #define QCOM_ID_MSM8625 129 20 31 #define QCOM_ID_MPQ8064 130 21 32 #define QCOM_ID_MSM8960AB 138 22 33 #define QCOM_ID_APQ8060AB 139 23 34 #define QCOM_ID_MSM8260AB 140 24 35 #define QCOM_ID_MSM8660AB 141 36 + #define QCOM_ID_MSM8930AA 142 37 + #define QCOM_ID_MSM8630AA 143 38 + #define QCOM_ID_MSM8230AA 144 25 39 #define QCOM_ID_MSM8626 145 26 40 #define QCOM_ID_MSM8610 147 27 41 #define QCOM_ID_APQ8064AB 153 42 + #define QCOM_ID_MSM8930AB 154 43 + #define QCOM_ID_MSM8630AB 155 44 + #define QCOM_ID_MSM8230AB 156 45 + #define QCOM_ID_APQ8030AB 157 28 46 #define QCOM_ID_MSM8226 158 29 47 #define QCOM_ID_MSM8526 159 48 + #define QCOM_ID_APQ8030AA 160 30 49 #define QCOM_ID_MSM8110 161 31 50 #define QCOM_ID_MSM8210 162 32 51 #define QCOM_ID_MSM8810 163 33 52 #define QCOM_ID_MSM8212 164 34 53 #define QCOM_ID_MSM8612 165 35 54 #define QCOM_ID_MSM8112 166 55 + #define QCOM_ID_MSM8125 167 36 56 #define QCOM_ID_MSM8225Q 168 37 57 #define QCOM_ID_MSM8625Q 169 38 58 #define QCOM_ID_MSM8125Q 170 39 59 #define QCOM_ID_APQ8064AA 172 40 60 #define QCOM_ID_APQ8084 178 61 + #define QCOM_ID_MSM8130 179 62 + #define QCOM_ID_MSM8130AA 180 63 + #define QCOM_ID_MSM8130AB 181 64 + #define QCOM_ID_MSM8627AA 182 65 + #define QCOM_ID_MSM8227AA 183 41 66 #define QCOM_ID_APQ8074 184 42 67 #define QCOM_ID_MSM8274 185 43 68 #define QCOM_ID_MSM8674 186 69 + #define QCOM_ID_MDM9635 187 44 70 #define QCOM_ID_MSM8974PRO_AC 194 45 71 #define QCOM_ID_MSM8126 198 46 72 #define QCOM_ID_APQ8026 199 47 73 #define QCOM_ID_MSM8926 200 74 + #define QCOM_ID_IPQ8062 201 75 + #define QCOM_ID_IPQ8064 202 76 + #define QCOM_ID_IPQ8066 203 77 + #define QCOM_ID_IPQ8068 204 48 78 #define QCOM_ID_MSM8326 205 49 79 #define QCOM_ID_MSM8916 206 50 80 #define QCOM_ID_MSM8994 207 ··· 98 68 #define QCOM_ID_MSM8510 225 99 69 #define QCOM_ID_MSM8512 226 100 70 #define QCOM_ID_MSM8936 233 71 + #define QCOM_ID_MDM9640 234 101 72 #define QCOM_ID_MSM8939 239 102 73 #define QCOM_ID_APQ8036 240 103 74 #define QCOM_ID_APQ8039 241 75 + #define QCOM_ID_MSM8236 242 76 + #define QCOM_ID_MSM8636 243 77 + #define QCOM_ID_MSM8909 245 104 78 #define QCOM_ID_MSM8996 246 105 79 #define QCOM_ID_APQ8016 247 106 80 #define QCOM_ID_MSM8216 248 107 81 #define QCOM_ID_MSM8116 249 108 82 #define QCOM_ID_MSM8616 250 109 83 #define QCOM_ID_MSM8992 251 84 + #define QCOM_ID_APQ8092 252 110 85 #define QCOM_ID_APQ8094 253 86 + #define QCOM_ID_MSM8209 258 87 + #define QCOM_ID_MSM8208 259 88 + #define QCOM_ID_MDM9209 260 89 + #define QCOM_ID_MDM9309 261 90 + #define QCOM_ID_MDM9609 262 91 + #define QCOM_ID_MSM8239 263 92 + #define QCOM_ID_MSM8952 264 93 + #define QCOM_ID_APQ8009 265 111 94 #define QCOM_ID_MSM8956 266 95 + #define QCOM_ID_MSM8929 268 96 + #define QCOM_ID_MSM8629 269 97 + #define QCOM_ID_MSM8229 270 98 + #define QCOM_ID_APQ8029 271 99 + #define QCOM_ID_APQ8056 274 100 + #define QCOM_ID_MSM8609 275 101 + #define QCOM_ID_APQ8076 277 112 102 #define QCOM_ID_MSM8976 278 103 + #define QCOM_ID_MDM9650 279 104 + #define QCOM_ID_IPQ8065 280 105 + #define QCOM_ID_IPQ8069 281 106 + #define QCOM_ID_MDM9655 283 107 + #define QCOM_ID_MDM9250 284 108 + #define QCOM_ID_MDM9255 285 109 + #define QCOM_ID_MDM9350 286 110 + #define QCOM_ID_APQ8052 289 113 111 #define QCOM_ID_MDM9607 290 114 112 #define QCOM_ID_APQ8096 291 115 113 #define QCOM_ID_MSM8998 292 116 114 #define QCOM_ID_MSM8953 293 115 + #define QCOM_ID_MSM8937 294 116 + #define QCOM_ID_APQ8037 295 117 117 #define QCOM_ID_MDM8207 296 118 118 #define QCOM_ID_MDM9207 297 119 119 #define QCOM_ID_MDM9307 298 120 120 #define QCOM_ID_MDM9628 299 121 + #define QCOM_ID_MSM8909W 300 122 + #define QCOM_ID_APQ8009W 301 123 + #define QCOM_ID_MSM8996L 302 124 + #define QCOM_ID_MSM8917 303 121 125 #define QCOM_ID_APQ8053 304 122 126 #define QCOM_ID_MSM8996SG 305 127 + #define QCOM_ID_APQ8017 307 128 + #define QCOM_ID_MSM8217 308 129 + #define QCOM_ID_MSM8617 309 123 130 #define QCOM_ID_MSM8996AU 310 124 131 #define QCOM_ID_APQ8096AU 311 125 132 #define QCOM_ID_APQ8096SG 312 133 + #define QCOM_ID_MSM8940 313 134 + #define QCOM_ID_SDX201 314 126 135 #define QCOM_ID_SDM660 317 127 136 #define QCOM_ID_SDM630 318 128 137 #define QCOM_ID_APQ8098 319 138 + #define QCOM_ID_MSM8920 320 129 139 #define QCOM_ID_SDM845 321 130 140 #define QCOM_ID_MDM9206 322 131 141 #define QCOM_ID_IPQ8074 323 ··· 173 103 #define QCOM_ID_SDM658 325 174 104 #define QCOM_ID_SDA658 326 175 105 #define QCOM_ID_SDA630 327 106 + #define QCOM_ID_MSM8905 331 107 + #define QCOM_ID_SDX202 333 176 108 #define QCOM_ID_SDM450 338 177 109 #define QCOM_ID_SM8150 339 178 110 #define QCOM_ID_SDA845 341 ··· 186 114 #define QCOM_ID_SDM632 349 187 115 #define QCOM_ID_SDA632 350 188 116 #define QCOM_ID_SDA450 351 117 + #define QCOM_ID_SDM439 353 118 + #define QCOM_ID_SDM429 354 189 119 #define QCOM_ID_SM8250 356 190 120 #define QCOM_ID_SA8155 362 121 + #define QCOM_ID_SDA439 363 122 + #define QCOM_ID_SDA429 364 191 123 #define QCOM_ID_IPQ8070 375 192 124 #define QCOM_ID_IPQ8071 376 125 + #define QCOM_ID_QM215 386 193 126 #define QCOM_ID_IPQ8072A 389 194 127 #define QCOM_ID_IPQ8074A 390 195 128 #define QCOM_ID_IPQ8076A 391 ··· 204 127 #define QCOM_ID_IPQ8071A 396 205 128 #define QCOM_ID_IPQ6018 402 206 129 #define QCOM_ID_IPQ6028 403 130 + #define QCOM_ID_SDM429W 416 207 131 #define QCOM_ID_SM4250 417 208 132 #define QCOM_ID_IPQ6000 421 209 133 #define QCOM_ID_IPQ6010 422 210 134 #define QCOM_ID_SC7180 425 211 135 #define QCOM_ID_SM6350 434 136 + #define QCOM_ID_QCM2150 436 137 + #define QCOM_ID_SDA429W 437 212 138 #define QCOM_ID_SM8350 439 213 139 #define QCOM_ID_SM6115 444 214 140 #define QCOM_ID_SC8280XP 449 ··· 235 155 #define QCOM_ID_QRU1032 588 236 156 #define QCOM_ID_QRU1052 589 237 157 #define QCOM_ID_QRU1062 590 158 + #define QCOM_ID_IPQ5332 592 159 + #define QCOM_ID_IPQ5322 593 238 160 239 161 /* 240 162 * The board type and revision information, used by Qualcomm bootloaders and ··· 247 165 248 166 #define QCOM_BOARD_ID_MTP 8 249 167 #define QCOM_BOARD_ID_DRAGONBOARD 10 168 + #define QCOM_BOARD_ID_QRD 11 250 169 #define QCOM_BOARD_ID_SBC 24 251 170 252 171 #endif /* _DT_BINDINGS_ARM_QCOM_IDS_H */
+16
include/dt-bindings/firmware/qcom,scm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ 2 + /* 3 + * Copyright (c) 2010-2015, 2018-2019 The Linux Foundation. All rights reserved. 4 + * Copyright (C) 2015 Linaro Ltd. 5 + */ 6 + 7 + #ifndef _DT_BINDINGS_FIRMWARE_QCOM_SCM_H 8 + #define _DT_BINDINGS_FIRMWARE_QCOM_SCM_H 9 + 10 + #define QCOM_SCM_VMID_HLOS 0x3 11 + #define QCOM_SCM_VMID_MSS_MSA 0xF 12 + #define QCOM_SCM_VMID_WLAN 0x18 13 + #define QCOM_SCM_VMID_WLAN_CE 0x19 14 + #define QCOM_SCM_VMID_NAV 0x2B 15 + 16 + #endif
+10
include/dt-bindings/power/allwinner,sun20i-d1-ppu.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 + 3 + #ifndef _DT_BINDINGS_POWER_SUN20I_D1_PPU_H_ 4 + #define _DT_BINDINGS_POWER_SUN20I_D1_PPU_H_ 5 + 6 + #define PD_CPU 0 7 + #define PD_VE 1 8 + #define PD_DSP 2 9 + 10 + #endif /* _DT_BINDINGS_POWER_SUN20I_D1_PPU_H_ */
+44
include/dt-bindings/power/mediatek,mt8188-power.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ 2 + /* 3 + * Copyright (c) 2022 MediaTek Inc. 4 + * Author: Garmin Chang <garmin.chang@mediatek.com> 5 + */ 6 + 7 + #ifndef _DT_BINDINGS_POWER_MT8188_POWER_H 8 + #define _DT_BINDINGS_POWER_MT8188_POWER_H 9 + 10 + #define MT8188_POWER_DOMAIN_MFG0 0 11 + #define MT8188_POWER_DOMAIN_MFG1 1 12 + #define MT8188_POWER_DOMAIN_MFG2 2 13 + #define MT8188_POWER_DOMAIN_MFG3 3 14 + #define MT8188_POWER_DOMAIN_MFG4 4 15 + #define MT8188_POWER_DOMAIN_PEXTP_MAC_P0 5 16 + #define MT8188_POWER_DOMAIN_PEXTP_PHY_TOP 6 17 + #define MT8188_POWER_DOMAIN_CSIRX_TOP 7 18 + #define MT8188_POWER_DOMAIN_ETHER 8 19 + #define MT8188_POWER_DOMAIN_HDMI_TX 9 20 + #define MT8188_POWER_DOMAIN_ADSP_AO 10 21 + #define MT8188_POWER_DOMAIN_ADSP_INFRA 11 22 + #define MT8188_POWER_DOMAIN_ADSP 12 23 + #define MT8188_POWER_DOMAIN_AUDIO 13 24 + #define MT8188_POWER_DOMAIN_AUDIO_ASRC 14 25 + #define MT8188_POWER_DOMAIN_VPPSYS0 15 26 + #define MT8188_POWER_DOMAIN_VDOSYS0 16 27 + #define MT8188_POWER_DOMAIN_VDOSYS1 17 28 + #define MT8188_POWER_DOMAIN_DP_TX 18 29 + #define MT8188_POWER_DOMAIN_EDP_TX 19 30 + #define MT8188_POWER_DOMAIN_VPPSYS1 20 31 + #define MT8188_POWER_DOMAIN_WPE 21 32 + #define MT8188_POWER_DOMAIN_VDEC0 22 33 + #define MT8188_POWER_DOMAIN_VDEC1 23 34 + #define MT8188_POWER_DOMAIN_VENC 24 35 + #define MT8188_POWER_DOMAIN_IMG_VCORE 25 36 + #define MT8188_POWER_DOMAIN_IMG_MAIN 26 37 + #define MT8188_POWER_DOMAIN_DIP 27 38 + #define MT8188_POWER_DOMAIN_IPE 28 39 + #define MT8188_POWER_DOMAIN_CAM_VCORE 29 40 + #define MT8188_POWER_DOMAIN_CAM_MAIN 30 41 + #define MT8188_POWER_DOMAIN_CAM_SUBA 31 42 + #define MT8188_POWER_DOMAIN_CAM_SUBB 32 43 + 44 + #endif /* _DT_BINDINGS_POWER_MT8188_POWER_H */
+20 -10
include/dt-bindings/power/qcom-rpmpd.h
··· 4 4 #ifndef _DT_BINDINGS_POWER_QCOM_RPMPD_H 5 5 #define _DT_BINDINGS_POWER_QCOM_RPMPD_H 6 6 7 + /* SA8775P Power Domain Indexes */ 8 + #define SA8775P_CX 0 9 + #define SA8775P_CX_AO 1 10 + #define SA8775P_DDR 2 11 + #define SA8775P_EBI 3 12 + #define SA8775P_GFX 4 13 + #define SA8775P_LCX 5 14 + #define SA8775P_LMX 6 15 + #define SA8775P_MMCX 7 16 + #define SA8775P_MMCX_AO 8 17 + #define SA8775P_MSS 9 18 + #define SA8775P_MX 10 19 + #define SA8775P_MX_AO 11 20 + #define SA8775P_MXC 12 21 + #define SA8775P_MXC_AO 13 22 + #define SA8775P_NSP0 14 23 + #define SA8775P_NSP1 15 24 + #define SA8775P_XO 16 25 + 7 26 /* SDM670 Power Domain Indexes */ 8 27 #define SDM670_MX 0 9 28 #define SDM670_MX_AO 1 ··· 211 192 #define RPMH_REGULATOR_LEVEL_MIN_SVS 48 212 193 #define RPMH_REGULATOR_LEVEL_LOW_SVS_D1 56 213 194 #define RPMH_REGULATOR_LEVEL_LOW_SVS 64 195 + #define RPMH_REGULATOR_LEVEL_LOW_SVS_L1 80 214 196 #define RPMH_REGULATOR_LEVEL_SVS 128 215 197 #define RPMH_REGULATOR_LEVEL_SVS_L0 144 216 198 #define RPMH_REGULATOR_LEVEL_SVS_L1 192 ··· 326 306 #define SDM660_SSCCX_VFL 7 327 307 #define SDM660_SSCMX 8 328 308 #define SDM660_SSCMX_VFL 9 329 - 330 - /* SM4250 Power Domains */ 331 - #define SM4250_VDDCX 0 332 - #define SM4250_VDDCX_AO 1 333 - #define SM4250_VDDCX_VFL 2 334 - #define SM4250_VDDMX 3 335 - #define SM4250_VDDMX_AO 4 336 - #define SM4250_VDDMX_VFL 5 337 - #define SM4250_VDD_LPI_CX 6 338 - #define SM4250_VDD_LPI_MX 7 339 309 340 310 /* SM6115 Power Domains */ 341 311 #define SM6115_VDDCX 0
+1
include/dt-bindings/power/r8a779g0-sysc.h
··· 38 38 #define R8A779G0_PD_A3VIP2 58 39 39 #define R8A779G0_PD_A3ISP0 60 40 40 #define R8A779G0_PD_A3ISP1 61 41 + #define R8A779G0_PD_A3DUL 62 41 42 42 43 /* Always-on power area */ 43 44 #define R8A779G0_PD_ALWAYS_ON 64
+17
include/dt-bindings/power/starfive,jh7110-pmu.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 + /* 3 + * Copyright (C) 2022 StarFive Technology Co., Ltd. 4 + * Author: Walker Chen <walker.chen@starfivetech.com> 5 + */ 6 + #ifndef __DT_BINDINGS_POWER_JH7110_POWER_H__ 7 + #define __DT_BINDINGS_POWER_JH7110_POWER_H__ 8 + 9 + #define JH7110_PD_SYSTOP 0 10 + #define JH7110_PD_CPU 1 11 + #define JH7110_PD_GPUA 2 12 + #define JH7110_PD_VDEC 3 13 + #define JH7110_PD_VOUT 4 14 + #define JH7110_PD_ISP 5 15 + #define JH7110_PD_VENC 6 16 + 17 + #endif
+45
include/dt-bindings/reset/mt8195-resets.h
··· 35 35 #define MT8195_INFRA_RST2_PCIE_P1_SWRST 4 36 36 #define MT8195_INFRA_RST2_USBSIF_P1_SWRST 5 37 37 38 + /* VDOSYS1 */ 39 + #define MT8195_VDOSYS1_SW0_RST_B_SMI_LARB2 0 40 + #define MT8195_VDOSYS1_SW0_RST_B_SMI_LARB3 1 41 + #define MT8195_VDOSYS1_SW0_RST_B_GALS 2 42 + #define MT8195_VDOSYS1_SW0_RST_B_FAKE_ENG0 3 43 + #define MT8195_VDOSYS1_SW0_RST_B_FAKE_ENG1 4 44 + #define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA0 5 45 + #define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA1 6 46 + #define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA2 7 47 + #define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA3 8 48 + #define MT8195_VDOSYS1_SW0_RST_B_VPP_MERGE0 9 49 + #define MT8195_VDOSYS1_SW0_RST_B_VPP_MERGE1 10 50 + #define MT8195_VDOSYS1_SW0_RST_B_VPP_MERGE2 11 51 + #define MT8195_VDOSYS1_SW0_RST_B_VPP_MERGE3 12 52 + #define MT8195_VDOSYS1_SW0_RST_B_VPP_MERGE4 13 53 + #define MT8195_VDOSYS1_SW0_RST_B_VPP2_TO_VDO1_DL_ASYNC 14 54 + #define MT8195_VDOSYS1_SW0_RST_B_VPP3_TO_VDO1_DL_ASYNC 15 55 + #define MT8195_VDOSYS1_SW0_RST_B_DISP_MUTEX 16 56 + #define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA4 17 57 + #define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA5 18 58 + #define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA6 19 59 + #define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA7 20 60 + #define MT8195_VDOSYS1_SW0_RST_B_DP_INTF0 21 61 + #define MT8195_VDOSYS1_SW0_RST_B_DPI0 22 62 + #define MT8195_VDOSYS1_SW0_RST_B_DPI1 23 63 + #define MT8195_VDOSYS1_SW0_RST_B_DISP_MONITOR 24 64 + #define MT8195_VDOSYS1_SW0_RST_B_MERGE0_DL_ASYNC 25 65 + #define MT8195_VDOSYS1_SW0_RST_B_MERGE1_DL_ASYNC 26 66 + #define MT8195_VDOSYS1_SW0_RST_B_MERGE2_DL_ASYNC 27 67 + #define MT8195_VDOSYS1_SW0_RST_B_MERGE3_DL_ASYNC 28 68 + #define MT8195_VDOSYS1_SW0_RST_B_MERGE4_DL_ASYNC 29 69 + #define MT8195_VDOSYS1_SW0_RST_B_VDO0_DSC_TO_VDO1_DL_ASYNC 30 70 + #define MT8195_VDOSYS1_SW0_RST_B_VDO0_MERGE_TO_VDO1_DL_ASYNC 31 71 + #define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE0 32 72 + #define MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE0 33 73 + #define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_BE 34 74 + #define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE1 48 75 + #define MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE1 49 76 + #define MT8195_VDOSYS1_SW1_RST_B_DISP_MIXER 50 77 + #define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE0_DL_ASYNC 51 78 + #define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE1_DL_ASYNC 52 79 + #define MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE0_DL_ASYNC 53 80 + #define MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE1_DL_ASYNC 54 81 + #define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_BE_DL_ASYNC 55 82 + 38 83 #endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8195 */
+4
include/linux/firmware/xlnx-zynqmp.h
··· 79 79 #define EVENT_ERROR_PSM_ERR1 (0x28108000U) 80 80 #define EVENT_ERROR_PSM_ERR2 (0x2810C000U) 81 81 82 + /* ZynqMP SD tap delay tuning */ 83 + #define SD_ITAPDLY 0xFF180314 84 + #define SD_OTAPDLYSEL 0xFF180318 85 + 82 86 enum pm_api_cb_id { 83 87 PM_INIT_SUSPEND_CB = 30, 84 88 PM_ACKNOWLEDGE_CB = 31,
+2 -4
include/linux/qcom_scm.h include/linux/firmware/qcom/qcom_scm.h
··· 9 9 #include <linux/types.h> 10 10 #include <linux/cpumask.h> 11 11 12 + #include <dt-bindings/firmware/qcom,scm.h> 13 + 12 14 #define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) 13 15 #define QCOM_SCM_CPU_PWR_DOWN_L2_ON 0x0 14 16 #define QCOM_SCM_CPU_PWR_DOWN_L2_OFF 0x1 ··· 53 51 QCOM_SCM_ICE_CIPHER_AES_256_CBC = 4, 54 52 }; 55 53 56 - #define QCOM_SCM_VMID_HLOS 0x3 57 - #define QCOM_SCM_VMID_MSS_MSA 0xF 58 - #define QCOM_SCM_VMID_WLAN 0x18 59 - #define QCOM_SCM_VMID_WLAN_CE 0x19 60 54 #define QCOM_SCM_PERM_READ 0x4 61 55 #define QCOM_SCM_PERM_WRITE 0x2 62 56 #define QCOM_SCM_PERM_EXEC 0x1
-5
include/linux/scmi_protocol.h
··· 804 804 805 805 #define to_scmi_dev(d) container_of(d, struct scmi_device, dev) 806 806 807 - struct scmi_device * 808 - scmi_device_create(struct device_node *np, struct device *parent, int protocol, 809 - const char *name); 810 - void scmi_device_destroy(struct scmi_device *scmi_dev); 811 - 812 807 struct scmi_device_id { 813 808 u8 protocol_id; 814 809 const char *name;
+26
include/linux/soc/apple/rtkit.h
··· 22 22 * @size: Size of the shared memory buffer. 23 23 * @iova: Device VA of shared memory buffer. 24 24 * @is_mapped: Shared memory buffer is managed by the co-processor. 25 + * @private: Private data pointer for the parent driver. 25 26 */ 26 27 27 28 struct apple_rtkit_shmem { ··· 31 30 size_t size; 32 31 dma_addr_t iova; 33 32 bool is_mapped; 33 + void *private; 34 34 }; 35 35 36 36 /* ··· 80 78 const struct apple_rtkit_ops *ops); 81 79 82 80 /* 81 + * Non-devm version of devm_apple_rtkit_init. Must be freed with 82 + * apple_rtkit_free. 83 + * 84 + * @dev: Pointer to the device node this coprocessor is assocated with 85 + * @cookie: opaque cookie passed to all functions defined in rtkit_ops 86 + * @mbox_name: mailbox name used to communicate with the co-processor 87 + * @mbox_idx: mailbox index to be used if mbox_name is NULL 88 + * @ops: pointer to rtkit_ops to be used for this co-processor 89 + */ 90 + struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie, 91 + const char *mbox_name, int mbox_idx, 92 + const struct apple_rtkit_ops *ops); 93 + 94 + /* 95 + * Free an instance of apple_rtkit. 96 + */ 97 + void apple_rtkit_free(struct apple_rtkit *rtk); 98 + 99 + /* 83 100 * Reinitialize internal structures. Must only be called with the co-processor 84 101 * is held in reset. 85 102 */ ··· 124 103 * Shutdown the co-processor 125 104 */ 126 105 int apple_rtkit_shutdown(struct apple_rtkit *rtk); 106 + 107 + /* 108 + * Put the co-processor into idle mode 109 + */ 110 + int apple_rtkit_idle(struct apple_rtkit *rtk); 127 111 128 112 /* 129 113 * Checks if RTKit is running and ready to handle messages.
+121
include/linux/soc/mediatek/infracfg.h
··· 140 140 #define MT8192_TOP_AXI_PROT_EN_MM_2_MDP_2ND BIT(13) 141 141 #define MT8192_TOP_AXI_PROT_EN_VDNR_CAM BIT(21) 142 142 143 + #define MT8188_TOP_AXI_PROT_EN_SET 0x2A0 144 + #define MT8188_TOP_AXI_PROT_EN_CLR 0x2A4 145 + #define MT8188_TOP_AXI_PROT_EN_STA 0x228 146 + #define MT8188_TOP_AXI_PROT_EN_1_SET 0x2A8 147 + #define MT8188_TOP_AXI_PROT_EN_1_CLR 0x2AC 148 + #define MT8188_TOP_AXI_PROT_EN_1_STA 0x258 149 + #define MT8188_TOP_AXI_PROT_EN_2_SET 0x714 150 + #define MT8188_TOP_AXI_PROT_EN_2_CLR 0x718 151 + #define MT8188_TOP_AXI_PROT_EN_2_STA 0x724 152 + 153 + #define MT8188_TOP_AXI_PROT_EN_MM_SET 0x2D4 154 + #define MT8188_TOP_AXI_PROT_EN_MM_CLR 0x2D8 155 + #define MT8188_TOP_AXI_PROT_EN_MM_STA 0x2EC 156 + #define MT8188_TOP_AXI_PROT_EN_MM_2_SET 0xDCC 157 + #define MT8188_TOP_AXI_PROT_EN_MM_2_CLR 0xDD0 158 + #define MT8188_TOP_AXI_PROT_EN_MM_2_STA 0xDD8 159 + 160 + #define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET 0xB84 161 + #define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR 0xB88 162 + #define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA 0xB90 163 + #define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET 0xBCC 164 + #define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR 0xBD0 165 + #define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA 0xBD8 166 + 167 + #define MT8188_TOP_AXI_PROT_EN_MFG1_STEP1 BIT(11) 168 + #define MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP2 BIT(7) 169 + #define MT8188_TOP_AXI_PROT_EN_1_MFG1_STEP3 BIT(19) 170 + #define MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP4 BIT(5) 171 + #define MT8188_TOP_AXI_PROT_EN_MFG1_STEP5 GENMASK(22, 21) 172 + #define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1_STEP6 BIT(17) 173 + 174 + #define MT8188_TOP_AXI_PROT_EN_PEXTP_MAC_P0_STEP1 BIT(2) 175 + #define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_PEXTP_MAC_P0_STEP2 (BIT(8) | BIT(18) | BIT(30)) 176 + #define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_ETHER_STEP1 BIT(24) 177 + #define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_HDMI_TX_STEP1 BIT(20) 178 + #define MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP1 GENMASK(31, 29) 179 + #define MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP2 (GENMASK(4, 3) | BIT(28)) 180 + #define MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP1 (GENMASK(16, 14) | BIT(23) | \ 181 + BIT(27)) 182 + #define MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP2 (GENMASK(19, 17) | GENMASK(26, 25)) 183 + #define MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP1 GENMASK(11, 8) 184 + #define MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP2 GENMASK(22, 21) 185 + #define MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1 BIT(20) 186 + #define MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2 BIT(12) 187 + #define MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP1 BIT(24) 188 + #define MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP2 BIT(13) 189 + 190 + #define MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP1 BIT(10) 191 + #define MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP2 GENMASK(9, 8) 192 + #define MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP3 BIT(23) 193 + #define MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP4 (BIT(1) | BIT(4) | BIT(11)) 194 + #define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0_STEP5 (BIT(20)) 195 + #define MT8188_TOP_AXI_PROT_EN_MM_VDOSYS0_STEP1 (GENMASK(18, 17) | GENMASK(21, 20)) 196 + #define MT8188_TOP_AXI_PROT_EN_VDOSYS0_STEP2 BIT(6) 197 + #define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0_STEP3 BIT(21) 198 + #define MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP1 GENMASK(31, 30) 199 + #define MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP2 BIT(22) 200 + #define MT8188_TOP_AXI_PROT_EN_MM_2_VDOSYS1_STEP3 BIT(10) 201 + #define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_DP_TX_STEP1 BIT(23) 202 + #define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_EDP_TX_STEP1 BIT(22) 203 + 204 + #define MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP1 GENMASK(6, 5) 205 + #define MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP2 BIT(23) 206 + #define MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS1_STEP3 BIT(18) 207 + #define MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP1 BIT(23) 208 + #define MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP2 BIT(21) 209 + #define MT8188_TOP_AXI_PROT_EN_MM_VDEC0_STEP1 BIT(13) 210 + #define MT8188_TOP_AXI_PROT_EN_MM_2_VDEC0_STEP2 BIT(13) 211 + #define MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP1 BIT(14) 212 + #define MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP2 BIT(29) 213 + #define MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP1 (BIT(9) | BIT(11)) 214 + #define MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP2 BIT(26) 215 + #define MT8188_TOP_AXI_PROT_EN_MM_2_VENC_STEP3 BIT(2) 216 + #define MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP1 (BIT(1) | BIT(3)) 217 + #define MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP2 BIT(25) 218 + #define MT8188_TOP_AXI_PROT_EN_MM_2_IMG_VCORE_STEP3 BIT(16) 219 + #define MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP1 GENMASK(27, 26) 220 + #define MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP2 GENMASK(25, 24) 221 + #define MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP1 (BIT(2) | BIT(4)) 222 + #define MT8188_TOP_AXI_PROT_EN_2_CAM_VCORE_STEP2 BIT(0) 223 + #define MT8188_TOP_AXI_PROT_EN_1_CAM_VCORE_STEP3 BIT(22) 224 + #define MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP4 BIT(24) 225 + #define MT8188_TOP_AXI_PROT_EN_MM_2_CAM_VCORE_STEP5 BIT(17) 226 + #define MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP1 GENMASK(31, 30) 227 + #define MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP2 BIT(2) 228 + #define MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP3 GENMASK(29, 28) 229 + #define MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP4 BIT(1) 230 + 231 + #define MT8188_SMI_COMMON_CLAMP_EN_STA 0x3C0 232 + #define MT8188_SMI_COMMON_CLAMP_EN_SET 0x3C4 233 + #define MT8188_SMI_COMMON_CLAMP_EN_CLR 0x3C8 234 + 235 + #define MT8188_SMI_COMMON_SMI_CLAMP_DIP_TO_VDO0 GENMASK(3, 1) 236 + #define MT8188_SMI_COMMON_SMI_CLAMP_DIP_TO_VPP1 GENMASK(2, 1) 237 + #define MT8188_SMI_COMMON_SMI_CLAMP_IPE_TO_VPP1 BIT(0) 238 + 239 + #define MT8188_SMI_COMMON_SMI_CLAMP_CAM_SUBA_TO_VPP0 GENMASK(3, 2) 240 + #define MT8188_SMI_COMMON_SMI_CLAMP_CAM_SUBB_TO_VDO0 GENMASK(3, 2) 241 + 242 + #define MT8188_SMI_LARB10_RESET_ADDR 0xC 243 + #define MT8188_SMI_LARB11A_RESET_ADDR 0xC 244 + #define MT8188_SMI_LARB11C_RESET_ADDR 0xC 245 + #define MT8188_SMI_LARB12_RESET_ADDR 0xC 246 + #define MT8188_SMI_LARB11B_RESET_ADDR 0xC 247 + #define MT8188_SMI_LARB15_RESET_ADDR 0xC 248 + #define MT8188_SMI_LARB16B_RESET_ADDR 0xA0 249 + #define MT8188_SMI_LARB17B_RESET_ADDR 0xA0 250 + #define MT8188_SMI_LARB16A_RESET_ADDR 0xA0 251 + #define MT8188_SMI_LARB17A_RESET_ADDR 0xA0 252 + 253 + #define MT8188_SMI_LARB10_RESET BIT(0) 254 + #define MT8188_SMI_LARB11A_RESET BIT(0) 255 + #define MT8188_SMI_LARB11C_RESET BIT(0) 256 + #define MT8188_SMI_LARB12_RESET BIT(8) 257 + #define MT8188_SMI_LARB11B_RESET BIT(0) 258 + #define MT8188_SMI_LARB15_RESET BIT(0) 259 + #define MT8188_SMI_LARB16B_RESET BIT(4) 260 + #define MT8188_SMI_LARB17B_RESET BIT(4) 261 + #define MT8188_SMI_LARB16A_RESET BIT(4) 262 + #define MT8188_SMI_LARB17A_RESET BIT(4) 263 + 143 264 #define MT8186_TOP_AXI_PROT_EN_SET (0x2A0) 144 265 #define MT8186_TOP_AXI_PROT_EN_CLR (0x2A4) 145 266 #define MT8186_TOP_AXI_PROT_EN_STA (0x228)
+25
include/linux/soc/mediatek/mtk-mmsys.h
··· 6 6 #ifndef __MTK_MMSYS_H 7 7 #define __MTK_MMSYS_H 8 8 9 + #include <linux/mailbox_controller.h> 10 + #include <linux/mailbox/mtk-cmdq-mailbox.h> 11 + #include <linux/soc/mediatek/mtk-cmdq.h> 12 + 9 13 enum mtk_ddp_comp_id; 10 14 struct device; 11 15 ··· 40 36 DDP_COMPONENT_DSI1, 41 37 DDP_COMPONENT_DSI2, 42 38 DDP_COMPONENT_DSI3, 39 + DDP_COMPONENT_ETHDR_MIXER, 43 40 DDP_COMPONENT_GAMMA, 41 + DDP_COMPONENT_MDP_RDMA0, 42 + DDP_COMPONENT_MDP_RDMA1, 43 + DDP_COMPONENT_MDP_RDMA2, 44 + DDP_COMPONENT_MDP_RDMA3, 45 + DDP_COMPONENT_MDP_RDMA4, 46 + DDP_COMPONENT_MDP_RDMA5, 47 + DDP_COMPONENT_MDP_RDMA6, 48 + DDP_COMPONENT_MDP_RDMA7, 44 49 DDP_COMPONENT_MERGE0, 45 50 DDP_COMPONENT_MERGE1, 46 51 DDP_COMPONENT_MERGE2, ··· 86 73 enum mtk_ddp_comp_id next); 87 74 88 75 void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val); 76 + 77 + void mtk_mmsys_merge_async_config(struct device *dev, int idx, int width, 78 + int height, struct cmdq_pkt *cmdq_pkt); 79 + 80 + void mtk_mmsys_hdr_config(struct device *dev, int be_width, int be_height, 81 + struct cmdq_pkt *cmdq_pkt); 82 + 83 + void mtk_mmsys_mixer_in_config(struct device *dev, int idx, bool alpha_sel, u16 alpha, 84 + u8 mode, u32 biwidth, struct cmdq_pkt *cmdq_pkt); 85 + 86 + void mtk_mmsys_mixer_in_channel_swap(struct device *dev, int idx, bool channel_swap, 87 + struct cmdq_pkt *cmdq_pkt); 89 88 90 89 #endif /* __MTK_MMSYS_H */
+1 -1
include/linux/soc/qcom/apr.h
··· 153 153 154 154 struct apr_driver { 155 155 int (*probe)(struct apr_device *sl); 156 - int (*remove)(struct apr_device *sl); 156 + void (*remove)(struct apr_device *sl); 157 157 int (*callback)(struct apr_device *a, 158 158 struct apr_resp_pkt *d); 159 159 int (*gpr_callback)(struct gpr_resp_pkt *d, void *data, int op);
+32
include/linux/soc/qcom/pmic_glink.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2022, Linaro Ltd 4 + */ 5 + #ifndef __SOC_QCOM_PMIC_GLINK_H__ 6 + #define __SOC_QCOM_PMIC_GLINK_H__ 7 + 8 + struct pmic_glink; 9 + struct pmic_glink_client; 10 + 11 + #define PMIC_GLINK_OWNER_BATTMGR 32778 12 + #define PMIC_GLINK_OWNER_USBC 32779 13 + #define PMIC_GLINK_OWNER_USBC_PAN 32780 14 + 15 + #define PMIC_GLINK_REQ_RESP 1 16 + #define PMIC_GLINK_NOTIFY 2 17 + 18 + struct pmic_glink_hdr { 19 + __le32 owner; 20 + __le32 type; 21 + __le32 opcode; 22 + }; 23 + 24 + int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len); 25 + 26 + struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev, 27 + unsigned int id, 28 + void (*cb)(const void *, size_t, void *), 29 + void (*pdr)(void *, int), 30 + void *priv); 31 + 32 + #endif
+4 -30
include/memory/renesas-rpc-if.h
··· 65 65 66 66 struct rpcif { 67 67 struct device *dev; 68 - void __iomem *base; 69 68 void __iomem *dirmap; 70 - struct regmap *regmap; 71 - struct reset_control *rstc; 72 69 size_t size; 73 - enum rpcif_type type; 74 - enum rpcif_data_dir dir; 75 - u8 bus_size; 76 - u8 xfer_size; 77 - void *buffer; 78 - u32 xferlen; 79 - u32 smcr; 80 - u32 smadr; 81 - u32 command; /* DRCMR or SMCMR */ 82 - u32 option; /* DROPR or SMOPR */ 83 - u32 enable; /* DRENR or SMENR */ 84 - u32 dummy; /* DRDMCR or SMDMCR */ 85 - u32 ddr; /* DRDRENR or SMDRENR */ 86 70 }; 87 71 88 72 int rpcif_sw_init(struct rpcif *rpc, struct device *dev); 89 - int rpcif_hw_init(struct rpcif *rpc, bool hyperflash); 90 - void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs, 73 + int rpcif_hw_init(struct device *dev, bool hyperflash); 74 + void rpcif_prepare(struct device *dev, const struct rpcif_op *op, u64 *offs, 91 75 size_t *len); 92 - int rpcif_manual_xfer(struct rpcif *rpc); 93 - ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf); 94 - 95 - static inline void rpcif_enable_rpm(struct rpcif *rpc) 96 - { 97 - pm_runtime_enable(rpc->dev); 98 - } 99 - 100 - static inline void rpcif_disable_rpm(struct rpcif *rpc) 101 - { 102 - pm_runtime_disable(rpc->dev); 103 - } 76 + int rpcif_manual_xfer(struct device *dev); 77 + ssize_t rpcif_dirmap_read(struct device *dev, u64 offs, size_t len, void *buf); 104 78 105 79 #endif // __RENESAS_RPC_IF_H
+12 -6
include/trace/events/scmi.h
··· 139 139 ); 140 140 141 141 TRACE_EVENT(scmi_msg_dump, 142 - TP_PROTO(u8 protocol_id, u8 msg_id, unsigned char *tag, u16 seq, 143 - int status, void *buf, size_t len), 144 - TP_ARGS(protocol_id, msg_id, tag, seq, status, buf, len), 142 + TP_PROTO(int id, u8 channel_id, u8 protocol_id, u8 msg_id, 143 + unsigned char *tag, u16 seq, int status, 144 + void *buf, size_t len), 145 + TP_ARGS(id, channel_id, protocol_id, msg_id, tag, seq, status, 146 + buf, len), 145 147 146 148 TP_STRUCT__entry( 149 + __field(int, id) 150 + __field(u8, channel_id) 147 151 __field(u8, protocol_id) 148 152 __field(u8, msg_id) 149 153 __array(char, tag, 5) ··· 158 154 ), 159 155 160 156 TP_fast_assign( 157 + __entry->id = id; 158 + __entry->channel_id = channel_id; 161 159 __entry->protocol_id = protocol_id; 162 160 __entry->msg_id = msg_id; 163 161 strscpy(__entry->tag, tag, 5); ··· 169 163 memcpy(__get_dynamic_array(cmd), buf, __entry->len); 170 164 ), 171 165 172 - TP_printk("pt=%02X t=%s msg_id=%02X seq=%04X s=%d pyld=%s", 173 - __entry->protocol_id, __entry->tag, __entry->msg_id, 174 - __entry->seq, __entry->status, 166 + TP_printk("id=%d ch=%02X pt=%02X t=%s msg_id=%02X seq=%04X s=%d pyld=%s", 167 + __entry->id, __entry->channel_id, __entry->protocol_id, 168 + __entry->tag, __entry->msg_id, __entry->seq, __entry->status, 175 169 __print_hex_str(__get_dynamic_array(cmd), __entry->len)) 176 170 ); 177 171 #endif /* _TRACE_SCMI_H */
+1 -3
sound/soc/qcom/qdsp6/q6core.c
··· 339 339 return 0; 340 340 } 341 341 342 - static int q6core_exit(struct apr_device *adev) 342 + static void q6core_exit(struct apr_device *adev) 343 343 { 344 344 struct q6core *core = dev_get_drvdata(&adev->dev); 345 345 ··· 350 350 351 351 g_core = NULL; 352 352 kfree(core); 353 - 354 - return 0; 355 353 } 356 354 357 355 #ifdef CONFIG_OF