Pull ARM driver updates from Arnd Bergmann: "There are a few separately maintained driver subsystems that we merge through the SoC tree, notable changes are: - Memory controller updates, mainly for Tegra and Mediatek SoCs, and clarifications for the memory controller DT bindings - SCMI firmware interface updates, in particular a new transport based on OPTEE and support for atomic operations. - Cleanups to the TEE subsystem, refactoring its memory management For SoC specific drivers without a separate subsystem, changes include - Smaller updates and fixes for TI, AT91/SAMA5, Qualcomm and NXP Layerscape SoCs. - Driver support for Microchip SAMA5D29, Tesla FSD, Renesas RZ/G2L, and Qualcomm SM8450. - Better power management on Mediatek MT81xx, NXP i.MX8MQ and older NVIDIA Tegra chips" * tag 'arm-drivers-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (154 commits) ARM: spear: fix typos in comments soc/microchip: fix invalid free in mpfs_sys_controller_delete soc: s4: Add support for power domains controller dt-bindings: power: add Amlogic s4 power domains bindings ARM: at91: add support in soc driver for new SAMA5D29 soc: mediatek: mmsys: add sw0_rst_offset in mmsys driver data dt-bindings: memory: renesas,rpc-if: Document RZ/V2L SoC memory: emif: check the pointer temp in get_device_details() memory: emif: Add check for setup_interrupts dt-bindings: arm: mediatek: mmsys: add support for MT8186 dt-bindings: mediatek: add compatible for MT8186 pwrap soc: mediatek: pwrap: add pwrap driver for MT8186 SoC soc: mediatek: mmsys: add mmsys reset control for MT8186 soc: mediatek: mtk-infracfg: Disable ACP on MT8192 soc: ti: k3-socinfo: Add AM62x JTAG ID soc: mediatek: add MTK mutex support for MT8186 soc: mediatek: mmsys: add mt8186 mmsys routing table soc: mediatek: pm-domains: Add support for mt8186 dt-bindings: power: Add MT8186 power domains soc: mediatek: pm-domains: Add support for mt8195 ...
Unified · Split
| @@ -29,6 +29,7 @@ properties: · 28 unmodified lines | ||
| 29 | 29 | - mediatek,mt8167-mmsys |
| 30 | 30 | - mediatek,mt8173-mmsys |
| 31 | 31 | - mediatek,mt8183-mmsys |
| 32 | + - mediatek,mt8186-mmsys | |
| 32 | 33 | - mediatek,mt8192-mmsys |
| 33 | 34 | - mediatek,mt8365-mmsys |
| 34 | 35 | - const: syscon |
| @@ -27,6 +27,8 @@ properties: · 26 unmodified lines | ||
| 27 | 27 | - qcom,sm6350-llcc |
| 28 | 28 | - qcom,sm8150-llcc |
| 29 | 29 | - qcom,sm8250-llcc |
| 30 | + - qcom,sm8350-llcc | |
| 31 | + - qcom,sm8450-llcc | |
| 30 | 32 | |
| 31 | 33 | reg: |
| 32 | 34 | items: |
| @@ -0,0 +1,198 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/clock/tesla,fsd-clock.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Tesla FSD (Full Self-Driving) SoC clock controller | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Alim Akhtar <alim.akhtar@samsung.com> | |
| 11 | + - linux-fsd@tesla.com | |
| 12 | + | |
| 13 | +description: | | |
| 14 | + FSD clock controller consist of several clock management unit | |
| 15 | + (CMU), which generates clocks for various inteernal SoC blocks. | |
| 16 | + The root clock comes from external OSC clock (24 MHz). | |
| 17 | + | |
| 18 | + All available clocks are defined as preprocessor macros in | |
| 19 | + 'dt-bindings/clock/fsd-clk.h' header. | |
| 20 | + | |
| 21 | +properties: | |
| 22 | + compatible: | |
| 23 | + enum: | |
| 24 | + - tesla,fsd-clock-cmu | |
| 25 | + - tesla,fsd-clock-imem | |
| 26 | + - tesla,fsd-clock-peric | |
| 27 | + - tesla,fsd-clock-fsys0 | |
| 28 | + - tesla,fsd-clock-fsys1 | |
| 29 | + - tesla,fsd-clock-mfc | |
| 30 | + - tesla,fsd-clock-cam_csi | |
| 31 | + | |
| 32 | + clocks: | |
| 33 | + minItems: 1 | |
| 34 | + maxItems: 6 | |
| 35 | + | |
| 36 | + clock-names: | |
| 37 | + minItems: 1 | |
| 38 | + maxItems: 6 | |
| 39 | + | |
| 40 | + "#clock-cells": | |
| 41 | + const: 1 | |
| 42 | + | |
| 43 | + reg: | |
| 44 | + maxItems: 1 | |
| 45 | + | |
| 46 | +allOf: | |
| 47 | + - if: | |
| 48 | + properties: | |
| 49 | + compatible: | |
| 50 | + contains: | |
| 51 | + const: tesla,fsd-clock-cmu | |
| 52 | + then: | |
| 53 | + properties: | |
| 54 | + clocks: | |
| 55 | + items: | |
| 56 | + - description: External reference clock (24 MHz) | |
| 57 | + clock-names: | |
| 58 | + items: | |
| 59 | + - const: fin_pll | |
| 60 | + | |
| 61 | + - if: | |
| 62 | + properties: | |
| 63 | + compatible: | |
| 64 | + contains: | |
| 65 | + const: tesla,fsd-clock-imem | |
| 66 | + then: | |
| 67 | + properties: | |
| 68 | + clocks: | |
| 69 | + items: | |
| 70 | + - description: External reference clock (24 MHz) | |
| 71 | + - description: IMEM TCU clock (from CMU_CMU) | |
| 72 | + - description: IMEM bus clock (from CMU_CMU) | |
| 73 | + - description: IMEM DMA clock (from CMU_CMU) | |
| 74 | + clock-names: | |
| 75 | + items: | |
| 76 | + - const: fin_pll | |
| 77 | + - const: dout_cmu_imem_tcuclk | |
| 78 | + - const: dout_cmu_imem_aclk | |
| 79 | + - const: dout_cmu_imem_dmaclk | |
| 80 | + | |
| 81 | + - if: | |
| 82 | + properties: | |
| 83 | + compatible: | |
| 84 | + contains: | |
| 85 | + const: tesla,fsd-clock-peric | |
| 86 | + then: | |
| 87 | + properties: | |
| 88 | + clocks: | |
| 89 | + items: | |
| 90 | + - description: External reference clock (24 MHz) | |
| 91 | + - description: Shared0 PLL div4 clock (from CMU_CMU) | |
| 92 | + - description: PERIC shared1 div36 clock (from CMU_CMU) | |
| 93 | + - description: PERIC shared0 div3 TBU clock (from CMU_CMU) | |
| 94 | + - description: PERIC shared0 div20 clock (from CMU_CMU) | |
| 95 | + - description: PERIC shared1 div4 DMAclock (from CMU_CMU) | |
| 96 | + clock-names: | |
| 97 | + items: | |
| 98 | + - const: fin_pll | |
| 99 | + - const: dout_cmu_pll_shared0_div4 | |
| 100 | + - const: dout_cmu_peric_shared1div36 | |
| 101 | + - const: dout_cmu_peric_shared0div3_tbuclk | |
| 102 | + - const: dout_cmu_peric_shared0div20 | |
| 103 | + - const: dout_cmu_peric_shared1div4_dmaclk | |
| 104 | + | |
| 105 | + - if: | |
| 106 | + properties: | |
| 107 | + compatible: | |
| 108 | + contains: | |
| 109 | + const: tesla,fsd-clock-fsys0 | |
| 110 | + then: | |
| 111 | + properties: | |
| 112 | + clocks: | |
| 113 | + items: | |
| 114 | + - description: External reference clock (24 MHz) | |
| 115 | + - description: Shared0 PLL div6 clock (from CMU_CMU) | |
| 116 | + - description: FSYS0 shared1 div4 clock (from CMU_CMU) | |
| 117 | + - description: FSYS0 shared0 div4 clock (from CMU_CMU) | |
| 118 | + clock-names: | |
| 119 | + items: | |
| 120 | + - const: fin_pll | |
| 121 | + - const: dout_cmu_pll_shared0_div6 | |
| 122 | + - const: dout_cmu_fsys0_shared1div4 | |
| 123 | + - const: dout_cmu_fsys0_shared0div4 | |
| 124 | + | |
| 125 | + - if: | |
| 126 | + properties: | |
| 127 | + compatible: | |
| 128 | + contains: | |
| 129 | + const: tesla,fsd-clock-fsys1 | |
| 130 | + then: | |
| 131 | + properties: | |
| 132 | + clocks: | |
| 133 | + items: | |
| 134 | + - description: External reference clock (24 MHz) | |
| 135 | + - description: FSYS1 shared0 div8 clock (from CMU_CMU) | |
| 136 | + - description: FSYS1 shared0 div4 clock (from CMU_CMU) | |
| 137 | + clock-names: | |
| 138 | + items: | |
| 139 | + - const: fin_pll | |
| 140 | + - const: dout_cmu_fsys1_shared0div8 | |
| 141 | + - const: dout_cmu_fsys1_shared0div4 | |
| 142 | + | |
| 143 | + - if: | |
| 144 | + properties: | |
| 145 | + compatible: | |
| 146 | + contains: | |
| 147 | + const: tesla,fsd-clock-mfc | |
| 148 | + then: | |
| 149 | + properties: | |
| 150 | + clocks: | |
| 151 | + items: | |
| 152 | + - description: External reference clock (24 MHz) | |
| 153 | + clock-names: | |
| 154 | + items: | |
| 155 | + - const: fin_pll | |
| 156 | + | |
| 157 | + - if: | |
| 158 | + properties: | |
| 159 | + compatible: | |
| 160 | + contains: | |
| 161 | + const: tesla,fsd-clock-cam_csi | |
| 162 | + then: | |
| 163 | + properties: | |
| 164 | + clocks: | |
| 165 | + items: | |
| 166 | + - description: External reference clock (24 MHz) | |
| 167 | + clock-names: | |
| 168 | + items: | |
| 169 | + - const: fin_pll | |
| 170 | + | |
| 171 | +required: | |
| 172 | + - compatible | |
| 173 | + - "#clock-cells" | |
| 174 | + - clocks | |
| 175 | + - clock-names | |
| 176 | + - reg | |
| 177 | + | |
| 178 | +additionalProperties: false | |
| 179 | + | |
| 180 | +examples: | |
| 181 | + # Clock controller node for CMU_FSYS1 | |
| 182 | + - | | |
| 183 | + #include <dt-bindings/clock/fsd-clk.h> | |
| 184 | + | |
| 185 | + clock_fsys1: clock-controller@16810000 { | |
| 186 | + compatible = "tesla,fsd-clock-fsys1"; | |
| 187 | + reg = <0x16810000 0x3000>; | |
| 188 | + #clock-cells = <1>; | |
| 189 | + | |
| 190 | + clocks = <&fin_pll>, | |
| 191 | + <&clock_cmu DOUT_CMU_FSYS1_SHARED0DIV8>, | |
| 192 | + <&clock_cmu DOUT_CMU_FSYS1_SHARED0DIV4>; | |
| 193 | + clock-names = "fin_pll", | |
| 194 | + "dout_cmu_fsys1_shared0div8", | |
| 195 | + "dout_cmu_fsys1_shared0div4"; | |
| 196 | + }; | |
| 197 | + | |
| 198 | +... | |
| @@ -38,6 +38,9 @@ properties: · 37 unmodified lines | ||
| 38 | 38 | The virtio transport only supports a single device. |
| 39 | 39 | items: |
| 40 | 40 | - const: arm,scmi-virtio |
| 41 | + - description: SCMI compliant firmware with OP-TEE transport | |
| 42 | + items: | |
| 43 | + - const: linaro,scmi-optee | |
| 41 | 44 | |
| 42 | 45 | interrupts: |
| 43 | 46 | description: |
| @@ -78,11 +81,24 @@ properties: · 34 unmodified lines | ||
| 78 | 81 | '#size-cells': |
| 79 | 82 | const: 0 |
| 80 | 83 | |
| 84 | + atomic-threshold-us: | |
| 85 | + description: | |
| 86 | + An optional time value, expressed in microseconds, representing, on this | |
| 87 | + platform, the threshold above which any SCMI command, advertised to have | |
| 88 | + an higher-than-threshold execution latency, should not be considered for | |
| 89 | + atomic mode of operation, even if requested. | |
| 90 | + default: 0 | |
| 91 | + | |
| 81 | 92 | arm,smc-id: |
| 82 | 93 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 83 | 94 | description: |
| 84 | 95 | SMC id required when using smc or hvc transports |
| 85 | 96 | |
| 97 | + linaro,optee-channel-id: | |
| 98 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 99 | + description: | |
| 100 | + Channel specifier required when using OP-TEE transport. | |
| 101 | + | |
| 86 | 102 | protocol@11: |
| 87 | 103 | type: object |
| 88 | 104 | properties: |
| @@ -195,6 +211,12 @@ patternProperties: · 106 unmodified lines | ||
| 195 | 211 | minItems: 1 |
| 196 | 212 | maxItems: 2 |
| 197 | 213 | |
| 214 | + linaro,optee-channel-id: | |
| 215 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 216 | + description: | |
| 217 | + Channel specifier required when using OP-TEE transport and | |
| 218 | + protocol has a dedicated communication channel. | |
| 219 | + | |
| 198 | 220 | required: |
| 199 | 221 | - reg |
| 200 | 222 | |
| @@ -226,6 +248,16 @@ else: · 25 unmodified lines | ||
| 226 | 248 | - arm,smc-id |
| 227 | 249 | - shmem |
| 228 | 250 | |
| 251 | + else: | |
| 252 | + if: | |
| 253 | + properties: | |
| 254 | + compatible: | |
| 255 | + contains: | |
| 256 | + const: linaro,scmi-optee | |
| 257 | + then: | |
| 258 | + required: | |
| 259 | + - linaro,optee-channel-id | |
| 260 | + | |
| 229 | 261 | examples: |
| 230 | 262 | - | |
| 231 | 263 | firmware { |
| @@ -240,6 +272,8 @@ examples: · 8 unmodified lines | ||
| 240 | 272 | #address-cells = <1>; |
| 241 | 273 | #size-cells = <0>; |
| 242 | 274 | |
| 275 | + atomic-threshold-us = <10000>; | |
| 276 | + | |
| 243 | 277 | scmi_devpd: protocol@11 { |
| 244 | 278 | reg = <0x11>; |
| 245 | 279 | #power-domain-cells = <1>; |
| @@ -340,7 +374,48 @@ examples: · 94 unmodified lines | ||
| 340 | 374 | reg = <0x11>; |
| 341 | 375 | #power-domain-cells = <1>; |
| 342 | 376 | }; |
| 377 | + }; | |
| 378 | + }; | |
| 379 | + | |
| 380 | + - | | |
| 381 | + firmware { | |
| 382 | + scmi { | |
| 383 | + compatible = "linaro,scmi-optee"; | |
| 384 | + linaro,optee-channel-id = <0>; | |
| 343 | 385 | |
| 386 | + #address-cells = <1>; | |
| 387 | + #size-cells = <0>; | |
| 388 | + | |
| 389 | + scmi_dvfs1: protocol@13 { | |
| 390 | + reg = <0x13>; | |
| 391 | + linaro,optee-channel-id = <1>; | |
| 392 | + shmem = <&cpu_optee_lpri0>; | |
| 393 | + #clock-cells = <1>; | |
| 394 | + }; | |
| 395 | + | |
| 396 | + scmi_clk0: protocol@14 { | |
| 397 | + reg = <0x14>; | |
| 398 | + #clock-cells = <1>; | |
| 399 | + }; | |
| 400 | + }; | |
| 401 | + }; | |
| 402 | + | |
| 403 | + soc { | |
| 404 | + #address-cells = <2>; | |
| 405 | + #size-cells = <2>; | |
| 406 | + | |
| 407 | + sram@51000000 { | |
| 408 | + compatible = "mmio-sram"; | |
| 409 | + reg = <0x0 0x51000000 0x0 0x10000>; | |
| 410 | + | |
| 411 | + #address-cells = <1>; | |
| 412 | + #size-cells = <1>; | |
| 413 | + ranges = <0 0x0 0x51000000 0x10000>; | |
| 414 | + | |
| 415 | + cpu_optee_lpri0: optee-sram-section@0 { | |
| 416 | + compatible = "arm,scmi-shmem"; | |
| 417 | + reg = <0x0 0x80>; | |
| 418 | + }; | |
| 344 | 419 | }; |
| 345 | 420 | }; |
| 346 | 421 | |
| @@ -0,0 +1,135 @@ | ||
| 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/ddr/jedec,lpddr2-timings.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: LPDDR2 SDRAM AC timing parameters for a given speed-bin | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> | |
| 11 | + | |
| 12 | +properties: | |
| 13 | + compatible: | |
| 14 | + const: jedec,lpddr2-timings | |
| 15 | + | |
| 16 | + max-freq: | |
| 17 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 18 | + description: | | |
| 19 | + Maximum DDR clock frequency for the speed-bin, in Hz. | |
| 20 | + | |
| 21 | + min-freq: | |
| 22 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 23 | + description: | | |
| 24 | + Minimum DDR clock frequency for the speed-bin, in Hz. | |
| 25 | + | |
| 26 | + tCKESR: | |
| 27 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 28 | + description: | | |
| 29 | + CKE minimum pulse width during SELF REFRESH (low pulse width during | |
| 30 | + SELF REFRESH) in pico seconds. | |
| 31 | + | |
| 32 | + tDQSCK-max: | |
| 33 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 34 | + description: | | |
| 35 | + DQS output data access time from CK_t/CK_c in pico seconds. | |
| 36 | + | |
| 37 | + tDQSCK-max-derated: | |
| 38 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 39 | + description: | | |
| 40 | + DQS output data access time from CK_t/CK_c, temperature de-rated, in pico | |
| 41 | + seconds. | |
| 42 | + | |
| 43 | + tFAW: | |
| 44 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 45 | + description: | | |
| 46 | + Four-bank activate window in pico seconds. | |
| 47 | + | |
| 48 | + tRAS-max-ns: | |
| 49 | + description: | | |
| 50 | + Row active time in nano seconds. | |
| 51 | + | |
| 52 | + tRAS-min: | |
| 53 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 54 | + description: | | |
| 55 | + Row active time in pico seconds. | |
| 56 | + | |
| 57 | + tRCD: | |
| 58 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 59 | + description: | | |
| 60 | + RAS-to-CAS delay in pico seconds. | |
| 61 | + | |
| 62 | + tRPab: | |
| 63 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 64 | + description: | | |
| 65 | + Row precharge time (all banks) in pico seconds. | |
| 66 | + | |
| 67 | + tRRD: | |
| 68 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 69 | + description: | | |
| 70 | + Active bank A to active bank B in pico seconds. | |
| 71 | + | |
| 72 | + tRTP: | |
| 73 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 74 | + description: | | |
| 75 | + Internal READ to PRECHARGE command delay in pico seconds. | |
| 76 | + | |
| 77 | + tWR: | |
| 78 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 79 | + description: | | |
| 80 | + WRITE recovery time in pico seconds. | |
| 81 | + | |
| 82 | + tWTR: | |
| 83 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 84 | + description: | | |
| 85 | + Internal WRITE-to-READ command delay in pico seconds. | |
| 86 | + | |
| 87 | + tXP: | |
| 88 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 89 | + description: | | |
| 90 | + Exit power-down to next valid command delay in pico seconds. | |
| 91 | + | |
| 92 | + tZQCL: | |
| 93 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 94 | + description: | | |
| 95 | + Long calibration time in pico seconds. | |
| 96 | + | |
| 97 | + tZQCS: | |
| 98 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 99 | + description: | | |
| 100 | + Short calibration time in pico seconds. | |
| 101 | + | |
| 102 | + tZQinit: | |
| 103 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 104 | + description: | | |
| 105 | + Initialization calibration time in pico seconds. | |
| 106 | + | |
| 107 | +required: | |
| 108 | + - compatible | |
| 109 | + - min-freq | |
| 110 | + - max-freq | |
| 111 | + | |
| 112 | +additionalProperties: false | |
| 113 | + | |
| 114 | +examples: | |
| 115 | + - | | |
| 116 | + timings { | |
| 117 | + compatible = "jedec,lpddr2-timings"; | |
| 118 | + min-freq = <10000000>; | |
| 119 | + max-freq = <400000000>; | |
| 120 | + tCKESR = <15000>; | |
| 121 | + tDQSCK-max = <5500>; | |
| 122 | + tFAW = <50000>; | |
| 123 | + tRAS-max-ns = <70000>; | |
| 124 | + tRAS-min = <42000>; | |
| 125 | + tRPab = <21000>; | |
| 126 | + tRCD = <18000>; | |
| 127 | + tRRD = <10000>; | |
| 128 | + tRTP = <7500>; | |
| 129 | + tWR = <15000>; | |
| 130 | + tWTR = <7500>; | |
| 131 | + tXP = <7500>; | |
| 132 | + tZQCL = <360000>; | |
| 133 | + tZQCS = <90000>; | |
| 134 | + tZQinit = <1000000>; | |
| 135 | + }; | |
| @@ -30,12 +30,26 @@ properties: · 29 unmodified lines | ||
| 30 | 30 | maximum: 255 |
| 31 | 31 | description: | |
| 32 | 32 | Revision 1 value of SDRAM chip. Obtained from device datasheet. |
| 33 | + Property is deprecated, use revision-id instead. | |
| 34 | + deprecated: true | |
| 33 | 35 | |
| 34 | 36 | revision-id2: |
| 35 | 37 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 36 | 38 | maximum: 255 |
| 37 | 39 | description: | |
| 38 | 40 | Revision 2 value of SDRAM chip. Obtained from device datasheet. |
| 41 | + Property is deprecated, use revision-id instead. | |
| 42 | + deprecated: true | |
| 43 | + | |
| 44 | + revision-id: | |
| 45 | + $ref: /schemas/types.yaml#/definitions/uint32-array | |
| 46 | + description: | | |
| 47 | + Revision IDs read from Mode Register 6 and 7. One byte per uint32 cell (i.e. <MR6 MR7>). | |
| 48 | + minItems: 2 | |
| 49 | + maxItems: 2 | |
| 50 | + items: | |
| 51 | + minimum: 0 | |
| 52 | + maximum: 255 | |
| 39 | 53 | |
| 40 | 54 | density: |
| 41 | 55 | $ref: /schemas/types.yaml#/definitions/uint32 |
| @@ -142,14 +156,12 @@ properties: · 100 unmodified lines | ||
| 142 | 156 | |
| 143 | 157 | patternProperties: |
| 144 | 158 | "^lpddr2-timings": |
| 145 | − type: object | |
| 159 | + $ref: jedec,lpddr2-timings.yaml | |
| 146 | 160 | description: | |
| 147 | 161 | The lpddr2 node may have one or more child nodes of type "lpddr2-timings". |
| 148 | 162 | "lpddr2-timings" provides AC timing parameters of the device for |
| 149 | 163 | a given speed-bin. The user may provide the timings for as many |
| 150 | − speed-bins as is required. Please see Documentation/devicetree/ | |
| 151 | − bindings/memory-controllers/ddr/lpddr2-timings.txt for more information | |
| 152 | − on "lpddr2-timings". | |
| 164 | + speed-bins as is required. | |
| 153 | 165 | |
| 154 | 166 | required: |
| 155 | 167 | - compatible |
| @@ -164,8 +176,7 @@ examples: · 8 unmodified lines | ||
| 164 | 176 | compatible = "elpida,ECB240ABACN", "jedec,lpddr2-s4"; |
| 165 | 177 | density = <2048>; |
| 166 | 178 | io-width = <32>; |
| 167 | − revision-id1 = <1>; | |
| 168 | − revision-id2 = <0>; | |
| 179 | + revision-id = <1 0>; | |
| 169 | 180 | |
| 170 | 181 | tRPab-min-tck = <3>; |
| 171 | 182 | tRCD-min-tck = <3>; |
| @@ -0,0 +1,157 @@ | ||
| 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/ddr/jedec,lpddr3-timings.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: LPDDR3 SDRAM AC timing parameters for a given speed-bin | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> | |
| 11 | + | |
| 12 | +properties: | |
| 13 | + compatible: | |
| 14 | + const: jedec,lpddr3-timings | |
| 15 | + | |
| 16 | + reg: | |
| 17 | + maxItems: 1 | |
| 18 | + description: | | |
| 19 | + Maximum DDR clock frequency for the speed-bin, in Hz. | |
| 20 | + Property is deprecated, use max-freq. | |
| 21 | + deprecated: true | |
| 22 | + | |
| 23 | + max-freq: | |
| 24 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 25 | + description: | | |
| 26 | + Maximum DDR clock frequency for the speed-bin, in Hz. | |
| 27 | + | |
| 28 | + min-freq: | |
| 29 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 30 | + description: | | |
| 31 | + Minimum DDR clock frequency for the speed-bin, in Hz. | |
| 32 | + | |
| 33 | + tCKE: | |
| 34 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 35 | + description: | | |
| 36 | + CKE minimum pulse width (HIGH and LOW pulse width) in pico seconds. | |
| 37 | + | |
| 38 | + tCKESR: | |
| 39 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 40 | + description: | | |
| 41 | + CKE minimum pulse width during SELF REFRESH (low pulse width during | |
| 42 | + SELF REFRESH) in pico seconds. | |
| 43 | + | |
| 44 | + tFAW: | |
| 45 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 46 | + description: | | |
| 47 | + Four-bank activate window in pico seconds. | |
| 48 | + | |
| 49 | + tMRD: | |
| 50 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 51 | + description: | | |
| 52 | + Mode register set command delay in pico seconds. | |
| 53 | + | |
| 54 | + tR2R-C2C: | |
| 55 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 56 | + description: | | |
| 57 | + Additional READ-to-READ delay in chip-to-chip cases in pico seconds. | |
| 58 | + | |
| 59 | + tRAS: | |
| 60 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 61 | + description: | | |
| 62 | + Row active time in pico seconds. | |
| 63 | + | |
| 64 | + tRC: | |
| 65 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 66 | + description: | | |
| 67 | + ACTIVATE-to-ACTIVATE command period in pico seconds. | |
| 68 | + | |
| 69 | + tRCD: | |
| 70 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 71 | + description: | | |
| 72 | + RAS-to-CAS delay in pico seconds. | |
| 73 | + | |
| 74 | + tRFC: | |
| 75 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 76 | + description: | | |
| 77 | + Refresh Cycle time in pico seconds. | |
| 78 | + | |
| 79 | + tRPab: | |
| 80 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 81 | + description: | | |
| 82 | + Row precharge time (all banks) in pico seconds. | |
| 83 | + | |
| 84 | + tRPpb: | |
| 85 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 86 | + description: | | |
| 87 | + Row precharge time (single banks) in pico seconds. | |
| 88 | + | |
| 89 | + tRRD: | |
| 90 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 91 | + description: | | |
| 92 | + Active bank A to active bank B in pico seconds. | |
| 93 | + | |
| 94 | + tRTP: | |
| 95 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 96 | + description: | | |
| 97 | + Internal READ to PRECHARGE command delay in pico seconds. | |
| 98 | + | |
| 99 | + tW2W-C2C: | |
| 100 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 101 | + description: | | |
| 102 | + Additional WRITE-to-WRITE delay in chip-to-chip cases in pico seconds. | |
| 103 | + | |
| 104 | + tWR: | |
| 105 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 106 | + description: | | |
| 107 | + WRITE recovery time in pico seconds. | |
| 108 | + | |
| 109 | + tWTR: | |
| 110 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 111 | + description: | | |
| 112 | + Internal WRITE-to-READ command delay in pico seconds. | |
| 113 | + | |
| 114 | + tXP: | |
| 115 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 116 | + description: | | |
| 117 | + Exit power-down to next valid command delay in pico seconds. | |
| 118 | + | |
| 119 | + tXSR: | |
| 120 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 121 | + description: | | |
| 122 | + SELF REFRESH exit to next valid command delay in pico seconds. | |
| 123 | + | |
| 124 | +required: | |
| 125 | + - compatible | |
| 126 | + - min-freq | |
| 127 | + - max-freq | |
| 128 | + | |
| 129 | +additionalProperties: false | |
| 130 | + | |
| 131 | +examples: | |
| 132 | + - | | |
| 133 | + lpddr3 { | |
| 134 | + timings { | |
| 135 | + compatible = "jedec,lpddr3-timings"; | |
| 136 | + max-freq = <800000000>; | |
| 137 | + min-freq = <100000000>; | |
| 138 | + tCKE = <3750>; | |
| 139 | + tCKESR = <3750>; | |
| 140 | + tFAW = <25000>; | |
| 141 | + tMRD = <7000>; | |
| 142 | + tR2R-C2C = <0>; | |
| 143 | + tRAS = <23000>; | |
| 144 | + tRC = <33750>; | |
| 145 | + tRCD = <10000>; | |
| 146 | + tRFC = <65000>; | |
| 147 | + tRPab = <12000>; | |
| 148 | + tRPpb = <12000>; | |
| 149 | + tRRD = <6000>; | |
| 150 | + tRTP = <3750>; | |
| 151 | + tW2W-C2C = <0>; | |
| 152 | + tWR = <7500>; | |
| 153 | + tWTR = <3750>; | |
| 154 | + tXP = <3750>; | |
| 155 | + tXSR = <70000>; | |
| 156 | + }; | |
| 157 | + }; | |
| @@ -0,0 +1,263 @@ | ||
| 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/ddr/jedec,lpddr3.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: LPDDR3 SDRAM compliant to JEDEC JESD209-3 | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> | |
| 11 | + | |
| 12 | +properties: | |
| 13 | + compatible: | |
| 14 | + items: | |
| 15 | + - enum: | |
| 16 | + - samsung,K3QF2F20DB | |
| 17 | + - const: jedec,lpddr3 | |
| 18 | + | |
| 19 | + '#address-cells': | |
| 20 | + const: 1 | |
| 21 | + deprecated: true | |
| 22 | + | |
| 23 | + density: | |
| 24 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 25 | + description: | | |
| 26 | + Density in megabits of SDRAM chip. | |
| 27 | + enum: | |
| 28 | + - 4096 | |
| 29 | + - 8192 | |
| 30 | + - 16384 | |
| 31 | + - 32768 | |
| 32 | + | |
| 33 | + io-width: | |
| 34 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 35 | + description: | | |
| 36 | + IO bus width in bits of SDRAM chip. | |
| 37 | + enum: | |
| 38 | + - 32 | |
| 39 | + - 16 | |
| 40 | + | |
| 41 | + manufacturer-id: | |
| 42 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 43 | + description: | | |
| 44 | + Manufacturer ID value read from Mode Register 5. The property is | |
| 45 | + deprecated, manufacturer should be derived from the compatible. | |
| 46 | + deprecated: true | |
| 47 | + | |
| 48 | + revision-id: | |
| 49 | + $ref: /schemas/types.yaml#/definitions/uint32-array | |
| 50 | + minItems: 2 | |
| 51 | + maxItems: 2 | |
| 52 | + items: | |
| 53 | + maximum: 255 | |
| 54 | + description: | | |
| 55 | + Revision value of SDRAM chip read from Mode Registers 6 and 7. | |
| 56 | + | |
| 57 | + '#size-cells': | |
| 58 | + const: 0 | |
| 59 | + deprecated: true | |
| 60 | + | |
| 61 | + tCKE-min-tck: | |
| 62 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 63 | + maximum: 15 | |
| 64 | + description: | | |
| 65 | + CKE minimum pulse width (HIGH and LOW pulse width) in terms of number | |
| 66 | + of clock cycles. | |
| 67 | + | |
| 68 | + tCKESR-min-tck: | |
| 69 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 70 | + maximum: 15 | |
| 71 | + description: | | |
| 72 | + CKE minimum pulse width during SELF REFRESH (low pulse width during | |
| 73 | + SELF REFRESH) in terms of number of clock cycles. | |
| 74 | + | |
| 75 | + tDQSCK-min-tck: | |
| 76 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 77 | + maximum: 15 | |
| 78 | + description: | | |
| 79 | + DQS output data access time from CK_t/CK_c in terms of number of clock | |
| 80 | + cycles. | |
| 81 | + | |
| 82 | + tFAW-min-tck: | |
| 83 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 84 | + maximum: 63 | |
| 85 | + description: | | |
| 86 | + Four-bank activate window in terms of number of clock cycles. | |
| 87 | + | |
| 88 | + tMRD-min-tck: | |
| 89 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 90 | + maximum: 15 | |
| 91 | + description: | | |
| 92 | + Mode register set command delay in terms of number of clock cycles. | |
| 93 | + | |
| 94 | + tR2R-C2C-min-tck: | |
| 95 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 96 | + enum: [0, 1] | |
| 97 | + description: | | |
| 98 | + Additional READ-to-READ delay in chip-to-chip cases in terms of number | |
| 99 | + of clock cycles. | |
| 100 | + | |
| 101 | + tRAS-min-tck: | |
| 102 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 103 | + maximum: 63 | |
| 104 | + description: | | |
| 105 | + Row active time in terms of number of clock cycles. | |
| 106 | + | |
| 107 | + tRC-min-tck: | |
| 108 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 109 | + maximum: 63 | |
| 110 | + description: | | |
| 111 | + ACTIVATE-to-ACTIVATE command period in terms of number of clock cycles. | |
| 112 | + | |
| 113 | + tRCD-min-tck: | |
| 114 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 115 | + maximum: 15 | |
| 116 | + description: | | |
| 117 | + RAS-to-CAS delay in terms of number of clock cycles. | |
| 118 | + | |
| 119 | + tRFC-min-tck: | |
| 120 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 121 | + maximum: 255 | |
| 122 | + description: | | |
| 123 | + Refresh Cycle time in terms of number of clock cycles. | |
| 124 | + | |
| 125 | + tRL-min-tck: | |
| 126 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 127 | + maximum: 15 | |
| 128 | + description: | | |
| 129 | + READ data latency in terms of number of clock cycles. | |
| 130 | + | |
| 131 | + tRPab-min-tck: | |
| 132 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 133 | + maximum: 15 | |
| 134 | + description: | | |
| 135 | + Row precharge time (all banks) in terms of number of clock cycles. | |
| 136 | + | |
| 137 | + tRPpb-min-tck: | |
| 138 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 139 | + maximum: 15 | |
| 140 | + description: | | |
| 141 | + Row precharge time (single banks) in terms of number of clock cycles. | |
| 142 | + | |
| 143 | + tRRD-min-tck: | |
| 144 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 145 | + maximum: 15 | |
| 146 | + description: | | |
| 147 | + Active bank A to active bank B in terms of number of clock cycles. | |
| 148 | + | |
| 149 | + tRTP-min-tck: | |
| 150 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 151 | + maximum: 15 | |
| 152 | + description: | | |
| 153 | + Internal READ to PRECHARGE command delay in terms of number of clock | |
| 154 | + cycles. | |
| 155 | + | |
| 156 | + tW2W-C2C-min-tck: | |
| 157 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 158 | + enum: [0, 1] | |
| 159 | + description: | | |
| 160 | + Additional WRITE-to-WRITE delay in chip-to-chip cases in terms of number | |
| 161 | + of clock cycles. | |
| 162 | + | |
| 163 | + tWL-min-tck: | |
| 164 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 165 | + maximum: 15 | |
| 166 | + description: | | |
| 167 | + WRITE data latency in terms of number of clock cycles. | |
| 168 | + | |
| 169 | + tWR-min-tck: | |
| 170 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 171 | + maximum: 15 | |
| 172 | + description: | | |
| 173 | + WRITE recovery time in terms of number of clock cycles. | |
| 174 | + | |
| 175 | + tWTR-min-tck: | |
| 176 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 177 | + maximum: 15 | |
| 178 | + description: | | |
| 179 | + Internal WRITE-to-READ command delay in terms of number of clock cycles. | |
| 180 | + | |
| 181 | + tXP-min-tck: | |
| 182 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 183 | + maximum: 255 | |
| 184 | + description: | | |
| 185 | + Exit power-down to next valid command delay in terms of number of clock | |
| 186 | + cycles. | |
| 187 | + | |
| 188 | + tXSR-min-tck: | |
| 189 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 190 | + maximum: 1023 | |
| 191 | + description: | | |
| 192 | + SELF REFRESH exit to next valid command delay in terms of number of clock | |
| 193 | + cycles. | |
| 194 | + | |
| 195 | +patternProperties: | |
| 196 | + "^timings((-[0-9])+|(@[0-9a-f]+))?$": | |
| 197 | + $ref: jedec,lpddr3-timings.yaml | |
| 198 | + description: | | |
| 199 | + The lpddr3 node may have one or more child nodes with timings. | |
| 200 | + Each timing node provides AC timing parameters of the device for a given | |
| 201 | + speed-bin. The user may provide the timings for as many speed-bins as is | |
| 202 | + required. | |
| 203 | + | |
| 204 | +required: | |
| 205 | + - compatible | |
| 206 | + - density | |
| 207 | + - io-width | |
| 208 | + | |
| 209 | +additionalProperties: false | |
| 210 | + | |
| 211 | +examples: | |
| 212 | + - | | |
| 213 | + lpddr3 { | |
| 214 | + compatible = "samsung,K3QF2F20DB", "jedec,lpddr3"; | |
| 215 | + density = <16384>; | |
| 216 | + io-width = <32>; | |
| 217 | + | |
| 218 | + tCKE-min-tck = <2>; | |
| 219 | + tCKESR-min-tck = <2>; | |
| 220 | + tDQSCK-min-tck = <5>; | |
| 221 | + tFAW-min-tck = <5>; | |
| 222 | + tMRD-min-tck = <5>; | |
| 223 | + tR2R-C2C-min-tck = <0>; | |
| 224 | + tRAS-min-tck = <5>; | |
| 225 | + tRC-min-tck = <6>; | |
| 226 | + tRCD-min-tck = <3>; | |
| 227 | + tRFC-min-tck = <17>; | |
| 228 | + tRL-min-tck = <14>; | |
| 229 | + tRPab-min-tck = <2>; | |
| 230 | + tRPpb-min-tck = <2>; | |
| 231 | + tRRD-min-tck = <2>; | |
| 232 | + tRTP-min-tck = <2>; | |
| 233 | + tW2W-C2C-min-tck = <0>; | |
| 234 | + tWL-min-tck = <8>; | |
| 235 | + tWR-min-tck = <7>; | |
| 236 | + tWTR-min-tck = <2>; | |
| 237 | + tXP-min-tck = <2>; | |
| 238 | + tXSR-min-tck = <12>; | |
| 239 | + | |
| 240 | + timings { | |
| 241 | + compatible = "jedec,lpddr3-timings"; | |
| 242 | + max-freq = <800000000>; | |
| 243 | + min-freq = <100000000>; | |
| 244 | + tCKE = <3750>; | |
| 245 | + tCKESR = <3750>; | |
| 246 | + tFAW = <25000>; | |
| 247 | + tMRD = <7000>; | |
| 248 | + tR2R-C2C = <0>; | |
| 249 | + tRAS = <23000>; | |
| 250 | + tRC = <33750>; | |
| 251 | + tRCD = <10000>; | |
| 252 | + tRFC = <65000>; | |
| 253 | + tRPab = <12000>; | |
| 254 | + tRPpb = <12000>; | |
| 255 | + tRRD = <6000>; | |
| 256 | + tRTP = <3750>; | |
| 257 | + tW2W-C2C = <0>; | |
| 258 | + tWR = <7500>; | |
| 259 | + tWTR = <3750>; | |
| 260 | + tXP = <3750>; | |
| 261 | + tXSR = <70000>; | |
| 262 | + }; | |
| 263 | + }; | |
| @@ -1,52 +0,0 @@ | ||
| 1 | −* AC timing parameters of LPDDR2(JESD209-2) memories for a given speed-bin | |
| 2 | − | |
| 3 | −Required properties: | |
| 4 | −- compatible : Should be "jedec,lpddr2-timings" | |
| 5 | −- min-freq : minimum DDR clock frequency for the speed-bin. Type is <u32> | |
| 6 | −- max-freq : maximum DDR clock frequency for the speed-bin. Type is <u32> | |
| 7 | − | |
| 8 | −Optional properties: | |
| 9 | − | |
| 10 | −The following properties represent AC timing parameters from the memory | |
| 11 | −data-sheet of the device for a given speed-bin. All these properties are | |
| 12 | −of type <u32> and the default unit is ps (pico seconds). Parameters with | |
| 13 | −a different unit have a suffix indicating the unit such as 'tRAS-max-ns' | |
| 14 | −- tRCD | |
| 15 | −- tWR | |
| 16 | −- tRAS-min | |
| 17 | −- tRRD | |
| 18 | −- tWTR | |
| 19 | −- tXP | |
| 20 | −- tRTP | |
| 21 | −- tDQSCK-max | |
| 22 | −- tFAW | |
| 23 | −- tZQCS | |
| 24 | −- tZQinit | |
| 25 | −- tRPab | |
| 26 | −- tZQCL | |
| 27 | −- tCKESR | |
| 28 | −- tRAS-max-ns | |
| 29 | −- tDQSCK-max-derated | |
| 30 | − | |
| 31 | −Example: | |
| 32 | − | |
| 33 | −timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { | |
| 34 | − compatible = "jedec,lpddr2-timings"; | |
| 35 | − min-freq = <10000000>; | |
| 36 | − max-freq = <400000000>; | |
| 37 | − tRPab = <21000>; | |
| 38 | − tRCD = <18000>; | |
| 39 | − tWR = <15000>; | |
| 40 | − tRAS-min = <42000>; | |
| 41 | − tRRD = <10000>; | |
| 42 | − tWTR = <7500>; | |
| 43 | − tXP = <7500>; | |
| 44 | − tRTP = <7500>; | |
| 45 | − tCKESR = <15000>; | |
| 46 | − tDQSCK-max = <5500>; | |
| 47 | − tFAW = <50000>; | |
| 48 | − tZQCS = <90000>; | |
| 49 | − tZQCL = <360000>; | |
| 50 | − tZQinit = <1000000>; | |
| 51 | − tRAS-max-ns = <70000>; | |
| 52 | −}; | |
| @@ -1,58 +0,0 @@ | ||
| 1 | −* AC timing parameters of LPDDR3 memories for a given speed-bin. | |
| 2 | − | |
| 3 | −The structures are based on LPDDR2 and extended where needed. | |
| 4 | − | |
| 5 | −Required properties: | |
| 6 | −- compatible : Should be "jedec,lpddr3-timings" | |
| 7 | −- min-freq : minimum DDR clock frequency for the speed-bin. Type is <u32> | |
| 8 | −- reg : maximum DDR clock frequency for the speed-bin. Type is <u32> | |
| 9 | − | |
| 10 | −Optional properties: | |
| 11 | − | |
| 12 | −The following properties represent AC timing parameters from the memory | |
| 13 | −data-sheet of the device for a given speed-bin. All these properties are | |
| 14 | −of type <u32> and the default unit is ps (pico seconds). | |
| 15 | −- tRFC | |
| 16 | −- tRRD | |
| 17 | −- tRPab | |
| 18 | −- tRPpb | |
| 19 | −- tRCD | |
| 20 | −- tRC | |
| 21 | −- tRAS | |
| 22 | −- tWTR | |
| 23 | −- tWR | |
| 24 | −- tRTP | |
| 25 | −- tW2W-C2C | |
| 26 | −- tR2R-C2C | |
| 27 | −- tFAW | |
| 28 | −- tXSR | |
| 29 | −- tXP | |
| 30 | −- tCKE | |
| 31 | −- tCKESR | |
| 32 | −- tMRD | |
| 33 | − | |
| 34 | −Example: | |
| 35 | − | |
| 36 | −timings_samsung_K3QF2F20DB_800mhz: lpddr3-timings@800000000 { | |
| 37 | − compatible = "jedec,lpddr3-timings"; | |
| 38 | − reg = <800000000>; /* workaround: it shows max-freq */ | |
| 39 | − min-freq = <100000000>; | |
| 40 | − tRFC = <65000>; | |
| 41 | − tRRD = <6000>; | |
| 42 | − tRPab = <12000>; | |
| 43 | − tRPpb = <12000>; | |
| 44 | − tRCD = <10000>; | |
| 45 | − tRC = <33750>; | |
| 46 | − tRAS = <23000>; | |
| 47 | − tWTR = <3750>; | |
| 48 | − tWR = <7500>; | |
| 49 | − tRTP = <3750>; | |
| 50 | − tW2W-C2C = <0>; | |
| 51 | − tR2R-C2C = <0>; | |
| 52 | − tFAW = <25000>; | |
| 53 | − tXSR = <70000>; | |
| 54 | − tXP = <3750>; | |
| 55 | − tCKE = <3750>; | |
| 56 | − tCKESR = <3750>; | |
| 57 | − tMRD = <7000>; | |
| 58 | −}; | |
| @@ -1,107 +0,0 @@ | ||
| 1 | −* LPDDR3 SDRAM memories compliant to JEDEC JESD209-3C | |
| 2 | − | |
| 3 | −Required properties: | |
| 4 | −- compatible : Should be "<vendor>,<type>", and generic value "jedec,lpddr3". | |
| 5 | − Example "<vendor>,<type>" values: | |
| 6 | − "samsung,K3QF2F20DB" | |
| 7 | − | |
| 8 | −- density : <u32> representing density in Mb (Mega bits) | |
| 9 | −- io-width : <u32> representing bus width. Possible values are 8, 16, 32, 64 | |
| 10 | −- #address-cells: Must be set to 1 | |
| 11 | −- #size-cells: Must be set to 0 | |
| 12 | − | |
| 13 | −Optional properties: | |
| 14 | − | |
| 15 | −- manufacturer-id : <u32> Manufacturer ID value read from Mode Register 5 | |
| 16 | −- revision-id : <u32 u32> Revision IDs read from Mode Registers 6 and 7 | |
| 17 | − | |
| 18 | −The following optional properties represent the minimum value of some AC | |
| 19 | −timing parameters of the DDR device in terms of number of clock cycles. | |
| 20 | −These values shall be obtained from the device data-sheet. | |
| 21 | −- tRFC-min-tck | |
| 22 | −- tRRD-min-tck | |
| 23 | −- tRPab-min-tck | |
| 24 | −- tRPpb-min-tck | |
| 25 | −- tRCD-min-tck | |
| 26 | −- tRC-min-tck | |
| 27 | −- tRAS-min-tck | |
| 28 | −- tWTR-min-tck | |
| 29 | −- tWR-min-tck | |
| 30 | −- tRTP-min-tck | |
| 31 | −- tW2W-C2C-min-tck | |
| 32 | −- tR2R-C2C-min-tck | |
| 33 | −- tWL-min-tck | |
| 34 | −- tDQSCK-min-tck | |
| 35 | −- tRL-min-tck | |
| 36 | −- tFAW-min-tck | |
| 37 | −- tXSR-min-tck | |
| 38 | −- tXP-min-tck | |
| 39 | −- tCKE-min-tck | |
| 40 | −- tCKESR-min-tck | |
| 41 | −- tMRD-min-tck | |
| 42 | − | |
| 43 | −Child nodes: | |
| 44 | −- The lpddr3 node may have one or more child nodes of type "lpddr3-timings". | |
| 45 | − "lpddr3-timings" provides AC timing parameters of the device for | |
| 46 | − a given speed-bin. Please see | |
| 47 | − Documentation/devicetree/bindings/memory-controllers/ddr/lpddr3-timings.txt | |
| 48 | − for more information on "lpddr3-timings" | |
| 49 | − | |
| 50 | −Example: | |
| 51 | − | |
| 52 | −samsung_K3QF2F20DB: lpddr3 { | |
| 53 | − compatible = "samsung,K3QF2F20DB", "jedec,lpddr3"; | |
| 54 | − density = <16384>; | |
| 55 | − io-width = <32>; | |
| 56 | − manufacturer-id = <1>; | |
| 57 | − revision-id = <123 234>; | |
| 58 | − #address-cells = <1>; | |
| 59 | − #size-cells = <0>; | |
| 60 | − | |
| 61 | − tRFC-min-tck = <17>; | |
| 62 | − tRRD-min-tck = <2>; | |
| 63 | − tRPab-min-tck = <2>; | |
| 64 | − tRPpb-min-tck = <2>; | |
| 65 | − tRCD-min-tck = <3>; | |
| 66 | − tRC-min-tck = <6>; | |
| 67 | − tRAS-min-tck = <5>; | |
| 68 | − tWTR-min-tck = <2>; | |
| 69 | − tWR-min-tck = <7>; | |
| 70 | − tRTP-min-tck = <2>; | |
| 71 | − tW2W-C2C-min-tck = <0>; | |
| 72 | − tR2R-C2C-min-tck = <0>; | |
| 73 | − tWL-min-tck = <8>; | |
| 74 | − tDQSCK-min-tck = <5>; | |
| 75 | − tRL-min-tck = <14>; | |
| 76 | − tFAW-min-tck = <5>; | |
| 77 | − tXSR-min-tck = <12>; | |
| 78 | − tXP-min-tck = <2>; | |
| 79 | − tCKE-min-tck = <2>; | |
| 80 | − tCKESR-min-tck = <2>; | |
| 81 | − tMRD-min-tck = <5>; | |
| 82 | − | |
| 83 | − timings_samsung_K3QF2F20DB_800mhz: lpddr3-timings@800000000 { | |
| 84 | − compatible = "jedec,lpddr3-timings"; | |
| 85 | − /* workaround: 'reg' shows max-freq */ | |
| 86 | − reg = <800000000>; | |
| 87 | − min-freq = <100000000>; | |
| 88 | − tRFC = <65000>; | |
| 89 | − tRRD = <6000>; | |
| 90 | − tRPab = <12000>; | |
| 91 | − tRPpb = <12000>; | |
| 92 | − tRCD = <10000>; | |
| 93 | − tRC = <33750>; | |
| 94 | − tRAS = <23000>; | |
| 95 | − tWTR = <3750>; | |
| 96 | − tWR = <7500>; | |
| 97 | − tRTP = <3750>; | |
| 98 | − tW2W-C2C = <0>; | |
| 99 | − tR2R-C2C = <0>; | |
| 100 | − tFAW = <25000>; | |
| 101 | − tXSR = <70000>; | |
| 102 | − tXP = <3750>; | |
| 103 | − tCKE = <3750>; | |
| 104 | − tCKESR = <3750>; | |
| 105 | − tMRD = <7000>; | |
| 106 | − }; | |
| 107 | −} | |
| @@ -0,0 +1,113 @@ | ||
| 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/fsl/fsl,ifc.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: FSL/NXP Integrated Flash Controller | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Li Yang <leoyang.li@nxp.com> | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + NXP's integrated flash controller (IFC) is an advanced version of the | |
| 14 | + enhanced local bus controller which includes similar programming and signal | |
| 15 | + interfaces with an extended feature set. The IFC provides access to multiple | |
| 16 | + external memory types, such as NAND flash (SLC and MLC), NOR flash, EPROM, | |
| 17 | + SRAM and other memories where address and data are shared on a bus. | |
| 18 | + | |
| 19 | +properties: | |
| 20 | + $nodename: | |
| 21 | + pattern: "^memory-controller@[0-9a-f]+$" | |
| 22 | + | |
| 23 | + compatible: | |
| 24 | + const: fsl,ifc | |
| 25 | + | |
| 26 | + "#address-cells": | |
| 27 | + enum: [2, 3] | |
| 28 | + description: | | |
| 29 | + Should be either two or three. The first cell is the chipselect | |
| 30 | + number, and the remaining cells are the offset into the chipselect. | |
| 31 | + | |
| 32 | + "#size-cells": | |
| 33 | + enum: [1, 2] | |
| 34 | + description: | | |
| 35 | + Either one or two, depending on how large each chipselect can be. | |
| 36 | + | |
| 37 | + reg: | |
| 38 | + maxItems: 1 | |
| 39 | + | |
| 40 | + interrupts: | |
| 41 | + minItems: 1 | |
| 42 | + maxItems: 2 | |
| 43 | + description: | | |
| 44 | + IFC may have one or two interrupts. If two interrupt specifiers are | |
| 45 | + present, the first is the "common" interrupt (CM_EVTER_STAT), and the | |
| 46 | + second is the NAND interrupt (NAND_EVTER_STAT). If there is only one, | |
| 47 | + that interrupt reports both types of event. | |
| 48 | + | |
| 49 | + little-endian: | |
| 50 | + type: boolean | |
| 51 | + description: | | |
| 52 | + If this property is absent, the big-endian mode will be in use as default | |
| 53 | + for registers. | |
| 54 | + | |
| 55 | + ranges: | |
| 56 | + description: | | |
| 57 | + Each range corresponds to a single chipselect, and covers the entire | |
| 58 | + access window as configured. | |
| 59 | + | |
| 60 | +patternProperties: | |
| 61 | + "^.*@[a-f0-9]+(,[a-f0-9]+)+$": | |
| 62 | + type: object | |
| 63 | + description: | | |
| 64 | + Child device nodes describe the devices connected to IFC such as NOR (e.g. | |
| 65 | + cfi-flash) and NAND (fsl,ifc-nand). There might be board specific devices | |
| 66 | + like FPGAs, CPLDs, etc. | |
| 67 | + | |
| 68 | + required: | |
| 69 | + - compatible | |
| 70 | + - reg | |
| 71 | + | |
| 72 | +required: | |
| 73 | + - compatible | |
| 74 | + - reg | |
| 75 | + - interrupts | |
| 76 | + | |
| 77 | +additionalProperties: false | |
| 78 | + | |
| 79 | +examples: | |
| 80 | + - | | |
| 81 | + soc { | |
| 82 | + #address-cells = <2>; | |
| 83 | + #size-cells = <2>; | |
| 84 | + | |
| 85 | + memory-controller@ffe1e000 { | |
| 86 | + compatible = "fsl,ifc"; | |
| 87 | + #address-cells = <2>; | |
| 88 | + #size-cells = <1>; | |
| 89 | + reg = <0x0 0xffe1e000 0 0x2000>; | |
| 90 | + interrupts = <16 2 19 2>; | |
| 91 | + little-endian; | |
| 92 | + | |
| 93 | + /* NOR, NAND Flashes and CPLD on board */ | |
| 94 | + ranges = <0x0 0x0 0x0 0xee000000 0x02000000>, | |
| 95 | + <0x1 0x0 0x0 0xffa00000 0x00010000>, | |
| 96 | + <0x3 0x0 0x0 0xffb00000 0x00020000>; | |
| 97 | + | |
| 98 | + flash@0,0 { | |
| 99 | + #address-cells = <1>; | |
| 100 | + #size-cells = <1>; | |
| 101 | + compatible = "cfi-flash"; | |
| 102 | + reg = <0x0 0x0 0x2000000>; | |
| 103 | + bank-width = <2>; | |
| 104 | + device-width = <1>; | |
| 105 | + | |
| 106 | + partition@0 { | |
| 107 | + /* 32MB for user data */ | |
| 108 | + reg = <0x0 0x02000000>; | |
| 109 | + label = "NOR Data"; | |
| 110 | + }; | |
| 111 | + }; | |
| 112 | + }; | |
| 113 | + }; | |
| @@ -1,82 +0,0 @@ | ||
| 1 | −Integrated Flash Controller | |
| 2 | − | |
| 3 | −Properties: | |
| 4 | −- name : Should be ifc | |
| 5 | −- compatible : should contain "fsl,ifc". The version of the integrated | |
| 6 | − flash controller can be found in the IFC_REV register at | |
| 7 | − offset zero. | |
| 8 | − | |
| 9 | −- #address-cells : Should be either two or three. The first cell is the | |
| 10 | − chipselect number, and the remaining cells are the | |
| 11 | − offset into the chipselect. | |
| 12 | −- #size-cells : Either one or two, depending on how large each chipselect | |
| 13 | − can be. | |
| 14 | −- reg : Offset and length of the register set for the device | |
| 15 | −- interrupts: IFC may have one or two interrupts. If two interrupt | |
| 16 | − specifiers are present, the first is the "common" | |
| 17 | − interrupt (CM_EVTER_STAT), and the second is the NAND | |
| 18 | − interrupt (NAND_EVTER_STAT). If there is only one, | |
| 19 | − that interrupt reports both types of event. | |
| 20 | − | |
| 21 | −- little-endian : If this property is absent, the big-endian mode will | |
| 22 | − be in use as default for registers. | |
| 23 | − | |
| 24 | −- ranges : Each range corresponds to a single chipselect, and covers | |
| 25 | − the entire access window as configured. | |
| 26 | − | |
| 27 | −Child device nodes describe the devices connected to IFC such as NOR (e.g. | |
| 28 | −cfi-flash) and NAND (fsl,ifc-nand). There might be board specific devices | |
| 29 | −like FPGAs, CPLDs, etc. | |
| 30 | − | |
| 31 | −Example: | |
| 32 | − | |
| 33 | − ifc@ffe1e000 { | |
| 34 | − compatible = "fsl,ifc", "simple-bus"; | |
| 35 | − #address-cells = <2>; | |
| 36 | − #size-cells = <1>; | |
| 37 | − reg = <0x0 0xffe1e000 0 0x2000>; | |
| 38 | − interrupts = <16 2 19 2>; | |
| 39 | − little-endian; | |
| 40 | − | |
| 41 | − /* NOR, NAND Flashes and CPLD on board */ | |
| 42 | − ranges = <0x0 0x0 0x0 0xee000000 0x02000000 | |
| 43 | − 0x1 0x0 0x0 0xffa00000 0x00010000 | |
| 44 | − 0x3 0x0 0x0 0xffb00000 0x00020000>; | |
| 45 | − | |
| 46 | − flash@0,0 { | |
| 47 | − #address-cells = <1>; | |
| 48 | − #size-cells = <1>; | |
| 49 | − compatible = "cfi-flash"; | |
| 50 | − reg = <0x0 0x0 0x2000000>; | |
| 51 | − bank-width = <2>; | |
| 52 | − device-width = <1>; | |
| 53 | − | |
| 54 | − partition@0 { | |
| 55 | − /* 32MB for user data */ | |
| 56 | − reg = <0x0 0x02000000>; | |
| 57 | − label = "NOR Data"; | |
| 58 | − }; | |
| 59 | − }; | |
| 60 | − | |
| 61 | − flash@1,0 { | |
| 62 | − #address-cells = <1>; | |
| 63 | − #size-cells = <1>; | |
| 64 | − compatible = "fsl,ifc-nand"; | |
| 65 | − reg = <0x1 0x0 0x10000>; | |
| 66 | − | |
| 67 | − partition@0 { | |
| 68 | − /* This location must not be altered */ | |
| 69 | − /* 1MB for u-boot Bootloader Image */ | |
| 70 | − reg = <0x0 0x00100000>; | |
| 71 | − label = "NAND U-Boot Image"; | |
| 72 | − read-only; | |
| 73 | − }; | |
| 74 | − }; | |
| 75 | − | |
| 76 | − cpld@3,0 { | |
| 77 | − #address-cells = <1>; | |
| 78 | − #size-cells = <1>; | |
| 79 | − compatible = "fsl,p1010rdb-cpld"; | |
| 80 | − reg = <0x3 0x0 0x000001f>; | |
| 81 | − }; | |
| 82 | − }; | |
| @@ -16,7 +16,7 @@ description: | · 15 unmodified lines | ||
| 16 | 16 | MediaTek SMI have two generations of HW architecture, here is the list |
| 17 | 17 | which generation the SoCs use: |
| 18 | 18 | generation 1: mt2701 and mt7623. |
| 19 | − generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8192 and mt8195. | |
| 19 | + generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8192 and mt8195. | |
| 20 | 20 | |
| 21 | 21 | There's slight differences between the two SMI, for generation 2, the |
| 22 | 22 | register which control the iommu port is at each larb's register base. But |
| @@ -35,6 +35,7 @@ properties: · 12 unmodified lines | ||
| 35 | 35 | - mediatek,mt8167-smi-common |
| 36 | 36 | - mediatek,mt8173-smi-common |
| 37 | 37 | - mediatek,mt8183-smi-common |
| 38 | + - mediatek,mt8186-smi-common | |
| 38 | 39 | - mediatek,mt8192-smi-common |
| 39 | 40 | - mediatek,mt8195-smi-common-vdo |
| 40 | 41 | - mediatek,mt8195-smi-common-vpp |
| @@ -88,10 +89,9 @@ allOf: · 47 unmodified lines | ||
| 88 | 89 | - mediatek,mt2701-smi-common |
| 89 | 90 | then: |
| 90 | 91 | properties: |
| 91 | − clock: | |
| 92 | − items: | |
| 93 | − minItems: 3 | |
| 94 | − maxItems: 3 | |
| 92 | + clocks: | |
| 93 | + minItems: 3 | |
| 94 | + maxItems: 3 | |
| 95 | 95 | clock-names: |
| 96 | 96 | items: |
| 97 | 97 | - const: apb |
| @@ -108,10 +108,9 @@ allOf: · 10 unmodified lines | ||
| 108 | 108 | required: |
| 109 | 109 | - mediatek,smi |
| 110 | 110 | properties: |
| 111 | − clock: | |
| 112 | − items: | |
| 113 | − minItems: 3 | |
| 114 | − maxItems: 3 | |
| 111 | + clocks: | |
| 112 | + minItems: 3 | |
| 113 | + maxItems: 3 | |
| 115 | 114 | clock-names: |
| 116 | 115 | items: |
| 117 | 116 | - const: apb |
| @@ -127,16 +126,16 @@ allOf: · 9 unmodified lines | ||
| 127 | 126 | enum: |
| 128 | 127 | - mediatek,mt6779-smi-common |
| 129 | 128 | - mediatek,mt8183-smi-common |
| 129 | + - mediatek,mt8186-smi-common | |
| 130 | 130 | - mediatek,mt8192-smi-common |
| 131 | 131 | - mediatek,mt8195-smi-common-vdo |
| 132 | 132 | - mediatek,mt8195-smi-common-vpp |
| 133 | 133 | |
| 134 | 134 | then: |
| 135 | 135 | properties: |
| 136 | − clock: | |
| 137 | − items: | |
| 138 | − minItems: 4 | |
| 139 | − maxItems: 4 | |
| 136 | + clocks: | |
| 137 | + minItems: 4 | |
| 138 | + maxItems: 4 | |
| 140 | 139 | clock-names: |
| 141 | 140 | items: |
| 142 | 141 | - const: apb |
| @@ -146,10 +145,9 @@ allOf: · 3 unmodified lines | ||
| 146 | 145 | |
| 147 | 146 | else: # for gen2 HW that don't have gals |
| 148 | 147 | properties: |
| 149 | − clock: | |
| 150 | − items: | |
| 151 | − minItems: 2 | |
| 152 | − maxItems: 2 | |
| 148 | + clocks: | |
| 149 | + minItems: 2 | |
| 150 | + maxItems: 2 | |
| 153 | 151 | clock-names: |
| 154 | 152 | items: |
| 155 | 153 | - const: apb |
| @@ -23,6 +23,7 @@ properties: · 22 unmodified lines | ||
| 23 | 23 | - mediatek,mt8167-smi-larb |
| 24 | 24 | - mediatek,mt8173-smi-larb |
| 25 | 25 | - mediatek,mt8183-smi-larb |
| 26 | + - mediatek,mt8186-smi-larb | |
| 26 | 27 | - mediatek,mt8192-smi-larb |
| 27 | 28 | - mediatek,mt8195-smi-larb |
| 28 | 29 | |
| @@ -75,15 +76,16 @@ allOf: · 46 unmodified lines | ||
| 75 | 76 | compatible: |
| 76 | 77 | enum: |
| 77 | 78 | - mediatek,mt8183-smi-larb |
| 79 | + - mediatek,mt8186-smi-larb | |
| 78 | 80 | - mediatek,mt8195-smi-larb |
| 79 | 81 | |
| 80 | 82 | then: |
| 81 | 83 | properties: |
| 82 | − clock: | |
| 83 | − items: | |
| 84 | − minItems: 3 | |
| 85 | − maxItems: 3 | |
| 84 | + clocks: | |
| 85 | + minItems: 2 | |
| 86 | + maxItems: 3 | |
| 86 | 87 | clock-names: |
| 88 | + minItems: 2 | |
| 87 | 89 | items: |
| 88 | 90 | - const: apb |
| 89 | 91 | - const: smi |
| @@ -91,10 +93,9 @@ allOf: · 1 unmodified line | ||
| 91 | 93 | |
| 92 | 94 | else: |
| 93 | 95 | properties: |
| 94 | − clock: | |
| 95 | − items: | |
| 96 | − minItems: 2 | |
| 97 | − maxItems: 2 | |
| 96 | + clocks: | |
| 97 | + minItems: 2 | |
| 98 | + maxItems: 2 | |
| 98 | 99 | clock-names: |
| 99 | 100 | items: |
| 100 | 101 | - const: apb |
| @@ -108,7 +109,7 @@ allOf: · 7 unmodified lines | ||
| 108 | 109 | - mediatek,mt2701-smi-larb |
| 109 | 110 | - mediatek,mt2712-smi-larb |
| 110 | 111 | - mediatek,mt6779-smi-larb |
| 111 | − - mediatek,mt8167-smi-larb | |
| 112 | + - mediatek,mt8186-smi-larb | |
| 112 | 113 | - mediatek,mt8192-smi-larb |
| 113 | 114 | - mediatek,mt8195-smi-larb |
| 114 | 115 | |
| @@ -40,7 +40,8 @@ properties: · 39 unmodified lines | ||
| 40 | 40 | - items: |
| 41 | 41 | - enum: |
| 42 | 42 | - renesas,r9a07g044-rpc-if # RZ/G2{L,LC} |
| 43 | − - const: renesas,rzg2l-rpc-if # RZ/G2L family | |
| 43 | + - renesas,r9a07g054-rpc-if # RZ/V2L | |
| 44 | + - const: renesas,rzg2l-rpc-if | |
| 44 | 45 | |
| 45 | 46 | reg: |
| 46 | 47 | items: |
| @@ -51,8 +51,7 @@ properties: · 50 unmodified lines | ||
| 51 | 51 | $ref: '/schemas/types.yaml#/definitions/phandle' |
| 52 | 52 | description: | |
| 53 | 53 | phandle of the connected DRAM memory device. For more information please |
| 54 | − refer to documentation file: | |
| 55 | − Documentation/devicetree/bindings/memory-controllers/ddr/lpddr3.txt | |
| 54 | + refer to jedec,lpddr3.yaml. | |
| 56 | 55 | |
| 57 | 56 | operating-points-v2: true |
| 58 | 57 | |
| @@ -12,13 +12,14 @@ maintainers: · 11 unmodified lines | ||
| 12 | 12 | - Jianxin Pan <jianxin.pan@amlogic.com> |
| 13 | 13 | |
| 14 | 14 | description: |+ |
| 15 | − Secure Power Domains used in Meson A1/C1 SoCs, and should be the child node | |
| 15 | + Secure Power Domains used in Meson A1/C1/S4 SoCs, and should be the child node | |
| 16 | 16 | of secure-monitor. |
| 17 | 17 | |
| 18 | 18 | properties: |
| 19 | 19 | compatible: |
| 20 | 20 | enum: |
| 21 | 21 | - amlogic,meson-a1-pwrc |
| 22 | + - amlogic,meson-s4-pwrc | |
| 22 | 23 | |
| 23 | 24 | "#power-domain-cells": |
| 24 | 25 | const: 1 |
| @@ -26,7 +26,9 @@ properties: · 25 unmodified lines | ||
| 26 | 26 | - mediatek,mt8167-power-controller |
| 27 | 27 | - mediatek,mt8173-power-controller |
| 28 | 28 | - mediatek,mt8183-power-controller |
| 29 | + - mediatek,mt8186-power-controller | |
| 29 | 30 | - mediatek,mt8192-power-controller |
| 31 | + - mediatek,mt8195-power-controller | |
| 30 | 32 | |
| 31 | 33 | '#power-domain-cells': |
| 32 | 34 | const: 1 |
| @@ -64,6 +66,7 @@ patternProperties: · 31 unmodified lines | ||
| 64 | 66 | "include/dt-bindings/power/mt8173-power.h" - for MT8173 type power domain. |
| 65 | 67 | "include/dt-bindings/power/mt8183-power.h" - for MT8183 type power domain. |
| 66 | 68 | "include/dt-bindings/power/mt8192-power.h" - for MT8192 type power domain. |
| 69 | + "include/dt-bindings/power/mt8195-power.h" - for MT8195 type power domain. | |
| 67 | 70 | maxItems: 1 |
| 68 | 71 | |
| 69 | 72 | clocks: |
| @@ -17,6 +17,7 @@ properties: · 16 unmodified lines | ||
| 17 | 17 | compatible: |
| 18 | 18 | enum: |
| 19 | 19 | - qcom,mdm9607-rpmpd |
| 20 | + - qcom,msm8226-rpmpd | |
| 20 | 21 | - qcom,msm8916-rpmpd |
| 21 | 22 | - qcom,msm8939-rpmpd |
| 22 | 23 | - qcom,msm8953-rpmpd |
| @@ -47,6 +47,10 @@ properties: · 46 unmodified lines | ||
| 47 | 47 | - qcom,sm8350-cdsp-pas |
| 48 | 48 | - qcom,sm8350-slpi-pas |
| 49 | 49 | - qcom,sm8350-mpss-pas |
| 50 | + - qcom,sm8450-adsp-pas | |
| 51 | + - qcom,sm8450-cdsp-pas | |
| 52 | + - qcom,sm8450-mpss-pas | |
| 53 | + - qcom,sm8450-slpi-pas | |
| 50 | 54 | |
| 51 | 55 | reg: |
| 52 | 56 | maxItems: 1 |
| @@ -175,6 +179,10 @@ allOf: · 122 unmodified lines | ||
| 175 | 179 | - qcom,sm8350-cdsp-pas |
| 176 | 180 | - qcom,sm8350-slpi-pas |
| 177 | 181 | - qcom,sm8350-mpss-pas |
| 182 | + - qcom,sm8450-adsp-pas | |
| 183 | + - qcom,sm8450-cdsp-pas | |
| 184 | + - qcom,sm8450-slpi-pas | |
| 185 | + - qcom,sm8450-mpss-pas | |
| 178 | 186 | then: |
| 179 | 187 | properties: |
| 180 | 188 | clocks: |
| @@ -283,6 +291,9 @@ allOf: · 102 unmodified lines | ||
| 283 | 291 | - qcom,sm8350-adsp-pas |
| 284 | 292 | - qcom,sm8350-cdsp-pas |
| 285 | 293 | - qcom,sm8350-slpi-pas |
| 294 | + - qcom,sm8450-adsp-pas | |
| 295 | + - qcom,sm8450-cdsp-pas | |
| 296 | + - qcom,sm8450-slpi-pas | |
| 286 | 297 | then: |
| 287 | 298 | properties: |
| 288 | 299 | interrupts: |
| @@ -312,6 +323,7 @@ allOf: · 23 unmodified lines | ||
| 312 | 323 | - qcom,sm6350-mpss-pas |
| 313 | 324 | - qcom,sm8150-mpss-pas |
| 314 | 325 | - qcom,sm8350-mpss-pas |
| 326 | + - qcom,sm8450-mpss-pas | |
| 315 | 327 | then: |
| 316 | 328 | properties: |
| 317 | 329 | interrupts: |
| @@ -434,6 +446,7 @@ allOf: · 116 unmodified lines | ||
| 434 | 446 | - qcom,sm6350-mpss-pas |
| 435 | 447 | - qcom,sm8150-mpss-pas |
| 436 | 448 | - qcom,sm8350-mpss-pas |
| 449 | + - qcom,sm8450-mpss-pas | |
| 437 | 450 | then: |
| 438 | 451 | properties: |
| 439 | 452 | power-domains: |
| @@ -458,6 +471,8 @@ allOf: · 18 unmodified lines | ||
| 458 | 471 | - qcom,sm8250-slpi-pas |
| 459 | 472 | - qcom,sm8350-adsp-pas |
| 460 | 473 | - qcom,sm8350-slpi-pas |
| 474 | + - qcom,sm8450-adsp-pas | |
| 475 | + - qcom,sm8450-slpi-pas | |
| 461 | 476 | then: |
| 462 | 477 | properties: |
| 463 | 478 | power-domains: |
| @@ -475,6 +490,7 @@ allOf: · 11 unmodified lines | ||
| 475 | 490 | contains: |
| 476 | 491 | enum: |
| 477 | 492 | - qcom,sm8350-cdsp-pas |
| 493 | + - qcom,sm8450-cdsp-pas | |
| 478 | 494 | then: |
| 479 | 495 | properties: |
| 480 | 496 | power-domains: |
| @@ -27,6 +27,7 @@ Required properties in pwrap device node. · 26 unmodified lines | ||
| 27 | 27 | "mediatek,mt8135-pwrap" for MT8135 SoCs |
| 28 | 28 | "mediatek,mt8173-pwrap" for MT8173 SoCs |
| 29 | 29 | "mediatek,mt8183-pwrap" for MT8183 SoCs |
| 30 | + "mediatek,mt8186-pwrap" for MT8186 SoCs | |
| 30 | 31 | "mediatek,mt8195-pwrap" for MT8195 SoCs |
| 31 | 32 | "mediatek,mt8516-pwrap" for MT8516 SoCs |
| 32 | 33 | - interrupts: IRQ for pwrap in SOC |
| @@ -357,8 +357,7 @@ static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) · 356 unmodified lines | ||
| 357 | 357 | { |
| 358 | 358 | int cpu; |
| 359 | 359 | |
| 360 | − if (qcom_scm_set_cold_boot_addr(secondary_startup_arm, | |
| 361 | − cpu_present_mask)) { | |
| 360 | + if (qcom_scm_set_cold_boot_addr(secondary_startup_arm)) { | |
| 362 | 361 | for_each_present_cpu(cpu) { |
| 363 | 362 | if (cpu == smp_processor_id()) |
| 364 | 363 | continue; |
| @@ -29,7 +29,7 @@ void __init spear13xx_l2x0_init(void) · 28 unmodified lines | ||
| 29 | 29 | /* |
| 30 | 30 | * 512KB (64KB/way), 8-way associativity, parity supported |
| 31 | 31 | * |
| 32 | − * FIXME: 9th bit, of Auxillary Controller register must be set | |
| 32 | + * FIXME: 9th bit, of Auxiliary Controller register must be set | |
| 33 | 33 | * for some spear13xx devices for stable L2 operation. |
| 34 | 34 | * |
| 35 | 35 | * Enable Early BRESP, L2 prefetch for Instruction and Data, |
| @@ -64,6 +64,11 @@ struct cs_timing_state { · 63 unmodified lines | ||
| 64 | 64 | struct cs_timing cs[MAX_CS_COUNT]; |
| 65 | 65 | }; |
| 66 | 66 | |
| 67 | +struct weim_priv { | |
| 68 | + void __iomem *base; | |
| 69 | + struct cs_timing_state timing_state; | |
| 70 | +}; | |
| 71 | + | |
| 67 | 72 | static const struct of_device_id weim_id_table[] = { |
| 68 | 73 | /* i.MX1/21 */ |
| 69 | 74 | { .compatible = "fsl,imx1-weim", .data = &imx1_weim_devtype, }, |
| @@ -128,21 +133,26 @@ err: · 58 unmodified lines | ||
| 128 | 133 | } |
| 129 | 134 | |
| 130 | 135 | /* Parse and set the timing for this device. */ |
| 131 | −static int weim_timing_setup(struct device *dev, | |
| 132 | − struct device_node *np, void __iomem *base, | |
| 133 | − const struct imx_weim_devtype *devtype, | |
| 134 | − struct cs_timing_state *ts) | |
| 136 | +static int weim_timing_setup(struct device *dev, struct device_node *np, | |
| 137 | + const struct imx_weim_devtype *devtype) | |
| 135 | 138 | { |
| 136 | 139 | u32 cs_idx, value[MAX_CS_REGS_COUNT]; |
| 137 | 140 | int i, ret; |
| 138 | 141 | int reg_idx, num_regs; |
| 139 | 142 | struct cs_timing *cst; |
| 143 | + struct weim_priv *priv; | |
| 144 | + struct cs_timing_state *ts; | |
| 145 | + void __iomem *base; | |
| 140 | 146 | |
| 141 | 147 | if (WARN_ON(devtype->cs_regs_count > MAX_CS_REGS_COUNT)) |
| 142 | 148 | return -EINVAL; |
| 143 | 149 | if (WARN_ON(devtype->cs_count > MAX_CS_COUNT)) |
| 144 | 150 | return -EINVAL; |
| 145 | 151 | |
| 152 | + priv = dev_get_drvdata(dev); | |
| 153 | + base = priv->base; | |
| 154 | + ts = &priv->timing_state; | |
| 155 | + | |
| 146 | 156 | ret = of_property_read_u32_array(np, "fsl,weim-cs-timing", |
| 147 | 157 | value, devtype->cs_regs_count); |
| 148 | 158 | if (ret) |
| @@ -189,14 +199,15 @@ static int weim_timing_setup(struct device *dev, · 40 unmodified lines | ||
| 189 | 199 | return 0; |
| 190 | 200 | } |
| 191 | 201 | |
| 192 | −static int weim_parse_dt(struct platform_device *pdev, void __iomem *base) | |
| 202 | +static int weim_parse_dt(struct platform_device *pdev) | |
| 193 | 203 | { |
| 194 | 204 | const struct of_device_id *of_id = of_match_device(weim_id_table, |
| 195 | 205 | &pdev->dev); |
| 196 | 206 | const struct imx_weim_devtype *devtype = of_id->data; |
| 197 | 207 | struct device_node *child; |
| 198 | 208 | int ret, have_child = 0; |
| 199 | − struct cs_timing_state ts = {}; | |
| 209 | + struct weim_priv *priv; | |
| 210 | + void __iomem *base; | |
| 200 | 211 | u32 reg; |
| 201 | 212 | |
| 202 | 213 | if (devtype == &imx50_weim_devtype) { |
| @@ -205,6 +216,9 @@ static int weim_parse_dt(struct platform_device *pdev, void __iomem *base) · 2 unmodified lines | ||
| 205 | 216 | return ret; |
| 206 | 217 | } |
| 207 | 218 | |
| 219 | + priv = dev_get_drvdata(&pdev->dev); | |
| 220 | + base = priv->base; | |
| 221 | + | |
| 208 | 222 | if (of_property_read_bool(pdev->dev.of_node, "fsl,burst-clk-enable")) { |
| 209 | 223 | if (devtype->wcr_bcm) { |
| 210 | 224 | reg = readl(base + devtype->wcr_offset); |
| @@ -229,7 +243,7 @@ static int weim_parse_dt(struct platform_device *pdev, void __iomem *base) · 18 unmodified lines | ||
| 229 | 243 | } |
| 230 | 244 | |
| 231 | 245 | for_each_available_child_of_node(pdev->dev.of_node, child) { |
| 232 | − ret = weim_timing_setup(&pdev->dev, child, base, devtype, &ts); | |
| 246 | + ret = weim_timing_setup(&pdev->dev, child, devtype); | |
| 233 | 247 | if (ret) |
| 234 | 248 | dev_warn(&pdev->dev, "%pOF set timing failed.\n", |
| 235 | 249 | child); |
| @@ -248,17 +262,25 @@ static int weim_parse_dt(struct platform_device *pdev, void __iomem *base) · 12 unmodified lines | ||
| 248 | 262 | |
| 249 | 263 | static int weim_probe(struct platform_device *pdev) |
| 250 | 264 | { |
| 265 | + struct weim_priv *priv; | |
| 251 | 266 | struct resource *res; |
| 252 | 267 | struct clk *clk; |
| 253 | 268 | void __iomem *base; |
| 254 | 269 | int ret; |
| 255 | 270 | |
| 271 | + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | |
| 272 | + if (!priv) | |
| 273 | + return -ENOMEM; | |
| 274 | + | |
| 256 | 275 | /* get the resource */ |
| 257 | 276 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 258 | 277 | base = devm_ioremap_resource(&pdev->dev, res); |
| 259 | 278 | if (IS_ERR(base)) |
| 260 | 279 | return PTR_ERR(base); |
| 261 | 280 | |
| 281 | + priv->base = base; | |
| 282 | + dev_set_drvdata(&pdev->dev, priv); | |
| 283 | + | |
| 262 | 284 | /* get the clock */ |
| 263 | 285 | clk = devm_clk_get(&pdev->dev, NULL); |
| 264 | 286 | if (IS_ERR(clk)) |
| @@ -269,7 +291,7 @@ static int weim_probe(struct platform_device *pdev) · 4 unmodified lines | ||
| 269 | 291 | return ret; |
| 270 | 292 | |
| 271 | 293 | /* parse the device node */ |
| 272 | − ret = weim_parse_dt(pdev, base); | |
| 294 | + ret = weim_parse_dt(pdev); | |
| 273 | 295 | if (ret) |
| 274 | 296 | clk_disable_unprepare(clk); |
| 275 | 297 | else |
| @@ -278,6 +300,81 @@ static int weim_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 278 | 300 | return ret; |
| 279 | 301 | } |
| 280 | 302 | |
| 303 | +#if IS_ENABLED(CONFIG_OF_DYNAMIC) | |
| 304 | +static int of_weim_notify(struct notifier_block *nb, unsigned long action, | |
| 305 | + void *arg) | |
| 306 | +{ | |
| 307 | + const struct imx_weim_devtype *devtype; | |
| 308 | + struct of_reconfig_data *rd = arg; | |
| 309 | + const struct of_device_id *of_id; | |
| 310 | + struct platform_device *pdev; | |
| 311 | + int ret = NOTIFY_OK; | |
| 312 | + | |
| 313 | + switch (of_reconfig_get_state_change(action, rd)) { | |
| 314 | + case OF_RECONFIG_CHANGE_ADD: | |
| 315 | + of_id = of_match_node(weim_id_table, rd->dn->parent); | |
| 316 | + if (!of_id) | |
| 317 | + return NOTIFY_OK; /* not for us */ | |
| 318 | + | |
| 319 | + devtype = of_id->data; | |
| 320 | + | |
| 321 | + pdev = of_find_device_by_node(rd->dn->parent); | |
| 322 | + if (!pdev) { | |
| 323 | + pr_err("%s: could not find platform device for '%pOF'\n", | |
| 324 | + __func__, rd->dn->parent); | |
| 325 | + | |
| 326 | + return notifier_from_errno(-EINVAL); | |
| 327 | + } | |
| 328 | + | |
| 329 | + if (weim_timing_setup(&pdev->dev, rd->dn, devtype)) | |
| 330 | + dev_warn(&pdev->dev, | |
| 331 | + "Failed to setup timing for '%pOF'\n", rd->dn); | |
| 332 | + | |
| 333 | + if (!of_node_check_flag(rd->dn, OF_POPULATED)) { | |
| 334 | + if (!of_platform_device_create(rd->dn, NULL, &pdev->dev)) { | |
| 335 | + dev_err(&pdev->dev, | |
| 336 | + "Failed to create child device '%pOF'\n", | |
| 337 | + rd->dn); | |
| 338 | + ret = notifier_from_errno(-EINVAL); | |
| 339 | + } | |
| 340 | + } | |
| 341 | + | |
| 342 | + platform_device_put(pdev); | |
| 343 | + | |
| 344 | + break; | |
| 345 | + case OF_RECONFIG_CHANGE_REMOVE: | |
| 346 | + if (!of_node_check_flag(rd->dn, OF_POPULATED)) | |
| 347 | + return NOTIFY_OK; /* device already destroyed */ | |
| 348 | + | |
| 349 | + of_id = of_match_node(weim_id_table, rd->dn->parent); | |
| 350 | + if (!of_id) | |
| 351 | + return NOTIFY_OK; /* not for us */ | |
| 352 | + | |
| 353 | + pdev = of_find_device_by_node(rd->dn); | |
| 354 | + if (!pdev) { | |
| 355 | + dev_err(&pdev->dev, | |
| 356 | + "Could not find platform device for '%pOF'\n", | |
| 357 | + rd->dn); | |
| 358 | + | |
| 359 | + ret = notifier_from_errno(-EINVAL); | |
| 360 | + } else { | |
| 361 | + of_platform_device_destroy(&pdev->dev, NULL); | |
| 362 | + platform_device_put(pdev); | |
| 363 | + } | |
| 364 | + | |
| 365 | + break; | |
| 366 | + default: | |
| 367 | + break; | |
| 368 | + } | |
| 369 | + | |
| 370 | + return ret; | |
| 371 | +} | |
| 372 | + | |
| 373 | +struct notifier_block weim_of_notifier = { | |
| 374 | + .notifier_call = of_weim_notify, | |
| 375 | +}; | |
| 376 | +#endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */ | |
| 377 | + | |
| 281 | 378 | static struct platform_driver weim_driver = { |
| 282 | 379 | .driver = { |
| 283 | 380 | .name = "imx-weim", |
| @@ -285,7 +382,27 @@ static struct platform_driver weim_driver = { · 1 unmodified line | ||
| 285 | 382 | }, |
| 286 | 383 | .probe = weim_probe, |
| 287 | 384 | }; |
| 288 | −module_platform_driver(weim_driver); | |
| 385 | + | |
| 386 | +static int __init weim_init(void) | |
| 387 | +{ | |
| 388 | +#if IS_ENABLED(CONFIG_OF_DYNAMIC) | |
| 389 | + WARN_ON(of_reconfig_notifier_register(&weim_of_notifier)); | |
| 390 | +#endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */ | |
| 391 | + | |
| 392 | + return platform_driver_register(&weim_driver); | |
| 393 | +} | |
| 394 | +module_init(weim_init); | |
| 395 | + | |
| 396 | +static void __exit weim_exit(void) | |
| 397 | +{ | |
| 398 | +#if IS_ENABLED(CONFIG_OF_DYNAMIC) | |
| 399 | + of_reconfig_notifier_unregister(&weim_of_notifier); | |
| 400 | +#endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */ | |
| 401 | + | |
| 402 | + return platform_driver_unregister(&weim_driver); | |
| 403 | + | |
| 404 | +} | |
| 405 | +module_exit(weim_exit); | |
| 289 | 406 | |
| 290 | 407 | MODULE_AUTHOR("Freescale Semiconductor Inc."); |
| 291 | 408 | MODULE_DESCRIPTION("i.MX EIM Controller Driver"); |
| @@ -145,10 +145,10 @@ static int optee_rng_init(struct hwrng *rng) · 144 unmodified lines | ||
| 145 | 145 | struct optee_rng_private *pvt_data = to_optee_rng_private(rng); |
| 146 | 146 | struct tee_shm *entropy_shm_pool = NULL; |
| 147 | 147 | |
| 148 | − entropy_shm_pool = tee_shm_alloc(pvt_data->ctx, MAX_ENTROPY_REQ_SZ, | |
| 149 | − TEE_SHM_MAPPED | TEE_SHM_DMA_BUF); | |
| 148 | + entropy_shm_pool = tee_shm_alloc_kernel_buf(pvt_data->ctx, | |
| 149 | + MAX_ENTROPY_REQ_SZ); | |
| 150 | 150 | if (IS_ERR(entropy_shm_pool)) { |
| 151 | − dev_err(pvt_data->dev, "tee_shm_alloc failed\n"); | |
| 151 | + dev_err(pvt_data->dev, "tee_shm_alloc_kernel_buf failed\n"); | |
| 152 | 152 | return PTR_ERR(entropy_shm_pool); |
| 153 | 153 | } |
| 154 | 154 | |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * System Control and Power Interface (SCMI) Protocol based clock driver |
| 4 | 4 | * |
| 5 | − * Copyright (C) 2018-2021 ARM Ltd. | |
| 5 | + * Copyright (C) 2018-2022 ARM Ltd. | |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #include <linux/clk-provider.h> |
| @@ -88,21 +88,51 @@ static void scmi_clk_disable(struct clk_hw *hw) · 79 unmodified lines | ||
| 88 | 88 | scmi_proto_clk_ops->disable(clk->ph, clk->id); |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | +static int scmi_clk_atomic_enable(struct clk_hw *hw) | |
| 92 | +{ | |
| 93 | + struct scmi_clk *clk = to_scmi_clk(hw); | |
| 94 | + | |
| 95 | + return scmi_proto_clk_ops->enable_atomic(clk->ph, clk->id); | |
| 96 | +} | |
| 97 | + | |
| 98 | +static void scmi_clk_atomic_disable(struct clk_hw *hw) | |
| 99 | +{ | |
| 100 | + struct scmi_clk *clk = to_scmi_clk(hw); | |
| 101 | + | |
| 102 | + scmi_proto_clk_ops->disable_atomic(clk->ph, clk->id); | |
| 103 | +} | |
| 104 | + | |
| 105 | +/* | |
| 106 | + * We can provide enable/disable atomic callbacks only if the underlying SCMI | |
| 107 | + * transport for an SCMI instance is configured to handle SCMI commands in an | |
| 108 | + * atomic manner. | |
| 109 | + * | |
| 110 | + * When no SCMI atomic transport support is available we instead provide only | |
| 111 | + * the prepare/unprepare API, as allowed by the clock framework when atomic | |
| 112 | + * calls are not available. | |
| 113 | + * | |
| 114 | + * Two distinct sets of clk_ops are provided since we could have multiple SCMI | |
| 115 | + * instances with different underlying transport quality, so they cannot be | |
| 116 | + * shared. | |
| 117 | + */ | |
| 91 | 118 | static const struct clk_ops scmi_clk_ops = { |
| 92 | 119 | .recalc_rate = scmi_clk_recalc_rate, |
| 93 | 120 | .round_rate = scmi_clk_round_rate, |
| 94 | 121 | .set_rate = scmi_clk_set_rate, |
| 95 | − /* | |
| 96 | − * We can't provide enable/disable callback as we can't perform the same | |
| 97 | − * in atomic context. Since the clock framework provides standard API | |
| 98 | − * clk_prepare_enable that helps cases using clk_enable in non-atomic | |
| 99 | − * context, it should be fine providing prepare/unprepare. | |
| 100 | − */ | |
| 101 | 122 | .prepare = scmi_clk_enable, |
| 102 | 123 | .unprepare = scmi_clk_disable, |
| 103 | 124 | }; |
| 104 | 125 | |
| 105 | −static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk) | |
| 126 | +static const struct clk_ops scmi_atomic_clk_ops = { | |
| 127 | + .recalc_rate = scmi_clk_recalc_rate, | |
| 128 | + .round_rate = scmi_clk_round_rate, | |
| 129 | + .set_rate = scmi_clk_set_rate, | |
| 130 | + .enable = scmi_clk_atomic_enable, | |
| 131 | + .disable = scmi_clk_atomic_disable, | |
| 132 | +}; | |
| 133 | + | |
| 134 | +static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk, | |
| 135 | + const struct clk_ops *scmi_ops) | |
| 106 | 136 | { |
| 107 | 137 | int ret; |
| 108 | 138 | unsigned long min_rate, max_rate; |
| @@ -110,7 +140,7 @@ static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk) · 1 unmodified line | ||
| 110 | 140 | struct clk_init_data init = { |
| 111 | 141 | .flags = CLK_GET_RATE_NOCACHE, |
| 112 | 142 | .num_parents = 0, |
| 113 | − .ops = &scmi_clk_ops, | |
| 143 | + .ops = scmi_ops, | |
| 114 | 144 | .name = sclk->info->name, |
| 115 | 145 | }; |
| 116 | 146 | |
| @@ -139,6 +169,8 @@ static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk) · 22 unmodified lines | ||
| 139 | 169 | static int scmi_clocks_probe(struct scmi_device *sdev) |
| 140 | 170 | { |
| 141 | 171 | int idx, count, err; |
| 172 | + unsigned int atomic_threshold; | |
| 173 | + bool is_atomic; | |
| 142 | 174 | struct clk_hw **hws; |
| 143 | 175 | struct clk_hw_onecell_data *clk_data; |
| 144 | 176 | struct device *dev = &sdev->dev; |
| @@ -168,8 +200,11 @@ static int scmi_clocks_probe(struct scmi_device *sdev) · 23 unmodified lines | ||
| 168 | 200 | clk_data->num = count; |
| 169 | 201 | hws = clk_data->hws; |
| 170 | 202 | |
| 203 | + is_atomic = handle->is_transport_atomic(handle, &atomic_threshold); | |
| 204 | + | |
| 171 | 205 | for (idx = 0; idx < count; idx++) { |
| 172 | 206 | struct scmi_clk *sclk; |
| 207 | + const struct clk_ops *scmi_ops; | |
| 173 | 208 | |
| 174 | 209 | sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL); |
| 175 | 210 | if (!sclk) |
| @@ -184,13 +219,27 @@ static int scmi_clocks_probe(struct scmi_device *sdev) · 8 unmodified lines | ||
| 184 | 219 | sclk->id = idx; |
| 185 | 220 | sclk->ph = ph; |
| 186 | 221 | |
| 187 | − err = scmi_clk_ops_init(dev, sclk); | |
| 222 | + /* | |
| 223 | + * Note that when transport is atomic but SCMI protocol did not | |
| 224 | + * specify (or support) an enable_latency associated with a | |
| 225 | + * clock, we default to use atomic operations mode. | |
| 226 | + */ | |
| 227 | + if (is_atomic && | |
| 228 | + sclk->info->enable_latency <= atomic_threshold) | |
| 229 | + scmi_ops = &scmi_atomic_clk_ops; | |
| 230 | + else | |
| 231 | + scmi_ops = &scmi_clk_ops; | |
| 232 | + | |
| 233 | + err = scmi_clk_ops_init(dev, sclk, scmi_ops); | |
| 188 | 234 | if (err) { |
| 189 | 235 | dev_err(dev, "failed to register clock %d\n", idx); |
| 190 | 236 | devm_kfree(dev, sclk); |
| 191 | 237 | hws[idx] = NULL; |
| 192 | 238 | } else { |
| 193 | − dev_dbg(dev, "Registered clock:%s\n", sclk->info->name); | |
| 239 | + dev_dbg(dev, "Registered clock:%s%s\n", | |
| 240 | + sclk->info->name, | |
| 241 | + scmi_ops == &scmi_atomic_clk_ops ? | |
| 242 | + " (atomic ops)" : ""); | |
| 194 | 243 | hws[idx] = &sclk->hw; |
| 195 | 244 | } |
| 196 | 245 | } |
| @@ -11,6 +11,7 @@ config COMMON_CLK_SAMSUNG · 10 unmodified lines | ||
| 11 | 11 | select EXYNOS_5410_COMMON_CLK if ARM && SOC_EXYNOS5410 |
| 12 | 12 | select EXYNOS_5420_COMMON_CLK if ARM && SOC_EXYNOS5420 |
| 13 | 13 | select EXYNOS_ARM64_COMMON_CLK if ARM64 && ARCH_EXYNOS |
| 14 | + select TESLA_FSD_COMMON_CLK if ARM64 && ARCH_TESLA_FSD | |
| 14 | 15 | |
| 15 | 16 | config S3C64XX_COMMON_CLK |
| 16 | 17 | bool "Samsung S3C64xx clock controller support" if COMPILE_TEST |
| @@ -124,3 +125,11 @@ config S3C2443_COMMON_CLK · 107 unmodified lines | ||
| 124 | 125 | help |
| 125 | 126 | Support for the clock controller present on the Samsung |
| 126 | 127 | S3C2416/S3C2443 SoCs. Choose Y here only if you build for this SoC. |
| 128 | + | |
| 129 | +config TESLA_FSD_COMMON_CLK | |
| 130 | + bool "Tesla FSD clock controller support" if COMPILE_TEST | |
| 131 | + depends on COMMON_CLK_SAMSUNG | |
| 132 | + depends on EXYNOS_ARM64_COMMON_CLK | |
| 133 | + help | |
| 134 | + Support for the clock controller present on the Tesla FSD SoC. | |
| 135 | + Choose Y here only if you build for this SoC. | |
| @@ -26,3 +26,4 @@ obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o · 25 unmodified lines | ||
| 26 | 26 | obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o |
| 27 | 27 | obj-$(CONFIG_S3C64XX_COMMON_CLK) += clk-s3c64xx.o |
| 28 | 28 | obj-$(CONFIG_S5PV210_COMMON_CLK) += clk-s5pv210.o clk-s5pv210-audss.o |
| 29 | +obj-$(CONFIG_TESLA_FSD_COMMON_CLK) += clk-fsd.o | |
| @@ -0,0 +1,1803 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +/* | |
| 3 | + * Copyright (c) 2017-2022 Samsung Electronics Co., Ltd. | |
| 4 | + * https://www.samsung.com | |
| 5 | + * Copyright (c) 2017-2022 Tesla, Inc. | |
| 6 | + * https://www.tesla.com | |
| 7 | + * | |
| 8 | + * Common Clock Framework support for FSD SoC. | |
| 9 | + */ | |
| 10 | + | |
| 11 | +#include <linux/clk.h> | |
| 12 | +#include <linux/clk-provider.h> | |
| 13 | +#include <linux/init.h> | |
| 14 | +#include <linux/kernel.h> | |
| 15 | +#include <linux/of.h> | |
| 16 | +#include <linux/of_address.h> | |
| 17 | +#include <linux/of_device.h> | |
| 18 | +#include <linux/platform_device.h> | |
| 19 | + | |
| 20 | +#include <dt-bindings/clock/fsd-clk.h> | |
| 21 | + | |
| 22 | +#include "clk.h" | |
| 23 | +#include "clk-exynos-arm64.h" | |
| 24 | + | |
| 25 | +/* Register Offset definitions for CMU_CMU (0x11c10000) */ | |
| 26 | +#define PLL_LOCKTIME_PLL_SHARED0 0x0 | |
| 27 | +#define PLL_LOCKTIME_PLL_SHARED1 0x4 | |
| 28 | +#define PLL_LOCKTIME_PLL_SHARED2 0x8 | |
| 29 | +#define PLL_LOCKTIME_PLL_SHARED3 0xc | |
| 30 | +#define PLL_CON0_PLL_SHARED0 0x100 | |
| 31 | +#define PLL_CON0_PLL_SHARED1 0x120 | |
| 32 | +#define PLL_CON0_PLL_SHARED2 0x140 | |
| 33 | +#define PLL_CON0_PLL_SHARED3 0x160 | |
| 34 | +#define MUX_CMU_CIS0_CLKMUX 0x1000 | |
| 35 | +#define MUX_CMU_CIS1_CLKMUX 0x1004 | |
| 36 | +#define MUX_CMU_CIS2_CLKMUX 0x1008 | |
| 37 | +#define MUX_CMU_CPUCL_SWITCHMUX 0x100c | |
| 38 | +#define MUX_CMU_FSYS1_ACLK_MUX 0x1014 | |
| 39 | +#define MUX_PLL_SHARED0_MUX 0x1020 | |
| 40 | +#define MUX_PLL_SHARED1_MUX 0x1024 | |
| 41 | +#define DIV_CMU_CIS0_CLK 0x1800 | |
| 42 | +#define DIV_CMU_CIS1_CLK 0x1804 | |
| 43 | +#define DIV_CMU_CIS2_CLK 0x1808 | |
| 44 | +#define DIV_CMU_CMU_ACLK 0x180c | |
| 45 | +#define DIV_CMU_CPUCL_SWITCH 0x1810 | |
| 46 | +#define DIV_CMU_FSYS0_SHARED0DIV4 0x181c | |
| 47 | +#define DIV_CMU_FSYS0_SHARED1DIV3 0x1820 | |
| 48 | +#define DIV_CMU_FSYS0_SHARED1DIV4 0x1824 | |
| 49 | +#define DIV_CMU_FSYS1_SHARED0DIV4 0x1828 | |
| 50 | +#define DIV_CMU_FSYS1_SHARED0DIV8 0x182c | |
| 51 | +#define DIV_CMU_IMEM_ACLK 0x1834 | |
| 52 | +#define DIV_CMU_IMEM_DMACLK 0x1838 | |
| 53 | +#define DIV_CMU_IMEM_TCUCLK 0x183c | |
| 54 | +#define DIV_CMU_PERIC_SHARED0DIV20 0x1844 | |
| 55 | +#define DIV_CMU_PERIC_SHARED0DIV3_TBUCLK 0x1848 | |
| 56 | +#define DIV_CMU_PERIC_SHARED1DIV36 0x184c | |
| 57 | +#define DIV_CMU_PERIC_SHARED1DIV4_DMACLK 0x1850 | |
| 58 | +#define DIV_PLL_SHARED0_DIV2 0x1858 | |
| 59 | +#define DIV_PLL_SHARED0_DIV3 0x185c | |
| 60 | +#define DIV_PLL_SHARED0_DIV4 0x1860 | |
| 61 | +#define DIV_PLL_SHARED0_DIV6 0x1864 | |
| 62 | +#define DIV_PLL_SHARED1_DIV3 0x1868 | |
| 63 | +#define DIV_PLL_SHARED1_DIV36 0x186c | |
| 64 | +#define DIV_PLL_SHARED1_DIV4 0x1870 | |
| 65 | +#define DIV_PLL_SHARED1_DIV9 0x1874 | |
| 66 | +#define GAT_CMU_CIS0_CLKGATE 0x2000 | |
| 67 | +#define GAT_CMU_CIS1_CLKGATE 0x2004 | |
| 68 | +#define GAT_CMU_CIS2_CLKGATE 0x2008 | |
| 69 | +#define GAT_CMU_CPUCL_SWITCH_GATE 0x200c | |
| 70 | +#define GAT_CMU_FSYS0_SHARED0DIV4_GATE 0x2018 | |
| 71 | +#define GAT_CMU_FSYS0_SHARED1DIV4_CLK 0x201c | |
| 72 | +#define GAT_CMU_FSYS0_SHARED1DIV4_GATE 0x2020 | |
| 73 | +#define GAT_CMU_FSYS1_SHARED0DIV4_GATE 0x2024 | |
| 74 | +#define GAT_CMU_FSYS1_SHARED1DIV4_GATE 0x2028 | |
| 75 | +#define GAT_CMU_IMEM_ACLK_GATE 0x2030 | |
| 76 | +#define GAT_CMU_IMEM_DMACLK_GATE 0x2034 | |
| 77 | +#define GAT_CMU_IMEM_TCUCLK_GATE 0x2038 | |
| 78 | +#define GAT_CMU_PERIC_SHARED0DIVE3_TBUCLK_GATE 0x2040 | |
| 79 | +#define GAT_CMU_PERIC_SHARED0DIVE4_GATE 0x2044 | |
| 80 | +#define GAT_CMU_PERIC_SHARED1DIV4_DMACLK_GATE 0x2048 | |
| 81 | +#define GAT_CMU_PERIC_SHARED1DIVE4_GATE 0x204c | |
| 82 | +#define GAT_CMU_CMU_CMU_IPCLKPORT_PCLK 0x2054 | |
| 83 | +#define GAT_CMU_AXI2APB_CMU_IPCLKPORT_ACLK 0x2058 | |
| 84 | +#define GAT_CMU_NS_BRDG_CMU_IPCLKPORT_CLK__PSOC_CMU__CLK_CMU 0x205c | |
| 85 | +#define GAT_CMU_SYSREG_CMU_IPCLKPORT_PCLK 0x2060 | |
| 86 | + | |
| 87 | +static const unsigned long cmu_clk_regs[] __initconst = { | |
| 88 | + PLL_LOCKTIME_PLL_SHARED0, | |
| 89 | + PLL_LOCKTIME_PLL_SHARED1, | |
| 90 | + PLL_LOCKTIME_PLL_SHARED2, | |
| 91 | + PLL_LOCKTIME_PLL_SHARED3, | |
| 92 | + PLL_CON0_PLL_SHARED0, | |
| 93 | + PLL_CON0_PLL_SHARED1, | |
| 94 | + PLL_CON0_PLL_SHARED2, | |
| 95 | + PLL_CON0_PLL_SHARED3, | |
| 96 | + MUX_CMU_CIS0_CLKMUX, | |
| 97 | + MUX_CMU_CIS1_CLKMUX, | |
| 98 | + MUX_CMU_CIS2_CLKMUX, | |
| 99 | + MUX_CMU_CPUCL_SWITCHMUX, | |
| 100 | + MUX_CMU_FSYS1_ACLK_MUX, | |
| 101 | + MUX_PLL_SHARED0_MUX, | |
| 102 | + MUX_PLL_SHARED1_MUX, | |
| 103 | + DIV_CMU_CIS0_CLK, | |
| 104 | + DIV_CMU_CIS1_CLK, | |
| 105 | + DIV_CMU_CIS2_CLK, | |
| 106 | + DIV_CMU_CMU_ACLK, | |
| 107 | + DIV_CMU_CPUCL_SWITCH, | |
| 108 | + DIV_CMU_FSYS0_SHARED0DIV4, | |
| 109 | + DIV_CMU_FSYS0_SHARED1DIV3, | |
| 110 | + DIV_CMU_FSYS0_SHARED1DIV4, | |
| 111 | + DIV_CMU_FSYS1_SHARED0DIV4, | |
| 112 | + DIV_CMU_FSYS1_SHARED0DIV8, | |
| 113 | + DIV_CMU_IMEM_ACLK, | |
| 114 | + DIV_CMU_IMEM_DMACLK, | |
| 115 | + DIV_CMU_IMEM_TCUCLK, | |
| 116 | + DIV_CMU_PERIC_SHARED0DIV20, | |
| 117 | + DIV_CMU_PERIC_SHARED0DIV3_TBUCLK, | |
| 118 | + DIV_CMU_PERIC_SHARED1DIV36, | |
| 119 | + DIV_CMU_PERIC_SHARED1DIV4_DMACLK, | |
| 120 | + DIV_PLL_SHARED0_DIV2, | |
| 121 | + DIV_PLL_SHARED0_DIV3, | |
| 122 | + DIV_PLL_SHARED0_DIV4, | |
| 123 | + DIV_PLL_SHARED0_DIV6, | |
| 124 | + DIV_PLL_SHARED1_DIV3, | |
| 125 | + DIV_PLL_SHARED1_DIV36, | |
| 126 | + DIV_PLL_SHARED1_DIV4, | |
| 127 | + DIV_PLL_SHARED1_DIV9, | |
| 128 | + GAT_CMU_CIS0_CLKGATE, | |
| 129 | + GAT_CMU_CIS1_CLKGATE, | |
| 130 | + GAT_CMU_CIS2_CLKGATE, | |
| 131 | + GAT_CMU_CPUCL_SWITCH_GATE, | |
| 132 | + GAT_CMU_FSYS0_SHARED0DIV4_GATE, | |
| 133 | + GAT_CMU_FSYS0_SHARED1DIV4_CLK, | |
| 134 | + GAT_CMU_FSYS0_SHARED1DIV4_GATE, | |
| 135 | + GAT_CMU_FSYS1_SHARED0DIV4_GATE, | |
| 136 | + GAT_CMU_FSYS1_SHARED1DIV4_GATE, | |
| 137 | + GAT_CMU_IMEM_ACLK_GATE, | |
| 138 | + GAT_CMU_IMEM_DMACLK_GATE, | |
| 139 | + GAT_CMU_IMEM_TCUCLK_GATE, | |
| 140 | + GAT_CMU_PERIC_SHARED0DIVE3_TBUCLK_GATE, | |
| 141 | + GAT_CMU_PERIC_SHARED0DIVE4_GATE, | |
| 142 | + GAT_CMU_PERIC_SHARED1DIV4_DMACLK_GATE, | |
| 143 | + GAT_CMU_PERIC_SHARED1DIVE4_GATE, | |
| 144 | + GAT_CMU_CMU_CMU_IPCLKPORT_PCLK, | |
| 145 | + GAT_CMU_AXI2APB_CMU_IPCLKPORT_ACLK, | |
| 146 | + GAT_CMU_NS_BRDG_CMU_IPCLKPORT_CLK__PSOC_CMU__CLK_CMU, | |
| 147 | + GAT_CMU_SYSREG_CMU_IPCLKPORT_PCLK, | |
| 148 | +}; | |
| 149 | + | |
| 150 | +static const struct samsung_pll_rate_table pll_shared0_rate_table[] __initconst = { | |
| 151 | + PLL_35XX_RATE(24 * MHZ, 2000000000U, 250, 3, 0), | |
| 152 | +}; | |
| 153 | + | |
| 154 | +static const struct samsung_pll_rate_table pll_shared1_rate_table[] __initconst = { | |
| 155 | + PLL_35XX_RATE(24 * MHZ, 2400000000U, 200, 2, 0), | |
| 156 | +}; | |
| 157 | + | |
| 158 | +static const struct samsung_pll_rate_table pll_shared2_rate_table[] __initconst = { | |
| 159 | + PLL_35XX_RATE(24 * MHZ, 2400000000U, 200, 2, 0), | |
| 160 | +}; | |
| 161 | + | |
| 162 | +static const struct samsung_pll_rate_table pll_shared3_rate_table[] __initconst = { | |
| 163 | + PLL_35XX_RATE(24 * MHZ, 1800000000U, 150, 2, 0), | |
| 164 | +}; | |
| 165 | + | |
| 166 | +static const struct samsung_pll_clock cmu_pll_clks[] __initconst = { | |
| 167 | + PLL(pll_142xx, 0, "fout_pll_shared0", "fin_pll", PLL_LOCKTIME_PLL_SHARED0, | |
| 168 | + PLL_CON0_PLL_SHARED0, pll_shared0_rate_table), | |
| 169 | + PLL(pll_142xx, 0, "fout_pll_shared1", "fin_pll", PLL_LOCKTIME_PLL_SHARED1, | |
| 170 | + PLL_CON0_PLL_SHARED1, pll_shared1_rate_table), | |
| 171 | + PLL(pll_142xx, 0, "fout_pll_shared2", "fin_pll", PLL_LOCKTIME_PLL_SHARED2, | |
| 172 | + PLL_CON0_PLL_SHARED2, pll_shared2_rate_table), | |
| 173 | + PLL(pll_142xx, 0, "fout_pll_shared3", "fin_pll", PLL_LOCKTIME_PLL_SHARED3, | |
| 174 | + PLL_CON0_PLL_SHARED3, pll_shared3_rate_table), | |
| 175 | +}; | |
| 176 | + | |
| 177 | +/* List of parent clocks for Muxes in CMU_CMU */ | |
| 178 | +PNAME(mout_cmu_shared0_pll_p) = { "fin_pll", "fout_pll_shared0" }; | |
| 179 | +PNAME(mout_cmu_shared1_pll_p) = { "fin_pll", "fout_pll_shared1" }; | |
| 180 | +PNAME(mout_cmu_shared2_pll_p) = { "fin_pll", "fout_pll_shared2" }; | |
| 181 | +PNAME(mout_cmu_shared3_pll_p) = { "fin_pll", "fout_pll_shared3" }; | |
| 182 | +PNAME(mout_cmu_cis0_clkmux_p) = { "fin_pll", "dout_cmu_pll_shared0_div4" }; | |
| 183 | +PNAME(mout_cmu_cis1_clkmux_p) = { "fin_pll", "dout_cmu_pll_shared0_div4" }; | |
| 184 | +PNAME(mout_cmu_cis2_clkmux_p) = { "fin_pll", "dout_cmu_pll_shared0_div4" }; | |
| 185 | +PNAME(mout_cmu_cpucl_switchmux_p) = { "mout_cmu_pll_shared2", "mout_cmu_pll_shared0_mux" }; | |
| 186 | +PNAME(mout_cmu_fsys1_aclk_mux_p) = { "dout_cmu_pll_shared0_div4", "fin_pll" }; | |
| 187 | +PNAME(mout_cmu_pll_shared0_mux_p) = { "fin_pll", "mout_cmu_pll_shared0" }; | |
| 188 | +PNAME(mout_cmu_pll_shared1_mux_p) = { "fin_pll", "mout_cmu_pll_shared1" }; | |
| 189 | + | |
| 190 | +static const struct samsung_mux_clock cmu_mux_clks[] __initconst = { | |
| 191 | + MUX(0, "mout_cmu_pll_shared0", mout_cmu_shared0_pll_p, PLL_CON0_PLL_SHARED0, 4, 1), | |
| 192 | + MUX(0, "mout_cmu_pll_shared1", mout_cmu_shared1_pll_p, PLL_CON0_PLL_SHARED1, 4, 1), | |
| 193 | + MUX(0, "mout_cmu_pll_shared2", mout_cmu_shared2_pll_p, PLL_CON0_PLL_SHARED2, 4, 1), | |
| 194 | + MUX(0, "mout_cmu_pll_shared3", mout_cmu_shared3_pll_p, PLL_CON0_PLL_SHARED3, 4, 1), | |
| 195 | + MUX(0, "mout_cmu_cis0_clkmux", mout_cmu_cis0_clkmux_p, MUX_CMU_CIS0_CLKMUX, 0, 1), | |
| 196 | + MUX(0, "mout_cmu_cis1_clkmux", mout_cmu_cis1_clkmux_p, MUX_CMU_CIS1_CLKMUX, 0, 1), | |
| 197 | + MUX(0, "mout_cmu_cis2_clkmux", mout_cmu_cis2_clkmux_p, MUX_CMU_CIS2_CLKMUX, 0, 1), | |
| 198 | + MUX(0, "mout_cmu_cpucl_switchmux", mout_cmu_cpucl_switchmux_p, | |
| 199 | + MUX_CMU_CPUCL_SWITCHMUX, 0, 1), | |
| 200 | + MUX(0, "mout_cmu_fsys1_aclk_mux", mout_cmu_fsys1_aclk_mux_p, MUX_CMU_FSYS1_ACLK_MUX, 0, 1), | |
| 201 | + MUX(0, "mout_cmu_pll_shared0_mux", mout_cmu_pll_shared0_mux_p, MUX_PLL_SHARED0_MUX, 0, 1), | |
| 202 | + MUX(0, "mout_cmu_pll_shared1_mux", mout_cmu_pll_shared1_mux_p, MUX_PLL_SHARED1_MUX, 0, 1), | |
| 203 | +}; | |
| 204 | + | |
| 205 | +static const struct samsung_div_clock cmu_div_clks[] __initconst = { | |
| 206 | + DIV(0, "dout_cmu_cis0_clk", "cmu_cis0_clkgate", DIV_CMU_CIS0_CLK, 0, 4), | |
| 207 | + DIV(0, "dout_cmu_cis1_clk", "cmu_cis1_clkgate", DIV_CMU_CIS1_CLK, 0, 4), | |
| 208 | + DIV(0, "dout_cmu_cis2_clk", "cmu_cis2_clkgate", DIV_CMU_CIS2_CLK, 0, 4), | |
| 209 | + DIV(0, "dout_cmu_cmu_aclk", "dout_cmu_pll_shared1_div9", DIV_CMU_CMU_ACLK, 0, 4), | |
| 210 | + DIV(0, "dout_cmu_cpucl_switch", "cmu_cpucl_switch_gate", DIV_CMU_CPUCL_SWITCH, 0, 4), | |
| 211 | + DIV(DOUT_CMU_FSYS0_SHARED0DIV4, "dout_cmu_fsys0_shared0div4", "cmu_fsys0_shared0div4_gate", | |
| 212 | + DIV_CMU_FSYS0_SHARED0DIV4, 0, 4), | |
| 213 | + DIV(0, "dout_cmu_fsys0_shared1div3", "cmu_fsys0_shared1div4_clk", | |
| 214 | + DIV_CMU_FSYS0_SHARED1DIV3, 0, 4), | |
| 215 | + DIV(DOUT_CMU_FSYS0_SHARED1DIV4, "dout_cmu_fsys0_shared1div4", "cmu_fsys0_shared1div4_gate", | |
| 216 | + DIV_CMU_FSYS0_SHARED1DIV4, 0, 4), | |
| 217 | + DIV(DOUT_CMU_FSYS1_SHARED0DIV4, "dout_cmu_fsys1_shared0div4", "cmu_fsys1_shared0div4_gate", | |
| 218 | + DIV_CMU_FSYS1_SHARED0DIV4, 0, 4), | |
| 219 | + DIV(DOUT_CMU_FSYS1_SHARED0DIV8, "dout_cmu_fsys1_shared0div8", "cmu_fsys1_shared1div4_gate", | |
| 220 | + DIV_CMU_FSYS1_SHARED0DIV8, 0, 4), | |
| 221 | + DIV(DOUT_CMU_IMEM_ACLK, "dout_cmu_imem_aclk", "cmu_imem_aclk_gate", | |
| 222 | + DIV_CMU_IMEM_ACLK, 0, 4), | |
| 223 | + DIV(DOUT_CMU_IMEM_DMACLK, "dout_cmu_imem_dmaclk", "cmu_imem_dmaclk_gate", | |
| 224 | + DIV_CMU_IMEM_DMACLK, 0, 4), | |
| 225 | + DIV(DOUT_CMU_IMEM_TCUCLK, "dout_cmu_imem_tcuclk", "cmu_imem_tcuclk_gate", | |
| 226 | + DIV_CMU_IMEM_TCUCLK, 0, 4), | |
| 227 | + DIV(DOUT_CMU_PERIC_SHARED0DIV20, "dout_cmu_peric_shared0div20", | |
| 228 | + "cmu_peric_shared0dive4_gate", DIV_CMU_PERIC_SHARED0DIV20, 0, 4), | |
| 229 | + DIV(DOUT_CMU_PERIC_SHARED0DIV3_TBUCLK, "dout_cmu_peric_shared0div3_tbuclk", | |
| 230 | + "cmu_peric_shared0dive3_tbuclk_gate", DIV_CMU_PERIC_SHARED0DIV3_TBUCLK, 0, 4), | |
| 231 | + DIV(DOUT_CMU_PERIC_SHARED1DIV36, "dout_cmu_peric_shared1div36", | |
| 232 | + "cmu_peric_shared1dive4_gate", DIV_CMU_PERIC_SHARED1DIV36, 0, 4), | |
| 233 | + DIV(DOUT_CMU_PERIC_SHARED1DIV4_DMACLK, "dout_cmu_peric_shared1div4_dmaclk", | |
| 234 | + "cmu_peric_shared1div4_dmaclk_gate", DIV_CMU_PERIC_SHARED1DIV4_DMACLK, 0, 4), | |
| 235 | + DIV(0, "dout_cmu_pll_shared0_div2", "mout_cmu_pll_shared0_mux", | |
| 236 | + DIV_PLL_SHARED0_DIV2, 0, 4), | |
| 237 | + DIV(0, "dout_cmu_pll_shared0_div3", "mout_cmu_pll_shared0_mux", | |
| 238 | + DIV_PLL_SHARED0_DIV3, 0, 4), | |
| 239 | + DIV(DOUT_CMU_PLL_SHARED0_DIV4, "dout_cmu_pll_shared0_div4", "dout_cmu_pll_shared0_div2", | |
| 240 | + DIV_PLL_SHARED0_DIV4, 0, 4), | |
| 241 | + DIV(DOUT_CMU_PLL_SHARED0_DIV6, "dout_cmu_pll_shared0_div6", "dout_cmu_pll_shared0_div3", | |
| 242 | + DIV_PLL_SHARED0_DIV6, 0, 4), | |
| 243 | + DIV(0, "dout_cmu_pll_shared1_div3", "mout_cmu_pll_shared1_mux", | |
| 244 | + DIV_PLL_SHARED1_DIV3, 0, 4), | |
| 245 | + DIV(0, "dout_cmu_pll_shared1_div36", "dout_cmu_pll_shared1_div9", | |
| 246 | + DIV_PLL_SHARED1_DIV36, 0, 4), | |
| 247 | + DIV(0, "dout_cmu_pll_shared1_div4", "mout_cmu_pll_shared1_mux", | |
| 248 | + DIV_PLL_SHARED1_DIV4, 0, 4), | |
| 249 | + DIV(0, "dout_cmu_pll_shared1_div9", "dout_cmu_pll_shared1_div3", | |
| 250 | + DIV_PLL_SHARED1_DIV9, 0, 4), | |
| 251 | +}; | |
| 252 | + | |
| 253 | +static const struct samsung_gate_clock cmu_gate_clks[] __initconst = { | |
| 254 | + GATE(0, "cmu_cis0_clkgate", "mout_cmu_cis0_clkmux", GAT_CMU_CIS0_CLKGATE, 21, | |
| 255 | + CLK_IGNORE_UNUSED, 0), | |
| 256 | + GATE(0, "cmu_cis1_clkgate", "mout_cmu_cis1_clkmux", GAT_CMU_CIS1_CLKGATE, 21, | |
| 257 | + CLK_IGNORE_UNUSED, 0), | |
| 258 | + GATE(0, "cmu_cis2_clkgate", "mout_cmu_cis2_clkmux", GAT_CMU_CIS2_CLKGATE, 21, | |
| 259 | + CLK_IGNORE_UNUSED, 0), | |
| 260 | + GATE(CMU_CPUCL_SWITCH_GATE, "cmu_cpucl_switch_gate", "mout_cmu_cpucl_switchmux", | |
| 261 | + GAT_CMU_CPUCL_SWITCH_GATE, 21, CLK_IGNORE_UNUSED, 0), | |
| 262 | + GATE(GAT_CMU_FSYS0_SHARED0DIV4, "cmu_fsys0_shared0div4_gate", "dout_cmu_pll_shared0_div4", | |
| 263 | + GAT_CMU_FSYS0_SHARED0DIV4_GATE, 21, CLK_IGNORE_UNUSED, 0), | |
| 264 | + GATE(0, "cmu_fsys0_shared1div4_clk", "dout_cmu_pll_shared1_div3", | |
| 265 | + GAT_CMU_FSYS0_SHARED1DIV4_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 266 | + GATE(0, "cmu_fsys0_shared1div4_gate", "dout_cmu_pll_shared1_div4", | |
| 267 | + GAT_CMU_FSYS0_SHARED1DIV4_GATE, 21, CLK_IGNORE_UNUSED, 0), | |
| 268 | + GATE(0, "cmu_fsys1_shared0div4_gate", "mout_cmu_fsys1_aclk_mux", | |
| 269 | + GAT_CMU_FSYS1_SHARED0DIV4_GATE, 21, CLK_IGNORE_UNUSED, 0), | |
| 270 | + GATE(0, "cmu_fsys1_shared1div4_gate", "dout_cmu_fsys1_shared0div4", | |
| 271 | + GAT_CMU_FSYS1_SHARED1DIV4_GATE, 21, CLK_IGNORE_UNUSED, 0), | |
| 272 | + GATE(0, "cmu_imem_aclk_gate", "dout_cmu_pll_shared1_div9", GAT_CMU_IMEM_ACLK_GATE, 21, | |
| 273 | + CLK_IGNORE_UNUSED, 0), | |
| 274 | + GATE(0, "cmu_imem_dmaclk_gate", "mout_cmu_pll_shared1_mux", GAT_CMU_IMEM_DMACLK_GATE, 21, | |
| 275 | + CLK_IGNORE_UNUSED, 0), | |
| 276 | + GATE(0, "cmu_imem_tcuclk_gate", "dout_cmu_pll_shared0_div3", GAT_CMU_IMEM_TCUCLK_GATE, 21, | |
| 277 | + CLK_IGNORE_UNUSED, 0), | |
| 278 | + GATE(0, "cmu_peric_shared0dive3_tbuclk_gate", "dout_cmu_pll_shared0_div3", | |
| 279 | + GAT_CMU_PERIC_SHARED0DIVE3_TBUCLK_GATE, 21, CLK_IGNORE_UNUSED, 0), | |
| 280 | + GATE(0, "cmu_peric_shared0dive4_gate", "dout_cmu_pll_shared0_div4", | |
| 281 | + GAT_CMU_PERIC_SHARED0DIVE4_GATE, 21, CLK_IGNORE_UNUSED, 0), | |
| 282 | + GATE(0, "cmu_peric_shared1div4_dmaclk_gate", "dout_cmu_pll_shared1_div4", | |
| 283 | + GAT_CMU_PERIC_SHARED1DIV4_DMACLK_GATE, 21, CLK_IGNORE_UNUSED, 0), | |
| 284 | + GATE(0, "cmu_peric_shared1dive4_gate", "dout_cmu_pll_shared1_div36", | |
| 285 | + GAT_CMU_PERIC_SHARED1DIVE4_GATE, 21, CLK_IGNORE_UNUSED, 0), | |
| 286 | + GATE(0, "cmu_uid_cmu_cmu_cmu_ipclkport_pclk", "dout_cmu_cmu_aclk", | |
| 287 | + GAT_CMU_CMU_CMU_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 288 | + GATE(0, "cmu_uid_axi2apb_cmu_ipclkport_aclk", "dout_cmu_cmu_aclk", | |
| 289 | + GAT_CMU_AXI2APB_CMU_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 290 | + GATE(0, "cmu_uid_ns_brdg_cmu_ipclkport_clk__psoc_cmu__clk_cmu", "dout_cmu_cmu_aclk", | |
| 291 | + GAT_CMU_NS_BRDG_CMU_IPCLKPORT_CLK__PSOC_CMU__CLK_CMU, 21, CLK_IGNORE_UNUSED, 0), | |
| 292 | + GATE(0, "cmu_uid_sysreg_cmu_ipclkport_pclk", "dout_cmu_cmu_aclk", | |
| 293 | + GAT_CMU_SYSREG_CMU_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 294 | +}; | |
| 295 | + | |
| 296 | +static const struct samsung_cmu_info cmu_cmu_info __initconst = { | |
| 297 | + .pll_clks = cmu_pll_clks, | |
| 298 | + .nr_pll_clks = ARRAY_SIZE(cmu_pll_clks), | |
| 299 | + .mux_clks = cmu_mux_clks, | |
| 300 | + .nr_mux_clks = ARRAY_SIZE(cmu_mux_clks), | |
| 301 | + .div_clks = cmu_div_clks, | |
| 302 | + .nr_div_clks = ARRAY_SIZE(cmu_div_clks), | |
| 303 | + .gate_clks = cmu_gate_clks, | |
| 304 | + .nr_gate_clks = ARRAY_SIZE(cmu_gate_clks), | |
| 305 | + .nr_clk_ids = CMU_NR_CLK, | |
| 306 | + .clk_regs = cmu_clk_regs, | |
| 307 | + .nr_clk_regs = ARRAY_SIZE(cmu_clk_regs), | |
| 308 | +}; | |
| 309 | + | |
| 310 | +static void __init fsd_clk_cmu_init(struct device_node *np) | |
| 311 | +{ | |
| 312 | + samsung_cmu_register_one(np, &cmu_cmu_info); | |
| 313 | +} | |
| 314 | + | |
| 315 | +CLK_OF_DECLARE(fsd_clk_cmu, "tesla,fsd-clock-cmu", fsd_clk_cmu_init); | |
| 316 | + | |
| 317 | +/* Register Offset definitions for CMU_PERIC (0x14010000) */ | |
| 318 | +#define PLL_CON0_PERIC_DMACLK_MUX 0x100 | |
| 319 | +#define PLL_CON0_PERIC_EQOS_BUSCLK_MUX 0x120 | |
| 320 | +#define PLL_CON0_PERIC_PCLK_MUX 0x140 | |
| 321 | +#define PLL_CON0_PERIC_TBUCLK_MUX 0x160 | |
| 322 | +#define PLL_CON0_SPI_CLK 0x180 | |
| 323 | +#define PLL_CON0_SPI_PCLK 0x1a0 | |
| 324 | +#define PLL_CON0_UART_CLK 0x1c0 | |
| 325 | +#define PLL_CON0_UART_PCLK 0x1e0 | |
| 326 | +#define MUX_PERIC_EQOS_PHYRXCLK 0x1000 | |
| 327 | +#define DIV_EQOS_BUSCLK 0x1800 | |
| 328 | +#define DIV_PERIC_MCAN_CLK 0x1804 | |
| 329 | +#define DIV_RGMII_CLK 0x1808 | |
| 330 | +#define DIV_RII_CLK 0x180c | |
| 331 | +#define DIV_RMII_CLK 0x1810 | |
| 332 | +#define DIV_SPI_CLK 0x1814 | |
| 333 | +#define DIV_UART_CLK 0x1818 | |
| 334 | +#define GAT_EQOS_TOP_IPCLKPORT_CLK_PTP_REF_I 0x2000 | |
| 335 | +#define GAT_GPIO_PERIC_IPCLKPORT_OSCCLK 0x2004 | |
| 336 | +#define GAT_PERIC_ADC0_IPCLKPORT_I_OSCCLK 0x2008 | |
| 337 | +#define GAT_PERIC_CMU_PERIC_IPCLKPORT_PCLK 0x200c | |
| 338 | +#define GAT_PERIC_PWM0_IPCLKPORT_I_OSCCLK 0x2010 | |
| 339 | +#define GAT_PERIC_PWM1_IPCLKPORT_I_OSCCLK 0x2014 | |
| 340 | +#define GAT_ASYNC_APB_DMA0_IPCLKPORT_PCLKM 0x2018 | |
| 341 | +#define GAT_ASYNC_APB_DMA0_IPCLKPORT_PCLKS 0x201c | |
| 342 | +#define GAT_ASYNC_APB_DMA1_IPCLKPORT_PCLKM 0x2020 | |
| 343 | +#define GAT_ASYNC_APB_DMA1_IPCLKPORT_PCLKS 0x2024 | |
| 344 | +#define GAT_AXI2APB_PERIC0_IPCLKPORT_ACLK 0x2028 | |
| 345 | +#define GAT_AXI2APB_PERIC1_IPCLKPORT_ACLK 0x202c | |
| 346 | +#define GAT_AXI2APB_PERIC2_IPCLKPORT_ACLK 0x2030 | |
| 347 | +#define GAT_BUS_D_PERIC_IPCLKPORT_DMACLK 0x2034 | |
| 348 | +#define GAT_BUS_D_PERIC_IPCLKPORT_EQOSCLK 0x2038 | |
| 349 | +#define GAT_BUS_D_PERIC_IPCLKPORT_MAINCLK 0x203c | |
| 350 | +#define GAT_BUS_P_PERIC_IPCLKPORT_EQOSCLK 0x2040 | |
| 351 | +#define GAT_BUS_P_PERIC_IPCLKPORT_MAINCLK 0x2044 | |
| 352 | +#define GAT_BUS_P_PERIC_IPCLKPORT_SMMUCLK 0x2048 | |
| 353 | +#define GAT_EQOS_TOP_IPCLKPORT_ACLK_I 0x204c | |
| 354 | +#define GAT_EQOS_TOP_IPCLKPORT_CLK_RX_I 0x2050 | |
| 355 | +#define GAT_EQOS_TOP_IPCLKPORT_HCLK_I 0x2054 | |
| 356 | +#define GAT_EQOS_TOP_IPCLKPORT_RGMII_CLK_I 0x2058 | |
| 357 | +#define GAT_EQOS_TOP_IPCLKPORT_RII_CLK_I 0x205c | |
| 358 | +#define GAT_EQOS_TOP_IPCLKPORT_RMII_CLK_I 0x2060 | |
| 359 | +#define GAT_GPIO_PERIC_IPCLKPORT_PCLK 0x2064 | |
| 360 | +#define GAT_NS_BRDG_PERIC_IPCLKPORT_CLK__PSOC_PERIC__CLK_PERIC_D 0x2068 | |
| 361 | +#define GAT_NS_BRDG_PERIC_IPCLKPORT_CLK__PSOC_PERIC__CLK_PERIC_P 0x206c | |
| 362 | +#define GAT_PERIC_ADC0_IPCLKPORT_PCLK_S0 0x2070 | |
| 363 | +#define GAT_PERIC_DMA0_IPCLKPORT_ACLK 0x2074 | |
| 364 | +#define GAT_PERIC_DMA1_IPCLKPORT_ACLK 0x2078 | |
| 365 | +#define GAT_PERIC_I2C0_IPCLKPORT_I_PCLK 0x207c | |
| 366 | +#define GAT_PERIC_I2C1_IPCLKPORT_I_PCLK 0x2080 | |
| 367 | +#define GAT_PERIC_I2C2_IPCLKPORT_I_PCLK 0x2084 | |
| 368 | +#define GAT_PERIC_I2C3_IPCLKPORT_I_PCLK 0x2088 | |
| 369 | +#define GAT_PERIC_I2C4_IPCLKPORT_I_PCLK 0x208c | |
| 370 | +#define GAT_PERIC_I2C5_IPCLKPORT_I_PCLK 0x2090 | |
| 371 | +#define GAT_PERIC_I2C6_IPCLKPORT_I_PCLK 0x2094 | |
| 372 | +#define GAT_PERIC_I2C7_IPCLKPORT_I_PCLK 0x2098 | |
| 373 | +#define GAT_PERIC_MCAN0_IPCLKPORT_CCLK 0x209c | |
| 374 | +#define GAT_PERIC_MCAN0_IPCLKPORT_PCLK 0x20a0 | |
| 375 | +#define GAT_PERIC_MCAN1_IPCLKPORT_CCLK 0x20a4 | |
| 376 | +#define GAT_PERIC_MCAN1_IPCLKPORT_PCLK 0x20a8 | |
| 377 | +#define GAT_PERIC_MCAN2_IPCLKPORT_CCLK 0x20ac | |
| 378 | +#define GAT_PERIC_MCAN2_IPCLKPORT_PCLK 0x20b0 | |
| 379 | +#define GAT_PERIC_MCAN3_IPCLKPORT_CCLK 0x20b4 | |
| 380 | +#define GAT_PERIC_MCAN3_IPCLKPORT_PCLK 0x20b8 | |
| 381 | +#define GAT_PERIC_PWM0_IPCLKPORT_I_PCLK_S0 0x20bc | |
| 382 | +#define GAT_PERIC_PWM1_IPCLKPORT_I_PCLK_S0 0x20c0 | |
| 383 | +#define GAT_PERIC_SMMU_IPCLKPORT_CCLK 0x20c4 | |
| 384 | +#define GAT_PERIC_SMMU_IPCLKPORT_PERIC_BCLK 0x20c8 | |
| 385 | +#define GAT_PERIC_SPI0_IPCLKPORT_I_PCLK 0x20cc | |
| 386 | +#define GAT_PERIC_SPI0_IPCLKPORT_I_SCLK_SPI 0x20d0 | |
| 387 | +#define GAT_PERIC_SPI1_IPCLKPORT_I_PCLK 0x20d4 | |
| 388 | +#define GAT_PERIC_SPI1_IPCLKPORT_I_SCLK_SPI 0x20d8 | |
| 389 | +#define GAT_PERIC_SPI2_IPCLKPORT_I_PCLK 0x20dc | |
| 390 | +#define GAT_PERIC_SPI2_IPCLKPORT_I_SCLK_SPI 0x20e0 | |
| 391 | +#define GAT_PERIC_TDM0_IPCLKPORT_HCLK_M 0x20e4 | |
| 392 | +#define GAT_PERIC_TDM0_IPCLKPORT_PCLK 0x20e8 | |
| 393 | +#define GAT_PERIC_TDM1_IPCLKPORT_HCLK_M 0x20ec | |
| 394 | +#define GAT_PERIC_TDM1_IPCLKPORT_PCLK 0x20f0 | |
| 395 | +#define GAT_PERIC_UART0_IPCLKPORT_I_SCLK_UART 0x20f4 | |
| 396 | +#define GAT_PERIC_UART0_IPCLKPORT_PCLK 0x20f8 | |
| 397 | +#define GAT_PERIC_UART1_IPCLKPORT_I_SCLK_UART 0x20fc | |
| 398 | +#define GAT_PERIC_UART1_IPCLKPORT_PCLK 0x2100 | |
| 399 | +#define GAT_SYSREG_PERI_IPCLKPORT_PCLK 0x2104 | |
| 400 | + | |
| 401 | +static const unsigned long peric_clk_regs[] __initconst = { | |
| 402 | + PLL_CON0_PERIC_DMACLK_MUX, | |
| 403 | + PLL_CON0_PERIC_EQOS_BUSCLK_MUX, | |
| 404 | + PLL_CON0_PERIC_PCLK_MUX, | |
| 405 | + PLL_CON0_PERIC_TBUCLK_MUX, | |
| 406 | + PLL_CON0_SPI_CLK, | |
| 407 | + PLL_CON0_SPI_PCLK, | |
| 408 | + PLL_CON0_UART_CLK, | |
| 409 | + PLL_CON0_UART_PCLK, | |
| 410 | + MUX_PERIC_EQOS_PHYRXCLK, | |
| 411 | + DIV_EQOS_BUSCLK, | |
| 412 | + DIV_PERIC_MCAN_CLK, | |
| 413 | + DIV_RGMII_CLK, | |
| 414 | + DIV_RII_CLK, | |
| 415 | + DIV_RMII_CLK, | |
| 416 | + DIV_SPI_CLK, | |
| 417 | + DIV_UART_CLK, | |
| 418 | + GAT_EQOS_TOP_IPCLKPORT_CLK_PTP_REF_I, | |
| 419 | + GAT_GPIO_PERIC_IPCLKPORT_OSCCLK, | |
| 420 | + GAT_PERIC_ADC0_IPCLKPORT_I_OSCCLK, | |
| 421 | + GAT_PERIC_CMU_PERIC_IPCLKPORT_PCLK, | |
| 422 | + GAT_PERIC_PWM0_IPCLKPORT_I_OSCCLK, | |
| 423 | + GAT_PERIC_PWM1_IPCLKPORT_I_OSCCLK, | |
| 424 | + GAT_ASYNC_APB_DMA0_IPCLKPORT_PCLKM, | |
| 425 | + GAT_ASYNC_APB_DMA0_IPCLKPORT_PCLKS, | |
| 426 | + GAT_ASYNC_APB_DMA1_IPCLKPORT_PCLKM, | |
| 427 | + GAT_ASYNC_APB_DMA1_IPCLKPORT_PCLKS, | |
| 428 | + GAT_AXI2APB_PERIC0_IPCLKPORT_ACLK, | |
| 429 | + GAT_AXI2APB_PERIC1_IPCLKPORT_ACLK, | |
| 430 | + GAT_AXI2APB_PERIC2_IPCLKPORT_ACLK, | |
| 431 | + GAT_BUS_D_PERIC_IPCLKPORT_DMACLK, | |
| 432 | + GAT_BUS_D_PERIC_IPCLKPORT_EQOSCLK, | |
| 433 | + GAT_BUS_D_PERIC_IPCLKPORT_MAINCLK, | |
| 434 | + GAT_BUS_P_PERIC_IPCLKPORT_EQOSCLK, | |
| 435 | + GAT_BUS_P_PERIC_IPCLKPORT_MAINCLK, | |
| 436 | + GAT_BUS_P_PERIC_IPCLKPORT_SMMUCLK, | |
| 437 | + GAT_EQOS_TOP_IPCLKPORT_ACLK_I, | |
| 438 | + GAT_EQOS_TOP_IPCLKPORT_CLK_RX_I, | |
| 439 | + GAT_EQOS_TOP_IPCLKPORT_HCLK_I, | |
| 440 | + GAT_EQOS_TOP_IPCLKPORT_RGMII_CLK_I, | |
| 441 | + GAT_EQOS_TOP_IPCLKPORT_RII_CLK_I, | |
| 442 | + GAT_EQOS_TOP_IPCLKPORT_RMII_CLK_I, | |
| 443 | + GAT_GPIO_PERIC_IPCLKPORT_PCLK, | |
| 444 | + GAT_NS_BRDG_PERIC_IPCLKPORT_CLK__PSOC_PERIC__CLK_PERIC_D, | |
| 445 | + GAT_NS_BRDG_PERIC_IPCLKPORT_CLK__PSOC_PERIC__CLK_PERIC_P, | |
| 446 | + GAT_PERIC_ADC0_IPCLKPORT_PCLK_S0, | |
| 447 | + GAT_PERIC_DMA0_IPCLKPORT_ACLK, | |
| 448 | + GAT_PERIC_DMA1_IPCLKPORT_ACLK, | |
| 449 | + GAT_PERIC_I2C0_IPCLKPORT_I_PCLK, | |
| 450 | + GAT_PERIC_I2C1_IPCLKPORT_I_PCLK, | |
| 451 | + GAT_PERIC_I2C2_IPCLKPORT_I_PCLK, | |
| 452 | + GAT_PERIC_I2C3_IPCLKPORT_I_PCLK, | |
| 453 | + GAT_PERIC_I2C4_IPCLKPORT_I_PCLK, | |
| 454 | + GAT_PERIC_I2C5_IPCLKPORT_I_PCLK, | |
| 455 | + GAT_PERIC_I2C6_IPCLKPORT_I_PCLK, | |
| 456 | + GAT_PERIC_I2C7_IPCLKPORT_I_PCLK, | |
| 457 | + GAT_PERIC_MCAN0_IPCLKPORT_CCLK, | |
| 458 | + GAT_PERIC_MCAN0_IPCLKPORT_PCLK, | |
| 459 | + GAT_PERIC_MCAN1_IPCLKPORT_CCLK, | |
| 460 | + GAT_PERIC_MCAN1_IPCLKPORT_PCLK, | |
| 461 | + GAT_PERIC_MCAN2_IPCLKPORT_CCLK, | |
| 462 | + GAT_PERIC_MCAN2_IPCLKPORT_PCLK, | |
| 463 | + GAT_PERIC_MCAN3_IPCLKPORT_CCLK, | |
| 464 | + GAT_PERIC_MCAN3_IPCLKPORT_PCLK, | |
| 465 | + GAT_PERIC_PWM0_IPCLKPORT_I_PCLK_S0, | |
| 466 | + GAT_PERIC_PWM1_IPCLKPORT_I_PCLK_S0, | |
| 467 | + GAT_PERIC_SMMU_IPCLKPORT_CCLK, | |
| 468 | + GAT_PERIC_SMMU_IPCLKPORT_PERIC_BCLK, | |
| 469 | + GAT_PERIC_SPI0_IPCLKPORT_I_PCLK, | |
| 470 | + GAT_PERIC_SPI0_IPCLKPORT_I_SCLK_SPI, | |
| 471 | + GAT_PERIC_SPI1_IPCLKPORT_I_PCLK, | |
| 472 | + GAT_PERIC_SPI1_IPCLKPORT_I_SCLK_SPI, | |
| 473 | + GAT_PERIC_SPI2_IPCLKPORT_I_PCLK, | |
| 474 | + GAT_PERIC_SPI2_IPCLKPORT_I_SCLK_SPI, | |
| 475 | + GAT_PERIC_TDM0_IPCLKPORT_HCLK_M, | |
| 476 | + GAT_PERIC_TDM0_IPCLKPORT_PCLK, | |
| 477 | + GAT_PERIC_TDM1_IPCLKPORT_HCLK_M, | |
| 478 | + GAT_PERIC_TDM1_IPCLKPORT_PCLK, | |
| 479 | + GAT_PERIC_UART0_IPCLKPORT_I_SCLK_UART, | |
| 480 | + GAT_PERIC_UART0_IPCLKPORT_PCLK, | |
| 481 | + GAT_PERIC_UART1_IPCLKPORT_I_SCLK_UART, | |
| 482 | + GAT_PERIC_UART1_IPCLKPORT_PCLK, | |
| 483 | + GAT_SYSREG_PERI_IPCLKPORT_PCLK, | |
| 484 | +}; | |
| 485 | + | |
| 486 | +static const struct samsung_fixed_rate_clock peric_fixed_clks[] __initconst = { | |
| 487 | + FRATE(PERIC_EQOS_PHYRXCLK, "eqos_phyrxclk", NULL, 0, 125000000), | |
| 488 | +}; | |
| 489 | + | |
| 490 | +/* List of parent clocks for Muxes in CMU_PERIC */ | |
| 491 | +PNAME(mout_peric_dmaclk_p) = { "fin_pll", "cmu_peric_shared1div4_dmaclk_gate" }; | |
| 492 | +PNAME(mout_peric_eqos_busclk_p) = { "fin_pll", "dout_cmu_pll_shared0_div4" }; | |
| 493 | +PNAME(mout_peric_pclk_p) = { "fin_pll", "dout_cmu_peric_shared1div36" }; | |
| 494 | +PNAME(mout_peric_tbuclk_p) = { "fin_pll", "dout_cmu_peric_shared0div3_tbuclk" }; | |
| 495 | +PNAME(mout_peric_spi_clk_p) = { "fin_pll", "dout_cmu_peric_shared0div20" }; | |
| 496 | +PNAME(mout_peric_spi_pclk_p) = { "fin_pll", "dout_cmu_peric_shared1div36" }; | |
| 497 | +PNAME(mout_peric_uart_clk_p) = { "fin_pll", "dout_cmu_peric_shared1div4_dmaclk" }; | |
| 498 | +PNAME(mout_peric_uart_pclk_p) = { "fin_pll", "dout_cmu_peric_shared1div36" }; | |
| 499 | +PNAME(mout_peric_eqos_phyrxclk_p) = { "dout_peric_rgmii_clk", "eqos_phyrxclk" }; | |
| 500 | + | |
| 501 | +static const struct samsung_mux_clock peric_mux_clks[] __initconst = { | |
| 502 | + MUX(0, "mout_peric_dmaclk", mout_peric_dmaclk_p, PLL_CON0_PERIC_DMACLK_MUX, 4, 1), | |
| 503 | + MUX(0, "mout_peric_eqos_busclk", mout_peric_eqos_busclk_p, | |
| 504 | + PLL_CON0_PERIC_EQOS_BUSCLK_MUX, 4, 1), | |
| 505 | + MUX(0, "mout_peric_pclk", mout_peric_pclk_p, PLL_CON0_PERIC_PCLK_MUX, 4, 1), | |
| 506 | + MUX(0, "mout_peric_tbuclk", mout_peric_tbuclk_p, PLL_CON0_PERIC_TBUCLK_MUX, 4, 1), | |
| 507 | + MUX(0, "mout_peric_spi_clk", mout_peric_spi_clk_p, PLL_CON0_SPI_CLK, 4, 1), | |
| 508 | + MUX(0, "mout_peric_spi_pclk", mout_peric_spi_pclk_p, PLL_CON0_SPI_PCLK, 4, 1), | |
| 509 | + MUX(0, "mout_peric_uart_clk", mout_peric_uart_clk_p, PLL_CON0_UART_CLK, 4, 1), | |
| 510 | + MUX(0, "mout_peric_uart_pclk", mout_peric_uart_pclk_p, PLL_CON0_UART_PCLK, 4, 1), | |
| 511 | + MUX(PERIC_EQOS_PHYRXCLK_MUX, "mout_peric_eqos_phyrxclk", mout_peric_eqos_phyrxclk_p, | |
| 512 | + MUX_PERIC_EQOS_PHYRXCLK, 0, 1), | |
| 513 | +}; | |
| 514 | + | |
| 515 | +static const struct samsung_div_clock peric_div_clks[] __initconst = { | |
| 516 | + DIV(0, "dout_peric_eqos_busclk", "mout_peric_eqos_busclk", DIV_EQOS_BUSCLK, 0, 4), | |
| 517 | + DIV(0, "dout_peric_mcan_clk", "mout_peric_dmaclk", DIV_PERIC_MCAN_CLK, 0, 4), | |
| 518 | + DIV(PERIC_DOUT_RGMII_CLK, "dout_peric_rgmii_clk", "mout_peric_eqos_busclk", | |
| 519 | + DIV_RGMII_CLK, 0, 4), | |
| 520 | + DIV(0, "dout_peric_rii_clk", "dout_peric_rmii_clk", DIV_RII_CLK, 0, 4), | |
| 521 | + DIV(0, "dout_peric_rmii_clk", "dout_peric_rgmii_clk", DIV_RMII_CLK, 0, 4), | |
| 522 | + DIV(0, "dout_peric_spi_clk", "mout_peric_spi_clk", DIV_SPI_CLK, 0, 6), | |
| 523 | + DIV(0, "dout_peric_uart_clk", "mout_peric_uart_clk", DIV_UART_CLK, 0, 6), | |
| 524 | +}; | |
| 525 | + | |
| 526 | +static const struct samsung_gate_clock peric_gate_clks[] __initconst = { | |
| 527 | + GATE(PERIC_EQOS_TOP_IPCLKPORT_CLK_PTP_REF_I, "peric_eqos_top_ipclkport_clk_ptp_ref_i", | |
| 528 | + "fin_pll", GAT_EQOS_TOP_IPCLKPORT_CLK_PTP_REF_I, 21, CLK_IGNORE_UNUSED, 0), | |
| 529 | + GATE(0, "peric_gpio_peric_ipclkport_oscclk", "fin_pll", GAT_GPIO_PERIC_IPCLKPORT_OSCCLK, | |
| 530 | + 21, CLK_IGNORE_UNUSED, 0), | |
| 531 | + GATE(PERIC_PCLK_ADCIF, "peric_adc0_ipclkport_i_oscclk", "fin_pll", | |
| 532 | + GAT_PERIC_ADC0_IPCLKPORT_I_OSCCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 533 | + GATE(0, "peric_cmu_peric_ipclkport_pclk", "mout_peric_pclk", | |
| 534 | + GAT_PERIC_CMU_PERIC_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 535 | + GATE(0, "peric_pwm0_ipclkport_i_oscclk", "fin_pll", GAT_PERIC_PWM0_IPCLKPORT_I_OSCCLK, 21, | |
| 536 | + CLK_IGNORE_UNUSED, 0), | |
| 537 | + GATE(0, "peric_pwm1_ipclkport_i_oscclk", "fin_pll", GAT_PERIC_PWM1_IPCLKPORT_I_OSCCLK, 21, | |
| 538 | + CLK_IGNORE_UNUSED, 0), | |
| 539 | + GATE(0, "peric_async_apb_dma0_ipclkport_pclkm", "mout_peric_dmaclk", | |
| 540 | + GAT_ASYNC_APB_DMA0_IPCLKPORT_PCLKM, 21, CLK_IGNORE_UNUSED, 0), | |
| 541 | + GATE(0, "peric_async_apb_dma0_ipclkport_pclks", "mout_peric_pclk", | |
| 542 | + GAT_ASYNC_APB_DMA0_IPCLKPORT_PCLKS, 21, CLK_IGNORE_UNUSED, 0), | |
| 543 | + GATE(0, "peric_async_apb_dma1_ipclkport_pclkm", "mout_peric_dmaclk", | |
| 544 | + GAT_ASYNC_APB_DMA1_IPCLKPORT_PCLKM, 21, CLK_IGNORE_UNUSED, 0), | |
| 545 | + GATE(0, "peric_async_apb_dma1_ipclkport_pclks", "mout_peric_pclk", | |
| 546 | + GAT_ASYNC_APB_DMA1_IPCLKPORT_PCLKS, 21, CLK_IGNORE_UNUSED, 0), | |
| 547 | + GATE(0, "peric_axi2apb_peric0_ipclkport_aclk", "mout_peric_pclk", | |
| 548 | + GAT_AXI2APB_PERIC0_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 549 | + GATE(0, "peric_axi2apb_peric1_ipclkport_aclk", "mout_peric_pclk", | |
| 550 | + GAT_AXI2APB_PERIC1_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 551 | + GATE(0, "peric_axi2apb_peric2_ipclkport_aclk", "mout_peric_pclk", | |
| 552 | + GAT_AXI2APB_PERIC2_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 553 | + GATE(0, "peric_bus_d_peric_ipclkport_dmaclk", "mout_peric_dmaclk", | |
| 554 | + GAT_BUS_D_PERIC_IPCLKPORT_DMACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 555 | + GATE(PERIC_BUS_D_PERIC_IPCLKPORT_EQOSCLK, "peric_bus_d_peric_ipclkport_eqosclk", | |
| 556 | + "dout_peric_eqos_busclk", GAT_BUS_D_PERIC_IPCLKPORT_EQOSCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 557 | + GATE(0, "peric_bus_d_peric_ipclkport_mainclk", "mout_peric_tbuclk", | |
| 558 | + GAT_BUS_D_PERIC_IPCLKPORT_MAINCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 559 | + GATE(PERIC_BUS_P_PERIC_IPCLKPORT_EQOSCLK, "peric_bus_p_peric_ipclkport_eqosclk", | |
| 560 | + "dout_peric_eqos_busclk", GAT_BUS_P_PERIC_IPCLKPORT_EQOSCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 561 | + GATE(0, "peric_bus_p_peric_ipclkport_mainclk", "mout_peric_pclk", | |
| 562 | + GAT_BUS_P_PERIC_IPCLKPORT_MAINCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 563 | + GATE(0, "peric_bus_p_peric_ipclkport_smmuclk", "mout_peric_tbuclk", | |
| 564 | + GAT_BUS_P_PERIC_IPCLKPORT_SMMUCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 565 | + GATE(PERIC_EQOS_TOP_IPCLKPORT_ACLK_I, "peric_eqos_top_ipclkport_aclk_i", | |
| 566 | + "dout_peric_eqos_busclk", GAT_EQOS_TOP_IPCLKPORT_ACLK_I, 21, CLK_IGNORE_UNUSED, 0), | |
| 567 | + GATE(PERIC_EQOS_TOP_IPCLKPORT_CLK_RX_I, "peric_eqos_top_ipclkport_clk_rx_i", | |
| 568 | + "mout_peric_eqos_phyrxclk", GAT_EQOS_TOP_IPCLKPORT_CLK_RX_I, 21, CLK_IGNORE_UNUSED, 0), | |
| 569 | + GATE(PERIC_EQOS_TOP_IPCLKPORT_HCLK_I, "peric_eqos_top_ipclkport_hclk_i", | |
| 570 | + "dout_peric_eqos_busclk", GAT_EQOS_TOP_IPCLKPORT_HCLK_I, 21, CLK_IGNORE_UNUSED, 0), | |
| 571 | + GATE(PERIC_EQOS_TOP_IPCLKPORT_RGMII_CLK_I, "peric_eqos_top_ipclkport_rgmii_clk_i", | |
| 572 | + "dout_peric_rgmii_clk", GAT_EQOS_TOP_IPCLKPORT_RGMII_CLK_I, 21, CLK_IGNORE_UNUSED, 0), | |
| 573 | + GATE(0, "peric_eqos_top_ipclkport_rii_clk_i", "dout_peric_rii_clk", | |
| 574 | + GAT_EQOS_TOP_IPCLKPORT_RII_CLK_I, 21, CLK_IGNORE_UNUSED, 0), | |
| 575 | + GATE(0, "peric_eqos_top_ipclkport_rmii_clk_i", "dout_peric_rmii_clk", | |
| 576 | + GAT_EQOS_TOP_IPCLKPORT_RMII_CLK_I, 21, CLK_IGNORE_UNUSED, 0), | |
| 577 | + GATE(0, "peric_gpio_peric_ipclkport_pclk", "mout_peric_pclk", | |
| 578 | + GAT_GPIO_PERIC_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 579 | + GATE(0, "peric_ns_brdg_peric_ipclkport_clk__psoc_peric__clk_peric_d", "mout_peric_tbuclk", | |
| 580 | + GAT_NS_BRDG_PERIC_IPCLKPORT_CLK__PSOC_PERIC__CLK_PERIC_D, 21, CLK_IGNORE_UNUSED, 0), | |
| 581 | + GATE(0, "peric_ns_brdg_peric_ipclkport_clk__psoc_peric__clk_peric_p", "mout_peric_pclk", | |
| 582 | + GAT_NS_BRDG_PERIC_IPCLKPORT_CLK__PSOC_PERIC__CLK_PERIC_P, 21, CLK_IGNORE_UNUSED, 0), | |
| 583 | + GATE(0, "peric_adc0_ipclkport_pclk_s0", "mout_peric_pclk", | |
| 584 | + GAT_PERIC_ADC0_IPCLKPORT_PCLK_S0, 21, CLK_IGNORE_UNUSED, 0), | |
| 585 | + GATE(PERIC_DMA0_IPCLKPORT_ACLK, "peric_dma0_ipclkport_aclk", "mout_peric_dmaclk", | |
| 586 | + GAT_PERIC_DMA0_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 587 | + GATE(PERIC_DMA1_IPCLKPORT_ACLK, "peric_dma1_ipclkport_aclk", "mout_peric_dmaclk", | |
| 588 | + GAT_PERIC_DMA1_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 589 | + GATE(PERIC_PCLK_HSI2C0, "peric_i2c0_ipclkport_i_pclk", "mout_peric_pclk", | |
| 590 | + GAT_PERIC_I2C0_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 591 | + GATE(PERIC_PCLK_HSI2C1, "peric_i2c1_ipclkport_i_pclk", "mout_peric_pclk", | |
| 592 | + GAT_PERIC_I2C1_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 593 | + GATE(PERIC_PCLK_HSI2C2, "peric_i2c2_ipclkport_i_pclk", "mout_peric_pclk", | |
| 594 | + GAT_PERIC_I2C2_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 595 | + GATE(PERIC_PCLK_HSI2C3, "peric_i2c3_ipclkport_i_pclk", "mout_peric_pclk", | |
| 596 | + GAT_PERIC_I2C3_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 597 | + GATE(PERIC_PCLK_HSI2C4, "peric_i2c4_ipclkport_i_pclk", "mout_peric_pclk", | |
| 598 | + GAT_PERIC_I2C4_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 599 | + GATE(PERIC_PCLK_HSI2C5, "peric_i2c5_ipclkport_i_pclk", "mout_peric_pclk", | |
| 600 | + GAT_PERIC_I2C5_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 601 | + GATE(PERIC_PCLK_HSI2C6, "peric_i2c6_ipclkport_i_pclk", "mout_peric_pclk", | |
| 602 | + GAT_PERIC_I2C6_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 603 | + GATE(PERIC_PCLK_HSI2C7, "peric_i2c7_ipclkport_i_pclk", "mout_peric_pclk", | |
| 604 | + GAT_PERIC_I2C7_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 605 | + GATE(PERIC_MCAN0_IPCLKPORT_CCLK, "peric_mcan0_ipclkport_cclk", "dout_peric_mcan_clk", | |
| 606 | + GAT_PERIC_MCAN0_IPCLKPORT_CCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 607 | + GATE(PERIC_MCAN0_IPCLKPORT_PCLK, "peric_mcan0_ipclkport_pclk", "mout_peric_pclk", | |
| 608 | + GAT_PERIC_MCAN0_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 609 | + GATE(PERIC_MCAN1_IPCLKPORT_CCLK, "peric_mcan1_ipclkport_cclk", "dout_peric_mcan_clk", | |
| 610 | + GAT_PERIC_MCAN1_IPCLKPORT_CCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 611 | + GATE(PERIC_MCAN1_IPCLKPORT_PCLK, "peric_mcan1_ipclkport_pclk", "mout_peric_pclk", | |
| 612 | + GAT_PERIC_MCAN1_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 613 | + GATE(PERIC_MCAN2_IPCLKPORT_CCLK, "peric_mcan2_ipclkport_cclk", "dout_peric_mcan_clk", | |
| 614 | + GAT_PERIC_MCAN2_IPCLKPORT_CCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 615 | + GATE(PERIC_MCAN2_IPCLKPORT_PCLK, "peric_mcan2_ipclkport_pclk", "mout_peric_pclk", | |
| 616 | + GAT_PERIC_MCAN2_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 617 | + GATE(PERIC_MCAN3_IPCLKPORT_CCLK, "peric_mcan3_ipclkport_cclk", "dout_peric_mcan_clk", | |
| 618 | + GAT_PERIC_MCAN3_IPCLKPORT_CCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 619 | + GATE(PERIC_MCAN3_IPCLKPORT_PCLK, "peric_mcan3_ipclkport_pclk", "mout_peric_pclk", | |
| 620 | + GAT_PERIC_MCAN3_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 621 | + GATE(PERIC_PWM0_IPCLKPORT_I_PCLK_S0, "peric_pwm0_ipclkport_i_pclk_s0", "mout_peric_pclk", | |
| 622 | + GAT_PERIC_PWM0_IPCLKPORT_I_PCLK_S0, 21, CLK_IGNORE_UNUSED, 0), | |
| 623 | + GATE(PERIC_PWM1_IPCLKPORT_I_PCLK_S0, "peric_pwm1_ipclkport_i_pclk_s0", "mout_peric_pclk", | |
| 624 | + GAT_PERIC_PWM1_IPCLKPORT_I_PCLK_S0, 21, CLK_IGNORE_UNUSED, 0), | |
| 625 | + GATE(0, "peric_smmu_ipclkport_cclk", "mout_peric_tbuclk", | |
| 626 | + GAT_PERIC_SMMU_IPCLKPORT_CCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 627 | + GATE(0, "peric_smmu_ipclkport_peric_bclk", "mout_peric_tbuclk", | |
| 628 | + GAT_PERIC_SMMU_IPCLKPORT_PERIC_BCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 629 | + GATE(PERIC_PCLK_SPI0, "peric_spi0_ipclkport_i_pclk", "mout_peric_spi_pclk", | |
| 630 | + GAT_PERIC_SPI0_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 631 | + GATE(PERIC_SCLK_SPI0, "peric_spi0_ipclkport_i_sclk_spi", "dout_peric_spi_clk", | |
| 632 | + GAT_PERIC_SPI0_IPCLKPORT_I_SCLK_SPI, 21, CLK_IGNORE_UNUSED, 0), | |
| 633 | + GATE(PERIC_PCLK_SPI1, "peric_spi1_ipclkport_i_pclk", "mout_peric_spi_pclk", | |
| 634 | + GAT_PERIC_SPI1_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 635 | + GATE(PERIC_SCLK_SPI1, "peric_spi1_ipclkport_i_sclk_spi", "dout_peric_spi_clk", | |
| 636 | + GAT_PERIC_SPI1_IPCLKPORT_I_SCLK_SPI, 21, CLK_IGNORE_UNUSED, 0), | |
| 637 | + GATE(PERIC_PCLK_SPI2, "peric_spi2_ipclkport_i_pclk", "mout_peric_spi_pclk", | |
| 638 | + GAT_PERIC_SPI2_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 639 | + GATE(PERIC_SCLK_SPI2, "peric_spi2_ipclkport_i_sclk_spi", "dout_peric_spi_clk", | |
| 640 | + GAT_PERIC_SPI2_IPCLKPORT_I_SCLK_SPI, 21, CLK_IGNORE_UNUSED, 0), | |
| 641 | + GATE(PERIC_HCLK_TDM0, "peric_tdm0_ipclkport_hclk_m", "mout_peric_pclk", | |
| 642 | + GAT_PERIC_TDM0_IPCLKPORT_HCLK_M, 21, CLK_IGNORE_UNUSED, 0), | |
| 643 | + GATE(PERIC_PCLK_TDM0, "peric_tdm0_ipclkport_pclk", "mout_peric_pclk", | |
| 644 | + GAT_PERIC_TDM0_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 645 | + GATE(PERIC_HCLK_TDM1, "peric_tdm1_ipclkport_hclk_m", "mout_peric_pclk", | |
| 646 | + GAT_PERIC_TDM1_IPCLKPORT_HCLK_M, 21, CLK_IGNORE_UNUSED, 0), | |
| 647 | + GATE(PERIC_PCLK_TDM1, "peric_tdm1_ipclkport_pclk", "mout_peric_pclk", | |
| 648 | + GAT_PERIC_TDM1_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 649 | + GATE(PERIC_SCLK_UART0, "peric_uart0_ipclkport_i_sclk_uart", "dout_peric_uart_clk", | |
| 650 | + GAT_PERIC_UART0_IPCLKPORT_I_SCLK_UART, 21, CLK_IGNORE_UNUSED, 0), | |
| 651 | + GATE(PERIC_PCLK_UART0, "peric_uart0_ipclkport_pclk", "mout_peric_uart_pclk", | |
| 652 | + GAT_PERIC_UART0_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 653 | + GATE(PERIC_SCLK_UART1, "peric_uart1_ipclkport_i_sclk_uart", "dout_peric_uart_clk", | |
| 654 | + GAT_PERIC_UART1_IPCLKPORT_I_SCLK_UART, 21, CLK_IGNORE_UNUSED, 0), | |
| 655 | + GATE(PERIC_PCLK_UART1, "peric_uart1_ipclkport_pclk", "mout_peric_uart_pclk", | |
| 656 | + GAT_PERIC_UART1_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 657 | + GATE(0, "peric_sysreg_peri_ipclkport_pclk", "mout_peric_pclk", | |
| 658 | + GAT_SYSREG_PERI_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 659 | +}; | |
| 660 | + | |
| 661 | +static const struct samsung_cmu_info peric_cmu_info __initconst = { | |
| 662 | + .mux_clks = peric_mux_clks, | |
| 663 | + .nr_mux_clks = ARRAY_SIZE(peric_mux_clks), | |
| 664 | + .div_clks = peric_div_clks, | |
| 665 | + .nr_div_clks = ARRAY_SIZE(peric_div_clks), | |
| 666 | + .gate_clks = peric_gate_clks, | |
| 667 | + .nr_gate_clks = ARRAY_SIZE(peric_gate_clks), | |
| 668 | + .fixed_clks = peric_fixed_clks, | |
| 669 | + .nr_fixed_clks = ARRAY_SIZE(peric_fixed_clks), | |
| 670 | + .nr_clk_ids = PERIC_NR_CLK, | |
| 671 | + .clk_regs = peric_clk_regs, | |
| 672 | + .nr_clk_regs = ARRAY_SIZE(peric_clk_regs), | |
| 673 | + .clk_name = "dout_cmu_pll_shared0_div4", | |
| 674 | +}; | |
| 675 | + | |
| 676 | +/* Register Offset definitions for CMU_FSYS0 (0x15010000) */ | |
| 677 | +#define PLL_CON0_CLKCMU_FSYS0_UNIPRO 0x100 | |
| 678 | +#define PLL_CON0_CLK_FSYS0_SLAVEBUSCLK 0x140 | |
| 679 | +#define PLL_CON0_EQOS_RGMII_125_MUX1 0x160 | |
| 680 | +#define DIV_CLK_UNIPRO 0x1800 | |
| 681 | +#define DIV_EQS_RGMII_CLK_125 0x1804 | |
| 682 | +#define DIV_PERIBUS_GRP 0x1808 | |
| 683 | +#define DIV_EQOS_RII_CLK2O5 0x180c | |
| 684 | +#define DIV_EQOS_RMIICLK_25 0x1810 | |
| 685 | +#define DIV_PCIE_PHY_OSCCLK 0x1814 | |
| 686 | +#define GAT_FSYS0_EQOS_TOP0_IPCLKPORT_CLK_PTP_REF_I 0x2004 | |
| 687 | +#define GAT_FSYS0_EQOS_TOP0_IPCLKPORT_CLK_RX_I 0x2008 | |
| 688 | +#define GAT_FSYS0_FSYS0_CMU_FSYS0_IPCLKPORT_PCLK 0x200c | |
| 689 | +#define GAT_FSYS0_GPIO_FSYS0_IPCLKPORT_OSCCLK 0x2010 | |
| 690 | +#define GAT_FSYS0_PCIE_TOP_IPCLKPORT_PCIEG3_PHY_X4_INST_0_PLL_REFCLK_FROM_XO 0x2014 | |
| 691 | +#define GAT_FSYS0_PCIE_TOP_IPCLKPORT_PIPE_PAL_INST_0_I_IMMORTAL_CLK 0x2018 | |
| 692 | +#define GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_AUX_CLK_SOC 0x201c | |
| 693 | +#define GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_MPHY_REFCLK_IXTAL24 0x2020 | |
| 694 | +#define GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_MPHY_REFCLK_IXTAL26 0x2024 | |
| 695 | +#define GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_MPHY_REFCLK_IXTAL24 0x2028 | |
| 696 | +#define GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_MPHY_REFCLK_IXTAL26 0x202c | |
| 697 | +#define GAT_FSYS0_AHBBR_FSYS0_IPCLKPORT_HCLK 0x2038 | |
| 698 | +#define GAT_FSYS0_AXI2APB_FSYS0_IPCLKPORT_ACLK 0x203c | |
| 699 | +#define GAT_FSYS0_BUS_D_FSYS0_IPCLKPORT_MAINCLK 0x2040 | |
| 700 | +#define GAT_FSYS0_BUS_D_FSYS0_IPCLKPORT_PERICLK 0x2044 | |
| 701 | +#define GAT_FSYS0_BUS_P_FSYS0_IPCLKPORT_MAINCLK 0x2048 | |
| 702 | +#define GAT_FSYS0_BUS_P_FSYS0_IPCLKPORT_TCUCLK 0x204c | |
| 703 | +#define GAT_FSYS0_CPE425_IPCLKPORT_ACLK 0x2050 | |
| 704 | +#define GAT_FSYS0_EQOS_TOP0_IPCLKPORT_ACLK_I 0x2054 | |
| 705 | +#define GAT_FSYS0_EQOS_TOP0_IPCLKPORT_HCLK_I 0x2058 | |
| 706 | +#define GAT_FSYS0_EQOS_TOP0_IPCLKPORT_RGMII_CLK_I 0x205c | |
| 707 | +#define GAT_FSYS0_EQOS_TOP0_IPCLKPORT_RII_CLK_I 0x2060 | |
| 708 | +#define GAT_FSYS0_EQOS_TOP0_IPCLKPORT_RMII_CLK_I 0x2064 | |
| 709 | +#define GAT_FSYS0_GPIO_FSYS0_IPCLKPORT_PCLK 0x2068 | |
| 710 | +#define GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_D 0x206c | |
| 711 | +#define GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_D1 0x2070 | |
| 712 | +#define GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_P 0x2074 | |
| 713 | +#define GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_S 0x2078 | |
| 714 | +#define GAT_FSYS0_PCIE_TOP_IPCLKPORT_PCIEG3_PHY_X4_INST_0_I_APB_PCLK 0x207c | |
| 715 | +#define GAT_FSYS0_PCIE_TOP_IPCLKPORT_PCIEG3_PHY_X4_INST_0_PLL_REFCLK_FROM_SYSPLL 0x2080 | |
| 716 | +#define GAT_FSYS0_PCIE_TOP_IPCLKPORT_PIPE_PAL_INST_0_I_APB_PCLK_0 0x2084 | |
| 717 | +#define GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_DBI_ACLK_SOC 0x2088 | |
| 718 | +#define GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK 0x208c | |
| 719 | +#define GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_MSTR_ACLK_SOC 0x2090 | |
| 720 | +#define GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_SLV_ACLK_SOC 0x2094 | |
| 721 | +#define GAT_FSYS0_SMMU_FSYS0_IPCLKPORT_CCLK 0x2098 | |
| 722 | +#define GAT_FSYS0_SMMU_FSYS0_IPCLKPORT_FSYS0_BCLK 0x209c | |
| 723 | +#define GAT_FSYS0_SYSREG_FSYS0_IPCLKPORT_PCLK 0x20a0 | |
| 724 | +#define GAT_FSYS0_UFS_TOP0_IPCLKPORT_HCLK_BUS 0x20a4 | |
| 725 | +#define GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_ACLK 0x20a8 | |
| 726 | +#define GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_CLK_UNIPRO 0x20ac | |
| 727 | +#define GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_FMP_CLK 0x20b0 | |
| 728 | +#define GAT_FSYS0_UFS_TOP1_IPCLKPORT_HCLK_BUS 0x20b4 | |
| 729 | +#define GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_ACLK 0x20b8 | |
| 730 | +#define GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_CLK_UNIPRO 0x20bc | |
| 731 | +#define GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_FMP_CLK 0x20c0 | |
| 732 | +#define GAT_FSYS0_RII_CLK_DIVGATE 0x20d4 | |
| 733 | + | |
| 734 | +static const unsigned long fsys0_clk_regs[] __initconst = { | |
| 735 | + PLL_CON0_CLKCMU_FSYS0_UNIPRO, | |
| 736 | + PLL_CON0_CLK_FSYS0_SLAVEBUSCLK, | |
| 737 | + PLL_CON0_EQOS_RGMII_125_MUX1, | |
| 738 | + DIV_CLK_UNIPRO, | |
| 739 | + DIV_EQS_RGMII_CLK_125, | |
| 740 | + DIV_PERIBUS_GRP, | |
| 741 | + DIV_EQOS_RII_CLK2O5, | |
| 742 | + DIV_EQOS_RMIICLK_25, | |
| 743 | + DIV_PCIE_PHY_OSCCLK, | |
| 744 | + GAT_FSYS0_EQOS_TOP0_IPCLKPORT_CLK_PTP_REF_I, | |
| 745 | + GAT_FSYS0_EQOS_TOP0_IPCLKPORT_CLK_RX_I, | |
| 746 | + GAT_FSYS0_FSYS0_CMU_FSYS0_IPCLKPORT_PCLK, | |
| 747 | + GAT_FSYS0_GPIO_FSYS0_IPCLKPORT_OSCCLK, | |
| 748 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_PCIEG3_PHY_X4_INST_0_PLL_REFCLK_FROM_XO, | |
| 749 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_PIPE_PAL_INST_0_I_IMMORTAL_CLK, | |
| 750 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_AUX_CLK_SOC, | |
| 751 | + GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_MPHY_REFCLK_IXTAL24, | |
| 752 | + GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_MPHY_REFCLK_IXTAL26, | |
| 753 | + GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_MPHY_REFCLK_IXTAL24, | |
| 754 | + GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_MPHY_REFCLK_IXTAL26, | |
| 755 | + GAT_FSYS0_AHBBR_FSYS0_IPCLKPORT_HCLK, | |
| 756 | + GAT_FSYS0_AXI2APB_FSYS0_IPCLKPORT_ACLK, | |
| 757 | + GAT_FSYS0_BUS_D_FSYS0_IPCLKPORT_MAINCLK, | |
| 758 | + GAT_FSYS0_BUS_D_FSYS0_IPCLKPORT_PERICLK, | |
| 759 | + GAT_FSYS0_BUS_P_FSYS0_IPCLKPORT_MAINCLK, | |
| 760 | + GAT_FSYS0_BUS_P_FSYS0_IPCLKPORT_TCUCLK, | |
| 761 | + GAT_FSYS0_CPE425_IPCLKPORT_ACLK, | |
| 762 | + GAT_FSYS0_EQOS_TOP0_IPCLKPORT_ACLK_I, | |
| 763 | + GAT_FSYS0_EQOS_TOP0_IPCLKPORT_HCLK_I, | |
| 764 | + GAT_FSYS0_EQOS_TOP0_IPCLKPORT_RGMII_CLK_I, | |
| 765 | + GAT_FSYS0_EQOS_TOP0_IPCLKPORT_RII_CLK_I, | |
| 766 | + GAT_FSYS0_EQOS_TOP0_IPCLKPORT_RMII_CLK_I, | |
| 767 | + GAT_FSYS0_GPIO_FSYS0_IPCLKPORT_PCLK, | |
| 768 | + GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_D, | |
| 769 | + GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_D1, | |
| 770 | + GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_P, | |
| 771 | + GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_S, | |
| 772 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_PCIEG3_PHY_X4_INST_0_I_APB_PCLK, | |
| 773 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_PCIEG3_PHY_X4_INST_0_PLL_REFCLK_FROM_SYSPLL, | |
| 774 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_PIPE_PAL_INST_0_I_APB_PCLK_0, | |
| 775 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_DBI_ACLK_SOC, | |
| 776 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK, | |
| 777 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_MSTR_ACLK_SOC, | |
| 778 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_SLV_ACLK_SOC, | |
| 779 | + GAT_FSYS0_SMMU_FSYS0_IPCLKPORT_CCLK, | |
| 780 | + GAT_FSYS0_SMMU_FSYS0_IPCLKPORT_FSYS0_BCLK, | |
| 781 | + GAT_FSYS0_SYSREG_FSYS0_IPCLKPORT_PCLK, | |
| 782 | + GAT_FSYS0_UFS_TOP0_IPCLKPORT_HCLK_BUS, | |
| 783 | + GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_ACLK, | |
| 784 | + GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_CLK_UNIPRO, | |
| 785 | + GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_FMP_CLK, | |
| 786 | + GAT_FSYS0_UFS_TOP1_IPCLKPORT_HCLK_BUS, | |
| 787 | + GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_ACLK, | |
| 788 | + GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_CLK_UNIPRO, | |
| 789 | + GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_FMP_CLK, | |
| 790 | + GAT_FSYS0_RII_CLK_DIVGATE, | |
| 791 | +}; | |
| 792 | + | |
| 793 | +static const struct samsung_fixed_rate_clock fsys0_fixed_clks[] __initconst = { | |
| 794 | + FRATE(0, "pad_eqos0_phyrxclk", NULL, 0, 125000000), | |
| 795 | + FRATE(0, "i_mphy_refclk_ixtal26", NULL, 0, 26000000), | |
| 796 | + FRATE(0, "xtal_clk_pcie_phy", NULL, 0, 100000000), | |
| 797 | +}; | |
| 798 | + | |
| 799 | +/* List of parent clocks for Muxes in CMU_FSYS0 */ | |
| 800 | +PNAME(mout_fsys0_clkcmu_fsys0_unipro_p) = { "fin_pll", "dout_cmu_pll_shared0_div6" }; | |
| 801 | +PNAME(mout_fsys0_clk_fsys0_slavebusclk_p) = { "fin_pll", "dout_cmu_fsys0_shared1div4" }; | |
| 802 | +PNAME(mout_fsys0_eqos_rgmii_125_mux1_p) = { "fin_pll", "dout_cmu_fsys0_shared0div4" }; | |
| 803 | + | |
| 804 | +static const struct samsung_mux_clock fsys0_mux_clks[] __initconst = { | |
| 805 | + MUX(0, "mout_fsys0_clkcmu_fsys0_unipro", mout_fsys0_clkcmu_fsys0_unipro_p, | |
| 806 | + PLL_CON0_CLKCMU_FSYS0_UNIPRO, 4, 1), | |
| 807 | + MUX(0, "mout_fsys0_clk_fsys0_slavebusclk", mout_fsys0_clk_fsys0_slavebusclk_p, | |
| 808 | + PLL_CON0_CLK_FSYS0_SLAVEBUSCLK, 4, 1), | |
| 809 | + MUX(0, "mout_fsys0_eqos_rgmii_125_mux1", mout_fsys0_eqos_rgmii_125_mux1_p, | |
| 810 | + PLL_CON0_EQOS_RGMII_125_MUX1, 4, 1), | |
| 811 | +}; | |
| 812 | + | |
| 813 | +static const struct samsung_div_clock fsys0_div_clks[] __initconst = { | |
| 814 | + DIV(0, "dout_fsys0_clk_unipro", "mout_fsys0_clkcmu_fsys0_unipro", DIV_CLK_UNIPRO, 0, 4), | |
| 815 | + DIV(0, "dout_fsys0_eqs_rgmii_clk_125", "mout_fsys0_eqos_rgmii_125_mux1", | |
| 816 | + DIV_EQS_RGMII_CLK_125, 0, 4), | |
| 817 | + DIV(FSYS0_DOUT_FSYS0_PERIBUS_GRP, "dout_fsys0_peribus_grp", | |
| 818 | + "mout_fsys0_clk_fsys0_slavebusclk", DIV_PERIBUS_GRP, 0, 4), | |
| 819 | + DIV(0, "dout_fsys0_eqos_rii_clk2o5", "fsys0_rii_clk_divgate", DIV_EQOS_RII_CLK2O5, 0, 4), | |
| 820 | + DIV(0, "dout_fsys0_eqos_rmiiclk_25", "mout_fsys0_eqos_rgmii_125_mux1", | |
| 821 | + DIV_EQOS_RMIICLK_25, 0, 5), | |
| 822 | + DIV(0, "dout_fsys0_pcie_phy_oscclk", "mout_fsys0_eqos_rgmii_125_mux1", | |
| 823 | + DIV_PCIE_PHY_OSCCLK, 0, 4), | |
| 824 | +}; | |
| 825 | + | |
| 826 | +static const struct samsung_gate_clock fsys0_gate_clks[] __initconst = { | |
| 827 | + GATE(FSYS0_EQOS_TOP0_IPCLKPORT_CLK_RX_I, "fsys0_eqos_top0_ipclkport_clk_rx_i", | |
| 828 | + "pad_eqos0_phyrxclk", GAT_FSYS0_EQOS_TOP0_IPCLKPORT_CLK_RX_I, 21, | |
| 829 | + CLK_IGNORE_UNUSED, 0), | |
| 830 | + GATE(PCIE_SUBCTRL_INST0_AUX_CLK_SOC, | |
| 831 | + "fsys0_pcie_top_ipclkport_fsd_pcie_sub_ctrl_inst_0_aux_clk_soc", "fin_pll", | |
| 832 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_AUX_CLK_SOC, 21, | |
| 833 | + CLK_IGNORE_UNUSED, 0), | |
| 834 | + GATE(0, "fsys0_fsys0_cmu_fsys0_ipclkport_pclk", "dout_fsys0_peribus_grp", | |
| 835 | + GAT_FSYS0_FSYS0_CMU_FSYS0_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 836 | + GATE(0, | |
| 837 | + "fsys0_pcie_top_ipclkport_pcieg3_phy_x4_inst_0_pll_refclk_from_xo", | |
| 838 | + "xtal_clk_pcie_phy", | |
| 839 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_PCIEG3_PHY_X4_INST_0_PLL_REFCLK_FROM_XO, 21, | |
| 840 | + CLK_IGNORE_UNUSED, 0), | |
| 841 | + GATE(UFS0_MPHY_REFCLK_IXTAL24, "fsys0_ufs_top0_ipclkport_i_mphy_refclk_ixtal24", | |
| 842 | + "i_mphy_refclk_ixtal26", GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_MPHY_REFCLK_IXTAL24, 21, | |
| 843 | + CLK_IGNORE_UNUSED, 0), | |
| 844 | + GATE(UFS0_MPHY_REFCLK_IXTAL26, "fsys0_ufs_top0_ipclkport_i_mphy_refclk_ixtal26", | |
| 845 | + "i_mphy_refclk_ixtal26", GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_MPHY_REFCLK_IXTAL26, 21, | |
| 846 | + CLK_IGNORE_UNUSED, 0), | |
| 847 | + GATE(UFS1_MPHY_REFCLK_IXTAL24, "fsys0_ufs_top1_ipclkport_i_mphy_refclk_ixtal24", | |
| 848 | + "i_mphy_refclk_ixtal26", GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_MPHY_REFCLK_IXTAL24, 21, | |
| 849 | + CLK_IGNORE_UNUSED, 0), | |
| 850 | + GATE(UFS1_MPHY_REFCLK_IXTAL26, "fsys0_ufs_top1_ipclkport_i_mphy_refclk_ixtal26", | |
| 851 | + "i_mphy_refclk_ixtal26", GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_MPHY_REFCLK_IXTAL26, 21, | |
| 852 | + CLK_IGNORE_UNUSED, 0), | |
| 853 | + GATE(0, "fsys0_ahbbr_fsys0_ipclkport_hclk", "dout_fsys0_peribus_grp", | |
| 854 | + GAT_FSYS0_AHBBR_FSYS0_IPCLKPORT_HCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 855 | + GATE(0, "fsys0_axi2apb_fsys0_ipclkport_aclk", "dout_fsys0_peribus_grp", | |
| 856 | + GAT_FSYS0_AXI2APB_FSYS0_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 857 | + GATE(0, "fsys0_bus_d_fsys0_ipclkport_mainclk", "mout_fsys0_clk_fsys0_slavebusclk", | |
| 858 | + GAT_FSYS0_BUS_D_FSYS0_IPCLKPORT_MAINCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 859 | + GATE(0, "fsys0_bus_d_fsys0_ipclkport_periclk", "dout_fsys0_peribus_grp", | |
| 860 | + GAT_FSYS0_BUS_D_FSYS0_IPCLKPORT_PERICLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 861 | + GATE(0, "fsys0_bus_p_fsys0_ipclkport_mainclk", "dout_fsys0_peribus_grp", | |
| 862 | + GAT_FSYS0_BUS_P_FSYS0_IPCLKPORT_MAINCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 863 | + GATE(0, "fsys0_bus_p_fsys0_ipclkport_tcuclk", "mout_fsys0_eqos_rgmii_125_mux1", | |
| 864 | + GAT_FSYS0_BUS_P_FSYS0_IPCLKPORT_TCUCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 865 | + GATE(0, "fsys0_cpe425_ipclkport_aclk", "mout_fsys0_clk_fsys0_slavebusclk", | |
| 866 | + GAT_FSYS0_CPE425_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 867 | + GATE(FSYS0_EQOS_TOP0_IPCLKPORT_ACLK_I, "fsys0_eqos_top0_ipclkport_aclk_i", | |
| 868 | + "dout_fsys0_peribus_grp", GAT_FSYS0_EQOS_TOP0_IPCLKPORT_ACLK_I, 21, | |
| 869 | + CLK_IGNORE_UNUSED, 0), | |
| 870 | + GATE(FSYS0_EQOS_TOP0_IPCLKPORT_HCLK_I, "fsys0_eqos_top0_ipclkport_hclk_i", | |
| 871 | + "dout_fsys0_peribus_grp", GAT_FSYS0_EQOS_TOP0_IPCLKPORT_HCLK_I, 21, | |
| 872 | + CLK_IGNORE_UNUSED, 0), | |
| 873 | + GATE(FSYS0_EQOS_TOP0_IPCLKPORT_RGMII_CLK_I, "fsys0_eqos_top0_ipclkport_rgmii_clk_i", | |
| 874 | + "dout_fsys0_eqs_rgmii_clk_125", GAT_FSYS0_EQOS_TOP0_IPCLKPORT_RGMII_CLK_I, 21, | |
| 875 | + CLK_IGNORE_UNUSED, 0), | |
| 876 | + GATE(0, "fsys0_eqos_top0_ipclkport_rii_clk_i", "dout_fsys0_eqos_rii_clk2o5", | |
| 877 | + GAT_FSYS0_EQOS_TOP0_IPCLKPORT_RII_CLK_I, 21, CLK_IGNORE_UNUSED, 0), | |
| 878 | + GATE(0, "fsys0_eqos_top0_ipclkport_rmii_clk_i", "dout_fsys0_eqos_rmiiclk_25", | |
| 879 | + GAT_FSYS0_EQOS_TOP0_IPCLKPORT_RMII_CLK_I, 21, CLK_IGNORE_UNUSED, 0), | |
| 880 | + GATE(0, "fsys0_gpio_fsys0_ipclkport_pclk", "dout_fsys0_peribus_grp", | |
| 881 | + GAT_FSYS0_GPIO_FSYS0_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 882 | + GATE(0, "fsys0_gpio_fsys0_ipclkport_oscclk", "fin_pll", | |
| 883 | + GAT_FSYS0_GPIO_FSYS0_IPCLKPORT_OSCCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 884 | + GATE(0, "fsys0_ns_brdg_fsys0_ipclkport_clk__psoc_fsys0__clk_fsys0_d", | |
| 885 | + "mout_fsys0_clk_fsys0_slavebusclk", | |
| 886 | + GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_D, 21, | |
| 887 | + CLK_IGNORE_UNUSED, 0), | |
| 888 | + GATE(0, "fsys0_ns_brdg_fsys0_ipclkport_clk__psoc_fsys0__clk_fsys0_d1", | |
| 889 | + "mout_fsys0_eqos_rgmii_125_mux1", | |
| 890 | + GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_D1, 21, | |
| 891 | + CLK_IGNORE_UNUSED, 0), | |
| 892 | + GATE(0, "fsys0_ns_brdg_fsys0_ipclkport_clk__psoc_fsys0__clk_fsys0_p", | |
| 893 | + "dout_fsys0_peribus_grp", | |
| 894 | + GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_P, 21, | |
| 895 | + CLK_IGNORE_UNUSED, 0), | |
| 896 | + GATE(0, "fsys0_ns_brdg_fsys0_ipclkport_clk__psoc_fsys0__clk_fsys0_s", | |
| 897 | + "mout_fsys0_clk_fsys0_slavebusclk", | |
| 898 | + GAT_FSYS0_NS_BRDG_FSYS0_IPCLKPORT_CLK__PSOC_FSYS0__CLK_FSYS0_S, 21, | |
| 899 | + CLK_IGNORE_UNUSED, 0), | |
| 900 | + GATE(0, "fsys0_pcie_top_ipclkport_pcieg3_phy_x4_inst_0_i_apb_pclk", | |
| 901 | + "dout_fsys0_peribus_grp", | |
| 902 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_PCIEG3_PHY_X4_INST_0_I_APB_PCLK, 21, | |
| 903 | + CLK_IGNORE_UNUSED, 0), | |
| 904 | + GATE(0, | |
| 905 | + "fsys0_pcie_top_ipclkport_pcieg3_phy_x4_inst_0_pll_refclk_from_syspll", | |
| 906 | + "dout_fsys0_pcie_phy_oscclk", | |
| 907 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_PCIEG3_PHY_X4_INST_0_PLL_REFCLK_FROM_SYSPLL, | |
| 908 | + 21, CLK_IGNORE_UNUSED, 0), | |
| 909 | + GATE(0, "fsys0_pcie_top_ipclkport_pipe_pal_inst_0_i_apb_pclk_0", "dout_fsys0_peribus_grp", | |
| 910 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_PIPE_PAL_INST_0_I_APB_PCLK_0, 21, CLK_IGNORE_UNUSED, 0), | |
| 911 | + GATE(0, "fsys0_pcie_top_ipclkport_pipe_pal_inst_0_i_immortal_clk", "fin_pll", | |
| 912 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_PIPE_PAL_INST_0_I_IMMORTAL_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 913 | + GATE(PCIE_SUBCTRL_INST0_DBI_ACLK_SOC, | |
| 914 | + "fsys0_pcie_top_ipclkport_fsd_pcie_sub_ctrl_inst_0_dbi_aclk_soc", | |
| 915 | + "dout_fsys0_peribus_grp", | |
| 916 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_DBI_ACLK_SOC, 21, | |
| 917 | + CLK_IGNORE_UNUSED, 0), | |
| 918 | + GATE(0, "fsys0_pcie_top_ipclkport_fsd_pcie_sub_ctrl_inst_0_i_driver_apb_clk", | |
| 919 | + "dout_fsys0_peribus_grp", | |
| 920 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK, 21, | |
| 921 | + CLK_IGNORE_UNUSED, 0), | |
| 922 | + GATE(PCIE_SUBCTRL_INST0_MSTR_ACLK_SOC, | |
| 923 | + "fsys0_pcie_top_ipclkport_fsd_pcie_sub_ctrl_inst_0_mstr_aclk_soc", | |
| 924 | + "mout_fsys0_clk_fsys0_slavebusclk", | |
| 925 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_MSTR_ACLK_SOC, 21, | |
| 926 | + CLK_IGNORE_UNUSED, 0), | |
| 927 | + GATE(PCIE_SUBCTRL_INST0_SLV_ACLK_SOC, | |
| 928 | + "fsys0_pcie_top_ipclkport_fsd_pcie_sub_ctrl_inst_0_slv_aclk_soc", | |
| 929 | + "mout_fsys0_clk_fsys0_slavebusclk", | |
| 930 | + GAT_FSYS0_PCIE_TOP_IPCLKPORT_FSD_PCIE_SUB_CTRL_INST_0_SLV_ACLK_SOC, 21, | |
| 931 | + CLK_IGNORE_UNUSED, 0), | |
| 932 | + GATE(0, "fsys0_smmu_fsys0_ipclkport_cclk", "mout_fsys0_eqos_rgmii_125_mux1", | |
| 933 | + GAT_FSYS0_SMMU_FSYS0_IPCLKPORT_CCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 934 | + GATE(0, "fsys0_smmu_fsys0_ipclkport_fsys0_bclk", "mout_fsys0_clk_fsys0_slavebusclk", | |
| 935 | + GAT_FSYS0_SMMU_FSYS0_IPCLKPORT_FSYS0_BCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 936 | + GATE(0, "fsys0_sysreg_fsys0_ipclkport_pclk", "dout_fsys0_peribus_grp", | |
| 937 | + GAT_FSYS0_SYSREG_FSYS0_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 938 | + GATE(UFS0_TOP0_HCLK_BUS, "fsys0_ufs_top0_ipclkport_hclk_bus", "dout_fsys0_peribus_grp", | |
| 939 | + GAT_FSYS0_UFS_TOP0_IPCLKPORT_HCLK_BUS, 21, CLK_IGNORE_UNUSED, 0), | |
| 940 | + GATE(UFS0_TOP0_ACLK, "fsys0_ufs_top0_ipclkport_i_aclk", "dout_fsys0_peribus_grp", | |
| 941 | + GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 942 | + GATE(UFS0_TOP0_CLK_UNIPRO, "fsys0_ufs_top0_ipclkport_i_clk_unipro", "dout_fsys0_clk_unipro", | |
| 943 | + GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_CLK_UNIPRO, 21, CLK_IGNORE_UNUSED, 0), | |
| 944 | + GATE(UFS0_TOP0_FMP_CLK, "fsys0_ufs_top0_ipclkport_i_fmp_clk", "dout_fsys0_peribus_grp", | |
| 945 | + GAT_FSYS0_UFS_TOP0_IPCLKPORT_I_FMP_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 946 | + GATE(UFS1_TOP1_HCLK_BUS, "fsys0_ufs_top1_ipclkport_hclk_bus", "dout_fsys0_peribus_grp", | |
| 947 | + GAT_FSYS0_UFS_TOP1_IPCLKPORT_HCLK_BUS, 21, CLK_IGNORE_UNUSED, 0), | |
| 948 | + GATE(UFS1_TOP1_ACLK, "fsys0_ufs_top1_ipclkport_i_aclk", "dout_fsys0_peribus_grp", | |
| 949 | + GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 950 | + GATE(UFS1_TOP1_CLK_UNIPRO, "fsys0_ufs_top1_ipclkport_i_clk_unipro", "dout_fsys0_clk_unipro", | |
| 951 | + GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_CLK_UNIPRO, 21, CLK_IGNORE_UNUSED, 0), | |
| 952 | + GATE(UFS1_TOP1_FMP_CLK, "fsys0_ufs_top1_ipclkport_i_fmp_clk", "dout_fsys0_peribus_grp", | |
| 953 | + GAT_FSYS0_UFS_TOP1_IPCLKPORT_I_FMP_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 954 | + GATE(0, "fsys0_rii_clk_divgate", "dout_fsys0_eqos_rmiiclk_25", GAT_FSYS0_RII_CLK_DIVGATE, | |
| 955 | + 21, CLK_IGNORE_UNUSED, 0), | |
| 956 | + GATE(FSYS0_EQOS_TOP0_IPCLKPORT_CLK_PTP_REF_I, "fsys0_eqos_top0_ipclkport_clk_ptp_ref_i", | |
| 957 | + "fin_pll", GAT_FSYS0_EQOS_TOP0_IPCLKPORT_CLK_PTP_REF_I, 21, CLK_IGNORE_UNUSED, 0), | |
| 958 | +}; | |
| 959 | + | |
| 960 | +static const struct samsung_cmu_info fsys0_cmu_info __initconst = { | |
| 961 | + .mux_clks = fsys0_mux_clks, | |
| 962 | + .nr_mux_clks = ARRAY_SIZE(fsys0_mux_clks), | |
| 963 | + .div_clks = fsys0_div_clks, | |
| 964 | + .nr_div_clks = ARRAY_SIZE(fsys0_div_clks), | |
| 965 | + .gate_clks = fsys0_gate_clks, | |
| 966 | + .nr_gate_clks = ARRAY_SIZE(fsys0_gate_clks), | |
| 967 | + .fixed_clks = fsys0_fixed_clks, | |
| 968 | + .nr_fixed_clks = ARRAY_SIZE(fsys0_fixed_clks), | |
| 969 | + .nr_clk_ids = FSYS0_NR_CLK, | |
| 970 | + .clk_regs = fsys0_clk_regs, | |
| 971 | + .nr_clk_regs = ARRAY_SIZE(fsys0_clk_regs), | |
| 972 | + .clk_name = "dout_cmu_fsys0_shared1div4", | |
| 973 | +}; | |
| 974 | + | |
| 975 | +/* Register Offset definitions for CMU_FSYS1 (0x16810000) */ | |
| 976 | +#define PLL_CON0_ACLK_FSYS1_BUSP_MUX 0x100 | |
| 977 | +#define PLL_CON0_PCLKL_FSYS1_BUSP_MUX 0x180 | |
| 978 | +#define DIV_CLK_FSYS1_PHY0_OSCCLK 0x1800 | |
| 979 | +#define DIV_CLK_FSYS1_PHY1_OSCCLK 0x1804 | |
| 980 | +#define GAT_FSYS1_CMU_FSYS1_IPCLKPORT_PCLK 0x2000 | |
| 981 | +#define GAT_FSYS1_PCIE_LINK0_IPCLKPORT_AUXCLK 0x2004 | |
| 982 | +#define GAT_FSYS1_PCIE_LINK0_IPCLKPORT_I_SOC_REF_CLK 0x2008 | |
| 983 | +#define GAT_FSYS1_PCIE_LINK1_IPCLKPORT_AUXCLK 0x200c | |
| 984 | +#define GAT_FSYS1_PCIE_PHY0_IPCLKPORT_I_REF_XTAL 0x202c | |
| 985 | +#define GAT_FSYS1_PHY0_OSCCLLK 0x2034 | |
| 986 | +#define GAT_FSYS1_PHY1_OSCCLK 0x2038 | |
| 987 | +#define GAT_FSYS1_AXI2APB_FSYS1_IPCLKPORT_ACLK 0x203c | |
| 988 | +#define GAT_FSYS1_BUS_D0_FSYS1_IPCLKPORT_MAINCLK 0x2040 | |
| 989 | +#define GAT_FSYS1_BUS_S0_FSYS1_IPCLKPORT_M250CLK 0x2048 | |
| 990 | +#define GAT_FSYS1_BUS_S0_FSYS1_IPCLKPORT_MAINCLK 0x204c | |
| 991 | +#define GAT_FSYS1_CPE425_0_FSYS1_IPCLKPORT_ACLK 0x2054 | |
| 992 | +#define GAT_FSYS1_NS_BRDG_FSYS1_IPCLKPORT_CLK__PSOC_FSYS1__CLK_FSYS1_D0 0x205c | |
| 993 | +#define GAT_FSYS1_NS_BRDG_FSYS1_IPCLKPORT_CLK__PSOC_FSYS1__CLK_FSYS1_S0 0x2064 | |
| 994 | +#define GAT_FSYS1_PCIE_LINK0_IPCLKPORT_DBI_ACLK 0x206c | |
| 995 | +#define GAT_FSYS1_PCIE_LINK0_IPCLKPORT_I_APB_CLK 0x2070 | |
| 996 | +#define GAT_FSYS1_PCIE_LINK0_IPCLKPORT_I_DRIVER_APB_CLK 0x2074 | |
| 997 | +#define GAT_FSYS1_PCIE_LINK0_IPCLKPORT_MSTR_ACLK 0x2078 | |
| 998 | +#define GAT_FSYS1_PCIE_LINK0_IPCLKPORT_SLV_ACLK 0x207c | |
| 999 | +#define GAT_FSYS1_PCIE_LINK1_IPCLKPORT_DBI_ACLK 0x2080 | |
| 1000 | +#define GAT_FSYS1_PCIE_LINK1_IPCLKPORT_I_DRIVER_APB_CLK 0x2084 | |
| 1001 | +#define GAT_FSYS1_PCIE_LINK1_IPCLKPORT_MSTR_ACLK 0x2088 | |
| 1002 | +#define GAT_FSYS1_PCIE_LINK1_IPCLKPORT_SLV_ACLK 0x208c | |
| 1003 | +#define GAT_FSYS1_PCIE_PHY0_IPCLKPORT_I_APB_CLK 0x20a4 | |
| 1004 | +#define GAT_FSYS1_PCIE_PHY0_IPCLKPORT_I_REF_SOC_PLL 0x20a8 | |
| 1005 | +#define GAT_FSYS1_SYSREG_FSYS1_IPCLKPORT_PCLK 0x20b4 | |
| 1006 | +#define GAT_FSYS1_TBU0_FSYS1_IPCLKPORT_ACLK 0x20b8 | |
| 1007 | + | |
| 1008 | +static const unsigned long fsys1_clk_regs[] __initconst = { | |
| 1009 | + PLL_CON0_ACLK_FSYS1_BUSP_MUX, | |
| 1010 | + PLL_CON0_PCLKL_FSYS1_BUSP_MUX, | |
| 1011 | + DIV_CLK_FSYS1_PHY0_OSCCLK, | |
| 1012 | + DIV_CLK_FSYS1_PHY1_OSCCLK, | |
| 1013 | + GAT_FSYS1_CMU_FSYS1_IPCLKPORT_PCLK, | |
| 1014 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_AUXCLK, | |
| 1015 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_I_SOC_REF_CLK, | |
| 1016 | + GAT_FSYS1_PCIE_LINK1_IPCLKPORT_AUXCLK, | |
| 1017 | + GAT_FSYS1_PCIE_PHY0_IPCLKPORT_I_REF_XTAL, | |
| 1018 | + GAT_FSYS1_PHY0_OSCCLLK, | |
| 1019 | + GAT_FSYS1_PHY1_OSCCLK, | |
| 1020 | + GAT_FSYS1_AXI2APB_FSYS1_IPCLKPORT_ACLK, | |
| 1021 | + GAT_FSYS1_BUS_D0_FSYS1_IPCLKPORT_MAINCLK, | |
| 1022 | + GAT_FSYS1_BUS_S0_FSYS1_IPCLKPORT_M250CLK, | |
| 1023 | + GAT_FSYS1_BUS_S0_FSYS1_IPCLKPORT_MAINCLK, | |
| 1024 | + GAT_FSYS1_CPE425_0_FSYS1_IPCLKPORT_ACLK, | |
| 1025 | + GAT_FSYS1_NS_BRDG_FSYS1_IPCLKPORT_CLK__PSOC_FSYS1__CLK_FSYS1_D0, | |
| 1026 | + GAT_FSYS1_NS_BRDG_FSYS1_IPCLKPORT_CLK__PSOC_FSYS1__CLK_FSYS1_S0, | |
| 1027 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_DBI_ACLK, | |
| 1028 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_I_APB_CLK, | |
| 1029 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_I_DRIVER_APB_CLK, | |
| 1030 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_MSTR_ACLK, | |
| 1031 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_SLV_ACLK, | |
| 1032 | + GAT_FSYS1_PCIE_LINK1_IPCLKPORT_DBI_ACLK, | |
| 1033 | + GAT_FSYS1_PCIE_LINK1_IPCLKPORT_I_DRIVER_APB_CLK, | |
| 1034 | + GAT_FSYS1_PCIE_LINK1_IPCLKPORT_MSTR_ACLK, | |
| 1035 | + GAT_FSYS1_PCIE_LINK1_IPCLKPORT_SLV_ACLK, | |
| 1036 | + GAT_FSYS1_PCIE_PHY0_IPCLKPORT_I_APB_CLK, | |
| 1037 | + GAT_FSYS1_PCIE_PHY0_IPCLKPORT_I_REF_SOC_PLL, | |
| 1038 | + GAT_FSYS1_SYSREG_FSYS1_IPCLKPORT_PCLK, | |
| 1039 | + GAT_FSYS1_TBU0_FSYS1_IPCLKPORT_ACLK, | |
| 1040 | +}; | |
| 1041 | + | |
| 1042 | +static const struct samsung_fixed_rate_clock fsys1_fixed_clks[] __initconst = { | |
| 1043 | + FRATE(0, "clk_fsys1_phy0_ref", NULL, 0, 100000000), | |
| 1044 | + FRATE(0, "clk_fsys1_phy1_ref", NULL, 0, 100000000), | |
| 1045 | +}; | |
| 1046 | + | |
| 1047 | +/* List of parent clocks for Muxes in CMU_FSYS1 */ | |
| 1048 | +PNAME(mout_fsys1_pclkl_fsys1_busp_mux_p) = { "fin_pll", "dout_cmu_fsys1_shared0div8" }; | |
| 1049 | +PNAME(mout_fsys1_aclk_fsys1_busp_mux_p) = { "fin_pll", "dout_cmu_fsys1_shared0div4" }; | |
| 1050 | + | |
| 1051 | +static const struct samsung_mux_clock fsys1_mux_clks[] __initconst = { | |
| 1052 | + MUX(0, "mout_fsys1_pclkl_fsys1_busp_mux", mout_fsys1_pclkl_fsys1_busp_mux_p, | |
| 1053 | + PLL_CON0_PCLKL_FSYS1_BUSP_MUX, 4, 1), | |
| 1054 | + MUX(0, "mout_fsys1_aclk_fsys1_busp_mux", mout_fsys1_aclk_fsys1_busp_mux_p, | |
| 1055 | + PLL_CON0_ACLK_FSYS1_BUSP_MUX, 4, 1), | |
| 1056 | +}; | |
| 1057 | + | |
| 1058 | +static const struct samsung_div_clock fsys1_div_clks[] __initconst = { | |
| 1059 | + DIV(0, "dout_fsys1_clk_fsys1_phy0_oscclk", "fsys1_phy0_osccllk", | |
| 1060 | + DIV_CLK_FSYS1_PHY0_OSCCLK, 0, 4), | |
| 1061 | + DIV(0, "dout_fsys1_clk_fsys1_phy1_oscclk", "fsys1_phy1_oscclk", | |
| 1062 | + DIV_CLK_FSYS1_PHY1_OSCCLK, 0, 4), | |
| 1063 | +}; | |
| 1064 | + | |
| 1065 | +static const struct samsung_gate_clock fsys1_gate_clks[] __initconst = { | |
| 1066 | + GATE(0, "fsys1_cmu_fsys1_ipclkport_pclk", "mout_fsys1_pclkl_fsys1_busp_mux", | |
| 1067 | + GAT_FSYS1_CMU_FSYS1_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1068 | + GATE(0, "fsys1_pcie_phy0_ipclkport_i_ref_xtal", "clk_fsys1_phy0_ref", | |
| 1069 | + GAT_FSYS1_PCIE_PHY0_IPCLKPORT_I_REF_XTAL, 21, CLK_IGNORE_UNUSED, 0), | |
| 1070 | + GATE(0, "fsys1_phy0_osccllk", "mout_fsys1_aclk_fsys1_busp_mux", | |
| 1071 | + GAT_FSYS1_PHY0_OSCCLLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1072 | + GATE(0, "fsys1_phy1_oscclk", "mout_fsys1_aclk_fsys1_busp_mux", | |
| 1073 | + GAT_FSYS1_PHY1_OSCCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1074 | + GATE(0, "fsys1_axi2apb_fsys1_ipclkport_aclk", "mout_fsys1_pclkl_fsys1_busp_mux", | |
| 1075 | + GAT_FSYS1_AXI2APB_FSYS1_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1076 | + GATE(0, "fsys1_bus_d0_fsys1_ipclkport_mainclk", "mout_fsys1_aclk_fsys1_busp_mux", | |
| 1077 | + GAT_FSYS1_BUS_D0_FSYS1_IPCLKPORT_MAINCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1078 | + GATE(0, "fsys1_bus_s0_fsys1_ipclkport_m250clk", "mout_fsys1_pclkl_fsys1_busp_mux", | |
| 1079 | + GAT_FSYS1_BUS_S0_FSYS1_IPCLKPORT_M250CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1080 | + GATE(0, "fsys1_bus_s0_fsys1_ipclkport_mainclk", "mout_fsys1_aclk_fsys1_busp_mux", | |
| 1081 | + GAT_FSYS1_BUS_S0_FSYS1_IPCLKPORT_MAINCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1082 | + GATE(0, "fsys1_cpe425_0_fsys1_ipclkport_aclk", "mout_fsys1_aclk_fsys1_busp_mux", | |
| 1083 | + GAT_FSYS1_CPE425_0_FSYS1_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1084 | + GATE(0, "fsys1_ns_brdg_fsys1_ipclkport_clk__psoc_fsys1__clk_fsys1_d0", | |
| 1085 | + "mout_fsys1_aclk_fsys1_busp_mux", | |
| 1086 | + GAT_FSYS1_NS_BRDG_FSYS1_IPCLKPORT_CLK__PSOC_FSYS1__CLK_FSYS1_D0, 21, | |
| 1087 | + CLK_IGNORE_UNUSED, 0), | |
| 1088 | + GATE(0, "fsys1_ns_brdg_fsys1_ipclkport_clk__psoc_fsys1__clk_fsys1_s0", | |
| 1089 | + "mout_fsys1_aclk_fsys1_busp_mux", | |
| 1090 | + GAT_FSYS1_NS_BRDG_FSYS1_IPCLKPORT_CLK__PSOC_FSYS1__CLK_FSYS1_S0, 21, | |
| 1091 | + CLK_IGNORE_UNUSED, 0), | |
| 1092 | + GATE(PCIE_LINK0_IPCLKPORT_DBI_ACLK, "fsys1_pcie_link0_ipclkport_dbi_aclk", | |
| 1093 | + "mout_fsys1_aclk_fsys1_busp_mux", GAT_FSYS1_PCIE_LINK0_IPCLKPORT_DBI_ACLK, 21, | |
| 1094 | + CLK_IGNORE_UNUSED, 0), | |
| 1095 | + GATE(0, "fsys1_pcie_link0_ipclkport_i_apb_clk", "mout_fsys1_pclkl_fsys1_busp_mux", | |
| 1096 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_I_APB_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1097 | + GATE(0, "fsys1_pcie_link0_ipclkport_i_soc_ref_clk", "fin_pll", | |
| 1098 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_I_SOC_REF_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1099 | + GATE(0, "fsys1_pcie_link0_ipclkport_i_driver_apb_clk", "mout_fsys1_pclkl_fsys1_busp_mux", | |
| 1100 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_I_DRIVER_APB_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1101 | + GATE(PCIE_LINK0_IPCLKPORT_MSTR_ACLK, "fsys1_pcie_link0_ipclkport_mstr_aclk", | |
| 1102 | + "mout_fsys1_aclk_fsys1_busp_mux", GAT_FSYS1_PCIE_LINK0_IPCLKPORT_MSTR_ACLK, 21, | |
| 1103 | + CLK_IGNORE_UNUSED, 0), | |
| 1104 | + GATE(PCIE_LINK0_IPCLKPORT_SLV_ACLK, "fsys1_pcie_link0_ipclkport_slv_aclk", | |
| 1105 | + "mout_fsys1_aclk_fsys1_busp_mux", GAT_FSYS1_PCIE_LINK0_IPCLKPORT_SLV_ACLK, 21, | |
| 1106 | + CLK_IGNORE_UNUSED, 0), | |
| 1107 | + GATE(PCIE_LINK1_IPCLKPORT_DBI_ACLK, "fsys1_pcie_link1_ipclkport_dbi_aclk", | |
| 1108 | + "mout_fsys1_aclk_fsys1_busp_mux", GAT_FSYS1_PCIE_LINK1_IPCLKPORT_DBI_ACLK, 21, | |
| 1109 | + CLK_IGNORE_UNUSED, 0), | |
| 1110 | + GATE(0, "fsys1_pcie_link1_ipclkport_i_driver_apb_clk", "mout_fsys1_pclkl_fsys1_busp_mux", | |
| 1111 | + GAT_FSYS1_PCIE_LINK1_IPCLKPORT_I_DRIVER_APB_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1112 | + GATE(PCIE_LINK1_IPCLKPORT_MSTR_ACLK, "fsys1_pcie_link1_ipclkport_mstr_aclk", | |
| 1113 | + "mout_fsys1_aclk_fsys1_busp_mux", GAT_FSYS1_PCIE_LINK1_IPCLKPORT_MSTR_ACLK, 21, | |
| 1114 | + CLK_IGNORE_UNUSED, 0), | |
| 1115 | + GATE(PCIE_LINK1_IPCLKPORT_SLV_ACLK, "fsys1_pcie_link1_ipclkport_slv_aclk", | |
| 1116 | + "mout_fsys1_aclk_fsys1_busp_mux", GAT_FSYS1_PCIE_LINK1_IPCLKPORT_SLV_ACLK, 21, | |
| 1117 | + CLK_IGNORE_UNUSED, 0), | |
| 1118 | + GATE(0, "fsys1_pcie_phy0_ipclkport_i_apb_clk", "mout_fsys1_pclkl_fsys1_busp_mux", | |
| 1119 | + GAT_FSYS1_PCIE_PHY0_IPCLKPORT_I_APB_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1120 | + GATE(PCIE_LINK0_IPCLKPORT_AUX_ACLK, "fsys1_pcie_link0_ipclkport_auxclk", "fin_pll", | |
| 1121 | + GAT_FSYS1_PCIE_LINK0_IPCLKPORT_AUXCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1122 | + GATE(PCIE_LINK1_IPCLKPORT_AUX_ACLK, "fsys1_pcie_link1_ipclkport_auxclk", "fin_pll", | |
| 1123 | + GAT_FSYS1_PCIE_LINK1_IPCLKPORT_AUXCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1124 | + GATE(0, "fsys1_pcie_phy0_ipclkport_i_ref_soc_pll", "dout_fsys1_clk_fsys1_phy0_oscclk", | |
| 1125 | + GAT_FSYS1_PCIE_PHY0_IPCLKPORT_I_REF_SOC_PLL, 21, CLK_IGNORE_UNUSED, 0), | |
| 1126 | + GATE(0, "fsys1_sysreg_fsys1_ipclkport_pclk", "mout_fsys1_pclkl_fsys1_busp_mux", | |
| 1127 | + GAT_FSYS1_SYSREG_FSYS1_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1128 | + GATE(0, "fsys1_tbu0_fsys1_ipclkport_aclk", "mout_fsys1_aclk_fsys1_busp_mux", | |
| 1129 | + GAT_FSYS1_TBU0_FSYS1_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1130 | +}; | |
| 1131 | + | |
| 1132 | +static const struct samsung_cmu_info fsys1_cmu_info __initconst = { | |
| 1133 | + .mux_clks = fsys1_mux_clks, | |
| 1134 | + .nr_mux_clks = ARRAY_SIZE(fsys1_mux_clks), | |
| 1135 | + .div_clks = fsys1_div_clks, | |
| 1136 | + .nr_div_clks = ARRAY_SIZE(fsys1_div_clks), | |
| 1137 | + .gate_clks = fsys1_gate_clks, | |
| 1138 | + .nr_gate_clks = ARRAY_SIZE(fsys1_gate_clks), | |
| 1139 | + .fixed_clks = fsys1_fixed_clks, | |
| 1140 | + .nr_fixed_clks = ARRAY_SIZE(fsys1_fixed_clks), | |
| 1141 | + .nr_clk_ids = FSYS1_NR_CLK, | |
| 1142 | + .clk_regs = fsys1_clk_regs, | |
| 1143 | + .nr_clk_regs = ARRAY_SIZE(fsys1_clk_regs), | |
| 1144 | + .clk_name = "dout_cmu_fsys1_shared0div4", | |
| 1145 | +}; | |
| 1146 | + | |
| 1147 | +/* Register Offset definitions for CMU_IMEM (0x10010000) */ | |
| 1148 | +#define PLL_CON0_CLK_IMEM_ACLK 0x100 | |
| 1149 | +#define PLL_CON0_CLK_IMEM_INTMEMCLK 0x120 | |
| 1150 | +#define PLL_CON0_CLK_IMEM_TCUCLK 0x140 | |
| 1151 | +#define DIV_OSCCLK_IMEM_TMUTSCLK 0x1800 | |
| 1152 | +#define GAT_IMEM_IMEM_CMU_IMEM_IPCLKPORT_PCLK 0x2000 | |
| 1153 | +#define GAT_IMEM_MCT_IPCLKPORT_OSCCLK__ALO 0x2004 | |
| 1154 | +#define GAT_IMEM_OTP_CON_TOP_IPCLKPORT_I_OSCCLK 0x2008 | |
| 1155 | +#define GAT_IMEM_RSTNSYNC_OSCCLK_IPCLKPORT_CLK 0x200c | |
| 1156 | +#define GAT_IMEM_TMU_CPU0_IPCLKPORT_I_CLK 0x2010 | |
| 1157 | +#define GAT_IMEM_TMU_CPU0_IPCLKPORT_I_CLK_TS 0x2014 | |
| 1158 | +#define GAT_IMEM_TMU_CPU2_IPCLKPORT_I_CLK 0x2018 | |
| 1159 | +#define GAT_IMEM_TMU_CPU2_IPCLKPORT_I_CLK_TS 0x201c | |
| 1160 | +#define GAT_IMEM_TMU_GPU_IPCLKPORT_I_CLK 0x2020 | |
| 1161 | +#define GAT_IMEM_TMU_GPU_IPCLKPORT_I_CLK_TS 0x2024 | |
| 1162 | +#define GAT_IMEM_TMU_GT_IPCLKPORT_I_CLK 0x2028 | |
| 1163 | +#define GAT_IMEM_TMU_GT_IPCLKPORT_I_CLK_TS 0x202c | |
| 1164 | +#define GAT_IMEM_TMU_TOP_IPCLKPORT_I_CLK 0x2030 | |
| 1165 | +#define GAT_IMEM_TMU_TOP_IPCLKPORT_I_CLK_TS 0x2034 | |
| 1166 | +#define GAT_IMEM_WDT0_IPCLKPORT_CLK 0x2038 | |
| 1167 | +#define GAT_IMEM_WDT1_IPCLKPORT_CLK 0x203c | |
| 1168 | +#define GAT_IMEM_WDT2_IPCLKPORT_CLK 0x2040 | |
| 1169 | +#define GAT_IMEM_ADM_AXI4ST_I0_IMEM_IPCLKPORT_ACLKM 0x2044 | |
| 1170 | +#define GAT_IMEM_ADM_AXI4ST_I1_IMEM_IPCLKPORT_ACLKM 0x2048 | |
| 1171 | +#define GAT_IMEM_ADM_AXI4ST_I2_IMEM_IPCLKPORT_ACLKM 0x204c | |
| 1172 | +#define GAT_IMEM_ADS_AXI4ST_I0_IMEM_IPCLKPORT_ACLKS 0x2050 | |
| 1173 | +#define GAT_IMEM_ADS_AXI4ST_I1_IMEM_IPCLKPORT_ACLKS 0x2054 | |
| 1174 | +#define GAT_IMEM_ADS_AXI4ST_I2_IMEM_IPCLKPORT_ACLKS 0x2058 | |
| 1175 | +#define GAT_IMEM_ASYNC_DMA0_IPCLKPORT_PCLKM 0x205c | |
| 1176 | +#define GAT_IMEM_ASYNC_DMA0_IPCLKPORT_PCLKS 0x2060 | |
| 1177 | +#define GAT_IMEM_ASYNC_DMA1_IPCLKPORT_PCLKM 0x2064 | |
| 1178 | +#define GAT_IMEM_ASYNC_DMA1_IPCLKPORT_PCLKS 0x2068 | |
| 1179 | +#define GAT_IMEM_AXI2APB_IMEMP0_IPCLKPORT_ACLK 0x206c | |
| 1180 | +#define GAT_IMEM_AXI2APB_IMEMP1_IPCLKPORT_ACLK 0x2070 | |
| 1181 | +#define GAT_IMEM_BUS_D_IMEM_IPCLKPORT_MAINCLK 0x2074 | |
| 1182 | +#define GAT_IMEM_BUS_P_IMEM_IPCLKPORT_MAINCLK 0x2078 | |
| 1183 | +#define GAT_IMEM_BUS_P_IMEM_IPCLKPORT_PERICLK 0x207c | |
| 1184 | +#define GAT_IMEM_BUS_P_IMEM_IPCLKPORT_TCUCLK 0x2080 | |
| 1185 | +#define GAT_IMEM_DMA0_IPCLKPORT_ACLK 0x2084 | |
| 1186 | +#define GAT_IMEM_DMA1_IPCLKPORT_ACLK 0x2088 | |
| 1187 | +#define GAT_IMEM_GIC500_INPUT_SYNC_IPCLKPORT_CLK 0x208c | |
| 1188 | +#define GAT_IMEM_GIC_IPCLKPORT_CLK 0x2090 | |
| 1189 | +#define GAT_IMEM_INTMEM_IPCLKPORT_ACLK 0x2094 | |
| 1190 | +#define GAT_IMEM_MAILBOX_SCS_CA72_IPCLKPORT_PCLK 0x2098 | |
| 1191 | +#define GAT_IMEM_MAILBOX_SMS_CA72_IPCLKPORT_PCLK 0x209c | |
| 1192 | +#define GAT_IMEM_MCT_IPCLKPORT_PCLK 0x20a0 | |
| 1193 | +#define GAT_IMEM_NS_BRDG_IMEM_IPCLKPORT_CLK__PSCO_IMEM__CLK_IMEM_D 0x20a4 | |
| 1194 | +#define GAT_IMEM_NS_BRDG_IMEM_IPCLKPORT_CLK__PSCO_IMEM__CLK_IMEM_TCU 0x20a8 | |
| 1195 | +#define GAT_IMEM_NS_BRDG_IMEM_IPCLKPORT_CLK__PSOC_IMEM__CLK_IMEM_P 0x20ac | |
| 1196 | +#define GAT_IMEM_OTP_CON_TOP_IPCLKPORT_PCLK 0x20b0 | |
| 1197 | +#define GAT_IMEM_RSTNSYNC_ACLK_IPCLKPORT_CLK 0x20b4 | |
| 1198 | +#define GAT_IMEM_RSTNSYNC_INTMEMCLK_IPCLKPORT_CLK 0x20b8 | |
| 1199 | +#define GAT_IMEM_RSTNSYNC_TCUCLK_IPCLKPORT_CLK 0x20bc | |
| 1200 | +#define GAT_IMEM_SFRIF_TMU0_IMEM_IPCLKPORT_PCLK 0x20c0 | |
| 1201 | +#define GAT_IMEM_SFRIF_TMU1_IMEM_IPCLKPORT_PCLK 0x20c4 | |
| 1202 | +#define GAT_IMEM_SYSREG_IMEM_IPCLKPORT_PCLK 0x20c8 | |
| 1203 | +#define GAT_IMEM_TBU_IMEM_IPCLKPORT_ACLK 0x20cc | |
| 1204 | +#define GAT_IMEM_TCU_IPCLKPORT_ACLK 0x20d0 | |
| 1205 | +#define GAT_IMEM_WDT0_IPCLKPORT_PCLK 0x20d4 | |
| 1206 | +#define GAT_IMEM_WDT1_IPCLKPORT_PCLK 0x20d8 | |
| 1207 | +#define GAT_IMEM_WDT2_IPCLKPORT_PCLK 0x20dc | |
| 1208 | + | |
| 1209 | +static const unsigned long imem_clk_regs[] __initconst = { | |
| 1210 | + PLL_CON0_CLK_IMEM_ACLK, | |
| 1211 | + PLL_CON0_CLK_IMEM_INTMEMCLK, | |
| 1212 | + PLL_CON0_CLK_IMEM_TCUCLK, | |
| 1213 | + DIV_OSCCLK_IMEM_TMUTSCLK, | |
| 1214 | + GAT_IMEM_IMEM_CMU_IMEM_IPCLKPORT_PCLK, | |
| 1215 | + GAT_IMEM_MCT_IPCLKPORT_OSCCLK__ALO, | |
| 1216 | + GAT_IMEM_OTP_CON_TOP_IPCLKPORT_I_OSCCLK, | |
| 1217 | + GAT_IMEM_RSTNSYNC_OSCCLK_IPCLKPORT_CLK, | |
| 1218 | + GAT_IMEM_TMU_CPU0_IPCLKPORT_I_CLK, | |
| 1219 | + GAT_IMEM_TMU_CPU0_IPCLKPORT_I_CLK_TS, | |
| 1220 | + GAT_IMEM_TMU_CPU2_IPCLKPORT_I_CLK, | |
| 1221 | + GAT_IMEM_TMU_CPU2_IPCLKPORT_I_CLK_TS, | |
| 1222 | + GAT_IMEM_TMU_GPU_IPCLKPORT_I_CLK, | |
| 1223 | + GAT_IMEM_TMU_GPU_IPCLKPORT_I_CLK_TS, | |
| 1224 | + GAT_IMEM_TMU_GT_IPCLKPORT_I_CLK, | |
| 1225 | + GAT_IMEM_TMU_GT_IPCLKPORT_I_CLK_TS, | |
| 1226 | + GAT_IMEM_TMU_TOP_IPCLKPORT_I_CLK, | |
| 1227 | + GAT_IMEM_TMU_TOP_IPCLKPORT_I_CLK_TS, | |
| 1228 | + GAT_IMEM_WDT0_IPCLKPORT_CLK, | |
| 1229 | + GAT_IMEM_WDT1_IPCLKPORT_CLK, | |
| 1230 | + GAT_IMEM_WDT2_IPCLKPORT_CLK, | |
| 1231 | + GAT_IMEM_ADM_AXI4ST_I0_IMEM_IPCLKPORT_ACLKM, | |
| 1232 | + GAT_IMEM_ADM_AXI4ST_I1_IMEM_IPCLKPORT_ACLKM, | |
| 1233 | + GAT_IMEM_ADM_AXI4ST_I2_IMEM_IPCLKPORT_ACLKM, | |
| 1234 | + GAT_IMEM_ADS_AXI4ST_I0_IMEM_IPCLKPORT_ACLKS, | |
| 1235 | + GAT_IMEM_ADS_AXI4ST_I1_IMEM_IPCLKPORT_ACLKS, | |
| 1236 | + GAT_IMEM_ADS_AXI4ST_I2_IMEM_IPCLKPORT_ACLKS, | |
| 1237 | + GAT_IMEM_ASYNC_DMA0_IPCLKPORT_PCLKM, | |
| 1238 | + GAT_IMEM_ASYNC_DMA0_IPCLKPORT_PCLKS, | |
| 1239 | + GAT_IMEM_ASYNC_DMA1_IPCLKPORT_PCLKM, | |
| 1240 | + GAT_IMEM_ASYNC_DMA1_IPCLKPORT_PCLKS, | |
| 1241 | + GAT_IMEM_AXI2APB_IMEMP0_IPCLKPORT_ACLK, | |
| 1242 | + GAT_IMEM_AXI2APB_IMEMP1_IPCLKPORT_ACLK, | |
| 1243 | + GAT_IMEM_BUS_D_IMEM_IPCLKPORT_MAINCLK, | |
| 1244 | + GAT_IMEM_BUS_P_IMEM_IPCLKPORT_MAINCLK, | |
| 1245 | + GAT_IMEM_BUS_P_IMEM_IPCLKPORT_PERICLK, | |
| 1246 | + GAT_IMEM_BUS_P_IMEM_IPCLKPORT_TCUCLK, | |
| 1247 | + GAT_IMEM_DMA0_IPCLKPORT_ACLK, | |
| 1248 | + GAT_IMEM_DMA1_IPCLKPORT_ACLK, | |
| 1249 | + GAT_IMEM_GIC500_INPUT_SYNC_IPCLKPORT_CLK, | |
| 1250 | + GAT_IMEM_GIC_IPCLKPORT_CLK, | |
| 1251 | + GAT_IMEM_INTMEM_IPCLKPORT_ACLK, | |
| 1252 | + GAT_IMEM_MAILBOX_SCS_CA72_IPCLKPORT_PCLK, | |
| 1253 | + GAT_IMEM_MAILBOX_SMS_CA72_IPCLKPORT_PCLK, | |
| 1254 | + GAT_IMEM_MCT_IPCLKPORT_PCLK, | |
| 1255 | + GAT_IMEM_NS_BRDG_IMEM_IPCLKPORT_CLK__PSCO_IMEM__CLK_IMEM_D, | |
| 1256 | + GAT_IMEM_NS_BRDG_IMEM_IPCLKPORT_CLK__PSCO_IMEM__CLK_IMEM_TCU, | |
| 1257 | + GAT_IMEM_NS_BRDG_IMEM_IPCLKPORT_CLK__PSOC_IMEM__CLK_IMEM_P, | |
| 1258 | + GAT_IMEM_OTP_CON_TOP_IPCLKPORT_PCLK, | |
| 1259 | + GAT_IMEM_RSTNSYNC_ACLK_IPCLKPORT_CLK, | |
| 1260 | + GAT_IMEM_RSTNSYNC_INTMEMCLK_IPCLKPORT_CLK, | |
| 1261 | + GAT_IMEM_RSTNSYNC_TCUCLK_IPCLKPORT_CLK, | |
| 1262 | + GAT_IMEM_SFRIF_TMU0_IMEM_IPCLKPORT_PCLK, | |
| 1263 | + GAT_IMEM_SFRIF_TMU1_IMEM_IPCLKPORT_PCLK, | |
| 1264 | + GAT_IMEM_SYSREG_IMEM_IPCLKPORT_PCLK, | |
| 1265 | + GAT_IMEM_TBU_IMEM_IPCLKPORT_ACLK, | |
| 1266 | + GAT_IMEM_TCU_IPCLKPORT_ACLK, | |
| 1267 | + GAT_IMEM_WDT0_IPCLKPORT_PCLK, | |
| 1268 | + GAT_IMEM_WDT1_IPCLKPORT_PCLK, | |
| 1269 | + GAT_IMEM_WDT2_IPCLKPORT_PCLK, | |
| 1270 | +}; | |
| 1271 | + | |
| 1272 | +PNAME(mout_imem_clk_imem_tcuclk_p) = { "fin_pll", "dout_cmu_imem_tcuclk" }; | |
| 1273 | +PNAME(mout_imem_clk_imem_aclk_p) = { "fin_pll", "dout_cmu_imem_aclk" }; | |
| 1274 | +PNAME(mout_imem_clk_imem_intmemclk_p) = { "fin_pll", "dout_cmu_imem_dmaclk" }; | |
| 1275 | + | |
| 1276 | +static const struct samsung_mux_clock imem_mux_clks[] __initconst = { | |
| 1277 | + MUX(0, "mout_imem_clk_imem_tcuclk", mout_imem_clk_imem_tcuclk_p, | |
| 1278 | + PLL_CON0_CLK_IMEM_TCUCLK, 4, 1), | |
| 1279 | + MUX(0, "mout_imem_clk_imem_aclk", mout_imem_clk_imem_aclk_p, PLL_CON0_CLK_IMEM_ACLK, 4, 1), | |
| 1280 | + MUX(0, "mout_imem_clk_imem_intmemclk", mout_imem_clk_imem_intmemclk_p, | |
| 1281 | + PLL_CON0_CLK_IMEM_INTMEMCLK, 4, 1), | |
| 1282 | +}; | |
| 1283 | + | |
| 1284 | +static const struct samsung_div_clock imem_div_clks[] __initconst = { | |
| 1285 | + DIV(0, "dout_imem_oscclk_imem_tmutsclk", "fin_pll", DIV_OSCCLK_IMEM_TMUTSCLK, 0, 4), | |
| 1286 | +}; | |
| 1287 | + | |
| 1288 | +static const struct samsung_gate_clock imem_gate_clks[] __initconst = { | |
| 1289 | + GATE(0, "imem_imem_cmu_imem_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1290 | + GAT_IMEM_IMEM_CMU_IMEM_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1291 | + GATE(0, "imem_otp_con_top_ipclkport_i_oscclk", "fin_pll", | |
| 1292 | + GAT_IMEM_OTP_CON_TOP_IPCLKPORT_I_OSCCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1293 | + GATE(0, "imem_tmu_top_ipclkport_i_clk", "fin_pll", | |
| 1294 | + GAT_IMEM_TMU_TOP_IPCLKPORT_I_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1295 | + GATE(0, "imem_tmu_gt_ipclkport_i_clk", "fin_pll", | |
| 1296 | + GAT_IMEM_TMU_GT_IPCLKPORT_I_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1297 | + GATE(0, "imem_tmu_cpu0_ipclkport_i_clk", "fin_pll", | |
| 1298 | + GAT_IMEM_TMU_CPU0_IPCLKPORT_I_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1299 | + GATE(0, "imem_tmu_gpu_ipclkport_i_clk", "fin_pll", | |
| 1300 | + GAT_IMEM_TMU_GPU_IPCLKPORT_I_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1301 | + GATE(0, "imem_mct_ipclkport_oscclk__alo", "fin_pll", | |
| 1302 | + GAT_IMEM_MCT_IPCLKPORT_OSCCLK__ALO, 21, CLK_IGNORE_UNUSED, 0), | |
| 1303 | + GATE(0, "imem_wdt0_ipclkport_clk", "fin_pll", | |
| 1304 | + GAT_IMEM_WDT0_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1305 | + GATE(0, "imem_wdt1_ipclkport_clk", "fin_pll", | |
| 1306 | + GAT_IMEM_WDT1_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1307 | + GATE(0, "imem_wdt2_ipclkport_clk", "fin_pll", | |
| 1308 | + GAT_IMEM_WDT2_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1309 | + GATE(IMEM_TMU_CPU0_IPCLKPORT_I_CLK_TS, "imem_tmu_cpu0_ipclkport_i_clk_ts", | |
| 1310 | + "dout_imem_oscclk_imem_tmutsclk", | |
| 1311 | + GAT_IMEM_TMU_CPU0_IPCLKPORT_I_CLK_TS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1312 | + GATE(IMEM_TMU_CPU2_IPCLKPORT_I_CLK_TS, "imem_tmu_cpu2_ipclkport_i_clk_ts", | |
| 1313 | + "dout_imem_oscclk_imem_tmutsclk", | |
| 1314 | + GAT_IMEM_TMU_CPU2_IPCLKPORT_I_CLK_TS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1315 | + GATE(IMEM_TMU_GPU_IPCLKPORT_I_CLK_TS, "imem_tmu_gpu_ipclkport_i_clk_ts", | |
| 1316 | + "dout_imem_oscclk_imem_tmutsclk", | |
| 1317 | + GAT_IMEM_TMU_GPU_IPCLKPORT_I_CLK_TS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1318 | + GATE(IMEM_TMU_GT_IPCLKPORT_I_CLK_TS, "imem_tmu_gt_ipclkport_i_clk_ts", | |
| 1319 | + "dout_imem_oscclk_imem_tmutsclk", | |
| 1320 | + GAT_IMEM_TMU_GT_IPCLKPORT_I_CLK_TS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1321 | + GATE(IMEM_TMU_TOP_IPCLKPORT_I_CLK_TS, "imem_tmu_top_ipclkport_i_clk_ts", | |
| 1322 | + "dout_imem_oscclk_imem_tmutsclk", | |
| 1323 | + GAT_IMEM_TMU_TOP_IPCLKPORT_I_CLK_TS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1324 | + GATE(0, "imem_adm_axi4st_i0_imem_ipclkport_aclkm", "mout_imem_clk_imem_aclk", | |
| 1325 | + GAT_IMEM_ADM_AXI4ST_I0_IMEM_IPCLKPORT_ACLKM, 21, CLK_IGNORE_UNUSED, 0), | |
| 1326 | + GATE(0, "imem_adm_axi4st_i1_imem_ipclkport_aclkm", "mout_imem_clk_imem_aclk", | |
| 1327 | + GAT_IMEM_ADM_AXI4ST_I1_IMEM_IPCLKPORT_ACLKM, 21, CLK_IGNORE_UNUSED, 0), | |
| 1328 | + GATE(0, "imem_adm_axi4st_i2_imem_ipclkport_aclkm", "mout_imem_clk_imem_aclk", | |
| 1329 | + GAT_IMEM_ADM_AXI4ST_I2_IMEM_IPCLKPORT_ACLKM, 21, CLK_IGNORE_UNUSED, 0), | |
| 1330 | + GATE(0, "imem_ads_axi4st_i0_imem_ipclkport_aclks", "mout_imem_clk_imem_aclk", | |
| 1331 | + GAT_IMEM_ADS_AXI4ST_I0_IMEM_IPCLKPORT_ACLKS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1332 | + GATE(0, "imem_ads_axi4st_i1_imem_ipclkport_aclks", "mout_imem_clk_imem_aclk", | |
| 1333 | + GAT_IMEM_ADS_AXI4ST_I1_IMEM_IPCLKPORT_ACLKS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1334 | + GATE(0, "imem_ads_axi4st_i2_imem_ipclkport_aclks", "mout_imem_clk_imem_aclk", | |
| 1335 | + GAT_IMEM_ADS_AXI4ST_I2_IMEM_IPCLKPORT_ACLKS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1336 | + GATE(0, "imem_async_dma0_ipclkport_pclkm", "mout_imem_clk_imem_tcuclk", | |
| 1337 | + GAT_IMEM_ASYNC_DMA0_IPCLKPORT_PCLKM, 21, CLK_IGNORE_UNUSED, 0), | |
| 1338 | + GATE(0, "imem_async_dma0_ipclkport_pclks", "mout_imem_clk_imem_aclk", | |
| 1339 | + GAT_IMEM_ASYNC_DMA0_IPCLKPORT_PCLKS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1340 | + GATE(0, "imem_async_dma1_ipclkport_pclkm", "mout_imem_clk_imem_tcuclk", | |
| 1341 | + GAT_IMEM_ASYNC_DMA1_IPCLKPORT_PCLKM, 21, CLK_IGNORE_UNUSED, 0), | |
| 1342 | + GATE(0, "imem_async_dma1_ipclkport_pclks", "mout_imem_clk_imem_aclk", | |
| 1343 | + GAT_IMEM_ASYNC_DMA1_IPCLKPORT_PCLKS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1344 | + GATE(0, "imem_axi2apb_imemp0_ipclkport_aclk", "mout_imem_clk_imem_aclk", | |
| 1345 | + GAT_IMEM_AXI2APB_IMEMP0_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1346 | + GATE(0, "imem_axi2apb_imemp1_ipclkport_aclk", "mout_imem_clk_imem_aclk", | |
| 1347 | + GAT_IMEM_AXI2APB_IMEMP1_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1348 | + GATE(0, "imem_bus_d_imem_ipclkport_mainclk", "mout_imem_clk_imem_tcuclk", | |
| 1349 | + GAT_IMEM_BUS_D_IMEM_IPCLKPORT_MAINCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1350 | + GATE(0, "imem_bus_p_imem_ipclkport_mainclk", "mout_imem_clk_imem_aclk", | |
| 1351 | + GAT_IMEM_BUS_P_IMEM_IPCLKPORT_MAINCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1352 | + GATE(0, "imem_bus_p_imem_ipclkport_pericclk", "mout_imem_clk_imem_aclk", | |
| 1353 | + GAT_IMEM_BUS_P_IMEM_IPCLKPORT_PERICLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1354 | + GATE(0, "imem_bus_p_imem_ipclkport_tcuclk", "mout_imem_clk_imem_tcuclk", | |
| 1355 | + GAT_IMEM_BUS_P_IMEM_IPCLKPORT_TCUCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1356 | + GATE(IMEM_DMA0_IPCLKPORT_ACLK, "imem_dma0_ipclkport_aclk", "mout_imem_clk_imem_tcuclk", | |
| 1357 | + GAT_IMEM_DMA0_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED | CLK_IS_CRITICAL, 0), | |
| 1358 | + GATE(IMEM_DMA1_IPCLKPORT_ACLK, "imem_dma1_ipclkport_aclk", "mout_imem_clk_imem_tcuclk", | |
| 1359 | + GAT_IMEM_DMA1_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED | CLK_IS_CRITICAL, 0), | |
| 1360 | + GATE(0, "imem_gic500_input_sync_ipclkport_clk", "mout_imem_clk_imem_aclk", | |
| 1361 | + GAT_IMEM_GIC500_INPUT_SYNC_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1362 | + GATE(0, "imem_gic_ipclkport_clk", "mout_imem_clk_imem_aclk", | |
| 1363 | + GAT_IMEM_GIC_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1364 | + GATE(0, "imem_intmem_ipclkport_aclk", "mout_imem_clk_imem_intmemclk", | |
| 1365 | + GAT_IMEM_INTMEM_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1366 | + GATE(0, "imem_mailbox_scs_ca72_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1367 | + GAT_IMEM_MAILBOX_SCS_CA72_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1368 | + GATE(0, "imem_mailbox_sms_ca72_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1369 | + GAT_IMEM_MAILBOX_SMS_CA72_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1370 | + GATE(IMEM_MCT_PCLK, "imem_mct_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1371 | + GAT_IMEM_MCT_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1372 | + GATE(0, "imem_ns_brdg_imem_ipclkport_clk__psco_imem__clk_imem_d", | |
| 1373 | + "mout_imem_clk_imem_tcuclk", | |
| 1374 | + GAT_IMEM_NS_BRDG_IMEM_IPCLKPORT_CLK__PSCO_IMEM__CLK_IMEM_D, 21, CLK_IGNORE_UNUSED, 0), | |
| 1375 | + GATE(0, "imem_ns_brdg_imem_ipclkport_clk__psco_imem__clk_imem_tcu", | |
| 1376 | + "mout_imem_clk_imem_tcuclk", | |
| 1377 | + GAT_IMEM_NS_BRDG_IMEM_IPCLKPORT_CLK__PSCO_IMEM__CLK_IMEM_TCU, 21, | |
| 1378 | + CLK_IGNORE_UNUSED, 0), | |
| 1379 | + GATE(0, "imem_ns_brdg_imem_ipclkport_clk__psoc_imem__clk_imem_p", "mout_imem_clk_imem_aclk", | |
| 1380 | + GAT_IMEM_NS_BRDG_IMEM_IPCLKPORT_CLK__PSOC_IMEM__CLK_IMEM_P, 21, CLK_IGNORE_UNUSED, 0), | |
| 1381 | + GATE(0, "imem_otp_con_top_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1382 | + GAT_IMEM_OTP_CON_TOP_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1383 | + GATE(0, "imem_rstnsync_aclk_ipclkport_clk", "mout_imem_clk_imem_aclk", | |
| 1384 | + GAT_IMEM_RSTNSYNC_ACLK_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1385 | + GATE(0, "imem_rstnsync_oscclk_ipclkport_clk", "fin_pll", | |
| 1386 | + GAT_IMEM_RSTNSYNC_OSCCLK_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1387 | + GATE(0, "imem_rstnsync_intmemclk_ipclkport_clk", "mout_imem_clk_imem_intmemclk", | |
| 1388 | + GAT_IMEM_RSTNSYNC_INTMEMCLK_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1389 | + GATE(0, "imem_rstnsync_tcuclk_ipclkport_clk", "mout_imem_clk_imem_tcuclk", | |
| 1390 | + GAT_IMEM_RSTNSYNC_TCUCLK_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1391 | + GATE(0, "imem_sfrif_tmu0_imem_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1392 | + GAT_IMEM_SFRIF_TMU0_IMEM_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1393 | + GATE(0, "imem_sfrif_tmu1_imem_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1394 | + GAT_IMEM_SFRIF_TMU1_IMEM_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1395 | + GATE(0, "imem_tmu_cpu2_ipclkport_i_clk", "fin_pll", | |
| 1396 | + GAT_IMEM_TMU_CPU2_IPCLKPORT_I_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1397 | + GATE(0, "imem_sysreg_imem_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1398 | + GAT_IMEM_SYSREG_IMEM_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1399 | + GATE(0, "imem_tbu_imem_ipclkport_aclk", "mout_imem_clk_imem_tcuclk", | |
| 1400 | + GAT_IMEM_TBU_IMEM_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1401 | + GATE(0, "imem_tcu_ipclkport_aclk", "mout_imem_clk_imem_tcuclk", | |
| 1402 | + GAT_IMEM_TCU_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1403 | + GATE(IMEM_WDT0_IPCLKPORT_PCLK, "imem_wdt0_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1404 | + GAT_IMEM_WDT0_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1405 | + GATE(IMEM_WDT1_IPCLKPORT_PCLK, "imem_wdt1_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1406 | + GAT_IMEM_WDT1_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1407 | + GATE(IMEM_WDT2_IPCLKPORT_PCLK, "imem_wdt2_ipclkport_pclk", "mout_imem_clk_imem_aclk", | |
| 1408 | + GAT_IMEM_WDT2_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1409 | +}; | |
| 1410 | + | |
| 1411 | +static const struct samsung_cmu_info imem_cmu_info __initconst = { | |
| 1412 | + .mux_clks = imem_mux_clks, | |
| 1413 | + .nr_mux_clks = ARRAY_SIZE(imem_mux_clks), | |
| 1414 | + .div_clks = imem_div_clks, | |
| 1415 | + .nr_div_clks = ARRAY_SIZE(imem_div_clks), | |
| 1416 | + .gate_clks = imem_gate_clks, | |
| 1417 | + .nr_gate_clks = ARRAY_SIZE(imem_gate_clks), | |
| 1418 | + .nr_clk_ids = IMEM_NR_CLK, | |
| 1419 | + .clk_regs = imem_clk_regs, | |
| 1420 | + .nr_clk_regs = ARRAY_SIZE(imem_clk_regs), | |
| 1421 | +}; | |
| 1422 | + | |
| 1423 | +static void __init fsd_clk_imem_init(struct device_node *np) | |
| 1424 | +{ | |
| 1425 | + samsung_cmu_register_one(np, &imem_cmu_info); | |
| 1426 | +} | |
| 1427 | + | |
| 1428 | +CLK_OF_DECLARE(fsd_clk_imem, "tesla,fsd-clock-imem", fsd_clk_imem_init); | |
| 1429 | + | |
| 1430 | +/* Register Offset definitions for CMU_MFC (0x12810000) */ | |
| 1431 | +#define PLL_LOCKTIME_PLL_MFC 0x0 | |
| 1432 | +#define PLL_CON0_PLL_MFC 0x100 | |
| 1433 | +#define MUX_MFC_BUSD 0x1000 | |
| 1434 | +#define MUX_MFC_BUSP 0x1008 | |
| 1435 | +#define DIV_MFC_BUSD_DIV4 0x1800 | |
| 1436 | +#define GAT_MFC_CMU_MFC_IPCLKPORT_PCLK 0x2000 | |
| 1437 | +#define GAT_MFC_AS_P_MFC_IPCLKPORT_PCLKM 0x2004 | |
| 1438 | +#define GAT_MFC_AS_P_MFC_IPCLKPORT_PCLKS 0x2008 | |
| 1439 | +#define GAT_MFC_AXI2APB_MFC_IPCLKPORT_ACLK 0x200c | |
| 1440 | +#define GAT_MFC_MFC_IPCLKPORT_ACLK 0x2010 | |
| 1441 | +#define GAT_MFC_NS_BRDG_MFC_IPCLKPORT_CLK__PMFC__CLK_MFC_D 0x2018 | |
| 1442 | +#define GAT_MFC_NS_BRDG_MFC_IPCLKPORT_CLK__PMFC__CLK_MFC_P 0x201c | |
| 1443 | +#define GAT_MFC_PPMU_MFCD0_IPCLKPORT_ACLK 0x2028 | |
| 1444 | +#define GAT_MFC_PPMU_MFCD0_IPCLKPORT_PCLK 0x202c | |
| 1445 | +#define GAT_MFC_PPMU_MFCD1_IPCLKPORT_ACLK 0x2030 | |
| 1446 | +#define GAT_MFC_PPMU_MFCD1_IPCLKPORT_PCLK 0x2034 | |
| 1447 | +#define GAT_MFC_SYSREG_MFC_IPCLKPORT_PCLK 0x2038 | |
| 1448 | +#define GAT_MFC_TBU_MFCD0_IPCLKPORT_CLK 0x203c | |
| 1449 | +#define GAT_MFC_TBU_MFCD1_IPCLKPORT_CLK 0x2040 | |
| 1450 | +#define GAT_MFC_BUSD_DIV4_GATE 0x2044 | |
| 1451 | +#define GAT_MFC_BUSD_GATE 0x2048 | |
| 1452 | + | |
| 1453 | +static const unsigned long mfc_clk_regs[] __initconst = { | |
| 1454 | + PLL_LOCKTIME_PLL_MFC, | |
| 1455 | + PLL_CON0_PLL_MFC, | |
| 1456 | + MUX_MFC_BUSD, | |
| 1457 | + MUX_MFC_BUSP, | |
| 1458 | + DIV_MFC_BUSD_DIV4, | |
| 1459 | + GAT_MFC_CMU_MFC_IPCLKPORT_PCLK, | |
| 1460 | + GAT_MFC_AS_P_MFC_IPCLKPORT_PCLKM, | |
| 1461 | + GAT_MFC_AS_P_MFC_IPCLKPORT_PCLKS, | |
| 1462 | + GAT_MFC_AXI2APB_MFC_IPCLKPORT_ACLK, | |
| 1463 | + GAT_MFC_MFC_IPCLKPORT_ACLK, | |
| 1464 | + GAT_MFC_NS_BRDG_MFC_IPCLKPORT_CLK__PMFC__CLK_MFC_D, | |
| 1465 | + GAT_MFC_NS_BRDG_MFC_IPCLKPORT_CLK__PMFC__CLK_MFC_P, | |
| 1466 | + GAT_MFC_PPMU_MFCD0_IPCLKPORT_ACLK, | |
| 1467 | + GAT_MFC_PPMU_MFCD0_IPCLKPORT_PCLK, | |
| 1468 | + GAT_MFC_PPMU_MFCD1_IPCLKPORT_ACLK, | |
| 1469 | + GAT_MFC_PPMU_MFCD1_IPCLKPORT_PCLK, | |
| 1470 | + GAT_MFC_SYSREG_MFC_IPCLKPORT_PCLK, | |
| 1471 | + GAT_MFC_TBU_MFCD0_IPCLKPORT_CLK, | |
| 1472 | + GAT_MFC_TBU_MFCD1_IPCLKPORT_CLK, | |
| 1473 | + GAT_MFC_BUSD_DIV4_GATE, | |
| 1474 | + GAT_MFC_BUSD_GATE, | |
| 1475 | +}; | |
| 1476 | + | |
| 1477 | +static const struct samsung_pll_rate_table pll_mfc_rate_table[] __initconst = { | |
| 1478 | + PLL_35XX_RATE(24 * MHZ, 666000000U, 111, 4, 0), | |
| 1479 | +}; | |
| 1480 | + | |
| 1481 | +static const struct samsung_pll_clock mfc_pll_clks[] __initconst = { | |
| 1482 | + PLL(pll_142xx, 0, "fout_pll_mfc", "fin_pll", | |
| 1483 | + PLL_LOCKTIME_PLL_MFC, PLL_CON0_PLL_MFC, pll_mfc_rate_table), | |
| 1484 | +}; | |
| 1485 | + | |
| 1486 | +PNAME(mout_mfc_pll_p) = { "fin_pll", "fout_pll_mfc" }; | |
| 1487 | +PNAME(mout_mfc_busp_p) = { "fin_pll", "dout_mfc_busd_div4" }; | |
| 1488 | +PNAME(mout_mfc_busd_p) = { "fin_pll", "mfc_busd_gate" }; | |
| 1489 | + | |
| 1490 | +static const struct samsung_mux_clock mfc_mux_clks[] __initconst = { | |
| 1491 | + MUX(0, "mout_mfc_pll", mout_mfc_pll_p, PLL_CON0_PLL_MFC, 4, 1), | |
| 1492 | + MUX(0, "mout_mfc_busp", mout_mfc_busp_p, MUX_MFC_BUSP, 0, 1), | |
| 1493 | + MUX(0, "mout_mfc_busd", mout_mfc_busd_p, MUX_MFC_BUSD, 0, 1), | |
| 1494 | +}; | |
| 1495 | + | |
| 1496 | +static const struct samsung_div_clock mfc_div_clks[] __initconst = { | |
| 1497 | + DIV(0, "dout_mfc_busd_div4", "mfc_busd_div4_gate", DIV_MFC_BUSD_DIV4, 0, 4), | |
| 1498 | +}; | |
| 1499 | + | |
| 1500 | +static const struct samsung_gate_clock mfc_gate_clks[] __initconst = { | |
| 1501 | + GATE(0, "mfc_cmu_mfc_ipclkport_pclk", "mout_mfc_busp", | |
| 1502 | + GAT_MFC_CMU_MFC_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1503 | + GATE(0, "mfc_as_p_mfc_ipclkport_pclkm", "mout_mfc_busd", | |
| 1504 | + GAT_MFC_AS_P_MFC_IPCLKPORT_PCLKM, 21, CLK_IGNORE_UNUSED, 0), | |
| 1505 | + GATE(0, "mfc_as_p_mfc_ipclkport_pclks", "mout_mfc_busp", | |
| 1506 | + GAT_MFC_AS_P_MFC_IPCLKPORT_PCLKS, 21, CLK_IGNORE_UNUSED, 0), | |
| 1507 | + GATE(0, "mfc_axi2apb_mfc_ipclkport_aclk", "mout_mfc_busp", | |
| 1508 | + GAT_MFC_AXI2APB_MFC_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1509 | + GATE(MFC_MFC_IPCLKPORT_ACLK, "mfc_mfc_ipclkport_aclk", "mout_mfc_busd", | |
| 1510 | + GAT_MFC_MFC_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1511 | + GATE(0, "mfc_ns_brdg_mfc_ipclkport_clk__pmfc__clk_mfc_d", "mout_mfc_busd", | |
| 1512 | + GAT_MFC_NS_BRDG_MFC_IPCLKPORT_CLK__PMFC__CLK_MFC_D, 21, CLK_IGNORE_UNUSED, 0), | |
| 1513 | + GATE(0, "mfc_ns_brdg_mfc_ipclkport_clk__pmfc__clk_mfc_p", "mout_mfc_busp", | |
| 1514 | + GAT_MFC_NS_BRDG_MFC_IPCLKPORT_CLK__PMFC__CLK_MFC_P, 21, CLK_IGNORE_UNUSED, 0), | |
| 1515 | + GATE(0, "mfc_ppmu_mfcd0_ipclkport_aclk", "mout_mfc_busd", | |
| 1516 | + GAT_MFC_PPMU_MFCD0_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1517 | + GATE(0, "mfc_ppmu_mfcd0_ipclkport_pclk", "mout_mfc_busp", | |
| 1518 | + GAT_MFC_PPMU_MFCD0_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1519 | + GATE(0, "mfc_ppmu_mfcd1_ipclkport_aclk", "mout_mfc_busd", | |
| 1520 | + GAT_MFC_PPMU_MFCD1_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1521 | + GATE(0, "mfc_ppmu_mfcd1_ipclkport_pclk", "mout_mfc_busp", | |
| 1522 | + GAT_MFC_PPMU_MFCD1_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1523 | + GATE(0, "mfc_sysreg_mfc_ipclkport_pclk", "mout_mfc_busp", | |
| 1524 | + GAT_MFC_SYSREG_MFC_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1525 | + GATE(0, "mfc_tbu_mfcd0_ipclkport_clk", "mout_mfc_busd", | |
| 1526 | + GAT_MFC_TBU_MFCD0_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1527 | + GATE(0, "mfc_tbu_mfcd1_ipclkport_clk", "mout_mfc_busd", | |
| 1528 | + GAT_MFC_TBU_MFCD1_IPCLKPORT_CLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1529 | + GATE(0, "mfc_busd_div4_gate", "mout_mfc_pll", | |
| 1530 | + GAT_MFC_BUSD_DIV4_GATE, 21, CLK_IGNORE_UNUSED, 0), | |
| 1531 | + GATE(0, "mfc_busd_gate", "mout_mfc_pll", GAT_MFC_BUSD_GATE, 21, CLK_IS_CRITICAL, 0), | |
| 1532 | +}; | |
| 1533 | + | |
| 1534 | +static const struct samsung_cmu_info mfc_cmu_info __initconst = { | |
| 1535 | + .pll_clks = mfc_pll_clks, | |
| 1536 | + .nr_pll_clks = ARRAY_SIZE(mfc_pll_clks), | |
| 1537 | + .mux_clks = mfc_mux_clks, | |
| 1538 | + .nr_mux_clks = ARRAY_SIZE(mfc_mux_clks), | |
| 1539 | + .div_clks = mfc_div_clks, | |
| 1540 | + .nr_div_clks = ARRAY_SIZE(mfc_div_clks), | |
| 1541 | + .gate_clks = mfc_gate_clks, | |
| 1542 | + .nr_gate_clks = ARRAY_SIZE(mfc_gate_clks), | |
| 1543 | + .nr_clk_ids = MFC_NR_CLK, | |
| 1544 | + .clk_regs = mfc_clk_regs, | |
| 1545 | + .nr_clk_regs = ARRAY_SIZE(mfc_clk_regs), | |
| 1546 | +}; | |
| 1547 | + | |
| 1548 | +/* Register Offset definitions for CMU_CAM_CSI (0x12610000) */ | |
| 1549 | +#define PLL_LOCKTIME_PLL_CAM_CSI 0x0 | |
| 1550 | +#define PLL_CON0_PLL_CAM_CSI 0x100 | |
| 1551 | +#define DIV_CAM_CSI0_ACLK 0x1800 | |
| 1552 | +#define DIV_CAM_CSI1_ACLK 0x1804 | |
| 1553 | +#define DIV_CAM_CSI2_ACLK 0x1808 | |
| 1554 | +#define DIV_CAM_CSI_BUSD 0x180c | |
| 1555 | +#define DIV_CAM_CSI_BUSP 0x1810 | |
| 1556 | +#define GAT_CAM_CSI_CMU_CAM_CSI_IPCLKPORT_PCLK 0x2000 | |
| 1557 | +#define GAT_CAM_AXI2APB_CAM_CSI_IPCLKPORT_ACLK 0x2004 | |
| 1558 | +#define GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_CSI0 0x2008 | |
| 1559 | +#define GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_CSI1 0x200c | |
| 1560 | +#define GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_CSI2 0x2010 | |
| 1561 | +#define GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_SOC_NOC 0x2014 | |
| 1562 | +#define GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__NOC 0x2018 | |
| 1563 | +#define GAT_CAM_CSI0_0_IPCLKPORT_I_ACLK 0x201c | |
| 1564 | +#define GAT_CAM_CSI0_0_IPCLKPORT_I_PCLK 0x2020 | |
| 1565 | +#define GAT_CAM_CSI0_1_IPCLKPORT_I_ACLK 0x2024 | |
| 1566 | +#define GAT_CAM_CSI0_1_IPCLKPORT_I_PCLK 0x2028 | |
| 1567 | +#define GAT_CAM_CSI0_2_IPCLKPORT_I_ACLK 0x202c | |
| 1568 | +#define GAT_CAM_CSI0_2_IPCLKPORT_I_PCLK 0x2030 | |
| 1569 | +#define GAT_CAM_CSI0_3_IPCLKPORT_I_ACLK 0x2034 | |
| 1570 | +#define GAT_CAM_CSI0_3_IPCLKPORT_I_PCLK 0x2038 | |
| 1571 | +#define GAT_CAM_CSI1_0_IPCLKPORT_I_ACLK 0x203c | |
| 1572 | +#define GAT_CAM_CSI1_0_IPCLKPORT_I_PCLK 0x2040 | |
| 1573 | +#define GAT_CAM_CSI1_1_IPCLKPORT_I_ACLK 0x2044 | |
| 1574 | +#define GAT_CAM_CSI1_1_IPCLKPORT_I_PCLK 0x2048 | |
| 1575 | +#define GAT_CAM_CSI1_2_IPCLKPORT_I_ACLK 0x204c | |
| 1576 | +#define GAT_CAM_CSI1_2_IPCLKPORT_I_PCLK 0x2050 | |
| 1577 | +#define GAT_CAM_CSI1_3_IPCLKPORT_I_ACLK 0x2054 | |
| 1578 | +#define GAT_CAM_CSI1_3_IPCLKPORT_I_PCLK 0x2058 | |
| 1579 | +#define GAT_CAM_CSI2_0_IPCLKPORT_I_ACLK 0x205c | |
| 1580 | +#define GAT_CAM_CSI2_0_IPCLKPORT_I_PCLK 0x2060 | |
| 1581 | +#define GAT_CAM_CSI2_1_IPCLKPORT_I_ACLK 0x2064 | |
| 1582 | +#define GAT_CAM_CSI2_1_IPCLKPORT_I_PCLK 0x2068 | |
| 1583 | +#define GAT_CAM_CSI2_2_IPCLKPORT_I_ACLK 0x206c | |
| 1584 | +#define GAT_CAM_CSI2_2_IPCLKPORT_I_PCLK 0x2070 | |
| 1585 | +#define GAT_CAM_CSI2_3_IPCLKPORT_I_ACLK 0x2074 | |
| 1586 | +#define GAT_CAM_CSI2_3_IPCLKPORT_I_PCLK 0x2078 | |
| 1587 | +#define GAT_CAM_NS_BRDG_CAM_CSI_IPCLKPORT_CLK__PSOC_CAM_CSI__CLK_CAM_CSI_D 0x207c | |
| 1588 | +#define GAT_CAM_NS_BRDG_CAM_CSI_IPCLKPORT_CLK__PSOC_CAM_CSI__CLK_CAM_CSI_P 0x2080 | |
| 1589 | +#define GAT_CAM_SYSREG_CAM_CSI_IPCLKPORT_PCLK 0x2084 | |
| 1590 | +#define GAT_CAM_TBU_CAM_CSI_IPCLKPORT_ACLK 0x2088 | |
| 1591 | + | |
| 1592 | +static const unsigned long cam_csi_clk_regs[] __initconst = { | |
| 1593 | + PLL_LOCKTIME_PLL_CAM_CSI, | |
| 1594 | + PLL_CON0_PLL_CAM_CSI, | |
| 1595 | + DIV_CAM_CSI0_ACLK, | |
| 1596 | + DIV_CAM_CSI1_ACLK, | |
| 1597 | + DIV_CAM_CSI2_ACLK, | |
| 1598 | + DIV_CAM_CSI_BUSD, | |
| 1599 | + DIV_CAM_CSI_BUSP, | |
| 1600 | + GAT_CAM_CSI_CMU_CAM_CSI_IPCLKPORT_PCLK, | |
| 1601 | + GAT_CAM_AXI2APB_CAM_CSI_IPCLKPORT_ACLK, | |
| 1602 | + GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_CSI0, | |
| 1603 | + GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_CSI1, | |
| 1604 | + GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_CSI2, | |
| 1605 | + GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_SOC_NOC, | |
| 1606 | + GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__NOC, | |
| 1607 | + GAT_CAM_CSI0_0_IPCLKPORT_I_ACLK, | |
| 1608 | + GAT_CAM_CSI0_0_IPCLKPORT_I_PCLK, | |
| 1609 | + GAT_CAM_CSI0_1_IPCLKPORT_I_ACLK, | |
| 1610 | + GAT_CAM_CSI0_1_IPCLKPORT_I_PCLK, | |
| 1611 | + GAT_CAM_CSI0_2_IPCLKPORT_I_ACLK, | |
| 1612 | + GAT_CAM_CSI0_2_IPCLKPORT_I_PCLK, | |
| 1613 | + GAT_CAM_CSI0_3_IPCLKPORT_I_ACLK, | |
| 1614 | + GAT_CAM_CSI0_3_IPCLKPORT_I_PCLK, | |
| 1615 | + GAT_CAM_CSI1_0_IPCLKPORT_I_ACLK, | |
| 1616 | + GAT_CAM_CSI1_0_IPCLKPORT_I_PCLK, | |
| 1617 | + GAT_CAM_CSI1_1_IPCLKPORT_I_ACLK, | |
| 1618 | + GAT_CAM_CSI1_1_IPCLKPORT_I_PCLK, | |
| 1619 | + GAT_CAM_CSI1_2_IPCLKPORT_I_ACLK, | |
| 1620 | + GAT_CAM_CSI1_2_IPCLKPORT_I_PCLK, | |
| 1621 | + GAT_CAM_CSI1_3_IPCLKPORT_I_ACLK, | |
| 1622 | + GAT_CAM_CSI1_3_IPCLKPORT_I_PCLK, | |
| 1623 | + GAT_CAM_CSI2_0_IPCLKPORT_I_ACLK, | |
| 1624 | + GAT_CAM_CSI2_0_IPCLKPORT_I_PCLK, | |
| 1625 | + GAT_CAM_CSI2_1_IPCLKPORT_I_ACLK, | |
| 1626 | + GAT_CAM_CSI2_1_IPCLKPORT_I_PCLK, | |
| 1627 | + GAT_CAM_CSI2_2_IPCLKPORT_I_ACLK, | |
| 1628 | + GAT_CAM_CSI2_2_IPCLKPORT_I_PCLK, | |
| 1629 | + GAT_CAM_CSI2_3_IPCLKPORT_I_ACLK, | |
| 1630 | + GAT_CAM_CSI2_3_IPCLKPORT_I_PCLK, | |
| 1631 | + GAT_CAM_NS_BRDG_CAM_CSI_IPCLKPORT_CLK__PSOC_CAM_CSI__CLK_CAM_CSI_D, | |
| 1632 | + GAT_CAM_NS_BRDG_CAM_CSI_IPCLKPORT_CLK__PSOC_CAM_CSI__CLK_CAM_CSI_P, | |
| 1633 | + GAT_CAM_SYSREG_CAM_CSI_IPCLKPORT_PCLK, | |
| 1634 | + GAT_CAM_TBU_CAM_CSI_IPCLKPORT_ACLK, | |
| 1635 | +}; | |
| 1636 | + | |
| 1637 | +static const struct samsung_pll_rate_table pll_cam_csi_rate_table[] __initconst = { | |
| 1638 | + PLL_35XX_RATE(24 * MHZ, 1066000000U, 533, 12, 0), | |
| 1639 | +}; | |
| 1640 | + | |
| 1641 | +static const struct samsung_pll_clock cam_csi_pll_clks[] __initconst = { | |
| 1642 | + PLL(pll_142xx, 0, "fout_pll_cam_csi", "fin_pll", | |
| 1643 | + PLL_LOCKTIME_PLL_CAM_CSI, PLL_CON0_PLL_CAM_CSI, pll_cam_csi_rate_table), | |
| 1644 | +}; | |
| 1645 | + | |
| 1646 | +PNAME(mout_cam_csi_pll_p) = { "fin_pll", "fout_pll_cam_csi" }; | |
| 1647 | + | |
| 1648 | +static const struct samsung_mux_clock cam_csi_mux_clks[] __initconst = { | |
| 1649 | + MUX(0, "mout_cam_csi_pll", mout_cam_csi_pll_p, PLL_CON0_PLL_CAM_CSI, 4, 1), | |
| 1650 | +}; | |
| 1651 | + | |
| 1652 | +static const struct samsung_div_clock cam_csi_div_clks[] __initconst = { | |
| 1653 | + DIV(0, "dout_cam_csi0_aclk", "mout_cam_csi_pll", DIV_CAM_CSI0_ACLK, 0, 4), | |
| 1654 | + DIV(0, "dout_cam_csi1_aclk", "mout_cam_csi_pll", DIV_CAM_CSI1_ACLK, 0, 4), | |
| 1655 | + DIV(0, "dout_cam_csi2_aclk", "mout_cam_csi_pll", DIV_CAM_CSI2_ACLK, 0, 4), | |
| 1656 | + DIV(0, "dout_cam_csi_busd", "mout_cam_csi_pll", DIV_CAM_CSI_BUSD, 0, 4), | |
| 1657 | + DIV(0, "dout_cam_csi_busp", "mout_cam_csi_pll", DIV_CAM_CSI_BUSP, 0, 4), | |
| 1658 | +}; | |
| 1659 | + | |
| 1660 | +static const struct samsung_gate_clock cam_csi_gate_clks[] __initconst = { | |
| 1661 | + GATE(0, "cam_csi_cmu_cam_csi_ipclkport_pclk", "dout_cam_csi_busp", | |
| 1662 | + GAT_CAM_CSI_CMU_CAM_CSI_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1663 | + GATE(0, "cam_axi2apb_cam_csi_ipclkport_aclk", "dout_cam_csi_busp", | |
| 1664 | + GAT_CAM_AXI2APB_CAM_CSI_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1665 | + GATE(0, "cam_csi_bus_d_cam_csi_ipclkport_clk__system__clk_csi0", "dout_cam_csi0_aclk", | |
| 1666 | + GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_CSI0, 21, CLK_IGNORE_UNUSED, 0), | |
| 1667 | + GATE(0, "cam_csi_bus_d_cam_csi_ipclkport_clk__system__clk_csi1", "dout_cam_csi1_aclk", | |
| 1668 | + GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_CSI1, 21, CLK_IGNORE_UNUSED, 0), | |
| 1669 | + GATE(0, "cam_csi_bus_d_cam_csi_ipclkport_clk__system__clk_csi2", "dout_cam_csi2_aclk", | |
| 1670 | + GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_CSI2, 21, CLK_IGNORE_UNUSED, 0), | |
| 1671 | + GATE(0, "cam_csi_bus_d_cam_csi_ipclkport_clk__system__clk_soc_noc", "dout_cam_csi_busd", | |
| 1672 | + GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__CLK_SOC_NOC, 21, | |
| 1673 | + CLK_IGNORE_UNUSED, 0), | |
| 1674 | + GATE(0, "cam_csi_bus_d_cam_csi_ipclkport_clk__system__noc", "dout_cam_csi_busd", | |
| 1675 | + GAT_CAM_CSI_BUS_D_CAM_CSI_IPCLKPORT_CLK__SYSTEM__NOC, 21, CLK_IGNORE_UNUSED, 0), | |
| 1676 | + GATE(CAM_CSI0_0_IPCLKPORT_I_ACLK, "cam_csi0_0_ipclkport_i_aclk", "dout_cam_csi0_aclk", | |
| 1677 | + GAT_CAM_CSI0_0_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1678 | + GATE(0, "cam_csi0_0_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1679 | + GAT_CAM_CSI0_0_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1680 | + GATE(CAM_CSI0_1_IPCLKPORT_I_ACLK, "cam_csi0_1_ipclkport_i_aclk", "dout_cam_csi0_aclk", | |
| 1681 | + GAT_CAM_CSI0_1_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1682 | + GATE(0, "cam_csi0_1_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1683 | + GAT_CAM_CSI0_1_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1684 | + GATE(CAM_CSI0_2_IPCLKPORT_I_ACLK, "cam_csi0_2_ipclkport_i_aclk", "dout_cam_csi0_aclk", | |
| 1685 | + GAT_CAM_CSI0_2_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1686 | + GATE(0, "cam_csi0_2_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1687 | + GAT_CAM_CSI0_2_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1688 | + GATE(CAM_CSI0_3_IPCLKPORT_I_ACLK, "cam_csi0_3_ipclkport_i_aclk", "dout_cam_csi0_aclk", | |
| 1689 | + GAT_CAM_CSI0_3_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1690 | + GATE(0, "cam_csi0_3_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1691 | + GAT_CAM_CSI0_3_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1692 | + GATE(CAM_CSI1_0_IPCLKPORT_I_ACLK, "cam_csi1_0_ipclkport_i_aclk", "dout_cam_csi1_aclk", | |
| 1693 | + GAT_CAM_CSI1_0_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1694 | + GATE(0, "cam_csi1_0_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1695 | + GAT_CAM_CSI1_0_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1696 | + GATE(CAM_CSI1_1_IPCLKPORT_I_ACLK, "cam_csi1_1_ipclkport_i_aclk", "dout_cam_csi1_aclk", | |
| 1697 | + GAT_CAM_CSI1_1_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1698 | + GATE(0, "cam_csi1_1_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1699 | + GAT_CAM_CSI1_1_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1700 | + GATE(CAM_CSI1_2_IPCLKPORT_I_ACLK, "cam_csi1_2_ipclkport_i_aclk", "dout_cam_csi1_aclk", | |
| 1701 | + GAT_CAM_CSI1_2_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1702 | + GATE(0, "cam_csi1_2_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1703 | + GAT_CAM_CSI1_2_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1704 | + GATE(CAM_CSI1_3_IPCLKPORT_I_ACLK, "cam_csi1_3_ipclkport_i_aclk", "dout_cam_csi1_aclk", | |
| 1705 | + GAT_CAM_CSI1_3_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1706 | + GATE(0, "cam_csi1_3_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1707 | + GAT_CAM_CSI1_3_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1708 | + GATE(CAM_CSI2_0_IPCLKPORT_I_ACLK, "cam_csi2_0_ipclkport_i_aclk", "dout_cam_csi2_aclk", | |
| 1709 | + GAT_CAM_CSI2_0_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1710 | + GATE(0, "cam_csi2_0_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1711 | + GAT_CAM_CSI2_0_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1712 | + GATE(CAM_CSI2_1_IPCLKPORT_I_ACLK, "cam_csi2_1_ipclkport_i_aclk", "dout_cam_csi2_aclk", | |
| 1713 | + GAT_CAM_CSI2_1_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1714 | + GATE(0, "cam_csi2_1_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1715 | + GAT_CAM_CSI2_1_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1716 | + GATE(CAM_CSI2_2_IPCLKPORT_I_ACLK, "cam_csi2_2_ipclkport_i_aclk", "dout_cam_csi2_aclk", | |
| 1717 | + GAT_CAM_CSI2_2_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1718 | + GATE(0, "cam_csi2_2_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1719 | + GAT_CAM_CSI2_2_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1720 | + GATE(CAM_CSI2_3_IPCLKPORT_I_ACLK, "cam_csi2_3_ipclkport_i_aclk", "dout_cam_csi2_aclk", | |
| 1721 | + GAT_CAM_CSI2_3_IPCLKPORT_I_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1722 | + GATE(0, "cam_csi2_3_ipclkport_i_pclk", "dout_cam_csi_busp", | |
| 1723 | + GAT_CAM_CSI2_3_IPCLKPORT_I_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1724 | + GATE(0, "cam_ns_brdg_cam_csi_ipclkport_clk__psoc_cam_csi__clk_cam_csi_d", | |
| 1725 | + "dout_cam_csi_busd", | |
| 1726 | + GAT_CAM_NS_BRDG_CAM_CSI_IPCLKPORT_CLK__PSOC_CAM_CSI__CLK_CAM_CSI_D, 21, | |
| 1727 | + CLK_IGNORE_UNUSED, 0), | |
| 1728 | + GATE(0, "cam_ns_brdg_cam_csi_ipclkport_clk__psoc_cam_csi__clk_cam_csi_p", | |
| 1729 | + "dout_cam_csi_busp", | |
| 1730 | + GAT_CAM_NS_BRDG_CAM_CSI_IPCLKPORT_CLK__PSOC_CAM_CSI__CLK_CAM_CSI_P, 21, | |
| 1731 | + CLK_IGNORE_UNUSED, 0), | |
| 1732 | + GATE(0, "cam_sysreg_cam_csi_ipclkport_pclk", "dout_cam_csi_busp", | |
| 1733 | + GAT_CAM_SYSREG_CAM_CSI_IPCLKPORT_PCLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1734 | + GATE(0, "cam_tbu_cam_csi_ipclkport_aclk", "dout_cam_csi_busd", | |
| 1735 | + GAT_CAM_TBU_CAM_CSI_IPCLKPORT_ACLK, 21, CLK_IGNORE_UNUSED, 0), | |
| 1736 | +}; | |
| 1737 | + | |
| 1738 | +static const struct samsung_cmu_info cam_csi_cmu_info __initconst = { | |
| 1739 | + .pll_clks = cam_csi_pll_clks, | |
| 1740 | + .nr_pll_clks = ARRAY_SIZE(cam_csi_pll_clks), | |
| 1741 | + .mux_clks = cam_csi_mux_clks, | |
| 1742 | + .nr_mux_clks = ARRAY_SIZE(cam_csi_mux_clks), | |
| 1743 | + .div_clks = cam_csi_div_clks, | |
| 1744 | + .nr_div_clks = ARRAY_SIZE(cam_csi_div_clks), | |
| 1745 | + .gate_clks = cam_csi_gate_clks, | |
| 1746 | + .nr_gate_clks = ARRAY_SIZE(cam_csi_gate_clks), | |
| 1747 | + .nr_clk_ids = CAM_CSI_NR_CLK, | |
| 1748 | + .clk_regs = cam_csi_clk_regs, | |
| 1749 | + .nr_clk_regs = ARRAY_SIZE(cam_csi_clk_regs), | |
| 1750 | +}; | |
| 1751 | + | |
| 1752 | +/** | |
| 1753 | + * fsd_cmu_probe - Probe function for FSD platform clocks | |
| 1754 | + * @pdev: Pointer to platform device | |
| 1755 | + * | |
| 1756 | + * Configure clock hierarchy for clock domains of FSD platform | |
| 1757 | + */ | |
| 1758 | +static int __init fsd_cmu_probe(struct platform_device *pdev) | |
| 1759 | +{ | |
| 1760 | + const struct samsung_cmu_info *info; | |
| 1761 | + struct device *dev = &pdev->dev; | |
| 1762 | + | |
| 1763 | + info = of_device_get_match_data(dev); | |
| 1764 | + exynos_arm64_register_cmu(dev, dev->of_node, info); | |
| 1765 | + | |
| 1766 | + return 0; | |
| 1767 | +} | |
| 1768 | + | |
| 1769 | +/* CMUs which belong to Power Domains and need runtime PM to be implemented */ | |
| 1770 | +static const struct of_device_id fsd_cmu_of_match[] = { | |
| 1771 | + { | |
| 1772 | + .compatible = "tesla,fsd-clock-peric", | |
| 1773 | + .data = &peric_cmu_info, | |
| 1774 | + }, { | |
| 1775 | + .compatible = "tesla,fsd-clock-fsys0", | |
| 1776 | + .data = &fsys0_cmu_info, | |
| 1777 | + }, { | |
| 1778 | + .compatible = "tesla,fsd-clock-fsys1", | |
| 1779 | + .data = &fsys1_cmu_info, | |
| 1780 | + }, { | |
| 1781 | + .compatible = "tesla,fsd-clock-mfc", | |
| 1782 | + .data = &mfc_cmu_info, | |
| 1783 | + }, { | |
| 1784 | + .compatible = "tesla,fsd-clock-cam_csi", | |
| 1785 | + .data = &cam_csi_cmu_info, | |
| 1786 | + }, { | |
| 1787 | + }, | |
| 1788 | +}; | |
| 1789 | + | |
| 1790 | +static struct platform_driver fsd_cmu_driver __refdata = { | |
| 1791 | + .driver = { | |
| 1792 | + .name = "fsd-cmu", | |
| 1793 | + .of_match_table = fsd_cmu_of_match, | |
| 1794 | + .suppress_bind_attrs = true, | |
| 1795 | + }, | |
| 1796 | + .probe = fsd_cmu_probe, | |
| 1797 | +}; | |
| 1798 | + | |
| 1799 | +static int __init fsd_cmu_init(void) | |
| 1800 | +{ | |
| 1801 | + return platform_driver_register(&fsd_cmu_driver); | |
| 1802 | +} | |
| 1803 | +core_initcall(fsd_cmu_init); | |
| @@ -1469,6 +1469,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, · 1468 unmodified lines | ||
| 1469 | 1469 | case pll_1450x: |
| 1470 | 1470 | case pll_1451x: |
| 1471 | 1471 | case pll_1452x: |
| 1472 | + case pll_142xx: | |
| 1472 | 1473 | pll->enable_offs = PLL35XX_ENABLE_SHIFT; |
| 1473 | 1474 | pll->lock_offs = PLL35XX_LOCK_STAT_SHIFT; |
| 1474 | 1475 | if (!pll->rate_table) |
| @@ -39,6 +39,7 @@ enum samsung_pll_type { · 38 unmodified lines | ||
| 39 | 39 | pll_1460x, |
| 40 | 40 | pll_0822x, |
| 41 | 41 | pll_0831x, |
| 42 | + pll_142xx, | |
| 42 | 43 | }; |
| 43 | 44 | |
| 44 | 45 | #define PLL_RATE(_fin, _m, _p, _s, _k, _ks) \ |
| @@ -122,10 +122,6 @@ static int spm_cpuidle_register(struct device *cpuidle_dev, int cpu) · 121 unmodified lines | ||
| 122 | 122 | if (ret <= 0) |
| 123 | 123 | return ret ? : -ENODEV; |
| 124 | 124 | |
| 125 | − ret = qcom_scm_set_warm_boot_addr(cpu_resume_arm, cpumask_of(cpu)); | |
| 126 | − if (ret) | |
| 127 | − return ret; | |
| 128 | − | |
| 129 | 125 | return cpuidle_register(&data->cpuidle_driver, NULL); |
| 130 | 126 | } |
| 131 | 127 | |
| @@ -136,6 +132,10 @@ static int spm_cpuidle_drv_probe(struct platform_device *pdev) · 4 unmodified lines | ||
| 136 | 132 | if (!qcom_scm_is_available()) |
| 137 | 133 | return -EPROBE_DEFER; |
| 138 | 134 | |
| 135 | + ret = qcom_scm_set_warm_boot_addr(cpu_resume_arm); | |
| 136 | + if (ret) | |
| 137 | + return dev_err_probe(&pdev->dev, ret, "set warm boot addr failed"); | |
| 138 | + | |
| 139 | 139 | for_each_possible_cpu(cpu) { |
| 140 | 140 | ret = spm_cpuidle_register(&pdev->dev, cpu); |
| 141 | 141 | if (ret && ret != -ENODEV) { |
| @@ -155,6 +155,22 @@ static struct platform_driver spm_cpuidle_driver = { · 13 unmodified lines | ||
| 155 | 155 | }, |
| 156 | 156 | }; |
| 157 | 157 | |
| 158 | +static bool __init qcom_spm_find_any_cpu(void) | |
| 159 | +{ | |
| 160 | + struct device_node *cpu_node, *saw_node; | |
| 161 | + | |
| 162 | + for_each_of_cpu_node(cpu_node) { | |
| 163 | + saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); | |
| 164 | + if (of_device_is_available(saw_node)) { | |
| 165 | + of_node_put(saw_node); | |
| 166 | + of_node_put(cpu_node); | |
| 167 | + return true; | |
| 168 | + } | |
| 169 | + of_node_put(saw_node); | |
| 170 | + } | |
| 171 | + return false; | |
| 172 | +} | |
| 173 | + | |
| 158 | 174 | static int __init qcom_spm_cpuidle_init(void) |
| 159 | 175 | { |
| 160 | 176 | struct platform_device *pdev; |
| @@ -164,6 +180,10 @@ static int __init qcom_spm_cpuidle_init(void) · 3 unmodified lines | ||
| 164 | 180 | if (ret) |
| 165 | 181 | return ret; |
| 166 | 182 | |
| 183 | + /* Make sure there is actually any CPU managed by the SPM */ | |
| 184 | + if (!qcom_spm_find_any_cpu()) | |
| 185 | + return 0; | |
| 186 | + | |
| 167 | 187 | pdev = platform_device_register_simple("qcom-spm-cpuidle", |
| 168 | 188 | -1, NULL, 0); |
| 169 | 189 | if (IS_ERR(pdev)) { |
| @@ -54,6 +54,18 @@ config ARM_SCMI_TRANSPORT_MAILBOX · 53 unmodified lines | ||
| 54 | 54 | If you want the ARM SCMI PROTOCOL stack to include support for a |
| 55 | 55 | transport based on mailboxes, answer Y. |
| 56 | 56 | |
| 57 | +config ARM_SCMI_TRANSPORT_OPTEE | |
| 58 | + bool "SCMI transport based on OP-TEE service" | |
| 59 | + depends on OPTEE=y || OPTEE=ARM_SCMI_PROTOCOL | |
| 60 | + select ARM_SCMI_HAVE_TRANSPORT | |
| 61 | + select ARM_SCMI_HAVE_SHMEM | |
| 62 | + default y | |
| 63 | + help | |
| 64 | + This enables the OP-TEE service based transport for SCMI. | |
| 65 | + | |
| 66 | + If you want the ARM SCMI PROTOCOL stack to include support for a | |
| 67 | + transport based on OP-TEE SCMI service, answer Y. | |
| 68 | + | |
| 57 | 69 | config ARM_SCMI_TRANSPORT_SMC |
| 58 | 70 | bool "SCMI transport based on SMC" |
| 59 | 71 | depends on HAVE_ARM_SMCCC_DISCOVERY |
| @@ -66,6 +78,20 @@ config ARM_SCMI_TRANSPORT_SMC · 6 unmodified lines | ||
| 66 | 78 | If you want the ARM SCMI PROTOCOL stack to include support for a |
| 67 | 79 | transport based on SMC, answer Y. |
| 68 | 80 | |
| 81 | +config ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE | |
| 82 | + bool "Enable atomic mode support for SCMI SMC transport" | |
| 83 | + depends on ARM_SCMI_TRANSPORT_SMC | |
| 84 | + help | |
| 85 | + Enable support of atomic operation for SCMI SMC based transport. | |
| 86 | + | |
| 87 | + If you want the SCMI SMC based transport to operate in atomic | |
| 88 | + mode, avoiding any kind of sleeping behaviour for selected | |
| 89 | + transactions on the TX path, answer Y. | |
| 90 | + Enabling atomic mode operations allows any SCMI driver using this | |
| 91 | + transport to optionally ask for atomic SCMI transactions and operate | |
| 92 | + in atomic context too, at the price of using a number of busy-waiting | |
| 93 | + primitives all over instead. If unsure say N. | |
| 94 | + | |
| 69 | 95 | config ARM_SCMI_TRANSPORT_VIRTIO |
| 70 | 96 | bool "SCMI transport based on VirtIO" |
| 71 | 97 | depends on VIRTIO=y || VIRTIO=ARM_SCMI_PROTOCOL |
| @@ -77,6 +103,36 @@ config ARM_SCMI_TRANSPORT_VIRTIO · 5 unmodified lines | ||
| 77 | 103 | If you want the ARM SCMI PROTOCOL stack to include support for a |
| 78 | 104 | transport based on VirtIO, answer Y. |
| 79 | 105 | |
| 106 | +config ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE | |
| 107 | + bool "SCMI VirtIO transport Version 1 compliance" | |
| 108 | + depends on ARM_SCMI_TRANSPORT_VIRTIO | |
| 109 | + default y | |
| 110 | + help | |
| 111 | + This enforces strict compliance with VirtIO Version 1 specification. | |
| 112 | + | |
| 113 | + If you want the ARM SCMI VirtIO transport layer to refuse to work | |
| 114 | + with Legacy VirtIO backends and instead support only VirtIO Version 1 | |
| 115 | + devices (or above), answer Y. | |
| 116 | + | |
| 117 | + If you want instead to support also old Legacy VirtIO backends (like | |
| 118 | + the ones implemented by kvmtool) and let the core Kernel VirtIO layer | |
| 119 | + take care of the needed conversions, say N. | |
| 120 | + | |
| 121 | +config ARM_SCMI_TRANSPORT_VIRTIO_ATOMIC_ENABLE | |
| 122 | + bool "Enable atomic mode for SCMI VirtIO transport" | |
| 123 | + depends on ARM_SCMI_TRANSPORT_VIRTIO | |
| 124 | + help | |
| 125 | + Enable support of atomic operation for SCMI VirtIO based transport. | |
| 126 | + | |
| 127 | + If you want the SCMI VirtIO based transport to operate in atomic | |
| 128 | + mode, avoiding any kind of sleeping behaviour for selected | |
| 129 | + transactions on the TX path, answer Y. | |
| 130 | + | |
| 131 | + Enabling atomic mode operations allows any SCMI driver using this | |
| 132 | + transport to optionally ask for atomic SCMI transactions and operate | |
| 133 | + in atomic context too, at the price of using a number of busy-waiting | |
| 134 | + primitives all over instead. If unsure say N. | |
| 135 | + | |
| 80 | 136 | endif #ARM_SCMI_PROTOCOL |
| 81 | 137 | |
| 82 | 138 | config ARM_SCMI_POWER_DOMAIN |
| @@ -6,8 +6,16 @@ scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_MAILBOX) += mailbox.o · 5 unmodified lines | ||
| 6 | 6 | scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_SMC) += smc.o |
| 7 | 7 | scmi-transport-$(CONFIG_ARM_SCMI_HAVE_MSG) += msg.o |
| 8 | 8 | scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO) += virtio.o |
| 9 | +scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += optee.o | |
| 9 | 10 | scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o |
| 10 | 11 | scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \ |
| 11 | 12 | $(scmi-transport-y) |
| 12 | 13 | obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o |
| 13 | 14 | obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o |
| 15 | + | |
| 16 | +ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy) | |
| 17 | +# The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame | |
| 18 | +# pointer in Thumb2 mode, which is forcibly enabled by Clang when profiling | |
| 19 | +# hooks are inserted via the -pg switch. | |
| 20 | +CFLAGS_REMOVE_smc.o += $(CC_FLAGS_FTRACE) | |
| 21 | +endif | |
| @@ -27,7 +27,8 @@ struct scmi_msg_resp_clock_protocol_attributes { · 26 unmodified lines | ||
| 27 | 27 | struct scmi_msg_resp_clock_attributes { |
| 28 | 28 | __le32 attributes; |
| 29 | 29 | #define CLOCK_ENABLE BIT(0) |
| 30 | − u8 name[SCMI_MAX_STR_SIZE]; | |
| 30 | + u8 name[SCMI_MAX_STR_SIZE]; | |
| 31 | + __le32 clock_enable_latency; | |
| 31 | 32 | }; |
| 32 | 33 | |
| 33 | 34 | struct scmi_clock_set_config { |
| @@ -116,10 +117,15 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph, · 82 unmodified lines | ||
| 116 | 117 | attr = t->rx.buf; |
| 117 | 118 | |
| 118 | 119 | ret = ph->xops->do_xfer(ph, t); |
| 119 | − if (!ret) | |
| 120 | + if (!ret) { | |
| 120 | 121 | strlcpy(clk->name, attr->name, SCMI_MAX_STR_SIZE); |
| 121 | − else | |
| 122 | + /* Is optional field clock_enable_latency provided ? */ | |
| 123 | + if (t->rx.len == sizeof(*attr)) | |
| 124 | + clk->enable_latency = | |
| 125 | + le32_to_cpu(attr->clock_enable_latency); | |
| 126 | + } else { | |
| 122 | 127 | clk->name[0] = '\0'; |
| 128 | + } | |
| 123 | 129 | |
| 124 | 130 | ph->xops->xfer_put(ph, t); |
| 125 | 131 | return ret; |
| @@ -273,7 +279,7 @@ static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph, · 147 unmodified lines | ||
| 273 | 279 | |
| 274 | 280 | static int |
| 275 | 281 | scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id, |
| 276 | − u32 config) | |
| 282 | + u32 config, bool atomic) | |
| 277 | 283 | { |
| 278 | 284 | int ret; |
| 279 | 285 | struct scmi_xfer *t; |
| @@ -284,6 +290,8 @@ scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id, · 4 unmodified lines | ||
| 284 | 290 | if (ret) |
| 285 | 291 | return ret; |
| 286 | 292 | |
| 293 | + t->hdr.poll_completion = atomic; | |
| 294 | + | |
| 287 | 295 | cfg = t->tx.buf; |
| 288 | 296 | cfg->id = cpu_to_le32(clk_id); |
| 289 | 297 | cfg->attributes = cpu_to_le32(config); |
| @@ -296,12 +304,24 @@ scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id, · 6 unmodified lines | ||
| 296 | 304 | |
| 297 | 305 | static int scmi_clock_enable(const struct scmi_protocol_handle *ph, u32 clk_id) |
| 298 | 306 | { |
| 299 | − return scmi_clock_config_set(ph, clk_id, CLOCK_ENABLE); | |
| 307 | + return scmi_clock_config_set(ph, clk_id, CLOCK_ENABLE, false); | |
| 300 | 308 | } |
| 301 | 309 | |
| 302 | 310 | static int scmi_clock_disable(const struct scmi_protocol_handle *ph, u32 clk_id) |
| 303 | 311 | { |
| 304 | − return scmi_clock_config_set(ph, clk_id, 0); | |
| 312 | + return scmi_clock_config_set(ph, clk_id, 0, false); | |
| 313 | +} | |
| 314 | + | |
| 315 | +static int scmi_clock_enable_atomic(const struct scmi_protocol_handle *ph, | |
| 316 | + u32 clk_id) | |
| 317 | +{ | |
| 318 | + return scmi_clock_config_set(ph, clk_id, CLOCK_ENABLE, true); | |
| 319 | +} | |
| 320 | + | |
| 321 | +static int scmi_clock_disable_atomic(const struct scmi_protocol_handle *ph, | |
| 322 | + u32 clk_id) | |
| 323 | +{ | |
| 324 | + return scmi_clock_config_set(ph, clk_id, 0, true); | |
| 305 | 325 | } |
| 306 | 326 | |
| 307 | 327 | static int scmi_clock_count_get(const struct scmi_protocol_handle *ph) |
| @@ -330,6 +350,8 @@ static const struct scmi_clk_proto_ops clk_proto_ops = { · 22 unmodified lines | ||
| 330 | 350 | .rate_set = scmi_clock_rate_set, |
| 331 | 351 | .enable = scmi_clock_enable, |
| 332 | 352 | .disable = scmi_clock_disable, |
| 353 | + .enable_atomic = scmi_clock_enable_atomic, | |
| 354 | + .disable_atomic = scmi_clock_disable_atomic, | |
| 333 | 355 | }; |
| 334 | 356 | |
| 335 | 357 | static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph) |
| @@ -339,11 +339,16 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id); · 338 unmodified lines | ||
| 339 | 339 | * @dev: Reference to device in the SCMI hierarchy corresponding to this |
| 340 | 340 | * channel |
| 341 | 341 | * @handle: Pointer to SCMI entity handle |
| 342 | + * @no_completion_irq: Flag to indicate that this channel has no completion | |
| 343 | + * interrupt mechanism for synchronous commands. | |
| 344 | + * This can be dynamically set by transports at run-time | |
| 345 | + * inside their provided .chan_setup(). | |
| 342 | 346 | * @transport_info: Transport layer related information |
| 343 | 347 | */ |
| 344 | 348 | struct scmi_chan_info { |
| 345 | 349 | struct device *dev; |
| 346 | 350 | struct scmi_handle *handle; |
| 351 | + bool no_completion_irq; | |
| 347 | 352 | void *transport_info; |
| 348 | 353 | }; |
| 349 | 354 | |
| @@ -373,7 +378,8 @@ struct scmi_transport_ops { · 23 unmodified lines | ||
| 373 | 378 | unsigned int (*get_max_msg)(struct scmi_chan_info *base_cinfo); |
| 374 | 379 | int (*send_message)(struct scmi_chan_info *cinfo, |
| 375 | 380 | struct scmi_xfer *xfer); |
| 376 | − void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret); | |
| 381 | + void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret, | |
| 382 | + struct scmi_xfer *xfer); | |
| 377 | 383 | void (*fetch_response)(struct scmi_chan_info *cinfo, |
| 378 | 384 | struct scmi_xfer *xfer); |
| 379 | 385 | void (*fetch_notification)(struct scmi_chan_info *cinfo, |
| @@ -402,6 +408,18 @@ struct scmi_device *scmi_child_dev_find(struct device *parent, · 22 unmodified lines | ||
| 402 | 408 | * be pending simultaneously in the system. May be overridden by the |
| 403 | 409 | * get_max_msg op. |
| 404 | 410 | * @max_msg_size: Maximum size of data per message that can be handled. |
| 411 | + * @force_polling: Flag to force this whole transport to use SCMI core polling | |
| 412 | + * mechanism instead of completion interrupts even if available. | |
| 413 | + * @sync_cmds_completed_on_ret: Flag to indicate that the transport assures | |
| 414 | + * synchronous-command messages are atomically | |
| 415 | + * completed on .send_message: no need to poll | |
| 416 | + * actively waiting for a response. | |
| 417 | + * Used by core internally only when polling is | |
| 418 | + * selected as a waiting for reply method: i.e. | |
| 419 | + * if a completion irq was found use that anyway. | |
| 420 | + * @atomic_enabled: Flag to indicate that this transport, which is assured not | |
| 421 | + * to sleep anywhere on the TX path, can be used in atomic mode | |
| 422 | + * when requested. | |
| 405 | 423 | */ |
| 406 | 424 | struct scmi_desc { |
| 407 | 425 | int (*transport_init)(void); |
| @@ -410,6 +428,9 @@ struct scmi_desc { · 2 unmodified lines | ||
| 410 | 428 | int max_rx_timeout_ms; |
| 411 | 429 | int max_msg; |
| 412 | 430 | int max_msg_size; |
| 431 | + const bool force_polling; | |
| 432 | + const bool sync_cmds_completed_on_ret; | |
| 433 | + const bool atomic_enabled; | |
| 413 | 434 | }; |
| 414 | 435 | |
| 415 | 436 | #ifdef CONFIG_ARM_SCMI_TRANSPORT_MAILBOX |
| @@ -421,6 +442,9 @@ extern const struct scmi_desc scmi_smc_desc; · 5 unmodified lines | ||
| 421 | 442 | #ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO |
| 422 | 443 | extern const struct scmi_desc scmi_virtio_desc; |
| 423 | 444 | #endif |
| 445 | +#ifdef CONFIG_ARM_SCMI_TRANSPORT_OPTEE | |
| 446 | +extern const struct scmi_desc scmi_optee_desc; | |
| 447 | +#endif | |
| 424 | 448 | |
| 425 | 449 | void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr, void *priv); |
| 426 | 450 | void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id); |
| @@ -131,6 +131,12 @@ struct scmi_protocol_instance { · 130 unmodified lines | ||
| 131 | 131 | * MAX_PROTOCOLS_IMP elements allocated by the base protocol |
| 132 | 132 | * @active_protocols: IDR storing device_nodes for protocols actually defined |
| 133 | 133 | * in the DT and confirmed as implemented by fw. |
| 134 | + * @atomic_threshold: Optional system wide DT-configured threshold, expressed | |
| 135 | + * in microseconds, for atomic operations. | |
| 136 | + * Only SCMI synchronous commands reported by the platform | |
| 137 | + * to have an execution latency lesser-equal to the threshold | |
| 138 | + * should be considered for atomic mode operation: such | |
| 139 | + * decision is finally left up to the SCMI drivers. | |
| 134 | 140 | * @notify_priv: Pointer to private data structure specific to notifications. |
| 135 | 141 | * @node: List head |
| 136 | 142 | * @users: Number of users of this instance |
| @@ -149,6 +155,7 @@ struct scmi_info { · 12 unmodified lines | ||
| 149 | 155 | struct mutex protocols_mtx; |
| 150 | 156 | u8 *protocols_imp; |
| 151 | 157 | struct idr active_protocols; |
| 158 | + unsigned int atomic_threshold; | |
| 152 | 159 | void *notify_priv; |
| 153 | 160 | struct list_head node; |
| 154 | 161 | int users; |
| @@ -609,6 +616,25 @@ static inline void scmi_clear_channel(struct scmi_info *info, · 454 unmodified lines | ||
| 609 | 616 | info->desc->ops->clear_channel(cinfo); |
| 610 | 617 | } |
| 611 | 618 | |
| 619 | +static inline bool is_polling_required(struct scmi_chan_info *cinfo, | |
| 620 | + struct scmi_info *info) | |
| 621 | +{ | |
| 622 | + return cinfo->no_completion_irq || info->desc->force_polling; | |
| 623 | +} | |
| 624 | + | |
| 625 | +static inline bool is_transport_polling_capable(struct scmi_info *info) | |
| 626 | +{ | |
| 627 | + return info->desc->ops->poll_done || | |
| 628 | + info->desc->sync_cmds_completed_on_ret; | |
| 629 | +} | |
| 630 | + | |
| 631 | +static inline bool is_polling_enabled(struct scmi_chan_info *cinfo, | |
| 632 | + struct scmi_info *info) | |
| 633 | +{ | |
| 634 | + return is_polling_required(cinfo, info) && | |
| 635 | + is_transport_polling_capable(info); | |
| 636 | +} | |
| 637 | + | |
| 612 | 638 | static void scmi_handle_notification(struct scmi_chan_info *cinfo, |
| 613 | 639 | u32 msg_hdr, void *priv) |
| 614 | 640 | { |
| @@ -629,7 +655,8 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo, · 14 unmodified lines | ||
| 629 | 655 | |
| 630 | 656 | unpack_scmi_header(msg_hdr, &xfer->hdr); |
| 631 | 657 | if (priv) |
| 632 | − xfer->priv = priv; | |
| 658 | + /* Ensure order between xfer->priv store and following ops */ | |
| 659 | + smp_store_mb(xfer->priv, priv); | |
| 633 | 660 | info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size, |
| 634 | 661 | xfer); |
| 635 | 662 | scmi_notify(cinfo->handle, xfer->hdr.protocol_id, |
| @@ -661,7 +688,8 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo, · 25 unmodified lines | ||
| 661 | 688 | xfer->rx.len = info->desc->max_msg_size; |
| 662 | 689 | |
| 663 | 690 | if (priv) |
| 664 | − xfer->priv = priv; | |
| 691 | + /* Ensure order between xfer->priv store and following ops */ | |
| 692 | + smp_store_mb(xfer->priv, priv); | |
| 665 | 693 | info->desc->ops->fetch_response(cinfo, xfer); |
| 666 | 694 | |
| 667 | 695 | trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id, |
| @@ -724,8 +752,6 @@ static void xfer_put(const struct scmi_protocol_handle *ph, · 56 unmodified lines | ||
| 724 | 752 | __scmi_xfer_put(&info->tx_minfo, xfer); |
| 725 | 753 | } |
| 726 | 754 | |
| 727 | −#define SCMI_MAX_POLL_TO_NS (100 * NSEC_PER_USEC) | |
| 728 | − | |
| 729 | 755 | static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo, |
| 730 | 756 | struct scmi_xfer *xfer, ktime_t stop) |
| 731 | 757 | { |
| @@ -740,6 +766,79 @@ static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo, · 8 unmodified lines | ||
| 740 | 766 | ktime_after(ktime_get(), stop); |
| 741 | 767 | } |
| 742 | 768 | |
| 769 | +/** | |
| 770 | + * scmi_wait_for_message_response - An helper to group all the possible ways of | |
| 771 | + * waiting for a synchronous message response. | |
| 772 | + * | |
| 773 | + * @cinfo: SCMI channel info | |
| 774 | + * @xfer: Reference to the transfer being waited for. | |
| 775 | + * | |
| 776 | + * Chooses waiting strategy (sleep-waiting vs busy-waiting) depending on | |
| 777 | + * configuration flags like xfer->hdr.poll_completion. | |
| 778 | + * | |
| 779 | + * Return: 0 on Success, error otherwise. | |
| 780 | + */ | |
| 781 | +static int scmi_wait_for_message_response(struct scmi_chan_info *cinfo, | |
| 782 | + struct scmi_xfer *xfer) | |
| 783 | +{ | |
| 784 | + struct scmi_info *info = handle_to_scmi_info(cinfo->handle); | |
| 785 | + struct device *dev = info->dev; | |
| 786 | + int ret = 0, timeout_ms = info->desc->max_rx_timeout_ms; | |
| 787 | + | |
| 788 | + trace_scmi_xfer_response_wait(xfer->transfer_id, xfer->hdr.id, | |
| 789 | + xfer->hdr.protocol_id, xfer->hdr.seq, | |
| 790 | + timeout_ms, | |
| 791 | + xfer->hdr.poll_completion); | |
| 792 | + | |
| 793 | + if (xfer->hdr.poll_completion) { | |
| 794 | + /* | |
| 795 | + * Real polling is needed only if transport has NOT declared | |
| 796 | + * itself to support synchronous commands replies. | |
| 797 | + */ | |
| 798 | + if (!info->desc->sync_cmds_completed_on_ret) { | |
| 799 | + /* | |
| 800 | + * Poll on xfer using transport provided .poll_done(); | |
| 801 | + * assumes no completion interrupt was available. | |
| 802 | + */ | |
| 803 | + ktime_t stop = ktime_add_ms(ktime_get(), timeout_ms); | |
| 804 | + | |
| 805 | + spin_until_cond(scmi_xfer_done_no_timeout(cinfo, | |
| 806 | + xfer, stop)); | |
| 807 | + if (ktime_after(ktime_get(), stop)) { | |
| 808 | + dev_err(dev, | |
| 809 | + "timed out in resp(caller: %pS) - polling\n", | |
| 810 | + (void *)_RET_IP_); | |
| 811 | + ret = -ETIMEDOUT; | |
| 812 | + } | |
| 813 | + } | |
| 814 | + | |
| 815 | + if (!ret) { | |
| 816 | + unsigned long flags; | |
| 817 | + | |
| 818 | + /* | |
| 819 | + * Do not fetch_response if an out-of-order delayed | |
| 820 | + * response is being processed. | |
| 821 | + */ | |
| 822 | + spin_lock_irqsave(&xfer->lock, flags); | |
| 823 | + if (xfer->state == SCMI_XFER_SENT_OK) { | |
| 824 | + info->desc->ops->fetch_response(cinfo, xfer); | |
| 825 | + xfer->state = SCMI_XFER_RESP_OK; | |
| 826 | + } | |
| 827 | + spin_unlock_irqrestore(&xfer->lock, flags); | |
| 828 | + } | |
| 829 | + } else { | |
| 830 | + /* And we wait for the response. */ | |
| 831 | + if (!wait_for_completion_timeout(&xfer->done, | |
| 832 | + msecs_to_jiffies(timeout_ms))) { | |
| 833 | + dev_err(dev, "timed out in resp(caller: %pS)\n", | |
| 834 | + (void *)_RET_IP_); | |
| 835 | + ret = -ETIMEDOUT; | |
| 836 | + } | |
| 837 | + } | |
| 838 | + | |
| 839 | + return ret; | |
| 840 | +} | |
| 841 | + | |
| 743 | 842 | /** |
| 744 | 843 | * do_xfer() - Do one transfer |
| 745 | 844 | * |
| @@ -754,18 +853,26 @@ static int do_xfer(const struct scmi_protocol_handle *ph, · 8 unmodified lines | ||
| 754 | 853 | struct scmi_xfer *xfer) |
| 755 | 854 | { |
| 756 | 855 | int ret; |
| 757 | − int timeout; | |
| 758 | 856 | const struct scmi_protocol_instance *pi = ph_to_pi(ph); |
| 759 | 857 | struct scmi_info *info = handle_to_scmi_info(pi->handle); |
| 760 | 858 | struct device *dev = info->dev; |
| 761 | 859 | struct scmi_chan_info *cinfo; |
| 762 | 860 | |
| 763 | − if (xfer->hdr.poll_completion && !info->desc->ops->poll_done) { | |
| 861 | + /* Check for polling request on custom command xfers at first */ | |
| 862 | + if (xfer->hdr.poll_completion && !is_transport_polling_capable(info)) { | |
| 764 | 863 | dev_warn_once(dev, |
| 765 | 864 | "Polling mode is not supported by transport.\n"); |
| 766 | 865 | return -EINVAL; |
| 767 | 866 | } |
| 768 | 867 | |
| 868 | + cinfo = idr_find(&info->tx_idr, pi->proto->id); | |
| 869 | + if (unlikely(!cinfo)) | |
| 870 | + return -EINVAL; | |
| 871 | + | |
| 872 | + /* True ONLY if also supported by transport. */ | |
| 873 | + if (is_polling_enabled(cinfo, info)) | |
| 874 | + xfer->hdr.poll_completion = true; | |
| 875 | + | |
| 769 | 876 | /* |
| 770 | 877 | * Initialise protocol id now from protocol handle to avoid it being |
| 771 | 878 | * overridden by mistake (or malice) by the protocol code mangling with |
| @@ -774,10 +881,6 @@ static int do_xfer(const struct scmi_protocol_handle *ph, · 2 unmodified lines | ||
| 774 | 881 | xfer->hdr.protocol_id = pi->proto->id; |
| 775 | 882 | reinit_completion(&xfer->done); |
| 776 | 883 | |
| 777 | − cinfo = idr_find(&info->tx_idr, xfer->hdr.protocol_id); | |
| 778 | − if (unlikely(!cinfo)) | |
| 779 | − return -EINVAL; | |
| 780 | − | |
| 781 | 884 | trace_scmi_xfer_begin(xfer->transfer_id, xfer->hdr.id, |
| 782 | 885 | xfer->hdr.protocol_id, xfer->hdr.seq, |
| 783 | 886 | xfer->hdr.poll_completion); |
| @@ -798,41 +901,12 @@ static int do_xfer(const struct scmi_protocol_handle *ph, · 14 unmodified lines | ||
| 798 | 901 | return ret; |
| 799 | 902 | } |
| 800 | 903 | |
| 801 | − if (xfer->hdr.poll_completion) { | |
| 802 | − ktime_t stop = ktime_add_ns(ktime_get(), SCMI_MAX_POLL_TO_NS); | |
| 803 | − | |
| 804 | − spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop)); | |
| 805 | − if (ktime_before(ktime_get(), stop)) { | |
| 806 | − unsigned long flags; | |
| 807 | − | |
| 808 | − /* | |
| 809 | − * Do not fetch_response if an out-of-order delayed | |
| 810 | − * response is being processed. | |
| 811 | − */ | |
| 812 | − spin_lock_irqsave(&xfer->lock, flags); | |
| 813 | − if (xfer->state == SCMI_XFER_SENT_OK) { | |
| 814 | − info->desc->ops->fetch_response(cinfo, xfer); | |
| 815 | − xfer->state = SCMI_XFER_RESP_OK; | |
| 816 | − } | |
| 817 | − spin_unlock_irqrestore(&xfer->lock, flags); | |
| 818 | − } else { | |
| 819 | − ret = -ETIMEDOUT; | |
| 820 | − } | |
| 821 | − } else { | |
| 822 | − /* And we wait for the response. */ | |
| 823 | − timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms); | |
| 824 | − if (!wait_for_completion_timeout(&xfer->done, timeout)) { | |
| 825 | − dev_err(dev, "timed out in resp(caller: %pS)\n", | |
| 826 | − (void *)_RET_IP_); | |
| 827 | − ret = -ETIMEDOUT; | |
| 828 | − } | |
| 829 | − } | |
| 830 | − | |
| 904 | + ret = scmi_wait_for_message_response(cinfo, xfer); | |
| 831 | 905 | if (!ret && xfer->hdr.status) |
| 832 | 906 | ret = scmi_to_linux_errno(xfer->hdr.status); |
| 833 | 907 | |
| 834 | 908 | if (info->desc->ops->mark_txdone) |
| 835 | − info->desc->ops->mark_txdone(cinfo, ret); | |
| 909 | + info->desc->ops->mark_txdone(cinfo, ret, xfer); | |
| 836 | 910 | |
| 837 | 911 | trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id, |
| 838 | 912 | xfer->hdr.protocol_id, xfer->hdr.seq, ret); |
| @@ -858,6 +932,20 @@ static void reset_rx_to_maxsz(const struct scmi_protocol_handle *ph, · 19 unmodified lines | ||
| 858 | 932 | * @ph: Pointer to SCMI protocol handle |
| 859 | 933 | * @xfer: Transfer to initiate and wait for response |
| 860 | 934 | * |
| 935 | + * Using asynchronous commands in atomic/polling mode should be avoided since | |
| 936 | + * it could cause long busy-waiting here, so ignore polling for the delayed | |
| 937 | + * response and WARN if it was requested for this command transaction since | |
| 938 | + * upper layers should refrain from issuing such kind of requests. | |
| 939 | + * | |
| 940 | + * The only other option would have been to refrain from using any asynchronous | |
| 941 | + * command even if made available, when an atomic transport is detected, and | |
| 942 | + * instead forcibly use the synchronous version (thing that can be easily | |
| 943 | + * attained at the protocol layer), but this would also have led to longer | |
| 944 | + * stalls of the channel for synchronous commands and possibly timeouts. | |
| 945 | + * (in other words there is usually a good reason if a platform provides an | |
| 946 | + * asynchronous version of a command and we should prefer to use it...just not | |
| 947 | + * when using atomic/polling mode) | |
| 948 | + * | |
| 861 | 949 | * Return: -ETIMEDOUT in case of no delayed response, if transmit error, |
| 862 | 950 | * return corresponding error, else if all goes well, return 0. |
| 863 | 951 | */ |
| @@ -869,12 +957,24 @@ static int do_xfer_with_response(const struct scmi_protocol_handle *ph, · 5 unmodified lines | ||
| 869 | 957 | |
| 870 | 958 | xfer->async_done = &async_response; |
| 871 | 959 | |
| 960 | + /* | |
| 961 | + * Delayed responses should not be polled, so an async command should | |
| 962 | + * not have been used when requiring an atomic/poll context; WARN and | |
| 963 | + * perform instead a sleeping wait. | |
| 964 | + * (Note Async + IgnoreDelayedResponses are sent via do_xfer) | |
| 965 | + */ | |
| 966 | + WARN_ON_ONCE(xfer->hdr.poll_completion); | |
| 967 | + | |
| 872 | 968 | ret = do_xfer(ph, xfer); |
| 873 | 969 | if (!ret) { |
| 874 | − if (!wait_for_completion_timeout(xfer->async_done, timeout)) | |
| 970 | + if (!wait_for_completion_timeout(xfer->async_done, timeout)) { | |
| 971 | + dev_err(ph->dev, | |
| 972 | + "timed out in delayed resp(caller: %pS)\n", | |
| 973 | + (void *)_RET_IP_); | |
| 875 | 974 | ret = -ETIMEDOUT; |
| 876 | − else if (xfer->hdr.status) | |
| 975 | + } else if (xfer->hdr.status) { | |
| 877 | 976 | ret = scmi_to_linux_errno(xfer->hdr.status); |
| 977 | + } | |
| 878 | 978 | } |
| 879 | 979 | |
| 880 | 980 | xfer->async_done = NULL; |
| @@ -1308,6 +1408,29 @@ static void scmi_devm_protocol_put(struct scmi_device *sdev, u8 protocol_id) · 427 unmodified lines | ||
| 1308 | 1408 | WARN_ON(ret); |
| 1309 | 1409 | } |
| 1310 | 1410 | |
| 1411 | +/** | |
| 1412 | + * scmi_is_transport_atomic - Method to check if underlying transport for an | |
| 1413 | + * SCMI instance is configured as atomic. | |
| 1414 | + * | |
| 1415 | + * @handle: A reference to the SCMI platform instance. | |
| 1416 | + * @atomic_threshold: An optional return value for the system wide currently | |
| 1417 | + * configured threshold for atomic operations. | |
| 1418 | + * | |
| 1419 | + * Return: True if transport is configured as atomic | |
| 1420 | + */ | |
| 1421 | +static bool scmi_is_transport_atomic(const struct scmi_handle *handle, | |
| 1422 | + unsigned int *atomic_threshold) | |
| 1423 | +{ | |
| 1424 | + bool ret; | |
| 1425 | + struct scmi_info *info = handle_to_scmi_info(handle); | |
| 1426 | + | |
| 1427 | + ret = info->desc->atomic_enabled && is_transport_polling_capable(info); | |
| 1428 | + if (ret && atomic_threshold) | |
| 1429 | + *atomic_threshold = info->atomic_threshold; | |
| 1430 | + | |
| 1431 | + return ret; | |
| 1432 | +} | |
| 1433 | + | |
| 1311 | 1434 | static inline |
| 1312 | 1435 | struct scmi_handle *scmi_handle_get_from_info_unlocked(struct scmi_info *info) |
| 1313 | 1436 | { |
| @@ -1499,6 +1622,16 @@ static int scmi_chan_setup(struct scmi_info *info, struct device *dev, · 185 unmodified lines | ||
| 1499 | 1622 | if (ret) |
| 1500 | 1623 | return ret; |
| 1501 | 1624 | |
| 1625 | + if (tx && is_polling_required(cinfo, info)) { | |
| 1626 | + if (is_transport_polling_capable(info)) | |
| 1627 | + dev_info(dev, | |
| 1628 | + "Enabled polling mode TX channel - prot_id:%d\n", | |
| 1629 | + prot_id); | |
| 1630 | + else | |
| 1631 | + dev_warn(dev, | |
| 1632 | + "Polling mode NOT supported by transport.\n"); | |
| 1633 | + } | |
| 1634 | + | |
| 1502 | 1635 | idr_alloc: |
| 1503 | 1636 | ret = idr_alloc(idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL); |
| 1504 | 1637 | if (ret != prot_id) { |
| @@ -1836,6 +1969,14 @@ static int scmi_probe(struct platform_device *pdev) · 331 unmodified lines | ||
| 1836 | 1969 | handle->devm_protocol_get = scmi_devm_protocol_get; |
| 1837 | 1970 | handle->devm_protocol_put = scmi_devm_protocol_put; |
| 1838 | 1971 | |
| 1972 | + /* System wide atomic threshold for atomic ops .. if any */ | |
| 1973 | + if (!of_property_read_u32(np, "atomic-threshold-us", | |
| 1974 | + &info->atomic_threshold)) | |
| 1975 | + dev_info(dev, | |
| 1976 | + "SCMI System wide atomic threshold set to %d us\n", | |
| 1977 | + info->atomic_threshold); | |
| 1978 | + handle->is_transport_atomic = scmi_is_transport_atomic; | |
| 1979 | + | |
| 1839 | 1980 | if (desc->ops->link_supplier) { |
| 1840 | 1981 | ret = desc->ops->link_supplier(dev); |
| 1841 | 1982 | if (ret) |
| @@ -1853,6 +1994,10 @@ static int scmi_probe(struct platform_device *pdev) · 11 unmodified lines | ||
| 1853 | 1994 | if (scmi_notification_init(handle)) |
| 1854 | 1995 | dev_err(dev, "SCMI Notifications NOT available.\n"); |
| 1855 | 1996 | |
| 1997 | + if (info->desc->atomic_enabled && !is_transport_polling_capable(info)) | |
| 1998 | + dev_err(dev, | |
| 1999 | + "Transport is not polling capable. Atomic mode not supported.\n"); | |
| 2000 | + | |
| 1856 | 2001 | /* |
| 1857 | 2002 | * Trigger SCMI Base protocol initialization. |
| 1858 | 2003 | * It's mandatory and won't be ever released/deinit until the |
| @@ -1994,6 +2139,9 @@ static const struct of_device_id scmi_of_match[] = { · 135 unmodified lines | ||
| 1994 | 2139 | #ifdef CONFIG_ARM_SCMI_TRANSPORT_MAILBOX |
| 1995 | 2140 | { .compatible = "arm,scmi", .data = &scmi_mailbox_desc }, |
| 1996 | 2141 | #endif |
| 2142 | +#ifdef CONFIG_ARM_SCMI_TRANSPORT_OPTEE | |
| 2143 | + { .compatible = "linaro,scmi-optee", .data = &scmi_optee_desc }, | |
| 2144 | +#endif | |
| 1997 | 2145 | #ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC |
| 1998 | 2146 | { .compatible = "arm,scmi-smc", .data = &scmi_smc_desc}, |
| 1999 | 2147 | #endif |
| @@ -140,7 +140,8 @@ static int mailbox_send_message(struct scmi_chan_info *cinfo, · 139 unmodified lines | ||
| 140 | 140 | return ret; |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | −static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret) | |
| 143 | +static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret, | |
| 144 | + struct scmi_xfer *__unused) | |
| 144 | 145 | { |
| 145 | 146 | struct scmi_mailbox *smbox = cinfo->transport_info; |
| 146 | 147 | |
| @@ -0,0 +1,567 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +/* | |
| 3 | + * Copyright (C) 2019-2021 Linaro Ltd. | |
| 4 | + */ | |
| 5 | + | |
| 6 | +#include <linux/io.h> | |
| 7 | +#include <linux/of.h> | |
| 8 | +#include <linux/of_address.h> | |
| 9 | +#include <linux/kernel.h> | |
| 10 | +#include <linux/module.h> | |
| 11 | +#include <linux/mutex.h> | |
| 12 | +#include <linux/slab.h> | |
| 13 | +#include <linux/tee_drv.h> | |
| 14 | +#include <linux/uuid.h> | |
| 15 | +#include <uapi/linux/tee.h> | |
| 16 | + | |
| 17 | +#include "common.h" | |
| 18 | + | |
| 19 | +#define SCMI_OPTEE_MAX_MSG_SIZE 128 | |
| 20 | + | |
| 21 | +enum scmi_optee_pta_cmd { | |
| 22 | + /* | |
| 23 | + * PTA_SCMI_CMD_CAPABILITIES - Get channel capabilities | |
| 24 | + * | |
| 25 | + * [out] value[0].a: Capability bit mask (enum pta_scmi_caps) | |
| 26 | + * [out] value[0].b: Extended capabilities or 0 | |
| 27 | + */ | |
| 28 | + PTA_SCMI_CMD_CAPABILITIES = 0, | |
| 29 | + | |
| 30 | + /* | |
| 31 | + * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL - Process SCMI message in SMT buffer | |
| 32 | + * | |
| 33 | + * [in] value[0].a: Channel handle | |
| 34 | + * | |
| 35 | + * Shared memory used for SCMI message/response exhange is expected | |
| 36 | + * already identified and bound to channel handle in both SCMI agent | |
| 37 | + * and SCMI server (OP-TEE) parts. | |
| 38 | + * The memory uses SMT header to carry SCMI meta-data (protocol ID and | |
| 39 | + * protocol message ID). | |
| 40 | + */ | |
| 41 | + PTA_SCMI_CMD_PROCESS_SMT_CHANNEL = 1, | |
| 42 | + | |
| 43 | + /* | |
| 44 | + * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE - Process SMT/SCMI message | |
| 45 | + * | |
| 46 | + * [in] value[0].a: Channel handle | |
| 47 | + * [in/out] memref[1]: Message/response buffer (SMT and SCMI payload) | |
| 48 | + * | |
| 49 | + * Shared memory used for SCMI message/response is a SMT buffer | |
| 50 | + * referenced by param[1]. It shall be 128 bytes large to fit response | |
| 51 | + * payload whatever message playload size. | |
| 52 | + * The memory uses SMT header to carry SCMI meta-data (protocol ID and | |
| 53 | + * protocol message ID). | |
| 54 | + */ | |
| 55 | + PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE = 2, | |
| 56 | + | |
| 57 | + /* | |
| 58 | + * PTA_SCMI_CMD_GET_CHANNEL - Get channel handle | |
| 59 | + * | |
| 60 | + * SCMI shm information are 0 if agent expects to use OP-TEE regular SHM | |
| 61 | + * | |
| 62 | + * [in] value[0].a: Channel identifier | |
| 63 | + * [out] value[0].a: Returned channel handle | |
| 64 | + * [in] value[0].b: Requested capabilities mask (enum pta_scmi_caps) | |
| 65 | + */ | |
| 66 | + PTA_SCMI_CMD_GET_CHANNEL = 3, | |
| 67 | +}; | |
| 68 | + | |
| 69 | +/* | |
| 70 | + * OP-TEE SCMI service capabilities bit flags (32bit) | |
| 71 | + * | |
| 72 | + * PTA_SCMI_CAPS_SMT_HEADER | |
| 73 | + * When set, OP-TEE supports command using SMT header protocol (SCMI shmem) in | |
| 74 | + * shared memory buffers to carry SCMI protocol synchronisation information. | |
| 75 | + */ | |
| 76 | +#define PTA_SCMI_CAPS_NONE 0 | |
| 77 | +#define PTA_SCMI_CAPS_SMT_HEADER BIT(0) | |
| 78 | + | |
| 79 | +/** | |
| 80 | + * struct scmi_optee_channel - Description of an OP-TEE SCMI channel | |
| 81 | + * | |
| 82 | + * @channel_id: OP-TEE channel ID used for this transport | |
| 83 | + * @tee_session: TEE session identifier | |
| 84 | + * @caps: OP-TEE SCMI channel capabilities | |
| 85 | + * @mu: Mutex protection on channel access | |
| 86 | + * @cinfo: SCMI channel information | |
| 87 | + * @shmem: Virtual base address of the shared memory | |
| 88 | + * @tee_shm: Reference to TEE shared memory or NULL if using static shmem | |
| 89 | + * @link: Reference in agent's channel list | |
| 90 | + */ | |
| 91 | +struct scmi_optee_channel { | |
| 92 | + u32 channel_id; | |
| 93 | + u32 tee_session; | |
| 94 | + u32 caps; | |
| 95 | + struct mutex mu; | |
| 96 | + struct scmi_chan_info *cinfo; | |
| 97 | + struct scmi_shared_mem __iomem *shmem; | |
| 98 | + struct tee_shm *tee_shm; | |
| 99 | + struct list_head link; | |
| 100 | +}; | |
| 101 | + | |
| 102 | +/** | |
| 103 | + * struct scmi_optee_agent - OP-TEE transport private data | |
| 104 | + * | |
| 105 | + * @dev: Device used for communication with TEE | |
| 106 | + * @tee_ctx: TEE context used for communication | |
| 107 | + * @caps: Supported channel capabilities | |
| 108 | + * @mu: Mutex for protection of @channel_list | |
| 109 | + * @channel_list: List of all created channels for the agent | |
| 110 | + */ | |
| 111 | +struct scmi_optee_agent { | |
| 112 | + struct device *dev; | |
| 113 | + struct tee_context *tee_ctx; | |
| 114 | + u32 caps; | |
| 115 | + struct mutex mu; | |
| 116 | + struct list_head channel_list; | |
| 117 | +}; | |
| 118 | + | |
| 119 | +/* There can be only 1 SCMI service in OP-TEE we connect to */ | |
| 120 | +static struct scmi_optee_agent *scmi_optee_private; | |
| 121 | + | |
| 122 | +/* Forward reference to scmi_optee transport initialization */ | |
| 123 | +static int scmi_optee_init(void); | |
| 124 | + | |
| 125 | +/* Open a session toward SCMI OP-TEE service with REE_KERNEL identity */ | |
| 126 | +static int open_session(struct scmi_optee_agent *agent, u32 *tee_session) | |
| 127 | +{ | |
| 128 | + struct device *dev = agent->dev; | |
| 129 | + struct tee_client_device *scmi_pta = to_tee_client_device(dev); | |
| 130 | + struct tee_ioctl_open_session_arg arg = { }; | |
| 131 | + int ret; | |
| 132 | + | |
| 133 | + memcpy(arg.uuid, scmi_pta->id.uuid.b, TEE_IOCTL_UUID_LEN); | |
| 134 | + arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL; | |
| 135 | + | |
| 136 | + ret = tee_client_open_session(agent->tee_ctx, &arg, NULL); | |
| 137 | + if (ret < 0 || arg.ret) { | |
| 138 | + dev_err(dev, "Can't open tee session: %d / %#x\n", ret, arg.ret); | |
| 139 | + return -EOPNOTSUPP; | |
| 140 | + } | |
| 141 | + | |
| 142 | + *tee_session = arg.session; | |
| 143 | + | |
| 144 | + return 0; | |
| 145 | +} | |
| 146 | + | |
| 147 | +static void close_session(struct scmi_optee_agent *agent, u32 tee_session) | |
| 148 | +{ | |
| 149 | + tee_client_close_session(agent->tee_ctx, tee_session); | |
| 150 | +} | |
| 151 | + | |
| 152 | +static int get_capabilities(struct scmi_optee_agent *agent) | |
| 153 | +{ | |
| 154 | + struct tee_ioctl_invoke_arg arg = { }; | |
| 155 | + struct tee_param param[1] = { }; | |
| 156 | + u32 caps; | |
| 157 | + u32 tee_session; | |
| 158 | + int ret; | |
| 159 | + | |
| 160 | + ret = open_session(agent, &tee_session); | |
| 161 | + if (ret) | |
| 162 | + return ret; | |
| 163 | + | |
| 164 | + arg.func = PTA_SCMI_CMD_CAPABILITIES; | |
| 165 | + arg.session = tee_session; | |
| 166 | + arg.num_params = 1; | |
| 167 | + | |
| 168 | + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT; | |
| 169 | + | |
| 170 | + ret = tee_client_invoke_func(agent->tee_ctx, &arg, param); | |
| 171 | + | |
| 172 | + close_session(agent, tee_session); | |
| 173 | + | |
| 174 | + if (ret < 0 || arg.ret) { | |
| 175 | + dev_err(agent->dev, "Can't get capabilities: %d / %#x\n", ret, arg.ret); | |
| 176 | + return -EOPNOTSUPP; | |
| 177 | + } | |
| 178 | + | |
| 179 | + caps = param[0].u.value.a; | |
| 180 | + | |
| 181 | + if (!(caps & PTA_SCMI_CAPS_SMT_HEADER)) { | |
| 182 | + dev_err(agent->dev, "OP-TEE SCMI PTA doesn't support SMT\n"); | |
| 183 | + return -EOPNOTSUPP; | |
| 184 | + } | |
| 185 | + | |
| 186 | + agent->caps = caps; | |
| 187 | + | |
| 188 | + return 0; | |
| 189 | +} | |
| 190 | + | |
| 191 | +static int get_channel(struct scmi_optee_channel *channel) | |
| 192 | +{ | |
| 193 | + struct device *dev = scmi_optee_private->dev; | |
| 194 | + struct tee_ioctl_invoke_arg arg = { }; | |
| 195 | + struct tee_param param[1] = { }; | |
| 196 | + unsigned int caps = PTA_SCMI_CAPS_SMT_HEADER; | |
| 197 | + int ret; | |
| 198 | + | |
| 199 | + arg.func = PTA_SCMI_CMD_GET_CHANNEL; | |
| 200 | + arg.session = channel->tee_session; | |
| 201 | + arg.num_params = 1; | |
| 202 | + | |
| 203 | + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT; | |
| 204 | + param[0].u.value.a = channel->channel_id; | |
| 205 | + param[0].u.value.b = caps; | |
| 206 | + | |
| 207 | + ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param); | |
| 208 | + | |
| 209 | + if (ret || arg.ret) { | |
| 210 | + dev_err(dev, "Can't get channel with caps %#x: %d / %#x\n", caps, ret, arg.ret); | |
| 211 | + return -EOPNOTSUPP; | |
| 212 | + } | |
| 213 | + | |
| 214 | + /* From now on use channel identifer provided by OP-TEE SCMI service */ | |
| 215 | + channel->channel_id = param[0].u.value.a; | |
| 216 | + channel->caps = caps; | |
| 217 | + | |
| 218 | + return 0; | |
| 219 | +} | |
| 220 | + | |
| 221 | +static int invoke_process_smt_channel(struct scmi_optee_channel *channel) | |
| 222 | +{ | |
| 223 | + struct tee_ioctl_invoke_arg arg = { }; | |
| 224 | + struct tee_param param[2] = { }; | |
| 225 | + int ret; | |
| 226 | + | |
| 227 | + arg.session = channel->tee_session; | |
| 228 | + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; | |
| 229 | + param[0].u.value.a = channel->channel_id; | |
| 230 | + | |
| 231 | + if (channel->tee_shm) { | |
| 232 | + param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; | |
| 233 | + param[1].u.memref.shm = channel->tee_shm; | |
| 234 | + param[1].u.memref.size = SCMI_OPTEE_MAX_MSG_SIZE; | |
| 235 | + arg.num_params = 2; | |
| 236 | + arg.func = PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE; | |
| 237 | + } else { | |
| 238 | + arg.num_params = 1; | |
| 239 | + arg.func = PTA_SCMI_CMD_PROCESS_SMT_CHANNEL; | |
| 240 | + } | |
| 241 | + | |
| 242 | + ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param); | |
| 243 | + if (ret < 0 || arg.ret) { | |
| 244 | + dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n", | |
| 245 | + channel->channel_id, ret, arg.ret); | |
| 246 | + return -EIO; | |
| 247 | + } | |
| 248 | + | |
| 249 | + return 0; | |
| 250 | +} | |
| 251 | + | |
| 252 | +static int scmi_optee_link_supplier(struct device *dev) | |
| 253 | +{ | |
| 254 | + if (!scmi_optee_private) { | |
| 255 | + if (scmi_optee_init()) | |
| 256 | + dev_dbg(dev, "Optee bus not yet ready\n"); | |
| 257 | + | |
| 258 | + /* Wait for optee bus */ | |
| 259 | + return -EPROBE_DEFER; | |
| 260 | + } | |
| 261 | + | |
| 262 | + if (!device_link_add(dev, scmi_optee_private->dev, DL_FLAG_AUTOREMOVE_CONSUMER)) { | |
| 263 | + dev_err(dev, "Adding link to supplier optee device failed\n"); | |
| 264 | + return -ECANCELED; | |
| 265 | + } | |
| 266 | + | |
| 267 | + return 0; | |
| 268 | +} | |
| 269 | + | |
| 270 | +static bool scmi_optee_chan_available(struct device *dev, int idx) | |
| 271 | +{ | |
| 272 | + u32 channel_id; | |
| 273 | + | |
| 274 | + return !of_property_read_u32_index(dev->of_node, "linaro,optee-channel-id", | |
| 275 | + idx, &channel_id); | |
| 276 | +} | |
| 277 | + | |
| 278 | +static void scmi_optee_clear_channel(struct scmi_chan_info *cinfo) | |
| 279 | +{ | |
| 280 | + struct scmi_optee_channel *channel = cinfo->transport_info; | |
| 281 | + | |
| 282 | + shmem_clear_channel(channel->shmem); | |
| 283 | +} | |
| 284 | + | |
| 285 | +static int setup_static_shmem(struct device *dev, struct scmi_chan_info *cinfo, | |
| 286 | + struct scmi_optee_channel *channel) | |
| 287 | +{ | |
| 288 | + struct device_node *np; | |
| 289 | + resource_size_t size; | |
| 290 | + struct resource res; | |
| 291 | + int ret; | |
| 292 | + | |
| 293 | + np = of_parse_phandle(cinfo->dev->of_node, "shmem", 0); | |
| 294 | + if (!of_device_is_compatible(np, "arm,scmi-shmem")) { | |
| 295 | + ret = -ENXIO; | |
| 296 | + goto out; | |
| 297 | + } | |
| 298 | + | |
| 299 | + ret = of_address_to_resource(np, 0, &res); | |
| 300 | + if (ret) { | |
| 301 | + dev_err(dev, "Failed to get SCMI Tx shared memory\n"); | |
| 302 | + goto out; | |
| 303 | + } | |
| 304 | + | |
| 305 | + size = resource_size(&res); | |
| 306 | + | |
| 307 | + channel->shmem = devm_ioremap(dev, res.start, size); | |
| 308 | + if (!channel->shmem) { | |
| 309 | + dev_err(dev, "Failed to ioremap SCMI Tx shared memory\n"); | |
| 310 | + ret = -EADDRNOTAVAIL; | |
| 311 | + goto out; | |
| 312 | + } | |
| 313 | + | |
| 314 | + ret = 0; | |
| 315 | + | |
| 316 | +out: | |
| 317 | + of_node_put(np); | |
| 318 | + | |
| 319 | + return ret; | |
| 320 | +} | |
| 321 | + | |
| 322 | +static int setup_shmem(struct device *dev, struct scmi_chan_info *cinfo, | |
| 323 | + struct scmi_optee_channel *channel) | |
| 324 | +{ | |
| 325 | + if (of_find_property(cinfo->dev->of_node, "shmem", NULL)) | |
| 326 | + return setup_static_shmem(dev, cinfo, channel); | |
| 327 | + else | |
| 328 | + return -ENOMEM; | |
| 329 | +} | |
| 330 | + | |
| 331 | +static int scmi_optee_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, bool tx) | |
| 332 | +{ | |
| 333 | + struct scmi_optee_channel *channel; | |
| 334 | + uint32_t channel_id; | |
| 335 | + int ret; | |
| 336 | + | |
| 337 | + if (!tx) | |
| 338 | + return -ENODEV; | |
| 339 | + | |
| 340 | + channel = devm_kzalloc(dev, sizeof(*channel), GFP_KERNEL); | |
| 341 | + if (!channel) | |
| 342 | + return -ENOMEM; | |
| 343 | + | |
| 344 | + ret = of_property_read_u32_index(cinfo->dev->of_node, "linaro,optee-channel-id", | |
| 345 | + 0, &channel_id); | |
| 346 | + if (ret) | |
| 347 | + return ret; | |
| 348 | + | |
| 349 | + cinfo->transport_info = channel; | |
| 350 | + channel->cinfo = cinfo; | |
| 351 | + channel->channel_id = channel_id; | |
| 352 | + mutex_init(&channel->mu); | |
| 353 | + | |
| 354 | + ret = setup_shmem(dev, cinfo, channel); | |
| 355 | + if (ret) | |
| 356 | + return ret; | |
| 357 | + | |
| 358 | + ret = open_session(scmi_optee_private, &channel->tee_session); | |
| 359 | + if (ret) | |
| 360 | + goto err_free_shm; | |
| 361 | + | |
| 362 | + ret = get_channel(channel); | |
| 363 | + if (ret) | |
| 364 | + goto err_close_sess; | |
| 365 | + | |
| 366 | + /* Enable polling */ | |
| 367 | + cinfo->no_completion_irq = true; | |
| 368 | + | |
| 369 | + mutex_lock(&scmi_optee_private->mu); | |
| 370 | + list_add(&channel->link, &scmi_optee_private->channel_list); | |
| 371 | + mutex_unlock(&scmi_optee_private->mu); | |
| 372 | + | |
| 373 | + return 0; | |
| 374 | + | |
| 375 | +err_close_sess: | |
| 376 | + close_session(scmi_optee_private, channel->tee_session); | |
| 377 | +err_free_shm: | |
| 378 | + if (channel->tee_shm) | |
| 379 | + tee_shm_free(channel->tee_shm); | |
| 380 | + | |
| 381 | + return ret; | |
| 382 | +} | |
| 383 | + | |
| 384 | +static int scmi_optee_chan_free(int id, void *p, void *data) | |
| 385 | +{ | |
| 386 | + struct scmi_chan_info *cinfo = p; | |
| 387 | + struct scmi_optee_channel *channel = cinfo->transport_info; | |
| 388 | + | |
| 389 | + mutex_lock(&scmi_optee_private->mu); | |
| 390 | + list_del(&channel->link); | |
| 391 | + mutex_unlock(&scmi_optee_private->mu); | |
| 392 | + | |
| 393 | + close_session(scmi_optee_private, channel->tee_session); | |
| 394 | + | |
| 395 | + if (channel->tee_shm) { | |
| 396 | + tee_shm_free(channel->tee_shm); | |
| 397 | + channel->tee_shm = NULL; | |
| 398 | + } | |
| 399 | + | |
| 400 | + cinfo->transport_info = NULL; | |
| 401 | + channel->cinfo = NULL; | |
| 402 | + | |
| 403 | + scmi_free_channel(cinfo, data, id); | |
| 404 | + | |
| 405 | + return 0; | |
| 406 | +} | |
| 407 | + | |
| 408 | +static struct scmi_shared_mem *get_channel_shm(struct scmi_optee_channel *chan, | |
| 409 | + struct scmi_xfer *xfer) | |
| 410 | +{ | |
| 411 | + if (!chan) | |
| 412 | + return NULL; | |
| 413 | + | |
| 414 | + return chan->shmem; | |
| 415 | +} | |
| 416 | + | |
| 417 | + | |
| 418 | +static int scmi_optee_send_message(struct scmi_chan_info *cinfo, | |
| 419 | + struct scmi_xfer *xfer) | |
| 420 | +{ | |
| 421 | + struct scmi_optee_channel *channel = cinfo->transport_info; | |
| 422 | + struct scmi_shared_mem *shmem = get_channel_shm(channel, xfer); | |
| 423 | + int ret; | |
| 424 | + | |
| 425 | + mutex_lock(&channel->mu); | |
| 426 | + shmem_tx_prepare(shmem, xfer); | |
| 427 | + | |
| 428 | + ret = invoke_process_smt_channel(channel); | |
| 429 | + if (ret) | |
| 430 | + mutex_unlock(&channel->mu); | |
| 431 | + | |
| 432 | + return ret; | |
| 433 | +} | |
| 434 | + | |
| 435 | +static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo, | |
| 436 | + struct scmi_xfer *xfer) | |
| 437 | +{ | |
| 438 | + struct scmi_optee_channel *channel = cinfo->transport_info; | |
| 439 | + struct scmi_shared_mem *shmem = get_channel_shm(channel, xfer); | |
| 440 | + | |
| 441 | + shmem_fetch_response(shmem, xfer); | |
| 442 | +} | |
| 443 | + | |
| 444 | +static void scmi_optee_mark_txdone(struct scmi_chan_info *cinfo, int ret, | |
| 445 | + struct scmi_xfer *__unused) | |
| 446 | +{ | |
| 447 | + struct scmi_optee_channel *channel = cinfo->transport_info; | |
| 448 | + | |
| 449 | + mutex_unlock(&channel->mu); | |
| 450 | +} | |
| 451 | + | |
| 452 | +static struct scmi_transport_ops scmi_optee_ops = { | |
| 453 | + .link_supplier = scmi_optee_link_supplier, | |
| 454 | + .chan_available = scmi_optee_chan_available, | |
| 455 | + .chan_setup = scmi_optee_chan_setup, | |
| 456 | + .chan_free = scmi_optee_chan_free, | |
| 457 | + .send_message = scmi_optee_send_message, | |
| 458 | + .mark_txdone = scmi_optee_mark_txdone, | |
| 459 | + .fetch_response = scmi_optee_fetch_response, | |
| 460 | + .clear_channel = scmi_optee_clear_channel, | |
| 461 | +}; | |
| 462 | + | |
| 463 | +static int scmi_optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data) | |
| 464 | +{ | |
| 465 | + return ver->impl_id == TEE_IMPL_ID_OPTEE; | |
| 466 | +} | |
| 467 | + | |
| 468 | +static int scmi_optee_service_probe(struct device *dev) | |
| 469 | +{ | |
| 470 | + struct scmi_optee_agent *agent; | |
| 471 | + struct tee_context *tee_ctx; | |
| 472 | + int ret; | |
| 473 | + | |
| 474 | + /* Only one SCMI OP-TEE device allowed */ | |
| 475 | + if (scmi_optee_private) { | |
| 476 | + dev_err(dev, "An SCMI OP-TEE device was already initialized: only one allowed\n"); | |
| 477 | + return -EBUSY; | |
| 478 | + } | |
| 479 | + | |
| 480 | + tee_ctx = tee_client_open_context(NULL, scmi_optee_ctx_match, NULL, NULL); | |
| 481 | + if (IS_ERR(tee_ctx)) | |
| 482 | + return -ENODEV; | |
| 483 | + | |
| 484 | + agent = devm_kzalloc(dev, sizeof(*agent), GFP_KERNEL); | |
| 485 | + if (!agent) { | |
| 486 | + ret = -ENOMEM; | |
| 487 | + goto err; | |
| 488 | + } | |
| 489 | + | |
| 490 | + agent->dev = dev; | |
| 491 | + agent->tee_ctx = tee_ctx; | |
| 492 | + INIT_LIST_HEAD(&agent->channel_list); | |
| 493 | + mutex_init(&agent->mu); | |
| 494 | + | |
| 495 | + ret = get_capabilities(agent); | |
| 496 | + if (ret) | |
| 497 | + goto err; | |
| 498 | + | |
| 499 | + /* Ensure agent resources are all visible before scmi_optee_private is */ | |
| 500 | + smp_mb(); | |
| 501 | + scmi_optee_private = agent; | |
| 502 | + | |
| 503 | + return 0; | |
| 504 | + | |
| 505 | +err: | |
| 506 | + tee_client_close_context(tee_ctx); | |
| 507 | + | |
| 508 | + return ret; | |
| 509 | +} | |
| 510 | + | |
| 511 | +static int scmi_optee_service_remove(struct device *dev) | |
| 512 | +{ | |
| 513 | + struct scmi_optee_agent *agent = scmi_optee_private; | |
| 514 | + | |
| 515 | + if (!scmi_optee_private) | |
| 516 | + return -EINVAL; | |
| 517 | + | |
| 518 | + if (!list_empty(&scmi_optee_private->channel_list)) | |
| 519 | + return -EBUSY; | |
| 520 | + | |
| 521 | + /* Ensure cleared reference is visible before resources are released */ | |
| 522 | + smp_store_mb(scmi_optee_private, NULL); | |
| 523 | + | |
| 524 | + tee_client_close_context(agent->tee_ctx); | |
| 525 | + | |
| 526 | + return 0; | |
| 527 | +} | |
| 528 | + | |
| 529 | +static const struct tee_client_device_id scmi_optee_service_id[] = { | |
| 530 | + { | |
| 531 | + UUID_INIT(0xa8cfe406, 0xd4f5, 0x4a2e, | |
| 532 | + 0x9f, 0x8d, 0xa2, 0x5d, 0xc7, 0x54, 0xc0, 0x99) | |
| 533 | + }, | |
| 534 | + { } | |
| 535 | +}; | |
| 536 | + | |
| 537 | +MODULE_DEVICE_TABLE(tee, scmi_optee_service_id); | |
| 538 | + | |
| 539 | +static struct tee_client_driver scmi_optee_driver = { | |
| 540 | + .id_table = scmi_optee_service_id, | |
| 541 | + .driver = { | |
| 542 | + .name = "scmi-optee", | |
| 543 | + .bus = &tee_bus_type, | |
| 544 | + .probe = scmi_optee_service_probe, | |
| 545 | + .remove = scmi_optee_service_remove, | |
| 546 | + }, | |
| 547 | +}; | |
| 548 | + | |
| 549 | +static int scmi_optee_init(void) | |
| 550 | +{ | |
| 551 | + return driver_register(&scmi_optee_driver.driver); | |
| 552 | +} | |
| 553 | + | |
| 554 | +static void scmi_optee_exit(void) | |
| 555 | +{ | |
| 556 | + if (scmi_optee_private) | |
| 557 | + driver_unregister(&scmi_optee_driver.driver); | |
| 558 | +} | |
| 559 | + | |
| 560 | +const struct scmi_desc scmi_optee_desc = { | |
| 561 | + .transport_exit = scmi_optee_exit, | |
| 562 | + .ops = &scmi_optee_ops, | |
| 563 | + .max_rx_timeout_ms = 30, | |
| 564 | + .max_msg = 20, | |
| 565 | + .max_msg_size = SCMI_OPTEE_MAX_MSG_SIZE, | |
| 566 | + .sync_cmds_completed_on_ret = true, | |
| 567 | +}; | |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 9 | #include <linux/arm-smccc.h> |
| 10 | +#include <linux/atomic.h> | |
| 10 | 11 | #include <linux/device.h> |
| 11 | 12 | #include <linux/err.h> |
| 12 | 13 | #include <linux/interrupt.h> |
| @@ -14,6 +15,7 @@ · 1 unmodified line | ||
| 14 | 15 | #include <linux/of.h> |
| 15 | 16 | #include <linux/of_address.h> |
| 16 | 17 | #include <linux/of_irq.h> |
| 18 | +#include <linux/processor.h> | |
| 17 | 19 | #include <linux/slab.h> |
| 18 | 20 | |
| 19 | 21 | #include "common.h" |
| @@ -23,26 +25,29 @@ · 3 unmodified lines | ||
| 23 | 25 | * |
| 24 | 26 | * @cinfo: SCMI channel info |
| 25 | 27 | * @shmem: Transmit/Receive shared memory area |
| 26 | − * @shmem_lock: Lock to protect access to Tx/Rx shared memory area | |
| 28 | + * @shmem_lock: Lock to protect access to Tx/Rx shared memory area. | |
| 29 | + * Used when NOT operating in atomic mode. | |
| 30 | + * @inflight: Atomic flag to protect access to Tx/Rx shared memory area. | |
| 31 | + * Used when operating in atomic mode. | |
| 27 | 32 | * @func_id: smc/hvc call function id |
| 28 | − * @irq: Optional; employed when platforms indicates msg completion by intr. | |
| 29 | − * @tx_complete: Optional, employed only when irq is valid. | |
| 30 | 33 | */ |
| 31 | 34 | |
| 32 | 35 | struct scmi_smc { |
| 33 | 36 | struct scmi_chan_info *cinfo; |
| 34 | 37 | struct scmi_shared_mem __iomem *shmem; |
| 38 | + /* Protect access to shmem area */ | |
| 35 | 39 | struct mutex shmem_lock; |
| 40 | +#define INFLIGHT_NONE MSG_TOKEN_MAX | |
| 41 | + atomic_t inflight; | |
| 36 | 42 | u32 func_id; |
| 37 | − int irq; | |
| 38 | − struct completion tx_complete; | |
| 39 | 43 | }; |
| 40 | 44 | |
| 41 | 45 | static irqreturn_t smc_msg_done_isr(int irq, void *data) |
| 42 | 46 | { |
| 43 | 47 | struct scmi_smc *scmi_info = data; |
| 44 | 48 | |
| 45 | − complete(&scmi_info->tx_complete); | |
| 49 | + scmi_rx_callback(scmi_info->cinfo, | |
| 50 | + shmem_read_header(scmi_info->shmem), NULL); | |
| 46 | 51 | |
| 47 | 52 | return IRQ_HANDLED; |
| 48 | 53 | } |
| @@ -57,6 +62,41 @@ static bool smc_chan_available(struct device *dev, int idx) · 8 unmodified lines | ||
| 57 | 62 | return true; |
| 58 | 63 | } |
| 59 | 64 | |
| 65 | +static inline void smc_channel_lock_init(struct scmi_smc *scmi_info) | |
| 66 | +{ | |
| 67 | + if (IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE)) | |
| 68 | + atomic_set(&scmi_info->inflight, INFLIGHT_NONE); | |
| 69 | + else | |
| 70 | + mutex_init(&scmi_info->shmem_lock); | |
| 71 | +} | |
| 72 | + | |
| 73 | +static bool smc_xfer_inflight(struct scmi_xfer *xfer, atomic_t *inflight) | |
| 74 | +{ | |
| 75 | + int ret; | |
| 76 | + | |
| 77 | + ret = atomic_cmpxchg(inflight, INFLIGHT_NONE, xfer->hdr.seq); | |
| 78 | + | |
| 79 | + return ret == INFLIGHT_NONE; | |
| 80 | +} | |
| 81 | + | |
| 82 | +static inline void | |
| 83 | +smc_channel_lock_acquire(struct scmi_smc *scmi_info, | |
| 84 | + struct scmi_xfer *xfer __maybe_unused) | |
| 85 | +{ | |
| 86 | + if (IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE)) | |
| 87 | + spin_until_cond(smc_xfer_inflight(xfer, &scmi_info->inflight)); | |
| 88 | + else | |
| 89 | + mutex_lock(&scmi_info->shmem_lock); | |
| 90 | +} | |
| 91 | + | |
| 92 | +static inline void smc_channel_lock_release(struct scmi_smc *scmi_info) | |
| 93 | +{ | |
| 94 | + if (IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE)) | |
| 95 | + atomic_set(&scmi_info->inflight, INFLIGHT_NONE); | |
| 96 | + else | |
| 97 | + mutex_unlock(&scmi_info->shmem_lock); | |
| 98 | +} | |
| 99 | + | |
| 60 | 100 | static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, |
| 61 | 101 | bool tx) |
| 62 | 102 | { |
| @@ -111,13 +151,13 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, · 48 unmodified lines | ||
| 111 | 151 | dev_err(dev, "failed to setup SCMI smc irq\n"); |
| 112 | 152 | return ret; |
| 113 | 153 | } |
| 114 | − init_completion(&scmi_info->tx_complete); | |
| 115 | − scmi_info->irq = irq; | |
| 154 | + } else { | |
| 155 | + cinfo->no_completion_irq = true; | |
| 116 | 156 | } |
| 117 | 157 | |
| 118 | 158 | scmi_info->func_id = func_id; |
| 119 | 159 | scmi_info->cinfo = cinfo; |
| 120 | − mutex_init(&scmi_info->shmem_lock); | |
| 160 | + smc_channel_lock_init(scmi_info); | |
| 121 | 161 | cinfo->transport_info = scmi_info; |
| 122 | 162 | |
| 123 | 163 | return 0; |
| @@ -142,26 +182,22 @@ static int smc_send_message(struct scmi_chan_info *cinfo, · 18 unmodified lines | ||
| 142 | 182 | struct scmi_smc *scmi_info = cinfo->transport_info; |
| 143 | 183 | struct arm_smccc_res res; |
| 144 | 184 | |
| 145 | − mutex_lock(&scmi_info->shmem_lock); | |
| 185 | + /* | |
| 186 | + * Channel will be released only once response has been | |
| 187 | + * surely fully retrieved, so after .mark_txdone() | |
| 188 | + */ | |
| 189 | + smc_channel_lock_acquire(scmi_info, xfer); | |
| 146 | 190 | |
| 147 | 191 | shmem_tx_prepare(scmi_info->shmem, xfer); |
| 148 | 192 | |
| 149 | − if (scmi_info->irq) | |
| 150 | − reinit_completion(&scmi_info->tx_complete); | |
| 151 | − | |
| 152 | 193 | arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res); |
| 153 | 194 | |
| 154 | − if (scmi_info->irq) | |
| 155 | − wait_for_completion(&scmi_info->tx_complete); | |
| 156 | − | |
| 157 | − scmi_rx_callback(scmi_info->cinfo, | |
| 158 | − shmem_read_header(scmi_info->shmem), NULL); | |
| 159 | − | |
| 160 | − mutex_unlock(&scmi_info->shmem_lock); | |
| 161 | − | |
| 162 | 195 | /* Only SMCCC_RET_NOT_SUPPORTED is valid error code */ |
| 163 | − if (res.a0) | |
| 196 | + if (res.a0) { | |
| 197 | + smc_channel_lock_release(scmi_info); | |
| 164 | 198 | return -EOPNOTSUPP; |
| 199 | + } | |
| 200 | + | |
| 165 | 201 | return 0; |
| 166 | 202 | } |
| 167 | 203 | |
| @@ -173,12 +209,12 @@ static void smc_fetch_response(struct scmi_chan_info *cinfo, · 5 unmodified lines | ||
| 173 | 209 | shmem_fetch_response(scmi_info->shmem, xfer); |
| 174 | 210 | } |
| 175 | 211 | |
| 176 | −static bool | |
| 177 | −smc_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) | |
| 212 | +static void smc_mark_txdone(struct scmi_chan_info *cinfo, int ret, | |
| 213 | + struct scmi_xfer *__unused) | |
| 178 | 214 | { |
| 179 | 215 | struct scmi_smc *scmi_info = cinfo->transport_info; |
| 180 | 216 | |
| 181 | − return shmem_poll_done(scmi_info->shmem, xfer); | |
| 217 | + smc_channel_lock_release(scmi_info); | |
| 182 | 218 | } |
| 183 | 219 | |
| 184 | 220 | static const struct scmi_transport_ops scmi_smc_ops = { |
| @@ -186,8 +222,8 @@ static const struct scmi_transport_ops scmi_smc_ops = { · 1 unmodified line | ||
| 186 | 222 | .chan_setup = smc_chan_setup, |
| 187 | 223 | .chan_free = smc_chan_free, |
| 188 | 224 | .send_message = smc_send_message, |
| 225 | + .mark_txdone = smc_mark_txdone, | |
| 189 | 226 | .fetch_response = smc_fetch_response, |
| 190 | − .poll_done = smc_poll_done, | |
| 191 | 227 | }; |
| 192 | 228 | |
| 193 | 229 | const struct scmi_desc scmi_smc_desc = { |
| @@ -195,4 +231,14 @@ const struct scmi_desc scmi_smc_desc = { · 1 unmodified line | ||
| 195 | 231 | .max_rx_timeout_ms = 30, |
| 196 | 232 | .max_msg = 20, |
| 197 | 233 | .max_msg_size = 128, |
| 234 | + /* | |
| 235 | + * Setting .sync_cmds_atomic_replies to true for SMC assumes that, | |
| 236 | + * once the SMC instruction has completed successfully, the issued | |
| 237 | + * SCMI command would have been already fully processed by the SCMI | |
| 238 | + * platform firmware and so any possible response value expected | |
| 239 | + * for the issued command will be immmediately ready to be fetched | |
| 240 | + * from the shared memory area. | |
| 241 | + */ | |
| 242 | + .sync_cmds_completed_on_ret = true, | |
| 243 | + .atomic_enabled = IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE), | |
| 198 | 244 | }; |
| @@ -3,8 +3,8 @@ · 2 unmodified lines | ||
| 3 | 3 | * Virtio Transport driver for Arm System Control and Management Interface |
| 4 | 4 | * (SCMI). |
| 5 | 5 | * |
| 6 | − * Copyright (C) 2020-2021 OpenSynergy. | |
| 7 | − * Copyright (C) 2021 ARM Ltd. | |
| 6 | + * Copyright (C) 2020-2022 OpenSynergy. | |
| 7 | + * Copyright (C) 2021-2022 ARM Ltd. | |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | /** |
| @@ -17,7 +17,9 @@ · 6 unmodified lines | ||
| 17 | 17 | * virtqueue. Access to each virtqueue is protected by spinlocks. |
| 18 | 18 | */ |
| 19 | 19 | |
| 20 | +#include <linux/completion.h> | |
| 20 | 21 | #include <linux/errno.h> |
| 22 | +#include <linux/refcount.h> | |
| 21 | 23 | #include <linux/slab.h> |
| 22 | 24 | #include <linux/virtio.h> |
| 23 | 25 | #include <linux/virtio_config.h> |
| @@ -27,6 +29,7 @@ · 3 unmodified lines | ||
| 27 | 29 | |
| 28 | 30 | #include "common.h" |
| 29 | 31 | |
| 32 | +#define VIRTIO_MAX_RX_TIMEOUT_MS 60000 | |
| 30 | 33 | #define VIRTIO_SCMI_MAX_MSG_SIZE 128 /* Value may be increased. */ |
| 31 | 34 | #define VIRTIO_SCMI_MAX_PDU_SIZE \ |
| 32 | 35 | (VIRTIO_SCMI_MAX_MSG_SIZE + SCMI_MSG_MAX_PROT_OVERHEAD) |
| @@ -37,25 +40,46 @@ · 4 unmodified lines | ||
| 37 | 40 | * |
| 38 | 41 | * @vqueue: Associated virtqueue |
| 39 | 42 | * @cinfo: SCMI Tx or Rx channel |
| 43 | + * @free_lock: Protects access to the @free_list. | |
| 40 | 44 | * @free_list: List of unused scmi_vio_msg, maintained for Tx channels only |
| 45 | + * @deferred_tx_work: Worker for TX deferred replies processing | |
| 46 | + * @deferred_tx_wq: Workqueue for TX deferred replies | |
| 47 | + * @pending_lock: Protects access to the @pending_cmds_list. | |
| 48 | + * @pending_cmds_list: List of pre-fetched commands queueud for later processing | |
| 41 | 49 | * @is_rx: Whether channel is an Rx channel |
| 42 | − * @ready: Whether transport user is ready to hear about channel | |
| 43 | 50 | * @max_msg: Maximum number of pending messages for this channel. |
| 44 | − * @lock: Protects access to all members except ready. | |
| 45 | − * @ready_lock: Protects access to ready. If required, it must be taken before | |
| 46 | − * lock. | |
| 51 | + * @lock: Protects access to all members except users, free_list and | |
| 52 | + * pending_cmds_list. | |
| 53 | + * @shutdown_done: A reference to a completion used when freeing this channel. | |
| 54 | + * @users: A reference count to currently active users of this channel. | |
| 47 | 55 | */ |
| 48 | 56 | struct scmi_vio_channel { |
| 49 | 57 | struct virtqueue *vqueue; |
| 50 | 58 | struct scmi_chan_info *cinfo; |
| 59 | + /* lock to protect access to the free list. */ | |
| 60 | + spinlock_t free_lock; | |
| 51 | 61 | struct list_head free_list; |
| 62 | + /* lock to protect access to the pending list. */ | |
| 63 | + spinlock_t pending_lock; | |
| 64 | + struct list_head pending_cmds_list; | |
| 65 | + struct work_struct deferred_tx_work; | |
| 66 | + struct workqueue_struct *deferred_tx_wq; | |
| 52 | 67 | bool is_rx; |
| 53 | − bool ready; | |
| 54 | 68 | unsigned int max_msg; |
| 55 | − /* lock to protect access to all members except ready. */ | |
| 69 | + /* | |
| 70 | + * Lock to protect access to all members except users, free_list and | |
| 71 | + * pending_cmds_list | |
| 72 | + */ | |
| 56 | 73 | spinlock_t lock; |
| 57 | − /* lock to rotects access to ready flag. */ | |
| 58 | − spinlock_t ready_lock; | |
| 74 | + struct completion *shutdown_done; | |
| 75 | + refcount_t users; | |
| 76 | +}; | |
| 77 | + | |
| 78 | +enum poll_states { | |
| 79 | + VIO_MSG_NOT_POLLED, | |
| 80 | + VIO_MSG_POLL_TIMEOUT, | |
| 81 | + VIO_MSG_POLLING, | |
| 82 | + VIO_MSG_POLL_DONE, | |
| 59 | 83 | }; |
| 60 | 84 | |
| 61 | 85 | /** |
| @@ -65,29 +89,154 @@ struct scmi_vio_channel { · 3 unmodified lines | ||
| 65 | 89 | * @input: SDU used for (delayed) responses and notifications |
| 66 | 90 | * @list: List which scmi_vio_msg may be part of |
| 67 | 91 | * @rx_len: Input SDU size in bytes, once input has been received |
| 92 | + * @poll_idx: Last used index registered for polling purposes if this message | |
| 93 | + * transaction reply was configured for polling. | |
| 94 | + * @poll_status: Polling state for this message. | |
| 95 | + * @poll_lock: A lock to protect @poll_status | |
| 96 | + * @users: A reference count to track this message users and avoid premature | |
| 97 | + * freeing (and reuse) when polling and IRQ execution paths interleave. | |
| 68 | 98 | */ |
| 69 | 99 | struct scmi_vio_msg { |
| 70 | 100 | struct scmi_msg_payld *request; |
| 71 | 101 | struct scmi_msg_payld *input; |
| 72 | 102 | struct list_head list; |
| 73 | 103 | unsigned int rx_len; |
| 104 | + unsigned int poll_idx; | |
| 105 | + enum poll_states poll_status; | |
| 106 | + /* Lock to protect access to poll_status */ | |
| 107 | + spinlock_t poll_lock; | |
| 108 | + refcount_t users; | |
| 74 | 109 | }; |
| 75 | 110 | |
| 76 | 111 | /* Only one SCMI VirtIO device can possibly exist */ |
| 77 | 112 | static struct virtio_device *scmi_vdev; |
| 78 | 113 | |
| 114 | +static void scmi_vio_channel_ready(struct scmi_vio_channel *vioch, | |
| 115 | + struct scmi_chan_info *cinfo) | |
| 116 | +{ | |
| 117 | + unsigned long flags; | |
| 118 | + | |
| 119 | + spin_lock_irqsave(&vioch->lock, flags); | |
| 120 | + cinfo->transport_info = vioch; | |
| 121 | + /* Indirectly setting channel not available any more */ | |
| 122 | + vioch->cinfo = cinfo; | |
| 123 | + spin_unlock_irqrestore(&vioch->lock, flags); | |
| 124 | + | |
| 125 | + refcount_set(&vioch->users, 1); | |
| 126 | +} | |
| 127 | + | |
| 128 | +static inline bool scmi_vio_channel_acquire(struct scmi_vio_channel *vioch) | |
| 129 | +{ | |
| 130 | + return refcount_inc_not_zero(&vioch->users); | |
| 131 | +} | |
| 132 | + | |
| 133 | +static inline void scmi_vio_channel_release(struct scmi_vio_channel *vioch) | |
| 134 | +{ | |
| 135 | + if (refcount_dec_and_test(&vioch->users)) { | |
| 136 | + unsigned long flags; | |
| 137 | + | |
| 138 | + spin_lock_irqsave(&vioch->lock, flags); | |
| 139 | + if (vioch->shutdown_done) { | |
| 140 | + vioch->cinfo = NULL; | |
| 141 | + complete(vioch->shutdown_done); | |
| 142 | + } | |
| 143 | + spin_unlock_irqrestore(&vioch->lock, flags); | |
| 144 | + } | |
| 145 | +} | |
| 146 | + | |
| 147 | +static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch) | |
| 148 | +{ | |
| 149 | + unsigned long flags; | |
| 150 | + DECLARE_COMPLETION_ONSTACK(vioch_shutdown_done); | |
| 151 | + void *deferred_wq = NULL; | |
| 152 | + | |
| 153 | + /* | |
| 154 | + * Prepare to wait for the last release if not already released | |
| 155 | + * or in progress. | |
| 156 | + */ | |
| 157 | + spin_lock_irqsave(&vioch->lock, flags); | |
| 158 | + if (!vioch->cinfo || vioch->shutdown_done) { | |
| 159 | + spin_unlock_irqrestore(&vioch->lock, flags); | |
| 160 | + return; | |
| 161 | + } | |
| 162 | + | |
| 163 | + vioch->shutdown_done = &vioch_shutdown_done; | |
| 164 | + virtio_break_device(vioch->vqueue->vdev); | |
| 165 | + if (!vioch->is_rx && vioch->deferred_tx_wq) { | |
| 166 | + deferred_wq = vioch->deferred_tx_wq; | |
| 167 | + /* Cannot be kicked anymore after this...*/ | |
| 168 | + vioch->deferred_tx_wq = NULL; | |
| 169 | + } | |
| 170 | + spin_unlock_irqrestore(&vioch->lock, flags); | |
| 171 | + | |
| 172 | + if (deferred_wq) | |
| 173 | + destroy_workqueue(deferred_wq); | |
| 174 | + | |
| 175 | + scmi_vio_channel_release(vioch); | |
| 176 | + | |
| 177 | + /* Let any possibly concurrent RX path release the channel */ | |
| 178 | + wait_for_completion(vioch->shutdown_done); | |
| 179 | +} | |
| 180 | + | |
| 181 | +/* Assumes to be called with vio channel acquired already */ | |
| 182 | +static struct scmi_vio_msg * | |
| 183 | +scmi_virtio_get_free_msg(struct scmi_vio_channel *vioch) | |
| 184 | +{ | |
| 185 | + unsigned long flags; | |
| 186 | + struct scmi_vio_msg *msg; | |
| 187 | + | |
| 188 | + spin_lock_irqsave(&vioch->free_lock, flags); | |
| 189 | + if (list_empty(&vioch->free_list)) { | |
| 190 | + spin_unlock_irqrestore(&vioch->free_lock, flags); | |
| 191 | + return NULL; | |
| 192 | + } | |
| 193 | + | |
| 194 | + msg = list_first_entry(&vioch->free_list, typeof(*msg), list); | |
| 195 | + list_del_init(&msg->list); | |
| 196 | + spin_unlock_irqrestore(&vioch->free_lock, flags); | |
| 197 | + | |
| 198 | + /* Still no users, no need to acquire poll_lock */ | |
| 199 | + msg->poll_status = VIO_MSG_NOT_POLLED; | |
| 200 | + refcount_set(&msg->users, 1); | |
| 201 | + | |
| 202 | + return msg; | |
| 203 | +} | |
| 204 | + | |
| 205 | +static inline bool scmi_vio_msg_acquire(struct scmi_vio_msg *msg) | |
| 206 | +{ | |
| 207 | + return refcount_inc_not_zero(&msg->users); | |
| 208 | +} | |
| 209 | + | |
| 210 | +/* Assumes to be called with vio channel acquired already */ | |
| 211 | +static inline bool scmi_vio_msg_release(struct scmi_vio_channel *vioch, | |
| 212 | + struct scmi_vio_msg *msg) | |
| 213 | +{ | |
| 214 | + bool ret; | |
| 215 | + | |
| 216 | + ret = refcount_dec_and_test(&msg->users); | |
| 217 | + if (ret) { | |
| 218 | + unsigned long flags; | |
| 219 | + | |
| 220 | + spin_lock_irqsave(&vioch->free_lock, flags); | |
| 221 | + list_add_tail(&msg->list, &vioch->free_list); | |
| 222 | + spin_unlock_irqrestore(&vioch->free_lock, flags); | |
| 223 | + } | |
| 224 | + | |
| 225 | + return ret; | |
| 226 | +} | |
| 227 | + | |
| 79 | 228 | static bool scmi_vio_have_vq_rx(struct virtio_device *vdev) |
| 80 | 229 | { |
| 81 | 230 | return virtio_has_feature(vdev, VIRTIO_SCMI_F_P2A_CHANNELS); |
| 82 | 231 | } |
| 83 | 232 | |
| 84 | 233 | static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch, |
| 85 | − struct scmi_vio_msg *msg, | |
| 86 | − struct device *dev) | |
| 234 | + struct scmi_vio_msg *msg) | |
| 87 | 235 | { |
| 88 | 236 | struct scatterlist sg_in; |
| 89 | 237 | int rc; |
| 90 | 238 | unsigned long flags; |
| 239 | + struct device *dev = &vioch->vqueue->vdev->dev; | |
| 91 | 240 | |
| 92 | 241 | sg_init_one(&sg_in, msg->input, VIRTIO_SCMI_MAX_PDU_SIZE); |
| 93 | 242 | |
| @@ -95,7 +244,7 @@ static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch, · 1 unmodified line | ||
| 95 | 244 | |
| 96 | 245 | rc = virtqueue_add_inbuf(vioch->vqueue, &sg_in, 1, msg, GFP_ATOMIC); |
| 97 | 246 | if (rc) |
| 98 | − dev_err_once(dev, "failed to add to virtqueue (%d)\n", rc); | |
| 247 | + dev_err(dev, "failed to add to RX virtqueue (%d)\n", rc); | |
| 99 | 248 | else |
| 100 | 249 | virtqueue_kick(vioch->vqueue); |
| 101 | 250 | |
| @@ -104,22 +253,22 @@ static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch, · 2 unmodified lines | ||
| 104 | 253 | return rc; |
| 105 | 254 | } |
| 106 | 255 | |
| 256 | +/* | |
| 257 | + * Assume to be called with channel already acquired or not ready at all; | |
| 258 | + * vioch->lock MUST NOT have been already acquired. | |
| 259 | + */ | |
| 107 | 260 | static void scmi_finalize_message(struct scmi_vio_channel *vioch, |
| 108 | 261 | struct scmi_vio_msg *msg) |
| 109 | 262 | { |
| 110 | − if (vioch->is_rx) { | |
| 111 | − scmi_vio_feed_vq_rx(vioch, msg, vioch->cinfo->dev); | |
| 112 | − } else { | |
| 113 | − /* Here IRQs are assumed to be already disabled by the caller */ | |
| 114 | − spin_lock(&vioch->lock); | |
| 115 | − list_add(&msg->list, &vioch->free_list); | |
| 116 | − spin_unlock(&vioch->lock); | |
| 117 | − } | |
| 263 | + if (vioch->is_rx) | |
| 264 | + scmi_vio_feed_vq_rx(vioch, msg); | |
| 265 | + else | |
| 266 | + scmi_vio_msg_release(vioch, msg); | |
| 118 | 267 | } |
| 119 | 268 | |
| 120 | 269 | static void scmi_vio_complete_cb(struct virtqueue *vqueue) |
| 121 | 270 | { |
| 122 | − unsigned long ready_flags; | |
| 271 | + unsigned long flags; | |
| 123 | 272 | unsigned int length; |
| 124 | 273 | struct scmi_vio_channel *vioch; |
| 125 | 274 | struct scmi_vio_msg *msg; |
| @@ -130,27 +279,25 @@ static void scmi_vio_complete_cb(struct virtqueue *vqueue) · 4 unmodified lines | ||
| 130 | 279 | vioch = &((struct scmi_vio_channel *)vqueue->vdev->priv)[vqueue->index]; |
| 131 | 280 | |
| 132 | 281 | for (;;) { |
| 133 | − spin_lock_irqsave(&vioch->ready_lock, ready_flags); | |
| 282 | + if (!scmi_vio_channel_acquire(vioch)) | |
| 283 | + return; | |
| 134 | 284 | |
| 135 | − if (!vioch->ready) { | |
| 136 | − if (!cb_enabled) | |
| 137 | − (void)virtqueue_enable_cb(vqueue); | |
| 138 | − goto unlock_ready_out; | |
| 139 | − } | |
| 140 | − | |
| 141 | − /* IRQs already disabled here no need to irqsave */ | |
| 142 | − spin_lock(&vioch->lock); | |
| 285 | + spin_lock_irqsave(&vioch->lock, flags); | |
| 143 | 286 | if (cb_enabled) { |
| 144 | 287 | virtqueue_disable_cb(vqueue); |
| 145 | 288 | cb_enabled = false; |
| 146 | 289 | } |
| 290 | + | |
| 147 | 291 | msg = virtqueue_get_buf(vqueue, &length); |
| 148 | 292 | if (!msg) { |
| 149 | − if (virtqueue_enable_cb(vqueue)) | |
| 150 | − goto unlock_out; | |
| 293 | + if (virtqueue_enable_cb(vqueue)) { | |
| 294 | + spin_unlock_irqrestore(&vioch->lock, flags); | |
| 295 | + scmi_vio_channel_release(vioch); | |
| 296 | + return; | |
| 297 | + } | |
| 151 | 298 | cb_enabled = true; |
| 152 | 299 | } |
| 153 | − spin_unlock(&vioch->lock); | |
| 300 | + spin_unlock_irqrestore(&vioch->lock, flags); | |
| 154 | 301 | |
| 155 | 302 | if (msg) { |
| 156 | 303 | msg->rx_len = length; |
| @@ -161,19 +308,57 @@ static void scmi_vio_complete_cb(struct virtqueue *vqueue) · 4 unmodified lines | ||
| 161 | 308 | } |
| 162 | 309 | |
| 163 | 310 | /* |
| 164 | − * Release ready_lock and re-enable IRQs between loop iterations | |
| 165 | − * to allow virtio_chan_free() to possibly kick in and set the | |
| 166 | − * flag vioch->ready to false even in between processing of | |
| 167 | − * messages, so as to force outstanding messages to be ignored | |
| 168 | − * when system is shutting down. | |
| 311 | + * Release vio channel between loop iterations to allow | |
| 312 | + * virtio_chan_free() to eventually fully release it when | |
| 313 | + * shutting down; in such a case, any outstanding message will | |
| 314 | + * be ignored since this loop will bail out at the next | |
| 315 | + * iteration. | |
| 316 | + */ | |
| 317 | + scmi_vio_channel_release(vioch); | |
| 318 | + } | |
| 319 | +} | |
| 320 | + | |
| 321 | +static void scmi_vio_deferred_tx_worker(struct work_struct *work) | |
| 322 | +{ | |
| 323 | + unsigned long flags; | |
| 324 | + struct scmi_vio_channel *vioch; | |
| 325 | + struct scmi_vio_msg *msg, *tmp; | |
| 326 | + | |
| 327 | + vioch = container_of(work, struct scmi_vio_channel, deferred_tx_work); | |
| 328 | + | |
| 329 | + if (!scmi_vio_channel_acquire(vioch)) | |
| 330 | + return; | |
| 331 | + | |
| 332 | + /* | |
| 333 | + * Process pre-fetched messages: these could be non-polled messages or | |
| 334 | + * late timed-out replies to polled messages dequeued by chance while | |
| 335 | + * polling for some other messages: this worker is in charge to process | |
| 336 | + * the valid non-expired messages and anyway finally free all of them. | |
| 337 | + */ | |
| 338 | + spin_lock_irqsave(&vioch->pending_lock, flags); | |
| 339 | + | |
| 340 | + /* Scan the list of possibly pre-fetched messages during polling. */ | |
| 341 | + list_for_each_entry_safe(msg, tmp, &vioch->pending_cmds_list, list) { | |
| 342 | + list_del(&msg->list); | |
| 343 | + | |
| 344 | + /* | |
| 345 | + * Channel is acquired here (cannot vanish) and this message | |
| 346 | + * is no more processed elsewhere so no poll_lock needed. | |
| 169 | 347 | */ |
| 170 | − spin_unlock_irqrestore(&vioch->ready_lock, ready_flags); | |
| 348 | + if (msg->poll_status == VIO_MSG_NOT_POLLED) | |
| 349 | + scmi_rx_callback(vioch->cinfo, | |
| 350 | + msg_read_header(msg->input), msg); | |
| 351 | + | |
| 352 | + /* Free the processed message once done */ | |
| 353 | + scmi_vio_msg_release(vioch, msg); | |
| 171 | 354 | } |
| 172 | 355 | |
| 173 | −unlock_out: | |
| 174 | − spin_unlock(&vioch->lock); | |
| 175 | −unlock_ready_out: | |
| 176 | − spin_unlock_irqrestore(&vioch->ready_lock, ready_flags); | |
| 356 | + spin_unlock_irqrestore(&vioch->pending_lock, flags); | |
| 357 | + | |
| 358 | + /* Process possibly still pending messages */ | |
| 359 | + scmi_vio_complete_cb(vioch->vqueue); | |
| 360 | + | |
| 361 | + scmi_vio_channel_release(vioch); | |
| 177 | 362 | } |
| 178 | 363 | |
| 179 | 364 | static const char *const scmi_vio_vqueue_names[] = { "tx", "rx" }; |
| @@ -193,8 +378,8 @@ static unsigned int virtio_get_max_msg(struct scmi_chan_info *base_cinfo) · 13 unmodified lines | ||
| 193 | 378 | static int virtio_link_supplier(struct device *dev) |
| 194 | 379 | { |
| 195 | 380 | if (!scmi_vdev) { |
| 196 | − dev_notice_once(dev, | |
| 197 | − "Deferring probe after not finding a bound scmi-virtio device\n"); | |
| 381 | + dev_notice(dev, | |
| 382 | + "Deferring probe after not finding a bound scmi-virtio device\n"); | |
| 198 | 383 | return -EPROBE_DEFER; |
| 199 | 384 | } |
| 200 | 385 | |
| @@ -234,7 +419,6 @@ static bool virtio_chan_available(struct device *dev, int idx) · 33 unmodified lines | ||
| 234 | 419 | static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, |
| 235 | 420 | bool tx) |
| 236 | 421 | { |
| 237 | − unsigned long flags; | |
| 238 | 422 | struct scmi_vio_channel *vioch; |
| 239 | 423 | int index = tx ? VIRTIO_SCMI_VQ_TX : VIRTIO_SCMI_VQ_RX; |
| 240 | 424 | int i; |
| @@ -244,6 +428,19 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, · 3 unmodified lines | ||
| 244 | 428 | |
| 245 | 429 | vioch = &((struct scmi_vio_channel *)scmi_vdev->priv)[index]; |
| 246 | 430 | |
| 431 | + /* Setup a deferred worker for polling. */ | |
| 432 | + if (tx && !vioch->deferred_tx_wq) { | |
| 433 | + vioch->deferred_tx_wq = | |
| 434 | + alloc_workqueue(dev_name(&scmi_vdev->dev), | |
| 435 | + WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS, | |
| 436 | + 0); | |
| 437 | + if (!vioch->deferred_tx_wq) | |
| 438 | + return -ENOMEM; | |
| 439 | + | |
| 440 | + INIT_WORK(&vioch->deferred_tx_work, | |
| 441 | + scmi_vio_deferred_tx_worker); | |
| 442 | + } | |
| 443 | + | |
| 247 | 444 | for (i = 0; i < vioch->max_msg; i++) { |
| 248 | 445 | struct scmi_vio_msg *msg; |
| 249 | 446 | |
| @@ -257,6 +454,8 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, · 7 unmodified lines | ||
| 257 | 454 | GFP_KERNEL); |
| 258 | 455 | if (!msg->request) |
| 259 | 456 | return -ENOMEM; |
| 457 | + spin_lock_init(&msg->poll_lock); | |
| 458 | + refcount_set(&msg->users, 1); | |
| 260 | 459 | } |
| 261 | 460 | |
| 262 | 461 | msg->input = devm_kzalloc(cinfo->dev, VIRTIO_SCMI_MAX_PDU_SIZE, |
| @@ -264,44 +463,23 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, · 1 unmodified line | ||
| 264 | 463 | if (!msg->input) |
| 265 | 464 | return -ENOMEM; |
| 266 | 465 | |
| 267 | − if (tx) { | |
| 268 | − spin_lock_irqsave(&vioch->lock, flags); | |
| 269 | − list_add_tail(&msg->list, &vioch->free_list); | |
| 270 | − spin_unlock_irqrestore(&vioch->lock, flags); | |
| 271 | − } else { | |
| 272 | − scmi_vio_feed_vq_rx(vioch, msg, cinfo->dev); | |
| 273 | − } | |
| 466 | + scmi_finalize_message(vioch, msg); | |
| 274 | 467 | } |
| 275 | 468 | |
| 276 | − spin_lock_irqsave(&vioch->lock, flags); | |
| 277 | − cinfo->transport_info = vioch; | |
| 278 | − /* Indirectly setting channel not available any more */ | |
| 279 | − vioch->cinfo = cinfo; | |
| 280 | − spin_unlock_irqrestore(&vioch->lock, flags); | |
| 281 | − | |
| 282 | − spin_lock_irqsave(&vioch->ready_lock, flags); | |
| 283 | − vioch->ready = true; | |
| 284 | − spin_unlock_irqrestore(&vioch->ready_lock, flags); | |
| 469 | + scmi_vio_channel_ready(vioch, cinfo); | |
| 285 | 470 | |
| 286 | 471 | return 0; |
| 287 | 472 | } |
| 288 | 473 | |
| 289 | 474 | static int virtio_chan_free(int id, void *p, void *data) |
| 290 | 475 | { |
| 291 | − unsigned long flags; | |
| 292 | 476 | struct scmi_chan_info *cinfo = p; |
| 293 | 477 | struct scmi_vio_channel *vioch = cinfo->transport_info; |
| 294 | 478 | |
| 295 | − spin_lock_irqsave(&vioch->ready_lock, flags); | |
| 296 | − vioch->ready = false; | |
| 297 | − spin_unlock_irqrestore(&vioch->ready_lock, flags); | |
| 479 | + scmi_vio_channel_cleanup_sync(vioch); | |
| 298 | 480 | |
| 299 | 481 | scmi_free_channel(cinfo, data, id); |
| 300 | 482 | |
| 301 | − spin_lock_irqsave(&vioch->lock, flags); | |
| 302 | − vioch->cinfo = NULL; | |
| 303 | − spin_unlock_irqrestore(&vioch->lock, flags); | |
| 304 | − | |
| 305 | 483 | return 0; |
| 306 | 484 | } |
| 307 | 485 | |
| @@ -316,33 +494,56 @@ static int virtio_send_message(struct scmi_chan_info *cinfo, · 8 unmodified lines | ||
| 316 | 494 | int rc; |
| 317 | 495 | struct scmi_vio_msg *msg; |
| 318 | 496 | |
| 319 | − spin_lock_irqsave(&vioch->lock, flags); | |
| 497 | + if (!scmi_vio_channel_acquire(vioch)) | |
| 498 | + return -EINVAL; | |
| 320 | 499 | |
| 321 | − if (list_empty(&vioch->free_list)) { | |
| 322 | − spin_unlock_irqrestore(&vioch->lock, flags); | |
| 500 | + msg = scmi_virtio_get_free_msg(vioch); | |
| 501 | + if (!msg) { | |
| 502 | + scmi_vio_channel_release(vioch); | |
| 323 | 503 | return -EBUSY; |
| 324 | 504 | } |
| 325 | 505 | |
| 326 | − msg = list_first_entry(&vioch->free_list, typeof(*msg), list); | |
| 327 | − list_del(&msg->list); | |
| 328 | − | |
| 329 | 506 | msg_tx_prepare(msg->request, xfer); |
| 330 | 507 | |
| 331 | 508 | sg_init_one(&sg_out, msg->request, msg_command_size(xfer)); |
| 332 | 509 | sg_init_one(&sg_in, msg->input, msg_response_size(xfer)); |
| 333 | 510 | |
| 511 | + spin_lock_irqsave(&vioch->lock, flags); | |
| 512 | + | |
| 513 | + /* | |
| 514 | + * If polling was requested for this transaction: | |
| 515 | + * - retrieve last used index (will be used as polling reference) | |
| 516 | + * - bind the polled message to the xfer via .priv | |
| 517 | + * - grab an additional msg refcount for the poll-path | |
| 518 | + */ | |
| 519 | + if (xfer->hdr.poll_completion) { | |
| 520 | + msg->poll_idx = virtqueue_enable_cb_prepare(vioch->vqueue); | |
| 521 | + /* Still no users, no need to acquire poll_lock */ | |
| 522 | + msg->poll_status = VIO_MSG_POLLING; | |
| 523 | + scmi_vio_msg_acquire(msg); | |
| 524 | + /* Ensure initialized msg is visibly bound to xfer */ | |
| 525 | + smp_store_mb(xfer->priv, msg); | |
| 526 | + } | |
| 527 | + | |
| 334 | 528 | rc = virtqueue_add_sgs(vioch->vqueue, sgs, 1, 1, msg, GFP_ATOMIC); |
| 335 | − if (rc) { | |
| 336 | − list_add(&msg->list, &vioch->free_list); | |
| 337 | − dev_err_once(vioch->cinfo->dev, | |
| 338 | − "%s() failed to add to virtqueue (%d)\n", __func__, | |
| 339 | − rc); | |
| 340 | − } else { | |
| 529 | + if (rc) | |
| 530 | + dev_err(vioch->cinfo->dev, | |
| 531 | + "failed to add to TX virtqueue (%d)\n", rc); | |
| 532 | + else | |
| 341 | 533 | virtqueue_kick(vioch->vqueue); |
| 342 | − } | |
| 343 | 534 | |
| 344 | 535 | spin_unlock_irqrestore(&vioch->lock, flags); |
| 345 | 536 | |
| 537 | + if (rc) { | |
| 538 | + /* Ensure order between xfer->priv clear and vq feeding */ | |
| 539 | + smp_store_mb(xfer->priv, NULL); | |
| 540 | + if (xfer->hdr.poll_completion) | |
| 541 | + scmi_vio_msg_release(vioch, msg); | |
| 542 | + scmi_vio_msg_release(vioch, msg); | |
| 543 | + } | |
| 544 | + | |
| 545 | + scmi_vio_channel_release(vioch); | |
| 546 | + | |
| 346 | 547 | return rc; |
| 347 | 548 | } |
| 348 | 549 | |
| @@ -351,10 +552,8 @@ static void virtio_fetch_response(struct scmi_chan_info *cinfo, · 2 unmodified lines | ||
| 351 | 552 | { |
| 352 | 553 | struct scmi_vio_msg *msg = xfer->priv; |
| 353 | 554 | |
| 354 | − if (msg) { | |
| 555 | + if (msg) | |
| 355 | 556 | msg_fetch_response(msg->input, msg->rx_len, xfer); |
| 356 | − xfer->priv = NULL; | |
| 357 | − } | |
| 358 | 557 | } |
| 359 | 558 | |
| 360 | 559 | static void virtio_fetch_notification(struct scmi_chan_info *cinfo, |
| @@ -362,10 +561,225 @@ static void virtio_fetch_notification(struct scmi_chan_info *cinfo, · 1 unmodified line | ||
| 362 | 561 | { |
| 363 | 562 | struct scmi_vio_msg *msg = xfer->priv; |
| 364 | 563 | |
| 365 | − if (msg) { | |
| 564 | + if (msg) | |
| 366 | 565 | msg_fetch_notification(msg->input, msg->rx_len, max_len, xfer); |
| 367 | − xfer->priv = NULL; | |
| 566 | +} | |
| 567 | + | |
| 568 | +/** | |
| 569 | + * virtio_mark_txdone - Mark transmission done | |
| 570 | + * | |
| 571 | + * Free only completed polling transfer messages. | |
| 572 | + * | |
| 573 | + * Note that in the SCMI VirtIO transport we never explicitly release still | |
| 574 | + * outstanding but timed-out messages by forcibly re-adding them to the | |
| 575 | + * free-list inside the TX code path; we instead let IRQ/RX callbacks, or the | |
| 576 | + * TX deferred worker, eventually clean up such messages once, finally, a late | |
| 577 | + * reply is received and discarded (if ever). | |
| 578 | + * | |
| 579 | + * This approach was deemed preferable since those pending timed-out buffers are | |
| 580 | + * still effectively owned by the SCMI platform VirtIO device even after timeout | |
| 581 | + * expiration: forcibly freeing and reusing them before they had been returned | |
| 582 | + * explicitly by the SCMI platform could lead to subtle bugs due to message | |
| 583 | + * corruption. | |
| 584 | + * An SCMI platform VirtIO device which never returns message buffers is | |
| 585 | + * anyway broken and it will quickly lead to exhaustion of available messages. | |
| 586 | + * | |
| 587 | + * For this same reason, here, we take care to free only the polled messages | |
| 588 | + * that had been somehow replied (only if not by chance already processed on the | |
| 589 | + * IRQ path - the initial scmi_vio_msg_release() takes care of this) and also | |
| 590 | + * any timed-out polled message if that indeed appears to have been at least | |
| 591 | + * dequeued from the virtqueues (VIO_MSG_POLL_DONE): this is needed since such | |
| 592 | + * messages won't be freed elsewhere. Any other polled message is marked as | |
| 593 | + * VIO_MSG_POLL_TIMEOUT. | |
| 594 | + * | |
| 595 | + * Possible late replies to timed-out polled messages will be eventually freed | |
| 596 | + * by RX callbacks if delivered on the IRQ path or by the deferred TX worker if | |
| 597 | + * dequeued on some other polling path. | |
| 598 | + * | |
| 599 | + * @cinfo: SCMI channel info | |
| 600 | + * @ret: Transmission return code | |
| 601 | + * @xfer: Transfer descriptor | |
| 602 | + */ | |
| 603 | +static void virtio_mark_txdone(struct scmi_chan_info *cinfo, int ret, | |
| 604 | + struct scmi_xfer *xfer) | |
| 605 | +{ | |
| 606 | + unsigned long flags; | |
| 607 | + struct scmi_vio_channel *vioch = cinfo->transport_info; | |
| 608 | + struct scmi_vio_msg *msg = xfer->priv; | |
| 609 | + | |
| 610 | + if (!msg || !scmi_vio_channel_acquire(vioch)) | |
| 611 | + return; | |
| 612 | + | |
| 613 | + /* Ensure msg is unbound from xfer anyway at this point */ | |
| 614 | + smp_store_mb(xfer->priv, NULL); | |
| 615 | + | |
| 616 | + /* Must be a polled xfer and not already freed on the IRQ path */ | |
| 617 | + if (!xfer->hdr.poll_completion || scmi_vio_msg_release(vioch, msg)) { | |
| 618 | + scmi_vio_channel_release(vioch); | |
| 619 | + return; | |
| 368 | 620 | } |
| 621 | + | |
| 622 | + spin_lock_irqsave(&msg->poll_lock, flags); | |
| 623 | + /* Do not free timedout polled messages only if still inflight */ | |
| 624 | + if (ret != -ETIMEDOUT || msg->poll_status == VIO_MSG_POLL_DONE) | |
| 625 | + scmi_vio_msg_release(vioch, msg); | |
| 626 | + else if (msg->poll_status == VIO_MSG_POLLING) | |
| 627 | + msg->poll_status = VIO_MSG_POLL_TIMEOUT; | |
| 628 | + spin_unlock_irqrestore(&msg->poll_lock, flags); | |
| 629 | + | |
| 630 | + scmi_vio_channel_release(vioch); | |
| 631 | +} | |
| 632 | + | |
| 633 | +/** | |
| 634 | + * virtio_poll_done - Provide polling support for VirtIO transport | |
| 635 | + * | |
| 636 | + * @cinfo: SCMI channel info | |
| 637 | + * @xfer: Reference to the transfer being poll for. | |
| 638 | + * | |
| 639 | + * VirtIO core provides a polling mechanism based only on last used indexes: | |
| 640 | + * this means that it is possible to poll the virtqueues waiting for something | |
| 641 | + * new to arrive from the host side, but the only way to check if the freshly | |
| 642 | + * arrived buffer was indeed what we were waiting for is to compare the newly | |
| 643 | + * arrived message descriptor with the one we are polling on. | |
| 644 | + * | |
| 645 | + * As a consequence it can happen to dequeue something different from the buffer | |
| 646 | + * we were poll-waiting for: if that is the case such early fetched buffers are | |
| 647 | + * then added to a the @pending_cmds_list list for later processing by a | |
| 648 | + * dedicated deferred worker. | |
| 649 | + * | |
| 650 | + * So, basically, once something new is spotted we proceed to de-queue all the | |
| 651 | + * freshly received used buffers until we found the one we were polling on, or, | |
| 652 | + * we have 'seemingly' emptied the virtqueue; if some buffers are still pending | |
| 653 | + * in the vqueue at the end of the polling loop (possible due to inherent races | |
| 654 | + * in virtqueues handling mechanisms), we similarly kick the deferred worker | |
| 655 | + * and let it process those, to avoid indefinitely looping in the .poll_done | |
| 656 | + * busy-waiting helper. | |
| 657 | + * | |
| 658 | + * Finally, we delegate to the deferred worker also the final free of any timed | |
| 659 | + * out reply to a polled message that we should dequeue. | |
| 660 | + * | |
| 661 | + * Note that, since we do NOT have per-message suppress notification mechanism, | |
| 662 | + * the message we are polling for could be alternatively delivered via usual | |
| 663 | + * IRQs callbacks on another core which happened to have IRQs enabled while we | |
| 664 | + * are actively polling for it here: in such a case it will be handled as such | |
| 665 | + * by scmi_rx_callback() and the polling loop in the SCMI Core TX path will be | |
| 666 | + * transparently terminated anyway. | |
| 667 | + * | |
| 668 | + * Return: True once polling has successfully completed. | |
| 669 | + */ | |
| 670 | +static bool virtio_poll_done(struct scmi_chan_info *cinfo, | |
| 671 | + struct scmi_xfer *xfer) | |
| 672 | +{ | |
| 673 | + bool pending, found = false; | |
| 674 | + unsigned int length, any_prefetched = 0; | |
| 675 | + unsigned long flags; | |
| 676 | + struct scmi_vio_msg *next_msg, *msg = xfer->priv; | |
| 677 | + struct scmi_vio_channel *vioch = cinfo->transport_info; | |
| 678 | + | |
| 679 | + if (!msg) | |
| 680 | + return true; | |
| 681 | + | |
| 682 | + /* | |
| 683 | + * Processed already by other polling loop on another CPU ? | |
| 684 | + * | |
| 685 | + * Note that this message is acquired on the poll path so cannot vanish | |
| 686 | + * while inside this loop iteration even if concurrently processed on | |
| 687 | + * the IRQ path. | |
| 688 | + * | |
| 689 | + * Avoid to acquire poll_lock since polled_status can be changed | |
| 690 | + * in a relevant manner only later in this same thread of execution: | |
| 691 | + * any other possible changes made concurrently by other polling loops | |
| 692 | + * or by a reply delivered on the IRQ path have no meaningful impact on | |
| 693 | + * this loop iteration: in other words it is harmless to allow this | |
| 694 | + * possible race but let has avoid spinlocking with irqs off in this | |
| 695 | + * initial part of the polling loop. | |
| 696 | + */ | |
| 697 | + if (msg->poll_status == VIO_MSG_POLL_DONE) | |
| 698 | + return true; | |
| 699 | + | |
| 700 | + if (!scmi_vio_channel_acquire(vioch)) | |
| 701 | + return true; | |
| 702 | + | |
| 703 | + /* Has cmdq index moved at all ? */ | |
| 704 | + pending = virtqueue_poll(vioch->vqueue, msg->poll_idx); | |
| 705 | + if (!pending) { | |
| 706 | + scmi_vio_channel_release(vioch); | |
| 707 | + return false; | |
| 708 | + } | |
| 709 | + | |
| 710 | + spin_lock_irqsave(&vioch->lock, flags); | |
| 711 | + virtqueue_disable_cb(vioch->vqueue); | |
| 712 | + | |
| 713 | + /* | |
| 714 | + * Process all new messages till the polled-for message is found OR | |
| 715 | + * the vqueue is empty. | |
| 716 | + */ | |
| 717 | + while ((next_msg = virtqueue_get_buf(vioch->vqueue, &length))) { | |
| 718 | + bool next_msg_done = false; | |
| 719 | + | |
| 720 | + /* | |
| 721 | + * Mark any dequeued buffer message as VIO_MSG_POLL_DONE so | |
| 722 | + * that can be properly freed even on timeout in mark_txdone. | |
| 723 | + */ | |
| 724 | + spin_lock(&next_msg->poll_lock); | |
| 725 | + if (next_msg->poll_status == VIO_MSG_POLLING) { | |
| 726 | + next_msg->poll_status = VIO_MSG_POLL_DONE; | |
| 727 | + next_msg_done = true; | |
| 728 | + } | |
| 729 | + spin_unlock(&next_msg->poll_lock); | |
| 730 | + | |
| 731 | + next_msg->rx_len = length; | |
| 732 | + /* Is the message we were polling for ? */ | |
| 733 | + if (next_msg == msg) { | |
| 734 | + found = true; | |
| 735 | + break; | |
| 736 | + } else if (next_msg_done) { | |
| 737 | + /* Skip the rest if this was another polled msg */ | |
| 738 | + continue; | |
| 739 | + } | |
| 740 | + | |
| 741 | + /* | |
| 742 | + * Enqueue for later processing any non-polled message and any | |
| 743 | + * timed-out polled one that we happen to have dequeued. | |
| 744 | + */ | |
| 745 | + spin_lock(&next_msg->poll_lock); | |
| 746 | + if (next_msg->poll_status == VIO_MSG_NOT_POLLED || | |
| 747 | + next_msg->poll_status == VIO_MSG_POLL_TIMEOUT) { | |
| 748 | + spin_unlock(&next_msg->poll_lock); | |
| 749 | + | |
| 750 | + any_prefetched++; | |
| 751 | + spin_lock(&vioch->pending_lock); | |
| 752 | + list_add_tail(&next_msg->list, | |
| 753 | + &vioch->pending_cmds_list); | |
| 754 | + spin_unlock(&vioch->pending_lock); | |
| 755 | + } else { | |
| 756 | + spin_unlock(&next_msg->poll_lock); | |
| 757 | + } | |
| 758 | + } | |
| 759 | + | |
| 760 | + /* | |
| 761 | + * When the polling loop has successfully terminated if something | |
| 762 | + * else was queued in the meantime, it will be served by a deferred | |
| 763 | + * worker OR by the normal IRQ/callback OR by other poll loops. | |
| 764 | + * | |
| 765 | + * If we are still looking for the polled reply, the polling index has | |
| 766 | + * to be updated to the current vqueue last used index. | |
| 767 | + */ | |
| 768 | + if (found) { | |
| 769 | + pending = !virtqueue_enable_cb(vioch->vqueue); | |
| 770 | + } else { | |
| 771 | + msg->poll_idx = virtqueue_enable_cb_prepare(vioch->vqueue); | |
| 772 | + pending = virtqueue_poll(vioch->vqueue, msg->poll_idx); | |
| 773 | + } | |
| 774 | + | |
| 775 | + if (vioch->deferred_tx_wq && (any_prefetched || pending)) | |
| 776 | + queue_work(vioch->deferred_tx_wq, &vioch->deferred_tx_work); | |
| 777 | + | |
| 778 | + spin_unlock_irqrestore(&vioch->lock, flags); | |
| 779 | + | |
| 780 | + scmi_vio_channel_release(vioch); | |
| 781 | + | |
| 782 | + return found; | |
| 369 | 783 | } |
| 370 | 784 | |
| 371 | 785 | static const struct scmi_transport_ops scmi_virtio_ops = { |
| @@ -377,6 +791,8 @@ static const struct scmi_transport_ops scmi_virtio_ops = { · 5 unmodified lines | ||
| 377 | 791 | .send_message = virtio_send_message, |
| 378 | 792 | .fetch_response = virtio_fetch_response, |
| 379 | 793 | .fetch_notification = virtio_fetch_notification, |
| 794 | + .mark_txdone = virtio_mark_txdone, | |
| 795 | + .poll_done = virtio_poll_done, | |
| 380 | 796 | }; |
| 381 | 797 | |
| 382 | 798 | static int scmi_vio_probe(struct virtio_device *vdev) |
| @@ -417,8 +833,10 @@ static int scmi_vio_probe(struct virtio_device *vdev) · 34 unmodified lines | ||
| 417 | 833 | unsigned int sz; |
| 418 | 834 | |
| 419 | 835 | spin_lock_init(&channels[i].lock); |
| 420 | − spin_lock_init(&channels[i].ready_lock); | |
| 836 | + spin_lock_init(&channels[i].free_lock); | |
| 421 | 837 | INIT_LIST_HEAD(&channels[i].free_list); |
| 838 | + spin_lock_init(&channels[i].pending_lock); | |
| 839 | + INIT_LIST_HEAD(&channels[i].pending_cmds_list); | |
| 422 | 840 | channels[i].vqueue = vqs[i]; |
| 423 | 841 | |
| 424 | 842 | sz = virtqueue_get_vring_size(channels[i].vqueue); |
| @@ -427,10 +845,10 @@ static int scmi_vio_probe(struct virtio_device *vdev) · 2 unmodified lines | ||
| 427 | 845 | sz /= DESCRIPTORS_PER_TX_MSG; |
| 428 | 846 | |
| 429 | 847 | if (sz > MSG_TOKEN_MAX) { |
| 430 | − dev_info_once(dev, | |
| 431 | − "%s virtqueue could hold %d messages. Only %ld allowed to be pending.\n", | |
| 432 | − channels[i].is_rx ? "rx" : "tx", | |
| 433 | − sz, MSG_TOKEN_MAX); | |
| 848 | + dev_info(dev, | |
| 849 | + "%s virtqueue could hold %d messages. Only %ld allowed to be pending.\n", | |
| 850 | + channels[i].is_rx ? "rx" : "tx", | |
| 851 | + sz, MSG_TOKEN_MAX); | |
| 434 | 852 | sz = MSG_TOKEN_MAX; |
| 435 | 853 | } |
| 436 | 854 | channels[i].max_msg = sz; |
| @@ -460,12 +878,13 @@ static void scmi_vio_remove(struct virtio_device *vdev) · 23 unmodified lines | ||
| 460 | 878 | |
| 461 | 879 | static int scmi_vio_validate(struct virtio_device *vdev) |
| 462 | 880 | { |
| 881 | +#ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE | |
| 463 | 882 | if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { |
| 464 | 883 | dev_err(&vdev->dev, |
| 465 | 884 | "device does not comply with spec version 1.x\n"); |
| 466 | 885 | return -EINVAL; |
| 467 | 886 | } |
| 468 | − | |
| 887 | +#endif | |
| 469 | 888 | return 0; |
| 470 | 889 | } |
| 471 | 890 | |
| @@ -503,7 +922,9 @@ const struct scmi_desc scmi_virtio_desc = { · 31 unmodified lines | ||
| 503 | 922 | .transport_init = virtio_scmi_init, |
| 504 | 923 | .transport_exit = virtio_scmi_exit, |
| 505 | 924 | .ops = &scmi_virtio_ops, |
| 506 | − .max_rx_timeout_ms = 60000, /* for non-realtime virtio devices */ | |
| 925 | + /* for non-realtime virtio devices */ | |
| 926 | + .max_rx_timeout_ms = VIRTIO_MAX_RX_TIMEOUT_MS, | |
| 507 | 927 | .max_msg = 0, /* overridden by virtio_get_max_msg() */ |
| 508 | 928 | .max_msg_size = VIRTIO_SCMI_MAX_MSG_SIZE, |
| 929 | + .atomic_enabled = IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_ATOMIC_ENABLE), | |
| 509 | 930 | }; |
| @@ -43,3 +43,48 @@ bool imx_sc_rm_is_resource_owned(struct imx_sc_ipc *ipc, u16 resource) · 42 unmodified lines | ||
| 43 | 43 | return hdr->func; |
| 44 | 44 | } |
| 45 | 45 | EXPORT_SYMBOL(imx_sc_rm_is_resource_owned); |
| 46 | + | |
| 47 | +struct imx_sc_msg_rm_get_resource_owner { | |
| 48 | + struct imx_sc_rpc_msg hdr; | |
| 49 | + union { | |
| 50 | + struct { | |
| 51 | + u16 resource; | |
| 52 | + } req; | |
| 53 | + struct { | |
| 54 | + u8 val; | |
| 55 | + } resp; | |
| 56 | + } data; | |
| 57 | +} __packed __aligned(4); | |
| 58 | + | |
| 59 | +/* | |
| 60 | + * This function get @resource partition number | |
| 61 | + * | |
| 62 | + * @param[in] ipc IPC handle | |
| 63 | + * @param[in] resource resource the control is associated with | |
| 64 | + * @param[out] pt pointer to return the partition number | |
| 65 | + * | |
| 66 | + * @return Returns 0 for success and < 0 for errors. | |
| 67 | + */ | |
| 68 | +int imx_sc_rm_get_resource_owner(struct imx_sc_ipc *ipc, u16 resource, u8 *pt) | |
| 69 | +{ | |
| 70 | + struct imx_sc_msg_rm_get_resource_owner msg; | |
| 71 | + struct imx_sc_rpc_msg *hdr = &msg.hdr; | |
| 72 | + int ret; | |
| 73 | + | |
| 74 | + hdr->ver = IMX_SC_RPC_VERSION; | |
| 75 | + hdr->svc = IMX_SC_RPC_SVC_RM; | |
| 76 | + hdr->func = IMX_SC_RM_FUNC_GET_RESOURCE_OWNER; | |
| 77 | + hdr->size = 2; | |
| 78 | + | |
| 79 | + msg.data.req.resource = resource; | |
| 80 | + | |
| 81 | + ret = imx_scu_call_rpc(ipc, &msg, true); | |
| 82 | + if (ret) | |
| 83 | + return ret; | |
| 84 | + | |
| 85 | + if (pt) | |
| 86 | + *pt = msg.data.resp.val; | |
| 87 | + | |
| 88 | + return 0; | |
| 89 | +} | |
| 90 | +EXPORT_SYMBOL(imx_sc_rm_get_resource_owner); | |
| @@ -155,6 +155,10 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { · 154 unmodified lines | ||
| 155 | 155 | { "vpu-pid", IMX_SC_R_VPU_PID0, 8, true, 0 }, |
| 156 | 156 | { "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, false, 0 }, |
| 157 | 157 | { "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, false, 0 }, |
| 158 | + { "vpu-enc1", IMX_SC_R_VPU_ENC_1, 1, false, 0 }, | |
| 159 | + { "vpu-mu0", IMX_SC_R_VPU_MU_0, 1, false, 0 }, | |
| 160 | + { "vpu-mu1", IMX_SC_R_VPU_MU_1, 1, false, 0 }, | |
| 161 | + { "vpu-mu2", IMX_SC_R_VPU_MU_2, 1, false, 0 }, | |
| 158 | 162 | |
| 159 | 163 | /* GPU SS */ |
| 160 | 164 | { "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, true, 0 }, |
| @@ -49,26 +49,12 @@ struct qcom_scm_mem_map_info { · 48 unmodified lines | ||
| 49 | 49 | __le64 mem_size; |
| 50 | 50 | }; |
| 51 | 51 | |
| 52 | −#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 | |
| 53 | −#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01 | |
| 54 | −#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 | |
| 55 | −#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20 | |
| 56 | − | |
| 57 | −#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04 | |
| 58 | −#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02 | |
| 59 | −#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10 | |
| 60 | −#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40 | |
| 61 | − | |
| 62 | −struct qcom_scm_wb_entry { | |
| 63 | − int flag; | |
| 64 | − void *entry; | |
| 52 | +/* Each bit configures cold/warm boot address for one of the 4 CPUs */ | |
| 53 | +static const u8 qcom_scm_cpu_cold_bits[QCOM_SCM_BOOT_MAX_CPUS] = { | |
| 54 | + 0, BIT(0), BIT(3), BIT(5) | |
| 65 | 55 | }; |
| 66 | − | |
| 67 | −static struct qcom_scm_wb_entry qcom_scm_wb[] = { | |
| 68 | − { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 }, | |
| 69 | − { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 }, | |
| 70 | − { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 }, | |
| 71 | − { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 }, | |
| 56 | +static const u8 qcom_scm_cpu_warm_bits[QCOM_SCM_BOOT_MAX_CPUS] = { | |
| 57 | + BIT(2), BIT(1), BIT(4), BIT(6) | |
| 72 | 58 | }; |
| 73 | 59 | |
| 74 | 60 | static const char * const qcom_scm_convention_names[] = { |
| @@ -179,9 +165,8 @@ found: · 104 unmodified lines | ||
| 179 | 165 | /** |
| 180 | 166 | * qcom_scm_call() - Invoke a syscall in the secure world |
| 181 | 167 | * @dev: device |
| 182 | − * @svc_id: service identifier | |
| 183 | − * @cmd_id: command identifier | |
| 184 | 168 | * @desc: Descriptor structure containing arguments and return values |
| 169 | + * @res: Structure containing results from SMC/HVC call | |
| 185 | 170 | * |
| 186 | 171 | * Sends a command to the SCM and waits for the command to finish processing. |
| 187 | 172 | * This should *only* be called in pre-emptible context. |
| @@ -205,8 +190,6 @@ static int qcom_scm_call(struct device *dev, const struct qcom_scm_desc *desc, · 17 unmodified lines | ||
| 205 | 190 | /** |
| 206 | 191 | * qcom_scm_call_atomic() - atomic variation of qcom_scm_call() |
| 207 | 192 | * @dev: device |
| 208 | − * @svc_id: service identifier | |
| 209 | − * @cmd_id: command identifier | |
| 210 | 193 | * @desc: Descriptor structure containing arguments and return values |
| 211 | 194 | * @res: Structure containing results from SMC/HVC call |
| 212 | 195 | * |
| @@ -260,97 +243,83 @@ static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id, · 47 unmodified lines | ||
| 260 | 243 | return ret ? false : !!res.result[0]; |
| 261 | 244 | } |
| 262 | 245 | |
| 263 | −/** | |
| 264 | − * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus | |
| 265 | − * @entry: Entry point function for the cpus | |
| 266 | − * @cpus: The cpumask of cpus that will use the entry point | |
| 267 | − * | |
| 268 | − * Set the Linux entry point for the SCM to transfer control to when coming | |
| 269 | − * out of a power down. CPU power down may be executed on cpuidle or hotplug. | |
| 270 | − */ | |
| 271 | −int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) | |
| 246 | +static int qcom_scm_set_boot_addr(void *entry, const u8 *cpu_bits) | |
| 272 | 247 | { |
| 273 | − int ret; | |
| 274 | − int flags = 0; | |
| 275 | 248 | int cpu; |
| 249 | + unsigned int flags = 0; | |
| 276 | 250 | struct qcom_scm_desc desc = { |
| 277 | 251 | .svc = QCOM_SCM_SVC_BOOT, |
| 278 | 252 | .cmd = QCOM_SCM_BOOT_SET_ADDR, |
| 279 | 253 | .arginfo = QCOM_SCM_ARGS(2), |
| 254 | + .owner = ARM_SMCCC_OWNER_SIP, | |
| 280 | 255 | }; |
| 281 | 256 | |
| 282 | − /* | |
| 283 | − * Reassign only if we are switching from hotplug entry point | |
| 284 | − * to cpuidle entry point or vice versa. | |
| 285 | − */ | |
| 286 | − for_each_cpu(cpu, cpus) { | |
| 287 | − if (entry == qcom_scm_wb[cpu].entry) | |
| 288 | − continue; | |
| 289 | − flags |= qcom_scm_wb[cpu].flag; | |
| 257 | + for_each_present_cpu(cpu) { | |
| 258 | + if (cpu >= QCOM_SCM_BOOT_MAX_CPUS) | |
| 259 | + return -EINVAL; | |
| 260 | + flags |= cpu_bits[cpu]; | |
| 290 | 261 | } |
| 291 | 262 | |
| 292 | − /* No change in entry function */ | |
| 293 | − if (!flags) | |
| 294 | − return 0; | |
| 295 | − | |
| 296 | 263 | desc.args[0] = flags; |
| 297 | 264 | desc.args[1] = virt_to_phys(entry); |
| 298 | 265 | |
| 299 | − ret = qcom_scm_call(__scm->dev, &desc, NULL); | |
| 300 | − if (!ret) { | |
| 301 | − for_each_cpu(cpu, cpus) | |
| 302 | − qcom_scm_wb[cpu].entry = entry; | |
| 303 | − } | |
| 304 | − | |
| 305 | − return ret; | |
| 266 | + return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL); | |
| 306 | 267 | } |
| 307 | −EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); | |
| 308 | 268 | |
| 309 | −/** | |
| 310 | − * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus | |
| 311 | − * @entry: Entry point function for the cpus | |
| 312 | − * @cpus: The cpumask of cpus that will use the entry point | |
| 313 | − * | |
| 314 | − * Set the cold boot address of the cpus. Any cpu outside the supported | |
| 315 | − * range would be removed from the cpu present mask. | |
| 316 | − */ | |
| 317 | −int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) | |
| 269 | +static int qcom_scm_set_boot_addr_mc(void *entry, unsigned int flags) | |
| 318 | 270 | { |
| 319 | − int flags = 0; | |
| 320 | − int cpu; | |
| 321 | − int scm_cb_flags[] = { | |
| 322 | − QCOM_SCM_FLAG_COLDBOOT_CPU0, | |
| 323 | − QCOM_SCM_FLAG_COLDBOOT_CPU1, | |
| 324 | − QCOM_SCM_FLAG_COLDBOOT_CPU2, | |
| 325 | − QCOM_SCM_FLAG_COLDBOOT_CPU3, | |
| 326 | − }; | |
| 327 | 271 | struct qcom_scm_desc desc = { |
| 328 | 272 | .svc = QCOM_SCM_SVC_BOOT, |
| 329 | − .cmd = QCOM_SCM_BOOT_SET_ADDR, | |
| 330 | − .arginfo = QCOM_SCM_ARGS(2), | |
| 273 | + .cmd = QCOM_SCM_BOOT_SET_ADDR_MC, | |
| 331 | 274 | .owner = ARM_SMCCC_OWNER_SIP, |
| 275 | + .arginfo = QCOM_SCM_ARGS(6), | |
| 276 | + .args = { | |
| 277 | + virt_to_phys(entry), | |
| 278 | + /* Apply to all CPUs in all affinity levels */ | |
| 279 | + ~0ULL, ~0ULL, ~0ULL, ~0ULL, | |
| 280 | + flags, | |
| 281 | + }, | |
| 332 | 282 | }; |
| 333 | 283 | |
| 334 | − if (!cpus || cpumask_empty(cpus)) | |
| 335 | − return -EINVAL; | |
| 284 | + /* Need a device for DMA of the additional arguments */ | |
| 285 | + if (!__scm || __get_convention() == SMC_CONVENTION_LEGACY) | |
| 286 | + return -EOPNOTSUPP; | |
| 336 | 287 | |
| 337 | − for_each_cpu(cpu, cpus) { | |
| 338 | − if (cpu < ARRAY_SIZE(scm_cb_flags)) | |
| 339 | − flags |= scm_cb_flags[cpu]; | |
| 340 | − else | |
| 341 | − set_cpu_present(cpu, false); | |
| 342 | − } | |
| 288 | + return qcom_scm_call(__scm->dev, &desc, NULL); | |
| 289 | +} | |
| 343 | 290 | |
| 344 | − desc.args[0] = flags; | |
| 345 | − desc.args[1] = virt_to_phys(entry); | |
| 291 | +/** | |
| 292 | + * qcom_scm_set_warm_boot_addr() - Set the warm boot address for all cpus | |
| 293 | + * @entry: Entry point function for the cpus | |
| 294 | + * | |
| 295 | + * Set the Linux entry point for the SCM to transfer control to when coming | |
| 296 | + * out of a power down. CPU power down may be executed on cpuidle or hotplug. | |
| 297 | + */ | |
| 298 | +int qcom_scm_set_warm_boot_addr(void *entry) | |
| 299 | +{ | |
| 300 | + if (qcom_scm_set_boot_addr_mc(entry, QCOM_SCM_BOOT_MC_FLAG_WARMBOOT)) | |
| 301 | + /* Fallback to old SCM call */ | |
| 302 | + return qcom_scm_set_boot_addr(entry, qcom_scm_cpu_warm_bits); | |
| 303 | + return 0; | |
| 304 | +} | |
| 305 | +EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); | |
| 346 | 306 | |
| 347 | − return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL); | |
| 307 | +/** | |
| 308 | + * qcom_scm_set_cold_boot_addr() - Set the cold boot address for all cpus | |
| 309 | + * @entry: Entry point function for the cpus | |
| 310 | + */ | |
| 311 | +int qcom_scm_set_cold_boot_addr(void *entry) | |
| 312 | +{ | |
| 313 | + if (qcom_scm_set_boot_addr_mc(entry, QCOM_SCM_BOOT_MC_FLAG_COLDBOOT)) | |
| 314 | + /* Fallback to old SCM call */ | |
| 315 | + return qcom_scm_set_boot_addr(entry, qcom_scm_cpu_cold_bits); | |
| 316 | + return 0; | |
| 348 | 317 | } |
| 349 | 318 | EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); |
| 350 | 319 | |
| 351 | 320 | /** |
| 352 | 321 | * qcom_scm_cpu_power_down() - Power down the cpu |
| 353 | − * @flags - Flags to flush cache | |
| 322 | + * @flags: Flags to flush cache | |
| 354 | 323 | * |
| 355 | 324 | * This is an end point to power down cpu. If there was a pending interrupt, |
| 356 | 325 | * the control would return from this function, otherwise, the cpu jumps to the |
| @@ -435,10 +404,16 @@ static void qcom_scm_set_download_mode(bool enable) · 78 unmodified lines | ||
| 435 | 404 | * and optional blob of data used for authenticating the metadata |
| 436 | 405 | * and the rest of the firmware |
| 437 | 406 | * @size: size of the metadata |
| 407 | + * @ctx: optional metadata context | |
| 438 | 408 | * |
| 439 | − * Returns 0 on success. | |
| 409 | + * Return: 0 on success. | |
| 410 | + * | |
| 411 | + * Upon successful return, the PAS metadata context (@ctx) will be used to | |
| 412 | + * track the metadata allocation, this needs to be released by invoking | |
| 413 | + * qcom_scm_pas_metadata_release() by the caller. | |
| 440 | 414 | */ |
| 441 | −int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) | |
| 415 | +int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size, | |
| 416 | + struct qcom_scm_pas_metadata *ctx) | |
| 442 | 417 | { |
| 443 | 418 | dma_addr_t mdata_phys; |
| 444 | 419 | void *mdata_buf; |
| @@ -467,7 +442,7 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) · 22 unmodified lines | ||
| 467 | 442 | |
| 468 | 443 | ret = qcom_scm_clk_enable(); |
| 469 | 444 | if (ret) |
| 470 | − goto free_metadata; | |
| 445 | + goto out; | |
| 471 | 446 | |
| 472 | 447 | desc.args[1] = mdata_phys; |
| 473 | 448 | |
| @@ -475,13 +450,36 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) · 1 unmodified line | ||
| 475 | 450 | |
| 476 | 451 | qcom_scm_clk_disable(); |
| 477 | 452 | |
| 478 | −free_metadata: | |
| 479 | − dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys); | |
| 453 | +out: | |
| 454 | + if (ret < 0 || !ctx) { | |
| 455 | + dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys); | |
| 456 | + } else if (ctx) { | |
| 457 | + ctx->ptr = mdata_buf; | |
| 458 | + ctx->phys = mdata_phys; | |
| 459 | + ctx->size = size; | |
| 460 | + } | |
| 480 | 461 | |
| 481 | 462 | return ret ? : res.result[0]; |
| 482 | 463 | } |
| 483 | 464 | EXPORT_SYMBOL(qcom_scm_pas_init_image); |
| 484 | 465 | |
| 466 | +/** | |
| 467 | + * qcom_scm_pas_metadata_release() - release metadata context | |
| 468 | + * @ctx: metadata context | |
| 469 | + */ | |
| 470 | +void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx) | |
| 471 | +{ | |
| 472 | + if (!ctx->ptr) | |
| 473 | + return; | |
| 474 | + | |
| 475 | + dma_free_coherent(__scm->dev, ctx->size, ctx->ptr, ctx->phys); | |
| 476 | + | |
| 477 | + ctx->ptr = NULL; | |
| 478 | + ctx->phys = 0; | |
| 479 | + ctx->size = 0; | |
| 480 | +} | |
| 481 | +EXPORT_SYMBOL(qcom_scm_pas_metadata_release); | |
| 482 | + | |
| 485 | 483 | /** |
| 486 | 484 | * qcom_scm_pas_mem_setup() - Prepare the memory related to a given peripheral |
| 487 | 485 | * for firmware loading |
| @@ -749,12 +747,6 @@ int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) · 261 unmodified lines | ||
| 749 | 747 | }; |
| 750 | 748 | int ret; |
| 751 | 749 | |
| 752 | − desc.args[0] = addr; | |
| 753 | − desc.args[1] = size; | |
| 754 | − desc.args[2] = spare; | |
| 755 | − desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL, | |
| 756 | − QCOM_SCM_VAL); | |
| 757 | − | |
| 758 | 750 | ret = qcom_scm_call(__scm->dev, &desc, NULL); |
| 759 | 751 | |
| 760 | 752 | /* the pg table has been initialized already, ignore the error */ |
| @@ -765,6 +757,21 @@ int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) · 4 unmodified lines | ||
| 765 | 757 | } |
| 766 | 758 | EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init); |
| 767 | 759 | |
| 760 | +int qcom_scm_iommu_set_cp_pool_size(u32 spare, u32 size) | |
| 761 | +{ | |
| 762 | + struct qcom_scm_desc desc = { | |
| 763 | + .svc = QCOM_SCM_SVC_MP, | |
| 764 | + .cmd = QCOM_SCM_MP_IOMMU_SET_CP_POOL_SIZE, | |
| 765 | + .arginfo = QCOM_SCM_ARGS(2), | |
| 766 | + .args[0] = size, | |
| 767 | + .args[1] = spare, | |
| 768 | + .owner = ARM_SMCCC_OWNER_SIP, | |
| 769 | + }; | |
| 770 | + | |
| 771 | + return qcom_scm_call(__scm->dev, &desc, NULL); | |
| 772 | +} | |
| 773 | +EXPORT_SYMBOL(qcom_scm_iommu_set_cp_pool_size); | |
| 774 | + | |
| 768 | 775 | int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size, |
| 769 | 776 | u32 cp_nonpixel_start, |
| 770 | 777 | u32 cp_nonpixel_size) |
| @@ -1131,6 +1138,22 @@ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) · 360 unmodified lines | ||
| 1131 | 1138 | } |
| 1132 | 1139 | EXPORT_SYMBOL(qcom_scm_hdcp_req); |
| 1133 | 1140 | |
| 1141 | +int qcom_scm_iommu_set_pt_format(u32 sec_id, u32 ctx_num, u32 pt_fmt) | |
| 1142 | +{ | |
| 1143 | + struct qcom_scm_desc desc = { | |
| 1144 | + .svc = QCOM_SCM_SVC_SMMU_PROGRAM, | |
| 1145 | + .cmd = QCOM_SCM_SMMU_PT_FORMAT, | |
| 1146 | + .arginfo = QCOM_SCM_ARGS(3), | |
| 1147 | + .args[0] = sec_id, | |
| 1148 | + .args[1] = ctx_num, | |
| 1149 | + .args[2] = pt_fmt, /* 0: LPAE AArch32 - 1: AArch64 */ | |
| 1150 | + .owner = ARM_SMCCC_OWNER_SIP, | |
| 1151 | + }; | |
| 1152 | + | |
| 1153 | + return qcom_scm_call(__scm->dev, &desc, NULL); | |
| 1154 | +} | |
| 1155 | +EXPORT_SYMBOL(qcom_scm_iommu_set_pt_format); | |
| 1156 | + | |
| 1134 | 1157 | int qcom_scm_qsmmu500_wait_safe_toggle(bool en) |
| 1135 | 1158 | { |
| 1136 | 1159 | struct qcom_scm_desc desc = { |
| @@ -78,8 +78,13 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, · 77 unmodified lines | ||
| 78 | 78 | #define QCOM_SCM_BOOT_SET_ADDR 0x01 |
| 79 | 79 | #define QCOM_SCM_BOOT_TERMINATE_PC 0x02 |
| 80 | 80 | #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 |
| 81 | +#define QCOM_SCM_BOOT_SET_ADDR_MC 0x11 | |
| 81 | 82 | #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a |
| 82 | 83 | #define QCOM_SCM_FLUSH_FLAG_MASK 0x3 |
| 84 | +#define QCOM_SCM_BOOT_MAX_CPUS 4 | |
| 85 | +#define QCOM_SCM_BOOT_MC_FLAG_AARCH64 BIT(0) | |
| 86 | +#define QCOM_SCM_BOOT_MC_FLAG_COLDBOOT BIT(1) | |
| 87 | +#define QCOM_SCM_BOOT_MC_FLAG_WARMBOOT BIT(2) | |
| 83 | 88 | |
| 84 | 89 | #define QCOM_SCM_SVC_PIL 0x02 |
| 85 | 90 | #define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01 |
| @@ -100,6 +105,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, · 14 unmodified lines | ||
| 100 | 105 | #define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02 |
| 101 | 106 | #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03 |
| 102 | 107 | #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04 |
| 108 | +#define QCOM_SCM_MP_IOMMU_SET_CP_POOL_SIZE 0x05 | |
| 103 | 109 | #define QCOM_SCM_MP_VIDEO_VAR 0x08 |
| 104 | 110 | #define QCOM_SCM_MP_ASSIGN 0x16 |
| 105 | 111 | |
| @@ -119,6 +125,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, · 13 unmodified lines | ||
| 119 | 125 | #define QCOM_SCM_LMH_LIMIT_DCVSH 0x10 |
| 120 | 126 | |
| 121 | 127 | #define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 |
| 128 | +#define QCOM_SCM_SMMU_PT_FORMAT 0x01 | |
| 122 | 129 | #define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x03 |
| 123 | 130 | #define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x02 |
| 124 | 131 | |
| @@ -3412,7 +3412,7 @@ static int ti_sci_probe(struct platform_device *pdev) · 3411 unmodified lines | ||
| 3412 | 3412 | ret = register_restart_handler(&info->nb); |
| 3413 | 3413 | if (ret) { |
| 3414 | 3414 | dev_err(dev, "reboot registration fail(%d)\n", ret); |
| 3415 | − return ret; | |
| 3415 | + goto out; | |
| 3416 | 3416 | } |
| 3417 | 3417 | } |
| 3418 | 3418 | |
| @@ -424,7 +424,7 @@ static void __finalize_command(struct brcmstb_dpfe_priv *priv) · 423 unmodified lines | ||
| 424 | 424 | |
| 425 | 425 | /* |
| 426 | 426 | * It depends on the API version which MBOX register we have to write to |
| 427 | − * to signal we are done. | |
| 427 | + * signal we are done. | |
| 428 | 428 | */ |
| 429 | 429 | release_mbox = (priv->dpfe_api->version < 2) |
| 430 | 430 | ? REG_TO_HOST_MBOX : REG_TO_DCPU_MBOX; |
| @@ -1025,7 +1025,7 @@ static struct emif_data *__init_or_module get_device_details( · 1024 unmodified lines | ||
| 1025 | 1025 | temp = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); |
| 1026 | 1026 | dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL); |
| 1027 | 1027 | |
| 1028 | − if (!emif || !pd || !dev_info) { | |
| 1028 | + if (!emif || !temp || !dev_info) { | |
| 1029 | 1029 | dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__); |
| 1030 | 1030 | goto error; |
| 1031 | 1031 | } |
| @@ -1117,7 +1117,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev) · 85 unmodified lines | ||
| 1117 | 1117 | { |
| 1118 | 1118 | struct emif_data *emif; |
| 1119 | 1119 | struct resource *res; |
| 1120 | − int irq; | |
| 1120 | + int irq, ret; | |
| 1121 | 1121 | |
| 1122 | 1122 | if (pdev->dev.of_node) |
| 1123 | 1123 | emif = of_get_memory_device_details(pdev->dev.of_node, &pdev->dev); |
| @@ -1147,7 +1147,9 @@ static int __init_or_module emif_probe(struct platform_device *pdev) · 23 unmodified lines | ||
| 1147 | 1147 | emif_onetime_settings(emif); |
| 1148 | 1148 | emif_debugfs_init(emif); |
| 1149 | 1149 | disable_and_clear_all_interrupts(emif); |
| 1150 | − setup_interrupts(emif, irq); | |
| 1150 | + ret = setup_interrupts(emif, irq); | |
| 1151 | + if (ret) | |
| 1152 | + goto error; | |
| 1151 | 1153 | |
| 1152 | 1154 | /* One-time actions taken on probing the first device */ |
| 1153 | 1155 | if (!emif1) { |
| @@ -88,6 +88,7 @@ static int fsl_ifc_ctrl_remove(struct platform_device *dev) · 87 unmodified lines | ||
| 88 | 88 | { |
| 89 | 89 | struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(&dev->dev); |
| 90 | 90 | |
| 91 | + of_platform_depopulate(&dev->dev); | |
| 91 | 92 | free_irq(ctrl->nand_irq, ctrl); |
| 92 | 93 | free_irq(ctrl->irq, ctrl); |
| 93 | 94 | |
| @@ -285,8 +286,16 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) · 191 unmodified lines | ||
| 285 | 286 | } |
| 286 | 287 | } |
| 287 | 288 | |
| 289 | + /* legacy dts may still use "simple-bus" compatible */ | |
| 290 | + ret = of_platform_populate(dev->dev.of_node, NULL, NULL, | |
| 291 | + &dev->dev); | |
| 292 | + if (ret) | |
| 293 | + goto err_free_nandirq; | |
| 294 | + | |
| 288 | 295 | return 0; |
| 289 | 296 | |
| 297 | +err_free_nandirq: | |
| 298 | + free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev); | |
| 290 | 299 | err_free_irq: |
| 291 | 300 | free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev); |
| 292 | 301 | err_unmap_nandirq: |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <linux/device.h> |
| 9 | 9 | #include <linux/err.h> |
| 10 | 10 | #include <linux/io.h> |
| 11 | +#include <linux/iopoll.h> | |
| 11 | 12 | #include <linux/module.h> |
| 12 | 13 | #include <linux/of.h> |
| 13 | 14 | #include <linux/of_platform.h> |
| @@ -32,6 +33,10 @@ · 18 unmodified lines | ||
| 32 | 33 | #define SMI_DUMMY 0x444 |
| 33 | 34 | |
| 34 | 35 | /* SMI LARB */ |
| 36 | +#define SMI_LARB_SLP_CON 0xc | |
| 37 | +#define SLP_PROT_EN BIT(0) | |
| 38 | +#define SLP_PROT_RDY BIT(16) | |
| 39 | + | |
| 35 | 40 | #define SMI_LARB_CMD_THRT_CON 0x24 |
| 36 | 41 | #define SMI_LARB_THRT_RD_NU_LMT_MSK GENMASK(7, 4) |
| 37 | 42 | #define SMI_LARB_THRT_RD_NU_LMT (5 << 4) |
| @@ -81,6 +86,7 @@ · 43 unmodified lines | ||
| 81 | 86 | |
| 82 | 87 | #define MTK_SMI_FLAG_THRT_UPDATE BIT(0) |
| 83 | 88 | #define MTK_SMI_FLAG_SW_FLAG BIT(1) |
| 89 | +#define MTK_SMI_FLAG_SLEEP_CTL BIT(2) | |
| 84 | 90 | #define MTK_SMI_CAPS(flags, _x) (!!((flags) & (_x))) |
| 85 | 91 | |
| 86 | 92 | struct mtk_smi_reg_pair { |
| @@ -94,8 +100,6 @@ enum mtk_smi_type { · 7 unmodified lines | ||
| 94 | 100 | MTK_SMI_GEN2_SUB_COMM, /* gen2 smi sub common */ |
| 95 | 101 | }; |
| 96 | 102 | |
| 97 | −#define MTK_SMI_CLK_NR_MAX 4 | |
| 98 | − | |
| 99 | 103 | /* larbs: Require apb/smi clocks while gals is optional. */ |
| 100 | 104 | static const char * const mtk_smi_larb_clks[] = {"apb", "smi", "gals"}; |
| 101 | 105 | #define MTK_SMI_LARB_REQ_CLK_NR 2 |
| @@ -106,6 +110,7 @@ static const char * const mtk_smi_larb_clks[] = {"apb", "smi", "gals"}; · 4 unmodified lines | ||
| 106 | 110 | * sub common: Require apb/smi/gals0 clocks in has_gals case. Otherwise, only apb/smi are required. |
| 107 | 111 | */ |
| 108 | 112 | static const char * const mtk_smi_common_clks[] = {"apb", "smi", "gals0", "gals1"}; |
| 113 | +#define MTK_SMI_CLK_NR_MAX ARRAY_SIZE(mtk_smi_common_clks) | |
| 109 | 114 | #define MTK_SMI_COM_REQ_CLK_NR 2 |
| 110 | 115 | #define MTK_SMI_COM_GALS_REQ_CLK_NR MTK_SMI_CLK_NR_MAX |
| 111 | 116 | #define MTK_SMI_SUB_COM_GALS_REQ_CLK_NR 3 |
| @@ -335,13 +340,19 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = { · 223 unmodified lines | ||
| 335 | 340 | /* IPU0 | IPU1 | CCU */ |
| 336 | 341 | }; |
| 337 | 342 | |
| 343 | +static const struct mtk_smi_larb_gen mtk_smi_larb_mt8186 = { | |
| 344 | + .config_port = mtk_smi_larb_config_port_gen2_general, | |
| 345 | + .flags_general = MTK_SMI_FLAG_SLEEP_CTL, | |
| 346 | +}; | |
| 347 | + | |
| 338 | 348 | static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = { |
| 339 | 349 | .config_port = mtk_smi_larb_config_port_gen2_general, |
| 340 | 350 | }; |
| 341 | 351 | |
| 342 | 352 | static const struct mtk_smi_larb_gen mtk_smi_larb_mt8195 = { |
| 343 | 353 | .config_port = mtk_smi_larb_config_port_gen2_general, |
| 344 | − .flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG, | |
| 354 | + .flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG | | |
| 355 | + MTK_SMI_FLAG_SLEEP_CTL, | |
| 345 | 356 | .ostd = mtk_smi_larb_mt8195_ostd, |
| 346 | 357 | }; |
| 347 | 358 | |
| @@ -352,11 +363,32 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = { · 4 unmodified lines | ||
| 352 | 363 | {.compatible = "mediatek,mt8167-smi-larb", .data = &mtk_smi_larb_mt8167}, |
| 353 | 364 | {.compatible = "mediatek,mt8173-smi-larb", .data = &mtk_smi_larb_mt8173}, |
| 354 | 365 | {.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183}, |
| 366 | + {.compatible = "mediatek,mt8186-smi-larb", .data = &mtk_smi_larb_mt8186}, | |
| 355 | 367 | {.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192}, |
| 356 | 368 | {.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195}, |
| 357 | 369 | {} |
| 358 | 370 | }; |
| 359 | 371 | |
| 372 | +static int mtk_smi_larb_sleep_ctrl_enable(struct mtk_smi_larb *larb) | |
| 373 | +{ | |
| 374 | + int ret; | |
| 375 | + u32 tmp; | |
| 376 | + | |
| 377 | + writel_relaxed(SLP_PROT_EN, larb->base + SMI_LARB_SLP_CON); | |
| 378 | + ret = readl_poll_timeout_atomic(larb->base + SMI_LARB_SLP_CON, | |
| 379 | + tmp, !!(tmp & SLP_PROT_RDY), 10, 1000); | |
| 380 | + if (ret) { | |
| 381 | + /* TODO: Reset this larb if it fails here. */ | |
| 382 | + dev_err(larb->smi.dev, "sleep ctrl is not ready(0x%x).\n", tmp); | |
| 383 | + } | |
| 384 | + return ret; | |
| 385 | +} | |
| 386 | + | |
| 387 | +static void mtk_smi_larb_sleep_ctrl_disable(struct mtk_smi_larb *larb) | |
| 388 | +{ | |
| 389 | + writel_relaxed(0, larb->base + SMI_LARB_SLP_CON); | |
| 390 | +} | |
| 391 | + | |
| 360 | 392 | static int mtk_smi_device_link_common(struct device *dev, struct device **com_dev) |
| 361 | 393 | { |
| 362 | 394 | struct platform_device *smi_com_pdev; |
| @@ -466,9 +498,12 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev) · 103 unmodified lines | ||
| 466 | 498 | int ret; |
| 467 | 499 | |
| 468 | 500 | ret = clk_bulk_prepare_enable(larb->smi.clk_num, larb->smi.clks); |
| 469 | − if (ret < 0) | |
| 501 | + if (ret) | |
| 470 | 502 | return ret; |
| 471 | 503 | |
| 504 | + if (MTK_SMI_CAPS(larb->larb_gen->flags_general, MTK_SMI_FLAG_SLEEP_CTL)) | |
| 505 | + mtk_smi_larb_sleep_ctrl_disable(larb); | |
| 506 | + | |
| 472 | 507 | /* Configure the basic setting for this larb */ |
| 473 | 508 | larb_gen->config_port(dev); |
| 474 | 509 | |
| @@ -478,6 +513,13 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev) · 3 unmodified lines | ||
| 478 | 513 | static int __maybe_unused mtk_smi_larb_suspend(struct device *dev) |
| 479 | 514 | { |
| 480 | 515 | struct mtk_smi_larb *larb = dev_get_drvdata(dev); |
| 516 | + int ret; | |
| 517 | + | |
| 518 | + if (MTK_SMI_CAPS(larb->larb_gen->flags_general, MTK_SMI_FLAG_SLEEP_CTL)) { | |
| 519 | + ret = mtk_smi_larb_sleep_ctrl_enable(larb); | |
| 520 | + if (ret) | |
| 521 | + return ret; | |
| 522 | + } | |
| 481 | 523 | |
| 482 | 524 | clk_bulk_disable_unprepare(larb->smi.clk_num, larb->smi.clks); |
| 483 | 525 | return 0; |
| @@ -530,6 +572,12 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = { · 46 unmodified lines | ||
| 530 | 572 | F_MMU1_LARB(7), |
| 531 | 573 | }; |
| 532 | 574 | |
| 575 | +static const struct mtk_smi_common_plat mtk_smi_common_mt8186 = { | |
| 576 | + .type = MTK_SMI_GEN2, | |
| 577 | + .has_gals = true, | |
| 578 | + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(4) | F_MMU1_LARB(7), | |
| 579 | +}; | |
| 580 | + | |
| 533 | 581 | static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = { |
| 534 | 582 | .type = MTK_SMI_GEN2, |
| 535 | 583 | .has_gals = true, |
| @@ -564,6 +612,7 @@ static const struct of_device_id mtk_smi_common_of_ids[] = { · 28 unmodified lines | ||
| 564 | 612 | {.compatible = "mediatek,mt8167-smi-common", .data = &mtk_smi_common_gen2}, |
| 565 | 613 | {.compatible = "mediatek,mt8173-smi-common", .data = &mtk_smi_common_gen2}, |
| 566 | 614 | {.compatible = "mediatek,mt8183-smi-common", .data = &mtk_smi_common_mt8183}, |
| 615 | + {.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186}, | |
| 567 | 616 | {.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192}, |
| 568 | 617 | {.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo}, |
| 569 | 618 | {.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp}, |
| @@ -212,8 +212,10 @@ static int of_lpddr3_do_get_timings(struct device_node *np, · 211 unmodified lines | ||
| 212 | 212 | { |
| 213 | 213 | int ret; |
| 214 | 214 | |
| 215 | − /* The 'reg' param required since DT has changed, used as 'max-freq' */ | |
| 216 | − ret = of_property_read_u32(np, "reg", &tim->max_freq); | |
| 215 | + ret = of_property_read_u32(np, "max-freq", &tim->max_freq); | |
| 216 | + if (ret) | |
| 217 | + /* Deprecated way of passing max-freq as 'reg' */ | |
| 218 | + ret = of_property_read_u32(np, "reg", &tim->max_freq); | |
| 217 | 219 | ret |= of_property_read_u32(np, "min-freq", &tim->min_freq); |
| 218 | 220 | ret |= of_property_read_u32(np, "tRFC", &tim->tRFC); |
| 219 | 221 | ret |= of_property_read_u32(np, "tRRD", &tim->tRRD); |
| @@ -316,14 +318,21 @@ const struct lpddr2_info · 96 unmodified lines | ||
| 316 | 318 | struct property *prop; |
| 317 | 319 | const char *cp; |
| 318 | 320 | int err; |
| 319 | − | |
| 320 | − err = of_property_read_u32(np, "revision-id1", &info.revision_id1); | |
| 321 | − if (err) | |
| 322 | − info.revision_id1 = -ENOENT; | |
| 323 | − | |
| 324 | − err = of_property_read_u32(np, "revision-id2", &info.revision_id2); | |
| 325 | − if (err) | |
| 326 | − info.revision_id2 = -ENOENT; | |
| 321 | + u32 revision_id[2]; | |
| 322 | + | |
| 323 | + err = of_property_read_u32_array(np, "revision-id", revision_id, 2); | |
| 324 | + if (!err) { | |
| 325 | + info.revision_id1 = revision_id[0]; | |
| 326 | + info.revision_id2 = revision_id[1]; | |
| 327 | + } else { | |
| 328 | + err = of_property_read_u32(np, "revision-id1", &info.revision_id1); | |
| 329 | + if (err) | |
| 330 | + info.revision_id1 = -ENOENT; | |
| 331 | + | |
| 332 | + err = of_property_read_u32(np, "revision-id2", &info.revision_id2); | |
| 333 | + if (err) | |
| 334 | + info.revision_id2 = -ENOENT; | |
| 335 | + } | |
| 327 | 336 | |
| 328 | 337 | err = of_property_read_u32(np, "io-width", &info.io_width); |
| 329 | 338 | if (err) |
| @@ -28,6 +28,7 @@ config TEGRA30_EMC · 27 unmodified lines | ||
| 28 | 28 | default y |
| 29 | 29 | depends on ARCH_TEGRA_3x_SOC || COMPILE_TEST |
| 30 | 30 | select PM_OPP |
| 31 | + select DDR | |
| 31 | 32 | help |
| 32 | 33 | This driver is for the External Memory Controller (EMC) found on |
| 33 | 34 | Tegra30 chips. The EMC controls the external DRAM on the board. |
| @@ -540,7 +540,7 @@ static int emc_read_lpddr_mode_register(struct tegra_emc *emc, · 539 unmodified lines | ||
| 540 | 540 | unsigned int register_addr, |
| 541 | 541 | unsigned int *register_data) |
| 542 | 542 | { |
| 543 | − u32 memory_dev = emem_dev + 1; | |
| 543 | + u32 memory_dev = emem_dev ? 1 : 2; | |
| 544 | 544 | u32 val, mr_mask = 0xff; |
| 545 | 545 | int err; |
| 546 | 546 | |
| @@ -711,7 +711,7 @@ static int tegra210_emc_cd_set_state(struct thermal_cooling_device *cd, · 710 unmodified lines | ||
| 711 | 711 | return 0; |
| 712 | 712 | } |
| 713 | 713 | |
| 714 | −static struct thermal_cooling_device_ops tegra210_emc_cd_ops = { | |
| 714 | +static const struct thermal_cooling_device_ops tegra210_emc_cd_ops = { | |
| 715 | 715 | .get_max_state = tegra210_emc_cd_max_state, |
| 716 | 716 | .get_cur_state = tegra210_emc_cd_get_state, |
| 717 | 717 | .set_cur_state = tegra210_emc_cd_set_state, |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | * Copyright (C) 2019 GRATE-DRIVER project |
| 10 | 10 | */ |
| 11 | 11 | |
| 12 | +#include <linux/bitfield.h> | |
| 12 | 13 | #include <linux/clk.h> |
| 13 | 14 | #include <linux/clk/tegra.h> |
| 14 | 15 | #include <linux/debugfs.h> |
| @@ -31,11 +32,15 @@ · 16 unmodified lines | ||
| 31 | 32 | #include <soc/tegra/common.h> |
| 32 | 33 | #include <soc/tegra/fuse.h> |
| 33 | 34 | |
| 35 | +#include "../jedec_ddr.h" | |
| 36 | +#include "../of_memory.h" | |
| 37 | + | |
| 34 | 38 | #include "mc.h" |
| 35 | 39 | |
| 36 | 40 | #define EMC_INTSTATUS 0x000 |
| 37 | 41 | #define EMC_INTMASK 0x004 |
| 38 | 42 | #define EMC_DBG 0x008 |
| 43 | +#define EMC_ADR_CFG 0x010 | |
| 39 | 44 | #define EMC_CFG 0x00c |
| 40 | 45 | #define EMC_REFCTRL 0x020 |
| 41 | 46 | #define EMC_TIMING_CONTROL 0x028 |
| @@ -81,6 +86,7 @@ · 39 unmodified lines | ||
| 81 | 86 | #define EMC_EMRS 0x0d0 |
| 82 | 87 | #define EMC_SELF_REF 0x0e0 |
| 83 | 88 | #define EMC_MRW 0x0e8 |
| 89 | +#define EMC_MRR 0x0ec | |
| 84 | 90 | #define EMC_XM2DQSPADCTRL3 0x0f8 |
| 85 | 91 | #define EMC_FBIO_SPARE 0x100 |
| 86 | 92 | #define EMC_FBIO_CFG5 0x104 |
| @@ -208,6 +214,13 @@ · 121 unmodified lines | ||
| 208 | 214 | |
| 209 | 215 | #define EMC_REFRESH_OVERFLOW_INT BIT(3) |
| 210 | 216 | #define EMC_CLKCHANGE_COMPLETE_INT BIT(4) |
| 217 | +#define EMC_MRR_DIVLD_INT BIT(5) | |
| 218 | + | |
| 219 | +#define EMC_MRR_DEV_SELECTN GENMASK(31, 30) | |
| 220 | +#define EMC_MRR_MRR_MA GENMASK(23, 16) | |
| 221 | +#define EMC_MRR_MRR_DATA GENMASK(15, 0) | |
| 222 | + | |
| 223 | +#define EMC_ADR_CFG_EMEM_NUMDEV BIT(0) | |
| 211 | 224 | |
| 212 | 225 | enum emc_dram_type { |
| 213 | 226 | DRAM_TYPE_DDR3, |
| @@ -378,6 +391,8 @@ struct tegra_emc { · 164 unmodified lines | ||
| 378 | 391 | |
| 379 | 392 | /* protect shared rate-change code path */ |
| 380 | 393 | struct mutex rate_lock; |
| 394 | + | |
| 395 | + bool mrr_error; | |
| 381 | 396 | }; |
| 382 | 397 | |
| 383 | 398 | static int emc_seq_update_timing(struct tegra_emc *emc) |
| @@ -1008,12 +1023,18 @@ static int emc_load_timings_from_dt(struct tegra_emc *emc, · 624 unmodified lines | ||
| 1008 | 1023 | return 0; |
| 1009 | 1024 | } |
| 1010 | 1025 | |
| 1011 | −static struct device_node *emc_find_node_by_ram_code(struct device *dev) | |
| 1026 | +static struct device_node *emc_find_node_by_ram_code(struct tegra_emc *emc) | |
| 1012 | 1027 | { |
| 1028 | + struct device *dev = emc->dev; | |
| 1013 | 1029 | struct device_node *np; |
| 1014 | 1030 | u32 value, ram_code; |
| 1015 | 1031 | int err; |
| 1016 | 1032 | |
| 1033 | + if (emc->mrr_error) { | |
| 1034 | + dev_warn(dev, "memory timings skipped due to MRR error\n"); | |
| 1035 | + return NULL; | |
| 1036 | + } | |
| 1037 | + | |
| 1017 | 1038 | if (of_get_child_count(dev->of_node) == 0) { |
| 1018 | 1039 | dev_info_once(dev, "device-tree doesn't have memory timings\n"); |
| 1019 | 1040 | return NULL; |
| @@ -1035,11 +1056,73 @@ static struct device_node *emc_find_node_by_ram_code(struct device *dev) · 15 unmodified lines | ||
| 1035 | 1056 | return NULL; |
| 1036 | 1057 | } |
| 1037 | 1058 | |
| 1059 | +static int emc_read_lpddr_mode_register(struct tegra_emc *emc, | |
| 1060 | + unsigned int emem_dev, | |
| 1061 | + unsigned int register_addr, | |
| 1062 | + unsigned int *register_data) | |
| 1063 | +{ | |
| 1064 | + u32 memory_dev = emem_dev ? 1 : 2; | |
| 1065 | + u32 val, mr_mask = 0xff; | |
| 1066 | + int err; | |
| 1067 | + | |
| 1068 | + /* clear data-valid interrupt status */ | |
| 1069 | + writel_relaxed(EMC_MRR_DIVLD_INT, emc->regs + EMC_INTSTATUS); | |
| 1070 | + | |
| 1071 | + /* issue mode register read request */ | |
| 1072 | + val = FIELD_PREP(EMC_MRR_DEV_SELECTN, memory_dev); | |
| 1073 | + val |= FIELD_PREP(EMC_MRR_MRR_MA, register_addr); | |
| 1074 | + | |
| 1075 | + writel_relaxed(val, emc->regs + EMC_MRR); | |
| 1076 | + | |
| 1077 | + /* wait for the LPDDR2 data-valid interrupt */ | |
| 1078 | + err = readl_relaxed_poll_timeout_atomic(emc->regs + EMC_INTSTATUS, val, | |
| 1079 | + val & EMC_MRR_DIVLD_INT, | |
| 1080 | + 1, 100); | |
| 1081 | + if (err) { | |
| 1082 | + dev_err(emc->dev, "mode register %u read failed: %d\n", | |
| 1083 | + register_addr, err); | |
| 1084 | + emc->mrr_error = true; | |
| 1085 | + return err; | |
| 1086 | + } | |
| 1087 | + | |
| 1088 | + /* read out mode register data */ | |
| 1089 | + val = readl_relaxed(emc->regs + EMC_MRR); | |
| 1090 | + *register_data = FIELD_GET(EMC_MRR_MRR_DATA, val) & mr_mask; | |
| 1091 | + | |
| 1092 | + return 0; | |
| 1093 | +} | |
| 1094 | + | |
| 1095 | +static void emc_read_lpddr_sdram_info(struct tegra_emc *emc, | |
| 1096 | + unsigned int emem_dev) | |
| 1097 | +{ | |
| 1098 | + union lpddr2_basic_config4 basic_conf4; | |
| 1099 | + unsigned int manufacturer_id; | |
| 1100 | + unsigned int revision_id1; | |
| 1101 | + unsigned int revision_id2; | |
| 1102 | + | |
| 1103 | + /* these registers are standard for all LPDDR JEDEC memory chips */ | |
| 1104 | + emc_read_lpddr_mode_register(emc, emem_dev, 5, &manufacturer_id); | |
| 1105 | + emc_read_lpddr_mode_register(emc, emem_dev, 6, &revision_id1); | |
| 1106 | + emc_read_lpddr_mode_register(emc, emem_dev, 7, &revision_id2); | |
| 1107 | + emc_read_lpddr_mode_register(emc, emem_dev, 8, &basic_conf4.value); | |
| 1108 | + | |
| 1109 | + dev_info(emc->dev, "SDRAM[dev%u]: manufacturer: 0x%x (%s) rev1: 0x%x rev2: 0x%x prefetch: S%u density: %uMbit iowidth: %ubit\n", | |
| 1110 | + emem_dev, manufacturer_id, | |
| 1111 | + lpddr2_jedec_manufacturer(manufacturer_id), | |
| 1112 | + revision_id1, revision_id2, | |
| 1113 | + 4 >> basic_conf4.arch_type, | |
| 1114 | + 64 << basic_conf4.density, | |
| 1115 | + 32 >> basic_conf4.io_width); | |
| 1116 | +} | |
| 1117 | + | |
| 1038 | 1118 | static int emc_setup_hw(struct tegra_emc *emc) |
| 1039 | 1119 | { |
| 1120 | + u32 fbio_cfg5, emc_cfg, emc_dbg, emc_adr_cfg; | |
| 1040 | 1121 | u32 intmask = EMC_REFRESH_OVERFLOW_INT; |
| 1041 | − u32 fbio_cfg5, emc_cfg, emc_dbg; | |
| 1122 | + static bool print_sdram_info_once; | |
| 1042 | 1123 | enum emc_dram_type dram_type; |
| 1124 | + const char *dram_type_str; | |
| 1125 | + unsigned int emem_numdev; | |
| 1043 | 1126 | |
| 1044 | 1127 | fbio_cfg5 = readl_relaxed(emc->regs + EMC_FBIO_CFG5); |
| 1045 | 1128 | dram_type = fbio_cfg5 & EMC_FBIO_CFG5_DRAM_TYPE_MASK; |
| @@ -1076,6 +1159,34 @@ static int emc_setup_hw(struct tegra_emc *emc) · 30 unmodified lines | ||
| 1076 | 1159 | emc_dbg &= ~EMC_DBG_FORCE_UPDATE; |
| 1077 | 1160 | writel_relaxed(emc_dbg, emc->regs + EMC_DBG); |
| 1078 | 1161 | |
| 1162 | + switch (dram_type) { | |
| 1163 | + case DRAM_TYPE_DDR1: | |
| 1164 | + dram_type_str = "DDR1"; | |
| 1165 | + break; | |
| 1166 | + case DRAM_TYPE_LPDDR2: | |
| 1167 | + dram_type_str = "LPDDR2"; | |
| 1168 | + break; | |
| 1169 | + case DRAM_TYPE_DDR2: | |
| 1170 | + dram_type_str = "DDR2"; | |
| 1171 | + break; | |
| 1172 | + case DRAM_TYPE_DDR3: | |
| 1173 | + dram_type_str = "DDR3"; | |
| 1174 | + break; | |
| 1175 | + } | |
| 1176 | + | |
| 1177 | + emc_adr_cfg = readl_relaxed(emc->regs + EMC_ADR_CFG); | |
| 1178 | + emem_numdev = FIELD_GET(EMC_ADR_CFG_EMEM_NUMDEV, emc_adr_cfg) + 1; | |
| 1179 | + | |
| 1180 | + dev_info_once(emc->dev, "%u %s %s attached\n", emem_numdev, | |
| 1181 | + dram_type_str, emem_numdev == 2 ? "devices" : "device"); | |
| 1182 | + | |
| 1183 | + if (dram_type == DRAM_TYPE_LPDDR2 && !print_sdram_info_once) { | |
| 1184 | + while (emem_numdev--) | |
| 1185 | + emc_read_lpddr_sdram_info(emc, emem_numdev); | |
| 1186 | + | |
| 1187 | + print_sdram_info_once = true; | |
| 1188 | + } | |
| 1189 | + | |
| 1079 | 1190 | return 0; |
| 1080 | 1191 | } |
| 1081 | 1192 | |
| @@ -1538,14 +1649,6 @@ static int tegra_emc_probe(struct platform_device *pdev) · 456 unmodified lines | ||
| 1538 | 1649 | emc->clk_nb.notifier_call = emc_clk_change_notify; |
| 1539 | 1650 | emc->dev = &pdev->dev; |
| 1540 | 1651 | |
| 1541 | − np = emc_find_node_by_ram_code(&pdev->dev); | |
| 1542 | − if (np) { | |
| 1543 | − err = emc_load_timings_from_dt(emc, np); | |
| 1544 | − of_node_put(np); | |
| 1545 | − if (err) | |
| 1546 | − return err; | |
| 1547 | − } | |
| 1548 | − | |
| 1549 | 1652 | emc->regs = devm_platform_ioremap_resource(pdev, 0); |
| 1550 | 1653 | if (IS_ERR(emc->regs)) |
| 1551 | 1654 | return PTR_ERR(emc->regs); |
| @@ -1554,6 +1657,14 @@ static int tegra_emc_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 1554 | 1657 | if (err) |
| 1555 | 1658 | return err; |
| 1556 | 1659 | |
| 1660 | + np = emc_find_node_by_ram_code(emc); | |
| 1661 | + if (np) { | |
| 1662 | + err = emc_load_timings_from_dt(emc, np); | |
| 1663 | + of_node_put(np); | |
| 1664 | + if (err) | |
| 1665 | + return err; | |
| 1666 | + } | |
| 1667 | + | |
| 1557 | 1668 | err = platform_get_irq(pdev, 0); |
| 1558 | 1669 | if (err < 0) |
| 1559 | 1670 | return err; |
| @@ -928,7 +928,8 @@ static void q6v5proc_halt_axi_port(struct q6v5 *qproc, · 927 unmodified lines | ||
| 928 | 928 | regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0); |
| 929 | 929 | } |
| 930 | 930 | |
| 931 | −static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) | |
| 931 | +static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw, | |
| 932 | + const char *fw_name) | |
| 932 | 933 | { |
| 933 | 934 | unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; |
| 934 | 935 | dma_addr_t phys; |
| @@ -939,7 +940,7 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) · 4 unmodified lines | ||
| 939 | 940 | void *ptr; |
| 940 | 941 | int ret; |
| 941 | 942 | |
| 942 | − metadata = qcom_mdt_read_metadata(fw, &size); | |
| 943 | + metadata = qcom_mdt_read_metadata(fw, &size, fw_name, qproc->dev); | |
| 943 | 944 | if (IS_ERR(metadata)) |
| 944 | 945 | return PTR_ERR(metadata); |
| 945 | 946 | |
| @@ -1289,7 +1290,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc) · 343 unmodified lines | ||
| 1289 | 1290 | /* Initialize the RMB validator */ |
| 1290 | 1291 | writel(0, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG); |
| 1291 | 1292 | |
| 1292 | − ret = q6v5_mpss_init_image(qproc, fw); | |
| 1293 | + ret = q6v5_mpss_init_image(qproc, fw, qproc->hexagon_mdt_image); | |
| 1293 | 1294 | if (ret) |
| 1294 | 1295 | goto release_firmware; |
| 1295 | 1296 | |
| @@ -79,6 +79,8 @@ struct qcom_adsp { · 78 unmodified lines | ||
| 79 | 79 | struct qcom_rproc_subdev smd_subdev; |
| 80 | 80 | struct qcom_rproc_ssr ssr_subdev; |
| 81 | 81 | struct qcom_sysmon *sysmon; |
| 82 | + | |
| 83 | + struct qcom_scm_pas_metadata pas_metadata; | |
| 82 | 84 | }; |
| 83 | 85 | |
| 84 | 86 | static void adsp_minidump(struct rproc *rproc) |
| @@ -126,14 +128,34 @@ static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds, · 41 unmodified lines | ||
| 126 | 128 | } |
| 127 | 129 | } |
| 128 | 130 | |
| 131 | +static int adsp_unprepare(struct rproc *rproc) | |
| 132 | +{ | |
| 133 | + struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; | |
| 134 | + | |
| 135 | + /* | |
| 136 | + * adsp_load() did pass pas_metadata to the SCM driver for storing | |
| 137 | + * metadata context. It might have been released already if | |
| 138 | + * auth_and_reset() was successful, but in other cases clean it up | |
| 139 | + * here. | |
| 140 | + */ | |
| 141 | + qcom_scm_pas_metadata_release(&adsp->pas_metadata); | |
| 142 | + | |
| 143 | + return 0; | |
| 144 | +} | |
| 145 | + | |
| 129 | 146 | static int adsp_load(struct rproc *rproc, const struct firmware *fw) |
| 130 | 147 | { |
| 131 | 148 | struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; |
| 132 | 149 | int ret; |
| 133 | 150 | |
| 134 | − ret = qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id, | |
| 135 | − adsp->mem_region, adsp->mem_phys, adsp->mem_size, | |
| 136 | − &adsp->mem_reloc); | |
| 151 | + ret = qcom_mdt_pas_init(adsp->dev, fw, rproc->firmware, adsp->pas_id, | |
| 152 | + adsp->mem_phys, &adsp->pas_metadata); | |
| 153 | + if (ret) | |
| 154 | + return ret; | |
| 155 | + | |
| 156 | + ret = qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, adsp->pas_id, | |
| 157 | + adsp->mem_region, adsp->mem_phys, adsp->mem_size, | |
| 158 | + &adsp->mem_reloc); | |
| 137 | 159 | if (ret) |
| 138 | 160 | return ret; |
| 139 | 161 | |
| @@ -185,6 +207,8 @@ static int adsp_start(struct rproc *rproc) · 45 unmodified lines | ||
| 185 | 207 | goto disable_px_supply; |
| 186 | 208 | } |
| 187 | 209 | |
| 210 | + qcom_scm_pas_metadata_release(&adsp->pas_metadata); | |
| 211 | + | |
| 188 | 212 | return 0; |
| 189 | 213 | |
| 190 | 214 | disable_px_supply: |
| @@ -255,6 +279,7 @@ static unsigned long adsp_panic(struct rproc *rproc) · 64 unmodified lines | ||
| 255 | 279 | } |
| 256 | 280 | |
| 257 | 281 | static const struct rproc_ops adsp_ops = { |
| 282 | + .unprepare = adsp_unprepare, | |
| 258 | 283 | .start = adsp_start, |
| 259 | 284 | .stop = adsp_stop, |
| 260 | 285 | .da_to_va = adsp_da_to_va, |
| @@ -264,6 +289,7 @@ static const struct rproc_ops adsp_ops = { · 3 unmodified lines | ||
| 264 | 289 | }; |
| 265 | 290 | |
| 266 | 291 | static const struct rproc_ops adsp_minidump_ops = { |
| 292 | + .unprepare = adsp_unprepare, | |
| 267 | 293 | .start = adsp_start, |
| 268 | 294 | .stop = adsp_stop, |
| 269 | 295 | .da_to_va = adsp_da_to_va, |
| @@ -853,6 +879,10 @@ static const struct of_device_id adsp_of_match[] = { · 583 unmodified lines | ||
| 853 | 879 | { .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource}, |
| 854 | 880 | { .compatible = "qcom,sm8350-slpi-pas", .data = &sm8350_slpi_resource}, |
| 855 | 881 | { .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init}, |
| 882 | + { .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource}, | |
| 883 | + { .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource}, | |
| 884 | + { .compatible = "qcom,sm8450-slpi-pas", .data = &sm8350_slpi_resource}, | |
| 885 | + { .compatible = "qcom,sm8450-mpss-pas", .data = &mpss_resource_init}, | |
| 856 | 886 | { }, |
| 857 | 887 | }; |
| 858 | 888 | MODULE_DEVICE_TABLE(of, adsp_of_match); |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/platform_device.h> |
| 12 | 12 | #include <linux/pm_domain.h> |
| 13 | 13 | #include <dt-bindings/power/meson-a1-power.h> |
| 14 | +#include <dt-bindings/power/meson-s4-power.h> | |
| 14 | 15 | #include <linux/arm-smccc.h> |
| 15 | 16 | #include <linux/firmware/meson/meson_sm.h> |
| 16 | 17 | #include <linux/module.h> |
| @@ -119,6 +120,18 @@ static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = { · 102 unmodified lines | ||
| 119 | 120 | SEC_PD(RSA, 0), |
| 120 | 121 | }; |
| 121 | 122 | |
| 123 | +static struct meson_secure_pwrc_domain_desc s4_pwrc_domains[] = { | |
| 124 | + SEC_PD(S4_DOS_HEVC, 0), | |
| 125 | + SEC_PD(S4_DOS_VDEC, 0), | |
| 126 | + SEC_PD(S4_VPU_HDMI, 0), | |
| 127 | + SEC_PD(S4_USB_COMB, 0), | |
| 128 | + SEC_PD(S4_GE2D, 0), | |
| 129 | + /* ETH is for ethernet online wakeup, and should be always on */ | |
| 130 | + SEC_PD(S4_ETH, GENPD_FLAG_ALWAYS_ON), | |
| 131 | + SEC_PD(S4_DEMOD, 0), | |
| 132 | + SEC_PD(S4_AUDIO, 0), | |
| 133 | +}; | |
| 134 | + | |
| 122 | 135 | static int meson_secure_pwrc_probe(struct platform_device *pdev) |
| 123 | 136 | { |
| 124 | 137 | int i; |
| @@ -187,11 +200,20 @@ static struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = { · 62 unmodified lines | ||
| 187 | 200 | .count = ARRAY_SIZE(a1_pwrc_domains), |
| 188 | 201 | }; |
| 189 | 202 | |
| 203 | +static struct meson_secure_pwrc_domain_data meson_secure_s4_pwrc_data = { | |
| 204 | + .domains = s4_pwrc_domains, | |
| 205 | + .count = ARRAY_SIZE(s4_pwrc_domains), | |
| 206 | +}; | |
| 207 | + | |
| 190 | 208 | static const struct of_device_id meson_secure_pwrc_match_table[] = { |
| 191 | 209 | { |
| 192 | 210 | .compatible = "amlogic,meson-a1-pwrc", |
| 193 | 211 | .data = &meson_secure_a1_pwrc_data, |
| 194 | 212 | }, |
| 213 | + { | |
| 214 | + .compatible = "amlogic,meson-s4-pwrc", | |
| 215 | + .data = &meson_secure_s4_pwrc_data, | |
| 216 | + }, | |
| 195 | 217 | { /* sentinel */ } |
| 196 | 218 | }; |
| 197 | 219 | MODULE_DEVICE_TABLE(of, meson_secure_pwrc_match_table); |
| @@ -156,6 +156,9 @@ static const struct at91_soc socs[] __initconst = { · 155 unmodified lines | ||
| 156 | 156 | AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, |
| 157 | 157 | AT91_CIDR_VERSION_MASK, SAMA5D28C_LD2G_EXID_MATCH, |
| 158 | 158 | "sama5d28c 256MiB LPDDR2 SiP", "sama5d2"), |
| 159 | + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, | |
| 160 | + AT91_CIDR_VERSION_MASK, SAMA5D29CN_EXID_MATCH, | |
| 161 | + "sama5d29", "sama5d2"), | |
| 159 | 162 | AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, |
| 160 | 163 | AT91_CIDR_VERSION_MASK, SAMA5D31_EXID_MATCH, |
| 161 | 164 | "sama5d31", "sama5d3"), |
| @@ -95,6 +95,7 @@ at91_soc_init(const struct at91_soc *socs); · 94 unmodified lines | ||
| 95 | 95 | #define SAMA5D28C_LD2G_EXID_MATCH 0x00000072 |
| 96 | 96 | #define SAMA5D28CU_EXID_MATCH 0x00000010 |
| 97 | 97 | #define SAMA5D28CN_EXID_MATCH 0x00000020 |
| 98 | +#define SAMA5D29CN_EXID_MATCH 0x00000023 | |
| 98 | 99 | |
| 99 | 100 | #define SAMA5D3_CIDR_MATCH 0x0a5c07c0 |
| 100 | 101 | #define SAMA5D31_EXID_MATCH 0x00444300 |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | #include <dt-bindings/power/imx8mm-power.h> |
| 17 | 17 | #include <dt-bindings/power/imx8mn-power.h> |
| 18 | +#include <dt-bindings/power/imx8mq-power.h> | |
| 18 | 19 | |
| 19 | 20 | #define BLK_SFT_RSTN 0x0 |
| 20 | 21 | #define BLK_CLK_EN 0x4 |
| @@ -589,6 +590,68 @@ static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = { · 568 unmodified lines | ||
| 589 | 590 | .num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data), |
| 590 | 591 | }; |
| 591 | 592 | |
| 593 | +static int imx8mq_vpu_power_notifier(struct notifier_block *nb, | |
| 594 | + unsigned long action, void *data) | |
| 595 | +{ | |
| 596 | + struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl, | |
| 597 | + power_nb); | |
| 598 | + | |
| 599 | + if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF) | |
| 600 | + return NOTIFY_OK; | |
| 601 | + | |
| 602 | + /* | |
| 603 | + * The ADB in the VPUMIX domain has no separate reset and clock | |
| 604 | + * enable bits, but is ungated and reset together with the VPUs. The | |
| 605 | + * reset and clock enable inputs to the ADB is a logical OR of the | |
| 606 | + * VPU bits. In order to set the G2 fuse bits, the G2 clock must | |
| 607 | + * also be enabled. | |
| 608 | + */ | |
| 609 | + regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1)); | |
| 610 | + regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1)); | |
| 611 | + | |
| 612 | + if (action == GENPD_NOTIFY_ON) { | |
| 613 | + /* | |
| 614 | + * On power up we have no software backchannel to the GPC to | |
| 615 | + * wait for the ADB handshake to happen, so we just delay for a | |
| 616 | + * bit. On power down the GPC driver waits for the handshake. | |
| 617 | + */ | |
| 618 | + udelay(5); | |
| 619 | + | |
| 620 | + /* set "fuse" bits to enable the VPUs */ | |
| 621 | + regmap_set_bits(bc->regmap, 0x8, 0xffffffff); | |
| 622 | + regmap_set_bits(bc->regmap, 0xc, 0xffffffff); | |
| 623 | + regmap_set_bits(bc->regmap, 0x10, 0xffffffff); | |
| 624 | + } | |
| 625 | + | |
| 626 | + return NOTIFY_OK; | |
| 627 | +} | |
| 628 | + | |
| 629 | +static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = { | |
| 630 | + [IMX8MQ_VPUBLK_PD_G1] = { | |
| 631 | + .name = "vpublk-g1", | |
| 632 | + .clk_names = (const char *[]){ "g1", }, | |
| 633 | + .num_clks = 1, | |
| 634 | + .gpc_name = "g1", | |
| 635 | + .rst_mask = BIT(1), | |
| 636 | + .clk_mask = BIT(1), | |
| 637 | + }, | |
| 638 | + [IMX8MQ_VPUBLK_PD_G2] = { | |
| 639 | + .name = "vpublk-g2", | |
| 640 | + .clk_names = (const char *[]){ "g2", }, | |
| 641 | + .num_clks = 1, | |
| 642 | + .gpc_name = "g2", | |
| 643 | + .rst_mask = BIT(0), | |
| 644 | + .clk_mask = BIT(0), | |
| 645 | + }, | |
| 646 | +}; | |
| 647 | + | |
| 648 | +static const struct imx8m_blk_ctrl_data imx8mq_vpu_blk_ctl_dev_data = { | |
| 649 | + .max_reg = 0x14, | |
| 650 | + .power_notifier_fn = imx8mq_vpu_power_notifier, | |
| 651 | + .domains = imx8mq_vpu_blk_ctl_domain_data, | |
| 652 | + .num_domains = ARRAY_SIZE(imx8mq_vpu_blk_ctl_domain_data), | |
| 653 | +}; | |
| 654 | + | |
| 592 | 655 | static const struct of_device_id imx8m_blk_ctrl_of_match[] = { |
| 593 | 656 | { |
| 594 | 657 | .compatible = "fsl,imx8mm-vpu-blk-ctrl", |
| @@ -599,6 +662,9 @@ static const struct of_device_id imx8m_blk_ctrl_of_match[] = { · 4 unmodified lines | ||
| 599 | 662 | }, { |
| 600 | 663 | .compatible = "fsl,imx8mn-disp-blk-ctrl", |
| 601 | 664 | .data = &imx8mn_disp_blk_ctl_dev_data |
| 665 | + }, { | |
| 666 | + .compatible = "fsl,imx8mq-vpu-blk-ctrl", | |
| 667 | + .data = &imx8mq_vpu_blk_ctl_dev_data | |
| 602 | 668 | }, { |
| 603 | 669 | /* Sentinel */ |
| 604 | 670 | } |
| @@ -40,9 +40,6 @@ static int __init imx_soc_device_init(void) · 39 unmodified lines | ||
| 40 | 40 | if (!__mxc_cpu_type) |
| 41 | 41 | return 0; |
| 42 | 42 | |
| 43 | − if (of_machine_is_compatible("fsl,ls1021a")) | |
| 44 | − return 0; | |
| 45 | − | |
| 46 | 43 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); |
| 47 | 44 | if (!soc_dev_attr) |
| 48 | 45 | return -ENOMEM; |
| @@ -18,6 +18,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { · 17 unmodified lines | ||
| 18 | 18 | .name = "mm", |
| 19 | 19 | .sta_mask = PWR_STATUS_DISP, |
| 20 | 20 | .ctl_offs = SPM_DIS_PWR_CON, |
| 21 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 22 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 21 | 23 | .sram_pdn_bits = GENMASK(11, 8), |
| 22 | 24 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 23 | 25 | .bp_infracfg = { |
| @@ -30,6 +32,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { · 6 unmodified lines | ||
| 30 | 32 | .name = "vdec", |
| 31 | 33 | .sta_mask = PWR_STATUS_VDEC, |
| 32 | 34 | .ctl_offs = SPM_VDE_PWR_CON, |
| 35 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 36 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 33 | 37 | .sram_pdn_bits = GENMASK(8, 8), |
| 34 | 38 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 35 | 39 | .caps = MTK_SCPD_ACTIVE_WAKEUP, |
| @@ -38,6 +42,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { · 2 unmodified lines | ||
| 38 | 42 | .name = "isp", |
| 39 | 43 | .sta_mask = PWR_STATUS_ISP, |
| 40 | 44 | .ctl_offs = SPM_ISP_PWR_CON, |
| 45 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 46 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 41 | 47 | .sram_pdn_bits = GENMASK(11, 8), |
| 42 | 48 | .sram_pdn_ack_bits = GENMASK(13, 12), |
| 43 | 49 | .caps = MTK_SCPD_ACTIVE_WAKEUP, |
| @@ -46,6 +52,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { · 2 unmodified lines | ||
| 46 | 52 | .name = "mfg_async", |
| 47 | 53 | .sta_mask = MT8167_PWR_STATUS_MFG_ASYNC, |
| 48 | 54 | .ctl_offs = SPM_MFG_ASYNC_PWR_CON, |
| 55 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 56 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 49 | 57 | .sram_pdn_bits = 0, |
| 50 | 58 | .sram_pdn_ack_bits = 0, |
| 51 | 59 | .bp_infracfg = { |
| @@ -57,6 +65,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { · 5 unmodified lines | ||
| 57 | 65 | .name = "mfg_2d", |
| 58 | 66 | .sta_mask = MT8167_PWR_STATUS_MFG_2D, |
| 59 | 67 | .ctl_offs = SPM_MFG_2D_PWR_CON, |
| 68 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 69 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 60 | 70 | .sram_pdn_bits = GENMASK(11, 8), |
| 61 | 71 | .sram_pdn_ack_bits = GENMASK(15, 12), |
| 62 | 72 | }, |
| @@ -64,6 +74,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { · 1 unmodified line | ||
| 64 | 74 | .name = "mfg", |
| 65 | 75 | .sta_mask = PWR_STATUS_MFG, |
| 66 | 76 | .ctl_offs = SPM_MFG_PWR_CON, |
| 77 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 78 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 67 | 79 | .sram_pdn_bits = GENMASK(11, 8), |
| 68 | 80 | .sram_pdn_ack_bits = GENMASK(15, 12), |
| 69 | 81 | }, |
| @@ -71,6 +83,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { · 1 unmodified line | ||
| 71 | 83 | .name = "conn", |
| 72 | 84 | .sta_mask = PWR_STATUS_CONN, |
| 73 | 85 | .ctl_offs = SPM_CONN_PWR_CON, |
| 86 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 87 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 74 | 88 | .sram_pdn_bits = GENMASK(8, 8), |
| 75 | 89 | .sram_pdn_ack_bits = 0, |
| 76 | 90 | .caps = MTK_SCPD_ACTIVE_WAKEUP, |
| @@ -85,8 +99,6 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { · 8 unmodified lines | ||
| 85 | 99 | static const struct scpsys_soc_data mt8167_scpsys_data = { |
| 86 | 100 | .domains_data = scpsys_domain_data_mt8167, |
| 87 | 101 | .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8167), |
| 88 | − .pwr_sta_offs = SPM_PWR_STATUS, | |
| 89 | − .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 90 | 102 | }; |
| 91 | 103 | |
| 92 | 104 | #endif /* __SOC_MEDIATEK_MT8167_PM_DOMAINS_H */ |
| @@ -15,6 +15,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 14 unmodified lines | ||
| 15 | 15 | .name = "vdec", |
| 16 | 16 | .sta_mask = PWR_STATUS_VDEC, |
| 17 | 17 | .ctl_offs = SPM_VDE_PWR_CON, |
| 18 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 19 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 18 | 20 | .sram_pdn_bits = GENMASK(11, 8), |
| 19 | 21 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 20 | 22 | }, |
| @@ -22,6 +24,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 1 unmodified line | ||
| 22 | 24 | .name = "venc", |
| 23 | 25 | .sta_mask = PWR_STATUS_VENC, |
| 24 | 26 | .ctl_offs = SPM_VEN_PWR_CON, |
| 27 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 28 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 25 | 29 | .sram_pdn_bits = GENMASK(11, 8), |
| 26 | 30 | .sram_pdn_ack_bits = GENMASK(15, 12), |
| 27 | 31 | }, |
| @@ -29,6 +33,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 1 unmodified line | ||
| 29 | 33 | .name = "isp", |
| 30 | 34 | .sta_mask = PWR_STATUS_ISP, |
| 31 | 35 | .ctl_offs = SPM_ISP_PWR_CON, |
| 36 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 37 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 32 | 38 | .sram_pdn_bits = GENMASK(11, 8), |
| 33 | 39 | .sram_pdn_ack_bits = GENMASK(13, 12), |
| 34 | 40 | }, |
| @@ -36,6 +42,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 1 unmodified line | ||
| 36 | 42 | .name = "mm", |
| 37 | 43 | .sta_mask = PWR_STATUS_DISP, |
| 38 | 44 | .ctl_offs = SPM_DIS_PWR_CON, |
| 45 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 46 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 39 | 47 | .sram_pdn_bits = GENMASK(11, 8), |
| 40 | 48 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 41 | 49 | .bp_infracfg = { |
| @@ -47,6 +55,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 5 unmodified lines | ||
| 47 | 55 | .name = "venc_lt", |
| 48 | 56 | .sta_mask = PWR_STATUS_VENC_LT, |
| 49 | 57 | .ctl_offs = SPM_VEN2_PWR_CON, |
| 58 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 59 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 50 | 60 | .sram_pdn_bits = GENMASK(11, 8), |
| 51 | 61 | .sram_pdn_ack_bits = GENMASK(15, 12), |
| 52 | 62 | }, |
| @@ -54,6 +64,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 1 unmodified line | ||
| 54 | 64 | .name = "audio", |
| 55 | 65 | .sta_mask = PWR_STATUS_AUDIO, |
| 56 | 66 | .ctl_offs = SPM_AUDIO_PWR_CON, |
| 67 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 68 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 57 | 69 | .sram_pdn_bits = GENMASK(11, 8), |
| 58 | 70 | .sram_pdn_ack_bits = GENMASK(15, 12), |
| 59 | 71 | }, |
| @@ -61,6 +73,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 1 unmodified line | ||
| 61 | 73 | .name = "usb", |
| 62 | 74 | .sta_mask = PWR_STATUS_USB, |
| 63 | 75 | .ctl_offs = SPM_USB_PWR_CON, |
| 76 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 77 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 64 | 78 | .sram_pdn_bits = GENMASK(11, 8), |
| 65 | 79 | .sram_pdn_ack_bits = GENMASK(15, 12), |
| 66 | 80 | .caps = MTK_SCPD_ACTIVE_WAKEUP, |
| @@ -69,6 +83,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 2 unmodified lines | ||
| 69 | 83 | .name = "mfg_async", |
| 70 | 84 | .sta_mask = PWR_STATUS_MFG_ASYNC, |
| 71 | 85 | .ctl_offs = SPM_MFG_ASYNC_PWR_CON, |
| 86 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 87 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 72 | 88 | .sram_pdn_bits = GENMASK(11, 8), |
| 73 | 89 | .sram_pdn_ack_bits = 0, |
| 74 | 90 | .caps = MTK_SCPD_DOMAIN_SUPPLY, |
| @@ -77,6 +93,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 2 unmodified lines | ||
| 77 | 93 | .name = "mfg_2d", |
| 78 | 94 | .sta_mask = PWR_STATUS_MFG_2D, |
| 79 | 95 | .ctl_offs = SPM_MFG_2D_PWR_CON, |
| 96 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 97 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 80 | 98 | .sram_pdn_bits = GENMASK(11, 8), |
| 81 | 99 | .sram_pdn_ack_bits = GENMASK(13, 12), |
| 82 | 100 | }, |
| @@ -84,6 +102,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 1 unmodified line | ||
| 84 | 102 | .name = "mfg", |
| 85 | 103 | .sta_mask = PWR_STATUS_MFG, |
| 86 | 104 | .ctl_offs = SPM_MFG_PWR_CON, |
| 105 | + .pwr_sta_offs = SPM_PWR_STATUS, | |
| 106 | + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 87 | 107 | .sram_pdn_bits = GENMASK(13, 8), |
| 88 | 108 | .sram_pdn_ack_bits = GENMASK(21, 16), |
| 89 | 109 | .bp_infracfg = { |
| @@ -98,8 +118,6 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { · 8 unmodified lines | ||
| 98 | 118 | static const struct scpsys_soc_data mt8173_scpsys_data = { |
| 99 | 119 | .domains_data = scpsys_domain_data_mt8173, |
| 100 | 120 | .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8173), |
| 101 | − .pwr_sta_offs = SPM_PWR_STATUS, | |
| 102 | − .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, | |
| 103 | 121 | }; |
| 104 | 122 | |
| 105 | 123 | #endif /* __SOC_MEDIATEK_MT8173_PM_DOMAINS_H */ |
| @@ -25,6 +25,8 @@ · 24 unmodified lines | ||
| 25 | 25 | #define MT8183_RDMA0_SOUT_COLOR0 0x1 |
| 26 | 26 | #define MT8183_RDMA1_SOUT_DSI0 0x1 |
| 27 | 27 | |
| 28 | +#define MT8183_MMSYS_SW0_RST_B 0x140 | |
| 29 | + | |
| 28 | 30 | static const struct mtk_mmsys_routes mmsys_mt8183_routing_table[] = { |
| 29 | 31 | { |
| 30 | 32 | DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL_2L0, |
| @@ -15,6 +15,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 14 unmodified lines | ||
| 15 | 15 | .name = "audio", |
| 16 | 16 | .sta_mask = PWR_STATUS_AUDIO, |
| 17 | 17 | .ctl_offs = 0x0314, |
| 18 | + .pwr_sta_offs = 0x0180, | |
| 19 | + .pwr_sta2nd_offs = 0x0184, | |
| 18 | 20 | .sram_pdn_bits = GENMASK(11, 8), |
| 19 | 21 | .sram_pdn_ack_bits = GENMASK(15, 12), |
| 20 | 22 | }, |
| @@ -22,6 +24,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 1 unmodified line | ||
| 22 | 24 | .name = "conn", |
| 23 | 25 | .sta_mask = PWR_STATUS_CONN, |
| 24 | 26 | .ctl_offs = 0x032c, |
| 27 | + .pwr_sta_offs = 0x0180, | |
| 28 | + .pwr_sta2nd_offs = 0x0184, | |
| 25 | 29 | .sram_pdn_bits = 0, |
| 26 | 30 | .sram_pdn_ack_bits = 0, |
| 27 | 31 | .bp_infracfg = { |
| @@ -33,6 +37,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 5 unmodified lines | ||
| 33 | 37 | .name = "mfg_async", |
| 34 | 38 | .sta_mask = PWR_STATUS_MFG_ASYNC, |
| 35 | 39 | .ctl_offs = 0x0334, |
| 40 | + .pwr_sta_offs = 0x0180, | |
| 41 | + .pwr_sta2nd_offs = 0x0184, | |
| 36 | 42 | .sram_pdn_bits = 0, |
| 37 | 43 | .sram_pdn_ack_bits = 0, |
| 38 | 44 | }, |
| @@ -40,6 +46,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 1 unmodified line | ||
| 40 | 46 | .name = "mfg", |
| 41 | 47 | .sta_mask = PWR_STATUS_MFG, |
| 42 | 48 | .ctl_offs = 0x0338, |
| 49 | + .pwr_sta_offs = 0x0180, | |
| 50 | + .pwr_sta2nd_offs = 0x0184, | |
| 43 | 51 | .sram_pdn_bits = GENMASK(8, 8), |
| 44 | 52 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 45 | 53 | .caps = MTK_SCPD_DOMAIN_SUPPLY, |
| @@ -48,6 +56,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 2 unmodified lines | ||
| 48 | 56 | .name = "mfg_core0", |
| 49 | 57 | .sta_mask = BIT(7), |
| 50 | 58 | .ctl_offs = 0x034c, |
| 59 | + .pwr_sta_offs = 0x0180, | |
| 60 | + .pwr_sta2nd_offs = 0x0184, | |
| 51 | 61 | .sram_pdn_bits = GENMASK(8, 8), |
| 52 | 62 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 53 | 63 | }, |
| @@ -55,6 +65,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 1 unmodified line | ||
| 55 | 65 | .name = "mfg_core1", |
| 56 | 66 | .sta_mask = BIT(20), |
| 57 | 67 | .ctl_offs = 0x0310, |
| 68 | + .pwr_sta_offs = 0x0180, | |
| 69 | + .pwr_sta2nd_offs = 0x0184, | |
| 58 | 70 | .sram_pdn_bits = GENMASK(8, 8), |
| 59 | 71 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 60 | 72 | }, |
| @@ -62,6 +74,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 1 unmodified line | ||
| 62 | 74 | .name = "mfg_2d", |
| 63 | 75 | .sta_mask = PWR_STATUS_MFG_2D, |
| 64 | 76 | .ctl_offs = 0x0348, |
| 77 | + .pwr_sta_offs = 0x0180, | |
| 78 | + .pwr_sta2nd_offs = 0x0184, | |
| 65 | 79 | .sram_pdn_bits = GENMASK(8, 8), |
| 66 | 80 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 67 | 81 | .bp_infracfg = { |
| @@ -75,6 +89,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 7 unmodified lines | ||
| 75 | 89 | .name = "disp", |
| 76 | 90 | .sta_mask = PWR_STATUS_DISP, |
| 77 | 91 | .ctl_offs = 0x030c, |
| 92 | + .pwr_sta_offs = 0x0180, | |
| 93 | + .pwr_sta2nd_offs = 0x0184, | |
| 78 | 94 | .sram_pdn_bits = GENMASK(8, 8), |
| 79 | 95 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 80 | 96 | .bp_infracfg = { |
| @@ -94,6 +110,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 13 unmodified lines | ||
| 94 | 110 | .name = "cam", |
| 95 | 111 | .sta_mask = BIT(25), |
| 96 | 112 | .ctl_offs = 0x0344, |
| 113 | + .pwr_sta_offs = 0x0180, | |
| 114 | + .pwr_sta2nd_offs = 0x0184, | |
| 97 | 115 | .sram_pdn_bits = GENMASK(9, 8), |
| 98 | 116 | .sram_pdn_ack_bits = GENMASK(13, 12), |
| 99 | 117 | .bp_infracfg = { |
| @@ -117,6 +135,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 17 unmodified lines | ||
| 117 | 135 | .name = "isp", |
| 118 | 136 | .sta_mask = PWR_STATUS_ISP, |
| 119 | 137 | .ctl_offs = 0x0308, |
| 138 | + .pwr_sta_offs = 0x0180, | |
| 139 | + .pwr_sta2nd_offs = 0x0184, | |
| 120 | 140 | .sram_pdn_bits = GENMASK(9, 8), |
| 121 | 141 | .sram_pdn_ack_bits = GENMASK(13, 12), |
| 122 | 142 | .bp_infracfg = { |
| @@ -140,6 +160,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 17 unmodified lines | ||
| 140 | 160 | .name = "vdec", |
| 141 | 161 | .sta_mask = BIT(31), |
| 142 | 162 | .ctl_offs = 0x0300, |
| 163 | + .pwr_sta_offs = 0x0180, | |
| 164 | + .pwr_sta2nd_offs = 0x0184, | |
| 143 | 165 | .sram_pdn_bits = GENMASK(8, 8), |
| 144 | 166 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 145 | 167 | .bp_smi = { |
| @@ -153,6 +175,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 7 unmodified lines | ||
| 153 | 175 | .name = "venc", |
| 154 | 176 | .sta_mask = PWR_STATUS_VENC, |
| 155 | 177 | .ctl_offs = 0x0304, |
| 178 | + .pwr_sta_offs = 0x0180, | |
| 179 | + .pwr_sta2nd_offs = 0x0184, | |
| 156 | 180 | .sram_pdn_bits = GENMASK(11, 8), |
| 157 | 181 | .sram_pdn_ack_bits = GENMASK(15, 12), |
| 158 | 182 | .bp_smi = { |
| @@ -166,6 +190,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 7 unmodified lines | ||
| 166 | 190 | .name = "vpu_top", |
| 167 | 191 | .sta_mask = BIT(26), |
| 168 | 192 | .ctl_offs = 0x0324, |
| 193 | + .pwr_sta_offs = 0x0180, | |
| 194 | + .pwr_sta2nd_offs = 0x0184, | |
| 169 | 195 | .sram_pdn_bits = GENMASK(8, 8), |
| 170 | 196 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 171 | 197 | .bp_infracfg = { |
| @@ -193,6 +219,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 21 unmodified lines | ||
| 193 | 219 | .name = "vpu_core0", |
| 194 | 220 | .sta_mask = BIT(27), |
| 195 | 221 | .ctl_offs = 0x33c, |
| 222 | + .pwr_sta_offs = 0x0180, | |
| 223 | + .pwr_sta2nd_offs = 0x0184, | |
| 196 | 224 | .sram_pdn_bits = GENMASK(11, 8), |
| 197 | 225 | .sram_pdn_ack_bits = GENMASK(13, 12), |
| 198 | 226 | .bp_infracfg = { |
| @@ -211,6 +239,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 12 unmodified lines | ||
| 211 | 239 | .name = "vpu_core1", |
| 212 | 240 | .sta_mask = BIT(28), |
| 213 | 241 | .ctl_offs = 0x0340, |
| 242 | + .pwr_sta_offs = 0x0180, | |
| 243 | + .pwr_sta2nd_offs = 0x0184, | |
| 214 | 244 | .sram_pdn_bits = GENMASK(11, 8), |
| 215 | 245 | .sram_pdn_ack_bits = GENMASK(13, 12), |
| 216 | 246 | .bp_infracfg = { |
| @@ -230,8 +260,6 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { · 13 unmodified lines | ||
| 230 | 260 | static const struct scpsys_soc_data mt8183_scpsys_data = { |
| 231 | 261 | .domains_data = scpsys_domain_data_mt8183, |
| 232 | 262 | .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8183), |
| 233 | − .pwr_sta_offs = 0x0180, | |
| 234 | − .pwr_sta2nd_offs = 0x0184 | |
| 235 | 263 | }; |
| 236 | 264 | |
| 237 | 265 | #endif /* __SOC_MEDIATEK_MT8183_PM_DOMAINS_H */ |
| @@ -0,0 +1,115 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ | |
| 2 | + | |
| 3 | +#ifndef __SOC_MEDIATEK_MT8186_MMSYS_H | |
| 4 | +#define __SOC_MEDIATEK_MT8186_MMSYS_H | |
| 5 | + | |
| 6 | +#define MT8186_MMSYS_OVL_CON 0xF04 | |
| 7 | +#define MT8186_MMSYS_OVL0_CON_MASK 0x3 | |
| 8 | +#define MT8186_MMSYS_OVL0_2L_CON_MASK 0xC | |
| 9 | +#define MT8186_OVL0_GO_BLEND BIT(0) | |
| 10 | +#define MT8186_OVL0_GO_BG BIT(1) | |
| 11 | +#define MT8186_OVL0_2L_GO_BLEND BIT(2) | |
| 12 | +#define MT8186_OVL0_2L_GO_BG BIT(3) | |
| 13 | +#define MT8186_DISP_RDMA0_SOUT_SEL 0xF0C | |
| 14 | +#define MT8186_RDMA0_SOUT_SEL_MASK 0xF | |
| 15 | +#define MT8186_RDMA0_SOUT_TO_DSI0 (0) | |
| 16 | +#define MT8186_RDMA0_SOUT_TO_COLOR0 (1) | |
| 17 | +#define MT8186_RDMA0_SOUT_TO_DPI0 (2) | |
| 18 | +#define MT8186_DISP_OVL0_2L_MOUT_EN 0xF14 | |
| 19 | +#define MT8186_OVL0_2L_MOUT_EN_MASK 0xF | |
| 20 | +#define MT8186_OVL0_2L_MOUT_TO_RDMA0 BIT(0) | |
| 21 | +#define MT8186_OVL0_2L_MOUT_TO_RDMA1 BIT(3) | |
| 22 | +#define MT8186_DISP_OVL0_MOUT_EN 0xF18 | |
| 23 | +#define MT8186_OVL0_MOUT_EN_MASK 0xF | |
| 24 | +#define MT8186_OVL0_MOUT_TO_RDMA0 BIT(0) | |
| 25 | +#define MT8186_OVL0_MOUT_TO_RDMA1 BIT(3) | |
| 26 | +#define MT8186_DISP_DITHER0_MOUT_EN 0xF20 | |
| 27 | +#define MT8186_DITHER0_MOUT_EN_MASK 0xF | |
| 28 | +#define MT8186_DITHER0_MOUT_TO_DSI0 BIT(0) | |
| 29 | +#define MT8186_DITHER0_MOUT_TO_RDMA1 BIT(2) | |
| 30 | +#define MT8186_DITHER0_MOUT_TO_DPI0 BIT(3) | |
| 31 | +#define MT8186_DISP_RDMA0_SEL_IN 0xF28 | |
| 32 | +#define MT8186_RDMA0_SEL_IN_MASK 0xF | |
| 33 | +#define MT8186_RDMA0_FROM_OVL0 0 | |
| 34 | +#define MT8186_RDMA0_FROM_OVL0_2L 2 | |
| 35 | +#define MT8186_DISP_DSI0_SEL_IN 0xF30 | |
| 36 | +#define MT8186_DSI0_SEL_IN_MASK 0xF | |
| 37 | +#define MT8186_DSI0_FROM_RDMA0 0 | |
| 38 | +#define MT8186_DSI0_FROM_DITHER0 1 | |
| 39 | +#define MT8186_DSI0_FROM_RDMA1 2 | |
| 40 | +#define MT8186_DISP_RDMA1_MOUT_EN 0xF3C | |
| 41 | +#define MT8186_RDMA1_MOUT_EN_MASK 0xF | |
| 42 | +#define MT8186_RDMA1_MOUT_TO_DPI0_SEL BIT(0) | |
| 43 | +#define MT8186_RDMA1_MOUT_TO_DSI0_SEL BIT(2) | |
| 44 | +#define MT8186_DISP_RDMA1_SEL_IN 0xF40 | |
| 45 | +#define MT8186_RDMA1_SEL_IN_MASK 0xF | |
| 46 | +#define MT8186_RDMA1_FROM_OVL0 0 | |
| 47 | +#define MT8186_RDMA1_FROM_OVL0_2L 2 | |
| 48 | +#define MT8186_RDMA1_FROM_DITHER0 3 | |
| 49 | +#define MT8186_DISP_DPI0_SEL_IN 0xF44 | |
| 50 | +#define MT8186_DPI0_SEL_IN_MASK 0xF | |
| 51 | +#define MT8186_DPI0_FROM_RDMA1 0 | |
| 52 | +#define MT8186_DPI0_FROM_DITHER0 1 | |
| 53 | +#define MT8186_DPI0_FROM_RDMA0 2 | |
| 54 | + | |
| 55 | +#define MT8186_MMSYS_SW0_RST_B 0x160 | |
| 56 | + | |
| 57 | +static const struct mtk_mmsys_routes mmsys_mt8186_routing_table[] = { | |
| 58 | + { | |
| 59 | + DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, | |
| 60 | + MT8186_DISP_OVL0_MOUT_EN, MT8186_OVL0_MOUT_EN_MASK, | |
| 61 | + MT8186_OVL0_MOUT_TO_RDMA0 | |
| 62 | + }, | |
| 63 | + { | |
| 64 | + DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, | |
| 65 | + MT8186_DISP_RDMA0_SEL_IN, MT8186_RDMA0_SEL_IN_MASK, | |
| 66 | + MT8186_RDMA0_FROM_OVL0 | |
| 67 | + }, | |
| 68 | + { | |
| 69 | + DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, | |
| 70 | + MT8186_MMSYS_OVL_CON, MT8186_MMSYS_OVL0_CON_MASK, | |
| 71 | + MT8186_OVL0_GO_BLEND | |
| 72 | + }, | |
| 73 | + { | |
| 74 | + DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0, | |
| 75 | + MT8186_DISP_RDMA0_SOUT_SEL, MT8186_RDMA0_SOUT_SEL_MASK, | |
| 76 | + MT8186_RDMA0_SOUT_TO_COLOR0 | |
| 77 | + }, | |
| 78 | + { | |
| 79 | + DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0, | |
| 80 | + MT8186_DISP_DITHER0_MOUT_EN, MT8186_DITHER0_MOUT_EN_MASK, | |
| 81 | + MT8186_DITHER0_MOUT_TO_DSI0, | |
| 82 | + }, | |
| 83 | + { | |
| 84 | + DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0, | |
| 85 | + MT8186_DISP_DSI0_SEL_IN, MT8186_DSI0_SEL_IN_MASK, | |
| 86 | + MT8186_DSI0_FROM_DITHER0 | |
| 87 | + }, | |
| 88 | + { | |
| 89 | + DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA1, | |
| 90 | + MT8186_DISP_OVL0_2L_MOUT_EN, MT8186_OVL0_2L_MOUT_EN_MASK, | |
| 91 | + MT8186_OVL0_2L_MOUT_TO_RDMA1 | |
| 92 | + }, | |
| 93 | + { | |
| 94 | + DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA1, | |
| 95 | + MT8186_DISP_RDMA1_SEL_IN, MT8186_RDMA1_SEL_IN_MASK, | |
| 96 | + MT8186_RDMA1_FROM_OVL0_2L | |
| 97 | + }, | |
| 98 | + { | |
| 99 | + DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA1, | |
| 100 | + MT8186_MMSYS_OVL_CON, MT8186_MMSYS_OVL0_2L_CON_MASK, | |
| 101 | + MT8186_OVL0_2L_GO_BLEND | |
| 102 | + }, | |
| 103 | + { | |
| 104 | + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, | |
| 105 | + MT8186_DISP_RDMA1_MOUT_EN, MT8186_RDMA1_MOUT_EN_MASK, | |
| 106 | + MT8186_RDMA1_MOUT_TO_DPI0_SEL | |
| 107 | + }, | |
| 108 | + { | |
| 109 | + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, | |
| 110 | + MT8186_DISP_DPI0_SEL_IN, MT8186_DPI0_SEL_IN_MASK, | |
| 111 | + MT8186_DPI0_FROM_RDMA1 | |
| 112 | + }, | |
| 113 | +}; | |
| 114 | + | |
| 115 | +#endif /* __SOC_MEDIATEK_MT8186_MMSYS_H */ | |
| @@ -0,0 +1,344 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ | |
| 2 | +/* | |
| 3 | + * Copyright (c) 2022 MediaTek Inc. | |
| 4 | + * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> | |
| 5 | + */ | |
| 6 | + | |
| 7 | +#ifndef __SOC_MEDIATEK_MT8186_PM_DOMAINS_H | |
| 8 | +#define __SOC_MEDIATEK_MT8186_PM_DOMAINS_H | |
| 9 | + | |
| 10 | +#include "mtk-pm-domains.h" | |
| 11 | +#include <dt-bindings/power/mt8186-power.h> | |
| 12 | + | |
| 13 | +/* | |
| 14 | + * MT8186 power domain support | |
| 15 | + */ | |
| 16 | + | |
| 17 | +static const struct scpsys_domain_data scpsys_domain_data_mt8186[] = { | |
| 18 | + [MT8186_POWER_DOMAIN_MFG0] = { | |
| 19 | + .name = "mfg0", | |
| 20 | + .sta_mask = BIT(2), | |
| 21 | + .ctl_offs = 0x308, | |
| 22 | + .pwr_sta_offs = 0x16C, | |
| 23 | + .pwr_sta2nd_offs = 0x170, | |
| 24 | + .sram_pdn_bits = BIT(8), | |
| 25 | + .sram_pdn_ack_bits = BIT(12), | |
| 26 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, | |
| 27 | + }, | |
| 28 | + [MT8186_POWER_DOMAIN_MFG1] = { | |
| 29 | + .name = "mfg1", | |
| 30 | + .sta_mask = BIT(3), | |
| 31 | + .ctl_offs = 0x30c, | |
| 32 | + .pwr_sta_offs = 0x16C, | |
| 33 | + .pwr_sta2nd_offs = 0x170, | |
| 34 | + .sram_pdn_bits = BIT(8), | |
| 35 | + .sram_pdn_ack_bits = BIT(12), | |
| 36 | + .bp_infracfg = { | |
| 37 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP1, | |
| 38 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 39 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 40 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 41 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_MFG1_STEP2, | |
| 42 | + MT8186_TOP_AXI_PROT_EN_SET, | |
| 43 | + MT8186_TOP_AXI_PROT_EN_CLR, | |
| 44 | + MT8186_TOP_AXI_PROT_EN_STA), | |
| 45 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_MFG1_STEP3, | |
| 46 | + MT8186_TOP_AXI_PROT_EN_SET, | |
| 47 | + MT8186_TOP_AXI_PROT_EN_CLR, | |
| 48 | + MT8186_TOP_AXI_PROT_EN_STA), | |
| 49 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP4, | |
| 50 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 51 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 52 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 53 | + }, | |
| 54 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 55 | + }, | |
| 56 | + [MT8186_POWER_DOMAIN_MFG2] = { | |
| 57 | + .name = "mfg2", | |
| 58 | + .sta_mask = BIT(4), | |
| 59 | + .ctl_offs = 0x310, | |
| 60 | + .pwr_sta_offs = 0x16C, | |
| 61 | + .pwr_sta2nd_offs = 0x170, | |
| 62 | + .sram_pdn_bits = BIT(8), | |
| 63 | + .sram_pdn_ack_bits = BIT(12), | |
| 64 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 65 | + }, | |
| 66 | + [MT8186_POWER_DOMAIN_MFG3] = { | |
| 67 | + .name = "mfg3", | |
| 68 | + .sta_mask = BIT(5), | |
| 69 | + .ctl_offs = 0x314, | |
| 70 | + .pwr_sta_offs = 0x16C, | |
| 71 | + .pwr_sta2nd_offs = 0x170, | |
| 72 | + .sram_pdn_bits = BIT(8), | |
| 73 | + .sram_pdn_ack_bits = BIT(12), | |
| 74 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 75 | + }, | |
| 76 | + [MT8186_POWER_DOMAIN_SSUSB] = { | |
| 77 | + .name = "ssusb", | |
| 78 | + .sta_mask = BIT(20), | |
| 79 | + .ctl_offs = 0x9F0, | |
| 80 | + .pwr_sta_offs = 0x16C, | |
| 81 | + .pwr_sta2nd_offs = 0x170, | |
| 82 | + .sram_pdn_bits = BIT(8), | |
| 83 | + .sram_pdn_ack_bits = BIT(12), | |
| 84 | + .caps = MTK_SCPD_ACTIVE_WAKEUP, | |
| 85 | + }, | |
| 86 | + [MT8186_POWER_DOMAIN_SSUSB_P1] = { | |
| 87 | + .name = "ssusb_p1", | |
| 88 | + .sta_mask = BIT(19), | |
| 89 | + .ctl_offs = 0x9F4, | |
| 90 | + .pwr_sta_offs = 0x16C, | |
| 91 | + .pwr_sta2nd_offs = 0x170, | |
| 92 | + .sram_pdn_bits = BIT(8), | |
| 93 | + .sram_pdn_ack_bits = BIT(12), | |
| 94 | + .caps = MTK_SCPD_ACTIVE_WAKEUP, | |
| 95 | + }, | |
| 96 | + [MT8186_POWER_DOMAIN_DIS] = { | |
| 97 | + .name = "dis", | |
| 98 | + .sta_mask = BIT(21), | |
| 99 | + .ctl_offs = 0x354, | |
| 100 | + .pwr_sta_offs = 0x16C, | |
| 101 | + .pwr_sta2nd_offs = 0x170, | |
| 102 | + .sram_pdn_bits = BIT(8), | |
| 103 | + .sram_pdn_ack_bits = BIT(12), | |
| 104 | + .bp_infracfg = { | |
| 105 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_DIS_STEP1, | |
| 106 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 107 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 108 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 109 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_DIS_STEP2, | |
| 110 | + MT8186_TOP_AXI_PROT_EN_SET, | |
| 111 | + MT8186_TOP_AXI_PROT_EN_CLR, | |
| 112 | + MT8186_TOP_AXI_PROT_EN_STA), | |
| 113 | + }, | |
| 114 | + }, | |
| 115 | + [MT8186_POWER_DOMAIN_IMG] = { | |
| 116 | + .name = "img", | |
| 117 | + .sta_mask = BIT(13), | |
| 118 | + .ctl_offs = 0x334, | |
| 119 | + .pwr_sta_offs = 0x16C, | |
| 120 | + .pwr_sta2nd_offs = 0x170, | |
| 121 | + .sram_pdn_bits = BIT(8), | |
| 122 | + .sram_pdn_ack_bits = BIT(12), | |
| 123 | + .bp_infracfg = { | |
| 124 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IMG_STEP1, | |
| 125 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 126 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 127 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 128 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IMG_STEP2, | |
| 129 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 130 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 131 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 132 | + }, | |
| 133 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 134 | + }, | |
| 135 | + [MT8186_POWER_DOMAIN_IMG2] = { | |
| 136 | + .name = "img2", | |
| 137 | + .sta_mask = BIT(14), | |
| 138 | + .ctl_offs = 0x338, | |
| 139 | + .pwr_sta_offs = 0x16C, | |
| 140 | + .pwr_sta2nd_offs = 0x170, | |
| 141 | + .sram_pdn_bits = BIT(8), | |
| 142 | + .sram_pdn_ack_bits = BIT(12), | |
| 143 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 144 | + }, | |
| 145 | + [MT8186_POWER_DOMAIN_IPE] = { | |
| 146 | + .name = "ipe", | |
| 147 | + .sta_mask = BIT(15), | |
| 148 | + .ctl_offs = 0x33C, | |
| 149 | + .pwr_sta_offs = 0x16C, | |
| 150 | + .pwr_sta2nd_offs = 0x170, | |
| 151 | + .sram_pdn_bits = BIT(8), | |
| 152 | + .sram_pdn_ack_bits = BIT(12), | |
| 153 | + .bp_infracfg = { | |
| 154 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IPE_STEP1, | |
| 155 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 156 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 157 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 158 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IPE_STEP2, | |
| 159 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 160 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 161 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 162 | + }, | |
| 163 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 164 | + }, | |
| 165 | + [MT8186_POWER_DOMAIN_CAM] = { | |
| 166 | + .name = "cam", | |
| 167 | + .sta_mask = BIT(23), | |
| 168 | + .ctl_offs = 0x35C, | |
| 169 | + .pwr_sta_offs = 0x16C, | |
| 170 | + .pwr_sta2nd_offs = 0x170, | |
| 171 | + .sram_pdn_bits = BIT(8), | |
| 172 | + .sram_pdn_ack_bits = BIT(12), | |
| 173 | + .bp_infracfg = { | |
| 174 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CAM_STEP1, | |
| 175 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 176 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 177 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 178 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CAM_STEP2, | |
| 179 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 180 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 181 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 182 | + }, | |
| 183 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 184 | + }, | |
| 185 | + [MT8186_POWER_DOMAIN_CAM_RAWA] = { | |
| 186 | + .name = "cam_rawa", | |
| 187 | + .sta_mask = BIT(24), | |
| 188 | + .ctl_offs = 0x360, | |
| 189 | + .pwr_sta_offs = 0x16C, | |
| 190 | + .pwr_sta2nd_offs = 0x170, | |
| 191 | + .sram_pdn_bits = BIT(8), | |
| 192 | + .sram_pdn_ack_bits = BIT(12), | |
| 193 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 194 | + }, | |
| 195 | + [MT8186_POWER_DOMAIN_CAM_RAWB] = { | |
| 196 | + .name = "cam_rawb", | |
| 197 | + .sta_mask = BIT(25), | |
| 198 | + .ctl_offs = 0x364, | |
| 199 | + .pwr_sta_offs = 0x16C, | |
| 200 | + .pwr_sta2nd_offs = 0x170, | |
| 201 | + .sram_pdn_bits = BIT(8), | |
| 202 | + .sram_pdn_ack_bits = BIT(12), | |
| 203 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 204 | + }, | |
| 205 | + [MT8186_POWER_DOMAIN_VENC] = { | |
| 206 | + .name = "venc", | |
| 207 | + .sta_mask = BIT(18), | |
| 208 | + .ctl_offs = 0x348, | |
| 209 | + .pwr_sta_offs = 0x16C, | |
| 210 | + .pwr_sta2nd_offs = 0x170, | |
| 211 | + .sram_pdn_bits = BIT(8), | |
| 212 | + .sram_pdn_ack_bits = BIT(12), | |
| 213 | + .bp_infracfg = { | |
| 214 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VENC_STEP1, | |
| 215 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 216 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 217 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 218 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VENC_STEP2, | |
| 219 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 220 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 221 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 222 | + }, | |
| 223 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 224 | + }, | |
| 225 | + [MT8186_POWER_DOMAIN_VDEC] = { | |
| 226 | + .name = "vdec", | |
| 227 | + .sta_mask = BIT(16), | |
| 228 | + .ctl_offs = 0x340, | |
| 229 | + .pwr_sta_offs = 0x16C, | |
| 230 | + .pwr_sta2nd_offs = 0x170, | |
| 231 | + .sram_pdn_bits = BIT(8), | |
| 232 | + .sram_pdn_ack_bits = BIT(12), | |
| 233 | + .bp_infracfg = { | |
| 234 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP1, | |
| 235 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 236 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 237 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 238 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP2, | |
| 239 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 240 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 241 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 242 | + }, | |
| 243 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 244 | + }, | |
| 245 | + [MT8186_POWER_DOMAIN_WPE] = { | |
| 246 | + .name = "wpe", | |
| 247 | + .sta_mask = BIT(0), | |
| 248 | + .ctl_offs = 0x3F8, | |
| 249 | + .pwr_sta_offs = 0x16C, | |
| 250 | + .pwr_sta2nd_offs = 0x170, | |
| 251 | + .sram_pdn_bits = BIT(8), | |
| 252 | + .sram_pdn_ack_bits = BIT(12), | |
| 253 | + .bp_infracfg = { | |
| 254 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_2_WPE_STEP1, | |
| 255 | + MT8186_TOP_AXI_PROT_EN_2_SET, | |
| 256 | + MT8186_TOP_AXI_PROT_EN_2_CLR, | |
| 257 | + MT8186_TOP_AXI_PROT_EN_2_STA), | |
| 258 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_2_WPE_STEP2, | |
| 259 | + MT8186_TOP_AXI_PROT_EN_2_SET, | |
| 260 | + MT8186_TOP_AXI_PROT_EN_2_CLR, | |
| 261 | + MT8186_TOP_AXI_PROT_EN_2_STA), | |
| 262 | + }, | |
| 263 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 264 | + }, | |
| 265 | + [MT8186_POWER_DOMAIN_CONN_ON] = { | |
| 266 | + .name = "conn_on", | |
| 267 | + .sta_mask = BIT(1), | |
| 268 | + .ctl_offs = 0x304, | |
| 269 | + .pwr_sta_offs = 0x16C, | |
| 270 | + .pwr_sta2nd_offs = 0x170, | |
| 271 | + .bp_infracfg = { | |
| 272 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CONN_ON_STEP1, | |
| 273 | + MT8186_TOP_AXI_PROT_EN_1_SET, | |
| 274 | + MT8186_TOP_AXI_PROT_EN_1_CLR, | |
| 275 | + MT8186_TOP_AXI_PROT_EN_1_STA), | |
| 276 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP2, | |
| 277 | + MT8186_TOP_AXI_PROT_EN_SET, | |
| 278 | + MT8186_TOP_AXI_PROT_EN_CLR, | |
| 279 | + MT8186_TOP_AXI_PROT_EN_STA), | |
| 280 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP3, | |
| 281 | + MT8186_TOP_AXI_PROT_EN_SET, | |
| 282 | + MT8186_TOP_AXI_PROT_EN_CLR, | |
| 283 | + MT8186_TOP_AXI_PROT_EN_STA), | |
| 284 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP4, | |
| 285 | + MT8186_TOP_AXI_PROT_EN_SET, | |
| 286 | + MT8186_TOP_AXI_PROT_EN_CLR, | |
| 287 | + MT8186_TOP_AXI_PROT_EN_STA), | |
| 288 | + }, | |
| 289 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, | |
| 290 | + }, | |
| 291 | + [MT8186_POWER_DOMAIN_CSIRX_TOP] = { | |
| 292 | + .name = "csirx_top", | |
| 293 | + .sta_mask = BIT(6), | |
| 294 | + .ctl_offs = 0x318, | |
| 295 | + .pwr_sta_offs = 0x16C, | |
| 296 | + .pwr_sta2nd_offs = 0x170, | |
| 297 | + .sram_pdn_bits = BIT(8), | |
| 298 | + .sram_pdn_ack_bits = BIT(12), | |
| 299 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 300 | + }, | |
| 301 | + [MT8186_POWER_DOMAIN_ADSP_AO] = { | |
| 302 | + .name = "adsp_ao", | |
| 303 | + .sta_mask = BIT(17), | |
| 304 | + .ctl_offs = 0x9FC, | |
| 305 | + .pwr_sta_offs = 0x16C, | |
| 306 | + .pwr_sta2nd_offs = 0x170, | |
| 307 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 308 | + }, | |
| 309 | + [MT8186_POWER_DOMAIN_ADSP_INFRA] = { | |
| 310 | + .name = "adsp_infra", | |
| 311 | + .sta_mask = BIT(10), | |
| 312 | + .ctl_offs = 0x9F8, | |
| 313 | + .pwr_sta_offs = 0x16C, | |
| 314 | + .pwr_sta2nd_offs = 0x170, | |
| 315 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 316 | + }, | |
| 317 | + [MT8186_POWER_DOMAIN_ADSP_TOP] = { | |
| 318 | + .name = "adsp_top", | |
| 319 | + .sta_mask = BIT(31), | |
| 320 | + .ctl_offs = 0x3E4, | |
| 321 | + .pwr_sta_offs = 0x16C, | |
| 322 | + .pwr_sta2nd_offs = 0x170, | |
| 323 | + .sram_pdn_bits = BIT(8), | |
| 324 | + .sram_pdn_ack_bits = BIT(12), | |
| 325 | + .bp_infracfg = { | |
| 326 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP1, | |
| 327 | + MT8186_TOP_AXI_PROT_EN_3_SET, | |
| 328 | + MT8186_TOP_AXI_PROT_EN_3_CLR, | |
| 329 | + MT8186_TOP_AXI_PROT_EN_3_STA), | |
| 330 | + BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP2, | |
| 331 | + MT8186_TOP_AXI_PROT_EN_3_SET, | |
| 332 | + MT8186_TOP_AXI_PROT_EN_3_CLR, | |
| 333 | + MT8186_TOP_AXI_PROT_EN_3_STA), | |
| 334 | + }, | |
| 335 | + .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, | |
| 336 | + }, | |
| 337 | +}; | |
| 338 | + | |
| 339 | +static const struct scpsys_soc_data mt8186_scpsys_data = { | |
| 340 | + .domains_data = scpsys_domain_data_mt8186, | |
| 341 | + .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8186), | |
| 342 | +}; | |
| 343 | + | |
| 344 | +#endif /* __SOC_MEDIATEK_MT8186_PM_DOMAINS_H */ | |
| @@ -15,6 +15,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 14 unmodified lines | ||
| 15 | 15 | .name = "audio", |
| 16 | 16 | .sta_mask = BIT(21), |
| 17 | 17 | .ctl_offs = 0x0354, |
| 18 | + .pwr_sta_offs = 0x016c, | |
| 19 | + .pwr_sta2nd_offs = 0x0170, | |
| 18 | 20 | .sram_pdn_bits = GENMASK(8, 8), |
| 19 | 21 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 20 | 22 | .bp_infracfg = { |
| @@ -28,6 +30,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 7 unmodified lines | ||
| 28 | 30 | .name = "conn", |
| 29 | 31 | .sta_mask = PWR_STATUS_CONN, |
| 30 | 32 | .ctl_offs = 0x0304, |
| 33 | + .pwr_sta_offs = 0x016c, | |
| 34 | + .pwr_sta2nd_offs = 0x0170, | |
| 31 | 35 | .sram_pdn_bits = 0, |
| 32 | 36 | .sram_pdn_ack_bits = 0, |
| 33 | 37 | .bp_infracfg = { |
| @@ -50,6 +54,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 16 unmodified lines | ||
| 50 | 54 | .name = "mfg0", |
| 51 | 55 | .sta_mask = BIT(2), |
| 52 | 56 | .ctl_offs = 0x0308, |
| 57 | + .pwr_sta_offs = 0x016c, | |
| 58 | + .pwr_sta2nd_offs = 0x0170, | |
| 53 | 59 | .sram_pdn_bits = GENMASK(8, 8), |
| 54 | 60 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 55 | 61 | }, |
| @@ -57,6 +63,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 1 unmodified line | ||
| 57 | 63 | .name = "mfg1", |
| 58 | 64 | .sta_mask = BIT(3), |
| 59 | 65 | .ctl_offs = 0x030c, |
| 66 | + .pwr_sta_offs = 0x016c, | |
| 67 | + .pwr_sta2nd_offs = 0x0170, | |
| 60 | 68 | .sram_pdn_bits = GENMASK(8, 8), |
| 61 | 69 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 62 | 70 | .bp_infracfg = { |
| @@ -82,6 +90,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 19 unmodified lines | ||
| 82 | 90 | .name = "mfg2", |
| 83 | 91 | .sta_mask = BIT(4), |
| 84 | 92 | .ctl_offs = 0x0310, |
| 93 | + .pwr_sta_offs = 0x016c, | |
| 94 | + .pwr_sta2nd_offs = 0x0170, | |
| 85 | 95 | .sram_pdn_bits = GENMASK(8, 8), |
| 86 | 96 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 87 | 97 | }, |
| @@ -89,6 +99,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 1 unmodified line | ||
| 89 | 99 | .name = "mfg3", |
| 90 | 100 | .sta_mask = BIT(5), |
| 91 | 101 | .ctl_offs = 0x0314, |
| 102 | + .pwr_sta_offs = 0x016c, | |
| 103 | + .pwr_sta2nd_offs = 0x0170, | |
| 92 | 104 | .sram_pdn_bits = GENMASK(8, 8), |
| 93 | 105 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 94 | 106 | }, |
| @@ -96,6 +108,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 1 unmodified line | ||
| 96 | 108 | .name = "mfg4", |
| 97 | 109 | .sta_mask = BIT(6), |
| 98 | 110 | .ctl_offs = 0x0318, |
| 111 | + .pwr_sta_offs = 0x016c, | |
| 112 | + .pwr_sta2nd_offs = 0x0170, | |
| 99 | 113 | .sram_pdn_bits = GENMASK(8, 8), |
| 100 | 114 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 101 | 115 | }, |
| @@ -103,6 +117,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 1 unmodified line | ||
| 103 | 117 | .name = "mfg5", |
| 104 | 118 | .sta_mask = BIT(7), |
| 105 | 119 | .ctl_offs = 0x031c, |
| 120 | + .pwr_sta_offs = 0x016c, | |
| 121 | + .pwr_sta2nd_offs = 0x0170, | |
| 106 | 122 | .sram_pdn_bits = GENMASK(8, 8), |
| 107 | 123 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 108 | 124 | }, |
| @@ -110,6 +126,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 1 unmodified line | ||
| 110 | 126 | .name = "mfg6", |
| 111 | 127 | .sta_mask = BIT(8), |
| 112 | 128 | .ctl_offs = 0x0320, |
| 129 | + .pwr_sta_offs = 0x016c, | |
| 130 | + .pwr_sta2nd_offs = 0x0170, | |
| 113 | 131 | .sram_pdn_bits = GENMASK(8, 8), |
| 114 | 132 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 115 | 133 | }, |
| @@ -117,6 +135,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 1 unmodified line | ||
| 117 | 135 | .name = "disp", |
| 118 | 136 | .sta_mask = BIT(20), |
| 119 | 137 | .ctl_offs = 0x0350, |
| 138 | + .pwr_sta_offs = 0x016c, | |
| 139 | + .pwr_sta2nd_offs = 0x0170, | |
| 120 | 140 | .sram_pdn_bits = GENMASK(8, 8), |
| 121 | 141 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 122 | 142 | .bp_infracfg = { |
| @@ -146,6 +166,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 23 unmodified lines | ||
| 146 | 166 | .name = "ipe", |
| 147 | 167 | .sta_mask = BIT(14), |
| 148 | 168 | .ctl_offs = 0x0338, |
| 169 | + .pwr_sta_offs = 0x016c, | |
| 170 | + .pwr_sta2nd_offs = 0x0170, | |
| 149 | 171 | .sram_pdn_bits = GENMASK(8, 8), |
| 150 | 172 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 151 | 173 | .bp_infracfg = { |
| @@ -163,6 +185,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 11 unmodified lines | ||
| 163 | 185 | .name = "isp", |
| 164 | 186 | .sta_mask = BIT(12), |
| 165 | 187 | .ctl_offs = 0x0330, |
| 188 | + .pwr_sta_offs = 0x016c, | |
| 189 | + .pwr_sta2nd_offs = 0x0170, | |
| 166 | 190 | .sram_pdn_bits = GENMASK(8, 8), |
| 167 | 191 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 168 | 192 | .bp_infracfg = { |
| @@ -180,6 +204,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 11 unmodified lines | ||
| 180 | 204 | .name = "isp2", |
| 181 | 205 | .sta_mask = BIT(13), |
| 182 | 206 | .ctl_offs = 0x0334, |
| 207 | + .pwr_sta_offs = 0x016c, | |
| 208 | + .pwr_sta2nd_offs = 0x0170, | |
| 183 | 209 | .sram_pdn_bits = GENMASK(8, 8), |
| 184 | 210 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 185 | 211 | .bp_infracfg = { |
| @@ -197,6 +223,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 11 unmodified lines | ||
| 197 | 223 | .name = "mdp", |
| 198 | 224 | .sta_mask = BIT(19), |
| 199 | 225 | .ctl_offs = 0x034c, |
| 226 | + .pwr_sta_offs = 0x016c, | |
| 227 | + .pwr_sta2nd_offs = 0x0170, | |
| 200 | 228 | .sram_pdn_bits = GENMASK(8, 8), |
| 201 | 229 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 202 | 230 | .bp_infracfg = { |
| @@ -214,6 +242,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 11 unmodified lines | ||
| 214 | 242 | .name = "venc", |
| 215 | 243 | .sta_mask = BIT(17), |
| 216 | 244 | .ctl_offs = 0x0344, |
| 245 | + .pwr_sta_offs = 0x016c, | |
| 246 | + .pwr_sta2nd_offs = 0x0170, | |
| 217 | 247 | .sram_pdn_bits = GENMASK(8, 8), |
| 218 | 248 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 219 | 249 | .bp_infracfg = { |
| @@ -231,6 +261,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 11 unmodified lines | ||
| 231 | 261 | .name = "vdec", |
| 232 | 262 | .sta_mask = BIT(15), |
| 233 | 263 | .ctl_offs = 0x033c, |
| 264 | + .pwr_sta_offs = 0x016c, | |
| 265 | + .pwr_sta2nd_offs = 0x0170, | |
| 234 | 266 | .sram_pdn_bits = GENMASK(8, 8), |
| 235 | 267 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 236 | 268 | .bp_infracfg = { |
| @@ -248,6 +280,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 11 unmodified lines | ||
| 248 | 280 | .name = "vdec2", |
| 249 | 281 | .sta_mask = BIT(16), |
| 250 | 282 | .ctl_offs = 0x0340, |
| 283 | + .pwr_sta_offs = 0x016c, | |
| 284 | + .pwr_sta2nd_offs = 0x0170, | |
| 251 | 285 | .sram_pdn_bits = GENMASK(8, 8), |
| 252 | 286 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 253 | 287 | }, |
| @@ -255,6 +289,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 1 unmodified line | ||
| 255 | 289 | .name = "cam", |
| 256 | 290 | .sta_mask = BIT(23), |
| 257 | 291 | .ctl_offs = 0x035c, |
| 292 | + .pwr_sta_offs = 0x016c, | |
| 293 | + .pwr_sta2nd_offs = 0x0170, | |
| 258 | 294 | .sram_pdn_bits = GENMASK(8, 8), |
| 259 | 295 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 260 | 296 | .bp_infracfg = { |
| @@ -284,6 +320,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 23 unmodified lines | ||
| 284 | 320 | .name = "cam_rawa", |
| 285 | 321 | .sta_mask = BIT(24), |
| 286 | 322 | .ctl_offs = 0x0360, |
| 323 | + .pwr_sta_offs = 0x016c, | |
| 324 | + .pwr_sta2nd_offs = 0x0170, | |
| 287 | 325 | .sram_pdn_bits = GENMASK(8, 8), |
| 288 | 326 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 289 | 327 | }, |
| @@ -291,6 +329,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 1 unmodified line | ||
| 291 | 329 | .name = "cam_rawb", |
| 292 | 330 | .sta_mask = BIT(25), |
| 293 | 331 | .ctl_offs = 0x0364, |
| 332 | + .pwr_sta_offs = 0x016c, | |
| 333 | + .pwr_sta2nd_offs = 0x0170, | |
| 294 | 334 | .sram_pdn_bits = GENMASK(8, 8), |
| 295 | 335 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 296 | 336 | }, |
| @@ -298,6 +338,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 1 unmodified line | ||
| 298 | 338 | .name = "cam_rawc", |
| 299 | 339 | .sta_mask = BIT(26), |
| 300 | 340 | .ctl_offs = 0x0368, |
| 341 | + .pwr_sta_offs = 0x016c, | |
| 342 | + .pwr_sta2nd_offs = 0x0170, | |
| 301 | 343 | .sram_pdn_bits = GENMASK(8, 8), |
| 302 | 344 | .sram_pdn_ack_bits = GENMASK(12, 12), |
| 303 | 345 | }, |
| @@ -306,8 +348,6 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { · 2 unmodified lines | ||
| 306 | 348 | static const struct scpsys_soc_data mt8192_scpsys_data = { |
| 307 | 349 | .domains_data = scpsys_domain_data_mt8192, |
| 308 | 350 | .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8192), |
| 309 | − .pwr_sta_offs = 0x016c, | |
| 310 | − .pwr_sta2nd_offs = 0x0170, | |
| 311 | 351 | }; |
| 312 | 352 | |
| 313 | 353 | #endif /* __SOC_MEDIATEK_MT8192_PM_DOMAINS_H */ |
| @@ -0,0 +1,613 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ | |
| 2 | +/* | |
| 3 | + * Copyright (c) 2021 MediaTek Inc. | |
| 4 | + * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> | |
| 5 | + */ | |
| 6 | + | |
| 7 | +#ifndef __SOC_MEDIATEK_MT8195_PM_DOMAINS_H | |
| 8 | +#define __SOC_MEDIATEK_MT8195_PM_DOMAINS_H | |
| 9 | + | |
| 10 | +#include "mtk-pm-domains.h" | |
| 11 | +#include <dt-bindings/power/mt8195-power.h> | |
| 12 | + | |
| 13 | +/* | |
| 14 | + * MT8195 power domain support | |
| 15 | + */ | |
| 16 | + | |
| 17 | +static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = { | |
| 18 | + [MT8195_POWER_DOMAIN_PCIE_MAC_P0] = { | |
| 19 | + .name = "pcie_mac_p0", | |
| 20 | + .sta_mask = BIT(11), | |
| 21 | + .ctl_offs = 0x328, | |
| 22 | + .pwr_sta_offs = 0x174, | |
| 23 | + .pwr_sta2nd_offs = 0x178, | |
| 24 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 25 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 26 | + .bp_infracfg = { | |
| 27 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P0, | |
| 28 | + MT8195_TOP_AXI_PROT_EN_VDNR_SET, | |
| 29 | + MT8195_TOP_AXI_PROT_EN_VDNR_CLR, | |
| 30 | + MT8195_TOP_AXI_PROT_EN_VDNR_STA1), | |
| 31 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P0, | |
| 32 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_SET, | |
| 33 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR, | |
| 34 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1), | |
| 35 | + }, | |
| 36 | + }, | |
| 37 | + [MT8195_POWER_DOMAIN_PCIE_MAC_P1] = { | |
| 38 | + .name = "pcie_mac_p1", | |
| 39 | + .sta_mask = BIT(12), | |
| 40 | + .ctl_offs = 0x32C, | |
| 41 | + .pwr_sta_offs = 0x174, | |
| 42 | + .pwr_sta2nd_offs = 0x178, | |
| 43 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 44 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 45 | + .bp_infracfg = { | |
| 46 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P1, | |
| 47 | + MT8195_TOP_AXI_PROT_EN_VDNR_SET, | |
| 48 | + MT8195_TOP_AXI_PROT_EN_VDNR_CLR, | |
| 49 | + MT8195_TOP_AXI_PROT_EN_VDNR_STA1), | |
| 50 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P1, | |
| 51 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_SET, | |
| 52 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR, | |
| 53 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1), | |
| 54 | + }, | |
| 55 | + }, | |
| 56 | + [MT8195_POWER_DOMAIN_PCIE_PHY] = { | |
| 57 | + .name = "pcie_phy", | |
| 58 | + .sta_mask = BIT(13), | |
| 59 | + .ctl_offs = 0x330, | |
| 60 | + .pwr_sta_offs = 0x174, | |
| 61 | + .pwr_sta2nd_offs = 0x178, | |
| 62 | + .caps = MTK_SCPD_ACTIVE_WAKEUP, | |
| 63 | + }, | |
| 64 | + [MT8195_POWER_DOMAIN_SSUSB_PCIE_PHY] = { | |
| 65 | + .name = "ssusb_pcie_phy", | |
| 66 | + .sta_mask = BIT(14), | |
| 67 | + .ctl_offs = 0x334, | |
| 68 | + .pwr_sta_offs = 0x174, | |
| 69 | + .pwr_sta2nd_offs = 0x178, | |
| 70 | + .caps = MTK_SCPD_ACTIVE_WAKEUP, | |
| 71 | + }, | |
| 72 | + [MT8195_POWER_DOMAIN_CSI_RX_TOP] = { | |
| 73 | + .name = "csi_rx_top", | |
| 74 | + .sta_mask = BIT(18), | |
| 75 | + .ctl_offs = 0x3C4, | |
| 76 | + .pwr_sta_offs = 0x174, | |
| 77 | + .pwr_sta2nd_offs = 0x178, | |
| 78 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 79 | + }, | |
| 80 | + [MT8195_POWER_DOMAIN_ETHER] = { | |
| 81 | + .name = "ether", | |
| 82 | + .sta_mask = BIT(3), | |
| 83 | + .ctl_offs = 0x344, | |
| 84 | + .pwr_sta_offs = 0x16c, | |
| 85 | + .pwr_sta2nd_offs = 0x170, | |
| 86 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 87 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 88 | + .caps = MTK_SCPD_ACTIVE_WAKEUP, | |
| 89 | + }, | |
| 90 | + [MT8195_POWER_DOMAIN_ADSP] = { | |
| 91 | + .name = "adsp", | |
| 92 | + .sta_mask = BIT(10), | |
| 93 | + .ctl_offs = 0x360, | |
| 94 | + .pwr_sta_offs = 0x16c, | |
| 95 | + .pwr_sta2nd_offs = 0x170, | |
| 96 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 97 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 98 | + .bp_infracfg = { | |
| 99 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_ADSP, | |
| 100 | + MT8195_TOP_AXI_PROT_EN_2_SET, | |
| 101 | + MT8195_TOP_AXI_PROT_EN_2_CLR, | |
| 102 | + MT8195_TOP_AXI_PROT_EN_2_STA1), | |
| 103 | + }, | |
| 104 | + .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP, | |
| 105 | + }, | |
| 106 | + [MT8195_POWER_DOMAIN_AUDIO] = { | |
| 107 | + .name = "audio", | |
| 108 | + .sta_mask = BIT(8), | |
| 109 | + .ctl_offs = 0x358, | |
| 110 | + .pwr_sta_offs = 0x16c, | |
| 111 | + .pwr_sta2nd_offs = 0x170, | |
| 112 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 113 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 114 | + .bp_infracfg = { | |
| 115 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_AUDIO, | |
| 116 | + MT8195_TOP_AXI_PROT_EN_2_SET, | |
| 117 | + MT8195_TOP_AXI_PROT_EN_2_CLR, | |
| 118 | + MT8195_TOP_AXI_PROT_EN_2_STA1), | |
| 119 | + }, | |
| 120 | + }, | |
| 121 | + [MT8195_POWER_DOMAIN_MFG0] = { | |
| 122 | + .name = "mfg0", | |
| 123 | + .sta_mask = BIT(1), | |
| 124 | + .ctl_offs = 0x300, | |
| 125 | + .pwr_sta_offs = 0x174, | |
| 126 | + .pwr_sta2nd_offs = 0x178, | |
| 127 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 128 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 129 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, | |
| 130 | + }, | |
| 131 | + [MT8195_POWER_DOMAIN_MFG1] = { | |
| 132 | + .name = "mfg1", | |
| 133 | + .sta_mask = BIT(2), | |
| 134 | + .ctl_offs = 0x304, | |
| 135 | + .pwr_sta_offs = 0x174, | |
| 136 | + .pwr_sta2nd_offs = 0x178, | |
| 137 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 138 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 139 | + .bp_infracfg = { | |
| 140 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MFG1, | |
| 141 | + MT8195_TOP_AXI_PROT_EN_SET, | |
| 142 | + MT8195_TOP_AXI_PROT_EN_CLR, | |
| 143 | + MT8195_TOP_AXI_PROT_EN_STA1), | |
| 144 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_MFG1, | |
| 145 | + MT8195_TOP_AXI_PROT_EN_2_SET, | |
| 146 | + MT8195_TOP_AXI_PROT_EN_2_CLR, | |
| 147 | + MT8195_TOP_AXI_PROT_EN_2_STA1), | |
| 148 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_1_MFG1, | |
| 149 | + MT8195_TOP_AXI_PROT_EN_1_SET, | |
| 150 | + MT8195_TOP_AXI_PROT_EN_1_CLR, | |
| 151 | + MT8195_TOP_AXI_PROT_EN_1_STA1), | |
| 152 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_MFG1_2ND, | |
| 153 | + MT8195_TOP_AXI_PROT_EN_2_SET, | |
| 154 | + MT8195_TOP_AXI_PROT_EN_2_CLR, | |
| 155 | + MT8195_TOP_AXI_PROT_EN_2_STA1), | |
| 156 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MFG1_2ND, | |
| 157 | + MT8195_TOP_AXI_PROT_EN_SET, | |
| 158 | + MT8195_TOP_AXI_PROT_EN_CLR, | |
| 159 | + MT8195_TOP_AXI_PROT_EN_STA1), | |
| 160 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1, | |
| 161 | + MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, | |
| 162 | + MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, | |
| 163 | + MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1), | |
| 164 | + }, | |
| 165 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 166 | + }, | |
| 167 | + [MT8195_POWER_DOMAIN_MFG2] = { | |
| 168 | + .name = "mfg2", | |
| 169 | + .sta_mask = BIT(3), | |
| 170 | + .ctl_offs = 0x308, | |
| 171 | + .pwr_sta_offs = 0x174, | |
| 172 | + .pwr_sta2nd_offs = 0x178, | |
| 173 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 174 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 175 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 176 | + }, | |
| 177 | + [MT8195_POWER_DOMAIN_MFG3] = { | |
| 178 | + .name = "mfg3", | |
| 179 | + .sta_mask = BIT(4), | |
| 180 | + .ctl_offs = 0x30C, | |
| 181 | + .pwr_sta_offs = 0x174, | |
| 182 | + .pwr_sta2nd_offs = 0x178, | |
| 183 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 184 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 185 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 186 | + }, | |
| 187 | + [MT8195_POWER_DOMAIN_MFG4] = { | |
| 188 | + .name = "mfg4", | |
| 189 | + .sta_mask = BIT(5), | |
| 190 | + .ctl_offs = 0x310, | |
| 191 | + .pwr_sta_offs = 0x174, | |
| 192 | + .pwr_sta2nd_offs = 0x178, | |
| 193 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 194 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 195 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 196 | + }, | |
| 197 | + [MT8195_POWER_DOMAIN_MFG5] = { | |
| 198 | + .name = "mfg5", | |
| 199 | + .sta_mask = BIT(6), | |
| 200 | + .ctl_offs = 0x314, | |
| 201 | + .pwr_sta_offs = 0x174, | |
| 202 | + .pwr_sta2nd_offs = 0x178, | |
| 203 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 204 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 205 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 206 | + }, | |
| 207 | + [MT8195_POWER_DOMAIN_MFG6] = { | |
| 208 | + .name = "mfg6", | |
| 209 | + .sta_mask = BIT(7), | |
| 210 | + .ctl_offs = 0x318, | |
| 211 | + .pwr_sta_offs = 0x174, | |
| 212 | + .pwr_sta2nd_offs = 0x178, | |
| 213 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 214 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 215 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 216 | + }, | |
| 217 | + [MT8195_POWER_DOMAIN_VPPSYS0] = { | |
| 218 | + .name = "vppsys0", | |
| 219 | + .sta_mask = BIT(11), | |
| 220 | + .ctl_offs = 0x364, | |
| 221 | + .pwr_sta_offs = 0x16c, | |
| 222 | + .pwr_sta2nd_offs = 0x170, | |
| 223 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 224 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 225 | + .bp_infracfg = { | |
| 226 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VPPSYS0, | |
| 227 | + MT8195_TOP_AXI_PROT_EN_SET, | |
| 228 | + MT8195_TOP_AXI_PROT_EN_CLR, | |
| 229 | + MT8195_TOP_AXI_PROT_EN_STA1), | |
| 230 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0, | |
| 231 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 232 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 233 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 234 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VPPSYS0_2ND, | |
| 235 | + MT8195_TOP_AXI_PROT_EN_SET, | |
| 236 | + MT8195_TOP_AXI_PROT_EN_CLR, | |
| 237 | + MT8195_TOP_AXI_PROT_EN_STA1), | |
| 238 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0_2ND, | |
| 239 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 240 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 241 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 242 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0, | |
| 243 | + MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, | |
| 244 | + MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, | |
| 245 | + MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1), | |
| 246 | + }, | |
| 247 | + }, | |
| 248 | + [MT8195_POWER_DOMAIN_VDOSYS0] = { | |
| 249 | + .name = "vdosys0", | |
| 250 | + .sta_mask = BIT(13), | |
| 251 | + .ctl_offs = 0x36C, | |
| 252 | + .pwr_sta_offs = 0x16c, | |
| 253 | + .pwr_sta2nd_offs = 0x170, | |
| 254 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 255 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 256 | + .bp_infracfg = { | |
| 257 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS0, | |
| 258 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 259 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 260 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 261 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDOSYS0, | |
| 262 | + MT8195_TOP_AXI_PROT_EN_SET, | |
| 263 | + MT8195_TOP_AXI_PROT_EN_CLR, | |
| 264 | + MT8195_TOP_AXI_PROT_EN_STA1), | |
| 265 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0, | |
| 266 | + MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, | |
| 267 | + MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, | |
| 268 | + MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1), | |
| 269 | + }, | |
| 270 | + }, | |
| 271 | + [MT8195_POWER_DOMAIN_VPPSYS1] = { | |
| 272 | + .name = "vppsys1", | |
| 273 | + .sta_mask = BIT(12), | |
| 274 | + .ctl_offs = 0x368, | |
| 275 | + .pwr_sta_offs = 0x16c, | |
| 276 | + .pwr_sta2nd_offs = 0x170, | |
| 277 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 278 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 279 | + .bp_infracfg = { | |
| 280 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1, | |
| 281 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 282 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 283 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 284 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1_2ND, | |
| 285 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 286 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 287 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 288 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS1, | |
| 289 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 290 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 291 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 292 | + }, | |
| 293 | + }, | |
| 294 | + [MT8195_POWER_DOMAIN_VDOSYS1] = { | |
| 295 | + .name = "vdosys1", | |
| 296 | + .sta_mask = BIT(14), | |
| 297 | + .ctl_offs = 0x370, | |
| 298 | + .pwr_sta_offs = 0x16c, | |
| 299 | + .pwr_sta2nd_offs = 0x170, | |
| 300 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 301 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 302 | + .bp_infracfg = { | |
| 303 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1, | |
| 304 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 305 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 306 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 307 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1_2ND, | |
| 308 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 309 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 310 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 311 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDOSYS1, | |
| 312 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 313 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 314 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 315 | + }, | |
| 316 | + }, | |
| 317 | + [MT8195_POWER_DOMAIN_DP_TX] = { | |
| 318 | + .name = "dp_tx", | |
| 319 | + .sta_mask = BIT(16), | |
| 320 | + .ctl_offs = 0x378, | |
| 321 | + .pwr_sta_offs = 0x16c, | |
| 322 | + .pwr_sta2nd_offs = 0x170, | |
| 323 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 324 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 325 | + .bp_infracfg = { | |
| 326 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_DP_TX, | |
| 327 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_SET, | |
| 328 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR, | |
| 329 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1), | |
| 330 | + }, | |
| 331 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 332 | + }, | |
| 333 | + [MT8195_POWER_DOMAIN_EPD_TX] = { | |
| 334 | + .name = "epd_tx", | |
| 335 | + .sta_mask = BIT(17), | |
| 336 | + .ctl_offs = 0x37C, | |
| 337 | + .pwr_sta_offs = 0x16c, | |
| 338 | + .pwr_sta2nd_offs = 0x170, | |
| 339 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 340 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 341 | + .bp_infracfg = { | |
| 342 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_EPD_TX, | |
| 343 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_SET, | |
| 344 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR, | |
| 345 | + MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1), | |
| 346 | + }, | |
| 347 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 348 | + }, | |
| 349 | + [MT8195_POWER_DOMAIN_HDMI_TX] = { | |
| 350 | + .name = "hdmi_tx", | |
| 351 | + .sta_mask = BIT(18), | |
| 352 | + .ctl_offs = 0x380, | |
| 353 | + .pwr_sta_offs = 0x16c, | |
| 354 | + .pwr_sta2nd_offs = 0x170, | |
| 355 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 356 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 357 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, | |
| 358 | + }, | |
| 359 | + [MT8195_POWER_DOMAIN_WPESYS] = { | |
| 360 | + .name = "wpesys", | |
| 361 | + .sta_mask = BIT(15), | |
| 362 | + .ctl_offs = 0x374, | |
| 363 | + .pwr_sta_offs = 0x16c, | |
| 364 | + .pwr_sta2nd_offs = 0x170, | |
| 365 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 366 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 367 | + .bp_infracfg = { | |
| 368 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS, | |
| 369 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 370 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 371 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 372 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_WPESYS, | |
| 373 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 374 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 375 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 376 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS_2ND, | |
| 377 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 378 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 379 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 380 | + }, | |
| 381 | + }, | |
| 382 | + [MT8195_POWER_DOMAIN_VDEC0] = { | |
| 383 | + .name = "vdec0", | |
| 384 | + .sta_mask = BIT(20), | |
| 385 | + .ctl_offs = 0x388, | |
| 386 | + .pwr_sta_offs = 0x16c, | |
| 387 | + .pwr_sta2nd_offs = 0x170, | |
| 388 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 389 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 390 | + .bp_infracfg = { | |
| 391 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC0, | |
| 392 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 393 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 394 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 395 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0, | |
| 396 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 397 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 398 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 399 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC0_2ND, | |
| 400 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 401 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 402 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 403 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0_2ND, | |
| 404 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 405 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 406 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 407 | + }, | |
| 408 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 409 | + }, | |
| 410 | + [MT8195_POWER_DOMAIN_VDEC1] = { | |
| 411 | + .name = "vdec1", | |
| 412 | + .sta_mask = BIT(21), | |
| 413 | + .ctl_offs = 0x38C, | |
| 414 | + .pwr_sta_offs = 0x16c, | |
| 415 | + .pwr_sta2nd_offs = 0x170, | |
| 416 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 417 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 418 | + .bp_infracfg = { | |
| 419 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC1, | |
| 420 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 421 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 422 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 423 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC1_2ND, | |
| 424 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 425 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 426 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 427 | + }, | |
| 428 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 429 | + }, | |
| 430 | + [MT8195_POWER_DOMAIN_VDEC2] = { | |
| 431 | + .name = "vdec2", | |
| 432 | + .sta_mask = BIT(22), | |
| 433 | + .ctl_offs = 0x390, | |
| 434 | + .pwr_sta_offs = 0x16c, | |
| 435 | + .pwr_sta2nd_offs = 0x170, | |
| 436 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 437 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 438 | + .bp_infracfg = { | |
| 439 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2, | |
| 440 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 441 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 442 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 443 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2_2ND, | |
| 444 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 445 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 446 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 447 | + }, | |
| 448 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 449 | + }, | |
| 450 | + [MT8195_POWER_DOMAIN_VENC] = { | |
| 451 | + .name = "venc", | |
| 452 | + .sta_mask = BIT(23), | |
| 453 | + .ctl_offs = 0x394, | |
| 454 | + .pwr_sta_offs = 0x16c, | |
| 455 | + .pwr_sta2nd_offs = 0x170, | |
| 456 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 457 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 458 | + .bp_infracfg = { | |
| 459 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC, | |
| 460 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 461 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 462 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 463 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC_2ND, | |
| 464 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 465 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 466 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 467 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VENC, | |
| 468 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 469 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 470 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 471 | + }, | |
| 472 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 473 | + }, | |
| 474 | + [MT8195_POWER_DOMAIN_VENC_CORE1] = { | |
| 475 | + .name = "venc_core1", | |
| 476 | + .sta_mask = BIT(24), | |
| 477 | + .ctl_offs = 0x398, | |
| 478 | + .pwr_sta_offs = 0x16c, | |
| 479 | + .pwr_sta2nd_offs = 0x170, | |
| 480 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 481 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 482 | + .bp_infracfg = { | |
| 483 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC_CORE1, | |
| 484 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 485 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 486 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 487 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VENC_CORE1, | |
| 488 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 489 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 490 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 491 | + }, | |
| 492 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 493 | + }, | |
| 494 | + [MT8195_POWER_DOMAIN_IMG] = { | |
| 495 | + .name = "img", | |
| 496 | + .sta_mask = BIT(29), | |
| 497 | + .ctl_offs = 0x3AC, | |
| 498 | + .pwr_sta_offs = 0x16c, | |
| 499 | + .pwr_sta2nd_offs = 0x170, | |
| 500 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 501 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 502 | + .bp_infracfg = { | |
| 503 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IMG, | |
| 504 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 505 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 506 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 507 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IMG_2ND, | |
| 508 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 509 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 510 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 511 | + }, | |
| 512 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 513 | + }, | |
| 514 | + [MT8195_POWER_DOMAIN_DIP] = { | |
| 515 | + .name = "dip", | |
| 516 | + .sta_mask = BIT(30), | |
| 517 | + .ctl_offs = 0x3B0, | |
| 518 | + .pwr_sta_offs = 0x16c, | |
| 519 | + .pwr_sta2nd_offs = 0x170, | |
| 520 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 521 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 522 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 523 | + }, | |
| 524 | + [MT8195_POWER_DOMAIN_IPE] = { | |
| 525 | + .name = "ipe", | |
| 526 | + .sta_mask = BIT(31), | |
| 527 | + .ctl_offs = 0x3B4, | |
| 528 | + .pwr_sta_offs = 0x16c, | |
| 529 | + .pwr_sta2nd_offs = 0x170, | |
| 530 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 531 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 532 | + .bp_infracfg = { | |
| 533 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IPE, | |
| 534 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 535 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 536 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 537 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_IPE, | |
| 538 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 539 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 540 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 541 | + }, | |
| 542 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 543 | + }, | |
| 544 | + [MT8195_POWER_DOMAIN_CAM] = { | |
| 545 | + .name = "cam", | |
| 546 | + .sta_mask = BIT(25), | |
| 547 | + .ctl_offs = 0x39C, | |
| 548 | + .pwr_sta_offs = 0x16c, | |
| 549 | + .pwr_sta2nd_offs = 0x170, | |
| 550 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 551 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 552 | + .bp_infracfg = { | |
| 553 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_CAM, | |
| 554 | + MT8195_TOP_AXI_PROT_EN_2_SET, | |
| 555 | + MT8195_TOP_AXI_PROT_EN_2_CLR, | |
| 556 | + MT8195_TOP_AXI_PROT_EN_2_STA1), | |
| 557 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_CAM, | |
| 558 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 559 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 560 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 561 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_1_CAM, | |
| 562 | + MT8195_TOP_AXI_PROT_EN_1_SET, | |
| 563 | + MT8195_TOP_AXI_PROT_EN_1_CLR, | |
| 564 | + MT8195_TOP_AXI_PROT_EN_1_STA1), | |
| 565 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_CAM_2ND, | |
| 566 | + MT8195_TOP_AXI_PROT_EN_MM_SET, | |
| 567 | + MT8195_TOP_AXI_PROT_EN_MM_CLR, | |
| 568 | + MT8195_TOP_AXI_PROT_EN_MM_STA1), | |
| 569 | + BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_CAM, | |
| 570 | + MT8195_TOP_AXI_PROT_EN_MM_2_SET, | |
| 571 | + MT8195_TOP_AXI_PROT_EN_MM_2_CLR, | |
| 572 | + MT8195_TOP_AXI_PROT_EN_MM_2_STA1), | |
| 573 | + }, | |
| 574 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 575 | + }, | |
| 576 | + [MT8195_POWER_DOMAIN_CAM_RAWA] = { | |
| 577 | + .name = "cam_rawa", | |
| 578 | + .sta_mask = BIT(26), | |
| 579 | + .ctl_offs = 0x3A0, | |
| 580 | + .pwr_sta_offs = 0x16c, | |
| 581 | + .pwr_sta2nd_offs = 0x170, | |
| 582 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 583 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 584 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 585 | + }, | |
| 586 | + [MT8195_POWER_DOMAIN_CAM_RAWB] = { | |
| 587 | + .name = "cam_rawb", | |
| 588 | + .sta_mask = BIT(27), | |
| 589 | + .ctl_offs = 0x3A4, | |
| 590 | + .pwr_sta_offs = 0x16c, | |
| 591 | + .pwr_sta2nd_offs = 0x170, | |
| 592 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 593 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 594 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 595 | + }, | |
| 596 | + [MT8195_POWER_DOMAIN_CAM_MRAW] = { | |
| 597 | + .name = "cam_mraw", | |
| 598 | + .sta_mask = BIT(28), | |
| 599 | + .ctl_offs = 0x3A8, | |
| 600 | + .pwr_sta_offs = 0x16c, | |
| 601 | + .pwr_sta2nd_offs = 0x170, | |
| 602 | + .sram_pdn_bits = GENMASK(8, 8), | |
| 603 | + .sram_pdn_ack_bits = GENMASK(12, 12), | |
| 604 | + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, | |
| 605 | + }, | |
| 606 | +}; | |
| 607 | + | |
| 608 | +static const struct scpsys_soc_data mt8195_scpsys_data = { | |
| 609 | + .domains_data = scpsys_domain_data_mt8195, | |
| 610 | + .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8195), | |
| 611 | +}; | |
| 612 | + | |
| 613 | +#endif /* __SOC_MEDIATEK_MT8195_PM_DOMAINS_H */ | |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/export.h> |
| 7 | 7 | #include <linux/jiffies.h> |
| 8 | 8 | #include <linux/regmap.h> |
| 9 | +#include <linux/mfd/syscon.h> | |
| 9 | 10 | #include <linux/soc/mediatek/infracfg.h> |
| 10 | 11 | #include <asm/processor.h> |
| 11 | 12 | |
| @@ -72,3 +73,21 @@ int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask, · 60 unmodified lines | ||
| 72 | 73 | |
| 73 | 74 | return ret; |
| 74 | 75 | } |
| 76 | + | |
| 77 | +static int __init mtk_infracfg_init(void) | |
| 78 | +{ | |
| 79 | + struct regmap *infracfg; | |
| 80 | + | |
| 81 | + /* | |
| 82 | + * MT8192 has an experimental path to route GPU traffic to the DSU's | |
| 83 | + * Accelerator Coherency Port, which is inadvertently enabled by | |
| 84 | + * default. It turns out not to work, so disable it to prevent spurious | |
| 85 | + * GPU faults. | |
| 86 | + */ | |
| 87 | + infracfg = syscon_regmap_lookup_by_compatible("mediatek,mt8192-infracfg"); | |
| 88 | + if (!IS_ERR(infracfg)) | |
| 89 | + regmap_set_bits(infracfg, MT8192_INFRA_CTRL, | |
| 90 | + MT8192_INFRA_CTRL_DISABLE_MFG2ACP); | |
| 91 | + return 0; | |
| 92 | +} | |
| 93 | +postcore_initcall(mtk_infracfg_init); | |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include "mtk-mmsys.h" |
| 16 | 16 | #include "mt8167-mmsys.h" |
| 17 | 17 | #include "mt8183-mmsys.h" |
| 18 | +#include "mt8186-mmsys.h" | |
| 18 | 19 | #include "mt8192-mmsys.h" |
| 19 | 20 | #include "mt8365-mmsys.h" |
| 20 | 21 | |
| @@ -48,12 +49,21 @@ static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = { · 27 unmodified lines | ||
| 48 | 49 | .clk_driver = "clk-mt8173-mm", |
| 49 | 50 | .routes = mmsys_default_routing_table, |
| 50 | 51 | .num_routes = ARRAY_SIZE(mmsys_default_routing_table), |
| 52 | + .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B, | |
| 51 | 53 | }; |
| 52 | 54 | |
| 53 | 55 | static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = { |
| 54 | 56 | .clk_driver = "clk-mt8183-mm", |
| 55 | 57 | .routes = mmsys_mt8183_routing_table, |
| 56 | 58 | .num_routes = ARRAY_SIZE(mmsys_mt8183_routing_table), |
| 59 | + .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B, | |
| 60 | +}; | |
| 61 | + | |
| 62 | +static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = { | |
| 63 | + .clk_driver = "clk-mt8186-mm", | |
| 64 | + .routes = mmsys_mt8186_routing_table, | |
| 65 | + .num_routes = ARRAY_SIZE(mmsys_mt8186_routing_table), | |
| 66 | + .sw0_rst_offset = MT8186_MMSYS_SW0_RST_B, | |
| 57 | 67 | }; |
| 58 | 68 | |
| 59 | 69 | static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = { |
| @@ -121,14 +131,14 @@ static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned l · 61 unmodified lines | ||
| 121 | 131 | |
| 122 | 132 | spin_lock_irqsave(&mmsys->lock, flags); |
| 123 | 133 | |
| 124 | − reg = readl_relaxed(mmsys->regs + MMSYS_SW0_RST_B); | |
| 134 | + reg = readl_relaxed(mmsys->regs + mmsys->data->sw0_rst_offset); | |
| 125 | 135 | |
| 126 | 136 | if (assert) |
| 127 | 137 | reg &= ~BIT(id); |
| 128 | 138 | else |
| 129 | 139 | reg |= BIT(id); |
| 130 | 140 | |
| 131 | − writel_relaxed(reg, mmsys->regs + MMSYS_SW0_RST_B); | |
| 141 | + writel_relaxed(reg, mmsys->regs + mmsys->data->sw0_rst_offset); | |
| 132 | 142 | |
| 133 | 143 | spin_unlock_irqrestore(&mmsys->lock, flags); |
| 134 | 144 | |
| @@ -242,6 +252,10 @@ static const struct of_device_id of_match_mtk_mmsys[] = { · 107 unmodified lines | ||
| 242 | 252 | .compatible = "mediatek,mt8183-mmsys", |
| 243 | 253 | .data = &mt8183_mmsys_driver_data, |
| 244 | 254 | }, |
| 255 | + { | |
| 256 | + .compatible = "mediatek,mt8186-mmsys", | |
| 257 | + .data = &mt8186_mmsys_driver_data, | |
| 258 | + }, | |
| 245 | 259 | { |
| 246 | 260 | .compatible = "mediatek,mt8192-mmsys", |
| 247 | 261 | .data = &mt8192_mmsys_driver_data, |
| @@ -78,8 +78,6 @@ · 77 unmodified lines | ||
| 78 | 78 | #define DSI_SEL_IN_RDMA 0x1 |
| 79 | 79 | #define DSI_SEL_IN_MASK 0x1 |
| 80 | 80 | |
| 81 | −#define MMSYS_SW0_RST_B 0x140 | |
| 82 | − | |
| 83 | 81 | struct mtk_mmsys_routes { |
| 84 | 82 | u32 from_comp; |
| 85 | 83 | u32 to_comp; |
| @@ -92,6 +90,7 @@ struct mtk_mmsys_driver_data { · 6 unmodified lines | ||
| 92 | 90 | const char *clk_driver; |
| 93 | 91 | const struct mtk_mmsys_routes *routes; |
| 94 | 92 | const unsigned int num_routes; |
| 93 | + const u16 sw0_rst_offset; | |
| 95 | 94 | }; |
| 96 | 95 | |
| 97 | 96 | /* |
| @@ -26,6 +26,23 @@ · 25 unmodified lines | ||
| 26 | 26 | |
| 27 | 27 | #define INT_MUTEX BIT(1) |
| 28 | 28 | |
| 29 | +#define MT8186_MUTEX_MOD_DISP_OVL0 0 | |
| 30 | +#define MT8186_MUTEX_MOD_DISP_OVL0_2L 1 | |
| 31 | +#define MT8186_MUTEX_MOD_DISP_RDMA0 2 | |
| 32 | +#define MT8186_MUTEX_MOD_DISP_COLOR0 4 | |
| 33 | +#define MT8186_MUTEX_MOD_DISP_CCORR0 5 | |
| 34 | +#define MT8186_MUTEX_MOD_DISP_AAL0 7 | |
| 35 | +#define MT8186_MUTEX_MOD_DISP_GAMMA0 8 | |
| 36 | +#define MT8186_MUTEX_MOD_DISP_POSTMASK0 9 | |
| 37 | +#define MT8186_MUTEX_MOD_DISP_DITHER0 10 | |
| 38 | +#define MT8186_MUTEX_MOD_DISP_RDMA1 17 | |
| 39 | + | |
| 40 | +#define MT8186_MUTEX_SOF_SINGLE_MODE 0 | |
| 41 | +#define MT8186_MUTEX_SOF_DSI0 1 | |
| 42 | +#define MT8186_MUTEX_SOF_DPI0 2 | |
| 43 | +#define MT8186_MUTEX_EOF_DSI0 (MT8186_MUTEX_SOF_DSI0 << 6) | |
| 44 | +#define MT8186_MUTEX_EOF_DPI0 (MT8186_MUTEX_SOF_DPI0 << 6) | |
| 45 | + | |
| 29 | 46 | #define MT8167_MUTEX_MOD_DISP_PWM 1 |
| 30 | 47 | #define MT8167_MUTEX_MOD_DISP_OVL0 6 |
| 31 | 48 | #define MT8167_MUTEX_MOD_DISP_OVL1 7 |
| @@ -226,6 +243,19 @@ static const unsigned int mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = { · 194 unmodified lines | ||
| 226 | 243 | [DDP_COMPONENT_WDMA0] = MT8183_MUTEX_MOD_DISP_WDMA0, |
| 227 | 244 | }; |
| 228 | 245 | |
| 246 | +static const unsigned int mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = { | |
| 247 | + [DDP_COMPONENT_AAL0] = MT8186_MUTEX_MOD_DISP_AAL0, | |
| 248 | + [DDP_COMPONENT_CCORR] = MT8186_MUTEX_MOD_DISP_CCORR0, | |
| 249 | + [DDP_COMPONENT_COLOR0] = MT8186_MUTEX_MOD_DISP_COLOR0, | |
| 250 | + [DDP_COMPONENT_DITHER] = MT8186_MUTEX_MOD_DISP_DITHER0, | |
| 251 | + [DDP_COMPONENT_GAMMA] = MT8186_MUTEX_MOD_DISP_GAMMA0, | |
| 252 | + [DDP_COMPONENT_OVL0] = MT8186_MUTEX_MOD_DISP_OVL0, | |
| 253 | + [DDP_COMPONENT_OVL_2L0] = MT8186_MUTEX_MOD_DISP_OVL0_2L, | |
| 254 | + [DDP_COMPONENT_POSTMASK0] = MT8186_MUTEX_MOD_DISP_POSTMASK0, | |
| 255 | + [DDP_COMPONENT_RDMA0] = MT8186_MUTEX_MOD_DISP_RDMA0, | |
| 256 | + [DDP_COMPONENT_RDMA1] = MT8186_MUTEX_MOD_DISP_RDMA1, | |
| 257 | +}; | |
| 258 | + | |
| 229 | 259 | static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = { |
| 230 | 260 | [DDP_COMPONENT_AAL0] = MT8192_MUTEX_MOD_DISP_AAL0, |
| 231 | 261 | [DDP_COMPONENT_CCORR] = MT8192_MUTEX_MOD_DISP_CCORR0, |
| @@ -264,6 +294,12 @@ static const unsigned int mt8183_mutex_sof[MUTEX_SOF_DSI3 + 1] = { · 32 unmodified lines | ||
| 264 | 294 | [MUTEX_SOF_DPI0] = MT8183_MUTEX_SOF_DPI0 | MT8183_MUTEX_EOF_DPI0, |
| 265 | 295 | }; |
| 266 | 296 | |
| 297 | +static const unsigned int mt8186_mutex_sof[MUTEX_SOF_DSI3 + 1] = { | |
| 298 | + [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, | |
| 299 | + [MUTEX_SOF_DSI0] = MT8186_MUTEX_SOF_DSI0 | MT8186_MUTEX_EOF_DSI0, | |
| 300 | + [MUTEX_SOF_DPI0] = MT8186_MUTEX_SOF_DPI0 | MT8186_MUTEX_EOF_DPI0, | |
| 301 | +}; | |
| 302 | + | |
| 267 | 303 | static const struct mtk_mutex_data mt2701_mutex_driver_data = { |
| 268 | 304 | .mutex_mod = mt2701_mutex_mod, |
| 269 | 305 | .mutex_sof = mt2712_mutex_sof, |
| @@ -301,6 +337,13 @@ static const struct mtk_mutex_data mt8183_mutex_driver_data = { · 31 unmodified lines | ||
| 301 | 337 | .no_clk = true, |
| 302 | 338 | }; |
| 303 | 339 | |
| 340 | +static const struct mtk_mutex_data mt8186_mutex_driver_data = { | |
| 341 | + .mutex_mod = mt8186_mutex_mod, | |
| 342 | + .mutex_sof = mt8186_mutex_sof, | |
| 343 | + .mutex_mod_reg = MT8183_MUTEX0_MOD0, | |
| 344 | + .mutex_sof_reg = MT8183_MUTEX0_SOF0, | |
| 345 | +}; | |
| 346 | + | |
| 304 | 347 | static const struct mtk_mutex_data mt8192_mutex_driver_data = { |
| 305 | 348 | .mutex_mod = mt8192_mutex_mod, |
| 306 | 349 | .mutex_sof = mt8183_mutex_sof, |
| @@ -540,6 +583,8 @@ static const struct of_device_id mutex_driver_dt_match[] = { · 233 unmodified lines | ||
| 540 | 583 | .data = &mt8173_mutex_driver_data}, |
| 541 | 584 | { .compatible = "mediatek,mt8183-disp-mutex", |
| 542 | 585 | .data = &mt8183_mutex_driver_data}, |
| 586 | + { .compatible = "mediatek,mt8186-disp-mutex", | |
| 587 | + .data = &mt8186_mutex_driver_data}, | |
| 543 | 588 | { .compatible = "mediatek,mt8192-disp-mutex", |
| 544 | 589 | .data = &mt8192_mutex_driver_data}, |
| 545 | 590 | {}, |
| @@ -19,7 +19,9 @@ · 18 unmodified lines | ||
| 19 | 19 | #include "mt8167-pm-domains.h" |
| 20 | 20 | #include "mt8173-pm-domains.h" |
| 21 | 21 | #include "mt8183-pm-domains.h" |
| 22 | +#include "mt8186-pm-domains.h" | |
| 22 | 23 | #include "mt8192-pm-domains.h" |
| 24 | +#include "mt8195-pm-domains.h" | |
| 23 | 25 | |
| 24 | 26 | #define MTK_POLL_DELAY_US 10 |
| 25 | 27 | #define MTK_POLL_TIMEOUT USEC_PER_SEC |
| @@ -60,10 +62,10 @@ static bool scpsys_domain_is_on(struct scpsys_domain *pd) · 34 unmodified lines | ||
| 60 | 62 | struct scpsys *scpsys = pd->scpsys; |
| 61 | 63 | u32 status, status2; |
| 62 | 64 | |
| 63 | − regmap_read(scpsys->base, scpsys->soc_data->pwr_sta_offs, &status); | |
| 65 | + regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status); | |
| 64 | 66 | status &= pd->data->sta_mask; |
| 65 | 67 | |
| 66 | − regmap_read(scpsys->base, scpsys->soc_data->pwr_sta2nd_offs, &status2); | |
| 68 | + regmap_read(scpsys->base, pd->data->pwr_sta2nd_offs, &status2); | |
| 67 | 69 | status2 &= pd->data->sta_mask; |
| 68 | 70 | |
| 69 | 71 | /* A domain is on when both status bits are set. */ |
| @@ -443,6 +445,9 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no · 373 unmodified lines | ||
| 443 | 445 | pd->genpd.power_off = scpsys_power_off; |
| 444 | 446 | pd->genpd.power_on = scpsys_power_on; |
| 445 | 447 | |
| 448 | + if (MTK_SCPD_CAPS(pd, MTK_SCPD_ACTIVE_WAKEUP)) | |
| 449 | + pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; | |
| 450 | + | |
| 446 | 451 | if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) |
| 447 | 452 | pm_genpd_init(&pd->genpd, NULL, true); |
| 448 | 453 | else |
| @@ -562,10 +567,18 @@ static const struct of_device_id scpsys_of_match[] = { · 113 unmodified lines | ||
| 562 | 567 | .compatible = "mediatek,mt8183-power-controller", |
| 563 | 568 | .data = &mt8183_scpsys_data, |
| 564 | 569 | }, |
| 570 | + { | |
| 571 | + .compatible = "mediatek,mt8186-power-controller", | |
| 572 | + .data = &mt8186_scpsys_data, | |
| 573 | + }, | |
| 565 | 574 | { |
| 566 | 575 | .compatible = "mediatek,mt8192-power-controller", |
| 567 | 576 | .data = &mt8192_scpsys_data, |
| 568 | 577 | }, |
| 578 | + { | |
| 579 | + .compatible = "mediatek,mt8195-power-controller", | |
| 580 | + .data = &mt8195_scpsys_data, | |
| 581 | + }, | |
| 569 | 582 | { } |
| 570 | 583 | }; |
| 571 | 584 | |
| @@ -37,7 +37,7 @@ · 36 unmodified lines | ||
| 37 | 37 | #define PWR_STATUS_AUDIO BIT(24) |
| 38 | 38 | #define PWR_STATUS_USB BIT(25) |
| 39 | 39 | |
| 40 | −#define SPM_MAX_BUS_PROT_DATA 5 | |
| 40 | +#define SPM_MAX_BUS_PROT_DATA 6 | |
| 41 | 41 | |
| 42 | 42 | #define _BUS_PROT(_mask, _set, _clr, _sta, _update, _ignore) { \ |
| 43 | 43 | .bus_prot_mask = (_mask), \ |
| @@ -72,8 +72,6 @@ struct scpsys_bus_prot_data { · 28 unmodified lines | ||
| 72 | 72 | bool ignore_clr_ack; |
| 73 | 73 | }; |
| 74 | 74 | |
| 75 | −#define MAX_SUBSYS_CLKS 10 | |
| 76 | − | |
| 77 | 75 | /** |
| 78 | 76 | * struct scpsys_domain_data - scp domain data for power on/off flow |
| 79 | 77 | * @name: The name of the power domain. |
| @@ -94,13 +92,13 @@ struct scpsys_domain_data { · 14 unmodified lines | ||
| 94 | 92 | u8 caps; |
| 95 | 93 | const struct scpsys_bus_prot_data bp_infracfg[SPM_MAX_BUS_PROT_DATA]; |
| 96 | 94 | const struct scpsys_bus_prot_data bp_smi[SPM_MAX_BUS_PROT_DATA]; |
| 95 | + int pwr_sta_offs; | |
| 96 | + int pwr_sta2nd_offs; | |
| 97 | 97 | }; |
| 98 | 98 | |
| 99 | 99 | struct scpsys_soc_data { |
| 100 | 100 | const struct scpsys_domain_data *domains_data; |
| 101 | 101 | int num_domains; |
| 102 | − int pwr_sta_offs; | |
| 103 | − int pwr_sta2nd_offs; | |
| 104 | 102 | }; |
| 105 | 103 | |
| 106 | 104 | #endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */ |
| @@ -30,6 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #define PWRAP_GET_WACS_REQ(x) (((x) >> 19) & 0x00000001) |
| 31 | 31 | #define PWRAP_STATE_SYNC_IDLE0 BIT(20) |
| 32 | 32 | #define PWRAP_STATE_INIT_DONE0 BIT(21) |
| 33 | +#define PWRAP_STATE_INIT_DONE0_MT8186 BIT(22) | |
| 33 | 34 | #define PWRAP_STATE_INIT_DONE1 BIT(15) |
| 34 | 35 | |
| 35 | 36 | /* macro for WACS FSM */ |
| @@ -77,6 +78,7 @@ · 41 unmodified lines | ||
| 77 | 78 | #define PWRAP_CAP_INT1_EN BIT(3) |
| 78 | 79 | #define PWRAP_CAP_WDT_SRC1 BIT(4) |
| 79 | 80 | #define PWRAP_CAP_ARB BIT(5) |
| 81 | +#define PWRAP_CAP_ARB_MT8186 BIT(8) | |
| 80 | 82 | |
| 81 | 83 | /* defines for slave device wrapper registers */ |
| 82 | 84 | enum dew_regs { |
| @@ -1063,6 +1065,55 @@ static int mt8516_regs[] = { · 980 unmodified lines | ||
| 1063 | 1065 | [PWRAP_MSB_FIRST] = 0x170, |
| 1064 | 1066 | }; |
| 1065 | 1067 | |
| 1068 | +static int mt8186_regs[] = { | |
| 1069 | + [PWRAP_MUX_SEL] = 0x0, | |
| 1070 | + [PWRAP_WRAP_EN] = 0x4, | |
| 1071 | + [PWRAP_DIO_EN] = 0x8, | |
| 1072 | + [PWRAP_RDDMY] = 0x20, | |
| 1073 | + [PWRAP_CSHEXT_WRITE] = 0x24, | |
| 1074 | + [PWRAP_CSHEXT_READ] = 0x28, | |
| 1075 | + [PWRAP_CSLEXT_WRITE] = 0x2C, | |
| 1076 | + [PWRAP_CSLEXT_READ] = 0x30, | |
| 1077 | + [PWRAP_EXT_CK_WRITE] = 0x34, | |
| 1078 | + [PWRAP_STAUPD_CTRL] = 0x3C, | |
| 1079 | + [PWRAP_STAUPD_GRPEN] = 0x40, | |
| 1080 | + [PWRAP_EINT_STA0_ADR] = 0x44, | |
| 1081 | + [PWRAP_EINT_STA1_ADR] = 0x48, | |
| 1082 | + [PWRAP_INT_CLR] = 0xC8, | |
| 1083 | + [PWRAP_INT_FLG] = 0xC4, | |
| 1084 | + [PWRAP_MAN_EN] = 0x7C, | |
| 1085 | + [PWRAP_MAN_CMD] = 0x80, | |
| 1086 | + [PWRAP_WACS0_EN] = 0x8C, | |
| 1087 | + [PWRAP_WACS1_EN] = 0x94, | |
| 1088 | + [PWRAP_WACS2_EN] = 0x9C, | |
| 1089 | + [PWRAP_INIT_DONE0] = 0x90, | |
| 1090 | + [PWRAP_INIT_DONE1] = 0x98, | |
| 1091 | + [PWRAP_INIT_DONE2] = 0xA0, | |
| 1092 | + [PWRAP_INT_EN] = 0xBC, | |
| 1093 | + [PWRAP_INT1_EN] = 0xCC, | |
| 1094 | + [PWRAP_INT1_FLG] = 0xD4, | |
| 1095 | + [PWRAP_INT1_CLR] = 0xD8, | |
| 1096 | + [PWRAP_TIMER_EN] = 0xF0, | |
| 1097 | + [PWRAP_WDT_UNIT] = 0xF8, | |
| 1098 | + [PWRAP_WDT_SRC_EN] = 0xFC, | |
| 1099 | + [PWRAP_WDT_SRC_EN_1] = 0x100, | |
| 1100 | + [PWRAP_WDT_FLG] = 0x104, | |
| 1101 | + [PWRAP_SPMINF_STA] = 0x1B4, | |
| 1102 | + [PWRAP_DCM_EN] = 0x1EC, | |
| 1103 | + [PWRAP_DCM_DBC_PRD] = 0x1F0, | |
| 1104 | + [PWRAP_GPSINF_0_STA] = 0x204, | |
| 1105 | + [PWRAP_GPSINF_1_STA] = 0x208, | |
| 1106 | + [PWRAP_WACS0_CMD] = 0xC00, | |
| 1107 | + [PWRAP_WACS0_RDATA] = 0xC04, | |
| 1108 | + [PWRAP_WACS0_VLDCLR] = 0xC08, | |
| 1109 | + [PWRAP_WACS1_CMD] = 0xC10, | |
| 1110 | + [PWRAP_WACS1_RDATA] = 0xC14, | |
| 1111 | + [PWRAP_WACS1_VLDCLR] = 0xC18, | |
| 1112 | + [PWRAP_WACS2_CMD] = 0xC20, | |
| 1113 | + [PWRAP_WACS2_RDATA] = 0xC24, | |
| 1114 | + [PWRAP_WACS2_VLDCLR] = 0xC28, | |
| 1115 | +}; | |
| 1116 | + | |
| 1066 | 1117 | enum pmic_type { |
| 1067 | 1118 | PMIC_MT6323, |
| 1068 | 1119 | PMIC_MT6351, |
| @@ -1083,6 +1134,7 @@ enum pwrap_type { · 14 unmodified lines | ||
| 1083 | 1134 | PWRAP_MT8135, |
| 1084 | 1135 | PWRAP_MT8173, |
| 1085 | 1136 | PWRAP_MT8183, |
| 1137 | + PWRAP_MT8186, | |
| 1086 | 1138 | PWRAP_MT8195, |
| 1087 | 1139 | PWRAP_MT8516, |
| 1088 | 1140 | }; |
| @@ -1535,6 +1587,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) · 446 unmodified lines | ||
| 1535 | 1587 | case PWRAP_MT6779: |
| 1536 | 1588 | case PWRAP_MT6797: |
| 1537 | 1589 | case PWRAP_MT8173: |
| 1590 | + case PWRAP_MT8186: | |
| 1538 | 1591 | case PWRAP_MT8516: |
| 1539 | 1592 | pwrap_writel(wrp, 1, PWRAP_CIPHER_EN); |
| 1540 | 1593 | break; |
| @@ -2069,6 +2122,19 @@ static struct pmic_wrapper_type pwrap_mt8516 = { · 528 unmodified lines | ||
| 2069 | 2122 | .init_soc_specific = NULL, |
| 2070 | 2123 | }; |
| 2071 | 2124 | |
| 2125 | +static struct pmic_wrapper_type pwrap_mt8186 = { | |
| 2126 | + .regs = mt8186_regs, | |
| 2127 | + .type = PWRAP_MT8186, | |
| 2128 | + .arb_en_all = 0xfb27f, | |
| 2129 | + .int_en_all = 0xfffffffe, /* disable WatchDog Timeout for bit 1 */ | |
| 2130 | + .int1_en_all = 0x000017ff, /* disable Matching interrupt for bit 13 */ | |
| 2131 | + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, | |
| 2132 | + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, | |
| 2133 | + .caps = PWRAP_CAP_INT1_EN | PWRAP_CAP_ARB_MT8186, | |
| 2134 | + .init_reg_clock = pwrap_common_init_reg_clock, | |
| 2135 | + .init_soc_specific = NULL, | |
| 2136 | +}; | |
| 2137 | + | |
| 2072 | 2138 | static const struct of_device_id of_pwrap_match_tbl[] = { |
| 2073 | 2139 | { |
| 2074 | 2140 | .compatible = "mediatek,mt2701-pwrap", |
| @@ -2097,6 +2163,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = { · 22 unmodified lines | ||
| 2097 | 2163 | }, { |
| 2098 | 2164 | .compatible = "mediatek,mt8183-pwrap", |
| 2099 | 2165 | .data = &pwrap_mt8183, |
| 2166 | + }, { | |
| 2167 | + .compatible = "mediatek,mt8186-pwrap", | |
| 2168 | + .data = &pwrap_mt8186, | |
| 2100 | 2169 | }, { |
| 2101 | 2170 | .compatible = "mediatek,mt8195-pwrap", |
| 2102 | 2171 | .data = &pwrap_mt8195, |
| @@ -2209,6 +2278,8 @@ static int pwrap_probe(struct platform_device *pdev) · 106 unmodified lines | ||
| 2209 | 2278 | |
| 2210 | 2279 | if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB)) |
| 2211 | 2280 | mask_done = PWRAP_STATE_INIT_DONE1; |
| 2281 | + else if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB_MT8186)) | |
| 2282 | + mask_done = PWRAP_STATE_INIT_DONE0_MT8186; | |
| 2212 | 2283 | else |
| 2213 | 2284 | mask_done = PWRAP_STATE_INIT_DONE0; |
| 2214 | 2285 | |
| @@ -95,9 +95,9 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev) · 94 unmodified lines | ||
| 95 | 95 | { |
| 96 | 96 | struct device *dev = &pdev->dev; |
| 97 | 97 | struct mpfs_sys_controller *sys_controller; |
| 98 | − int i; | |
| 98 | + int i, ret; | |
| 99 | 99 | |
| 100 | − sys_controller = devm_kzalloc(dev, sizeof(*sys_controller), GFP_KERNEL); | |
| 100 | + sys_controller = kzalloc(sizeof(*sys_controller), GFP_KERNEL); | |
| 101 | 101 | if (!sys_controller) |
| 102 | 102 | return -ENOMEM; |
| 103 | 103 | |
| @@ -106,9 +106,12 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 106 | 106 | sys_controller->client.tx_block = 1U; |
| 107 | 107 | |
| 108 | 108 | sys_controller->chan = mbox_request_channel(&sys_controller->client, 0); |
| 109 | − if (IS_ERR(sys_controller->chan)) | |
| 110 | − return dev_err_probe(dev, PTR_ERR(sys_controller->chan), | |
| 111 | − "Failed to get mbox channel\n"); | |
| 109 | + if (IS_ERR(sys_controller->chan)) { | |
| 110 | + ret = dev_err_probe(dev, PTR_ERR(sys_controller->chan), | |
| 111 | + "Failed to get mbox channel\n"); | |
| 112 | + kfree(sys_controller); | |
| 113 | + return ret; | |
| 114 | + } | |
| 112 | 115 | |
| 113 | 116 | init_completion(&sys_controller->c); |
| 114 | 117 | kref_init(&sys_controller->consumers); |
| @@ -653,7 +653,6 @@ static void apr_remove(struct rpmsg_device *rpdev) · 652 unmodified lines | ||
| 653 | 653 | |
| 654 | 654 | pdr_handle_release(apr->pdr); |
| 655 | 655 | device_for_each_child(&rpdev->dev, NULL, apr_remove_device); |
| 656 | − flush_workqueue(apr->rxwq); | |
| 657 | 656 | destroy_workqueue(apr->rxwq); |
| 658 | 657 | } |
| 659 | 658 | |
| @@ -29,17 +29,13 @@ · 28 unmodified lines | ||
| 29 | 29 | #define ATTR1_FIXED_SIZE_SHIFT 0x03 |
| 30 | 30 | #define ATTR1_PRIORITY_SHIFT 0x04 |
| 31 | 31 | #define ATTR1_MAX_CAP_SHIFT 0x10 |
| 32 | −#define ATTR0_RES_WAYS_MASK GENMASK(11, 0) | |
| 33 | −#define ATTR0_BONUS_WAYS_MASK GENMASK(27, 16) | |
| 32 | +#define ATTR0_RES_WAYS_MASK GENMASK(15, 0) | |
| 33 | +#define ATTR0_BONUS_WAYS_MASK GENMASK(31, 16) | |
| 34 | 34 | #define ATTR0_BONUS_WAYS_SHIFT 0x10 |
| 35 | 35 | #define LLCC_STATUS_READ_DELAY 100 |
| 36 | 36 | |
| 37 | 37 | #define CACHE_LINE_SIZE_SHIFT 6 |
| 38 | 38 | |
| 39 | −#define LLCC_COMMON_HW_INFO 0x00030000 | |
| 40 | −#define LLCC_MAJOR_VERSION_MASK GENMASK(31, 24) | |
| 41 | − | |
| 42 | −#define LLCC_COMMON_STATUS0 0x0003000c | |
| 43 | 39 | #define LLCC_LB_CNT_MASK GENMASK(31, 28) |
| 44 | 40 | #define LLCC_LB_CNT_SHIFT 28 |
| 45 | 41 | |
| @@ -52,9 +48,13 @@ · 6 unmodified lines | ||
| 52 | 48 | #define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00 |
| 53 | 49 | #define LLCC_TRP_PCB_ACT 0x21f04 |
| 54 | 50 | #define LLCC_TRP_WRSC_EN 0x21f20 |
| 51 | +#define LLCC_TRP_WRSC_CACHEABLE_EN 0x21f2c | |
| 55 | 52 | |
| 56 | 53 | #define BANK_OFFSET_STRIDE 0x80000 |
| 57 | 54 | |
| 55 | +#define LLCC_VERSION_2_0_0_0 0x02000000 | |
| 56 | +#define LLCC_VERSION_2_1_0_0 0x02010000 | |
| 57 | + | |
| 58 | 58 | /** |
| 59 | 59 | * struct llcc_slice_config - Data associated with the llcc slice |
| 60 | 60 | * @usecase_id: Unique id for the client's use case |
| @@ -79,6 +79,8 @@ · 18 unmodified lines | ||
| 79 | 79 | * collapse. |
| 80 | 80 | * @activate_on_init: Activate the slice immediately after it is programmed |
| 81 | 81 | * @write_scid_en: Bit enables write cache support for a given scid. |
| 82 | + * @write_scid_cacheable_en: Enables write cache cacheable support for a | |
| 83 | + * given scid (not supported on v2 or older hardware). | |
| 82 | 84 | */ |
| 83 | 85 | struct llcc_slice_config { |
| 84 | 86 | u32 usecase_id; |
| @@ -94,12 +96,19 @@ struct llcc_slice_config { · 9 unmodified lines | ||
| 94 | 96 | bool retain_on_pc; |
| 95 | 97 | bool activate_on_init; |
| 96 | 98 | bool write_scid_en; |
| 99 | + bool write_scid_cacheable_en; | |
| 97 | 100 | }; |
| 98 | 101 | |
| 99 | 102 | struct qcom_llcc_config { |
| 100 | 103 | const struct llcc_slice_config *sct_data; |
| 101 | 104 | int size; |
| 102 | 105 | bool need_llcc_cfg; |
| 106 | + const u32 *reg_offset; | |
| 107 | +}; | |
| 108 | + | |
| 109 | +enum llcc_reg_offset { | |
| 110 | + LLCC_COMMON_HW_INFO, | |
| 111 | + LLCC_COMMON_STATUS0, | |
| 103 | 112 | }; |
| 104 | 113 | |
| 105 | 114 | static const struct llcc_slice_config sc7180_data[] = { |
| @@ -217,42 +226,96 @@ static const struct llcc_slice_config sm8350_data[] = { · 111 unmodified lines | ||
| 217 | 226 | { LLCC_CPUHWT, 5, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 1 }, |
| 218 | 227 | }; |
| 219 | 228 | |
| 229 | +static const struct llcc_slice_config sm8450_data[] = { | |
| 230 | + {LLCC_CPUSS, 1, 3072, 1, 0, 0xFFFF, 0x0, 0, 0, 0, 1, 1, 0, 0 }, | |
| 231 | + {LLCC_VIDSC0, 2, 512, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 232 | + {LLCC_AUDIO, 6, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, | |
| 233 | + {LLCC_MDMHPGRW, 7, 1024, 3, 0, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 234 | + {LLCC_MODHW, 9, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 235 | + {LLCC_CMPT, 10, 4096, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 236 | + {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 237 | + {LLCC_GPU, 12, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 1, 0 }, | |
| 238 | + {LLCC_MMUHWT, 13, 768, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0 }, | |
| 239 | + {LLCC_DISP, 16, 4096, 2, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 240 | + {LLCC_MDMPNG, 21, 1024, 1, 1, 0xF000, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 241 | + {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, | |
| 242 | + {LLCC_CVP, 28, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 243 | + {LLCC_MODPE, 29, 64, 1, 1, 0xF000, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 244 | + {LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xF0, 1, 0, 0, 1, 0, 0, 0 }, | |
| 245 | + {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0 }, | |
| 246 | + {LLCC_CVPFW, 17, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 247 | + {LLCC_CPUSS1, 3, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 248 | + {LLCC_CAMEXP0, 4, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 249 | + {LLCC_CPUMTE, 23, 256, 1, 1, 0x0FFF, 0x0, 0, 0, 0, 0, 1, 0, 0 }, | |
| 250 | + {LLCC_CPUHWT, 5, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 1, 0, 0 }, | |
| 251 | + {LLCC_CAMEXP1, 27, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, | |
| 252 | + {LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, | |
| 253 | +}; | |
| 254 | + | |
| 255 | +static const u32 llcc_v1_2_reg_offset[] = { | |
| 256 | + [LLCC_COMMON_HW_INFO] = 0x00030000, | |
| 257 | + [LLCC_COMMON_STATUS0] = 0x0003000c, | |
| 258 | +}; | |
| 259 | + | |
| 260 | +static const u32 llcc_v21_reg_offset[] = { | |
| 261 | + [LLCC_COMMON_HW_INFO] = 0x00034000, | |
| 262 | + [LLCC_COMMON_STATUS0] = 0x0003400c, | |
| 263 | +}; | |
| 264 | + | |
| 220 | 265 | static const struct qcom_llcc_config sc7180_cfg = { |
| 221 | 266 | .sct_data = sc7180_data, |
| 222 | 267 | .size = ARRAY_SIZE(sc7180_data), |
| 223 | 268 | .need_llcc_cfg = true, |
| 269 | + .reg_offset = llcc_v1_2_reg_offset, | |
| 224 | 270 | }; |
| 225 | 271 | |
| 226 | 272 | static const struct qcom_llcc_config sc7280_cfg = { |
| 227 | 273 | .sct_data = sc7280_data, |
| 228 | 274 | .size = ARRAY_SIZE(sc7280_data), |
| 229 | 275 | .need_llcc_cfg = true, |
| 276 | + .reg_offset = llcc_v1_2_reg_offset, | |
| 230 | 277 | }; |
| 231 | 278 | |
| 232 | 279 | static const struct qcom_llcc_config sdm845_cfg = { |
| 233 | 280 | .sct_data = sdm845_data, |
| 234 | 281 | .size = ARRAY_SIZE(sdm845_data), |
| 235 | 282 | .need_llcc_cfg = false, |
| 283 | + .reg_offset = llcc_v1_2_reg_offset, | |
| 236 | 284 | }; |
| 237 | 285 | |
| 238 | 286 | static const struct qcom_llcc_config sm6350_cfg = { |
| 239 | 287 | .sct_data = sm6350_data, |
| 240 | 288 | .size = ARRAY_SIZE(sm6350_data), |
| 289 | + .need_llcc_cfg = true, | |
| 290 | + .reg_offset = llcc_v1_2_reg_offset, | |
| 241 | 291 | }; |
| 242 | 292 | |
| 243 | 293 | static const struct qcom_llcc_config sm8150_cfg = { |
| 244 | 294 | .sct_data = sm8150_data, |
| 245 | 295 | .size = ARRAY_SIZE(sm8150_data), |
| 296 | + .need_llcc_cfg = true, | |
| 297 | + .reg_offset = llcc_v1_2_reg_offset, | |
| 246 | 298 | }; |
| 247 | 299 | |
| 248 | 300 | static const struct qcom_llcc_config sm8250_cfg = { |
| 249 | 301 | .sct_data = sm8250_data, |
| 250 | 302 | .size = ARRAY_SIZE(sm8250_data), |
| 303 | + .need_llcc_cfg = true, | |
| 304 | + .reg_offset = llcc_v1_2_reg_offset, | |
| 251 | 305 | }; |
| 252 | 306 | |
| 253 | 307 | static const struct qcom_llcc_config sm8350_cfg = { |
| 254 | 308 | .sct_data = sm8350_data, |
| 255 | 309 | .size = ARRAY_SIZE(sm8350_data), |
| 310 | + .need_llcc_cfg = true, | |
| 311 | + .reg_offset = llcc_v1_2_reg_offset, | |
| 312 | +}; | |
| 313 | + | |
| 314 | +static const struct qcom_llcc_config sm8450_cfg = { | |
| 315 | + .sct_data = sm8450_data, | |
| 316 | + .size = ARRAY_SIZE(sm8450_data), | |
| 317 | + .need_llcc_cfg = true, | |
| 318 | + .reg_offset = llcc_v21_reg_offset, | |
| 256 | 319 | }; |
| 257 | 320 | |
| 258 | 321 | static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; |
| @@ -504,7 +567,7 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, · 245 unmodified lines | ||
| 504 | 567 | return ret; |
| 505 | 568 | } |
| 506 | 569 | |
| 507 | − if (drv_data->major_version == 2) { | |
| 570 | + if (drv_data->version >= LLCC_VERSION_2_0_0_0) { | |
| 508 | 571 | u32 wren; |
| 509 | 572 | |
| 510 | 573 | wren = config->write_scid_en << config->slice_id; |
| @@ -514,6 +577,16 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, · 3 unmodified lines | ||
| 514 | 577 | return ret; |
| 515 | 578 | } |
| 516 | 579 | |
| 580 | + if (drv_data->version >= LLCC_VERSION_2_1_0_0) { | |
| 581 | + u32 wr_cache_en; | |
| 582 | + | |
| 583 | + wr_cache_en = config->write_scid_cacheable_en << config->slice_id; | |
| 584 | + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_WRSC_CACHEABLE_EN, | |
| 585 | + BIT(config->slice_id), wr_cache_en); | |
| 586 | + if (ret) | |
| 587 | + return ret; | |
| 588 | + } | |
| 589 | + | |
| 517 | 590 | if (config->activate_on_init) { |
| 518 | 591 | desc.slice_id = config->slice_id; |
| 519 | 592 | ret = llcc_slice_activate(&desc); |
| @@ -598,15 +671,18 @@ static int qcom_llcc_probe(struct platform_device *pdev) · 78 unmodified lines | ||
| 598 | 671 | goto err; |
| 599 | 672 | } |
| 600 | 673 | |
| 601 | − /* Extract major version of the IP */ | |
| 602 | − ret = regmap_read(drv_data->bcast_regmap, LLCC_COMMON_HW_INFO, &version); | |
| 674 | + cfg = of_device_get_match_data(&pdev->dev); | |
| 675 | + | |
| 676 | + /* Extract version of the IP */ | |
| 677 | + ret = regmap_read(drv_data->bcast_regmap, cfg->reg_offset[LLCC_COMMON_HW_INFO], | |
| 678 | + &version); | |
| 603 | 679 | if (ret) |
| 604 | 680 | goto err; |
| 605 | 681 | |
| 606 | − drv_data->major_version = FIELD_GET(LLCC_MAJOR_VERSION_MASK, version); | |
| 682 | + drv_data->version = version; | |
| 607 | 683 | |
| 608 | − ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, | |
| 609 | − &num_banks); | |
| 684 | + ret = regmap_read(drv_data->regmap, cfg->reg_offset[LLCC_COMMON_STATUS0], | |
| 685 | + &num_banks); | |
| 610 | 686 | if (ret) |
| 611 | 687 | goto err; |
| 612 | 688 | |
| @@ -614,7 +690,6 @@ static int qcom_llcc_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 614 | 690 | num_banks >>= LLCC_LB_CNT_SHIFT; |
| 615 | 691 | drv_data->num_banks = num_banks; |
| 616 | 692 | |
| 617 | − cfg = of_device_get_match_data(&pdev->dev); | |
| 618 | 693 | llcc_cfg = cfg->sct_data; |
| 619 | 694 | sz = cfg->size; |
| 620 | 695 | |
| @@ -632,9 +707,8 @@ static int qcom_llcc_probe(struct platform_device *pdev) · 11 unmodified lines | ||
| 632 | 707 | for (i = 0; i < num_banks; i++) |
| 633 | 708 | drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; |
| 634 | 709 | |
| 635 | − drv_data->bitmap = devm_kcalloc(dev, | |
| 636 | − BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), | |
| 637 | − GFP_KERNEL); | |
| 710 | + drv_data->bitmap = devm_bitmap_zalloc(dev, drv_data->max_slices, | |
| 711 | + GFP_KERNEL); | |
| 638 | 712 | if (!drv_data->bitmap) { |
| 639 | 713 | ret = -ENOMEM; |
| 640 | 714 | goto err; |
| @@ -672,6 +746,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { · 31 unmodified lines | ||
| 672 | 746 | { .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg }, |
| 673 | 747 | { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg }, |
| 674 | 748 | { .compatible = "qcom,sm8350-llcc", .data = &sm8350_cfg }, |
| 749 | + { .compatible = "qcom,sm8450-llcc", .data = &sm8450_cfg }, | |
| 675 | 750 | { } |
| 676 | 751 | }; |
| 677 | 752 | |
| @@ -31,6 +31,44 @@ static bool mdt_phdr_valid(const struct elf32_phdr *phdr) · 30 unmodified lines | ||
| 31 | 31 | return true; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | +static ssize_t mdt_load_split_segment(void *ptr, const struct elf32_phdr *phdrs, | |
| 35 | + unsigned int segment, const char *fw_name, | |
| 36 | + struct device *dev) | |
| 37 | +{ | |
| 38 | + const struct elf32_phdr *phdr = &phdrs[segment]; | |
| 39 | + const struct firmware *seg_fw; | |
| 40 | + char *seg_name; | |
| 41 | + ssize_t ret; | |
| 42 | + | |
| 43 | + if (strlen(fw_name) < 4) | |
| 44 | + return -EINVAL; | |
| 45 | + | |
| 46 | + seg_name = kstrdup(fw_name, GFP_KERNEL); | |
| 47 | + if (!seg_name) | |
| 48 | + return -ENOMEM; | |
| 49 | + | |
| 50 | + sprintf(seg_name + strlen(fw_name) - 3, "b%02d", segment); | |
| 51 | + ret = request_firmware_into_buf(&seg_fw, seg_name, dev, | |
| 52 | + ptr, phdr->p_filesz); | |
| 53 | + if (ret) { | |
| 54 | + dev_err(dev, "error %zd loading %s\n", ret, seg_name); | |
| 55 | + kfree(seg_name); | |
| 56 | + return ret; | |
| 57 | + } | |
| 58 | + | |
| 59 | + if (seg_fw->size != phdr->p_filesz) { | |
| 60 | + dev_err(dev, | |
| 61 | + "failed to load segment %d from truncated file %s\n", | |
| 62 | + segment, seg_name); | |
| 63 | + ret = -EINVAL; | |
| 64 | + } | |
| 65 | + | |
| 66 | + release_firmware(seg_fw); | |
| 67 | + kfree(seg_name); | |
| 68 | + | |
| 69 | + return ret; | |
| 70 | +} | |
| 71 | + | |
| 34 | 72 | /** |
| 35 | 73 | * qcom_mdt_get_size() - acquire size of the memory region needed to load mdt |
| 36 | 74 | * @fw: firmware object for the mdt file |
| @@ -83,13 +121,17 @@ EXPORT_SYMBOL_GPL(qcom_mdt_get_size); · 46 unmodified lines | ||
| 83 | 121 | * |
| 84 | 122 | * Return: pointer to data, or ERR_PTR() |
| 85 | 123 | */ |
| 86 | −void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len) | |
| 124 | +void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len, | |
| 125 | + const char *fw_name, struct device *dev) | |
| 87 | 126 | { |
| 88 | 127 | const struct elf32_phdr *phdrs; |
| 89 | 128 | const struct elf32_hdr *ehdr; |
| 129 | + unsigned int hash_segment = 0; | |
| 90 | 130 | size_t hash_offset; |
| 91 | 131 | size_t hash_size; |
| 92 | 132 | size_t ehdr_size; |
| 133 | + unsigned int i; | |
| 134 | + ssize_t ret; | |
| 93 | 135 | void *data; |
| 94 | 136 | |
| 95 | 137 | ehdr = (struct elf32_hdr *)fw->data; |
| @@ -101,24 +143,44 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len) · 5 unmodified lines | ||
| 101 | 143 | if (phdrs[0].p_type == PT_LOAD) |
| 102 | 144 | return ERR_PTR(-EINVAL); |
| 103 | 145 | |
| 104 | − if ((phdrs[1].p_flags & QCOM_MDT_TYPE_MASK) != QCOM_MDT_TYPE_HASH) | |
| 146 | + for (i = 1; i < ehdr->e_phnum; i++) { | |
| 147 | + if ((phdrs[i].p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH) { | |
| 148 | + hash_segment = i; | |
| 149 | + break; | |
| 150 | + } | |
| 151 | + } | |
| 152 | + | |
| 153 | + if (!hash_segment) { | |
| 154 | + dev_err(dev, "no hash segment found in %s\n", fw_name); | |
| 105 | 155 | return ERR_PTR(-EINVAL); |
| 156 | + } | |
| 106 | 157 | |
| 107 | 158 | ehdr_size = phdrs[0].p_filesz; |
| 108 | − hash_size = phdrs[1].p_filesz; | |
| 159 | + hash_size = phdrs[hash_segment].p_filesz; | |
| 109 | 160 | |
| 110 | 161 | data = kmalloc(ehdr_size + hash_size, GFP_KERNEL); |
| 111 | 162 | if (!data) |
| 112 | 163 | return ERR_PTR(-ENOMEM); |
| 113 | 164 | |
| 114 | − /* Is the header and hash already packed */ | |
| 115 | − if (ehdr_size + hash_size == fw->size) | |
| 116 | − hash_offset = phdrs[0].p_filesz; | |
| 117 | − else | |
| 118 | − hash_offset = phdrs[1].p_offset; | |
| 119 | − | |
| 165 | + /* Copy ELF header */ | |
| 120 | 166 | memcpy(data, fw->data, ehdr_size); |
| 121 | − memcpy(data + ehdr_size, fw->data + hash_offset, hash_size); | |
| 167 | + | |
| 168 | + if (ehdr_size + hash_size == fw->size) { | |
| 169 | + /* Firmware is split and hash is packed following the ELF header */ | |
| 170 | + hash_offset = phdrs[0].p_filesz; | |
| 171 | + memcpy(data + ehdr_size, fw->data + hash_offset, hash_size); | |
| 172 | + } else if (phdrs[hash_segment].p_offset + hash_size <= fw->size) { | |
| 173 | + /* Hash is in its own segment, but within the loaded file */ | |
| 174 | + hash_offset = phdrs[hash_segment].p_offset; | |
| 175 | + memcpy(data + ehdr_size, fw->data + hash_offset, hash_size); | |
| 176 | + } else { | |
| 177 | + /* Hash is in its own segment, beyond the loaded file */ | |
| 178 | + ret = mdt_load_split_segment(data + ehdr_size, phdrs, hash_segment, fw_name, dev); | |
| 179 | + if (ret) { | |
| 180 | + kfree(data); | |
| 181 | + return ERR_PTR(ret); | |
| 182 | + } | |
| 183 | + } | |
| 122 | 184 | |
| 123 | 185 | *data_len = ehdr_size + hash_size; |
| 124 | 186 | |
| @@ -126,23 +188,85 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len) · 1 unmodified line | ||
| 126 | 188 | } |
| 127 | 189 | EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata); |
| 128 | 190 | |
| 191 | +/** | |
| 192 | + * qcom_mdt_pas_init() - initialize PAS region for firmware loading | |
| 193 | + * @dev: device handle to associate resources with | |
| 194 | + * @fw: firmware object for the mdt file | |
| 195 | + * @firmware: name of the firmware, for construction of segment file names | |
| 196 | + * @pas_id: PAS identifier | |
| 197 | + * @mem_phys: physical address of allocated memory region | |
| 198 | + * @ctx: PAS metadata context, to be released by caller | |
| 199 | + * | |
| 200 | + * Returns 0 on success, negative errno otherwise. | |
| 201 | + */ | |
| 202 | +int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, | |
| 203 | + const char *fw_name, int pas_id, phys_addr_t mem_phys, | |
| 204 | + struct qcom_scm_pas_metadata *ctx) | |
| 205 | +{ | |
| 206 | + const struct elf32_phdr *phdrs; | |
| 207 | + const struct elf32_phdr *phdr; | |
| 208 | + const struct elf32_hdr *ehdr; | |
| 209 | + phys_addr_t min_addr = PHYS_ADDR_MAX; | |
| 210 | + phys_addr_t max_addr = 0; | |
| 211 | + size_t metadata_len; | |
| 212 | + void *metadata; | |
| 213 | + int ret; | |
| 214 | + int i; | |
| 215 | + | |
| 216 | + ehdr = (struct elf32_hdr *)fw->data; | |
| 217 | + phdrs = (struct elf32_phdr *)(ehdr + 1); | |
| 218 | + | |
| 219 | + for (i = 0; i < ehdr->e_phnum; i++) { | |
| 220 | + phdr = &phdrs[i]; | |
| 221 | + | |
| 222 | + if (!mdt_phdr_valid(phdr)) | |
| 223 | + continue; | |
| 224 | + | |
| 225 | + if (phdr->p_paddr < min_addr) | |
| 226 | + min_addr = phdr->p_paddr; | |
| 227 | + | |
| 228 | + if (phdr->p_paddr + phdr->p_memsz > max_addr) | |
| 229 | + max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K); | |
| 230 | + } | |
| 231 | + | |
| 232 | + metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev); | |
| 233 | + if (IS_ERR(metadata)) { | |
| 234 | + ret = PTR_ERR(metadata); | |
| 235 | + dev_err(dev, "error %d reading firmware %s metadata\n", ret, fw_name); | |
| 236 | + goto out; | |
| 237 | + } | |
| 238 | + | |
| 239 | + ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, ctx); | |
| 240 | + kfree(metadata); | |
| 241 | + if (ret) { | |
| 242 | + /* Invalid firmware metadata */ | |
| 243 | + dev_err(dev, "error %d initializing firmware %s\n", ret, fw_name); | |
| 244 | + goto out; | |
| 245 | + } | |
| 246 | + | |
| 247 | + ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); | |
| 248 | + if (ret) { | |
| 249 | + /* Unable to set up relocation */ | |
| 250 | + dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name); | |
| 251 | + goto out; | |
| 252 | + } | |
| 253 | + | |
| 254 | +out: | |
| 255 | + return ret; | |
| 256 | +} | |
| 257 | +EXPORT_SYMBOL_GPL(qcom_mdt_pas_init); | |
| 258 | + | |
| 129 | 259 | static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, |
| 130 | − const char *firmware, int pas_id, void *mem_region, | |
| 260 | + const char *fw_name, int pas_id, void *mem_region, | |
| 131 | 261 | phys_addr_t mem_phys, size_t mem_size, |
| 132 | 262 | phys_addr_t *reloc_base, bool pas_init) |
| 133 | 263 | { |
| 134 | 264 | const struct elf32_phdr *phdrs; |
| 135 | 265 | const struct elf32_phdr *phdr; |
| 136 | 266 | const struct elf32_hdr *ehdr; |
| 137 | − const struct firmware *seg_fw; | |
| 138 | 267 | phys_addr_t mem_reloc; |
| 139 | 268 | phys_addr_t min_addr = PHYS_ADDR_MAX; |
| 140 | − phys_addr_t max_addr = 0; | |
| 141 | − size_t metadata_len; | |
| 142 | − size_t fw_name_len; | |
| 143 | 269 | ssize_t offset; |
| 144 | − void *metadata; | |
| 145 | − char *fw_name; | |
| 146 | 270 | bool relocate = false; |
| 147 | 271 | void *ptr; |
| 148 | 272 | int ret = 0; |
| @@ -154,34 +278,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, · 5 unmodified lines | ||
| 154 | 278 | ehdr = (struct elf32_hdr *)fw->data; |
| 155 | 279 | phdrs = (struct elf32_phdr *)(ehdr + 1); |
| 156 | 280 | |
| 157 | − fw_name_len = strlen(firmware); | |
| 158 | − if (fw_name_len <= 4) | |
| 159 | − return -EINVAL; | |
| 160 | − | |
| 161 | − fw_name = kstrdup(firmware, GFP_KERNEL); | |
| 162 | − if (!fw_name) | |
| 163 | − return -ENOMEM; | |
| 164 | − | |
| 165 | − if (pas_init) { | |
| 166 | − metadata = qcom_mdt_read_metadata(fw, &metadata_len); | |
| 167 | − if (IS_ERR(metadata)) { | |
| 168 | − ret = PTR_ERR(metadata); | |
| 169 | − dev_err(dev, "error %d reading firmware %s metadata\n", | |
| 170 | − ret, fw_name); | |
| 171 | − goto out; | |
| 172 | − } | |
| 173 | − | |
| 174 | − ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len); | |
| 175 | − | |
| 176 | − kfree(metadata); | |
| 177 | − if (ret) { | |
| 178 | − /* Invalid firmware metadata */ | |
| 179 | − dev_err(dev, "error %d initializing firmware %s\n", | |
| 180 | − ret, fw_name); | |
| 181 | − goto out; | |
| 182 | − } | |
| 183 | − } | |
| 184 | − | |
| 185 | 281 | for (i = 0; i < ehdr->e_phnum; i++) { |
| 186 | 282 | phdr = &phdrs[i]; |
| 187 | 283 | |
| @@ -193,23 +289,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, · 5 unmodified lines | ||
| 193 | 289 | |
| 194 | 290 | if (phdr->p_paddr < min_addr) |
| 195 | 291 | min_addr = phdr->p_paddr; |
| 196 | − | |
| 197 | − if (phdr->p_paddr + phdr->p_memsz > max_addr) | |
| 198 | − max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K); | |
| 199 | 292 | } |
| 200 | 293 | |
| 201 | 294 | if (relocate) { |
| 202 | − if (pas_init) { | |
| 203 | − ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, | |
| 204 | − max_addr - min_addr); | |
| 205 | − if (ret) { | |
| 206 | − /* Unable to set up relocation */ | |
| 207 | − dev_err(dev, "error %d setting up firmware %s\n", | |
| 208 | − ret, fw_name); | |
| 209 | − goto out; | |
| 210 | − } | |
| 211 | − } | |
| 212 | − | |
| 213 | 295 | /* |
| 214 | 296 | * The image is relocatable, so offset each segment based on |
| 215 | 297 | * the lowest segment address. |
| @@ -246,7 +328,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, · 30 unmodified lines | ||
| 246 | 328 | |
| 247 | 329 | ptr = mem_region + offset; |
| 248 | 330 | |
| 249 | − if (phdr->p_filesz && phdr->p_offset < fw->size) { | |
| 331 | + if (phdr->p_filesz && phdr->p_offset < fw->size && | |
| 332 | + phdr->p_offset + phdr->p_filesz <= fw->size) { | |
| 250 | 333 | /* Firmware is large enough to be non-split */ |
| 251 | 334 | if (phdr->p_offset + phdr->p_filesz > fw->size) { |
| 252 | 335 | dev_err(dev, "file %s segment %d would be truncated\n", |
| @@ -258,25 +341,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, · 5 unmodified lines | ||
| 258 | 341 | memcpy(ptr, fw->data + phdr->p_offset, phdr->p_filesz); |
| 259 | 342 | } else if (phdr->p_filesz) { |
| 260 | 343 | /* Firmware not large enough, load split-out segments */ |
| 261 | − sprintf(fw_name + fw_name_len - 3, "b%02d", i); | |
| 262 | − ret = request_firmware_into_buf(&seg_fw, fw_name, dev, | |
| 263 | − ptr, phdr->p_filesz); | |
| 264 | − if (ret) { | |
| 265 | − dev_err(dev, "error %d loading %s\n", | |
| 266 | − ret, fw_name); | |
| 267 | − break; | |
| 268 | − } | |
| 269 | − | |
| 270 | − if (seg_fw->size != phdr->p_filesz) { | |
| 271 | − dev_err(dev, | |
| 272 | − "failed to load segment %d from truncated file %s\n", | |
| 273 | − i, fw_name); | |
| 274 | − release_firmware(seg_fw); | |
| 275 | − ret = -EINVAL; | |
| 344 | + ret = mdt_load_split_segment(ptr, phdrs, i, fw_name, dev); | |
| 345 | + if (ret) | |
| 276 | 346 | break; |
| 277 | − } | |
| 278 | − | |
| 279 | − release_firmware(seg_fw); | |
| 280 | 347 | } |
| 281 | 348 | |
| 282 | 349 | if (phdr->p_memsz > phdr->p_filesz) |
| @@ -286,9 +353,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, · 3 unmodified lines | ||
| 286 | 353 | if (reloc_base) |
| 287 | 354 | *reloc_base = mem_reloc; |
| 288 | 355 | |
| 289 | −out: | |
| 290 | − kfree(fw_name); | |
| 291 | − | |
| 292 | 356 | return ret; |
| 293 | 357 | } |
| 294 | 358 | |
| @@ -310,6 +374,12 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw, · 15 unmodified lines | ||
| 310 | 374 | phys_addr_t mem_phys, size_t mem_size, |
| 311 | 375 | phys_addr_t *reloc_base) |
| 312 | 376 | { |
| 377 | + int ret; | |
| 378 | + | |
| 379 | + ret = qcom_mdt_pas_init(dev, fw, firmware, pas_id, mem_phys, NULL); | |
| 380 | + if (ret) | |
| 381 | + return ret; | |
| 382 | + | |
| 313 | 383 | return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys, |
| 314 | 384 | mem_size, reloc_base, true); |
| 315 | 385 | } |
| @@ -206,6 +206,7 @@ struct ocmem *of_get_ocmem(struct device *dev) · 205 unmodified lines | ||
| 206 | 206 | ocmem = platform_get_drvdata(pdev); |
| 207 | 207 | if (!ocmem) { |
| 208 | 208 | dev_err(dev, "Cannot get ocmem\n"); |
| 209 | + put_device(&pdev->dev); | |
| 209 | 210 | return ERR_PTR(-ENODEV); |
| 210 | 211 | } |
| 211 | 212 | return ocmem; |
| @@ -451,7 +451,11 @@ struct qmp *qmp_get(struct device *dev) · 450 unmodified lines | ||
| 451 | 451 | |
| 452 | 452 | qmp = platform_get_drvdata(pdev); |
| 453 | 453 | |
| 454 | − return qmp ? qmp : ERR_PTR(-EPROBE_DEFER); | |
| 454 | + if (!qmp) { | |
| 455 | + put_device(&pdev->dev); | |
| 456 | + return ERR_PTR(-EPROBE_DEFER); | |
| 457 | + } | |
| 458 | + return qmp; | |
| 455 | 459 | } |
| 456 | 460 | EXPORT_SYMBOL(qmp_get); |
| 457 | 461 | |
| @@ -497,7 +501,7 @@ static int qmp_probe(struct platform_device *pdev) · 39 unmodified lines | ||
| 497 | 501 | } |
| 498 | 502 | |
| 499 | 503 | irq = platform_get_irq(pdev, 0); |
| 500 | − ret = devm_request_irq(&pdev->dev, irq, qmp_intr, IRQF_ONESHOT, | |
| 504 | + ret = devm_request_irq(&pdev->dev, irq, qmp_intr, 0, | |
| 501 | 505 | "aoss-qmp", qmp); |
| 502 | 506 | if (ret < 0) { |
| 503 | 507 | dev_err(&pdev->dev, "failed to request interrupt\n"); |
| @@ -138,6 +138,22 @@ static const struct rpmpd_desc mdm9607_desc = { · 137 unmodified lines | ||
| 138 | 138 | .max_state = RPM_SMD_LEVEL_TURBO, |
| 139 | 139 | }; |
| 140 | 140 | |
| 141 | +/* msm8226 RPM Power Domains */ | |
| 142 | +DEFINE_RPMPD_PAIR(msm8226, vddcx, vddcx_ao, SMPA, CORNER, 1); | |
| 143 | +DEFINE_RPMPD_VFC(msm8226, vddcx_vfc, SMPA, 1); | |
| 144 | + | |
| 145 | +static struct rpmpd *msm8226_rpmpds[] = { | |
| 146 | + [MSM8226_VDDCX] = &msm8226_vddcx, | |
| 147 | + [MSM8226_VDDCX_AO] = &msm8226_vddcx_ao, | |
| 148 | + [MSM8226_VDDCX_VFC] = &msm8226_vddcx_vfc, | |
| 149 | +}; | |
| 150 | + | |
| 151 | +static const struct rpmpd_desc msm8226_desc = { | |
| 152 | + .rpmpds = msm8226_rpmpds, | |
| 153 | + .num_pds = ARRAY_SIZE(msm8226_rpmpds), | |
| 154 | + .max_state = MAX_CORNER_RPMPD_STATE, | |
| 155 | +}; | |
| 156 | + | |
| 141 | 157 | /* msm8939 RPM Power Domains */ |
| 142 | 158 | DEFINE_RPMPD_PAIR(msm8939, vddmd, vddmd_ao, SMPA, CORNER, 1); |
| 143 | 159 | DEFINE_RPMPD_VFC(msm8939, vddmd_vfc, SMPA, 1); |
| @@ -436,6 +452,7 @@ static const struct rpmpd_desc qcm2290_desc = { · 292 unmodified lines | ||
| 436 | 452 | |
| 437 | 453 | static const struct of_device_id rpmpd_match_table[] = { |
| 438 | 454 | { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc }, |
| 455 | + { .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc }, | |
| 439 | 456 | { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc }, |
| 440 | 457 | { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc }, |
| 441 | 458 | { .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc }, |
| @@ -610,6 +627,9 @@ static int rpmpd_probe(struct platform_device *pdev) · 168 unmodified lines | ||
| 610 | 627 | |
| 611 | 628 | data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains), |
| 612 | 629 | GFP_KERNEL); |
| 630 | + if (!data->domains) | |
| 631 | + return -ENOMEM; | |
| 632 | + | |
| 613 | 633 | data->num_domains = num; |
| 614 | 634 | |
| 615 | 635 | for (i = 0; i < num; i++) { |
| @@ -104,6 +104,14 @@ static const char *const pmic_models[] = { · 103 unmodified lines | ||
| 104 | 104 | [36] = "PM8009", |
| 105 | 105 | [38] = "PM8150C", |
| 106 | 106 | [41] = "SMB2351", |
| 107 | + [47] = "PMK8350", | |
| 108 | + [48] = "PM8350", | |
| 109 | + [49] = "PM8350C", | |
| 110 | + [50] = "PM8350B", | |
| 111 | + [51] = "PMR735A", | |
| 112 | + [52] = "PMR735B", | |
| 113 | + [58] = "PM8450", | |
| 114 | + [65] = "PM8010", | |
| 107 | 115 | }; |
| 108 | 116 | #endif /* CONFIG_DEBUG_FS */ |
| 109 | 117 | |
| @@ -314,10 +322,14 @@ static const struct soc_id soc_id[] = { · 204 unmodified lines | ||
| 314 | 322 | { 422, "IPQ6010" }, |
| 315 | 323 | { 425, "SC7180" }, |
| 316 | 324 | { 434, "SM6350" }, |
| 325 | + { 439, "SM8350" }, | |
| 326 | + { 449, "SC8280XP" }, | |
| 317 | 327 | { 453, "IPQ6005" }, |
| 318 | 328 | { 455, "QRB5165" }, |
| 319 | 329 | { 457, "SM8450" }, |
| 320 | 330 | { 459, "SM7225" }, |
| 331 | + { 460, "SA8540P" }, | |
| 332 | + { 480, "SM8450" }, | |
| 321 | 333 | }; |
| 322 | 334 | |
| 323 | 335 | static const char *socinfo_machine(struct device *dev, unsigned int id) |
| @@ -40,6 +40,11 @@ config ARCH_RMOBILE · 39 unmodified lines | ||
| 40 | 40 | select SYS_SUPPORTS_SH_TMU |
| 41 | 41 | select SYSC_RMOBILE |
| 42 | 42 | |
| 43 | +config ARCH_RZG2L | |
| 44 | + bool | |
| 45 | + select PM | |
| 46 | + select PM_GENERIC_DOMAINS | |
| 47 | + | |
| 43 | 48 | config ARCH_RZN1 |
| 44 | 49 | bool |
| 45 | 50 | select ARM_AMBA |
| @@ -293,9 +298,16 @@ config ARCH_R8A774B1 · 247 unmodified lines | ||
| 293 | 298 | |
| 294 | 299 | config ARCH_R9A07G044 |
| 295 | 300 | bool "ARM64 Platform support for RZ/G2L" |
| 301 | + select ARCH_RZG2L | |
| 296 | 302 | help |
| 297 | 303 | This enables support for the Renesas RZ/G2L SoC variants. |
| 298 | 304 | |
| 305 | +config ARCH_R9A07G054 | |
| 306 | + bool "ARM64 Platform support for RZ/V2L" | |
| 307 | + select ARCH_RZG2L | |
| 308 | + help | |
| 309 | + This enables support for the Renesas RZ/V2L SoC variants. | |
| 310 | + | |
| 299 | 311 | endif # ARM64 |
| 300 | 312 | |
| 301 | 313 | config RST_RCAR |
| @@ -64,6 +64,10 @@ static const struct renesas_family fam_rzg2l __initconst __maybe_unused = { · 63 unmodified lines | ||
| 64 | 64 | .name = "RZ/G2L", |
| 65 | 65 | }; |
| 66 | 66 | |
| 67 | +static const struct renesas_family fam_rzv2l __initconst __maybe_unused = { | |
| 68 | + .name = "RZ/V2L", | |
| 69 | +}; | |
| 70 | + | |
| 67 | 71 | static const struct renesas_family fam_shmobile __initconst __maybe_unused = { |
| 68 | 72 | .name = "SH-Mobile", |
| 69 | 73 | .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */ |
| @@ -144,6 +148,11 @@ static const struct renesas_soc soc_rz_g2l __initconst __maybe_unused = { · 74 unmodified lines | ||
| 144 | 148 | .id = 0x841c447, |
| 145 | 149 | }; |
| 146 | 150 | |
| 151 | +static const struct renesas_soc soc_rz_v2l __initconst __maybe_unused = { | |
| 152 | + .family = &fam_rzv2l, | |
| 153 | + .id = 0x8447447, | |
| 154 | +}; | |
| 155 | + | |
| 147 | 156 | static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = { |
| 148 | 157 | .family = &fam_rcar_gen1, |
| 149 | 158 | }; |
| @@ -334,6 +343,9 @@ static const struct of_device_id renesas_socs[] __initconst = { · 184 unmodified lines | ||
| 334 | 343 | #if defined(CONFIG_ARCH_R9A07G044) |
| 335 | 344 | { .compatible = "renesas,r9a07g044", .data = &soc_rz_g2l }, |
| 336 | 345 | #endif |
| 346 | +#if defined(CONFIG_ARCH_R9A07G054) | |
| 347 | + { .compatible = "renesas,r9a07g054", .data = &soc_rz_v2l }, | |
| 348 | +#endif | |
| 337 | 349 | #ifdef CONFIG_ARCH_SH73A0 |
| 338 | 350 | { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 }, |
| 339 | 351 | #endif |
| @@ -367,6 +379,7 @@ static const struct renesas_id id_prr __initconst = { · 27 unmodified lines | ||
| 367 | 379 | static const struct of_device_id renesas_ids[] __initconst = { |
| 368 | 380 | { .compatible = "renesas,bsid", .data = &id_bsid }, |
| 369 | 381 | { .compatible = "renesas,r9a07g044-sysc", .data = &id_rzg2l }, |
| 382 | + { .compatible = "renesas,r9a07g054-sysc", .data = &id_rzg2l }, | |
| 370 | 383 | { .compatible = "renesas,prr", .data = &id_prr }, |
| 371 | 384 | { /* sentinel */ } |
| 372 | 385 | }; |
| @@ -380,9 +393,11 @@ static int __init renesas_soc_init(void) · 7 unmodified lines | ||
| 380 | 393 | const struct renesas_soc *soc; |
| 381 | 394 | const struct renesas_id *id; |
| 382 | 395 | void __iomem *chipid = NULL; |
| 396 | + const char *rev_prefix = ""; | |
| 383 | 397 | struct soc_device *soc_dev; |
| 384 | 398 | struct device_node *np; |
| 385 | 399 | const char *soc_id; |
| 400 | + int ret; | |
| 386 | 401 | |
| 387 | 402 | match = of_match_node(renesas_socs, of_root); |
| 388 | 403 | if (!match) |
| @@ -403,6 +418,17 @@ static int __init renesas_soc_init(void) · 14 unmodified lines | ||
| 403 | 418 | chipid = ioremap(family->reg, 4); |
| 404 | 419 | } |
| 405 | 420 | |
| 421 | + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | |
| 422 | + if (!soc_dev_attr) | |
| 423 | + return -ENOMEM; | |
| 424 | + | |
| 425 | + np = of_find_node_by_path("/"); | |
| 426 | + of_property_read_string(np, "model", &soc_dev_attr->machine); | |
| 427 | + of_node_put(np); | |
| 428 | + | |
| 429 | + soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL); | |
| 430 | + soc_dev_attr->soc_id = kstrdup_const(soc_id, GFP_KERNEL); | |
| 431 | + | |
| 406 | 432 | if (chipid) { |
| 407 | 433 | product = readl(chipid + id->offset); |
| 408 | 434 | iounmap(chipid); |
| @@ -417,41 +443,39 @@ static int __init renesas_soc_init(void) · 8 unmodified lines | ||
| 417 | 443 | |
| 418 | 444 | eshi = ((product >> 4) & 0x0f) + 1; |
| 419 | 445 | eslo = product & 0xf; |
| 446 | + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", | |
| 447 | + eshi, eslo); | |
| 448 | + } else if (id == &id_rzg2l) { | |
| 449 | + eshi = ((product >> 28) & 0x0f); | |
| 450 | + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u", | |
| 451 | + eshi); | |
| 452 | + rev_prefix = "Rev "; | |
| 420 | 453 | } |
| 421 | 454 | |
| 422 | 455 | if (soc->id && |
| 423 | 456 | ((product & id->mask) >> __ffs(id->mask)) != soc->id) { |
| 424 | 457 | pr_warn("SoC mismatch (product = 0x%x)\n", product); |
| 425 | − return -ENODEV; | |
| 458 | + ret = -ENODEV; | |
| 459 | + goto free_soc_dev_attr; | |
| 426 | 460 | } |
| 427 | 461 | } |
| 428 | 462 | |
| 429 | − soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | |
| 430 | − if (!soc_dev_attr) | |
| 431 | − return -ENOMEM; | |
| 432 | − | |
| 433 | − np = of_find_node_by_path("/"); | |
| 434 | − of_property_read_string(np, "model", &soc_dev_attr->machine); | |
| 435 | − of_node_put(np); | |
| 436 | − | |
| 437 | − soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL); | |
| 438 | − soc_dev_attr->soc_id = kstrdup_const(soc_id, GFP_KERNEL); | |
| 439 | − if (eshi) | |
| 440 | − soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", eshi, | |
| 441 | − eslo); | |
| 442 | − | |
| 443 | − pr_info("Detected Renesas %s %s %s\n", soc_dev_attr->family, | |
| 444 | − soc_dev_attr->soc_id, soc_dev_attr->revision ?: ""); | |
| 463 | + pr_info("Detected Renesas %s %s %s%s\n", soc_dev_attr->family, | |
| 464 | + soc_dev_attr->soc_id, rev_prefix, soc_dev_attr->revision ?: ""); | |
| 445 | 465 | |
| 446 | 466 | soc_dev = soc_device_register(soc_dev_attr); |
| 447 | 467 | if (IS_ERR(soc_dev)) { |
| 448 | − kfree(soc_dev_attr->revision); | |
| 449 | − kfree_const(soc_dev_attr->soc_id); | |
| 450 | − kfree_const(soc_dev_attr->family); | |
| 451 | − kfree(soc_dev_attr); | |
| 452 | − return PTR_ERR(soc_dev); | |
| 468 | + ret = PTR_ERR(soc_dev); | |
| 469 | + goto free_soc_dev_attr; | |
| 453 | 470 | } |
| 454 | 471 | |
| 455 | 472 | return 0; |
| 473 | + | |
| 474 | +free_soc_dev_attr: | |
| 475 | + kfree(soc_dev_attr->revision); | |
| 476 | + kfree_const(soc_dev_attr->soc_id); | |
| 477 | + kfree_const(soc_dev_attr->family); | |
| 478 | + kfree(soc_dev_attr); | |
| 479 | + return ret; | |
| 456 | 480 | } |
| 457 | 481 | early_initcall(renesas_soc_init); |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | 2 | /* |
| 3 | − * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. | |
| 3 | + * Copyright (c) 2013-2021, NVIDIA CORPORATION. All rights reserved. | |
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | 6 | #include <linux/clk.h> |
| @@ -161,6 +161,12 @@ static const struct nvmem_cell_info tegra_fuse_cells[] = { · 154 unmodified lines | ||
| 161 | 161 | .bytes = 4, |
| 162 | 162 | .bit_offset = 0, |
| 163 | 163 | .nbits = 32, |
| 164 | + }, { | |
| 165 | + .name = "gcplex-config-fuse", | |
| 166 | + .offset = 0x1c8, | |
| 167 | + .bytes = 4, | |
| 168 | + .bit_offset = 0, | |
| 169 | + .nbits = 32, | |
| 164 | 170 | }, { |
| 165 | 171 | .name = "tsensor-realignment", |
| 166 | 172 | .offset = 0x1fc, |
| @@ -179,13 +185,25 @@ static const struct nvmem_cell_info tegra_fuse_cells[] = { · 12 unmodified lines | ||
| 179 | 185 | .bytes = 4, |
| 180 | 186 | .bit_offset = 0, |
| 181 | 187 | .nbits = 32, |
| 188 | + }, { | |
| 189 | + .name = "pdi0", | |
| 190 | + .offset = 0x300, | |
| 191 | + .bytes = 4, | |
| 192 | + .bit_offset = 0, | |
| 193 | + .nbits = 32, | |
| 194 | + }, { | |
| 195 | + .name = "pdi1", | |
| 196 | + .offset = 0x304, | |
| 197 | + .bytes = 4, | |
| 198 | + .bit_offset = 0, | |
| 199 | + .nbits = 32, | |
| 182 | 200 | }, |
| 183 | 201 | }; |
| 184 | 202 | |
| 185 | 203 | static void tegra_fuse_restore(void *base) |
| 186 | 204 | { |
| 205 | + fuse->base = (void __iomem *)base; | |
| 187 | 206 | fuse->clk = NULL; |
| 188 | − fuse->base = base; | |
| 189 | 207 | } |
| 190 | 208 | |
| 191 | 209 | static int tegra_fuse_probe(struct platform_device *pdev) |
| @@ -195,7 +213,7 @@ static int tegra_fuse_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 195 | 213 | struct resource *res; |
| 196 | 214 | int err; |
| 197 | 215 | |
| 198 | − err = devm_add_action(&pdev->dev, tegra_fuse_restore, base); | |
| 216 | + err = devm_add_action(&pdev->dev, tegra_fuse_restore, (void __force *)base); | |
| 199 | 217 | if (err) |
| 200 | 218 | return err; |
| 201 | 219 | |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | * drivers/soc/tegra/pmc.c |
| 4 | 4 | * |
| 5 | 5 | * Copyright (c) 2010 Google, Inc |
| 6 | − * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved. | |
| 6 | + * Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved. | |
| 7 | 7 | * |
| 8 | 8 | * Author: |
| 9 | 9 | * Colin Cross <ccross@google.com> |
| @@ -54,6 +54,7 @@ · 44 unmodified lines | ||
| 54 | 54 | #include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h> |
| 55 | 55 | #include <dt-bindings/gpio/tegra186-gpio.h> |
| 56 | 56 | #include <dt-bindings/gpio/tegra194-gpio.h> |
| 57 | +#include <dt-bindings/gpio/tegra234-gpio.h> | |
| 57 | 58 | #include <dt-bindings/soc/tegra-pmc.h> |
| 58 | 59 | |
| 59 | 60 | #define PMC_CNTRL 0x0 |
| @@ -3066,7 +3067,7 @@ static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc, · 3006 unmodified lines | ||
| 3066 | 3067 | } |
| 3067 | 3068 | |
| 3068 | 3069 | static const struct tegra_pmc_soc tegra20_pmc_soc = { |
| 3069 | − .supports_core_domain = false, | |
| 3070 | + .supports_core_domain = true, | |
| 3070 | 3071 | .num_powergates = ARRAY_SIZE(tegra20_powergates), |
| 3071 | 3072 | .powergates = tegra20_powergates, |
| 3072 | 3073 | .num_cpu_powergates = 0, |
| @@ -3127,7 +3128,7 @@ static const char * const tegra30_reset_sources[] = { · 54 unmodified lines | ||
| 3127 | 3128 | }; |
| 3128 | 3129 | |
| 3129 | 3130 | static const struct tegra_pmc_soc tegra30_pmc_soc = { |
| 3130 | − .supports_core_domain = false, | |
| 3131 | + .supports_core_domain = true, | |
| 3131 | 3132 | .num_powergates = ARRAY_SIZE(tegra30_powergates), |
| 3132 | 3133 | .powergates = tegra30_powergates, |
| 3133 | 3134 | .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates), |
| @@ -3788,6 +3789,11 @@ static const char * const tegra234_reset_sources[] = { · 654 unmodified lines | ||
| 3788 | 3789 | "FUSECRC", |
| 3789 | 3790 | }; |
| 3790 | 3791 | |
| 3792 | +static const struct tegra_wake_event tegra234_wake_events[] = { | |
| 3793 | + TEGRA_WAKE_GPIO("power", 29, 1, TEGRA234_AON_GPIO(EE, 4)), | |
| 3794 | + TEGRA_WAKE_IRQ("rtc", 73, 10), | |
| 3795 | +}; | |
| 3796 | + | |
| 3791 | 3797 | static const struct tegra_pmc_soc tegra234_pmc_soc = { |
| 3792 | 3798 | .supports_core_domain = false, |
| 3793 | 3799 | .num_powergates = 0, |
| @@ -3812,8 +3818,8 @@ static const struct tegra_pmc_soc tegra234_pmc_soc = { · 18 unmodified lines | ||
| 3812 | 3818 | .num_reset_sources = ARRAY_SIZE(tegra234_reset_sources), |
| 3813 | 3819 | .reset_levels = tegra186_reset_levels, |
| 3814 | 3820 | .num_reset_levels = ARRAY_SIZE(tegra186_reset_levels), |
| 3815 | − .num_wake_events = 0, | |
| 3816 | − .wake_events = NULL, | |
| 3821 | + .num_wake_events = ARRAY_SIZE(tegra234_wake_events), | |
| 3822 | + .wake_events = tegra234_wake_events, | |
| 3817 | 3823 | .pmc_clks_data = NULL, |
| 3818 | 3824 | .num_pmc_clks = 0, |
| 3819 | 3825 | .has_blink_output = false, |
| @@ -1402,12 +1402,10 @@ static int k3_ringacc_init(struct platform_device *pdev, · 1401 unmodified lines | ||
| 1402 | 1402 | sizeof(*ringacc->rings) * |
| 1403 | 1403 | ringacc->num_rings, |
| 1404 | 1404 | GFP_KERNEL); |
| 1405 | − ringacc->rings_inuse = devm_kcalloc(dev, | |
| 1406 | − BITS_TO_LONGS(ringacc->num_rings), | |
| 1407 | − sizeof(unsigned long), GFP_KERNEL); | |
| 1408 | − ringacc->proxy_inuse = devm_kcalloc(dev, | |
| 1409 | − BITS_TO_LONGS(ringacc->num_proxies), | |
| 1410 | − sizeof(unsigned long), GFP_KERNEL); | |
| 1405 | + ringacc->rings_inuse = devm_bitmap_zalloc(dev, ringacc->num_rings, | |
| 1406 | + GFP_KERNEL); | |
| 1407 | + ringacc->proxy_inuse = devm_bitmap_zalloc(dev, ringacc->num_proxies, | |
| 1408 | + GFP_KERNEL); | |
| 1411 | 1409 | |
| 1412 | 1410 | if (!ringacc->rings || !ringacc->rings_inuse || !ringacc->proxy_inuse) |
| 1413 | 1411 | return -ENOMEM; |
| @@ -1483,9 +1481,8 @@ struct k3_ringacc *k3_ringacc_dmarings_init(struct platform_device *pdev, · 69 unmodified lines | ||
| 1483 | 1481 | sizeof(*ringacc->rings) * |
| 1484 | 1482 | ringacc->num_rings * 2, |
| 1485 | 1483 | GFP_KERNEL); |
| 1486 | − ringacc->rings_inuse = devm_kcalloc(dev, | |
| 1487 | − BITS_TO_LONGS(ringacc->num_rings), | |
| 1488 | − sizeof(unsigned long), GFP_KERNEL); | |
| 1484 | + ringacc->rings_inuse = devm_bitmap_zalloc(dev, ringacc->num_rings, | |
| 1485 | + GFP_KERNEL); | |
| 1489 | 1486 | |
| 1490 | 1487 | if (!ringacc->rings || !ringacc->rings_inuse) |
| 1491 | 1488 | return ERR_PTR(-ENOMEM); |
| @@ -42,6 +42,7 @@ static const struct k3_soc_id { · 41 unmodified lines | ||
| 42 | 42 | { 0xBB6D, "J7200" }, |
| 43 | 43 | { 0xBB38, "AM64X" }, |
| 44 | 44 | { 0xBB75, "J721S2"}, |
| 45 | + { 0xBB7E, "AM62X" }, | |
| 45 | 46 | }; |
| 46 | 47 | |
| 47 | 48 | static int |
| @@ -819,7 +819,7 @@ static int omap_sr_probe(struct platform_device *pdev) · 818 unmodified lines | ||
| 819 | 819 | { |
| 820 | 820 | struct omap_sr *sr_info; |
| 821 | 821 | struct omap_sr_data *pdata = pdev->dev.platform_data; |
| 822 | − struct resource *mem, *irq; | |
| 822 | + struct resource *mem; | |
| 823 | 823 | struct dentry *nvalue_dir; |
| 824 | 824 | int i, ret = 0; |
| 825 | 825 | |
| @@ -844,7 +844,11 @@ static int omap_sr_probe(struct platform_device *pdev) · 18 unmodified lines | ||
| 844 | 844 | if (IS_ERR(sr_info->base)) |
| 845 | 845 | return PTR_ERR(sr_info->base); |
| 846 | 846 | |
| 847 | − irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
| 847 | + ret = platform_get_irq_optional(pdev, 0); | |
| 848 | + if (ret < 0 && ret != -ENXIO) | |
| 849 | + return dev_err_probe(&pdev->dev, ret, "failed to get IRQ resource\n"); | |
| 850 | + if (ret > 0) | |
| 851 | + sr_info->irq = ret; | |
| 848 | 852 | |
| 849 | 853 | sr_info->fck = devm_clk_get(pdev->dev.parent, "fck"); |
| 850 | 854 | if (IS_ERR(sr_info->fck)) |
| @@ -870,9 +874,6 @@ static int omap_sr_probe(struct platform_device *pdev) · 19 unmodified lines | ||
| 870 | 874 | sr_info->autocomp_active = false; |
| 871 | 875 | sr_info->ip_type = pdata->ip_type; |
| 872 | 876 | |
| 873 | − if (irq) | |
| 874 | − sr_info->irq = irq->start; | |
| 875 | − | |
| 876 | 877 | sr_set_clk_length(sr_info); |
| 877 | 878 | |
| 878 | 879 | list_add(&sr_info->node, &sr_list); |
| @@ -926,7 +927,7 @@ static int omap_sr_probe(struct platform_device *pdev) · 47 unmodified lines | ||
| 926 | 927 | |
| 927 | 928 | } |
| 928 | 929 | |
| 929 | − return ret; | |
| 930 | + return 0; | |
| 930 | 931 | |
| 931 | 932 | err_debugfs: |
| 932 | 933 | debugfs_remove_recursive(sr_info->dbg_dir); |
| @@ -450,9 +450,9 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev) · 449 unmodified lines | ||
| 450 | 450 | return PTR_ERR(m3_ipc->ipc_mem_base); |
| 451 | 451 | |
| 452 | 452 | irq = platform_get_irq(pdev, 0); |
| 453 | − if (!irq) { | |
| 453 | + if (irq < 0) { | |
| 454 | 454 | dev_err(&pdev->dev, "no irq resource\n"); |
| 455 | − return -ENXIO; | |
| 455 | + return irq; | |
| 456 | 456 | } |
| 457 | 457 | |
| 458 | 458 | ret = devm_request_irq(dev, irq, wkup_m3_txev_handler, |
| @@ -122,7 +122,7 @@ static int amd_params_to_tee_params(struct tee_param *tee, u32 count, · 121 unmodified lines | ||
| 122 | 122 | } |
| 123 | 123 | |
| 124 | 124 | static DEFINE_MUTEX(ta_refcount_mutex); |
| 125 | −static struct list_head ta_list = LIST_HEAD_INIT(ta_list); | |
| 125 | +static LIST_HEAD(ta_list); | |
| 126 | 126 | |
| 127 | 127 | static u32 get_ta_refcount(u32 ta_handle) |
| 128 | 128 | { |
| @@ -8,13 +8,17 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <linux/psp-sev.h> |
| 9 | 9 | #include "amdtee_private.h" |
| 10 | 10 | |
| 11 | −static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm, | |
| 12 | − size_t size) | |
| 11 | +static int pool_op_alloc(struct tee_shm_pool *pool, struct tee_shm *shm, | |
| 12 | + size_t size, size_t align) | |
| 13 | 13 | { |
| 14 | 14 | unsigned int order = get_order(size); |
| 15 | 15 | unsigned long va; |
| 16 | 16 | int rc; |
| 17 | 17 | |
| 18 | + /* | |
| 19 | + * Ignore alignment since this is already going to be page aligned | |
| 20 | + * and there's no need for any larger alignment. | |
| 21 | + */ | |
| 18 | 22 | va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order); |
| 19 | 23 | if (!va) |
| 20 | 24 | return -ENOMEM; |
| @@ -34,7 +38,7 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm, · 13 unmodified lines | ||
| 34 | 38 | return 0; |
| 35 | 39 | } |
| 36 | 40 | |
| 37 | −static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm) | |
| 41 | +static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm) | |
| 38 | 42 | { |
| 39 | 43 | /* Unmap the shared memory from TEE */ |
| 40 | 44 | amdtee_unmap_shmem(shm); |
| @@ -42,52 +46,25 @@ static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm) · 1 unmodified line | ||
| 42 | 46 | shm->kaddr = NULL; |
| 43 | 47 | } |
| 44 | 48 | |
| 45 | −static void pool_op_destroy_poolmgr(struct tee_shm_pool_mgr *poolm) | |
| 49 | +static void pool_op_destroy_pool(struct tee_shm_pool *pool) | |
| 46 | 50 | { |
| 47 | − kfree(poolm); | |
| 51 | + kfree(pool); | |
| 48 | 52 | } |
| 49 | 53 | |
| 50 | −static const struct tee_shm_pool_mgr_ops pool_ops = { | |
| 54 | +static const struct tee_shm_pool_ops pool_ops = { | |
| 51 | 55 | .alloc = pool_op_alloc, |
| 52 | 56 | .free = pool_op_free, |
| 53 | − .destroy_poolmgr = pool_op_destroy_poolmgr, | |
| 57 | + .destroy_pool = pool_op_destroy_pool, | |
| 54 | 58 | }; |
| 55 | 59 | |
| 56 | −static struct tee_shm_pool_mgr *pool_mem_mgr_alloc(void) | |
| 57 | −{ | |
| 58 | − struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | |
| 59 | − | |
| 60 | − if (!mgr) | |
| 61 | − return ERR_PTR(-ENOMEM); | |
| 62 | − | |
| 63 | − mgr->ops = &pool_ops; | |
| 64 | − | |
| 65 | − return mgr; | |
| 66 | −} | |
| 67 | − | |
| 68 | 60 | struct tee_shm_pool *amdtee_config_shm(void) |
| 69 | 61 | { |
| 70 | − struct tee_shm_pool_mgr *priv_mgr; | |
| 71 | − struct tee_shm_pool_mgr *dmabuf_mgr; | |
| 72 | − void *rc; | |
| 62 | + struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL); | |
| 73 | 63 | |
| 74 | − rc = pool_mem_mgr_alloc(); | |
| 75 | − if (IS_ERR(rc)) | |
| 76 | − return rc; | |
| 77 | − priv_mgr = rc; | |
| 78 | − | |
| 79 | − rc = pool_mem_mgr_alloc(); | |
| 80 | − if (IS_ERR(rc)) { | |
| 81 | − tee_shm_pool_mgr_destroy(priv_mgr); | |
| 82 | − return rc; | |
| 83 | − } | |
| 84 | − dmabuf_mgr = rc; | |
| 64 | + if (!pool) | |
| 65 | + return ERR_PTR(-ENOMEM); | |
| 85 | 66 | |
| 86 | − rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); | |
| 87 | − if (IS_ERR(rc)) { | |
| 88 | − tee_shm_pool_mgr_destroy(priv_mgr); | |
| 89 | − tee_shm_pool_mgr_destroy(dmabuf_mgr); | |
| 90 | − } | |
| 67 | + pool->ops = &pool_ops; | |
| 91 | 68 | |
| 92 | − return rc; | |
| 69 | + return pool; | |
| 93 | 70 | } |
| @@ -7,11 +7,3 @@ config OPTEE · 6 unmodified lines | ||
| 7 | 7 | help |
| 8 | 8 | This implements the OP-TEE Trusted Execution Environment (TEE) |
| 9 | 9 | driver. |
| 10 | − | |
| 11 | −config OPTEE_SHM_NUM_PRIV_PAGES | |
| 12 | − int "Private Shared Memory Pages" | |
| 13 | − default 1 | |
| 14 | − depends on OPTEE | |
| 15 | − help | |
| 16 | − This sets the number of private shared memory pages to be | |
| 17 | − used by OP-TEE TEE driver. | |
| @@ -120,7 +120,7 @@ struct tee_shm *optee_get_msg_arg(struct tee_context *ctx, size_t num_params, · 119 unmodified lines | ||
| 120 | 120 | if (optee->rpc_arg_count) |
| 121 | 121 | sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count); |
| 122 | 122 | |
| 123 | − shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV); | |
| 123 | + shm = tee_shm_alloc_priv_buf(ctx, sz); | |
| 124 | 124 | if (IS_ERR(shm)) |
| 125 | 125 | return shm; |
| 126 | 126 | |
| @@ -18,8 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/workqueue.h> |
| 19 | 19 | #include "optee_private.h" |
| 20 | 20 | |
| 21 | −int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, | |
| 22 | − struct tee_shm *shm, size_t size, | |
| 21 | +int optee_pool_op_alloc_helper(struct tee_shm_pool *pool, struct tee_shm *shm, | |
| 22 | + size_t size, size_t align, | |
| 23 | 23 | int (*shm_register)(struct tee_context *ctx, |
| 24 | 24 | struct tee_shm *shm, |
| 25 | 25 | struct page **pages, |
| @@ -30,6 +30,10 @@ int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, · 4 unmodified lines | ||
| 30 | 30 | struct page *page; |
| 31 | 31 | int rc = 0; |
| 32 | 32 | |
| 33 | + /* | |
| 34 | + * Ignore alignment since this is already going to be page aligned | |
| 35 | + * and there's no need for any larger alignment. | |
| 36 | + */ | |
| 33 | 37 | page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); |
| 34 | 38 | if (!page) |
| 35 | 39 | return -ENOMEM; |
| @@ -51,7 +55,6 @@ int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, · 15 unmodified lines | ||
| 51 | 55 | for (i = 0; i < nr_pages; i++) |
| 52 | 56 | pages[i] = page + i; |
| 53 | 57 | |
| 54 | − shm->flags |= TEE_SHM_REGISTER; | |
| 55 | 58 | rc = shm_register(shm->ctx, shm, pages, nr_pages, |
| 56 | 59 | (unsigned long)shm->kaddr); |
| 57 | 60 | kfree(pages); |
| @@ -62,10 +65,20 @@ int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, · 4 unmodified lines | ||
| 62 | 65 | return 0; |
| 63 | 66 | |
| 64 | 67 | err: |
| 65 | − __free_pages(page, order); | |
| 68 | + free_pages((unsigned long)shm->kaddr, order); | |
| 66 | 69 | return rc; |
| 67 | 70 | } |
| 68 | 71 | |
| 72 | +void optee_pool_op_free_helper(struct tee_shm_pool *pool, struct tee_shm *shm, | |
| 73 | + int (*shm_unregister)(struct tee_context *ctx, | |
| 74 | + struct tee_shm *shm)) | |
| 75 | +{ | |
| 76 | + if (shm_unregister) | |
| 77 | + shm_unregister(shm->ctx, shm); | |
| 78 | + free_pages((unsigned long)shm->kaddr, get_order(shm->size)); | |
| 79 | + shm->kaddr = NULL; | |
| 80 | +} | |
| 81 | + | |
| 69 | 82 | static void optee_bus_scan(struct work_struct *work) |
| 70 | 83 | { |
| 71 | 84 | WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP)); |
| @@ -121,10 +121,9 @@ static int __optee_enumerate_devices(u32 func) · 120 unmodified lines | ||
| 121 | 121 | if (rc < 0 || !shm_size) |
| 122 | 122 | goto out_sess; |
| 123 | 123 | |
| 124 | − device_shm = tee_shm_alloc(ctx, shm_size, | |
| 125 | − TEE_SHM_MAPPED | TEE_SHM_DMA_BUF); | |
| 124 | + device_shm = tee_shm_alloc_kernel_buf(ctx, shm_size); | |
| 126 | 125 | if (IS_ERR(device_shm)) { |
| 127 | − pr_err("tee_shm_alloc failed\n"); | |
| 126 | + pr_err("tee_shm_alloc_kernel_buf failed\n"); | |
| 128 | 127 | rc = PTR_ERR(device_shm); |
| 129 | 128 | goto out_sess; |
| 130 | 129 | } |
| @@ -369,30 +369,28 @@ static int optee_ffa_shm_unregister_supp(struct tee_context *ctx, · 368 unmodified lines | ||
| 369 | 369 | * The main function is optee_ffa_shm_pool_alloc_pages(). |
| 370 | 370 | */ |
| 371 | 371 | |
| 372 | −static int pool_ffa_op_alloc(struct tee_shm_pool_mgr *poolm, | |
| 373 | − struct tee_shm *shm, size_t size) | |
| 372 | +static int pool_ffa_op_alloc(struct tee_shm_pool *pool, | |
| 373 | + struct tee_shm *shm, size_t size, size_t align) | |
| 374 | 374 | { |
| 375 | − return optee_pool_op_alloc_helper(poolm, shm, size, | |
| 375 | + return optee_pool_op_alloc_helper(pool, shm, size, align, | |
| 376 | 376 | optee_ffa_shm_register); |
| 377 | 377 | } |
| 378 | 378 | |
| 379 | −static void pool_ffa_op_free(struct tee_shm_pool_mgr *poolm, | |
| 379 | +static void pool_ffa_op_free(struct tee_shm_pool *pool, | |
| 380 | 380 | struct tee_shm *shm) |
| 381 | 381 | { |
| 382 | − optee_ffa_shm_unregister(shm->ctx, shm); | |
| 383 | − free_pages((unsigned long)shm->kaddr, get_order(shm->size)); | |
| 384 | − shm->kaddr = NULL; | |
| 382 | + optee_pool_op_free_helper(pool, shm, optee_ffa_shm_unregister); | |
| 385 | 383 | } |
| 386 | 384 | |
| 387 | −static void pool_ffa_op_destroy_poolmgr(struct tee_shm_pool_mgr *poolm) | |
| 385 | +static void pool_ffa_op_destroy_pool(struct tee_shm_pool *pool) | |
| 388 | 386 | { |
| 389 | − kfree(poolm); | |
| 387 | + kfree(pool); | |
| 390 | 388 | } |
| 391 | 389 | |
| 392 | −static const struct tee_shm_pool_mgr_ops pool_ffa_ops = { | |
| 390 | +static const struct tee_shm_pool_ops pool_ffa_ops = { | |
| 393 | 391 | .alloc = pool_ffa_op_alloc, |
| 394 | 392 | .free = pool_ffa_op_free, |
| 395 | − .destroy_poolmgr = pool_ffa_op_destroy_poolmgr, | |
| 393 | + .destroy_pool = pool_ffa_op_destroy_pool, | |
| 396 | 394 | }; |
| 397 | 395 | |
| 398 | 396 | /** |
| @@ -401,16 +399,16 @@ static const struct tee_shm_pool_mgr_ops pool_ffa_ops = { · 2 unmodified lines | ||
| 401 | 399 | * This pool is used with OP-TEE over FF-A. In this case command buffers |
| 402 | 400 | * and such are allocated from kernel's own memory. |
| 403 | 401 | */ |
| 404 | −static struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void) | |
| 402 | +static struct tee_shm_pool *optee_ffa_shm_pool_alloc_pages(void) | |
| 405 | 403 | { |
| 406 | − struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | |
| 404 | + struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL); | |
| 407 | 405 | |
| 408 | − if (!mgr) | |
| 406 | + if (!pool) | |
| 409 | 407 | return ERR_PTR(-ENOMEM); |
| 410 | 408 | |
| 411 | − mgr->ops = &pool_ffa_ops; | |
| 409 | + pool->ops = &pool_ffa_ops; | |
| 412 | 410 | |
| 413 | − return mgr; | |
| 411 | + return pool; | |
| 414 | 412 | } |
| 415 | 413 | |
| 416 | 414 | /* |
| @@ -440,8 +438,8 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx, · 23 unmodified lines | ||
| 440 | 438 | shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b); |
| 441 | 439 | break; |
| 442 | 440 | case OPTEE_RPC_SHM_TYPE_KERNEL: |
| 443 | − shm = tee_shm_alloc(optee->ctx, arg->params[0].u.value.b, | |
| 444 | − TEE_SHM_MAPPED | TEE_SHM_PRIV); | |
| 441 | + shm = tee_shm_alloc_priv_buf(optee->ctx, | |
| 442 | + arg->params[0].u.value.b); | |
| 445 | 443 | break; |
| 446 | 444 | default: |
| 447 | 445 | arg->ret = TEEC_ERROR_BAD_PARAMETERS; |
| @@ -700,33 +698,6 @@ static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev, · 252 unmodified lines | ||
| 700 | 698 | return true; |
| 701 | 699 | } |
| 702 | 700 | |
| 703 | −static struct tee_shm_pool *optee_ffa_config_dyn_shm(void) | |
| 704 | −{ | |
| 705 | − struct tee_shm_pool_mgr *priv_mgr; | |
| 706 | − struct tee_shm_pool_mgr *dmabuf_mgr; | |
| 707 | − void *rc; | |
| 708 | − | |
| 709 | − rc = optee_ffa_shm_pool_alloc_pages(); | |
| 710 | − if (IS_ERR(rc)) | |
| 711 | − return rc; | |
| 712 | − priv_mgr = rc; | |
| 713 | − | |
| 714 | − rc = optee_ffa_shm_pool_alloc_pages(); | |
| 715 | − if (IS_ERR(rc)) { | |
| 716 | − tee_shm_pool_mgr_destroy(priv_mgr); | |
| 717 | − return rc; | |
| 718 | − } | |
| 719 | − dmabuf_mgr = rc; | |
| 720 | − | |
| 721 | − rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); | |
| 722 | − if (IS_ERR(rc)) { | |
| 723 | − tee_shm_pool_mgr_destroy(priv_mgr); | |
| 724 | − tee_shm_pool_mgr_destroy(dmabuf_mgr); | |
| 725 | − } | |
| 726 | − | |
| 727 | − return rc; | |
| 728 | −} | |
| 729 | − | |
| 730 | 701 | static void optee_ffa_get_version(struct tee_device *teedev, |
| 731 | 702 | struct tee_ioctl_version_data *vers) |
| 732 | 703 | { |
| @@ -824,7 +795,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) · 91 unmodified lines | ||
| 824 | 795 | if (!optee) |
| 825 | 796 | return -ENOMEM; |
| 826 | 797 | |
| 827 | − pool = optee_ffa_config_dyn_shm(); | |
| 798 | + pool = optee_ffa_shm_pool_alloc_pages(); | |
| 828 | 799 | if (IS_ERR(pool)) { |
| 829 | 800 | rc = PTR_ERR(pool); |
| 830 | 801 | goto err_free_optee; |
| @@ -229,13 +229,16 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session); · 228 unmodified lines | ||
| 229 | 229 | int optee_enumerate_devices(u32 func); |
| 230 | 230 | void optee_unregister_devices(void); |
| 231 | 231 | |
| 232 | −int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, | |
| 233 | − struct tee_shm *shm, size_t size, | |
| 232 | +int optee_pool_op_alloc_helper(struct tee_shm_pool *pool, struct tee_shm *shm, | |
| 233 | + size_t size, size_t align, | |
| 234 | 234 | int (*shm_register)(struct tee_context *ctx, |
| 235 | 235 | struct tee_shm *shm, |
| 236 | 236 | struct page **pages, |
| 237 | 237 | size_t num_pages, |
| 238 | 238 | unsigned long start)); |
| 239 | +void optee_pool_op_free_helper(struct tee_shm_pool *pool, struct tee_shm *shm, | |
| 240 | + int (*shm_unregister)(struct tee_context *ctx, | |
| 241 | + struct tee_shm *shm)); | |
| 239 | 242 | |
| 240 | 243 | |
| 241 | 244 | void optee_remove_common(struct optee *optee); |
| @@ -42,7 +42,15 @@ · 41 unmodified lines | ||
| 42 | 42 | * 6. Driver initialization. |
| 43 | 43 | */ |
| 44 | 44 | |
| 45 | −#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES | |
| 45 | +/* | |
| 46 | + * A typical OP-TEE private shm allocation is 224 bytes (argument struct | |
| 47 | + * with 6 parameters, needed for open session). So with an alignment of 512 | |
| 48 | + * we'll waste a bit more than 50%. However, it's only expected that we'll | |
| 49 | + * have a handful of these structs allocated at a time. Most memory will | |
| 50 | + * be allocated aligned to the page size, So all in all this should scale | |
| 51 | + * up and down quite well. | |
| 52 | + */ | |
| 53 | +#define OPTEE_MIN_STATIC_POOL_ALIGN 9 /* 512 bytes aligned */ | |
| 46 | 54 | |
| 47 | 55 | /* |
| 48 | 56 | * 1. Convert between struct tee_param and struct optee_msg_param |
| @@ -220,7 +228,7 @@ static int optee_to_msg_param(struct optee *optee, · 171 unmodified lines | ||
| 220 | 228 | case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: |
| 221 | 229 | case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: |
| 222 | 230 | case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: |
| 223 | − if (tee_shm_is_registered(p->u.memref.shm)) | |
| 231 | + if (tee_shm_is_dynamic(p->u.memref.shm)) | |
| 224 | 232 | rc = to_msg_param_reg_mem(mp, p); |
| 225 | 233 | else |
| 226 | 234 | rc = to_msg_param_tmp_mem(mp, p); |
| @@ -522,38 +530,38 @@ static int optee_shm_unregister_supp(struct tee_context *ctx, · 295 unmodified lines | ||
| 522 | 530 | * The main function is optee_shm_pool_alloc_pages(). |
| 523 | 531 | */ |
| 524 | 532 | |
| 525 | −static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, | |
| 526 | − struct tee_shm *shm, size_t size) | |
| 533 | +static int pool_op_alloc(struct tee_shm_pool *pool, | |
| 534 | + struct tee_shm *shm, size_t size, size_t align) | |
| 527 | 535 | { |
| 528 | 536 | /* |
| 529 | 537 | * Shared memory private to the OP-TEE driver doesn't need |
| 530 | 538 | * to be registered with OP-TEE. |
| 531 | 539 | */ |
| 532 | 540 | if (shm->flags & TEE_SHM_PRIV) |
| 533 | − return optee_pool_op_alloc_helper(poolm, shm, size, NULL); | |
| 541 | + return optee_pool_op_alloc_helper(pool, shm, size, align, NULL); | |
| 534 | 542 | |
| 535 | − return optee_pool_op_alloc_helper(poolm, shm, size, optee_shm_register); | |
| 543 | + return optee_pool_op_alloc_helper(pool, shm, size, align, | |
| 544 | + optee_shm_register); | |
| 536 | 545 | } |
| 537 | 546 | |
| 538 | −static void pool_op_free(struct tee_shm_pool_mgr *poolm, | |
| 547 | +static void pool_op_free(struct tee_shm_pool *pool, | |
| 539 | 548 | struct tee_shm *shm) |
| 540 | 549 | { |
| 541 | 550 | if (!(shm->flags & TEE_SHM_PRIV)) |
| 542 | − optee_shm_unregister(shm->ctx, shm); | |
| 543 | − | |
| 544 | − free_pages((unsigned long)shm->kaddr, get_order(shm->size)); | |
| 545 | − shm->kaddr = NULL; | |
| 551 | + optee_pool_op_free_helper(pool, shm, optee_shm_unregister); | |
| 552 | + else | |
| 553 | + optee_pool_op_free_helper(pool, shm, NULL); | |
| 546 | 554 | } |
| 547 | 555 | |
| 548 | −static void pool_op_destroy_poolmgr(struct tee_shm_pool_mgr *poolm) | |
| 556 | +static void pool_op_destroy_pool(struct tee_shm_pool *pool) | |
| 549 | 557 | { |
| 550 | − kfree(poolm); | |
| 558 | + kfree(pool); | |
| 551 | 559 | } |
| 552 | 560 | |
| 553 | −static const struct tee_shm_pool_mgr_ops pool_ops = { | |
| 561 | +static const struct tee_shm_pool_ops pool_ops = { | |
| 554 | 562 | .alloc = pool_op_alloc, |
| 555 | 563 | .free = pool_op_free, |
| 556 | − .destroy_poolmgr = pool_op_destroy_poolmgr, | |
| 564 | + .destroy_pool = pool_op_destroy_pool, | |
| 557 | 565 | }; |
| 558 | 566 | |
| 559 | 567 | /** |
| @@ -562,16 +570,16 @@ static const struct tee_shm_pool_mgr_ops pool_ops = { · 2 unmodified lines | ||
| 562 | 570 | * This pool is used when OP-TEE supports dymanic SHM. In this case |
| 563 | 571 | * command buffers and such are allocated from kernel's own memory. |
| 564 | 572 | */ |
| 565 | −static struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void) | |
| 573 | +static struct tee_shm_pool *optee_shm_pool_alloc_pages(void) | |
| 566 | 574 | { |
| 567 | − struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | |
| 575 | + struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL); | |
| 568 | 576 | |
| 569 | − if (!mgr) | |
| 577 | + if (!pool) | |
| 570 | 578 | return ERR_PTR(-ENOMEM); |
| 571 | 579 | |
| 572 | − mgr->ops = &pool_ops; | |
| 580 | + pool->ops = &pool_ops; | |
| 573 | 581 | |
| 574 | − return mgr; | |
| 582 | + return pool; | |
| 575 | 583 | } |
| 576 | 584 | |
| 577 | 585 | /* |
| @@ -642,8 +650,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, · 64 unmodified lines | ||
| 642 | 650 | shm = optee_rpc_cmd_alloc_suppl(ctx, sz); |
| 643 | 651 | break; |
| 644 | 652 | case OPTEE_RPC_SHM_TYPE_KERNEL: |
| 645 | − shm = tee_shm_alloc(optee->ctx, sz, | |
| 646 | − TEE_SHM_MAPPED | TEE_SHM_PRIV); | |
| 653 | + shm = tee_shm_alloc_priv_buf(optee->ctx, sz); | |
| 647 | 654 | break; |
| 648 | 655 | default: |
| 649 | 656 | arg->ret = TEEC_ERROR_BAD_PARAMETERS; |
| @@ -662,7 +669,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, · 12 unmodified lines | ||
| 662 | 669 | |
| 663 | 670 | sz = tee_shm_get_size(shm); |
| 664 | 671 | |
| 665 | − if (tee_shm_is_registered(shm)) { | |
| 672 | + if (tee_shm_is_dynamic(shm)) { | |
| 666 | 673 | struct page **pages; |
| 667 | 674 | u64 *pages_list; |
| 668 | 675 | size_t page_num; |
| @@ -768,8 +775,7 @@ static void optee_handle_rpc(struct tee_context *ctx, · 99 unmodified lines | ||
| 768 | 775 | |
| 769 | 776 | switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) { |
| 770 | 777 | case OPTEE_SMC_RPC_FUNC_ALLOC: |
| 771 | − shm = tee_shm_alloc(optee->ctx, param->a1, | |
| 772 | − TEE_SHM_MAPPED | TEE_SHM_PRIV); | |
| 778 | + shm = tee_shm_alloc_priv_buf(optee->ctx, param->a1); | |
| 773 | 779 | if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) { |
| 774 | 780 | reg_pair_from_64(¶m->a1, ¶m->a2, pa); |
| 775 | 781 | reg_pair_from_64(¶m->a4, ¶m->a5, |
| @@ -1143,33 +1149,6 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, · 367 unmodified lines | ||
| 1143 | 1149 | return true; |
| 1144 | 1150 | } |
| 1145 | 1151 | |
| 1146 | −static struct tee_shm_pool *optee_config_dyn_shm(void) | |
| 1147 | −{ | |
| 1148 | − struct tee_shm_pool_mgr *priv_mgr; | |
| 1149 | − struct tee_shm_pool_mgr *dmabuf_mgr; | |
| 1150 | − void *rc; | |
| 1151 | − | |
| 1152 | − rc = optee_shm_pool_alloc_pages(); | |
| 1153 | − if (IS_ERR(rc)) | |
| 1154 | − return rc; | |
| 1155 | − priv_mgr = rc; | |
| 1156 | − | |
| 1157 | − rc = optee_shm_pool_alloc_pages(); | |
| 1158 | − if (IS_ERR(rc)) { | |
| 1159 | − tee_shm_pool_mgr_destroy(priv_mgr); | |
| 1160 | − return rc; | |
| 1161 | − } | |
| 1162 | − dmabuf_mgr = rc; | |
| 1163 | − | |
| 1164 | − rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); | |
| 1165 | − if (IS_ERR(rc)) { | |
| 1166 | − tee_shm_pool_mgr_destroy(priv_mgr); | |
| 1167 | − tee_shm_pool_mgr_destroy(dmabuf_mgr); | |
| 1168 | − } | |
| 1169 | − | |
| 1170 | − return rc; | |
| 1171 | −} | |
| 1172 | − | |
| 1173 | 1152 | static struct tee_shm_pool * |
| 1174 | 1153 | optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) |
| 1175 | 1154 | { |
| @@ -1183,10 +1162,7 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) · 7 unmodified lines | ||
| 1183 | 1162 | phys_addr_t begin; |
| 1184 | 1163 | phys_addr_t end; |
| 1185 | 1164 | void *va; |
| 1186 | − struct tee_shm_pool_mgr *priv_mgr; | |
| 1187 | − struct tee_shm_pool_mgr *dmabuf_mgr; | |
| 1188 | 1165 | void *rc; |
| 1189 | − const int sz = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; | |
| 1190 | 1166 | |
| 1191 | 1167 | invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc); |
| 1192 | 1168 | if (res.result.status != OPTEE_SMC_RETURN_OK) { |
| @@ -1204,11 +1180,6 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) · 11 unmodified lines | ||
| 1204 | 1180 | paddr = begin; |
| 1205 | 1181 | size = end - begin; |
| 1206 | 1182 | |
| 1207 | − if (size < 2 * OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE) { | |
| 1208 | − pr_err("too small shared memory area\n"); | |
| 1209 | − return ERR_PTR(-EINVAL); | |
| 1210 | − } | |
| 1211 | − | |
| 1212 | 1183 | va = memremap(paddr, size, MEMREMAP_WB); |
| 1213 | 1184 | if (!va) { |
| 1214 | 1185 | pr_err("shared memory ioremap failed\n"); |
| @@ -1216,35 +1187,13 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) · 1 unmodified line | ||
| 1216 | 1187 | } |
| 1217 | 1188 | vaddr = (unsigned long)va; |
| 1218 | 1189 | |
| 1219 | − rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, sz, | |
| 1220 | − 3 /* 8 bytes aligned */); | |
| 1190 | + rc = tee_shm_pool_alloc_res_mem(vaddr, paddr, size, | |
| 1191 | + OPTEE_MIN_STATIC_POOL_ALIGN); | |
| 1221 | 1192 | if (IS_ERR(rc)) |
| 1222 | − goto err_memunmap; | |
| 1223 | − priv_mgr = rc; | |
| 1224 | − | |
| 1225 | − vaddr += sz; | |
| 1226 | − paddr += sz; | |
| 1227 | − size -= sz; | |
| 1228 | − | |
| 1229 | − rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, size, PAGE_SHIFT); | |
| 1230 | − if (IS_ERR(rc)) | |
| 1231 | − goto err_free_priv_mgr; | |
| 1232 | − dmabuf_mgr = rc; | |
| 1233 | − | |
| 1234 | − rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); | |
| 1235 | − if (IS_ERR(rc)) | |
| 1236 | − goto err_free_dmabuf_mgr; | |
| 1237 | − | |
| 1238 | − *memremaped_shm = va; | |
| 1239 | − | |
| 1240 | − return rc; | |
| 1193 | + memunmap(va); | |
| 1194 | + else | |
| 1195 | + *memremaped_shm = va; | |
| 1241 | 1196 | |
| 1242 | −err_free_dmabuf_mgr: | |
| 1243 | − tee_shm_pool_mgr_destroy(dmabuf_mgr); | |
| 1244 | −err_free_priv_mgr: | |
| 1245 | − tee_shm_pool_mgr_destroy(priv_mgr); | |
| 1246 | −err_memunmap: | |
| 1247 | − memunmap(va); | |
| 1248 | 1197 | return rc; |
| 1249 | 1198 | } |
| 1250 | 1199 | |
| @@ -1366,7 +1315,7 @@ static int optee_probe(struct platform_device *pdev) · 115 unmodified lines | ||
| 1366 | 1315 | * Try to use dynamic shared memory if possible |
| 1367 | 1316 | */ |
| 1368 | 1317 | if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) |
| 1369 | − pool = optee_config_dyn_shm(); | |
| 1318 | + pool = optee_shm_pool_alloc_pages(); | |
| 1370 | 1319 | |
| 1371 | 1320 | /* |
| 1372 | 1321 | * If dynamic shared memory is not available or failed - try static one |
| @@ -297,7 +297,7 @@ static int tee_ioctl_shm_alloc(struct tee_context *ctx, · 296 unmodified lines | ||
| 297 | 297 | if (data.flags) |
| 298 | 298 | return -EINVAL; |
| 299 | 299 | |
| 300 | − shm = tee_shm_alloc(ctx, data.size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF); | |
| 300 | + shm = tee_shm_alloc_user_buf(ctx, data.size); | |
| 301 | 301 | if (IS_ERR(shm)) |
| 302 | 302 | return PTR_ERR(shm); |
| 303 | 303 | |
| @@ -334,8 +334,7 @@ tee_ioctl_shm_register(struct tee_context *ctx, · 30 unmodified lines | ||
| 334 | 334 | if (data.flags) |
| 335 | 335 | return -EINVAL; |
| 336 | 336 | |
| 337 | − shm = tee_shm_register(ctx, data.addr, data.length, | |
| 338 | − TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED); | |
| 337 | + shm = tee_shm_register_user_buf(ctx, data.addr, data.length); | |
| 339 | 338 | if (IS_ERR(shm)) |
| 340 | 339 | return PTR_ERR(shm); |
| 341 | 340 | |
| @@ -12,17 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/mutex.h> |
| 13 | 13 | #include <linux/types.h> |
| 14 | 14 | |
| 15 | −/** | |
| 16 | − * struct tee_shm_pool - shared memory pool | |
| 17 | − * @private_mgr: pool manager for shared memory only between kernel | |
| 18 | − * and secure world | |
| 19 | − * @dma_buf_mgr: pool manager for shared memory exported to user space | |
| 20 | − */ | |
| 21 | −struct tee_shm_pool { | |
| 22 | − struct tee_shm_pool_mgr *private_mgr; | |
| 23 | − struct tee_shm_pool_mgr *dma_buf_mgr; | |
| 24 | −}; | |
| 25 | − | |
| 26 | 15 | #define TEE_DEVICE_FLAG_REGISTERED 0x1 |
| 27 | 16 | #define TEE_MAX_DEV_NAME_LEN 32 |
| 28 | 17 | |
| @@ -68,4 +57,8 @@ void tee_device_put(struct tee_device *teedev); · 39 unmodified lines | ||
| 68 | 57 | void teedev_ctx_get(struct tee_context *ctx); |
| 69 | 58 | void teedev_ctx_put(struct tee_context *ctx); |
| 70 | 59 | |
| 60 | +struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size); | |
| 61 | +struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx, | |
| 62 | + unsigned long addr, size_t length); | |
| 63 | + | |
| 71 | 64 | #endif /*TEE_PRIVATE_H*/ |
| @@ -12,17 +12,43 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/uio.h> |
| 13 | 13 | #include "tee_private.h" |
| 14 | 14 | |
| 15 | +static void shm_put_kernel_pages(struct page **pages, size_t page_count) | |
| 16 | +{ | |
| 17 | + size_t n; | |
| 18 | + | |
| 19 | + for (n = 0; n < page_count; n++) | |
| 20 | + put_page(pages[n]); | |
| 21 | +} | |
| 22 | + | |
| 23 | +static int shm_get_kernel_pages(unsigned long start, size_t page_count, | |
| 24 | + struct page **pages) | |
| 25 | +{ | |
| 26 | + struct kvec *kiov; | |
| 27 | + size_t n; | |
| 28 | + int rc; | |
| 29 | + | |
| 30 | + kiov = kcalloc(page_count, sizeof(*kiov), GFP_KERNEL); | |
| 31 | + if (!kiov) | |
| 32 | + return -ENOMEM; | |
| 33 | + | |
| 34 | + for (n = 0; n < page_count; n++) { | |
| 35 | + kiov[n].iov_base = (void *)(start + n * PAGE_SIZE); | |
| 36 | + kiov[n].iov_len = PAGE_SIZE; | |
| 37 | + } | |
| 38 | + | |
| 39 | + rc = get_kernel_pages(kiov, page_count, 0, pages); | |
| 40 | + kfree(kiov); | |
| 41 | + | |
| 42 | + return rc; | |
| 43 | +} | |
| 44 | + | |
| 15 | 45 | static void release_registered_pages(struct tee_shm *shm) |
| 16 | 46 | { |
| 17 | 47 | if (shm->pages) { |
| 18 | − if (shm->flags & TEE_SHM_USER_MAPPED) { | |
| 48 | + if (shm->flags & TEE_SHM_USER_MAPPED) | |
| 19 | 49 | unpin_user_pages(shm->pages, shm->num_pages); |
| 20 | − } else { | |
| 21 | − size_t n; | |
| 22 | − | |
| 23 | − for (n = 0; n < shm->num_pages; n++) | |
| 24 | − put_page(shm->pages[n]); | |
| 25 | − } | |
| 50 | + else | |
| 51 | + shm_put_kernel_pages(shm->pages, shm->num_pages); | |
| 26 | 52 | |
| 27 | 53 | kfree(shm->pages); |
| 28 | 54 | } |
| @@ -31,15 +57,8 @@ static void release_registered_pages(struct tee_shm *shm) · 2 unmodified lines | ||
| 31 | 57 | static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm) |
| 32 | 58 | { |
| 33 | 59 | if (shm->flags & TEE_SHM_POOL) { |
| 34 | − struct tee_shm_pool_mgr *poolm; | |
| 35 | − | |
| 36 | − if (shm->flags & TEE_SHM_DMA_BUF) | |
| 37 | − poolm = teedev->pool->dma_buf_mgr; | |
| 38 | − else | |
| 39 | − poolm = teedev->pool->private_mgr; | |
| 40 | − | |
| 41 | − poolm->ops->free(poolm, shm); | |
| 42 | − } else if (shm->flags & TEE_SHM_REGISTER) { | |
| 60 | + teedev->pool->ops->free(teedev->pool, shm); | |
| 61 | + } else if (shm->flags & TEE_SHM_DYNAMIC) { | |
| 43 | 62 | int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm); |
| 44 | 63 | |
| 45 | 64 | if (rc) |
| @@ -56,25 +75,14 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm) · 10 unmodified lines | ||
| 56 | 75 | tee_device_put(teedev); |
| 57 | 76 | } |
| 58 | 77 | |
| 59 | −struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) | |
| 78 | +static struct tee_shm *shm_alloc_helper(struct tee_context *ctx, size_t size, | |
| 79 | + size_t align, u32 flags, int id) | |
| 60 | 80 | { |
| 61 | 81 | struct tee_device *teedev = ctx->teedev; |
| 62 | − struct tee_shm_pool_mgr *poolm = NULL; | |
| 63 | 82 | struct tee_shm *shm; |
| 64 | 83 | void *ret; |
| 65 | 84 | int rc; |
| 66 | 85 | |
| 67 | − if (!(flags & TEE_SHM_MAPPED)) { | |
| 68 | − dev_err(teedev->dev.parent, | |
| 69 | − "only mapped allocations supported\n"); | |
| 70 | − return ERR_PTR(-EINVAL); | |
| 71 | − } | |
| 72 | − | |
| 73 | − if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_PRIV))) { | |
| 74 | − dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags); | |
| 75 | − return ERR_PTR(-EINVAL); | |
| 76 | − } | |
| 77 | − | |
| 78 | 86 | if (!tee_device_get(teedev)) |
| 79 | 87 | return ERR_PTR(-EINVAL); |
| 80 | 88 | |
| @@ -91,41 +99,76 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) · 10 unmodified lines | ||
| 91 | 99 | } |
| 92 | 100 | |
| 93 | 101 | refcount_set(&shm->refcount, 1); |
| 94 | − shm->flags = flags | TEE_SHM_POOL; | |
| 102 | + shm->flags = flags; | |
| 103 | + shm->id = id; | |
| 104 | + | |
| 105 | + /* | |
| 106 | + * We're assigning this as it is needed if the shm is to be | |
| 107 | + * registered. If this function returns OK then the caller expected | |
| 108 | + * to call teedev_ctx_get() or clear shm->ctx in case it's not | |
| 109 | + * needed any longer. | |
| 110 | + */ | |
| 95 | 111 | shm->ctx = ctx; |
| 96 | − if (flags & TEE_SHM_DMA_BUF) | |
| 97 | − poolm = teedev->pool->dma_buf_mgr; | |
| 98 | − else | |
| 99 | − poolm = teedev->pool->private_mgr; | |
| 100 | 112 | |
| 101 | − rc = poolm->ops->alloc(poolm, shm, size); | |
| 113 | + rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align); | |
| 102 | 114 | if (rc) { |
| 103 | 115 | ret = ERR_PTR(rc); |
| 104 | 116 | goto err_kfree; |
| 105 | 117 | } |
| 106 | 118 | |
| 107 | − if (flags & TEE_SHM_DMA_BUF) { | |
| 108 | − mutex_lock(&teedev->mutex); | |
| 109 | − shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL); | |
| 110 | − mutex_unlock(&teedev->mutex); | |
| 111 | − if (shm->id < 0) { | |
| 112 | − ret = ERR_PTR(shm->id); | |
| 113 | − goto err_pool_free; | |
| 114 | − } | |
| 115 | − } | |
| 116 | − | |
| 117 | 119 | teedev_ctx_get(ctx); |
| 118 | − | |
| 119 | 120 | return shm; |
| 120 | −err_pool_free: | |
| 121 | − poolm->ops->free(poolm, shm); | |
| 122 | 121 | err_kfree: |
| 123 | 122 | kfree(shm); |
| 124 | 123 | err_dev_put: |
| 125 | 124 | tee_device_put(teedev); |
| 126 | 125 | return ret; |
| 127 | 126 | } |
| 128 | −EXPORT_SYMBOL_GPL(tee_shm_alloc); | |
| 127 | + | |
| 128 | +/** | |
| 129 | + * tee_shm_alloc_user_buf() - Allocate shared memory for user space | |
| 130 | + * @ctx: Context that allocates the shared memory | |
| 131 | + * @size: Requested size of shared memory | |
| 132 | + * | |
| 133 | + * Memory allocated as user space shared memory is automatically freed when | |
| 134 | + * the TEE file pointer is closed. The primary usage of this function is | |
| 135 | + * when the TEE driver doesn't support registering ordinary user space | |
| 136 | + * memory. | |
| 137 | + * | |
| 138 | + * @returns a pointer to 'struct tee_shm' | |
| 139 | + */ | |
| 140 | +struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size) | |
| 141 | +{ | |
| 142 | + u32 flags = TEE_SHM_DYNAMIC | TEE_SHM_POOL; | |
| 143 | + struct tee_device *teedev = ctx->teedev; | |
| 144 | + struct tee_shm *shm; | |
| 145 | + void *ret; | |
| 146 | + int id; | |
| 147 | + | |
| 148 | + mutex_lock(&teedev->mutex); | |
| 149 | + id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL); | |
| 150 | + mutex_unlock(&teedev->mutex); | |
| 151 | + if (id < 0) | |
| 152 | + return ERR_PTR(id); | |
| 153 | + | |
| 154 | + shm = shm_alloc_helper(ctx, size, PAGE_SIZE, flags, id); | |
| 155 | + if (IS_ERR(shm)) { | |
| 156 | + mutex_lock(&teedev->mutex); | |
| 157 | + idr_remove(&teedev->idr, id); | |
| 158 | + mutex_unlock(&teedev->mutex); | |
| 159 | + return shm; | |
| 160 | + } | |
| 161 | + | |
| 162 | + mutex_lock(&teedev->mutex); | |
| 163 | + ret = idr_replace(&teedev->idr, shm, id); | |
| 164 | + mutex_unlock(&teedev->mutex); | |
| 165 | + if (IS_ERR(ret)) { | |
| 166 | + tee_shm_free(shm); | |
| 167 | + return ret; | |
| 168 | + } | |
| 169 | + | |
| 170 | + return shm; | |
| 171 | +} | |
| 129 | 172 | |
| 130 | 173 | /** |
| 131 | 174 | * tee_shm_alloc_kernel_buf() - Allocate shared memory for kernel buffer |
| @@ -141,32 +184,54 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc); · 9 unmodified lines | ||
| 141 | 184 | */ |
| 142 | 185 | struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size) |
| 143 | 186 | { |
| 144 | − return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED); | |
| 187 | + u32 flags = TEE_SHM_DYNAMIC | TEE_SHM_POOL; | |
| 188 | + | |
| 189 | + return shm_alloc_helper(ctx, size, PAGE_SIZE, flags, -1); | |
| 145 | 190 | } |
| 146 | 191 | EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf); |
| 147 | 192 | |
| 148 | −struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, | |
| 149 | − size_t length, u32 flags) | |
| 193 | +/** | |
| 194 | + * tee_shm_alloc_priv_buf() - Allocate shared memory for a privately shared | |
| 195 | + * kernel buffer | |
| 196 | + * @ctx: Context that allocates the shared memory | |
| 197 | + * @size: Requested size of shared memory | |
| 198 | + * | |
| 199 | + * This function returns similar shared memory as | |
| 200 | + * tee_shm_alloc_kernel_buf(), but with the difference that the memory | |
| 201 | + * might not be registered in secure world in case the driver supports | |
| 202 | + * passing memory not registered in advance. | |
| 203 | + * | |
| 204 | + * This function should normally only be used internally in the TEE | |
| 205 | + * drivers. | |
| 206 | + * | |
| 207 | + * @returns a pointer to 'struct tee_shm' | |
| 208 | + */ | |
| 209 | +struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size) | |
| 210 | +{ | |
| 211 | + u32 flags = TEE_SHM_PRIV | TEE_SHM_POOL; | |
| 212 | + | |
| 213 | + return shm_alloc_helper(ctx, size, sizeof(long) * 2, flags, -1); | |
| 214 | +} | |
| 215 | +EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_buf); | |
| 216 | + | |
| 217 | +static struct tee_shm * | |
| 218 | +register_shm_helper(struct tee_context *ctx, unsigned long addr, | |
| 219 | + size_t length, u32 flags, int id) | |
| 150 | 220 | { |
| 151 | 221 | struct tee_device *teedev = ctx->teedev; |
| 152 | − const u32 req_user_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED; | |
| 153 | − const u32 req_kernel_flags = TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED; | |
| 154 | 222 | struct tee_shm *shm; |
| 223 | + unsigned long start; | |
| 224 | + size_t num_pages; | |
| 155 | 225 | void *ret; |
| 156 | 226 | int rc; |
| 157 | − int num_pages; | |
| 158 | − unsigned long start; | |
| 159 | − | |
| 160 | − if (flags != req_user_flags && flags != req_kernel_flags) | |
| 161 | − return ERR_PTR(-ENOTSUPP); | |
| 162 | 227 | |
| 163 | 228 | if (!tee_device_get(teedev)) |
| 164 | 229 | return ERR_PTR(-EINVAL); |
| 165 | 230 | |
| 166 | 231 | if (!teedev->desc->ops->shm_register || |
| 167 | 232 | !teedev->desc->ops->shm_unregister) { |
| 168 | − tee_device_put(teedev); | |
| 169 | − return ERR_PTR(-ENOTSUPP); | |
| 233 | + ret = ERR_PTR(-ENOTSUPP); | |
| 234 | + goto err_dev_put; | |
| 170 | 235 | } |
| 171 | 236 | |
| 172 | 237 | teedev_ctx_get(ctx); |
| @@ -174,13 +239,13 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, · 1 unmodified line | ||
| 174 | 239 | shm = kzalloc(sizeof(*shm), GFP_KERNEL); |
| 175 | 240 | if (!shm) { |
| 176 | 241 | ret = ERR_PTR(-ENOMEM); |
| 177 | − goto err; | |
| 242 | + goto err_ctx_put; | |
| 178 | 243 | } |
| 179 | 244 | |
| 180 | 245 | refcount_set(&shm->refcount, 1); |
| 181 | − shm->flags = flags | TEE_SHM_REGISTER; | |
| 246 | + shm->flags = flags; | |
| 182 | 247 | shm->ctx = ctx; |
| 183 | − shm->id = -1; | |
| 248 | + shm->id = id; | |
| 184 | 249 | addr = untagged_addr(addr); |
| 185 | 250 | start = rounddown(addr, PAGE_SIZE); |
| 186 | 251 | shm->offset = addr - start; |
| @@ -189,71 +254,106 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, · 2 unmodified lines | ||
| 189 | 254 | shm->pages = kcalloc(num_pages, sizeof(*shm->pages), GFP_KERNEL); |
| 190 | 255 | if (!shm->pages) { |
| 191 | 256 | ret = ERR_PTR(-ENOMEM); |
| 192 | − goto err; | |
| 257 | + goto err_free_shm; | |
| 193 | 258 | } |
| 194 | 259 | |
| 195 | − if (flags & TEE_SHM_USER_MAPPED) { | |
| 260 | + if (flags & TEE_SHM_USER_MAPPED) | |
| 196 | 261 | rc = pin_user_pages_fast(start, num_pages, FOLL_WRITE, |
| 197 | 262 | shm->pages); |
| 198 | − } else { | |
| 199 | − struct kvec *kiov; | |
| 200 | − int i; | |
| 201 | − | |
| 202 | − kiov = kcalloc(num_pages, sizeof(*kiov), GFP_KERNEL); | |
| 203 | − if (!kiov) { | |
| 204 | − ret = ERR_PTR(-ENOMEM); | |
| 205 | − goto err; | |
| 206 | − } | |
| 207 | − | |
| 208 | − for (i = 0; i < num_pages; i++) { | |
| 209 | − kiov[i].iov_base = (void *)(start + i * PAGE_SIZE); | |
| 210 | − kiov[i].iov_len = PAGE_SIZE; | |
| 211 | − } | |
| 212 | − | |
| 213 | − rc = get_kernel_pages(kiov, num_pages, 0, shm->pages); | |
| 214 | − kfree(kiov); | |
| 215 | − } | |
| 263 | + else | |
| 264 | + rc = shm_get_kernel_pages(start, num_pages, shm->pages); | |
| 216 | 265 | if (rc > 0) |
| 217 | 266 | shm->num_pages = rc; |
| 218 | 267 | if (rc != num_pages) { |
| 219 | 268 | if (rc >= 0) |
| 220 | 269 | rc = -ENOMEM; |
| 221 | 270 | ret = ERR_PTR(rc); |
| 222 | − goto err; | |
| 223 | − } | |
| 224 | − | |
| 225 | − mutex_lock(&teedev->mutex); | |
| 226 | − shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL); | |
| 227 | − mutex_unlock(&teedev->mutex); | |
| 228 | − | |
| 229 | − if (shm->id < 0) { | |
| 230 | − ret = ERR_PTR(shm->id); | |
| 231 | − goto err; | |
| 271 | + goto err_put_shm_pages; | |
| 232 | 272 | } |
| 233 | 273 | |
| 234 | 274 | rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages, |
| 235 | 275 | shm->num_pages, start); |
| 236 | 276 | if (rc) { |
| 237 | 277 | ret = ERR_PTR(rc); |
| 238 | − goto err; | |
| 278 | + goto err_put_shm_pages; | |
| 239 | 279 | } |
| 240 | 280 | |
| 241 | 281 | return shm; |
| 242 | −err: | |
| 243 | − if (shm) { | |
| 244 | − if (shm->id >= 0) { | |
| 245 | − mutex_lock(&teedev->mutex); | |
| 246 | − idr_remove(&teedev->idr, shm->id); | |
| 247 | − mutex_unlock(&teedev->mutex); | |
| 248 | − } | |
| 249 | − release_registered_pages(shm); | |
| 250 | − } | |
| 282 | +err_put_shm_pages: | |
| 283 | + if (flags & TEE_SHM_USER_MAPPED) | |
| 284 | + unpin_user_pages(shm->pages, shm->num_pages); | |
| 285 | + else | |
| 286 | + shm_put_kernel_pages(shm->pages, shm->num_pages); | |
| 287 | + kfree(shm->pages); | |
| 288 | +err_free_shm: | |
| 251 | 289 | kfree(shm); |
| 290 | +err_ctx_put: | |
| 252 | 291 | teedev_ctx_put(ctx); |
| 292 | +err_dev_put: | |
| 253 | 293 | tee_device_put(teedev); |
| 254 | 294 | return ret; |
| 255 | 295 | } |
| 256 | −EXPORT_SYMBOL_GPL(tee_shm_register); | |
| 296 | + | |
| 297 | +/** | |
| 298 | + * tee_shm_register_user_buf() - Register a userspace shared memory buffer | |
| 299 | + * @ctx: Context that registers the shared memory | |
| 300 | + * @addr: The userspace address of the shared buffer | |
| 301 | + * @length: Length of the shared buffer | |
| 302 | + * | |
| 303 | + * @returns a pointer to 'struct tee_shm' | |
| 304 | + */ | |
| 305 | +struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx, | |
| 306 | + unsigned long addr, size_t length) | |
| 307 | +{ | |
| 308 | + u32 flags = TEE_SHM_USER_MAPPED | TEE_SHM_DYNAMIC; | |
| 309 | + struct tee_device *teedev = ctx->teedev; | |
| 310 | + struct tee_shm *shm; | |
| 311 | + void *ret; | |
| 312 | + int id; | |
| 313 | + | |
| 314 | + mutex_lock(&teedev->mutex); | |
| 315 | + id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL); | |
| 316 | + mutex_unlock(&teedev->mutex); | |
| 317 | + if (id < 0) | |
| 318 | + return ERR_PTR(id); | |
| 319 | + | |
| 320 | + shm = register_shm_helper(ctx, addr, length, flags, id); | |
| 321 | + if (IS_ERR(shm)) { | |
| 322 | + mutex_lock(&teedev->mutex); | |
| 323 | + idr_remove(&teedev->idr, id); | |
| 324 | + mutex_unlock(&teedev->mutex); | |
| 325 | + return shm; | |
| 326 | + } | |
| 327 | + | |
| 328 | + mutex_lock(&teedev->mutex); | |
| 329 | + ret = idr_replace(&teedev->idr, shm, id); | |
| 330 | + mutex_unlock(&teedev->mutex); | |
| 331 | + if (IS_ERR(ret)) { | |
| 332 | + tee_shm_free(shm); | |
| 333 | + return ret; | |
| 334 | + } | |
| 335 | + | |
| 336 | + return shm; | |
| 337 | +} | |
| 338 | + | |
| 339 | +/** | |
| 340 | + * tee_shm_register_kernel_buf() - Register kernel memory to be shared with | |
| 341 | + * secure world | |
| 342 | + * @ctx: Context that registers the shared memory | |
| 343 | + * @addr: The buffer | |
| 344 | + * @length: Length of the buffer | |
| 345 | + * | |
| 346 | + * @returns a pointer to 'struct tee_shm' | |
| 347 | + */ | |
| 348 | + | |
| 349 | +struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx, | |
| 350 | + void *addr, size_t length) | |
| 351 | +{ | |
| 352 | + u32 flags = TEE_SHM_DYNAMIC; | |
| 353 | + | |
| 354 | + return register_shm_helper(ctx, (unsigned long)addr, length, flags, -1); | |
| 355 | +} | |
| 356 | +EXPORT_SYMBOL_GPL(tee_shm_register_kernel_buf); | |
| 257 | 357 | |
| 258 | 358 | static int tee_shm_fop_release(struct inode *inode, struct file *filp) |
| 259 | 359 | { |
| @@ -293,7 +393,7 @@ int tee_shm_get_fd(struct tee_shm *shm) · 33 unmodified lines | ||
| 293 | 393 | { |
| 294 | 394 | int fd; |
| 295 | 395 | |
| 296 | − if (!(shm->flags & TEE_SHM_DMA_BUF)) | |
| 396 | + if (shm->id < 0) | |
| 297 | 397 | return -EINVAL; |
| 298 | 398 | |
| 299 | 399 | /* matched by tee_shm_put() in tee_shm_op_release() */ |
| @@ -323,7 +423,7 @@ EXPORT_SYMBOL_GPL(tee_shm_free); · 23 unmodified lines | ||
| 323 | 423 | */ |
| 324 | 424 | int tee_shm_va2pa(struct tee_shm *shm, void *va, phys_addr_t *pa) |
| 325 | 425 | { |
| 326 | − if (!(shm->flags & TEE_SHM_MAPPED)) | |
| 426 | + if (!shm->kaddr) | |
| 327 | 427 | return -EINVAL; |
| 328 | 428 | /* Check that we're in the range of the shm */ |
| 329 | 429 | if ((char *)va < (char *)shm->kaddr) |
| @@ -345,7 +445,7 @@ EXPORT_SYMBOL_GPL(tee_shm_va2pa); · 15 unmodified lines | ||
| 345 | 445 | */ |
| 346 | 446 | int tee_shm_pa2va(struct tee_shm *shm, phys_addr_t pa, void **va) |
| 347 | 447 | { |
| 348 | − if (!(shm->flags & TEE_SHM_MAPPED)) | |
| 448 | + if (!shm->kaddr) | |
| 349 | 449 | return -EINVAL; |
| 350 | 450 | /* Check that we're in the range of the shm */ |
| 351 | 451 | if (pa < shm->paddr) |
| @@ -373,7 +473,7 @@ EXPORT_SYMBOL_GPL(tee_shm_pa2va); · 21 unmodified lines | ||
| 373 | 473 | */ |
| 374 | 474 | void *tee_shm_get_va(struct tee_shm *shm, size_t offs) |
| 375 | 475 | { |
| 376 | − if (!(shm->flags & TEE_SHM_MAPPED)) | |
| 476 | + if (!shm->kaddr) | |
| 377 | 477 | return ERR_PTR(-EINVAL); |
| 378 | 478 | if (offs >= shm->size) |
| 379 | 479 | return ERR_PTR(-EINVAL); |
| @@ -448,7 +548,7 @@ void tee_shm_put(struct tee_shm *shm) · 68 unmodified lines | ||
| 448 | 548 | * the refcount_inc() in tee_shm_get_from_id() never starts |
| 449 | 549 | * from 0. |
| 450 | 550 | */ |
| 451 | − if (shm->flags & TEE_SHM_DMA_BUF) | |
| 551 | + if (shm->id >= 0) | |
| 452 | 552 | idr_remove(&teedev->idr, shm->id); |
| 453 | 553 | do_release = true; |
| 454 | 554 | } |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | 2 | /* |
| 3 | − * Copyright (c) 2015, Linaro Limited | |
| 3 | + * Copyright (c) 2015, 2017, 2022 Linaro Limited | |
| 4 | 4 | */ |
| 5 | 5 | #include <linux/device.h> |
| 6 | 6 | #include <linux/dma-buf.h> |
| @@ -9,14 +9,16 @@ · 2 unmodified lines | ||
| 9 | 9 | #include <linux/tee_drv.h> |
| 10 | 10 | #include "tee_private.h" |
| 11 | 11 | |
| 12 | −static int pool_op_gen_alloc(struct tee_shm_pool_mgr *poolm, | |
| 13 | − struct tee_shm *shm, size_t size) | |
| 12 | +static int pool_op_gen_alloc(struct tee_shm_pool *pool, struct tee_shm *shm, | |
| 13 | + size_t size, size_t align) | |
| 14 | 14 | { |
| 15 | 15 | unsigned long va; |
| 16 | − struct gen_pool *genpool = poolm->private_data; | |
| 17 | − size_t s = roundup(size, 1 << genpool->min_alloc_order); | |
| 16 | + struct gen_pool *genpool = pool->private_data; | |
| 17 | + size_t a = max_t(size_t, align, BIT(genpool->min_alloc_order)); | |
| 18 | + struct genpool_data_align data = { .align = a }; | |
| 19 | + size_t s = roundup(size, a); | |
| 18 | 20 | |
| 19 | − va = gen_pool_alloc(genpool, s); | |
| 21 | + va = gen_pool_alloc_algo(genpool, s, gen_pool_first_fit_align, &data); | |
| 20 | 22 | if (!va) |
| 21 | 23 | return -ENOMEM; |
| 22 | 24 | |
| @@ -24,163 +26,67 @@ static int pool_op_gen_alloc(struct tee_shm_pool_mgr *poolm, · 1 unmodified line | ||
| 24 | 26 | shm->kaddr = (void *)va; |
| 25 | 27 | shm->paddr = gen_pool_virt_to_phys(genpool, va); |
| 26 | 28 | shm->size = s; |
| 29 | + /* | |
| 30 | + * This is from a static shared memory pool so no need to register | |
| 31 | + * each chunk, and no need to unregister later either. | |
| 32 | + */ | |
| 33 | + shm->flags &= ~TEE_SHM_DYNAMIC; | |
| 27 | 34 | return 0; |
| 28 | 35 | } |
| 29 | 36 | |
| 30 | −static void pool_op_gen_free(struct tee_shm_pool_mgr *poolm, | |
| 31 | − struct tee_shm *shm) | |
| 37 | +static void pool_op_gen_free(struct tee_shm_pool *pool, struct tee_shm *shm) | |
| 32 | 38 | { |
| 33 | − gen_pool_free(poolm->private_data, (unsigned long)shm->kaddr, | |
| 39 | + gen_pool_free(pool->private_data, (unsigned long)shm->kaddr, | |
| 34 | 40 | shm->size); |
| 35 | 41 | shm->kaddr = NULL; |
| 36 | 42 | } |
| 37 | 43 | |
| 38 | −static void pool_op_gen_destroy_poolmgr(struct tee_shm_pool_mgr *poolm) | |
| 44 | +static void pool_op_gen_destroy_pool(struct tee_shm_pool *pool) | |
| 39 | 45 | { |
| 40 | − gen_pool_destroy(poolm->private_data); | |
| 41 | − kfree(poolm); | |
| 46 | + gen_pool_destroy(pool->private_data); | |
| 47 | + kfree(pool); | |
| 42 | 48 | } |
| 43 | 49 | |
| 44 | −static const struct tee_shm_pool_mgr_ops pool_ops_generic = { | |
| 50 | +static const struct tee_shm_pool_ops pool_ops_generic = { | |
| 45 | 51 | .alloc = pool_op_gen_alloc, |
| 46 | 52 | .free = pool_op_gen_free, |
| 47 | − .destroy_poolmgr = pool_op_gen_destroy_poolmgr, | |
| 53 | + .destroy_pool = pool_op_gen_destroy_pool, | |
| 48 | 54 | }; |
| 49 | 55 | |
| 50 | −/** | |
| 51 | − * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved | |
| 52 | − * memory range | |
| 53 | − * @priv_info: Information for driver private shared memory pool | |
| 54 | − * @dmabuf_info: Information for dma-buf shared memory pool | |
| 55 | − * | |
| 56 | − * Start and end of pools will must be page aligned. | |
| 57 | − * | |
| 58 | − * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied | |
| 59 | − * in @dmabuf, others will use the range provided by @priv. | |
| 60 | − * | |
| 61 | − * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. | |
| 62 | − */ | |
| 63 | −struct tee_shm_pool * | |
| 64 | −tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info, | |
| 65 | − struct tee_shm_pool_mem_info *dmabuf_info) | |
| 66 | −{ | |
| 67 | − struct tee_shm_pool_mgr *priv_mgr; | |
| 68 | − struct tee_shm_pool_mgr *dmabuf_mgr; | |
| 69 | − void *rc; | |
| 70 | − | |
| 71 | − /* | |
| 72 | − * Create the pool for driver private shared memory | |
| 73 | − */ | |
| 74 | − rc = tee_shm_pool_mgr_alloc_res_mem(priv_info->vaddr, priv_info->paddr, | |
| 75 | − priv_info->size, | |
| 76 | − 3 /* 8 byte aligned */); | |
| 77 | − if (IS_ERR(rc)) | |
| 78 | − return rc; | |
| 79 | − priv_mgr = rc; | |
| 80 | − | |
| 81 | − /* | |
| 82 | − * Create the pool for dma_buf shared memory | |
| 83 | − */ | |
| 84 | − rc = tee_shm_pool_mgr_alloc_res_mem(dmabuf_info->vaddr, | |
| 85 | − dmabuf_info->paddr, | |
| 86 | − dmabuf_info->size, PAGE_SHIFT); | |
| 87 | − if (IS_ERR(rc)) | |
| 88 | − goto err_free_priv_mgr; | |
| 89 | − dmabuf_mgr = rc; | |
| 90 | − | |
| 91 | − rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); | |
| 92 | − if (IS_ERR(rc)) | |
| 93 | − goto err_free_dmabuf_mgr; | |
| 94 | − | |
| 95 | − return rc; | |
| 96 | − | |
| 97 | −err_free_dmabuf_mgr: | |
| 98 | − tee_shm_pool_mgr_destroy(dmabuf_mgr); | |
| 99 | −err_free_priv_mgr: | |
| 100 | − tee_shm_pool_mgr_destroy(priv_mgr); | |
| 101 | − | |
| 102 | − return rc; | |
| 103 | −} | |
| 104 | −EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem); | |
| 105 | − | |
| 106 | −struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr, | |
| 107 | − phys_addr_t paddr, | |
| 108 | − size_t size, | |
| 109 | − int min_alloc_order) | |
| 56 | +struct tee_shm_pool *tee_shm_pool_alloc_res_mem(unsigned long vaddr, | |
| 57 | + phys_addr_t paddr, size_t size, | |
| 58 | + int min_alloc_order) | |
| 110 | 59 | { |
| 111 | 60 | const size_t page_mask = PAGE_SIZE - 1; |
| 112 | − struct tee_shm_pool_mgr *mgr; | |
| 61 | + struct tee_shm_pool *pool; | |
| 113 | 62 | int rc; |
| 114 | 63 | |
| 115 | 64 | /* Start and end must be page aligned */ |
| 116 | 65 | if (vaddr & page_mask || paddr & page_mask || size & page_mask) |
| 117 | 66 | return ERR_PTR(-EINVAL); |
| 118 | 67 | |
| 119 | − mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | |
| 120 | − if (!mgr) | |
| 68 | + pool = kzalloc(sizeof(*pool), GFP_KERNEL); | |
| 69 | + if (!pool) | |
| 121 | 70 | return ERR_PTR(-ENOMEM); |
| 122 | 71 | |
| 123 | − mgr->private_data = gen_pool_create(min_alloc_order, -1); | |
| 124 | − if (!mgr->private_data) { | |
| 72 | + pool->private_data = gen_pool_create(min_alloc_order, -1); | |
| 73 | + if (!pool->private_data) { | |
| 125 | 74 | rc = -ENOMEM; |
| 126 | 75 | goto err; |
| 127 | 76 | } |
| 128 | 77 | |
| 129 | − gen_pool_set_algo(mgr->private_data, gen_pool_best_fit, NULL); | |
| 130 | − rc = gen_pool_add_virt(mgr->private_data, vaddr, paddr, size, -1); | |
| 78 | + rc = gen_pool_add_virt(pool->private_data, vaddr, paddr, size, -1); | |
| 131 | 79 | if (rc) { |
| 132 | − gen_pool_destroy(mgr->private_data); | |
| 80 | + gen_pool_destroy(pool->private_data); | |
| 133 | 81 | goto err; |
| 134 | 82 | } |
| 135 | 83 | |
| 136 | − mgr->ops = &pool_ops_generic; | |
| 84 | + pool->ops = &pool_ops_generic; | |
| 137 | 85 | |
| 138 | − return mgr; | |
| 86 | + return pool; | |
| 139 | 87 | err: |
| 140 | − kfree(mgr); | |
| 88 | + kfree(pool); | |
| 141 | 89 | |
| 142 | 90 | return ERR_PTR(rc); |
| 143 | 91 | } |
| 144 | −EXPORT_SYMBOL_GPL(tee_shm_pool_mgr_alloc_res_mem); | |
| 145 | − | |
| 146 | −static bool check_mgr_ops(struct tee_shm_pool_mgr *mgr) | |
| 147 | −{ | |
| 148 | − return mgr && mgr->ops && mgr->ops->alloc && mgr->ops->free && | |
| 149 | − mgr->ops->destroy_poolmgr; | |
| 150 | −} | |
| 151 | − | |
| 152 | −struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr, | |
| 153 | − struct tee_shm_pool_mgr *dmabuf_mgr) | |
| 154 | −{ | |
| 155 | − struct tee_shm_pool *pool; | |
| 156 | − | |
| 157 | − if (!check_mgr_ops(priv_mgr) || !check_mgr_ops(dmabuf_mgr)) | |
| 158 | − return ERR_PTR(-EINVAL); | |
| 159 | − | |
| 160 | − pool = kzalloc(sizeof(*pool), GFP_KERNEL); | |
| 161 | − if (!pool) | |
| 162 | − return ERR_PTR(-ENOMEM); | |
| 163 | − | |
| 164 | − pool->private_mgr = priv_mgr; | |
| 165 | − pool->dma_buf_mgr = dmabuf_mgr; | |
| 166 | − | |
| 167 | − return pool; | |
| 168 | −} | |
| 169 | −EXPORT_SYMBOL_GPL(tee_shm_pool_alloc); | |
| 170 | − | |
| 171 | −/** | |
| 172 | − * tee_shm_pool_free() - Free a shared memory pool | |
| 173 | − * @pool: The shared memory pool to free | |
| 174 | − * | |
| 175 | − * There must be no remaining shared memory allocated from this pool when | |
| 176 | − * this function is called. | |
| 177 | − */ | |
| 178 | −void tee_shm_pool_free(struct tee_shm_pool *pool) | |
| 179 | −{ | |
| 180 | − if (pool->private_mgr) | |
| 181 | − tee_shm_pool_mgr_destroy(pool->private_mgr); | |
| 182 | − if (pool->dma_buf_mgr) | |
| 183 | − tee_shm_pool_mgr_destroy(pool->dma_buf_mgr); | |
| 184 | − kfree(pool); | |
| 185 | −} | |
| 186 | −EXPORT_SYMBOL_GPL(tee_shm_pool_free); | |
| 92 | +EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem); | |
| @@ -0,0 +1,150 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | +/* | |
| 3 | + * Copyright (c) 2017 - 2022: Samsung Electronics Co., Ltd. | |
| 4 | + * https://www.samsung.com | |
| 5 | + * Copyright (c) 2017-2022 Tesla, Inc. | |
| 6 | + * https://www.tesla.com | |
| 7 | + * | |
| 8 | + * The constants defined in this header are being used in dts | |
| 9 | + * and fsd platform driver. | |
| 10 | + */ | |
| 11 | + | |
| 12 | +#ifndef _DT_BINDINGS_CLOCK_FSD_H | |
| 13 | +#define _DT_BINDINGS_CLOCK_FSD_H | |
| 14 | + | |
| 15 | +/* CMU */ | |
| 16 | +#define DOUT_CMU_PLL_SHARED0_DIV4 1 | |
| 17 | +#define DOUT_CMU_PERIC_SHARED1DIV36 2 | |
| 18 | +#define DOUT_CMU_PERIC_SHARED0DIV3_TBUCLK 3 | |
| 19 | +#define DOUT_CMU_PERIC_SHARED0DIV20 4 | |
| 20 | +#define DOUT_CMU_PERIC_SHARED1DIV4_DMACLK 5 | |
| 21 | +#define DOUT_CMU_PLL_SHARED0_DIV6 6 | |
| 22 | +#define DOUT_CMU_FSYS0_SHARED1DIV4 7 | |
| 23 | +#define DOUT_CMU_FSYS0_SHARED0DIV4 8 | |
| 24 | +#define DOUT_CMU_FSYS1_SHARED0DIV8 9 | |
| 25 | +#define DOUT_CMU_FSYS1_SHARED0DIV4 10 | |
| 26 | +#define CMU_CPUCL_SWITCH_GATE 11 | |
| 27 | +#define DOUT_CMU_IMEM_TCUCLK 12 | |
| 28 | +#define DOUT_CMU_IMEM_ACLK 13 | |
| 29 | +#define DOUT_CMU_IMEM_DMACLK 14 | |
| 30 | +#define GAT_CMU_FSYS0_SHARED0DIV4 15 | |
| 31 | +#define CMU_NR_CLK 16 | |
| 32 | + | |
| 33 | +/* PERIC */ | |
| 34 | +#define PERIC_SCLK_UART0 1 | |
| 35 | +#define PERIC_PCLK_UART0 2 | |
| 36 | +#define PERIC_SCLK_UART1 3 | |
| 37 | +#define PERIC_PCLK_UART1 4 | |
| 38 | +#define PERIC_DMA0_IPCLKPORT_ACLK 5 | |
| 39 | +#define PERIC_DMA1_IPCLKPORT_ACLK 6 | |
| 40 | +#define PERIC_PWM0_IPCLKPORT_I_PCLK_S0 7 | |
| 41 | +#define PERIC_PWM1_IPCLKPORT_I_PCLK_S0 8 | |
| 42 | +#define PERIC_PCLK_SPI0 9 | |
| 43 | +#define PERIC_SCLK_SPI0 10 | |
| 44 | +#define PERIC_PCLK_SPI1 11 | |
| 45 | +#define PERIC_SCLK_SPI1 12 | |
| 46 | +#define PERIC_PCLK_SPI2 13 | |
| 47 | +#define PERIC_SCLK_SPI2 14 | |
| 48 | +#define PERIC_PCLK_TDM0 15 | |
| 49 | +#define PERIC_PCLK_HSI2C0 16 | |
| 50 | +#define PERIC_PCLK_HSI2C1 17 | |
| 51 | +#define PERIC_PCLK_HSI2C2 18 | |
| 52 | +#define PERIC_PCLK_HSI2C3 19 | |
| 53 | +#define PERIC_PCLK_HSI2C4 20 | |
| 54 | +#define PERIC_PCLK_HSI2C5 21 | |
| 55 | +#define PERIC_PCLK_HSI2C6 22 | |
| 56 | +#define PERIC_PCLK_HSI2C7 23 | |
| 57 | +#define PERIC_MCAN0_IPCLKPORT_CCLK 24 | |
| 58 | +#define PERIC_MCAN0_IPCLKPORT_PCLK 25 | |
| 59 | +#define PERIC_MCAN1_IPCLKPORT_CCLK 26 | |
| 60 | +#define PERIC_MCAN1_IPCLKPORT_PCLK 27 | |
| 61 | +#define PERIC_MCAN2_IPCLKPORT_CCLK 28 | |
| 62 | +#define PERIC_MCAN2_IPCLKPORT_PCLK 29 | |
| 63 | +#define PERIC_MCAN3_IPCLKPORT_CCLK 30 | |
| 64 | +#define PERIC_MCAN3_IPCLKPORT_PCLK 31 | |
| 65 | +#define PERIC_PCLK_ADCIF 32 | |
| 66 | +#define PERIC_EQOS_TOP_IPCLKPORT_CLK_PTP_REF_I 33 | |
| 67 | +#define PERIC_EQOS_TOP_IPCLKPORT_ACLK_I 34 | |
| 68 | +#define PERIC_EQOS_TOP_IPCLKPORT_HCLK_I 35 | |
| 69 | +#define PERIC_EQOS_TOP_IPCLKPORT_RGMII_CLK_I 36 | |
| 70 | +#define PERIC_EQOS_TOP_IPCLKPORT_CLK_RX_I 37 | |
| 71 | +#define PERIC_BUS_D_PERIC_IPCLKPORT_EQOSCLK 38 | |
| 72 | +#define PERIC_BUS_P_PERIC_IPCLKPORT_EQOSCLK 39 | |
| 73 | +#define PERIC_HCLK_TDM0 40 | |
| 74 | +#define PERIC_PCLK_TDM1 41 | |
| 75 | +#define PERIC_HCLK_TDM1 42 | |
| 76 | +#define PERIC_EQOS_PHYRXCLK_MUX 43 | |
| 77 | +#define PERIC_EQOS_PHYRXCLK 44 | |
| 78 | +#define PERIC_DOUT_RGMII_CLK 45 | |
| 79 | +#define PERIC_NR_CLK 46 | |
| 80 | + | |
| 81 | +/* FSYS0 */ | |
| 82 | +#define UFS0_MPHY_REFCLK_IXTAL24 1 | |
| 83 | +#define UFS0_MPHY_REFCLK_IXTAL26 2 | |
| 84 | +#define UFS1_MPHY_REFCLK_IXTAL24 3 | |
| 85 | +#define UFS1_MPHY_REFCLK_IXTAL26 4 | |
| 86 | +#define UFS0_TOP0_HCLK_BUS 5 | |
| 87 | +#define UFS0_TOP0_ACLK 6 | |
| 88 | +#define UFS0_TOP0_CLK_UNIPRO 7 | |
| 89 | +#define UFS0_TOP0_FMP_CLK 8 | |
| 90 | +#define UFS1_TOP1_HCLK_BUS 9 | |
| 91 | +#define UFS1_TOP1_ACLK 10 | |
| 92 | +#define UFS1_TOP1_CLK_UNIPRO 11 | |
| 93 | +#define UFS1_TOP1_FMP_CLK 12 | |
| 94 | +#define PCIE_SUBCTRL_INST0_DBI_ACLK_SOC 13 | |
| 95 | +#define PCIE_SUBCTRL_INST0_AUX_CLK_SOC 14 | |
| 96 | +#define PCIE_SUBCTRL_INST0_MSTR_ACLK_SOC 15 | |
| 97 | +#define PCIE_SUBCTRL_INST0_SLV_ACLK_SOC 16 | |
| 98 | +#define FSYS0_EQOS_TOP0_IPCLKPORT_CLK_PTP_REF_I 17 | |
| 99 | +#define FSYS0_EQOS_TOP0_IPCLKPORT_ACLK_I 18 | |
| 100 | +#define FSYS0_EQOS_TOP0_IPCLKPORT_HCLK_I 19 | |
| 101 | +#define FSYS0_EQOS_TOP0_IPCLKPORT_RGMII_CLK_I 20 | |
| 102 | +#define FSYS0_EQOS_TOP0_IPCLKPORT_CLK_RX_I 21 | |
| 103 | +#define FSYS0_DOUT_FSYS0_PERIBUS_GRP 22 | |
| 104 | +#define FSYS0_NR_CLK 23 | |
| 105 | + | |
| 106 | +/* FSYS1 */ | |
| 107 | +#define PCIE_LINK0_IPCLKPORT_DBI_ACLK 1 | |
| 108 | +#define PCIE_LINK0_IPCLKPORT_AUX_ACLK 2 | |
| 109 | +#define PCIE_LINK0_IPCLKPORT_MSTR_ACLK 3 | |
| 110 | +#define PCIE_LINK0_IPCLKPORT_SLV_ACLK 4 | |
| 111 | +#define PCIE_LINK1_IPCLKPORT_DBI_ACLK 5 | |
| 112 | +#define PCIE_LINK1_IPCLKPORT_AUX_ACLK 6 | |
| 113 | +#define PCIE_LINK1_IPCLKPORT_MSTR_ACLK 7 | |
| 114 | +#define PCIE_LINK1_IPCLKPORT_SLV_ACLK 8 | |
| 115 | +#define FSYS1_NR_CLK 9 | |
| 116 | + | |
| 117 | +/* IMEM */ | |
| 118 | +#define IMEM_DMA0_IPCLKPORT_ACLK 1 | |
| 119 | +#define IMEM_DMA1_IPCLKPORT_ACLK 2 | |
| 120 | +#define IMEM_WDT0_IPCLKPORT_PCLK 3 | |
| 121 | +#define IMEM_WDT1_IPCLKPORT_PCLK 4 | |
| 122 | +#define IMEM_WDT2_IPCLKPORT_PCLK 5 | |
| 123 | +#define IMEM_MCT_PCLK 6 | |
| 124 | +#define IMEM_TMU_CPU0_IPCLKPORT_I_CLK_TS 7 | |
| 125 | +#define IMEM_TMU_CPU2_IPCLKPORT_I_CLK_TS 8 | |
| 126 | +#define IMEM_TMU_TOP_IPCLKPORT_I_CLK_TS 9 | |
| 127 | +#define IMEM_TMU_GPU_IPCLKPORT_I_CLK_TS 10 | |
| 128 | +#define IMEM_TMU_GT_IPCLKPORT_I_CLK_TS 11 | |
| 129 | +#define IMEM_NR_CLK 12 | |
| 130 | + | |
| 131 | +/* MFC */ | |
| 132 | +#define MFC_MFC_IPCLKPORT_ACLK 1 | |
| 133 | +#define MFC_NR_CLK 2 | |
| 134 | + | |
| 135 | +/* CAM_CSI */ | |
| 136 | +#define CAM_CSI0_0_IPCLKPORT_I_ACLK 1 | |
| 137 | +#define CAM_CSI0_1_IPCLKPORT_I_ACLK 2 | |
| 138 | +#define CAM_CSI0_2_IPCLKPORT_I_ACLK 3 | |
| 139 | +#define CAM_CSI0_3_IPCLKPORT_I_ACLK 4 | |
| 140 | +#define CAM_CSI1_0_IPCLKPORT_I_ACLK 5 | |
| 141 | +#define CAM_CSI1_1_IPCLKPORT_I_ACLK 6 | |
| 142 | +#define CAM_CSI1_2_IPCLKPORT_I_ACLK 7 | |
| 143 | +#define CAM_CSI1_3_IPCLKPORT_I_ACLK 8 | |
| 144 | +#define CAM_CSI2_0_IPCLKPORT_I_ACLK 9 | |
| 145 | +#define CAM_CSI2_1_IPCLKPORT_I_ACLK 10 | |
| 146 | +#define CAM_CSI2_2_IPCLKPORT_I_ACLK 11 | |
| 147 | +#define CAM_CSI2_3_IPCLKPORT_I_ACLK 12 | |
| 148 | +#define CAM_CSI_NR_CLK 13 | |
| 149 | + | |
| 150 | +#endif /*_DT_BINDINGS_CLOCK_FSD_H */ | |
| @@ -18,4 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #define IMX8M_POWER_DOMAIN_MIPI_CSI2 9 |
| 19 | 19 | #define IMX8M_POWER_DOMAIN_PCIE2 10 |
| 20 | 20 | |
| 21 | +#define IMX8MQ_VPUBLK_PD_G1 0 | |
| 22 | +#define IMX8MQ_VPUBLK_PD_G2 1 | |
| 23 | + | |
| 21 | 24 | #endif |
| @@ -0,0 +1,19 @@ | ||
| 1 | +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ | |
| 2 | +/* | |
| 3 | + * Copyright (c) 2021 Amlogic, Inc. | |
| 4 | + * Author: Shunzhou Jiang <shunzhou.jiang@amlogic.com> | |
| 5 | + */ | |
| 6 | + | |
| 7 | +#ifndef _DT_BINDINGS_MESON_S4_POWER_H | |
| 8 | +#define _DT_BINDINGS_MESON_S4_POWER_H | |
| 9 | + | |
| 10 | +#define PWRC_S4_DOS_HEVC_ID 0 | |
| 11 | +#define PWRC_S4_DOS_VDEC_ID 1 | |
| 12 | +#define PWRC_S4_VPU_HDMI_ID 2 | |
| 13 | +#define PWRC_S4_USB_COMB_ID 3 | |
| 14 | +#define PWRC_S4_GE2D_ID 4 | |
| 15 | +#define PWRC_S4_ETH_ID 5 | |
| 16 | +#define PWRC_S4_DEMOD_ID 6 | |
| 17 | +#define PWRC_S4_AUDIO_ID 7 | |
| 18 | + | |
| 19 | +#endif | |
| @@ -0,0 +1,32 @@ | ||
| 1 | +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ | |
| 2 | +/* | |
| 3 | + * Copyright (c) 2022 MediaTek Inc. | |
| 4 | + * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> | |
| 5 | + */ | |
| 6 | + | |
| 7 | +#ifndef _DT_BINDINGS_POWER_MT8186_POWER_H | |
| 8 | +#define _DT_BINDINGS_POWER_MT8186_POWER_H | |
| 9 | + | |
| 10 | +#define MT8186_POWER_DOMAIN_MFG0 0 | |
| 11 | +#define MT8186_POWER_DOMAIN_MFG1 1 | |
| 12 | +#define MT8186_POWER_DOMAIN_MFG2 2 | |
| 13 | +#define MT8186_POWER_DOMAIN_MFG3 3 | |
| 14 | +#define MT8186_POWER_DOMAIN_SSUSB 4 | |
| 15 | +#define MT8186_POWER_DOMAIN_SSUSB_P1 5 | |
| 16 | +#define MT8186_POWER_DOMAIN_DIS 6 | |
| 17 | +#define MT8186_POWER_DOMAIN_IMG 7 | |
| 18 | +#define MT8186_POWER_DOMAIN_IMG2 8 | |
| 19 | +#define MT8186_POWER_DOMAIN_IPE 9 | |
| 20 | +#define MT8186_POWER_DOMAIN_CAM 10 | |
| 21 | +#define MT8186_POWER_DOMAIN_CAM_RAWA 11 | |
| 22 | +#define MT8186_POWER_DOMAIN_CAM_RAWB 12 | |
| 23 | +#define MT8186_POWER_DOMAIN_VENC 13 | |
| 24 | +#define MT8186_POWER_DOMAIN_VDEC 14 | |
| 25 | +#define MT8186_POWER_DOMAIN_WPE 15 | |
| 26 | +#define MT8186_POWER_DOMAIN_CONN_ON 16 | |
| 27 | +#define MT8186_POWER_DOMAIN_CSIRX_TOP 17 | |
| 28 | +#define MT8186_POWER_DOMAIN_ADSP_AO 18 | |
| 29 | +#define MT8186_POWER_DOMAIN_ADSP_INFRA 19 | |
| 30 | +#define MT8186_POWER_DOMAIN_ADSP_TOP 20 | |
| 31 | + | |
| 32 | +#endif /* _DT_BINDINGS_POWER_MT8186_POWER_H */ | |
| @@ -0,0 +1,46 @@ | ||
| 1 | +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ | |
| 2 | +/* | |
| 3 | + * Copyright (c) 2021 MediaTek Inc. | |
| 4 | + * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> | |
| 5 | + */ | |
| 6 | + | |
| 7 | +#ifndef _DT_BINDINGS_POWER_MT8195_POWER_H | |
| 8 | +#define _DT_BINDINGS_POWER_MT8195_POWER_H | |
| 9 | + | |
| 10 | +#define MT8195_POWER_DOMAIN_PCIE_MAC_P0 0 | |
| 11 | +#define MT8195_POWER_DOMAIN_PCIE_MAC_P1 1 | |
| 12 | +#define MT8195_POWER_DOMAIN_PCIE_PHY 2 | |
| 13 | +#define MT8195_POWER_DOMAIN_SSUSB_PCIE_PHY 3 | |
| 14 | +#define MT8195_POWER_DOMAIN_CSI_RX_TOP 4 | |
| 15 | +#define MT8195_POWER_DOMAIN_ETHER 5 | |
| 16 | +#define MT8195_POWER_DOMAIN_ADSP 6 | |
| 17 | +#define MT8195_POWER_DOMAIN_AUDIO 7 | |
| 18 | +#define MT8195_POWER_DOMAIN_MFG0 8 | |
| 19 | +#define MT8195_POWER_DOMAIN_MFG1 9 | |
| 20 | +#define MT8195_POWER_DOMAIN_MFG2 10 | |
| 21 | +#define MT8195_POWER_DOMAIN_MFG3 11 | |
| 22 | +#define MT8195_POWER_DOMAIN_MFG4 12 | |
| 23 | +#define MT8195_POWER_DOMAIN_MFG5 13 | |
| 24 | +#define MT8195_POWER_DOMAIN_MFG6 14 | |
| 25 | +#define MT8195_POWER_DOMAIN_VPPSYS0 15 | |
| 26 | +#define MT8195_POWER_DOMAIN_VDOSYS0 16 | |
| 27 | +#define MT8195_POWER_DOMAIN_VPPSYS1 17 | |
| 28 | +#define MT8195_POWER_DOMAIN_VDOSYS1 18 | |
| 29 | +#define MT8195_POWER_DOMAIN_DP_TX 19 | |
| 30 | +#define MT8195_POWER_DOMAIN_EPD_TX 20 | |
| 31 | +#define MT8195_POWER_DOMAIN_HDMI_TX 21 | |
| 32 | +#define MT8195_POWER_DOMAIN_WPESYS 22 | |
| 33 | +#define MT8195_POWER_DOMAIN_VDEC0 23 | |
| 34 | +#define MT8195_POWER_DOMAIN_VDEC1 24 | |
| 35 | +#define MT8195_POWER_DOMAIN_VDEC2 25 | |
| 36 | +#define MT8195_POWER_DOMAIN_VENC 26 | |
| 37 | +#define MT8195_POWER_DOMAIN_VENC_CORE1 27 | |
| 38 | +#define MT8195_POWER_DOMAIN_IMG 28 | |
| 39 | +#define MT8195_POWER_DOMAIN_DIP 29 | |
| 40 | +#define MT8195_POWER_DOMAIN_IPE 30 | |
| 41 | +#define MT8195_POWER_DOMAIN_CAM 31 | |
| 42 | +#define MT8195_POWER_DOMAIN_CAM_RAWA 32 | |
| 43 | +#define MT8195_POWER_DOMAIN_CAM_RAWB 33 | |
| 44 | +#define MT8195_POWER_DOMAIN_CAM_MRAW 34 | |
| 45 | + | |
| 46 | +#endif /* _DT_BINDINGS_POWER_MT8195_POWER_H */ | |
| @@ -139,6 +139,11 @@ · 138 unmodified lines | ||
| 139 | 139 | #define MDM9607_VDDMX_AO 4 |
| 140 | 140 | #define MDM9607_VDDMX_VFL 5 |
| 141 | 141 | |
| 142 | +/* MSM8226 Power Domain Indexes */ | |
| 143 | +#define MSM8226_VDDCX 0 | |
| 144 | +#define MSM8226_VDDCX_AO 1 | |
| 145 | +#define MSM8226_VDDCX_VFC 2 | |
| 146 | + | |
| 142 | 147 | /* MSM8939 Power Domains */ |
| 143 | 148 | #define MSM8939_VDDMDCX 0 |
| 144 | 149 | #define MSM8939_VDDMDCX_AO 1 |
| @@ -59,11 +59,16 @@ enum imx_sc_rm_func { · 58 unmodified lines | ||
| 59 | 59 | |
| 60 | 60 | #if IS_ENABLED(CONFIG_IMX_SCU) |
| 61 | 61 | bool imx_sc_rm_is_resource_owned(struct imx_sc_ipc *ipc, u16 resource); |
| 62 | +int imx_sc_rm_get_resource_owner(struct imx_sc_ipc *ipc, u16 resource, u8 *pt); | |
| 62 | 63 | #else |
| 63 | 64 | static inline bool |
| 64 | 65 | imx_sc_rm_is_resource_owned(struct imx_sc_ipc *ipc, u16 resource) |
| 65 | 66 | { |
| 66 | 67 | return true; |
| 67 | 68 | } |
| 69 | +static inline int imx_sc_rm_get_resource_owner(struct imx_sc_ipc *ipc, u16 resource, u8 *pt) | |
| 70 | +{ | |
| 71 | + return -EOPNOTSUPP; | |
| 72 | +} | |
| 68 | 73 | #endif |
| 69 | 74 | #endif |
| @@ -63,13 +63,21 @@ enum qcom_scm_ice_cipher { · 62 unmodified lines | ||
| 63 | 63 | |
| 64 | 64 | extern bool qcom_scm_is_available(void); |
| 65 | 65 | |
| 66 | −extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); | |
| 67 | −extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); | |
| 66 | +extern int qcom_scm_set_cold_boot_addr(void *entry); | |
| 67 | +extern int qcom_scm_set_warm_boot_addr(void *entry); | |
| 68 | 68 | extern void qcom_scm_cpu_power_down(u32 flags); |
| 69 | 69 | extern int qcom_scm_set_remote_state(u32 state, u32 id); |
| 70 | 70 | |
| 71 | +struct qcom_scm_pas_metadata { | |
| 72 | + void *ptr; | |
| 73 | + dma_addr_t phys; | |
| 74 | + ssize_t size; | |
| 75 | +}; | |
| 76 | + | |
| 71 | 77 | extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, |
| 72 | − size_t size); | |
| 78 | + size_t size, | |
| 79 | + struct qcom_scm_pas_metadata *ctx); | |
| 80 | +void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx); | |
| 73 | 81 | extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, |
| 74 | 82 | phys_addr_t size); |
| 75 | 83 | extern int qcom_scm_pas_auth_and_reset(u32 peripheral); |
| @@ -83,6 +91,7 @@ extern bool qcom_scm_restore_sec_cfg_available(void); · 7 unmodified lines | ||
| 83 | 91 | extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); |
| 84 | 92 | extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size); |
| 85 | 93 | extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); |
| 94 | +extern int qcom_scm_iommu_set_cp_pool_size(u32 spare, u32 size); | |
| 86 | 95 | extern int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size, |
| 87 | 96 | u32 cp_nonpixel_start, |
| 88 | 97 | u32 cp_nonpixel_size); |
| @@ -107,6 +116,7 @@ extern bool qcom_scm_hdcp_available(void); · 18 unmodified lines | ||
| 107 | 116 | extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, |
| 108 | 117 | u32 *resp); |
| 109 | 118 | |
| 119 | +extern int qcom_scm_iommu_set_pt_format(u32 sec_id, u32 ctx_num, u32 pt_fmt); | |
| 110 | 120 | extern int qcom_scm_qsmmu500_wait_safe_toggle(bool en); |
| 111 | 121 | |
| 112 | 122 | extern int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val, |
| @@ -42,6 +42,7 @@ struct scmi_revision_info { · 41 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | struct scmi_clock_info { |
| 44 | 44 | char name[SCMI_MAX_STR_SIZE]; |
| 45 | + unsigned int enable_latency; | |
| 45 | 46 | bool rate_discrete; |
| 46 | 47 | union { |
| 47 | 48 | struct { |
| @@ -82,6 +83,9 @@ struct scmi_clk_proto_ops { · 34 unmodified lines | ||
| 82 | 83 | u64 rate); |
| 83 | 84 | int (*enable)(const struct scmi_protocol_handle *ph, u32 clk_id); |
| 84 | 85 | int (*disable)(const struct scmi_protocol_handle *ph, u32 clk_id); |
| 86 | + int (*enable_atomic)(const struct scmi_protocol_handle *ph, u32 clk_id); | |
| 87 | + int (*disable_atomic)(const struct scmi_protocol_handle *ph, | |
| 88 | + u32 clk_id); | |
| 85 | 89 | }; |
| 86 | 90 | |
| 87 | 91 | /** |
| @@ -612,6 +616,15 @@ struct scmi_notify_ops { · 524 unmodified lines | ||
| 612 | 616 | * @devm_protocol_get: devres managed method to acquire a protocol and get specific |
| 613 | 617 | * operations and a dedicated protocol handler |
| 614 | 618 | * @devm_protocol_put: devres managed method to release a protocol |
| 619 | + * @is_transport_atomic: method to check if the underlying transport for this | |
| 620 | + * instance handle is configured to support atomic | |
| 621 | + * transactions for commands. | |
| 622 | + * Some users of the SCMI stack in the upper layers could | |
| 623 | + * be interested to know if they can assume SCMI | |
| 624 | + * command transactions associated to this handle will | |
| 625 | + * never sleep and act accordingly. | |
| 626 | + * An optional atomic threshold value could be returned | |
| 627 | + * where configured. | |
| 615 | 628 | * @notify_ops: pointer to set of notifications related operations |
| 616 | 629 | */ |
| 617 | 630 | struct scmi_handle { |
| @@ -622,6 +635,8 @@ struct scmi_handle { · 4 unmodified lines | ||
| 622 | 635 | (*devm_protocol_get)(struct scmi_device *sdev, u8 proto, |
| 623 | 636 | struct scmi_protocol_handle **ph); |
| 624 | 637 | void (*devm_protocol_put)(struct scmi_device *sdev, u8 proto); |
| 638 | + bool (*is_transport_atomic)(const struct scmi_handle *handle, | |
| 639 | + unsigned int *atomic_threshold); | |
| 625 | 640 | |
| 626 | 641 | const struct scmi_notify_ops *notify_ops; |
| 627 | 642 | }; |
| @@ -2,6 +2,88 @@ · 1 unmodified line | ||
| 2 | 2 | #ifndef __SOC_MEDIATEK_INFRACFG_H |
| 3 | 3 | #define __SOC_MEDIATEK_INFRACFG_H |
| 4 | 4 | |
| 5 | +#define MT8195_TOP_AXI_PROT_EN_STA1 0x228 | |
| 6 | +#define MT8195_TOP_AXI_PROT_EN_1_STA1 0x258 | |
| 7 | +#define MT8195_TOP_AXI_PROT_EN_SET 0x2a0 | |
| 8 | +#define MT8195_TOP_AXI_PROT_EN_CLR 0x2a4 | |
| 9 | +#define MT8195_TOP_AXI_PROT_EN_1_SET 0x2a8 | |
| 10 | +#define MT8195_TOP_AXI_PROT_EN_1_CLR 0x2ac | |
| 11 | +#define MT8195_TOP_AXI_PROT_EN_MM_SET 0x2d4 | |
| 12 | +#define MT8195_TOP_AXI_PROT_EN_MM_CLR 0x2d8 | |
| 13 | +#define MT8195_TOP_AXI_PROT_EN_MM_STA1 0x2ec | |
| 14 | +#define MT8195_TOP_AXI_PROT_EN_2_SET 0x714 | |
| 15 | +#define MT8195_TOP_AXI_PROT_EN_2_CLR 0x718 | |
| 16 | +#define MT8195_TOP_AXI_PROT_EN_2_STA1 0x724 | |
| 17 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_SET 0xb84 | |
| 18 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_CLR 0xb88 | |
| 19 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_STA1 0xb90 | |
| 20 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_1_SET 0xba4 | |
| 21 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR 0xba8 | |
| 22 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1 0xbb0 | |
| 23 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_2_SET 0xbb8 | |
| 24 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_2_CLR 0xbbc | |
| 25 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_2_STA1 0xbc4 | |
| 26 | +#define MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET 0xbcc | |
| 27 | +#define MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR 0xbd0 | |
| 28 | +#define MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1 0xbd8 | |
| 29 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_SET 0xdcc | |
| 30 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_CLR 0xdd0 | |
| 31 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_STA1 0xdd8 | |
| 32 | + | |
| 33 | +#define MT8195_TOP_AXI_PROT_EN_VDOSYS0 BIT(6) | |
| 34 | +#define MT8195_TOP_AXI_PROT_EN_VPPSYS0 BIT(10) | |
| 35 | +#define MT8195_TOP_AXI_PROT_EN_MFG1 BIT(11) | |
| 36 | +#define MT8195_TOP_AXI_PROT_EN_MFG1_2ND GENMASK(22, 21) | |
| 37 | +#define MT8195_TOP_AXI_PROT_EN_VPPSYS0_2ND BIT(23) | |
| 38 | +#define MT8195_TOP_AXI_PROT_EN_1_MFG1 GENMASK(20, 19) | |
| 39 | +#define MT8195_TOP_AXI_PROT_EN_1_CAM BIT(22) | |
| 40 | +#define MT8195_TOP_AXI_PROT_EN_2_CAM BIT(0) | |
| 41 | +#define MT8195_TOP_AXI_PROT_EN_2_MFG1_2ND GENMASK(6, 5) | |
| 42 | +#define MT8195_TOP_AXI_PROT_EN_2_MFG1 BIT(7) | |
| 43 | +#define MT8195_TOP_AXI_PROT_EN_2_AUDIO (BIT(9) | BIT(11)) | |
| 44 | +#define MT8195_TOP_AXI_PROT_EN_2_ADSP (BIT(12) | GENMASK(16, 14)) | |
| 45 | +#define MT8195_TOP_AXI_PROT_EN_MM_CAM (BIT(0) | BIT(2) | BIT(4)) | |
| 46 | +#define MT8195_TOP_AXI_PROT_EN_MM_IPE BIT(1) | |
| 47 | +#define MT8195_TOP_AXI_PROT_EN_MM_IMG BIT(3) | |
| 48 | +#define MT8195_TOP_AXI_PROT_EN_MM_VDOSYS0 GENMASK(21, 17) | |
| 49 | +#define MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1 GENMASK(8, 5) | |
| 50 | +#define MT8195_TOP_AXI_PROT_EN_MM_VENC (BIT(9) | BIT(11)) | |
| 51 | +#define MT8195_TOP_AXI_PROT_EN_MM_VENC_CORE1 (BIT(10) | BIT(12)) | |
| 52 | +#define MT8195_TOP_AXI_PROT_EN_MM_VDEC0 BIT(13) | |
| 53 | +#define MT8195_TOP_AXI_PROT_EN_MM_VDEC1 BIT(14) | |
| 54 | +#define MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1_2ND BIT(22) | |
| 55 | +#define MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1_2ND BIT(23) | |
| 56 | +#define MT8195_TOP_AXI_PROT_EN_MM_CAM_2ND BIT(24) | |
| 57 | +#define MT8195_TOP_AXI_PROT_EN_MM_IMG_2ND BIT(25) | |
| 58 | +#define MT8195_TOP_AXI_PROT_EN_MM_VENC_2ND BIT(26) | |
| 59 | +#define MT8195_TOP_AXI_PROT_EN_MM_WPESYS BIT(27) | |
| 60 | +#define MT8195_TOP_AXI_PROT_EN_MM_VDEC0_2ND BIT(28) | |
| 61 | +#define MT8195_TOP_AXI_PROT_EN_MM_VDEC1_2ND BIT(29) | |
| 62 | +#define MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1 GENMASK(31, 30) | |
| 63 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0_2ND (GENMASK(1, 0) | BIT(4) | BIT(11)) | |
| 64 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_VENC BIT(2) | |
| 65 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_VENC_CORE1 (BIT(3) | BIT(15)) | |
| 66 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_CAM (BIT(5) | BIT(17)) | |
| 67 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS1 (GENMASK(7, 6) | BIT(18)) | |
| 68 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0 GENMASK(9, 8) | |
| 69 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_VDOSYS1 BIT(10) | |
| 70 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2_2ND BIT(12) | |
| 71 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0_2ND BIT(13) | |
| 72 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS_2ND BIT(14) | |
| 73 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_IPE BIT(16) | |
| 74 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2 BIT(21) | |
| 75 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0 BIT(22) | |
| 76 | +#define MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS GENMASK(24, 23) | |
| 77 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_1_EPD_TX BIT(1) | |
| 78 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_1_DP_TX BIT(2) | |
| 79 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P0 (BIT(11) | BIT(28)) | |
| 80 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P1 (BIT(12) | BIT(29)) | |
| 81 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P0 BIT(13) | |
| 82 | +#define MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P1 BIT(14) | |
| 83 | +#define MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1 (BIT(17) | BIT(19)) | |
| 84 | +#define MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0 BIT(20) | |
| 85 | +#define MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0 BIT(21) | |
| 86 | + | |
| 5 | 87 | #define MT8192_TOP_AXI_PROT_EN_STA1 0x228 |
| 6 | 88 | #define MT8192_TOP_AXI_PROT_EN_1_STA1 0x258 |
| 7 | 89 | #define MT8192_TOP_AXI_PROT_EN_SET 0x2a0 |
| @@ -58,6 +140,54 @@ · 50 unmodified lines | ||
| 58 | 140 | #define MT8192_TOP_AXI_PROT_EN_MM_2_MDP_2ND BIT(13) |
| 59 | 141 | #define MT8192_TOP_AXI_PROT_EN_VDNR_CAM BIT(21) |
| 60 | 142 | |
| 143 | +#define MT8186_TOP_AXI_PROT_EN_SET (0x2A0) | |
| 144 | +#define MT8186_TOP_AXI_PROT_EN_CLR (0x2A4) | |
| 145 | +#define MT8186_TOP_AXI_PROT_EN_STA (0x228) | |
| 146 | +#define MT8186_TOP_AXI_PROT_EN_1_SET (0x2A8) | |
| 147 | +#define MT8186_TOP_AXI_PROT_EN_1_CLR (0x2AC) | |
| 148 | +#define MT8186_TOP_AXI_PROT_EN_1_STA (0x258) | |
| 149 | +#define MT8186_TOP_AXI_PROT_EN_2_SET (0x2B0) | |
| 150 | +#define MT8186_TOP_AXI_PROT_EN_2_CLR (0x2B4) | |
| 151 | +#define MT8186_TOP_AXI_PROT_EN_2_STA (0x26C) | |
| 152 | +#define MT8186_TOP_AXI_PROT_EN_3_SET (0x2B8) | |
| 153 | +#define MT8186_TOP_AXI_PROT_EN_3_CLR (0x2BC) | |
| 154 | +#define MT8186_TOP_AXI_PROT_EN_3_STA (0x2C8) | |
| 155 | + | |
| 156 | +/* MFG1 */ | |
| 157 | +#define MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP1 (GENMASK(28, 27)) | |
| 158 | +#define MT8186_TOP_AXI_PROT_EN_MFG1_STEP2 (GENMASK(22, 21)) | |
| 159 | +#define MT8186_TOP_AXI_PROT_EN_MFG1_STEP3 (BIT(25)) | |
| 160 | +#define MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP4 (BIT(29)) | |
| 161 | +/* DIS */ | |
| 162 | +#define MT8186_TOP_AXI_PROT_EN_1_DIS_STEP1 (GENMASK(12, 11)) | |
| 163 | +#define MT8186_TOP_AXI_PROT_EN_DIS_STEP2 (GENMASK(2, 1) | GENMASK(11, 10)) | |
| 164 | +/* IMG */ | |
| 165 | +#define MT8186_TOP_AXI_PROT_EN_1_IMG_STEP1 (BIT(23)) | |
| 166 | +#define MT8186_TOP_AXI_PROT_EN_1_IMG_STEP2 (BIT(15)) | |
| 167 | +/* IPE */ | |
| 168 | +#define MT8186_TOP_AXI_PROT_EN_1_IPE_STEP1 (BIT(24)) | |
| 169 | +#define MT8186_TOP_AXI_PROT_EN_1_IPE_STEP2 (BIT(16)) | |
| 170 | +/* CAM */ | |
| 171 | +#define MT8186_TOP_AXI_PROT_EN_1_CAM_STEP1 (GENMASK(22, 21)) | |
| 172 | +#define MT8186_TOP_AXI_PROT_EN_1_CAM_STEP2 (GENMASK(14, 13)) | |
| 173 | +/* VENC */ | |
| 174 | +#define MT8186_TOP_AXI_PROT_EN_1_VENC_STEP1 (BIT(31)) | |
| 175 | +#define MT8186_TOP_AXI_PROT_EN_1_VENC_STEP2 (BIT(19)) | |
| 176 | +/* VDEC */ | |
| 177 | +#define MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP1 (BIT(30)) | |
| 178 | +#define MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP2 (BIT(17)) | |
| 179 | +/* WPE */ | |
| 180 | +#define MT8186_TOP_AXI_PROT_EN_2_WPE_STEP1 (BIT(17)) | |
| 181 | +#define MT8186_TOP_AXI_PROT_EN_2_WPE_STEP2 (BIT(16)) | |
| 182 | +/* CONN_ON */ | |
| 183 | +#define MT8186_TOP_AXI_PROT_EN_1_CONN_ON_STEP1 (BIT(18)) | |
| 184 | +#define MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP2 (BIT(14)) | |
| 185 | +#define MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP3 (BIT(13)) | |
| 186 | +#define MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP4 (BIT(16)) | |
| 187 | +/* ADSP_TOP */ | |
| 188 | +#define MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP1 (GENMASK(12, 11)) | |
| 189 | +#define MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP2 (GENMASK(1, 0)) | |
| 190 | + | |
| 61 | 191 | #define MT8183_TOP_AXI_PROT_EN_STA1 0x228 |
| 62 | 192 | #define MT8183_TOP_AXI_PROT_EN_STA1_1 0x258 |
| 63 | 193 | #define MT8183_TOP_AXI_PROT_EN_SET 0x2a0 |
| @@ -147,6 +277,9 @@ · 83 unmodified lines | ||
| 147 | 277 | #define INFRA_TOPAXI_PROTECTEN_SET 0x0260 |
| 148 | 278 | #define INFRA_TOPAXI_PROTECTEN_CLR 0x0264 |
| 149 | 279 | |
| 280 | +#define MT8192_INFRA_CTRL 0x290 | |
| 281 | +#define MT8192_INFRA_CTRL_DISABLE_MFG2ACP BIT(9) | |
| 282 | + | |
| 150 | 283 | #define REG_INFRA_MISC 0xf00 |
| 151 | 284 | #define F_DDR_4GB_SUPPORT_EN BIT(13) |
| 152 | 285 | |
| @@ -35,7 +35,12 @@ · 34 unmodified lines | ||
| 35 | 35 | #define LLCC_WRCACHE 31 |
| 36 | 36 | #define LLCC_CVPFW 32 |
| 37 | 37 | #define LLCC_CPUSS1 33 |
| 38 | +#define LLCC_CAMEXP0 34 | |
| 39 | +#define LLCC_CPUMTE 35 | |
| 38 | 40 | #define LLCC_CPUHWT 36 |
| 41 | +#define LLCC_MDMCLAD2 37 | |
| 42 | +#define LLCC_CAMEXP1 38 | |
| 43 | +#define LLCC_AENPU 45 | |
| 39 | 44 | |
| 40 | 45 | /** |
| 41 | 46 | * struct llcc_slice_desc - Cache slice descriptor |
| @@ -83,7 +88,7 @@ struct llcc_edac_reg_data { · 41 unmodified lines | ||
| 83 | 88 | * @bitmap: Bit map to track the active slice ids |
| 84 | 89 | * @offsets: Pointer to the bank offsets array |
| 85 | 90 | * @ecc_irq: interrupt for llcc cache error detection and reporting |
| 86 | − * @major_version: Indicates the LLCC major version | |
| 91 | + * @version: Indicates the LLCC version | |
| 87 | 92 | */ |
| 88 | 93 | struct llcc_drv_data { |
| 89 | 94 | struct regmap *regmap; |
| @@ -96,7 +101,7 @@ struct llcc_drv_data { · 6 unmodified lines | ||
| 96 | 101 | unsigned long *bitmap; |
| 97 | 102 | u32 *offsets; |
| 98 | 103 | int ecc_irq; |
| 99 | − u32 major_version; | |
| 104 | + u32 version; | |
| 100 | 105 | }; |
| 101 | 106 | |
| 102 | 107 | #if IS_ENABLED(CONFIG_QCOM_LLCC) |
| @@ -10,10 +10,14 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | struct device; |
| 12 | 12 | struct firmware; |
| 13 | +struct qcom_scm_pas_metadata; | |
| 13 | 14 | |
| 14 | 15 | #if IS_ENABLED(CONFIG_QCOM_MDT_LOADER) |
| 15 | 16 | |
| 16 | 17 | ssize_t qcom_mdt_get_size(const struct firmware *fw); |
| 18 | +int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, | |
| 19 | + const char *fw_name, int pas_id, phys_addr_t mem_phys, | |
| 20 | + struct qcom_scm_pas_metadata *pas_metadata_ctx); | |
| 17 | 21 | int qcom_mdt_load(struct device *dev, const struct firmware *fw, |
| 18 | 22 | const char *fw_name, int pas_id, void *mem_region, |
| 19 | 23 | phys_addr_t mem_phys, size_t mem_size, |
| @@ -23,7 +27,8 @@ int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw, · 3 unmodified lines | ||
| 23 | 27 | const char *fw_name, int pas_id, void *mem_region, |
| 24 | 28 | phys_addr_t mem_phys, size_t mem_size, |
| 25 | 29 | phys_addr_t *reloc_base); |
| 26 | −void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len); | |
| 30 | +void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len, | |
| 31 | + const char *fw_name, struct device *dev); | |
| 27 | 32 | |
| 28 | 33 | #else /* !IS_ENABLED(CONFIG_QCOM_MDT_LOADER) */ |
| 29 | 34 | |
| @@ -32,6 +37,13 @@ static inline ssize_t qcom_mdt_get_size(const struct firmware *fw) · 2 unmodified lines | ||
| 32 | 37 | return -ENODEV; |
| 33 | 38 | } |
| 34 | 39 | |
| 40 | +static inline int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, | |
| 41 | + const char *fw_name, int pas_id, phys_addr_t mem_phys, | |
| 42 | + struct qcom_scm_pas_metadata *pas_metadata_ctx) | |
| 43 | +{ | |
| 44 | + return -ENODEV; | |
| 45 | +} | |
| 46 | + | |
| 35 | 47 | static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw, |
| 36 | 48 | const char *fw_name, int pas_id, |
| 37 | 49 | void *mem_region, phys_addr_t mem_phys, |
| @@ -51,7 +63,8 @@ static inline int qcom_mdt_load_no_init(struct device *dev, · 13 unmodified lines | ||
| 51 | 63 | } |
| 52 | 64 | |
| 53 | 65 | static inline void *qcom_mdt_read_metadata(const struct firmware *fw, |
| 54 | − size_t *data_len) | |
| 66 | + size_t *data_len, const char *fw_name, | |
| 67 | + struct device *dev) | |
| 55 | 68 | { |
| 56 | 69 | return ERR_PTR(-ENODEV); |
| 57 | 70 | } |
| @@ -645,7 +645,7 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, · 644 unmodified lines | ||
| 645 | 645 | |
| 646 | 646 | static inline struct ti_sci_resource * |
| 647 | 647 | devm_ti_sci_get_resource(const struct ti_sci_handle *handle, struct device *dev, |
| 648 | − u32 dev_id, u32 sub_type); | |
| 648 | + u32 dev_id, u32 sub_type) | |
| 649 | 649 | { |
| 650 | 650 | return ERR_PTR(-EINVAL); |
| 651 | 651 | } |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | 2 | /* |
| 3 | − * Copyright (c) 2015-2016, Linaro Limited | |
| 3 | + * Copyright (c) 2015-2022 Linaro Limited | |
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | 6 | #ifndef __TEE_DRV_H |
| @@ -20,14 +20,11 @@ · 13 unmodified lines | ||
| 20 | 20 | * specific TEE driver. |
| 21 | 21 | */ |
| 22 | 22 | |
| 23 | −#define TEE_SHM_MAPPED BIT(0) /* Memory mapped by the kernel */ | |
| 24 | −#define TEE_SHM_DMA_BUF BIT(1) /* Memory with dma-buf handle */ | |
| 25 | −#define TEE_SHM_EXT_DMA_BUF BIT(2) /* Memory with dma-buf handle */ | |
| 26 | −#define TEE_SHM_REGISTER BIT(3) /* Memory registered in secure world */ | |
| 27 | −#define TEE_SHM_USER_MAPPED BIT(4) /* Memory mapped in user space */ | |
| 28 | −#define TEE_SHM_POOL BIT(5) /* Memory allocated from pool */ | |
| 29 | −#define TEE_SHM_KERNEL_MAPPED BIT(6) /* Memory mapped in kernel space */ | |
| 30 | −#define TEE_SHM_PRIV BIT(7) /* Memory private to TEE driver */ | |
| 23 | +#define TEE_SHM_DYNAMIC BIT(0) /* Dynamic shared memory registered */ | |
| 24 | + /* in secure world */ | |
| 25 | +#define TEE_SHM_USER_MAPPED BIT(1) /* Memory mapped in user space */ | |
| 26 | +#define TEE_SHM_POOL BIT(2) /* Memory allocated from pool */ | |
| 27 | +#define TEE_SHM_PRIV BIT(3) /* Memory private to TEE driver */ | |
| 31 | 28 | |
| 32 | 29 | struct device; |
| 33 | 30 | struct tee_device; |
| @@ -221,92 +218,39 @@ struct tee_shm { · 187 unmodified lines | ||
| 221 | 218 | }; |
| 222 | 219 | |
| 223 | 220 | /** |
| 224 | − * struct tee_shm_pool_mgr - shared memory manager | |
| 221 | + * struct tee_shm_pool - shared memory pool | |
| 225 | 222 | * @ops: operations |
| 226 | 223 | * @private_data: private data for the shared memory manager |
| 227 | 224 | */ |
| 228 | −struct tee_shm_pool_mgr { | |
| 229 | − const struct tee_shm_pool_mgr_ops *ops; | |
| 225 | +struct tee_shm_pool { | |
| 226 | + const struct tee_shm_pool_ops *ops; | |
| 230 | 227 | void *private_data; |
| 231 | 228 | }; |
| 232 | 229 | |
| 233 | 230 | /** |
| 234 | − * struct tee_shm_pool_mgr_ops - shared memory pool manager operations | |
| 231 | + * struct tee_shm_pool_ops - shared memory pool operations | |
| 235 | 232 | * @alloc: called when allocating shared memory |
| 236 | 233 | * @free: called when freeing shared memory |
| 237 | − * @destroy_poolmgr: called when destroying the pool manager | |
| 234 | + * @destroy_pool: called when destroying the pool | |
| 238 | 235 | */ |
| 239 | −struct tee_shm_pool_mgr_ops { | |
| 240 | − int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm, | |
| 241 | − size_t size); | |
| 242 | − void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm); | |
| 243 | − void (*destroy_poolmgr)(struct tee_shm_pool_mgr *poolmgr); | |
| 236 | +struct tee_shm_pool_ops { | |
| 237 | + int (*alloc)(struct tee_shm_pool *pool, struct tee_shm *shm, | |
| 238 | + size_t size, size_t align); | |
| 239 | + void (*free)(struct tee_shm_pool *pool, struct tee_shm *shm); | |
| 240 | + void (*destroy_pool)(struct tee_shm_pool *pool); | |
| 244 | 241 | }; |
| 245 | 242 | |
| 246 | −/** | |
| 247 | − * tee_shm_pool_alloc() - Create a shared memory pool from shm managers | |
| 248 | − * @priv_mgr: manager for driver private shared memory allocations | |
| 249 | − * @dmabuf_mgr: manager for dma-buf shared memory allocations | |
| 250 | − * | |
| 251 | − * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied | |
| 252 | − * in @dmabuf, others will use the range provided by @priv. | |
| 253 | − * | |
| 254 | − * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. | |
| 255 | − */ | |
| 256 | −struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr, | |
| 257 | − struct tee_shm_pool_mgr *dmabuf_mgr); | |
| 258 | − | |
| 259 | 243 | /* |
| 260 | − * tee_shm_pool_mgr_alloc_res_mem() - Create a shm manager for reserved | |
| 261 | − * memory | |
| 244 | + * tee_shm_pool_alloc_res_mem() - Create a shm manager for reserved memory | |
| 262 | 245 | * @vaddr: Virtual address of start of pool |
| 263 | 246 | * @paddr: Physical address of start of pool |
| 264 | 247 | * @size: Size in bytes of the pool |
| 265 | 248 | * |
| 266 | − * @returns pointer to a 'struct tee_shm_pool_mgr' or an ERR_PTR on failure. | |
| 267 | − */ | |
| 268 | −struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr, | |
| 269 | − phys_addr_t paddr, | |
| 270 | − size_t size, | |
| 271 | − int min_alloc_order); | |
| 272 | − | |
| 273 | −/** | |
| 274 | − * tee_shm_pool_mgr_destroy() - Free a shared memory manager | |
| 275 | − */ | |
| 276 | −static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm) | |
| 277 | −{ | |
| 278 | − poolm->ops->destroy_poolmgr(poolm); | |
| 279 | −} | |
| 280 | − | |
| 281 | −/** | |
| 282 | − * struct tee_shm_pool_mem_info - holds information needed to create a shared | |
| 283 | − * memory pool | |
| 284 | − * @vaddr: Virtual address of start of pool | |
| 285 | − * @paddr: Physical address of start of pool | |
| 286 | − * @size: Size in bytes of the pool | |
| 287 | − */ | |
| 288 | −struct tee_shm_pool_mem_info { | |
| 289 | − unsigned long vaddr; | |
| 290 | − phys_addr_t paddr; | |
| 291 | − size_t size; | |
| 292 | −}; | |
| 293 | − | |
| 294 | −/** | |
| 295 | − * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved | |
| 296 | − * memory range | |
| 297 | − * @priv_info: Information for driver private shared memory pool | |
| 298 | − * @dmabuf_info: Information for dma-buf shared memory pool | |
| 299 | − * | |
| 300 | − * Start and end of pools will must be page aligned. | |
| 301 | − * | |
| 302 | − * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied | |
| 303 | − * in @dmabuf, others will use the range provided by @priv. | |
| 304 | − * | |
| 305 | 249 | * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. |
| 306 | 250 | */ |
| 307 | −struct tee_shm_pool * | |
| 308 | −tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info, | |
| 309 | − struct tee_shm_pool_mem_info *dmabuf_info); | |
| 251 | +struct tee_shm_pool *tee_shm_pool_alloc_res_mem(unsigned long vaddr, | |
| 252 | + phys_addr_t paddr, size_t size, | |
| 253 | + int min_alloc_order); | |
| 310 | 254 | |
| 311 | 255 | /** |
| 312 | 256 | * tee_shm_pool_free() - Free a shared memory pool |
| @@ -315,7 +259,10 @@ tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info, · 2 unmodified lines | ||
| 315 | 259 | * The must be no remaining shared memory allocated from this pool when |
| 316 | 260 | * this function is called. |
| 317 | 261 | */ |
| 318 | −void tee_shm_pool_free(struct tee_shm_pool *pool); | |
| 262 | +static inline void tee_shm_pool_free(struct tee_shm_pool *pool) | |
| 263 | +{ | |
| 264 | + pool->ops->destroy_pool(pool); | |
| 265 | +} | |
| 319 | 266 | |
| 320 | 267 | /** |
| 321 | 268 | * tee_get_drvdata() - Return driver_data pointer |
| @@ -323,43 +270,20 @@ void tee_shm_pool_free(struct tee_shm_pool *pool); · 1 unmodified line | ||
| 323 | 270 | */ |
| 324 | 271 | void *tee_get_drvdata(struct tee_device *teedev); |
| 325 | 272 | |
| 326 | −/** | |
| 327 | − * tee_shm_alloc() - Allocate shared memory | |
| 328 | − * @ctx: Context that allocates the shared memory | |
| 329 | − * @size: Requested size of shared memory | |
| 330 | − * @flags: Flags setting properties for the requested shared memory. | |
| 331 | − * | |
| 332 | − * Memory allocated as global shared memory is automatically freed when the | |
| 333 | − * TEE file pointer is closed. The @flags field uses the bits defined by | |
| 334 | − * TEE_SHM_* above. TEE_SHM_MAPPED must currently always be set. If | |
| 335 | − * TEE_SHM_DMA_BUF global shared memory will be allocated and associated | |
| 336 | − * with a dma-buf handle, else driver private memory. | |
| 337 | − * | |
| 338 | − * @returns a pointer to 'struct tee_shm' | |
| 339 | − */ | |
| 340 | −struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags); | |
| 273 | +struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size); | |
| 341 | 274 | struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size); |
| 342 | 275 | |
| 343 | −/** | |
| 344 | − * tee_shm_register() - Register shared memory buffer | |
| 345 | − * @ctx: Context that registers the shared memory | |
| 346 | − * @addr: Address is userspace of the shared buffer | |
| 347 | − * @length: Length of the shared buffer | |
| 348 | − * @flags: Flags setting properties for the requested shared memory. | |
| 349 | − * | |
| 350 | − * @returns a pointer to 'struct tee_shm' | |
| 351 | − */ | |
| 352 | −struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, | |
| 353 | − size_t length, u32 flags); | |
| 276 | +struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx, | |
| 277 | + void *addr, size_t length); | |
| 354 | 278 | |
| 355 | 279 | /** |
| 356 | − * tee_shm_is_registered() - Check if shared memory object in registered in TEE | |
| 280 | + * tee_shm_is_dynamic() - Check if shared memory object is of the dynamic kind | |
| 357 | 281 | * @shm: Shared memory handle |
| 358 | − * @returns true if object is registered in TEE | |
| 282 | + * @returns true if object is dynamic shared memory | |
| 359 | 283 | */ |
| 360 | −static inline bool tee_shm_is_registered(struct tee_shm *shm) | |
| 284 | +static inline bool tee_shm_is_dynamic(struct tee_shm *shm) | |
| 361 | 285 | { |
| 362 | − return shm && (shm->flags & TEE_SHM_REGISTER); | |
| 286 | + return shm && (shm->flags & TEE_SHM_DYNAMIC); | |
| 363 | 287 | } |
| 364 | 288 | |
| 365 | 289 | /** |
| @@ -931,7 +931,7 @@ enum mrq_reset_commands { · 930 unmodified lines | ||
| 931 | 931 | * @brief Request with MRQ_RESET |
| 932 | 932 | * |
| 933 | 933 | * Used by the sender of an #MRQ_RESET message to request BPMP to |
| 934 | − * assert or or deassert a given reset line. | |
| 934 | + * assert or deassert a given reset line. | |
| 935 | 935 | */ |
| 936 | 936 | struct mrq_reset_request { |
| 937 | 937 | /** @brief Reset action to perform (@ref mrq_reset_commands) */ |
| @@ -33,6 +33,34 @@ TRACE_EVENT(scmi_xfer_begin, · 32 unmodified lines | ||
| 33 | 33 | __entry->seq, __entry->poll) |
| 34 | 34 | ); |
| 35 | 35 | |
| 36 | +TRACE_EVENT(scmi_xfer_response_wait, | |
| 37 | + TP_PROTO(int transfer_id, u8 msg_id, u8 protocol_id, u16 seq, | |
| 38 | + u32 timeout, bool poll), | |
| 39 | + TP_ARGS(transfer_id, msg_id, protocol_id, seq, timeout, poll), | |
| 40 | + | |
| 41 | + TP_STRUCT__entry( | |
| 42 | + __field(int, transfer_id) | |
| 43 | + __field(u8, msg_id) | |
| 44 | + __field(u8, protocol_id) | |
| 45 | + __field(u16, seq) | |
| 46 | + __field(u32, timeout) | |
| 47 | + __field(bool, poll) | |
| 48 | + ), | |
| 49 | + | |
| 50 | + TP_fast_assign( | |
| 51 | + __entry->transfer_id = transfer_id; | |
| 52 | + __entry->msg_id = msg_id; | |
| 53 | + __entry->protocol_id = protocol_id; | |
| 54 | + __entry->seq = seq; | |
| 55 | + __entry->timeout = timeout; | |
| 56 | + __entry->poll = poll; | |
| 57 | + ), | |
| 58 | + | |
| 59 | + TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u tmo_ms=%u poll=%u", | |
| 60 | + __entry->transfer_id, __entry->msg_id, __entry->protocol_id, | |
| 61 | + __entry->seq, __entry->timeout, __entry->poll) | |
| 62 | +); | |
| 63 | + | |
| 36 | 64 | TRACE_EVENT(scmi_xfer_end, |
| 37 | 65 | TP_PROTO(int transfer_id, u8 msg_id, u8 protocol_id, u16 seq, |
| 38 | 66 | int status), |
| @@ -70,17 +70,15 @@ static int trusted_tee_seal(struct trusted_key_payload *p, char *datablob) · 69 unmodified lines | ||
| 70 | 70 | memset(&inv_arg, 0, sizeof(inv_arg)); |
| 71 | 71 | memset(¶m, 0, sizeof(param)); |
| 72 | 72 | |
| 73 | − reg_shm_in = tee_shm_register(pvt_data.ctx, (unsigned long)p->key, | |
| 74 | − p->key_len, TEE_SHM_DMA_BUF | | |
| 75 | − TEE_SHM_KERNEL_MAPPED); | |
| 73 | + reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->key, | |
| 74 | + p->key_len); | |
| 76 | 75 | if (IS_ERR(reg_shm_in)) { |
| 77 | 76 | dev_err(pvt_data.dev, "key shm register failed\n"); |
| 78 | 77 | return PTR_ERR(reg_shm_in); |
| 79 | 78 | } |
| 80 | 79 | |
| 81 | − reg_shm_out = tee_shm_register(pvt_data.ctx, (unsigned long)p->blob, | |
| 82 | − sizeof(p->blob), TEE_SHM_DMA_BUF | | |
| 83 | − TEE_SHM_KERNEL_MAPPED); | |
| 80 | + reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob, | |
| 81 | + sizeof(p->blob)); | |
| 84 | 82 | if (IS_ERR(reg_shm_out)) { |
| 85 | 83 | dev_err(pvt_data.dev, "blob shm register failed\n"); |
| 86 | 84 | ret = PTR_ERR(reg_shm_out); |
| @@ -131,17 +129,15 @@ static int trusted_tee_unseal(struct trusted_key_payload *p, char *datablob) · 44 unmodified lines | ||
| 131 | 129 | memset(&inv_arg, 0, sizeof(inv_arg)); |
| 132 | 130 | memset(¶m, 0, sizeof(param)); |
| 133 | 131 | |
| 134 | − reg_shm_in = tee_shm_register(pvt_data.ctx, (unsigned long)p->blob, | |
| 135 | − p->blob_len, TEE_SHM_DMA_BUF | | |
| 136 | − TEE_SHM_KERNEL_MAPPED); | |
| 132 | + reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob, | |
| 133 | + p->blob_len); | |
| 137 | 134 | if (IS_ERR(reg_shm_in)) { |
| 138 | 135 | dev_err(pvt_data.dev, "blob shm register failed\n"); |
| 139 | 136 | return PTR_ERR(reg_shm_in); |
| 140 | 137 | } |
| 141 | 138 | |
| 142 | − reg_shm_out = tee_shm_register(pvt_data.ctx, (unsigned long)p->key, | |
| 143 | − sizeof(p->key), TEE_SHM_DMA_BUF | | |
| 144 | − TEE_SHM_KERNEL_MAPPED); | |
| 139 | + reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->key, | |
| 140 | + sizeof(p->key)); | |
| 145 | 141 | if (IS_ERR(reg_shm_out)) { |
| 146 | 142 | dev_err(pvt_data.dev, "key shm register failed\n"); |
| 147 | 143 | ret = PTR_ERR(reg_shm_out); |
| @@ -192,8 +188,7 @@ static int trusted_tee_get_random(unsigned char *key, size_t key_len) · 44 unmodified lines | ||
| 192 | 188 | memset(&inv_arg, 0, sizeof(inv_arg)); |
| 193 | 189 | memset(¶m, 0, sizeof(param)); |
| 194 | 190 | |
| 195 | − reg_shm = tee_shm_register(pvt_data.ctx, (unsigned long)key, key_len, | |
| 196 | − TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED); | |
| 191 | + reg_shm = tee_shm_register_kernel_buf(pvt_data.ctx, key, key_len); | |
| 197 | 192 | if (IS_ERR(reg_shm)) { |
| 198 | 193 | dev_err(pvt_data.dev, "key shm register failed\n"); |
| 199 | 194 | return PTR_ERR(reg_shm); |