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

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

Pull SoC driver updates from Arnd Bergmann:
"Updates are across the usual driver subsystems with SoC specific
drivers:

- added soc specicific drivers for sophgo cv1800 and sg2044, qualcomm
sm8750, and amlogic c3 and s4 chips.

- cache controller updates for sifive chips, plus binding changes for
other cache descriptions.

- memory controller drivers for mediatek mt6893, stm32 and cleanups
for a few more drivers

- reset controller drivers for T-Head TH1502, Sophgo sg2044 and
Renesas RZ/V2H(P)

- SCMI firmware updates to better deal with buggy firmware, plus
better support for Qualcomm X1E and NXP i.MX specific interfaces

- a new platform driver for the crypto firmware on Cznic Turris
Omnia/MOX

- cleanups for the TEE firmware subsystem and amdtee driver

- minor updates and fixes for freescale/nxp, qualcomm, google,
aspeed, wondermedia, ti, nxp, renesas, hisilicon, mediatek,
broadcom and samsung SoCs"

* tag 'soc-drivers-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (133 commits)
soc: aspeed: Add NULL check in aspeed_lpc_enable_snoop()
soc: aspeed: lpc: Fix impossible judgment condition
ARM: aspeed: Don't select SRAM
docs: firmware: qcom_scm: Fix kernel-doc warning
soc: fsl: qe: Consolidate chained IRQ handler install/remove
firmware: qcom: scm: Allow QSEECOM for HP EliteBook Ultra G1q
dt-bindings: mfd: qcom,tcsr: Add compatible for ipq5018
dt-bindings: cache: add QiLai compatible to ax45mp
memory: stm32_omm: Fix error handling in stm32_omm_disable_child()
dt-bindings: cache: Convert marvell,tauros2-cache to DT schema
dt-bindings: cache: Convert marvell,{feroceon,kirkwood}-cache to DT schema
soc: samsung: exynos-pmu: enable CPU hotplug support for gs101
MAINTAINERS: Add google,gs101-pmu-intr-gen.yaml binding file
dt-bindings: soc: samsung: exynos-pmu: gs101: add google,pmu-intr-gen phandle
dt-bindings: soc: google: Add gs101-pmu-intr-gen binding documentation
bus: fsl-mc: Use strscpy() instead of strscpy_pad()
soc: fsl: qbman: Remove const from portal->cgrs allocation type
bus: fsl_mc: Fix driver_managed_dma check
bus: fsl-mc: increase MC_CMD_COMPLETION_TIMEOUT_MS value
bus: fsl-mc: drop useless cleanup
...

+6466 -716
+91
Documentation/ABI/testing/debugfs-scmi-raw
··· 31 31 (receiving an EOF at each message boundary). 32 32 Users: Debugging, any userspace test suite 33 33 34 + What: /sys/kernel/debug/scmi/<n>/raw/message_poll 35 + Date: June 2025 36 + KernelVersion: 6.16 37 + Contact: cristian.marussi@arm.com 38 + Description: SCMI Raw message injection/snooping facility using polling mode; 39 + write a complete SCMI command message (header included) in 40 + little-endian binary format to have it sent to the configured 41 + backend SCMI server for instance <n>, using polling mode on 42 + the reception path. (if transport is polling capable) 43 + Any subsequently received response can be read from this same 44 + entry if it arrived within the configured timeout. 45 + Each write to the entry causes one command request to be built 46 + and sent while the replies are read back one message at time 47 + (receiving an EOF at each message boundary). 48 + Users: Debugging, any userspace test suite 49 + 50 + What: /sys/kernel/debug/scmi/<n>/raw/message_poll_async 51 + Date: June 2025 52 + KernelVersion: 6.16 53 + Contact: cristian.marussi@arm.com 54 + Description: SCMI Raw asynchronous message injection/snooping facility using 55 + polling-mode; write a complete SCMI asynchronous command message 56 + (header included) in little-endian binary format to have it sent 57 + to the configured backend SCMI server for instance <n>, using 58 + polling-mode on the reception path of the immediate part of the 59 + asynchronous command. (if transport is polling capable) 60 + Any subsequently received response can be read from this same 61 + entry if it arrived within the configured timeout. 62 + Any additional delayed response received afterwards can be read 63 + from this same entry too if it arrived within the configured 64 + timeout. 65 + Each write to the entry causes one command request to be built 66 + and sent while the replies are read back one message at time 67 + (receiving an EOF at each message boundary). 68 + Users: Debugging, any userspace test suite 69 + 34 70 What: /sys/kernel/debug/scmi/<n>/raw/errors 35 71 Date: March 2023 36 72 KernelVersion: 6.3 ··· 134 98 in little-endian binary format to have it sent to the configured 135 99 backend SCMI server for instance <n> through the <m> transport 136 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 118 + 119 + 120 + What: /sys/kernel/debug/scmi/<n>/raw/channels/<m>/message_poll 121 + Date: June 2025 122 + KernelVersion: 6.16 123 + Contact: cristian.marussi@arm.com 124 + Description: SCMI Raw message injection/snooping facility using polling mode; 125 + write a complete SCMI command message (header included) in 126 + little-endian binary format to have it sent to the configured 127 + backend SCMI server for instance <n> through the <m> transport 128 + channel, using polling mode on the reception path. 129 + (if transport is polling capable) 130 + Any subsequently received response can be read from this same 131 + entry if it arrived on channel <m> within the configured 132 + timeout. 133 + Each write to the entry causes one command request to be built 134 + and sent while the replies are read back one message at time 135 + (receiving an EOF at each message boundary). 136 + Channel identifier <m> matches the SCMI protocol number which 137 + has been associated with this transport channel in the DT 138 + description, with base protocol number 0x10 being the default 139 + channel for this instance. 140 + Note that these per-channel entries rooted at <..>/channels 141 + exist only if the transport is configured to have more than 142 + one default channel. 143 + Users: Debugging, any userspace test suite 144 + 145 + What: /sys/kernel/debug/scmi/<n>/raw/channels/<m>/message_poll_async 146 + Date: June 2025 147 + KernelVersion: 6.16 148 + Contact: cristian.marussi@arm.com 149 + Description: SCMI Raw asynchronous message injection/snooping facility using 150 + polling-mode; write a complete SCMI asynchronous command message 151 + (header included) in little-endian binary format to have it sent 152 + to the configured backend SCMI server for instance <n> through 153 + the <m> transport channel, using polling mode on the reception 154 + path of the immediate part of the asynchronous command. 155 + (if transport is polling capable) 137 156 Any subsequently received response can be read from this same 138 157 entry if it arrived on channel <m> within the configured 139 158 timeout.
-14
Documentation/ABI/testing/debugfs-turris-mox-rwtm
··· 1 - What: /sys/kernel/debug/turris-mox-rwtm/do_sign 2 - Date: Jun 2020 3 - KernelVersion: 5.8 4 - Contact: Marek Behún <kabel@kernel.org> 5 - Description: 6 - 7 - ======= =========================================================== 8 - (Write) Message to sign with the ECDSA private key stored in 9 - device's OTP. The message must be exactly 64 bytes 10 - (since this is intended for SHA-512 hashes). 11 - (Read) The resulting signature, 136 bytes. This contains the 12 - R and S values of the ECDSA signature, both in 13 - big-endian format. 14 - ======= ===========================================================
-9
Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
··· 12 12 Description: (Read) MAC addresses burned into eFuses of this Turris Mox board. 13 13 Format: %pM 14 14 15 - What: /sys/firmware/turris-mox-rwtm/pubkey 16 - Date: August 2019 17 - KernelVersion: 5.4 18 - Contact: Marek Behún <kabel@kernel.org> 19 - Description: (Read) ECDSA public key (in pubkey hex compressed form) computed 20 - as pair to the ECDSA private key burned into eFuses of this 21 - Turris Mox Board. 22 - Format: string 23 - 24 15 What: /sys/firmware/turris-mox-rwtm/ram_size 25 16 Date: August 2019 26 17 KernelVersion: 5.4
+19 -1
Documentation/devicetree/bindings/cache/andestech,ax45mp-cache.yaml
··· 28 28 properties: 29 29 compatible: 30 30 items: 31 + - enum: 32 + - andestech,qilai-ax45mp-cache 33 + - renesas,r9a07g043f-ax45mp-cache 31 34 - const: andestech,ax45mp-cache 32 35 - const: cache 33 36 ··· 68 65 - cache-size 69 66 - cache-unified 70 67 68 + allOf: 69 + - if: 70 + properties: 71 + compatible: 72 + contains: 73 + const: andestech,qilai-ax45mp-cache 74 + 75 + then: 76 + properties: 77 + cache-sets: 78 + const: 2048 79 + cache-size: 80 + const: 2097152 81 + 71 82 examples: 72 83 - | 73 84 #include <dt-bindings/interrupt-controller/irq.h> 74 85 75 86 cache-controller@13400000 { 76 - compatible = "andestech,ax45mp-cache", "cache"; 87 + compatible = "renesas,r9a07g043f-ax45mp-cache", "andestech,ax45mp-cache", 88 + "cache"; 77 89 reg = <0x13400000 0x100000>; 78 90 interrupts = <508 IRQ_TYPE_LEVEL_HIGH>; 79 91 cache-line-size = <64>;
-16
Documentation/devicetree/bindings/cache/marvell,feroceon-cache.txt
··· 1 - * Marvell Feroceon Cache 2 - 3 - Required properties: 4 - - compatible : Should be either "marvell,feroceon-cache" or 5 - "marvell,kirkwood-cache". 6 - 7 - Optional properties: 8 - - reg : Address of the L2 cache control register. Mandatory for 9 - "marvell,kirkwood-cache", not used by "marvell,feroceon-cache" 10 - 11 - 12 - Example: 13 - l2: l2-cache@20128 { 14 - compatible = "marvell,kirkwood-cache"; 15 - reg = <0x20128 0x4>; 16 - };
+45
Documentation/devicetree/bindings/cache/marvell,kirkwood-cache.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/cache/marvell,kirkwood-cache.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Marvell Feroceon/Kirkwood Cache 8 + 9 + maintainers: 10 + - Andrew Lunn <andrew@lunn.ch> 11 + - Gregory Clement <gregory.clement@bootlin.com> 12 + 13 + properties: 14 + compatible: 15 + enum: 16 + - marvell,feroceon-cache 17 + - marvell,kirkwood-cache 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + allOf: 23 + - if: 24 + properties: 25 + compatible: 26 + contains: 27 + const: marvell,kirkwood-cache 28 + then: 29 + required: 30 + - reg 31 + else: 32 + properties: 33 + reg: false 34 + 35 + required: 36 + - compatible 37 + 38 + additionalProperties: false 39 + 40 + examples: 41 + - | 42 + l2-cache@20128 { 43 + compatible = "marvell,kirkwood-cache"; 44 + reg = <0x20128 0x4>; 45 + };
-17
Documentation/devicetree/bindings/cache/marvell,tauros2-cache.txt
··· 1 - * Marvell Tauros2 Cache 2 - 3 - Required properties: 4 - - compatible : Should be "marvell,tauros2-cache". 5 - - marvell,tauros2-cache-features : Specify the features supported for the 6 - tauros2 cache. 7 - The features including 8 - CACHE_TAUROS2_PREFETCH_ON (1 << 0) 9 - CACHE_TAUROS2_LINEFILL_BURST8 (1 << 1) 10 - The definition can be found at 11 - arch/arm/include/asm/hardware/cache-tauros2.h 12 - 13 - Example: 14 - L2: l2-cache { 15 - compatible = "marvell,tauros2-cache"; 16 - marvell,tauros2-cache-features = <0x3>; 17 - };
+39
Documentation/devicetree/bindings/cache/marvell,tauros2-cache.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/cache/marvell,tauros2-cache.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Marvell Tauros2 Cache 8 + 9 + maintainers: 10 + - Andrew Lunn <andrew@lunn.ch> 11 + - Gregory Clement <gregory.clement@bootlin.com> 12 + 13 + properties: 14 + compatible: 15 + const: marvell,tauros2-cache 16 + 17 + marvell,tauros2-cache-features: 18 + description: > 19 + Specify the features supported for the tauros2 cache. The features include: 20 + 21 + - CACHE_TAUROS2_PREFETCH_ON (1 << 0) 22 + - CACHE_TAUROS2_LINEFILL_BURST8 (1 << 1) 23 + 24 + The definition can be found at arch/arm/include/asm/hardware/cache-tauros2.h 25 + $ref: /schemas/types.yaml#/definitions/uint32 26 + maximum: 0x3 27 + 28 + required: 29 + - compatible 30 + - marvell,tauros2-cache-features 31 + 32 + additionalProperties: false 33 + 34 + examples: 35 + - | 36 + l2-cache { 37 + compatible = "marvell,tauros2-cache"; 38 + marvell,tauros2-cache-features = <0x3>; 39 + };
+2
Documentation/devicetree/bindings/cache/qcom,llcc.yaml
··· 40 40 - qcom,sm8450-llcc 41 41 - qcom,sm8550-llcc 42 42 - qcom,sm8650-llcc 43 + - qcom,sm8750-llcc 43 44 - qcom,x1e80100-llcc 44 45 45 46 reg: ··· 275 274 - qcom,sm8450-llcc 276 275 - qcom,sm8550-llcc 277 276 - qcom,sm8650-llcc 277 + - qcom,sm8750-llcc 278 278 then: 279 279 properties: 280 280 reg:
+41 -3
Documentation/devicetree/bindings/cache/sifive,ccache0.yaml
··· 39 39 - const: cache 40 40 - items: 41 41 - enum: 42 + - eswin,eic7700-l3-cache 42 43 - starfive,jh7100-ccache 43 44 - starfive,jh7110-ccache 44 45 - const: sifive,ccache0 ··· 56 55 enum: [2, 3] 57 56 58 57 cache-sets: 59 - enum: [1024, 2048] 58 + enum: [1024, 2048, 4096] 60 59 61 60 cache-size: 62 - const: 2097152 61 + enum: [2097152, 4194304] 63 62 64 63 cache-unified: true 65 64 ··· 90 89 compatible: 91 90 contains: 92 91 enum: 92 + - eswin,eic7700-l3-cache 93 93 - sifive,fu740-c000-ccache 94 94 - starfive,jh7100-ccache 95 95 - starfive,jh7110-ccache ··· 114 112 properties: 115 113 compatible: 116 114 contains: 115 + const: eswin,eic7700-l3-cache 116 + 117 + then: 118 + properties: 119 + cache-size: 120 + const: 4194304 121 + 122 + else: 123 + properties: 124 + cache-size: 125 + const: 2097152 126 + 127 + - if: 128 + properties: 129 + compatible: 130 + contains: 117 131 enum: 118 132 - sifive,fu740-c000-ccache 119 133 - starfive,jh7100-ccache ··· 140 122 cache-sets: 141 123 const: 2048 142 124 143 - else: 125 + - if: 126 + properties: 127 + compatible: 128 + contains: 129 + enum: 130 + - microchip,mpfs-ccache 131 + - sifive,fu540-c000-ccache 132 + 133 + then: 144 134 properties: 145 135 cache-sets: 146 136 const: 1024 137 + 138 + - if: 139 + properties: 140 + compatible: 141 + contains: 142 + enum: 143 + - eswin,eic7700-l3-cache 144 + 145 + then: 146 + properties: 147 + cache-sets: 148 + const: 4096 147 149 148 150 - if: 149 151 properties:
+35
Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
··· 27 27 mboxes: 28 28 maxItems: 1 29 29 30 + pmic: 31 + description: Child node describing the main PMIC. 32 + type: object 33 + additionalProperties: true 34 + 35 + properties: 36 + compatible: 37 + const: samsung,s2mpg10-pmic 38 + 30 39 shmem: 31 40 description: 32 41 List of phandle pointing to the shared memory (SHM) area. The memory ··· 52 43 53 44 examples: 54 45 - | 46 + #include <dt-bindings/interrupt-controller/irq.h> 47 + 55 48 power-management { 56 49 compatible = "google,gs101-acpm-ipc"; 57 50 mboxes = <&ap2apm_mailbox>; 58 51 shmem = <&apm_sram>; 52 + 53 + pmic { 54 + compatible = "samsung,s2mpg10-pmic"; 55 + interrupts-extended = <&gpa0 6 IRQ_TYPE_LEVEL_LOW>; 56 + 57 + regulators { 58 + LDO1 { 59 + regulator-name = "vdd_ldo1"; 60 + regulator-min-microvolt = <700000>; 61 + regulator-max-microvolt = <1300000>; 62 + regulator-always-on; 63 + }; 64 + 65 + // ... 66 + 67 + BUCK1 { 68 + regulator-name = "vdd_mif"; 69 + regulator-min-microvolt = <450000>; 70 + regulator-max-microvolt = <1300000>; 71 + regulator-always-on; 72 + regulator-boot-on; 73 + }; 74 + }; 75 + }; 59 76 };
+23
Documentation/devicetree/bindings/firmware/nxp,imx95-scmi.yaml
··· 11 11 - Peng Fan <peng.fan@nxp.com> 12 12 13 13 properties: 14 + protocol@80: 15 + description: 16 + SCMI LMM protocol which is for boot, shutdown, and reset of other logical 17 + machines (LM). It is usually used to allow one LM to manage another used 18 + as an offload or accelerator engine. 19 + $ref: '/schemas/firmware/arm,scmi.yaml#/$defs/protocol-node' 20 + unevaluatedProperties: false 21 + 22 + properties: 23 + reg: 24 + const: 0x80 25 + 14 26 protocol@81: 15 27 $ref: '/schemas/firmware/arm,scmi.yaml#/$defs/protocol-node' 16 28 unevaluatedProperties: false ··· 30 18 properties: 31 19 reg: 32 20 const: 0x81 21 + 22 + protocol@82: 23 + description: 24 + SCMI CPU Protocol which allows an agent to start or stop a CPU. It is 25 + used to manage auxiliary CPUs in a LM. 26 + $ref: '/schemas/firmware/arm,scmi.yaml#/$defs/protocol-node' 27 + unevaluatedProperties: false 28 + 29 + properties: 30 + reg: 31 + const: 0x82 33 32 34 33 protocol@84: 35 34 $ref: '/schemas/firmware/arm,scmi.yaml#/$defs/protocol-node'
+37
Documentation/devicetree/bindings/hwinfo/via,vt8500-scc-id.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/hwinfo/via,vt8500-scc-id.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: VIA/WonderMedia SoC system configuration information 8 + 9 + maintainers: 10 + - Alexey Charkov <alchark@gmail.com> 11 + 12 + description: 13 + The system configuration controller on VIA/WonderMedia SoC's contains a chip 14 + identifier and revision used to differentiate between different hardware 15 + versions of on-chip IP blocks having their own peculiarities which may or 16 + may not be captured by their respective DT compatible strings 17 + 18 + properties: 19 + compatible: 20 + items: 21 + - const: via,vt8500-scc-id 22 + 23 + reg: 24 + maxItems: 1 25 + 26 + required: 27 + - compatible 28 + - reg 29 + 30 + additionalProperties: false 31 + 32 + examples: 33 + - | 34 + chipid@d8120000 { 35 + compatible = "via,vt8500-scc-id"; 36 + reg = <0xd8120000 0x4>; 37 + };
+1
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml
··· 33 33 - mediatek,mt2712-smi-common 34 34 - mediatek,mt6779-smi-common 35 35 - mediatek,mt6795-smi-common 36 + - mediatek,mt6893-smi-common 36 37 - mediatek,mt8167-smi-common 37 38 - mediatek,mt8173-smi-common 38 39 - mediatek,mt8183-smi-common
+1
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
··· 21 21 - mediatek,mt2712-smi-larb 22 22 - mediatek,mt6779-smi-larb 23 23 - mediatek,mt6795-smi-larb 24 + - mediatek,mt6893-smi-larb 24 25 - mediatek,mt8167-smi-larb 25 26 - mediatek,mt8173-smi-larb 26 27 - mediatek,mt8183-smi-larb
+226
Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/memory-controllers/st,stm32mp25-omm.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: STM32 Octo Memory Manager (OMM) 8 + 9 + maintainers: 10 + - Patrice Chotard <patrice.chotard@foss.st.com> 11 + 12 + description: | 13 + The STM32 Octo Memory Manager is a low-level interface that enables an 14 + efficient OCTOSPI pin assignment with a full I/O matrix (before alternate 15 + function map) and multiplex of single/dual/quad/octal SPI interfaces over 16 + the same bus. It Supports up to: 17 + - Two single/dual/quad/octal SPI interfaces 18 + - Two ports for pin assignment 19 + 20 + properties: 21 + compatible: 22 + const: st,stm32mp25-omm 23 + 24 + "#address-cells": 25 + const: 2 26 + 27 + "#size-cells": 28 + const: 1 29 + 30 + ranges: 31 + description: | 32 + Reflects the memory layout per OSPI instance. 33 + Format: 34 + <chip-select> 0 <registers base address> <size> 35 + minItems: 2 36 + maxItems: 2 37 + 38 + reg: 39 + items: 40 + - description: OMM registers 41 + - description: OMM memory map area 42 + 43 + reg-names: 44 + items: 45 + - const: regs 46 + - const: memory_map 47 + 48 + memory-region: 49 + description: 50 + Memory region shared between the 2 OCTOSPI instance. 51 + One or two phandle to a node describing a memory mapped region 52 + depending of child number. 53 + minItems: 1 54 + maxItems: 2 55 + 56 + memory-region-names: 57 + description: 58 + Identify to which OSPI instance the memory region belongs to. 59 + items: 60 + enum: [ospi1, ospi2] 61 + minItems: 1 62 + maxItems: 2 63 + 64 + clocks: 65 + maxItems: 3 66 + 67 + clock-names: 68 + items: 69 + - const: omm 70 + - const: ospi1 71 + - const: ospi2 72 + 73 + resets: 74 + maxItems: 3 75 + 76 + reset-names: 77 + items: 78 + - const: omm 79 + - const: ospi1 80 + - const: ospi2 81 + 82 + access-controllers: 83 + maxItems: 1 84 + 85 + power-domains: 86 + maxItems: 1 87 + 88 + st,syscfg-amcr: 89 + $ref: /schemas/types.yaml#/definitions/phandle-array 90 + description: | 91 + The Address Mapping Control Register (AMCR) is used to split the 256MB 92 + memory map area shared between the 2 OSPI instance. The Octo Memory 93 + Manager sets the AMCR depending of the memory-region configuration. 94 + The memory split bitmask description is: 95 + - 000: OCTOSPI1 (256 Mbytes), OCTOSPI2 unmapped 96 + - 001: OCTOSPI1 (192 Mbytes), OCTOSPI2 (64 Mbytes) 97 + - 010: OCTOSPI1 (128 Mbytes), OCTOSPI2 (128 Mbytes) 98 + - 011: OCTOSPI1 (64 Mbytes), OCTOSPI2 (192 Mbytes) 99 + - 1xx: OCTOSPI1 unmapped, OCTOSPI2 (256 Mbytes) 100 + items: 101 + - items: 102 + - description: phandle to syscfg 103 + - description: register offset within syscfg 104 + - description: register bitmask for memory split 105 + 106 + st,omm-req2ack-ns: 107 + description: 108 + In multiplexed mode (MUXEN = 1), this field defines the time in 109 + nanoseconds between two transactions. 110 + default: 0 111 + 112 + st,omm-cssel-ovr: 113 + $ref: /schemas/types.yaml#/definitions/uint32 114 + description: | 115 + Configure the chip select selector override for the 2 OCTOSPIs. 116 + - 0: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS1 117 + - 1: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS1 118 + - 2: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS2 119 + - 3: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS2 120 + minimum: 0 121 + maximum: 3 122 + default: 0 123 + 124 + st,omm-mux: 125 + $ref: /schemas/types.yaml#/definitions/uint32 126 + description: | 127 + Configure the muxing between the 2 OCTOSPIs busses and the 2 output ports. 128 + - 0: direct mode 129 + - 1: mux OCTOSPI1 and OCTOSPI2 to port 1 130 + - 2: swapped mode 131 + - 3: mux OCTOSPI1 and OCTOSPI2 to port 2 132 + minimum: 0 133 + maximum: 3 134 + default: 0 135 + 136 + patternProperties: 137 + ^spi@[0-9]: 138 + type: object 139 + $ref: /schemas/spi/st,stm32mp25-ospi.yaml# 140 + description: Required spi child node 141 + 142 + required: 143 + - compatible 144 + - reg 145 + - "#address-cells" 146 + - "#size-cells" 147 + - clocks 148 + - clock-names 149 + - resets 150 + - reset-names 151 + - st,syscfg-amcr 152 + - ranges 153 + 154 + additionalProperties: false 155 + 156 + examples: 157 + - | 158 + #include <dt-bindings/clock/st,stm32mp25-rcc.h> 159 + #include <dt-bindings/interrupt-controller/arm-gic.h> 160 + #include <dt-bindings/reset/st,stm32mp25-rcc.h> 161 + ommanager@40500000 { 162 + compatible = "st,stm32mp25-omm"; 163 + reg = <0x40500000 0x400>, <0x60000000 0x10000000>; 164 + reg-names = "regs", "memory_map"; 165 + ranges = <0 0 0x40430000 0x400>, 166 + <1 0 0x40440000 0x400>; 167 + memory-region = <&mm_ospi1>, <&mm_ospi2>; 168 + memory-region-names = "ospi1", "ospi2"; 169 + pinctrl-0 = <&ospi_port1_clk_pins_a 170 + &ospi_port1_io03_pins_a 171 + &ospi_port1_cs0_pins_a>; 172 + pinctrl-1 = <&ospi_port1_clk_sleep_pins_a 173 + &ospi_port1_io03_sleep_pins_a 174 + &ospi_port1_cs0_sleep_pins_a>; 175 + pinctrl-names = "default", "sleep"; 176 + clocks = <&rcc CK_BUS_OSPIIOM>, 177 + <&scmi_clk CK_SCMI_OSPI1>, 178 + <&scmi_clk CK_SCMI_OSPI2>; 179 + clock-names = "omm", "ospi1", "ospi2"; 180 + resets = <&rcc OSPIIOM_R>, 181 + <&scmi_reset RST_SCMI_OSPI1>, 182 + <&scmi_reset RST_SCMI_OSPI2>; 183 + reset-names = "omm", "ospi1", "ospi2"; 184 + access-controllers = <&rifsc 111>; 185 + power-domains = <&CLUSTER_PD>; 186 + #address-cells = <2>; 187 + #size-cells = <1>; 188 + st,syscfg-amcr = <&syscfg 0x2c00 0x7>; 189 + st,omm-req2ack-ns = <0>; 190 + st,omm-mux = <0>; 191 + st,omm-cssel-ovr = <0>; 192 + 193 + spi@0 { 194 + compatible = "st,stm32mp25-ospi"; 195 + reg = <0 0 0x400>; 196 + memory-region = <&mm_ospi1>; 197 + interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>; 198 + dmas = <&hpdma 2 0x62 0x00003121 0x0>, 199 + <&hpdma 2 0x42 0x00003112 0x0>; 200 + dma-names = "tx", "rx"; 201 + clocks = <&scmi_clk CK_SCMI_OSPI1>; 202 + resets = <&scmi_reset RST_SCMI_OSPI1>, <&scmi_reset RST_SCMI_OSPI1DLL>; 203 + access-controllers = <&rifsc 74>; 204 + power-domains = <&CLUSTER_PD>; 205 + #address-cells = <1>; 206 + #size-cells = <0>; 207 + st,syscfg-dlyb = <&syscfg 0x1000>; 208 + }; 209 + 210 + spi@1 { 211 + compatible = "st,stm32mp25-ospi"; 212 + reg = <1 0 0x400>; 213 + memory-region = <&mm_ospi1>; 214 + interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>; 215 + dmas = <&hpdma 3 0x62 0x00003121 0x0>, 216 + <&hpdma 3 0x42 0x00003112 0x0>; 217 + dma-names = "tx", "rx"; 218 + clocks = <&scmi_clk CK_KER_OSPI2>; 219 + resets = <&scmi_reset RST_SCMI_OSPI2>, <&scmi_reset RST_SCMI_OSPI1DLL>; 220 + access-controllers = <&rifsc 75>; 221 + power-domains = <&CLUSTER_PD>; 222 + #address-cells = <1>; 223 + #size-cells = <0>; 224 + st,syscfg-dlyb = <&syscfg 0x1000>; 225 + }; 226 + };
+1
Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
··· 41 41 - qcom,sm8450-tcsr 42 42 - qcom,tcsr-apq8064 43 43 - qcom,tcsr-apq8084 44 + - qcom,tcsr-ipq5018 44 45 - qcom,tcsr-ipq5332 45 46 - qcom,tcsr-ipq5424 46 47 - qcom,tcsr-ipq6018
+14 -8
Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
··· 12 12 13 13 properties: 14 14 compatible: 15 - enum: 16 - - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs 17 - - amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs 18 - - amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs 19 - - amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs 20 - - amlogic,meson-s4-reset # Reset Controller on S4 and compatible SoCs 21 - - amlogic,c3-reset # Reset Controller on C3 and compatible SoCs 22 - - amlogic,t7-reset 15 + oneOf: 16 + - enum: 17 + - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs 18 + - amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs 19 + - amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs 20 + - amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs 21 + - amlogic,meson-s4-reset # Reset Controller on S4 and compatible SoCs 22 + - amlogic,c3-reset # Reset Controller on C3 and compatible SoCs 23 + - amlogic,t7-reset 24 + - items: 25 + - enum: 26 + - amlogic,a4-reset 27 + - amlogic,a5-reset 28 + - const: amlogic,meson-s4-reset 23 29 24 30 reg: 25 31 maxItems: 1
+56
Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/reset/renesas,rzv2h-usb2phy-reset.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Renesas RZ/V2H(P) USB2PHY Port reset Control 8 + 9 + maintainers: 10 + - Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> 11 + 12 + description: 13 + The RZ/V2H(P) USB2PHY Control mainly controls Port reset and power down of the 14 + USB2.0 PHY. 15 + 16 + properties: 17 + compatible: 18 + const: renesas,r9a09g057-usb2phy-reset # RZ/V2H(P) 19 + 20 + reg: 21 + maxItems: 1 22 + 23 + clocks: 24 + maxItems: 1 25 + 26 + resets: 27 + maxItems: 1 28 + 29 + power-domains: 30 + maxItems: 1 31 + 32 + '#reset-cells': 33 + const: 0 34 + 35 + required: 36 + - compatible 37 + - reg 38 + - clocks 39 + - resets 40 + - power-domains 41 + - '#reset-cells' 42 + 43 + additionalProperties: false 44 + 45 + examples: 46 + - | 47 + #include <dt-bindings/clock/renesas,r9a09g057-cpg.h> 48 + 49 + reset-controller@15830000 { 50 + compatible = "renesas,r9a09g057-usb2phy-reset"; 51 + reg = <0x15830000 0x10000>; 52 + clocks = <&cpg CPG_MOD 0xb6>; 53 + resets = <&cpg 0xaf>; 54 + power-domains = <&cpg>; 55 + #reset-cells = <0>; 56 + };
+6 -1
Documentation/devicetree/bindings/reset/sophgo,sg2042-reset.yaml
··· 11 11 12 12 properties: 13 13 compatible: 14 - const: sophgo,sg2042-reset 14 + oneOf: 15 + - items: 16 + - enum: 17 + - sophgo,sg2044-reset 18 + - const: sophgo,sg2042-reset 19 + - const: sophgo,sg2042-reset 15 20 16 21 reg: 17 22 maxItems: 1
+44
Documentation/devicetree/bindings/reset/thead,th1520-reset.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/reset/thead,th1520-reset.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: T-HEAD TH1520 SoC Reset Controller 8 + 9 + description: 10 + The T-HEAD TH1520 reset controller is a hardware block that asserts/deasserts 11 + resets for SoC subsystems. 12 + 13 + maintainers: 14 + - Michal Wilczynski <m.wilczynski@samsung.com> 15 + 16 + properties: 17 + compatible: 18 + enum: 19 + - thead,th1520-reset 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + "#reset-cells": 25 + const: 1 26 + 27 + required: 28 + - compatible 29 + - reg 30 + - "#reset-cells" 31 + 32 + additionalProperties: false 33 + 34 + examples: 35 + - | 36 + soc { 37 + #address-cells = <2>; 38 + #size-cells = <2>; 39 + rst: reset-controller@ffef528000 { 40 + compatible = "thead,th1520-reset"; 41 + reg = <0xff 0xef528000 0x0 0x1000>; 42 + #reset-cells = <1>; 43 + }; 44 + };
+2
Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml
··· 22 22 - amlogic,meson-axg-clk-measure 23 23 - amlogic,meson-g12a-clk-measure 24 24 - amlogic,meson-sm1-clk-measure 25 + - amlogic,c3-clk-measure 26 + - amlogic,s4-clk-measure 25 27 26 28 reg: 27 29 maxItems: 1
+35
Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/soc/google/google,gs101-pmu-intr-gen.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Google Power Management Unit (PMU) Interrupt Generation 8 + 9 + description: | 10 + PMU interrupt generator for handshaking between PMU through interrupts. 11 + 12 + maintainers: 13 + - Peter Griffin <peter.griffin@linaro.org> 14 + 15 + properties: 16 + compatible: 17 + items: 18 + - const: google,gs101-pmu-intr-gen 19 + - const: syscon 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + required: 25 + - compatible 26 + - reg 27 + 28 + additionalProperties: false 29 + 30 + examples: 31 + - | 32 + pmu_intr_gen: syscon@17470000 { 33 + compatible = "google,gs101-pmu-intr-gen", "syscon"; 34 + reg = <0x17470000 0x10000>; 35 + };
+1
Documentation/devicetree/bindings/soc/mediatek/mediatek,mt8183-dvfsrc.yaml
··· 23 23 compatible: 24 24 oneOf: 25 25 - enum: 26 + - mediatek,mt6893-dvfsrc 26 27 - mediatek,mt8183-dvfsrc 27 28 - mediatek,mt8195-dvfsrc 28 29 - items:
+15
Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
··· 36 36 - const: err 37 37 - const: wakeup 38 38 39 + clocks: 40 + maxItems: 1 41 + 42 + clock-names: 43 + items: 44 + - const: ram 45 + 39 46 qcom,ipc: 40 47 $ref: /schemas/types.yaml#/definitions/phandle-array 41 48 items: ··· 52 45 - description: u32 representing the ipc bit within the register 53 46 description: 54 47 Three entries specifying the outgoing ipc bit used for signaling the RPM. 48 + 49 + clock-controller: 50 + type: object 51 + additionalProperties: true 52 + properties: 53 + compatible: 54 + contains: 55 + const: qcom,rpmcc 55 56 56 57 patternProperties: 57 58 "^regulators(-[01])?$":
+22 -2
Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml
··· 44 44 45 45 properties: 46 46 compatible: 47 - const: qcom,rpmh-rsc 47 + oneOf: 48 + - items: 49 + - enum: 50 + - qcom,sc7180-rpmh-apps-rsc 51 + - qcom,sdm845-rpmh-apps-rsc 52 + - const: qcom,rpmh-rsc 53 + - const: qcom,rpmh-rsc 48 54 49 55 interrupts: 50 56 minItems: 1 ··· 130 124 - qcom,tcs-offset 131 125 - reg 132 126 - reg-names 133 - - power-domains 127 + 128 + allOf: 129 + # Some platforms may lack a OSI-mode PSCI implementation, which implies the 130 + # system power domain can't provide feedback about entering power collapse 131 + - if: 132 + not: 133 + properties: 134 + compatible: 135 + contains: 136 + enum: 137 + - qcom,sc7180-rpmh-apps-rsc 138 + - qcom,sdm845-rpmh-apps-rsc 139 + then: 140 + required: 141 + - power-domains 134 142 135 143 additionalProperties: false 136 144
+15
Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
··· 129 129 description: 130 130 Node for reboot method 131 131 132 + google,pmu-intr-gen-syscon: 133 + $ref: /schemas/types.yaml#/definitions/phandle 134 + description: 135 + Phandle to PMU interrupt generation interface. 136 + 132 137 required: 133 138 - compatible 134 139 - reg ··· 193 188 else: 194 189 properties: 195 190 dp-phy: false 191 + 192 + - if: 193 + properties: 194 + compatible: 195 + contains: 196 + enum: 197 + - google,gs101-pmu 198 + then: 199 + required: 200 + - google,pmu-intr-gen-syscon 196 201 197 202 examples: 198 203 - |
+86
Documentation/devicetree/bindings/soc/sophgo/sophgo,cv1800b-rtc.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/sophgo/sophgo,cv1800b-rtc.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Real Time Clock of the Sophgo CV1800 SoC 8 + 9 + description: 10 + The RTC (Real Time Clock) is an independently powered module in the chip. It 11 + contains a 32KHz oscillator and a Power-On-Reset (POR) sub-module, which can 12 + be used for time display and scheduled alarm produce. In addition, the 13 + hardware state machine provides triggering and timing control for chip 14 + power-on, power-off and reset. 15 + 16 + Furthermore, the 8051 subsystem is located within RTCSYS and is independently 17 + powered. System software can use the 8051 to manage wake conditions and wake 18 + the system while the system is asleep, and communicate with external devices 19 + through peripheral controllers. 20 + 21 + Technical Reference Manual available at 22 + https://github.com/sophgo/sophgo-doc/tree/main/SG200X/TRM 23 + 24 + maintainers: 25 + - sophgo@lists.linux.dev 26 + 27 + allOf: 28 + - $ref: /schemas/rtc/rtc.yaml# 29 + 30 + properties: 31 + compatible: 32 + items: 33 + - const: sophgo,cv1800b-rtc 34 + - const: syscon 35 + 36 + reg: 37 + maxItems: 1 38 + 39 + interrupts: 40 + items: 41 + - description: RTC Alarm 42 + - description: RTC Longpress 43 + - description: VBAT DET 44 + 45 + interrupt-names: 46 + items: 47 + - const: alarm 48 + - const: longpress 49 + - const: vbat 50 + 51 + clocks: 52 + items: 53 + - description: RTC clock source 54 + - description: DW8051 MCU clock source 55 + 56 + clock-names: 57 + items: 58 + - const: rtc 59 + - const: mcu 60 + 61 + required: 62 + - compatible 63 + - reg 64 + - interrupts 65 + - interrupt-names 66 + - clocks 67 + - clock-names 68 + 69 + unevaluatedProperties: false 70 + 71 + examples: 72 + - | 73 + #include <dt-bindings/clock/sophgo,cv1800.h> 74 + #include <dt-bindings/interrupt-controller/irq.h> 75 + 76 + rtc@5025000 { 77 + compatible = "sophgo,cv1800b-rtc", "syscon"; 78 + reg = <0x5025000 0x2000>; 79 + interrupts = <17 IRQ_TYPE_LEVEL_HIGH>, 80 + <18 IRQ_TYPE_LEVEL_HIGH>, 81 + <19 IRQ_TYPE_LEVEL_HIGH>; 82 + interrupt-names = "alarm", "longpress", "vbat"; 83 + clocks = <&clk CLK_RTC_25M>, 84 + <&clk CLK_SRC_RTC_SYS_0>; 85 + clock-names = "rtc", "mcu"; 86 + };
+31 -1
MAINTAINERS
··· 2537 2537 F: include/linux/armada-37xx-rwtm-mailbox.h 2538 2538 F: include/linux/moxtet.h 2539 2539 F: include/linux/turris-omnia-mcu-interface.h 2540 + F: include/linux/turris-signing-key.h 2540 2541 2541 2542 ARM/FARADAY FA526 PORT 2542 2543 M: Hans Ulli Kroll <ulli.kroll@googlemail.com> ··· 3111 3110 F: arch/arm/mach-shmobile/ 3112 3111 F: arch/arm64/boot/dts/renesas/ 3113 3112 F: arch/riscv/boot/dts/renesas/ 3114 - F: drivers/nvmem/rcar-efuse.c 3115 3113 F: drivers/pmdomain/renesas/ 3116 3114 F: drivers/soc/renesas/ 3117 3115 F: include/linux/soc/renesas/ 3116 + N: rcar 3118 3117 K: \brenesas, 3119 3118 3120 3119 ARM/RISCPC ARCHITECTURE ··· 3481 3480 M: Krzysztof Kozlowski <krzk@kernel.org> 3482 3481 L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 3483 3482 S: Odd Fixes 3483 + F: Documentation/devicetree/bindings/hwinfo/via,vt8500-scc-id.yaml 3484 3484 F: Documentation/devicetree/bindings/i2c/wm,wm8505-i2c.yaml 3485 3485 F: Documentation/devicetree/bindings/interrupt-controller/via,vt8500-intc.yaml 3486 3486 F: Documentation/devicetree/bindings/pwm/via,vt8500-pwm.yaml ··· 3492 3490 F: drivers/mmc/host/wmt-sdmmc.c 3493 3491 F: drivers/pwm/pwm-vt8500.c 3494 3492 F: drivers/rtc/rtc-vt8500.c 3493 + F: drivers/soc/vt8500/ 3495 3494 F: drivers/tty/serial/vt8500_serial.c 3496 3495 F: drivers/video/fbdev/vt8500lcdfb.* 3497 3496 F: drivers/video/fbdev/wm8505fb* ··· 10197 10194 S: Maintained 10198 10195 C: irc://irc.oftc.net/pixel6-kernel-dev 10199 10196 F: Documentation/devicetree/bindings/clock/google,gs101-clock.yaml 10197 + F: Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml 10200 10198 F: arch/arm64/boot/dts/exynos/google/ 10201 10199 F: drivers/clk/samsung/clk-gs101.c 10202 10200 F: drivers/phy/samsung/phy-gs101-ufs.c ··· 21019 21015 F: Documentation/devicetree/bindings/net/renesas,r9a09g057-gbeth.yaml 21020 21016 F: drivers/net/ethernet/stmicro/stmmac/dwmac-renesas-gbeth.c 21021 21017 21018 + RENESAS RZ/V2H(P) USB2PHY PORT RESET DRIVER 21019 + M: Fabrizio Castro <fabrizio.castro.jz@renesas.com> 21020 + M: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> 21021 + L: linux-renesas-soc@vger.kernel.org 21022 + S: Supported 21023 + F: Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml 21024 + F: drivers/reset/reset-rzv2h-usb2phy.c 21025 + 21022 21026 RENESAS RZ/V2M I2C DRIVER 21023 21027 M: Fabrizio Castro <fabrizio.castro.jz@renesas.com> 21024 21028 L: linux-i2c@vger.kernel.org ··· 21239 21227 F: Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml 21240 21228 F: Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml 21241 21229 F: Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml 21230 + F: Documentation/devicetree/bindings/reset/thead,th1520-reset.yaml 21242 21231 F: arch/riscv/boot/dts/thead/ 21243 21232 F: drivers/clk/thead/clk-th1520-ap.c 21244 21233 F: drivers/firmware/thead,th1520-aon.c ··· 21247 21234 F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c 21248 21235 F: drivers/pinctrl/pinctrl-th1520.c 21249 21236 F: drivers/pmdomain/thead/ 21237 + F: drivers/reset/reset-th1520.c 21250 21238 F: include/dt-bindings/clock/thead,th1520-clk-ap.h 21251 21239 F: include/dt-bindings/power/thead,th1520-power.h 21240 + F: include/dt-bindings/reset/thead,th1520-reset.h 21252 21241 F: include/linux/firmware/thead/thead,th1520-aon.h 21253 21242 21254 21243 RNBD BLOCK DRIVERS ··· 23311 23296 S: Maintained 23312 23297 F: drivers/i2c/busses/i2c-stm32* 23313 23298 23299 + ST STM32 OCTO MEMORY MANAGER 23300 + M: Patrice Chotard <patrice.chotard@foss.st.com> 23301 + S: Maintained 23302 + F: Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml 23303 + F: drivers/memory/stm32_omm.c 23304 + 23314 23305 ST STM32 SPI DRIVER 23315 23306 M: Alain Volmat <alain.volmat@foss.st.com> 23316 23307 L: linux-spi@vger.kernel.org ··· 23965 23944 F: include/linux/sc[mp]i_protocol.h 23966 23945 F: include/trace/events/scmi.h 23967 23946 F: include/uapi/linux/virtio_scmi.h 23947 + 23948 + SYSTEM CONTROL MANAGEMENT INTERFACE (SCMI) i.MX Extension Message Protocol drivers 23949 + M: Peng Fan <peng.fan@nxp.com> 23950 + L: arm-scmi@vger.kernel.org 23951 + L: imx@lists.linux.dev 23952 + L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 23953 + S: Maintained 23954 + F: Documentation/devicetree/bindings/firmware/nxp,*scmi.yaml 23955 + F: drivers/firmware/arm_scmi/vendors/imx/ 23968 23956 23969 23957 SYSTEM RESET/SHUTDOWN DRIVERS 23970 23958 M: Sebastian Reichel <sre@kernel.org>
-1
arch/arm/mach-aspeed/Kconfig
··· 2 2 menuconfig ARCH_ASPEED 3 3 bool "Aspeed BMC architectures" 4 4 depends on (CPU_LITTLE_ENDIAN && ARCH_MULTI_V5) || ARCH_MULTI_V6 || ARCH_MULTI_V7 5 - select SRAM 6 5 select WATCHDOG 7 6 select ASPEED_WATCHDOG 8 7 select MFD_SYSCON
+2 -8
drivers/bus/brcmstb_gisb.c
··· 395 395 &dev_attr_gisb_arb_timeout.attr, 396 396 NULL, 397 397 }; 398 - 399 - static struct attribute_group gisb_arb_sysfs_attr_group = { 400 - .attrs = gisb_arb_sysfs_attrs, 401 - }; 398 + ATTRIBUTE_GROUPS(gisb_arb_sysfs); 402 399 403 400 static const struct of_device_id brcmstb_gisb_arb_of_match[] = { 404 401 { .compatible = "brcm,gisb-arb", .data = gisb_offsets_bcm7445 }, ··· 487 490 } 488 491 } 489 492 490 - err = sysfs_create_group(&pdev->dev.kobj, &gisb_arb_sysfs_attr_group); 491 - if (err) 492 - return err; 493 - 494 493 platform_set_drvdata(pdev, gdev); 495 494 496 495 list_add_tail(&gdev->next, &brcmstb_gisb_arb_device_list); ··· 543 550 .name = "brcm-gisb-arb", 544 551 .of_match_table = brcmstb_gisb_arb_of_match, 545 552 .pm = &brcmstb_gisb_arb_pm_ops, 553 + .dev_groups = gisb_arb_sysfs_groups, 546 554 }, 547 555 }; 548 556
-2
drivers/bus/fsl-mc/dprc-driver.c
··· 806 806 dev_set_msi_domain(&mc_dev->dev, NULL); 807 807 } 808 808 809 - fsl_mc_cleanup_all_resource_pools(mc_dev); 810 - 811 809 /* if this step fails we cannot go further with cleanup as there is no way of 812 810 * communicating with the firmware 813 811 */
+2 -2
drivers/bus/fsl-mc/dprc.c
··· 489 489 cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); 490 490 cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); 491 491 cmd_params->obj_id = cpu_to_le32(obj_id); 492 - strscpy_pad(cmd_params->obj_type, obj_type, 16); 492 + strscpy(cmd_params->obj_type, obj_type); 493 493 494 494 /* send command to mc*/ 495 495 return mc_send_command(mc_io, &cmd); ··· 561 561 cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; 562 562 cmd_params->obj_id = cpu_to_le32(obj_id); 563 563 cmd_params->region_index = region_index; 564 - strscpy_pad(cmd_params->obj_type, obj_type, 16); 564 + strscpy(cmd_params->obj_type, obj_type); 565 565 566 566 /* send command to mc*/ 567 567 err = mc_send_command(mc_io, &cmd);
-21
drivers/bus/fsl-mc/fsl-mc-allocator.c
··· 555 555 } 556 556 } 557 557 558 - static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, 559 - enum fsl_mc_pool_type pool_type) 560 - { 561 - struct fsl_mc_resource *resource; 562 - struct fsl_mc_resource *next; 563 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); 564 - struct fsl_mc_resource_pool *res_pool = 565 - &mc_bus->resource_pools[pool_type]; 566 - 567 - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) 568 - devm_kfree(&mc_bus_dev->dev, resource); 569 - } 570 - 571 - void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) 572 - { 573 - int pool_type; 574 - 575 - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) 576 - fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type); 577 - } 578 - 579 558 /* 580 559 * fsl_mc_allocator_probe - callback invoked when an allocatable device is 581 560 * being added to the system
+7 -5
drivers/bus/fsl-mc/fsl-mc-bus.c
··· 139 139 140 140 static int fsl_mc_dma_configure(struct device *dev) 141 141 { 142 + const struct device_driver *drv = READ_ONCE(dev->driver); 142 143 struct device *dma_dev = dev; 143 144 struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 144 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); 145 145 u32 input_id = mc_dev->icid; 146 146 int ret; 147 147 ··· 153 153 else 154 154 ret = acpi_dma_configure_id(dev, DEV_DMA_COHERENT, &input_id); 155 155 156 - /* @mc_drv may not be valid when we're called from the IOMMU layer */ 157 - if (!ret && dev->driver && !mc_drv->driver_managed_dma) { 156 + /* @drv may not be valid when we're called from the IOMMU layer */ 157 + if (!ret && drv && !to_fsl_mc_driver(drv)->driver_managed_dma) { 158 158 ret = iommu_device_use_default_domain(dev); 159 159 if (ret) 160 160 arch_teardown_dma_ops(dev); ··· 906 906 907 907 error_cleanup_dev: 908 908 kfree(mc_dev->regions); 909 - kfree(mc_bus); 910 - kfree(mc_dev); 909 + if (mc_bus) 910 + kfree(mc_bus); 911 + else 912 + kfree(mc_dev); 911 913 912 914 return error; 913 915 }
-2
drivers/bus/fsl-mc/fsl-mc-private.h
··· 629 629 630 630 void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev); 631 631 632 - void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev); 633 - 634 632 int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, 635 633 enum fsl_mc_pool_type pool_type, 636 634 struct fsl_mc_resource
+9 -2
drivers/bus/fsl-mc/fsl-mc-uapi.c
··· 48 48 DPRC_GET_POOL, 49 49 DPRC_GET_POOL_COUNT, 50 50 DPRC_GET_CONNECTION, 51 + DPRC_GET_MEM, 51 52 DPCI_GET_LINK_STATE, 52 53 DPCI_GET_PEER_ATTR, 53 54 DPAIOP_GET_SL_VERSION, ··· 195 194 .token = true, 196 195 .size = 32, 197 196 }, 197 + [DPRC_GET_MEM] = { 198 + .cmdid_value = 0x16D0, 199 + .cmdid_mask = 0xFFF0, 200 + .token = true, 201 + .size = 12, 202 + }, 198 203 199 204 [DPCI_GET_LINK_STATE] = { 200 205 .cmdid_value = 0x0E10, ··· 282 275 .size = 8, 283 276 }, 284 277 [DPSW_GET_TAILDROP] = { 285 - .cmdid_value = 0x0A80, 278 + .cmdid_value = 0x0A90, 286 279 .cmdid_mask = 0xFFF0, 287 280 .token = true, 288 281 .size = 14, 289 282 }, 290 283 [DPSW_SET_TAILDROP] = { 291 - .cmdid_value = 0x0A90, 284 + .cmdid_value = 0x0A80, 292 285 .cmdid_mask = 0xFFF0, 293 286 .token = true, 294 287 .size = 24,
+13 -6
drivers/bus/fsl-mc/mc-io.c
··· 214 214 if (error < 0) 215 215 goto error_cleanup_resource; 216 216 217 - dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev, 218 - &dpmcp_dev->dev, 219 - DL_FLAG_AUTOREMOVE_CONSUMER); 220 - if (!dpmcp_dev->consumer_link) { 221 - error = -EINVAL; 222 - goto error_cleanup_mc_io; 217 + /* If the DPRC device itself tries to allocate a portal (usually for 218 + * UAPI interaction), don't add a device link between them since the 219 + * DPMCP device is an actual child device of the DPRC and a reverse 220 + * dependency is not allowed. 221 + */ 222 + if (mc_dev != mc_bus_dev) { 223 + dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev, 224 + &dpmcp_dev->dev, 225 + DL_FLAG_AUTOREMOVE_CONSUMER); 226 + if (!dpmcp_dev->consumer_link) { 227 + error = -EINVAL; 228 + goto error_cleanup_mc_io; 229 + } 223 230 } 224 231 225 232 *new_mc_io = mc_io;
+1 -1
drivers/bus/fsl-mc/mc-sys.c
··· 19 19 /* 20 20 * Timeout in milliseconds to wait for the completion of an MC command 21 21 */ 22 - #define MC_CMD_COMPLETION_TIMEOUT_MS 500 22 + #define MC_CMD_COMPLETION_TIMEOUT_MS 15000 23 23 24 24 /* 25 25 * usleep_range() min and max values used to throttle down polling
-49
drivers/bus/ti-sysc.c
··· 677 677 return 0; 678 678 } 679 679 680 - /* Interconnect instances to probe before l4_per instances */ 681 - static struct resource early_bus_ranges[] = { 682 - /* am3/4 l4_wkup */ 683 - { .start = 0x44c00000, .end = 0x44c00000 + 0x300000, }, 684 - /* omap4/5 and dra7 l4_cfg */ 685 - { .start = 0x4a000000, .end = 0x4a000000 + 0x300000, }, 686 - /* omap4 l4_wkup */ 687 - { .start = 0x4a300000, .end = 0x4a300000 + 0x30000, }, 688 - /* omap5 and dra7 l4_wkup without dra7 dcan segment */ 689 - { .start = 0x4ae00000, .end = 0x4ae00000 + 0x30000, }, 690 - }; 691 - 692 - static atomic_t sysc_defer = ATOMIC_INIT(10); 693 - 694 - /** 695 - * sysc_defer_non_critical - defer non_critical interconnect probing 696 - * @ddata: device driver data 697 - * 698 - * We want to probe l4_cfg and l4_wkup interconnect instances before any 699 - * l4_per instances as l4_per instances depend on resources on l4_cfg and 700 - * l4_wkup interconnects. 701 - */ 702 - static int sysc_defer_non_critical(struct sysc *ddata) 703 - { 704 - struct resource *res; 705 - int i; 706 - 707 - if (!atomic_read(&sysc_defer)) 708 - return 0; 709 - 710 - for (i = 0; i < ARRAY_SIZE(early_bus_ranges); i++) { 711 - res = &early_bus_ranges[i]; 712 - if (ddata->module_pa >= res->start && 713 - ddata->module_pa <= res->end) { 714 - atomic_set(&sysc_defer, 0); 715 - 716 - return 0; 717 - } 718 - } 719 - 720 - atomic_dec_if_positive(&sysc_defer); 721 - 722 - return -EPROBE_DEFER; 723 - } 724 - 725 680 static struct device_node *stdout_path; 726 681 727 682 static void sysc_init_stdout_path(struct sysc *ddata) ··· 899 944 int error; 900 945 901 946 error = sysc_parse_and_check_child_range(ddata); 902 - if (error) 903 - return error; 904 - 905 - error = sysc_defer_non_critical(ddata); 906 947 if (error) 907 948 return error; 908 949
+2
drivers/cache/sifive_ccache.c
··· 118 118 } 119 119 120 120 static const struct of_device_id sifive_ccache_ids[] = { 121 + { .compatible = "eswin,eic7700-l3-cache", 122 + .data = (void *)(QUIRK_NONSTANDARD_CACHE_OPS) }, 121 123 { .compatible = "sifive,fu540-c000-ccache" }, 122 124 { .compatible = "sifive,fu740-c000-ccache" }, 123 125 { .compatible = "starfive,jh7100-ccache",
+17
drivers/firmware/Kconfig
··· 267 267 other manufacturing data and also utilize the Entropy Bit Generator 268 268 for hardware random number generation. 269 269 270 + if TURRIS_MOX_RWTM 271 + 272 + config TURRIS_MOX_RWTM_KEYCTL 273 + bool "Turris Mox rWTM ECDSA message signing" 274 + default y 275 + depends on KEYS 276 + depends on ASYMMETRIC_KEY_TYPE 277 + select CZNIC_PLATFORMS 278 + select TURRIS_SIGNING_KEY 279 + help 280 + Say Y here to add support for ECDSA message signing with board private 281 + key (each Turris Mox has an ECDSA private key generated in the secure 282 + coprocessor when manufactured). This functionality is exposed via the 283 + keyctl() syscall. 284 + 285 + endif # TURRIS_MOX_RWTM 286 + 270 287 source "drivers/firmware/arm_ffa/Kconfig" 271 288 source "drivers/firmware/broadcom/Kconfig" 272 289 source "drivers/firmware/cirrus/Kconfig"
+13
drivers/firmware/arm_scmi/Kconfig
··· 69 69 such useful debug counters. This can be helpful for debugging and 70 70 SCMI monitoring. 71 71 72 + config ARM_SCMI_QUIRKS 73 + bool "Enable SCMI Quirks framework" 74 + depends on JUMP_LABEL || COMPILE_TEST 75 + default y 76 + help 77 + Enables support for SCMI Quirks framework to workaround SCMI platform 78 + firmware bugs on system already deployed in the wild. 79 + 80 + The framework allows the definition of platform-specific code quirks 81 + that will be associated and enabled only on the desired platforms 82 + depending on the SCMI firmware advertised versions and/or machine 83 + compatibles. 84 + 72 85 source "drivers/firmware/arm_scmi/transports/Kconfig" 73 86 source "drivers/firmware/arm_scmi/vendors/imx/Kconfig" 74 87
+1
drivers/firmware/arm_scmi/Makefile
··· 3 3 scmi-core-objs := $(scmi-bus-y) 4 4 5 5 scmi-driver-y = driver.o notify.o 6 + scmi-driver-$(CONFIG_ARM_SCMI_QUIRKS) += quirks.o 6 7 scmi-driver-$(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT) += raw_mode.o 7 8 scmi-transport-$(CONFIG_ARM_SCMI_HAVE_SHMEM) = shmem.o 8 9 scmi-transport-$(CONFIG_ARM_SCMI_HAVE_MSG) += msg.o
+41 -36
drivers/firmware/arm_scmi/bus.c
··· 201 201 scmi_protocol_device_unrequest(entry); 202 202 } 203 203 204 - static const struct scmi_device_id * 205 - scmi_dev_match_id(struct scmi_device *scmi_dev, const struct scmi_driver *scmi_drv) 204 + static int scmi_dev_match_by_id_table(struct scmi_device *scmi_dev, 205 + const struct scmi_device_id *id_table) 206 206 { 207 - const struct scmi_device_id *id = scmi_drv->id_table; 207 + if (!id_table || !id_table->name) 208 + return 0; 208 209 209 - if (!id) 210 - return NULL; 210 + /* Always skip transport devices from matching */ 211 + for (; id_table->protocol_id && id_table->name; id_table++) 212 + if (id_table->protocol_id == scmi_dev->protocol_id && 213 + strncmp(scmi_dev->name, "__scmi_transport_device", 23) && 214 + !strcmp(id_table->name, scmi_dev->name)) 215 + return 1; 216 + return 0; 217 + } 211 218 212 - for (; id->protocol_id; id++) 213 - if (id->protocol_id == scmi_dev->protocol_id) { 214 - if (!id->name) 215 - return id; 216 - else if (!strcmp(id->name, scmi_dev->name)) 217 - return id; 218 - } 219 - 220 - return NULL; 219 + static int scmi_dev_match_id(struct scmi_device *scmi_dev, 220 + const struct scmi_driver *scmi_drv) 221 + { 222 + return scmi_dev_match_by_id_table(scmi_dev, scmi_drv->id_table); 221 223 } 222 224 223 225 static int scmi_dev_match(struct device *dev, const struct device_driver *drv) 224 226 { 225 227 const struct scmi_driver *scmi_drv = to_scmi_driver(drv); 226 228 struct scmi_device *scmi_dev = to_scmi_dev(dev); 227 - const struct scmi_device_id *id; 228 229 229 - id = scmi_dev_match_id(scmi_dev, scmi_drv); 230 - if (id) 231 - return 1; 232 - 233 - return 0; 230 + return scmi_dev_match_id(scmi_dev, scmi_drv); 234 231 } 235 232 236 233 static int scmi_match_by_id_table(struct device *dev, const void *data) 237 234 { 238 - struct scmi_device *sdev = to_scmi_dev(dev); 235 + struct scmi_device *scmi_dev = to_scmi_dev(dev); 239 236 const struct scmi_device_id *id_table = data; 240 237 241 - return sdev->protocol_id == id_table->protocol_id && 242 - (id_table->name && !strcmp(sdev->name, id_table->name)); 238 + return scmi_dev_match_by_id_table(scmi_dev, id_table); 243 239 } 244 240 245 241 static struct scmi_device *scmi_child_dev_find(struct device *parent, 246 242 int prot_id, const char *name) 247 243 { 248 - struct scmi_device_id id_table; 244 + struct scmi_device_id id_table[2] = { 0 }; 249 245 struct device *dev; 250 246 251 - id_table.protocol_id = prot_id; 252 - id_table.name = name; 247 + id_table[0].protocol_id = prot_id; 248 + id_table[0].name = name; 253 249 254 250 dev = device_find_child(parent, &id_table, scmi_match_by_id_table); 255 251 if (!dev) ··· 459 463 return NULL; 460 464 } 461 465 466 + static struct scmi_device * 467 + _scmi_device_create(struct device_node *np, struct device *parent, 468 + int protocol, const char *name) 469 + { 470 + struct scmi_device *sdev; 471 + 472 + sdev = __scmi_device_create(np, parent, protocol, name); 473 + if (!sdev) 474 + pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n", 475 + of_node_full_name(parent->of_node), protocol, name); 476 + 477 + return sdev; 478 + } 479 + 462 480 /** 463 481 * scmi_device_create - A method to create one or more SCMI devices 464 482 * ··· 505 495 struct scmi_device *scmi_dev = NULL; 506 496 507 497 if (name) 508 - return __scmi_device_create(np, parent, protocol, name); 498 + return _scmi_device_create(np, parent, protocol, name); 509 499 510 500 mutex_lock(&scmi_requested_devices_mtx); 511 501 phead = idr_find(&scmi_requested_devices, protocol); ··· 519 509 list_for_each_entry(rdev, phead, node) { 520 510 struct scmi_device *sdev; 521 511 522 - sdev = __scmi_device_create(np, parent, 523 - rdev->id_table->protocol_id, 524 - rdev->id_table->name); 525 - /* Report errors and carry on... */ 512 + sdev = _scmi_device_create(np, parent, 513 + rdev->id_table->protocol_id, 514 + rdev->id_table->name); 526 515 if (sdev) 527 516 scmi_dev = sdev; 528 - else 529 - pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n", 530 - of_node_full_name(parent->of_node), 531 - rdev->id_table->protocol_id, 532 - rdev->id_table->name); 533 517 } 518 + 534 519 mutex_unlock(&scmi_requested_devices_mtx); 535 520 536 521 return scmi_dev;
+20 -13
drivers/firmware/arm_scmi/clock.c
··· 11 11 12 12 #include "protocols.h" 13 13 #include "notify.h" 14 + #include "quirks.h" 14 15 15 16 /* Updated only after ALL the mandatory features for that version are merged */ 16 17 #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x30000 ··· 430 429 msg->rate_index = cpu_to_le32(desc_index); 431 430 } 432 431 432 + #define QUIRK_OUT_OF_SPEC_TRIPLET \ 433 + ({ \ 434 + /* \ 435 + * A known quirk: a triplet is returned but num_returned != 3 \ 436 + * Check for a safe payload size and fix. \ 437 + */ \ 438 + if (st->num_returned != 3 && st->num_remaining == 0 && \ 439 + st->rx_len == sizeof(*r) + sizeof(__le32) * 2 * 3) { \ 440 + st->num_returned = 3; \ 441 + st->num_remaining = 0; \ 442 + } else { \ 443 + dev_err(p->dev, \ 444 + "Cannot fix out-of-spec reply !\n"); \ 445 + return -EPROTO; \ 446 + } \ 447 + }) 448 + 433 449 static int 434 450 iter_clk_describe_update_state(struct scmi_iterator_state *st, 435 451 const void *response, void *priv) ··· 468 450 p->clk->name, st->num_returned, st->num_remaining, 469 451 st->rx_len); 470 452 471 - /* 472 - * A known quirk: a triplet is returned but num_returned != 3 473 - * Check for a safe payload size and fix. 474 - */ 475 - if (st->num_returned != 3 && st->num_remaining == 0 && 476 - st->rx_len == sizeof(*r) + sizeof(__le32) * 2 * 3) { 477 - st->num_returned = 3; 478 - st->num_remaining = 0; 479 - } else { 480 - dev_err(p->dev, 481 - "Cannot fix out-of-spec reply !\n"); 482 - return -EPROTO; 483 - } 453 + SCMI_QUIRK(clock_rates_triplet_out_of_spec, 454 + QUIRK_OUT_OF_SPEC_TRIPLET); 484 455 } 485 456 486 457 return 0;
+1
drivers/firmware/arm_scmi/common.h
··· 475 475 if (ret) \ 476 476 goto err; \ 477 477 \ 478 + spdev->dev.parent = dev; \ 478 479 ret = platform_device_add(spdev); \ 479 480 if (ret) \ 480 481 goto err; \
+74 -45
drivers/firmware/arm_scmi/driver.c
··· 11 11 * various power domain DVFS including the core/cluster, certain system 12 12 * clocks configuration, thermal sensors and many others. 13 13 * 14 - * Copyright (C) 2018-2024 ARM Ltd. 14 + * Copyright (C) 2018-2025 ARM Ltd. 15 15 */ 16 16 17 17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ··· 38 38 39 39 #include "common.h" 40 40 #include "notify.h" 41 + #include "quirks.h" 41 42 42 43 #include "raw_mode.h" 43 44 ··· 440 439 struct scmi_info *info, 441 440 int prot_id, const char *name) 442 441 { 443 - struct scmi_device *sdev; 444 - 445 442 mutex_lock(&info->devreq_mtx); 446 - sdev = scmi_device_create(np, info->dev, prot_id, name); 447 - if (name && !sdev) 448 - dev_err(info->dev, 449 - "failed to create device for protocol 0x%X (%s)\n", 450 - prot_id, name); 443 + scmi_device_create(np, info->dev, prot_id, name); 451 444 mutex_unlock(&info->devreq_mtx); 452 445 } 453 446 ··· 1185 1190 * RX path since it will be already queued at the end of the TX 1186 1191 * poll loop. 1187 1192 */ 1188 - if (!xfer->hdr.poll_completion) 1193 + if (!xfer->hdr.poll_completion || 1194 + xfer->hdr.type == MSG_TYPE_DELAYED_RESP) 1189 1195 scmi_raw_message_report(info->raw, xfer, 1190 1196 SCMI_RAW_REPLY_QUEUE, 1191 1197 cinfo->id); ··· 1734 1738 } 1735 1739 1736 1740 /** 1741 + * scmi_protocol_msg_check - Check protocol message attributes 1742 + * 1743 + * @ph: A reference to the protocol handle. 1744 + * @message_id: The ID of the message to check. 1745 + * @attributes: A parameter to optionally return the retrieved message 1746 + * attributes, in case of Success. 1747 + * 1748 + * An helper to check protocol message attributes for a specific protocol 1749 + * and message pair. 1750 + * 1751 + * Return: 0 on SUCCESS 1752 + */ 1753 + static int scmi_protocol_msg_check(const struct scmi_protocol_handle *ph, 1754 + u32 message_id, u32 *attributes) 1755 + { 1756 + int ret; 1757 + struct scmi_xfer *t; 1758 + 1759 + ret = xfer_get_init(ph, PROTOCOL_MESSAGE_ATTRIBUTES, 1760 + sizeof(__le32), 0, &t); 1761 + if (ret) 1762 + return ret; 1763 + 1764 + put_unaligned_le32(message_id, t->tx.buf); 1765 + ret = do_xfer(ph, t); 1766 + if (!ret && attributes) 1767 + *attributes = get_unaligned_le32(t->rx.buf); 1768 + xfer_put(ph, t); 1769 + 1770 + return ret; 1771 + } 1772 + 1773 + /** 1737 1774 * struct scmi_iterator - Iterator descriptor 1738 1775 * @msg: A reference to the message TX buffer; filled by @prepare_message with 1739 1776 * a proper custom command payload for each multi-part command request. ··· 1898 1869 __le32 db_preserve_hmask; 1899 1870 }; 1900 1871 1872 + #define QUIRK_PERF_FC_FORCE \ 1873 + ({ \ 1874 + if (pi->proto->id == SCMI_PROTOCOL_PERF && \ 1875 + message_id == 0x8 /* PERF_LEVEL_GET */) \ 1876 + attributes |= BIT(0); \ 1877 + }) 1878 + 1901 1879 static void 1902 1880 scmi_common_fastchannel_init(const struct scmi_protocol_handle *ph, 1903 1881 u8 describe_id, u32 message_id, u32 valid_size, ··· 1914 1878 int ret; 1915 1879 u32 flags; 1916 1880 u64 phys_addr; 1881 + u32 attributes; 1917 1882 u8 size; 1918 1883 void __iomem *addr; 1919 1884 struct scmi_xfer *t; ··· 1922 1885 struct scmi_msg_get_fc_info *info; 1923 1886 struct scmi_msg_resp_desc_fc *resp; 1924 1887 const struct scmi_protocol_instance *pi = ph_to_pi(ph); 1888 + 1889 + /* Check if the MSG_ID supports fastchannel */ 1890 + ret = scmi_protocol_msg_check(ph, message_id, &attributes); 1891 + SCMI_QUIRK(perf_level_get_fc_force, QUIRK_PERF_FC_FORCE); 1892 + if (ret || !MSG_SUPPORTS_FASTCHANNEL(attributes)) { 1893 + dev_dbg(ph->dev, 1894 + "Skip FC init for 0x%02X/%d domain:%d - ret:%d\n", 1895 + pi->proto->id, message_id, domain, ret); 1896 + return; 1897 + } 1925 1898 1926 1899 if (!p_addr) { 1927 1900 ret = -EINVAL; ··· 2048 2001 SCMI_PROTO_FC_RING_DB(32); 2049 2002 else /* db->width == 8 */ 2050 2003 SCMI_PROTO_FC_RING_DB(64); 2051 - } 2052 - 2053 - /** 2054 - * scmi_protocol_msg_check - Check protocol message attributes 2055 - * 2056 - * @ph: A reference to the protocol handle. 2057 - * @message_id: The ID of the message to check. 2058 - * @attributes: A parameter to optionally return the retrieved message 2059 - * attributes, in case of Success. 2060 - * 2061 - * An helper to check protocol message attributes for a specific protocol 2062 - * and message pair. 2063 - * 2064 - * Return: 0 on SUCCESS 2065 - */ 2066 - static int scmi_protocol_msg_check(const struct scmi_protocol_handle *ph, 2067 - u32 message_id, u32 *attributes) 2068 - { 2069 - int ret; 2070 - struct scmi_xfer *t; 2071 - 2072 - ret = xfer_get_init(ph, PROTOCOL_MESSAGE_ATTRIBUTES, 2073 - sizeof(__le32), 0, &t); 2074 - if (ret) 2075 - return ret; 2076 - 2077 - put_unaligned_le32(message_id, t->tx.buf); 2078 - ret = do_xfer(ph, t); 2079 - if (!ret && attributes) 2080 - *attributes = get_unaligned_le32(t->rx.buf); 2081 - xfer_put(ph, t); 2082 - 2083 - return ret; 2084 2004 } 2085 2005 2086 2006 static const struct scmi_proto_helpers_ops helpers_ops = { ··· 2842 2828 struct scmi_info *info = bus_nb_to_scmi_info(nb); 2843 2829 struct scmi_device *sdev = to_scmi_dev(data); 2844 2830 2845 - /* Skip transport devices and devices of different SCMI instances */ 2846 - if (!strncmp(sdev->name, "__scmi_transport_device", 23) || 2847 - sdev->dev.parent != info->dev) 2831 + /* Skip devices of different SCMI instances */ 2832 + if (sdev->dev.parent != info->dev) 2848 2833 return NOTIFY_DONE; 2849 2834 2850 2835 switch (action) { ··· 3114 3101 return &trans->desc; 3115 3102 } 3116 3103 3104 + static void scmi_enable_matching_quirks(struct scmi_info *info) 3105 + { 3106 + struct scmi_revision_info *rev = &info->version; 3107 + 3108 + dev_dbg(info->dev, "Looking for quirks matching: %s/%s/0x%08X\n", 3109 + rev->vendor_id, rev->sub_vendor_id, rev->impl_ver); 3110 + 3111 + /* Enable applicable quirks */ 3112 + scmi_quirks_enable(info->dev, rev->vendor_id, 3113 + rev->sub_vendor_id, rev->impl_ver); 3114 + } 3115 + 3117 3116 static int scmi_probe(struct platform_device *pdev) 3118 3117 { 3119 3118 int ret; ··· 3246 3221 mutex_lock(&scmi_list_mutex); 3247 3222 list_add_tail(&info->node, &scmi_list); 3248 3223 mutex_unlock(&scmi_list_mutex); 3224 + 3225 + scmi_enable_matching_quirks(info); 3249 3226 3250 3227 for_each_available_child_of_node(np, child) { 3251 3228 u32 prot_id; ··· 3407 3380 3408 3381 static int __init scmi_driver_init(void) 3409 3382 { 3383 + scmi_quirks_initialize(); 3384 + 3410 3385 /* Bail out if no SCMI transport was configured */ 3411 3386 if (WARN_ON(!IS_ENABLED(CONFIG_ARM_SCMI_HAVE_TRANSPORT))) 3412 3387 return -EINVAL;
+2
drivers/firmware/arm_scmi/protocols.h
··· 31 31 32 32 #define SCMI_PROTOCOL_VENDOR_BASE 0x80 33 33 34 + #define MSG_SUPPORTS_FASTCHANNEL(x) ((x) & BIT(0)) 35 + 34 36 enum scmi_common_cmd { 35 37 PROTOCOL_VERSION = 0x0, 36 38 PROTOCOL_ATTRIBUTES = 0x1,
+322
drivers/firmware/arm_scmi/quirks.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * System Control and Management Interface (SCMI) Message Protocol Quirks 4 + * 5 + * Copyright (C) 2025 ARM Ltd. 6 + */ 7 + 8 + /** 9 + * DOC: Theory of operation 10 + * 11 + * A framework to define SCMI quirks and their activation conditions based on 12 + * existing static_keys kernel facilities. 13 + * 14 + * Quirks are named and their activation conditions defined using the macro 15 + * DEFINE_SCMI_QUIRK() in this file. 16 + * 17 + * After a quirk is defined, a corresponding entry must also be added to the 18 + * global @scmi_quirks_table in this file using __DECLARE_SCMI_QUIRK_ENTRY(). 19 + * 20 + * Additionally a corresponding quirk declaration must be added also to the 21 + * quirk.h file using DECLARE_SCMI_QUIRK(). 22 + * 23 + * The needed quirk code-snippet itself will be defined local to the SCMI code 24 + * that is meant to fix and will be associated to the previously defined quirk 25 + * and related activation conditions using the macro SCMI_QUIRK(). 26 + * 27 + * At runtime, during the SCMI stack probe sequence, once the SCMI Server had 28 + * advertised the running platform Vendor, SubVendor and Implementation Version 29 + * data, all the defined quirks matching the activation conditions will be 30 + * enabled. 31 + * 32 + * Example 33 + * 34 + * quirk.c 35 + * ------- 36 + * DEFINE_SCMI_QUIRK(fix_me, "vendor", "subvend", "0x12000-0x30000", 37 + * "someone,plat_A", "another,plat_b", "vend,sku"); 38 + * 39 + * static struct scmi_quirk *scmi_quirks_table[] = { 40 + * ... 41 + * __DECLARE_SCMI_QUIRK_ENTRY(fix_me), 42 + * NULL 43 + * }; 44 + * 45 + * quirk.h 46 + * ------- 47 + * DECLARE_SCMI_QUIRK(fix_me); 48 + * 49 + * <somewhere_in_the_scmi_stack.c> 50 + * ------------------------------ 51 + * 52 + * #define QUIRK_CODE_SNIPPET_FIX_ME() \ 53 + * ({ \ 54 + * if (p->condition) \ 55 + * a_ptr->calculated_val = 123; \ 56 + * }) 57 + * 58 + * 59 + * int some_function_to_fix(int param, struct something *p) 60 + * { 61 + * struct some_strut *a_ptr; 62 + * 63 + * a_ptr = some_load_func(p); 64 + * SCMI_QUIRK(fix_me, QUIRK_CODE_SNIPPET_FIX_ME); 65 + * some_more_func(a_ptr); 66 + * ... 67 + * 68 + * return 0; 69 + * } 70 + * 71 + */ 72 + 73 + #include <linux/ctype.h> 74 + #include <linux/device.h> 75 + #include <linux/export.h> 76 + #include <linux/hashtable.h> 77 + #include <linux/kstrtox.h> 78 + #include <linux/of.h> 79 + #include <linux/slab.h> 80 + #include <linux/static_key.h> 81 + #include <linux/string.h> 82 + #include <linux/stringhash.h> 83 + #include <linux/types.h> 84 + 85 + #include "quirks.h" 86 + 87 + #define SCMI_QUIRKS_HT_SZ 4 88 + 89 + struct scmi_quirk { 90 + bool enabled; 91 + const char *name; 92 + char *vendor; 93 + char *sub_vendor_id; 94 + char *impl_ver_range; 95 + u32 start_range; 96 + u32 end_range; 97 + struct static_key_false *key; 98 + struct hlist_node hash; 99 + unsigned int hkey; 100 + const char *const compats[]; 101 + }; 102 + 103 + #define __DEFINE_SCMI_QUIRK_ENTRY(_qn, _ven, _sub, _impl, ...) \ 104 + static struct scmi_quirk scmi_quirk_entry_ ## _qn = { \ 105 + .name = __stringify(quirk_ ## _qn), \ 106 + .vendor = _ven, \ 107 + .sub_vendor_id = _sub, \ 108 + .impl_ver_range = _impl, \ 109 + .key = &(scmi_quirk_ ## _qn), \ 110 + .compats = { __VA_ARGS__ __VA_OPT__(,) NULL }, \ 111 + } 112 + 113 + #define __DECLARE_SCMI_QUIRK_ENTRY(_qn) (&(scmi_quirk_entry_ ## _qn)) 114 + 115 + /* 116 + * Define a quirk by name and provide the matching tokens where: 117 + * 118 + * _qn: A string which will be used to build the quirk and the global 119 + * static_key names. 120 + * _ven : SCMI Vendor ID string match, NULL means any. 121 + * _sub : SCMI SubVendor ID string match, NULL means any. 122 + * _impl : SCMI Implementation Version string match, NULL means any. 123 + * This string can be used to express version ranges which will be 124 + * interpreted as follows: 125 + * 126 + * NULL [0, 0xFFFFFFFF] 127 + * "X" [X, X] 128 + * "X-" [X, 0xFFFFFFFF] 129 + * "-X" [0, X] 130 + * "X-Y" [X, Y] 131 + * 132 + * with X <= Y and <v> in [X, Y] meaning X <= <v> <= Y 133 + * 134 + * ... : An optional variadic macros argument used to provide a comma-separated 135 + * list of compatible strings matches; when no variadic argument is 136 + * provided, ANY compatible will match this quirk. 137 + * 138 + * This implicitly define also a properly named global static-key that 139 + * will be used to dynamically enable the quirk at initialization time. 140 + * 141 + * Note that it is possible to associate multiple quirks to the same 142 + * matching pattern, if your firmware quality is really astounding :P 143 + * 144 + * Example: 145 + * 146 + * Compatibles list NOT provided, so ANY compatible will match: 147 + * 148 + * DEFINE_SCMI_QUIRK(my_new_issue, "Vend", "SVend", "0x12000-0x30000"); 149 + * 150 + * 151 + * A few compatibles provided to match against: 152 + * 153 + * DEFINE_SCMI_QUIRK(my_new_issue, "Vend", "SVend", "0x12000-0x30000", 154 + * "xvend,plat_a", "xvend,plat_b", "xvend,sku_name"); 155 + */ 156 + #define DEFINE_SCMI_QUIRK(_qn, _ven, _sub, _impl, ...) \ 157 + DEFINE_STATIC_KEY_FALSE(scmi_quirk_ ## _qn); \ 158 + __DEFINE_SCMI_QUIRK_ENTRY(_qn, _ven, _sub, _impl, ##__VA_ARGS__) 159 + 160 + /* 161 + * Same as DEFINE_SCMI_QUIRK but EXPORTED: this is meant to address quirks 162 + * that possibly reside in code that is included in loadable kernel modules 163 + * that needs to be able to access the global static keys at runtime to 164 + * determine if enabled or not. (see SCMI_QUIRK to understand usage) 165 + */ 166 + #define DEFINE_SCMI_QUIRK_EXPORTED(_qn, _ven, _sub, _impl, ...) \ 167 + DEFINE_STATIC_KEY_FALSE(scmi_quirk_ ## _qn); \ 168 + EXPORT_SYMBOL_GPL(scmi_quirk_ ## _qn); \ 169 + __DEFINE_SCMI_QUIRK_ENTRY(_qn, _ven, _sub, _impl, ##__VA_ARGS__) 170 + 171 + /* Global Quirks Definitions */ 172 + DEFINE_SCMI_QUIRK(clock_rates_triplet_out_of_spec, NULL, NULL, NULL); 173 + DEFINE_SCMI_QUIRK(perf_level_get_fc_force, "Qualcomm", NULL, "0x20000-"); 174 + 175 + /* 176 + * Quirks Pointers Array 177 + * 178 + * This is filled at compile-time with the list of pointers to all the currently 179 + * defined quirks descriptors. 180 + */ 181 + static struct scmi_quirk *scmi_quirks_table[] = { 182 + __DECLARE_SCMI_QUIRK_ENTRY(clock_rates_triplet_out_of_spec), 183 + __DECLARE_SCMI_QUIRK_ENTRY(perf_level_get_fc_force), 184 + NULL 185 + }; 186 + 187 + /* 188 + * Quirks HashTable 189 + * 190 + * A run-time populated hashtable containing all the defined quirks descriptors 191 + * hashed by matching pattern. 192 + */ 193 + static DEFINE_READ_MOSTLY_HASHTABLE(scmi_quirks_ht, SCMI_QUIRKS_HT_SZ); 194 + 195 + static unsigned int scmi_quirk_signature(const char *vend, const char *sub_vend) 196 + { 197 + char *signature, *p; 198 + unsigned int hash32; 199 + unsigned long hash = 0; 200 + 201 + /* vendor_id/sub_vendor_id guaranteed <= SCMI_SHORT_NAME_MAX_SIZE */ 202 + signature = kasprintf(GFP_KERNEL, "|%s|%s|", vend ?: "", sub_vend ?: ""); 203 + if (!signature) 204 + return 0; 205 + 206 + pr_debug("SCMI Quirk Signature >>>%s<<<\n", signature); 207 + 208 + p = signature; 209 + while (*p) 210 + hash = partial_name_hash(tolower(*p++), hash); 211 + hash32 = end_name_hash(hash); 212 + 213 + kfree(signature); 214 + 215 + return hash32; 216 + } 217 + 218 + static int scmi_quirk_range_parse(struct scmi_quirk *quirk) 219 + { 220 + const char *last, *first = quirk->impl_ver_range; 221 + size_t len; 222 + char *sep; 223 + int ret; 224 + 225 + quirk->start_range = 0; 226 + quirk->end_range = 0xFFFFFFFF; 227 + len = quirk->impl_ver_range ? strlen(quirk->impl_ver_range) : 0; 228 + if (!len) 229 + return 0; 230 + 231 + last = first + len - 1; 232 + sep = strchr(quirk->impl_ver_range, '-'); 233 + if (sep) 234 + *sep = '\0'; 235 + 236 + if (sep == first) /* -X */ 237 + ret = kstrtouint(first + 1, 0, &quirk->end_range); 238 + else /* X OR X- OR X-y */ 239 + ret = kstrtouint(first, 0, &quirk->start_range); 240 + if (ret) 241 + return ret; 242 + 243 + if (!sep) 244 + quirk->end_range = quirk->start_range; 245 + else if (sep != last) /* x-Y */ 246 + ret = kstrtouint(sep + 1, 0, &quirk->end_range); 247 + 248 + if (quirk->start_range > quirk->end_range) 249 + return -EINVAL; 250 + 251 + return ret; 252 + } 253 + 254 + void scmi_quirks_initialize(void) 255 + { 256 + struct scmi_quirk *quirk; 257 + int i; 258 + 259 + for (i = 0, quirk = scmi_quirks_table[0]; quirk; 260 + i++, quirk = scmi_quirks_table[i]) { 261 + int ret; 262 + 263 + ret = scmi_quirk_range_parse(quirk); 264 + if (ret) { 265 + pr_err("SCMI skip QUIRK [%s] - BAD RANGE - |%s|\n", 266 + quirk->name, quirk->impl_ver_range); 267 + continue; 268 + } 269 + quirk->hkey = scmi_quirk_signature(quirk->vendor, 270 + quirk->sub_vendor_id); 271 + 272 + hash_add(scmi_quirks_ht, &quirk->hash, quirk->hkey); 273 + 274 + pr_debug("Registered SCMI QUIRK [%s] -- %p - Key [0x%08X] - %s/%s/[0x%08X-0x%08X]\n", 275 + quirk->name, quirk, quirk->hkey, 276 + quirk->vendor, quirk->sub_vendor_id, 277 + quirk->start_range, quirk->end_range); 278 + } 279 + 280 + pr_debug("SCMI Quirks initialized\n"); 281 + } 282 + 283 + void scmi_quirks_enable(struct device *dev, const char *vend, 284 + const char *subv, const u32 impl) 285 + { 286 + for (int i = 3; i >= 0; i--) { 287 + struct scmi_quirk *quirk; 288 + unsigned int hkey; 289 + 290 + hkey = scmi_quirk_signature(i > 1 ? vend : NULL, 291 + i > 2 ? subv : NULL); 292 + 293 + /* 294 + * Note that there could be multiple matches so we 295 + * will enable multiple quirk part of a hash collision 296 + * domain...BUT we cannot assume that ALL quirks on the 297 + * same collision domain are a full match. 298 + */ 299 + hash_for_each_possible(scmi_quirks_ht, quirk, hash, hkey) { 300 + if (quirk->enabled || quirk->hkey != hkey || 301 + impl < quirk->start_range || 302 + impl > quirk->end_range) 303 + continue; 304 + 305 + if (quirk->compats[0] && 306 + !of_machine_compatible_match(quirk->compats)) 307 + continue; 308 + 309 + dev_info(dev, "Enabling SCMI Quirk [%s]\n", 310 + quirk->name); 311 + 312 + dev_dbg(dev, 313 + "Quirk matched on: %s/%s/%s/[0x%08X-0x%08X]\n", 314 + quirk->compats[0], quirk->vendor, 315 + quirk->sub_vendor_id, 316 + quirk->start_range, quirk->end_range); 317 + 318 + static_branch_enable(quirk->key); 319 + quirk->enabled = true; 320 + } 321 + } 322 + }
+52
drivers/firmware/arm_scmi/quirks.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * System Control and Management Interface (SCMI) Message Protocol Quirks 4 + * 5 + * Copyright (C) 2025 ARM Ltd. 6 + */ 7 + #ifndef _SCMI_QUIRKS_H 8 + #define _SCMI_QUIRKS_H 9 + 10 + #include <linux/static_key.h> 11 + #include <linux/types.h> 12 + 13 + #ifdef CONFIG_ARM_SCMI_QUIRKS 14 + 15 + #define DECLARE_SCMI_QUIRK(_qn) \ 16 + DECLARE_STATIC_KEY_FALSE(scmi_quirk_ ## _qn) 17 + 18 + /* 19 + * A helper to associate the actual code snippet to use as a quirk 20 + * named as _qn. 21 + */ 22 + #define SCMI_QUIRK(_qn, _blk) \ 23 + do { \ 24 + if (static_branch_unlikely(&(scmi_quirk_ ## _qn))) \ 25 + (_blk); \ 26 + } while (0) 27 + 28 + void scmi_quirks_initialize(void); 29 + void scmi_quirks_enable(struct device *dev, const char *vend, 30 + const char *subv, const u32 impl); 31 + 32 + #else 33 + 34 + #define DECLARE_SCMI_QUIRK(_qn) 35 + /* Force quirks compilation even when SCMI Quirks are disabled */ 36 + #define SCMI_QUIRK(_qn, _blk) \ 37 + do { \ 38 + if (0) \ 39 + (_blk); \ 40 + } while (0) 41 + 42 + static inline void scmi_quirks_initialize(void) { } 43 + static inline void scmi_quirks_enable(struct device *dev, const char *vend, 44 + const char *sub_vend, const u32 impl) { } 45 + 46 + #endif /* CONFIG_ARM_SCMI_QUIRKS */ 47 + 48 + /* Quirk delarations */ 49 + DECLARE_SCMI_QUIRK(clock_rates_triplet_out_of_spec); 50 + DECLARE_SCMI_QUIRK(perf_level_get_fc_force); 51 + 52 + #endif /* _SCMI_QUIRKS_H */
+67 -5
drivers/firmware/arm_scmi/raw_mode.c
··· 671 671 * @len: Length of the message in @buf. 672 672 * @chan_id: The channel ID to use. 673 673 * @async: A flag stating if an asynchronous command is required. 674 + * @poll: A flag stating if a polling transmission is required. 674 675 * 675 676 * Return: 0 on Success 676 677 */ 677 678 static int scmi_raw_message_send(struct scmi_raw_mode_info *raw, 678 - void *buf, size_t len, u8 chan_id, bool async) 679 + void *buf, size_t len, u8 chan_id, 680 + bool async, bool poll) 679 681 { 680 682 int ret; 681 683 struct scmi_xfer *xfer; ··· 685 683 ret = scmi_xfer_raw_get_init(raw, buf, len, &xfer); 686 684 if (ret) 687 685 return ret; 686 + 687 + if (poll) { 688 + if (is_transport_polling_capable(raw->desc)) { 689 + xfer->hdr.poll_completion = true; 690 + } else { 691 + dev_err(raw->handle->dev, 692 + "Failed to send RAW message - Polling NOT supported\n"); 693 + return -EINVAL; 694 + } 695 + } 688 696 689 697 ret = scmi_do_xfer_raw_start(raw, xfer, chan_id, async); 690 698 if (ret) ··· 813 801 static ssize_t scmi_dbg_raw_mode_common_write(struct file *filp, 814 802 const char __user *buf, 815 803 size_t count, loff_t *ppos, 816 - bool async) 804 + bool async, bool poll) 817 805 { 818 806 int ret; 819 807 struct scmi_dbg_raw_data *rd = filp->private_data; ··· 843 831 } 844 832 845 833 ret = scmi_raw_message_send(rd->raw, rd->tx.buf, rd->tx_size, 846 - rd->chan_id, async); 834 + rd->chan_id, async, poll); 847 835 848 836 /* Reset ppos for next message ... */ 849 837 rd->tx_size = 0; ··· 887 875 const char __user *buf, 888 876 size_t count, loff_t *ppos) 889 877 { 890 - return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, false); 878 + return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, 879 + false, false); 891 880 } 892 881 893 882 static __poll_t scmi_dbg_raw_mode_message_poll(struct file *filp, ··· 977 964 const char __user *buf, 978 965 size_t count, loff_t *ppos) 979 966 { 980 - return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, true); 967 + return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, 968 + true, false); 981 969 } 982 970 983 971 static const struct file_operations scmi_dbg_raw_mode_message_async_fops = { ··· 986 972 .release = scmi_dbg_raw_mode_release, 987 973 .read = scmi_dbg_raw_mode_message_read, 988 974 .write = scmi_dbg_raw_mode_message_async_write, 975 + .poll = scmi_dbg_raw_mode_message_poll, 976 + .owner = THIS_MODULE, 977 + }; 978 + 979 + static ssize_t scmi_dbg_raw_mode_message_poll_write(struct file *filp, 980 + const char __user *buf, 981 + size_t count, loff_t *ppos) 982 + { 983 + return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, 984 + false, true); 985 + } 986 + 987 + static const struct file_operations scmi_dbg_raw_mode_message_poll_fops = { 988 + .open = scmi_dbg_raw_mode_open, 989 + .release = scmi_dbg_raw_mode_release, 990 + .read = scmi_dbg_raw_mode_message_read, 991 + .write = scmi_dbg_raw_mode_message_poll_write, 992 + .poll = scmi_dbg_raw_mode_message_poll, 993 + .owner = THIS_MODULE, 994 + }; 995 + 996 + static ssize_t scmi_dbg_raw_mode_message_poll_async_write(struct file *filp, 997 + const char __user *buf, 998 + size_t count, loff_t *ppos) 999 + { 1000 + return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, 1001 + true, true); 1002 + } 1003 + 1004 + static const struct file_operations scmi_dbg_raw_mode_message_poll_async_fops = { 1005 + .open = scmi_dbg_raw_mode_open, 1006 + .release = scmi_dbg_raw_mode_release, 1007 + .read = scmi_dbg_raw_mode_message_read, 1008 + .write = scmi_dbg_raw_mode_message_poll_async_write, 989 1009 .poll = scmi_dbg_raw_mode_message_poll, 990 1010 .owner = THIS_MODULE, 991 1011 }; ··· 1247 1199 debugfs_create_file("message_async", 0600, raw->dentry, raw, 1248 1200 &scmi_dbg_raw_mode_message_async_fops); 1249 1201 1202 + debugfs_create_file("message_poll", 0600, raw->dentry, raw, 1203 + &scmi_dbg_raw_mode_message_poll_fops); 1204 + 1205 + debugfs_create_file("message_poll_async", 0600, raw->dentry, raw, 1206 + &scmi_dbg_raw_mode_message_poll_async_fops); 1207 + 1250 1208 debugfs_create_file("notification", 0400, raw->dentry, raw, 1251 1209 &scmi_dbg_raw_mode_notification_fops); 1252 1210 ··· 1284 1230 debugfs_create_file_aux_num("message_async", 0600, chd, 1285 1231 raw, channels[i], 1286 1232 &scmi_dbg_raw_mode_message_async_fops); 1233 + 1234 + debugfs_create_file_aux_num("message_poll", 0600, chd, 1235 + raw, channels[i], 1236 + &scmi_dbg_raw_mode_message_poll_fops); 1237 + 1238 + debugfs_create_file_aux_num("message_poll_async", 0600, 1239 + chd, raw, channels[i], 1240 + &scmi_dbg_raw_mode_message_poll_async_fops); 1287 1241 } 1288 1242 } 1289 1243
+24
drivers/firmware/arm_scmi/vendors/imx/Kconfig
··· 12 12 To compile this driver as a module, choose M here: the 13 13 module will be called imx-sm-bbm. 14 14 15 + config IMX_SCMI_CPU_EXT 16 + tristate "i.MX SCMI CPU EXTENSION" 17 + depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF) 18 + depends on IMX_SCMI_CPU_DRV 19 + default y if ARCH_MXC 20 + help 21 + This enables i.MX System CPU Protocol to manage cpu 22 + start, stop and etc. 23 + 24 + To compile this driver as a module, choose M here: the 25 + module will be called imx-sm-cpu. 26 + 27 + config IMX_SCMI_LMM_EXT 28 + tristate "i.MX SCMI LMM EXTENSION" 29 + depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF) 30 + depends on IMX_SCMI_LMM_DRV 31 + default y if ARCH_MXC 32 + help 33 + This enables i.MX System Logical Machine Protocol to 34 + manage Logical Machines boot, shutdown and etc. 35 + 36 + To compile this driver as a module, choose M here: the 37 + module will be called imx-sm-lmm. 38 + 15 39 config IMX_SCMI_MISC_EXT 16 40 tristate "i.MX SCMI MISC EXTENSION" 17 41 depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+2
drivers/firmware/arm_scmi/vendors/imx/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 obj-$(CONFIG_IMX_SCMI_BBM_EXT) += imx-sm-bbm.o 3 + obj-$(CONFIG_IMX_SCMI_CPU_EXT) += imx-sm-cpu.o 4 + obj-$(CONFIG_IMX_SCMI_LMM_EXT) += imx-sm-lmm.o 3 5 obj-$(CONFIG_IMX_SCMI_MISC_EXT) += imx-sm-misc.o
+276
drivers/firmware/arm_scmi/vendors/imx/imx-sm-cpu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * System control and Management Interface (SCMI) NXP CPU Protocol 4 + * 5 + * Copyright 2025 NXP 6 + */ 7 + 8 + #include <linux/bits.h> 9 + #include <linux/io.h> 10 + #include <linux/module.h> 11 + #include <linux/of.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/scmi_protocol.h> 14 + #include <linux/scmi_imx_protocol.h> 15 + 16 + #include "../../protocols.h" 17 + #include "../../notify.h" 18 + 19 + #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x10000 20 + 21 + enum scmi_imx_cpu_protocol_cmd { 22 + SCMI_IMX_CPU_ATTRIBUTES = 0x3, 23 + SCMI_IMX_CPU_START = 0x4, 24 + SCMI_IMX_CPU_STOP = 0x5, 25 + SCMI_IMX_CPU_RESET_VECTOR_SET = 0x6, 26 + SCMI_IMX_CPU_INFO_GET = 0xC, 27 + }; 28 + 29 + struct scmi_imx_cpu_info { 30 + u32 nr_cpu; 31 + }; 32 + 33 + #define SCMI_IMX_CPU_NR_CPU_MASK GENMASK(15, 0) 34 + struct scmi_msg_imx_cpu_protocol_attributes { 35 + __le32 attributes; 36 + }; 37 + 38 + struct scmi_msg_imx_cpu_attributes_out { 39 + __le32 attributes; 40 + #define CPU_MAX_NAME 16 41 + u8 name[CPU_MAX_NAME]; 42 + }; 43 + 44 + struct scmi_imx_cpu_reset_vector_set_in { 45 + __le32 cpuid; 46 + #define CPU_VEC_FLAGS_RESUME BIT(31) 47 + #define CPU_VEC_FLAGS_START BIT(30) 48 + #define CPU_VEC_FLAGS_BOOT BIT(29) 49 + __le32 flags; 50 + __le32 resetvectorlow; 51 + __le32 resetvectorhigh; 52 + }; 53 + 54 + struct scmi_imx_cpu_info_get_out { 55 + #define CPU_RUN_MODE_START 0 56 + #define CPU_RUN_MODE_HOLD 1 57 + #define CPU_RUN_MODE_STOP 2 58 + #define CPU_RUN_MODE_SLEEP 3 59 + __le32 runmode; 60 + __le32 sleepmode; 61 + __le32 resetvectorlow; 62 + __le32 resetvectorhigh; 63 + }; 64 + 65 + static int scmi_imx_cpu_validate_cpuid(const struct scmi_protocol_handle *ph, 66 + u32 cpuid) 67 + { 68 + struct scmi_imx_cpu_info *info = ph->get_priv(ph); 69 + 70 + if (cpuid >= info->nr_cpu) 71 + return -EINVAL; 72 + 73 + return 0; 74 + } 75 + 76 + static int scmi_imx_cpu_start(const struct scmi_protocol_handle *ph, 77 + u32 cpuid, bool start) 78 + { 79 + struct scmi_xfer *t; 80 + u8 msg_id; 81 + int ret; 82 + 83 + ret = scmi_imx_cpu_validate_cpuid(ph, cpuid); 84 + if (ret) 85 + return ret; 86 + 87 + if (start) 88 + msg_id = SCMI_IMX_CPU_START; 89 + else 90 + msg_id = SCMI_IMX_CPU_STOP; 91 + 92 + ret = ph->xops->xfer_get_init(ph, msg_id, sizeof(u32), 0, &t); 93 + if (ret) 94 + return ret; 95 + 96 + put_unaligned_le32(cpuid, t->tx.buf); 97 + ret = ph->xops->do_xfer(ph, t); 98 + 99 + ph->xops->xfer_put(ph, t); 100 + 101 + return ret; 102 + } 103 + 104 + static int scmi_imx_cpu_reset_vector_set(const struct scmi_protocol_handle *ph, 105 + u32 cpuid, u64 vector, bool start, 106 + bool boot, bool resume) 107 + { 108 + struct scmi_imx_cpu_reset_vector_set_in *in; 109 + struct scmi_xfer *t; 110 + int ret; 111 + 112 + ret = scmi_imx_cpu_validate_cpuid(ph, cpuid); 113 + if (ret) 114 + return ret; 115 + 116 + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_CPU_RESET_VECTOR_SET, sizeof(*in), 117 + 0, &t); 118 + if (ret) 119 + return ret; 120 + 121 + in = t->tx.buf; 122 + in->cpuid = cpu_to_le32(cpuid); 123 + in->flags = cpu_to_le32(0); 124 + if (start) 125 + in->flags |= le32_encode_bits(1, CPU_VEC_FLAGS_START); 126 + if (boot) 127 + in->flags |= le32_encode_bits(1, CPU_VEC_FLAGS_BOOT); 128 + if (resume) 129 + in->flags |= le32_encode_bits(1, CPU_VEC_FLAGS_RESUME); 130 + in->resetvectorlow = cpu_to_le32(lower_32_bits(vector)); 131 + in->resetvectorhigh = cpu_to_le32(upper_32_bits(vector)); 132 + ret = ph->xops->do_xfer(ph, t); 133 + 134 + ph->xops->xfer_put(ph, t); 135 + 136 + return ret; 137 + } 138 + 139 + static int scmi_imx_cpu_started(const struct scmi_protocol_handle *ph, u32 cpuid, 140 + bool *started) 141 + { 142 + struct scmi_imx_cpu_info_get_out *out; 143 + struct scmi_xfer *t; 144 + u32 mode; 145 + int ret; 146 + 147 + if (!started) 148 + return -EINVAL; 149 + 150 + *started = false; 151 + ret = scmi_imx_cpu_validate_cpuid(ph, cpuid); 152 + if (ret) 153 + return ret; 154 + 155 + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_CPU_INFO_GET, sizeof(u32), 156 + 0, &t); 157 + if (ret) 158 + return ret; 159 + 160 + put_unaligned_le32(cpuid, t->tx.buf); 161 + ret = ph->xops->do_xfer(ph, t); 162 + if (!ret) { 163 + out = t->rx.buf; 164 + mode = le32_to_cpu(out->runmode); 165 + if (mode == CPU_RUN_MODE_START || mode == CPU_RUN_MODE_SLEEP) 166 + *started = true; 167 + } 168 + 169 + ph->xops->xfer_put(ph, t); 170 + 171 + return ret; 172 + } 173 + 174 + static const struct scmi_imx_cpu_proto_ops scmi_imx_cpu_proto_ops = { 175 + .cpu_reset_vector_set = scmi_imx_cpu_reset_vector_set, 176 + .cpu_start = scmi_imx_cpu_start, 177 + .cpu_started = scmi_imx_cpu_started, 178 + }; 179 + 180 + static int scmi_imx_cpu_protocol_attributes_get(const struct scmi_protocol_handle *ph, 181 + struct scmi_imx_cpu_info *info) 182 + { 183 + struct scmi_msg_imx_cpu_protocol_attributes *attr; 184 + struct scmi_xfer *t; 185 + int ret; 186 + 187 + ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, 188 + sizeof(*attr), &t); 189 + if (ret) 190 + return ret; 191 + 192 + attr = t->rx.buf; 193 + 194 + ret = ph->xops->do_xfer(ph, t); 195 + if (!ret) { 196 + info->nr_cpu = le32_get_bits(attr->attributes, SCMI_IMX_CPU_NR_CPU_MASK); 197 + dev_info(ph->dev, "i.MX SM CPU: %d cpus\n", 198 + info->nr_cpu); 199 + } 200 + 201 + ph->xops->xfer_put(ph, t); 202 + 203 + return ret; 204 + } 205 + 206 + static int scmi_imx_cpu_attributes_get(const struct scmi_protocol_handle *ph, 207 + u32 cpuid) 208 + { 209 + struct scmi_msg_imx_cpu_attributes_out *out; 210 + char name[SCMI_SHORT_NAME_MAX_SIZE] = {'\0'}; 211 + struct scmi_xfer *t; 212 + int ret; 213 + 214 + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_CPU_ATTRIBUTES, sizeof(u32), 0, &t); 215 + if (ret) 216 + return ret; 217 + 218 + put_unaligned_le32(cpuid, t->tx.buf); 219 + ret = ph->xops->do_xfer(ph, t); 220 + if (!ret) { 221 + out = t->rx.buf; 222 + strscpy(name, out->name, SCMI_SHORT_NAME_MAX_SIZE); 223 + dev_info(ph->dev, "i.MX CPU: name: %s\n", name); 224 + } else { 225 + dev_err(ph->dev, "i.MX cpu: Failed to get info of cpu(%u)\n", cpuid); 226 + } 227 + 228 + ph->xops->xfer_put(ph, t); 229 + 230 + return ret; 231 + } 232 + 233 + static int scmi_imx_cpu_protocol_init(const struct scmi_protocol_handle *ph) 234 + { 235 + struct scmi_imx_cpu_info *info; 236 + u32 version; 237 + int ret, i; 238 + 239 + ret = ph->xops->version_get(ph, &version); 240 + if (ret) 241 + return ret; 242 + 243 + dev_info(ph->dev, "NXP SM CPU Protocol Version %d.%d\n", 244 + PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); 245 + 246 + info = devm_kzalloc(ph->dev, sizeof(*info), GFP_KERNEL); 247 + if (!info) 248 + return -ENOMEM; 249 + 250 + ret = scmi_imx_cpu_protocol_attributes_get(ph, info); 251 + if (ret) 252 + return ret; 253 + 254 + for (i = 0; i < info->nr_cpu; i++) { 255 + ret = scmi_imx_cpu_attributes_get(ph, i); 256 + if (ret) 257 + return ret; 258 + } 259 + 260 + return ph->set_priv(ph, info, version); 261 + } 262 + 263 + static const struct scmi_protocol scmi_imx_cpu = { 264 + .id = SCMI_PROTOCOL_IMX_CPU, 265 + .owner = THIS_MODULE, 266 + .instance_init = &scmi_imx_cpu_protocol_init, 267 + .ops = &scmi_imx_cpu_proto_ops, 268 + .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, 269 + .vendor_id = SCMI_IMX_VENDOR, 270 + .sub_vendor_id = SCMI_IMX_SUBVENDOR, 271 + }; 272 + module_scmi_protocol(scmi_imx_cpu); 273 + 274 + MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_CPU) "-" SCMI_IMX_VENDOR); 275 + MODULE_DESCRIPTION("i.MX SCMI CPU driver"); 276 + MODULE_LICENSE("GPL");
+263
drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * System control and Management Interface (SCMI) NXP LMM Protocol 4 + * 5 + * Copyright 2025 NXP 6 + */ 7 + 8 + #include <linux/bits.h> 9 + #include <linux/io.h> 10 + #include <linux/module.h> 11 + #include <linux/of.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/scmi_protocol.h> 14 + #include <linux/scmi_imx_protocol.h> 15 + 16 + #include "../../protocols.h" 17 + #include "../../notify.h" 18 + 19 + #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x10000 20 + 21 + enum scmi_imx_lmm_protocol_cmd { 22 + SCMI_IMX_LMM_ATTRIBUTES = 0x3, 23 + SCMI_IMX_LMM_BOOT = 0x4, 24 + SCMI_IMX_LMM_RESET = 0x5, 25 + SCMI_IMX_LMM_SHUTDOWN = 0x6, 26 + SCMI_IMX_LMM_WAKE = 0x7, 27 + SCMI_IMX_LMM_SUSPEND = 0x8, 28 + SCMI_IMX_LMM_NOTIFY = 0x9, 29 + SCMI_IMX_LMM_RESET_REASON = 0xA, 30 + SCMI_IMX_LMM_POWER_ON = 0xB, 31 + SCMI_IMX_LMM_RESET_VECTOR_SET = 0xC, 32 + }; 33 + 34 + struct scmi_imx_lmm_priv { 35 + u32 nr_lmm; 36 + }; 37 + 38 + #define SCMI_IMX_LMM_NR_LM_MASK GENMASK(5, 0) 39 + #define SCMI_IMX_LMM_NR_MAX 16 40 + struct scmi_msg_imx_lmm_protocol_attributes { 41 + __le32 attributes; 42 + }; 43 + 44 + struct scmi_msg_imx_lmm_attributes_out { 45 + __le32 lmid; 46 + __le32 attributes; 47 + __le32 state; 48 + __le32 errstatus; 49 + u8 name[LMM_MAX_NAME]; 50 + }; 51 + 52 + struct scmi_imx_lmm_reset_vector_set_in { 53 + __le32 lmid; 54 + __le32 cpuid; 55 + __le32 flags; /* reserved for future extension */ 56 + __le32 resetvectorlow; 57 + __le32 resetvectorhigh; 58 + }; 59 + 60 + struct scmi_imx_lmm_shutdown_in { 61 + __le32 lmid; 62 + #define SCMI_IMX_LMM_SHUTDOWN_GRACEFUL BIT(0) 63 + __le32 flags; 64 + }; 65 + 66 + static int scmi_imx_lmm_validate_lmid(const struct scmi_protocol_handle *ph, u32 lmid) 67 + { 68 + struct scmi_imx_lmm_priv *priv = ph->get_priv(ph); 69 + 70 + if (lmid >= priv->nr_lmm) 71 + return -EINVAL; 72 + 73 + return 0; 74 + } 75 + 76 + static int scmi_imx_lmm_attributes(const struct scmi_protocol_handle *ph, 77 + u32 lmid, struct scmi_imx_lmm_info *info) 78 + { 79 + struct scmi_msg_imx_lmm_attributes_out *out; 80 + struct scmi_xfer *t; 81 + int ret; 82 + 83 + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_ATTRIBUTES, sizeof(u32), 0, &t); 84 + if (ret) 85 + return ret; 86 + 87 + put_unaligned_le32(lmid, t->tx.buf); 88 + ret = ph->xops->do_xfer(ph, t); 89 + if (!ret) { 90 + out = t->rx.buf; 91 + info->lmid = le32_to_cpu(out->lmid); 92 + info->state = le32_to_cpu(out->state); 93 + info->errstatus = le32_to_cpu(out->errstatus); 94 + strscpy(info->name, out->name); 95 + dev_dbg(ph->dev, "i.MX LMM: Logical Machine(%d), name: %s\n", 96 + info->lmid, info->name); 97 + } else { 98 + dev_err(ph->dev, "i.MX LMM: Failed to get info of Logical Machine(%u)\n", lmid); 99 + } 100 + 101 + ph->xops->xfer_put(ph, t); 102 + 103 + return ret; 104 + } 105 + 106 + static int 107 + scmi_imx_lmm_power_boot(const struct scmi_protocol_handle *ph, u32 lmid, bool boot) 108 + { 109 + struct scmi_xfer *t; 110 + u8 msg_id; 111 + int ret; 112 + 113 + ret = scmi_imx_lmm_validate_lmid(ph, lmid); 114 + if (ret) 115 + return ret; 116 + 117 + if (boot) 118 + msg_id = SCMI_IMX_LMM_BOOT; 119 + else 120 + msg_id = SCMI_IMX_LMM_POWER_ON; 121 + 122 + ret = ph->xops->xfer_get_init(ph, msg_id, sizeof(u32), 0, &t); 123 + if (ret) 124 + return ret; 125 + 126 + put_unaligned_le32(lmid, t->tx.buf); 127 + ret = ph->xops->do_xfer(ph, t); 128 + 129 + ph->xops->xfer_put(ph, t); 130 + 131 + return ret; 132 + } 133 + 134 + static int scmi_imx_lmm_reset_vector_set(const struct scmi_protocol_handle *ph, 135 + u32 lmid, u32 cpuid, u32 flags, u64 vector) 136 + { 137 + struct scmi_imx_lmm_reset_vector_set_in *in; 138 + struct scmi_xfer *t; 139 + int ret; 140 + 141 + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_RESET_VECTOR_SET, sizeof(*in), 142 + 0, &t); 143 + if (ret) 144 + return ret; 145 + 146 + in = t->tx.buf; 147 + in->lmid = cpu_to_le32(lmid); 148 + in->cpuid = cpu_to_le32(cpuid); 149 + in->flags = cpu_to_le32(0); 150 + in->resetvectorlow = cpu_to_le32(lower_32_bits(vector)); 151 + in->resetvectorhigh = cpu_to_le32(upper_32_bits(vector)); 152 + ret = ph->xops->do_xfer(ph, t); 153 + 154 + ph->xops->xfer_put(ph, t); 155 + 156 + return ret; 157 + } 158 + 159 + static int scmi_imx_lmm_shutdown(const struct scmi_protocol_handle *ph, u32 lmid, 160 + u32 flags) 161 + { 162 + struct scmi_imx_lmm_shutdown_in *in; 163 + struct scmi_xfer *t; 164 + int ret; 165 + 166 + ret = scmi_imx_lmm_validate_lmid(ph, lmid); 167 + if (ret) 168 + return ret; 169 + 170 + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_SHUTDOWN, sizeof(*in), 171 + 0, &t); 172 + if (ret) 173 + return ret; 174 + 175 + in = t->tx.buf; 176 + in->lmid = cpu_to_le32(lmid); 177 + if (flags & SCMI_IMX_LMM_SHUTDOWN_GRACEFUL) 178 + in->flags = cpu_to_le32(SCMI_IMX_LMM_SHUTDOWN_GRACEFUL); 179 + else 180 + in->flags = cpu_to_le32(0); 181 + ret = ph->xops->do_xfer(ph, t); 182 + 183 + ph->xops->xfer_put(ph, t); 184 + 185 + return ret; 186 + } 187 + 188 + static const struct scmi_imx_lmm_proto_ops scmi_imx_lmm_proto_ops = { 189 + .lmm_power_boot = scmi_imx_lmm_power_boot, 190 + .lmm_info = scmi_imx_lmm_attributes, 191 + .lmm_reset_vector_set = scmi_imx_lmm_reset_vector_set, 192 + .lmm_shutdown = scmi_imx_lmm_shutdown, 193 + }; 194 + 195 + static int scmi_imx_lmm_protocol_attributes_get(const struct scmi_protocol_handle *ph, 196 + struct scmi_imx_lmm_priv *priv) 197 + { 198 + struct scmi_msg_imx_lmm_protocol_attributes *attr; 199 + struct scmi_xfer *t; 200 + int ret; 201 + 202 + ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, 203 + sizeof(*attr), &t); 204 + if (ret) 205 + return ret; 206 + 207 + attr = t->rx.buf; 208 + 209 + ret = ph->xops->do_xfer(ph, t); 210 + if (!ret) { 211 + priv->nr_lmm = le32_get_bits(attr->attributes, SCMI_IMX_LMM_NR_LM_MASK); 212 + if (priv->nr_lmm > SCMI_IMX_LMM_NR_MAX) { 213 + dev_err(ph->dev, "i.MX LMM: %d:Exceed max supported Logical Machines\n", 214 + priv->nr_lmm); 215 + ret = -EINVAL; 216 + } else { 217 + dev_info(ph->dev, "i.MX LMM: %d Logical Machines\n", priv->nr_lmm); 218 + } 219 + } 220 + 221 + ph->xops->xfer_put(ph, t); 222 + 223 + return ret; 224 + } 225 + 226 + static int scmi_imx_lmm_protocol_init(const struct scmi_protocol_handle *ph) 227 + { 228 + struct scmi_imx_lmm_priv *info; 229 + u32 version; 230 + int ret; 231 + 232 + ret = ph->xops->version_get(ph, &version); 233 + if (ret) 234 + return ret; 235 + 236 + dev_info(ph->dev, "NXP SM LMM Version %d.%d\n", 237 + PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); 238 + 239 + info = devm_kzalloc(ph->dev, sizeof(*info), GFP_KERNEL); 240 + if (!info) 241 + return -ENOMEM; 242 + 243 + ret = scmi_imx_lmm_protocol_attributes_get(ph, info); 244 + if (ret) 245 + return ret; 246 + 247 + return ph->set_priv(ph, info, version); 248 + } 249 + 250 + static const struct scmi_protocol scmi_imx_lmm = { 251 + .id = SCMI_PROTOCOL_IMX_LMM, 252 + .owner = THIS_MODULE, 253 + .instance_init = &scmi_imx_lmm_protocol_init, 254 + .ops = &scmi_imx_lmm_proto_ops, 255 + .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, 256 + .vendor_id = SCMI_IMX_VENDOR, 257 + .sub_vendor_id = SCMI_IMX_SUBVENDOR, 258 + }; 259 + module_scmi_protocol(scmi_imx_lmm); 260 + 261 + MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_LMM) "-" SCMI_IMX_VENDOR); 262 + MODULE_DESCRIPTION("i.MX SCMI LMM driver"); 263 + MODULE_LICENSE("GPL");
+828
drivers/firmware/arm_scmi/vendors/imx/imx95.rst
··· 32 32 The SM implements an interface compliant with the Arm SCMI Specification 33 33 with additional vendor specific extensions. 34 34 35 + System Control and Management Logical Machine Management Vendor Protocol 36 + ======================================================================== 37 + 38 + The SM adds the concept of logical machines (LMs). These are analogous to 39 + VMs and each has its own instance of SCMI. All normal SCMI calls only apply 40 + the LM running the calling agent. That includes boot, shutdown, reset, 41 + suspend, wake, etc. If a caller makes the SCMI base call to get a list 42 + of agents, it will only get those on that LM. Each LM is completely isolated 43 + from the others. This is mandatory for these to operate independently. 44 + 45 + This protocol is intended to support boot, shutdown, and reset of other logical 46 + machines (LM). It is usually used to allow one LM(e.g. OSPM) to manage 47 + another LM which is usually an offload or accelerator engine. Notifications 48 + from this protocol can also be used to manage a communication link to another 49 + LM. The LMM protocol provides commands to: 50 + 51 + - Describe the protocol version. 52 + - Discover implementation attributes. 53 + - Discover all the LMs defined in the system. 54 + - Boot a target LM. 55 + - Shutdown a target LM (gracefully or forcibly). 56 + - Reset a target LM (gracefully or forcibly). 57 + - Wake a target LM from suspend. 58 + - Suspend a target LM (gracefully). 59 + - Read boot/shutdown/reset information for a target LM. 60 + - Get notifications when a target LM boots or shuts down (e.g. LM 'X' requested 61 + notification of LM 'Y' boots or shuts down, when LM 'Y' boots or shuts down, 62 + SCMI firmware will send notification to LM 'X'). 63 + 64 + 'Graceful' means asking LM itself to shutdown/reset/etc (e.g. sending 65 + notification to Linux, Then Linux reboots or powers down itself). It is async 66 + command that the SUCCESS of the command just means the command successfully 67 + return, not means reboot/reset successfully finished. 68 + 69 + 'Forceful' means the SM will force shutdown/reset/etc the LM. It is sync 70 + command that the SUCCESS of the command means the LM has been successfully 71 + shutdown/reset/etc. 72 + If the commands not have Graceful/Forceful flag settings, such as WAKE, SUSEND, 73 + it is a Graceful command. 74 + 75 + Commands: 76 + _________ 77 + 78 + PROTOCOL_VERSION 79 + ~~~~~~~~~~~~~~~~ 80 + 81 + message_id: 0x0 82 + protocol_id: 0x80 83 + This command is mandatory. 84 + 85 + +---------------+--------------------------------------------------------------+ 86 + |Return values | 87 + +---------------+--------------------------------------------------------------+ 88 + |Name |Description | 89 + +---------------+--------------------------------------------------------------+ 90 + |int32 status | See ARM SCMI Specification for status code definitions. | 91 + +---------------+--------------------------------------------------------------+ 92 + |uint32 version | For this revision of the specification, this value must be | 93 + | | 0x10000. | 94 + +---------------+--------------------------------------------------------------+ 95 + 96 + PROTOCOL_ATTRIBUTES 97 + ~~~~~~~~~~~~~~~~~~~ 98 + 99 + message_id: 0x1 100 + protocol_id: 0x80 101 + This command is mandatory. 102 + 103 + +------------------+-----------------------------------------------------------+ 104 + |Return values | 105 + +------------------+-----------------------------------------------------------+ 106 + |Name |Description | 107 + +------------------+-----------------------------------------------------------+ 108 + |int32 status | See ARM SCMI Specification for status code definitions. | 109 + +------------------+-----------------------------------------------------------+ 110 + |uint32 attributes |Protocol attributes: | 111 + | |Bits[31:5] Reserved, must be zero. | 112 + | |Bits[4:0] Number of Logical Machines | 113 + | |Note that due to both hardware limitations and reset reason| 114 + | |field limitations, the max number of LM is 16. The minimum | 115 + | |is 1. | 116 + +------------------+-----------------------------------------------------------+ 117 + 118 + PROTOCOL_MESSAGE_ATTRIBUTES 119 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 120 + 121 + message_id: 0x2 122 + protocol_id: 0x80 123 + This command is mandatory. 124 + 125 + +------------------+-----------------------------------------------------------+ 126 + |Return values | 127 + +------------------+-----------------------------------------------------------+ 128 + |Name |Description | 129 + +------------------+-----------------------------------------------------------+ 130 + |int32 status |SUCCESS: in case the message is implemented and available | 131 + | |to use. | 132 + | |NOT_FOUND: if the message identified by message_id is | 133 + | |invalid or not implemented | 134 + +------------------+-----------------------------------------------------------+ 135 + |uint32 attributes |Flags that are associated with a specific command in the | 136 + | |protocol. For all commands in this protocol, this | 137 + | |parameter has a value of 0 | 138 + +------------------+-----------------------------------------------------------+ 139 + 140 + LMM_ATTRIBUTES 141 + ~~~~~~~~~~~~~~ 142 + 143 + message_id: 0x3 144 + protocol_id: 0x80 145 + This command is mandatory. 146 + 147 + +------------------+-----------------------------------------------------------+ 148 + |Parameters | 149 + +------------------+-----------------------------------------------------------+ 150 + |Name |Description | 151 + +------------------+-----------------------------------------------------------+ 152 + |uint32 lmid |ID of the Logical Machine | 153 + +------------------+-----------------------------------------------------------+ 154 + |Return values | 155 + +------------------+-----------------------------------------------------------+ 156 + |Name |Description | 157 + +------------------+-----------------------------------------------------------+ 158 + |int32 status |SUCCESS: if valid attributes are returned. | 159 + | |NOT_FOUND: if lmid not points to a valid logical machine. | 160 + | |DENIED: if the agent does not have permission to get info | 161 + | |for the LM specified by lmid. | 162 + +------------------+-----------------------------------------------------------+ 163 + |uint32 lmid |Identifier of the LM whose identification is requested. | 164 + | |This field is: Populated with the lmid of the calling | 165 + | |agent, when the lmid parameter passed via the command is | 166 + | |0xFFFFFFFF. Identical to the lmid field passed via the | 167 + | |calling parameters, in all other cases | 168 + +------------------+-----------------------------------------------------------+ 169 + |uint32 attributes | Bits[31:0] reserved. must be zero | 170 + +------------------+-----------------------------------------------------------+ 171 + |uint32 state | Current state of the LM | 172 + +------------------+-----------------------------------------------------------+ 173 + |uint32 errStatus | Last error status recorded | 174 + +------------------+-----------------------------------------------------------+ 175 + |char name[16] | A NULL terminated ASCII string with the LM name, of up | 176 + | | to 16 bytes | 177 + +------------------+-----------------------------------------------------------+ 178 + 179 + LMM_BOOT 180 + ~~~~~~~~ 181 + 182 + message_id: 0x4 183 + protocol_id: 0x80 184 + This command is mandatory. 185 + 186 + +------------------+-----------------------------------------------------------+ 187 + |Parameters | 188 + +------------------+-----------------------------------------------------------+ 189 + |Name |Description | 190 + +------------------+-----------------------------------------------------------+ 191 + |uint32 lmid |ID of the Logical Machine | 192 + +------------------+-----------------------------------------------------------+ 193 + |Return values | 194 + +------------------+-----------------------------------------------------------+ 195 + |Name |Description | 196 + +------------------+-----------------------------------------------------------+ 197 + |int32 status |SUCCESS: if LM boots successfully started. | 198 + | |NOT_FOUND: if lmid not points to a valid logical machine. | 199 + | |INVALID_PARAMETERS: if lmid is same as the caller. | 200 + | |DENIED: if the agent does not have permission to manage the| 201 + | |the LM specified by lmid. | 202 + +------------------+-----------------------------------------------------------+ 203 + 204 + LMM_RESET 205 + ~~~~~~~~~ 206 + 207 + message_id: 0x5 208 + protocol_id: 0x80 209 + This command is mandatory. 210 + 211 + +------------------+-----------------------------------------------------------+ 212 + |Parameters | 213 + +------------------+-----------------------------------------------------------+ 214 + |Name |Description | 215 + +------------------+-----------------------------------------------------------+ 216 + |uint32 lmid |ID of the Logical Machine | 217 + +------------------+-----------------------------------------------------------+ 218 + |uint32 flags |Reset flags: | 219 + | |Bits[31:1] Reserved, must be zero. | 220 + | |Bit[0] Graceful request: | 221 + | |Set to 1 if the request is a graceful request. | 222 + | |Set to 0 if the request is a forceful request. | 223 + +------------------+-----------------------------------------------------------+ 224 + |Return values | 225 + +------------------+-----------------------------------------------------------+ 226 + |Name |Description | 227 + +------------------+-----------------------------------------------------------+ 228 + |int32 status |SUCCESS: The LMM RESET command finished successfully in | 229 + | |graceful reset or LM successfully resets in forceful reset.| 230 + | |NOT_FOUND: if lmid not points to a valid logical machine. | 231 + | |INVALID_PARAMETERS: if lmid is same as the caller. | 232 + | |DENIED: if the agent does not have permission to manage the| 233 + | |the LM specified by lmid. | 234 + +------------------+-----------------------------------------------------------+ 235 + 236 + LMM_SHUTDOWN 237 + ~~~~~~~~~~~~ 238 + 239 + message_id: 0x6 240 + protocol_id: 0x80 241 + This command is mandatory. 242 + 243 + +------------------+-----------------------------------------------------------+ 244 + |Parameters | 245 + +------------------+-----------------------------------------------------------+ 246 + |Name |Description | 247 + +------------------+-----------------------------------------------------------+ 248 + |uint32 lmid |ID of the Logical Machine | 249 + +------------------+-----------------------------------------------------------+ 250 + |uint32 flags |Reset flags: | 251 + | |Bits[31:1] Reserved, must be zero. | 252 + | |Bit[0] Graceful request: | 253 + | |Set to 1 if the request is a graceful request. | 254 + | |Set to 0 if the request is a forceful request. | 255 + +------------------+-----------------------------------------------------------+ 256 + |Return values | 257 + +------------------+-----------------------------------------------------------+ 258 + |Name |Description | 259 + +------------------+-----------------------------------------------------------+ 260 + |int32 status |SUCCESS: The LMM shutdown command finished successfully in | 261 + | |graceful request or LM successfully shutdown in forceful | 262 + | |request. | 263 + | |NOT_FOUND: if lmid not points to a valid logical machine. | 264 + | |INVALID_PARAMETERS: if lmid is same as the caller. | 265 + | |DENIED: if the agent does not have permission to manage the| 266 + | |the LM specified by lmid. | 267 + +------------------+-----------------------------------------------------------+ 268 + 269 + LMM_WAKE 270 + ~~~~~~~~ 271 + 272 + message_id: 0x7 273 + protocol_id: 0x80 274 + This command is mandatory. 275 + 276 + +------------------+-----------------------------------------------------------+ 277 + |Parameters | 278 + +------------------+-----------------------------------------------------------+ 279 + |Name |Description | 280 + +------------------+-----------------------------------------------------------+ 281 + |uint32 lmid |ID of the Logical Machine | 282 + +------------------+-----------------------------------------------------------+ 283 + |Return values | 284 + +------------------+-----------------------------------------------------------+ 285 + |Name |Description | 286 + +------------------+-----------------------------------------------------------+ 287 + |int32 status |SUCCESS: if LM wake command successfully returns. | 288 + | |NOT_FOUND: if lmid not points to a valid logical machine. | 289 + | |INVALID_PARAMETERS: if lmid is same as the caller. | 290 + | |DENIED: if the agent does not have permission to manage the| 291 + | |the LM specified by lmid. | 292 + +------------------+-----------------------------------------------------------+ 293 + 294 + LMM_SUSPEND 295 + ~~~~~~~~~~~ 296 + 297 + message_id: 0x8 298 + protocol_id: 0x80 299 + This command is mandatory. 300 + 301 + +------------------+-----------------------------------------------------------+ 302 + |Parameters | 303 + +------------------+-----------------------------------------------------------+ 304 + |Name |Description | 305 + +------------------+-----------------------------------------------------------+ 306 + |uint32 lmid |ID of the Logical Machine | 307 + +------------------+-----------------------------------------------------------+ 308 + |Return values | 309 + +------------------+-----------------------------------------------------------+ 310 + |Name |Description | 311 + +------------------+-----------------------------------------------------------+ 312 + |int32 status |SUCCESS: if LM suspend command successfully returns. | 313 + | |NOT_FOUND: if lmid not points to a valid logical machine. | 314 + | |INVALID_PARAMETERS: if lmid is same as the caller. | 315 + | |DENIED: if the agent does not have permission to manage the| 316 + | |the LM specified by lmid. | 317 + +------------------+-----------------------------------------------------------+ 318 + 319 + LMM_NOTIFY 320 + ~~~~~~~~~~ 321 + 322 + message_id: 0x9 323 + protocol_id: 0x80 324 + This command is mandatory. 325 + 326 + +------------------+-----------------------------------------------------------+ 327 + |Parameters | 328 + +------------------+-----------------------------------------------------------+ 329 + |Name |Description | 330 + +------------------+-----------------------------------------------------------+ 331 + |uint32 lmid |ID of the Logical Machine | 332 + +------------------+-----------------------------------------------------------+ 333 + |uint32 flags |Notification flags: | 334 + | |Bits[31:3] Reserved, must be zero. | 335 + | |Bit[3] Wake (resume) notification: | 336 + | |Set to 1 to send notification. | 337 + | |Set to 0 if no notification. | 338 + | |Bit[2] Suspend (sleep) notification: | 339 + | |Set to 1 to send notification. | 340 + | |Set to 0 if no notification. | 341 + | |Bit[1] Shutdown (off) notification: | 342 + | |Set to 1 to send notification. | 343 + | |Set to 0 if no notification. | 344 + | |Bit[0] Boot (on) notification: | 345 + | |Set to 1 to send notification. | 346 + | |Set to 0 if no notification | 347 + +------------------+-----------------------------------------------------------+ 348 + |Return values | 349 + +------------------+-----------------------------------------------------------+ 350 + |Name |Description | 351 + +------------------+-----------------------------------------------------------+ 352 + |int32 status |SUCCESS: if the notification state successfully updated. | 353 + | |NOT_FOUND: if lmid not points to a valid logical machine. | 354 + | |INVALID_PARAMETERS: if input attributes flag specifies | 355 + | |unsupported or invalid configurations. | 356 + | |DENIED: if the agent does not have permission to request | 357 + | |the notification. | 358 + +------------------+-----------------------------------------------------------+ 359 + 360 + LMM_RESET_REASON 361 + ~~~~~~~~~~~~~~~~ 362 + 363 + message_id: 0xA 364 + protocol_id: 0x80 365 + This command is mandatory. 366 + 367 + This command is to return the reset reason that caused the last reset, such as 368 + POR, WDOG, JTAG and etc. 369 + 370 + +---------------------+--------------------------------------------------------+ 371 + |Parameters | 372 + +---------------------+--------------------------------------------------------+ 373 + |Name |Description | 374 + +---------------------+--------------------------------------------------------+ 375 + |uint32 lmid |ID of the Logical Machine | 376 + +---------------------+--------------------------------------------------------+ 377 + |Return values | 378 + +---------------------+--------------------------------------------------------+ 379 + |Name |Description | 380 + +---------------------+--------------------------------------------------------+ 381 + |int32 status |SUCCESS: if the reset reason of the LM successfully | 382 + | |updated. | 383 + | |NOT_FOUND: if lmid not points to a valid logical machine| 384 + | |DENIED: if the agent does not have permission to request| 385 + | |the reset reason. | 386 + +---------------------+--------------------------------------------------------+ 387 + |uint32 bootflags |Boot reason flags. This parameter has the format: | 388 + | |Bits[31] Valid. | 389 + | |Set to 1 if the entire reason is valid. | 390 + | |Set to 0 if the entire reason is not valid. | 391 + | |Bits[30:29] Reserved, must be zero. | 392 + | |Bit[28] Valid origin: | 393 + | |Set to 1 if the origin field is valid. | 394 + | |Set to 0 if the origin field is not valid. | 395 + | |Bits[27:24] Origin. | 396 + | |Logical Machine(LM) ID that causes the BOOT of this LM | 397 + | |Bit[23] Valid err ID: | 398 + | |Set to 1 if the error ID field is valid. | 399 + | |Set to 0 if the error ID field is not valid. | 400 + | |Bits[22:8] Error ID(Agent ID of the system). | 401 + | |Bit[7:0] Reason(WDOG, POR, FCCU and etc): | 402 + | |See the SRESR register description in the System | 403 + | |Reset Controller (SRC) section in SoC reference mannual | 404 + | |One reason maps to BIT(reason) in SRESR | 405 + +---------------------+--------------------------------------------------------+ 406 + |uint32 shutdownflags |Shutdown reason flags. This parameter has the format: | 407 + | |Bits[31] Valid. | 408 + | |Set to 1 if the entire reason is valid. | 409 + | |Set to 0 if the entire reason is not valid. | 410 + | |Bits[30:29] Number of valid extended info words. | 411 + | |Bit[28] Valid origin: | 412 + | |Set to 1 if the origin field is valid. | 413 + | |Set to 0 if the origin field is not valid. | 414 + | |Bits[27:24] Origin. | 415 + | |Logical Machine(LM) ID that causes the BOOT of this LM | 416 + | |Bit[23] Valid err ID: | 417 + | |Set to 1 if the error ID field is valid. | 418 + | |Set to 0 if the error ID field is not valid. | 419 + | |Bits[22:8] Error ID(Agent ID of the System). | 420 + | |Bit[7:0] Reason | 421 + | |See the SRESR register description in the System | 422 + | |Reset Controller (SRC) section in SoC reference mannual | 423 + | |One reason maps to BIT(reason) in SRESR | 424 + +---------------------+--------------------------------------------------------+ 425 + |uint32 extinfo[3] |Array of extended info words(e.g. fault pc) | 426 + +---------------------+--------------------------------------------------------+ 427 + 428 + LMM_POWER_ON 429 + ~~~~~~~~~~~~ 430 + 431 + message_id: 0xB 432 + protocol_id: 0x80 433 + This command is mandatory. 434 + 435 + +------------------+-----------------------------------------------------------+ 436 + |Parameters | 437 + +------------------+-----------------------------------------------------------+ 438 + |Name |Description | 439 + +------------------+-----------------------------------------------------------+ 440 + |uint32 lmid |ID of the Logical Machine | 441 + +------------------+-----------------------------------------------------------+ 442 + |Return values | 443 + +------------------+-----------------------------------------------------------+ 444 + |Name |Description | 445 + +------------------+-----------------------------------------------------------+ 446 + |int32 status |SUCCESS: if LM successfully powers on. | 447 + | |NOT_FOUND: if lmid not points to a valid logical machine. | 448 + | |INVALID_PARAMETERS: if lmid is same as the caller. | 449 + | |DENIED: if the agent does not have permission to manage the| 450 + | |the LM specified by lmid. | 451 + +------------------+-----------------------------------------------------------+ 452 + 453 + LMM_RESET_VECTOR_SET 454 + ~~~~~~~~~~~~~~~~~~~~ 455 + 456 + message_id: 0xC 457 + protocol_id: 0x80 458 + This command is mandatory. 459 + 460 + +-----------------------+------------------------------------------------------+ 461 + |Parameters | 462 + +-----------------------+------------------------------------------------------+ 463 + |Name |Description | 464 + +-----------------------+------------------------------------------------------+ 465 + |uint32 lmid |ID of the Logical Machine | 466 + +-----------------------+------------------------------------------------------+ 467 + |uint32 cpuid |ID of the CPU inside the LM | 468 + +-----------------------+------------------------------------------------------+ 469 + |uint32 flags |Reset vector flags | 470 + | |Bits[31:0] Reserved, must be zero. | 471 + +-----------------------+------------------------------------------------------+ 472 + |uint32 resetVectorLow |Lower vector | 473 + +-----------------------+------------------------------------------------------+ 474 + |uint32 resetVectorHigh |Higher vector | 475 + +-----------------------+------------------------------------------------------+ 476 + |Return values | 477 + +-----------------------+------------------------------------------------------+ 478 + |Name |Description | 479 + +-----------------------+------------------------------------------------------+ 480 + |int32 status |SUCCESS: If reset vector is set successfully. | 481 + | |NOT_FOUND: if lmid not points to a valid logical | 482 + | |machine, or cpuId is not valid. | 483 + | |INVALID_PARAMETERS: if reset vector is invalid. | 484 + | |DENIED: if the agent does not have permission to set | 485 + | |the reset vector for the CPU in the LM. | 486 + +-----------------------+------------------------------------------------------+ 487 + 488 + NEGOTIATE_PROTOCOL_VERSION 489 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 490 + 491 + message_id: 0x10 492 + protocol_id: 0x80 493 + This command is mandatory. 494 + 495 + +--------------------+---------------------------------------------------------+ 496 + |Parameters | 497 + +--------------------+---------------------------------------------------------+ 498 + |Name |Description | 499 + +--------------------+---------------------------------------------------------+ 500 + |uint32 version |The negotiated protocol version the agent intends to use | 501 + +--------------------+---------------------------------------------------------+ 502 + |Return values | 503 + +--------------------+---------------------------------------------------------+ 504 + |Name |Description | 505 + +--------------------+---------------------------------------------------------+ 506 + |int32 status |SUCCESS: if the negotiated protocol version is supported | 507 + | |by the platform. All commands, responses, and | 508 + | |notifications post successful return of this command must| 509 + | |comply with the negotiated version. | 510 + | |NOT_SUPPORTED: if the protocol version is not supported. | 511 + +--------------------+---------------------------------------------------------+ 512 + 513 + Notifications 514 + _____________ 515 + 516 + LMM_EVENT 517 + ~~~~~~~~~ 518 + 519 + message_id: 0x0 520 + protocol_id: 0x80 521 + 522 + +------------------+-----------------------------------------------------------+ 523 + |Parameters | 524 + +------------------+-----------------------------------------------------------+ 525 + |Name |Description | 526 + +------------------+-----------------------------------------------------------+ 527 + |uint32 lmid |Identifier for the LM that caused the transition. | 528 + +------------------+-----------------------------------------------------------+ 529 + |uint32 eventlm |Identifier of the LM this event refers to. | 530 + +------------------+-----------------------------------------------------------+ 531 + |uint32 flags |LM events: | 532 + | |Bits[31:3] Reserved, must be zero. | 533 + | |Bit[3] Wake (resume) event: | 534 + | |1 LM has awakened. | 535 + | |0 not a wake event. | 536 + | |Bit[2] Suspend (sleep) event: | 537 + | |1 LM has suspended. | 538 + | |0 not a suspend event. | 539 + | |Bit[1] Shutdown (off) event: | 540 + | |1 LM has shutdown. | 541 + | |0 not a shutdown event. | 542 + | |Bit[0] Boot (on) event: | 543 + | |1 LM has booted. | 544 + | |0 not a boot event. | 545 + +------------------+-----------------------------------------------------------+ 546 + 35 547 SCMI_BBM: System Control and Management BBM Vendor Protocol 36 548 ============================================================== 37 549 ··· 947 435 | |1 button change detected. | 948 436 | |0 no button change detected. | 949 437 +------------------+-----------------------------------------------------------+ 438 + 439 + System Control and Management CPU Vendor Protocol 440 + ================================================= 441 + 442 + This protocol allows an agent to start or stop a CPU. It is used to manage 443 + auxiliary CPUs in a target LM (e.g. additional cores in an AP cluster or 444 + Cortex-M cores). 445 + Note: 446 + - For cores in AP cluster, PSCI should be used and PSCI firmware will use CPU 447 + protocol to handle them. For cores in non-AP cluster, Operating System(e.g. 448 + Linux OS) could use CPU protocols to control Cortex-M7 cores. 449 + - CPU indicates the core and its auxiliary peripherals(e.g. TCM) inside 450 + i.MX SoC 451 + 452 + There are cases where giving an agent full control of a CPU via the CPU 453 + protocol is not desired. The LMM protocol is more restricted to just boot, 454 + shutdown, etc. So an agent might boot another logical machine but not be 455 + able to directly mess the state of its CPUs. Its also the reason there is an 456 + LMM power on command even though that could have been done through the 457 + power protocol. 458 + 459 + The CPU protocol provides commands to: 460 + 461 + - Describe the protocol version. 462 + - Discover implementation attributes. 463 + - Discover the CPUs defined in the system. 464 + - Start a CPU. 465 + - Stop a CPU. 466 + - Set the boot and resume addresses for a CPU. 467 + - Set the sleep mode of a CPU. 468 + - Configure wake-up sources for a CPU. 469 + - Configure power domain reactions (LPM mode and retention mask) for a CPU. 470 + - The CPU IDs can be found in the CPU section of the SoC DEVICE: SM Device 471 + Interface. They can also be found in the SoC RM. See the CPU Mode Control 472 + (CMC) list in General Power Controller (GPC) section. 473 + 474 + CPU settings are not aggregated and setting their state is normally exclusive 475 + to one client. 476 + 477 + Commands: 478 + _________ 479 + 480 + PROTOCOL_VERSION 481 + ~~~~~~~~~~~~~~~~ 482 + 483 + message_id: 0x0 484 + protocol_id: 0x82 485 + This command is mandatory. 486 + 487 + +---------------+--------------------------------------------------------------+ 488 + |Return values | 489 + +---------------+--------------------------------------------------------------+ 490 + |Name |Description | 491 + +---------------+--------------------------------------------------------------+ 492 + |int32 status | See ARM SCMI Specification for status code definitions. | 493 + +---------------+--------------------------------------------------------------+ 494 + |uint32 version | For this revision of the specification, this value must be | 495 + | | 0x10000. | 496 + +---------------+--------------------------------------------------------------+ 497 + 498 + PROTOCOL_ATTRIBUTES 499 + ~~~~~~~~~~~~~~~~~~~ 500 + 501 + message_id: 0x1 502 + protocol_id: 0x82 503 + This command is mandatory. 504 + 505 + +---------------+--------------------------------------------------------------+ 506 + |Return values | 507 + +------------------+-----------------------------------------------------------+ 508 + |Name |Description | 509 + +------------------+-----------------------------------------------------------+ 510 + |int32 status | See ARM SCMI Specification for status code definitions. | 511 + +------------------+-----------------------------------------------------------+ 512 + |uint32 attributes |Protocol attributes: | 513 + | |Bits[31:16] Reserved, must be zero. | 514 + | |Bits[15:0] Number of CPUs | 515 + +------------------+-----------------------------------------------------------+ 516 + 517 + PROTOCOL_MESSAGE_ATTRIBUTES 518 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 519 + 520 + message_id: 0x2 521 + protocol_id: 0x82 522 + This command is mandatory. 523 + 524 + +---------------+--------------------------------------------------------------+ 525 + |Return values | 526 + +------------------+-----------------------------------------------------------+ 527 + |Name |Description | 528 + +------------------+-----------------------------------------------------------+ 529 + |int32 status |SUCCESS: in case the message is implemented and available | 530 + | |to use. | 531 + | |NOT_FOUND: if the message identified by message_id is | 532 + | |invalid or not implemented | 533 + +------------------+-----------------------------------------------------------+ 534 + |uint32 attributes |Flags that are associated with a specific command in the | 535 + | |protocol. For all commands in this protocol, this | 536 + | |parameter has a value of 0 | 537 + +------------------+-----------------------------------------------------------+ 538 + 539 + CPU_ATTRIBUTES 540 + ~~~~~~~~~~~~~~ 541 + 542 + message_id: 0x4 543 + protocol_id: 0x82 544 + This command is mandatory. 545 + 546 + +------------------+-----------------------------------------------------------+ 547 + |Parameters | 548 + +------------------+-----------------------------------------------------------+ 549 + |Name |Description | 550 + +------------------+-----------------------------------------------------------+ 551 + |uint32 cpuid |Identifier for the CPU | 552 + +------------------+-----------------------------------------------------------+ 553 + |Return values | 554 + +------------------+-----------------------------------------------------------+ 555 + |Name |Description | 556 + +------------------+-----------------------------------------------------------+ 557 + |int32 status |SUCCESS: if valid attributes are returned successfully. | 558 + | |NOT_FOUND: if the cpuid is not valid. | 559 + +------------------+-----------------------------------------------------------+ 560 + |uint32 attributes |Bits[31:0] Reserved, must be zero | 561 + +------------------+-----------------------------------------------------------+ 562 + |char name[16] |NULL terminated ASCII string with CPU name up to 16 bytes | 563 + +------------------+-----------------------------------------------------------+ 564 + 565 + CPU_START 566 + ~~~~~~~~~ 567 + 568 + message_id: 0x4 569 + protocol_id: 0x82 570 + This command is mandatory. 571 + 572 + +------------------+-----------------------------------------------------------+ 573 + |Parameters | 574 + +------------------+-----------------------------------------------------------+ 575 + |Name |Description | 576 + +------------------+-----------------------------------------------------------+ 577 + |uint32 cpuid |Identifier for the CPU | 578 + +------------------+-----------------------------------------------------------+ 579 + |Return values | 580 + +------------------+-----------------------------------------------------------+ 581 + |Name |Description | 582 + +------------------+-----------------------------------------------------------+ 583 + |int32 status |SUCCESS: if the cpu is started successfully. | 584 + | |NOT_FOUND: if cpuid is not valid. | 585 + | |DENIED: the calling agent is not allowed to start this CPU.| 586 + +------------------+-----------------------------------------------------------+ 587 + 588 + CPU_STOP 589 + ~~~~~~~~ 590 + 591 + message_id: 0x5 592 + protocol_id: 0x82 593 + This command is mandatory. 594 + 595 + +------------------+-----------------------------------------------------------+ 596 + |Parameters | 597 + +------------------+-----------------------------------------------------------+ 598 + |Name |Description | 599 + +------------------+-----------------------------------------------------------+ 600 + |uint32 cpuid |Identifier for the CPU | 601 + +------------------+-----------------------------------------------------------+ 602 + |Return values | 603 + +------------------+-----------------------------------------------------------+ 604 + |Name |Description | 605 + +------------------+-----------------------------------------------------------+ 606 + |int32 status |SUCCESS: if the cpu is started successfully. | 607 + | |NOT_FOUND: if cpuid is not valid. | 608 + | |DENIED: the calling agent is not allowed to stop this CPU. | 609 + +------------------+-----------------------------------------------------------+ 610 + 611 + CPU_RESET_VECTOR_SET 612 + ~~~~~~~~~~~~~~~~~~~~ 613 + 614 + message_id: 0x6 615 + protocol_id: 0x82 616 + This command is mandatory. 617 + 618 + +----------------------+-------------------------------------------------------+ 619 + |Parameters | 620 + +----------------------+-------------------------------------------------------+ 621 + |Name |Description | 622 + +----------------------+-------------------------------------------------------+ 623 + |uint32 cpuid |Identifier for the CPU | 624 + +----------------------+-------------------------------------------------------+ 625 + |uint32 flags |Reset vector flags: | 626 + | |Bit[31] Resume flag. | 627 + | |Set to 1 to update the reset vector used on resume. | 628 + | |Bit[30] Boot flag. | 629 + | |Set to 1 to update the reset vector used for boot. | 630 + | |Bits[29:1] Reserved, must be zero. | 631 + | |Bit[0] Table flag. | 632 + | |Set to 1 if vector is the vector table base address. | 633 + +----------------------+-------------------------------------------------------+ 634 + |uint32 resetVectorLow |Lower vector: | 635 + | |If bit[0] of flags is 0, the lower 32 bits of the | 636 + | |physical address where the CPU should execute from on | 637 + | |reset. If bit[0] of flags is 1, the lower 32 bits of | 638 + | |the vector table base address | 639 + +----------------------+-------------------------------------------------------+ 640 + |uint32 resetVectorhigh|Upper vector: | 641 + | |If bit[0] of flags is 0, the upper 32 bits of the | 642 + | |physical address where the CPU should execute from on | 643 + | |reset. If bit[0] of flags is 1, the upper 32 bits of | 644 + | |the vector table base address | 645 + +----------------------+-------------------------------------------------------+ 646 + |Return values | 647 + +----------------------+-------------------------------------------------------+ 648 + |Name |Description | 649 + +----------------------+-------------------------------------------------------+ 650 + |int32 status |SUCCESS: if the CPU reset vector is set successfully. | 651 + | |NOT_FOUND: if cpuId does not point to a valid CPU. | 652 + | |INVALID_PARAMETERS: the requested vector type is not | 653 + | |supported by this CPU. | 654 + | |DENIED: the calling agent is not allowed to set the | 655 + | |reset vector of this CPU | 656 + +----------------------+-------------------------------------------------------+ 657 + 658 + CPU_SLEEP_MODE_SET 659 + ~~~~~~~~~~~~~~~~~~ 660 + 661 + message_id: 0x7 662 + protocol_id: 0x82 663 + This command is mandatory. 664 + 665 + +----------------------+-------------------------------------------------------+ 666 + |Parameters | 667 + +----------------------+-------------------------------------------------------+ 668 + |Name |Description | 669 + +----------------------+-------------------------------------------------------+ 670 + |uint32 cpuid |Identifier for the CPU | 671 + +----------------------+-------------------------------------------------------+ 672 + |uint32 flags |Sleep mode flags: | 673 + | |Bits[31:1] Reserved, must be zero. | 674 + | |Bit[0] IRQ mux: | 675 + | |If set to 1 the wakeup mux source is the GIC, else if 0| 676 + | |then the GPC | 677 + +----------------------+-------------------------------------------------------+ 678 + |uint32 sleepmode |target sleep mode. When CPU runs into WFI, the GPC mode| 679 + | |will be triggered to be in below modes: | 680 + | |RUN: (0) | 681 + | |WAIT: (1) | 682 + | |STOP: (2) | 683 + | |SUSPEND: (3) | 684 + +----------------------+-------------------------------------------------------+ 685 + |Return values | 686 + +----------------------+-------------------------------------------------------+ 687 + |Name |Description | 688 + +----------------------+-------------------------------------------------------+ 689 + |int32 status |SUCCESS: if the CPU sleep mode is set successfully. | 690 + | |NOT_FOUND: if cpuId does not point to a valid CPU. | 691 + | |INVALID_PARAMETERS: the sleepmode or flags is invalid. | 692 + | |DENIED: the calling agent is not allowed to configure | 693 + | |the CPU | 694 + +----------------------+-------------------------------------------------------+ 695 + 696 + CPU_INFO_GET 697 + ~~~~~~~~~~~~ 698 + 699 + message_id: 0xC 700 + protocol_id: 0x82 701 + This command is mandatory. 702 + 703 + +----------------------+-------------------------------------------------------+ 704 + |Parameters | 705 + +----------------------+-------------------------------------------------------+ 706 + |Name |Description | 707 + +----------------------+-------------------------------------------------------+ 708 + |uint32 cpuid |Identifier for the CPU | 709 + +----------------------+-------------------------------------------------------+ 710 + |Return values | 711 + +----------------------+-------------------------------------------------------+ 712 + |Name |Description | 713 + +----------------------+-------------------------------------------------------+ 714 + |int32 status |SUCCESS: if valid attributes are returned successfully.| 715 + | |NOT_FOUND: if the cpuid is not valid. | 716 + +----------------------+-------------------------------------------------------+ 717 + |uint32 runmode |Run mode for the CPU | 718 + | |RUN(0):cpu started | 719 + | |HOLD(1):cpu powered up and reset asserted | 720 + | |STOP(2):cpu reseted and hold cpu | 721 + | |SUSPEND(3):in cpuidle state | 722 + +----------------------+-------------------------------------------------------+ 723 + |uint32 sleepmode |Sleep mode for the CPU, see CPU_SLEEP_MODE_SET | 724 + +----------------------+-------------------------------------------------------+ 725 + |uint32 resetvectorlow |Reset vector low 32 bits for the CPU | 726 + +----------------------+-------------------------------------------------------+ 727 + |uint32 resetvecothigh |Reset vector high 32 bits for the CPU | 728 + +----------------------+-------------------------------------------------------+ 729 + 730 + NEGOTIATE_PROTOCOL_VERSION 731 + ~~~~~~~~~~~~~~~~~~~~~~~~~~ 732 + 733 + message_id: 0x10 734 + protocol_id: 0x82 735 + This command is mandatory. 736 + 737 + +--------------------+---------------------------------------------------------+ 738 + |Parameters | 739 + +--------------------+---------------------------------------------------------+ 740 + |Name |Description | 741 + +--------------------+---------------------------------------------------------+ 742 + |uint32 version |The negotiated protocol version the agent intends to use | 743 + +--------------------+---------------------------------------------------------+ 744 + |Return values | 745 + +--------------------+---------------------------------------------------------+ 746 + |Name |Description | 747 + +--------------------+---------------------------------------------------------+ 748 + |int32 status |SUCCESS: if the negotiated protocol version is supported | 749 + | |by the platform. All commands, responses, and | 750 + | |notifications post successful return of this command must| 751 + | |comply with the negotiated version. | 752 + | |NOT_SUPPORTED: if the protocol version is not supported. | 753 + +--------------------+---------------------------------------------------------+ 950 754 951 755 SCMI_MISC: System Control and Management MISC Vendor Protocol 952 756 ================================================================
+22
drivers/firmware/imx/Kconfig
··· 23 23 This driver manages the IPC interface between host CPU and the 24 24 SCU firmware running on M4. 25 25 26 + config IMX_SCMI_CPU_DRV 27 + tristate "IMX SCMI CPU Protocol driver" 28 + depends on ARCH_MXC || COMPILE_TEST 29 + default y if ARCH_MXC 30 + help 31 + The System Controller Management Interface firmware (SCMI FW) is 32 + a low-level system function which runs on a dedicated Cortex-M 33 + core that could provide cpu management features. 34 + 35 + This driver can also be built as a module. 36 + 37 + config IMX_SCMI_LMM_DRV 38 + tristate "IMX SCMI LMM Protocol driver" 39 + depends on ARCH_MXC || COMPILE_TEST 40 + default y if ARCH_MXC 41 + help 42 + The System Controller Management Interface firmware (SCMI FW) is 43 + a low-level system function which runs on a dedicated Cortex-M 44 + core that could provide Logical Machine management features. 45 + 46 + This driver can also be built as a module. 47 + 26 48 config IMX_SCMI_MISC_DRV 27 49 tristate "IMX SCMI MISC Protocol driver" 28 50 depends on ARCH_MXC || COMPILE_TEST
+2
drivers/firmware/imx/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 obj-$(CONFIG_IMX_DSP) += imx-dsp.o 3 3 obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o imx-scu-irq.o rm.o imx-scu-soc.o 4 + obj-${CONFIG_IMX_SCMI_CPU_DRV} += sm-cpu.o 4 5 obj-${CONFIG_IMX_SCMI_MISC_DRV} += sm-misc.o 6 + obj-${CONFIG_IMX_SCMI_LMM_DRV} += sm-lmm.o
+85
drivers/firmware/imx/sm-cpu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2025 NXP 4 + */ 5 + 6 + #include <linux/firmware/imx/sm.h> 7 + #include <linux/module.h> 8 + #include <linux/of.h> 9 + #include <linux/platform_device.h> 10 + #include <linux/scmi_protocol.h> 11 + #include <linux/scmi_imx_protocol.h> 12 + 13 + static const struct scmi_imx_cpu_proto_ops *imx_cpu_ops; 14 + static struct scmi_protocol_handle *ph; 15 + 16 + int scmi_imx_cpu_reset_vector_set(u32 cpuid, u64 vector, bool start, bool boot, 17 + bool resume) 18 + { 19 + if (!ph) 20 + return -EPROBE_DEFER; 21 + 22 + return imx_cpu_ops->cpu_reset_vector_set(ph, cpuid, vector, start, 23 + boot, resume); 24 + } 25 + EXPORT_SYMBOL(scmi_imx_cpu_reset_vector_set); 26 + 27 + int scmi_imx_cpu_start(u32 cpuid, bool start) 28 + { 29 + if (!ph) 30 + return -EPROBE_DEFER; 31 + 32 + if (start) 33 + return imx_cpu_ops->cpu_start(ph, cpuid, true); 34 + 35 + return imx_cpu_ops->cpu_start(ph, cpuid, false); 36 + }; 37 + EXPORT_SYMBOL(scmi_imx_cpu_start); 38 + 39 + int scmi_imx_cpu_started(u32 cpuid, bool *started) 40 + { 41 + if (!ph) 42 + return -EPROBE_DEFER; 43 + 44 + if (!started) 45 + return -EINVAL; 46 + 47 + return imx_cpu_ops->cpu_started(ph, cpuid, started); 48 + }; 49 + EXPORT_SYMBOL(scmi_imx_cpu_started); 50 + 51 + static int scmi_imx_cpu_probe(struct scmi_device *sdev) 52 + { 53 + const struct scmi_handle *handle = sdev->handle; 54 + 55 + if (!handle) 56 + return -ENODEV; 57 + 58 + if (imx_cpu_ops) { 59 + dev_err(&sdev->dev, "sm cpu already initialized\n"); 60 + return -EEXIST; 61 + } 62 + 63 + imx_cpu_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_IMX_CPU, &ph); 64 + if (IS_ERR(imx_cpu_ops)) 65 + return PTR_ERR(imx_cpu_ops); 66 + 67 + return 0; 68 + } 69 + 70 + static const struct scmi_device_id scmi_id_table[] = { 71 + { SCMI_PROTOCOL_IMX_CPU, "imx-cpu" }, 72 + { }, 73 + }; 74 + MODULE_DEVICE_TABLE(scmi, scmi_id_table); 75 + 76 + static struct scmi_driver scmi_imx_cpu_driver = { 77 + .name = "scmi-imx-cpu", 78 + .probe = scmi_imx_cpu_probe, 79 + .id_table = scmi_id_table, 80 + }; 81 + module_scmi_driver(scmi_imx_cpu_driver); 82 + 83 + MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>"); 84 + MODULE_DESCRIPTION("IMX SM CPU driver"); 85 + MODULE_LICENSE("GPL");
+91
drivers/firmware/imx/sm-lmm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2025 NXP 4 + */ 5 + 6 + #include <linux/firmware/imx/sm.h> 7 + #include <linux/module.h> 8 + #include <linux/of.h> 9 + #include <linux/platform_device.h> 10 + #include <linux/scmi_protocol.h> 11 + #include <linux/scmi_imx_protocol.h> 12 + 13 + static const struct scmi_imx_lmm_proto_ops *imx_lmm_ops; 14 + static struct scmi_protocol_handle *ph; 15 + 16 + int scmi_imx_lmm_info(u32 lmid, struct scmi_imx_lmm_info *info) 17 + { 18 + if (!ph) 19 + return -EPROBE_DEFER; 20 + 21 + if (!info) 22 + return -EINVAL; 23 + 24 + return imx_lmm_ops->lmm_info(ph, lmid, info); 25 + }; 26 + EXPORT_SYMBOL(scmi_imx_lmm_info); 27 + 28 + int scmi_imx_lmm_reset_vector_set(u32 lmid, u32 cpuid, u32 flags, u64 vector) 29 + { 30 + if (!ph) 31 + return -EPROBE_DEFER; 32 + 33 + return imx_lmm_ops->lmm_reset_vector_set(ph, lmid, cpuid, flags, vector); 34 + } 35 + EXPORT_SYMBOL(scmi_imx_lmm_reset_vector_set); 36 + 37 + int scmi_imx_lmm_operation(u32 lmid, enum scmi_imx_lmm_op op, u32 flags) 38 + { 39 + if (!ph) 40 + return -EPROBE_DEFER; 41 + 42 + switch (op) { 43 + case SCMI_IMX_LMM_BOOT: 44 + return imx_lmm_ops->lmm_power_boot(ph, lmid, true); 45 + case SCMI_IMX_LMM_POWER_ON: 46 + return imx_lmm_ops->lmm_power_boot(ph, lmid, false); 47 + case SCMI_IMX_LMM_SHUTDOWN: 48 + return imx_lmm_ops->lmm_shutdown(ph, lmid, flags); 49 + default: 50 + break; 51 + } 52 + 53 + return -EINVAL; 54 + } 55 + EXPORT_SYMBOL(scmi_imx_lmm_operation); 56 + 57 + static int scmi_imx_lmm_probe(struct scmi_device *sdev) 58 + { 59 + const struct scmi_handle *handle = sdev->handle; 60 + 61 + if (!handle) 62 + return -ENODEV; 63 + 64 + if (imx_lmm_ops) { 65 + dev_err(&sdev->dev, "lmm already initialized\n"); 66 + return -EEXIST; 67 + } 68 + 69 + imx_lmm_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_IMX_LMM, &ph); 70 + if (IS_ERR(imx_lmm_ops)) 71 + return PTR_ERR(imx_lmm_ops); 72 + 73 + return 0; 74 + } 75 + 76 + static const struct scmi_device_id scmi_id_table[] = { 77 + { SCMI_PROTOCOL_IMX_LMM, "imx-lmm" }, 78 + { }, 79 + }; 80 + MODULE_DEVICE_TABLE(scmi, scmi_id_table); 81 + 82 + static struct scmi_driver scmi_imx_lmm_driver = { 83 + .name = "scmi-imx-lmm", 84 + .probe = scmi_imx_lmm_probe, 85 + .id_table = scmi_id_table, 86 + }; 87 + module_scmi_driver(scmi_imx_lmm_driver); 88 + 89 + MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>"); 90 + MODULE_DESCRIPTION("IMX SM LMM driver"); 91 + MODULE_LICENSE("GPL");
+3
drivers/firmware/qcom/qcom_scm.c
··· 1986 1986 */ 1987 1987 static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { 1988 1988 { .compatible = "asus,vivobook-s15" }, 1989 + { .compatible = "asus,zenbook-a14-ux3407qa" }, 1990 + { .compatible = "asus,zenbook-a14-ux3407ra" }, 1989 1991 { .compatible = "dell,xps13-9345" }, 1992 + { .compatible = "hp,elitebook-ultra-g1q" }, 1990 1993 { .compatible = "hp,omnibook-x14" }, 1991 1994 { .compatible = "huawei,gaokun3" }, 1992 1995 { .compatible = "lenovo,flex-5g" },
+3
drivers/firmware/qcom/qcom_scm.h
··· 44 44 45 45 /** 46 46 * struct qcom_scm_desc 47 + * @svc: Service identifier 48 + * @cmd: Command identifier 47 49 * @arginfo: Metadata describing the arguments in args[] 48 50 * @args: The array of arguments for the secure syscall 51 + * @owner: Owner identifier 49 52 */ 50 53 struct qcom_scm_desc { 51 54 u32 svc;
+1
drivers/firmware/qcom/qcom_tzmem.c
··· 79 79 "qcom,sc8180x", 80 80 "qcom,sdm670", /* failure in GPU firmware loading */ 81 81 "qcom,sdm845", /* reset in rmtfs memory assignment */ 82 + "qcom,sm7150", /* reset in rmtfs memory assignment */ 82 83 "qcom,sm8150", /* reset in rmtfs memory assignment */ 83 84 NULL 84 85 };
+8 -8
drivers/firmware/samsung/exynos-acpm-pmic.c
··· 43 43 return (data >> (ACPM_PMIC_BULK_SHIFT * i)) & ACPM_PMIC_BULK_MASK; 44 44 } 45 45 46 - static void acpm_pmic_set_xfer(struct acpm_xfer *xfer, u32 *cmd, 46 + static void acpm_pmic_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen, 47 47 unsigned int acpm_chan_id) 48 48 { 49 49 xfer->txd = cmd; 50 50 xfer->rxd = cmd; 51 - xfer->txlen = sizeof(cmd); 52 - xfer->rxlen = sizeof(cmd); 51 + xfer->txlen = cmdlen; 52 + xfer->rxlen = cmdlen; 53 53 xfer->acpm_chan_id = acpm_chan_id; 54 54 } 55 55 ··· 71 71 int ret; 72 72 73 73 acpm_pmic_init_read_cmd(cmd, type, reg, chan); 74 - acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id); 74 + acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id); 75 75 76 76 ret = acpm_do_xfer(handle, &xfer); 77 77 if (ret) ··· 104 104 return -EINVAL; 105 105 106 106 acpm_pmic_init_bulk_read_cmd(cmd, type, reg, chan, count); 107 - acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id); 107 + acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id); 108 108 109 109 ret = acpm_do_xfer(handle, &xfer); 110 110 if (ret) ··· 144 144 int ret; 145 145 146 146 acpm_pmic_init_write_cmd(cmd, type, reg, chan, value); 147 - acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id); 147 + acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id); 148 148 149 149 ret = acpm_do_xfer(handle, &xfer); 150 150 if (ret) ··· 184 184 return -EINVAL; 185 185 186 186 acpm_pmic_init_bulk_write_cmd(cmd, type, reg, chan, count, buf); 187 - acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id); 187 + acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id); 188 188 189 189 ret = acpm_do_xfer(handle, &xfer); 190 190 if (ret) ··· 214 214 int ret; 215 215 216 216 acpm_pmic_init_update_cmd(cmd, type, reg, chan, value, mask); 217 - acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id); 217 + acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id); 218 218 219 219 ret = acpm_do_xfer(handle, &xfer); 220 220 if (ret)
+23 -35
drivers/firmware/samsung/exynos-acpm.c
··· 15 15 #include <linux/firmware/samsung/exynos-acpm-protocol.h> 16 16 #include <linux/io.h> 17 17 #include <linux/iopoll.h> 18 + #include <linux/ktime.h> 18 19 #include <linux/mailbox/exynos-message.h> 19 20 #include <linux/mailbox_client.h> 20 21 #include <linux/module.h> ··· 33 32 34 33 #define ACPM_PROTOCOL_SEQNUM GENMASK(21, 16) 35 34 36 - /* The unit of counter is 20 us. 5000 * 20 = 100 ms */ 37 - #define ACPM_POLL_TIMEOUT 5000 35 + #define ACPM_POLL_TIMEOUT_US (100 * USEC_PER_MSEC) 38 36 #define ACPM_TX_TIMEOUT_US 500000 39 37 40 38 #define ACPM_GS101_INITDATA_BASE 0xa000 ··· 300 300 const struct acpm_xfer *xfer) 301 301 { 302 302 struct device *dev = achan->acpm->dev; 303 - unsigned int cnt_20us = 0; 303 + ktime_t timeout; 304 304 u32 seqnum; 305 305 int ret; 306 306 307 307 seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]); 308 308 309 + timeout = ktime_add_us(ktime_get(), ACPM_POLL_TIMEOUT_US); 309 310 do { 310 311 ret = acpm_get_rx(achan, xfer); 311 312 if (ret) ··· 316 315 return 0; 317 316 318 317 /* Determined experimentally. */ 319 - usleep_range(20, 30); 320 - cnt_20us++; 321 - } while (cnt_20us < ACPM_POLL_TIMEOUT); 318 + udelay(20); 319 + } while (ktime_before(ktime_get(), timeout)); 322 320 323 - dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx, cnt_20us = %d.\n", 324 - achan->id, seqnum, achan->bitmap_seqnum[0], cnt_20us); 321 + dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx.\n", 322 + achan->id, seqnum, achan->bitmap_seqnum[0]); 325 323 326 324 return -ETIME; 327 325 } ··· 649 649 650 650 platform_set_drvdata(pdev, acpm); 651 651 652 - return 0; 652 + return devm_of_platform_populate(dev); 653 653 } 654 654 655 655 /** ··· 677 677 } 678 678 679 679 /** 680 - * acpm_get_by_phandle() - get the ACPM handle using DT phandle. 681 - * @dev: device pointer requesting ACPM handle. 682 - * @property: property name containing phandle on ACPM node. 680 + * acpm_get_by_node() - get the ACPM handle using node pointer. 681 + * @dev: device pointer requesting ACPM handle. 682 + * @np: ACPM device tree node. 683 683 * 684 684 * Return: pointer to handle on success, ERR_PTR(-errno) otherwise. 685 685 */ 686 - static const struct acpm_handle *acpm_get_by_phandle(struct device *dev, 687 - const char *property) 686 + static const struct acpm_handle *acpm_get_by_node(struct device *dev, 687 + struct device_node *np) 688 688 { 689 689 struct platform_device *pdev; 690 - struct device_node *acpm_np; 691 690 struct device_link *link; 692 691 struct acpm_info *acpm; 693 692 694 - acpm_np = of_parse_phandle(dev->of_node, property, 0); 695 - if (!acpm_np) 696 - return ERR_PTR(-ENODEV); 697 - 698 - pdev = of_find_device_by_node(acpm_np); 699 - if (!pdev) { 700 - dev_err(dev, "Cannot find device node %s\n", acpm_np->name); 701 - of_node_put(acpm_np); 693 + pdev = of_find_device_by_node(np); 694 + if (!pdev) 702 695 return ERR_PTR(-EPROBE_DEFER); 703 - } 704 - 705 - of_node_put(acpm_np); 706 696 707 697 acpm = platform_get_drvdata(pdev); 708 698 if (!acpm) { 709 - dev_err(dev, "Cannot get drvdata from %s\n", 710 - dev_name(&pdev->dev)); 711 699 platform_device_put(pdev); 712 700 return ERR_PTR(-EPROBE_DEFER); 713 701 } 714 702 715 703 if (!try_module_get(pdev->dev.driver->owner)) { 716 - dev_err(dev, "Cannot get module reference.\n"); 717 704 platform_device_put(pdev); 718 705 return ERR_PTR(-EPROBE_DEFER); 719 706 } ··· 719 732 } 720 733 721 734 /** 722 - * devm_acpm_get_by_phandle() - managed get handle using phandle. 723 - * @dev: device pointer requesting ACPM handle. 724 - * @property: property name containing phandle on ACPM node. 735 + * devm_acpm_get_by_node() - managed get handle using node pointer. 736 + * @dev: device pointer requesting ACPM handle. 737 + * @np: ACPM device tree node. 725 738 * 726 739 * Return: pointer to handle on success, ERR_PTR(-errno) otherwise. 727 740 */ 728 - const struct acpm_handle *devm_acpm_get_by_phandle(struct device *dev, 729 - const char *property) 741 + const struct acpm_handle *devm_acpm_get_by_node(struct device *dev, 742 + struct device_node *np) 730 743 { 731 744 const struct acpm_handle **ptr, *handle; 732 745 ··· 734 747 if (!ptr) 735 748 return ERR_PTR(-ENOMEM); 736 749 737 - handle = acpm_get_by_phandle(dev, property); 750 + handle = acpm_get_by_node(dev, np); 738 751 if (!IS_ERR(handle)) { 739 752 *ptr = handle; 740 753 devres_add(dev, ptr); ··· 744 757 745 758 return handle; 746 759 } 760 + EXPORT_SYMBOL_GPL(devm_acpm_get_by_node); 747 761 748 762 static const struct acpm_match_data acpm_gs101 = { 749 763 .initdata_base = ACPM_GS101_INITDATA_BASE,
+11 -3
drivers/firmware/ti_sci.c
··· 2 2 /* 3 3 * Texas Instruments System Control Interface Protocol Driver 4 4 * 5 - * Copyright (C) 2015-2024 Texas Instruments Incorporated - https://www.ti.com/ 5 + * Copyright (C) 2015-2025 Texas Instruments Incorporated - https://www.ti.com/ 6 6 * Nishanth Menon 7 7 */ 8 8 ··· 3670 3670 struct ti_sci_info *info = dev_get_drvdata(dev); 3671 3671 struct device *cpu_dev, *cpu_dev_max = NULL; 3672 3672 s32 val, cpu_lat = 0; 3673 + u16 cpu_lat_ms; 3673 3674 int i, ret; 3674 3675 3675 3676 if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) { ··· 3683 3682 } 3684 3683 } 3685 3684 if (cpu_dev_max) { 3686 - dev_dbg(cpu_dev_max, "%s: sending max CPU latency=%u\n", __func__, cpu_lat); 3685 + /* 3686 + * PM QoS latency unit is usecs, device manager uses msecs. 3687 + * Convert to msecs and round down for device manager. 3688 + */ 3689 + cpu_lat_ms = cpu_lat / USEC_PER_MSEC; 3690 + dev_dbg(cpu_dev_max, "%s: sending max CPU latency=%u ms\n", __func__, 3691 + cpu_lat_ms); 3687 3692 ret = ti_sci_cmd_set_latency_constraint(&info->handle, 3688 - cpu_lat, TISCI_MSG_CONSTRAINT_SET); 3693 + cpu_lat_ms, 3694 + TISCI_MSG_CONSTRAINT_SET); 3689 3695 if (ret) 3690 3696 return ret; 3691 3697 }
+127 -141
drivers/firmware/turris-mox-rwtm.c
··· 2 2 /* 3 3 * Turris Mox rWTM firmware driver 4 4 * 5 - * Copyright (C) 2019, 2024 Marek Behún <kabel@kernel.org> 5 + * Copyright (C) 2019, 2024, 2025 Marek Behún <kabel@kernel.org> 6 6 */ 7 7 8 8 #include <crypto/sha2.h> 9 9 #include <linux/align.h> 10 10 #include <linux/armada-37xx-rwtm-mailbox.h> 11 + #include <linux/cleanup.h> 11 12 #include <linux/completion.h> 12 13 #include <linux/container_of.h> 13 - #include <linux/debugfs.h> 14 14 #include <linux/device.h> 15 15 #include <linux/dma-mapping.h> 16 16 #include <linux/err.h> 17 - #include <linux/fs.h> 18 17 #include <linux/hw_random.h> 19 18 #include <linux/if_ether.h> 19 + #include <linux/key.h> 20 20 #include <linux/kobject.h> 21 21 #include <linux/mailbox_client.h> 22 + #include <linux/math.h> 22 23 #include <linux/minmax.h> 23 24 #include <linux/module.h> 24 25 #include <linux/mutex.h> 25 26 #include <linux/platform_device.h> 26 27 #include <linux/sizes.h> 27 28 #include <linux/sysfs.h> 29 + #include <linux/turris-signing-key.h> 28 30 #include <linux/types.h> 29 31 30 32 #define DRIVER_NAME "turris-mox-rwtm" ··· 39 37 * https://gitlab.labs.nic.cz/turris/mox-boot-builder/tree/master/wtmi. 40 38 */ 41 39 42 - #define MOX_ECC_NUMBER_WORDS 17 43 - #define MOX_ECC_NUMBER_LEN (MOX_ECC_NUMBER_WORDS * sizeof(u32)) 44 - 45 - #define MOX_ECC_SIGNATURE_WORDS (2 * MOX_ECC_NUMBER_WORDS) 40 + enum { 41 + MOX_ECC_NUM_BITS = 521, 42 + MOX_ECC_NUM_LEN = DIV_ROUND_UP(MOX_ECC_NUM_BITS, 8), 43 + MOX_ECC_NUM_WORDS = DIV_ROUND_UP(MOX_ECC_NUM_BITS, 32), 44 + MOX_ECC_SIG_LEN = 2 * MOX_ECC_NUM_LEN, 45 + MOX_ECC_PUBKEY_LEN = 1 + MOX_ECC_NUM_LEN, 46 + }; 46 47 47 48 #define MBOX_STS_SUCCESS (0 << 30) 48 49 #define MBOX_STS_FAIL (1 << 30) ··· 82 77 * @ram_size: RAM size of the device 83 78 * @mac_address1: first MAC address of the device 84 79 * @mac_address2: second MAC address of the device 85 - * @has_pubkey: whether board ECDSA public key is present 86 80 * @pubkey: board ECDSA public key 87 - * @last_sig: last ECDSA signature generated with board ECDSA private key 88 - * @last_sig_done: whether the last ECDSA signing is complete 89 81 */ 90 82 struct mox_rwtm { 91 83 struct mbox_client mbox_client; ··· 102 100 int board_version, ram_size; 103 101 u8 mac_address1[ETH_ALEN], mac_address2[ETH_ALEN]; 104 102 105 - bool has_pubkey; 106 - u8 pubkey[135]; 107 - 108 - #ifdef CONFIG_DEBUG_FS 109 - /* 110 - * Signature process. This is currently done via debugfs, because it 111 - * does not conform to the sysfs standard "one file per attribute". 112 - * It should be rewritten via crypto API once akcipher API is available 113 - * from userspace. 114 - */ 115 - u32 last_sig[MOX_ECC_SIGNATURE_WORDS]; 116 - bool last_sig_done; 103 + #ifdef CONFIG_TURRIS_MOX_RWTM_KEYCTL 104 + u8 pubkey[MOX_ECC_PUBKEY_LEN]; 117 105 #endif 118 106 }; 119 107 ··· 112 120 return rwtm->mbox_client.dev; 113 121 } 114 122 115 - #define MOX_ATTR_RO(name, format, cat) \ 123 + #define MOX_ATTR_RO(name, format) \ 116 124 static ssize_t \ 117 125 name##_show(struct device *dev, struct device_attribute *a, \ 118 126 char *buf) \ 119 127 { \ 120 128 struct mox_rwtm *rwtm = dev_get_drvdata(dev); \ 121 - if (!rwtm->has_##cat) \ 129 + if (!rwtm->has_board_info) \ 122 130 return -ENODATA; \ 123 131 return sysfs_emit(buf, format, rwtm->name); \ 124 132 } \ 125 133 static DEVICE_ATTR_RO(name) 126 134 127 - MOX_ATTR_RO(serial_number, "%016llX\n", board_info); 128 - MOX_ATTR_RO(board_version, "%i\n", board_info); 129 - MOX_ATTR_RO(ram_size, "%i\n", board_info); 130 - MOX_ATTR_RO(mac_address1, "%pM\n", board_info); 131 - MOX_ATTR_RO(mac_address2, "%pM\n", board_info); 132 - MOX_ATTR_RO(pubkey, "%s\n", pubkey); 135 + MOX_ATTR_RO(serial_number, "%016llX\n"); 136 + MOX_ATTR_RO(board_version, "%i\n"); 137 + MOX_ATTR_RO(ram_size, "%i\n"); 138 + MOX_ATTR_RO(mac_address1, "%pM\n"); 139 + MOX_ATTR_RO(mac_address2, "%pM\n"); 133 140 134 141 static struct attribute *turris_mox_rwtm_attrs[] = { 135 142 &dev_attr_serial_number.attr, ··· 136 145 &dev_attr_ram_size.attr, 137 146 &dev_attr_mac_address1.attr, 138 147 &dev_attr_mac_address2.attr, 139 - &dev_attr_pubkey.attr, 140 148 NULL 141 149 }; 142 150 ATTRIBUTE_GROUPS(turris_mox_rwtm); ··· 237 247 pr_info(" burned RAM size %i MiB\n", rwtm->ram_size); 238 248 } 239 249 240 - ret = mox_rwtm_exec(rwtm, MBOX_CMD_ECDSA_PUB_KEY, NULL, false); 241 - if (ret == -ENODATA) { 242 - dev_warn(dev, "Board has no public key burned!\n"); 243 - } else if (ret == -EOPNOTSUPP) { 244 - dev_notice(dev, 245 - "Firmware does not support the ECDSA_PUB_KEY command\n"); 246 - } else if (ret < 0) { 247 - return ret; 248 - } else { 249 - u32 *s = reply->status; 250 - 251 - rwtm->has_pubkey = true; 252 - sprintf(rwtm->pubkey, 253 - "%06x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", 254 - ret, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 255 - s[8], s[9], s[10], s[11], s[12], s[13], s[14], s[15]); 256 - } 257 - 258 250 return 0; 259 251 } 260 252 ··· 278 306 return ret; 279 307 } 280 308 281 - #ifdef CONFIG_DEBUG_FS 282 - static int rwtm_debug_open(struct inode *inode, struct file *file) 283 - { 284 - file->private_data = inode->i_private; 309 + #ifdef CONFIG_TURRIS_MOX_RWTM_KEYCTL 285 310 286 - return nonseekable_open(inode, file); 311 + static void mox_ecc_number_to_bin(void *dst, const u32 *src) 312 + { 313 + __be32 tmp[MOX_ECC_NUM_WORDS]; 314 + 315 + cpu_to_be32_array(tmp, src, MOX_ECC_NUM_WORDS); 316 + 317 + memcpy(dst, (void *)tmp + 2, MOX_ECC_NUM_LEN); 287 318 } 288 319 289 - static ssize_t do_sign_read(struct file *file, char __user *buf, size_t len, 290 - loff_t *ppos) 320 + static void mox_ecc_public_key_to_bin(void *dst, u32 src_first, 321 + const u32 *src_rest) 291 322 { 292 - struct mox_rwtm *rwtm = file->private_data; 293 - ssize_t ret; 323 + __be32 tmp[MOX_ECC_NUM_WORDS - 1]; 324 + u8 *p = dst; 294 325 295 - /* only allow one read, of whole signature, from position 0 */ 296 - if (*ppos != 0) 297 - return 0; 326 + /* take 3 bytes from the first word */ 327 + *p++ = src_first >> 16; 328 + *p++ = src_first >> 8; 329 + *p++ = src_first; 298 330 299 - if (len < sizeof(rwtm->last_sig)) 300 - return -EINVAL; 301 - 302 - if (!rwtm->last_sig_done) 303 - return -ENODATA; 304 - 305 - ret = simple_read_from_buffer(buf, len, ppos, rwtm->last_sig, 306 - sizeof(rwtm->last_sig)); 307 - rwtm->last_sig_done = false; 308 - 309 - return ret; 331 + /* take the rest of the words */ 332 + cpu_to_be32_array(tmp, src_rest, MOX_ECC_NUM_WORDS - 1); 333 + memcpy(p, tmp, sizeof(tmp)); 310 334 } 311 335 312 - static ssize_t do_sign_write(struct file *file, const char __user *buf, 313 - size_t len, loff_t *ppos) 336 + static int mox_rwtm_sign(const struct key *key, const void *data, void *signature) 314 337 { 315 - struct mox_rwtm *rwtm = file->private_data; 316 - struct armada_37xx_rwtm_tx_msg msg; 317 - loff_t dummy = 0; 318 - ssize_t ret; 338 + struct mox_rwtm *rwtm = dev_get_drvdata(turris_signing_key_get_dev(key)); 339 + struct armada_37xx_rwtm_tx_msg msg = {}; 340 + u32 offset_r, offset_s; 341 + int ret; 319 342 320 - if (len != SHA512_DIGEST_SIZE) 321 - return -EINVAL; 322 - 323 - /* if last result is not zero user has not read that information yet */ 324 - if (rwtm->last_sig_done) 325 - return -EBUSY; 326 - 327 - if (!mutex_trylock(&rwtm->busy)) 328 - return -EBUSY; 343 + guard(mutex)(&rwtm->busy); 329 344 330 345 /* 331 - * Here we have to send: 332 - * 1. Address of the input to sign. 333 - * The input is an array of 17 32-bit words, the first (most 334 - * significat) is 0, the rest 16 words are copied from the SHA-512 335 - * hash given by the user and converted from BE to LE. 336 - * 2. Address of the buffer where ECDSA signature value R shall be 337 - * stored by the rWTM firmware. 338 - * 3. Address of the buffer where ECDSA signature value S shall be 339 - * stored by the rWTM firmware. 346 + * For MBOX_CMD_SIGN command: 347 + * args[0] - must be 1 348 + * args[1] - address of message M to sign; message is a 521-bit number 349 + * args[2] - address where the R part of the signature will be stored 350 + * args[3] - address where the S part of the signature will be stored 351 + * 352 + * M, R and S are 521-bit numbers encoded as seventeen 32-bit words, 353 + * most significat word first. 354 + * Since the message in @data is a sha512 digest, the most significat 355 + * word is always zero. 340 356 */ 357 + 358 + offset_r = MOX_ECC_NUM_WORDS * sizeof(u32); 359 + offset_s = 2 * MOX_ECC_NUM_WORDS * sizeof(u32); 360 + 341 361 memset(rwtm->buf, 0, sizeof(u32)); 342 - ret = simple_write_to_buffer(rwtm->buf + sizeof(u32), 343 - SHA512_DIGEST_SIZE, &dummy, buf, len); 344 - if (ret < 0) 345 - goto unlock_mutex; 346 - be32_to_cpu_array(rwtm->buf, rwtm->buf, MOX_ECC_NUMBER_WORDS); 362 + memcpy(rwtm->buf + sizeof(u32), data, SHA512_DIGEST_SIZE); 363 + be32_to_cpu_array(rwtm->buf, rwtm->buf, MOX_ECC_NUM_WORDS); 347 364 348 365 msg.args[0] = 1; 349 366 msg.args[1] = rwtm->buf_phys; 350 - msg.args[2] = rwtm->buf_phys + MOX_ECC_NUMBER_LEN; 351 - msg.args[3] = rwtm->buf_phys + 2 * MOX_ECC_NUMBER_LEN; 367 + msg.args[2] = rwtm->buf_phys + offset_r; 368 + msg.args[3] = rwtm->buf_phys + offset_s; 352 369 353 370 ret = mox_rwtm_exec(rwtm, MBOX_CMD_SIGN, &msg, true); 354 371 if (ret < 0) 355 - goto unlock_mutex; 372 + return ret; 356 373 357 - /* 358 - * Here we read the R and S values of the ECDSA signature 359 - * computed by the rWTM firmware and convert their words from 360 - * LE to BE. 361 - */ 362 - memcpy(rwtm->last_sig, rwtm->buf + MOX_ECC_NUMBER_LEN, 363 - sizeof(rwtm->last_sig)); 364 - cpu_to_be32_array(rwtm->last_sig, rwtm->last_sig, 365 - MOX_ECC_SIGNATURE_WORDS); 366 - rwtm->last_sig_done = true; 374 + /* convert R and S parts of the signature */ 375 + mox_ecc_number_to_bin(signature, rwtm->buf + offset_r); 376 + mox_ecc_number_to_bin(signature + MOX_ECC_NUM_LEN, rwtm->buf + offset_s); 367 377 368 - mutex_unlock(&rwtm->busy); 369 - return len; 370 - unlock_mutex: 371 - mutex_unlock(&rwtm->busy); 372 - return ret; 378 + return 0; 373 379 } 374 380 375 - static const struct file_operations do_sign_fops = { 376 - .owner = THIS_MODULE, 377 - .open = rwtm_debug_open, 378 - .read = do_sign_read, 379 - .write = do_sign_write, 381 + static const void *mox_rwtm_get_public_key(const struct key *key) 382 + { 383 + struct mox_rwtm *rwtm = dev_get_drvdata(turris_signing_key_get_dev(key)); 384 + 385 + return rwtm->pubkey; 386 + } 387 + 388 + static const struct turris_signing_key_subtype mox_signing_key_subtype = { 389 + .key_size = MOX_ECC_NUM_BITS, 390 + .data_size = SHA512_DIGEST_SIZE, 391 + .sig_size = MOX_ECC_SIG_LEN, 392 + .public_key_size = MOX_ECC_PUBKEY_LEN, 393 + .hash_algo = "sha512", 394 + .get_public_key = mox_rwtm_get_public_key, 395 + .sign = mox_rwtm_sign, 380 396 }; 381 397 382 - static void rwtm_debugfs_release(void *root) 398 + static int mox_register_signing_key(struct mox_rwtm *rwtm) 383 399 { 384 - debugfs_remove_recursive(root); 400 + struct armada_37xx_rwtm_rx_msg *reply = &rwtm->reply; 401 + struct device *dev = rwtm_dev(rwtm); 402 + int ret; 403 + 404 + ret = mox_rwtm_exec(rwtm, MBOX_CMD_ECDSA_PUB_KEY, NULL, false); 405 + if (ret == -ENODATA) { 406 + dev_warn(dev, "Board has no public key burned!\n"); 407 + } else if (ret == -EOPNOTSUPP) { 408 + dev_notice(dev, 409 + "Firmware does not support the ECDSA_PUB_KEY command\n"); 410 + } else if (ret < 0) { 411 + return ret; 412 + } else { 413 + char sn[17] = "unknown"; 414 + char desc[46]; 415 + 416 + if (rwtm->has_board_info) 417 + sprintf(sn, "%016llX", rwtm->serial_number); 418 + 419 + sprintf(desc, "Turris MOX SN %s rWTM ECDSA key", sn); 420 + 421 + mox_ecc_public_key_to_bin(rwtm->pubkey, ret, reply->status); 422 + 423 + ret = devm_turris_signing_key_create(dev, 424 + &mox_signing_key_subtype, 425 + desc); 426 + if (ret) 427 + return dev_err_probe(dev, ret, 428 + "Cannot create signing key\n"); 429 + } 430 + 431 + return 0; 385 432 } 386 433 387 - static void rwtm_register_debugfs(struct mox_rwtm *rwtm) 434 + #else /* CONFIG_TURRIS_MOX_RWTM_KEYCTL */ 435 + 436 + static inline int mox_register_signing_key(struct mox_rwtm *rwtm) 388 437 { 389 - struct dentry *root; 390 - 391 - root = debugfs_create_dir("turris-mox-rwtm", NULL); 392 - 393 - debugfs_create_file_unsafe("do_sign", 0600, root, rwtm, &do_sign_fops); 394 - 395 - devm_add_action_or_reset(rwtm_dev(rwtm), rwtm_debugfs_release, root); 438 + return 0; 396 439 } 397 - #else 398 - static inline void rwtm_register_debugfs(struct mox_rwtm *rwtm) 399 - { 400 - } 401 - #endif 440 + 441 + #endif /* !CONFIG_TURRIS_MOX_RWTM_KEYCTL */ 402 442 403 443 static void rwtm_devm_mbox_release(void *mbox) 404 444 { ··· 461 477 if (ret < 0) 462 478 dev_warn(dev, "Cannot read board information: %i\n", ret); 463 479 480 + ret = mox_register_signing_key(rwtm); 481 + if (ret < 0) 482 + return ret; 483 + 464 484 ret = check_get_random_support(rwtm); 465 485 if (ret < 0) { 466 486 dev_notice(dev, ··· 478 490 ret = devm_hwrng_register(dev, &rwtm->hwrng); 479 491 if (ret) 480 492 return dev_err_probe(dev, ret, "Cannot register HWRNG!\n"); 481 - 482 - rwtm_register_debugfs(rwtm); 483 493 484 494 dev_info(dev, "HWRNG successfully registered\n"); 485 495
+20 -3
drivers/memory/Kconfig
··· 32 32 33 33 config ATMEL_EBI 34 34 bool "Atmel EBI driver" 35 - default y if ARCH_AT91 35 + default ARCH_AT91 36 36 depends on ARCH_AT91 || COMPILE_TEST 37 37 depends on OF 38 38 select MFD_SYSCON ··· 147 147 148 148 config MVEBU_DEVBUS 149 149 bool "Marvell EBU Device Bus Controller" 150 - default y if PLAT_ORION 150 + default PLAT_ORION 151 151 depends on PLAT_ORION || COMPILE_TEST 152 152 depends on OF 153 153 help ··· 198 198 199 199 config PL353_SMC 200 200 tristate "ARM PL35X Static Memory Controller(SMC) driver" 201 - default y if ARM 201 + default ARM 202 202 depends on ARM || COMPILE_TEST 203 203 depends on ARM_AMBA 204 204 help ··· 224 224 controller. This driver configures the transactions with external 225 225 devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on 226 226 SOCs containing the FMC2 External Bus Interface. 227 + 228 + config STM32_OMM 229 + tristate "STM32 Octo Memory Manager" 230 + depends on SPI_STM32_OSPI || COMPILE_TEST 231 + help 232 + This driver manages the muxing between the 2 OSPI busses and 233 + the 2 output ports. There are 4 possible muxing configurations: 234 + - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2 235 + output is on port 2 236 + - OSPI1 and OSPI2 are multiplexed over the same output port 1 237 + - swapped mode (no multiplexing), OSPI1 output is on port 2, 238 + OSPI2 output is on port 1 239 + - OSPI1 and OSPI2 are multiplexed over the same output port 2 240 + It also manages : 241 + - the split of the memory area shared between the 2 OSPI instances. 242 + - chip select selection override. 243 + - the time between 2 transactions in multiplexed mode. 227 244 228 245 source "drivers/memory/samsung/Kconfig" 229 246 source "drivers/memory/tegra/Kconfig"
+1
drivers/memory/Makefile
··· 24 24 obj-$(CONFIG_PL353_SMC) += pl353-smc.o 25 25 obj-$(CONFIG_RENESAS_RPCIF) += renesas-rpc-if.o 26 26 obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o 27 + obj-$(CONFIG_STM32_OMM) += stm32_omm.o 27 28 28 29 obj-$(CONFIG_SAMSUNG_MC) += samsung/ 29 30 obj-$(CONFIG_TEGRA_MC) += tegra/
+1 -1
drivers/memory/bt1-l2-ctl.c
··· 222 222 if (ret) 223 223 return ret; 224 224 225 - return scnprintf(buf, PAGE_SIZE, "%u\n", data); 225 + return sysfs_emit(buf, "%u\n", data); 226 226 } 227 227 228 228 static ssize_t l2_ctl_latency_store(struct device *dev,
+52
drivers/memory/mtk-smi.c
··· 283 283 return 0; 284 284 } 285 285 286 + static const u8 mtk_smi_larb_mt6893_ostd[][SMI_LARB_PORT_NR_MAX] = { 287 + [0] = {0x2, 0x6, 0x2, 0x2, 0x2, 0x28, 0x18, 0x18, 0x1, 0x1, 0x1, 0x8, 288 + 0x8, 0x1, 0x3f}, 289 + [1] = {0x2, 0x6, 0x2, 0x2, 0x2, 0x28, 0x18, 0x18, 0x1, 0x1, 0x1, 0x8, 290 + 0x8, 0x1, 0x3f}, 291 + [2] = {0x5, 0x5, 0x5, 0x5, 0x1, 0x3f}, 292 + [3] = {0x5, 0x5, 0x5, 0x5, 0x1, 0x3f}, 293 + [4] = {0x28, 0x19, 0xb, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1}, 294 + [5] = {0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x16}, 295 + [6] = {}, 296 + [7] = {0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x1, 297 + 0x4, 0x1, 0xa, 0x6, 0x1, 0xa, 0x6, 0x1, 0x1, 0x1, 0x1, 0x5, 298 + 0x3, 0x3, 0x4}, 299 + [8] = {0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x1, 300 + 0x4, 0x1, 0xa, 0x6, 0x1, 0xa, 0x6, 0x1, 0x1, 0x1, 0x1, 0x5, 301 + 0x3, 0x3, 0x4}, 302 + [9] = {0x9, 0x7, 0xf, 0x8, 0x1, 0x8, 0x9, 0x3, 0x3, 0x6, 0x7, 0x4, 303 + 0x9, 0x3, 0x4, 0xe, 0x1, 0x7, 0x8, 0x7, 0x7, 0x1, 0x6, 0x2, 304 + 0xf, 0x8, 0x1, 0x1, 0x1}, 305 + [10] = {}, 306 + [11] = {0x9, 0x7, 0xf, 0x8, 0x1, 0x8, 0x9, 0x3, 0x3, 0x6, 0x7, 0x4, 307 + 0x9, 0x3, 0x4, 0xe, 0x1, 0x7, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 308 + 0x1, 0x1, 0x1, 0x1, 0x1}, 309 + [12] = {}, 310 + [13] = {0x2, 0xc, 0xc, 0xe, 0x6, 0x6, 0x6, 0x6, 0x6, 0x12, 0x6, 0x1}, 311 + [14] = {0x2, 0xc, 0xc, 0x28, 0x12, 0x6}, 312 + [15] = {0x28, 0x1, 0x2, 0x28, 0x1}, 313 + [16] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x2, 0x14, 0x14, 0x4, 0x4, 0x4, 0x2, 314 + 0x4, 0x2, 0x8, 0x4, 0x4}, 315 + [17] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x2, 0x14, 0x14, 0x4, 0x4, 0x4, 0x2, 316 + 0x4, 0x2, 0x8, 0x4, 0x4}, 317 + [18] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x2, 0x14, 0x14, 0x4, 0x4, 0x4, 0x2, 318 + 0x4, 0x2, 0x8, 0x4, 0x4}, 319 + [19] = {0x2, 0x2, 0x4, 0x2}, 320 + [20] = {0x9, 0x9, 0x5, 0x5, 0x1, 0x1}, 321 + }; 322 + 286 323 static const u8 mtk_smi_larb_mt8188_ostd[][SMI_LARB_PORT_NR_MAX] = { 287 324 [0] = {0x02, 0x18, 0x22, 0x22, 0x01, 0x02, 0x0a,}, 288 325 [1] = {0x12, 0x02, 0x14, 0x14, 0x01, 0x18, 0x0a,}, ··· 466 429 /* DUMMY | IPU0 | IPU1 | CCU | MDLA */ 467 430 }; 468 431 432 + static const struct mtk_smi_larb_gen mtk_smi_larb_mt6893 = { 433 + .config_port = mtk_smi_larb_config_port_gen2_general, 434 + .flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG, 435 + .ostd = mtk_smi_larb_mt6893_ostd, 436 + }; 437 + 469 438 static const struct mtk_smi_larb_gen mtk_smi_larb_mt8167 = { 470 439 /* mt8167 do not need the port in larb */ 471 440 .config_port = mtk_smi_larb_config_port_mt8167, ··· 517 474 {.compatible = "mediatek,mt2712-smi-larb", .data = &mtk_smi_larb_mt2712}, 518 475 {.compatible = "mediatek,mt6779-smi-larb", .data = &mtk_smi_larb_mt6779}, 519 476 {.compatible = "mediatek,mt6795-smi-larb", .data = &mtk_smi_larb_mt8173}, 477 + {.compatible = "mediatek,mt6893-smi-larb", .data = &mtk_smi_larb_mt6893}, 520 478 {.compatible = "mediatek,mt8167-smi-larb", .data = &mtk_smi_larb_mt8167}, 521 479 {.compatible = "mediatek,mt8173-smi-larb", .data = &mtk_smi_larb_mt8173}, 522 480 {.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183}, ··· 738 694 .init = mtk_smi_common_mt6795_init, 739 695 }; 740 696 697 + static const struct mtk_smi_common_plat mtk_smi_common_mt6893 = { 698 + .type = MTK_SMI_GEN2, 699 + .has_gals = true, 700 + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(4) | 701 + F_MMU1_LARB(5) | F_MMU1_LARB(7), 702 + }; 703 + 741 704 static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = { 742 705 .type = MTK_SMI_GEN2, 743 706 .has_gals = true, ··· 807 756 {.compatible = "mediatek,mt2712-smi-common", .data = &mtk_smi_common_gen2}, 808 757 {.compatible = "mediatek,mt6779-smi-common", .data = &mtk_smi_common_mt6779}, 809 758 {.compatible = "mediatek,mt6795-smi-common", .data = &mtk_smi_common_mt6795}, 759 + {.compatible = "mediatek,mt6893-smi-common", .data = &mtk_smi_common_mt6893}, 810 760 {.compatible = "mediatek,mt8167-smi-common", .data = &mtk_smi_common_gen2}, 811 761 {.compatible = "mediatek,mt8173-smi-common", .data = &mtk_smi_common_gen2}, 812 762 {.compatible = "mediatek,mt8183-smi-common", .data = &mtk_smi_common_mt8183},
+1 -14
drivers/memory/omap-gpmc.c
··· 2374 2374 2375 2375 static int gpmc_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) 2376 2376 { 2377 - return 1; /* we're input only */ 2377 + return GPIO_LINE_DIRECTION_IN; /* we're input only */ 2378 2378 } 2379 2379 2380 2380 static int gpmc_gpio_direction_input(struct gpio_chip *chip, 2381 2381 unsigned int offset) 2382 2382 { 2383 2383 return 0; /* we're input only */ 2384 - } 2385 - 2386 - static int gpmc_gpio_direction_output(struct gpio_chip *chip, 2387 - unsigned int offset, int value) 2388 - { 2389 - return -EINVAL; /* we're input only */ 2390 - } 2391 - 2392 - static void gpmc_gpio_set(struct gpio_chip *chip, unsigned int offset, 2393 - int value) 2394 - { 2395 2384 } 2396 2385 2397 2386 static int gpmc_gpio_get(struct gpio_chip *chip, unsigned int offset) ··· 2404 2415 gpmc->gpio_chip.ngpio = gpmc_nr_waitpins; 2405 2416 gpmc->gpio_chip.get_direction = gpmc_gpio_get_direction; 2406 2417 gpmc->gpio_chip.direction_input = gpmc_gpio_direction_input; 2407 - gpmc->gpio_chip.direction_output = gpmc_gpio_direction_output; 2408 - gpmc->gpio_chip.set = gpmc_gpio_set; 2409 2418 gpmc->gpio_chip.get = gpmc_gpio_get; 2410 2419 gpmc->gpio_chip.base = -1; 2411 2420
+479
drivers/memory/stm32_omm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) STMicroelectronics 2025 - All Rights Reserved 4 + * Author(s): Patrice Chotard <patrice.chotard@foss.st.com> for STMicroelectronics. 5 + */ 6 + 7 + #include <linux/bitfield.h> 8 + #include <linux/bus/stm32_firewall_device.h> 9 + #include <linux/clk.h> 10 + #include <linux/err.h> 11 + #include <linux/mfd/syscon.h> 12 + #include <linux/mod_devicetable.h> 13 + #include <linux/module.h> 14 + #include <linux/of_address.h> 15 + #include <linux/of_platform.h> 16 + #include <linux/pinctrl/consumer.h> 17 + #include <linux/pm_runtime.h> 18 + #include <linux/regmap.h> 19 + #include <linux/reset.h> 20 + 21 + #define OMM_CR 0 22 + #define CR_MUXEN BIT(0) 23 + #define CR_MUXENMODE_MASK GENMASK(1, 0) 24 + #define CR_CSSEL_OVR_EN BIT(4) 25 + #define CR_CSSEL_OVR_MASK GENMASK(6, 5) 26 + #define CR_REQ2ACK_MASK GENMASK(23, 16) 27 + 28 + #define OMM_CHILD_NB 2 29 + #define OMM_CLK_NB 3 30 + 31 + struct stm32_omm { 32 + struct resource *mm_res; 33 + struct clk_bulk_data clk_bulk[OMM_CLK_NB]; 34 + struct reset_control *child_reset[OMM_CHILD_NB]; 35 + void __iomem *io_base; 36 + u32 cr; 37 + u8 nb_child; 38 + bool restore_omm; 39 + }; 40 + 41 + static int stm32_omm_set_amcr(struct device *dev, bool set) 42 + { 43 + struct stm32_omm *omm = dev_get_drvdata(dev); 44 + resource_size_t mm_ospi2_size = 0; 45 + static const char * const mm_name[] = { "ospi1", "ospi2" }; 46 + struct regmap *syscfg_regmap; 47 + struct device_node *node; 48 + struct resource res, res1; 49 + u32 amcr_base, amcr_mask; 50 + int ret, idx; 51 + unsigned int i, amcr, read_amcr; 52 + 53 + for (i = 0; i < omm->nb_child; i++) { 54 + idx = of_property_match_string(dev->of_node, 55 + "memory-region-names", 56 + mm_name[i]); 57 + if (idx < 0) 58 + continue; 59 + 60 + /* res1 only used on second loop iteration */ 61 + res1.start = res.start; 62 + res1.end = res.end; 63 + 64 + node = of_parse_phandle(dev->of_node, "memory-region", idx); 65 + if (!node) 66 + continue; 67 + 68 + ret = of_address_to_resource(node, 0, &res); 69 + if (ret) { 70 + of_node_put(node); 71 + dev_err(dev, "unable to resolve memory region\n"); 72 + return ret; 73 + } 74 + 75 + /* check that memory region fits inside OMM memory map area */ 76 + if (!resource_contains(omm->mm_res, &res)) { 77 + dev_err(dev, "%s doesn't fit inside OMM memory map area\n", 78 + mm_name[i]); 79 + dev_err(dev, "%pR doesn't fit inside %pR\n", &res, omm->mm_res); 80 + of_node_put(node); 81 + 82 + return -EFAULT; 83 + } 84 + 85 + if (i == 1) { 86 + mm_ospi2_size = resource_size(&res); 87 + 88 + /* check that OMM memory region 1 doesn't overlap memory region 2 */ 89 + if (resource_overlaps(&res, &res1)) { 90 + dev_err(dev, "OMM memory-region %s overlaps memory region %s\n", 91 + mm_name[0], mm_name[1]); 92 + dev_err(dev, "%pR overlaps %pR\n", &res1, &res); 93 + of_node_put(node); 94 + 95 + return -EFAULT; 96 + } 97 + } 98 + of_node_put(node); 99 + } 100 + 101 + syscfg_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "st,syscfg-amcr"); 102 + if (IS_ERR(syscfg_regmap)) 103 + return dev_err_probe(dev, PTR_ERR(syscfg_regmap), 104 + "Failed to get st,syscfg-amcr property\n"); 105 + 106 + ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 1, 107 + &amcr_base); 108 + if (ret) 109 + return ret; 110 + 111 + ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 2, 112 + &amcr_mask); 113 + if (ret) 114 + return ret; 115 + 116 + amcr = mm_ospi2_size / SZ_64M; 117 + 118 + if (set) 119 + regmap_update_bits(syscfg_regmap, amcr_base, amcr_mask, amcr); 120 + 121 + /* read AMCR and check coherency with memory-map areas defined in DT */ 122 + regmap_read(syscfg_regmap, amcr_base, &read_amcr); 123 + read_amcr = read_amcr >> (ffs(amcr_mask) - 1); 124 + 125 + if (amcr != read_amcr) { 126 + dev_err(dev, "AMCR value not coherent with DT memory-map areas\n"); 127 + ret = -EINVAL; 128 + } 129 + 130 + return ret; 131 + } 132 + 133 + static int stm32_omm_toggle_child_clock(struct device *dev, bool enable) 134 + { 135 + struct stm32_omm *omm = dev_get_drvdata(dev); 136 + int i, ret; 137 + 138 + for (i = 0; i < omm->nb_child; i++) { 139 + if (enable) { 140 + ret = clk_prepare_enable(omm->clk_bulk[i + 1].clk); 141 + if (ret) { 142 + dev_err(dev, "Can not enable clock\n"); 143 + goto clk_error; 144 + } 145 + } else { 146 + clk_disable_unprepare(omm->clk_bulk[i + 1].clk); 147 + } 148 + } 149 + 150 + return 0; 151 + 152 + clk_error: 153 + while (i--) 154 + clk_disable_unprepare(omm->clk_bulk[i + 1].clk); 155 + 156 + return ret; 157 + } 158 + 159 + static int stm32_omm_disable_child(struct device *dev) 160 + { 161 + struct stm32_omm *omm = dev_get_drvdata(dev); 162 + struct reset_control *reset; 163 + int ret; 164 + u8 i; 165 + 166 + ret = stm32_omm_toggle_child_clock(dev, true); 167 + if (ret) 168 + return ret; 169 + 170 + for (i = 0; i < omm->nb_child; i++) { 171 + /* reset OSPI to ensure CR_EN bit is set to 0 */ 172 + reset = omm->child_reset[i]; 173 + ret = reset_control_acquire(reset); 174 + if (ret) { 175 + stm32_omm_toggle_child_clock(dev, false); 176 + dev_err(dev, "Can not acquire reset %d\n", ret); 177 + return ret; 178 + } 179 + 180 + reset_control_assert(reset); 181 + udelay(2); 182 + reset_control_deassert(reset); 183 + 184 + reset_control_release(reset); 185 + } 186 + 187 + return stm32_omm_toggle_child_clock(dev, false); 188 + } 189 + 190 + static int stm32_omm_configure(struct device *dev) 191 + { 192 + static const char * const clocks_name[] = {"omm", "ospi1", "ospi2"}; 193 + struct stm32_omm *omm = dev_get_drvdata(dev); 194 + unsigned long clk_rate_max = 0; 195 + u32 mux = 0; 196 + u32 cssel_ovr = 0; 197 + u32 req2ack = 0; 198 + struct reset_control *rstc; 199 + unsigned long clk_rate; 200 + int ret; 201 + u8 i; 202 + 203 + for (i = 0; i < OMM_CLK_NB; i++) 204 + omm->clk_bulk[i].id = clocks_name[i]; 205 + 206 + /* retrieve OMM, OSPI1 and OSPI2 clocks */ 207 + ret = devm_clk_bulk_get(dev, OMM_CLK_NB, omm->clk_bulk); 208 + if (ret) 209 + return dev_err_probe(dev, ret, "Failed to get OMM/OSPI's clocks\n"); 210 + 211 + /* Ensure both OSPI instance are disabled before configuring OMM */ 212 + ret = stm32_omm_disable_child(dev); 213 + if (ret) 214 + return ret; 215 + 216 + ret = pm_runtime_resume_and_get(dev); 217 + if (ret < 0) 218 + return ret; 219 + 220 + /* parse children's clock */ 221 + for (i = 1; i <= omm->nb_child; i++) { 222 + clk_rate = clk_get_rate(omm->clk_bulk[i].clk); 223 + if (!clk_rate) { 224 + dev_err(dev, "Invalid clock rate\n"); 225 + ret = -EINVAL; 226 + goto error; 227 + } 228 + 229 + if (clk_rate > clk_rate_max) 230 + clk_rate_max = clk_rate; 231 + } 232 + 233 + rstc = devm_reset_control_get_exclusive(dev, "omm"); 234 + if (IS_ERR(rstc)) { 235 + ret = dev_err_probe(dev, PTR_ERR(rstc), "reset get failed\n"); 236 + goto error; 237 + } 238 + 239 + reset_control_assert(rstc); 240 + udelay(2); 241 + reset_control_deassert(rstc); 242 + 243 + omm->cr = readl_relaxed(omm->io_base + OMM_CR); 244 + /* optional */ 245 + ret = of_property_read_u32(dev->of_node, "st,omm-mux", &mux); 246 + if (!ret) { 247 + if (mux & CR_MUXEN) { 248 + ret = of_property_read_u32(dev->of_node, "st,omm-req2ack-ns", 249 + &req2ack); 250 + if (!ret && !req2ack) { 251 + req2ack = DIV_ROUND_UP(req2ack, NSEC_PER_SEC / clk_rate_max) - 1; 252 + 253 + if (req2ack > 256) 254 + req2ack = 256; 255 + } 256 + 257 + req2ack = FIELD_PREP(CR_REQ2ACK_MASK, req2ack); 258 + 259 + omm->cr &= ~CR_REQ2ACK_MASK; 260 + omm->cr |= FIELD_PREP(CR_REQ2ACK_MASK, req2ack); 261 + 262 + /* 263 + * If the mux is enabled, the 2 OSPI clocks have to be 264 + * always enabled 265 + */ 266 + ret = stm32_omm_toggle_child_clock(dev, true); 267 + if (ret) 268 + goto error; 269 + } 270 + 271 + omm->cr &= ~CR_MUXENMODE_MASK; 272 + omm->cr |= FIELD_PREP(CR_MUXENMODE_MASK, mux); 273 + } 274 + 275 + /* optional */ 276 + ret = of_property_read_u32(dev->of_node, "st,omm-cssel-ovr", &cssel_ovr); 277 + if (!ret) { 278 + omm->cr &= ~CR_CSSEL_OVR_MASK; 279 + omm->cr |= FIELD_PREP(CR_CSSEL_OVR_MASK, cssel_ovr); 280 + omm->cr |= CR_CSSEL_OVR_EN; 281 + } 282 + 283 + omm->restore_omm = true; 284 + writel_relaxed(omm->cr, omm->io_base + OMM_CR); 285 + 286 + ret = stm32_omm_set_amcr(dev, true); 287 + 288 + error: 289 + pm_runtime_put_sync_suspend(dev); 290 + 291 + return ret; 292 + } 293 + 294 + static int stm32_omm_check_access(struct device_node *np) 295 + { 296 + struct stm32_firewall firewall; 297 + int ret; 298 + 299 + ret = stm32_firewall_get_firewall(np, &firewall, 1); 300 + if (ret) 301 + return ret; 302 + 303 + return stm32_firewall_grant_access(&firewall); 304 + } 305 + 306 + static int stm32_omm_probe(struct platform_device *pdev) 307 + { 308 + static const char * const resets_name[] = {"ospi1", "ospi2"}; 309 + struct device *dev = &pdev->dev; 310 + u8 child_access_granted = 0; 311 + struct stm32_omm *omm; 312 + int i, ret; 313 + 314 + omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL); 315 + if (!omm) 316 + return -ENOMEM; 317 + 318 + omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs"); 319 + if (IS_ERR(omm->io_base)) 320 + return PTR_ERR(omm->io_base); 321 + 322 + omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map"); 323 + if (!omm->mm_res) 324 + return -ENODEV; 325 + 326 + /* check child's access */ 327 + for_each_child_of_node_scoped(dev->of_node, child) { 328 + if (omm->nb_child >= OMM_CHILD_NB) { 329 + dev_err(dev, "Bad DT, found too much children\n"); 330 + return -E2BIG; 331 + } 332 + 333 + ret = stm32_omm_check_access(child); 334 + if (ret < 0 && ret != -EACCES) 335 + return ret; 336 + 337 + if (!ret) 338 + child_access_granted++; 339 + 340 + omm->nb_child++; 341 + } 342 + 343 + if (omm->nb_child != OMM_CHILD_NB) 344 + return -EINVAL; 345 + 346 + platform_set_drvdata(pdev, omm); 347 + 348 + devm_pm_runtime_enable(dev); 349 + 350 + /* check if OMM's resource access is granted */ 351 + ret = stm32_omm_check_access(dev->of_node); 352 + if (ret < 0 && ret != -EACCES) 353 + return ret; 354 + 355 + for (i = 0; i < omm->nb_child; i++) { 356 + omm->child_reset[i] = devm_reset_control_get_exclusive_released(dev, 357 + resets_name[i]); 358 + 359 + if (IS_ERR(omm->child_reset[i])) 360 + return dev_err_probe(dev, PTR_ERR(omm->child_reset[i]), 361 + "Can't get %s reset\n", resets_name[i]); 362 + } 363 + 364 + if (!ret && child_access_granted == OMM_CHILD_NB) { 365 + ret = stm32_omm_configure(dev); 366 + if (ret) 367 + return ret; 368 + } else { 369 + dev_dbg(dev, "Octo Memory Manager resource's access not granted\n"); 370 + /* 371 + * AMCR can't be set, so check if current value is coherent 372 + * with memory-map areas defined in DT 373 + */ 374 + ret = stm32_omm_set_amcr(dev, false); 375 + if (ret) 376 + return ret; 377 + } 378 + 379 + ret = devm_of_platform_populate(dev); 380 + if (ret) { 381 + if (omm->cr & CR_MUXEN) 382 + stm32_omm_toggle_child_clock(&pdev->dev, false); 383 + 384 + return dev_err_probe(dev, ret, "Failed to create Octo Memory Manager child\n"); 385 + } 386 + 387 + return 0; 388 + } 389 + 390 + static void stm32_omm_remove(struct platform_device *pdev) 391 + { 392 + struct stm32_omm *omm = platform_get_drvdata(pdev); 393 + 394 + if (omm->cr & CR_MUXEN) 395 + stm32_omm_toggle_child_clock(&pdev->dev, false); 396 + } 397 + 398 + static const struct of_device_id stm32_omm_of_match[] = { 399 + { .compatible = "st,stm32mp25-omm", }, 400 + {} 401 + }; 402 + MODULE_DEVICE_TABLE(of, stm32_omm_of_match); 403 + 404 + static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev) 405 + { 406 + struct stm32_omm *omm = dev_get_drvdata(dev); 407 + 408 + clk_disable_unprepare(omm->clk_bulk[0].clk); 409 + 410 + return 0; 411 + } 412 + 413 + static int __maybe_unused stm32_omm_runtime_resume(struct device *dev) 414 + { 415 + struct stm32_omm *omm = dev_get_drvdata(dev); 416 + 417 + return clk_prepare_enable(omm->clk_bulk[0].clk); 418 + } 419 + 420 + static int __maybe_unused stm32_omm_suspend(struct device *dev) 421 + { 422 + struct stm32_omm *omm = dev_get_drvdata(dev); 423 + 424 + if (omm->restore_omm && omm->cr & CR_MUXEN) 425 + stm32_omm_toggle_child_clock(dev, false); 426 + 427 + return pinctrl_pm_select_sleep_state(dev); 428 + } 429 + 430 + static int __maybe_unused stm32_omm_resume(struct device *dev) 431 + { 432 + struct stm32_omm *omm = dev_get_drvdata(dev); 433 + int ret; 434 + 435 + pinctrl_pm_select_default_state(dev); 436 + 437 + if (!omm->restore_omm) 438 + return 0; 439 + 440 + /* Ensure both OSPI instance are disabled before configuring OMM */ 441 + ret = stm32_omm_disable_child(dev); 442 + if (ret) 443 + return ret; 444 + 445 + ret = pm_runtime_resume_and_get(dev); 446 + if (ret < 0) 447 + return ret; 448 + 449 + writel_relaxed(omm->cr, omm->io_base + OMM_CR); 450 + ret = stm32_omm_set_amcr(dev, true); 451 + pm_runtime_put_sync_suspend(dev); 452 + if (ret) 453 + return ret; 454 + 455 + if (omm->cr & CR_MUXEN) 456 + ret = stm32_omm_toggle_child_clock(dev, true); 457 + 458 + return ret; 459 + } 460 + 461 + static const struct dev_pm_ops stm32_omm_pm_ops = { 462 + SET_RUNTIME_PM_OPS(stm32_omm_runtime_suspend, 463 + stm32_omm_runtime_resume, NULL) 464 + SET_SYSTEM_SLEEP_PM_OPS(stm32_omm_suspend, stm32_omm_resume) 465 + }; 466 + 467 + static struct platform_driver stm32_omm_driver = { 468 + .probe = stm32_omm_probe, 469 + .remove = stm32_omm_remove, 470 + .driver = { 471 + .name = "stm32-omm", 472 + .of_match_table = stm32_omm_of_match, 473 + .pm = &stm32_omm_pm_ops, 474 + }, 475 + }; 476 + module_platform_driver(stm32_omm_driver); 477 + 478 + MODULE_DESCRIPTION("STMicroelectronics Octo Memory Manager driver"); 479 + MODULE_LICENSE("GPL");
+4 -4
drivers/memory/tegra/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config TEGRA_MC 3 3 bool "NVIDIA Tegra Memory Controller support" 4 - default y 4 + default ARCH_TEGRA 5 5 depends on ARCH_TEGRA || (COMPILE_TEST && COMMON_CLK) 6 6 select INTERCONNECT 7 7 help ··· 12 12 13 13 config TEGRA20_EMC 14 14 tristate "NVIDIA Tegra20 External Memory Controller driver" 15 - default y 15 + default ARCH_TEGRA_2x_SOC 16 16 depends on ARCH_TEGRA_2x_SOC || COMPILE_TEST 17 17 select DEVFREQ_GOV_SIMPLE_ONDEMAND 18 18 select PM_DEVFREQ ··· 25 25 26 26 config TEGRA30_EMC 27 27 tristate "NVIDIA Tegra30 External Memory Controller driver" 28 - default y 28 + default ARCH_TEGRA_3x_SOC 29 29 depends on ARCH_TEGRA_3x_SOC || COMPILE_TEST 30 30 select PM_OPP 31 31 select DDR ··· 37 37 38 38 config TEGRA124_EMC 39 39 tristate "NVIDIA Tegra124 External Memory Controller driver" 40 - default y 40 + default ARCH_TEGRA_124_SOC 41 41 depends on ARCH_TEGRA_124_SOC || COMPILE_TEST 42 42 select TEGRA124_CLK_EMC if ARCH_TEGRA 43 43 select PM_OPP
+17
drivers/platform/cznic/Kconfig
··· 76 76 Say Y here to add support for the true random number generator 77 77 provided by CZ.NIC's Turris Omnia MCU. 78 78 79 + config TURRIS_OMNIA_MCU_KEYCTL 80 + bool "Turris Omnia MCU ECDSA message signing" 81 + default y 82 + depends on KEYS 83 + depends on ASYMMETRIC_KEY_TYPE 84 + depends on TURRIS_OMNIA_MCU_GPIO 85 + select TURRIS_SIGNING_KEY 86 + help 87 + Say Y here to add support for ECDSA message signing with board private 88 + key (if available on the MCU). This is exposed via the keyctl() 89 + syscall. 90 + 79 91 endif # TURRIS_OMNIA_MCU 92 + 93 + config TURRIS_SIGNING_KEY 94 + tristate 95 + depends on KEYS 96 + depends on ASYMMETRIC_KEY_TYPE 80 97 81 98 endif # CZNIC_PLATFORMS
+3
drivers/platform/cznic/Makefile
··· 3 3 obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o 4 4 turris-omnia-mcu-y := turris-omnia-mcu-base.o 5 5 turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_GPIO) += turris-omnia-mcu-gpio.o 6 + turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_KEYCTL) += turris-omnia-mcu-keyctl.o 6 7 turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP) += turris-omnia-mcu-sys-off-wakeup.o 7 8 turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_TRNG) += turris-omnia-mcu-trng.o 8 9 turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_WATCHDOG) += turris-omnia-mcu-watchdog.o 10 + 11 + obj-$(CONFIG_TURRIS_SIGNING_KEY) += turris-signing-key.o
+4
drivers/platform/cznic/turris-omnia-mcu-base.c
··· 392 392 if (err) 393 393 return err; 394 394 395 + err = omnia_mcu_register_keyctl(mcu); 396 + if (err) 397 + return err; 398 + 395 399 return omnia_mcu_register_trng(mcu); 396 400 } 397 401
+20 -1
drivers/platform/cznic/turris-omnia-mcu-gpio.c
··· 13 13 #include <linux/device.h> 14 14 #include <linux/devm-helpers.h> 15 15 #include <linux/errno.h> 16 + #include <linux/gpio/consumer.h> 16 17 #include <linux/gpio/driver.h> 17 18 #include <linux/i2c.h> 18 19 #include <linux/interrupt.h> ··· 196 195 }; 197 196 198 197 /* mapping from interrupts to indexes of GPIOs in the omnia_gpios array */ 199 - const u8 omnia_int_to_gpio_idx[32] = { 198 + static const u8 omnia_int_to_gpio_idx[32] = { 200 199 [__bf_shf(OMNIA_INT_CARD_DET)] = 4, 201 200 [__bf_shf(OMNIA_INT_MSATA_IND)] = 5, 202 201 [__bf_shf(OMNIA_INT_USB30_OVC)] = 6, ··· 1093 1092 } 1094 1093 1095 1094 return 0; 1095 + } 1096 + 1097 + int omnia_mcu_request_irq(struct omnia_mcu *mcu, u32 spec, 1098 + irq_handler_t thread_fn, const char *devname) 1099 + { 1100 + u8 irq_idx; 1101 + int irq; 1102 + 1103 + if (!spec) 1104 + return -EINVAL; 1105 + 1106 + irq_idx = omnia_int_to_gpio_idx[ffs(spec) - 1]; 1107 + irq = gpiod_to_irq(gpio_device_get_desc(mcu->gc.gpiodev, irq_idx)); 1108 + if (irq < 0) 1109 + return irq; 1110 + 1111 + return devm_request_threaded_irq(&mcu->client->dev, irq, NULL, 1112 + thread_fn, IRQF_ONESHOT, devname, mcu); 1096 1113 }
+162
drivers/platform/cznic/turris-omnia-mcu-keyctl.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * CZ.NIC's Turris Omnia MCU ECDSA message signing via keyctl 4 + * 5 + * 2025 by Marek Behún <kabel@kernel.org> 6 + */ 7 + 8 + #include <crypto/sha2.h> 9 + #include <linux/cleanup.h> 10 + #include <linux/completion.h> 11 + #include <linux/device.h> 12 + #include <linux/err.h> 13 + #include <linux/i2c.h> 14 + #include <linux/interrupt.h> 15 + #include <linux/key.h> 16 + #include <linux/mutex.h> 17 + #include <linux/string.h> 18 + #include <linux/types.h> 19 + 20 + #include <linux/turris-omnia-mcu-interface.h> 21 + #include <linux/turris-signing-key.h> 22 + #include "turris-omnia-mcu.h" 23 + 24 + static irqreturn_t omnia_msg_signed_irq_handler(int irq, void *dev_id) 25 + { 26 + u8 reply[1 + OMNIA_MCU_CRYPTO_SIGNATURE_LEN]; 27 + struct omnia_mcu *mcu = dev_id; 28 + int err; 29 + 30 + err = omnia_cmd_read(mcu->client, OMNIA_CMD_CRYPTO_COLLECT_SIGNATURE, 31 + reply, sizeof(reply)); 32 + if (!err && reply[0] != OMNIA_MCU_CRYPTO_SIGNATURE_LEN) 33 + err = -EIO; 34 + 35 + guard(mutex)(&mcu->sign_lock); 36 + 37 + if (mcu->sign_requested) { 38 + mcu->sign_err = err; 39 + if (!err) 40 + memcpy(mcu->signature, &reply[1], 41 + OMNIA_MCU_CRYPTO_SIGNATURE_LEN); 42 + mcu->sign_requested = false; 43 + complete(&mcu->msg_signed); 44 + } 45 + 46 + return IRQ_HANDLED; 47 + } 48 + 49 + static int omnia_mcu_sign(const struct key *key, const void *msg, 50 + void *signature) 51 + { 52 + struct omnia_mcu *mcu = dev_get_drvdata(turris_signing_key_get_dev(key)); 53 + u8 cmd[1 + SHA256_DIGEST_SIZE], reply; 54 + int err; 55 + 56 + scoped_guard(mutex, &mcu->sign_lock) { 57 + if (mcu->sign_requested) 58 + return -EBUSY; 59 + 60 + cmd[0] = OMNIA_CMD_CRYPTO_SIGN_MESSAGE; 61 + memcpy(&cmd[1], msg, SHA256_DIGEST_SIZE); 62 + 63 + err = omnia_cmd_write_read(mcu->client, cmd, sizeof(cmd), 64 + &reply, 1); 65 + if (err) 66 + return err; 67 + 68 + if (!reply) 69 + return -EBUSY; 70 + 71 + mcu->sign_requested = true; 72 + } 73 + 74 + if (wait_for_completion_interruptible(&mcu->msg_signed)) 75 + return -EINTR; 76 + 77 + guard(mutex)(&mcu->sign_lock); 78 + 79 + if (mcu->sign_err) 80 + return mcu->sign_err; 81 + 82 + memcpy(signature, mcu->signature, OMNIA_MCU_CRYPTO_SIGNATURE_LEN); 83 + 84 + /* forget the signature, for security */ 85 + memzero_explicit(mcu->signature, sizeof(mcu->signature)); 86 + 87 + return OMNIA_MCU_CRYPTO_SIGNATURE_LEN; 88 + } 89 + 90 + static const void *omnia_mcu_get_public_key(const struct key *key) 91 + { 92 + struct omnia_mcu *mcu = dev_get_drvdata(turris_signing_key_get_dev(key)); 93 + 94 + return mcu->board_public_key; 95 + } 96 + 97 + static const struct turris_signing_key_subtype omnia_signing_key_subtype = { 98 + .key_size = 256, 99 + .data_size = SHA256_DIGEST_SIZE, 100 + .sig_size = OMNIA_MCU_CRYPTO_SIGNATURE_LEN, 101 + .public_key_size = OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN, 102 + .hash_algo = "sha256", 103 + .get_public_key = omnia_mcu_get_public_key, 104 + .sign = omnia_mcu_sign, 105 + }; 106 + 107 + static int omnia_mcu_read_public_key(struct omnia_mcu *mcu) 108 + { 109 + u8 reply[1 + OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN]; 110 + int err; 111 + 112 + err = omnia_cmd_read(mcu->client, OMNIA_CMD_CRYPTO_GET_PUBLIC_KEY, 113 + reply, sizeof(reply)); 114 + if (err) 115 + return err; 116 + 117 + if (reply[0] != OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN) 118 + return -EIO; 119 + 120 + memcpy(mcu->board_public_key, &reply[1], 121 + OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN); 122 + 123 + return 0; 124 + } 125 + 126 + int omnia_mcu_register_keyctl(struct omnia_mcu *mcu) 127 + { 128 + struct device *dev = &mcu->client->dev; 129 + char desc[48]; 130 + int err; 131 + 132 + if (!(mcu->features & OMNIA_FEAT_CRYPTO)) 133 + return 0; 134 + 135 + err = omnia_mcu_read_public_key(mcu); 136 + if (err) 137 + return dev_err_probe(dev, err, 138 + "Cannot read board public key\n"); 139 + 140 + err = devm_mutex_init(dev, &mcu->sign_lock); 141 + if (err) 142 + return err; 143 + 144 + init_completion(&mcu->msg_signed); 145 + 146 + err = omnia_mcu_request_irq(mcu, OMNIA_INT_MESSAGE_SIGNED, 147 + omnia_msg_signed_irq_handler, 148 + "turris-omnia-mcu-keyctl"); 149 + if (err) 150 + return dev_err_probe(dev, err, 151 + "Cannot request MESSAGE_SIGNED IRQ\n"); 152 + 153 + sprintf(desc, "Turris Omnia SN %016llX MCU ECDSA key", 154 + mcu->board_serial_number); 155 + 156 + err = devm_turris_signing_key_create(dev, &omnia_signing_key_subtype, 157 + desc); 158 + if (err) 159 + return dev_err_probe(dev, err, "Cannot create signing key\n"); 160 + 161 + return 0; 162 + }
+4 -13
drivers/platform/cznic/turris-omnia-mcu-trng.c
··· 5 5 * 2024 by Marek Behún <kabel@kernel.org> 6 6 */ 7 7 8 - #include <linux/bitfield.h> 9 8 #include <linux/completion.h> 10 9 #include <linux/container_of.h> 11 10 #include <linux/errno.h> 12 - #include <linux/gpio/consumer.h> 13 - #include <linux/gpio/driver.h> 14 11 #include <linux/hw_random.h> 15 12 #include <linux/i2c.h> 16 13 #include <linux/interrupt.h> ··· 59 62 int omnia_mcu_register_trng(struct omnia_mcu *mcu) 60 63 { 61 64 struct device *dev = &mcu->client->dev; 62 - u8 irq_idx, dummy; 63 - int irq, err; 65 + u8 dummy; 66 + int err; 64 67 65 68 if (!(mcu->features & OMNIA_FEAT_TRNG)) 66 69 return 0; 67 - 68 - irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)]; 69 - irq = gpiod_to_irq(gpio_device_get_desc(mcu->gc.gpiodev, irq_idx)); 70 - if (irq < 0) 71 - return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n"); 72 70 73 71 /* 74 72 * If someone else cleared the TRNG interrupt but did not read the ··· 78 86 79 87 init_completion(&mcu->trng_entropy_ready); 80 88 81 - err = devm_request_threaded_irq(dev, irq, NULL, omnia_trng_irq_handler, 82 - IRQF_ONESHOT, "turris-omnia-mcu-trng", 83 - mcu); 89 + err = omnia_mcu_request_irq(mcu, OMNIA_INT_TRNG, omnia_trng_irq_handler, 90 + "turris-omnia-mcu-trng"); 84 91 if (err) 85 92 return dev_err_probe(dev, err, "Cannot request TRNG IRQ\n"); 86 93
+32 -1
drivers/platform/cznic/turris-omnia-mcu.h
··· 12 12 #include <linux/gpio/driver.h> 13 13 #include <linux/hw_random.h> 14 14 #include <linux/if_ether.h> 15 + #include <linux/interrupt.h> 15 16 #include <linux/mutex.h> 16 17 #include <linux/types.h> 17 18 #include <linux/watchdog.h> 18 19 #include <linux/workqueue.h> 20 + 21 + enum { 22 + OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN = 1 + 32, 23 + OMNIA_MCU_CRYPTO_SIGNATURE_LEN = 64, 24 + }; 19 25 20 26 struct i2c_client; 21 27 struct rtc_device; ··· 61 55 * @wdt: watchdog driver structure 62 56 * @trng: RNG driver structure 63 57 * @trng_entropy_ready: RNG entropy ready completion 58 + * @msg_signed: message signed completion 59 + * @sign_lock: mutex to protect message signing state 60 + * @sign_requested: flag indicating that message signing was requested but not completed 61 + * @sign_err: message signing error number, filled in interrupt handler 62 + * @signature: message signing signature, filled in interrupt handler 63 + * @board_public_key: board public key, if stored in MCU 64 64 */ 65 65 struct omnia_mcu { 66 66 struct i2c_client *client; ··· 100 88 struct hwrng trng; 101 89 struct completion trng_entropy_ready; 102 90 #endif 91 + 92 + #ifdef CONFIG_TURRIS_OMNIA_MCU_KEYCTL 93 + struct completion msg_signed; 94 + struct mutex sign_lock; 95 + bool sign_requested; 96 + int sign_err; 97 + u8 signature[OMNIA_MCU_CRYPTO_SIGNATURE_LEN]; 98 + u8 board_public_key[OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN]; 99 + #endif 103 100 }; 104 101 105 102 #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO 106 - extern const u8 omnia_int_to_gpio_idx[32]; 107 103 extern const struct attribute_group omnia_mcu_gpio_group; 108 104 int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu); 105 + int omnia_mcu_request_irq(struct omnia_mcu *mcu, u32 spec, 106 + irq_handler_t thread_fn, const char *devname); 109 107 #else 110 108 static inline int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu) 109 + { 110 + return 0; 111 + } 112 + #endif 113 + 114 + #ifdef CONFIG_TURRIS_OMNIA_MCU_KEYCTL 115 + int omnia_mcu_register_keyctl(struct omnia_mcu *mcu); 116 + #else 117 + static inline int omnia_mcu_register_keyctl(struct omnia_mcu *mcu) 111 118 { 112 119 return 0; 113 120 }
+193
drivers/platform/cznic/turris-signing-key.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Some of CZ.NIC's Turris devices support signing messages with a per-device unique asymmetric 4 + * cryptographic key that was burned into the device at manufacture. 5 + * 6 + * This helper module exposes this message signing ability via the keyctl() syscall. Upon load, it 7 + * creates the `.turris-signing-keys` keyring. A device-specific driver then has to create a signing 8 + * key by calling devm_turris_signing_key_create(). 9 + * 10 + * 2025 by Marek Behún <kabel@kernel.org> 11 + */ 12 + 13 + #include <linux/device.h> 14 + #include <linux/err.h> 15 + #include <linux/key-type.h> 16 + #include <linux/key.h> 17 + #include <linux/keyctl.h> 18 + #include <linux/module.h> 19 + #include <linux/seq_file.h> 20 + #include <linux/string.h> 21 + #include <linux/types.h> 22 + 23 + #include <linux/turris-signing-key.h> 24 + 25 + static int turris_signing_key_instantiate(struct key *key, 26 + struct key_preparsed_payload *payload) 27 + { 28 + return 0; 29 + } 30 + 31 + static void turris_signing_key_describe(const struct key *key, struct seq_file *m) 32 + { 33 + const struct turris_signing_key_subtype *subtype = dereference_key_rcu(key); 34 + 35 + if (!subtype) 36 + return; 37 + 38 + seq_printf(m, "%s: %*phN", key->description, subtype->public_key_size, 39 + subtype->get_public_key(key)); 40 + } 41 + 42 + static long turris_signing_key_read(const struct key *key, char *buffer, size_t buflen) 43 + { 44 + const struct turris_signing_key_subtype *subtype = dereference_key_rcu(key); 45 + 46 + if (!subtype) 47 + return -EIO; 48 + 49 + if (buffer) { 50 + if (buflen > subtype->public_key_size) 51 + buflen = subtype->public_key_size; 52 + 53 + memcpy(buffer, subtype->get_public_key(key), subtype->public_key_size); 54 + } 55 + 56 + return subtype->public_key_size; 57 + } 58 + 59 + static bool turris_signing_key_asym_valid_params(const struct turris_signing_key_subtype *subtype, 60 + const struct kernel_pkey_params *params) 61 + { 62 + if (params->encoding && strcmp(params->encoding, "raw")) 63 + return false; 64 + 65 + if (params->hash_algo && strcmp(params->hash_algo, subtype->hash_algo)) 66 + return false; 67 + 68 + return true; 69 + } 70 + 71 + static int turris_signing_key_asym_query(const struct kernel_pkey_params *params, 72 + struct kernel_pkey_query *info) 73 + { 74 + const struct turris_signing_key_subtype *subtype = dereference_key_rcu(params->key); 75 + 76 + if (!subtype) 77 + return -EIO; 78 + 79 + if (!turris_signing_key_asym_valid_params(subtype, params)) 80 + return -EINVAL; 81 + 82 + info->supported_ops = KEYCTL_SUPPORTS_SIGN; 83 + info->key_size = subtype->key_size; 84 + info->max_data_size = subtype->data_size; 85 + info->max_sig_size = subtype->sig_size; 86 + info->max_enc_size = 0; 87 + info->max_dec_size = 0; 88 + 89 + return 0; 90 + } 91 + 92 + static int turris_signing_key_asym_eds_op(struct kernel_pkey_params *params, 93 + const void *in, void *out) 94 + { 95 + const struct turris_signing_key_subtype *subtype = dereference_key_rcu(params->key); 96 + int err; 97 + 98 + if (!subtype) 99 + return -EIO; 100 + 101 + if (!turris_signing_key_asym_valid_params(subtype, params)) 102 + return -EINVAL; 103 + 104 + if (params->op != kernel_pkey_sign) 105 + return -EOPNOTSUPP; 106 + 107 + if (params->in_len != subtype->data_size || params->out_len != subtype->sig_size) 108 + return -EINVAL; 109 + 110 + err = subtype->sign(params->key, in, out); 111 + if (err) 112 + return err; 113 + 114 + return subtype->sig_size; 115 + } 116 + 117 + static struct key_type turris_signing_key_type = { 118 + .name = "turris-signing-key", 119 + .instantiate = turris_signing_key_instantiate, 120 + .describe = turris_signing_key_describe, 121 + .read = turris_signing_key_read, 122 + .asym_query = turris_signing_key_asym_query, 123 + .asym_eds_op = turris_signing_key_asym_eds_op, 124 + }; 125 + 126 + static struct key *turris_signing_keyring; 127 + 128 + static void turris_signing_key_release(void *key) 129 + { 130 + key_unlink(turris_signing_keyring, key); 131 + key_put(key); 132 + } 133 + 134 + int 135 + devm_turris_signing_key_create(struct device *dev, const struct turris_signing_key_subtype *subtype, 136 + const char *desc) 137 + { 138 + struct key *key; 139 + key_ref_t kref; 140 + 141 + kref = key_create(make_key_ref(turris_signing_keyring, true), 142 + turris_signing_key_type.name, desc, NULL, 0, 143 + (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | 144 + KEY_USR_SEARCH, 145 + KEY_ALLOC_BUILT_IN | KEY_ALLOC_SET_KEEP | KEY_ALLOC_NOT_IN_QUOTA); 146 + if (IS_ERR(kref)) 147 + return PTR_ERR(kref); 148 + 149 + key = key_ref_to_ptr(kref); 150 + key->payload.data[1] = dev; 151 + rcu_assign_keypointer(key, subtype); 152 + 153 + return devm_add_action_or_reset(dev, turris_signing_key_release, key); 154 + } 155 + EXPORT_SYMBOL_GPL(devm_turris_signing_key_create); 156 + 157 + static int turris_signing_key_init(void) 158 + { 159 + int err; 160 + 161 + err = register_key_type(&turris_signing_key_type); 162 + if (err) 163 + return err; 164 + 165 + turris_signing_keyring = keyring_alloc(".turris-signing-keys", 166 + GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), 167 + (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | 168 + KEY_USR_READ | KEY_USR_SEARCH, 169 + KEY_ALLOC_BUILT_IN | KEY_ALLOC_SET_KEEP | 170 + KEY_ALLOC_NOT_IN_QUOTA, 171 + NULL, NULL); 172 + if (IS_ERR(turris_signing_keyring)) { 173 + pr_err("Cannot allocate Turris keyring\n"); 174 + 175 + unregister_key_type(&turris_signing_key_type); 176 + 177 + return PTR_ERR(turris_signing_keyring); 178 + } 179 + 180 + return 0; 181 + } 182 + module_init(turris_signing_key_init); 183 + 184 + static void turris_signing_key_exit(void) 185 + { 186 + key_put(turris_signing_keyring); 187 + unregister_key_type(&turris_signing_key_type); 188 + } 189 + module_exit(turris_signing_key_exit); 190 + 191 + MODULE_AUTHOR("Marek Behun <kabel@kernel.org>"); 192 + MODULE_DESCRIPTION("CZ.NIC's Turris signing key helper"); 193 + MODULE_LICENSE("GPL");
+17
drivers/reset/Kconfig
··· 225 225 Support for USBPHY Control found on RZ/G2L family. It mainly 226 226 controls reset and power down of the USB/PHY. 227 227 228 + config RESET_RZV2H_USB2PHY 229 + tristate "Renesas RZ/V2H(P) (and similar SoCs) USB2PHY Reset driver" 230 + depends on ARCH_RENESAS || COMPILE_TEST 231 + help 232 + Support for USB2PHY Port reset Control found on the RZ/V2H(P) SoC 233 + (and similar SoCs). 234 + 228 235 config RESET_SCMI 229 236 tristate "Reset driver controlled via ARM SCMI interface" 230 237 depends on ARM_SCMI_PROTOCOL || COMPILE_TEST ··· 285 278 select RESET_SIMPLE 286 279 help 287 280 This enables the reset driver for Allwinner SoCs. 281 + 282 + config RESET_TH1520 283 + tristate "T-HEAD 1520 reset controller" 284 + depends on ARCH_THEAD || COMPILE_TEST 285 + select REGMAP_MMIO 286 + help 287 + This driver provides support for the T-HEAD TH1520 SoC reset controller, 288 + which manages hardware reset lines for SoC components such as the GPU. 289 + Enable this option if you need to control hardware resets on TH1520-based 290 + systems. 288 291 289 292 config RESET_TI_SCI 290 293 tristate "TI System Control Interface (TI-SCI) reset driver"
+2
drivers/reset/Makefile
··· 31 31 obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o 32 32 obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o 33 33 obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o 34 + obj-$(CONFIG_RESET_RZV2H_USB2PHY) += reset-rzv2h-usb2phy.o 34 35 obj-$(CONFIG_RESET_SCMI) += reset-scmi.o 35 36 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o 36 37 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o 37 38 obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o 38 39 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o 40 + obj-$(CONFIG_RESET_TH1520) += reset-th1520.o 39 41 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o 40 42 obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o 41 43 obj-$(CONFIG_RESET_TI_TPS380X) += reset-tps380x.o
+236
drivers/reset/reset-rzv2h-usb2phy.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Renesas RZ/V2H(P) USB2PHY Port reset control driver 4 + * 5 + * Copyright (C) 2025 Renesas Electronics Corporation 6 + */ 7 + 8 + #include <linux/cleanup.h> 9 + #include <linux/delay.h> 10 + #include <linux/io.h> 11 + #include <linux/module.h> 12 + #include <linux/of.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/pm_runtime.h> 15 + #include <linux/reset.h> 16 + #include <linux/reset-controller.h> 17 + 18 + struct rzv2h_usb2phy_regval { 19 + u16 reg; 20 + u16 val; 21 + }; 22 + 23 + struct rzv2h_usb2phy_reset_of_data { 24 + const struct rzv2h_usb2phy_regval *init_vals; 25 + unsigned int init_val_count; 26 + 27 + u16 reset_reg; 28 + u16 reset_assert_val; 29 + u16 reset_deassert_val; 30 + u16 reset_status_bits; 31 + u16 reset_release_val; 32 + 33 + u16 reset2_reg; 34 + u16 reset2_acquire_val; 35 + u16 reset2_release_val; 36 + }; 37 + 38 + struct rzv2h_usb2phy_reset_priv { 39 + const struct rzv2h_usb2phy_reset_of_data *data; 40 + void __iomem *base; 41 + struct device *dev; 42 + struct reset_controller_dev rcdev; 43 + spinlock_t lock; /* protects register accesses */ 44 + }; 45 + 46 + static inline struct rzv2h_usb2phy_reset_priv 47 + *rzv2h_usbphy_rcdev_to_priv(struct reset_controller_dev *rcdev) 48 + { 49 + return container_of(rcdev, struct rzv2h_usb2phy_reset_priv, rcdev); 50 + } 51 + 52 + /* This function must be called only after pm_runtime_resume_and_get() has been called */ 53 + static void rzv2h_usbphy_assert_helper(struct rzv2h_usb2phy_reset_priv *priv) 54 + { 55 + const struct rzv2h_usb2phy_reset_of_data *data = priv->data; 56 + 57 + scoped_guard(spinlock, &priv->lock) { 58 + writel(data->reset2_acquire_val, priv->base + data->reset2_reg); 59 + writel(data->reset_assert_val, priv->base + data->reset_reg); 60 + } 61 + 62 + usleep_range(11, 20); 63 + } 64 + 65 + static int rzv2h_usbphy_reset_assert(struct reset_controller_dev *rcdev, 66 + unsigned long id) 67 + { 68 + struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev); 69 + struct device *dev = priv->dev; 70 + int ret; 71 + 72 + ret = pm_runtime_resume_and_get(dev); 73 + if (ret) { 74 + dev_err(dev, "pm_runtime_resume_and_get failed\n"); 75 + return ret; 76 + } 77 + 78 + rzv2h_usbphy_assert_helper(priv); 79 + 80 + pm_runtime_put(dev); 81 + 82 + return 0; 83 + } 84 + 85 + static int rzv2h_usbphy_reset_deassert(struct reset_controller_dev *rcdev, 86 + unsigned long id) 87 + { 88 + struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev); 89 + const struct rzv2h_usb2phy_reset_of_data *data = priv->data; 90 + struct device *dev = priv->dev; 91 + int ret; 92 + 93 + ret = pm_runtime_resume_and_get(dev); 94 + if (ret) { 95 + dev_err(dev, "pm_runtime_resume_and_get failed\n"); 96 + return ret; 97 + } 98 + 99 + scoped_guard(spinlock, &priv->lock) { 100 + writel(data->reset_deassert_val, priv->base + data->reset_reg); 101 + writel(data->reset2_release_val, priv->base + data->reset2_reg); 102 + writel(data->reset_release_val, priv->base + data->reset_reg); 103 + } 104 + 105 + pm_runtime_put(dev); 106 + 107 + return 0; 108 + } 109 + 110 + static int rzv2h_usbphy_reset_status(struct reset_controller_dev *rcdev, 111 + unsigned long id) 112 + { 113 + struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev); 114 + struct device *dev = priv->dev; 115 + int ret; 116 + u32 reg; 117 + 118 + ret = pm_runtime_resume_and_get(dev); 119 + if (ret) { 120 + dev_err(dev, "pm_runtime_resume_and_get failed\n"); 121 + return ret; 122 + } 123 + 124 + reg = readl(priv->base + priv->data->reset_reg); 125 + 126 + pm_runtime_put(dev); 127 + 128 + return (reg & priv->data->reset_status_bits) == priv->data->reset_status_bits; 129 + } 130 + 131 + static const struct reset_control_ops rzv2h_usbphy_reset_ops = { 132 + .assert = rzv2h_usbphy_reset_assert, 133 + .deassert = rzv2h_usbphy_reset_deassert, 134 + .status = rzv2h_usbphy_reset_status, 135 + }; 136 + 137 + static int rzv2h_usb2phy_reset_of_xlate(struct reset_controller_dev *rcdev, 138 + const struct of_phandle_args *reset_spec) 139 + { 140 + /* No special handling needed, we have only one reset line per device */ 141 + return 0; 142 + } 143 + 144 + static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev) 145 + { 146 + const struct rzv2h_usb2phy_reset_of_data *data; 147 + struct rzv2h_usb2phy_reset_priv *priv; 148 + struct device *dev = &pdev->dev; 149 + struct reset_control *rstc; 150 + int error; 151 + 152 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 153 + if (!priv) 154 + return -ENOMEM; 155 + 156 + data = of_device_get_match_data(dev); 157 + priv->data = data; 158 + priv->dev = dev; 159 + priv->base = devm_platform_ioremap_resource(pdev, 0); 160 + if (IS_ERR(priv->base)) 161 + return PTR_ERR(priv->base); 162 + 163 + rstc = devm_reset_control_get_shared_deasserted(dev, NULL); 164 + if (IS_ERR(rstc)) 165 + return dev_err_probe(dev, PTR_ERR(rstc), 166 + "failed to get deasserted reset\n"); 167 + 168 + spin_lock_init(&priv->lock); 169 + 170 + error = devm_pm_runtime_enable(dev); 171 + if (error) 172 + return dev_err_probe(dev, error, "Failed to enable pm_runtime\n"); 173 + 174 + error = pm_runtime_resume_and_get(dev); 175 + if (error) 176 + return dev_err_probe(dev, error, "pm_runtime_resume_and_get failed\n"); 177 + 178 + for (unsigned int i = 0; i < data->init_val_count; i++) 179 + writel(data->init_vals[i].val, priv->base + data->init_vals[i].reg); 180 + 181 + /* keep usb2phy in asserted state */ 182 + rzv2h_usbphy_assert_helper(priv); 183 + 184 + pm_runtime_put(dev); 185 + 186 + priv->rcdev.ops = &rzv2h_usbphy_reset_ops; 187 + priv->rcdev.of_reset_n_cells = 0; 188 + priv->rcdev.nr_resets = 1; 189 + priv->rcdev.of_xlate = rzv2h_usb2phy_reset_of_xlate; 190 + priv->rcdev.of_node = dev->of_node; 191 + priv->rcdev.dev = dev; 192 + 193 + return devm_reset_controller_register(dev, &priv->rcdev); 194 + } 195 + 196 + /* 197 + * initialization values required to prepare the PHY to receive 198 + * assert and deassert requests. 199 + */ 200 + static const struct rzv2h_usb2phy_regval rzv2h_init_vals[] = { 201 + { .reg = 0xc10, .val = 0x67c }, 202 + { .reg = 0xc14, .val = 0x1f }, 203 + { .reg = 0x600, .val = 0x909 }, 204 + }; 205 + 206 + static const struct rzv2h_usb2phy_reset_of_data rzv2h_reset_of_data = { 207 + .init_vals = rzv2h_init_vals, 208 + .init_val_count = ARRAY_SIZE(rzv2h_init_vals), 209 + .reset_reg = 0, 210 + .reset_assert_val = 0x206, 211 + .reset_status_bits = BIT(2), 212 + .reset_deassert_val = 0x200, 213 + .reset_release_val = 0x0, 214 + .reset2_reg = 0xb04, 215 + .reset2_acquire_val = 0x303, 216 + .reset2_release_val = 0x3, 217 + }; 218 + 219 + static const struct of_device_id rzv2h_usb2phy_reset_of_match[] = { 220 + { .compatible = "renesas,r9a09g057-usb2phy-reset", .data = &rzv2h_reset_of_data }, 221 + { /* Sentinel */ } 222 + }; 223 + MODULE_DEVICE_TABLE(of, rzv2h_usb2phy_reset_of_match); 224 + 225 + static struct platform_driver rzv2h_usb2phy_reset_driver = { 226 + .driver = { 227 + .name = "rzv2h_usb2phy_reset", 228 + .of_match_table = rzv2h_usb2phy_reset_of_match, 229 + }, 230 + .probe = rzv2h_usb2phy_reset_probe, 231 + }; 232 + module_platform_driver(rzv2h_usb2phy_reset_driver); 233 + 234 + MODULE_LICENSE("GPL"); 235 + MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>"); 236 + MODULE_DESCRIPTION("Renesas RZ/V2H(P) USB2PHY Control");
+135
drivers/reset/reset-th1520.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2024 Samsung Electronics Co., Ltd. 4 + * Author: Michal Wilczynski <m.wilczynski@samsung.com> 5 + */ 6 + 7 + #include <linux/of.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/reset-controller.h> 10 + #include <linux/regmap.h> 11 + 12 + #include <dt-bindings/reset/thead,th1520-reset.h> 13 + 14 + /* register offset in VOSYS_REGMAP */ 15 + #define TH1520_GPU_RST_CFG 0x0 16 + #define TH1520_GPU_RST_CFG_MASK GENMASK(1, 0) 17 + 18 + /* register values */ 19 + #define TH1520_GPU_SW_GPU_RST BIT(0) 20 + #define TH1520_GPU_SW_CLKGEN_RST BIT(1) 21 + 22 + struct th1520_reset_priv { 23 + struct reset_controller_dev rcdev; 24 + struct regmap *map; 25 + }; 26 + 27 + struct th1520_reset_map { 28 + u32 bit; 29 + u32 reg; 30 + }; 31 + 32 + static const struct th1520_reset_map th1520_resets[] = { 33 + [TH1520_RESET_ID_GPU] = { 34 + .bit = TH1520_GPU_SW_GPU_RST, 35 + .reg = TH1520_GPU_RST_CFG, 36 + }, 37 + [TH1520_RESET_ID_GPU_CLKGEN] = { 38 + .bit = TH1520_GPU_SW_CLKGEN_RST, 39 + .reg = TH1520_GPU_RST_CFG, 40 + } 41 + }; 42 + 43 + static inline struct th1520_reset_priv * 44 + to_th1520_reset(struct reset_controller_dev *rcdev) 45 + { 46 + return container_of(rcdev, struct th1520_reset_priv, rcdev); 47 + } 48 + 49 + static int th1520_reset_assert(struct reset_controller_dev *rcdev, 50 + unsigned long id) 51 + { 52 + struct th1520_reset_priv *priv = to_th1520_reset(rcdev); 53 + const struct th1520_reset_map *reset; 54 + 55 + reset = &th1520_resets[id]; 56 + 57 + return regmap_update_bits(priv->map, reset->reg, reset->bit, 0); 58 + } 59 + 60 + static int th1520_reset_deassert(struct reset_controller_dev *rcdev, 61 + unsigned long id) 62 + { 63 + struct th1520_reset_priv *priv = to_th1520_reset(rcdev); 64 + const struct th1520_reset_map *reset; 65 + 66 + reset = &th1520_resets[id]; 67 + 68 + return regmap_update_bits(priv->map, reset->reg, reset->bit, 69 + reset->bit); 70 + } 71 + 72 + static const struct reset_control_ops th1520_reset_ops = { 73 + .assert = th1520_reset_assert, 74 + .deassert = th1520_reset_deassert, 75 + }; 76 + 77 + static const struct regmap_config th1520_reset_regmap_config = { 78 + .reg_bits = 32, 79 + .val_bits = 32, 80 + .reg_stride = 4, 81 + .fast_io = true, 82 + }; 83 + 84 + static int th1520_reset_probe(struct platform_device *pdev) 85 + { 86 + struct device *dev = &pdev->dev; 87 + struct th1520_reset_priv *priv; 88 + void __iomem *base; 89 + int ret; 90 + 91 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 92 + if (!priv) 93 + return -ENOMEM; 94 + 95 + base = devm_platform_ioremap_resource(pdev, 0); 96 + if (IS_ERR(base)) 97 + return PTR_ERR(base); 98 + 99 + priv->map = devm_regmap_init_mmio(dev, base, 100 + &th1520_reset_regmap_config); 101 + if (IS_ERR(priv->map)) 102 + return PTR_ERR(priv->map); 103 + 104 + /* Initialize GPU resets to asserted state */ 105 + ret = regmap_update_bits(priv->map, TH1520_GPU_RST_CFG, 106 + TH1520_GPU_RST_CFG_MASK, 0); 107 + if (ret) 108 + return ret; 109 + 110 + priv->rcdev.owner = THIS_MODULE; 111 + priv->rcdev.nr_resets = ARRAY_SIZE(th1520_resets); 112 + priv->rcdev.ops = &th1520_reset_ops; 113 + priv->rcdev.of_node = dev->of_node; 114 + 115 + return devm_reset_controller_register(dev, &priv->rcdev); 116 + } 117 + 118 + static const struct of_device_id th1520_reset_match[] = { 119 + { .compatible = "thead,th1520-reset" }, 120 + { /* sentinel */ } 121 + }; 122 + MODULE_DEVICE_TABLE(of, th1520_reset_match); 123 + 124 + static struct platform_driver th1520_reset_driver = { 125 + .driver = { 126 + .name = "th1520-reset", 127 + .of_match_table = th1520_reset_match, 128 + }, 129 + .probe = th1520_reset_probe, 130 + }; 131 + module_platform_driver(th1520_reset_driver); 132 + 133 + MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>"); 134 + MODULE_DESCRIPTION("T-HEAD TH1520 SoC reset controller"); 135 + MODULE_LICENSE("GPL");
+2
drivers/soc/Kconfig
··· 23 23 source "drivers/soc/renesas/Kconfig" 24 24 source "drivers/soc/rockchip/Kconfig" 25 25 source "drivers/soc/samsung/Kconfig" 26 + source "drivers/soc/sophgo/Kconfig" 26 27 source "drivers/soc/sunxi/Kconfig" 27 28 source "drivers/soc/tegra/Kconfig" 28 29 source "drivers/soc/ti/Kconfig" 29 30 source "drivers/soc/ux500/Kconfig" 30 31 source "drivers/soc/versatile/Kconfig" 32 + source "drivers/soc/vt8500/Kconfig" 31 33 source "drivers/soc/xilinx/Kconfig" 32 34 33 35 endmenu
+2
drivers/soc/Makefile
··· 29 29 obj-y += renesas/ 30 30 obj-y += rockchip/ 31 31 obj-$(CONFIG_SOC_SAMSUNG) += samsung/ 32 + obj-y += sophgo/ 32 33 obj-y += sunxi/ 33 34 obj-$(CONFIG_ARCH_TEGRA) += tegra/ 34 35 obj-y += ti/ 35 36 obj-$(CONFIG_ARCH_U8500) += ux500/ 36 37 obj-y += versatile/ 38 + obj-y += vt8500/ 37 39 obj-y += xilinx/
+422 -39
drivers/soc/amlogic/meson-clk-measure.c
··· 14 14 15 15 static DEFINE_MUTEX(measure_lock); 16 16 17 - #define MSR_CLK_DUTY 0x0 18 - #define MSR_CLK_REG0 0x4 19 - #define MSR_CLK_REG1 0x8 20 - #define MSR_CLK_REG2 0xc 21 - 22 17 #define MSR_DURATION GENMASK(15, 0) 23 18 #define MSR_ENABLE BIT(16) 24 19 #define MSR_CONT BIT(17) /* continuous measurement */ ··· 28 33 #define DIV_STEP 32 29 34 #define DIV_MAX 640 30 35 31 - #define CLK_MSR_MAX 128 32 - 33 36 struct meson_msr_id { 34 37 struct meson_msr *priv; 35 38 unsigned int id; 36 39 const char *name; 37 40 }; 38 41 42 + struct msr_reg_offset { 43 + unsigned int duty_val; 44 + unsigned int freq_ctrl; 45 + unsigned int duty_ctrl; 46 + unsigned int freq_val; 47 + }; 48 + 49 + struct meson_msr_data { 50 + struct meson_msr_id *msr_table; 51 + unsigned int msr_count; 52 + const struct msr_reg_offset *reg; 53 + }; 54 + 39 55 struct meson_msr { 40 56 struct regmap *regmap; 41 - struct meson_msr_id msr_table[CLK_MSR_MAX]; 57 + struct meson_msr_data data; 42 58 }; 43 59 44 60 #define CLK_MSR_ID(__id, __name) \ 45 61 [__id] = {.id = __id, .name = __name,} 46 62 47 - static struct meson_msr_id clk_msr_m8[CLK_MSR_MAX] = { 63 + static const struct meson_msr_id clk_msr_m8[] = { 48 64 CLK_MSR_ID(0, "ring_osc_out_ee0"), 49 65 CLK_MSR_ID(1, "ring_osc_out_ee1"), 50 66 CLK_MSR_ID(2, "ring_osc_out_ee2"), ··· 104 98 CLK_MSR_ID(63, "mipi_csi_cfg"), 105 99 }; 106 100 107 - static struct meson_msr_id clk_msr_gx[CLK_MSR_MAX] = { 101 + static const struct meson_msr_id clk_msr_gx[] = { 108 102 CLK_MSR_ID(0, "ring_osc_out_ee_0"), 109 103 CLK_MSR_ID(1, "ring_osc_out_ee_1"), 110 104 CLK_MSR_ID(2, "ring_osc_out_ee_2"), ··· 174 168 CLK_MSR_ID(82, "ge2d"), 175 169 }; 176 170 177 - static struct meson_msr_id clk_msr_axg[CLK_MSR_MAX] = { 171 + static const struct meson_msr_id clk_msr_axg[] = { 178 172 CLK_MSR_ID(0, "ring_osc_out_ee_0"), 179 173 CLK_MSR_ID(1, "ring_osc_out_ee_1"), 180 174 CLK_MSR_ID(2, "ring_osc_out_ee_2"), ··· 248 242 CLK_MSR_ID(109, "audio_locker_in"), 249 243 }; 250 244 251 - static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = { 245 + static const struct meson_msr_id clk_msr_g12a[] = { 252 246 CLK_MSR_ID(0, "ring_osc_out_ee_0"), 253 247 CLK_MSR_ID(1, "ring_osc_out_ee_1"), 254 248 CLK_MSR_ID(2, "ring_osc_out_ee_2"), ··· 364 358 CLK_MSR_ID(122, "audio_pdm_dclk"), 365 359 }; 366 360 367 - static struct meson_msr_id clk_msr_sm1[CLK_MSR_MAX] = { 361 + static const struct meson_msr_id clk_msr_sm1[] = { 368 362 CLK_MSR_ID(0, "ring_osc_out_ee_0"), 369 363 CLK_MSR_ID(1, "ring_osc_out_ee_1"), 370 364 CLK_MSR_ID(2, "ring_osc_out_ee_2"), ··· 494 488 CLK_MSR_ID(127, "csi2_data"), 495 489 }; 496 490 491 + static const struct meson_msr_id clk_msr_c3[] = { 492 + CLK_MSR_ID(0, "sys_clk"), 493 + CLK_MSR_ID(1, "axi_clk"), 494 + CLK_MSR_ID(2, "rtc_clk"), 495 + CLK_MSR_ID(3, "p20_usb2_ckout"), 496 + CLK_MSR_ID(4, "eth_mpll_test"), 497 + CLK_MSR_ID(5, "sys_pll"), 498 + CLK_MSR_ID(6, "cpu_clk_div16"), 499 + CLK_MSR_ID(7, "ts_pll"), 500 + CLK_MSR_ID(8, "fclk_div2"), 501 + CLK_MSR_ID(9, "fclk_div2p5"), 502 + CLK_MSR_ID(10, "fclk_div3"), 503 + CLK_MSR_ID(11, "fclk_div4"), 504 + CLK_MSR_ID(12, "fclk_div5"), 505 + CLK_MSR_ID(13, "fclk_div7"), 506 + CLK_MSR_ID(15, "fclk_50m"), 507 + CLK_MSR_ID(16, "sys_oscin32k_i"), 508 + CLK_MSR_ID(17, "mclk_pll"), 509 + CLK_MSR_ID(19, "hifi_pll"), 510 + CLK_MSR_ID(20, "gp0_pll"), 511 + CLK_MSR_ID(21, "gp1_pll"), 512 + CLK_MSR_ID(22, "eth_mppll_50m_ckout"), 513 + CLK_MSR_ID(23, "sys_pll_div16"), 514 + CLK_MSR_ID(24, "ddr_dpll_pt_clk"), 515 + CLK_MSR_ID(26, "nna_core"), 516 + CLK_MSR_ID(27, "rtc_sec_pulse_out"), 517 + CLK_MSR_ID(28, "rtc_osc_clk_out"), 518 + CLK_MSR_ID(29, "debug_in_clk"), 519 + CLK_MSR_ID(30, "mod_eth_phy_ref_clk"), 520 + CLK_MSR_ID(31, "mod_eth_tx_clk"), 521 + CLK_MSR_ID(32, "eth_125m"), 522 + CLK_MSR_ID(33, "eth_rmii"), 523 + CLK_MSR_ID(34, "co_clkin_to_mac"), 524 + CLK_MSR_ID(36, "co_rx_clk"), 525 + CLK_MSR_ID(37, "co_tx_clk"), 526 + CLK_MSR_ID(38, "eth_phy_rxclk"), 527 + CLK_MSR_ID(39, "eth_phy_plltxclk"), 528 + CLK_MSR_ID(40, "ephy_test_clk"), 529 + CLK_MSR_ID(66, "vapb"), 530 + CLK_MSR_ID(67, "ge2d"), 531 + CLK_MSR_ID(68, "dewarpa"), 532 + CLK_MSR_ID(70, "mipi_dsi_meas"), 533 + CLK_MSR_ID(71, "dsi_phy"), 534 + CLK_MSR_ID(79, "rama"), 535 + CLK_MSR_ID(94, "vc9000e_core"), 536 + CLK_MSR_ID(95, "vc9000e_sys"), 537 + CLK_MSR_ID(96, "vc9000e_aclk"), 538 + CLK_MSR_ID(97, "hcodec"), 539 + CLK_MSR_ID(106, "deskew_pll_clk_div32_out"), 540 + CLK_MSR_ID(107, "mipi_csi_phy_clk_out[0]"), 541 + CLK_MSR_ID(108, "mipi_csi_phy_clk_out[1]"), 542 + CLK_MSR_ID(110, "spifc"), 543 + CLK_MSR_ID(111, "saradc"), 544 + CLK_MSR_ID(112, "ts"), 545 + CLK_MSR_ID(113, "sd_emmc_c"), 546 + CLK_MSR_ID(114, "sd_emmc_b"), 547 + CLK_MSR_ID(115, "sd_emmc_a"), 548 + CLK_MSR_ID(116, "gpio_msr_clk"), 549 + CLK_MSR_ID(117, "spicc_b"), 550 + CLK_MSR_ID(118, "spicc_a"), 551 + CLK_MSR_ID(122, "mod_audio_pdm_dclk_o"), 552 + CLK_MSR_ID(124, "o_earcrx_dmac_clk"), 553 + CLK_MSR_ID(125, "o_earcrx_cmdc_clk"), 554 + CLK_MSR_ID(126, "o_earctx_dmac_clk"), 555 + CLK_MSR_ID(127, "o_earctx_cmdc_clk"), 556 + CLK_MSR_ID(128, "o_tohdmitx_bclk"), 557 + CLK_MSR_ID(129, "o_tohdmitx_mclk"), 558 + CLK_MSR_ID(130, "o_tohdmitx_spdif_clk"), 559 + CLK_MSR_ID(131, "o_toacodec_bclk"), 560 + CLK_MSR_ID(132, "o_toacodec_mclk"), 561 + CLK_MSR_ID(133, "o_spdifout_b_mst_clk"), 562 + CLK_MSR_ID(134, "o_spdifout_mst_clk"), 563 + CLK_MSR_ID(135, "o_spdifin_mst_clk"), 564 + CLK_MSR_ID(136, "o_audio_mclk"), 565 + CLK_MSR_ID(137, "o_vad_clk"), 566 + CLK_MSR_ID(138, "o_tdmout_d_sclk"), 567 + CLK_MSR_ID(139, "o_tdmout_c_sclk"), 568 + CLK_MSR_ID(140, "o_tdmout_b_sclk"), 569 + CLK_MSR_ID(141, "o_tdmout_a_sclk"), 570 + CLK_MSR_ID(142, "o_tdminb_1b_sclk"), 571 + CLK_MSR_ID(143, "o_tdmin_1b_sclk"), 572 + CLK_MSR_ID(144, "o_tdmin_d_sclk"), 573 + CLK_MSR_ID(145, "o_tdmin_c_sclk"), 574 + CLK_MSR_ID(146, "o_tdmin_b_sclk"), 575 + CLK_MSR_ID(147, "o_tdmin_a_sclk"), 576 + CLK_MSR_ID(148, "o_resampleb_clk"), 577 + CLK_MSR_ID(149, "o_resamplea_clk"), 578 + CLK_MSR_ID(150, "o_pdmb_sysclk"), 579 + CLK_MSR_ID(151, "o_pdmb_dclk"), 580 + CLK_MSR_ID(152, "o_pdm_sysclk"), 581 + CLK_MSR_ID(153, "o_pdm_dclk"), 582 + CLK_MSR_ID(154, "c_alockerb_out_clk"), 583 + CLK_MSR_ID(155, "c_alockerb_in_clk"), 584 + CLK_MSR_ID(156, "c_alocker_out_clk"), 585 + CLK_MSR_ID(157, "c_alocker_in_clk"), 586 + CLK_MSR_ID(158, "audio_mst_clk[34]"), 587 + CLK_MSR_ID(159, "audio_mst_clk[35]"), 588 + CLK_MSR_ID(160, "pwm_n"), 589 + CLK_MSR_ID(161, "pwm_m"), 590 + CLK_MSR_ID(162, "pwm_l"), 591 + CLK_MSR_ID(163, "pwm_k"), 592 + CLK_MSR_ID(164, "pwm_j"), 593 + CLK_MSR_ID(165, "pwm_i"), 594 + CLK_MSR_ID(166, "pwm_h"), 595 + CLK_MSR_ID(167, "pwm_g"), 596 + CLK_MSR_ID(168, "pwm_f"), 597 + CLK_MSR_ID(169, "pwm_e"), 598 + CLK_MSR_ID(170, "pwm_d"), 599 + CLK_MSR_ID(171, "pwm_c"), 600 + CLK_MSR_ID(172, "pwm_b"), 601 + CLK_MSR_ID(173, "pwm_a"), 602 + CLK_MSR_ID(174, "AU_DAC1_CLK_TO_GPIO"), 603 + CLK_MSR_ID(175, "AU_ADC_CLK_TO_GPIO"), 604 + CLK_MSR_ID(176, "rng_ring_osc_clk[0]"), 605 + CLK_MSR_ID(177, "rng_ring_osc_clk[1]"), 606 + CLK_MSR_ID(178, "rng_ring_osc_clk[2]"), 607 + CLK_MSR_ID(179, "rng_ring_osc_clk[3]"), 608 + CLK_MSR_ID(180, "sys_cpu_ring_osc_clk[0]"), 609 + CLK_MSR_ID(181, "sys_cpu_ring_osc_clk[1]"), 610 + CLK_MSR_ID(182, "sys_cpu_ring_osc_clk[2]"), 611 + CLK_MSR_ID(183, "sys_cpu_ring_osc_clk[3]"), 612 + CLK_MSR_ID(184, "sys_cpu_ring_osc_clk[4]"), 613 + CLK_MSR_ID(185, "sys_cpu_ring_osc_clk[5]"), 614 + CLK_MSR_ID(186, "sys_cpu_ring_osc_clk[6]"), 615 + CLK_MSR_ID(187, "sys_cpu_ring_osc_clk[7]"), 616 + CLK_MSR_ID(188, "sys_cpu_ring_osc_clk[8]"), 617 + CLK_MSR_ID(189, "sys_cpu_ring_osc_clk[9]"), 618 + CLK_MSR_ID(190, "sys_cpu_ring_osc_clk[10]"), 619 + CLK_MSR_ID(191, "sys_cpu_ring_osc_clk[11]"), 620 + CLK_MSR_ID(192, "am_ring_osc_clk_out[12](dmc)"), 621 + CLK_MSR_ID(193, "am_ring_osc_clk_out[13](rama)"), 622 + CLK_MSR_ID(194, "am_ring_osc_clk_out[14](nna)"), 623 + CLK_MSR_ID(195, "am_ring_osc_clk_out[15](nna)"), 624 + CLK_MSR_ID(200, "rng_ring_osc_clk_1[0]"), 625 + CLK_MSR_ID(201, "rng_ring_osc_clk_1[1]"), 626 + CLK_MSR_ID(202, "rng_ring_osc_clk_1[2]"), 627 + CLK_MSR_ID(203, "rng_ring_osc_clk_1[3]"), 628 + 629 + }; 630 + 631 + static const struct meson_msr_id clk_msr_s4[] = { 632 + CLK_MSR_ID(0, "sys_clk"), 633 + CLK_MSR_ID(1, "axi_clk"), 634 + CLK_MSR_ID(2, "rtc_clk"), 635 + CLK_MSR_ID(5, "mali"), 636 + CLK_MSR_ID(6, "cpu_clk_div16"), 637 + CLK_MSR_ID(7, "ceca_clk"), 638 + CLK_MSR_ID(8, "cecb_clk"), 639 + CLK_MSR_ID(10, "fclk_div5"), 640 + CLK_MSR_ID(11, "mpll0"), 641 + CLK_MSR_ID(12, "mpll1"), 642 + CLK_MSR_ID(13, "mpll2"), 643 + CLK_MSR_ID(14, "mpll3"), 644 + CLK_MSR_ID(15, "fclk_50m"), 645 + CLK_MSR_ID(16, "pcie_clk_inp"), 646 + CLK_MSR_ID(17, "pcie_clk_inn"), 647 + CLK_MSR_ID(18, "mpll_clk_test_out"), 648 + CLK_MSR_ID(19, "hifi_pll"), 649 + CLK_MSR_ID(20, "gp0_pll"), 650 + CLK_MSR_ID(21, "gp1_pll"), 651 + CLK_MSR_ID(22, "eth_mppll_50m_ckout"), 652 + CLK_MSR_ID(23, "sys_pll_div16"), 653 + CLK_MSR_ID(24, "ddr_dpll_pt_clk"), 654 + CLK_MSR_ID(30, "mod_eth_phy_ref_clk"), 655 + CLK_MSR_ID(31, "mod_eth_tx_clk"), 656 + CLK_MSR_ID(32, "eth_125m"), 657 + CLK_MSR_ID(33, "eth_rmii"), 658 + CLK_MSR_ID(34, "co_clkin_to_mac"), 659 + CLK_MSR_ID(35, "mod_eth_rx_clk_rmii"), 660 + CLK_MSR_ID(36, "co_rx_clk"), 661 + CLK_MSR_ID(37, "co_tx_clk"), 662 + CLK_MSR_ID(38, "eth_phy_rxclk"), 663 + CLK_MSR_ID(39, "eth_phy_plltxclk"), 664 + CLK_MSR_ID(40, "ephy_test_clk"), 665 + CLK_MSR_ID(50, "vid_pll_div_clk_out"), 666 + CLK_MSR_ID(51, "enci"), 667 + CLK_MSR_ID(52, "encp"), 668 + CLK_MSR_ID(53, "encl"), 669 + CLK_MSR_ID(54, "vdac"), 670 + CLK_MSR_ID(55, "cdac_clk_c"), 671 + CLK_MSR_ID(56, "mod_tcon_clko"), 672 + CLK_MSR_ID(57, "lcd_an_clk_ph2"), 673 + CLK_MSR_ID(58, "lcd_an_clk_ph3"), 674 + CLK_MSR_ID(59, "hdmitx_pixel"), 675 + CLK_MSR_ID(60, "vdin_meas"), 676 + CLK_MSR_ID(61, "vpu"), 677 + CLK_MSR_ID(62, "vpu_clkb"), 678 + CLK_MSR_ID(63, "vpu_clkb_tmp"), 679 + CLK_MSR_ID(64, "vpu_clkc"), 680 + CLK_MSR_ID(65, "vid_lock"), 681 + CLK_MSR_ID(66, "vapb"), 682 + CLK_MSR_ID(67, "ge2d"), 683 + CLK_MSR_ID(68, "cts_hdcp22_esmclk"), 684 + CLK_MSR_ID(69, "cts_hdcp22_skpclk"), 685 + CLK_MSR_ID(76, "hdmitx_tmds"), 686 + CLK_MSR_ID(77, "hdmitx_sys_clk"), 687 + CLK_MSR_ID(78, "hdmitx_fe_clk"), 688 + CLK_MSR_ID(79, "rama"), 689 + CLK_MSR_ID(93, "vdec"), 690 + CLK_MSR_ID(99, "hevcf"), 691 + CLK_MSR_ID(100, "demod_core"), 692 + CLK_MSR_ID(101, "adc_extclk_in"), 693 + CLK_MSR_ID(102, "cts_demod_core_t2_clk"), 694 + CLK_MSR_ID(103, "adc_dpll_intclk"), 695 + CLK_MSR_ID(104, "adc_dpll_clk_b3"), 696 + CLK_MSR_ID(105, "s2_adc_clk"), 697 + CLK_MSR_ID(106, "deskew_pll_clk_div32_out"), 698 + CLK_MSR_ID(110, "sc"), 699 + CLK_MSR_ID(111, "sar_adc"), 700 + CLK_MSR_ID(113, "sd_emmc_c"), 701 + CLK_MSR_ID(114, "sd_emmc_b"), 702 + CLK_MSR_ID(115, "sd_emmc_a"), 703 + CLK_MSR_ID(116, "gpio_msr_clk"), 704 + CLK_MSR_ID(118, "spicc0"), 705 + CLK_MSR_ID(121, "ts"), 706 + CLK_MSR_ID(130, "audio_vad_clk"), 707 + CLK_MSR_ID(131, "acodec_dac_clk_x128"), 708 + CLK_MSR_ID(132, "audio_locker_in_clk"), 709 + CLK_MSR_ID(133, "audio_locker_out_clk"), 710 + CLK_MSR_ID(134, "audio_tdmout_c_sclk"), 711 + CLK_MSR_ID(135, "audio_tdmout_b_sclk"), 712 + CLK_MSR_ID(136, "audio_tdmout_a_sclk"), 713 + CLK_MSR_ID(137, "audio_tdmin_lb_sclk"), 714 + CLK_MSR_ID(138, "audio_tdmin_c_sclk"), 715 + CLK_MSR_ID(139, "audio_tdmin_b_sclk"), 716 + CLK_MSR_ID(140, "audio_tdmin_a_sclk"), 717 + CLK_MSR_ID(141, "audio_resamplea_clk"), 718 + CLK_MSR_ID(142, "audio_pdm_sysclk"), 719 + CLK_MSR_ID(143, "audio_spdifout_b_mst_clk"), 720 + CLK_MSR_ID(144, "audio_spdifout_mst_clk"), 721 + CLK_MSR_ID(145, "audio_spdifin_mst_clk"), 722 + CLK_MSR_ID(146, "audio_pdm_dclk"), 723 + CLK_MSR_ID(147, "audio_resampleb_clk"), 724 + CLK_MSR_ID(160, "pwm_j"), 725 + CLK_MSR_ID(161, "pwm_i"), 726 + CLK_MSR_ID(162, "pwm_h"), 727 + CLK_MSR_ID(163, "pwm_g"), 728 + CLK_MSR_ID(164, "pwm_f"), 729 + CLK_MSR_ID(165, "pwm_e"), 730 + CLK_MSR_ID(166, "pwm_d"), 731 + CLK_MSR_ID(167, "pwm_c"), 732 + CLK_MSR_ID(168, "pwm_b"), 733 + CLK_MSR_ID(169, "pwm_a"), 734 + CLK_MSR_ID(176, "rng_ring_0"), 735 + CLK_MSR_ID(177, "rng_ring_1"), 736 + CLK_MSR_ID(178, "rng_ring_2"), 737 + CLK_MSR_ID(179, "rng_ring_3"), 738 + CLK_MSR_ID(180, "dmc_osc_ring(LVT16)"), 739 + CLK_MSR_ID(181, "gpu_osc_ring0(LVT16)"), 740 + CLK_MSR_ID(182, "gpu_osc_ring1(ULVT16)"), 741 + CLK_MSR_ID(183, "gpu_osc_ring2(SLVT16)"), 742 + CLK_MSR_ID(184, "vpu_osc_ring0(SVT24)"), 743 + CLK_MSR_ID(185, "vpu_osc_ring1(LVT20)"), 744 + CLK_MSR_ID(186, "vpu_osc_ring2(LVT16)"), 745 + CLK_MSR_ID(187, "dos_osc_ring0(SVT24)"), 746 + CLK_MSR_ID(188, "dos_osc_ring1(SVT16)"), 747 + CLK_MSR_ID(189, "dos_osc_ring2(LVT16)"), 748 + CLK_MSR_ID(190, "dos_osc_ring3(ULVT20)"), 749 + CLK_MSR_ID(192, "axi_sram_osc_ring(SVT16)"), 750 + CLK_MSR_ID(193, "demod_osc_ring0"), 751 + CLK_MSR_ID(194, "demod_osc_ring1"), 752 + CLK_MSR_ID(195, "sar_osc_ring"), 753 + CLK_MSR_ID(196, "sys_cpu_osc_ring0"), 754 + CLK_MSR_ID(197, "sys_cpu_osc_ring1"), 755 + CLK_MSR_ID(198, "sys_cpu_osc_ring2"), 756 + CLK_MSR_ID(199, "sys_cpu_osc_ring3"), 757 + CLK_MSR_ID(200, "sys_cpu_osc_ring4"), 758 + CLK_MSR_ID(201, "sys_cpu_osc_ring5"), 759 + CLK_MSR_ID(202, "sys_cpu_osc_ring6"), 760 + CLK_MSR_ID(203, "sys_cpu_osc_ring7"), 761 + CLK_MSR_ID(204, "sys_cpu_osc_ring8"), 762 + CLK_MSR_ID(205, "sys_cpu_osc_ring9"), 763 + CLK_MSR_ID(206, "sys_cpu_osc_ring10"), 764 + CLK_MSR_ID(207, "sys_cpu_osc_ring11"), 765 + CLK_MSR_ID(208, "sys_cpu_osc_ring12"), 766 + CLK_MSR_ID(209, "sys_cpu_osc_ring13"), 767 + CLK_MSR_ID(210, "sys_cpu_osc_ring14"), 768 + CLK_MSR_ID(211, "sys_cpu_osc_ring15"), 769 + CLK_MSR_ID(212, "sys_cpu_osc_ring16"), 770 + CLK_MSR_ID(213, "sys_cpu_osc_ring17"), 771 + CLK_MSR_ID(214, "sys_cpu_osc_ring18"), 772 + CLK_MSR_ID(215, "sys_cpu_osc_ring19"), 773 + CLK_MSR_ID(216, "sys_cpu_osc_ring20"), 774 + CLK_MSR_ID(217, "sys_cpu_osc_ring21"), 775 + CLK_MSR_ID(218, "sys_cpu_osc_ring22"), 776 + CLK_MSR_ID(219, "sys_cpu_osc_ring23"), 777 + CLK_MSR_ID(220, "sys_cpu_osc_ring24"), 778 + CLK_MSR_ID(221, "sys_cpu_osc_ring25"), 779 + CLK_MSR_ID(222, "sys_cpu_osc_ring26"), 780 + CLK_MSR_ID(223, "sys_cpu_osc_ring27"), 781 + 782 + }; 783 + 497 784 static int meson_measure_id(struct meson_msr_id *clk_msr_id, 498 - unsigned int duration) 785 + unsigned int duration) 499 786 { 500 787 struct meson_msr *priv = clk_msr_id->priv; 788 + const struct msr_reg_offset *reg = priv->data.reg; 501 789 unsigned int val; 502 790 int ret; 503 791 ··· 799 499 if (ret) 800 500 return ret; 801 501 802 - regmap_write(priv->regmap, MSR_CLK_REG0, 0); 502 + regmap_write(priv->regmap, reg->freq_ctrl, 0); 803 503 804 504 /* Set measurement duration */ 805 - regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_DURATION, 505 + regmap_update_bits(priv->regmap, reg->freq_ctrl, MSR_DURATION, 806 506 FIELD_PREP(MSR_DURATION, duration - 1)); 807 507 808 508 /* Set ID */ 809 - regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_CLK_SRC, 509 + regmap_update_bits(priv->regmap, reg->freq_ctrl, MSR_CLK_SRC, 810 510 FIELD_PREP(MSR_CLK_SRC, clk_msr_id->id)); 811 511 812 512 /* Enable & Start */ 813 - regmap_update_bits(priv->regmap, MSR_CLK_REG0, 513 + regmap_update_bits(priv->regmap, reg->freq_ctrl, 814 514 MSR_RUN | MSR_ENABLE, 815 515 MSR_RUN | MSR_ENABLE); 816 516 817 - ret = regmap_read_poll_timeout(priv->regmap, MSR_CLK_REG0, 517 + ret = regmap_read_poll_timeout(priv->regmap, reg->freq_ctrl, 818 518 val, !(val & MSR_BUSY), 10, 10000); 819 519 if (ret) { 820 520 mutex_unlock(&measure_lock); ··· 822 522 } 823 523 824 524 /* Disable */ 825 - regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_ENABLE, 0); 525 + regmap_update_bits(priv->regmap, reg->freq_ctrl, MSR_ENABLE, 0); 826 526 827 527 /* Get the value in multiple of gate time counts */ 828 - regmap_read(priv->regmap, MSR_CLK_REG2, &val); 528 + regmap_read(priv->regmap, reg->freq_val, &val); 829 529 830 530 mutex_unlock(&measure_lock); 831 531 ··· 873 573 static int clk_msr_summary_show(struct seq_file *s, void *data) 874 574 { 875 575 struct meson_msr_id *msr_table = s->private; 576 + unsigned int msr_count = msr_table->priv->data.msr_count; 876 577 unsigned int precision = 0; 877 578 int val, i; 878 579 879 580 seq_puts(s, " clock rate precision\n"); 880 581 seq_puts(s, "---------------------------------------------\n"); 881 582 882 - for (i = 0 ; i < CLK_MSR_MAX ; ++i) { 583 + for (i = 0 ; i < msr_count ; ++i) { 883 584 if (!msr_table[i].name) 884 585 continue; 885 586 ··· 896 595 } 897 596 DEFINE_SHOW_ATTRIBUTE(clk_msr_summary); 898 597 899 - static const struct regmap_config meson_clk_msr_regmap_config = { 598 + static struct regmap_config meson_clk_msr_regmap_config = { 900 599 .reg_bits = 32, 901 600 .val_bits = 32, 902 601 .reg_stride = 4, 903 - .max_register = MSR_CLK_REG2, 904 602 }; 905 603 906 604 static int meson_msr_probe(struct platform_device *pdev) 907 605 { 908 - const struct meson_msr_id *match_data; 606 + const struct meson_msr_data *match_data; 909 607 struct meson_msr *priv; 910 608 struct dentry *root, *clks; 609 + struct resource *res; 911 610 void __iomem *base; 912 611 int i; 913 612 ··· 922 621 return -ENODEV; 923 622 } 924 623 925 - memcpy(priv->msr_table, match_data, sizeof(priv->msr_table)); 624 + priv->data.msr_table = devm_kcalloc(&pdev->dev, 625 + match_data->msr_count, 626 + sizeof(struct meson_msr_id), 627 + GFP_KERNEL); 628 + if (!priv->data.msr_table) 629 + return -ENOMEM; 926 630 927 - base = devm_platform_ioremap_resource(pdev, 0); 631 + memcpy(priv->data.msr_table, match_data->msr_table, 632 + match_data->msr_count * sizeof(struct meson_msr_id)); 633 + priv->data.msr_count = match_data->msr_count; 634 + 635 + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 928 636 if (IS_ERR(base)) 929 637 return PTR_ERR(base); 930 638 639 + meson_clk_msr_regmap_config.max_register = resource_size(res) - 4; 931 640 priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, 932 641 &meson_clk_msr_regmap_config); 933 642 if (IS_ERR(priv->regmap)) 934 643 return PTR_ERR(priv->regmap); 935 644 645 + priv->data.reg = devm_kzalloc(&pdev->dev, sizeof(struct msr_reg_offset), 646 + GFP_KERNEL); 647 + if (!priv->data.reg) 648 + return -ENOMEM; 649 + 650 + memcpy((void *)priv->data.reg, match_data->reg, 651 + sizeof(struct msr_reg_offset)); 652 + 936 653 root = debugfs_create_dir("meson-clk-msr", NULL); 937 654 clks = debugfs_create_dir("clks", root); 938 655 939 656 debugfs_create_file("measure_summary", 0444, root, 940 - priv->msr_table, &clk_msr_summary_fops); 657 + priv->data.msr_table, &clk_msr_summary_fops); 941 658 942 - for (i = 0 ; i < CLK_MSR_MAX ; ++i) { 943 - if (!priv->msr_table[i].name) 659 + for (i = 0 ; i < priv->data.msr_count ; ++i) { 660 + if (!priv->data.msr_table[i].name) 944 661 continue; 945 662 946 - priv->msr_table[i].priv = priv; 663 + priv->data.msr_table[i].priv = priv; 947 664 948 - debugfs_create_file(priv->msr_table[i].name, 0444, clks, 949 - &priv->msr_table[i], &clk_msr_fops); 665 + debugfs_create_file(priv->data.msr_table[i].name, 0444, clks, 666 + &priv->data.msr_table[i], &clk_msr_fops); 950 667 } 951 668 952 669 return 0; 953 670 } 954 671 672 + static const struct msr_reg_offset msr_reg_offset = { 673 + .duty_val = 0x0, 674 + .freq_ctrl = 0x4, 675 + .duty_ctrl = 0x8, 676 + .freq_val = 0xc, 677 + }; 678 + 679 + static const struct meson_msr_data clk_msr_gx_data = { 680 + .msr_table = (void *)clk_msr_gx, 681 + .msr_count = ARRAY_SIZE(clk_msr_gx), 682 + .reg = &msr_reg_offset, 683 + }; 684 + 685 + static const struct meson_msr_data clk_msr_m8_data = { 686 + .msr_table = (void *)clk_msr_m8, 687 + .msr_count = ARRAY_SIZE(clk_msr_m8), 688 + .reg = &msr_reg_offset, 689 + }; 690 + 691 + static const struct meson_msr_data clk_msr_axg_data = { 692 + .msr_table = (void *)clk_msr_axg, 693 + .msr_count = ARRAY_SIZE(clk_msr_axg), 694 + .reg = &msr_reg_offset, 695 + }; 696 + 697 + static const struct meson_msr_data clk_msr_g12a_data = { 698 + .msr_table = (void *)clk_msr_g12a, 699 + .msr_count = ARRAY_SIZE(clk_msr_g12a), 700 + .reg = &msr_reg_offset, 701 + }; 702 + 703 + static const struct meson_msr_data clk_msr_sm1_data = { 704 + .msr_table = (void *)clk_msr_sm1, 705 + .msr_count = ARRAY_SIZE(clk_msr_sm1), 706 + .reg = &msr_reg_offset, 707 + }; 708 + 709 + static const struct msr_reg_offset msr_reg_offset_v2 = { 710 + .freq_ctrl = 0x0, 711 + .duty_ctrl = 0x4, 712 + .freq_val = 0x8, 713 + .duty_val = 0x18, 714 + }; 715 + 716 + static const struct meson_msr_data clk_msr_c3_data = { 717 + .msr_table = (void *)clk_msr_c3, 718 + .msr_count = ARRAY_SIZE(clk_msr_c3), 719 + .reg = &msr_reg_offset_v2, 720 + }; 721 + 722 + static const struct meson_msr_data clk_msr_s4_data = { 723 + .msr_table = (void *)clk_msr_s4, 724 + .msr_count = ARRAY_SIZE(clk_msr_s4), 725 + .reg = &msr_reg_offset_v2, 726 + }; 727 + 955 728 static const struct of_device_id meson_msr_match_table[] = { 956 729 { 957 730 .compatible = "amlogic,meson-gx-clk-measure", 958 - .data = (void *)clk_msr_gx, 731 + .data = &clk_msr_gx_data, 959 732 }, 960 733 { 961 734 .compatible = "amlogic,meson8-clk-measure", 962 - .data = (void *)clk_msr_m8, 735 + .data = &clk_msr_m8_data, 963 736 }, 964 737 { 965 738 .compatible = "amlogic,meson8b-clk-measure", 966 - .data = (void *)clk_msr_m8, 739 + .data = &clk_msr_m8_data, 967 740 }, 968 741 { 969 742 .compatible = "amlogic,meson-axg-clk-measure", 970 - .data = (void *)clk_msr_axg, 743 + .data = &clk_msr_axg_data, 971 744 }, 972 745 { 973 746 .compatible = "amlogic,meson-g12a-clk-measure", 974 - .data = (void *)clk_msr_g12a, 747 + .data = &clk_msr_g12a_data, 975 748 }, 976 749 { 977 750 .compatible = "amlogic,meson-sm1-clk-measure", 978 - .data = (void *)clk_msr_sm1, 751 + .data = &clk_msr_sm1_data, 752 + }, 753 + { 754 + .compatible = "amlogic,c3-clk-measure", 755 + .data = &clk_msr_c3_data, 756 + }, 757 + { 758 + .compatible = "amlogic,s4-clk-measure", 759 + .data = &clk_msr_s4_data, 979 760 }, 980 761 { /* sentinel */ } 981 762 };
+14 -3
drivers/soc/aspeed/aspeed-lpc-snoop.c
··· 166 166 int rc; 167 167 168 168 lpc_snoop->irq = platform_get_irq(pdev, 0); 169 - if (!lpc_snoop->irq) 169 + if (lpc_snoop->irq < 0) 170 170 return -ENODEV; 171 171 172 172 rc = devm_request_irq(dev, lpc_snoop->irq, ··· 200 200 lpc_snoop->chan[channel].miscdev.minor = MISC_DYNAMIC_MINOR; 201 201 lpc_snoop->chan[channel].miscdev.name = 202 202 devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, channel); 203 + if (!lpc_snoop->chan[channel].miscdev.name) { 204 + rc = -ENOMEM; 205 + goto err_free_fifo; 206 + } 203 207 lpc_snoop->chan[channel].miscdev.fops = &snoop_fops; 204 208 lpc_snoop->chan[channel].miscdev.parent = dev; 205 209 rc = misc_register(&lpc_snoop->chan[channel].miscdev); 206 210 if (rc) 207 - return rc; 211 + goto err_free_fifo; 208 212 209 213 /* Enable LPC snoop channel at requested port */ 210 214 switch (channel) { ··· 225 221 hicrb_en = HICRB_ENSNP1D; 226 222 break; 227 223 default: 228 - return -EINVAL; 224 + rc = -EINVAL; 225 + goto err_misc_deregister; 229 226 } 230 227 231 228 regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en); ··· 236 231 regmap_update_bits(lpc_snoop->regmap, HICRB, 237 232 hicrb_en, hicrb_en); 238 233 234 + return 0; 235 + 236 + err_misc_deregister: 237 + misc_deregister(&lpc_snoop->chan[channel].miscdev); 238 + err_free_fifo: 239 + kfifo_free(&lpc_snoop->chan[channel].fifo); 239 240 return rc; 240 241 } 241 242
+1 -1
drivers/soc/fsl/Kconfig
··· 36 36 config DPAA2_CONSOLE 37 37 tristate "QorIQ DPAA2 console driver" 38 38 depends on OF && (ARCH_LAYERSCAPE || COMPILE_TEST) 39 - default y 39 + default ARCH_LAYERSCAPE 40 40 help 41 41 Console driver for DPAA2 platforms. Exports 2 char devices, 42 42 /dev/dpaa2_mc_console and /dev/dpaa2_aiop_console,
+1 -1
drivers/soc/fsl/qbman/qman.c
··· 1270 1270 qm_dqrr_set_ithresh(p, QMAN_PIRQ_DQRR_ITHRESH); 1271 1271 qm_mr_set_ithresh(p, QMAN_PIRQ_MR_ITHRESH); 1272 1272 qm_out(p, QM_REG_ITPR, QMAN_PIRQ_IPERIOD); 1273 - portal->cgrs = kmalloc_array(2, sizeof(*cgrs), GFP_KERNEL); 1273 + portal->cgrs = kmalloc_array(2, sizeof(*portal->cgrs), GFP_KERNEL); 1274 1274 if (!portal->cgrs) 1275 1275 goto fail_cgrs; 1276 1276 /* initial snapshot is no-depletion */
+4 -11
drivers/soc/fsl/qe/qe_ic.c
··· 232 232 iowrite32be(value, base + (reg >> 2)); 233 233 } 234 234 235 - static inline struct qe_ic *qe_ic_from_irq(unsigned int virq) 236 - { 237 - return irq_get_chip_data(virq); 238 - } 239 - 240 235 static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d) 241 236 { 242 237 return irq_data_get_irq_chip_data(d); ··· 450 455 451 456 qe_ic_write(qe_ic->regs, QEIC_CICR, 0); 452 457 453 - irq_set_handler_data(qe_ic->virq_low, qe_ic); 454 - irq_set_chained_handler(qe_ic->virq_low, low_handler); 458 + irq_set_chained_handler_and_data(qe_ic->virq_low, low_handler, qe_ic); 455 459 456 - if (high_handler) { 457 - irq_set_handler_data(qe_ic->virq_high, qe_ic); 458 - irq_set_chained_handler(qe_ic->virq_high, high_handler); 459 - } 460 + if (high_handler) 461 + irq_set_chained_handler_and_data(qe_ic->virq_high, 462 + high_handler, qe_ic); 460 463 return 0; 461 464 } 462 465 static const struct of_device_id qe_ic_ids[] = {
+15 -27
drivers/soc/hisilicon/kunpeng_hccs.c
··· 167 167 168 168 static void hccs_unregister_pcc_channel(struct hccs_dev *hdev) 169 169 { 170 - struct hccs_mbox_client_info *cl_info = &hdev->cl_info; 171 - 172 - if (cl_info->pcc_comm_addr) 173 - iounmap(cl_info->pcc_comm_addr); 174 170 pcc_mbox_free_channel(hdev->cl_info.pcc_chan); 175 171 } 176 172 ··· 175 179 struct hccs_mbox_client_info *cl_info = &hdev->cl_info; 176 180 struct mbox_client *cl = &cl_info->client; 177 181 struct pcc_mbox_chan *pcc_chan; 182 + struct mbox_chan *mbox_chan; 178 183 struct device *dev = hdev->dev; 179 184 int rc; 180 185 ··· 193 196 goto out; 194 197 } 195 198 cl_info->pcc_chan = pcc_chan; 196 - cl_info->mbox_chan = pcc_chan->mchan; 199 + mbox_chan = pcc_chan->mchan; 197 200 198 201 /* 199 202 * pcc_chan->latency is just a nominal value. In reality the remote ··· 203 206 cl_info->deadline_us = 204 207 HCCS_PCC_CMD_WAIT_RETRIES_NUM * pcc_chan->latency; 205 208 if (!hdev->verspec_data->has_txdone_irq && 206 - cl_info->mbox_chan->mbox->txdone_irq) { 209 + mbox_chan->mbox->txdone_irq) { 207 210 dev_err(dev, "PCC IRQ in PCCT is enabled.\n"); 208 211 rc = -EINVAL; 209 212 goto err_mbx_channel_free; 210 213 } else if (hdev->verspec_data->has_txdone_irq && 211 - !cl_info->mbox_chan->mbox->txdone_irq) { 214 + !mbox_chan->mbox->txdone_irq) { 212 215 dev_err(dev, "PCC IRQ in PCCT isn't supported.\n"); 213 216 rc = -EINVAL; 214 217 goto err_mbx_channel_free; 215 218 } 216 219 217 - if (!pcc_chan->shmem_base_addr || 218 - pcc_chan->shmem_size != HCCS_PCC_SHARE_MEM_BYTES) { 219 - dev_err(dev, "The base address or size (%llu) of PCC communication region is invalid.\n", 220 - pcc_chan->shmem_size); 220 + if (pcc_chan->shmem_size != HCCS_PCC_SHARE_MEM_BYTES) { 221 + dev_err(dev, "Base size (%llu) of PCC communication region must be %d bytes.\n", 222 + pcc_chan->shmem_size, HCCS_PCC_SHARE_MEM_BYTES); 221 223 rc = -EINVAL; 222 - goto err_mbx_channel_free; 223 - } 224 - 225 - cl_info->pcc_comm_addr = ioremap(pcc_chan->shmem_base_addr, 226 - pcc_chan->shmem_size); 227 - if (!cl_info->pcc_comm_addr) { 228 - dev_err(dev, "Failed to ioremap PCC communication region for channel-%u.\n", 229 - hdev->chan_id); 230 - rc = -ENOMEM; 231 224 goto err_mbx_channel_free; 232 225 } 233 226 ··· 233 246 { 234 247 struct hccs_mbox_client_info *cl_info = &hdev->cl_info; 235 248 struct acpi_pcct_shared_memory __iomem *comm_base = 236 - cl_info->pcc_comm_addr; 249 + cl_info->pcc_chan->shmem; 237 250 u16 status; 238 251 int ret; 239 252 ··· 276 289 .status = 0, 277 290 }; 278 291 279 - memcpy_toio(hdev->cl_info.pcc_comm_addr, (void *)&tmp, 292 + memcpy_toio(hdev->cl_info.pcc_chan->shmem, (void *)&tmp, 280 293 sizeof(struct acpi_pcct_shared_memory)); 281 294 282 295 /* Copy the message to the PCC comm space */ ··· 296 309 .command = cmd, 297 310 }; 298 311 299 - memcpy_toio(hdev->cl_info.pcc_comm_addr, (void *)&tmp, 312 + memcpy_toio(hdev->cl_info.pcc_chan->shmem, (void *)&tmp, 300 313 sizeof(struct acpi_pcct_ext_pcc_shared_memory)); 301 314 302 315 /* Copy the message to the PCC comm space */ ··· 308 321 { 309 322 const struct hccs_verspecific_data *verspec_data = hdev->verspec_data; 310 323 struct hccs_mbox_client_info *cl_info = &hdev->cl_info; 324 + struct mbox_chan *mbox_chan = cl_info->pcc_chan->mchan; 311 325 struct hccs_fw_inner_head *fw_inner_head; 312 326 void __iomem *comm_space; 313 327 u16 space_size; 314 328 int ret; 315 329 316 - comm_space = cl_info->pcc_comm_addr + verspec_data->shared_mem_size; 330 + comm_space = cl_info->pcc_chan->shmem + verspec_data->shared_mem_size; 317 331 space_size = HCCS_PCC_SHARE_MEM_BYTES - verspec_data->shared_mem_size; 318 332 verspec_data->fill_pcc_shared_mem(hdev, cmd, desc, 319 333 comm_space, space_size); ··· 322 334 reinit_completion(&cl_info->done); 323 335 324 336 /* Ring doorbell */ 325 - ret = mbox_send_message(cl_info->mbox_chan, &cmd); 337 + ret = mbox_send_message(mbox_chan, &cmd); 326 338 if (ret < 0) { 327 339 dev_err(hdev->dev, "Send PCC mbox message failed, ret = %d.\n", 328 340 ret); ··· 344 356 345 357 end: 346 358 if (verspec_data->has_txdone_irq) 347 - mbox_chan_txdone(cl_info->mbox_chan, ret); 359 + mbox_chan_txdone(mbox_chan, ret); 348 360 else 349 - mbox_client_txdone(cl_info->mbox_chan, ret); 361 + mbox_client_txdone(mbox_chan, ret); 350 362 return ret; 351 363 } 352 364
-2
drivers/soc/hisilicon/kunpeng_hccs.h
··· 60 60 61 61 struct hccs_mbox_client_info { 62 62 struct mbox_client client; 63 - struct mbox_chan *mbox_chan; 64 63 struct pcc_mbox_chan *pcc_chan; 65 64 u64 deadline_us; 66 - void __iomem *pcc_comm_addr; 67 65 struct completion done; 68 66 }; 69 67
+115 -76
drivers/soc/imx/soc-imx8m.c
··· 24 24 #define OCOTP_UID_HIGH 0x420 25 25 26 26 #define IMX8MP_OCOTP_UID_OFFSET 0x10 27 + #define IMX8MP_OCOTP_UID_HIGH 0xE00 27 28 28 29 /* Same as ANADIG_DIGPROG_IMX7D */ 29 30 #define ANADIG_DIGPROG_IMX8MM 0x800 30 31 31 32 struct imx8_soc_data { 32 33 char *name; 33 - int (*soc_revision)(u32 *socrev, u64 *socuid); 34 + const char *ocotp_compatible; 35 + int (*soc_revision)(struct platform_device *pdev, u32 *socrev); 36 + int (*soc_uid)(struct platform_device *pdev, u64 *socuid); 37 + }; 38 + 39 + struct imx8_soc_drvdata { 40 + void __iomem *ocotp_base; 41 + struct clk *clk; 34 42 }; 35 43 36 44 #ifdef CONFIG_HAVE_ARM_SMCCC ··· 57 49 static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; }; 58 50 #endif 59 51 60 - static int imx8mq_soc_revision(u32 *socrev, u64 *socuid) 52 + static int imx8m_soc_uid(struct platform_device *pdev, u64 *socuid) 61 53 { 62 - struct device_node *np __free(device_node) = 63 - of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp"); 64 - void __iomem *ocotp_base; 54 + struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev); 55 + void __iomem *ocotp_base = drvdata->ocotp_base; 56 + 57 + *socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); 58 + *socuid <<= 32; 59 + *socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); 60 + 61 + return 0; 62 + } 63 + 64 + static int imx8mq_soc_revision(struct platform_device *pdev, u32 *socrev) 65 + { 66 + struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev); 67 + void __iomem *ocotp_base = drvdata->ocotp_base; 65 68 u32 magic; 66 69 u32 rev; 67 - struct clk *clk; 68 - int ret; 69 - 70 - if (!np) 71 - return -EINVAL; 72 - 73 - ocotp_base = of_iomap(np, 0); 74 - if (!ocotp_base) 75 - return -EINVAL; 76 - 77 - clk = of_clk_get_by_name(np, NULL); 78 - if (IS_ERR(clk)) { 79 - ret = PTR_ERR(clk); 80 - goto err_clk; 81 - } 82 - 83 - clk_prepare_enable(clk); 84 70 85 71 /* 86 72 * SOC revision on older imx8mq is not available in fuses so query ··· 87 85 rev = REV_B1; 88 86 } 89 87 90 - *socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); 91 - *socuid <<= 32; 92 - *socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); 93 - 94 88 *socrev = rev; 95 89 96 - clk_disable_unprepare(clk); 97 - clk_put(clk); 98 - iounmap(ocotp_base); 90 + return 0; 91 + } 92 + 93 + static int imx8mp_soc_uid(struct platform_device *pdev, u64 *socuid) 94 + { 95 + struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev); 96 + void __iomem *ocotp_base = drvdata->ocotp_base; 97 + 98 + socuid[0] = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + IMX8MP_OCOTP_UID_OFFSET); 99 + socuid[0] <<= 32; 100 + socuid[0] |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + IMX8MP_OCOTP_UID_OFFSET); 101 + 102 + socuid[1] = readl_relaxed(ocotp_base + IMX8MP_OCOTP_UID_HIGH + 0x10); 103 + socuid[1] <<= 32; 104 + socuid[1] |= readl_relaxed(ocotp_base + IMX8MP_OCOTP_UID_HIGH); 99 105 100 106 return 0; 101 - 102 - err_clk: 103 - iounmap(ocotp_base); 104 - return ret; 105 107 } 106 108 107 - static int imx8mm_soc_uid(u64 *socuid) 108 - { 109 - struct device_node *np __free(device_node) = 110 - of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp"); 111 - void __iomem *ocotp_base; 112 - struct clk *clk; 113 - int ret = 0; 114 - u32 offset = of_machine_is_compatible("fsl,imx8mp") ? 115 - IMX8MP_OCOTP_UID_OFFSET : 0; 116 - 117 - if (!np) 118 - return -EINVAL; 119 - 120 - ocotp_base = of_iomap(np, 0); 121 - if (!ocotp_base) 122 - return -EINVAL; 123 - 124 - clk = of_clk_get_by_name(np, NULL); 125 - if (IS_ERR(clk)) { 126 - ret = PTR_ERR(clk); 127 - goto err_clk; 128 - } 129 - 130 - clk_prepare_enable(clk); 131 - 132 - *socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset); 133 - *socuid <<= 32; 134 - *socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset); 135 - 136 - clk_disable_unprepare(clk); 137 - clk_put(clk); 138 - 139 - err_clk: 140 - iounmap(ocotp_base); 141 - return ret; 142 - } 143 - 144 - static int imx8mm_soc_revision(u32 *socrev, u64 *socuid) 109 + static int imx8mm_soc_revision(struct platform_device *pdev, u32 *socrev) 145 110 { 146 111 struct device_node *np __free(device_node) = 147 112 of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop"); ··· 125 156 126 157 iounmap(anatop_base); 127 158 128 - return imx8mm_soc_uid(socuid); 159 + return 0; 160 + } 161 + 162 + static int imx8m_soc_prepare(struct platform_device *pdev, const char *ocotp_compatible) 163 + { 164 + struct device_node *np __free(device_node) = 165 + of_find_compatible_node(NULL, NULL, ocotp_compatible); 166 + struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev); 167 + int ret = 0; 168 + 169 + if (!np) 170 + return -EINVAL; 171 + 172 + drvdata->ocotp_base = of_iomap(np, 0); 173 + if (!drvdata->ocotp_base) 174 + return -EINVAL; 175 + 176 + drvdata->clk = of_clk_get_by_name(np, NULL); 177 + if (IS_ERR(drvdata->clk)) { 178 + ret = PTR_ERR(drvdata->clk); 179 + goto err_clk; 180 + } 181 + 182 + return clk_prepare_enable(drvdata->clk); 183 + 184 + err_clk: 185 + iounmap(drvdata->ocotp_base); 186 + return ret; 187 + } 188 + 189 + static void imx8m_soc_unprepare(struct platform_device *pdev) 190 + { 191 + struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev); 192 + 193 + clk_disable_unprepare(drvdata->clk); 194 + clk_put(drvdata->clk); 195 + iounmap(drvdata->ocotp_base); 129 196 } 130 197 131 198 static const struct imx8_soc_data imx8mq_soc_data = { 132 199 .name = "i.MX8MQ", 200 + .ocotp_compatible = "fsl,imx8mq-ocotp", 133 201 .soc_revision = imx8mq_soc_revision, 202 + .soc_uid = imx8m_soc_uid, 134 203 }; 135 204 136 205 static const struct imx8_soc_data imx8mm_soc_data = { 137 206 .name = "i.MX8MM", 207 + .ocotp_compatible = "fsl,imx8mm-ocotp", 138 208 .soc_revision = imx8mm_soc_revision, 209 + .soc_uid = imx8m_soc_uid, 139 210 }; 140 211 141 212 static const struct imx8_soc_data imx8mn_soc_data = { 142 213 .name = "i.MX8MN", 214 + .ocotp_compatible = "fsl,imx8mm-ocotp", 143 215 .soc_revision = imx8mm_soc_revision, 216 + .soc_uid = imx8m_soc_uid, 144 217 }; 145 218 146 219 static const struct imx8_soc_data imx8mp_soc_data = { 147 220 .name = "i.MX8MP", 221 + .ocotp_compatible = "fsl,imx8mm-ocotp", 148 222 .soc_revision = imx8mm_soc_revision, 223 + .soc_uid = imx8mp_soc_uid, 149 224 }; 150 225 151 226 static __maybe_unused const struct of_device_id imx8_soc_match[] = { ··· 220 207 struct soc_device_attribute *soc_dev_attr; 221 208 struct platform_device *cpufreq_dev; 222 209 const struct imx8_soc_data *data; 210 + struct imx8_soc_drvdata *drvdata; 223 211 struct device *dev = &pdev->dev; 224 212 const struct of_device_id *id; 225 213 struct soc_device *soc_dev; 226 214 u32 soc_rev = 0; 227 - u64 soc_uid = 0; 215 + u64 soc_uid[2] = {0, 0}; 228 216 int ret; 229 217 230 218 soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr), GFP_KERNEL); 231 219 if (!soc_dev_attr) 232 220 return -ENOMEM; 221 + 222 + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); 223 + if (!drvdata) 224 + return -ENOMEM; 225 + 226 + platform_set_drvdata(pdev, drvdata); 233 227 234 228 soc_dev_attr->family = "Freescale i.MX"; 235 229 ··· 251 231 data = id->data; 252 232 if (data) { 253 233 soc_dev_attr->soc_id = data->name; 234 + ret = imx8m_soc_prepare(pdev, data->ocotp_compatible); 235 + if (ret) 236 + return ret; 237 + 254 238 if (data->soc_revision) { 255 - ret = data->soc_revision(&soc_rev, &soc_uid); 256 - if (ret) 239 + ret = data->soc_revision(pdev, &soc_rev); 240 + if (ret) { 241 + imx8m_soc_unprepare(pdev); 257 242 return ret; 243 + } 258 244 } 245 + if (data->soc_uid) { 246 + ret = data->soc_uid(pdev, soc_uid); 247 + if (ret) { 248 + imx8m_soc_unprepare(pdev); 249 + return ret; 250 + } 251 + } 252 + imx8m_soc_unprepare(pdev); 259 253 } 260 254 261 255 soc_dev_attr->revision = imx8_revision(dev, soc_rev); 262 256 if (!soc_dev_attr->revision) 263 257 return -ENOMEM; 264 258 265 - soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX", soc_uid); 259 + if (soc_uid[1]) 260 + soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX%016llX", 261 + soc_uid[1], soc_uid[0]); 262 + else 263 + soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX", 264 + soc_uid[0]); 266 265 if (!soc_dev_attr->serial_number) 267 266 return -ENOMEM; 268 267
+43 -10
drivers/soc/mediatek/mtk-dvfsrc.c
··· 446 446 return 0; 447 447 } 448 448 449 + static const struct dvfsrc_bw_constraints dvfsrc_bw_constr_v1 = { 0, 0, 0 }; 450 + static const struct dvfsrc_bw_constraints dvfsrc_bw_constr_v2 = { 451 + .max_dram_nom_bw = 255, 452 + .max_dram_peak_bw = 255, 453 + .max_dram_hrt_bw = 1023, 454 + }; 455 + 456 + static const struct dvfsrc_opp dvfsrc_opp_mt6893_lp4[] = { 457 + { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, 458 + { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, 459 + { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 }, 460 + { 0, 3 }, { 1, 3 }, { 2, 3 }, { 3, 3 }, 461 + { 1, 4 }, { 2, 4 }, { 3, 4 }, { 2, 5 }, 462 + { 3, 5 }, { 3, 6 }, { 4, 6 }, { 4, 7 }, 463 + }; 464 + 465 + static const struct dvfsrc_opp_desc dvfsrc_opp_mt6893_desc[] = { 466 + [0] = { 467 + .opps = dvfsrc_opp_mt6893_lp4, 468 + .num_opp = ARRAY_SIZE(dvfsrc_opp_mt6893_lp4), 469 + } 470 + }; 471 + 472 + static const struct dvfsrc_soc_data mt6893_data = { 473 + .opps_desc = dvfsrc_opp_mt6893_desc, 474 + .regs = dvfsrc_mt8195_regs, 475 + .get_target_level = dvfsrc_get_target_level_v2, 476 + .get_current_level = dvfsrc_get_current_level_v2, 477 + .get_vcore_level = dvfsrc_get_vcore_level_v2, 478 + .get_vscp_level = dvfsrc_get_vscp_level_v2, 479 + .set_dram_bw = dvfsrc_set_dram_bw_v1, 480 + .set_dram_peak_bw = dvfsrc_set_dram_peak_bw_v1, 481 + .set_dram_hrt_bw = dvfsrc_set_dram_hrt_bw_v1, 482 + .set_vcore_level = dvfsrc_set_vcore_level_v2, 483 + .set_vscp_level = dvfsrc_set_vscp_level_v2, 484 + .wait_for_opp_level = dvfsrc_wait_for_opp_level_v2, 485 + .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v1, 486 + .bw_constraints = &dvfsrc_bw_constr_v2, 487 + }; 488 + 449 489 static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp4[] = { 450 490 { 0, 0 }, { 0, 1 }, { 0, 2 }, { 1, 2 }, 451 491 }; ··· 509 469 } 510 470 }; 511 471 512 - static const struct dvfsrc_bw_constraints dvfsrc_bw_constr_mt8183 = { 0, 0, 0 }; 513 - 514 472 static const struct dvfsrc_soc_data mt8183_data = { 515 473 .opps_desc = dvfsrc_opp_mt8183_desc, 516 474 .regs = dvfsrc_mt8183_regs, ··· 520 482 .set_vcore_level = dvfsrc_set_vcore_level_v1, 521 483 .wait_for_opp_level = dvfsrc_wait_for_opp_level_v1, 522 484 .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v1, 523 - .bw_constraints = &dvfsrc_bw_constr_mt8183, 485 + .bw_constraints = &dvfsrc_bw_constr_v1, 524 486 }; 525 487 526 488 static const struct dvfsrc_opp dvfsrc_opp_mt8195_lp4[] = { ··· 539 501 } 540 502 }; 541 503 542 - static const struct dvfsrc_bw_constraints dvfsrc_bw_constr_mt8195 = { 543 - .max_dram_nom_bw = 255, 544 - .max_dram_peak_bw = 255, 545 - .max_dram_hrt_bw = 1023, 546 - }; 547 - 548 504 static const struct dvfsrc_soc_data mt8195_data = { 549 505 .opps_desc = dvfsrc_opp_mt8195_desc, 550 506 .regs = dvfsrc_mt8195_regs, ··· 553 521 .set_vscp_level = dvfsrc_set_vscp_level_v2, 554 522 .wait_for_opp_level = dvfsrc_wait_for_opp_level_v2, 555 523 .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v1, 556 - .bw_constraints = &dvfsrc_bw_constr_mt8195, 524 + .bw_constraints = &dvfsrc_bw_constr_v2, 557 525 }; 558 526 559 527 static const struct of_device_id mtk_dvfsrc_of_match[] = { 528 + { .compatible = "mediatek,mt6893-dvfsrc", .data = &mt6893_data }, 560 529 { .compatible = "mediatek,mt8183-dvfsrc", .data = &mt8183_data }, 561 530 { .compatible = "mediatek,mt8195-dvfsrc", .data = &mt8195_data }, 562 531 { /* sentinel */ }
+493 -4
drivers/soc/qcom/llcc-qcom.c
··· 35 35 #define ATTR0_RES_WAYS_MASK GENMASK(15, 0) 36 36 #define ATTR0_BONUS_WAYS_MASK GENMASK(31, 16) 37 37 #define ATTR0_BONUS_WAYS_SHIFT 16 38 + #define ATTR2_PROBE_TARGET_WAYS_MASK BIT(4) 39 + #define ATTR2_FIXED_SIZE_MASK BIT(8) 40 + #define ATTR2_PRIORITY_MASK GENMASK(14, 12) 41 + #define ATTR2_PARENT_SCID_MASK GENMASK(21, 16) 42 + #define ATTR2_IN_A_GROUP_MASK BIT(24) 38 43 #define LLCC_STATUS_READ_DELAY 100 39 44 40 45 #define CACHE_LINE_SIZE_SHIFT 6 ··· 54 49 #define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n) 55 50 #define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n) 56 51 #define LLCC_TRP_ATTR2_CFGn(n) (0x21100 + SZ_4 * n) 52 + #define LLCC_V6_TRP_ATTR0_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR0_CFG] + SZ_64 * (n)) 53 + #define LLCC_V6_TRP_ATTR1_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR1_CFG] + SZ_64 * (n)) 54 + #define LLCC_V6_TRP_ATTR2_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR2_CFG] + SZ_64 * (n)) 55 + #define LLCC_V6_TRP_ATTR3_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR3_CFG] + SZ_64 * (n)) 57 56 58 57 #define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00 59 58 #define LLCC_TRP_PCB_ACT 0x21f04 ··· 75 66 #define LLCC_VERSION_2_0_0_0 0x02000000 76 67 #define LLCC_VERSION_2_1_0_0 0x02010000 77 68 #define LLCC_VERSION_4_1_0_0 0x04010000 69 + #define LLCC_VERSION_6_0_0_0 0X06000000 78 70 79 71 /** 80 72 * struct llcc_slice_config - Data associated with the llcc slice ··· 116 106 * ovcap_en. 117 107 * @vict_prio: When current scid is under-capacity, allocate over other 118 108 * lower-than victim priority-line threshold scid. 109 + * @parent_slice_id: For grouped slices, specifies the slice id of the parent. 119 110 */ 120 111 struct llcc_slice_config { 121 112 u32 usecase_id; ··· 141 130 bool ovcap_en; 142 131 bool ovcap_prio; 143 132 bool vict_prio; 133 + u32 parent_slice_id; 144 134 }; 145 135 146 136 struct qcom_llcc_config { ··· 165 153 enum llcc_reg_offset { 166 154 LLCC_COMMON_HW_INFO, 167 155 LLCC_COMMON_STATUS0, 156 + LLCC_TRP_ATTR0_CFG, 157 + LLCC_TRP_ATTR1_CFG, 158 + LLCC_TRP_ATTR2_CFG, 159 + LLCC_TRP_ATTR3_CFG, 160 + LLCC_TRP_SID_DIS_CAP_ALLOC, 161 + LLCC_TRP_ALGO_STALE_EN, 162 + LLCC_TRP_ALGO_STALE_CAP_EN, 163 + LLCC_TRP_ALGO_MRU0, 164 + LLCC_TRP_ALGO_MRU1, 165 + LLCC_TRP_ALGO_ALLOC0, 166 + LLCC_TRP_ALGO_ALLOC1, 167 + LLCC_TRP_ALGO_ALLOC2, 168 + LLCC_TRP_ALGO_ALLOC3, 169 + LLCC_TRP_WRS_EN, 170 + LLCC_TRP_WRS_CACHEABLE_EN, 168 171 }; 169 172 170 173 static const struct llcc_slice_config ipq5424_data[] = { ··· 2689 2662 }, 2690 2663 }; 2691 2664 2665 + static const struct llcc_slice_config sm8750_data[] = { 2666 + { 2667 + .usecase_id = LLCC_CPUSS, 2668 + .slice_id = 1, 2669 + .max_cap = 5120, 2670 + .priority = 1, 2671 + .bonus_ways = 0xffffffff, 2672 + .activate_on_init = true, 2673 + .write_scid_en = true, 2674 + }, { 2675 + .usecase_id = LLCC_MDMHPFX, 2676 + .slice_id = 24, 2677 + .max_cap = 1024, 2678 + .priority = 5, 2679 + .fixed_size = true, 2680 + .bonus_ways = 0xffffffff, 2681 + }, { 2682 + .usecase_id = LLCC_VIDSC0, 2683 + .slice_id = 2, 2684 + .max_cap = 512, 2685 + .priority = 4, 2686 + .fixed_size = true, 2687 + .bonus_ways = 0xffffffff, 2688 + }, { 2689 + .usecase_id = LLCC_AUDIO, 2690 + .slice_id = 35, 2691 + .max_cap = 512, 2692 + .priority = 1, 2693 + .fixed_size = true, 2694 + .bonus_ways = 0xffffffff, 2695 + }, { 2696 + .usecase_id = LLCC_MDMHPGRW, 2697 + .slice_id = 25, 2698 + .max_cap = 1024, 2699 + .priority = 5, 2700 + .bonus_ways = 0xffffffff, 2701 + }, { 2702 + .usecase_id = LLCC_MODHW, 2703 + .slice_id = 26, 2704 + .max_cap = 1024, 2705 + .priority = 1, 2706 + .fixed_size = true, 2707 + .bonus_ways = 0xffffffff, 2708 + }, { 2709 + .usecase_id = LLCC_CMPT, 2710 + .slice_id = 34, 2711 + .max_cap = 4096, 2712 + .priority = 1, 2713 + .fixed_size = true, 2714 + .bonus_ways = 0xffffffff, 2715 + }, { 2716 + .usecase_id = LLCC_GPUHTW, 2717 + .slice_id = 11, 2718 + .max_cap = 512, 2719 + .priority = 1, 2720 + .fixed_size = true, 2721 + .bonus_ways = 0xffffffff, 2722 + }, { 2723 + .usecase_id = LLCC_GPU, 2724 + .slice_id = 9, 2725 + .max_cap = 5632, 2726 + .priority = 1, 2727 + .fixed_size = true, 2728 + .bonus_ways = 0xffffffff, 2729 + .write_scid_en = true, 2730 + .write_scid_cacheable_en = true 2731 + }, { 2732 + .usecase_id = LLCC_MMUHWT, 2733 + .slice_id = 18, 2734 + .max_cap = 768, 2735 + .priority = 1, 2736 + .fixed_size = true, 2737 + .bonus_ways = 0xffffffff, 2738 + .activate_on_init = true, 2739 + }, { 2740 + .usecase_id = LLCC_DISP, 2741 + .slice_id = 16, 2742 + .max_cap = 7168, 2743 + .priority = 1, 2744 + .fixed_size = true, 2745 + .bonus_ways = 0xffffffff, 2746 + .cache_mode = 2, 2747 + .stale_en = true, 2748 + }, { 2749 + .usecase_id = LLCC_VIDFW, 2750 + .slice_id = 17, 2751 + .priority = 4, 2752 + .fixed_size = true, 2753 + .bonus_ways = 0xffffffff, 2754 + }, { 2755 + .usecase_id = LLCC_CAMFW, 2756 + .slice_id = 20, 2757 + .priority = 4, 2758 + .fixed_size = true, 2759 + .bonus_ways = 0xffffffff, 2760 + }, { 2761 + .usecase_id = LLCC_MDMPNG, 2762 + .slice_id = 27, 2763 + .max_cap = 256, 2764 + .priority = 5, 2765 + .fixed_size = true, 2766 + .bonus_ways = 0xf0000000, 2767 + }, { 2768 + .usecase_id = LLCC_AUDHW, 2769 + .slice_id = 22, 2770 + .max_cap = 512, 2771 + .priority = 1, 2772 + .fixed_size = true, 2773 + .bonus_ways = 0xffffffff, 2774 + }, { 2775 + .usecase_id = LLCC_CVP, 2776 + .slice_id = 8, 2777 + .max_cap = 800, 2778 + .priority = 5, 2779 + .fixed_size = true, 2780 + .bonus_ways = 0xffffffff, 2781 + .vict_prio = true, 2782 + }, { 2783 + .usecase_id = LLCC_MODPE, 2784 + .slice_id = 29, 2785 + .max_cap = 256, 2786 + .priority = 1, 2787 + .fixed_size = true, 2788 + .bonus_ways = 0xf0000000, 2789 + .alloc_oneway_en = true, 2790 + }, { 2791 + .usecase_id = LLCC_WRCACHE, 2792 + .slice_id = 31, 2793 + .max_cap = 512, 2794 + .priority = 1, 2795 + .fixed_size = true, 2796 + .bonus_ways = 0xffffffff, 2797 + .activate_on_init = true, 2798 + }, { 2799 + .usecase_id = LLCC_CVPFW, 2800 + .slice_id = 19, 2801 + .max_cap = 64, 2802 + .priority = 4, 2803 + .fixed_size = true, 2804 + .bonus_ways = 0xffffffff, 2805 + }, { 2806 + .usecase_id = LLCC_CMPTHCP, 2807 + .slice_id = 15, 2808 + .max_cap = 256, 2809 + .priority = 4, 2810 + .fixed_size = true, 2811 + .bonus_ways = 0xffffffff, 2812 + }, { 2813 + .usecase_id = LLCC_LCPDARE, 2814 + .slice_id = 30, 2815 + .max_cap = 128, 2816 + .priority = 5, 2817 + .fixed_size = true, 2818 + .bonus_ways = 0xffffffff, 2819 + .activate_on_init = true, 2820 + .alloc_oneway_en = true, 2821 + }, { 2822 + .usecase_id = LLCC_AENPU, 2823 + .slice_id = 3, 2824 + .max_cap = 3072, 2825 + .priority = 1, 2826 + .fixed_size = true, 2827 + .bonus_ways = 0xffffffff, 2828 + .cache_mode = 2, 2829 + }, { 2830 + .usecase_id = LLCC_ISLAND1, 2831 + .slice_id = 12, 2832 + .max_cap = 7936, 2833 + .priority = 7, 2834 + .fixed_size = true, 2835 + .bonus_ways = 0x7fffffff, 2836 + }, { 2837 + .usecase_id = LLCC_DISP_WB, 2838 + .slice_id = 23, 2839 + .max_cap = 512, 2840 + .priority = 4, 2841 + .fixed_size = true, 2842 + .bonus_ways = 0xffffffff, 2843 + }, { 2844 + .usecase_id = LLCC_VIDVSP, 2845 + .slice_id = 4, 2846 + .max_cap = 256, 2847 + .priority = 4, 2848 + .fixed_size = true, 2849 + .bonus_ways = 0xffffffff, 2850 + }, { 2851 + .usecase_id = LLCC_VIDDEC, 2852 + .slice_id = 5, 2853 + .max_cap = 6144, 2854 + .priority = 4, 2855 + .fixed_size = true, 2856 + .bonus_ways = 0xffffffff, 2857 + .cache_mode = 2, 2858 + .ovcap_prio = true, 2859 + .parent_slice_id = 33, 2860 + }, { 2861 + .usecase_id = LLCC_CAMOFE, 2862 + .slice_id = 33, 2863 + .max_cap = 6144, 2864 + .priority = 4, 2865 + .fixed_size = true, 2866 + .bonus_ways = 0xffffffff, 2867 + .stale_en = true, 2868 + .ovcap_prio = true, 2869 + .parent_slice_id = 33, 2870 + }, { 2871 + .usecase_id = LLCC_CAMRTIP, 2872 + .slice_id = 13, 2873 + .max_cap = 1024, 2874 + .priority = 4, 2875 + .fixed_size = true, 2876 + .bonus_ways = 0xffffffff, 2877 + .stale_en = true, 2878 + .ovcap_prio = true, 2879 + .parent_slice_id = 33, 2880 + }, { 2881 + .usecase_id = LLCC_CAMSRTIP, 2882 + .slice_id = 14, 2883 + .max_cap = 6144, 2884 + .priority = 4, 2885 + .fixed_size = true, 2886 + .bonus_ways = 0xffffffff, 2887 + .stale_en = true, 2888 + .ovcap_prio = true, 2889 + .parent_slice_id = 33, 2890 + }, { 2891 + .usecase_id = LLCC_CAMRTRF, 2892 + .slice_id = 7, 2893 + .max_cap = 3584, 2894 + .priority = 1, 2895 + .fixed_size = true, 2896 + .bonus_ways = 0xffffffff, 2897 + .stale_en = true, 2898 + .ovcap_prio = true, 2899 + .parent_slice_id = 33, 2900 + }, { 2901 + .usecase_id = LLCC_CAMSRTRF, 2902 + .slice_id = 21, 2903 + .max_cap = 6144, 2904 + .priority = 1, 2905 + .fixed_size = true, 2906 + .bonus_ways = 0xffffffff, 2907 + .stale_en = true, 2908 + .ovcap_prio = true, 2909 + .parent_slice_id = 33, 2910 + }, { 2911 + .usecase_id = LLCC_CPUSSMPAM, 2912 + .slice_id = 6, 2913 + .max_cap = 2048, 2914 + .priority = 1, 2915 + .fixed_size = true, 2916 + .bonus_ways = 0xffffffff, 2917 + .activate_on_init = true, 2918 + .write_scid_en = true, 2919 + }, 2920 + }; 2921 + 2692 2922 static const struct llcc_slice_config qcs615_data[] = { 2693 2923 { 2694 2924 .usecase_id = LLCC_CPUSS, ··· 3445 3161 .drp_ecc_db_err_syn0 = 0x52120, 3446 3162 }; 3447 3163 3164 + static const struct llcc_edac_reg_offset llcc_v6_edac_reg_offset = { 3165 + .trp_ecc_error_status0 = 0x47448, 3166 + .trp_ecc_error_status1 = 0x47450, 3167 + .trp_ecc_sb_err_syn0 = 0x47490, 3168 + .trp_ecc_db_err_syn0 = 0x474d0, 3169 + .trp_ecc_error_cntr_clear = 0x47444, 3170 + .trp_interrupt_0_status = 0x47600, 3171 + .trp_interrupt_0_clear = 0x47604, 3172 + .trp_interrupt_0_enable = 0x47608, 3173 + 3174 + /* LLCC Common registers */ 3175 + .cmn_status0 = 0x6400c, 3176 + .cmn_interrupt_0_enable = 0x6401c, 3177 + .cmn_interrupt_2_enable = 0x6403c, 3178 + 3179 + /* LLCC DRP registers */ 3180 + .drp_ecc_error_cfg = 0x80000, 3181 + .drp_ecc_error_cntr_clear = 0x80004, 3182 + .drp_interrupt_status = 0x80020, 3183 + .drp_interrupt_clear = 0x80028, 3184 + .drp_interrupt_enable = 0x8002c, 3185 + .drp_ecc_error_status0 = 0x820f4, 3186 + .drp_ecc_error_status1 = 0x820f8, 3187 + .drp_ecc_sb_err_syn0 = 0x820fc, 3188 + .drp_ecc_db_err_syn0 = 0x82120, 3189 + }; 3190 + 3448 3191 /* LLCC register offset starting from v1.0.0 */ 3449 3192 static const u32 llcc_v1_reg_offset[] = { 3450 3193 [LLCC_COMMON_HW_INFO] = 0x00030000, ··· 3482 3171 static const u32 llcc_v2_1_reg_offset[] = { 3483 3172 [LLCC_COMMON_HW_INFO] = 0x00034000, 3484 3173 [LLCC_COMMON_STATUS0] = 0x0003400c, 3174 + }; 3175 + 3176 + /* LLCC register offset starting from v6.0.0 */ 3177 + static const u32 llcc_v6_reg_offset[] = { 3178 + [LLCC_COMMON_HW_INFO] = 0x00064000, 3179 + [LLCC_COMMON_STATUS0] = 0x0006400c, 3180 + [LLCC_TRP_ATTR0_CFG] = 0x00041000, 3181 + [LLCC_TRP_ATTR1_CFG] = 0x00041008, 3182 + [LLCC_TRP_ATTR2_CFG] = 0x00041010, 3183 + [LLCC_TRP_ATTR3_CFG] = 0x00041014, 3184 + [LLCC_TRP_SID_DIS_CAP_ALLOC] = 0x00042000, 3185 + [LLCC_TRP_ALGO_STALE_EN] = 0x00042008, 3186 + [LLCC_TRP_ALGO_STALE_CAP_EN] = 0x00042010, 3187 + [LLCC_TRP_ALGO_MRU0] = 0x00042018, 3188 + [LLCC_TRP_ALGO_MRU1] = 0x00042020, 3189 + [LLCC_TRP_ALGO_ALLOC0] = 0x00042028, 3190 + [LLCC_TRP_ALGO_ALLOC1] = 0x00042030, 3191 + [LLCC_TRP_ALGO_ALLOC2] = 0x00042038, 3192 + [LLCC_TRP_ALGO_ALLOC3] = 0x00042040, 3193 + [LLCC_TRP_WRS_EN] = 0x00042080, 3194 + [LLCC_TRP_WRS_CACHEABLE_EN] = 0x00042088, 3485 3195 }; 3486 3196 3487 3197 static const struct qcom_llcc_config qcs615_cfg[] = { ··· 3711 3379 }, 3712 3380 }; 3713 3381 3382 + static const struct qcom_llcc_config sm8750_cfg[] = { 3383 + { 3384 + .sct_data = sm8750_data, 3385 + .size = ARRAY_SIZE(sm8750_data), 3386 + .skip_llcc_cfg = false, 3387 + .reg_offset = llcc_v6_reg_offset, 3388 + .edac_reg_offset = &llcc_v6_edac_reg_offset, 3389 + }, 3390 + }; 3391 + 3714 3392 static const struct qcom_llcc_config x1e80100_cfg[] = { 3715 3393 { 3716 3394 .sct_data = x1e80100_data, ··· 3829 3487 static const struct qcom_sct_config sm8650_cfgs = { 3830 3488 .llcc_config = sm8650_cfg, 3831 3489 .num_config = ARRAY_SIZE(sm8650_cfg), 3490 + }; 3491 + 3492 + static const struct qcom_sct_config sm8750_cfgs = { 3493 + .llcc_config = sm8750_cfg, 3494 + .num_config = ARRAY_SIZE(sm8750_cfg), 3832 3495 }; 3833 3496 3834 3497 static const struct qcom_sct_config x1e80100_cfgs = { ··· 4216 3869 return ret; 4217 3870 } 4218 3871 3872 + static int _qcom_llcc_cfg_program_v6(const struct llcc_slice_config *config, 3873 + const struct qcom_llcc_config *cfg) 3874 + { 3875 + u32 stale_en, stale_cap_en, mru_uncap_en, mru_rollover; 3876 + u32 alloc_oneway_en, ovcap_en, ovcap_prio, vict_prio; 3877 + u32 attr0_cfg, attr1_cfg, attr2_cfg, attr3_cfg; 3878 + u32 attr0_val, attr1_val, attr2_val, attr3_val; 3879 + u32 slice_offset, reg_offset; 3880 + struct llcc_slice_desc *desc; 3881 + u32 wren, wr_cache_en; 3882 + int ret; 3883 + 3884 + attr0_cfg = LLCC_V6_TRP_ATTR0_CFGn(config->slice_id); 3885 + attr1_cfg = LLCC_V6_TRP_ATTR1_CFGn(config->slice_id); 3886 + attr2_cfg = LLCC_V6_TRP_ATTR2_CFGn(config->slice_id); 3887 + attr3_cfg = LLCC_V6_TRP_ATTR3_CFGn(config->slice_id); 3888 + 3889 + attr0_val = config->res_ways; 3890 + attr1_val = config->bonus_ways; 3891 + attr2_val = config->cache_mode; 3892 + attr2_val |= FIELD_PREP(ATTR2_PROBE_TARGET_WAYS_MASK, config->probe_target_ways); 3893 + attr2_val |= FIELD_PREP(ATTR2_FIXED_SIZE_MASK, config->fixed_size); 3894 + attr2_val |= FIELD_PREP(ATTR2_PRIORITY_MASK, config->priority); 3895 + 3896 + if (config->parent_slice_id && config->fixed_size) { 3897 + attr2_val |= FIELD_PREP(ATTR2_PARENT_SCID_MASK, config->parent_slice_id); 3898 + attr2_val |= ATTR2_IN_A_GROUP_MASK; 3899 + } 3900 + 3901 + attr3_val = MAX_CAP_TO_BYTES(config->max_cap); 3902 + attr3_val /= drv_data->num_banks; 3903 + attr3_val >>= CACHE_LINE_SIZE_SHIFT; 3904 + 3905 + ret = regmap_write(drv_data->bcast_regmap, attr0_cfg, attr0_val); 3906 + if (ret) 3907 + return ret; 3908 + 3909 + ret = regmap_write(drv_data->bcast_regmap, attr1_cfg, attr1_val); 3910 + if (ret) 3911 + return ret; 3912 + 3913 + ret = regmap_write(drv_data->bcast_regmap, attr2_cfg, attr2_val); 3914 + if (ret) 3915 + return ret; 3916 + 3917 + ret = regmap_write(drv_data->bcast_regmap, attr3_cfg, attr3_val); 3918 + if (ret) 3919 + return ret; 3920 + 3921 + slice_offset = config->slice_id % 32; 3922 + reg_offset = (config->slice_id / 32) * 4; 3923 + 3924 + wren = config->write_scid_en << slice_offset; 3925 + ret = regmap_update_bits(drv_data->bcast_regmap, 3926 + cfg->reg_offset[LLCC_TRP_WRS_EN] + reg_offset, 3927 + BIT(slice_offset), wren); 3928 + if (ret) 3929 + return ret; 3930 + 3931 + wr_cache_en = config->write_scid_cacheable_en << slice_offset; 3932 + ret = regmap_update_bits(drv_data->bcast_regmap, 3933 + cfg->reg_offset[LLCC_TRP_WRS_CACHEABLE_EN] + reg_offset, 3934 + BIT(slice_offset), wr_cache_en); 3935 + if (ret) 3936 + return ret; 3937 + 3938 + stale_en = config->stale_en << slice_offset; 3939 + ret = regmap_update_bits(drv_data->bcast_regmap, 3940 + cfg->reg_offset[LLCC_TRP_ALGO_STALE_EN] + reg_offset, 3941 + BIT(slice_offset), stale_en); 3942 + if (ret) 3943 + return ret; 3944 + 3945 + stale_cap_en = config->stale_cap_en << slice_offset; 3946 + ret = regmap_update_bits(drv_data->bcast_regmap, 3947 + cfg->reg_offset[LLCC_TRP_ALGO_STALE_CAP_EN] + reg_offset, 3948 + BIT(slice_offset), stale_cap_en); 3949 + if (ret) 3950 + return ret; 3951 + 3952 + mru_uncap_en = config->mru_uncap_en << slice_offset; 3953 + ret = regmap_update_bits(drv_data->bcast_regmap, 3954 + cfg->reg_offset[LLCC_TRP_ALGO_MRU0] + reg_offset, 3955 + BIT(slice_offset), mru_uncap_en); 3956 + if (ret) 3957 + return ret; 3958 + 3959 + mru_rollover = config->mru_rollover << slice_offset; 3960 + ret = regmap_update_bits(drv_data->bcast_regmap, 3961 + cfg->reg_offset[LLCC_TRP_ALGO_MRU1] + reg_offset, 3962 + BIT(slice_offset), mru_rollover); 3963 + if (ret) 3964 + return ret; 3965 + 3966 + alloc_oneway_en = config->alloc_oneway_en << slice_offset; 3967 + ret = regmap_update_bits(drv_data->bcast_regmap, 3968 + cfg->reg_offset[LLCC_TRP_ALGO_ALLOC0] + reg_offset, 3969 + BIT(slice_offset), alloc_oneway_en); 3970 + if (ret) 3971 + return ret; 3972 + 3973 + ovcap_en = config->ovcap_en << slice_offset; 3974 + ret = regmap_update_bits(drv_data->bcast_regmap, 3975 + cfg->reg_offset[LLCC_TRP_ALGO_ALLOC1] + reg_offset, 3976 + BIT(slice_offset), ovcap_en); 3977 + if (ret) 3978 + return ret; 3979 + 3980 + ovcap_prio = config->ovcap_prio << slice_offset; 3981 + ret = regmap_update_bits(drv_data->bcast_regmap, 3982 + cfg->reg_offset[LLCC_TRP_ALGO_ALLOC2] + reg_offset, 3983 + BIT(slice_offset), ovcap_prio); 3984 + if (ret) 3985 + return ret; 3986 + 3987 + vict_prio = config->vict_prio << slice_offset; 3988 + ret = regmap_update_bits(drv_data->bcast_regmap, 3989 + cfg->reg_offset[LLCC_TRP_ALGO_ALLOC3] + reg_offset, 3990 + BIT(slice_offset), vict_prio); 3991 + if (ret) 3992 + return ret; 3993 + 3994 + if (config->activate_on_init) { 3995 + desc = llcc_slice_getd(config->usecase_id); 3996 + if (PTR_ERR_OR_ZERO(desc)) 3997 + return -EINVAL; 3998 + 3999 + ret = llcc_slice_activate(desc); 4000 + } 4001 + 4002 + return ret; 4003 + } 4004 + 4219 4005 static int qcom_llcc_cfg_program(struct platform_device *pdev, 4220 4006 const struct qcom_llcc_config *cfg) 4221 4007 { ··· 4360 3880 sz = drv_data->cfg_size; 4361 3881 llcc_table = drv_data->cfg; 4362 3882 4363 - for (i = 0; i < sz; i++) { 4364 - ret = _qcom_llcc_cfg_program(&llcc_table[i], cfg); 4365 - if (ret) 4366 - return ret; 3883 + if (drv_data->version >= LLCC_VERSION_6_0_0_0) { 3884 + for (i = 0; i < sz; i++) { 3885 + ret = _qcom_llcc_cfg_program_v6(&llcc_table[i], cfg); 3886 + if (ret) 3887 + return ret; 3888 + } 3889 + } else { 3890 + for (i = 0; i < sz; i++) { 3891 + ret = _qcom_llcc_cfg_program(&llcc_table[i], cfg); 3892 + if (ret) 3893 + return ret; 3894 + } 4367 3895 } 4368 3896 4369 3897 return ret; ··· 4590 4102 { .compatible = "qcom,sm8450-llcc", .data = &sm8450_cfgs }, 4591 4103 { .compatible = "qcom,sm8550-llcc", .data = &sm8550_cfgs }, 4592 4104 { .compatible = "qcom,sm8650-llcc", .data = &sm8650_cfgs }, 4105 + { .compatible = "qcom,sm8750-llcc", .data = &sm8750_cfgs }, 4593 4106 { .compatible = "qcom,x1e80100-llcc", .data = &x1e80100_cfgs }, 4594 4107 { } 4595 4108 };
-4
drivers/soc/qcom/pmic_glink.c
··· 371 371 __pmic_glink = NULL; 372 372 } 373 373 374 - static const unsigned long pmic_glink_sc8280xp_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | 375 - BIT(PMIC_GLINK_CLIENT_ALTMODE); 376 - 377 374 static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | 378 375 BIT(PMIC_GLINK_CLIENT_ALTMODE) | 379 376 BIT(PMIC_GLINK_CLIENT_UCSI); 380 377 381 378 static const struct of_device_id pmic_glink_of_match[] = { 382 - { .compatible = "qcom,sc8280xp-pmic-glink", .data = &pmic_glink_sc8280xp_client_mask }, 383 379 { .compatible = "qcom,pmic-glink", .data = &pmic_glink_sm8450_client_mask }, 384 380 {} 385 381 };
+11
drivers/soc/qcom/qcom_pd_mapper.c
··· 488 488 NULL, 489 489 }; 490 490 491 + static const struct qcom_pdm_domain_data *sm7150_domains[] = { 492 + &adsp_audio_pd, 493 + &adsp_root_pd, 494 + &adsp_sensor_pd, 495 + &cdsp_root_pd, 496 + &mpss_root_pd_gps, 497 + &mpss_wlan_pd, 498 + NULL, 499 + }; 500 + 491 501 static const struct qcom_pdm_domain_data *sm8150_domains[] = { 492 502 &adsp_audio_pd, 493 503 &adsp_root_pd, ··· 575 565 { .compatible = "qcom,sm4250", .data = sm6115_domains, }, 576 566 { .compatible = "qcom,sm6115", .data = sm6115_domains, }, 577 567 { .compatible = "qcom,sm6350", .data = sm6350_domains, }, 568 + { .compatible = "qcom,sm7150", .data = sm7150_domains, }, 578 569 { .compatible = "qcom,sm7225", .data = sm6350_domains, }, 579 570 { .compatible = "qcom,sm7325", .data = sc7280_domains, }, 580 571 { .compatible = "qcom,sm8150", .data = sm8150_domains, },
+1 -1
drivers/soc/qcom/smem.c
··· 86 86 #define SMEM_GLOBAL_HOST 0xfffe 87 87 88 88 /* Max number of processors/hosts in a system */ 89 - #define SMEM_HOST_COUNT 20 89 + #define SMEM_HOST_COUNT 25 90 90 91 91 /** 92 92 * struct smem_proc_comm - proc_comm communication struct (legacy)
+1 -1
drivers/soc/qcom/smp2p.c
··· 575 575 smp2p->mbox_client.knows_txdone = true; 576 576 smp2p->mbox_chan = mbox_request_channel(&smp2p->mbox_client, 0); 577 577 if (IS_ERR(smp2p->mbox_chan)) { 578 - if (PTR_ERR(smp2p->mbox_chan) != -ENODEV) 578 + if (PTR_ERR(smp2p->mbox_chan) != -ENOENT) 579 579 return PTR_ERR(smp2p->mbox_chan); 580 580 581 581 smp2p->mbox_chan = NULL;
+1
drivers/soc/qcom/socinfo.c
··· 444 444 { qcom_board_id(IPQ5302) }, 445 445 { qcom_board_id(QCS8550) }, 446 446 { qcom_board_id(QCM8550) }, 447 + { qcom_board_id(SM8750) }, 447 448 { qcom_board_id(IPQ5300) }, 448 449 { qcom_board_id(IPQ5321) }, 449 450 { qcom_board_id(IPQ5424) },
+11
drivers/soc/renesas/Kconfig
··· 393 393 help 394 394 This enables support for the Renesas RZ/G3E SoC variants. 395 395 396 + config ARCH_R9A09G056 397 + bool "ARM64 Platform support for RZ/V2N" 398 + default y if ARCH_RENESAS 399 + select SYS_R9A09G056 400 + help 401 + This enables support for the Renesas RZ/V2N SoC variants. 402 + 396 403 config ARCH_R9A09G057 397 404 bool "ARM64 Platform support for RZ/V2H(P)" 398 405 default y if ARCH_RENESAS ··· 444 437 445 438 config SYS_R9A09G047 446 439 bool "Renesas RZ/G3E System controller support" if COMPILE_TEST 440 + select SYSC_RZ 441 + 442 + config SYS_R9A09G056 443 + bool "Renesas RZ/V2N System controller support" if COMPILE_TEST 447 444 select SYSC_RZ 448 445 449 446 config SYS_R9A09G057
+1
drivers/soc/renesas/Makefile
··· 8 8 endif 9 9 obj-$(CONFIG_SYSC_R9A08G045) += r9a08g045-sysc.o 10 10 obj-$(CONFIG_SYS_R9A09G047) += r9a09g047-sys.o 11 + obj-$(CONFIG_SYS_R9A09G056) += r9a09g056-sys.o 11 12 obj-$(CONFIG_SYS_R9A09G057) += r9a09g057-sys.o 12 13 13 14 # Family
+75
drivers/soc/renesas/r9a09g056-sys.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * RZ/V2N System controller (SYS) driver 4 + * 5 + * Copyright (C) 2025 Renesas Electronics Corp. 6 + */ 7 + 8 + #include <linux/bitfield.h> 9 + #include <linux/bits.h> 10 + #include <linux/device.h> 11 + #include <linux/init.h> 12 + #include <linux/io.h> 13 + 14 + #include "rz-sysc.h" 15 + 16 + /* Register Offsets */ 17 + #define SYS_LSI_MODE 0x300 18 + #define SYS_LSI_MODE_SEC_EN BIT(16) 19 + /* 20 + * BOOTPLLCA[1:0] 21 + * [0,0] => 1.1GHZ 22 + * [0,1] => 1.5GHZ 23 + * [1,0] => 1.6GHZ 24 + * [1,1] => 1.7GHZ 25 + */ 26 + #define SYS_LSI_MODE_STAT_BOOTPLLCA55 GENMASK(12, 11) 27 + #define SYS_LSI_MODE_CA55_1_7GHZ 0x3 28 + 29 + #define SYS_LSI_PRR 0x308 30 + #define SYS_LSI_PRR_GPU_DIS BIT(0) 31 + #define SYS_LSI_PRR_ISP_DIS BIT(4) 32 + 33 + #define SYS_RZV2N_FEATURE_G31 BIT(0) 34 + #define SYS_RZV2N_FEATURE_C55 BIT(1) 35 + #define SYS_RZV2N_FEATURE_SEC BIT(2) 36 + 37 + static void rzv2n_sys_print_id(struct device *dev, 38 + void __iomem *sysc_base, 39 + struct soc_device_attribute *soc_dev_attr) 40 + { 41 + u32 prr_val, mode_val; 42 + u8 feature_flags; 43 + 44 + prr_val = readl(sysc_base + SYS_LSI_PRR); 45 + mode_val = readl(sysc_base + SYS_LSI_MODE); 46 + 47 + /* Check GPU, ISP and Cryptographic configuration */ 48 + feature_flags = !(prr_val & SYS_LSI_PRR_GPU_DIS) ? SYS_RZV2N_FEATURE_G31 : 0; 49 + feature_flags |= !(prr_val & SYS_LSI_PRR_ISP_DIS) ? SYS_RZV2N_FEATURE_C55 : 0; 50 + feature_flags |= (mode_val & SYS_LSI_MODE_SEC_EN) ? SYS_RZV2N_FEATURE_SEC : 0; 51 + 52 + dev_info(dev, "Detected Renesas %s %sn%d Rev %s%s%s%s%s\n", soc_dev_attr->family, 53 + soc_dev_attr->soc_id, 41 + feature_flags, soc_dev_attr->revision, 54 + feature_flags ? " with" : "", 55 + feature_flags & SYS_RZV2N_FEATURE_G31 ? " GE3D (Mali-G31)" : "", 56 + feature_flags & SYS_RZV2N_FEATURE_SEC ? " Cryptographic engine" : "", 57 + feature_flags & SYS_RZV2N_FEATURE_C55 ? " ISP (Mali-C55)" : ""); 58 + 59 + /* Check CA55 PLL configuration */ 60 + if (FIELD_GET(SYS_LSI_MODE_STAT_BOOTPLLCA55, mode_val) != SYS_LSI_MODE_CA55_1_7GHZ) 61 + dev_warn(dev, "CA55 PLL is not set to 1.7GHz\n"); 62 + } 63 + 64 + static const struct rz_sysc_soc_id_init_data rzv2n_sys_soc_id_init_data __initconst = { 65 + .family = "RZ/V2N", 66 + .id = 0x867d447, 67 + .devid_offset = 0x304, 68 + .revision_mask = GENMASK(31, 28), 69 + .specific_id_mask = GENMASK(27, 0), 70 + .print_id = rzv2n_sys_print_id, 71 + }; 72 + 73 + const struct rz_sysc_init_data rzv2n_sys_init_data = { 74 + .soc_id_init_data = &rzv2n_sys_soc_id_init_data, 75 + };
+3
drivers/soc/renesas/rz-sysc.c
··· 88 88 #ifdef CONFIG_SYS_R9A09G047 89 89 { .compatible = "renesas,r9a09g047-sys", .data = &rzg3e_sys_init_data }, 90 90 #endif 91 + #ifdef CONFIG_SYS_R9A09G056 92 + { .compatible = "renesas,r9a09g056-sys", .data = &rzv2n_sys_init_data }, 93 + #endif 91 94 #ifdef CONFIG_SYS_R9A09G057 92 95 { .compatible = "renesas,r9a09g057-sys", .data = &rzv2h_sys_init_data }, 93 96 #endif
+1
drivers/soc/renesas/rz-sysc.h
··· 42 42 extern const struct rz_sysc_init_data rzg3e_sys_init_data; 43 43 extern const struct rz_sysc_init_data rzg3s_sysc_init_data; 44 44 extern const struct rz_sysc_init_data rzv2h_sys_init_data; 45 + extern const struct rz_sysc_init_data rzv2n_sys_init_data; 45 46 46 47 #endif /* __SOC_RENESAS_RZ_SYSC_H__ */
+77 -1
drivers/soc/samsung/exynos-pmu.c
··· 7 7 8 8 #include <linux/array_size.h> 9 9 #include <linux/arm-smccc.h> 10 + #include <linux/cpuhotplug.h> 10 11 #include <linux/of.h> 11 12 #include <linux/of_address.h> 12 13 #include <linux/mfd/core.h> ··· 34 33 struct device *dev; 35 34 const struct exynos_pmu_data *pmu_data; 36 35 struct regmap *pmureg; 36 + struct regmap *pmuintrgen; 37 37 }; 38 38 39 39 void __iomem *pmu_base_addr; ··· 224 222 }; 225 223 226 224 static const struct exynos_pmu_data gs101_pmu_data = { 227 - .pmu_secure = true 225 + .pmu_secure = true, 226 + .pmu_cpuhp = true, 228 227 }; 229 228 230 229 /* ··· 329 326 } 330 327 EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap_by_phandle); 331 328 329 + /* 330 + * CPU_INFORM register hint values which are used by 331 + * EL3 firmware (el3mon). 332 + */ 333 + #define CPU_INFORM_CLEAR 0 334 + #define CPU_INFORM_C2 1 335 + 336 + static int gs101_cpuhp_pmu_online(unsigned int cpu) 337 + { 338 + unsigned int cpuhint = smp_processor_id(); 339 + u32 reg, mask; 340 + 341 + /* clear cpu inform hint */ 342 + regmap_write(pmu_context->pmureg, GS101_CPU_INFORM(cpuhint), 343 + CPU_INFORM_CLEAR); 344 + 345 + mask = BIT(cpu); 346 + 347 + regmap_update_bits(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_ENABLE, 348 + mask, (0 << cpu)); 349 + 350 + regmap_read(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_UPEND, &reg); 351 + 352 + regmap_write(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_CLEAR, 353 + reg & mask); 354 + 355 + return 0; 356 + } 357 + 358 + static int gs101_cpuhp_pmu_offline(unsigned int cpu) 359 + { 360 + u32 reg, mask; 361 + unsigned int cpuhint = smp_processor_id(); 362 + 363 + /* set cpu inform hint */ 364 + regmap_write(pmu_context->pmureg, GS101_CPU_INFORM(cpuhint), 365 + CPU_INFORM_C2); 366 + 367 + mask = BIT(cpu); 368 + regmap_update_bits(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_ENABLE, 369 + mask, BIT(cpu)); 370 + 371 + regmap_read(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_UPEND, &reg); 372 + regmap_write(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_CLEAR, 373 + reg & mask); 374 + 375 + mask = (BIT(cpu + 8)); 376 + regmap_read(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_UPEND, &reg); 377 + regmap_write(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_CLEAR, 378 + reg & mask); 379 + return 0; 380 + } 381 + 332 382 static int exynos_pmu_probe(struct platform_device *pdev) 333 383 { 334 384 struct device *dev = &pdev->dev; ··· 433 377 434 378 pmu_context->pmureg = regmap; 435 379 pmu_context->dev = dev; 380 + 381 + if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp) { 382 + pmu_context->pmuintrgen = syscon_regmap_lookup_by_phandle(dev->of_node, 383 + "google,pmu-intr-gen-syscon"); 384 + if (IS_ERR(pmu_context->pmuintrgen)) { 385 + /* 386 + * To maintain support for older DTs that didn't specify syscon phandle 387 + * just issue a warning rather than fail to probe. 388 + */ 389 + dev_warn(&pdev->dev, "pmu-intr-gen syscon unavailable\n"); 390 + } else { 391 + cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, 392 + "soc/exynos-pmu:prepare", 393 + gs101_cpuhp_pmu_online, NULL); 394 + 395 + cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, 396 + "soc/exynos-pmu:online", 397 + NULL, gs101_cpuhp_pmu_offline); 398 + } 399 + } 436 400 437 401 if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_init) 438 402 pmu_context->pmu_data->pmu_init();
+1
drivers/soc/samsung/exynos-pmu.h
··· 22 22 const struct exynos_pmu_conf *pmu_config; 23 23 const struct exynos_pmu_conf *pmu_config_extra; 24 24 bool pmu_secure; 25 + bool pmu_cpuhp; 25 26 26 27 void (*pmu_init)(void); 27 28 void (*powerdown_conf)(enum sys_powerdown);
+34
drivers/soc/sophgo/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + # 3 + # Sophgo SoC drivers 4 + # 5 + 6 + if ARCH_SOPHGO || COMPILE_TEST 7 + menu "Sophgo SoC drivers" 8 + 9 + config SOPHGO_CV1800_RTCSYS 10 + tristate "Sophgo CV1800 RTC MFD" 11 + select MFD_CORE 12 + help 13 + If you say yes here you get support the RTC MFD driver for Sophgo 14 + CV1800 series SoC. The RTC module comprises a 32kHz oscillator, 15 + Power-on-Reset (PoR) sub-module, HW state machine to control chip 16 + power-on, power-off and reset. Furthermore, the 8051 subsystem is 17 + located within RTCSYS including associated SRAM block. 18 + 19 + This driver can also be built as a module. If so, the module will be 20 + called cv1800-rtcsys. 21 + 22 + config SOPHGO_SG2044_TOPSYS 23 + tristate "Sophgo SG2044 TOP syscon driver" 24 + select MFD_CORE 25 + help 26 + This is the core driver for the Sophgo SG2044 TOP system 27 + controller device. This driver provide PLL clock device 28 + for the SoC. 29 + 30 + This driver can also be built as a module. If so, the module 31 + will be called sg2044-topsys. 32 + 33 + endmenu 34 + endif
+4
drivers/soc/sophgo/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + obj-$(CONFIG_SOPHGO_CV1800_RTCSYS) += cv1800-rtcsys.o 4 + obj-$(CONFIG_SOPHGO_SG2044_TOPSYS) += sg2044-topsys.o
+63
drivers/soc/sophgo/cv1800-rtcsys.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Driver for Sophgo CV1800 series SoC RTC subsystem 4 + * 5 + * The RTC module comprises a 32kHz oscillator, Power-on-Reset (PoR) sub-module, 6 + * HW state machine to control chip power-on, power-off and reset. Furthermore, 7 + * the 8051 subsystem is located within RTCSYS including associated SRAM block. 8 + * 9 + * Copyright (C) 2025 Alexander Sverdlin <alexander.sverdlin@gmail.com> 10 + * 11 + */ 12 + 13 + #include <linux/mfd/core.h> 14 + #include <linux/module.h> 15 + #include <linux/of.h> 16 + #include <linux/property.h> 17 + 18 + static struct resource cv1800_rtcsys_irq_resources[] = { 19 + DEFINE_RES_IRQ_NAMED(0, "alarm"), 20 + }; 21 + 22 + static const struct mfd_cell cv1800_rtcsys_subdev[] = { 23 + { 24 + .name = "cv1800b-rtc", 25 + .num_resources = 1, 26 + .resources = &cv1800_rtcsys_irq_resources[0], 27 + }, 28 + }; 29 + 30 + static int cv1800_rtcsys_probe(struct platform_device *pdev) 31 + { 32 + int irq; 33 + 34 + irq = platform_get_irq_byname(pdev, "alarm"); 35 + if (irq < 0) 36 + return irq; 37 + cv1800_rtcsys_irq_resources[0].start = irq; 38 + cv1800_rtcsys_irq_resources[0].end = irq; 39 + 40 + return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, 41 + cv1800_rtcsys_subdev, 42 + ARRAY_SIZE(cv1800_rtcsys_subdev), 43 + NULL, 0, NULL); 44 + } 45 + 46 + static const struct of_device_id cv1800_rtcsys_of_match[] = { 47 + { .compatible = "sophgo,cv1800b-rtc" }, 48 + { /* sentinel */ } 49 + }; 50 + MODULE_DEVICE_TABLE(of, cv1800_rtcsys_of_match); 51 + 52 + static struct platform_driver cv1800_rtcsys_mfd = { 53 + .probe = cv1800_rtcsys_probe, 54 + .driver = { 55 + .name = "cv1800_rtcsys", 56 + .of_match_table = cv1800_rtcsys_of_match, 57 + }, 58 + }; 59 + module_platform_driver(cv1800_rtcsys_mfd); 60 + 61 + MODULE_AUTHOR("Alexander Sverdlin <alexander.sverdlin@gmail.com>"); 62 + MODULE_DESCRIPTION("Sophgo CV1800 series SoC RTC subsystem driver"); 63 + MODULE_LICENSE("GPL");
+45
drivers/soc/sophgo/sg2044-topsys.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Sophgo SG2044 multi-function system controller driver 4 + * 5 + * Copyright (C) 2025 Inochi Amaoto <inochiama@gmail.com> 6 + */ 7 + 8 + #include <linux/mfd/core.h> 9 + #include <linux/mod_devicetable.h> 10 + #include <linux/module.h> 11 + #include <linux/property.h> 12 + #include <linux/resource.h> 13 + 14 + static const struct mfd_cell sg2044_topsys_subdev[] = { 15 + { 16 + .name = "sg2044-pll", 17 + }, 18 + }; 19 + 20 + static int sg2044_topsys_probe(struct platform_device *pdev) 21 + { 22 + return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, 23 + sg2044_topsys_subdev, 24 + ARRAY_SIZE(sg2044_topsys_subdev), 25 + NULL, 0, NULL); 26 + } 27 + 28 + static const struct of_device_id sg2044_topsys_of_match[] = { 29 + { .compatible = "sophgo,sg2044-top-syscon" }, 30 + { /* sentinel */ } 31 + }; 32 + MODULE_DEVICE_TABLE(of, sg2044_topsys_of_match); 33 + 34 + static struct platform_driver sg2044_topsys_driver = { 35 + .probe = sg2044_topsys_probe, 36 + .driver = { 37 + .name = "sg2044-topsys", 38 + .of_match_table = sg2044_topsys_of_match, 39 + }, 40 + }; 41 + module_platform_driver(sg2044_topsys_driver); 42 + 43 + MODULE_AUTHOR("Inochi Amaoto <inochiama@gmail.com>"); 44 + MODULE_DESCRIPTION("Sophgo SG2044 multi-function system controller driver"); 45 + MODULE_LICENSE("GPL");
+1 -1
drivers/soc/ti/k3-ringacc.c
··· 1291 1291 1292 1292 mutex_lock(&k3_ringacc_list_lock); 1293 1293 list_for_each_entry(entry, &k3_ringacc_list, list) 1294 - if (entry->dev->of_node == ringacc_np) { 1294 + if (device_match_of_node(entry->dev, ringacc_np)) { 1295 1295 ringacc = entry; 1296 1296 break; 1297 1297 }
+2
drivers/soc/ti/k3-socinfo.c
··· 43 43 #define JTAG_ID_PARTNO_AM62AX 0xBB8D 44 44 #define JTAG_ID_PARTNO_AM62PX 0xBB9D 45 45 #define JTAG_ID_PARTNO_J722S 0xBBA0 46 + #define JTAG_ID_PARTNO_AM62LX 0xBBA7 46 47 47 48 static const struct k3_soc_id { 48 49 unsigned int id; ··· 59 58 { JTAG_ID_PARTNO_AM62AX, "AM62AX" }, 60 59 { JTAG_ID_PARTNO_AM62PX, "AM62PX" }, 61 60 { JTAG_ID_PARTNO_J722S, "J722S" }, 61 + { JTAG_ID_PARTNO_AM62LX, "AM62LX" }, 62 62 }; 63 63 64 64 static const char * const j721e_rev_string_map[] = {
+1 -2
drivers/soc/ti/knav_qmss_queue.c
··· 252 252 return qh; 253 253 254 254 err: 255 - if (qh->stats) 256 - free_percpu(qh->stats); 255 + free_percpu(qh->stats); 257 256 devm_kfree(inst->kdev->dev, qh); 258 257 return ERR_PTR(ret); 259 258 }
+3 -5
drivers/soc/ti/wkup_m3_ipc.c
··· 644 644 645 645 m3_ipc->mbox = mbox_request_channel(&m3_ipc->mbox_client, 0); 646 646 647 - if (IS_ERR(m3_ipc->mbox)) { 648 - dev_err(dev, "IPC Request for A8->M3 Channel failed! %ld\n", 649 - PTR_ERR(m3_ipc->mbox)); 650 - return PTR_ERR(m3_ipc->mbox); 651 - } 647 + if (IS_ERR(m3_ipc->mbox)) 648 + return dev_err_probe(dev, PTR_ERR(m3_ipc->mbox), 649 + "IPC Request for A8->M3 Channel failed!\n"); 652 650 653 651 if (of_property_read_u32(dev->of_node, "ti,rproc", &rproc_phandle)) { 654 652 dev_err(&pdev->dev, "could not get rproc phandle\n");
+19
drivers/soc/vt8500/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + 3 + if ARCH_VT8500 || COMPILE_TEST 4 + 5 + menu "VIA/WonderMedia SoC drivers" 6 + 7 + config WMT_SOCINFO 8 + bool "VIA/WonderMedia SoC Information driver" 9 + default ARCH_VT8500 10 + select SOC_BUS 11 + help 12 + Say yes to support decoding of VIA/WonderMedia system configuration 13 + register information. This currently includes just the chip ID register 14 + which helps identify the exact hardware revision of the SoC the kernel 15 + is running on (to know if any revision-specific quirks are required) 16 + 17 + endmenu 18 + 19 + endif
+2
drivers/soc/vt8500/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + obj-$(CONFIG_WMT_SOCINFO) += wmt-socinfo.o
+125
drivers/soc/vt8500/wmt-socinfo.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright 2025 Alexey Charkov <alchark@gmail.com> 4 + * Based on aspeed-socinfo.c 5 + */ 6 + 7 + #include <linux/dev_printk.h> 8 + #include <linux/device.h> 9 + #include <linux/io.h> 10 + #include <linux/of.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/sys_soc.h> 13 + 14 + static const struct { 15 + const char *name; 16 + const u32 id; 17 + } chip_id_table[] = { 18 + /* VIA */ 19 + { "VT8420", 0x3300 }, 20 + { "VT8430", 0x3357 }, 21 + { "VT8500", 0x3400 }, 22 + 23 + /* WonderMedia */ 24 + { "WM8425", 0x3429 }, 25 + { "WM8435", 0x3437 }, 26 + { "WM8440", 0x3451 }, 27 + { "WM8505", 0x3426 }, 28 + { "WM8650", 0x3465 }, 29 + { "WM8750", 0x3445 }, 30 + { "WM8850", 0x3481 }, 31 + { "WM8880", 0x3498 }, 32 + }; 33 + 34 + static const char *sccid_to_name(u32 sccid) 35 + { 36 + u32 id = sccid >> 16; 37 + unsigned int i; 38 + 39 + for (i = 0 ; i < ARRAY_SIZE(chip_id_table) ; ++i) { 40 + if (chip_id_table[i].id == id) 41 + return chip_id_table[i].name; 42 + } 43 + 44 + return "Unknown"; 45 + } 46 + 47 + static int wmt_socinfo_probe(struct platform_device *pdev) 48 + { 49 + struct device_node *np = pdev->dev.of_node; 50 + struct soc_device_attribute *attrs; 51 + struct soc_device *soc_dev; 52 + char letter, digit; 53 + void __iomem *reg; 54 + u32 sccid; 55 + 56 + reg = devm_of_iomap(&pdev->dev, np, 0, NULL); 57 + if (IS_ERR(reg)) 58 + return PTR_ERR(reg); 59 + 60 + sccid = readl(reg); 61 + 62 + attrs = devm_kzalloc(&pdev->dev, sizeof(*attrs), GFP_KERNEL); 63 + if (!attrs) 64 + return -ENOMEM; 65 + 66 + /* 67 + * Machine: VIA APC Rock 68 + * Family: WM8850 69 + * Revision: A2 70 + * SoC ID: raw silicon revision id (34810103 in hexadecimal) 71 + */ 72 + 73 + attrs->family = sccid_to_name(sccid); 74 + 75 + letter = (sccid >> 8) & 0xf; 76 + letter = (letter - 1) + 'A'; 77 + digit = sccid & 0xff; 78 + digit = (digit - 1) + '0'; 79 + attrs->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, 80 + "%c%c", letter, digit); 81 + 82 + attrs->soc_id = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%08x", sccid); 83 + 84 + if (!attrs->revision || !attrs->soc_id) 85 + return -ENOMEM; 86 + 87 + soc_dev = soc_device_register(attrs); 88 + if (IS_ERR(soc_dev)) 89 + return PTR_ERR(soc_dev); 90 + 91 + dev_info(&pdev->dev, 92 + "VIA/WonderMedia %s rev %s (%s)\n", 93 + attrs->family, 94 + attrs->revision, 95 + attrs->soc_id); 96 + 97 + platform_set_drvdata(pdev, soc_dev); 98 + return 0; 99 + } 100 + 101 + static void wmt_socinfo_remove(struct platform_device *pdev) 102 + { 103 + struct soc_device *soc_dev = platform_get_drvdata(pdev); 104 + 105 + soc_device_unregister(soc_dev); 106 + } 107 + 108 + static const struct of_device_id wmt_socinfo_ids[] = { 109 + { .compatible = "via,vt8500-scc-id" }, 110 + { /* Sentinel */ }, 111 + }; 112 + 113 + static struct platform_driver wmt_socinfo = { 114 + .probe = wmt_socinfo_probe, 115 + .remove = wmt_socinfo_remove, 116 + .driver = { 117 + .name = "wmt-socinfo", 118 + .of_match_table = wmt_socinfo_ids, 119 + }, 120 + }; 121 + module_platform_driver(wmt_socinfo); 122 + 123 + MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); 124 + MODULE_DESCRIPTION("VIA/WonderMedia socinfo driver"); 125 + MODULE_LICENSE("GPL");
+9 -7
drivers/tee/amdtee/core.c
··· 3 3 * Copyright 2019 Advanced Micro Devices, Inc. 4 4 */ 5 5 6 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 + 6 8 #include <linux/errno.h> 9 + #include <linux/device.h> 10 + #include <linux/firmware.h> 7 11 #include <linux/io.h> 12 + #include <linux/mm.h> 8 13 #include <linux/module.h> 14 + #include <linux/psp-tee.h> 9 15 #include <linux/slab.h> 10 16 #include <linux/string.h> 11 - #include <linux/device.h> 12 17 #include <linux/tee_core.h> 13 18 #include <linux/types.h> 14 - #include <linux/mm.h> 15 19 #include <linux/uaccess.h> 16 - #include <linux/firmware.h> 20 + 17 21 #include "amdtee_private.h" 18 - #include <linux/psp-tee.h> 19 22 20 23 static struct amdtee_driver_data *drv_data; 21 24 static DEFINE_MUTEX(session_list_mutex); ··· 461 458 462 459 rc = psp_check_tee_status(); 463 460 if (rc) { 464 - pr_err("amd-tee driver: tee not present\n"); 461 + pr_err("tee not present\n"); 465 462 return rc; 466 463 } 467 464 ··· 497 494 498 495 drv_data->amdtee = amdtee; 499 496 500 - pr_info("amd-tee driver initialization successful\n"); 501 497 return 0; 502 498 503 499 err_device_unregister: ··· 512 510 kfree(drv_data); 513 511 drv_data = NULL; 514 512 515 - pr_err("amd-tee driver initialization failed\n"); 513 + pr_err("initialization failed\n"); 516 514 return rc; 517 515 } 518 516 module_init(amdtee_driver_init);
+1 -2
drivers/tee/optee/smc_abi.c
··· 1551 1551 data_pa_high, data_pa_low, 0, 0, 0, &res); 1552 1552 if (!rc) 1553 1553 rc = res.a0; 1554 - if (fw) 1555 - release_firmware(fw); 1554 + release_firmware(fw); 1556 1555 kfree(data_buf); 1557 1556 1558 1557 if (!rc) {
+6 -5
drivers/tee/tee_core.c
··· 10 10 #include <linux/fs.h> 11 11 #include <linux/idr.h> 12 12 #include <linux/module.h> 13 + #include <linux/overflow.h> 13 14 #include <linux/slab.h> 14 15 #include <linux/tee_core.h> 15 16 #include <linux/uaccess.h> ··· 20 19 21 20 #define TEE_NUM_DEVICES 32 22 21 23 - #define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x)) 22 + #define TEE_IOCTL_PARAM_SIZE(x) (size_mul(sizeof(struct tee_param), (x))) 24 23 25 24 #define TEE_UUID_NS_NAME_SIZE 128 26 25 ··· 488 487 if (copy_from_user(&arg, uarg, sizeof(arg))) 489 488 return -EFAULT; 490 489 491 - if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len) 490 + if (size_add(sizeof(arg), TEE_IOCTL_PARAM_SIZE(arg.num_params)) != buf.buf_len) 492 491 return -EINVAL; 493 492 494 493 if (arg.num_params) { ··· 566 565 if (copy_from_user(&arg, uarg, sizeof(arg))) 567 566 return -EFAULT; 568 567 569 - if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len) 568 + if (size_add(sizeof(arg), TEE_IOCTL_PARAM_SIZE(arg.num_params)) != buf.buf_len) 570 569 return -EINVAL; 571 570 572 571 if (arg.num_params) { ··· 700 699 if (get_user(num_params, &uarg->num_params)) 701 700 return -EFAULT; 702 701 703 - if (sizeof(*uarg) + TEE_IOCTL_PARAM_SIZE(num_params) != buf.buf_len) 702 + if (size_add(sizeof(*uarg), TEE_IOCTL_PARAM_SIZE(num_params)) != buf.buf_len) 704 703 return -EINVAL; 705 704 706 705 params = kcalloc(num_params, sizeof(struct tee_param), GFP_KERNEL); ··· 799 798 get_user(num_params, &uarg->num_params)) 800 799 return -EFAULT; 801 800 802 - if (sizeof(*uarg) + TEE_IOCTL_PARAM_SIZE(num_params) > buf.buf_len) 801 + if (size_add(sizeof(*uarg), TEE_IOCTL_PARAM_SIZE(num_params)) > buf.buf_len) 803 802 return -EINVAL; 804 803 805 804 params = kcalloc(num_params, sizeof(struct tee_param), GFP_KERNEL);
+1
include/dt-bindings/arm/qcom,ids.h
··· 277 277 #define QCOM_ID_IPQ5302 595 278 278 #define QCOM_ID_QCS8550 603 279 279 #define QCOM_ID_QCM8550 604 280 + #define QCOM_ID_SM8750 618 280 281 #define QCOM_ID_IPQ5300 624 281 282 #define QCOM_ID_IPQ5321 650 282 283 #define QCOM_ID_IPQ5424 651
+16
include/dt-bindings/reset/thead,th1520-reset.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 + /* 3 + * Copyright (c) 2024 Samsung Electronics Co., Ltd. 4 + * Author: Michal Wilczynski <m.wilczynski@samsung.com> 5 + */ 6 + 7 + #ifndef _DT_BINDINGS_TH1520_RESET_H 8 + #define _DT_BINDINGS_TH1520_RESET_H 9 + 10 + #define TH1520_RESET_ID_GPU 0 11 + #define TH1520_RESET_ID_GPU_CLKGEN 1 12 + #define TH1520_RESET_ID_NPU 2 13 + #define TH1520_RESET_ID_WDT0 3 14 + #define TH1520_RESET_ID_WDT1 4 15 + 16 + #endif /* _DT_BINDINGS_TH1520_RESET_H */
+9 -6
include/linux/bus/stm32_firewall_device.h
··· 114 114 115 115 #else /* CONFIG_STM32_FIREWALL */ 116 116 117 - int stm32_firewall_get_firewall(struct device_node *np, struct stm32_firewall *firewall, 118 - unsigned int nb_firewall) 117 + static inline int stm32_firewall_get_firewall(struct device_node *np, 118 + struct stm32_firewall *firewall, 119 + unsigned int nb_firewall) 119 120 { 120 121 return -ENODEV; 121 122 } 122 123 123 - int stm32_firewall_grant_access(struct stm32_firewall *firewall) 124 + static inline int stm32_firewall_grant_access(struct stm32_firewall *firewall) 124 125 { 125 126 return -ENODEV; 126 127 } 127 128 128 - void stm32_firewall_release_access(struct stm32_firewall *firewall) 129 + static inline void stm32_firewall_release_access(struct stm32_firewall *firewall) 129 130 { 130 131 } 131 132 132 - int stm32_firewall_grant_access_by_id(struct stm32_firewall *firewall, u32 subsystem_id) 133 + static inline int stm32_firewall_grant_access_by_id(struct stm32_firewall *firewall, 134 + u32 subsystem_id) 133 135 { 134 136 return -ENODEV; 135 137 } 136 138 137 - void stm32_firewall_release_access_by_id(struct stm32_firewall *firewall, u32 subsystem_id) 139 + static inline void stm32_firewall_release_access_by_id(struct stm32_firewall *firewall, 140 + u32 subsystem_id) 138 141 { 139 142 } 140 143
+19
include/linux/firmware/imx/sm.h
··· 8 8 9 9 #include <linux/bitfield.h> 10 10 #include <linux/errno.h> 11 + #include <linux/scmi_imx_protocol.h> 11 12 #include <linux/types.h> 12 13 13 14 #define SCMI_IMX_CTRL_PDM_CLK_SEL 0 /* AON PDM clock sel */ ··· 21 20 int scmi_imx_misc_ctrl_get(u32 id, u32 *num, u32 *val); 22 21 int scmi_imx_misc_ctrl_set(u32 id, u32 val); 23 22 23 + int scmi_imx_cpu_start(u32 cpuid, bool start); 24 + int scmi_imx_cpu_started(u32 cpuid, bool *started); 25 + int scmi_imx_cpu_reset_vector_set(u32 cpuid, u64 vector, bool start, bool boot, 26 + bool resume); 27 + 28 + enum scmi_imx_lmm_op { 29 + SCMI_IMX_LMM_BOOT, 30 + SCMI_IMX_LMM_POWER_ON, 31 + SCMI_IMX_LMM_SHUTDOWN, 32 + }; 33 + 34 + /* For shutdown pperation */ 35 + #define SCMI_IMX_LMM_OP_FORCEFUL 0 36 + #define SCMI_IMX_LMM_OP_GRACEFUL BIT(0) 37 + 38 + int scmi_imx_lmm_operation(u32 lmid, enum scmi_imx_lmm_op op, u32 flags); 39 + int scmi_imx_lmm_info(u32 lmid, struct scmi_imx_lmm_info *info); 40 + int scmi_imx_lmm_reset_vector_set(u32 lmid, u32 cpuid, u32 flags, u64 vector); 24 41 #endif
+4 -2
include/linux/firmware/samsung/exynos-acpm-protocol.h
··· 11 11 #include <linux/types.h> 12 12 13 13 struct acpm_handle; 14 + struct device_node; 14 15 15 16 struct acpm_pmic_ops { 16 17 int (*read_reg)(const struct acpm_handle *handle, ··· 45 44 46 45 struct device; 47 46 48 - const struct acpm_handle *devm_acpm_get_by_phandle(struct device *dev, 49 - const char *property); 47 + const struct acpm_handle *devm_acpm_get_by_node(struct device *dev, 48 + struct device_node *np); 49 + 50 50 #endif /* __EXYNOS_ACPM_PROTOCOL_H */
+6
include/linux/reset.h
··· 1005 1005 } 1006 1006 1007 1007 static inline struct reset_control * 1008 + devm_reset_control_array_get_exclusive_released(struct device *dev) 1009 + { 1010 + return devm_reset_control_array_get(dev, RESET_CONTROL_EXCLUSIVE_RELEASED); 1011 + } 1012 + 1013 + static inline struct reset_control * 1008 1014 devm_reset_control_array_get_shared(struct device *dev) 1009 1015 { 1010 1016 return devm_reset_control_array_get(dev, RESET_CONTROL_SHARED);
+42
include/linux/scmi_imx_protocol.h
··· 11 11 #include <linux/bitfield.h> 12 12 #include <linux/device.h> 13 13 #include <linux/notifier.h> 14 + #include <linux/scmi_protocol.h> 14 15 #include <linux/types.h> 15 16 17 + #define SCMI_PROTOCOL_IMX_LMM 0x80 16 18 #define SCMI_PROTOCOL_IMX_BBM 0x81 19 + #define SCMI_PROTOCOL_IMX_CPU 0x82 17 20 #define SCMI_PROTOCOL_IMX_MISC 0x84 18 21 19 22 #define SCMI_IMX_VENDOR "NXP" ··· 59 56 u32 *num, u32 *val); 60 57 int (*misc_ctrl_req_notify)(const struct scmi_protocol_handle *ph, 61 58 u32 ctrl_id, u32 evt_id, u32 flags); 59 + }; 60 + 61 + /* See LMM_ATTRIBUTES in imx95.rst */ 62 + #define LMM_ID_DISCOVER 0xFFFFFFFFU 63 + #define LMM_MAX_NAME 16 64 + 65 + enum scmi_imx_lmm_state { 66 + LMM_STATE_LM_OFF, 67 + LMM_STATE_LM_ON, 68 + LMM_STATE_LM_SUSPEND, 69 + LMM_STATE_LM_POWERED, 70 + }; 71 + 72 + struct scmi_imx_lmm_info { 73 + u32 lmid; 74 + enum scmi_imx_lmm_state state; 75 + u32 errstatus; 76 + u8 name[LMM_MAX_NAME]; 77 + }; 78 + 79 + struct scmi_imx_lmm_proto_ops { 80 + int (*lmm_power_boot)(const struct scmi_protocol_handle *ph, u32 lmid, 81 + bool boot); 82 + int (*lmm_info)(const struct scmi_protocol_handle *ph, u32 lmid, 83 + struct scmi_imx_lmm_info *info); 84 + int (*lmm_reset_vector_set)(const struct scmi_protocol_handle *ph, 85 + u32 lmid, u32 cpuid, u32 flags, u64 vector); 86 + int (*lmm_shutdown)(const struct scmi_protocol_handle *ph, u32 lmid, 87 + u32 flags); 88 + }; 89 + 90 + struct scmi_imx_cpu_proto_ops { 91 + int (*cpu_reset_vector_set)(const struct scmi_protocol_handle *ph, 92 + u32 cpuid, u64 vector, bool start, 93 + bool boot, bool resume); 94 + int (*cpu_start)(const struct scmi_protocol_handle *ph, u32 cpuid, 95 + bool start); 96 + int (*cpu_started)(const struct scmi_protocol_handle *ph, u32 cpuid, 97 + bool *started); 62 98 }; 63 99 #endif
+8
include/linux/soc/qcom/llcc-qcom.h
··· 24 24 #define LLCC_CMPTDMA 15 25 25 #define LLCC_DISP 16 26 26 #define LLCC_VIDFW 17 27 + #define LLCC_CAMFW 18 27 28 #define LLCC_MDMHPFX 20 28 29 #define LLCC_MDMPNG 21 29 30 #define LLCC_AUDHW 22 ··· 68 67 #define LLCC_EVCS_LEFT 67 69 68 #define LLCC_EVCS_RIGHT 68 70 69 #define LLCC_SPAD 69 70 + #define LLCC_VIDDEC 70 71 + #define LLCC_CAMOFE 71 72 + #define LLCC_CAMRTIP 72 73 + #define LLCC_CAMSRTIP 73 74 + #define LLCC_CAMRTRF 74 75 + #define LLCC_CAMSRTRF 75 76 + #define LLCC_CPUSSMPAM 89 71 77 72 78 /** 73 79 * struct llcc_slice_desc - Cache slice descriptor
+11
include/linux/soc/samsung/exynos-regs-pmu.h
··· 658 658 #define EXYNOS5433_PAD_RETENTION_FSYSGENIO_OPTION (0x32A8) 659 659 660 660 /* For Tensor GS101 */ 661 + /* PMU ALIVE */ 661 662 #define GS101_SYSIP_DAT0 (0x810) 663 + #define GS101_CPU0_INFORM (0x860) 664 + #define GS101_CPU_INFORM(cpu) \ 665 + (GS101_CPU0_INFORM + (cpu*4)) 662 666 #define GS101_SYSTEM_CONFIGURATION (0x3A00) 663 667 #define GS101_PHY_CTRL_USB20 (0x3EB0) 664 668 #define GS101_PHY_CTRL_USBDP (0x3EB4) 669 + 670 + /* PMU INTR GEN */ 671 + #define GS101_GRP1_INTR_BID_UPEND (0x0108) 672 + #define GS101_GRP1_INTR_BID_CLEAR (0x010c) 673 + #define GS101_GRP2_INTR_BID_ENABLE (0x0200) 674 + #define GS101_GRP2_INTR_BID_UPEND (0x0208) 675 + #define GS101_GRP2_INTR_BID_CLEAR (0x020c) 665 676 666 677 #endif /* __LINUX_SOC_EXYNOS_REGS_PMU_H */
+35
include/linux/turris-signing-key.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * 2025 by Marek Behún <kabel@kernel.org> 4 + */ 5 + 6 + #ifndef __TURRIS_SIGNING_KEY_H 7 + #define __TURRIS_SIGNING_KEY_H 8 + 9 + #include <linux/key.h> 10 + #include <linux/types.h> 11 + 12 + struct device; 13 + 14 + #ifdef CONFIG_KEYS 15 + struct turris_signing_key_subtype { 16 + u16 key_size; 17 + u8 data_size; 18 + u8 sig_size; 19 + u8 public_key_size; 20 + const char *hash_algo; 21 + const void *(*get_public_key)(const struct key *key); 22 + int (*sign)(const struct key *key, const void *msg, void *signature); 23 + }; 24 + 25 + static inline struct device *turris_signing_key_get_dev(const struct key *key) 26 + { 27 + return key->payload.data[1]; 28 + } 29 + 30 + int 31 + devm_turris_signing_key_create(struct device *dev, const struct turris_signing_key_subtype *subtype, 32 + const char *desc); 33 + #endif 34 + 35 + #endif /* __TURRIS_SIGNING_KEY_H */