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

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

Pull ARM SoC driver updates from Arnd Bergmann:
"The most noteworthy SoC driver changes this time include:

- The TEE subsystem gains an in-kernel interface to access the TEE
from device drivers.

- The reset controller subsystem gains a driver for the Qualcomm
Snapdragon 845 Power Domain Controller.

- The Xilinx Zynq platform now has a firmware interface for its
platform management unit. This contains a firmware "ioctl"
interface that was a little controversial at first, but the version
we merged solved that by not exposing arbitrary firmware calls to
user space.

- The Amlogic Meson platform gains a "canvas" driver that is used for
video processing and shared between different high-level drivers.

The rest is more of the usual, mostly related to SoC specific power
management support and core drivers in drivers/soc:

- Several Renesas SoCs (RZ/G1N, RZ/G2M, R-Car V3M, RZ/A2M) gain new
features related to power and reset control.

- The Mediatek mt8183 and mt6765 SoC platforms gain support for their
respective power management chips.

- A new driver for NXP i.MX8, which need a firmware interface for
power management.

- The SCPI firmware interface now contains support estimating power
usage of performance states

- The NVIDIA Tegra "pmc" driver gains a few new features, in
particular a pinctrl interface for configuring the pads.

- Lots of small changes for Qualcomm, in particular the "smem" device
driver.

- Some cleanups for the TI OMAP series related to their sysc
controller.

Additional cleanups and bugfixes in SoC specific drivers include the
Meson, Keystone, NXP, AT91, Sunxi, Actions, and Tegra platforms"

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (129 commits)
firmware: tegra: bpmp: Implement suspend/resume support
drivers: clk: Add ZynqMP clock driver
dt-bindings: clock: Add bindings for ZynqMP clock driver
firmware: xilinx: Add zynqmp IOCTL API for device control
Documentation: xilinx: Add documentation for eemi APIs
MAINTAINERS: imx: include drivers/firmware/imx path
firmware: imx: add misc svc support
firmware: imx: add SCU firmware driver support
reset: Fix potential use-after-free in __of_reset_control_get()
dt-bindings: arm: fsl: add scu binding doc
soc: fsl: qbman: add interrupt coalesce changing APIs
soc: fsl: bman_portals: defer probe after bman's probe
soc: fsl: qbman: Use last response to determine valid bit
soc: fsl: qbman: Add 64 bit DMA addressing requirement to QBMan
soc: fsl: qbman: replace CPU 0 with any online CPU in hotplug handlers
soc: fsl: qbman: Check if CPU is offline when initializing portals
reset: qcom: PDC Global (Power Domain Controller) reset controller
dt-bindings: reset: Add PDC Global binding for SDM845 SoCs
reset: Grammar s/more then once/more than once/
bus: ti-sysc: Just use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS
...

+7174 -785
+183
Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
··· 1 + NXP i.MX System Controller Firmware (SCFW) 2 + -------------------------------------------------------------------- 3 + 4 + The System Controller Firmware (SCFW) is a low-level system function 5 + which runs on a dedicated Cortex-M core to provide power, clock, and 6 + resource management. It exists on some i.MX8 processors. e.g. i.MX8QM 7 + (QM, QP), and i.MX8QX (QXP, DX). 8 + 9 + The AP communicates with the SC using a multi-ported MU module found 10 + in the LSIO subsystem. The current definition of this MU module provides 11 + 5 remote AP connections to the SC to support up to 5 execution environments 12 + (TZ, HV, standard Linux, etc.). The SC side of this MU module interfaces 13 + with the LSIO DSC IP bus. The SC firmware will communicate with this MU 14 + using the MSI bus. 15 + 16 + System Controller Device Node: 17 + ============================================================ 18 + 19 + The scu node with the following properties shall be under the /firmware/ node. 20 + 21 + Required properties: 22 + ------------------- 23 + - compatible: should be "fsl,imx-scu". 24 + - mbox-names: should include "tx0", "tx1", "tx2", "tx3", 25 + "rx0", "rx1", "rx2", "rx3". 26 + - mboxes: List of phandle of 4 MU channels for tx and 4 MU channels 27 + for rx. All 8 MU channels must be in the same MU instance. 28 + Cross instances are not allowed. The MU instance can only 29 + be one of LSIO MU0~M4 for imx8qxp and imx8qm. Users need 30 + to make sure use the one which is not conflict with other 31 + execution environments. e.g. ATF. 32 + Note: 33 + Channel 0 must be "tx0" or "rx0". 34 + Channel 1 must be "tx1" or "rx1". 35 + Channel 2 must be "tx2" or "rx2". 36 + Channel 3 must be "tx3" or "rx3". 37 + e.g. 38 + mboxes = <&lsio_mu1 0 0 39 + &lsio_mu1 0 1 40 + &lsio_mu1 0 2 41 + &lsio_mu1 0 3 42 + &lsio_mu1 1 0 43 + &lsio_mu1 1 1 44 + &lsio_mu1 1 2 45 + &lsio_mu1 1 3>; 46 + See Documentation/devicetree/bindings/mailbox/fsl,mu.txt 47 + for detailed mailbox binding. 48 + 49 + i.MX SCU Client Device Node: 50 + ============================================================ 51 + 52 + Client nodes are maintained as children of the relevant IMX-SCU device node. 53 + 54 + Power domain bindings based on SCU Message Protocol 55 + ------------------------------------------------------------ 56 + 57 + This binding for the SCU power domain providers uses the generic power 58 + domain binding[2]. 59 + 60 + Required properties: 61 + - compatible: Should be "fsl,scu-pd". 62 + - #address-cells: Should be 1. 63 + - #size-cells: Should be 0. 64 + 65 + Required properties for power domain sub nodes: 66 + - #power-domain-cells: Must be 0. 67 + 68 + Optional Properties: 69 + - reg: Resource ID of this power domain. 70 + No exist means uncontrollable by user. 71 + See detailed Resource ID list from: 72 + include/dt-bindings/power/imx-rsrc.h 73 + - power-domains: phandle pointing to the parent power domain. 74 + 75 + Clock bindings based on SCU Message Protocol 76 + ------------------------------------------------------------ 77 + 78 + This binding uses the common clock binding[1]. 79 + 80 + Required properties: 81 + - compatible: Should be "fsl,imx8qxp-clock". 82 + - #clock-cells: Should be 1. Contains the Clock ID value. 83 + - clocks: List of clock specifiers, must contain an entry for 84 + each required entry in clock-names 85 + - clock-names: Should include entries "xtal_32KHz", "xtal_24MHz" 86 + 87 + The clock consumer should specify the desired clock by having the clock 88 + ID in its "clocks" phandle cell. 89 + 90 + See the full list of clock IDs from: 91 + include/dt-bindings/clock/imx8qxp-clock.h 92 + 93 + Pinctrl bindings based on SCU Message Protocol 94 + ------------------------------------------------------------ 95 + 96 + This binding uses the i.MX common pinctrl binding[3]. 97 + 98 + Required properties: 99 + - compatible: Should be "fsl,imx8qxp-iomuxc". 100 + 101 + Required properties for Pinctrl sub nodes: 102 + - fsl,pins: Each entry consists of 3 integers which represents 103 + the mux and config setting for one pin. The first 2 104 + integers <pin_id mux_mode> are specified using a 105 + PIN_FUNC_ID macro, which can be found in 106 + <dt-bindings/pinctrl/pads-imx8qxp.h>. 107 + The last integer CONFIG is the pad setting value like 108 + pull-up on this pin. 109 + 110 + Please refer to i.MX8QXP Reference Manual for detailed 111 + CONFIG settings. 112 + 113 + [1] Documentation/devicetree/bindings/clock/clock-bindings.txt 114 + [2] Documentation/devicetree/bindings/power/power_domain.txt 115 + [3] Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt 116 + 117 + Example (imx8qxp): 118 + ------------- 119 + lsio_mu1: mailbox@5d1c0000 { 120 + ... 121 + #mbox-cells = <2>; 122 + }; 123 + 124 + firmware { 125 + scu { 126 + compatible = "fsl,imx-scu"; 127 + mbox-names = "tx0", "tx1", "tx2", "tx3", 128 + "rx0", "rx1", "rx2", "rx3"; 129 + mboxes = <&lsio_mu1 0 0 130 + &lsio_mu1 0 1 131 + &lsio_mu1 0 2 132 + &lsio_mu1 0 3 133 + &lsio_mu1 1 0 134 + &lsio_mu1 1 1 135 + &lsio_mu1 1 2 136 + &lsio_mu1 1 3>; 137 + 138 + clk: clk { 139 + compatible = "fsl,imx8qxp-clk"; 140 + #clock-cells = <1>; 141 + }; 142 + 143 + iomuxc { 144 + compatible = "fsl,imx8qxp-iomuxc"; 145 + 146 + pinctrl_lpuart0: lpuart0grp { 147 + fsl,pins = < 148 + SC_P_UART0_RX_ADMA_UART0_RX 0x06000020 149 + SC_P_UART0_TX_ADMA_UART0_TX 0x06000020 150 + >; 151 + }; 152 + ... 153 + }; 154 + 155 + imx8qx-pm { 156 + compatible = "fsl,scu-pd"; 157 + #address-cells = <1>; 158 + #size-cells = <0>; 159 + 160 + pd_dma: dma-power-domain { 161 + #power-domain-cells = <0>; 162 + 163 + pd_dma_lpuart0: dma-lpuart0@57 { 164 + reg = <SC_R_UART_0>; 165 + #power-domain-cells = <0>; 166 + power-domains = <&pd_dma>; 167 + }; 168 + ... 169 + }; 170 + ... 171 + }; 172 + }; 173 + }; 174 + 175 + serial@5a060000 { 176 + ... 177 + pinctrl-names = "default"; 178 + pinctrl-0 = <&pinctrl_lpuart0>; 179 + clocks = <&clk IMX8QXP_UART0_CLK>, 180 + <&clk IMX8QXP_UART0_IPG_CLK>; 181 + clock-names = "per", "ipg"; 182 + power-domains = <&pd_dma_lpuart0>; 183 + };
+4
Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
··· 45 45 debug_messages - Map the Debug message region 46 46 - reg: register space corresponding to the debug_messages 47 47 - ti,system-reboot-controller: If system reboot can be triggered by SoC reboot 48 + - ti,host-id: Integer value corresponding to the host ID assigned by Firmware 49 + for identification of host processing entities such as virtual 50 + machines 48 51 49 52 Example (K2G): 50 53 ------------- 51 54 pmmc: pmmc { 52 55 compatible = "ti,k2g-sci"; 56 + ti,host-id = <2>; 53 57 mbox-names = "rx", "tx"; 54 58 mboxes= <&msgmgr &msgmgr_proxy_pmmc_rx>, 55 59 <&msgmgr &msgmgr_proxy_pmmc_tx>;
+17 -2
Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
··· 16 16 - reg: 17 17 Usage: required 18 18 Value Type: <prop-encoded-array> 19 - Definition: Start address and the the size of the register region. 19 + Definition: The first element specifies the llcc base start address and 20 + the size of the register region. The second element specifies 21 + the llcc broadcast base address and size of the register region. 22 + 23 + - reg-names: 24 + Usage: required 25 + Value Type: <stringlist> 26 + Definition: Register region names. Must be "llcc_base", "llcc_broadcast_base". 27 + 28 + - interrupts: 29 + Usage: required 30 + Definition: The interrupt is associated with the llcc edac device. 31 + It's used for llcc cache single and double bit error detection 32 + and reporting. 20 33 21 34 Example: 22 35 23 36 cache-controller@1100000 { 24 37 compatible = "qcom,sdm845-llcc"; 25 - reg = <0x1100000 0x250000>; 38 + reg = <0x1100000 0x200000>, <0x1300000 0x50000> ; 39 + reg-names = "llcc_base", "llcc_broadcast_base"; 40 + interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>; 26 41 };
+21 -12
Documentation/devicetree/bindings/firmware/qcom,scm.txt
··· 7 7 8 8 Required properties: 9 9 - compatible: must contain one of the following: 10 - * "qcom,scm-apq8064" for APQ8064 platforms 11 - * "qcom,scm-msm8660" for MSM8660 platforms 12 - * "qcom,scm-msm8690" for MSM8690 platforms 13 - * "qcom,scm-msm8996" for MSM8996 platforms 14 - * "qcom,scm-ipq4019" for IPQ4019 platforms 15 - * "qcom,scm" for later processors (MSM8916, APQ8084, MSM8974, etc) 16 - - clocks: One to three clocks may be required based on compatible. 17 - * No clock required for "qcom,scm-msm8996", "qcom,scm-ipq4019" 18 - * Only core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660", and "qcom,scm-msm8960" 19 - * Core, iface, and bus clocks required for "qcom,scm" 10 + * "qcom,scm-apq8064" 11 + * "qcom,scm-apq8084" 12 + * "qcom,scm-msm8660" 13 + * "qcom,scm-msm8916" 14 + * "qcom,scm-msm8960" 15 + * "qcom,scm-msm8974" 16 + * "qcom,scm-msm8996" 17 + * "qcom,scm-msm8998" 18 + * "qcom,scm-ipq4019" 19 + * "qcom,scm-sdm845" 20 + and: 21 + * "qcom,scm" 22 + - clocks: Specifies clocks needed by the SCM interface, if any: 23 + * core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660" and 24 + "qcom,scm-msm8960" 25 + * core, iface and bus clocks required for "qcom,scm-apq8084", 26 + "qcom,scm-msm8916" and "qcom,scm-msm8974" 20 27 - clock-names: Must contain "core" for the core clock, "iface" for the interface 21 28 clock and "bus" for the bus clock per the requirements of the compatible. 22 29 - qcom,dload-mode: phandle to the TCSR hardware block and offset of the ··· 33 26 34 27 firmware { 35 28 scm { 36 - compatible = "qcom,scm"; 37 - clocks = <&gcc GCC_CRYPTO_CLK> , <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>; 29 + compatible = "qcom,msm8916", "qcom,scm"; 30 + clocks = <&gcc GCC_CRYPTO_CLK> , 31 + <&gcc GCC_CRYPTO_AXI_CLK>, 32 + <&gcc GCC_CRYPTO_AHB_CLK>; 38 33 clock-names = "core", "bus", "iface"; 39 34 }; 40 35 };
+82
Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
··· 1 + ----------------------------------------------------------------- 2 + Device Tree Bindings for the Xilinx Zynq MPSoC Firmware Interface 3 + ----------------------------------------------------------------- 4 + 5 + The zynqmp-firmware node describes the interface to platform firmware. 6 + ZynqMP has an interface to communicate with secure firmware. Firmware 7 + driver provides an interface to firmware APIs. Interface APIs can be 8 + used by any driver to communicate to PMUFW(Platform Management Unit). 9 + These requests include clock management, pin control, device control, 10 + power management service, FPGA service and other platform management 11 + services. 12 + 13 + Required properties: 14 + - compatible: Must contain: "xlnx,zynqmp-firmware" 15 + - method: The method of calling the PM-API firmware layer. 16 + Permitted values are: 17 + - "smc" : SMC #0, following the SMCCC 18 + - "hvc" : HVC #0, following the SMCCC 19 + 20 + -------------------------------------------------------------------------- 21 + Device Tree Clock bindings for the Zynq Ultrascale+ MPSoC controlled using 22 + Zynq MPSoC firmware interface 23 + -------------------------------------------------------------------------- 24 + The clock controller is a h/w block of Zynq Ultrascale+ MPSoC clock 25 + tree. It reads required input clock frequencies from the devicetree and acts 26 + as clock provider for all clock consumers of PS clocks. 27 + 28 + See clock_bindings.txt for more information on the generic clock bindings. 29 + 30 + Required properties: 31 + - #clock-cells: Must be 1 32 + - compatible: Must contain: "xlnx,zynqmp-clk" 33 + - clocks: List of clock specifiers which are external input 34 + clocks to the given clock controller. Please refer 35 + the next section to find the input clocks for a 36 + given controller. 37 + - clock-names: List of clock names which are exteral input clocks 38 + to the given clock controller. Please refer to the 39 + clock bindings for more details. 40 + 41 + Input clocks for zynqmp Ultrascale+ clock controller: 42 + 43 + The Zynq UltraScale+ MPSoC has one primary and four alternative reference clock 44 + inputs. These required clock inputs are: 45 + - pss_ref_clk (PS reference clock) 46 + - video_clk (reference clock for video system ) 47 + - pss_alt_ref_clk (alternative PS reference clock) 48 + - aux_ref_clk 49 + - gt_crx_ref_clk (transceiver reference clock) 50 + 51 + The following strings are optional parameters to the 'clock-names' property in 52 + order to provide an optional (E)MIO clock source: 53 + - swdt0_ext_clk 54 + - swdt1_ext_clk 55 + - gem0_emio_clk 56 + - gem1_emio_clk 57 + - gem2_emio_clk 58 + - gem3_emio_clk 59 + - mio_clk_XX # with XX = 00..77 60 + - mio_clk_50_or_51 #for the mux clock to gem tsu from 50 or 51 61 + 62 + 63 + Output clocks are registered based on clock information received 64 + from firmware. Output clocks indexes are mentioned in 65 + include/dt-bindings/clock/xlnx,zynqmp-clk.h. 66 + 67 + ------- 68 + Example 69 + ------- 70 + 71 + firmware { 72 + zynqmp_firmware: zynqmp-firmware { 73 + compatible = "xlnx,zynqmp-firmware"; 74 + method = "smc"; 75 + zynqmp_clk: clock-controller { 76 + #clock-cells = <1>; 77 + compatible = "xlnx,zynqmp-clk"; 78 + clocks = <&pss_ref_clk>, <&video_clk>, <&pss_alt_ref_clk>, <&aux_ref_clk>, <&gt_crx_ref_clk>; 79 + clock-names = "pss_ref_clk", "video_clk", "pss_alt_ref_clk","aux_ref_clk", "gt_crx_ref_clk"; 80 + }; 81 + }; 82 + };
+2
Documentation/devicetree/bindings/power/renesas,apmu.txt
··· 8 8 - compatible: Should be "renesas,<soctype>-apmu", "renesas,apmu" as fallback. 9 9 Examples with soctypes are: 10 10 - "renesas,r8a7743-apmu" (RZ/G1M) 11 + - "renesas,r8a7744-apmu" (RZ/G1N) 11 12 - "renesas,r8a7745-apmu" (RZ/G1E) 13 + - "renesas,r8a77470-apmu" (RZ/G1C) 12 14 - "renesas,r8a7790-apmu" (R-Car H2) 13 15 - "renesas,r8a7791-apmu" (R-Car M2-W) 14 16 - "renesas,r8a7792-apmu" (R-Car V2H)
+3
Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
··· 8 8 Required properties: 9 9 - compatible: Must contain exactly one of the following: 10 10 - "renesas,r8a7743-sysc" (RZ/G1M) 11 + - "renesas,r8a7744-sysc" (RZ/G1N) 11 12 - "renesas,r8a7745-sysc" (RZ/G1E) 12 13 - "renesas,r8a77470-sysc" (RZ/G1C) 14 + - "renesas,r8a774a1-sysc" (RZ/G2M) 15 + - "renesas,r8a774c0-sysc" (RZ/G2E) 13 16 - "renesas,r8a7779-sysc" (R-Car H1) 14 17 - "renesas,r8a7790-sysc" (R-Car H2) 15 18 - "renesas,r8a7791-sysc" (R-Car M2-W)
+52
Documentation/devicetree/bindings/reset/qcom,pdc-global.txt
··· 1 + PDC Global 2 + ====================================== 3 + 4 + This binding describes a reset-controller found on PDC-Global (Power Domain 5 + Controller) block for Qualcomm Technologies Inc SDM845 SoCs. 6 + 7 + Required properties: 8 + - compatible: 9 + Usage: required 10 + Value type: <string> 11 + Definition: must be: 12 + "qcom,sdm845-pdc-global" 13 + 14 + - reg: 15 + Usage: required 16 + Value type: <prop-encoded-array> 17 + Definition: must specify the base address and size of the register 18 + space. 19 + 20 + - #reset-cells: 21 + Usage: required 22 + Value type: <uint> 23 + Definition: must be 1; cell entry represents the reset index. 24 + 25 + Example: 26 + 27 + pdc_reset: reset-controller@b2e0000 { 28 + compatible = "qcom,sdm845-pdc-global"; 29 + reg = <0xb2e0000 0x20000>; 30 + #reset-cells = <1>; 31 + }; 32 + 33 + PDC reset clients 34 + ====================================== 35 + 36 + Device nodes that need access to reset lines should 37 + specify them as a reset phandle in their corresponding node as 38 + specified in reset.txt. 39 + 40 + For a list of all valid reset indices see 41 + <dt-bindings/reset/qcom,sdm845-pdc.h> 42 + 43 + Example: 44 + 45 + modem-pil@4080000 { 46 + ... 47 + 48 + resets = <&pdc_reset PDC_MODEM_SYNC_RESET>; 49 + reset-names = "pdc_reset"; 50 + 51 + ... 52 + };
+3
Documentation/devicetree/bindings/reset/renesas,rst.txt
··· 16 16 - "renesas,<soctype>-rst" for R-Car Gen2 and Gen3, and RZ/G 17 17 Examples with soctypes are: 18 18 - "renesas,r8a7743-rst" (RZ/G1M) 19 + - "renesas,r8a7744-rst" (RZ/G1N) 19 20 - "renesas,r8a7745-rst" (RZ/G1E) 20 21 - "renesas,r8a77470-rst" (RZ/G1C) 22 + - "renesas,r8a774a1-rst" (RZ/G2M) 23 + - "renesas,r8a774c0-rst" (RZ/G2E) 21 24 - "renesas,r8a7778-reset-wdt" (R-Car M1A) 22 25 - "renesas,r8a7779-reset-wdt" (R-Car H1) 23 26 - "renesas,r8a7790-rst" (R-Car H2)
+29
Documentation/devicetree/bindings/soc/amlogic/amlogic,canvas.txt
··· 1 + Amlogic Canvas 2 + ================================ 3 + 4 + A canvas is a collection of metadata that describes a pixel buffer. 5 + Those metadata include: width, height, phyaddr, wrapping, block mode 6 + and endianness. 7 + 8 + Many IPs within Amlogic SoCs rely on canvas indexes to read/write pixel data 9 + rather than use the phy addresses directly. For instance, this is the case for 10 + the video decoders and the display. 11 + 12 + Amlogic SoCs have 256 canvas. 13 + 14 + Device Tree Bindings: 15 + --------------------- 16 + 17 + Video Lookup Table 18 + -------------------------- 19 + 20 + Required properties: 21 + - compatible: "amlogic,canvas" 22 + - reg: Base physical address and size of the canvas registers. 23 + 24 + Example: 25 + 26 + canvas: video-lut@48 { 27 + compatible = "amlogic,canvas"; 28 + reg = <0x0 0x48 0x0 0x14>; 29 + };
+2
Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
··· 19 19 Required properties in pwrap device node. 20 20 - compatible: 21 21 "mediatek,mt2701-pwrap" for MT2701/7623 SoCs 22 + "mediatek,mt6765-pwrap" for MT6765 SoCs 22 23 "mediatek,mt6797-pwrap" for MT6797 SoCs 23 24 "mediatek,mt7622-pwrap" for MT7622 SoCs 24 25 "mediatek,mt8135-pwrap" for MT8135 SoCs 25 26 "mediatek,mt8173-pwrap" for MT8173 SoCs 27 + "mediatek,mt8183-pwrap" for MT8183 SoCs 26 28 - interrupts: IRQ for pwrap in SOC 27 29 - reg-names: Must include the following entries: 28 30 "pwrap": Main registers base
+4
Documentation/devicetree/bindings/sram/sunxi-sram.txt
··· 18 18 - "allwinner,sun8i-h3-system-control" 19 19 - "allwinner,sun50i-a64-sram-controller" (deprecated) 20 20 - "allwinner,sun50i-a64-system-control" 21 + - "allwinner,sun50i-h6-system-control", "allwinner,sun50i-a64-system-control" 21 22 - reg : sram controller register offset + length 22 23 23 24 SRAM nodes ··· 54 53 55 54 The valid sections compatible for A64 are: 56 55 - allwinner,sun50i-a64-sram-c 56 + 57 + The valid sections compatible for H6 are: 58 + - allwinner,sun50i-h6-sram-c, allwinner,sun50i-a64-sram-c 57 59 58 60 Devices using SRAM sections 59 61 ---------------------------
+2
Documentation/devicetree/bindings/timer/renesas,tmu.txt
··· 12 12 - "renesas,tmu-r8a7740" for the r8a7740 TMU 13 13 - "renesas,tmu-r8a7778" for the r8a7778 TMU 14 14 - "renesas,tmu-r8a7779" for the r8a7779 TMU 15 + - "renesas,tmu-r8a77970" for the r8a77970 TMU 16 + - "renesas,tmu-r8a77980" for the r8a77980 TMU 15 17 - "renesas,tmu" for any TMU. 16 18 This is a fallback for the above renesas,tmu-* entries 17 19
+67
Documentation/xilinx/eemi.txt
··· 1 + --------------------------------------------------------------------- 2 + Xilinx Zynq MPSoC EEMI Documentation 3 + --------------------------------------------------------------------- 4 + 5 + Xilinx Zynq MPSoC Firmware Interface 6 + ------------------------------------- 7 + The zynqmp-firmware node describes the interface to platform firmware. 8 + ZynqMP has an interface to communicate with secure firmware. Firmware 9 + driver provides an interface to firmware APIs. Interface APIs can be 10 + used by any driver to communicate with PMC(Platform Management Controller). 11 + 12 + Embedded Energy Management Interface (EEMI) 13 + ---------------------------------------------- 14 + The embedded energy management interface is used to allow software 15 + components running across different processing clusters on a chip or 16 + device to communicate with a power management controller (PMC) on a 17 + device to issue or respond to power management requests. 18 + 19 + EEMI ops is a structure containing all eemi APIs supported by Zynq MPSoC. 20 + The zynqmp-firmware driver maintain all EEMI APIs in zynqmp_eemi_ops 21 + structure. Any driver who want to communicate with PMC using EEMI APIs 22 + can call zynqmp_pm_get_eemi_ops(). 23 + 24 + Example of EEMI ops: 25 + 26 + /* zynqmp-firmware driver maintain all EEMI APIs */ 27 + struct zynqmp_eemi_ops { 28 + int (*get_api_version)(u32 *version); 29 + int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out); 30 + }; 31 + 32 + static const struct zynqmp_eemi_ops eemi_ops = { 33 + .get_api_version = zynqmp_pm_get_api_version, 34 + .query_data = zynqmp_pm_query_data, 35 + }; 36 + 37 + Example of EEMI ops usage: 38 + 39 + static const struct zynqmp_eemi_ops *eemi_ops; 40 + u32 ret_payload[PAYLOAD_ARG_CNT]; 41 + int ret; 42 + 43 + eemi_ops = zynqmp_pm_get_eemi_ops(); 44 + if (!eemi_ops) 45 + return -ENXIO; 46 + 47 + ret = eemi_ops->query_data(qdata, ret_payload); 48 + 49 + IOCTL 50 + ------ 51 + IOCTL API is for device control and configuration. It is not a system 52 + IOCTL but it is an EEMI API. This API can be used by master to control 53 + any device specific configuration. IOCTL definitions can be platform 54 + specific. This API also manage shared device configuration. 55 + 56 + The following IOCTL IDs are valid for device control: 57 + - IOCTL_SET_PLL_FRAC_MODE 8 58 + - IOCTL_GET_PLL_FRAC_MODE 9 59 + - IOCTL_SET_PLL_FRAC_DATA 10 60 + - IOCTL_GET_PLL_FRAC_DATA 11 61 + 62 + Refer EEMI API guide [0] for IOCTL specific parameters and other EEMI APIs. 63 + 64 + References 65 + ---------- 66 + [0] Embedded Energy Management Interface (EEMI) API guide: 67 + https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf
+10
MAINTAINERS
··· 1471 1471 F: arch/arm/boot/dts/imx* 1472 1472 F: arch/arm/configs/imx*_defconfig 1473 1473 F: drivers/clk/imx/ 1474 + F: drivers/firmware/imx/ 1474 1475 F: drivers/soc/imx/ 1476 + F: include/linux/firmware/imx/ 1475 1477 F: include/soc/imx/ 1476 1478 1477 1479 ARM/FREESCALE VYBRID ARM ARCHITECTURE ··· 5402 5400 L: linux-edac@vger.kernel.org 5403 5401 S: Maintained 5404 5402 F: drivers/edac/ti_edac.c 5403 + 5404 + EDAC-QCOM 5405 + M: Channagoud Kadabi <ckadabi@codeaurora.org> 5406 + M: Venkata Narendra Kumar Gutta <vnkgutta@codeaurora.org> 5407 + L: linux-arm-msm@vger.kernel.org 5408 + L: linux-edac@vger.kernel.org 5409 + S: Maintained 5410 + F: drivers/edac/qcom_edac.c 5405 5411 5406 5412 EDIROL UA-101/UA-1000 DRIVER 5407 5413 M: Clemens Ladisch <clemens@ladisch.de>
+6
arch/arm/mach-shmobile/Kconfig
··· 55 55 select SYS_SUPPORTS_SH_MTU2 56 56 select RENESAS_OSTM 57 57 58 + config ARCH_R7S9210 59 + bool "RZ/A2 (R7S9210)" 60 + select PM 61 + select PM_GENERIC_DOMAINS 62 + select RENESAS_OSTM 63 + 58 64 config ARCH_R8A73A4 59 65 bool "R-Mobile APE6 (R8A73A40)" 60 66 select ARCH_RMOBILE
+1
arch/arm/mach-shmobile/Makefile
··· 14 14 obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o 15 15 obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o 16 16 obj-$(CONFIG_ARCH_R7S72100) += setup-r7s72100.o 17 + obj-$(CONFIG_ARCH_R7S9210) += setup-r7s9210.o 17 18 18 19 # CPU reset vector handling objects 19 20 cpu-y := platsmp.o headsmp.o
+27
arch/arm/mach-shmobile/setup-r7s9210.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * r7s9210 processor support 4 + * 5 + * Copyright (C) 2018 Renesas Electronics Corporation 6 + * Copyright (C) 2018 Chris Brandt 7 + * 8 + */ 9 + 10 + #include <linux/kernel.h> 11 + 12 + #include <asm/mach/arch.h> 13 + 14 + #include "common.h" 15 + 16 + static const char *const r7s9210_boards_compat_dt[] __initconst = { 17 + "renesas,r7s9210", 18 + NULL, 19 + }; 20 + 21 + DT_MACHINE_START(R7S72100_DT, "Generic R7S9210 (Flattened Device Tree)") 22 + .l2c_aux_val = 0, 23 + .l2c_aux_mask = ~0, 24 + .init_early = shmobile_init_delay, 25 + .init_late = shmobile_init_late, 26 + .dt_compat = r7s9210_boards_compat_dt, 27 + MACHINE_END
+1
arch/arm64/Kconfig.platforms
··· 302 302 303 303 config ARCH_ZYNQMP 304 304 bool "Xilinx ZynqMP Family" 305 + select ZYNQMP_FIRMWARE 305 306 help 306 307 This enables support for Xilinx ZynqMP Family 307 308
-3
drivers/bus/imx-weim.c
··· 156 156 } 157 157 158 158 for_each_available_child_of_node(pdev->dev.of_node, child) { 159 - if (!child->name) 160 - continue; 161 - 162 159 ret = weim_timing_setup(child, base, devtype); 163 160 if (ret) 164 161 dev_warn(&pdev->dev, "%pOF set timing failed.\n",
+48 -123
drivers/bus/ti-sysc.c
··· 701 701 return error; 702 702 } 703 703 704 - #ifdef CONFIG_PM_SLEEP 705 - static int sysc_suspend(struct device *dev) 706 - { 707 - struct sysc *ddata; 708 - int error; 709 - 710 - ddata = dev_get_drvdata(dev); 711 - 712 - if (ddata->cfg.quirks & (SYSC_QUIRK_RESOURCE_PROVIDER | 713 - SYSC_QUIRK_LEGACY_IDLE)) 714 - return 0; 715 - 716 - if (!ddata->enabled) 717 - return 0; 718 - 719 - dev_dbg(ddata->dev, "%s %s\n", __func__, 720 - ddata->name ? ddata->name : ""); 721 - 722 - error = pm_runtime_put_sync_suspend(dev); 723 - if (error < 0) { 724 - dev_warn(ddata->dev, "%s not idle %i %s\n", 725 - __func__, error, 726 - ddata->name ? ddata->name : ""); 727 - 728 - return 0; 729 - } 730 - 731 - ddata->needs_resume = true; 732 - 733 - return 0; 734 - } 735 - 736 - static int sysc_resume(struct device *dev) 737 - { 738 - struct sysc *ddata; 739 - int error; 740 - 741 - ddata = dev_get_drvdata(dev); 742 - 743 - if (ddata->cfg.quirks & (SYSC_QUIRK_RESOURCE_PROVIDER | 744 - SYSC_QUIRK_LEGACY_IDLE)) 745 - return 0; 746 - 747 - if (ddata->needs_resume) { 748 - dev_dbg(ddata->dev, "%s %s\n", __func__, 749 - ddata->name ? ddata->name : ""); 750 - 751 - error = pm_runtime_get_sync(dev); 752 - if (error < 0) { 753 - dev_err(ddata->dev, "%s error %i %s\n", 754 - __func__, error, 755 - ddata->name ? ddata->name : ""); 756 - 757 - return error; 758 - } 759 - 760 - ddata->needs_resume = false; 761 - } 762 - 763 - return 0; 764 - } 765 - 766 - static int sysc_noirq_suspend(struct device *dev) 704 + static int __maybe_unused sysc_noirq_suspend(struct device *dev) 767 705 { 768 706 struct sysc *ddata; 769 707 ··· 710 772 if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) 711 773 return 0; 712 774 713 - if (!(ddata->cfg.quirks & SYSC_QUIRK_RESOURCE_PROVIDER)) 714 - return 0; 715 - 716 - if (!ddata->enabled) 717 - return 0; 718 - 719 - dev_dbg(ddata->dev, "%s %s\n", __func__, 720 - ddata->name ? ddata->name : ""); 721 - 722 - ddata->needs_resume = true; 723 - 724 - return sysc_runtime_suspend(dev); 775 + return pm_runtime_force_suspend(dev); 725 776 } 726 777 727 - static int sysc_noirq_resume(struct device *dev) 778 + static int __maybe_unused sysc_noirq_resume(struct device *dev) 728 779 { 729 780 struct sysc *ddata; 730 781 ··· 722 795 if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) 723 796 return 0; 724 797 725 - if (!(ddata->cfg.quirks & SYSC_QUIRK_RESOURCE_PROVIDER)) 726 - return 0; 727 - 728 - if (ddata->needs_resume) { 729 - dev_dbg(ddata->dev, "%s %s\n", __func__, 730 - ddata->name ? ddata->name : ""); 731 - 732 - ddata->needs_resume = false; 733 - 734 - return sysc_runtime_resume(dev); 735 - } 736 - 737 - return 0; 798 + return pm_runtime_force_resume(dev); 738 799 } 739 - #endif 740 800 741 801 static const struct dev_pm_ops sysc_pm_ops = { 742 - SET_SYSTEM_SLEEP_PM_OPS(sysc_suspend, sysc_resume) 743 802 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sysc_noirq_suspend, sysc_noirq_resume) 744 803 SET_RUNTIME_PM_OPS(sysc_runtime_suspend, 745 804 sysc_runtime_resume, ··· 758 845 } 759 846 760 847 static const struct sysc_revision_quirk sysc_revision_quirks[] = { 761 - /* These need to use noirq_suspend */ 762 - SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 763 - SYSC_QUIRK_RESOURCE_PROVIDER), 764 - SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xffffffff, 765 - SYSC_QUIRK_RESOURCE_PROVIDER), 766 - SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffffffff, 767 - SYSC_QUIRK_RESOURCE_PROVIDER), 768 - SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 769 - SYSC_QUIRK_RESOURCE_PROVIDER), 770 - SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xffffffff, 771 - SYSC_QUIRK_RESOURCE_PROVIDER), 772 - SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 773 - SYSC_QUIRK_RESOURCE_PROVIDER), 774 - SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 775 - SYSC_QUIRK_RESOURCE_PROVIDER), 776 - SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff, 777 - SYSC_QUIRK_RESOURCE_PROVIDER), 778 - SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff, 779 - SYSC_QUIRK_RESOURCE_PROVIDER), 780 - 781 848 /* These drivers need to be fixed to not use pm_runtime_irq_safe() */ 782 - SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffffffff, 849 + SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffff00ff, 783 850 SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET), 784 851 SYSC_QUIRK("mmu", 0, 0, 0x10, 0x14, 0x00000020, 0xffffffff, 785 852 SYSC_QUIRK_LEGACY_IDLE), ··· 774 881 SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff, 775 882 SYSC_QUIRK_LEGACY_IDLE), 776 883 /* Some timers on omap4 and later */ 777 - SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffffffff, 884 + SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x50002100, 0xffffffff, 885 + SYSC_QUIRK_LEGACY_IDLE), 886 + SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff, 778 887 SYSC_QUIRK_LEGACY_IDLE), 779 888 SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff, 780 889 SYSC_QUIRK_LEGACY_IDLE), 781 890 /* Uarts on omap4 and later */ 782 - SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffffffff, 891 + SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff, 783 892 SYSC_QUIRK_LEGACY_IDLE), 784 - 785 - /* These devices don't yet suspend properly without legacy setting */ 786 - SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffffffff, 787 - SYSC_QUIRK_LEGACY_IDLE), 788 - SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xffffffff, 789 - SYSC_QUIRK_LEGACY_IDLE), 790 - SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0d00, 0xffffffff, 893 + SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff, 791 894 SYSC_QUIRK_LEGACY_IDLE), 792 895 793 896 #ifdef DEBUG 897 + SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0), 898 + SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0), 794 899 SYSC_QUIRK("aess", 0, 0, 0x10, -1, 0x40000000, 0xffffffff, 0), 900 + SYSC_QUIRK("cm", 0, 0, -1, -1, 0x40000301, 0xffffffff, 0), 901 + SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), 902 + SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902, 903 + 0xffff00f0, 0), 904 + SYSC_QUIRK("dcan", 0, 0, -1, -1, 0xffffffff, 0xffffffff, 0), 905 + SYSC_QUIRK("dcan", 0, 0, -1, -1, 0x00001401, 0xffffffff, 0), 906 + SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0), 907 + SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0), 795 908 SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0), 796 909 SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, 0), 910 + SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, 0), 797 911 SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0), 798 912 SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0), 913 + SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, 0), 914 + SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0), 799 915 SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0), 916 + SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0), 800 917 SYSC_QUIRK("mcbsp", 0, -1, 0x8c, -1, 0, 0, 0), 918 + SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffff00ff, 0), 919 + SYSC_QUIRK("mcspi", 0, 0, 0x110, 0x114, 0x40300a0b, 0xffffffff, 0), 801 920 SYSC_QUIRK("mailbox", 0, 0, 0x10, -1, 0x00000400, 0xffffffff, 0), 921 + SYSC_QUIRK("m3", 0, 0, -1, -1, 0x5f580105, 0x0fff0f00, 0), 922 + SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xfffffff0, 0), 923 + SYSC_QUIRK("ocp2scp", 0, 0, -1, -1, 0x50060007, 0xffffffff, 0), 924 + SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 0), 925 + SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 0), 926 + SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x00004102, 0xffffffff, 0), 927 + SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000400, 0xffffffff, 0), 928 + SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), 929 + SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4e8b0100, 0xffffffff, 0), 930 + SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4f000100, 0xffffffff, 0), 931 + SYSC_QUIRK("scm", 0, 0, -1, -1, 0x40000900, 0xffffffff, 0), 932 + SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff, 0), 933 + SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffff0ff0, 0), 934 + SYSC_QUIRK("sdio", 0, 0x2fc, 0x110, 0x114, 0x31010000, 0xffffffff, 0), 935 + SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff, 0), 802 936 SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40000902, 0xffffffff, 0), 803 937 SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40002903, 0xffffffff, 0), 804 938 SYSC_QUIRK("spinlock", 0, 0, 0x10, -1, 0x50020000, 0xffffffff, 0), 939 + SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -1, 0x00000020, 0xffffffff, 0), 940 + SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xffff00f0, 0), 941 + SYSC_QUIRK("timer32k", 0, 0, 0x4, -1, 0x00000060, 0xffffffff, 0), 805 942 SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0), 806 943 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0), 807 944 SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, 808 945 0xffffffff, 0), 946 + SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, 0), 947 + SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0), 809 948 #endif 810 949 }; 811 950 ··· 1146 1221 if (!pm_runtime_status_suspended(dev)) { 1147 1222 error = pm_generic_runtime_suspend(dev); 1148 1223 if (error) { 1149 - dev_warn(dev, "%s busy at %i: %i\n", 1150 - __func__, __LINE__, error); 1224 + dev_dbg(dev, "%s busy at %i: %i\n", 1225 + __func__, __LINE__, error); 1151 1226 1152 1227 return 0; 1153 1228 }
+1
drivers/clk/Kconfig
··· 299 299 source "drivers/clk/tegra/Kconfig" 300 300 source "drivers/clk/ti/Kconfig" 301 301 source "drivers/clk/uniphier/Kconfig" 302 + source "drivers/clk/zynqmp/Kconfig" 302 303 303 304 endmenu
+1
drivers/clk/Makefile
··· 108 108 endif 109 109 obj-$(CONFIG_ARCH_ZX) += zte/ 110 110 obj-$(CONFIG_ARCH_ZYNQ) += zynq/ 111 + obj-$(CONFIG_COMMON_CLK_ZYNQMP) += zynqmp/
+10
drivers/clk/zynqmp/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + config COMMON_CLK_ZYNQMP 4 + bool "Support for Xilinx ZynqMP Ultrascale+ clock controllers" 5 + depends on ARCH_ZYNQMP || COMPILE_TEST 6 + depends on ZYNQMP_FIRMWARE 7 + help 8 + Support for the Zynqmp Ultrascale clock controller. 9 + It has a dependency on the PMU firmware. 10 + Say Y if you want to include clock support.
+4
drivers/clk/zynqmp/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Zynq Ultrascale+ MPSoC clock specific Makefile 3 + 4 + obj-$(CONFIG_ARCH_ZYNQMP) += pll.o clk-gate-zynqmp.o divider.o clk-mux-zynqmp.o clkc.o
+144
drivers/clk/zynqmp/clk-gate-zynqmp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Zynq UltraScale+ MPSoC clock controller 4 + * 5 + * Copyright (C) 2016-2018 Xilinx 6 + * 7 + * Gated clock implementation 8 + */ 9 + 10 + #include <linux/clk-provider.h> 11 + #include <linux/slab.h> 12 + #include "clk-zynqmp.h" 13 + 14 + /** 15 + * struct clk_gate - gating clock 16 + * @hw: handle between common and hardware-specific interfaces 17 + * @flags: hardware-specific flags 18 + * @clk_id: Id of clock 19 + */ 20 + struct zynqmp_clk_gate { 21 + struct clk_hw hw; 22 + u8 flags; 23 + u32 clk_id; 24 + }; 25 + 26 + #define to_zynqmp_clk_gate(_hw) container_of(_hw, struct zynqmp_clk_gate, hw) 27 + 28 + /** 29 + * zynqmp_clk_gate_enable() - Enable clock 30 + * @hw: handle between common and hardware-specific interfaces 31 + * 32 + * Return: 0 on success else error code 33 + */ 34 + static int zynqmp_clk_gate_enable(struct clk_hw *hw) 35 + { 36 + struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw); 37 + const char *clk_name = clk_hw_get_name(hw); 38 + u32 clk_id = gate->clk_id; 39 + int ret; 40 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 41 + 42 + ret = eemi_ops->clock_enable(clk_id); 43 + 44 + if (ret) 45 + pr_warn_once("%s() clock enabled failed for %s, ret = %d\n", 46 + __func__, clk_name, ret); 47 + 48 + return ret; 49 + } 50 + 51 + /* 52 + * zynqmp_clk_gate_disable() - Disable clock 53 + * @hw: handle between common and hardware-specific interfaces 54 + */ 55 + static void zynqmp_clk_gate_disable(struct clk_hw *hw) 56 + { 57 + struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw); 58 + const char *clk_name = clk_hw_get_name(hw); 59 + u32 clk_id = gate->clk_id; 60 + int ret; 61 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 62 + 63 + ret = eemi_ops->clock_disable(clk_id); 64 + 65 + if (ret) 66 + pr_warn_once("%s() clock disable failed for %s, ret = %d\n", 67 + __func__, clk_name, ret); 68 + } 69 + 70 + /** 71 + * zynqmp_clk_gate_is_enable() - Check clock state 72 + * @hw: handle between common and hardware-specific interfaces 73 + * 74 + * Return: 1 if enabled, 0 if disabled else error code 75 + */ 76 + static int zynqmp_clk_gate_is_enabled(struct clk_hw *hw) 77 + { 78 + struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw); 79 + const char *clk_name = clk_hw_get_name(hw); 80 + u32 clk_id = gate->clk_id; 81 + int state, ret; 82 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 83 + 84 + ret = eemi_ops->clock_getstate(clk_id, &state); 85 + if (ret) { 86 + pr_warn_once("%s() clock get state failed for %s, ret = %d\n", 87 + __func__, clk_name, ret); 88 + return -EIO; 89 + } 90 + 91 + return state ? 1 : 0; 92 + } 93 + 94 + static const struct clk_ops zynqmp_clk_gate_ops = { 95 + .enable = zynqmp_clk_gate_enable, 96 + .disable = zynqmp_clk_gate_disable, 97 + .is_enabled = zynqmp_clk_gate_is_enabled, 98 + }; 99 + 100 + /** 101 + * zynqmp_clk_register_gate() - Register a gate clock with the clock framework 102 + * @name: Name of this clock 103 + * @clk_id: Id of this clock 104 + * @parents: Name of this clock's parents 105 + * @num_parents: Number of parents 106 + * @nodes: Clock topology node 107 + * 108 + * Return: clock hardware of the registered clock gate 109 + */ 110 + struct clk_hw *zynqmp_clk_register_gate(const char *name, u32 clk_id, 111 + const char * const *parents, 112 + u8 num_parents, 113 + const struct clock_topology *nodes) 114 + { 115 + struct zynqmp_clk_gate *gate; 116 + struct clk_hw *hw; 117 + int ret; 118 + struct clk_init_data init; 119 + 120 + /* allocate the gate */ 121 + gate = kzalloc(sizeof(*gate), GFP_KERNEL); 122 + if (!gate) 123 + return ERR_PTR(-ENOMEM); 124 + 125 + init.name = name; 126 + init.ops = &zynqmp_clk_gate_ops; 127 + init.flags = nodes->flag; 128 + init.parent_names = parents; 129 + init.num_parents = 1; 130 + 131 + /* struct clk_gate assignments */ 132 + gate->flags = nodes->type_flag; 133 + gate->hw.init = &init; 134 + gate->clk_id = clk_id; 135 + 136 + hw = &gate->hw; 137 + ret = clk_hw_register(NULL, hw); 138 + if (ret) { 139 + kfree(gate); 140 + hw = ERR_PTR(ret); 141 + } 142 + 143 + return hw; 144 + }
+141
drivers/clk/zynqmp/clk-mux-zynqmp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Zynq UltraScale+ MPSoC mux 4 + * 5 + * Copyright (C) 2016-2018 Xilinx 6 + */ 7 + 8 + #include <linux/clk-provider.h> 9 + #include <linux/slab.h> 10 + #include "clk-zynqmp.h" 11 + 12 + /* 13 + * DOC: basic adjustable multiplexer clock that cannot gate 14 + * 15 + * Traits of this clock: 16 + * prepare - clk_prepare only ensures that parents are prepared 17 + * enable - clk_enable only ensures that parents are enabled 18 + * rate - rate is only affected by parent switching. No clk_set_rate support 19 + * parent - parent is adjustable through clk_set_parent 20 + */ 21 + 22 + /** 23 + * struct zynqmp_clk_mux - multiplexer clock 24 + * 25 + * @hw: handle between common and hardware-specific interfaces 26 + * @flags: hardware-specific flags 27 + * @clk_id: Id of clock 28 + */ 29 + struct zynqmp_clk_mux { 30 + struct clk_hw hw; 31 + u8 flags; 32 + u32 clk_id; 33 + }; 34 + 35 + #define to_zynqmp_clk_mux(_hw) container_of(_hw, struct zynqmp_clk_mux, hw) 36 + 37 + /** 38 + * zynqmp_clk_mux_get_parent() - Get parent of clock 39 + * @hw: handle between common and hardware-specific interfaces 40 + * 41 + * Return: Parent index 42 + */ 43 + static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw) 44 + { 45 + struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(hw); 46 + const char *clk_name = clk_hw_get_name(hw); 47 + u32 clk_id = mux->clk_id; 48 + u32 val; 49 + int ret; 50 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 51 + 52 + ret = eemi_ops->clock_getparent(clk_id, &val); 53 + 54 + if (ret) 55 + pr_warn_once("%s() getparent failed for clock: %s, ret = %d\n", 56 + __func__, clk_name, ret); 57 + 58 + return val; 59 + } 60 + 61 + /** 62 + * zynqmp_clk_mux_set_parent() - Set parent of clock 63 + * @hw: handle between common and hardware-specific interfaces 64 + * @index: Parent index 65 + * 66 + * Return: 0 on success else error+reason 67 + */ 68 + static int zynqmp_clk_mux_set_parent(struct clk_hw *hw, u8 index) 69 + { 70 + struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(hw); 71 + const char *clk_name = clk_hw_get_name(hw); 72 + u32 clk_id = mux->clk_id; 73 + int ret; 74 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 75 + 76 + ret = eemi_ops->clock_setparent(clk_id, index); 77 + 78 + if (ret) 79 + pr_warn_once("%s() set parent failed for clock: %s, ret = %d\n", 80 + __func__, clk_name, ret); 81 + 82 + return ret; 83 + } 84 + 85 + static const struct clk_ops zynqmp_clk_mux_ops = { 86 + .get_parent = zynqmp_clk_mux_get_parent, 87 + .set_parent = zynqmp_clk_mux_set_parent, 88 + .determine_rate = __clk_mux_determine_rate, 89 + }; 90 + 91 + static const struct clk_ops zynqmp_clk_mux_ro_ops = { 92 + .get_parent = zynqmp_clk_mux_get_parent, 93 + }; 94 + 95 + /** 96 + * zynqmp_clk_register_mux() - Register a mux table with the clock 97 + * framework 98 + * @name: Name of this clock 99 + * @clk_id: Id of this clock 100 + * @parents: Name of this clock's parents 101 + * @num_parents: Number of parents 102 + * @nodes: Clock topology node 103 + * 104 + * Return: clock hardware of the registered clock mux 105 + */ 106 + struct clk_hw *zynqmp_clk_register_mux(const char *name, u32 clk_id, 107 + const char * const *parents, 108 + u8 num_parents, 109 + const struct clock_topology *nodes) 110 + { 111 + struct zynqmp_clk_mux *mux; 112 + struct clk_hw *hw; 113 + struct clk_init_data init; 114 + int ret; 115 + 116 + mux = kzalloc(sizeof(*mux), GFP_KERNEL); 117 + if (!mux) 118 + return ERR_PTR(-ENOMEM); 119 + 120 + init.name = name; 121 + if (nodes->type_flag & CLK_MUX_READ_ONLY) 122 + init.ops = &zynqmp_clk_mux_ro_ops; 123 + else 124 + init.ops = &zynqmp_clk_mux_ops; 125 + init.flags = nodes->flag; 126 + init.parent_names = parents; 127 + init.num_parents = num_parents; 128 + mux->flags = nodes->type_flag; 129 + mux->hw.init = &init; 130 + mux->clk_id = clk_id; 131 + 132 + hw = &mux->hw; 133 + ret = clk_hw_register(NULL, hw); 134 + if (ret) { 135 + kfree(hw); 136 + hw = ERR_PTR(ret); 137 + } 138 + 139 + return hw; 140 + } 141 + EXPORT_SYMBOL_GPL(zynqmp_clk_register_mux);
+68
drivers/clk/zynqmp/clk-zynqmp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2016-2018 Xilinx 4 + */ 5 + 6 + #ifndef __LINUX_CLK_ZYNQMP_H_ 7 + #define __LINUX_CLK_ZYNQMP_H_ 8 + 9 + #include <linux/spinlock.h> 10 + 11 + #include <linux/firmware/xlnx-zynqmp.h> 12 + 13 + /* Clock APIs payload parameters */ 14 + #define CLK_GET_NAME_RESP_LEN 16 15 + #define CLK_GET_TOPOLOGY_RESP_WORDS 3 16 + #define CLK_GET_PARENTS_RESP_WORDS 3 17 + #define CLK_GET_ATTR_RESP_WORDS 1 18 + 19 + enum topology_type { 20 + TYPE_INVALID, 21 + TYPE_MUX, 22 + TYPE_PLL, 23 + TYPE_FIXEDFACTOR, 24 + TYPE_DIV1, 25 + TYPE_DIV2, 26 + TYPE_GATE, 27 + }; 28 + 29 + /** 30 + * struct clock_topology - Clock topology 31 + * @type: Type of topology 32 + * @flag: Topology flags 33 + * @type_flag: Topology type specific flag 34 + */ 35 + struct clock_topology { 36 + u32 type; 37 + u32 flag; 38 + u32 type_flag; 39 + }; 40 + 41 + struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id, 42 + const char * const *parents, 43 + u8 num_parents, 44 + const struct clock_topology *nodes); 45 + 46 + struct clk_hw *zynqmp_clk_register_gate(const char *name, u32 clk_id, 47 + const char * const *parents, 48 + u8 num_parents, 49 + const struct clock_topology *nodes); 50 + 51 + struct clk_hw *zynqmp_clk_register_divider(const char *name, 52 + u32 clk_id, 53 + const char * const *parents, 54 + u8 num_parents, 55 + const struct clock_topology *nodes); 56 + 57 + struct clk_hw *zynqmp_clk_register_mux(const char *name, u32 clk_id, 58 + const char * const *parents, 59 + u8 num_parents, 60 + const struct clock_topology *nodes); 61 + 62 + struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, 63 + u32 clk_id, 64 + const char * const *parents, 65 + u8 num_parents, 66 + const struct clock_topology *nodes); 67 + 68 + #endif
+716
drivers/clk/zynqmp/clkc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Zynq UltraScale+ MPSoC clock controller 4 + * 5 + * Copyright (C) 2016-2018 Xilinx 6 + * 7 + * Based on drivers/clk/zynq/clkc.c 8 + */ 9 + 10 + #include <linux/bitfield.h> 11 + #include <linux/clk.h> 12 + #include <linux/clk-provider.h> 13 + #include <linux/module.h> 14 + #include <linux/of_platform.h> 15 + #include <linux/slab.h> 16 + #include <linux/string.h> 17 + 18 + #include "clk-zynqmp.h" 19 + 20 + #define MAX_PARENT 100 21 + #define MAX_NODES 6 22 + #define MAX_NAME_LEN 50 23 + 24 + #define CLK_TYPE_SHIFT 2 25 + 26 + #define PM_API_PAYLOAD_LEN 3 27 + 28 + #define NA_PARENT 0xFFFFFFFF 29 + #define DUMMY_PARENT 0xFFFFFFFE 30 + 31 + #define CLK_TYPE_FIELD_LEN 4 32 + #define CLK_TOPOLOGY_NODE_OFFSET 16 33 + #define NODES_PER_RESP 3 34 + 35 + #define CLK_TYPE_FIELD_MASK 0xF 36 + #define CLK_FLAG_FIELD_MASK GENMASK(21, 8) 37 + #define CLK_TYPE_FLAG_FIELD_MASK GENMASK(31, 24) 38 + 39 + #define CLK_PARENTS_ID_LEN 16 40 + #define CLK_PARENTS_ID_MASK 0xFFFF 41 + 42 + /* Flags for parents */ 43 + #define PARENT_CLK_SELF 0 44 + #define PARENT_CLK_NODE1 1 45 + #define PARENT_CLK_NODE2 2 46 + #define PARENT_CLK_NODE3 3 47 + #define PARENT_CLK_NODE4 4 48 + #define PARENT_CLK_EXTERNAL 5 49 + 50 + #define END_OF_CLK_NAME "END_OF_CLK" 51 + #define END_OF_TOPOLOGY_NODE 1 52 + #define END_OF_PARENTS 1 53 + #define RESERVED_CLK_NAME "" 54 + 55 + #define CLK_VALID_MASK 0x1 56 + 57 + enum clk_type { 58 + CLK_TYPE_OUTPUT, 59 + CLK_TYPE_EXTERNAL, 60 + }; 61 + 62 + /** 63 + * struct clock_parent - Clock parent 64 + * @name: Parent name 65 + * @id: Parent clock ID 66 + * @flag: Parent flags 67 + */ 68 + struct clock_parent { 69 + char name[MAX_NAME_LEN]; 70 + int id; 71 + u32 flag; 72 + }; 73 + 74 + /** 75 + * struct zynqmp_clock - Clock 76 + * @clk_name: Clock name 77 + * @valid: Validity flag of clock 78 + * @type: Clock type (Output/External) 79 + * @node: Clock topology nodes 80 + * @num_nodes: Number of nodes present in topology 81 + * @parent: Parent of clock 82 + * @num_parents: Number of parents of clock 83 + */ 84 + struct zynqmp_clock { 85 + char clk_name[MAX_NAME_LEN]; 86 + u32 valid; 87 + enum clk_type type; 88 + struct clock_topology node[MAX_NODES]; 89 + u32 num_nodes; 90 + struct clock_parent parent[MAX_PARENT]; 91 + u32 num_parents; 92 + }; 93 + 94 + static const char clk_type_postfix[][10] = { 95 + [TYPE_INVALID] = "", 96 + [TYPE_MUX] = "_mux", 97 + [TYPE_GATE] = "", 98 + [TYPE_DIV1] = "_div1", 99 + [TYPE_DIV2] = "_div2", 100 + [TYPE_FIXEDFACTOR] = "_ff", 101 + [TYPE_PLL] = "" 102 + }; 103 + 104 + static struct clk_hw *(* const clk_topology[]) (const char *name, u32 clk_id, 105 + const char * const *parents, 106 + u8 num_parents, 107 + const struct clock_topology *nodes) 108 + = { 109 + [TYPE_INVALID] = NULL, 110 + [TYPE_MUX] = zynqmp_clk_register_mux, 111 + [TYPE_PLL] = zynqmp_clk_register_pll, 112 + [TYPE_FIXEDFACTOR] = zynqmp_clk_register_fixed_factor, 113 + [TYPE_DIV1] = zynqmp_clk_register_divider, 114 + [TYPE_DIV2] = zynqmp_clk_register_divider, 115 + [TYPE_GATE] = zynqmp_clk_register_gate 116 + }; 117 + 118 + static struct zynqmp_clock *clock; 119 + static struct clk_hw_onecell_data *zynqmp_data; 120 + static unsigned int clock_max_idx; 121 + static const struct zynqmp_eemi_ops *eemi_ops; 122 + 123 + /** 124 + * zynqmp_is_valid_clock() - Check whether clock is valid or not 125 + * @clk_id: Clock index 126 + * 127 + * Return: 1 if clock is valid, 0 if clock is invalid else error code 128 + */ 129 + static inline int zynqmp_is_valid_clock(u32 clk_id) 130 + { 131 + if (clk_id > clock_max_idx) 132 + return -ENODEV; 133 + 134 + return clock[clk_id].valid; 135 + } 136 + 137 + /** 138 + * zynqmp_get_clock_name() - Get name of clock from Clock index 139 + * @clk_id: Clock index 140 + * @clk_name: Name of clock 141 + * 142 + * Return: 0 on success else error code 143 + */ 144 + static int zynqmp_get_clock_name(u32 clk_id, char *clk_name) 145 + { 146 + int ret; 147 + 148 + ret = zynqmp_is_valid_clock(clk_id); 149 + if (ret == 1) { 150 + strncpy(clk_name, clock[clk_id].clk_name, MAX_NAME_LEN); 151 + return 0; 152 + } 153 + 154 + return ret == 0 ? -EINVAL : ret; 155 + } 156 + 157 + /** 158 + * zynqmp_get_clock_type() - Get type of clock 159 + * @clk_id: Clock index 160 + * @type: Clock type: CLK_TYPE_OUTPUT or CLK_TYPE_EXTERNAL 161 + * 162 + * Return: 0 on success else error code 163 + */ 164 + static int zynqmp_get_clock_type(u32 clk_id, u32 *type) 165 + { 166 + int ret; 167 + 168 + ret = zynqmp_is_valid_clock(clk_id); 169 + if (ret == 1) { 170 + *type = clock[clk_id].type; 171 + return 0; 172 + } 173 + 174 + return ret == 0 ? -EINVAL : ret; 175 + } 176 + 177 + /** 178 + * zynqmp_pm_clock_get_num_clocks() - Get number of clocks in system 179 + * @nclocks: Number of clocks in system/board. 180 + * 181 + * Call firmware API to get number of clocks. 182 + * 183 + * Return: 0 on success else error code. 184 + */ 185 + static int zynqmp_pm_clock_get_num_clocks(u32 *nclocks) 186 + { 187 + struct zynqmp_pm_query_data qdata = {0}; 188 + u32 ret_payload[PAYLOAD_ARG_CNT]; 189 + int ret; 190 + 191 + qdata.qid = PM_QID_CLOCK_GET_NUM_CLOCKS; 192 + 193 + ret = eemi_ops->query_data(qdata, ret_payload); 194 + *nclocks = ret_payload[1]; 195 + 196 + return ret; 197 + } 198 + 199 + /** 200 + * zynqmp_pm_clock_get_name() - Get the name of clock for given id 201 + * @clock_id: ID of the clock to be queried 202 + * @name: Name of given clock 203 + * 204 + * This function is used to get name of clock specified by given 205 + * clock ID. 206 + * 207 + * Return: Returns 0, in case of error name would be 0 208 + */ 209 + static int zynqmp_pm_clock_get_name(u32 clock_id, char *name) 210 + { 211 + struct zynqmp_pm_query_data qdata = {0}; 212 + u32 ret_payload[PAYLOAD_ARG_CNT]; 213 + 214 + qdata.qid = PM_QID_CLOCK_GET_NAME; 215 + qdata.arg1 = clock_id; 216 + 217 + eemi_ops->query_data(qdata, ret_payload); 218 + memcpy(name, ret_payload, CLK_GET_NAME_RESP_LEN); 219 + 220 + return 0; 221 + } 222 + 223 + /** 224 + * zynqmp_pm_clock_get_topology() - Get the topology of clock for given id 225 + * @clock_id: ID of the clock to be queried 226 + * @index: Node index of clock topology 227 + * @topology: Buffer to store nodes in topology and flags 228 + * 229 + * This function is used to get topology information for the clock 230 + * specified by given clock ID. 231 + * 232 + * This API will return 3 node of topology with a single response. To get 233 + * other nodes, master should call same API in loop with new 234 + * index till error is returned. E.g First call should have 235 + * index 0 which will return nodes 0,1 and 2. Next call, index 236 + * should be 3 which will return nodes 3,4 and 5 and so on. 237 + * 238 + * Return: 0 on success else error+reason 239 + */ 240 + static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, u32 *topology) 241 + { 242 + struct zynqmp_pm_query_data qdata = {0}; 243 + u32 ret_payload[PAYLOAD_ARG_CNT]; 244 + int ret; 245 + 246 + qdata.qid = PM_QID_CLOCK_GET_TOPOLOGY; 247 + qdata.arg1 = clock_id; 248 + qdata.arg2 = index; 249 + 250 + ret = eemi_ops->query_data(qdata, ret_payload); 251 + memcpy(topology, &ret_payload[1], CLK_GET_TOPOLOGY_RESP_WORDS * 4); 252 + 253 + return ret; 254 + } 255 + 256 + /** 257 + * zynqmp_clk_register_fixed_factor() - Register fixed factor with the 258 + * clock framework 259 + * @name: Name of this clock 260 + * @clk_id: Clock ID 261 + * @parents: Name of this clock's parents 262 + * @num_parents: Number of parents 263 + * @nodes: Clock topology node 264 + * 265 + * Return: clock hardware to the registered clock 266 + */ 267 + struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id, 268 + const char * const *parents, 269 + u8 num_parents, 270 + const struct clock_topology *nodes) 271 + { 272 + u32 mult, div; 273 + struct clk_hw *hw; 274 + struct zynqmp_pm_query_data qdata = {0}; 275 + u32 ret_payload[PAYLOAD_ARG_CNT]; 276 + int ret; 277 + 278 + qdata.qid = PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS; 279 + qdata.arg1 = clk_id; 280 + 281 + ret = eemi_ops->query_data(qdata, ret_payload); 282 + mult = ret_payload[1]; 283 + div = ret_payload[2]; 284 + 285 + hw = clk_hw_register_fixed_factor(NULL, name, 286 + parents[0], 287 + nodes->flag, mult, 288 + div); 289 + 290 + return hw; 291 + } 292 + 293 + /** 294 + * zynqmp_pm_clock_get_parents() - Get the first 3 parents of clock for given id 295 + * @clock_id: Clock ID 296 + * @index: Parent index 297 + * @parents: 3 parents of the given clock 298 + * 299 + * This function is used to get 3 parents for the clock specified by 300 + * given clock ID. 301 + * 302 + * This API will return 3 parents with a single response. To get 303 + * other parents, master should call same API in loop with new 304 + * parent index till error is returned. E.g First call should have 305 + * index 0 which will return parents 0,1 and 2. Next call, index 306 + * should be 3 which will return parent 3,4 and 5 and so on. 307 + * 308 + * Return: 0 on success else error+reason 309 + */ 310 + static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, u32 *parents) 311 + { 312 + struct zynqmp_pm_query_data qdata = {0}; 313 + u32 ret_payload[PAYLOAD_ARG_CNT]; 314 + int ret; 315 + 316 + qdata.qid = PM_QID_CLOCK_GET_PARENTS; 317 + qdata.arg1 = clock_id; 318 + qdata.arg2 = index; 319 + 320 + ret = eemi_ops->query_data(qdata, ret_payload); 321 + memcpy(parents, &ret_payload[1], CLK_GET_PARENTS_RESP_WORDS * 4); 322 + 323 + return ret; 324 + } 325 + 326 + /** 327 + * zynqmp_pm_clock_get_attributes() - Get the attributes of clock for given id 328 + * @clock_id: Clock ID 329 + * @attr: Clock attributes 330 + * 331 + * This function is used to get clock's attributes(e.g. valid, clock type, etc). 332 + * 333 + * Return: 0 on success else error+reason 334 + */ 335 + static int zynqmp_pm_clock_get_attributes(u32 clock_id, u32 *attr) 336 + { 337 + struct zynqmp_pm_query_data qdata = {0}; 338 + u32 ret_payload[PAYLOAD_ARG_CNT]; 339 + int ret; 340 + 341 + qdata.qid = PM_QID_CLOCK_GET_ATTRIBUTES; 342 + qdata.arg1 = clock_id; 343 + 344 + ret = eemi_ops->query_data(qdata, ret_payload); 345 + memcpy(attr, &ret_payload[1], CLK_GET_ATTR_RESP_WORDS * 4); 346 + 347 + return ret; 348 + } 349 + 350 + /** 351 + * __zynqmp_clock_get_topology() - Get topology data of clock from firmware 352 + * response data 353 + * @topology: Clock topology 354 + * @data: Clock topology data received from firmware 355 + * @nnodes: Number of nodes 356 + * 357 + * Return: 0 on success else error+reason 358 + */ 359 + static int __zynqmp_clock_get_topology(struct clock_topology *topology, 360 + u32 *data, u32 *nnodes) 361 + { 362 + int i; 363 + 364 + for (i = 0; i < PM_API_PAYLOAD_LEN; i++) { 365 + if (!(data[i] & CLK_TYPE_FIELD_MASK)) 366 + return END_OF_TOPOLOGY_NODE; 367 + topology[*nnodes].type = data[i] & CLK_TYPE_FIELD_MASK; 368 + topology[*nnodes].flag = FIELD_GET(CLK_FLAG_FIELD_MASK, 369 + data[i]); 370 + topology[*nnodes].type_flag = 371 + FIELD_GET(CLK_TYPE_FLAG_FIELD_MASK, data[i]); 372 + (*nnodes)++; 373 + } 374 + 375 + return 0; 376 + } 377 + 378 + /** 379 + * zynqmp_clock_get_topology() - Get topology of clock from firmware using 380 + * PM_API 381 + * @clk_id: Clock index 382 + * @topology: Clock topology 383 + * @num_nodes: Number of nodes 384 + * 385 + * Return: 0 on success else error+reason 386 + */ 387 + static int zynqmp_clock_get_topology(u32 clk_id, 388 + struct clock_topology *topology, 389 + u32 *num_nodes) 390 + { 391 + int j, ret; 392 + u32 pm_resp[PM_API_PAYLOAD_LEN] = {0}; 393 + 394 + *num_nodes = 0; 395 + for (j = 0; j <= MAX_NODES; j += 3) { 396 + ret = zynqmp_pm_clock_get_topology(clk_id, j, pm_resp); 397 + if (ret) 398 + return ret; 399 + ret = __zynqmp_clock_get_topology(topology, pm_resp, num_nodes); 400 + if (ret == END_OF_TOPOLOGY_NODE) 401 + return 0; 402 + } 403 + 404 + return 0; 405 + } 406 + 407 + /** 408 + * __zynqmp_clock_get_topology() - Get parents info of clock from firmware 409 + * response data 410 + * @parents: Clock parents 411 + * @data: Clock parents data received from firmware 412 + * @nparent: Number of parent 413 + * 414 + * Return: 0 on success else error+reason 415 + */ 416 + static int __zynqmp_clock_get_parents(struct clock_parent *parents, u32 *data, 417 + u32 *nparent) 418 + { 419 + int i; 420 + struct clock_parent *parent; 421 + 422 + for (i = 0; i < PM_API_PAYLOAD_LEN; i++) { 423 + if (data[i] == NA_PARENT) 424 + return END_OF_PARENTS; 425 + 426 + parent = &parents[i]; 427 + parent->id = data[i] & CLK_PARENTS_ID_MASK; 428 + if (data[i] == DUMMY_PARENT) { 429 + strcpy(parent->name, "dummy_name"); 430 + parent->flag = 0; 431 + } else { 432 + parent->flag = data[i] >> CLK_PARENTS_ID_LEN; 433 + if (zynqmp_get_clock_name(parent->id, parent->name)) 434 + continue; 435 + } 436 + *nparent += 1; 437 + } 438 + 439 + return 0; 440 + } 441 + 442 + /** 443 + * zynqmp_clock_get_parents() - Get parents info from firmware using PM_API 444 + * @clk_id: Clock index 445 + * @parents: Clock parents 446 + * @num_parents: Total number of parents 447 + * 448 + * Return: 0 on success else error+reason 449 + */ 450 + static int zynqmp_clock_get_parents(u32 clk_id, struct clock_parent *parents, 451 + u32 *num_parents) 452 + { 453 + int j = 0, ret; 454 + u32 pm_resp[PM_API_PAYLOAD_LEN] = {0}; 455 + 456 + *num_parents = 0; 457 + do { 458 + /* Get parents from firmware */ 459 + ret = zynqmp_pm_clock_get_parents(clk_id, j, pm_resp); 460 + if (ret) 461 + return ret; 462 + 463 + ret = __zynqmp_clock_get_parents(&parents[j], pm_resp, 464 + num_parents); 465 + if (ret == END_OF_PARENTS) 466 + return 0; 467 + j += PM_API_PAYLOAD_LEN; 468 + } while (*num_parents <= MAX_PARENT); 469 + 470 + return 0; 471 + } 472 + 473 + /** 474 + * zynqmp_get_parent_list() - Create list of parents name 475 + * @np: Device node 476 + * @clk_id: Clock index 477 + * @parent_list: List of parent's name 478 + * @num_parents: Total number of parents 479 + * 480 + * Return: 0 on success else error+reason 481 + */ 482 + static int zynqmp_get_parent_list(struct device_node *np, u32 clk_id, 483 + const char **parent_list, u32 *num_parents) 484 + { 485 + int i = 0, ret; 486 + u32 total_parents = clock[clk_id].num_parents; 487 + struct clock_topology *clk_nodes; 488 + struct clock_parent *parents; 489 + 490 + clk_nodes = clock[clk_id].node; 491 + parents = clock[clk_id].parent; 492 + 493 + for (i = 0; i < total_parents; i++) { 494 + if (!parents[i].flag) { 495 + parent_list[i] = parents[i].name; 496 + } else if (parents[i].flag == PARENT_CLK_EXTERNAL) { 497 + ret = of_property_match_string(np, "clock-names", 498 + parents[i].name); 499 + if (ret < 0) 500 + strcpy(parents[i].name, "dummy_name"); 501 + parent_list[i] = parents[i].name; 502 + } else { 503 + strcat(parents[i].name, 504 + clk_type_postfix[clk_nodes[parents[i].flag - 1]. 505 + type]); 506 + parent_list[i] = parents[i].name; 507 + } 508 + } 509 + 510 + *num_parents = total_parents; 511 + return 0; 512 + } 513 + 514 + /** 515 + * zynqmp_register_clk_topology() - Register clock topology 516 + * @clk_id: Clock index 517 + * @clk_name: Clock Name 518 + * @num_parents: Total number of parents 519 + * @parent_names: List of parents name 520 + * 521 + * Return: Returns either clock hardware or error+reason 522 + */ 523 + static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name, 524 + int num_parents, 525 + const char **parent_names) 526 + { 527 + int j; 528 + u32 num_nodes; 529 + char *clk_out = NULL; 530 + struct clock_topology *nodes; 531 + struct clk_hw *hw = NULL; 532 + 533 + nodes = clock[clk_id].node; 534 + num_nodes = clock[clk_id].num_nodes; 535 + 536 + for (j = 0; j < num_nodes; j++) { 537 + /* 538 + * Clock name received from firmware is output clock name. 539 + * Intermediate clock names are postfixed with type of clock. 540 + */ 541 + if (j != (num_nodes - 1)) { 542 + clk_out = kasprintf(GFP_KERNEL, "%s%s", clk_name, 543 + clk_type_postfix[nodes[j].type]); 544 + } else { 545 + clk_out = kasprintf(GFP_KERNEL, "%s", clk_name); 546 + } 547 + 548 + if (!clk_topology[nodes[j].type]) 549 + continue; 550 + 551 + hw = (*clk_topology[nodes[j].type])(clk_out, clk_id, 552 + parent_names, 553 + num_parents, 554 + &nodes[j]); 555 + if (IS_ERR(hw)) 556 + pr_warn_once("%s() %s register fail with %ld\n", 557 + __func__, clk_name, PTR_ERR(hw)); 558 + 559 + parent_names[0] = clk_out; 560 + } 561 + kfree(clk_out); 562 + return hw; 563 + } 564 + 565 + /** 566 + * zynqmp_register_clocks() - Register clocks 567 + * @np: Device node 568 + * 569 + * Return: 0 on success else error code 570 + */ 571 + static int zynqmp_register_clocks(struct device_node *np) 572 + { 573 + int ret; 574 + u32 i, total_parents = 0, type = 0; 575 + const char *parent_names[MAX_PARENT]; 576 + 577 + for (i = 0; i < clock_max_idx; i++) { 578 + char clk_name[MAX_NAME_LEN]; 579 + 580 + /* get clock name, continue to next clock if name not found */ 581 + if (zynqmp_get_clock_name(i, clk_name)) 582 + continue; 583 + 584 + /* Check if clock is valid and output clock. 585 + * Do not register invalid or external clock. 586 + */ 587 + ret = zynqmp_get_clock_type(i, &type); 588 + if (ret || type != CLK_TYPE_OUTPUT) 589 + continue; 590 + 591 + /* Get parents of clock*/ 592 + if (zynqmp_get_parent_list(np, i, parent_names, 593 + &total_parents)) { 594 + WARN_ONCE(1, "No parents found for %s\n", 595 + clock[i].clk_name); 596 + continue; 597 + } 598 + 599 + zynqmp_data->hws[i] = 600 + zynqmp_register_clk_topology(i, clk_name, 601 + total_parents, 602 + parent_names); 603 + } 604 + 605 + for (i = 0; i < clock_max_idx; i++) { 606 + if (IS_ERR(zynqmp_data->hws[i])) { 607 + pr_err("Zynq Ultrascale+ MPSoC clk %s: register failed with %ld\n", 608 + clock[i].clk_name, PTR_ERR(zynqmp_data->hws[i])); 609 + WARN_ON(1); 610 + } 611 + } 612 + return 0; 613 + } 614 + 615 + /** 616 + * zynqmp_get_clock_info() - Get clock information from firmware using PM_API 617 + */ 618 + static void zynqmp_get_clock_info(void) 619 + { 620 + int i, ret; 621 + u32 attr, type = 0; 622 + 623 + for (i = 0; i < clock_max_idx; i++) { 624 + zynqmp_pm_clock_get_name(i, clock[i].clk_name); 625 + if (!strcmp(clock[i].clk_name, RESERVED_CLK_NAME)) 626 + continue; 627 + 628 + ret = zynqmp_pm_clock_get_attributes(i, &attr); 629 + if (ret) 630 + continue; 631 + 632 + clock[i].valid = attr & CLK_VALID_MASK; 633 + clock[i].type = attr >> CLK_TYPE_SHIFT ? CLK_TYPE_EXTERNAL : 634 + CLK_TYPE_OUTPUT; 635 + } 636 + 637 + /* Get topology of all clock */ 638 + for (i = 0; i < clock_max_idx; i++) { 639 + ret = zynqmp_get_clock_type(i, &type); 640 + if (ret || type != CLK_TYPE_OUTPUT) 641 + continue; 642 + 643 + ret = zynqmp_clock_get_topology(i, clock[i].node, 644 + &clock[i].num_nodes); 645 + if (ret) 646 + continue; 647 + 648 + ret = zynqmp_clock_get_parents(i, clock[i].parent, 649 + &clock[i].num_parents); 650 + if (ret) 651 + continue; 652 + } 653 + } 654 + 655 + /** 656 + * zynqmp_clk_setup() - Setup the clock framework and register clocks 657 + * @np: Device node 658 + * 659 + * Return: 0 on success else error code 660 + */ 661 + static int zynqmp_clk_setup(struct device_node *np) 662 + { 663 + int ret; 664 + 665 + ret = zynqmp_pm_clock_get_num_clocks(&clock_max_idx); 666 + if (ret) 667 + return ret; 668 + 669 + zynqmp_data = kzalloc(sizeof(*zynqmp_data) + sizeof(*zynqmp_data) * 670 + clock_max_idx, GFP_KERNEL); 671 + if (!zynqmp_data) 672 + return -ENOMEM; 673 + 674 + clock = kcalloc(clock_max_idx, sizeof(*clock), GFP_KERNEL); 675 + if (!clock) { 676 + kfree(zynqmp_data); 677 + return -ENOMEM; 678 + } 679 + 680 + zynqmp_get_clock_info(); 681 + zynqmp_register_clocks(np); 682 + 683 + zynqmp_data->num = clock_max_idx; 684 + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, zynqmp_data); 685 + 686 + return 0; 687 + } 688 + 689 + static int zynqmp_clock_probe(struct platform_device *pdev) 690 + { 691 + int ret; 692 + struct device *dev = &pdev->dev; 693 + 694 + eemi_ops = zynqmp_pm_get_eemi_ops(); 695 + if (!eemi_ops) 696 + return -ENXIO; 697 + 698 + ret = zynqmp_clk_setup(dev->of_node); 699 + 700 + return ret; 701 + } 702 + 703 + static const struct of_device_id zynqmp_clock_of_match[] = { 704 + {.compatible = "xlnx,zynqmp-clk"}, 705 + {}, 706 + }; 707 + MODULE_DEVICE_TABLE(of, zynqmp_clock_of_match); 708 + 709 + static struct platform_driver zynqmp_clock_driver = { 710 + .driver = { 711 + .name = "zynqmp_clock", 712 + .of_match_table = zynqmp_clock_of_match, 713 + }, 714 + .probe = zynqmp_clock_probe, 715 + }; 716 + module_platform_driver(zynqmp_clock_driver);
+217
drivers/clk/zynqmp/divider.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Zynq UltraScale+ MPSoC Divider support 4 + * 5 + * Copyright (C) 2016-2018 Xilinx 6 + * 7 + * Adjustable divider clock implementation 8 + */ 9 + 10 + #include <linux/clk.h> 11 + #include <linux/clk-provider.h> 12 + #include <linux/slab.h> 13 + #include "clk-zynqmp.h" 14 + 15 + /* 16 + * DOC: basic adjustable divider clock that cannot gate 17 + * 18 + * Traits of this clock: 19 + * prepare - clk_prepare only ensures that parents are prepared 20 + * enable - clk_enable only ensures that parents are enabled 21 + * rate - rate is adjustable. clk->rate = ceiling(parent->rate / divisor) 22 + * parent - fixed parent. No clk_set_parent support 23 + */ 24 + 25 + #define to_zynqmp_clk_divider(_hw) \ 26 + container_of(_hw, struct zynqmp_clk_divider, hw) 27 + 28 + #define CLK_FRAC BIT(13) /* has a fractional parent */ 29 + 30 + /** 31 + * struct zynqmp_clk_divider - adjustable divider clock 32 + * @hw: handle between common and hardware-specific interfaces 33 + * @flags: Hardware specific flags 34 + * @clk_id: Id of clock 35 + * @div_type: divisor type (TYPE_DIV1 or TYPE_DIV2) 36 + */ 37 + struct zynqmp_clk_divider { 38 + struct clk_hw hw; 39 + u8 flags; 40 + u32 clk_id; 41 + u32 div_type; 42 + }; 43 + 44 + static inline int zynqmp_divider_get_val(unsigned long parent_rate, 45 + unsigned long rate) 46 + { 47 + return DIV_ROUND_CLOSEST(parent_rate, rate); 48 + } 49 + 50 + /** 51 + * zynqmp_clk_divider_recalc_rate() - Recalc rate of divider clock 52 + * @hw: handle between common and hardware-specific interfaces 53 + * @parent_rate: rate of parent clock 54 + * 55 + * Return: 0 on success else error+reason 56 + */ 57 + static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw, 58 + unsigned long parent_rate) 59 + { 60 + struct zynqmp_clk_divider *divider = to_zynqmp_clk_divider(hw); 61 + const char *clk_name = clk_hw_get_name(hw); 62 + u32 clk_id = divider->clk_id; 63 + u32 div_type = divider->div_type; 64 + u32 div, value; 65 + int ret; 66 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 67 + 68 + ret = eemi_ops->clock_getdivider(clk_id, &div); 69 + 70 + if (ret) 71 + pr_warn_once("%s() get divider failed for %s, ret = %d\n", 72 + __func__, clk_name, ret); 73 + 74 + if (div_type == TYPE_DIV1) 75 + value = div & 0xFFFF; 76 + else 77 + value = div >> 16; 78 + 79 + return DIV_ROUND_UP_ULL(parent_rate, value); 80 + } 81 + 82 + /** 83 + * zynqmp_clk_divider_round_rate() - Round rate of divider clock 84 + * @hw: handle between common and hardware-specific interfaces 85 + * @rate: rate of clock to be set 86 + * @prate: rate of parent clock 87 + * 88 + * Return: 0 on success else error+reason 89 + */ 90 + static long zynqmp_clk_divider_round_rate(struct clk_hw *hw, 91 + unsigned long rate, 92 + unsigned long *prate) 93 + { 94 + struct zynqmp_clk_divider *divider = to_zynqmp_clk_divider(hw); 95 + const char *clk_name = clk_hw_get_name(hw); 96 + u32 clk_id = divider->clk_id; 97 + u32 div_type = divider->div_type; 98 + u32 bestdiv; 99 + int ret; 100 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 101 + 102 + /* if read only, just return current value */ 103 + if (divider->flags & CLK_DIVIDER_READ_ONLY) { 104 + ret = eemi_ops->clock_getdivider(clk_id, &bestdiv); 105 + 106 + if (ret) 107 + pr_warn_once("%s() get divider failed for %s, ret = %d\n", 108 + __func__, clk_name, ret); 109 + if (div_type == TYPE_DIV1) 110 + bestdiv = bestdiv & 0xFFFF; 111 + else 112 + bestdiv = bestdiv >> 16; 113 + 114 + return DIV_ROUND_UP_ULL((u64)*prate, bestdiv); 115 + } 116 + 117 + bestdiv = zynqmp_divider_get_val(*prate, rate); 118 + 119 + if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && 120 + (divider->flags & CLK_FRAC)) 121 + bestdiv = rate % *prate ? 1 : bestdiv; 122 + *prate = rate * bestdiv; 123 + 124 + return rate; 125 + } 126 + 127 + /** 128 + * zynqmp_clk_divider_set_rate() - Set rate of divider clock 129 + * @hw: handle between common and hardware-specific interfaces 130 + * @rate: rate of clock to be set 131 + * @parent_rate: rate of parent clock 132 + * 133 + * Return: 0 on success else error+reason 134 + */ 135 + static int zynqmp_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, 136 + unsigned long parent_rate) 137 + { 138 + struct zynqmp_clk_divider *divider = to_zynqmp_clk_divider(hw); 139 + const char *clk_name = clk_hw_get_name(hw); 140 + u32 clk_id = divider->clk_id; 141 + u32 div_type = divider->div_type; 142 + u32 value, div; 143 + int ret; 144 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 145 + 146 + value = zynqmp_divider_get_val(parent_rate, rate); 147 + if (div_type == TYPE_DIV1) { 148 + div = value & 0xFFFF; 149 + div |= 0xffff << 16; 150 + } else { 151 + div = 0xffff; 152 + div |= value << 16; 153 + } 154 + 155 + ret = eemi_ops->clock_setdivider(clk_id, div); 156 + 157 + if (ret) 158 + pr_warn_once("%s() set divider failed for %s, ret = %d\n", 159 + __func__, clk_name, ret); 160 + 161 + return ret; 162 + } 163 + 164 + static const struct clk_ops zynqmp_clk_divider_ops = { 165 + .recalc_rate = zynqmp_clk_divider_recalc_rate, 166 + .round_rate = zynqmp_clk_divider_round_rate, 167 + .set_rate = zynqmp_clk_divider_set_rate, 168 + }; 169 + 170 + /** 171 + * zynqmp_clk_register_divider() - Register a divider clock 172 + * @name: Name of this clock 173 + * @clk_id: Id of clock 174 + * @parents: Name of this clock's parents 175 + * @num_parents: Number of parents 176 + * @nodes: Clock topology node 177 + * 178 + * Return: clock hardware to registered clock divider 179 + */ 180 + struct clk_hw *zynqmp_clk_register_divider(const char *name, 181 + u32 clk_id, 182 + const char * const *parents, 183 + u8 num_parents, 184 + const struct clock_topology *nodes) 185 + { 186 + struct zynqmp_clk_divider *div; 187 + struct clk_hw *hw; 188 + struct clk_init_data init; 189 + int ret; 190 + 191 + /* allocate the divider */ 192 + div = kzalloc(sizeof(*div), GFP_KERNEL); 193 + if (!div) 194 + return ERR_PTR(-ENOMEM); 195 + 196 + init.name = name; 197 + init.ops = &zynqmp_clk_divider_ops; 198 + init.flags = nodes->flag; 199 + init.parent_names = parents; 200 + init.num_parents = 1; 201 + 202 + /* struct clk_divider assignments */ 203 + div->flags = nodes->type_flag; 204 + div->hw.init = &init; 205 + div->clk_id = clk_id; 206 + div->div_type = nodes->type; 207 + 208 + hw = &div->hw; 209 + ret = clk_hw_register(NULL, hw); 210 + if (ret) { 211 + kfree(div); 212 + hw = ERR_PTR(ret); 213 + } 214 + 215 + return hw; 216 + } 217 + EXPORT_SYMBOL_GPL(zynqmp_clk_register_divider);
+335
drivers/clk/zynqmp/pll.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Zynq UltraScale+ MPSoC PLL driver 4 + * 5 + * Copyright (C) 2016-2018 Xilinx 6 + */ 7 + 8 + #include <linux/clk.h> 9 + #include <linux/clk-provider.h> 10 + #include <linux/slab.h> 11 + #include "clk-zynqmp.h" 12 + 13 + /** 14 + * struct zynqmp_pll - PLL clock 15 + * @hw: Handle between common and hardware-specific interfaces 16 + * @clk_id: PLL clock ID 17 + */ 18 + struct zynqmp_pll { 19 + struct clk_hw hw; 20 + u32 clk_id; 21 + }; 22 + 23 + #define to_zynqmp_pll(_hw) container_of(_hw, struct zynqmp_pll, hw) 24 + 25 + #define PLL_FBDIV_MIN 25 26 + #define PLL_FBDIV_MAX 125 27 + 28 + #define PS_PLL_VCO_MIN 1500000000 29 + #define PS_PLL_VCO_MAX 3000000000UL 30 + 31 + enum pll_mode { 32 + PLL_MODE_INT, 33 + PLL_MODE_FRAC, 34 + }; 35 + 36 + #define FRAC_OFFSET 0x8 37 + #define PLLFCFG_FRAC_EN BIT(31) 38 + #define FRAC_DIV BIT(16) /* 2^16 */ 39 + 40 + /** 41 + * zynqmp_pll_get_mode() - Get mode of PLL 42 + * @hw: Handle between common and hardware-specific interfaces 43 + * 44 + * Return: Mode of PLL 45 + */ 46 + static inline enum pll_mode zynqmp_pll_get_mode(struct clk_hw *hw) 47 + { 48 + struct zynqmp_pll *clk = to_zynqmp_pll(hw); 49 + u32 clk_id = clk->clk_id; 50 + const char *clk_name = clk_hw_get_name(hw); 51 + u32 ret_payload[PAYLOAD_ARG_CNT]; 52 + int ret; 53 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 54 + 55 + ret = eemi_ops->ioctl(0, IOCTL_GET_PLL_FRAC_MODE, clk_id, 0, 56 + ret_payload); 57 + if (ret) 58 + pr_warn_once("%s() PLL get frac mode failed for %s, ret = %d\n", 59 + __func__, clk_name, ret); 60 + 61 + return ret_payload[1]; 62 + } 63 + 64 + /** 65 + * zynqmp_pll_set_mode() - Set the PLL mode 66 + * @hw: Handle between common and hardware-specific interfaces 67 + * @on: Flag to determine the mode 68 + */ 69 + static inline void zynqmp_pll_set_mode(struct clk_hw *hw, bool on) 70 + { 71 + struct zynqmp_pll *clk = to_zynqmp_pll(hw); 72 + u32 clk_id = clk->clk_id; 73 + const char *clk_name = clk_hw_get_name(hw); 74 + int ret; 75 + u32 mode; 76 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 77 + 78 + if (on) 79 + mode = PLL_MODE_FRAC; 80 + else 81 + mode = PLL_MODE_INT; 82 + 83 + ret = eemi_ops->ioctl(0, IOCTL_SET_PLL_FRAC_MODE, clk_id, mode, NULL); 84 + if (ret) 85 + pr_warn_once("%s() PLL set frac mode failed for %s, ret = %d\n", 86 + __func__, clk_name, ret); 87 + } 88 + 89 + /** 90 + * zynqmp_pll_round_rate() - Round a clock frequency 91 + * @hw: Handle between common and hardware-specific interfaces 92 + * @rate: Desired clock frequency 93 + * @prate: Clock frequency of parent clock 94 + * 95 + * Return: Frequency closest to @rate the hardware can generate 96 + */ 97 + static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate, 98 + unsigned long *prate) 99 + { 100 + u32 fbdiv; 101 + long rate_div, f; 102 + 103 + /* Enable the fractional mode if needed */ 104 + rate_div = (rate * FRAC_DIV) / *prate; 105 + f = rate_div % FRAC_DIV; 106 + zynqmp_pll_set_mode(hw, !!f); 107 + 108 + if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) { 109 + if (rate > PS_PLL_VCO_MAX) { 110 + fbdiv = rate / PS_PLL_VCO_MAX; 111 + rate = rate / (fbdiv + 1); 112 + } 113 + if (rate < PS_PLL_VCO_MIN) { 114 + fbdiv = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate); 115 + rate = rate * fbdiv; 116 + } 117 + return rate; 118 + } 119 + 120 + fbdiv = DIV_ROUND_CLOSEST(rate, *prate); 121 + fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); 122 + return *prate * fbdiv; 123 + } 124 + 125 + /** 126 + * zynqmp_pll_recalc_rate() - Recalculate clock frequency 127 + * @hw: Handle between common and hardware-specific interfaces 128 + * @parent_rate: Clock frequency of parent clock 129 + * 130 + * Return: Current clock frequency 131 + */ 132 + static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw, 133 + unsigned long parent_rate) 134 + { 135 + struct zynqmp_pll *clk = to_zynqmp_pll(hw); 136 + u32 clk_id = clk->clk_id; 137 + const char *clk_name = clk_hw_get_name(hw); 138 + u32 fbdiv, data; 139 + unsigned long rate, frac; 140 + u32 ret_payload[PAYLOAD_ARG_CNT]; 141 + int ret; 142 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 143 + 144 + ret = eemi_ops->clock_getdivider(clk_id, &fbdiv); 145 + if (ret) 146 + pr_warn_once("%s() get divider failed for %s, ret = %d\n", 147 + __func__, clk_name, ret); 148 + 149 + rate = parent_rate * fbdiv; 150 + if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) { 151 + eemi_ops->ioctl(0, IOCTL_GET_PLL_FRAC_DATA, clk_id, 0, 152 + ret_payload); 153 + data = ret_payload[1]; 154 + frac = (parent_rate * data) / FRAC_DIV; 155 + rate = rate + frac; 156 + } 157 + 158 + return rate; 159 + } 160 + 161 + /** 162 + * zynqmp_pll_set_rate() - Set rate of PLL 163 + * @hw: Handle between common and hardware-specific interfaces 164 + * @rate: Frequency of clock to be set 165 + * @parent_rate: Clock frequency of parent clock 166 + * 167 + * Set PLL divider to set desired rate. 168 + * 169 + * Returns: rate which is set on success else error code 170 + */ 171 + static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate, 172 + unsigned long parent_rate) 173 + { 174 + struct zynqmp_pll *clk = to_zynqmp_pll(hw); 175 + u32 clk_id = clk->clk_id; 176 + const char *clk_name = clk_hw_get_name(hw); 177 + u32 fbdiv; 178 + long rate_div, frac, m, f; 179 + int ret; 180 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 181 + 182 + if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) { 183 + rate_div = (rate * FRAC_DIV) / parent_rate; 184 + m = rate_div / FRAC_DIV; 185 + f = rate_div % FRAC_DIV; 186 + m = clamp_t(u32, m, (PLL_FBDIV_MIN), (PLL_FBDIV_MAX)); 187 + rate = parent_rate * m; 188 + frac = (parent_rate * f) / FRAC_DIV; 189 + 190 + ret = eemi_ops->clock_setdivider(clk_id, m); 191 + if (ret) 192 + pr_warn_once("%s() set divider failed for %s, ret = %d\n", 193 + __func__, clk_name, ret); 194 + 195 + eemi_ops->ioctl(0, IOCTL_SET_PLL_FRAC_DATA, clk_id, f, NULL); 196 + 197 + return rate + frac; 198 + } 199 + 200 + fbdiv = DIV_ROUND_CLOSEST(rate, parent_rate); 201 + fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); 202 + ret = eemi_ops->clock_setdivider(clk_id, fbdiv); 203 + if (ret) 204 + pr_warn_once("%s() set divider failed for %s, ret = %d\n", 205 + __func__, clk_name, ret); 206 + 207 + return parent_rate * fbdiv; 208 + } 209 + 210 + /** 211 + * zynqmp_pll_is_enabled() - Check if a clock is enabled 212 + * @hw: Handle between common and hardware-specific interfaces 213 + * 214 + * Return: 1 if the clock is enabled, 0 otherwise 215 + */ 216 + static int zynqmp_pll_is_enabled(struct clk_hw *hw) 217 + { 218 + struct zynqmp_pll *clk = to_zynqmp_pll(hw); 219 + const char *clk_name = clk_hw_get_name(hw); 220 + u32 clk_id = clk->clk_id; 221 + unsigned int state; 222 + int ret; 223 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 224 + 225 + ret = eemi_ops->clock_getstate(clk_id, &state); 226 + if (ret) { 227 + pr_warn_once("%s() clock get state failed for %s, ret = %d\n", 228 + __func__, clk_name, ret); 229 + return -EIO; 230 + } 231 + 232 + return state ? 1 : 0; 233 + } 234 + 235 + /** 236 + * zynqmp_pll_enable() - Enable clock 237 + * @hw: Handle between common and hardware-specific interfaces 238 + * 239 + * Return: 0 on success else error code 240 + */ 241 + static int zynqmp_pll_enable(struct clk_hw *hw) 242 + { 243 + struct zynqmp_pll *clk = to_zynqmp_pll(hw); 244 + const char *clk_name = clk_hw_get_name(hw); 245 + u32 clk_id = clk->clk_id; 246 + int ret; 247 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 248 + 249 + if (zynqmp_pll_is_enabled(hw)) 250 + return 0; 251 + 252 + ret = eemi_ops->clock_enable(clk_id); 253 + if (ret) 254 + pr_warn_once("%s() clock enable failed for %s, ret = %d\n", 255 + __func__, clk_name, ret); 256 + 257 + return ret; 258 + } 259 + 260 + /** 261 + * zynqmp_pll_disable() - Disable clock 262 + * @hw: Handle between common and hardware-specific interfaces 263 + */ 264 + static void zynqmp_pll_disable(struct clk_hw *hw) 265 + { 266 + struct zynqmp_pll *clk = to_zynqmp_pll(hw); 267 + const char *clk_name = clk_hw_get_name(hw); 268 + u32 clk_id = clk->clk_id; 269 + int ret; 270 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 271 + 272 + if (!zynqmp_pll_is_enabled(hw)) 273 + return; 274 + 275 + ret = eemi_ops->clock_disable(clk_id); 276 + if (ret) 277 + pr_warn_once("%s() clock disable failed for %s, ret = %d\n", 278 + __func__, clk_name, ret); 279 + } 280 + 281 + static const struct clk_ops zynqmp_pll_ops = { 282 + .enable = zynqmp_pll_enable, 283 + .disable = zynqmp_pll_disable, 284 + .is_enabled = zynqmp_pll_is_enabled, 285 + .round_rate = zynqmp_pll_round_rate, 286 + .recalc_rate = zynqmp_pll_recalc_rate, 287 + .set_rate = zynqmp_pll_set_rate, 288 + }; 289 + 290 + /** 291 + * zynqmp_clk_register_pll() - Register PLL with the clock framework 292 + * @name: PLL name 293 + * @clk_id: Clock ID 294 + * @parents: Name of this clock's parents 295 + * @num_parents: Number of parents 296 + * @nodes: Clock topology node 297 + * 298 + * Return: clock hardware to the registered clock 299 + */ 300 + struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id, 301 + const char * const *parents, 302 + u8 num_parents, 303 + const struct clock_topology *nodes) 304 + { 305 + struct zynqmp_pll *pll; 306 + struct clk_hw *hw; 307 + struct clk_init_data init; 308 + int ret; 309 + 310 + init.name = name; 311 + init.ops = &zynqmp_pll_ops; 312 + init.flags = nodes->flag; 313 + init.parent_names = parents; 314 + init.num_parents = 1; 315 + 316 + pll = kzalloc(sizeof(*pll), GFP_KERNEL); 317 + if (!pll) 318 + return ERR_PTR(-ENOMEM); 319 + 320 + pll->hw.init = &init; 321 + pll->clk_id = clk_id; 322 + 323 + hw = &pll->hw; 324 + ret = clk_hw_register(NULL, hw); 325 + if (ret) { 326 + kfree(pll); 327 + return ERR_PTR(ret); 328 + } 329 + 330 + clk_hw_set_rate_range(hw, PS_PLL_VCO_MIN, PS_PLL_VCO_MAX); 331 + if (ret < 0) 332 + pr_err("%s:ERROR clk_set_rate_range failed %d\n", name, ret); 333 + 334 + return hw; 335 + }
+14
drivers/edac/Kconfig
··· 460 460 Support for error detection and correction on the 461 461 TI SoCs. 462 462 463 + config EDAC_QCOM 464 + tristate "QCOM EDAC Controller" 465 + depends on ARCH_QCOM && QCOM_LLCC 466 + help 467 + Support for error detection and correction on the 468 + Qualcomm Technologies, Inc. SoCs. 469 + 470 + This driver reports Single Bit Errors (SBEs) and Double Bit Errors (DBEs). 471 + As of now, it supports error reporting for Last Level Cache Controller (LLCC) 472 + of Tag RAM and Data RAM. 473 + 474 + For debugging issues having to do with stability and overall system 475 + health, you should probably say 'Y' here. 476 + 463 477 endif # EDAC
+1
drivers/edac/Makefile
··· 77 77 obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o 78 78 obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o 79 79 obj-$(CONFIG_EDAC_TI) += ti_edac.o 80 + obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o
+414
drivers/edac/qcom_edac.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #include <linux/edac.h> 7 + #include <linux/interrupt.h> 8 + #include <linux/kernel.h> 9 + #include <linux/of.h> 10 + #include <linux/platform_device.h> 11 + #include <linux/regmap.h> 12 + #include <linux/soc/qcom/llcc-qcom.h> 13 + 14 + #include "edac_mc.h" 15 + #include "edac_device.h" 16 + 17 + #define EDAC_LLCC "qcom_llcc" 18 + 19 + #define LLCC_ERP_PANIC_ON_UE 1 20 + 21 + #define TRP_SYN_REG_CNT 6 22 + #define DRP_SYN_REG_CNT 8 23 + 24 + #define LLCC_COMMON_STATUS0 0x0003000c 25 + #define LLCC_LB_CNT_MASK GENMASK(31, 28) 26 + #define LLCC_LB_CNT_SHIFT 28 27 + 28 + /* Single & double bit syndrome register offsets */ 29 + #define TRP_ECC_SB_ERR_SYN0 0x0002304c 30 + #define TRP_ECC_DB_ERR_SYN0 0x00020370 31 + #define DRP_ECC_SB_ERR_SYN0 0x0004204c 32 + #define DRP_ECC_DB_ERR_SYN0 0x00042070 33 + 34 + /* Error register offsets */ 35 + #define TRP_ECC_ERROR_STATUS1 0x00020348 36 + #define TRP_ECC_ERROR_STATUS0 0x00020344 37 + #define DRP_ECC_ERROR_STATUS1 0x00042048 38 + #define DRP_ECC_ERROR_STATUS0 0x00042044 39 + 40 + /* TRP, DRP interrupt register offsets */ 41 + #define DRP_INTERRUPT_STATUS 0x00041000 42 + #define TRP_INTERRUPT_0_STATUS 0x00020480 43 + #define DRP_INTERRUPT_CLEAR 0x00041008 44 + #define DRP_ECC_ERROR_CNTR_CLEAR 0x00040004 45 + #define TRP_INTERRUPT_0_CLEAR 0x00020484 46 + #define TRP_ECC_ERROR_CNTR_CLEAR 0x00020440 47 + 48 + /* Mask and shift macros */ 49 + #define ECC_DB_ERR_COUNT_MASK GENMASK(4, 0) 50 + #define ECC_DB_ERR_WAYS_MASK GENMASK(31, 16) 51 + #define ECC_DB_ERR_WAYS_SHIFT BIT(4) 52 + 53 + #define ECC_SB_ERR_COUNT_MASK GENMASK(23, 16) 54 + #define ECC_SB_ERR_COUNT_SHIFT BIT(4) 55 + #define ECC_SB_ERR_WAYS_MASK GENMASK(15, 0) 56 + 57 + #define SB_ECC_ERROR BIT(0) 58 + #define DB_ECC_ERROR BIT(1) 59 + 60 + #define DRP_TRP_INT_CLEAR GENMASK(1, 0) 61 + #define DRP_TRP_CNT_CLEAR GENMASK(1, 0) 62 + 63 + /* Config registers offsets*/ 64 + #define DRP_ECC_ERROR_CFG 0x00040000 65 + 66 + /* Tag RAM, Data RAM interrupt register offsets */ 67 + #define CMN_INTERRUPT_0_ENABLE 0x0003001c 68 + #define CMN_INTERRUPT_2_ENABLE 0x0003003c 69 + #define TRP_INTERRUPT_0_ENABLE 0x00020488 70 + #define DRP_INTERRUPT_ENABLE 0x0004100c 71 + 72 + #define SB_ERROR_THRESHOLD 0x1 73 + #define SB_ERROR_THRESHOLD_SHIFT 24 74 + #define SB_DB_TRP_INTERRUPT_ENABLE 0x3 75 + #define TRP0_INTERRUPT_ENABLE 0x1 76 + #define DRP0_INTERRUPT_ENABLE BIT(6) 77 + #define SB_DB_DRP_INTERRUPT_ENABLE 0x3 78 + 79 + enum { 80 + LLCC_DRAM_CE = 0, 81 + LLCC_DRAM_UE, 82 + LLCC_TRAM_CE, 83 + LLCC_TRAM_UE, 84 + }; 85 + 86 + static const struct llcc_edac_reg_data edac_reg_data[] = { 87 + [LLCC_DRAM_CE] = { 88 + .name = "DRAM Single-bit", 89 + .synd_reg = DRP_ECC_SB_ERR_SYN0, 90 + .count_status_reg = DRP_ECC_ERROR_STATUS1, 91 + .ways_status_reg = DRP_ECC_ERROR_STATUS0, 92 + .reg_cnt = DRP_SYN_REG_CNT, 93 + .count_mask = ECC_SB_ERR_COUNT_MASK, 94 + .ways_mask = ECC_SB_ERR_WAYS_MASK, 95 + .count_shift = ECC_SB_ERR_COUNT_SHIFT, 96 + }, 97 + [LLCC_DRAM_UE] = { 98 + .name = "DRAM Double-bit", 99 + .synd_reg = DRP_ECC_DB_ERR_SYN0, 100 + .count_status_reg = DRP_ECC_ERROR_STATUS1, 101 + .ways_status_reg = DRP_ECC_ERROR_STATUS0, 102 + .reg_cnt = DRP_SYN_REG_CNT, 103 + .count_mask = ECC_DB_ERR_COUNT_MASK, 104 + .ways_mask = ECC_DB_ERR_WAYS_MASK, 105 + .ways_shift = ECC_DB_ERR_WAYS_SHIFT, 106 + }, 107 + [LLCC_TRAM_CE] = { 108 + .name = "TRAM Single-bit", 109 + .synd_reg = TRP_ECC_SB_ERR_SYN0, 110 + .count_status_reg = TRP_ECC_ERROR_STATUS1, 111 + .ways_status_reg = TRP_ECC_ERROR_STATUS0, 112 + .reg_cnt = TRP_SYN_REG_CNT, 113 + .count_mask = ECC_SB_ERR_COUNT_MASK, 114 + .ways_mask = ECC_SB_ERR_WAYS_MASK, 115 + .count_shift = ECC_SB_ERR_COUNT_SHIFT, 116 + }, 117 + [LLCC_TRAM_UE] = { 118 + .name = "TRAM Double-bit", 119 + .synd_reg = TRP_ECC_DB_ERR_SYN0, 120 + .count_status_reg = TRP_ECC_ERROR_STATUS1, 121 + .ways_status_reg = TRP_ECC_ERROR_STATUS0, 122 + .reg_cnt = TRP_SYN_REG_CNT, 123 + .count_mask = ECC_DB_ERR_COUNT_MASK, 124 + .ways_mask = ECC_DB_ERR_WAYS_MASK, 125 + .ways_shift = ECC_DB_ERR_WAYS_SHIFT, 126 + }, 127 + }; 128 + 129 + static int qcom_llcc_core_setup(struct regmap *llcc_bcast_regmap) 130 + { 131 + u32 sb_err_threshold; 132 + int ret; 133 + 134 + /* 135 + * Configure interrupt enable registers such that Tag, Data RAM related 136 + * interrupts are propagated to interrupt controller for servicing 137 + */ 138 + ret = regmap_update_bits(llcc_bcast_regmap, CMN_INTERRUPT_2_ENABLE, 139 + TRP0_INTERRUPT_ENABLE, 140 + TRP0_INTERRUPT_ENABLE); 141 + if (ret) 142 + return ret; 143 + 144 + ret = regmap_update_bits(llcc_bcast_regmap, TRP_INTERRUPT_0_ENABLE, 145 + SB_DB_TRP_INTERRUPT_ENABLE, 146 + SB_DB_TRP_INTERRUPT_ENABLE); 147 + if (ret) 148 + return ret; 149 + 150 + sb_err_threshold = (SB_ERROR_THRESHOLD << SB_ERROR_THRESHOLD_SHIFT); 151 + ret = regmap_write(llcc_bcast_regmap, DRP_ECC_ERROR_CFG, 152 + sb_err_threshold); 153 + if (ret) 154 + return ret; 155 + 156 + ret = regmap_update_bits(llcc_bcast_regmap, CMN_INTERRUPT_2_ENABLE, 157 + DRP0_INTERRUPT_ENABLE, 158 + DRP0_INTERRUPT_ENABLE); 159 + if (ret) 160 + return ret; 161 + 162 + ret = regmap_write(llcc_bcast_regmap, DRP_INTERRUPT_ENABLE, 163 + SB_DB_DRP_INTERRUPT_ENABLE); 164 + return ret; 165 + } 166 + 167 + /* Clear the error interrupt and counter registers */ 168 + static int 169 + qcom_llcc_clear_error_status(int err_type, struct llcc_drv_data *drv) 170 + { 171 + int ret = 0; 172 + 173 + switch (err_type) { 174 + case LLCC_DRAM_CE: 175 + case LLCC_DRAM_UE: 176 + ret = regmap_write(drv->bcast_regmap, DRP_INTERRUPT_CLEAR, 177 + DRP_TRP_INT_CLEAR); 178 + if (ret) 179 + return ret; 180 + 181 + ret = regmap_write(drv->bcast_regmap, DRP_ECC_ERROR_CNTR_CLEAR, 182 + DRP_TRP_CNT_CLEAR); 183 + if (ret) 184 + return ret; 185 + break; 186 + case LLCC_TRAM_CE: 187 + case LLCC_TRAM_UE: 188 + ret = regmap_write(drv->bcast_regmap, TRP_INTERRUPT_0_CLEAR, 189 + DRP_TRP_INT_CLEAR); 190 + if (ret) 191 + return ret; 192 + 193 + ret = regmap_write(drv->bcast_regmap, TRP_ECC_ERROR_CNTR_CLEAR, 194 + DRP_TRP_CNT_CLEAR); 195 + if (ret) 196 + return ret; 197 + break; 198 + default: 199 + ret = -EINVAL; 200 + edac_printk(KERN_CRIT, EDAC_LLCC, "Unexpected error type: %d\n", 201 + err_type); 202 + } 203 + return ret; 204 + } 205 + 206 + /* Dump Syndrome registers data for Tag RAM, Data RAM bit errors*/ 207 + static int 208 + dump_syn_reg_values(struct llcc_drv_data *drv, u32 bank, int err_type) 209 + { 210 + struct llcc_edac_reg_data reg_data = edac_reg_data[err_type]; 211 + int err_cnt, err_ways, ret, i; 212 + u32 synd_reg, synd_val; 213 + 214 + for (i = 0; i < reg_data.reg_cnt; i++) { 215 + synd_reg = reg_data.synd_reg + (i * 4); 216 + ret = regmap_read(drv->regmap, drv->offsets[bank] + synd_reg, 217 + &synd_val); 218 + if (ret) 219 + goto clear; 220 + 221 + edac_printk(KERN_CRIT, EDAC_LLCC, "%s: ECC_SYN%d: 0x%8x\n", 222 + reg_data.name, i, synd_val); 223 + } 224 + 225 + ret = regmap_read(drv->regmap, 226 + drv->offsets[bank] + reg_data.count_status_reg, 227 + &err_cnt); 228 + if (ret) 229 + goto clear; 230 + 231 + err_cnt &= reg_data.count_mask; 232 + err_cnt >>= reg_data.count_shift; 233 + edac_printk(KERN_CRIT, EDAC_LLCC, "%s: Error count: 0x%4x\n", 234 + reg_data.name, err_cnt); 235 + 236 + ret = regmap_read(drv->regmap, 237 + drv->offsets[bank] + reg_data.ways_status_reg, 238 + &err_ways); 239 + if (ret) 240 + goto clear; 241 + 242 + err_ways &= reg_data.ways_mask; 243 + err_ways >>= reg_data.ways_shift; 244 + 245 + edac_printk(KERN_CRIT, EDAC_LLCC, "%s: Error ways: 0x%4x\n", 246 + reg_data.name, err_ways); 247 + 248 + clear: 249 + return qcom_llcc_clear_error_status(err_type, drv); 250 + } 251 + 252 + static int 253 + dump_syn_reg(struct edac_device_ctl_info *edev_ctl, int err_type, u32 bank) 254 + { 255 + struct llcc_drv_data *drv = edev_ctl->pvt_info; 256 + int ret; 257 + 258 + ret = dump_syn_reg_values(drv, bank, err_type); 259 + if (ret) 260 + return ret; 261 + 262 + switch (err_type) { 263 + case LLCC_DRAM_CE: 264 + edac_device_handle_ce(edev_ctl, 0, bank, 265 + "LLCC Data RAM correctable Error"); 266 + break; 267 + case LLCC_DRAM_UE: 268 + edac_device_handle_ue(edev_ctl, 0, bank, 269 + "LLCC Data RAM uncorrectable Error"); 270 + break; 271 + case LLCC_TRAM_CE: 272 + edac_device_handle_ce(edev_ctl, 0, bank, 273 + "LLCC Tag RAM correctable Error"); 274 + break; 275 + case LLCC_TRAM_UE: 276 + edac_device_handle_ue(edev_ctl, 0, bank, 277 + "LLCC Tag RAM uncorrectable Error"); 278 + break; 279 + default: 280 + ret = -EINVAL; 281 + edac_printk(KERN_CRIT, EDAC_LLCC, "Unexpected error type: %d\n", 282 + err_type); 283 + } 284 + 285 + return ret; 286 + } 287 + 288 + static irqreturn_t 289 + llcc_ecc_irq_handler(int irq, void *edev_ctl) 290 + { 291 + struct edac_device_ctl_info *edac_dev_ctl = edev_ctl; 292 + struct llcc_drv_data *drv = edac_dev_ctl->pvt_info; 293 + irqreturn_t irq_rc = IRQ_NONE; 294 + u32 drp_error, trp_error, i; 295 + bool irq_handled; 296 + int ret; 297 + 298 + /* Iterate over the banks and look for Tag RAM or Data RAM errors */ 299 + for (i = 0; i < drv->num_banks; i++) { 300 + ret = regmap_read(drv->regmap, 301 + drv->offsets[i] + DRP_INTERRUPT_STATUS, 302 + &drp_error); 303 + 304 + if (!ret && (drp_error & SB_ECC_ERROR)) { 305 + edac_printk(KERN_CRIT, EDAC_LLCC, 306 + "Single Bit Error detected in Data RAM\n"); 307 + ret = dump_syn_reg(edev_ctl, LLCC_DRAM_CE, i); 308 + } else if (!ret && (drp_error & DB_ECC_ERROR)) { 309 + edac_printk(KERN_CRIT, EDAC_LLCC, 310 + "Double Bit Error detected in Data RAM\n"); 311 + ret = dump_syn_reg(edev_ctl, LLCC_DRAM_UE, i); 312 + } 313 + if (!ret) 314 + irq_handled = true; 315 + 316 + ret = regmap_read(drv->regmap, 317 + drv->offsets[i] + TRP_INTERRUPT_0_STATUS, 318 + &trp_error); 319 + 320 + if (!ret && (trp_error & SB_ECC_ERROR)) { 321 + edac_printk(KERN_CRIT, EDAC_LLCC, 322 + "Single Bit Error detected in Tag RAM\n"); 323 + ret = dump_syn_reg(edev_ctl, LLCC_TRAM_CE, i); 324 + } else if (!ret && (trp_error & DB_ECC_ERROR)) { 325 + edac_printk(KERN_CRIT, EDAC_LLCC, 326 + "Double Bit Error detected in Tag RAM\n"); 327 + ret = dump_syn_reg(edev_ctl, LLCC_TRAM_UE, i); 328 + } 329 + if (!ret) 330 + irq_handled = true; 331 + } 332 + 333 + if (irq_handled) 334 + irq_rc = IRQ_HANDLED; 335 + 336 + return irq_rc; 337 + } 338 + 339 + static int qcom_llcc_edac_probe(struct platform_device *pdev) 340 + { 341 + struct llcc_drv_data *llcc_driv_data = pdev->dev.platform_data; 342 + struct edac_device_ctl_info *edev_ctl; 343 + struct device *dev = &pdev->dev; 344 + int ecc_irq; 345 + int rc; 346 + 347 + rc = qcom_llcc_core_setup(llcc_driv_data->bcast_regmap); 348 + if (rc) 349 + return rc; 350 + 351 + /* Allocate edac control info */ 352 + edev_ctl = edac_device_alloc_ctl_info(0, "qcom-llcc", 1, "bank", 353 + llcc_driv_data->num_banks, 1, 354 + NULL, 0, 355 + edac_device_alloc_index()); 356 + 357 + if (!edev_ctl) 358 + return -ENOMEM; 359 + 360 + edev_ctl->dev = dev; 361 + edev_ctl->mod_name = dev_name(dev); 362 + edev_ctl->dev_name = dev_name(dev); 363 + edev_ctl->ctl_name = "llcc"; 364 + edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE; 365 + edev_ctl->pvt_info = llcc_driv_data; 366 + 367 + rc = edac_device_add_device(edev_ctl); 368 + if (rc) 369 + goto out_mem; 370 + 371 + platform_set_drvdata(pdev, edev_ctl); 372 + 373 + /* Request for ecc irq */ 374 + ecc_irq = llcc_driv_data->ecc_irq; 375 + if (ecc_irq < 0) { 376 + rc = -ENODEV; 377 + goto out_dev; 378 + } 379 + rc = devm_request_irq(dev, ecc_irq, llcc_ecc_irq_handler, 380 + IRQF_TRIGGER_HIGH, "llcc_ecc", edev_ctl); 381 + if (rc) 382 + goto out_dev; 383 + 384 + return rc; 385 + 386 + out_dev: 387 + edac_device_del_device(edev_ctl->dev); 388 + out_mem: 389 + edac_device_free_ctl_info(edev_ctl); 390 + 391 + return rc; 392 + } 393 + 394 + static int qcom_llcc_edac_remove(struct platform_device *pdev) 395 + { 396 + struct edac_device_ctl_info *edev_ctl = dev_get_drvdata(&pdev->dev); 397 + 398 + edac_device_del_device(edev_ctl->dev); 399 + edac_device_free_ctl_info(edev_ctl); 400 + 401 + return 0; 402 + } 403 + 404 + static struct platform_driver qcom_llcc_edac_driver = { 405 + .probe = qcom_llcc_edac_probe, 406 + .remove = qcom_llcc_edac_remove, 407 + .driver = { 408 + .name = "qcom_llcc_edac", 409 + }, 410 + }; 411 + module_platform_driver(qcom_llcc_edac_driver); 412 + 413 + MODULE_DESCRIPTION("QCOM EDAC driver"); 414 + MODULE_LICENSE("GPL v2");
+2
drivers/firmware/Kconfig
··· 289 289 source "drivers/firmware/broadcom/Kconfig" 290 290 source "drivers/firmware/google/Kconfig" 291 291 source "drivers/firmware/efi/Kconfig" 292 + source "drivers/firmware/imx/Kconfig" 292 293 source "drivers/firmware/meson/Kconfig" 293 294 source "drivers/firmware/tegra/Kconfig" 295 + source "drivers/firmware/xilinx/Kconfig" 294 296 295 297 endmenu
+2
drivers/firmware/Makefile
··· 31 31 obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ 32 32 obj-$(CONFIG_EFI) += efi/ 33 33 obj-$(CONFIG_UEFI_CPER) += efi/ 34 + obj-y += imx/ 34 35 obj-y += tegra/ 36 + obj-y += xilinx/
+1 -1
drivers/firmware/arm_scmi/base.c
··· 208 208 209 209 ret = scmi_do_xfer(handle, t); 210 210 if (!ret) 211 - memcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE); 211 + strlcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE); 212 212 213 213 scmi_xfer_put(handle, t); 214 214
+1 -1
drivers/firmware/arm_scmi/clock.c
··· 111 111 112 112 ret = scmi_do_xfer(handle, t); 113 113 if (!ret) 114 - memcpy(clk->name, attr->name, SCMI_MAX_STR_SIZE); 114 + strlcpy(clk->name, attr->name, SCMI_MAX_STR_SIZE); 115 115 else 116 116 clk->name[0] = '\0'; 117 117
+29 -1
drivers/firmware/arm_scmi/perf.c
··· 174 174 dom_info->mult_factor = 175 175 (dom_info->sustained_freq_khz * 1000) / 176 176 dom_info->sustained_perf_level; 177 - memcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); 177 + strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); 178 178 } 179 179 180 180 scmi_xfer_put(handle, t); ··· 427 427 return ret; 428 428 } 429 429 430 + static int scmi_dvfs_est_power_get(const struct scmi_handle *handle, u32 domain, 431 + unsigned long *freq, unsigned long *power) 432 + { 433 + struct scmi_perf_info *pi = handle->perf_priv; 434 + struct perf_dom_info *dom; 435 + unsigned long opp_freq; 436 + int idx, ret = -EINVAL; 437 + struct scmi_opp *opp; 438 + 439 + dom = pi->dom_info + domain; 440 + if (!dom) 441 + return -EIO; 442 + 443 + for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) { 444 + opp_freq = opp->perf * dom->mult_factor; 445 + if (opp_freq < *freq) 446 + continue; 447 + 448 + *freq = opp_freq; 449 + *power = opp->power; 450 + ret = 0; 451 + break; 452 + } 453 + 454 + return ret; 455 + } 456 + 430 457 static struct scmi_perf_ops perf_ops = { 431 458 .limits_set = scmi_perf_limits_set, 432 459 .limits_get = scmi_perf_limits_get, ··· 464 437 .device_opps_add = scmi_dvfs_device_opps_add, 465 438 .freq_set = scmi_dvfs_freq_set, 466 439 .freq_get = scmi_dvfs_freq_get, 440 + .est_power_get = scmi_dvfs_est_power_get, 467 441 }; 468 442 469 443 static int scmi_perf_protocol_init(struct scmi_handle *handle)
+1 -1
drivers/firmware/arm_scmi/power.c
··· 106 106 dom_info->state_set_notify = SUPPORTS_STATE_SET_NOTIFY(flags); 107 107 dom_info->state_set_async = SUPPORTS_STATE_SET_ASYNC(flags); 108 108 dom_info->state_set_sync = SUPPORTS_STATE_SET_SYNC(flags); 109 - memcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); 109 + strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); 110 110 } 111 111 112 112 scmi_xfer_put(handle, t);
+1 -1
drivers/firmware/arm_scmi/sensors.c
··· 140 140 s = &si->sensors[desc_index + cnt]; 141 141 s->id = le32_to_cpu(buf->desc[cnt].id); 142 142 s->type = SENSOR_TYPE(attrh); 143 - memcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE); 143 + strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE); 144 144 } 145 145 146 146 desc_index += num_returned;
+11
drivers/firmware/imx/Kconfig
··· 1 + config IMX_SCU 2 + bool "IMX SCU Protocol driver" 3 + depends on IMX_MBOX 4 + help 5 + The System Controller Firmware (SCFW) is a low-level system function 6 + which runs on a dedicated Cortex-M core to provide power, clock, and 7 + resource management. It exists on some i.MX8 processors. e.g. i.MX8QM 8 + (QM, QP), and i.MX8QX (QXP, DX). 9 + 10 + This driver manages the IPC interface between host CPU and the 11 + SCU firmware running on M4.
+2
drivers/firmware/imx/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o
+270
drivers/firmware/imx/imx-scu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright 2018 NXP 4 + * Author: Dong Aisheng <aisheng.dong@nxp.com> 5 + * 6 + * Implementation of the SCU IPC functions using MUs (client side). 7 + * 8 + */ 9 + 10 + #include <linux/err.h> 11 + #include <linux/firmware/imx/types.h> 12 + #include <linux/firmware/imx/ipc.h> 13 + #include <linux/interrupt.h> 14 + #include <linux/irq.h> 15 + #include <linux/kernel.h> 16 + #include <linux/mailbox_client.h> 17 + #include <linux/module.h> 18 + #include <linux/mutex.h> 19 + #include <linux/of_platform.h> 20 + #include <linux/platform_device.h> 21 + 22 + #define SCU_MU_CHAN_NUM 8 23 + #define MAX_RX_TIMEOUT (msecs_to_jiffies(30)) 24 + 25 + struct imx_sc_chan { 26 + struct imx_sc_ipc *sc_ipc; 27 + 28 + struct mbox_client cl; 29 + struct mbox_chan *ch; 30 + int idx; 31 + }; 32 + 33 + struct imx_sc_ipc { 34 + /* SCU uses 4 Tx and 4 Rx channels */ 35 + struct imx_sc_chan chans[SCU_MU_CHAN_NUM]; 36 + struct device *dev; 37 + struct mutex lock; 38 + struct completion done; 39 + 40 + /* temporarily store the SCU msg */ 41 + u32 *msg; 42 + u8 rx_size; 43 + u8 count; 44 + }; 45 + 46 + /* 47 + * This type is used to indicate error response for most functions. 48 + */ 49 + enum imx_sc_error_codes { 50 + IMX_SC_ERR_NONE = 0, /* Success */ 51 + IMX_SC_ERR_VERSION = 1, /* Incompatible API version */ 52 + IMX_SC_ERR_CONFIG = 2, /* Configuration error */ 53 + IMX_SC_ERR_PARM = 3, /* Bad parameter */ 54 + IMX_SC_ERR_NOACCESS = 4, /* Permission error (no access) */ 55 + IMX_SC_ERR_LOCKED = 5, /* Permission error (locked) */ 56 + IMX_SC_ERR_UNAVAILABLE = 6, /* Unavailable (out of resources) */ 57 + IMX_SC_ERR_NOTFOUND = 7, /* Not found */ 58 + IMX_SC_ERR_NOPOWER = 8, /* No power */ 59 + IMX_SC_ERR_IPC = 9, /* Generic IPC error */ 60 + IMX_SC_ERR_BUSY = 10, /* Resource is currently busy/active */ 61 + IMX_SC_ERR_FAIL = 11, /* General I/O failure */ 62 + IMX_SC_ERR_LAST 63 + }; 64 + 65 + static int imx_sc_linux_errmap[IMX_SC_ERR_LAST] = { 66 + 0, /* IMX_SC_ERR_NONE */ 67 + -EINVAL, /* IMX_SC_ERR_VERSION */ 68 + -EINVAL, /* IMX_SC_ERR_CONFIG */ 69 + -EINVAL, /* IMX_SC_ERR_PARM */ 70 + -EACCES, /* IMX_SC_ERR_NOACCESS */ 71 + -EACCES, /* IMX_SC_ERR_LOCKED */ 72 + -ERANGE, /* IMX_SC_ERR_UNAVAILABLE */ 73 + -EEXIST, /* IMX_SC_ERR_NOTFOUND */ 74 + -EPERM, /* IMX_SC_ERR_NOPOWER */ 75 + -EPIPE, /* IMX_SC_ERR_IPC */ 76 + -EBUSY, /* IMX_SC_ERR_BUSY */ 77 + -EIO, /* IMX_SC_ERR_FAIL */ 78 + }; 79 + 80 + static struct imx_sc_ipc *imx_sc_ipc_handle; 81 + 82 + static inline int imx_sc_to_linux_errno(int errno) 83 + { 84 + if (errno >= IMX_SC_ERR_NONE && errno < IMX_SC_ERR_LAST) 85 + return imx_sc_linux_errmap[errno]; 86 + return -EIO; 87 + } 88 + 89 + /* 90 + * Get the default handle used by SCU 91 + */ 92 + int imx_scu_get_handle(struct imx_sc_ipc **ipc) 93 + { 94 + if (!imx_sc_ipc_handle) 95 + return -EPROBE_DEFER; 96 + 97 + *ipc = imx_sc_ipc_handle; 98 + return 0; 99 + } 100 + EXPORT_SYMBOL(imx_scu_get_handle); 101 + 102 + static void imx_scu_rx_callback(struct mbox_client *c, void *msg) 103 + { 104 + struct imx_sc_chan *sc_chan = container_of(c, struct imx_sc_chan, cl); 105 + struct imx_sc_ipc *sc_ipc = sc_chan->sc_ipc; 106 + struct imx_sc_rpc_msg *hdr; 107 + u32 *data = msg; 108 + 109 + if (sc_chan->idx == 0) { 110 + hdr = msg; 111 + sc_ipc->rx_size = hdr->size; 112 + dev_dbg(sc_ipc->dev, "msg rx size %u\n", sc_ipc->rx_size); 113 + if (sc_ipc->rx_size > 4) 114 + dev_warn(sc_ipc->dev, "RPC does not support receiving over 4 words: %u\n", 115 + sc_ipc->rx_size); 116 + } 117 + 118 + sc_ipc->msg[sc_chan->idx] = *data; 119 + sc_ipc->count++; 120 + 121 + dev_dbg(sc_ipc->dev, "mu %u msg %u 0x%x\n", sc_chan->idx, 122 + sc_ipc->count, *data); 123 + 124 + if ((sc_ipc->rx_size != 0) && (sc_ipc->count == sc_ipc->rx_size)) 125 + complete(&sc_ipc->done); 126 + } 127 + 128 + static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg) 129 + { 130 + struct imx_sc_rpc_msg *hdr = msg; 131 + struct imx_sc_chan *sc_chan; 132 + u32 *data = msg; 133 + int ret; 134 + int i; 135 + 136 + /* Check size */ 137 + if (hdr->size > IMX_SC_RPC_MAX_MSG) 138 + return -EINVAL; 139 + 140 + dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr->svc, 141 + hdr->func, hdr->size); 142 + 143 + for (i = 0; i < hdr->size; i++) { 144 + sc_chan = &sc_ipc->chans[i % 4]; 145 + ret = mbox_send_message(sc_chan->ch, &data[i]); 146 + if (ret < 0) 147 + return ret; 148 + } 149 + 150 + return 0; 151 + } 152 + 153 + /* 154 + * RPC command/response 155 + */ 156 + int imx_scu_call_rpc(struct imx_sc_ipc *sc_ipc, void *msg, bool have_resp) 157 + { 158 + struct imx_sc_rpc_msg *hdr; 159 + int ret; 160 + 161 + if (WARN_ON(!sc_ipc || !msg)) 162 + return -EINVAL; 163 + 164 + mutex_lock(&sc_ipc->lock); 165 + reinit_completion(&sc_ipc->done); 166 + 167 + sc_ipc->msg = msg; 168 + sc_ipc->count = 0; 169 + ret = imx_scu_ipc_write(sc_ipc, msg); 170 + if (ret < 0) { 171 + dev_err(sc_ipc->dev, "RPC send msg failed: %d\n", ret); 172 + goto out; 173 + } 174 + 175 + if (have_resp) { 176 + if (!wait_for_completion_timeout(&sc_ipc->done, 177 + MAX_RX_TIMEOUT)) { 178 + dev_err(sc_ipc->dev, "RPC send msg timeout\n"); 179 + mutex_unlock(&sc_ipc->lock); 180 + return -ETIMEDOUT; 181 + } 182 + 183 + /* response status is stored in hdr->func field */ 184 + hdr = msg; 185 + ret = hdr->func; 186 + } 187 + 188 + out: 189 + mutex_unlock(&sc_ipc->lock); 190 + 191 + dev_dbg(sc_ipc->dev, "RPC SVC done\n"); 192 + 193 + return imx_sc_to_linux_errno(ret); 194 + } 195 + EXPORT_SYMBOL(imx_scu_call_rpc); 196 + 197 + static int imx_scu_probe(struct platform_device *pdev) 198 + { 199 + struct device *dev = &pdev->dev; 200 + struct imx_sc_ipc *sc_ipc; 201 + struct imx_sc_chan *sc_chan; 202 + struct mbox_client *cl; 203 + char *chan_name; 204 + int ret; 205 + int i; 206 + 207 + sc_ipc = devm_kzalloc(dev, sizeof(*sc_ipc), GFP_KERNEL); 208 + if (!sc_ipc) 209 + return -ENOMEM; 210 + 211 + for (i = 0; i < SCU_MU_CHAN_NUM; i++) { 212 + if (i < 4) 213 + chan_name = kasprintf(GFP_KERNEL, "tx%d", i); 214 + else 215 + chan_name = kasprintf(GFP_KERNEL, "rx%d", i - 4); 216 + 217 + if (!chan_name) 218 + return -ENOMEM; 219 + 220 + sc_chan = &sc_ipc->chans[i]; 221 + cl = &sc_chan->cl; 222 + cl->dev = dev; 223 + cl->tx_block = false; 224 + cl->knows_txdone = true; 225 + cl->rx_callback = imx_scu_rx_callback; 226 + 227 + sc_chan->sc_ipc = sc_ipc; 228 + sc_chan->idx = i % 4; 229 + sc_chan->ch = mbox_request_channel_byname(cl, chan_name); 230 + if (IS_ERR(sc_chan->ch)) { 231 + ret = PTR_ERR(sc_chan->ch); 232 + if (ret != -EPROBE_DEFER) 233 + dev_err(dev, "Failed to request mbox chan %s ret %d\n", 234 + chan_name, ret); 235 + return ret; 236 + } 237 + 238 + dev_dbg(dev, "request mbox chan %s\n", chan_name); 239 + /* chan_name is not used anymore by framework */ 240 + kfree(chan_name); 241 + } 242 + 243 + sc_ipc->dev = dev; 244 + mutex_init(&sc_ipc->lock); 245 + init_completion(&sc_ipc->done); 246 + 247 + imx_sc_ipc_handle = sc_ipc; 248 + 249 + dev_info(dev, "NXP i.MX SCU Initialized\n"); 250 + 251 + return devm_of_platform_populate(dev); 252 + } 253 + 254 + static const struct of_device_id imx_scu_match[] = { 255 + { .compatible = "fsl,imx-scu", }, 256 + { /* Sentinel */ } 257 + }; 258 + 259 + static struct platform_driver imx_scu_driver = { 260 + .driver = { 261 + .name = "imx-scu", 262 + .of_match_table = imx_scu_match, 263 + }, 264 + .probe = imx_scu_probe, 265 + }; 266 + builtin_platform_driver(imx_scu_driver); 267 + 268 + MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>"); 269 + MODULE_DESCRIPTION("IMX SCU firmware protocol driver"); 270 + MODULE_LICENSE("GPL v2");
+99
drivers/firmware/imx/misc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (C) 2016 Freescale Semiconductor, Inc. 4 + * Copyright 2017~2018 NXP 5 + * Author: Dong Aisheng <aisheng.dong@nxp.com> 6 + * 7 + * File containing client-side RPC functions for the MISC service. These 8 + * function are ported to clients that communicate to the SC. 9 + * 10 + */ 11 + 12 + #include <linux/firmware/imx/svc/misc.h> 13 + 14 + struct imx_sc_msg_req_misc_set_ctrl { 15 + struct imx_sc_rpc_msg hdr; 16 + u32 ctrl; 17 + u32 val; 18 + u16 resource; 19 + } __packed; 20 + 21 + struct imx_sc_msg_req_misc_get_ctrl { 22 + struct imx_sc_rpc_msg hdr; 23 + u32 ctrl; 24 + u16 resource; 25 + } __packed; 26 + 27 + struct imx_sc_msg_resp_misc_get_ctrl { 28 + struct imx_sc_rpc_msg hdr; 29 + u32 val; 30 + } __packed; 31 + 32 + /* 33 + * This function sets a miscellaneous control value. 34 + * 35 + * @param[in] ipc IPC handle 36 + * @param[in] resource resource the control is associated with 37 + * @param[in] ctrl control to change 38 + * @param[in] val value to apply to the control 39 + * 40 + * @return Returns 0 for success and < 0 for errors. 41 + */ 42 + 43 + int imx_sc_misc_set_control(struct imx_sc_ipc *ipc, u32 resource, 44 + u8 ctrl, u32 val) 45 + { 46 + struct imx_sc_msg_req_misc_set_ctrl msg; 47 + struct imx_sc_rpc_msg *hdr = &msg.hdr; 48 + 49 + hdr->ver = IMX_SC_RPC_VERSION; 50 + hdr->svc = (uint8_t)IMX_SC_RPC_SVC_MISC; 51 + hdr->func = (uint8_t)IMX_SC_MISC_FUNC_SET_CONTROL; 52 + hdr->size = 4; 53 + 54 + msg.ctrl = ctrl; 55 + msg.val = val; 56 + msg.resource = resource; 57 + 58 + return imx_scu_call_rpc(ipc, &msg, true); 59 + } 60 + EXPORT_SYMBOL(imx_sc_misc_set_control); 61 + 62 + /* 63 + * This function gets a miscellaneous control value. 64 + * 65 + * @param[in] ipc IPC handle 66 + * @param[in] resource resource the control is associated with 67 + * @param[in] ctrl control to get 68 + * @param[out] val pointer to return the control value 69 + * 70 + * @return Returns 0 for success and < 0 for errors. 71 + */ 72 + 73 + int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource, 74 + u8 ctrl, u32 *val) 75 + { 76 + struct imx_sc_msg_req_misc_get_ctrl msg; 77 + struct imx_sc_msg_resp_misc_get_ctrl *resp; 78 + struct imx_sc_rpc_msg *hdr = &msg.hdr; 79 + int ret; 80 + 81 + hdr->ver = IMX_SC_RPC_VERSION; 82 + hdr->svc = (uint8_t)IMX_SC_RPC_SVC_MISC; 83 + hdr->func = (uint8_t)IMX_SC_MISC_FUNC_GET_CONTROL; 84 + hdr->size = 3; 85 + 86 + msg.ctrl = ctrl; 87 + msg.resource = resource; 88 + 89 + ret = imx_scu_call_rpc(ipc, &msg, true); 90 + if (ret) 91 + return ret; 92 + 93 + resp = (struct imx_sc_msg_resp_misc_get_ctrl *)&msg; 94 + if (val != NULL) 95 + *val = resp->val; 96 + 97 + return 0; 98 + } 99 + EXPORT_SYMBOL(imx_sc_misc_get_control);
+56
drivers/firmware/meson/meson_sm.c
··· 24 24 #include <linux/printk.h> 25 25 #include <linux/types.h> 26 26 #include <linux/sizes.h> 27 + #include <linux/slab.h> 27 28 28 29 #include <linux/firmware/meson/meson_sm.h> 29 30 ··· 49 48 CMD(SM_EFUSE_READ, 0x82000030), 50 49 CMD(SM_EFUSE_WRITE, 0x82000031), 51 50 CMD(SM_EFUSE_USER_MAX, 0x82000033), 51 + CMD(SM_GET_CHIP_ID, 0x82000044), 52 52 { /* sentinel */ }, 53 53 }, 54 54 }; ··· 216 214 } 217 215 EXPORT_SYMBOL(meson_sm_call_write); 218 216 217 + #define SM_CHIP_ID_LENGTH 119 218 + #define SM_CHIP_ID_OFFSET 4 219 + #define SM_CHIP_ID_SIZE 12 220 + 221 + static ssize_t serial_show(struct device *dev, struct device_attribute *attr, 222 + char *buf) 223 + { 224 + uint8_t *id_buf; 225 + int ret; 226 + 227 + id_buf = kmalloc(SM_CHIP_ID_LENGTH, GFP_KERNEL); 228 + if (!id_buf) 229 + return -ENOMEM; 230 + 231 + ret = meson_sm_call_read(id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID, 232 + 0, 0, 0, 0, 0); 233 + if (ret < 0) { 234 + kfree(id_buf); 235 + return ret; 236 + } 237 + 238 + ret = sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", 239 + id_buf[SM_CHIP_ID_OFFSET + 0], 240 + id_buf[SM_CHIP_ID_OFFSET + 1], 241 + id_buf[SM_CHIP_ID_OFFSET + 2], 242 + id_buf[SM_CHIP_ID_OFFSET + 3], 243 + id_buf[SM_CHIP_ID_OFFSET + 4], 244 + id_buf[SM_CHIP_ID_OFFSET + 5], 245 + id_buf[SM_CHIP_ID_OFFSET + 6], 246 + id_buf[SM_CHIP_ID_OFFSET + 7], 247 + id_buf[SM_CHIP_ID_OFFSET + 8], 248 + id_buf[SM_CHIP_ID_OFFSET + 9], 249 + id_buf[SM_CHIP_ID_OFFSET + 10], 250 + id_buf[SM_CHIP_ID_OFFSET + 11]); 251 + 252 + kfree(id_buf); 253 + 254 + return ret; 255 + } 256 + 257 + static DEVICE_ATTR_RO(serial); 258 + 259 + static struct attribute *meson_sm_sysfs_attributes[] = { 260 + &dev_attr_serial.attr, 261 + NULL, 262 + }; 263 + 264 + static const struct attribute_group meson_sm_sysfs_attr_group = { 265 + .attrs = meson_sm_sysfs_attributes, 266 + }; 267 + 219 268 static const struct of_device_id meson_sm_ids[] = { 220 269 { .compatible = "amlogic,meson-gxbb-sm", .data = &gxbb_chip }, 221 270 { /* sentinel */ }, ··· 294 241 295 242 fw.chip = chip; 296 243 pr_info("secure-monitor enabled\n"); 244 + 245 + if (sysfs_create_group(&pdev->dev.kobj, &meson_sm_sysfs_attr_group)) 246 + goto out_in_base; 297 247 298 248 return 0; 299 249
+42 -32
drivers/firmware/qcom_scm.c
··· 525 525 return ret; 526 526 527 527 clks = (unsigned long)of_device_get_match_data(&pdev->dev); 528 - if (clks & SCM_HAS_CORE_CLK) { 529 - scm->core_clk = devm_clk_get(&pdev->dev, "core"); 530 - if (IS_ERR(scm->core_clk)) { 531 - if (PTR_ERR(scm->core_clk) != -EPROBE_DEFER) 532 - dev_err(&pdev->dev, 533 - "failed to acquire core clk\n"); 528 + 529 + scm->core_clk = devm_clk_get(&pdev->dev, "core"); 530 + if (IS_ERR(scm->core_clk)) { 531 + if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER) 532 + return PTR_ERR(scm->core_clk); 533 + 534 + if (clks & SCM_HAS_CORE_CLK) { 535 + dev_err(&pdev->dev, "failed to acquire core clk\n"); 534 536 return PTR_ERR(scm->core_clk); 535 537 } 538 + 539 + scm->core_clk = NULL; 536 540 } 537 541 538 - if (clks & SCM_HAS_IFACE_CLK) { 539 - scm->iface_clk = devm_clk_get(&pdev->dev, "iface"); 540 - if (IS_ERR(scm->iface_clk)) { 541 - if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER) 542 - dev_err(&pdev->dev, 543 - "failed to acquire iface clk\n"); 542 + scm->iface_clk = devm_clk_get(&pdev->dev, "iface"); 543 + if (IS_ERR(scm->iface_clk)) { 544 + if (PTR_ERR(scm->iface_clk) == -EPROBE_DEFER) 545 + return PTR_ERR(scm->iface_clk); 546 + 547 + if (clks & SCM_HAS_IFACE_CLK) { 548 + dev_err(&pdev->dev, "failed to acquire iface clk\n"); 544 549 return PTR_ERR(scm->iface_clk); 545 550 } 551 + 552 + scm->iface_clk = NULL; 546 553 } 547 554 548 - if (clks & SCM_HAS_BUS_CLK) { 549 - scm->bus_clk = devm_clk_get(&pdev->dev, "bus"); 550 - if (IS_ERR(scm->bus_clk)) { 551 - if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER) 552 - dev_err(&pdev->dev, 553 - "failed to acquire bus clk\n"); 555 + scm->bus_clk = devm_clk_get(&pdev->dev, "bus"); 556 + if (IS_ERR(scm->bus_clk)) { 557 + if (PTR_ERR(scm->bus_clk) == -EPROBE_DEFER) 558 + return PTR_ERR(scm->bus_clk); 559 + 560 + if (clks & SCM_HAS_BUS_CLK) { 561 + dev_err(&pdev->dev, "failed to acquire bus clk\n"); 554 562 return PTR_ERR(scm->bus_clk); 555 563 } 564 + 565 + scm->bus_clk = NULL; 556 566 } 557 567 558 568 scm->reset.ops = &qcom_scm_pas_reset_ops; ··· 604 594 { .compatible = "qcom,scm-apq8064", 605 595 /* FIXME: This should have .data = (void *) SCM_HAS_CORE_CLK */ 606 596 }, 607 - { .compatible = "qcom,scm-msm8660", 608 - .data = (void *) SCM_HAS_CORE_CLK, 597 + { .compatible = "qcom,scm-apq8084", .data = (void *)(SCM_HAS_CORE_CLK | 598 + SCM_HAS_IFACE_CLK | 599 + SCM_HAS_BUS_CLK) 609 600 }, 610 - { .compatible = "qcom,scm-msm8960", 611 - .data = (void *) SCM_HAS_CORE_CLK, 601 + { .compatible = "qcom,scm-ipq4019" }, 602 + { .compatible = "qcom,scm-msm8660", .data = (void *) SCM_HAS_CORE_CLK }, 603 + { .compatible = "qcom,scm-msm8960", .data = (void *) SCM_HAS_CORE_CLK }, 604 + { .compatible = "qcom,scm-msm8916", .data = (void *)(SCM_HAS_CORE_CLK | 605 + SCM_HAS_IFACE_CLK | 606 + SCM_HAS_BUS_CLK) 612 607 }, 613 - { .compatible = "qcom,scm-msm8996", 614 - .data = NULL, /* no clocks */ 608 + { .compatible = "qcom,scm-msm8974", .data = (void *)(SCM_HAS_CORE_CLK | 609 + SCM_HAS_IFACE_CLK | 610 + SCM_HAS_BUS_CLK) 615 611 }, 616 - { .compatible = "qcom,scm-ipq4019", 617 - .data = NULL, /* no clocks */ 618 - }, 619 - { .compatible = "qcom,scm", 620 - .data = (void *)(SCM_HAS_CORE_CLK 621 - | SCM_HAS_IFACE_CLK 622 - | SCM_HAS_BUS_CLK), 623 - }, 612 + { .compatible = "qcom,scm-msm8996" }, 613 + { .compatible = "qcom,scm" }, 624 614 {} 625 615 }; 626 616
+19
drivers/firmware/tegra/bpmp.c
··· 18 18 #include <linux/of_address.h> 19 19 #include <linux/of_device.h> 20 20 #include <linux/platform_device.h> 21 + #include <linux/pm.h> 21 22 #include <linux/semaphore.h> 22 23 #include <linux/sched/clock.h> 23 24 ··· 844 843 return err; 845 844 } 846 845 846 + static int __maybe_unused tegra_bpmp_resume(struct device *dev) 847 + { 848 + struct tegra_bpmp *bpmp = dev_get_drvdata(dev); 849 + unsigned int i; 850 + 851 + /* reset message channels */ 852 + tegra_bpmp_channel_reset(bpmp->tx_channel); 853 + tegra_bpmp_channel_reset(bpmp->rx_channel); 854 + 855 + for (i = 0; i < bpmp->threaded.count; i++) 856 + tegra_bpmp_channel_reset(&bpmp->threaded_channels[i]); 857 + 858 + return 0; 859 + } 860 + 861 + static SIMPLE_DEV_PM_OPS(tegra_bpmp_pm_ops, NULL, tegra_bpmp_resume); 862 + 847 863 static const struct tegra_bpmp_soc tegra186_soc = { 848 864 .channels = { 849 865 .cpu_tx = { ··· 889 871 .driver = { 890 872 .name = "tegra-bpmp", 891 873 .of_match_table = tegra_bpmp_match, 874 + .pm = &tegra_bpmp_pm_ops, 892 875 }, 893 876 .probe = tegra_bpmp_probe, 894 877 };
+20 -4
drivers/firmware/ti_sci.c
··· 66 66 67 67 /** 68 68 * struct ti_sci_desc - Description of SoC integration 69 - * @host_id: Host identifier representing the compute entity 69 + * @default_host_id: Host identifier representing the compute entity 70 70 * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds) 71 71 * @max_msgs: Maximum number of messages that can be pending 72 72 * simultaneously in the system 73 73 * @max_msg_size: Maximum size of data per message that can be handled. 74 74 */ 75 75 struct ti_sci_desc { 76 - u8 host_id; 76 + u8 default_host_id; 77 77 int max_rx_timeout_ms; 78 78 int max_msgs; 79 79 int max_msg_size; ··· 94 94 * @chan_rx: Receive mailbox channel 95 95 * @minfo: Message info 96 96 * @node: list head 97 + * @host_id: Host ID 97 98 * @users: Number of users of this instance 98 99 */ 99 100 struct ti_sci_info { ··· 111 110 struct mbox_chan *chan_rx; 112 111 struct ti_sci_xfers_info minfo; 113 112 struct list_head node; 113 + u8 host_id; 114 114 /* protected by ti_sci_list_mutex */ 115 115 int users; 116 116 ··· 372 370 373 371 hdr->seq = xfer_id; 374 372 hdr->type = msg_type; 375 - hdr->host = info->desc->host_id; 373 + hdr->host = info->host_id; 376 374 hdr->flags = msg_flags; 377 375 378 376 return xfer; ··· 1795 1793 1796 1794 /* Description for K2G */ 1797 1795 static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = { 1798 - .host_id = 2, 1796 + .default_host_id = 2, 1799 1797 /* Conservative duration */ 1800 1798 .max_rx_timeout_ms = 1000, 1801 1799 /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */ ··· 1821 1819 int ret = -EINVAL; 1822 1820 int i; 1823 1821 int reboot = 0; 1822 + u32 h_id; 1824 1823 1825 1824 of_id = of_match_device(ti_sci_of_match, dev); 1826 1825 if (!of_id) { ··· 1836 1833 1837 1834 info->dev = dev; 1838 1835 info->desc = desc; 1836 + ret = of_property_read_u32(dev->of_node, "ti,host-id", &h_id); 1837 + /* if the property is not present in DT, use a default from desc */ 1838 + if (ret < 0) { 1839 + info->host_id = info->desc->default_host_id; 1840 + } else { 1841 + if (!h_id) { 1842 + dev_warn(dev, "Host ID 0 is reserved for firmware\n"); 1843 + info->host_id = info->desc->default_host_id; 1844 + } else { 1845 + info->host_id = h_id; 1846 + } 1847 + } 1848 + 1839 1849 reboot = of_property_read_bool(dev->of_node, 1840 1850 "ti,system-reboot-controller"); 1841 1851 INIT_LIST_HEAD(&info->node);
+23
drivers/firmware/xilinx/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Kconfig for Xilinx firmwares 3 + 4 + menu "Zynq MPSoC Firmware Drivers" 5 + depends on ARCH_ZYNQMP 6 + 7 + config ZYNQMP_FIRMWARE 8 + bool "Enable Xilinx Zynq MPSoC firmware interface" 9 + help 10 + Firmware interface driver is used by different 11 + drivers to communicate with the firmware for 12 + various platform management services. 13 + Say yes to enable ZynqMP firmware interface driver. 14 + If in doubt, say N. 15 + 16 + config ZYNQMP_FIRMWARE_DEBUG 17 + bool "Enable Xilinx Zynq MPSoC firmware debug APIs" 18 + depends on ZYNQMP_FIRMWARE && DEBUG_FS 19 + help 20 + Say yes to enable ZynqMP firmware interface debug APIs. 21 + If in doubt, say N. 22 + 23 + endmenu
+5
drivers/firmware/xilinx/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Makefile for Xilinx firmwares 3 + 4 + obj-$(CONFIG_ZYNQMP_FIRMWARE) += zynqmp.o 5 + obj-$(CONFIG_ZYNQMP_FIRMWARE_DEBUG) += zynqmp-debug.o
+250
drivers/firmware/xilinx/zynqmp-debug.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Xilinx Zynq MPSoC Firmware layer for debugfs APIs 4 + * 5 + * Copyright (C) 2014-2018 Xilinx, Inc. 6 + * 7 + * Michal Simek <michal.simek@xilinx.com> 8 + * Davorin Mista <davorin.mista@aggios.com> 9 + * Jolly Shah <jollys@xilinx.com> 10 + * Rajan Vaja <rajanv@xilinx.com> 11 + */ 12 + 13 + #include <linux/compiler.h> 14 + #include <linux/module.h> 15 + #include <linux/slab.h> 16 + #include <linux/debugfs.h> 17 + #include <linux/uaccess.h> 18 + 19 + #include <linux/firmware/xlnx-zynqmp.h> 20 + #include "zynqmp-debug.h" 21 + 22 + #define PM_API_NAME_LEN 50 23 + 24 + struct pm_api_info { 25 + u32 api_id; 26 + char api_name[PM_API_NAME_LEN]; 27 + char api_name_len; 28 + }; 29 + 30 + static char debugfs_buf[PAGE_SIZE]; 31 + 32 + #define PM_API(id) {id, #id, strlen(#id)} 33 + static struct pm_api_info pm_api_list[] = { 34 + PM_API(PM_GET_API_VERSION), 35 + PM_API(PM_QUERY_DATA), 36 + }; 37 + 38 + struct dentry *firmware_debugfs_root; 39 + 40 + /** 41 + * zynqmp_pm_argument_value() - Extract argument value from a PM-API request 42 + * @arg: Entered PM-API argument in string format 43 + * 44 + * Return: Argument value in unsigned integer format on success 45 + * 0 otherwise 46 + */ 47 + static u64 zynqmp_pm_argument_value(char *arg) 48 + { 49 + u64 value; 50 + 51 + if (!arg) 52 + return 0; 53 + 54 + if (!kstrtou64(arg, 0, &value)) 55 + return value; 56 + 57 + return 0; 58 + } 59 + 60 + /** 61 + * get_pm_api_id() - Extract API-ID from a PM-API request 62 + * @pm_api_req: Entered PM-API argument in string format 63 + * @pm_id: API-ID 64 + * 65 + * Return: 0 on success else error code 66 + */ 67 + static int get_pm_api_id(char *pm_api_req, u32 *pm_id) 68 + { 69 + int i; 70 + 71 + for (i = 0; i < ARRAY_SIZE(pm_api_list) ; i++) { 72 + if (!strncasecmp(pm_api_req, pm_api_list[i].api_name, 73 + pm_api_list[i].api_name_len)) { 74 + *pm_id = pm_api_list[i].api_id; 75 + break; 76 + } 77 + } 78 + 79 + /* If no name was entered look for PM-API ID instead */ 80 + if (i == ARRAY_SIZE(pm_api_list) && kstrtouint(pm_api_req, 10, pm_id)) 81 + return -EINVAL; 82 + 83 + return 0; 84 + } 85 + 86 + static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret) 87 + { 88 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 89 + u32 pm_api_version; 90 + int ret; 91 + struct zynqmp_pm_query_data qdata = {0}; 92 + 93 + if (!eemi_ops) 94 + return -ENXIO; 95 + 96 + switch (pm_id) { 97 + case PM_GET_API_VERSION: 98 + ret = eemi_ops->get_api_version(&pm_api_version); 99 + sprintf(debugfs_buf, "PM-API Version = %d.%d\n", 100 + pm_api_version >> 16, pm_api_version & 0xffff); 101 + break; 102 + case PM_QUERY_DATA: 103 + qdata.qid = pm_api_arg[0]; 104 + qdata.arg1 = pm_api_arg[1]; 105 + qdata.arg2 = pm_api_arg[2]; 106 + qdata.arg3 = pm_api_arg[3]; 107 + 108 + ret = eemi_ops->query_data(qdata, pm_api_ret); 109 + if (ret) 110 + break; 111 + 112 + switch (qdata.qid) { 113 + case PM_QID_CLOCK_GET_NAME: 114 + sprintf(debugfs_buf, "Clock name = %s\n", 115 + (char *)pm_api_ret); 116 + break; 117 + case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS: 118 + sprintf(debugfs_buf, "Multiplier = %d, Divider = %d\n", 119 + pm_api_ret[1], pm_api_ret[2]); 120 + break; 121 + default: 122 + sprintf(debugfs_buf, 123 + "data[0] = 0x%08x\ndata[1] = 0x%08x\n data[2] = 0x%08x\ndata[3] = 0x%08x\n", 124 + pm_api_ret[0], pm_api_ret[1], 125 + pm_api_ret[2], pm_api_ret[3]); 126 + } 127 + break; 128 + default: 129 + sprintf(debugfs_buf, "Unsupported PM-API request\n"); 130 + ret = -EINVAL; 131 + } 132 + 133 + return ret; 134 + } 135 + 136 + /** 137 + * zynqmp_pm_debugfs_api_write() - debugfs write function 138 + * @file: User file 139 + * @ptr: User entered PM-API string 140 + * @len: Length of the userspace buffer 141 + * @off: Offset within the file 142 + * 143 + * Used for triggering pm api functions by writing 144 + * echo <pm_api_id> > /sys/kernel/debug/zynqmp_pm/power or 145 + * echo <pm_api_name> > /sys/kernel/debug/zynqmp_pm/power 146 + * 147 + * Return: Number of bytes copied if PM-API request succeeds, 148 + * the corresponding error code otherwise 149 + */ 150 + static ssize_t zynqmp_pm_debugfs_api_write(struct file *file, 151 + const char __user *ptr, size_t len, 152 + loff_t *off) 153 + { 154 + char *kern_buff, *tmp_buff; 155 + char *pm_api_req; 156 + u32 pm_id = 0; 157 + u64 pm_api_arg[4] = {0, 0, 0, 0}; 158 + /* Return values from PM APIs calls */ 159 + u32 pm_api_ret[4] = {0, 0, 0, 0}; 160 + 161 + int ret; 162 + int i = 0; 163 + 164 + strcpy(debugfs_buf, ""); 165 + 166 + if (*off != 0 || len == 0) 167 + return -EINVAL; 168 + 169 + kern_buff = kzalloc(len, GFP_KERNEL); 170 + if (!kern_buff) 171 + return -ENOMEM; 172 + 173 + tmp_buff = kern_buff; 174 + 175 + ret = strncpy_from_user(kern_buff, ptr, len); 176 + if (ret < 0) { 177 + ret = -EFAULT; 178 + goto err; 179 + } 180 + 181 + /* Read the API name from a user request */ 182 + pm_api_req = strsep(&kern_buff, " "); 183 + 184 + ret = get_pm_api_id(pm_api_req, &pm_id); 185 + if (ret < 0) 186 + goto err; 187 + 188 + /* Read node_id and arguments from the PM-API request */ 189 + pm_api_req = strsep(&kern_buff, " "); 190 + while ((i < ARRAY_SIZE(pm_api_arg)) && pm_api_req) { 191 + pm_api_arg[i++] = zynqmp_pm_argument_value(pm_api_req); 192 + pm_api_req = strsep(&kern_buff, " "); 193 + } 194 + 195 + ret = process_api_request(pm_id, pm_api_arg, pm_api_ret); 196 + 197 + err: 198 + kfree(tmp_buff); 199 + if (ret) 200 + return ret; 201 + 202 + return len; 203 + } 204 + 205 + /** 206 + * zynqmp_pm_debugfs_api_read() - debugfs read function 207 + * @file: User file 208 + * @ptr: Requested pm_api_version string 209 + * @len: Length of the userspace buffer 210 + * @off: Offset within the file 211 + * 212 + * Return: Length of the version string on success 213 + * else error code 214 + */ 215 + static ssize_t zynqmp_pm_debugfs_api_read(struct file *file, char __user *ptr, 216 + size_t len, loff_t *off) 217 + { 218 + return simple_read_from_buffer(ptr, len, off, debugfs_buf, 219 + strlen(debugfs_buf)); 220 + } 221 + 222 + /* Setup debugfs fops */ 223 + static const struct file_operations fops_zynqmp_pm_dbgfs = { 224 + .owner = THIS_MODULE, 225 + .write = zynqmp_pm_debugfs_api_write, 226 + .read = zynqmp_pm_debugfs_api_read, 227 + }; 228 + 229 + /** 230 + * zynqmp_pm_api_debugfs_init - Initialize debugfs interface 231 + * 232 + * Return: None 233 + */ 234 + void zynqmp_pm_api_debugfs_init(void) 235 + { 236 + /* Initialize debugfs interface */ 237 + firmware_debugfs_root = debugfs_create_dir("zynqmp-firmware", NULL); 238 + debugfs_create_file("pm", 0660, firmware_debugfs_root, NULL, 239 + &fops_zynqmp_pm_dbgfs); 240 + } 241 + 242 + /** 243 + * zynqmp_pm_api_debugfs_exit - Remove debugfs interface 244 + * 245 + * Return: None 246 + */ 247 + void zynqmp_pm_api_debugfs_exit(void) 248 + { 249 + debugfs_remove_recursive(firmware_debugfs_root); 250 + }
+24
drivers/firmware/xilinx/zynqmp-debug.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Xilinx Zynq MPSoC Firmware layer 4 + * 5 + * Copyright (C) 2014-2018 Xilinx 6 + * 7 + * Michal Simek <michal.simek@xilinx.com> 8 + * Davorin Mista <davorin.mista@aggios.com> 9 + * Jolly Shah <jollys@xilinx.com> 10 + * Rajan Vaja <rajanv@xilinx.com> 11 + */ 12 + 13 + #ifndef __FIRMWARE_ZYNQMP_DEBUG_H__ 14 + #define __FIRMWARE_ZYNQMP_DEBUG_H__ 15 + 16 + #if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE_DEBUG) 17 + void zynqmp_pm_api_debugfs_init(void); 18 + void zynqmp_pm_api_debugfs_exit(void); 19 + #else 20 + static inline void zynqmp_pm_api_debugfs_init(void) { } 21 + static inline void zynqmp_pm_api_debugfs_exit(void) { } 22 + #endif 23 + 24 + #endif /* __FIRMWARE_ZYNQMP_DEBUG_H__ */
+565
drivers/firmware/xilinx/zynqmp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Xilinx Zynq MPSoC Firmware layer 4 + * 5 + * Copyright (C) 2014-2018 Xilinx, Inc. 6 + * 7 + * Michal Simek <michal.simek@xilinx.com> 8 + * Davorin Mista <davorin.mista@aggios.com> 9 + * Jolly Shah <jollys@xilinx.com> 10 + * Rajan Vaja <rajanv@xilinx.com> 11 + */ 12 + 13 + #include <linux/arm-smccc.h> 14 + #include <linux/compiler.h> 15 + #include <linux/device.h> 16 + #include <linux/init.h> 17 + #include <linux/module.h> 18 + #include <linux/of.h> 19 + #include <linux/of_platform.h> 20 + #include <linux/slab.h> 21 + #include <linux/uaccess.h> 22 + 23 + #include <linux/firmware/xlnx-zynqmp.h> 24 + #include "zynqmp-debug.h" 25 + 26 + /** 27 + * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes 28 + * @ret_status: PMUFW return code 29 + * 30 + * Return: corresponding Linux error code 31 + */ 32 + static int zynqmp_pm_ret_code(u32 ret_status) 33 + { 34 + switch (ret_status) { 35 + case XST_PM_SUCCESS: 36 + case XST_PM_DOUBLE_REQ: 37 + return 0; 38 + case XST_PM_NO_ACCESS: 39 + return -EACCES; 40 + case XST_PM_ABORT_SUSPEND: 41 + return -ECANCELED; 42 + case XST_PM_INTERNAL: 43 + case XST_PM_CONFLICT: 44 + case XST_PM_INVALID_NODE: 45 + default: 46 + return -EINVAL; 47 + } 48 + } 49 + 50 + static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2, 51 + u32 *ret_payload) 52 + { 53 + return -ENODEV; 54 + } 55 + 56 + /* 57 + * PM function call wrapper 58 + * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration 59 + */ 60 + static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail; 61 + 62 + /** 63 + * do_fw_call_smc() - Call system-level platform management layer (SMC) 64 + * @arg0: Argument 0 to SMC call 65 + * @arg1: Argument 1 to SMC call 66 + * @arg2: Argument 2 to SMC call 67 + * @ret_payload: Returned value array 68 + * 69 + * Invoke platform management function via SMC call (no hypervisor present). 70 + * 71 + * Return: Returns status, either success or error+reason 72 + */ 73 + static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2, 74 + u32 *ret_payload) 75 + { 76 + struct arm_smccc_res res; 77 + 78 + arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res); 79 + 80 + if (ret_payload) { 81 + ret_payload[0] = lower_32_bits(res.a0); 82 + ret_payload[1] = upper_32_bits(res.a0); 83 + ret_payload[2] = lower_32_bits(res.a1); 84 + ret_payload[3] = upper_32_bits(res.a1); 85 + } 86 + 87 + return zynqmp_pm_ret_code((enum pm_ret_status)res.a0); 88 + } 89 + 90 + /** 91 + * do_fw_call_hvc() - Call system-level platform management layer (HVC) 92 + * @arg0: Argument 0 to HVC call 93 + * @arg1: Argument 1 to HVC call 94 + * @arg2: Argument 2 to HVC call 95 + * @ret_payload: Returned value array 96 + * 97 + * Invoke platform management function via HVC 98 + * HVC-based for communication through hypervisor 99 + * (no direct communication with ATF). 100 + * 101 + * Return: Returns status, either success or error+reason 102 + */ 103 + static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2, 104 + u32 *ret_payload) 105 + { 106 + struct arm_smccc_res res; 107 + 108 + arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res); 109 + 110 + if (ret_payload) { 111 + ret_payload[0] = lower_32_bits(res.a0); 112 + ret_payload[1] = upper_32_bits(res.a0); 113 + ret_payload[2] = lower_32_bits(res.a1); 114 + ret_payload[3] = upper_32_bits(res.a1); 115 + } 116 + 117 + return zynqmp_pm_ret_code((enum pm_ret_status)res.a0); 118 + } 119 + 120 + /** 121 + * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer 122 + * caller function depending on the configuration 123 + * @pm_api_id: Requested PM-API call 124 + * @arg0: Argument 0 to requested PM-API call 125 + * @arg1: Argument 1 to requested PM-API call 126 + * @arg2: Argument 2 to requested PM-API call 127 + * @arg3: Argument 3 to requested PM-API call 128 + * @ret_payload: Returned value array 129 + * 130 + * Invoke platform management function for SMC or HVC call, depending on 131 + * configuration. 132 + * Following SMC Calling Convention (SMCCC) for SMC64: 133 + * Pm Function Identifier, 134 + * PM_SIP_SVC + PM_API_ID = 135 + * ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) 136 + * ((SMC_64) << FUNCID_CC_SHIFT) 137 + * ((SIP_START) << FUNCID_OEN_SHIFT) 138 + * ((PM_API_ID) & FUNCID_NUM_MASK)) 139 + * 140 + * PM_SIP_SVC - Registered ZynqMP SIP Service Call. 141 + * PM_API_ID - Platform Management API ID. 142 + * 143 + * Return: Returns status, either success or error+reason 144 + */ 145 + int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1, 146 + u32 arg2, u32 arg3, u32 *ret_payload) 147 + { 148 + /* 149 + * Added SIP service call Function Identifier 150 + * Make sure to stay in x0 register 151 + */ 152 + u64 smc_arg[4]; 153 + 154 + smc_arg[0] = PM_SIP_SVC | pm_api_id; 155 + smc_arg[1] = ((u64)arg1 << 32) | arg0; 156 + smc_arg[2] = ((u64)arg3 << 32) | arg2; 157 + 158 + return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload); 159 + } 160 + 161 + static u32 pm_api_version; 162 + static u32 pm_tz_version; 163 + 164 + /** 165 + * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware 166 + * @version: Returned version value 167 + * 168 + * Return: Returns status, either success or error+reason 169 + */ 170 + static int zynqmp_pm_get_api_version(u32 *version) 171 + { 172 + u32 ret_payload[PAYLOAD_ARG_CNT]; 173 + int ret; 174 + 175 + if (!version) 176 + return -EINVAL; 177 + 178 + /* Check is PM API version already verified */ 179 + if (pm_api_version > 0) { 180 + *version = pm_api_version; 181 + return 0; 182 + } 183 + ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload); 184 + *version = ret_payload[1]; 185 + 186 + return ret; 187 + } 188 + 189 + /** 190 + * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version 191 + * @version: Returned version value 192 + * 193 + * Return: Returns status, either success or error+reason 194 + */ 195 + static int zynqmp_pm_get_trustzone_version(u32 *version) 196 + { 197 + u32 ret_payload[PAYLOAD_ARG_CNT]; 198 + int ret; 199 + 200 + if (!version) 201 + return -EINVAL; 202 + 203 + /* Check is PM trustzone version already verified */ 204 + if (pm_tz_version > 0) { 205 + *version = pm_tz_version; 206 + return 0; 207 + } 208 + ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0, 209 + 0, 0, ret_payload); 210 + *version = ret_payload[1]; 211 + 212 + return ret; 213 + } 214 + 215 + /** 216 + * get_set_conduit_method() - Choose SMC or HVC based communication 217 + * @np: Pointer to the device_node structure 218 + * 219 + * Use SMC or HVC-based functions to communicate with EL2/EL3. 220 + * 221 + * Return: Returns 0 on success or error code 222 + */ 223 + static int get_set_conduit_method(struct device_node *np) 224 + { 225 + const char *method; 226 + 227 + if (of_property_read_string(np, "method", &method)) { 228 + pr_warn("%s missing \"method\" property\n", __func__); 229 + return -ENXIO; 230 + } 231 + 232 + if (!strcmp("hvc", method)) { 233 + do_fw_call = do_fw_call_hvc; 234 + } else if (!strcmp("smc", method)) { 235 + do_fw_call = do_fw_call_smc; 236 + } else { 237 + pr_warn("%s Invalid \"method\" property: %s\n", 238 + __func__, method); 239 + return -EINVAL; 240 + } 241 + 242 + return 0; 243 + } 244 + 245 + /** 246 + * zynqmp_pm_query_data() - Get query data from firmware 247 + * @qdata: Variable to the zynqmp_pm_query_data structure 248 + * @out: Returned output value 249 + * 250 + * Return: Returns status, either success or error+reason 251 + */ 252 + static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out) 253 + { 254 + int ret; 255 + 256 + ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1, 257 + qdata.arg2, qdata.arg3, out); 258 + 259 + /* 260 + * For clock name query, all bytes in SMC response are clock name 261 + * characters and return code is always success. For invalid clocks, 262 + * clock name bytes would be zeros. 263 + */ 264 + return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret; 265 + } 266 + 267 + /** 268 + * zynqmp_pm_clock_enable() - Enable the clock for given id 269 + * @clock_id: ID of the clock to be enabled 270 + * 271 + * This function is used by master to enable the clock 272 + * including peripherals and PLL clocks. 273 + * 274 + * Return: Returns status, either success or error+reason 275 + */ 276 + static int zynqmp_pm_clock_enable(u32 clock_id) 277 + { 278 + return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL); 279 + } 280 + 281 + /** 282 + * zynqmp_pm_clock_disable() - Disable the clock for given id 283 + * @clock_id: ID of the clock to be disable 284 + * 285 + * This function is used by master to disable the clock 286 + * including peripherals and PLL clocks. 287 + * 288 + * Return: Returns status, either success or error+reason 289 + */ 290 + static int zynqmp_pm_clock_disable(u32 clock_id) 291 + { 292 + return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL); 293 + } 294 + 295 + /** 296 + * zynqmp_pm_clock_getstate() - Get the clock state for given id 297 + * @clock_id: ID of the clock to be queried 298 + * @state: 1/0 (Enabled/Disabled) 299 + * 300 + * This function is used by master to get the state of clock 301 + * including peripherals and PLL clocks. 302 + * 303 + * Return: Returns status, either success or error+reason 304 + */ 305 + static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state) 306 + { 307 + u32 ret_payload[PAYLOAD_ARG_CNT]; 308 + int ret; 309 + 310 + ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0, 311 + 0, 0, ret_payload); 312 + *state = ret_payload[1]; 313 + 314 + return ret; 315 + } 316 + 317 + /** 318 + * zynqmp_pm_clock_setdivider() - Set the clock divider for given id 319 + * @clock_id: ID of the clock 320 + * @divider: divider value 321 + * 322 + * This function is used by master to set divider for any clock 323 + * to achieve desired rate. 324 + * 325 + * Return: Returns status, either success or error+reason 326 + */ 327 + static int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider) 328 + { 329 + return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider, 330 + 0, 0, NULL); 331 + } 332 + 333 + /** 334 + * zynqmp_pm_clock_getdivider() - Get the clock divider for given id 335 + * @clock_id: ID of the clock 336 + * @divider: divider value 337 + * 338 + * This function is used by master to get divider values 339 + * for any clock. 340 + * 341 + * Return: Returns status, either success or error+reason 342 + */ 343 + static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider) 344 + { 345 + u32 ret_payload[PAYLOAD_ARG_CNT]; 346 + int ret; 347 + 348 + ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0, 349 + 0, 0, ret_payload); 350 + *divider = ret_payload[1]; 351 + 352 + return ret; 353 + } 354 + 355 + /** 356 + * zynqmp_pm_clock_setrate() - Set the clock rate for given id 357 + * @clock_id: ID of the clock 358 + * @rate: rate value in hz 359 + * 360 + * This function is used by master to set rate for any clock. 361 + * 362 + * Return: Returns status, either success or error+reason 363 + */ 364 + static int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate) 365 + { 366 + return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id, 367 + lower_32_bits(rate), 368 + upper_32_bits(rate), 369 + 0, NULL); 370 + } 371 + 372 + /** 373 + * zynqmp_pm_clock_getrate() - Get the clock rate for given id 374 + * @clock_id: ID of the clock 375 + * @rate: rate value in hz 376 + * 377 + * This function is used by master to get rate 378 + * for any clock. 379 + * 380 + * Return: Returns status, either success or error+reason 381 + */ 382 + static int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate) 383 + { 384 + u32 ret_payload[PAYLOAD_ARG_CNT]; 385 + int ret; 386 + 387 + ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0, 388 + 0, 0, ret_payload); 389 + *rate = ((u64)ret_payload[2] << 32) | ret_payload[1]; 390 + 391 + return ret; 392 + } 393 + 394 + /** 395 + * zynqmp_pm_clock_setparent() - Set the clock parent for given id 396 + * @clock_id: ID of the clock 397 + * @parent_id: parent id 398 + * 399 + * This function is used by master to set parent for any clock. 400 + * 401 + * Return: Returns status, either success or error+reason 402 + */ 403 + static int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id) 404 + { 405 + return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id, 406 + parent_id, 0, 0, NULL); 407 + } 408 + 409 + /** 410 + * zynqmp_pm_clock_getparent() - Get the clock parent for given id 411 + * @clock_id: ID of the clock 412 + * @parent_id: parent id 413 + * 414 + * This function is used by master to get parent index 415 + * for any clock. 416 + * 417 + * Return: Returns status, either success or error+reason 418 + */ 419 + static int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id) 420 + { 421 + u32 ret_payload[PAYLOAD_ARG_CNT]; 422 + int ret; 423 + 424 + ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0, 425 + 0, 0, ret_payload); 426 + *parent_id = ret_payload[1]; 427 + 428 + return ret; 429 + } 430 + 431 + /** 432 + * zynqmp_is_valid_ioctl() - Check whether IOCTL ID is valid or not 433 + * @ioctl_id: IOCTL ID 434 + * 435 + * Return: 1 if IOCTL is valid else 0 436 + */ 437 + static inline int zynqmp_is_valid_ioctl(u32 ioctl_id) 438 + { 439 + switch (ioctl_id) { 440 + case IOCTL_SET_PLL_FRAC_MODE: 441 + case IOCTL_GET_PLL_FRAC_MODE: 442 + case IOCTL_SET_PLL_FRAC_DATA: 443 + case IOCTL_GET_PLL_FRAC_DATA: 444 + return 1; 445 + default: 446 + return 0; 447 + } 448 + } 449 + 450 + /** 451 + * zynqmp_pm_ioctl() - PM IOCTL API for device control and configs 452 + * @node_id: Node ID of the device 453 + * @ioctl_id: ID of the requested IOCTL 454 + * @arg1: Argument 1 to requested IOCTL call 455 + * @arg2: Argument 2 to requested IOCTL call 456 + * @out: Returned output value 457 + * 458 + * This function calls IOCTL to firmware for device control and configuration. 459 + * 460 + * Return: Returns status, either success or error+reason 461 + */ 462 + static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, 463 + u32 *out) 464 + { 465 + if (!zynqmp_is_valid_ioctl(ioctl_id)) 466 + return -EINVAL; 467 + 468 + return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, ioctl_id, 469 + arg1, arg2, out); 470 + } 471 + 472 + static const struct zynqmp_eemi_ops eemi_ops = { 473 + .get_api_version = zynqmp_pm_get_api_version, 474 + .query_data = zynqmp_pm_query_data, 475 + .clock_enable = zynqmp_pm_clock_enable, 476 + .clock_disable = zynqmp_pm_clock_disable, 477 + .clock_getstate = zynqmp_pm_clock_getstate, 478 + .clock_setdivider = zynqmp_pm_clock_setdivider, 479 + .clock_getdivider = zynqmp_pm_clock_getdivider, 480 + .clock_setrate = zynqmp_pm_clock_setrate, 481 + .clock_getrate = zynqmp_pm_clock_getrate, 482 + .clock_setparent = zynqmp_pm_clock_setparent, 483 + .clock_getparent = zynqmp_pm_clock_getparent, 484 + .ioctl = zynqmp_pm_ioctl, 485 + }; 486 + 487 + /** 488 + * zynqmp_pm_get_eemi_ops - Get eemi ops functions 489 + * 490 + * Return: Pointer of eemi_ops structure 491 + */ 492 + const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void) 493 + { 494 + return &eemi_ops; 495 + } 496 + EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops); 497 + 498 + static int zynqmp_firmware_probe(struct platform_device *pdev) 499 + { 500 + struct device *dev = &pdev->dev; 501 + struct device_node *np; 502 + int ret; 503 + 504 + np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp"); 505 + if (!np) 506 + return 0; 507 + of_node_put(np); 508 + 509 + ret = get_set_conduit_method(dev->of_node); 510 + if (ret) 511 + return ret; 512 + 513 + /* Check PM API version number */ 514 + zynqmp_pm_get_api_version(&pm_api_version); 515 + if (pm_api_version < ZYNQMP_PM_VERSION) { 516 + panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n", 517 + __func__, 518 + ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR, 519 + pm_api_version >> 16, pm_api_version & 0xFFFF); 520 + } 521 + 522 + pr_info("%s Platform Management API v%d.%d\n", __func__, 523 + pm_api_version >> 16, pm_api_version & 0xFFFF); 524 + 525 + /* Check trustzone version number */ 526 + ret = zynqmp_pm_get_trustzone_version(&pm_tz_version); 527 + if (ret) 528 + panic("Legacy trustzone found without version support\n"); 529 + 530 + if (pm_tz_version < ZYNQMP_TZ_VERSION) 531 + panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n", 532 + __func__, 533 + ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR, 534 + pm_tz_version >> 16, pm_tz_version & 0xFFFF); 535 + 536 + pr_info("%s Trustzone version v%d.%d\n", __func__, 537 + pm_tz_version >> 16, pm_tz_version & 0xFFFF); 538 + 539 + zynqmp_pm_api_debugfs_init(); 540 + 541 + return of_platform_populate(dev->of_node, NULL, NULL, dev); 542 + } 543 + 544 + static int zynqmp_firmware_remove(struct platform_device *pdev) 545 + { 546 + zynqmp_pm_api_debugfs_exit(); 547 + 548 + return 0; 549 + } 550 + 551 + static const struct of_device_id zynqmp_firmware_of_match[] = { 552 + {.compatible = "xlnx,zynqmp-firmware"}, 553 + {}, 554 + }; 555 + MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match); 556 + 557 + static struct platform_driver zynqmp_firmware_driver = { 558 + .driver = { 559 + .name = "zynqmp_firmware", 560 + .of_match_table = zynqmp_firmware_of_match, 561 + }, 562 + .probe = zynqmp_firmware_probe, 563 + .remove = zynqmp_firmware_remove, 564 + }; 565 + module_platform_driver(zynqmp_firmware_driver);
+1 -2
drivers/memory/atmel-ebi.c
··· 327 327 return -EINVAL; 328 328 } 329 329 330 - ebid = devm_kzalloc(ebi->dev, 331 - sizeof(*ebid) + (numcs * sizeof(*ebid->configs)), 330 + ebid = devm_kzalloc(ebi->dev, struct_size(ebid, configs, numcs), 332 331 GFP_KERNEL); 333 332 if (!ebid) 334 333 return -ENOMEM;
+9
drivers/reset/Kconfig
··· 98 98 reset signals provided by AOSS for Modem, Venus, ADSP, 99 99 GPU, Camera, Wireless, Display subsystem. Otherwise, say N. 100 100 101 + config RESET_QCOM_PDC 102 + tristate "Qualcomm PDC Reset Driver" 103 + depends on ARCH_QCOM || COMPILE_TEST 104 + help 105 + This enables the PDC (Power Domain Controller) reset driver 106 + for Qualcomm Technologies Inc SDM845 SoCs. Say Y if you want 107 + to control reset signals provided by PDC for Modem, Compute, 108 + Display, GPU, Debug, AOP, Sensors, Audio, SP and APPS. 109 + 101 110 config RESET_SIMPLE 102 111 bool "Simple Reset Controller Driver" if COMPILE_TEST 103 112 default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
+1
drivers/reset/Makefile
··· 16 16 obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o 17 17 obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o 18 18 obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o 19 + obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o 19 20 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o 20 21 obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o 21 22 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
+8 -7
drivers/reset/core.c
··· 496 496 break; 497 497 } 498 498 } 499 - of_node_put(args.np); 500 499 501 500 if (!rcdev) { 502 - mutex_unlock(&reset_list_mutex); 503 - return ERR_PTR(-EPROBE_DEFER); 501 + rstc = ERR_PTR(-EPROBE_DEFER); 502 + goto out; 504 503 } 505 504 506 505 if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) { 507 - mutex_unlock(&reset_list_mutex); 508 - return ERR_PTR(-EINVAL); 506 + rstc = ERR_PTR(-EINVAL); 507 + goto out; 509 508 } 510 509 511 510 rstc_id = rcdev->of_xlate(rcdev, &args); 512 511 if (rstc_id < 0) { 513 - mutex_unlock(&reset_list_mutex); 514 - return ERR_PTR(rstc_id); 512 + rstc = ERR_PTR(rstc_id); 513 + goto out; 515 514 } 516 515 517 516 /* reset_list_mutex also protects the rcdev's reset_control list */ 518 517 rstc = __reset_control_get_internal(rcdev, rstc_id, shared); 519 518 519 + out: 520 520 mutex_unlock(&reset_list_mutex); 521 + of_node_put(args.np); 521 522 522 523 return rstc; 523 524 }
+124
drivers/reset/reset-qcom-pdc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2018 The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #include <linux/module.h> 7 + #include <linux/of_device.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/regmap.h> 10 + #include <linux/reset-controller.h> 11 + 12 + #include <dt-bindings/reset/qcom,sdm845-pdc.h> 13 + 14 + #define RPMH_PDC_SYNC_RESET 0x100 15 + 16 + struct qcom_pdc_reset_map { 17 + u8 bit; 18 + }; 19 + 20 + struct qcom_pdc_reset_data { 21 + struct reset_controller_dev rcdev; 22 + struct regmap *regmap; 23 + }; 24 + 25 + static const struct regmap_config sdm845_pdc_regmap_config = { 26 + .name = "pdc-reset", 27 + .reg_bits = 32, 28 + .reg_stride = 4, 29 + .val_bits = 32, 30 + .max_register = 0x20000, 31 + .fast_io = true, 32 + }; 33 + 34 + static const struct qcom_pdc_reset_map sdm845_pdc_resets[] = { 35 + [PDC_APPS_SYNC_RESET] = {0}, 36 + [PDC_SP_SYNC_RESET] = {1}, 37 + [PDC_AUDIO_SYNC_RESET] = {2}, 38 + [PDC_SENSORS_SYNC_RESET] = {3}, 39 + [PDC_AOP_SYNC_RESET] = {4}, 40 + [PDC_DEBUG_SYNC_RESET] = {5}, 41 + [PDC_GPU_SYNC_RESET] = {6}, 42 + [PDC_DISPLAY_SYNC_RESET] = {7}, 43 + [PDC_COMPUTE_SYNC_RESET] = {8}, 44 + [PDC_MODEM_SYNC_RESET] = {9}, 45 + }; 46 + 47 + static inline struct qcom_pdc_reset_data *to_qcom_pdc_reset_data( 48 + struct reset_controller_dev *rcdev) 49 + { 50 + return container_of(rcdev, struct qcom_pdc_reset_data, rcdev); 51 + } 52 + 53 + static int qcom_pdc_control_assert(struct reset_controller_dev *rcdev, 54 + unsigned long idx) 55 + { 56 + struct qcom_pdc_reset_data *data = to_qcom_pdc_reset_data(rcdev); 57 + 58 + return regmap_update_bits(data->regmap, RPMH_PDC_SYNC_RESET, 59 + BIT(sdm845_pdc_resets[idx].bit), 60 + BIT(sdm845_pdc_resets[idx].bit)); 61 + } 62 + 63 + static int qcom_pdc_control_deassert(struct reset_controller_dev *rcdev, 64 + unsigned long idx) 65 + { 66 + struct qcom_pdc_reset_data *data = to_qcom_pdc_reset_data(rcdev); 67 + 68 + return regmap_update_bits(data->regmap, RPMH_PDC_SYNC_RESET, 69 + BIT(sdm845_pdc_resets[idx].bit), 0); 70 + } 71 + 72 + static const struct reset_control_ops qcom_pdc_reset_ops = { 73 + .assert = qcom_pdc_control_assert, 74 + .deassert = qcom_pdc_control_deassert, 75 + }; 76 + 77 + static int qcom_pdc_reset_probe(struct platform_device *pdev) 78 + { 79 + struct qcom_pdc_reset_data *data; 80 + struct device *dev = &pdev->dev; 81 + void __iomem *base; 82 + struct resource *res; 83 + 84 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 85 + if (!data) 86 + return -ENOMEM; 87 + 88 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 89 + base = devm_ioremap_resource(dev, res); 90 + if (IS_ERR(base)) 91 + return PTR_ERR(base); 92 + 93 + data->regmap = devm_regmap_init_mmio(dev, base, 94 + &sdm845_pdc_regmap_config); 95 + if (IS_ERR(data->regmap)) { 96 + dev_err(dev, "Unable to initialize regmap\n"); 97 + return PTR_ERR(data->regmap); 98 + } 99 + 100 + data->rcdev.owner = THIS_MODULE; 101 + data->rcdev.ops = &qcom_pdc_reset_ops; 102 + data->rcdev.nr_resets = ARRAY_SIZE(sdm845_pdc_resets); 103 + data->rcdev.of_node = dev->of_node; 104 + 105 + return devm_reset_controller_register(dev, &data->rcdev); 106 + } 107 + 108 + static const struct of_device_id qcom_pdc_reset_of_match[] = { 109 + { .compatible = "qcom,sdm845-pdc-global" }, 110 + {} 111 + }; 112 + MODULE_DEVICE_TABLE(of, qcom_pdc_reset_of_match); 113 + 114 + static struct platform_driver qcom_pdc_reset_driver = { 115 + .probe = qcom_pdc_reset_probe, 116 + .driver = { 117 + .name = "qcom_pdc_reset", 118 + .of_match_table = qcom_pdc_reset_of_match, 119 + }, 120 + }; 121 + module_platform_driver(qcom_pdc_reset_driver); 122 + 123 + MODULE_DESCRIPTION("Qualcomm PDC Reset Driver"); 124 + MODULE_LICENSE("GPL v2");
+1 -1
drivers/soc/Makefile
··· 18 18 obj-y += renesas/ 19 19 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ 20 20 obj-$(CONFIG_SOC_SAMSUNG) += samsung/ 21 - obj-$(CONFIG_ARCH_SUNXI) += sunxi/ 21 + obj-y += sunxi/ 22 22 obj-$(CONFIG_ARCH_TEGRA) += tegra/ 23 23 obj-$(CONFIG_SOC_TI) += ti/ 24 24 obj-$(CONFIG_ARCH_U8500) += ux500/
+1 -1
drivers/soc/actions/Kconfig
··· 10 10 select PM_GENERIC_DOMAINS 11 11 help 12 12 Say 'y' here to enable support for Smart Power System (SPS) 13 - power-gating on Actions Semiconductor S500 SoC. 13 + power-gating on Actions Semiconductor S500, S700 and S900 SoCs. 14 14 If unsure, say 'n'. 15 15 16 16 endif
+2
drivers/soc/actions/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0+ 2 + 1 3 obj-$(CONFIG_OWL_PM_DOMAINS_HELPER) += owl-sps-helper.o 2 4 obj-$(CONFIG_OWL_PM_DOMAINS) += owl-sps.o
+1 -5
drivers/soc/actions/owl-sps-helper.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Actions Semi Owl Smart Power System (SPS) shared helpers 3 4 * ··· 6 5 * Author: Actions Semi, Inc. 7 6 * 8 7 * Copyright (c) 2017 Andreas Färber 9 - * 10 - * This program is free software; you can redistribute it and/or modify it 11 - * under the terms of the GNU General Public License as published by the 12 - * Free Software Foundation; either version 2 of the License, or (at your 13 - * option) any later version. 14 8 */ 15 9 16 10 #include <linux/delay.h>
+59 -5
drivers/soc/actions/owl-sps.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Actions Semi Owl Smart Power System (SPS) 3 4 * ··· 6 5 * Author: Actions Semi, Inc. 7 6 * 8 7 * Copyright (c) 2017 Andreas Färber 9 - * 10 - * This program is free software; you can redistribute it and/or modify it 11 - * under the terms of the GNU General Public License as published by the 12 - * Free Software Foundation; either version 2 of the License, or (at your 13 - * option) any later version. 14 8 */ 15 9 16 10 #include <linux/of_address.h> ··· 14 18 #include <linux/soc/actions/owl-sps.h> 15 19 #include <dt-bindings/power/owl-s500-powergate.h> 16 20 #include <dt-bindings/power/owl-s700-powergate.h> 21 + #include <dt-bindings/power/owl-s900-powergate.h> 17 22 18 23 struct owl_sps_domain_info { 19 24 const char *name; ··· 241 244 .domains = s700_sps_domains, 242 245 }; 243 246 247 + static const struct owl_sps_domain_info s900_sps_domains[] = { 248 + [S900_PD_GPU_B] = { 249 + .name = "GPU_B", 250 + .pwr_bit = 3, 251 + }, 252 + [S900_PD_VCE] = { 253 + .name = "VCE", 254 + .pwr_bit = 4, 255 + }, 256 + [S900_PD_SENSOR] = { 257 + .name = "SENSOR", 258 + .pwr_bit = 5, 259 + }, 260 + [S900_PD_VDE] = { 261 + .name = "VDE", 262 + .pwr_bit = 6, 263 + }, 264 + [S900_PD_HDE] = { 265 + .name = "HDE", 266 + .pwr_bit = 7, 267 + }, 268 + [S900_PD_USB3] = { 269 + .name = "USB3", 270 + .pwr_bit = 8, 271 + }, 272 + [S900_PD_DDR0] = { 273 + .name = "DDR0", 274 + .pwr_bit = 9, 275 + }, 276 + [S900_PD_DDR1] = { 277 + .name = "DDR1", 278 + .pwr_bit = 10, 279 + }, 280 + [S900_PD_DE] = { 281 + .name = "DE", 282 + .pwr_bit = 13, 283 + }, 284 + [S900_PD_NAND] = { 285 + .name = "NAND", 286 + .pwr_bit = 14, 287 + }, 288 + [S900_PD_USB2_H0] = { 289 + .name = "USB2_H0", 290 + .pwr_bit = 15, 291 + }, 292 + [S900_PD_USB2_H1] = { 293 + .name = "USB2_H1", 294 + .pwr_bit = 16, 295 + }, 296 + }; 297 + 298 + static const struct owl_sps_info s900_sps_info = { 299 + .num_domains = ARRAY_SIZE(s900_sps_domains), 300 + .domains = s900_sps_domains, 301 + }; 302 + 244 303 static const struct of_device_id owl_sps_of_matches[] = { 245 304 { .compatible = "actions,s500-sps", .data = &s500_sps_info }, 246 305 { .compatible = "actions,s700-sps", .data = &s700_sps_info }, 306 + { .compatible = "actions,s900-sps", .data = &s900_sps_info }, 247 307 { } 248 308 }; 249 309
+7
drivers/soc/amlogic/Kconfig
··· 1 1 menu "Amlogic SoC drivers" 2 2 3 + config MESON_CANVAS 4 + tristate "Amlogic Meson Canvas driver" 5 + depends on ARCH_MESON || COMPILE_TEST 6 + default n 7 + help 8 + Say yes to support the canvas IP for Amlogic SoCs. 9 + 3 10 config MESON_GX_SOCINFO 4 11 bool "Amlogic Meson GX SoC Information driver" 5 12 depends on ARCH_MESON || COMPILE_TEST
+1
drivers/soc/amlogic/Makefile
··· 1 + obj-$(CONFIG_MESON_CANVAS) += meson-canvas.o 1 2 obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o 2 3 obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o 3 4 obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o
+185
drivers/soc/amlogic/meson-canvas.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (C) 2018 BayLibre, SAS 4 + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. 5 + * Copyright (C) 2014 Endless Mobile 6 + */ 7 + 8 + #include <linux/kernel.h> 9 + #include <linux/mfd/syscon.h> 10 + #include <linux/module.h> 11 + #include <linux/regmap.h> 12 + #include <linux/soc/amlogic/meson-canvas.h> 13 + #include <linux/of_address.h> 14 + #include <linux/of_platform.h> 15 + #include <linux/io.h> 16 + 17 + #define NUM_CANVAS 256 18 + 19 + /* DMC Registers */ 20 + #define DMC_CAV_LUT_DATAL 0x00 21 + #define CANVAS_WIDTH_LBIT 29 22 + #define CANVAS_WIDTH_LWID 3 23 + #define DMC_CAV_LUT_DATAH 0x04 24 + #define CANVAS_WIDTH_HBIT 0 25 + #define CANVAS_HEIGHT_BIT 9 26 + #define CANVAS_WRAP_BIT 22 27 + #define CANVAS_BLKMODE_BIT 24 28 + #define CANVAS_ENDIAN_BIT 26 29 + #define DMC_CAV_LUT_ADDR 0x08 30 + #define CANVAS_LUT_WR_EN BIT(9) 31 + #define CANVAS_LUT_RD_EN BIT(8) 32 + 33 + struct meson_canvas { 34 + struct device *dev; 35 + void __iomem *reg_base; 36 + spinlock_t lock; /* canvas device lock */ 37 + u8 used[NUM_CANVAS]; 38 + }; 39 + 40 + static void canvas_write(struct meson_canvas *canvas, u32 reg, u32 val) 41 + { 42 + writel_relaxed(val, canvas->reg_base + reg); 43 + } 44 + 45 + static u32 canvas_read(struct meson_canvas *canvas, u32 reg) 46 + { 47 + return readl_relaxed(canvas->reg_base + reg); 48 + } 49 + 50 + struct meson_canvas *meson_canvas_get(struct device *dev) 51 + { 52 + struct device_node *canvas_node; 53 + struct platform_device *canvas_pdev; 54 + 55 + canvas_node = of_parse_phandle(dev->of_node, "amlogic,canvas", 0); 56 + if (!canvas_node) 57 + return ERR_PTR(-ENODEV); 58 + 59 + canvas_pdev = of_find_device_by_node(canvas_node); 60 + if (!canvas_pdev) 61 + return ERR_PTR(-EPROBE_DEFER); 62 + 63 + return dev_get_drvdata(&canvas_pdev->dev); 64 + } 65 + EXPORT_SYMBOL_GPL(meson_canvas_get); 66 + 67 + int meson_canvas_config(struct meson_canvas *canvas, u8 canvas_index, 68 + u32 addr, u32 stride, u32 height, 69 + unsigned int wrap, 70 + unsigned int blkmode, 71 + unsigned int endian) 72 + { 73 + unsigned long flags; 74 + 75 + spin_lock_irqsave(&canvas->lock, flags); 76 + if (!canvas->used[canvas_index]) { 77 + dev_err(canvas->dev, 78 + "Trying to setup non allocated canvas %u\n", 79 + canvas_index); 80 + spin_unlock_irqrestore(&canvas->lock, flags); 81 + return -EINVAL; 82 + } 83 + 84 + canvas_write(canvas, DMC_CAV_LUT_DATAL, 85 + ((addr + 7) >> 3) | 86 + (((stride + 7) >> 3) << CANVAS_WIDTH_LBIT)); 87 + 88 + canvas_write(canvas, DMC_CAV_LUT_DATAH, 89 + ((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) << 90 + CANVAS_WIDTH_HBIT) | 91 + (height << CANVAS_HEIGHT_BIT) | 92 + (wrap << CANVAS_WRAP_BIT) | 93 + (blkmode << CANVAS_BLKMODE_BIT) | 94 + (endian << CANVAS_ENDIAN_BIT)); 95 + 96 + canvas_write(canvas, DMC_CAV_LUT_ADDR, 97 + CANVAS_LUT_WR_EN | canvas_index); 98 + 99 + /* Force a read-back to make sure everything is flushed. */ 100 + canvas_read(canvas, DMC_CAV_LUT_DATAH); 101 + spin_unlock_irqrestore(&canvas->lock, flags); 102 + 103 + return 0; 104 + } 105 + EXPORT_SYMBOL_GPL(meson_canvas_config); 106 + 107 + int meson_canvas_alloc(struct meson_canvas *canvas, u8 *canvas_index) 108 + { 109 + int i; 110 + unsigned long flags; 111 + 112 + spin_lock_irqsave(&canvas->lock, flags); 113 + for (i = 0; i < NUM_CANVAS; ++i) { 114 + if (!canvas->used[i]) { 115 + canvas->used[i] = 1; 116 + spin_unlock_irqrestore(&canvas->lock, flags); 117 + *canvas_index = i; 118 + return 0; 119 + } 120 + } 121 + spin_unlock_irqrestore(&canvas->lock, flags); 122 + 123 + dev_err(canvas->dev, "No more canvas available\n"); 124 + return -ENODEV; 125 + } 126 + EXPORT_SYMBOL_GPL(meson_canvas_alloc); 127 + 128 + int meson_canvas_free(struct meson_canvas *canvas, u8 canvas_index) 129 + { 130 + unsigned long flags; 131 + 132 + spin_lock_irqsave(&canvas->lock, flags); 133 + if (!canvas->used[canvas_index]) { 134 + dev_err(canvas->dev, 135 + "Trying to free unused canvas %u\n", canvas_index); 136 + spin_unlock_irqrestore(&canvas->lock, flags); 137 + return -EINVAL; 138 + } 139 + canvas->used[canvas_index] = 0; 140 + spin_unlock_irqrestore(&canvas->lock, flags); 141 + 142 + return 0; 143 + } 144 + EXPORT_SYMBOL_GPL(meson_canvas_free); 145 + 146 + static int meson_canvas_probe(struct platform_device *pdev) 147 + { 148 + struct resource *res; 149 + struct meson_canvas *canvas; 150 + struct device *dev = &pdev->dev; 151 + 152 + canvas = devm_kzalloc(dev, sizeof(*canvas), GFP_KERNEL); 153 + if (!canvas) 154 + return -ENOMEM; 155 + 156 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 157 + canvas->reg_base = devm_ioremap_resource(dev, res); 158 + if (IS_ERR(canvas->reg_base)) 159 + return PTR_ERR(canvas->reg_base); 160 + 161 + canvas->dev = dev; 162 + spin_lock_init(&canvas->lock); 163 + dev_set_drvdata(dev, canvas); 164 + 165 + return 0; 166 + } 167 + 168 + static const struct of_device_id canvas_dt_match[] = { 169 + { .compatible = "amlogic,canvas" }, 170 + {} 171 + }; 172 + MODULE_DEVICE_TABLE(of, canvas_dt_match); 173 + 174 + static struct platform_driver meson_canvas_driver = { 175 + .probe = meson_canvas_probe, 176 + .driver = { 177 + .name = "amlogic-canvas", 178 + .of_match_table = canvas_dt_match, 179 + }, 180 + }; 181 + module_platform_driver(meson_canvas_driver); 182 + 183 + MODULE_DESCRIPTION("Amlogic Canvas driver"); 184 + MODULE_AUTHOR("Maxime Jourdan <mjourdan@baylibre.com>"); 185 + MODULE_LICENSE("GPL");
-3
drivers/soc/fsl/dpio/dpio-driver.c
··· 50 50 51 51 static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu) 52 52 { 53 - struct dpio_priv *priv; 54 53 int error; 55 54 struct fsl_mc_device_irq *irq; 56 55 cpumask_t mask; 57 - 58 - priv = dev_get_drvdata(&dpio_dev->dev); 59 56 60 57 irq = dpio_dev->irqs[0]; 61 58 error = devm_request_irq(&dpio_dev->dev,
+1 -1
drivers/soc/fsl/qbman/Kconfig
··· 1 1 menuconfig FSL_DPAA 2 2 bool "QorIQ DPAA1 framework support" 3 - depends on (FSL_SOC_BOOKE || ARCH_LAYERSCAPE) 3 + depends on ((FSL_SOC_BOOKE || ARCH_LAYERSCAPE) && ARCH_DMA_ADDR_T_64BIT) 4 4 select GENERIC_ALLOCATOR 5 5 help 6 6 The Freescale Data Path Acceleration Architecture (DPAA) is a set of
+2 -4
drivers/soc/fsl/qbman/bman.c
··· 562 562 dev_err(c->dev, "request_irq() failed\n"); 563 563 goto fail_irq; 564 564 } 565 - if (c->cpu != -1 && irq_can_set_affinity(c->irq) && 566 - irq_set_affinity(c->irq, cpumask_of(c->cpu))) { 567 - dev_err(c->dev, "irq_set_affinity() failed\n"); 565 + 566 + if (dpaa_set_portal_irq_affinity(c->dev, c->irq, c->cpu)) 568 567 goto fail_affinity; 569 - } 570 568 571 569 /* Need RCR to be empty before continuing */ 572 570 ret = bm_rcr_get_fill(p);
+12 -2
drivers/soc/fsl/qbman/bman_portal.c
··· 65 65 if (!pcfg) 66 66 return 0; 67 67 68 - irq_set_affinity(pcfg->irq, cpumask_of(0)); 68 + /* use any other online CPU */ 69 + cpu = cpumask_any_but(cpu_online_mask, cpu); 70 + irq_set_affinity(pcfg->irq, cpumask_of(cpu)); 69 71 return 0; 70 72 } 71 73 ··· 93 91 struct device_node *node = dev->of_node; 94 92 struct bm_portal_config *pcfg; 95 93 struct resource *addr_phys[2]; 96 - int irq, cpu; 94 + int irq, cpu, err; 95 + 96 + err = bman_is_probed(); 97 + if (!err) 98 + return -EPROBE_DEFER; 99 + if (err < 0) { 100 + dev_err(&pdev->dev, "failing probe due to bman probe error\n"); 101 + return -ENODEV; 102 + } 97 103 98 104 pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL); 99 105 if (!pcfg)
+20
drivers/soc/fsl/qbman/dpaa_sys.h
··· 111 111 #define QBMAN_MEMREMAP_ATTR MEMREMAP_WC 112 112 #endif 113 113 114 + static inline int dpaa_set_portal_irq_affinity(struct device *dev, 115 + int irq, int cpu) 116 + { 117 + int ret = 0; 118 + 119 + if (!irq_can_set_affinity(irq)) { 120 + dev_err(dev, "unable to set IRQ affinity\n"); 121 + return -EINVAL; 122 + } 123 + 124 + if (cpu == -1 || !cpu_online(cpu)) 125 + cpu = cpumask_any(cpu_online_mask); 126 + 127 + ret = irq_set_affinity(irq, cpumask_of(cpu)); 128 + if (ret) 129 + dev_err(dev, "irq_set_affinity() on CPU %d failed\n", cpu); 130 + 131 + return ret; 132 + } 133 + 114 134 #endif /* __DPAA_SYS_H */
+47 -6
drivers/soc/fsl/qbman/qman.c
··· 850 850 851 851 static inline int qm_mc_init(struct qm_portal *portal) 852 852 { 853 + u8 rr0, rr1; 853 854 struct qm_mc *mc = &portal->mc; 854 855 855 856 mc->cr = portal->addr.ce + QM_CL_CR; 856 857 mc->rr = portal->addr.ce + QM_CL_RR0; 857 - mc->rridx = (mc->cr->_ncw_verb & QM_MCC_VERB_VBIT) 858 - ? 0 : 1; 858 + /* 859 + * The expected valid bit polarity for the next CR command is 0 860 + * if RR1 contains a valid response, and is 1 if RR0 contains a 861 + * valid response. If both RR contain all 0, this indicates either 862 + * that no command has been executed since reset (in which case the 863 + * expected valid bit polarity is 1) 864 + */ 865 + rr0 = mc->rr->verb; 866 + rr1 = (mc->rr+1)->verb; 867 + if ((rr0 == 0 && rr1 == 0) || rr0 != 0) 868 + mc->rridx = 1; 869 + else 870 + mc->rridx = 0; 859 871 mc->vbit = mc->rridx ? QM_MCC_VERB_VBIT : 0; 860 872 #ifdef CONFIG_FSL_DPAA_CHECKING 861 873 mc->state = qman_mc_idle; ··· 1011 999 } 1012 1000 1013 1001 static struct workqueue_struct *qm_portal_wq; 1002 + 1003 + void qman_dqrr_set_ithresh(struct qman_portal *portal, u8 ithresh) 1004 + { 1005 + if (!portal) 1006 + return; 1007 + 1008 + qm_dqrr_set_ithresh(&portal->p, ithresh); 1009 + portal->p.dqrr.ithresh = ithresh; 1010 + } 1011 + EXPORT_SYMBOL(qman_dqrr_set_ithresh); 1012 + 1013 + void qman_dqrr_get_ithresh(struct qman_portal *portal, u8 *ithresh) 1014 + { 1015 + if (portal && ithresh) 1016 + *ithresh = portal->p.dqrr.ithresh; 1017 + } 1018 + EXPORT_SYMBOL(qman_dqrr_get_ithresh); 1019 + 1020 + void qman_portal_get_iperiod(struct qman_portal *portal, u32 *iperiod) 1021 + { 1022 + if (portal && iperiod) 1023 + *iperiod = qm_in(&portal->p, QM_REG_ITPR); 1024 + } 1025 + EXPORT_SYMBOL(qman_portal_get_iperiod); 1026 + 1027 + void qman_portal_set_iperiod(struct qman_portal *portal, u32 iperiod) 1028 + { 1029 + if (portal) 1030 + qm_out(&portal->p, QM_REG_ITPR, iperiod); 1031 + } 1032 + EXPORT_SYMBOL(qman_portal_set_iperiod); 1014 1033 1015 1034 int qman_wq_alloc(void) 1016 1035 { ··· 1253 1210 dev_err(c->dev, "request_irq() failed\n"); 1254 1211 goto fail_irq; 1255 1212 } 1256 - if (c->cpu != -1 && irq_can_set_affinity(c->irq) && 1257 - irq_set_affinity(c->irq, cpumask_of(c->cpu))) { 1258 - dev_err(c->dev, "irq_set_affinity() failed\n"); 1213 + 1214 + if (dpaa_set_portal_irq_affinity(c->dev, c->irq, c->cpu)) 1259 1215 goto fail_affinity; 1260 - } 1261 1216 1262 1217 /* Need EQCR to be empty before continuing */ 1263 1218 isdr &= ~QM_PIRQ_EQCI;
+4 -2
drivers/soc/fsl/qbman/qman_portal.c
··· 195 195 if (p) { 196 196 pcfg = qman_get_qm_portal_config(p); 197 197 if (pcfg) { 198 - irq_set_affinity(pcfg->irq, cpumask_of(0)); 199 - qman_portal_update_sdest(pcfg, 0); 198 + /* select any other online CPU */ 199 + cpu = cpumask_any_but(cpu_online_mask, cpu); 200 + irq_set_affinity(pcfg->irq, cpumask_of(cpu)); 201 + qman_portal_update_sdest(pcfg, cpu); 200 202 } 201 203 } 202 204 return 0;
+1 -5
drivers/soc/fsl/qe/qe.c
··· 588 588 } 589 589 590 590 /* Find the 'firmware' child node */ 591 - for_each_child_of_node(qe, fw) { 592 - if (strcmp(fw->name, "firmware") == 0) 593 - break; 594 - } 595 - 591 + fw = of_get_child_by_name(qe, "firmware"); 596 592 of_node_put(qe); 597 593 598 594 /* Did we find the 'firmware' node? */
+12 -14
drivers/soc/imx/gpc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> 3 4 * Copyright 2011-2013 Freescale Semiconductor, Inc. 4 - * 5 - * The code contained herein is licensed under the GNU General Public 6 - * License. You may obtain a copy of the GNU General Public License 7 - * Version 2 or later at the following locations: 8 - * 9 - * http://www.opensource.org/licenses/gpl-license.html 10 - * http://www.gnu.org/copyleft/gpl.html 11 5 */ 12 6 13 7 #include <linux/clk.h> ··· 63 69 u32 val; 64 70 65 71 /* Read ISO and ISO2SW power down delays */ 66 - regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val); 72 + regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS, &val); 67 73 iso = val & 0x3f; 68 74 iso2sw = (val >> 8) & 0x3f; 69 75 ··· 241 247 #define GPC_PGC_DOMAIN_ARM 0 242 248 #define GPC_PGC_DOMAIN_PU 1 243 249 #define GPC_PGC_DOMAIN_DISPLAY 2 250 + #define GPC_PGC_DOMAIN_PCI 3 244 251 245 252 static struct genpd_power_state imx6_pm_domain_pu_state = { 246 253 .power_off_latency_ns = 25000, ··· 249 254 }; 250 255 251 256 static struct imx_pm_domain imx_gpc_domains[] = { 252 - { 257 + [GPC_PGC_DOMAIN_ARM] { 253 258 .base = { 254 259 .name = "ARM", 255 260 .flags = GENPD_FLAG_ALWAYS_ON, 256 261 }, 257 - }, { 262 + }, 263 + [GPC_PGC_DOMAIN_PU] { 258 264 .base = { 259 265 .name = "PU", 260 266 .power_off = imx6_pm_domain_power_off, ··· 265 269 }, 266 270 .reg_offs = 0x260, 267 271 .cntr_pdn_bit = 0, 268 - }, { 272 + }, 273 + [GPC_PGC_DOMAIN_DISPLAY] { 269 274 .base = { 270 275 .name = "DISPLAY", 271 276 .power_off = imx6_pm_domain_power_off, ··· 274 277 }, 275 278 .reg_offs = 0x240, 276 279 .cntr_pdn_bit = 4, 277 - }, { 280 + }, 281 + [GPC_PGC_DOMAIN_PCI] { 278 282 .base = { 279 283 .name = "PCI", 280 284 .power_off = imx6_pm_domain_power_off, ··· 346 348 }; 347 349 348 350 static struct generic_pm_domain *imx_gpc_onecell_domains[] = { 349 - &imx_gpc_domains[0].base, 350 - &imx_gpc_domains[1].base, 351 + &imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base, 352 + &imx_gpc_domains[GPC_PGC_DOMAIN_PU].base, 351 353 }; 352 354 353 355 static struct genpd_onecell_data imx_gpc_onecell_data = {
+54 -46
drivers/soc/imx/gpcv2.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Copyright 2017 Impinj, Inc 3 4 * Author: Andrey Smirnov <andrew.smirnov@gmail.com> ··· 6 5 * Based on the code of analogus driver: 7 6 * 8 7 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> 9 - * 10 - * The code contained herein is licensed under the GNU General Public 11 - * License. You may obtain a copy of the GNU General Public License 12 - * Version 2 or later at the following locations: 13 - * 14 - * http://www.opensource.org/licenses/gpl-license.html 15 - * http://www.gnu.org/copyleft/gpl.html 16 8 */ 17 9 10 + #include <linux/of_device.h> 18 11 #include <linux/platform_device.h> 19 12 #include <linux/pm_domain.h> 20 13 #include <linux/regmap.h> 21 14 #include <linux/regulator/consumer.h> 22 15 #include <dt-bindings/power/imx7-power.h> 23 16 24 - #define GPC_LPCR_A7_BSC 0x000 17 + #define GPC_LPCR_A_CORE_BSC 0x000 25 18 26 19 #define GPC_PGC_CPU_MAPPING 0x0ec 27 - #define USB_HSIC_PHY_A7_DOMAIN BIT(6) 28 - #define USB_OTG2_PHY_A7_DOMAIN BIT(5) 29 - #define USB_OTG1_PHY_A7_DOMAIN BIT(4) 30 - #define PCIE_PHY_A7_DOMAIN BIT(3) 31 - #define MIPI_PHY_A7_DOMAIN BIT(2) 20 + #define USB_HSIC_PHY_A_CORE_DOMAIN BIT(6) 21 + #define USB_OTG2_PHY_A_CORE_DOMAIN BIT(5) 22 + #define USB_OTG1_PHY_A_CORE_DOMAIN BIT(4) 23 + #define PCIE_PHY_A_CORE_DOMAIN BIT(3) 24 + #define MIPI_PHY_A_CORE_DOMAIN BIT(2) 32 25 33 26 #define GPC_PU_PGC_SW_PUP_REQ 0x0f8 34 27 #define GPC_PU_PGC_SW_PDN_REQ 0x104 ··· 48 53 49 54 #define GPC_PGC_CTRL_PCR BIT(0) 50 55 51 - struct imx7_pgc_domain { 56 + struct imx_pgc_domain { 52 57 struct generic_pm_domain genpd; 53 58 struct regmap *regmap; 54 59 struct regulator *regulator; ··· 64 69 struct device *dev; 65 70 }; 66 71 67 - static int imx7_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, 72 + struct imx_pgc_domain_data { 73 + const struct imx_pgc_domain *domains; 74 + size_t domains_num; 75 + }; 76 + 77 + static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, 68 78 bool on) 69 79 { 70 - struct imx7_pgc_domain *domain = container_of(genpd, 71 - struct imx7_pgc_domain, 80 + struct imx_pgc_domain *domain = container_of(genpd, 81 + struct imx_pgc_domain, 72 82 genpd); 73 83 unsigned int offset = on ? 74 84 GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ; ··· 150 150 return ret; 151 151 } 152 152 153 - static int imx7_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd) 153 + static int imx_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd) 154 154 { 155 - return imx7_gpc_pu_pgc_sw_pxx_req(genpd, true); 155 + return imx_gpc_pu_pgc_sw_pxx_req(genpd, true); 156 156 } 157 157 158 - static int imx7_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd) 158 + static int imx_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd) 159 159 { 160 - return imx7_gpc_pu_pgc_sw_pxx_req(genpd, false); 160 + return imx_gpc_pu_pgc_sw_pxx_req(genpd, false); 161 161 } 162 162 163 - static const struct imx7_pgc_domain imx7_pgc_domains[] = { 163 + static const struct imx_pgc_domain imx7_pgc_domains[] = { 164 164 [IMX7_POWER_DOMAIN_MIPI_PHY] = { 165 165 .genpd = { 166 166 .name = "mipi-phy", 167 167 }, 168 168 .bits = { 169 169 .pxx = MIPI_PHY_SW_Pxx_REQ, 170 - .map = MIPI_PHY_A7_DOMAIN, 170 + .map = MIPI_PHY_A_CORE_DOMAIN, 171 171 }, 172 172 .voltage = 1000000, 173 173 .pgc = PGC_MIPI, ··· 179 179 }, 180 180 .bits = { 181 181 .pxx = PCIE_PHY_SW_Pxx_REQ, 182 - .map = PCIE_PHY_A7_DOMAIN, 182 + .map = PCIE_PHY_A_CORE_DOMAIN, 183 183 }, 184 184 .voltage = 1000000, 185 185 .pgc = PGC_PCIE, ··· 191 191 }, 192 192 .bits = { 193 193 .pxx = USB_HSIC_PHY_SW_Pxx_REQ, 194 - .map = USB_HSIC_PHY_A7_DOMAIN, 194 + .map = USB_HSIC_PHY_A_CORE_DOMAIN, 195 195 }, 196 196 .voltage = 1200000, 197 197 .pgc = PGC_USB_HSIC, 198 198 }, 199 199 }; 200 200 201 - static int imx7_pgc_domain_probe(struct platform_device *pdev) 201 + static const struct imx_pgc_domain_data imx7_pgc_domain_data = { 202 + .domains = imx7_pgc_domains, 203 + .domains_num = ARRAY_SIZE(imx7_pgc_domains), 204 + }; 205 + 206 + static int imx_pgc_domain_probe(struct platform_device *pdev) 202 207 { 203 - struct imx7_pgc_domain *domain = pdev->dev.platform_data; 208 + struct imx_pgc_domain *domain = pdev->dev.platform_data; 204 209 int ret; 205 210 206 211 domain->dev = &pdev->dev; ··· 238 233 return ret; 239 234 } 240 235 241 - static int imx7_pgc_domain_remove(struct platform_device *pdev) 236 + static int imx_pgc_domain_remove(struct platform_device *pdev) 242 237 { 243 - struct imx7_pgc_domain *domain = pdev->dev.platform_data; 238 + struct imx_pgc_domain *domain = pdev->dev.platform_data; 244 239 245 240 of_genpd_del_provider(domain->dev->of_node); 246 241 pm_genpd_remove(&domain->genpd); ··· 248 243 return 0; 249 244 } 250 245 251 - static const struct platform_device_id imx7_pgc_domain_id[] = { 252 - { "imx7-pgc-domain", }, 246 + static const struct platform_device_id imx_pgc_domain_id[] = { 247 + { "imx-pgc-domain", }, 253 248 { }, 254 249 }; 255 250 256 - static struct platform_driver imx7_pgc_domain_driver = { 251 + static struct platform_driver imx_pgc_domain_driver = { 257 252 .driver = { 258 - .name = "imx7-pgc", 253 + .name = "imx-pgc", 259 254 }, 260 - .probe = imx7_pgc_domain_probe, 261 - .remove = imx7_pgc_domain_remove, 262 - .id_table = imx7_pgc_domain_id, 255 + .probe = imx_pgc_domain_probe, 256 + .remove = imx_pgc_domain_remove, 257 + .id_table = imx_pgc_domain_id, 263 258 }; 264 - builtin_platform_driver(imx7_pgc_domain_driver) 259 + builtin_platform_driver(imx_pgc_domain_driver) 265 260 266 261 static int imx_gpcv2_probe(struct platform_device *pdev) 267 262 { 263 + static const struct imx_pgc_domain_data *domain_data; 268 264 static const struct regmap_range yes_ranges[] = { 269 - regmap_reg_range(GPC_LPCR_A7_BSC, 265 + regmap_reg_range(GPC_LPCR_A_CORE_BSC, 270 266 GPC_M4_PU_PDN_FLG), 271 267 regmap_reg_range(GPC_PGC_CTRL(PGC_MIPI), 272 268 GPC_PGC_SR(PGC_MIPI)), ··· 313 307 return ret; 314 308 } 315 309 310 + domain_data = of_device_get_match_data(&pdev->dev); 311 + 316 312 for_each_child_of_node(pgc_np, np) { 317 313 struct platform_device *pd_pdev; 318 - struct imx7_pgc_domain *domain; 314 + struct imx_pgc_domain *domain; 319 315 u32 domain_index; 320 316 321 317 ret = of_property_read_u32(np, "reg", &domain_index); ··· 327 319 return ret; 328 320 } 329 321 330 - if (domain_index >= ARRAY_SIZE(imx7_pgc_domains)) { 322 + if (domain_index >= domain_data->domains_num) { 331 323 dev_warn(dev, 332 324 "Domain index %d is out of bounds\n", 333 325 domain_index); 334 326 continue; 335 327 } 336 328 337 - pd_pdev = platform_device_alloc("imx7-pgc-domain", 329 + pd_pdev = platform_device_alloc("imx-pgc-domain", 338 330 domain_index); 339 331 if (!pd_pdev) { 340 332 dev_err(dev, "Failed to allocate platform device\n"); ··· 343 335 } 344 336 345 337 ret = platform_device_add_data(pd_pdev, 346 - &imx7_pgc_domains[domain_index], 347 - sizeof(imx7_pgc_domains[domain_index])); 338 + &domain_data->domains[domain_index], 339 + sizeof(domain_data->domains[domain_index])); 348 340 if (ret) { 349 341 platform_device_put(pd_pdev); 350 342 of_node_put(np); ··· 353 345 354 346 domain = pd_pdev->dev.platform_data; 355 347 domain->regmap = regmap; 356 - domain->genpd.power_on = imx7_gpc_pu_pgc_sw_pup_req; 357 - domain->genpd.power_off = imx7_gpc_pu_pgc_sw_pdn_req; 348 + domain->genpd.power_on = imx_gpc_pu_pgc_sw_pup_req; 349 + domain->genpd.power_off = imx_gpc_pu_pgc_sw_pdn_req; 358 350 359 351 pd_pdev->dev.parent = dev; 360 352 pd_pdev->dev.of_node = np; ··· 371 363 } 372 364 373 365 static const struct of_device_id imx_gpcv2_dt_ids[] = { 374 - { .compatible = "fsl,imx7d-gpc" }, 366 + { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, }, 375 367 { } 376 368 }; 377 369
+397 -122
drivers/soc/mediatek/mtk-pmic-wrap.c
··· 76 76 #define PWRAP_SLV_CAP_SECURITY BIT(2) 77 77 #define HAS_CAP(_c, _x) (((_c) & (_x)) == (_x)) 78 78 79 + /* Group of bits used for shown pwrap capability */ 80 + #define PWRAP_CAP_BRIDGE BIT(0) 81 + #define PWRAP_CAP_RESET BIT(1) 82 + #define PWRAP_CAP_DCM BIT(2) 83 + #define PWRAP_CAP_INT1_EN BIT(3) 84 + #define PWRAP_CAP_WDT_SRC1 BIT(4) 85 + 79 86 /* defines for slave device wrapper registers */ 80 87 enum dew_regs { 81 88 PWRAP_DEW_BASE, ··· 98 91 PWRAP_DEW_CIPHER_MODE, 99 92 PWRAP_DEW_CIPHER_SWRST, 100 93 94 + /* MT6323 only regs */ 95 + PWRAP_DEW_CIPHER_EN, 96 + PWRAP_DEW_RDDMY_NO, 97 + 98 + /* MT6358 only regs */ 99 + PWRAP_SMT_CON1, 100 + PWRAP_DRV_CON1, 101 + PWRAP_FILTER_CON0, 102 + PWRAP_GPIO_PULLEN0_CLR, 103 + PWRAP_RG_SPI_CON0, 104 + PWRAP_RG_SPI_RECORD0, 105 + PWRAP_RG_SPI_CON2, 106 + PWRAP_RG_SPI_CON3, 107 + PWRAP_RG_SPI_CON4, 108 + PWRAP_RG_SPI_CON5, 109 + PWRAP_RG_SPI_CON6, 110 + PWRAP_RG_SPI_CON7, 111 + PWRAP_RG_SPI_CON8, 112 + PWRAP_RG_SPI_CON13, 113 + PWRAP_SPISLV_KEY, 114 + 101 115 /* MT6397 only regs */ 102 116 PWRAP_DEW_EVENT_OUT_EN, 103 117 PWRAP_DEW_EVENT_SRC_EN, ··· 128 100 PWRAP_DEW_EVENT_TEST, 129 101 PWRAP_DEW_CIPHER_LOAD, 130 102 PWRAP_DEW_CIPHER_START, 131 - 132 - /* MT6323 only regs */ 133 - PWRAP_DEW_CIPHER_EN, 134 - PWRAP_DEW_RDDMY_NO, 135 103 }; 136 104 137 105 static const u32 mt6323_regs[] = { ··· 145 121 [PWRAP_DEW_CIPHER_MODE] = 0x01a0, 146 122 [PWRAP_DEW_CIPHER_SWRST] = 0x01a2, 147 123 [PWRAP_DEW_RDDMY_NO] = 0x01a4, 124 + }; 125 + 126 + static const u32 mt6351_regs[] = { 127 + [PWRAP_DEW_DIO_EN] = 0x02F2, 128 + [PWRAP_DEW_READ_TEST] = 0x02F4, 129 + [PWRAP_DEW_WRITE_TEST] = 0x02F6, 130 + [PWRAP_DEW_CRC_EN] = 0x02FA, 131 + [PWRAP_DEW_CRC_VAL] = 0x02FC, 132 + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0300, 133 + [PWRAP_DEW_CIPHER_IV_SEL] = 0x0302, 134 + [PWRAP_DEW_CIPHER_EN] = 0x0304, 135 + [PWRAP_DEW_CIPHER_RDY] = 0x0306, 136 + [PWRAP_DEW_CIPHER_MODE] = 0x0308, 137 + [PWRAP_DEW_CIPHER_SWRST] = 0x030A, 138 + [PWRAP_DEW_RDDMY_NO] = 0x030C, 139 + }; 140 + 141 + static const u32 mt6357_regs[] = { 142 + [PWRAP_DEW_DIO_EN] = 0x040A, 143 + [PWRAP_DEW_READ_TEST] = 0x040C, 144 + [PWRAP_DEW_WRITE_TEST] = 0x040E, 145 + [PWRAP_DEW_CRC_EN] = 0x0412, 146 + [PWRAP_DEW_CRC_VAL] = 0x0414, 147 + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0418, 148 + [PWRAP_DEW_CIPHER_IV_SEL] = 0x041A, 149 + [PWRAP_DEW_CIPHER_EN] = 0x041C, 150 + [PWRAP_DEW_CIPHER_RDY] = 0x041E, 151 + [PWRAP_DEW_CIPHER_MODE] = 0x0420, 152 + [PWRAP_DEW_CIPHER_SWRST] = 0x0422, 153 + [PWRAP_DEW_RDDMY_NO] = 0x0424, 154 + }; 155 + 156 + static const u32 mt6358_regs[] = { 157 + [PWRAP_SMT_CON1] = 0x0030, 158 + [PWRAP_DRV_CON1] = 0x0038, 159 + [PWRAP_FILTER_CON0] = 0x0040, 160 + [PWRAP_GPIO_PULLEN0_CLR] = 0x0098, 161 + [PWRAP_RG_SPI_CON0] = 0x0408, 162 + [PWRAP_RG_SPI_RECORD0] = 0x040a, 163 + [PWRAP_DEW_DIO_EN] = 0x040c, 164 + [PWRAP_DEW_READ_TEST] = 0x040e, 165 + [PWRAP_DEW_WRITE_TEST] = 0x0410, 166 + [PWRAP_DEW_CRC_EN] = 0x0414, 167 + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x041a, 168 + [PWRAP_DEW_CIPHER_IV_SEL] = 0x041c, 169 + [PWRAP_DEW_CIPHER_EN] = 0x041e, 170 + [PWRAP_DEW_CIPHER_RDY] = 0x0420, 171 + [PWRAP_DEW_CIPHER_MODE] = 0x0422, 172 + [PWRAP_DEW_CIPHER_SWRST] = 0x0424, 173 + [PWRAP_RG_SPI_CON2] = 0x0432, 174 + [PWRAP_RG_SPI_CON3] = 0x0434, 175 + [PWRAP_RG_SPI_CON4] = 0x0436, 176 + [PWRAP_RG_SPI_CON5] = 0x0438, 177 + [PWRAP_RG_SPI_CON6] = 0x043a, 178 + [PWRAP_RG_SPI_CON7] = 0x043c, 179 + [PWRAP_RG_SPI_CON8] = 0x043e, 180 + [PWRAP_RG_SPI_CON13] = 0x0448, 181 + [PWRAP_SPISLV_KEY] = 0x044a, 148 182 }; 149 183 150 184 static const u32 mt6397_regs[] = { ··· 226 144 [PWRAP_DEW_CIPHER_RDY] = 0xbc20, 227 145 [PWRAP_DEW_CIPHER_MODE] = 0xbc22, 228 146 [PWRAP_DEW_CIPHER_SWRST] = 0xbc24, 229 - }; 230 - 231 - static const u32 mt6351_regs[] = { 232 - [PWRAP_DEW_DIO_EN] = 0x02F2, 233 - [PWRAP_DEW_READ_TEST] = 0x02F4, 234 - [PWRAP_DEW_WRITE_TEST] = 0x02F6, 235 - [PWRAP_DEW_CRC_EN] = 0x02FA, 236 - [PWRAP_DEW_CRC_VAL] = 0x02FC, 237 - [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0300, 238 - [PWRAP_DEW_CIPHER_IV_SEL] = 0x0302, 239 - [PWRAP_DEW_CIPHER_EN] = 0x0304, 240 - [PWRAP_DEW_CIPHER_RDY] = 0x0306, 241 - [PWRAP_DEW_CIPHER_MODE] = 0x0308, 242 - [PWRAP_DEW_CIPHER_SWRST] = 0x030A, 243 - [PWRAP_DEW_RDDMY_NO] = 0x030C, 244 147 }; 245 148 246 149 enum pwrap_regs { ··· 288 221 PWRAP_CIPHER_SWRST, 289 222 PWRAP_DCM_EN, 290 223 PWRAP_DCM_DBC_PRD, 224 + PWRAP_EINT_STA0_ADR, 225 + PWRAP_EINT_STA1_ADR, 291 226 292 227 /* MT2701 only regs */ 293 228 PWRAP_ADC_CMD_ADDR, ··· 299 230 PWRAP_ADC_RDATA_ADDR2, 300 231 301 232 /* MT7622 only regs */ 302 - PWRAP_EINT_STA0_ADR, 303 - PWRAP_EINT_STA1_ADR, 304 233 PWRAP_STA, 305 234 PWRAP_CLR, 306 235 PWRAP_DVFS_ADR8, ··· 360 293 PWRAP_DVFS_WDATA7, 361 294 PWRAP_SPMINF_STA, 362 295 PWRAP_CIPHER_EN, 296 + 297 + /* MT8183 only regs */ 298 + PWRAP_SI_SAMPLE_CTRL, 299 + PWRAP_CSLEXT_WRITE, 300 + PWRAP_CSLEXT_READ, 301 + PWRAP_EXT_CK_WRITE, 302 + PWRAP_STAUPD_CTRL, 303 + PWRAP_WACS_P2P_EN, 304 + PWRAP_INIT_DONE_P2P, 305 + PWRAP_WACS_MD32_EN, 306 + PWRAP_INIT_DONE_MD32, 307 + PWRAP_INT1_EN, 308 + PWRAP_INT1_FLG, 309 + PWRAP_INT1_CLR, 310 + PWRAP_WDT_SRC_EN_1, 311 + PWRAP_INT_GPS_AUXADC_CMD_ADDR, 312 + PWRAP_INT_GPS_AUXADC_CMD, 313 + PWRAP_INT_GPS_AUXADC_RDATA_ADDR, 314 + PWRAP_EXT_GPS_AUXADC_RDATA_ADDR, 315 + PWRAP_GPSINF_0_STA, 316 + PWRAP_GPSINF_1_STA, 363 317 }; 364 318 365 319 static int mt2701_regs[] = { ··· 467 379 [PWRAP_ADC_RDY_ADDR] = 0x14c, 468 380 [PWRAP_ADC_RDATA_ADDR1] = 0x150, 469 381 [PWRAP_ADC_RDATA_ADDR2] = 0x154, 382 + }; 383 + 384 + static int mt6765_regs[] = { 385 + [PWRAP_MUX_SEL] = 0x0, 386 + [PWRAP_WRAP_EN] = 0x4, 387 + [PWRAP_DIO_EN] = 0x8, 388 + [PWRAP_RDDMY] = 0x20, 389 + [PWRAP_CSHEXT_WRITE] = 0x24, 390 + [PWRAP_CSHEXT_READ] = 0x28, 391 + [PWRAP_CSLEXT_START] = 0x2C, 392 + [PWRAP_CSLEXT_END] = 0x30, 393 + [PWRAP_STAUPD_PRD] = 0x3C, 394 + [PWRAP_HARB_HPRIO] = 0x68, 395 + [PWRAP_HIPRIO_ARB_EN] = 0x6C, 396 + [PWRAP_MAN_EN] = 0x7C, 397 + [PWRAP_MAN_CMD] = 0x80, 398 + [PWRAP_WACS0_EN] = 0x8C, 399 + [PWRAP_WACS1_EN] = 0x94, 400 + [PWRAP_WACS2_EN] = 0x9C, 401 + [PWRAP_INIT_DONE2] = 0xA0, 402 + [PWRAP_WACS2_CMD] = 0xC20, 403 + [PWRAP_WACS2_RDATA] = 0xC24, 404 + [PWRAP_WACS2_VLDCLR] = 0xC28, 405 + [PWRAP_INT_EN] = 0xB4, 406 + [PWRAP_INT_FLG_RAW] = 0xB8, 407 + [PWRAP_INT_FLG] = 0xBC, 408 + [PWRAP_INT_CLR] = 0xC0, 409 + [PWRAP_TIMER_EN] = 0xE8, 410 + [PWRAP_WDT_UNIT] = 0xF0, 411 + [PWRAP_WDT_SRC_EN] = 0xF4, 412 + [PWRAP_DCM_EN] = 0x1DC, 413 + [PWRAP_DCM_DBC_PRD] = 0x1E0, 470 414 }; 471 415 472 416 static int mt6797_regs[] = { ··· 646 526 [PWRAP_SPI2_CTRL] = 0x244, 647 527 }; 648 528 529 + static int mt8135_regs[] = { 530 + [PWRAP_MUX_SEL] = 0x0, 531 + [PWRAP_WRAP_EN] = 0x4, 532 + [PWRAP_DIO_EN] = 0x8, 533 + [PWRAP_SIDLY] = 0xc, 534 + [PWRAP_CSHEXT] = 0x10, 535 + [PWRAP_CSHEXT_WRITE] = 0x14, 536 + [PWRAP_CSHEXT_READ] = 0x18, 537 + [PWRAP_CSLEXT_START] = 0x1c, 538 + [PWRAP_CSLEXT_END] = 0x20, 539 + [PWRAP_STAUPD_PRD] = 0x24, 540 + [PWRAP_STAUPD_GRPEN] = 0x28, 541 + [PWRAP_STAUPD_MAN_TRIG] = 0x2c, 542 + [PWRAP_STAUPD_STA] = 0x30, 543 + [PWRAP_EVENT_IN_EN] = 0x34, 544 + [PWRAP_EVENT_DST_EN] = 0x38, 545 + [PWRAP_WRAP_STA] = 0x3c, 546 + [PWRAP_RRARB_INIT] = 0x40, 547 + [PWRAP_RRARB_EN] = 0x44, 548 + [PWRAP_RRARB_STA0] = 0x48, 549 + [PWRAP_RRARB_STA1] = 0x4c, 550 + [PWRAP_HARB_INIT] = 0x50, 551 + [PWRAP_HARB_HPRIO] = 0x54, 552 + [PWRAP_HIPRIO_ARB_EN] = 0x58, 553 + [PWRAP_HARB_STA0] = 0x5c, 554 + [PWRAP_HARB_STA1] = 0x60, 555 + [PWRAP_MAN_EN] = 0x64, 556 + [PWRAP_MAN_CMD] = 0x68, 557 + [PWRAP_MAN_RDATA] = 0x6c, 558 + [PWRAP_MAN_VLDCLR] = 0x70, 559 + [PWRAP_WACS0_EN] = 0x74, 560 + [PWRAP_INIT_DONE0] = 0x78, 561 + [PWRAP_WACS0_CMD] = 0x7c, 562 + [PWRAP_WACS0_RDATA] = 0x80, 563 + [PWRAP_WACS0_VLDCLR] = 0x84, 564 + [PWRAP_WACS1_EN] = 0x88, 565 + [PWRAP_INIT_DONE1] = 0x8c, 566 + [PWRAP_WACS1_CMD] = 0x90, 567 + [PWRAP_WACS1_RDATA] = 0x94, 568 + [PWRAP_WACS1_VLDCLR] = 0x98, 569 + [PWRAP_WACS2_EN] = 0x9c, 570 + [PWRAP_INIT_DONE2] = 0xa0, 571 + [PWRAP_WACS2_CMD] = 0xa4, 572 + [PWRAP_WACS2_RDATA] = 0xa8, 573 + [PWRAP_WACS2_VLDCLR] = 0xac, 574 + [PWRAP_INT_EN] = 0xb0, 575 + [PWRAP_INT_FLG_RAW] = 0xb4, 576 + [PWRAP_INT_FLG] = 0xb8, 577 + [PWRAP_INT_CLR] = 0xbc, 578 + [PWRAP_SIG_ADR] = 0xc0, 579 + [PWRAP_SIG_MODE] = 0xc4, 580 + [PWRAP_SIG_VALUE] = 0xc8, 581 + [PWRAP_SIG_ERRVAL] = 0xcc, 582 + [PWRAP_CRC_EN] = 0xd0, 583 + [PWRAP_EVENT_STA] = 0xd4, 584 + [PWRAP_EVENT_STACLR] = 0xd8, 585 + [PWRAP_TIMER_EN] = 0xdc, 586 + [PWRAP_TIMER_STA] = 0xe0, 587 + [PWRAP_WDT_UNIT] = 0xe4, 588 + [PWRAP_WDT_SRC_EN] = 0xe8, 589 + [PWRAP_WDT_FLG] = 0xec, 590 + [PWRAP_DEBUG_INT_SEL] = 0xf0, 591 + [PWRAP_CIPHER_KEY_SEL] = 0x134, 592 + [PWRAP_CIPHER_IV_SEL] = 0x138, 593 + [PWRAP_CIPHER_LOAD] = 0x13c, 594 + [PWRAP_CIPHER_START] = 0x140, 595 + [PWRAP_CIPHER_RDY] = 0x144, 596 + [PWRAP_CIPHER_MODE] = 0x148, 597 + [PWRAP_CIPHER_SWRST] = 0x14c, 598 + [PWRAP_DCM_EN] = 0x15c, 599 + [PWRAP_DCM_DBC_PRD] = 0x160, 600 + }; 601 + 649 602 static int mt8173_regs[] = { 650 603 [PWRAP_MUX_SEL] = 0x0, 651 604 [PWRAP_WRAP_EN] = 0x4, ··· 801 608 [PWRAP_DCM_DBC_PRD] = 0x148, 802 609 }; 803 610 804 - static int mt8135_regs[] = { 805 - [PWRAP_MUX_SEL] = 0x0, 806 - [PWRAP_WRAP_EN] = 0x4, 807 - [PWRAP_DIO_EN] = 0x8, 808 - [PWRAP_SIDLY] = 0xc, 809 - [PWRAP_CSHEXT] = 0x10, 810 - [PWRAP_CSHEXT_WRITE] = 0x14, 811 - [PWRAP_CSHEXT_READ] = 0x18, 812 - [PWRAP_CSLEXT_START] = 0x1c, 813 - [PWRAP_CSLEXT_END] = 0x20, 814 - [PWRAP_STAUPD_PRD] = 0x24, 815 - [PWRAP_STAUPD_GRPEN] = 0x28, 816 - [PWRAP_STAUPD_MAN_TRIG] = 0x2c, 817 - [PWRAP_STAUPD_STA] = 0x30, 818 - [PWRAP_EVENT_IN_EN] = 0x34, 819 - [PWRAP_EVENT_DST_EN] = 0x38, 820 - [PWRAP_WRAP_STA] = 0x3c, 821 - [PWRAP_RRARB_INIT] = 0x40, 822 - [PWRAP_RRARB_EN] = 0x44, 823 - [PWRAP_RRARB_STA0] = 0x48, 824 - [PWRAP_RRARB_STA1] = 0x4c, 825 - [PWRAP_HARB_INIT] = 0x50, 826 - [PWRAP_HARB_HPRIO] = 0x54, 827 - [PWRAP_HIPRIO_ARB_EN] = 0x58, 828 - [PWRAP_HARB_STA0] = 0x5c, 829 - [PWRAP_HARB_STA1] = 0x60, 830 - [PWRAP_MAN_EN] = 0x64, 831 - [PWRAP_MAN_CMD] = 0x68, 832 - [PWRAP_MAN_RDATA] = 0x6c, 833 - [PWRAP_MAN_VLDCLR] = 0x70, 834 - [PWRAP_WACS0_EN] = 0x74, 835 - [PWRAP_INIT_DONE0] = 0x78, 836 - [PWRAP_WACS0_CMD] = 0x7c, 837 - [PWRAP_WACS0_RDATA] = 0x80, 838 - [PWRAP_WACS0_VLDCLR] = 0x84, 839 - [PWRAP_WACS1_EN] = 0x88, 840 - [PWRAP_INIT_DONE1] = 0x8c, 841 - [PWRAP_WACS1_CMD] = 0x90, 842 - [PWRAP_WACS1_RDATA] = 0x94, 843 - [PWRAP_WACS1_VLDCLR] = 0x98, 844 - [PWRAP_WACS2_EN] = 0x9c, 845 - [PWRAP_INIT_DONE2] = 0xa0, 846 - [PWRAP_WACS2_CMD] = 0xa4, 847 - [PWRAP_WACS2_RDATA] = 0xa8, 848 - [PWRAP_WACS2_VLDCLR] = 0xac, 849 - [PWRAP_INT_EN] = 0xb0, 850 - [PWRAP_INT_FLG_RAW] = 0xb4, 851 - [PWRAP_INT_FLG] = 0xb8, 852 - [PWRAP_INT_CLR] = 0xbc, 853 - [PWRAP_SIG_ADR] = 0xc0, 854 - [PWRAP_SIG_MODE] = 0xc4, 855 - [PWRAP_SIG_VALUE] = 0xc8, 856 - [PWRAP_SIG_ERRVAL] = 0xcc, 857 - [PWRAP_CRC_EN] = 0xd0, 858 - [PWRAP_EVENT_STA] = 0xd4, 859 - [PWRAP_EVENT_STACLR] = 0xd8, 860 - [PWRAP_TIMER_EN] = 0xdc, 861 - [PWRAP_TIMER_STA] = 0xe0, 862 - [PWRAP_WDT_UNIT] = 0xe4, 863 - [PWRAP_WDT_SRC_EN] = 0xe8, 864 - [PWRAP_WDT_FLG] = 0xec, 865 - [PWRAP_DEBUG_INT_SEL] = 0xf0, 866 - [PWRAP_CIPHER_KEY_SEL] = 0x134, 867 - [PWRAP_CIPHER_IV_SEL] = 0x138, 868 - [PWRAP_CIPHER_LOAD] = 0x13c, 869 - [PWRAP_CIPHER_START] = 0x140, 870 - [PWRAP_CIPHER_RDY] = 0x144, 871 - [PWRAP_CIPHER_MODE] = 0x148, 872 - [PWRAP_CIPHER_SWRST] = 0x14c, 873 - [PWRAP_DCM_EN] = 0x15c, 874 - [PWRAP_DCM_DBC_PRD] = 0x160, 611 + static int mt8183_regs[] = { 612 + [PWRAP_MUX_SEL] = 0x0, 613 + [PWRAP_WRAP_EN] = 0x4, 614 + [PWRAP_DIO_EN] = 0x8, 615 + [PWRAP_SI_SAMPLE_CTRL] = 0xC, 616 + [PWRAP_RDDMY] = 0x14, 617 + [PWRAP_CSHEXT_WRITE] = 0x18, 618 + [PWRAP_CSHEXT_READ] = 0x1C, 619 + [PWRAP_CSLEXT_WRITE] = 0x20, 620 + [PWRAP_CSLEXT_READ] = 0x24, 621 + [PWRAP_EXT_CK_WRITE] = 0x28, 622 + [PWRAP_STAUPD_CTRL] = 0x30, 623 + [PWRAP_STAUPD_GRPEN] = 0x34, 624 + [PWRAP_EINT_STA0_ADR] = 0x38, 625 + [PWRAP_HARB_HPRIO] = 0x5C, 626 + [PWRAP_HIPRIO_ARB_EN] = 0x60, 627 + [PWRAP_MAN_EN] = 0x70, 628 + [PWRAP_MAN_CMD] = 0x74, 629 + [PWRAP_WACS0_EN] = 0x80, 630 + [PWRAP_INIT_DONE0] = 0x84, 631 + [PWRAP_WACS1_EN] = 0x88, 632 + [PWRAP_INIT_DONE1] = 0x8C, 633 + [PWRAP_WACS2_EN] = 0x90, 634 + [PWRAP_INIT_DONE2] = 0x94, 635 + [PWRAP_WACS_P2P_EN] = 0xA0, 636 + [PWRAP_INIT_DONE_P2P] = 0xA4, 637 + [PWRAP_WACS_MD32_EN] = 0xA8, 638 + [PWRAP_INIT_DONE_MD32] = 0xAC, 639 + [PWRAP_INT_EN] = 0xB0, 640 + [PWRAP_INT_FLG] = 0xB8, 641 + [PWRAP_INT_CLR] = 0xBC, 642 + [PWRAP_INT1_EN] = 0xC0, 643 + [PWRAP_INT1_FLG] = 0xC8, 644 + [PWRAP_INT1_CLR] = 0xCC, 645 + [PWRAP_SIG_ADR] = 0xD0, 646 + [PWRAP_CRC_EN] = 0xE0, 647 + [PWRAP_TIMER_EN] = 0xE4, 648 + [PWRAP_WDT_UNIT] = 0xEC, 649 + [PWRAP_WDT_SRC_EN] = 0xF0, 650 + [PWRAP_WDT_SRC_EN_1] = 0xF4, 651 + [PWRAP_INT_GPS_AUXADC_CMD_ADDR] = 0x1DC, 652 + [PWRAP_INT_GPS_AUXADC_CMD] = 0x1E0, 653 + [PWRAP_INT_GPS_AUXADC_RDATA_ADDR] = 0x1E4, 654 + [PWRAP_EXT_GPS_AUXADC_RDATA_ADDR] = 0x1E8, 655 + [PWRAP_GPSINF_0_STA] = 0x1EC, 656 + [PWRAP_GPSINF_1_STA] = 0x1F0, 657 + [PWRAP_WACS2_CMD] = 0xC20, 658 + [PWRAP_WACS2_RDATA] = 0xC24, 659 + [PWRAP_WACS2_VLDCLR] = 0xC28, 875 660 }; 876 661 877 662 enum pmic_type { 878 663 PMIC_MT6323, 879 664 PMIC_MT6351, 665 + PMIC_MT6357, 666 + PMIC_MT6358, 880 667 PMIC_MT6380, 881 668 PMIC_MT6397, 882 669 }; 883 670 884 671 enum pwrap_type { 885 672 PWRAP_MT2701, 673 + PWRAP_MT6765, 886 674 PWRAP_MT6797, 887 675 PWRAP_MT7622, 888 676 PWRAP_MT8135, 889 677 PWRAP_MT8173, 678 + PWRAP_MT8183, 890 679 }; 891 680 892 681 struct pmic_wrapper; ··· 906 731 enum pwrap_type type; 907 732 u32 arb_en_all; 908 733 u32 int_en_all; 734 + u32 int1_en_all; 909 735 u32 spi_w; 910 736 u32 wdt_src; 911 - unsigned int has_bridge:1; 737 + /* Flags indicating the capability for the target pwrap */ 738 + u32 caps; 912 739 int (*init_reg_clock)(struct pmic_wrapper *wrp); 913 740 int (*init_soc_specific)(struct pmic_wrapper *wrp); 914 741 }; ··· 1273 1096 ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY], 1274 1097 &rdata); 1275 1098 if (ret) 1276 - return 0; 1099 + return false; 1277 1100 1278 1101 return rdata == 1; 1279 1102 } ··· 1294 1117 pwrap_writel(wrp, 1, PWRAP_CIPHER_START); 1295 1118 break; 1296 1119 case PWRAP_MT2701: 1120 + case PWRAP_MT6765: 1297 1121 case PWRAP_MT6797: 1298 1122 case PWRAP_MT8173: 1299 1123 pwrap_writel(wrp, 1, PWRAP_CIPHER_EN); 1300 1124 break; 1301 1125 case PWRAP_MT7622: 1302 1126 pwrap_writel(wrp, 0, PWRAP_CIPHER_EN); 1127 + break; 1128 + case PWRAP_MT8183: 1303 1129 break; 1304 1130 } 1305 1131 ··· 1321 1141 break; 1322 1142 case PMIC_MT6323: 1323 1143 case PMIC_MT6351: 1144 + case PMIC_MT6357: 1324 1145 pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN], 1325 1146 0x1); 1326 1147 break; ··· 1457 1276 return 0; 1458 1277 } 1459 1278 1279 + static int pwrap_mt8183_init_soc_specific(struct pmic_wrapper *wrp) 1280 + { 1281 + pwrap_writel(wrp, 0xf5, PWRAP_STAUPD_GRPEN); 1282 + 1283 + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1); 1284 + pwrap_writel(wrp, 1, PWRAP_CRC_EN); 1285 + pwrap_writel(wrp, 0x416, PWRAP_SIG_ADR); 1286 + pwrap_writel(wrp, 0x42e, PWRAP_EINT_STA0_ADR); 1287 + 1288 + pwrap_writel(wrp, 1, PWRAP_WACS_P2P_EN); 1289 + pwrap_writel(wrp, 1, PWRAP_WACS_MD32_EN); 1290 + pwrap_writel(wrp, 1, PWRAP_INIT_DONE_P2P); 1291 + pwrap_writel(wrp, 1, PWRAP_INIT_DONE_MD32); 1292 + 1293 + return 0; 1294 + } 1295 + 1460 1296 static int pwrap_init(struct pmic_wrapper *wrp) 1461 1297 { 1462 1298 int ret; ··· 1546 1348 pwrap_writel(wrp, 1, PWRAP_INIT_DONE0); 1547 1349 pwrap_writel(wrp, 1, PWRAP_INIT_DONE1); 1548 1350 1549 - if (wrp->master->has_bridge) { 1351 + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_BRIDGE)) { 1550 1352 writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3); 1551 1353 writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4); 1552 1354 } ··· 1560 1362 struct pmic_wrapper *wrp = dev_id; 1561 1363 1562 1364 rdata = pwrap_readl(wrp, PWRAP_INT_FLG); 1563 - 1564 1365 dev_err(wrp->dev, "unexpected interrupt int=0x%x\n", rdata); 1565 - 1566 1366 pwrap_writel(wrp, 0xffffffff, PWRAP_INT_CLR); 1367 + 1368 + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_INT1_EN)) { 1369 + rdata = pwrap_readl(wrp, PWRAP_INT1_FLG); 1370 + dev_err(wrp->dev, "unexpected interrupt int1=0x%x\n", rdata); 1371 + pwrap_writel(wrp, 0xffffffff, PWRAP_INT1_CLR); 1372 + } 1567 1373 1568 1374 return IRQ_HANDLED; 1569 1375 } ··· 1600 1398 .pwrap_write = pwrap_write16, 1601 1399 }; 1602 1400 1401 + static const struct pwrap_slv_type pmic_mt6351 = { 1402 + .dew_regs = mt6351_regs, 1403 + .type = PMIC_MT6351, 1404 + .regmap = &pwrap_regmap_config16, 1405 + .caps = 0, 1406 + .pwrap_read = pwrap_read16, 1407 + .pwrap_write = pwrap_write16, 1408 + }; 1409 + 1410 + static const struct pwrap_slv_type pmic_mt6357 = { 1411 + .dew_regs = mt6357_regs, 1412 + .type = PMIC_MT6357, 1413 + .regmap = &pwrap_regmap_config16, 1414 + .caps = 0, 1415 + .pwrap_read = pwrap_read16, 1416 + .pwrap_write = pwrap_write16, 1417 + }; 1418 + 1419 + static const struct pwrap_slv_type pmic_mt6358 = { 1420 + .dew_regs = mt6358_regs, 1421 + .type = PMIC_MT6358, 1422 + .regmap = &pwrap_regmap_config16, 1423 + .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO, 1424 + .pwrap_read = pwrap_read16, 1425 + .pwrap_write = pwrap_write16, 1426 + }; 1427 + 1603 1428 static const struct pwrap_slv_type pmic_mt6380 = { 1604 1429 .dew_regs = NULL, 1605 1430 .type = PMIC_MT6380, ··· 1646 1417 .pwrap_write = pwrap_write16, 1647 1418 }; 1648 1419 1649 - static const struct pwrap_slv_type pmic_mt6351 = { 1650 - .dew_regs = mt6351_regs, 1651 - .type = PMIC_MT6351, 1652 - .regmap = &pwrap_regmap_config16, 1653 - .caps = 0, 1654 - .pwrap_read = pwrap_read16, 1655 - .pwrap_write = pwrap_write16, 1656 - }; 1657 - 1658 1420 static const struct of_device_id of_slave_match_tbl[] = { 1659 1421 { 1660 1422 .compatible = "mediatek,mt6323", 1661 1423 .data = &pmic_mt6323, 1424 + }, { 1425 + .compatible = "mediatek,mt6351", 1426 + .data = &pmic_mt6351, 1427 + }, { 1428 + .compatible = "mediatek,mt6357", 1429 + .data = &pmic_mt6357, 1430 + }, { 1431 + .compatible = "mediatek,mt6358", 1432 + .data = &pmic_mt6358, 1662 1433 }, { 1663 1434 /* The MT6380 PMIC only implements a regulator, so we bind it 1664 1435 * directly instead of using a MFD. ··· 1668 1439 }, { 1669 1440 .compatible = "mediatek,mt6397", 1670 1441 .data = &pmic_mt6397, 1671 - }, { 1672 - .compatible = "mediatek,mt6351", 1673 - .data = &pmic_mt6351, 1674 1442 }, { 1675 1443 /* sentinel */ 1676 1444 } ··· 1679 1453 .type = PWRAP_MT2701, 1680 1454 .arb_en_all = 0x3f, 1681 1455 .int_en_all = ~(u32)(BIT(31) | BIT(2)), 1456 + .int1_en_all = 0, 1682 1457 .spi_w = PWRAP_MAN_CMD_SPI_WRITE_NEW, 1683 1458 .wdt_src = PWRAP_WDT_SRC_MASK_ALL, 1684 - .has_bridge = 0, 1459 + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, 1685 1460 .init_reg_clock = pwrap_mt2701_init_reg_clock, 1686 1461 .init_soc_specific = pwrap_mt2701_init_soc_specific, 1462 + }; 1463 + 1464 + static const struct pmic_wrapper_type pwrap_mt6765 = { 1465 + .regs = mt6765_regs, 1466 + .type = PWRAP_MT6765, 1467 + .arb_en_all = 0x3fd35, 1468 + .int_en_all = 0xffffffff, 1469 + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, 1470 + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, 1471 + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, 1472 + .init_reg_clock = pwrap_common_init_reg_clock, 1473 + .init_soc_specific = NULL, 1687 1474 }; 1688 1475 1689 1476 static const struct pmic_wrapper_type pwrap_mt6797 = { ··· 1704 1465 .type = PWRAP_MT6797, 1705 1466 .arb_en_all = 0x01fff, 1706 1467 .int_en_all = 0xffffffc6, 1468 + .int1_en_all = 0, 1707 1469 .spi_w = PWRAP_MAN_CMD_SPI_WRITE, 1708 1470 .wdt_src = PWRAP_WDT_SRC_MASK_ALL, 1709 - .has_bridge = 0, 1471 + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, 1710 1472 .init_reg_clock = pwrap_common_init_reg_clock, 1711 1473 .init_soc_specific = NULL, 1712 1474 }; ··· 1717 1477 .type = PWRAP_MT7622, 1718 1478 .arb_en_all = 0xff, 1719 1479 .int_en_all = ~(u32)BIT(31), 1480 + .int1_en_all = 0, 1720 1481 .spi_w = PWRAP_MAN_CMD_SPI_WRITE, 1721 1482 .wdt_src = PWRAP_WDT_SRC_MASK_ALL, 1722 - .has_bridge = 0, 1483 + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, 1723 1484 .init_reg_clock = pwrap_common_init_reg_clock, 1724 1485 .init_soc_specific = pwrap_mt7622_init_soc_specific, 1725 1486 }; ··· 1730 1489 .type = PWRAP_MT8135, 1731 1490 .arb_en_all = 0x1ff, 1732 1491 .int_en_all = ~(u32)(BIT(31) | BIT(1)), 1492 + .int1_en_all = 0, 1733 1493 .spi_w = PWRAP_MAN_CMD_SPI_WRITE, 1734 1494 .wdt_src = PWRAP_WDT_SRC_MASK_ALL, 1735 - .has_bridge = 1, 1495 + .caps = PWRAP_CAP_BRIDGE | PWRAP_CAP_RESET | PWRAP_CAP_DCM, 1736 1496 .init_reg_clock = pwrap_common_init_reg_clock, 1737 1497 .init_soc_specific = pwrap_mt8135_init_soc_specific, 1738 1498 }; ··· 1743 1501 .type = PWRAP_MT8173, 1744 1502 .arb_en_all = 0x3f, 1745 1503 .int_en_all = ~(u32)(BIT(31) | BIT(1)), 1504 + .int1_en_all = 0, 1746 1505 .spi_w = PWRAP_MAN_CMD_SPI_WRITE, 1747 1506 .wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD, 1748 - .has_bridge = 0, 1507 + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, 1749 1508 .init_reg_clock = pwrap_common_init_reg_clock, 1750 1509 .init_soc_specific = pwrap_mt8173_init_soc_specific, 1510 + }; 1511 + 1512 + static const struct pmic_wrapper_type pwrap_mt8183 = { 1513 + .regs = mt8183_regs, 1514 + .type = PWRAP_MT8183, 1515 + .arb_en_all = 0x3fa75, 1516 + .int_en_all = 0xffffffff, 1517 + .int1_en_all = 0xeef7ffff, 1518 + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, 1519 + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, 1520 + .caps = PWRAP_CAP_INT1_EN | PWRAP_CAP_WDT_SRC1, 1521 + .init_reg_clock = pwrap_common_init_reg_clock, 1522 + .init_soc_specific = pwrap_mt8183_init_soc_specific, 1751 1523 }; 1752 1524 1753 1525 static const struct of_device_id of_pwrap_match_tbl[] = { 1754 1526 { 1755 1527 .compatible = "mediatek,mt2701-pwrap", 1756 1528 .data = &pwrap_mt2701, 1529 + }, { 1530 + .compatible = "mediatek,mt6765-pwrap", 1531 + .data = &pwrap_mt6765, 1757 1532 }, { 1758 1533 .compatible = "mediatek,mt6797-pwrap", 1759 1534 .data = &pwrap_mt6797, ··· 1783 1524 }, { 1784 1525 .compatible = "mediatek,mt8173-pwrap", 1785 1526 .data = &pwrap_mt8173, 1527 + }, { 1528 + .compatible = "mediatek,mt8183-pwrap", 1529 + .data = &pwrap_mt8183, 1786 1530 }, { 1787 1531 /* sentinel */ 1788 1532 } ··· 1823 1561 if (IS_ERR(wrp->base)) 1824 1562 return PTR_ERR(wrp->base); 1825 1563 1826 - wrp->rstc = devm_reset_control_get(wrp->dev, "pwrap"); 1827 - if (IS_ERR(wrp->rstc)) { 1828 - ret = PTR_ERR(wrp->rstc); 1829 - dev_dbg(wrp->dev, "cannot get pwrap reset: %d\n", ret); 1830 - return ret; 1564 + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_RESET)) { 1565 + wrp->rstc = devm_reset_control_get(wrp->dev, "pwrap"); 1566 + if (IS_ERR(wrp->rstc)) { 1567 + ret = PTR_ERR(wrp->rstc); 1568 + dev_dbg(wrp->dev, "cannot get pwrap reset: %d\n", ret); 1569 + return ret; 1570 + } 1831 1571 } 1832 1572 1833 - if (wrp->master->has_bridge) { 1573 + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_BRIDGE)) { 1834 1574 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 1835 1575 "pwrap-bridge"); 1836 1576 wrp->bridge_base = devm_ioremap_resource(wrp->dev, res); ··· 1872 1608 goto err_out1; 1873 1609 1874 1610 /* Enable internal dynamic clock */ 1875 - pwrap_writel(wrp, 1, PWRAP_DCM_EN); 1876 - pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); 1611 + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_DCM)) { 1612 + pwrap_writel(wrp, 1, PWRAP_DCM_EN); 1613 + pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); 1614 + } 1877 1615 1878 1616 /* 1879 1617 * The PMIC could already be initialized by the bootloader. ··· 1902 1636 * so STAUPD of WDT_SRC which should be turned off 1903 1637 */ 1904 1638 pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN); 1639 + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_WDT_SRC1)) 1640 + pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN_1); 1641 + 1905 1642 pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); 1906 1643 pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN); 1644 + /* 1645 + * We add INT1 interrupt to handle starvation and request exception 1646 + * If we support it, we should enable it here. 1647 + */ 1648 + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_INT1_EN)) 1649 + pwrap_writel(wrp, wrp->master->int1_en_all, PWRAP_INT1_EN); 1907 1650 1908 1651 irq = platform_get_irq(pdev, 0); 1909 1652 ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt,
+12 -9
drivers/soc/qcom/Kconfig
··· 33 33 34 34 config QCOM_GSBI 35 35 tristate "QCOM General Serial Bus Interface" 36 - depends on ARCH_QCOM 36 + depends on ARCH_QCOM || COMPILE_TEST 37 37 select MFD_SYSCON 38 38 help 39 39 Say y here to enable GSBI support. The GSBI provides control ··· 42 42 43 43 config QCOM_LLCC 44 44 tristate "Qualcomm Technologies, Inc. LLCC driver" 45 - depends on ARCH_QCOM 45 + depends on ARCH_QCOM || COMPILE_TEST 46 46 help 47 47 Qualcomm Technologies, Inc. platform specific 48 48 Last Level Cache Controller(LLCC) driver. This provides interfaces ··· 73 73 74 74 config QCOM_QMI_HELPERS 75 75 tristate 76 - depends on (ARCH_QCOM || COMPILE_TEST) && NET 76 + depends on ARCH_QCOM || COMPILE_TEST 77 + depends on NET 77 78 help 78 79 Helper library for handling QMI encoded messages. QMI encoded 79 80 messages are used in communication between the majority of QRTR ··· 95 94 96 95 config QCOM_RPMH 97 96 bool "Qualcomm RPM-Hardened (RPMH) Communication" 98 - depends on ARCH_QCOM && ARM64 && OF || COMPILE_TEST 97 + depends on ARCH_QCOM && ARM64 || COMPILE_TEST 99 98 help 100 99 Support for communication with the hardened-RPM blocks in 101 100 Qualcomm Technologies Inc (QTI) SoCs. RPMH communication uses an ··· 105 104 106 105 config QCOM_SMEM 107 106 tristate "Qualcomm Shared Memory Manager (SMEM)" 108 - depends on ARCH_QCOM 107 + depends on ARCH_QCOM || COMPILE_TEST 109 108 depends on HWSPINLOCK 110 109 help 111 110 Say y here to enable support for the Qualcomm Shared Memory Manager. ··· 114 113 115 114 config QCOM_SMD_RPM 116 115 tristate "Qualcomm Resource Power Manager (RPM) over SMD" 117 - depends on ARCH_QCOM 118 - depends on RPMSG && OF 116 + depends on ARCH_QCOM || COMPILE_TEST 117 + depends on RPMSG 119 118 help 120 119 If you say yes to this option, support will be included for the 121 120 Resource Power Manager system found in the Qualcomm 8974 based ··· 135 134 depends on MAILBOX 136 135 depends on QCOM_SMEM 137 136 select QCOM_SMEM_STATE 137 + select IRQ_DOMAIN 138 138 help 139 139 Say yes here to support the Qualcomm Shared Memory Point to Point 140 140 protocol. ··· 144 142 tristate "Qualcomm Shared Memory State Machine" 145 143 depends on QCOM_SMEM 146 144 select QCOM_SMEM_STATE 145 + select IRQ_DOMAIN 147 146 help 148 147 Say yes here to support the Qualcomm Shared Memory State Machine. 149 148 The state machine is represented by bits in shared memory. 150 149 151 150 config QCOM_WCNSS_CTRL 152 151 tristate "Qualcomm WCNSS control driver" 153 - depends on ARCH_QCOM 152 + depends on ARCH_QCOM || COMPILE_TEST 154 153 depends on RPMSG 155 154 help 156 155 Client driver for the WCNSS_CTRL SMD channel, used to download nv ··· 159 156 160 157 config QCOM_APR 161 158 tristate "Qualcomm APR Bus (Asynchronous Packet Router)" 162 - depends on ARCH_QCOM 159 + depends on ARCH_QCOM || COMPILE_TEST 163 160 depends on RPMSG 164 161 help 165 162 Enable APR IPC protocol support between
+2 -2
drivers/soc/qcom/apr.c
··· 87 87 } 88 88 89 89 if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) { 90 - dev_err(apr->dev, "APR: Wrong paket size\n"); 90 + dev_err(apr->dev, "APR: Wrong packet size\n"); 91 91 return -EINVAL; 92 92 } 93 93 ··· 221 221 if (np) 222 222 snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np); 223 223 else 224 - strncpy(adev->name, id->name, APR_NAME_SIZE); 224 + strscpy(adev->name, id->name, APR_NAME_SIZE); 225 225 226 226 dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, 227 227 id->domain_id, id->svc_id);
+50 -24
drivers/soc/qcom/llcc-slice.c
··· 13 13 #include <linux/mutex.h> 14 14 #include <linux/of_device.h> 15 15 #include <linux/regmap.h> 16 + #include <linux/sizes.h> 16 17 #include <linux/slab.h> 17 18 #include <linux/soc/qcom/llcc-qcom.h> 18 19 ··· 107 106 u32 slice_status; 108 107 int ret; 109 108 110 - act_ctrl_reg = drv_data->bcast_off + LLCC_TRP_ACT_CTRLn(sid); 111 - status_reg = drv_data->bcast_off + LLCC_TRP_STATUSn(sid); 109 + act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid); 110 + status_reg = LLCC_TRP_STATUSn(sid); 112 111 113 112 /* Set the ACTIVE trigger */ 114 113 act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG; 115 - ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val); 114 + ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg, 115 + act_ctrl_reg_val); 116 116 if (ret) 117 117 return ret; 118 118 119 119 /* Clear the ACTIVE trigger */ 120 120 act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG; 121 - ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val); 121 + ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg, 122 + act_ctrl_reg_val); 122 123 if (ret) 123 124 return ret; 124 125 125 - ret = regmap_read_poll_timeout(drv_data->regmap, status_reg, 126 + ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg, 126 127 slice_status, !(slice_status & status), 127 128 0, LLCC_STATUS_READ_DELAY); 128 129 return ret; ··· 226 223 u32 attr0_val; 227 224 u32 max_cap_cacheline; 228 225 u32 sz; 229 - int ret; 226 + int ret = 0; 230 227 const struct llcc_slice_config *llcc_table; 231 228 struct llcc_slice_desc desc; 232 - u32 bcast_off = drv_data->bcast_off; 233 229 234 230 sz = drv_data->cfg_size; 235 231 llcc_table = drv_data->cfg; 236 232 237 233 for (i = 0; i < sz; i++) { 238 - attr1_cfg = bcast_off + 239 - LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id); 240 - attr0_cfg = bcast_off + 241 - LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id); 234 + attr1_cfg = LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id); 235 + attr0_cfg = LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id); 242 236 243 237 attr1_val = llcc_table[i].cache_mode; 244 238 attr1_val |= llcc_table[i].probe_target_ways << ··· 260 260 attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK; 261 261 attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT; 262 262 263 - ret = regmap_write(drv_data->regmap, attr1_cfg, attr1_val); 263 + ret = regmap_write(drv_data->bcast_regmap, attr1_cfg, 264 + attr1_val); 264 265 if (ret) 265 266 return ret; 266 - ret = regmap_write(drv_data->regmap, attr0_cfg, attr0_val); 267 + ret = regmap_write(drv_data->bcast_regmap, attr0_cfg, 268 + attr0_val); 267 269 if (ret) 268 270 return ret; 269 271 if (llcc_table[i].activate_on_init) { ··· 281 279 { 282 280 u32 num_banks; 283 281 struct device *dev = &pdev->dev; 284 - struct resource *res; 285 - void __iomem *base; 282 + struct resource *llcc_banks_res, *llcc_bcast_res; 283 + void __iomem *llcc_banks_base, *llcc_bcast_base; 286 284 int ret, i; 285 + struct platform_device *llcc_edac; 287 286 288 287 drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); 289 288 if (!drv_data) 290 289 return -ENOMEM; 291 290 292 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 293 - base = devm_ioremap_resource(&pdev->dev, res); 294 - if (IS_ERR(base)) 295 - return PTR_ERR(base); 291 + llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 292 + "llcc_base"); 293 + llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res); 294 + if (IS_ERR(llcc_banks_base)) 295 + return PTR_ERR(llcc_banks_base); 296 296 297 - drv_data->regmap = devm_regmap_init_mmio(dev, base, 298 - &llcc_regmap_config); 297 + drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base, 298 + &llcc_regmap_config); 299 299 if (IS_ERR(drv_data->regmap)) 300 300 return PTR_ERR(drv_data->regmap); 301 + 302 + llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 303 + "llcc_broadcast_base"); 304 + llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res); 305 + if (IS_ERR(llcc_bcast_base)) 306 + return PTR_ERR(llcc_bcast_base); 307 + 308 + drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base, 309 + &llcc_regmap_config); 310 + if (IS_ERR(drv_data->bcast_regmap)) 311 + return PTR_ERR(drv_data->bcast_regmap); 301 312 302 313 ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, 303 314 &num_banks); ··· 333 318 for (i = 0; i < num_banks; i++) 334 319 drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; 335 320 336 - drv_data->bcast_off = num_banks * BANK_OFFSET_STRIDE; 337 - 338 321 drv_data->bitmap = devm_kcalloc(dev, 339 322 BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), 340 323 GFP_KERNEL); ··· 344 331 mutex_init(&drv_data->lock); 345 332 platform_set_drvdata(pdev, drv_data); 346 333 347 - return qcom_llcc_cfg_program(pdev); 334 + ret = qcom_llcc_cfg_program(pdev); 335 + if (ret) 336 + return ret; 337 + 338 + drv_data->ecc_irq = platform_get_irq(pdev, 0); 339 + if (drv_data->ecc_irq >= 0) { 340 + llcc_edac = platform_device_register_data(&pdev->dev, 341 + "qcom_llcc_edac", -1, drv_data, 342 + sizeof(*drv_data)); 343 + if (IS_ERR(llcc_edac)) 344 + dev_err(dev, "Failed to register llcc edac driver\n"); 345 + } 346 + 347 + return ret; 348 348 } 349 349 EXPORT_SYMBOL_GPL(qcom_llcc_probe); 350 350
+5
drivers/soc/qcom/rmtfs_mem.c
··· 212 212 dev_err(&pdev->dev, "failed to parse qcom,vmid\n"); 213 213 goto remove_cdev; 214 214 } else if (!ret) { 215 + if (!qcom_scm_is_available()) { 216 + ret = -EPROBE_DEFER; 217 + goto remove_cdev; 218 + } 219 + 215 220 perms[0].vmid = QCOM_SCM_VMID_HLOS; 216 221 perms[0].perm = QCOM_SCM_PERM_RW; 217 222 perms[1].vmid = vmid;
+2
drivers/soc/qcom/rpmh-rsc.c
··· 121 121 return -EAGAIN; 122 122 } 123 123 write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0); 124 + write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, m, 0); 124 125 } 125 126 bitmap_zero(tcs->slots, MAX_TCS_SLOTS); 126 127 spin_unlock(&tcs->lock); ··· 240 239 skip: 241 240 /* Reclaim the TCS */ 242 241 write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0); 242 + write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, i, 0); 243 243 write_tcs_reg(drv, RSC_DRV_IRQ_CLEAR, 0, BIT(i)); 244 244 spin_lock(&drv->lock); 245 245 clear_bit(i, drv->tcs_in_use);
+83 -91
drivers/soc/qcom/smem.c
··· 18 18 #include <linux/of.h> 19 19 #include <linux/of_address.h> 20 20 #include <linux/platform_device.h> 21 + #include <linux/sizes.h> 21 22 #include <linux/slab.h> 22 23 #include <linux/soc/qcom/smem.h> 23 24 ··· 278 277 u32 item_count; 279 278 280 279 unsigned num_regions; 281 - struct smem_region regions[0]; 280 + struct smem_region regions[]; 282 281 }; 283 282 284 283 static void * ··· 490 489 size_t *size) 491 490 { 492 491 struct smem_header *header; 493 - struct smem_region *area; 492 + struct smem_region *region; 494 493 struct smem_global_entry *entry; 495 494 u32 aux_base; 496 495 unsigned i; ··· 503 502 aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK; 504 503 505 504 for (i = 0; i < smem->num_regions; i++) { 506 - area = &smem->regions[i]; 505 + region = &smem->regions[i]; 507 506 508 - if (area->aux_base == aux_base || !aux_base) { 507 + if (region->aux_base == aux_base || !aux_base) { 509 508 if (size != NULL) 510 509 *size = le32_to_cpu(entry->size); 511 - return area->virt_base + le32_to_cpu(entry->offset); 510 + return region->virt_base + le32_to_cpu(entry->offset); 512 511 } 513 512 } 514 513 ··· 723 722 return le16_to_cpu(info->num_items); 724 723 } 725 724 725 + /* 726 + * Validate the partition header for a partition whose partition 727 + * table entry is supplied. Returns a pointer to its header if 728 + * valid, or a null pointer otherwise. 729 + */ 730 + static struct smem_partition_header * 731 + qcom_smem_partition_header(struct qcom_smem *smem, 732 + struct smem_ptable_entry *entry, u16 host0, u16 host1) 733 + { 734 + struct smem_partition_header *header; 735 + u32 size; 736 + 737 + header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); 738 + 739 + if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) { 740 + dev_err(smem->dev, "bad partition magic %02x %02x %02x %02x\n", 741 + header->magic[0], header->magic[1], 742 + header->magic[2], header->magic[3]); 743 + return NULL; 744 + } 745 + 746 + if (host0 != le16_to_cpu(header->host0)) { 747 + dev_err(smem->dev, "bad host0 (%hu != %hu)\n", 748 + host0, le16_to_cpu(header->host0)); 749 + return NULL; 750 + } 751 + if (host1 != le16_to_cpu(header->host1)) { 752 + dev_err(smem->dev, "bad host1 (%hu != %hu)\n", 753 + host1, le16_to_cpu(header->host1)); 754 + return NULL; 755 + } 756 + 757 + size = le32_to_cpu(header->size); 758 + if (size != le32_to_cpu(entry->size)) { 759 + dev_err(smem->dev, "bad partition size (%u != %u)\n", 760 + size, le32_to_cpu(entry->size)); 761 + return NULL; 762 + } 763 + 764 + if (le32_to_cpu(header->offset_free_uncached) > size) { 765 + dev_err(smem->dev, "bad partition free uncached (%u > %u)\n", 766 + le32_to_cpu(header->offset_free_uncached), size); 767 + return NULL; 768 + } 769 + 770 + return header; 771 + } 772 + 726 773 static int qcom_smem_set_global_partition(struct qcom_smem *smem) 727 774 { 728 775 struct smem_partition_header *header; 729 776 struct smem_ptable_entry *entry; 730 777 struct smem_ptable *ptable; 731 - u32 host0, host1, size; 732 778 bool found = false; 733 779 int i; 734 780 ··· 790 742 791 743 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { 792 744 entry = &ptable->entry[i]; 793 - host0 = le16_to_cpu(entry->host0); 794 - host1 = le16_to_cpu(entry->host1); 745 + if (!le32_to_cpu(entry->offset)) 746 + continue; 747 + if (!le32_to_cpu(entry->size)) 748 + continue; 795 749 796 - if (host0 == SMEM_GLOBAL_HOST && host0 == host1) { 750 + if (le16_to_cpu(entry->host0) != SMEM_GLOBAL_HOST) 751 + continue; 752 + 753 + if (le16_to_cpu(entry->host1) == SMEM_GLOBAL_HOST) { 797 754 found = true; 798 755 break; 799 756 } ··· 809 756 return -EINVAL; 810 757 } 811 758 812 - if (!le32_to_cpu(entry->offset) || !le32_to_cpu(entry->size)) { 813 - dev_err(smem->dev, "Invalid entry for global partition\n"); 759 + header = qcom_smem_partition_header(smem, entry, 760 + SMEM_GLOBAL_HOST, SMEM_GLOBAL_HOST); 761 + if (!header) 814 762 return -EINVAL; 815 - } 816 - 817 - header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); 818 - host0 = le16_to_cpu(header->host0); 819 - host1 = le16_to_cpu(header->host1); 820 - 821 - if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) { 822 - dev_err(smem->dev, "Global partition has invalid magic\n"); 823 - return -EINVAL; 824 - } 825 - 826 - if (host0 != SMEM_GLOBAL_HOST && host1 != SMEM_GLOBAL_HOST) { 827 - dev_err(smem->dev, "Global partition hosts are invalid\n"); 828 - return -EINVAL; 829 - } 830 - 831 - if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) { 832 - dev_err(smem->dev, "Global partition has invalid size\n"); 833 - return -EINVAL; 834 - } 835 - 836 - size = le32_to_cpu(header->offset_free_uncached); 837 - if (size > le32_to_cpu(header->size)) { 838 - dev_err(smem->dev, 839 - "Global partition has invalid free pointer\n"); 840 - return -EINVAL; 841 - } 842 763 843 764 smem->global_partition = header; 844 765 smem->global_cacheline = le32_to_cpu(entry->cacheline); ··· 820 793 return 0; 821 794 } 822 795 823 - static int qcom_smem_enumerate_partitions(struct qcom_smem *smem, 824 - unsigned int local_host) 796 + static int 797 + qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host) 825 798 { 826 799 struct smem_partition_header *header; 827 800 struct smem_ptable_entry *entry; 828 801 struct smem_ptable *ptable; 829 802 unsigned int remote_host; 830 - u32 host0, host1; 803 + u16 host0, host1; 831 804 int i; 832 805 833 806 ptable = qcom_smem_get_ptable(smem); ··· 836 809 837 810 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { 838 811 entry = &ptable->entry[i]; 839 - host0 = le16_to_cpu(entry->host0); 840 - host1 = le16_to_cpu(entry->host1); 841 - 842 - if (host0 != local_host && host1 != local_host) 843 - continue; 844 - 845 812 if (!le32_to_cpu(entry->offset)) 846 813 continue; 847 - 848 814 if (!le32_to_cpu(entry->size)) 849 815 continue; 850 816 817 + host0 = le16_to_cpu(entry->host0); 818 + host1 = le16_to_cpu(entry->host1); 851 819 if (host0 == local_host) 852 820 remote_host = host1; 853 - else 821 + else if (host1 == local_host) 854 822 remote_host = host0; 823 + else 824 + continue; 855 825 856 826 if (remote_host >= SMEM_HOST_COUNT) { 857 - dev_err(smem->dev, 858 - "Invalid remote host %d\n", 859 - remote_host); 827 + dev_err(smem->dev, "bad host %hu\n", remote_host); 860 828 return -EINVAL; 861 829 } 862 830 863 831 if (smem->partitions[remote_host]) { 864 - dev_err(smem->dev, 865 - "Already found a partition for host %d\n", 866 - remote_host); 832 + dev_err(smem->dev, "duplicate host %hu\n", remote_host); 867 833 return -EINVAL; 868 834 } 869 835 870 - header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); 871 - host0 = le16_to_cpu(header->host0); 872 - host1 = le16_to_cpu(header->host1); 873 - 874 - if (memcmp(header->magic, SMEM_PART_MAGIC, 875 - sizeof(header->magic))) { 876 - dev_err(smem->dev, 877 - "Partition %d has invalid magic\n", i); 836 + header = qcom_smem_partition_header(smem, entry, host0, host1); 837 + if (!header) 878 838 return -EINVAL; 879 - } 880 - 881 - if (host0 != local_host && host1 != local_host) { 882 - dev_err(smem->dev, 883 - "Partition %d hosts are invalid\n", i); 884 - return -EINVAL; 885 - } 886 - 887 - if (host0 != remote_host && host1 != remote_host) { 888 - dev_err(smem->dev, 889 - "Partition %d hosts are invalid\n", i); 890 - return -EINVAL; 891 - } 892 - 893 - if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) { 894 - dev_err(smem->dev, 895 - "Partition %d has invalid size\n", i); 896 - return -EINVAL; 897 - } 898 - 899 - if (le32_to_cpu(header->offset_free_uncached) > le32_to_cpu(header->size)) { 900 - dev_err(smem->dev, 901 - "Partition %d has invalid free pointer\n", i); 902 - return -EINVAL; 903 - } 904 839 905 840 smem->partitions[remote_host] = header; 906 841 smem->cacheline[remote_host] = le32_to_cpu(entry->cacheline); ··· 876 887 { 877 888 struct device_node *np; 878 889 struct resource r; 890 + resource_size_t size; 879 891 int ret; 880 892 881 893 np = of_parse_phandle(dev->of_node, name, 0); ··· 889 899 of_node_put(np); 890 900 if (ret) 891 901 return ret; 902 + size = resource_size(&r); 892 903 893 - smem->regions[i].aux_base = (u32)r.start; 894 - smem->regions[i].size = resource_size(&r); 895 - smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, resource_size(&r)); 904 + smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, size); 896 905 if (!smem->regions[i].virt_base) 897 906 return -ENOMEM; 907 + smem->regions[i].aux_base = (u32)r.start; 908 + smem->regions[i].size = size; 898 909 899 910 return 0; 900 911 } ··· 953 962 return -EINVAL; 954 963 } 955 964 965 + BUILD_BUG_ON(SMEM_HOST_APPS >= SMEM_HOST_COUNT); 956 966 ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS); 957 967 if (ret < 0 && ret != -ENOENT) 958 968 return ret;
+3
drivers/soc/qcom/spm.c
··· 219 219 cpumask_t mask; 220 220 bool use_scm_power_down = false; 221 221 222 + if (!qcom_scm_is_available()) 223 + return -EPROBE_DEFER; 224 + 222 225 for (i = 0; ; i++) { 223 226 state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); 224 227 if (!state_node)
+1 -1
drivers/soc/qcom/wcnss_ctrl.c
··· 281 281 struct rpmsg_channel_info chinfo; 282 282 struct wcnss_ctrl *_wcnss = wcnss; 283 283 284 - strncpy(chinfo.name, name, sizeof(chinfo.name)); 284 + strscpy(chinfo.name, name, sizeof(chinfo.name)); 285 285 chinfo.src = RPMSG_ADDR_ANY; 286 286 chinfo.dst = RPMSG_ADDR_ANY; 287 287
+15 -4
drivers/soc/renesas/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 1 2 config SOC_RENESAS 2 3 bool "Renesas SoC driver support" if COMPILE_TEST && !ARCH_RENESAS 3 4 default y if ARCH_RENESAS 4 5 select SOC_BUS 5 6 select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || \ 6 - ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77965 || \ 7 - ARCH_R8A77970 || ARCH_R8A77980 || ARCH_R8A77990 || \ 8 - ARCH_R8A77995 9 - select SYSC_R8A7743 if ARCH_R8A7743 7 + ARCH_R8A774A1 || ARCH_R8A774C0 || ARCH_R8A7795 || \ 8 + ARCH_R8A7796 || ARCH_R8A77965 || ARCH_R8A77970 || \ 9 + ARCH_R8A77980 || ARCH_R8A77990 || ARCH_R8A77995 10 + select SYSC_R8A7743 if ARCH_R8A7743 || ARCH_R8A7744 10 11 select SYSC_R8A7745 if ARCH_R8A7745 11 12 select SYSC_R8A77470 if ARCH_R8A77470 13 + select SYSC_R8A774A1 if ARCH_R8A774A1 14 + select SYSC_R8A774C0 if ARCH_R8A774C0 12 15 select SYSC_R8A7779 if ARCH_R8A7779 13 16 select SYSC_R8A7790 if ARCH_R8A7790 14 17 select SYSC_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793 ··· 38 35 39 36 config SYSC_R8A77470 40 37 bool "RZ/G1C System Controller support" if COMPILE_TEST 38 + select SYSC_RCAR 39 + 40 + config SYSC_R8A774A1 41 + bool "RZ/G2M System Controller support" if COMPILE_TEST 42 + select SYSC_RCAR 43 + 44 + config SYSC_R8A774C0 45 + bool "RZ/G2E System Controller support" if COMPILE_TEST 41 46 select SYSC_RCAR 42 47 43 48 config SYSC_R8A7779
+2
drivers/soc/renesas/Makefile
··· 6 6 obj-$(CONFIG_SYSC_R8A7743) += r8a7743-sysc.o 7 7 obj-$(CONFIG_SYSC_R8A7745) += r8a7745-sysc.o 8 8 obj-$(CONFIG_SYSC_R8A77470) += r8a77470-sysc.o 9 + obj-$(CONFIG_SYSC_R8A774A1) += r8a774a1-sysc.o 10 + obj-$(CONFIG_SYSC_R8A774C0) += r8a774c0-sysc.o 9 11 obj-$(CONFIG_SYSC_R8A7779) += r8a7779-sysc.o 10 12 obj-$(CONFIG_SYSC_R8A7790) += r8a7790-sysc.o 11 13 obj-$(CONFIG_SYSC_R8A7791) += r8a7791-sysc.o
+1 -4
drivers/soc/renesas/r8a7743-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas RZ/G1M System Controller 3 4 * 4 5 * Copyright (C) 2016 Cogent Embedded Inc. 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License version 2 as 8 - * published by the Free Software Foundation; of the License. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+1 -4
drivers/soc/renesas/r8a7745-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas RZ/G1E System Controller 3 4 * 4 5 * Copyright (C) 2016 Cogent Embedded Inc. 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License version 2 as 8 - * published by the Free Software Foundation; of the License. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+45
drivers/soc/renesas/r8a774a1-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Renesas RZ/G2M System Controller 4 + * Copyright (C) 2018 Renesas Electronics Corp. 5 + * 6 + * Based on Renesas R-Car M3-W System Controller 7 + * Copyright (C) 2016 Glider bvba 8 + */ 9 + 10 + #include <linux/bug.h> 11 + #include <linux/kernel.h> 12 + 13 + #include <dt-bindings/power/r8a774a1-sysc.h> 14 + 15 + #include "rcar-sysc.h" 16 + 17 + static const struct rcar_sysc_area r8a774a1_areas[] __initconst = { 18 + { "always-on", 0, 0, R8A774A1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, 19 + { "ca57-scu", 0x1c0, 0, R8A774A1_PD_CA57_SCU, R8A774A1_PD_ALWAYS_ON, 20 + PD_SCU }, 21 + { "ca57-cpu0", 0x80, 0, R8A774A1_PD_CA57_CPU0, R8A774A1_PD_CA57_SCU, 22 + PD_CPU_NOCR }, 23 + { "ca57-cpu1", 0x80, 1, R8A774A1_PD_CA57_CPU1, R8A774A1_PD_CA57_SCU, 24 + PD_CPU_NOCR }, 25 + { "ca53-scu", 0x140, 0, R8A774A1_PD_CA53_SCU, R8A774A1_PD_ALWAYS_ON, 26 + PD_SCU }, 27 + { "ca53-cpu0", 0x200, 0, R8A774A1_PD_CA53_CPU0, R8A774A1_PD_CA53_SCU, 28 + PD_CPU_NOCR }, 29 + { "ca53-cpu1", 0x200, 1, R8A774A1_PD_CA53_CPU1, R8A774A1_PD_CA53_SCU, 30 + PD_CPU_NOCR }, 31 + { "ca53-cpu2", 0x200, 2, R8A774A1_PD_CA53_CPU2, R8A774A1_PD_CA53_SCU, 32 + PD_CPU_NOCR }, 33 + { "ca53-cpu3", 0x200, 3, R8A774A1_PD_CA53_CPU3, R8A774A1_PD_CA53_SCU, 34 + PD_CPU_NOCR }, 35 + { "a3vc", 0x380, 0, R8A774A1_PD_A3VC, R8A774A1_PD_ALWAYS_ON }, 36 + { "a2vc0", 0x3c0, 0, R8A774A1_PD_A2VC0, R8A774A1_PD_A3VC }, 37 + { "a2vc1", 0x3c0, 1, R8A774A1_PD_A2VC1, R8A774A1_PD_A3VC }, 38 + { "3dg-a", 0x100, 0, R8A774A1_PD_3DG_A, R8A774A1_PD_ALWAYS_ON }, 39 + { "3dg-b", 0x100, 1, R8A774A1_PD_3DG_B, R8A774A1_PD_3DG_A }, 40 + }; 41 + 42 + const struct rcar_sysc_info r8a774a1_sysc_info __initconst = { 43 + .areas = r8a774a1_areas, 44 + .num_areas = ARRAY_SIZE(r8a774a1_areas), 45 + };
+68
drivers/soc/renesas/r8a774c0-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Renesas RZ/G2E System Controller 4 + * Copyright (C) 2018 Renesas Electronics Corp. 5 + * 6 + * Based on Renesas R-Car E3 System Controller 7 + */ 8 + 9 + #include <linux/bug.h> 10 + #include <linux/kernel.h> 11 + #include <linux/sys_soc.h> 12 + 13 + #include <dt-bindings/power/r8a774c0-sysc.h> 14 + 15 + #include "rcar-sysc.h" 16 + 17 + static struct rcar_sysc_area r8a774c0_areas[] __initdata = { 18 + { "always-on", 0, 0, R8A774C0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, 19 + { "ca53-scu", 0x140, 0, R8A774C0_PD_CA53_SCU, R8A774C0_PD_ALWAYS_ON, 20 + PD_SCU }, 21 + { "ca53-cpu0", 0x200, 0, R8A774C0_PD_CA53_CPU0, R8A774C0_PD_CA53_SCU, 22 + PD_CPU_NOCR }, 23 + { "ca53-cpu1", 0x200, 1, R8A774C0_PD_CA53_CPU1, R8A774C0_PD_CA53_SCU, 24 + PD_CPU_NOCR }, 25 + { "a3vc", 0x380, 0, R8A774C0_PD_A3VC, R8A774C0_PD_ALWAYS_ON }, 26 + { "a2vc1", 0x3c0, 1, R8A774C0_PD_A2VC1, R8A774C0_PD_A3VC }, 27 + { "3dg-a", 0x100, 0, R8A774C0_PD_3DG_A, R8A774C0_PD_ALWAYS_ON }, 28 + { "3dg-b", 0x100, 1, R8A774C0_PD_3DG_B, R8A774C0_PD_3DG_A }, 29 + }; 30 + 31 + static void __init rcar_sysc_fix_parent(struct rcar_sysc_area *areas, 32 + unsigned int num_areas, u8 id, 33 + int new_parent) 34 + { 35 + unsigned int i; 36 + 37 + for (i = 0; i < num_areas; i++) 38 + if (areas[i].isr_bit == id) { 39 + areas[i].parent = new_parent; 40 + return; 41 + } 42 + } 43 + 44 + /* Fixups for RZ/G2E ES1.0 revision */ 45 + static const struct soc_device_attribute r8a774c0[] __initconst = { 46 + { .soc_id = "r8a774c0", .revision = "ES1.0" }, 47 + { /* sentinel */ } 48 + }; 49 + 50 + static int __init r8a774c0_sysc_init(void) 51 + { 52 + if (soc_device_match(r8a774c0)) { 53 + rcar_sysc_fix_parent(r8a774c0_areas, 54 + ARRAY_SIZE(r8a774c0_areas), 55 + R8A774C0_PD_3DG_A, R8A774C0_PD_3DG_B); 56 + rcar_sysc_fix_parent(r8a774c0_areas, 57 + ARRAY_SIZE(r8a774c0_areas), 58 + R8A774C0_PD_3DG_B, R8A774C0_PD_ALWAYS_ON); 59 + } 60 + 61 + return 0; 62 + } 63 + 64 + const struct rcar_sysc_info r8a774c0_sysc_info __initconst = { 65 + .init = r8a774c0_sysc_init, 66 + .areas = r8a774c0_areas, 67 + .num_areas = ARRAY_SIZE(r8a774c0_areas), 68 + };
+1 -4
drivers/soc/renesas/r8a7779-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas R-Car H1 System Controller 3 4 * 4 5 * Copyright (C) 2016 Glider bvba 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; version 2 of the License. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+1 -4
drivers/soc/renesas/r8a7790-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas R-Car H2 System Controller 3 4 * 4 5 * Copyright (C) 2016 Glider bvba 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; version 2 of the License. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+1 -4
drivers/soc/renesas/r8a7791-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas R-Car M2-W/N System Controller 3 4 * 4 5 * Copyright (C) 2016 Glider bvba 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; version 2 of the License. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+1 -4
drivers/soc/renesas/r8a7792-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas R-Car V2H (R8A7792) System Controller 3 4 * 4 5 * Copyright (C) 2016 Cogent Embedded Inc. 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; version 2 of the License. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+1 -4
drivers/soc/renesas/r8a7794-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas R-Car E2 System Controller 3 4 * 4 5 * Copyright (C) 2016 Glider bvba 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; version 2 of the License. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+1 -4
drivers/soc/renesas/r8a7795-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas R-Car H3 System Controller 3 4 * 4 5 * Copyright (C) 2016-2017 Glider bvba 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; version 2 of the License. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+1 -4
drivers/soc/renesas/r8a7796-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas R-Car M3-W System Controller 3 4 * 4 5 * Copyright (C) 2016 Glider bvba 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; version 2 of the License. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+1 -4
drivers/soc/renesas/r8a77970-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas R-Car V3M System Controller 3 4 * 4 5 * Copyright (C) 2017 Cogent Embedded Inc. 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License version 2 as 8 - * published by the Free Software Foundation. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+1 -4
drivers/soc/renesas/r8a77995-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas R-Car D3 System Controller 3 4 * 4 5 * Copyright (C) 2017 Glider bvba 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; version 2 of the License. 9 6 */ 10 7 11 8 #include <linux/bug.h>
+6 -5
drivers/soc/renesas/rcar-rst.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * R-Car Gen1 RESET/WDT, R-Car Gen2, Gen3, and RZ/G RST Driver 3 4 * 4 5 * Copyright (C) 2016 Glider bvba 5 - * 6 - * This file is subject to the terms and conditions of the GNU General Public 7 - * License. See the file "COPYING" in the main directory of this archive 8 - * for more details. 9 6 */ 10 7 11 8 #include <linux/err.h> ··· 38 41 }; 39 42 40 43 static const struct of_device_id rcar_rst_matches[] __initconst = { 41 - /* RZ/G is handled like R-Car Gen2 */ 44 + /* RZ/G1 is handled like R-Car Gen2 */ 42 45 { .compatible = "renesas,r8a7743-rst", .data = &rcar_rst_gen2 }, 46 + { .compatible = "renesas,r8a7744-rst", .data = &rcar_rst_gen2 }, 43 47 { .compatible = "renesas,r8a7745-rst", .data = &rcar_rst_gen2 }, 44 48 { .compatible = "renesas,r8a77470-rst", .data = &rcar_rst_gen2 }, 49 + /* RZ/G2 is handled like R-Car Gen3 */ 50 + { .compatible = "renesas,r8a774a1-rst", .data = &rcar_rst_gen3 }, 51 + { .compatible = "renesas,r8a774c0-rst", .data = &rcar_rst_gen3 }, 45 52 /* R-Car Gen1 */ 46 53 { .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 }, 47 54 { .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 },
+9 -4
drivers/soc/renesas/rcar-sysc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * R-Car SYSC Power management support 3 4 * 4 5 * Copyright (C) 2014 Magnus Damm 5 6 * Copyright (C) 2015-2017 Glider bvba 6 - * 7 - * This file is subject to the terms and conditions of the GNU General Public 8 - * License. See the file "COPYING" in the main directory of this archive 9 - * for more details. 10 7 */ 11 8 12 9 #include <linux/clk/renesas.h> ··· 265 268 static const struct of_device_id rcar_sysc_matches[] __initconst = { 266 269 #ifdef CONFIG_SYSC_R8A7743 267 270 { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info }, 271 + /* RZ/G1N is identical to RZ/G2M w.r.t. power domains. */ 272 + { .compatible = "renesas,r8a7744-sysc", .data = &r8a7743_sysc_info }, 268 273 #endif 269 274 #ifdef CONFIG_SYSC_R8A7745 270 275 { .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info }, 271 276 #endif 272 277 #ifdef CONFIG_SYSC_R8A77470 273 278 { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info }, 279 + #endif 280 + #ifdef CONFIG_SYSC_R8A774A1 281 + { .compatible = "renesas,r8a774a1-sysc", .data = &r8a774a1_sysc_info }, 282 + #endif 283 + #ifdef CONFIG_SYSC_R8A774C0 284 + { .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info }, 274 285 #endif 275 286 #ifdef CONFIG_SYSC_R8A7779 276 287 { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
+4 -5
drivers/soc/renesas/rcar-sysc.h
··· 1 - /* 1 + /* SPDX-License-Identifier: GPL-2.0 2 + * 2 3 * Renesas R-Car System Controller 3 4 * 4 5 * Copyright (C) 2016 Glider bvba 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; version 2 of the License. 9 6 */ 10 7 #ifndef __SOC_RENESAS_RCAR_SYSC_H__ 11 8 #define __SOC_RENESAS_RCAR_SYSC_H__ ··· 49 52 extern const struct rcar_sysc_info r8a7743_sysc_info; 50 53 extern const struct rcar_sysc_info r8a7745_sysc_info; 51 54 extern const struct rcar_sysc_info r8a77470_sysc_info; 55 + extern const struct rcar_sysc_info r8a774a1_sysc_info; 56 + extern const struct rcar_sysc_info r8a774c0_sysc_info; 52 57 extern const struct rcar_sysc_info r8a7779_sysc_info; 53 58 extern const struct rcar_sysc_info r8a7790_sysc_info; 54 59 extern const struct rcar_sysc_info r8a7791_sysc_info;
+76 -24
drivers/soc/renesas/renesas-soc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Renesas SoC Identification 3 4 * 4 5 * Copyright (C) 2014-2016 Glider bvba 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; version 2 of the License. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 6 */ 15 7 16 8 #include <linux/io.h> ··· 38 46 .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */ 39 47 }; 40 48 41 - static const struct renesas_family fam_rza __initconst __maybe_unused = { 42 - .name = "RZ/A", 49 + static const struct renesas_family fam_rza1 __initconst __maybe_unused = { 50 + .name = "RZ/A1", 43 51 }; 44 52 45 - static const struct renesas_family fam_rzg __initconst __maybe_unused = { 46 - .name = "RZ/G", 53 + static const struct renesas_family fam_rza2 __initconst __maybe_unused = { 54 + .name = "RZ/A2", 55 + }; 56 + 57 + static const struct renesas_family fam_rzg1 __initconst __maybe_unused = { 58 + .name = "RZ/G1", 47 59 .reg = 0xff000044, /* PRR (Product Register) */ 60 + }; 61 + 62 + static const struct renesas_family fam_rzg2 __initconst __maybe_unused = { 63 + .name = "RZ/G2", 64 + .reg = 0xfff00044, /* PRR (Product Register) */ 48 65 }; 49 66 50 67 static const struct renesas_family fam_shmobile __initconst __maybe_unused = { ··· 68 67 }; 69 68 70 69 static const struct renesas_soc soc_rz_a1h __initconst __maybe_unused = { 71 - .family = &fam_rza, 70 + .family = &fam_rza1, 71 + }; 72 + 73 + static const struct renesas_soc soc_rz_a2m __initconst __maybe_unused = { 74 + .family = &fam_rza2, 75 + .id = 0x3b, 72 76 }; 73 77 74 78 static const struct renesas_soc soc_rmobile_ape6 __initconst __maybe_unused = { ··· 87 81 }; 88 82 89 83 static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = { 90 - .family = &fam_rzg, 84 + .family = &fam_rzg1, 91 85 .id = 0x45, 92 86 }; 93 87 94 88 static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = { 95 - .family = &fam_rzg, 89 + .family = &fam_rzg1, 96 90 .id = 0x47, 97 91 }; 98 92 99 93 static const struct renesas_soc soc_rz_g1n __initconst __maybe_unused = { 100 - .family = &fam_rzg, 94 + .family = &fam_rzg1, 101 95 .id = 0x4b, 102 96 }; 103 97 104 98 static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = { 105 - .family = &fam_rzg, 99 + .family = &fam_rzg1, 106 100 .id = 0x4c, 107 101 }; 108 102 109 103 static const struct renesas_soc soc_rz_g1c __initconst __maybe_unused = { 110 - .family = &fam_rzg, 104 + .family = &fam_rzg1, 111 105 .id = 0x53, 106 + }; 107 + 108 + static const struct renesas_soc soc_rz_g2m __initconst __maybe_unused = { 109 + .family = &fam_rzg2, 110 + .id = 0x52, 111 + }; 112 + 113 + static const struct renesas_soc soc_rz_g2e __initconst __maybe_unused = { 114 + .family = &fam_rzg2, 115 + .id = 0x57, 112 116 }; 113 117 114 118 static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = { ··· 200 184 #ifdef CONFIG_ARCH_R7S72100 201 185 { .compatible = "renesas,r7s72100", .data = &soc_rz_a1h }, 202 186 #endif 187 + #ifdef CONFIG_ARCH_R7S9210 188 + { .compatible = "renesas,r7s9210", .data = &soc_rz_a2m }, 189 + #endif 203 190 #ifdef CONFIG_ARCH_R8A73A4 204 191 { .compatible = "renesas,r8a73a4", .data = &soc_rmobile_ape6 }, 205 192 #endif ··· 223 204 #endif 224 205 #ifdef CONFIG_ARCH_R8A77470 225 206 { .compatible = "renesas,r8a77470", .data = &soc_rz_g1c }, 207 + #endif 208 + #ifdef CONFIG_ARCH_R8A774A1 209 + { .compatible = "renesas,r8a774a1", .data = &soc_rz_g2m }, 210 + #endif 211 + #ifdef CONFIG_ARCH_R8A774C0 212 + { .compatible = "renesas,r8a774c0", .data = &soc_rz_g2e }, 226 213 #endif 227 214 #ifdef CONFIG_ARCH_R8A7778 228 215 { .compatible = "renesas,r8a7778", .data = &soc_rcar_m1a }, ··· 287 262 void __iomem *chipid = NULL; 288 263 struct soc_device *soc_dev; 289 264 struct device_node *np; 290 - unsigned int product; 265 + unsigned int product, eshi = 0, eslo; 291 266 292 267 match = of_match_node(renesas_socs, of_root); 293 268 if (!match) ··· 295 270 296 271 soc = match->data; 297 272 family = soc->family; 273 + 274 + np = of_find_compatible_node(NULL, NULL, "renesas,bsid"); 275 + if (np) { 276 + chipid = of_iomap(np, 0); 277 + of_node_put(np); 278 + 279 + if (chipid) { 280 + product = readl(chipid); 281 + iounmap(chipid); 282 + 283 + if (soc->id && ((product >> 16) & 0xff) != soc->id) { 284 + pr_warn("SoC mismatch (product = 0x%x)\n", 285 + product); 286 + return -ENODEV; 287 + } 288 + } 289 + 290 + /* 291 + * TODO: Upper 4 bits of BSID are for chip version, but the 292 + * format is not known at this time so we don't know how to 293 + * specify eshi and eslo 294 + */ 295 + 296 + goto done; 297 + } 298 298 299 299 /* Try PRR first, then hardcoded fallback */ 300 300 np = of_find_compatible_node(NULL, NULL, "renesas,prr"); ··· 339 289 pr_warn("SoC mismatch (product = 0x%x)\n", product); 340 290 return -ENODEV; 341 291 } 292 + eshi = ((product >> 4) & 0x0f) + 1; 293 + eslo = product & 0xf; 342 294 } 343 295 296 + done: 344 297 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 345 298 if (!soc_dev_attr) 346 299 return -ENOMEM; ··· 355 302 soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL); 356 303 soc_dev_attr->soc_id = kstrdup_const(strchr(match->compatible, ',') + 1, 357 304 GFP_KERNEL); 358 - if (chipid) 359 - soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", 360 - ((product >> 4) & 0x0f) + 1, 361 - product & 0xf); 305 + if (eshi) 306 + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", eshi, 307 + eslo); 362 308 363 309 pr_info("Detected Renesas %s %s %s\n", soc_dev_attr->family, 364 310 soc_dev_attr->soc_id, soc_dev_attr->revision ?: "");
+384 -129
drivers/soc/tegra/pmc.c
··· 33 33 #include <linux/of_address.h> 34 34 #include <linux/of_clk.h> 35 35 #include <linux/of_platform.h> 36 + #include <linux/pinctrl/pinctrl.h> 37 + #include <linux/pinctrl/pinconf.h> 38 + #include <linux/pinctrl/pinconf-generic.h> 36 39 #include <linux/platform_device.h> 37 40 #include <linux/pm_domain.h> 38 41 #include <linux/reboot.h> ··· 47 44 #include <soc/tegra/common.h> 48 45 #include <soc/tegra/fuse.h> 49 46 #include <soc/tegra/pmc.h> 47 + 48 + #include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h> 50 49 51 50 #define PMC_CNTRL 0x0 52 51 #define PMC_CNTRL_INTR_POLARITY BIT(17) /* inverts INTR polarity */ ··· 69 64 #define REMOVE_CLAMPING 0x34 70 65 71 66 #define PWRGATE_STATUS 0x38 67 + 68 + #define PMC_IMPL_E_33V_PWR 0x40 72 69 73 70 #define PMC_PWR_DET 0x48 74 71 ··· 142 135 enum tegra_io_pad id; 143 136 unsigned int dpd; 144 137 unsigned int voltage; 138 + const char *name; 145 139 }; 146 140 147 141 struct tegra_pmc_regs { ··· 162 154 bool has_tsense_reset; 163 155 bool has_gpu_clamps; 164 156 bool needs_mbist_war; 157 + bool has_impl_33v_pwr; 165 158 166 159 const struct tegra_io_pad_soc *io_pads; 167 160 unsigned int num_io_pads; 161 + 162 + const struct pinctrl_pin_desc *pin_descs; 163 + unsigned int num_pin_descs; 168 164 169 165 const struct tegra_pmc_regs *regs; 170 166 void (*init)(struct tegra_pmc *pmc); ··· 228 216 DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX); 229 217 230 218 struct mutex powergates_lock; 219 + 220 + struct pinctrl_dev *pctl_dev; 231 221 }; 232 222 233 223 static struct tegra_pmc *pmc = &(struct tegra_pmc) { ··· 933 919 return NULL; 934 920 } 935 921 936 - static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request, 937 - unsigned long *status, u32 *mask) 922 + static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id, 923 + unsigned long *request, 924 + unsigned long *status, 925 + u32 *mask) 938 926 { 939 927 const struct tegra_io_pad_soc *pad; 940 - unsigned long rate, value; 941 928 942 929 pad = tegra_io_pad_find(pmc, id); 943 930 if (!pad) { ··· 958 943 *status = pmc->soc->regs->dpd2_status; 959 944 *request = pmc->soc->regs->dpd2_req; 960 945 } 946 + 947 + return 0; 948 + } 949 + 950 + static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request, 951 + unsigned long *status, u32 *mask) 952 + { 953 + unsigned long rate, value; 954 + int err; 955 + 956 + err = tegra_io_pad_get_dpd_register_bit(id, request, status, mask); 957 + if (err) 958 + return err; 961 959 962 960 if (pmc->clk) { 963 961 rate = clk_get_rate(pmc->clk); ··· 1086 1058 } 1087 1059 EXPORT_SYMBOL(tegra_io_pad_power_disable); 1088 1060 1089 - int tegra_io_pad_set_voltage(enum tegra_io_pad id, 1090 - enum tegra_io_pad_voltage voltage) 1061 + static int tegra_io_pad_is_powered(enum tegra_io_pad id) 1062 + { 1063 + unsigned long request, status; 1064 + u32 mask, value; 1065 + int err; 1066 + 1067 + err = tegra_io_pad_get_dpd_register_bit(id, &request, &status, &mask); 1068 + if (err) 1069 + return err; 1070 + 1071 + value = tegra_pmc_readl(status); 1072 + 1073 + return !(value & mask); 1074 + } 1075 + 1076 + static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage) 1091 1077 { 1092 1078 const struct tegra_io_pad_soc *pad; 1093 1079 u32 value; ··· 1115 1073 1116 1074 mutex_lock(&pmc->powergates_lock); 1117 1075 1118 - /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */ 1119 - value = tegra_pmc_readl(PMC_PWR_DET); 1120 - value |= BIT(pad->voltage); 1121 - tegra_pmc_writel(value, PMC_PWR_DET); 1076 + if (pmc->soc->has_impl_33v_pwr) { 1077 + value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR); 1122 1078 1123 - /* update I/O voltage */ 1124 - value = tegra_pmc_readl(PMC_PWR_DET_VALUE); 1079 + if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) 1080 + value &= ~BIT(pad->voltage); 1081 + else 1082 + value |= BIT(pad->voltage); 1125 1083 1126 - if (voltage == TEGRA_IO_PAD_1800000UV) 1127 - value &= ~BIT(pad->voltage); 1128 - else 1084 + tegra_pmc_writel(value, PMC_IMPL_E_33V_PWR); 1085 + } else { 1086 + /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */ 1087 + value = tegra_pmc_readl(PMC_PWR_DET); 1129 1088 value |= BIT(pad->voltage); 1089 + tegra_pmc_writel(value, PMC_PWR_DET); 1130 1090 1131 - tegra_pmc_writel(value, PMC_PWR_DET_VALUE); 1091 + /* update I/O voltage */ 1092 + value = tegra_pmc_readl(PMC_PWR_DET_VALUE); 1093 + 1094 + if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) 1095 + value &= ~BIT(pad->voltage); 1096 + else 1097 + value |= BIT(pad->voltage); 1098 + 1099 + tegra_pmc_writel(value, PMC_PWR_DET_VALUE); 1100 + } 1132 1101 1133 1102 mutex_unlock(&pmc->powergates_lock); 1134 1103 ··· 1147 1094 1148 1095 return 0; 1149 1096 } 1150 - EXPORT_SYMBOL(tegra_io_pad_set_voltage); 1151 1097 1152 - int tegra_io_pad_get_voltage(enum tegra_io_pad id) 1098 + static int tegra_io_pad_get_voltage(enum tegra_io_pad id) 1153 1099 { 1154 1100 const struct tegra_io_pad_soc *pad; 1155 1101 u32 value; ··· 1160 1108 if (pad->voltage == UINT_MAX) 1161 1109 return -ENOTSUPP; 1162 1110 1163 - value = tegra_pmc_readl(PMC_PWR_DET_VALUE); 1111 + if (pmc->soc->has_impl_33v_pwr) 1112 + value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR); 1113 + else 1114 + value = tegra_pmc_readl(PMC_PWR_DET_VALUE); 1164 1115 1165 1116 if ((value & BIT(pad->voltage)) == 0) 1166 - return TEGRA_IO_PAD_1800000UV; 1117 + return TEGRA_IO_PAD_VOLTAGE_1V8; 1167 1118 1168 - return TEGRA_IO_PAD_3300000UV; 1119 + return TEGRA_IO_PAD_VOLTAGE_3V3; 1169 1120 } 1170 - EXPORT_SYMBOL(tegra_io_pad_get_voltage); 1171 1121 1172 1122 /** 1173 1123 * tegra_io_rail_power_on() - enable power to I/O rail ··· 1342 1288 if (!pmc->soc->has_tsense_reset) 1343 1289 return; 1344 1290 1345 - np = of_find_node_by_name(pmc->dev->of_node, "i2c-thermtrip"); 1291 + np = of_get_child_by_name(pmc->dev->of_node, "i2c-thermtrip"); 1346 1292 if (!np) { 1347 1293 dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled); 1348 1294 return; ··· 1405 1351 1406 1352 out: 1407 1353 of_node_put(np); 1354 + } 1355 + 1356 + static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev) 1357 + { 1358 + return pmc->soc->num_io_pads; 1359 + } 1360 + 1361 + static const char *tegra_io_pad_pinctrl_get_group_name( 1362 + struct pinctrl_dev *pctl, unsigned int group) 1363 + { 1364 + return pmc->soc->io_pads[group].name; 1365 + } 1366 + 1367 + static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev, 1368 + unsigned int group, 1369 + const unsigned int **pins, 1370 + unsigned int *num_pins) 1371 + { 1372 + *pins = &pmc->soc->io_pads[group].id; 1373 + *num_pins = 1; 1374 + return 0; 1375 + } 1376 + 1377 + static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = { 1378 + .get_groups_count = tegra_io_pad_pinctrl_get_groups_count, 1379 + .get_group_name = tegra_io_pad_pinctrl_get_group_name, 1380 + .get_group_pins = tegra_io_pad_pinctrl_get_group_pins, 1381 + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 1382 + .dt_free_map = pinconf_generic_dt_free_map, 1383 + }; 1384 + 1385 + static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev, 1386 + unsigned int pin, unsigned long *config) 1387 + { 1388 + const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin); 1389 + enum pin_config_param param = pinconf_to_config_param(*config); 1390 + int ret; 1391 + u32 arg; 1392 + 1393 + if (!pad) 1394 + return -EINVAL; 1395 + 1396 + switch (param) { 1397 + case PIN_CONFIG_POWER_SOURCE: 1398 + ret = tegra_io_pad_get_voltage(pad->id); 1399 + if (ret < 0) 1400 + return ret; 1401 + arg = ret; 1402 + break; 1403 + case PIN_CONFIG_LOW_POWER_MODE: 1404 + ret = tegra_io_pad_is_powered(pad->id); 1405 + if (ret < 0) 1406 + return ret; 1407 + arg = !ret; 1408 + break; 1409 + default: 1410 + return -EINVAL; 1411 + } 1412 + 1413 + *config = pinconf_to_config_packed(param, arg); 1414 + 1415 + return 0; 1416 + } 1417 + 1418 + static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev, 1419 + unsigned int pin, unsigned long *configs, 1420 + unsigned int num_configs) 1421 + { 1422 + const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin); 1423 + enum pin_config_param param; 1424 + unsigned int i; 1425 + int err; 1426 + u32 arg; 1427 + 1428 + if (!pad) 1429 + return -EINVAL; 1430 + 1431 + for (i = 0; i < num_configs; ++i) { 1432 + param = pinconf_to_config_param(configs[i]); 1433 + arg = pinconf_to_config_argument(configs[i]); 1434 + 1435 + switch (param) { 1436 + case PIN_CONFIG_LOW_POWER_MODE: 1437 + if (arg) 1438 + err = tegra_io_pad_power_disable(pad->id); 1439 + else 1440 + err = tegra_io_pad_power_enable(pad->id); 1441 + if (err) 1442 + return err; 1443 + break; 1444 + case PIN_CONFIG_POWER_SOURCE: 1445 + if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 && 1446 + arg != TEGRA_IO_PAD_VOLTAGE_3V3) 1447 + return -EINVAL; 1448 + err = tegra_io_pad_set_voltage(pad->id, arg); 1449 + if (err) 1450 + return err; 1451 + break; 1452 + default: 1453 + return -EINVAL; 1454 + } 1455 + } 1456 + 1457 + return 0; 1458 + } 1459 + 1460 + static const struct pinconf_ops tegra_io_pad_pinconf_ops = { 1461 + .pin_config_get = tegra_io_pad_pinconf_get, 1462 + .pin_config_set = tegra_io_pad_pinconf_set, 1463 + .is_generic = true, 1464 + }; 1465 + 1466 + static struct pinctrl_desc tegra_pmc_pctl_desc = { 1467 + .pctlops = &tegra_io_pad_pinctrl_ops, 1468 + .confops = &tegra_io_pad_pinconf_ops, 1469 + }; 1470 + 1471 + static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc) 1472 + { 1473 + int err = 0; 1474 + 1475 + if (!pmc->soc->num_pin_descs) 1476 + return 0; 1477 + 1478 + tegra_pmc_pctl_desc.name = dev_name(pmc->dev); 1479 + tegra_pmc_pctl_desc.pins = pmc->soc->pin_descs; 1480 + tegra_pmc_pctl_desc.npins = pmc->soc->num_pin_descs; 1481 + 1482 + pmc->pctl_dev = devm_pinctrl_register(pmc->dev, &tegra_pmc_pctl_desc, 1483 + pmc); 1484 + if (IS_ERR(pmc->pctl_dev)) { 1485 + err = PTR_ERR(pmc->pctl_dev); 1486 + dev_err(pmc->dev, "unable to register pinctrl, %d\n", err); 1487 + } 1488 + 1489 + return err; 1408 1490 } 1409 1491 1410 1492 static int tegra_pmc_probe(struct platform_device *pdev) ··· 1620 1430 1621 1431 err = register_restart_handler(&tegra_pmc_restart_handler); 1622 1432 if (err) { 1623 - debugfs_remove(pmc->debugfs); 1624 1433 dev_err(&pdev->dev, "unable to register restart handler, %d\n", 1625 1434 err); 1626 - return err; 1435 + goto cleanup_debugfs; 1627 1436 } 1437 + 1438 + err = tegra_pmc_pinctrl_init(pmc); 1439 + if (err) 1440 + goto cleanup_restart_handler; 1628 1441 1629 1442 mutex_lock(&pmc->powergates_lock); 1630 1443 iounmap(pmc->base); ··· 1635 1442 mutex_unlock(&pmc->powergates_lock); 1636 1443 1637 1444 return 0; 1445 + 1446 + cleanup_restart_handler: 1447 + unregister_restart_handler(&tegra_pmc_restart_handler); 1448 + cleanup_debugfs: 1449 + debugfs_remove(pmc->debugfs); 1450 + return err; 1638 1451 } 1639 1452 1640 1453 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) ··· 1730 1531 .has_gpu_clamps = false, 1731 1532 .num_io_pads = 0, 1732 1533 .io_pads = NULL, 1534 + .num_pin_descs = 0, 1535 + .pin_descs = NULL, 1733 1536 .regs = &tegra20_pmc_regs, 1734 1537 .init = tegra20_pmc_init, 1735 1538 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, ··· 1768 1567 .cpu_powergates = tegra30_cpu_powergates, 1769 1568 .has_tsense_reset = true, 1770 1569 .has_gpu_clamps = false, 1570 + .has_impl_33v_pwr = false, 1771 1571 .num_io_pads = 0, 1772 1572 .io_pads = NULL, 1573 + .num_pin_descs = 0, 1574 + .pin_descs = NULL, 1773 1575 .regs = &tegra20_pmc_regs, 1774 1576 .init = tegra20_pmc_init, 1775 1577 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, ··· 1813 1609 .cpu_powergates = tegra114_cpu_powergates, 1814 1610 .has_tsense_reset = true, 1815 1611 .has_gpu_clamps = false, 1612 + .has_impl_33v_pwr = false, 1816 1613 .num_io_pads = 0, 1817 1614 .io_pads = NULL, 1615 + .num_pin_descs = 0, 1616 + .pin_descs = NULL, 1818 1617 .regs = &tegra20_pmc_regs, 1819 1618 .init = tegra20_pmc_init, 1820 1619 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, ··· 1856 1649 TEGRA_POWERGATE_CPU3, 1857 1650 }; 1858 1651 1652 + #define TEGRA_IO_PAD(_id, _dpd, _voltage, _name) \ 1653 + ((struct tegra_io_pad_soc) { \ 1654 + .id = (_id), \ 1655 + .dpd = (_dpd), \ 1656 + .voltage = (_voltage), \ 1657 + .name = (_name), \ 1658 + }) 1659 + 1660 + #define TEGRA_IO_PIN_DESC(_id, _dpd, _voltage, _name) \ 1661 + ((struct pinctrl_pin_desc) { \ 1662 + .number = (_id), \ 1663 + .name = (_name) \ 1664 + }) 1665 + 1666 + #define TEGRA124_IO_PAD_TABLE(_pad) \ 1667 + /* .id .dpd .voltage .name */ \ 1668 + _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \ 1669 + _pad(TEGRA_IO_PAD_BB, 15, UINT_MAX, "bb"), \ 1670 + _pad(TEGRA_IO_PAD_CAM, 36, UINT_MAX, "cam"), \ 1671 + _pad(TEGRA_IO_PAD_COMP, 22, UINT_MAX, "comp"), \ 1672 + _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \ 1673 + _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csb"), \ 1674 + _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "cse"), \ 1675 + _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \ 1676 + _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \ 1677 + _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \ 1678 + _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \ 1679 + _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \ 1680 + _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \ 1681 + _pad(TEGRA_IO_PAD_HV, 38, UINT_MAX, "hv"), \ 1682 + _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \ 1683 + _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \ 1684 + _pad(TEGRA_IO_PAD_NAND, 13, UINT_MAX, "nand"), \ 1685 + _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \ 1686 + _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \ 1687 + _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \ 1688 + _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \ 1689 + _pad(TEGRA_IO_PAD_SDMMC1, 33, UINT_MAX, "sdmmc1"), \ 1690 + _pad(TEGRA_IO_PAD_SDMMC3, 34, UINT_MAX, "sdmmc3"), \ 1691 + _pad(TEGRA_IO_PAD_SDMMC4, 35, UINT_MAX, "sdmmc4"), \ 1692 + _pad(TEGRA_IO_PAD_SYS_DDC, 58, UINT_MAX, "sys_ddc"), \ 1693 + _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \ 1694 + _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \ 1695 + _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \ 1696 + _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \ 1697 + _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb_bias") 1698 + 1859 1699 static const struct tegra_io_pad_soc tegra124_io_pads[] = { 1860 - { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX }, 1861 - { .id = TEGRA_IO_PAD_BB, .dpd = 15, .voltage = UINT_MAX }, 1862 - { .id = TEGRA_IO_PAD_CAM, .dpd = 36, .voltage = UINT_MAX }, 1863 - { .id = TEGRA_IO_PAD_COMP, .dpd = 22, .voltage = UINT_MAX }, 1864 - { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX }, 1865 - { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX }, 1866 - { .id = TEGRA_IO_PAD_CSIE, .dpd = 44, .voltage = UINT_MAX }, 1867 - { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX }, 1868 - { .id = TEGRA_IO_PAD_DSIB, .dpd = 39, .voltage = UINT_MAX }, 1869 - { .id = TEGRA_IO_PAD_DSIC, .dpd = 40, .voltage = UINT_MAX }, 1870 - { .id = TEGRA_IO_PAD_DSID, .dpd = 41, .voltage = UINT_MAX }, 1871 - { .id = TEGRA_IO_PAD_HDMI, .dpd = 28, .voltage = UINT_MAX }, 1872 - { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX }, 1873 - { .id = TEGRA_IO_PAD_HV, .dpd = 38, .voltage = UINT_MAX }, 1874 - { .id = TEGRA_IO_PAD_LVDS, .dpd = 57, .voltage = UINT_MAX }, 1875 - { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX }, 1876 - { .id = TEGRA_IO_PAD_NAND, .dpd = 13, .voltage = UINT_MAX }, 1877 - { .id = TEGRA_IO_PAD_PEX_BIAS, .dpd = 4, .voltage = UINT_MAX }, 1878 - { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 5, .voltage = UINT_MAX }, 1879 - { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX }, 1880 - { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX }, 1881 - { .id = TEGRA_IO_PAD_SDMMC1, .dpd = 33, .voltage = UINT_MAX }, 1882 - { .id = TEGRA_IO_PAD_SDMMC3, .dpd = 34, .voltage = UINT_MAX }, 1883 - { .id = TEGRA_IO_PAD_SDMMC4, .dpd = 35, .voltage = UINT_MAX }, 1884 - { .id = TEGRA_IO_PAD_SYS_DDC, .dpd = 58, .voltage = UINT_MAX }, 1885 - { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = UINT_MAX }, 1886 - { .id = TEGRA_IO_PAD_USB0, .dpd = 9, .voltage = UINT_MAX }, 1887 - { .id = TEGRA_IO_PAD_USB1, .dpd = 10, .voltage = UINT_MAX }, 1888 - { .id = TEGRA_IO_PAD_USB2, .dpd = 11, .voltage = UINT_MAX }, 1889 - { .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX }, 1700 + TEGRA124_IO_PAD_TABLE(TEGRA_IO_PAD) 1701 + }; 1702 + 1703 + static const struct pinctrl_pin_desc tegra124_pin_descs[] = { 1704 + TEGRA124_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) 1890 1705 }; 1891 1706 1892 1707 static const struct tegra_pmc_soc tegra124_pmc_soc = { ··· 1918 1689 .cpu_powergates = tegra124_cpu_powergates, 1919 1690 .has_tsense_reset = true, 1920 1691 .has_gpu_clamps = true, 1692 + .has_impl_33v_pwr = false, 1921 1693 .num_io_pads = ARRAY_SIZE(tegra124_io_pads), 1922 1694 .io_pads = tegra124_io_pads, 1695 + .num_pin_descs = ARRAY_SIZE(tegra124_pin_descs), 1696 + .pin_descs = tegra124_pin_descs, 1923 1697 .regs = &tegra20_pmc_regs, 1924 1698 .init = tegra20_pmc_init, 1925 1699 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, ··· 1962 1730 TEGRA_POWERGATE_CPU3, 1963 1731 }; 1964 1732 1733 + #define TEGRA210_IO_PAD_TABLE(_pad) \ 1734 + /* .id .dpd .voltage .name */ \ 1735 + _pad(TEGRA_IO_PAD_AUDIO, 17, 5, "audio"), \ 1736 + _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 18, "audio-hv"), \ 1737 + _pad(TEGRA_IO_PAD_CAM, 36, 10, "cam"), \ 1738 + _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \ 1739 + _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \ 1740 + _pad(TEGRA_IO_PAD_CSIC, 42, UINT_MAX, "csic"), \ 1741 + _pad(TEGRA_IO_PAD_CSID, 43, UINT_MAX, "csid"), \ 1742 + _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "csie"), \ 1743 + _pad(TEGRA_IO_PAD_CSIF, 45, UINT_MAX, "csif"), \ 1744 + _pad(TEGRA_IO_PAD_DBG, 25, 19, "dbg"), \ 1745 + _pad(TEGRA_IO_PAD_DEBUG_NONAO, 26, UINT_MAX, "debug-nonao"), \ 1746 + _pad(TEGRA_IO_PAD_DMIC, 50, 20, "dmic"), \ 1747 + _pad(TEGRA_IO_PAD_DP, 51, UINT_MAX, "dp"), \ 1748 + _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \ 1749 + _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \ 1750 + _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \ 1751 + _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \ 1752 + _pad(TEGRA_IO_PAD_EMMC, 35, UINT_MAX, "emmc"), \ 1753 + _pad(TEGRA_IO_PAD_EMMC2, 37, UINT_MAX, "emmc2"), \ 1754 + _pad(TEGRA_IO_PAD_GPIO, 27, 21, "gpio"), \ 1755 + _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \ 1756 + _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \ 1757 + _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \ 1758 + _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \ 1759 + _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \ 1760 + _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \ 1761 + _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \ 1762 + _pad(TEGRA_IO_PAD_PEX_CNTRL, UINT_MAX, 11, "pex-cntrl"), \ 1763 + _pad(TEGRA_IO_PAD_SDMMC1, 33, 12, "sdmmc1"), \ 1764 + _pad(TEGRA_IO_PAD_SDMMC3, 34, 13, "sdmmc3"), \ 1765 + _pad(TEGRA_IO_PAD_SPI, 46, 22, "spi"), \ 1766 + _pad(TEGRA_IO_PAD_SPI_HV, 47, 23, "spi-hv"), \ 1767 + _pad(TEGRA_IO_PAD_UART, 14, 2, "uart"), \ 1768 + _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \ 1769 + _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \ 1770 + _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \ 1771 + _pad(TEGRA_IO_PAD_USB3, 18, UINT_MAX, "usb3"), \ 1772 + _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias") 1773 + 1965 1774 static const struct tegra_io_pad_soc tegra210_io_pads[] = { 1966 - { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = 5 }, 1967 - { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = 18 }, 1968 - { .id = TEGRA_IO_PAD_CAM, .dpd = 36, .voltage = 10 }, 1969 - { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX }, 1970 - { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX }, 1971 - { .id = TEGRA_IO_PAD_CSIC, .dpd = 42, .voltage = UINT_MAX }, 1972 - { .id = TEGRA_IO_PAD_CSID, .dpd = 43, .voltage = UINT_MAX }, 1973 - { .id = TEGRA_IO_PAD_CSIE, .dpd = 44, .voltage = UINT_MAX }, 1974 - { .id = TEGRA_IO_PAD_CSIF, .dpd = 45, .voltage = UINT_MAX }, 1975 - { .id = TEGRA_IO_PAD_DBG, .dpd = 25, .voltage = 19 }, 1976 - { .id = TEGRA_IO_PAD_DEBUG_NONAO, .dpd = 26, .voltage = UINT_MAX }, 1977 - { .id = TEGRA_IO_PAD_DMIC, .dpd = 50, .voltage = 20 }, 1978 - { .id = TEGRA_IO_PAD_DP, .dpd = 51, .voltage = UINT_MAX }, 1979 - { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX }, 1980 - { .id = TEGRA_IO_PAD_DSIB, .dpd = 39, .voltage = UINT_MAX }, 1981 - { .id = TEGRA_IO_PAD_DSIC, .dpd = 40, .voltage = UINT_MAX }, 1982 - { .id = TEGRA_IO_PAD_DSID, .dpd = 41, .voltage = UINT_MAX }, 1983 - { .id = TEGRA_IO_PAD_EMMC, .dpd = 35, .voltage = UINT_MAX }, 1984 - { .id = TEGRA_IO_PAD_EMMC2, .dpd = 37, .voltage = UINT_MAX }, 1985 - { .id = TEGRA_IO_PAD_GPIO, .dpd = 27, .voltage = 21 }, 1986 - { .id = TEGRA_IO_PAD_HDMI, .dpd = 28, .voltage = UINT_MAX }, 1987 - { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX }, 1988 - { .id = TEGRA_IO_PAD_LVDS, .dpd = 57, .voltage = UINT_MAX }, 1989 - { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX }, 1990 - { .id = TEGRA_IO_PAD_PEX_BIAS, .dpd = 4, .voltage = UINT_MAX }, 1991 - { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 5, .voltage = UINT_MAX }, 1992 - { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX }, 1993 - { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = UINT_MAX, .voltage = 11 }, 1994 - { .id = TEGRA_IO_PAD_SDMMC1, .dpd = 33, .voltage = 12 }, 1995 - { .id = TEGRA_IO_PAD_SDMMC3, .dpd = 34, .voltage = 13 }, 1996 - { .id = TEGRA_IO_PAD_SPI, .dpd = 46, .voltage = 22 }, 1997 - { .id = TEGRA_IO_PAD_SPI_HV, .dpd = 47, .voltage = 23 }, 1998 - { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = 2 }, 1999 - { .id = TEGRA_IO_PAD_USB0, .dpd = 9, .voltage = UINT_MAX }, 2000 - { .id = TEGRA_IO_PAD_USB1, .dpd = 10, .voltage = UINT_MAX }, 2001 - { .id = TEGRA_IO_PAD_USB2, .dpd = 11, .voltage = UINT_MAX }, 2002 - { .id = TEGRA_IO_PAD_USB3, .dpd = 18, .voltage = UINT_MAX }, 2003 - { .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX }, 1775 + TEGRA210_IO_PAD_TABLE(TEGRA_IO_PAD) 1776 + }; 1777 + 1778 + static const struct pinctrl_pin_desc tegra210_pin_descs[] = { 1779 + TEGRA210_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) 2004 1780 }; 2005 1781 2006 1782 static const struct tegra_pmc_soc tegra210_pmc_soc = { ··· 2018 1778 .cpu_powergates = tegra210_cpu_powergates, 2019 1779 .has_tsense_reset = true, 2020 1780 .has_gpu_clamps = true, 1781 + .has_impl_33v_pwr = false, 2021 1782 .needs_mbist_war = true, 2022 1783 .num_io_pads = ARRAY_SIZE(tegra210_io_pads), 2023 1784 .io_pads = tegra210_io_pads, 1785 + .num_pin_descs = ARRAY_SIZE(tegra210_pin_descs), 1786 + .pin_descs = tegra210_pin_descs, 2024 1787 .regs = &tegra20_pmc_regs, 2025 1788 .init = tegra20_pmc_init, 2026 1789 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, 2027 1790 }; 2028 1791 1792 + #define TEGRA186_IO_PAD_TABLE(_pad) \ 1793 + /* .id .dpd .voltage .name */ \ 1794 + _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \ 1795 + _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \ 1796 + _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \ 1797 + _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \ 1798 + _pad(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, UINT_MAX, "pex-clk-bias"), \ 1799 + _pad(TEGRA_IO_PAD_PEX_CLK3, 5, UINT_MAX, "pex-clk3"), \ 1800 + _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \ 1801 + _pad(TEGRA_IO_PAD_PEX_CLK1, 7, UINT_MAX, "pex-clk1"), \ 1802 + _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \ 1803 + _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \ 1804 + _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \ 1805 + _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias"), \ 1806 + _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \ 1807 + _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \ 1808 + _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \ 1809 + _pad(TEGRA_IO_PAD_DBG, 25, UINT_MAX, "dbg"), \ 1810 + _pad(TEGRA_IO_PAD_HDMI_DP0, 28, UINT_MAX, "hdmi-dp0"), \ 1811 + _pad(TEGRA_IO_PAD_HDMI_DP1, 29, UINT_MAX, "hdmi-dp1"), \ 1812 + _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \ 1813 + _pad(TEGRA_IO_PAD_SDMMC2_HV, 34, 5, "sdmmc2-hv"), \ 1814 + _pad(TEGRA_IO_PAD_SDMMC4, 36, UINT_MAX, "sdmmc4"), \ 1815 + _pad(TEGRA_IO_PAD_CAM, 38, UINT_MAX, "cam"), \ 1816 + _pad(TEGRA_IO_PAD_DSIB, 40, UINT_MAX, "dsib"), \ 1817 + _pad(TEGRA_IO_PAD_DSIC, 41, UINT_MAX, "dsic"), \ 1818 + _pad(TEGRA_IO_PAD_DSID, 42, UINT_MAX, "dsid"), \ 1819 + _pad(TEGRA_IO_PAD_CSIC, 43, UINT_MAX, "csic"), \ 1820 + _pad(TEGRA_IO_PAD_CSID, 44, UINT_MAX, "csid"), \ 1821 + _pad(TEGRA_IO_PAD_CSIE, 45, UINT_MAX, "csie"), \ 1822 + _pad(TEGRA_IO_PAD_CSIF, 46, UINT_MAX, "csif"), \ 1823 + _pad(TEGRA_IO_PAD_SPI, 47, UINT_MAX, "spi"), \ 1824 + _pad(TEGRA_IO_PAD_UFS, 49, UINT_MAX, "ufs"), \ 1825 + _pad(TEGRA_IO_PAD_DMIC_HV, 52, 2, "dmic-hv"), \ 1826 + _pad(TEGRA_IO_PAD_EDP, 53, UINT_MAX, "edp"), \ 1827 + _pad(TEGRA_IO_PAD_SDMMC1_HV, 55, 4, "sdmmc1-hv"), \ 1828 + _pad(TEGRA_IO_PAD_SDMMC3_HV, 56, 6, "sdmmc3-hv"), \ 1829 + _pad(TEGRA_IO_PAD_CONN, 60, UINT_MAX, "conn"), \ 1830 + _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 1, "audio-hv"), \ 1831 + _pad(TEGRA_IO_PAD_AO_HV, UINT_MAX, 0, "ao-hv") 1832 + 2029 1833 static const struct tegra_io_pad_soc tegra186_io_pads[] = { 2030 - { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX }, 2031 - { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX }, 2032 - { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX }, 2033 - { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX }, 2034 - { .id = TEGRA_IO_PAD_PEX_CLK_BIAS, .dpd = 4, .voltage = UINT_MAX }, 2035 - { .id = TEGRA_IO_PAD_PEX_CLK3, .dpd = 5, .voltage = UINT_MAX }, 2036 - { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX }, 2037 - { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 7, .voltage = UINT_MAX }, 2038 - { .id = TEGRA_IO_PAD_USB0, .dpd = 9, .voltage = UINT_MAX }, 2039 - { .id = TEGRA_IO_PAD_USB1, .dpd = 10, .voltage = UINT_MAX }, 2040 - { .id = TEGRA_IO_PAD_USB2, .dpd = 11, .voltage = UINT_MAX }, 2041 - { .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX }, 2042 - { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = UINT_MAX }, 2043 - { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX }, 2044 - { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX }, 2045 - { .id = TEGRA_IO_PAD_DBG, .dpd = 25, .voltage = UINT_MAX }, 2046 - { .id = TEGRA_IO_PAD_HDMI_DP0, .dpd = 28, .voltage = UINT_MAX }, 2047 - { .id = TEGRA_IO_PAD_HDMI_DP1, .dpd = 29, .voltage = UINT_MAX }, 2048 - { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX }, 2049 - { .id = TEGRA_IO_PAD_SDMMC2_HV, .dpd = 34, .voltage = UINT_MAX }, 2050 - { .id = TEGRA_IO_PAD_SDMMC4, .dpd = 36, .voltage = UINT_MAX }, 2051 - { .id = TEGRA_IO_PAD_CAM, .dpd = 38, .voltage = UINT_MAX }, 2052 - { .id = TEGRA_IO_PAD_DSIB, .dpd = 40, .voltage = UINT_MAX }, 2053 - { .id = TEGRA_IO_PAD_DSIC, .dpd = 41, .voltage = UINT_MAX }, 2054 - { .id = TEGRA_IO_PAD_DSID, .dpd = 42, .voltage = UINT_MAX }, 2055 - { .id = TEGRA_IO_PAD_CSIC, .dpd = 43, .voltage = UINT_MAX }, 2056 - { .id = TEGRA_IO_PAD_CSID, .dpd = 44, .voltage = UINT_MAX }, 2057 - { .id = TEGRA_IO_PAD_CSIE, .dpd = 45, .voltage = UINT_MAX }, 2058 - { .id = TEGRA_IO_PAD_CSIF, .dpd = 46, .voltage = UINT_MAX }, 2059 - { .id = TEGRA_IO_PAD_SPI, .dpd = 47, .voltage = UINT_MAX }, 2060 - { .id = TEGRA_IO_PAD_UFS, .dpd = 49, .voltage = UINT_MAX }, 2061 - { .id = TEGRA_IO_PAD_DMIC_HV, .dpd = 52, .voltage = UINT_MAX }, 2062 - { .id = TEGRA_IO_PAD_EDP, .dpd = 53, .voltage = UINT_MAX }, 2063 - { .id = TEGRA_IO_PAD_SDMMC1_HV, .dpd = 55, .voltage = UINT_MAX }, 2064 - { .id = TEGRA_IO_PAD_SDMMC3_HV, .dpd = 56, .voltage = UINT_MAX }, 2065 - { .id = TEGRA_IO_PAD_CONN, .dpd = 60, .voltage = UINT_MAX }, 2066 - { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = UINT_MAX }, 1834 + TEGRA186_IO_PAD_TABLE(TEGRA_IO_PAD) 1835 + }; 1836 + 1837 + static const struct pinctrl_pin_desc tegra186_pin_descs[] = { 1838 + TEGRA186_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) 2067 1839 }; 2068 1840 2069 1841 static const struct tegra_pmc_regs tegra186_pmc_regs = { ··· 2128 1876 .cpu_powergates = NULL, 2129 1877 .has_tsense_reset = false, 2130 1878 .has_gpu_clamps = false, 1879 + .has_impl_33v_pwr = true, 2131 1880 .num_io_pads = ARRAY_SIZE(tegra186_io_pads), 2132 1881 .io_pads = tegra186_io_pads, 1882 + .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs), 1883 + .pin_descs = tegra186_pin_descs, 2133 1884 .regs = &tegra186_pmc_regs, 2134 1885 .init = NULL, 2135 1886 .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
+2 -2
drivers/soc/ti/knav_dma.c
··· 438 438 439 439 chan_num = of_channel_match_helper(dev->of_node, name, &instance); 440 440 if (chan_num < 0) { 441 - dev_err(kdev->dev, "No DMA instace with name %s\n", name); 441 + dev_err(kdev->dev, "No DMA instance with name %s\n", name); 442 442 return (void *)-EINVAL; 443 443 } 444 444 ··· 461 461 } 462 462 } 463 463 if (!found) { 464 - dev_err(kdev->dev, "No DMA instace with name %s\n", instance); 464 + dev_err(kdev->dev, "No DMA instance with name %s\n", instance); 465 465 return (void *)-EINVAL; 466 466 } 467 467
+3 -3
drivers/soc/ti/knav_qmss.h
··· 240 240 }; 241 241 242 242 /** 243 - * struct knav_queue_inst: qmss queue instace properties 243 + * struct knav_queue_inst: qmss queue instance properties 244 244 * @descs: descriptor pointer 245 245 * @desc_head, desc_tail, desc_count: descriptor counters 246 246 * @acc: accumulator channel pointer 247 247 * @kdev: qmss device pointer 248 248 * @range: range info 249 249 * @qmgr: queue manager info 250 - * @id: queue instace id 250 + * @id: queue instance id 251 251 * @irq_num: irq line number 252 252 * @notify_needed: notifier needed based on queue type 253 253 * @num_notifiers: total notifiers ··· 274 274 /** 275 275 * struct knav_queue: qmss queue properties 276 276 * @reg_push, reg_pop, reg_peek: push, pop queue registers 277 - * @inst: qmss queue instace properties 277 + * @inst: qmss queue instance properties 278 278 * @notifier_fn: notifier function 279 279 * @notifier_fn_arg: notifier function argument 280 280 * @notifier_enabled: notier enabled for a give queue
+1 -1
drivers/tee/optee/core.c
··· 696 696 return -ENODEV; 697 697 698 698 np = of_find_matching_node(fw_np, optee_match); 699 - if (!np) 699 + if (!np || !of_device_is_available(np)) 700 700 return -ENODEV; 701 701 702 702 optee = optee_probe(np);
+106 -7
drivers/tee/tee_core.c
··· 38 38 static struct class *tee_class; 39 39 static dev_t tee_devt; 40 40 41 - static int tee_open(struct inode *inode, struct file *filp) 41 + static struct tee_context *teedev_open(struct tee_device *teedev) 42 42 { 43 43 int rc; 44 - struct tee_device *teedev; 45 44 struct tee_context *ctx; 46 45 47 - teedev = container_of(inode->i_cdev, struct tee_device, cdev); 48 46 if (!tee_device_get(teedev)) 49 - return -EINVAL; 47 + return ERR_PTR(-EINVAL); 50 48 51 49 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 52 50 if (!ctx) { ··· 55 57 kref_init(&ctx->refcount); 56 58 ctx->teedev = teedev; 57 59 INIT_LIST_HEAD(&ctx->list_shm); 58 - filp->private_data = ctx; 59 60 rc = teedev->desc->ops->open(ctx); 60 61 if (rc) 61 62 goto err; 62 63 63 - return 0; 64 + return ctx; 64 65 err: 65 66 kfree(ctx); 66 67 tee_device_put(teedev); 67 - return rc; 68 + return ERR_PTR(rc); 69 + 68 70 } 69 71 70 72 void teedev_ctx_get(struct tee_context *ctx) ··· 96 98 { 97 99 tee_device_put(ctx->teedev); 98 100 teedev_ctx_put(ctx); 101 + } 102 + 103 + static int tee_open(struct inode *inode, struct file *filp) 104 + { 105 + struct tee_context *ctx; 106 + 107 + ctx = teedev_open(container_of(inode->i_cdev, struct tee_device, cdev)); 108 + if (IS_ERR(ctx)) 109 + return PTR_ERR(ctx); 110 + 111 + filp->private_data = ctx; 112 + return 0; 99 113 } 100 114 101 115 static int tee_release(struct inode *inode, struct file *filp) ··· 937 927 return dev_get_drvdata(&teedev->dev); 938 928 } 939 929 EXPORT_SYMBOL_GPL(tee_get_drvdata); 930 + 931 + struct match_dev_data { 932 + struct tee_ioctl_version_data *vers; 933 + const void *data; 934 + int (*match)(struct tee_ioctl_version_data *, const void *); 935 + }; 936 + 937 + static int match_dev(struct device *dev, const void *data) 938 + { 939 + const struct match_dev_data *match_data = data; 940 + struct tee_device *teedev = container_of(dev, struct tee_device, dev); 941 + 942 + teedev->desc->ops->get_version(teedev, match_data->vers); 943 + return match_data->match(match_data->vers, match_data->data); 944 + } 945 + 946 + struct tee_context * 947 + tee_client_open_context(struct tee_context *start, 948 + int (*match)(struct tee_ioctl_version_data *, 949 + const void *), 950 + const void *data, struct tee_ioctl_version_data *vers) 951 + { 952 + struct device *dev = NULL; 953 + struct device *put_dev = NULL; 954 + struct tee_context *ctx = NULL; 955 + struct tee_ioctl_version_data v; 956 + struct match_dev_data match_data = { vers ? vers : &v, data, match }; 957 + 958 + if (start) 959 + dev = &start->teedev->dev; 960 + 961 + do { 962 + dev = class_find_device(tee_class, dev, &match_data, match_dev); 963 + if (!dev) { 964 + ctx = ERR_PTR(-ENOENT); 965 + break; 966 + } 967 + 968 + put_device(put_dev); 969 + put_dev = dev; 970 + 971 + ctx = teedev_open(container_of(dev, struct tee_device, dev)); 972 + } while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM); 973 + 974 + put_device(put_dev); 975 + return ctx; 976 + } 977 + EXPORT_SYMBOL_GPL(tee_client_open_context); 978 + 979 + void tee_client_close_context(struct tee_context *ctx) 980 + { 981 + teedev_close_context(ctx); 982 + } 983 + EXPORT_SYMBOL_GPL(tee_client_close_context); 984 + 985 + void tee_client_get_version(struct tee_context *ctx, 986 + struct tee_ioctl_version_data *vers) 987 + { 988 + ctx->teedev->desc->ops->get_version(ctx->teedev, vers); 989 + } 990 + EXPORT_SYMBOL_GPL(tee_client_get_version); 991 + 992 + int tee_client_open_session(struct tee_context *ctx, 993 + struct tee_ioctl_open_session_arg *arg, 994 + struct tee_param *param) 995 + { 996 + if (!ctx->teedev->desc->ops->open_session) 997 + return -EINVAL; 998 + return ctx->teedev->desc->ops->open_session(ctx, arg, param); 999 + } 1000 + EXPORT_SYMBOL_GPL(tee_client_open_session); 1001 + 1002 + int tee_client_close_session(struct tee_context *ctx, u32 session) 1003 + { 1004 + if (!ctx->teedev->desc->ops->close_session) 1005 + return -EINVAL; 1006 + return ctx->teedev->desc->ops->close_session(ctx, session); 1007 + } 1008 + EXPORT_SYMBOL_GPL(tee_client_close_session); 1009 + 1010 + int tee_client_invoke_func(struct tee_context *ctx, 1011 + struct tee_ioctl_invoke_arg *arg, 1012 + struct tee_param *param) 1013 + { 1014 + if (!ctx->teedev->desc->ops->invoke_func) 1015 + return -EINVAL; 1016 + return ctx->teedev->desc->ops->invoke_func(ctx, arg, param); 1017 + } 1018 + EXPORT_SYMBOL_GPL(tee_client_invoke_func); 940 1019 941 1020 static int __init tee_init(void) 942 1021 {
+116
include/dt-bindings/clock/xlnx,zynqmp-clk.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Xilinx Zynq MPSoC Firmware layer 4 + * 5 + * Copyright (C) 2014-2018 Xilinx, Inc. 6 + * 7 + */ 8 + 9 + #ifndef _DT_BINDINGS_CLK_ZYNQMP_H 10 + #define _DT_BINDINGS_CLK_ZYNQMP_H 11 + 12 + #define IOPLL 0 13 + #define RPLL 1 14 + #define APLL 2 15 + #define DPLL 3 16 + #define VPLL 4 17 + #define IOPLL_TO_FPD 5 18 + #define RPLL_TO_FPD 6 19 + #define APLL_TO_LPD 7 20 + #define DPLL_TO_LPD 8 21 + #define VPLL_TO_LPD 9 22 + #define ACPU 10 23 + #define ACPU_HALF 11 24 + #define DBF_FPD 12 25 + #define DBF_LPD 13 26 + #define DBG_TRACE 14 27 + #define DBG_TSTMP 15 28 + #define DP_VIDEO_REF 16 29 + #define DP_AUDIO_REF 17 30 + #define DP_STC_REF 18 31 + #define GDMA_REF 19 32 + #define DPDMA_REF 20 33 + #define DDR_REF 21 34 + #define SATA_REF 22 35 + #define PCIE_REF 23 36 + #define GPU_REF 24 37 + #define GPU_PP0_REF 25 38 + #define GPU_PP1_REF 26 39 + #define TOPSW_MAIN 27 40 + #define TOPSW_LSBUS 28 41 + #define GTGREF0_REF 29 42 + #define LPD_SWITCH 30 43 + #define LPD_LSBUS 31 44 + #define USB0_BUS_REF 32 45 + #define USB1_BUS_REF 33 46 + #define USB3_DUAL_REF 34 47 + #define USB0 35 48 + #define USB1 36 49 + #define CPU_R5 37 50 + #define CPU_R5_CORE 38 51 + #define CSU_SPB 39 52 + #define CSU_PLL 40 53 + #define PCAP 41 54 + #define IOU_SWITCH 42 55 + #define GEM_TSU_REF 43 56 + #define GEM_TSU 44 57 + #define GEM0_REF 45 58 + #define GEM1_REF 46 59 + #define GEM2_REF 47 60 + #define GEM3_REF 48 61 + #define GEM0_TX 49 62 + #define GEM1_TX 50 63 + #define GEM2_TX 51 64 + #define GEM3_TX 52 65 + #define QSPI_REF 53 66 + #define SDIO0_REF 54 67 + #define SDIO1_REF 55 68 + #define UART0_REF 56 69 + #define UART1_REF 57 70 + #define SPI0_REF 58 71 + #define SPI1_REF 59 72 + #define NAND_REF 60 73 + #define I2C0_REF 61 74 + #define I2C1_REF 62 75 + #define CAN0_REF 63 76 + #define CAN1_REF 64 77 + #define CAN0 65 78 + #define CAN1 66 79 + #define DLL_REF 67 80 + #define ADMA_REF 68 81 + #define TIMESTAMP_REF 69 82 + #define AMS_REF 70 83 + #define PL0_REF 71 84 + #define PL1_REF 72 85 + #define PL2_REF 73 86 + #define PL3_REF 74 87 + #define WDT 75 88 + #define IOPLL_INT 76 89 + #define IOPLL_PRE_SRC 77 90 + #define IOPLL_HALF 78 91 + #define IOPLL_INT_MUX 79 92 + #define IOPLL_POST_SRC 80 93 + #define RPLL_INT 81 94 + #define RPLL_PRE_SRC 82 95 + #define RPLL_HALF 83 96 + #define RPLL_INT_MUX 84 97 + #define RPLL_POST_SRC 85 98 + #define APLL_INT 86 99 + #define APLL_PRE_SRC 87 100 + #define APLL_HALF 88 101 + #define APLL_INT_MUX 89 102 + #define APLL_POST_SRC 90 103 + #define DPLL_INT 91 104 + #define DPLL_PRE_SRC 92 105 + #define DPLL_HALF 93 106 + #define DPLL_INT_MUX 94 107 + #define DPLL_POST_SRC 95 108 + #define VPLL_INT 96 109 + #define VPLL_PRE_SRC 97 110 + #define VPLL_HALF 98 111 + #define VPLL_INT_MUX 99 112 + #define VPLL_POST_SRC 100 113 + #define CAN0_MIO 101 114 + #define CAN1_MIO 102 115 + 116 + #endif
+24
include/dt-bindings/power/r8a7744-sysc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 2 + * 3 + * Copyright (C) 2018 Renesas Electronics Corp. 4 + */ 5 + #ifndef __DT_BINDINGS_POWER_R8A7744_SYSC_H__ 6 + #define __DT_BINDINGS_POWER_R8A7744_SYSC_H__ 7 + 8 + /* 9 + * These power domain indices match the numbers of the interrupt bits 10 + * representing the power areas in the various Interrupt Registers 11 + * (e.g. SYSCISR, Interrupt Status Register) 12 + * 13 + * Note that RZ/G1N is identical to RZ/G2M w.r.t. power domains. 14 + */ 15 + 16 + #define R8A7744_PD_CA15_CPU0 0 17 + #define R8A7744_PD_CA15_CPU1 1 18 + #define R8A7744_PD_CA15_SCU 12 19 + #define R8A7744_PD_SGX 20 20 + 21 + /* Always-on power area */ 22 + #define R8A7744_PD_ALWAYS_ON 32 23 + 24 + #endif /* __DT_BINDINGS_POWER_R8A7744_SYSC_H__ */
+31
include/dt-bindings/power/r8a774a1-sysc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 2 + * 3 + * Copyright (C) 2018 Renesas Electronics Corp. 4 + */ 5 + #ifndef __DT_BINDINGS_POWER_R8A774A1_SYSC_H__ 6 + #define __DT_BINDINGS_POWER_R8A774A1_SYSC_H__ 7 + 8 + /* 9 + * These power domain indices match the numbers of the interrupt bits 10 + * representing the power areas in the various Interrupt Registers 11 + * (e.g. SYSCISR, Interrupt Status Register) 12 + */ 13 + 14 + #define R8A774A1_PD_CA57_CPU0 0 15 + #define R8A774A1_PD_CA57_CPU1 1 16 + #define R8A774A1_PD_CA53_CPU0 5 17 + #define R8A774A1_PD_CA53_CPU1 6 18 + #define R8A774A1_PD_CA53_CPU2 7 19 + #define R8A774A1_PD_CA53_CPU3 8 20 + #define R8A774A1_PD_CA57_SCU 12 21 + #define R8A774A1_PD_A3VC 14 22 + #define R8A774A1_PD_3DG_A 17 23 + #define R8A774A1_PD_3DG_B 18 24 + #define R8A774A1_PD_CA53_SCU 21 25 + #define R8A774A1_PD_A2VC0 25 26 + #define R8A774A1_PD_A2VC1 26 27 + 28 + /* Always-on power area */ 29 + #define R8A774A1_PD_ALWAYS_ON 32 30 + 31 + #endif /* __DT_BINDINGS_POWER_R8A774A1_SYSC_H__ */
+25
include/dt-bindings/power/r8a774c0-sysc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 2 + * 3 + * Copyright (C) 2018 Renesas Electronics Corp. 4 + */ 5 + #ifndef __DT_BINDINGS_POWER_R8A774C0_SYSC_H__ 6 + #define __DT_BINDINGS_POWER_R8A774C0_SYSC_H__ 7 + 8 + /* 9 + * These power domain indices match the numbers of the interrupt bits 10 + * representing the power areas in the various Interrupt Registers 11 + * (e.g. SYSCISR, Interrupt Status Register) 12 + */ 13 + 14 + #define R8A774C0_PD_CA53_CPU0 5 15 + #define R8A774C0_PD_CA53_CPU1 6 16 + #define R8A774C0_PD_A3VC 14 17 + #define R8A774C0_PD_3DG_A 17 18 + #define R8A774C0_PD_3DG_B 18 19 + #define R8A774C0_PD_CA53_SCU 21 20 + #define R8A774C0_PD_A2VC1 26 21 + 22 + /* Always-on power area */ 23 + #define R8A774C0_PD_ALWAYS_ON 32 24 + 25 + #endif /* __DT_BINDINGS_POWER_R8A774C0_SYSC_H__ */
+20
include/dt-bindings/reset/qcom,sdm845-pdc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2018 The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #ifndef _DT_BINDINGS_RESET_PDC_SDM_845_H 7 + #define _DT_BINDINGS_RESET_PDC_SDM_845_H 8 + 9 + #define PDC_APPS_SYNC_RESET 0 10 + #define PDC_SP_SYNC_RESET 1 11 + #define PDC_AUDIO_SYNC_RESET 2 12 + #define PDC_SENSORS_SYNC_RESET 3 13 + #define PDC_AOP_SYNC_RESET 4 14 + #define PDC_DEBUG_SYNC_RESET 5 15 + #define PDC_GPU_SYNC_RESET 6 16 + #define PDC_DISPLAY_SYNC_RESET 7 17 + #define PDC_COMPUTE_SYNC_RESET 8 18 + #define PDC_MODEM_SYNC_RESET 9 19 + 20 + #endif
+59
include/linux/firmware/imx/ipc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Copyright 2018 NXP 4 + * 5 + * Header file for the IPC implementation. 6 + */ 7 + 8 + #ifndef _SC_IPC_H 9 + #define _SC_IPC_H 10 + 11 + #include <linux/device.h> 12 + #include <linux/types.h> 13 + 14 + #define IMX_SC_RPC_VERSION 1 15 + #define IMX_SC_RPC_MAX_MSG 8 16 + 17 + struct imx_sc_ipc; 18 + 19 + enum imx_sc_rpc_svc { 20 + IMX_SC_RPC_SVC_UNKNOWN = 0, 21 + IMX_SC_RPC_SVC_RETURN = 1, 22 + IMX_SC_RPC_SVC_PM = 2, 23 + IMX_SC_RPC_SVC_RM = 3, 24 + IMX_SC_RPC_SVC_TIMER = 5, 25 + IMX_SC_RPC_SVC_PAD = 6, 26 + IMX_SC_RPC_SVC_MISC = 7, 27 + IMX_SC_RPC_SVC_IRQ = 8, 28 + IMX_SC_RPC_SVC_ABORT = 9 29 + }; 30 + 31 + struct imx_sc_rpc_msg { 32 + uint8_t ver; 33 + uint8_t size; 34 + uint8_t svc; 35 + uint8_t func; 36 + }; 37 + 38 + /* 39 + * This is an function to send an RPC message over an IPC channel. 40 + * It is called by client-side SCFW API function shims. 41 + * 42 + * @param[in] ipc IPC handle 43 + * @param[in,out] msg handle to a message 44 + * @param[in] have_resp response flag 45 + * 46 + * If have_resp is true then this function waits for a response 47 + * and returns the result in msg. 48 + */ 49 + int imx_scu_call_rpc(struct imx_sc_ipc *ipc, void *msg, bool have_resp); 50 + 51 + /* 52 + * This function gets the default ipc handle used by SCU 53 + * 54 + * @param[out] ipc sc ipc handle 55 + * 56 + * @return Returns an error code (0 = success, failed if < 0) 57 + */ 58 + int imx_scu_get_handle(struct imx_sc_ipc **ipc); 59 + #endif /* _SC_IPC_H */
+17
include/linux/firmware/imx/sci.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Copyright (C) 2016 Freescale Semiconductor, Inc. 4 + * Copyright 2017~2018 NXP 5 + * 6 + * Header file containing the public System Controller Interface (SCI) 7 + * definitions. 8 + */ 9 + 10 + #ifndef _SC_SCI_H 11 + #define _SC_SCI_H 12 + 13 + #include <linux/firmware/imx/ipc.h> 14 + #include <linux/firmware/imx/types.h> 15 + 16 + #include <linux/firmware/imx/svc/misc.h> 17 + #endif /* _SC_SCI_H */
+55
include/linux/firmware/imx/svc/misc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Copyright (C) 2016 Freescale Semiconductor, Inc. 4 + * Copyright 2017~2018 NXP 5 + * 6 + * Header file containing the public API for the System Controller (SC) 7 + * Miscellaneous (MISC) function. 8 + * 9 + * MISC_SVC (SVC) Miscellaneous Service 10 + * 11 + * Module for the Miscellaneous (MISC) service. 12 + */ 13 + 14 + #ifndef _SC_MISC_API_H 15 + #define _SC_MISC_API_H 16 + 17 + #include <linux/firmware/imx/sci.h> 18 + 19 + /* 20 + * This type is used to indicate RPC MISC function calls. 21 + */ 22 + enum imx_misc_func { 23 + IMX_SC_MISC_FUNC_UNKNOWN = 0, 24 + IMX_SC_MISC_FUNC_SET_CONTROL = 1, 25 + IMX_SC_MISC_FUNC_GET_CONTROL = 2, 26 + IMX_SC_MISC_FUNC_SET_MAX_DMA_GROUP = 4, 27 + IMX_SC_MISC_FUNC_SET_DMA_GROUP = 5, 28 + IMX_SC_MISC_FUNC_SECO_IMAGE_LOAD = 8, 29 + IMX_SC_MISC_FUNC_SECO_AUTHENTICATE = 9, 30 + IMX_SC_MISC_FUNC_DEBUG_OUT = 10, 31 + IMX_SC_MISC_FUNC_WAVEFORM_CAPTURE = 6, 32 + IMX_SC_MISC_FUNC_BUILD_INFO = 15, 33 + IMX_SC_MISC_FUNC_UNIQUE_ID = 19, 34 + IMX_SC_MISC_FUNC_SET_ARI = 3, 35 + IMX_SC_MISC_FUNC_BOOT_STATUS = 7, 36 + IMX_SC_MISC_FUNC_BOOT_DONE = 14, 37 + IMX_SC_MISC_FUNC_OTP_FUSE_READ = 11, 38 + IMX_SC_MISC_FUNC_OTP_FUSE_WRITE = 17, 39 + IMX_SC_MISC_FUNC_SET_TEMP = 12, 40 + IMX_SC_MISC_FUNC_GET_TEMP = 13, 41 + IMX_SC_MISC_FUNC_GET_BOOT_DEV = 16, 42 + IMX_SC_MISC_FUNC_GET_BUTTON_STATUS = 18, 43 + }; 44 + 45 + /* 46 + * Control Functions 47 + */ 48 + 49 + int imx_sc_misc_set_control(struct imx_sc_ipc *ipc, u32 resource, 50 + u8 ctrl, u32 val); 51 + 52 + int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource, 53 + u8 ctrl, u32 *val); 54 + 55 + #endif /* _SC_MISC_API_H */
+617
include/linux/firmware/imx/types.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Copyright (C) 2016 Freescale Semiconductor, Inc. 4 + * Copyright 2017~2018 NXP 5 + * 6 + * Header file containing types used across multiple service APIs. 7 + */ 8 + 9 + #ifndef _SC_TYPES_H 10 + #define _SC_TYPES_H 11 + 12 + /* 13 + * This type is used to indicate a resource. Resources include peripherals 14 + * and bus masters (but not memory regions). Note items from list should 15 + * never be changed or removed (only added to at the end of the list). 16 + */ 17 + enum imx_sc_rsrc { 18 + IMX_SC_R_A53 = 0, 19 + IMX_SC_R_A53_0 = 1, 20 + IMX_SC_R_A53_1 = 2, 21 + IMX_SC_R_A53_2 = 3, 22 + IMX_SC_R_A53_3 = 4, 23 + IMX_SC_R_A72 = 5, 24 + IMX_SC_R_A72_0 = 6, 25 + IMX_SC_R_A72_1 = 7, 26 + IMX_SC_R_A72_2 = 8, 27 + IMX_SC_R_A72_3 = 9, 28 + IMX_SC_R_CCI = 10, 29 + IMX_SC_R_DB = 11, 30 + IMX_SC_R_DRC_0 = 12, 31 + IMX_SC_R_DRC_1 = 13, 32 + IMX_SC_R_GIC_SMMU = 14, 33 + IMX_SC_R_IRQSTR_M4_0 = 15, 34 + IMX_SC_R_IRQSTR_M4_1 = 16, 35 + IMX_SC_R_SMMU = 17, 36 + IMX_SC_R_GIC = 18, 37 + IMX_SC_R_DC_0_BLIT0 = 19, 38 + IMX_SC_R_DC_0_BLIT1 = 20, 39 + IMX_SC_R_DC_0_BLIT2 = 21, 40 + IMX_SC_R_DC_0_BLIT_OUT = 22, 41 + IMX_SC_R_DC_0_CAPTURE0 = 23, 42 + IMX_SC_R_DC_0_CAPTURE1 = 24, 43 + IMX_SC_R_DC_0_WARP = 25, 44 + IMX_SC_R_DC_0_INTEGRAL0 = 26, 45 + IMX_SC_R_DC_0_INTEGRAL1 = 27, 46 + IMX_SC_R_DC_0_VIDEO0 = 28, 47 + IMX_SC_R_DC_0_VIDEO1 = 29, 48 + IMX_SC_R_DC_0_FRAC0 = 30, 49 + IMX_SC_R_DC_0_FRAC1 = 31, 50 + IMX_SC_R_DC_0 = 32, 51 + IMX_SC_R_GPU_2_PID0 = 33, 52 + IMX_SC_R_DC_0_PLL_0 = 34, 53 + IMX_SC_R_DC_0_PLL_1 = 35, 54 + IMX_SC_R_DC_1_BLIT0 = 36, 55 + IMX_SC_R_DC_1_BLIT1 = 37, 56 + IMX_SC_R_DC_1_BLIT2 = 38, 57 + IMX_SC_R_DC_1_BLIT_OUT = 39, 58 + IMX_SC_R_DC_1_CAPTURE0 = 40, 59 + IMX_SC_R_DC_1_CAPTURE1 = 41, 60 + IMX_SC_R_DC_1_WARP = 42, 61 + IMX_SC_R_DC_1_INTEGRAL0 = 43, 62 + IMX_SC_R_DC_1_INTEGRAL1 = 44, 63 + IMX_SC_R_DC_1_VIDEO0 = 45, 64 + IMX_SC_R_DC_1_VIDEO1 = 46, 65 + IMX_SC_R_DC_1_FRAC0 = 47, 66 + IMX_SC_R_DC_1_FRAC1 = 48, 67 + IMX_SC_R_DC_1 = 49, 68 + IMX_SC_R_GPU_3_PID0 = 50, 69 + IMX_SC_R_DC_1_PLL_0 = 51, 70 + IMX_SC_R_DC_1_PLL_1 = 52, 71 + IMX_SC_R_SPI_0 = 53, 72 + IMX_SC_R_SPI_1 = 54, 73 + IMX_SC_R_SPI_2 = 55, 74 + IMX_SC_R_SPI_3 = 56, 75 + IMX_SC_R_UART_0 = 57, 76 + IMX_SC_R_UART_1 = 58, 77 + IMX_SC_R_UART_2 = 59, 78 + IMX_SC_R_UART_3 = 60, 79 + IMX_SC_R_UART_4 = 61, 80 + IMX_SC_R_EMVSIM_0 = 62, 81 + IMX_SC_R_EMVSIM_1 = 63, 82 + IMX_SC_R_DMA_0_CH0 = 64, 83 + IMX_SC_R_DMA_0_CH1 = 65, 84 + IMX_SC_R_DMA_0_CH2 = 66, 85 + IMX_SC_R_DMA_0_CH3 = 67, 86 + IMX_SC_R_DMA_0_CH4 = 68, 87 + IMX_SC_R_DMA_0_CH5 = 69, 88 + IMX_SC_R_DMA_0_CH6 = 70, 89 + IMX_SC_R_DMA_0_CH7 = 71, 90 + IMX_SC_R_DMA_0_CH8 = 72, 91 + IMX_SC_R_DMA_0_CH9 = 73, 92 + IMX_SC_R_DMA_0_CH10 = 74, 93 + IMX_SC_R_DMA_0_CH11 = 75, 94 + IMX_SC_R_DMA_0_CH12 = 76, 95 + IMX_SC_R_DMA_0_CH13 = 77, 96 + IMX_SC_R_DMA_0_CH14 = 78, 97 + IMX_SC_R_DMA_0_CH15 = 79, 98 + IMX_SC_R_DMA_0_CH16 = 80, 99 + IMX_SC_R_DMA_0_CH17 = 81, 100 + IMX_SC_R_DMA_0_CH18 = 82, 101 + IMX_SC_R_DMA_0_CH19 = 83, 102 + IMX_SC_R_DMA_0_CH20 = 84, 103 + IMX_SC_R_DMA_0_CH21 = 85, 104 + IMX_SC_R_DMA_0_CH22 = 86, 105 + IMX_SC_R_DMA_0_CH23 = 87, 106 + IMX_SC_R_DMA_0_CH24 = 88, 107 + IMX_SC_R_DMA_0_CH25 = 89, 108 + IMX_SC_R_DMA_0_CH26 = 90, 109 + IMX_SC_R_DMA_0_CH27 = 91, 110 + IMX_SC_R_DMA_0_CH28 = 92, 111 + IMX_SC_R_DMA_0_CH29 = 93, 112 + IMX_SC_R_DMA_0_CH30 = 94, 113 + IMX_SC_R_DMA_0_CH31 = 95, 114 + IMX_SC_R_I2C_0 = 96, 115 + IMX_SC_R_I2C_1 = 97, 116 + IMX_SC_R_I2C_2 = 98, 117 + IMX_SC_R_I2C_3 = 99, 118 + IMX_SC_R_I2C_4 = 100, 119 + IMX_SC_R_ADC_0 = 101, 120 + IMX_SC_R_ADC_1 = 102, 121 + IMX_SC_R_FTM_0 = 103, 122 + IMX_SC_R_FTM_1 = 104, 123 + IMX_SC_R_CAN_0 = 105, 124 + IMX_SC_R_CAN_1 = 106, 125 + IMX_SC_R_CAN_2 = 107, 126 + IMX_SC_R_DMA_1_CH0 = 108, 127 + IMX_SC_R_DMA_1_CH1 = 109, 128 + IMX_SC_R_DMA_1_CH2 = 110, 129 + IMX_SC_R_DMA_1_CH3 = 111, 130 + IMX_SC_R_DMA_1_CH4 = 112, 131 + IMX_SC_R_DMA_1_CH5 = 113, 132 + IMX_SC_R_DMA_1_CH6 = 114, 133 + IMX_SC_R_DMA_1_CH7 = 115, 134 + IMX_SC_R_DMA_1_CH8 = 116, 135 + IMX_SC_R_DMA_1_CH9 = 117, 136 + IMX_SC_R_DMA_1_CH10 = 118, 137 + IMX_SC_R_DMA_1_CH11 = 119, 138 + IMX_SC_R_DMA_1_CH12 = 120, 139 + IMX_SC_R_DMA_1_CH13 = 121, 140 + IMX_SC_R_DMA_1_CH14 = 122, 141 + IMX_SC_R_DMA_1_CH15 = 123, 142 + IMX_SC_R_DMA_1_CH16 = 124, 143 + IMX_SC_R_DMA_1_CH17 = 125, 144 + IMX_SC_R_DMA_1_CH18 = 126, 145 + IMX_SC_R_DMA_1_CH19 = 127, 146 + IMX_SC_R_DMA_1_CH20 = 128, 147 + IMX_SC_R_DMA_1_CH21 = 129, 148 + IMX_SC_R_DMA_1_CH22 = 130, 149 + IMX_SC_R_DMA_1_CH23 = 131, 150 + IMX_SC_R_DMA_1_CH24 = 132, 151 + IMX_SC_R_DMA_1_CH25 = 133, 152 + IMX_SC_R_DMA_1_CH26 = 134, 153 + IMX_SC_R_DMA_1_CH27 = 135, 154 + IMX_SC_R_DMA_1_CH28 = 136, 155 + IMX_SC_R_DMA_1_CH29 = 137, 156 + IMX_SC_R_DMA_1_CH30 = 138, 157 + IMX_SC_R_DMA_1_CH31 = 139, 158 + IMX_SC_R_UNUSED1 = 140, 159 + IMX_SC_R_UNUSED2 = 141, 160 + IMX_SC_R_UNUSED3 = 142, 161 + IMX_SC_R_UNUSED4 = 143, 162 + IMX_SC_R_GPU_0_PID0 = 144, 163 + IMX_SC_R_GPU_0_PID1 = 145, 164 + IMX_SC_R_GPU_0_PID2 = 146, 165 + IMX_SC_R_GPU_0_PID3 = 147, 166 + IMX_SC_R_GPU_1_PID0 = 148, 167 + IMX_SC_R_GPU_1_PID1 = 149, 168 + IMX_SC_R_GPU_1_PID2 = 150, 169 + IMX_SC_R_GPU_1_PID3 = 151, 170 + IMX_SC_R_PCIE_A = 152, 171 + IMX_SC_R_SERDES_0 = 153, 172 + IMX_SC_R_MATCH_0 = 154, 173 + IMX_SC_R_MATCH_1 = 155, 174 + IMX_SC_R_MATCH_2 = 156, 175 + IMX_SC_R_MATCH_3 = 157, 176 + IMX_SC_R_MATCH_4 = 158, 177 + IMX_SC_R_MATCH_5 = 159, 178 + IMX_SC_R_MATCH_6 = 160, 179 + IMX_SC_R_MATCH_7 = 161, 180 + IMX_SC_R_MATCH_8 = 162, 181 + IMX_SC_R_MATCH_9 = 163, 182 + IMX_SC_R_MATCH_10 = 164, 183 + IMX_SC_R_MATCH_11 = 165, 184 + IMX_SC_R_MATCH_12 = 166, 185 + IMX_SC_R_MATCH_13 = 167, 186 + IMX_SC_R_MATCH_14 = 168, 187 + IMX_SC_R_PCIE_B = 169, 188 + IMX_SC_R_SATA_0 = 170, 189 + IMX_SC_R_SERDES_1 = 171, 190 + IMX_SC_R_HSIO_GPIO = 172, 191 + IMX_SC_R_MATCH_15 = 173, 192 + IMX_SC_R_MATCH_16 = 174, 193 + IMX_SC_R_MATCH_17 = 175, 194 + IMX_SC_R_MATCH_18 = 176, 195 + IMX_SC_R_MATCH_19 = 177, 196 + IMX_SC_R_MATCH_20 = 178, 197 + IMX_SC_R_MATCH_21 = 179, 198 + IMX_SC_R_MATCH_22 = 180, 199 + IMX_SC_R_MATCH_23 = 181, 200 + IMX_SC_R_MATCH_24 = 182, 201 + IMX_SC_R_MATCH_25 = 183, 202 + IMX_SC_R_MATCH_26 = 184, 203 + IMX_SC_R_MATCH_27 = 185, 204 + IMX_SC_R_MATCH_28 = 186, 205 + IMX_SC_R_LCD_0 = 187, 206 + IMX_SC_R_LCD_0_PWM_0 = 188, 207 + IMX_SC_R_LCD_0_I2C_0 = 189, 208 + IMX_SC_R_LCD_0_I2C_1 = 190, 209 + IMX_SC_R_PWM_0 = 191, 210 + IMX_SC_R_PWM_1 = 192, 211 + IMX_SC_R_PWM_2 = 193, 212 + IMX_SC_R_PWM_3 = 194, 213 + IMX_SC_R_PWM_4 = 195, 214 + IMX_SC_R_PWM_5 = 196, 215 + IMX_SC_R_PWM_6 = 197, 216 + IMX_SC_R_PWM_7 = 198, 217 + IMX_SC_R_GPIO_0 = 199, 218 + IMX_SC_R_GPIO_1 = 200, 219 + IMX_SC_R_GPIO_2 = 201, 220 + IMX_SC_R_GPIO_3 = 202, 221 + IMX_SC_R_GPIO_4 = 203, 222 + IMX_SC_R_GPIO_5 = 204, 223 + IMX_SC_R_GPIO_6 = 205, 224 + IMX_SC_R_GPIO_7 = 206, 225 + IMX_SC_R_GPT_0 = 207, 226 + IMX_SC_R_GPT_1 = 208, 227 + IMX_SC_R_GPT_2 = 209, 228 + IMX_SC_R_GPT_3 = 210, 229 + IMX_SC_R_GPT_4 = 211, 230 + IMX_SC_R_KPP = 212, 231 + IMX_SC_R_MU_0A = 213, 232 + IMX_SC_R_MU_1A = 214, 233 + IMX_SC_R_MU_2A = 215, 234 + IMX_SC_R_MU_3A = 216, 235 + IMX_SC_R_MU_4A = 217, 236 + IMX_SC_R_MU_5A = 218, 237 + IMX_SC_R_MU_6A = 219, 238 + IMX_SC_R_MU_7A = 220, 239 + IMX_SC_R_MU_8A = 221, 240 + IMX_SC_R_MU_9A = 222, 241 + IMX_SC_R_MU_10A = 223, 242 + IMX_SC_R_MU_11A = 224, 243 + IMX_SC_R_MU_12A = 225, 244 + IMX_SC_R_MU_13A = 226, 245 + IMX_SC_R_MU_5B = 227, 246 + IMX_SC_R_MU_6B = 228, 247 + IMX_SC_R_MU_7B = 229, 248 + IMX_SC_R_MU_8B = 230, 249 + IMX_SC_R_MU_9B = 231, 250 + IMX_SC_R_MU_10B = 232, 251 + IMX_SC_R_MU_11B = 233, 252 + IMX_SC_R_MU_12B = 234, 253 + IMX_SC_R_MU_13B = 235, 254 + IMX_SC_R_ROM_0 = 236, 255 + IMX_SC_R_FSPI_0 = 237, 256 + IMX_SC_R_FSPI_1 = 238, 257 + IMX_SC_R_IEE = 239, 258 + IMX_SC_R_IEE_R0 = 240, 259 + IMX_SC_R_IEE_R1 = 241, 260 + IMX_SC_R_IEE_R2 = 242, 261 + IMX_SC_R_IEE_R3 = 243, 262 + IMX_SC_R_IEE_R4 = 244, 263 + IMX_SC_R_IEE_R5 = 245, 264 + IMX_SC_R_IEE_R6 = 246, 265 + IMX_SC_R_IEE_R7 = 247, 266 + IMX_SC_R_SDHC_0 = 248, 267 + IMX_SC_R_SDHC_1 = 249, 268 + IMX_SC_R_SDHC_2 = 250, 269 + IMX_SC_R_ENET_0 = 251, 270 + IMX_SC_R_ENET_1 = 252, 271 + IMX_SC_R_MLB_0 = 253, 272 + IMX_SC_R_DMA_2_CH0 = 254, 273 + IMX_SC_R_DMA_2_CH1 = 255, 274 + IMX_SC_R_DMA_2_CH2 = 256, 275 + IMX_SC_R_DMA_2_CH3 = 257, 276 + IMX_SC_R_DMA_2_CH4 = 258, 277 + IMX_SC_R_USB_0 = 259, 278 + IMX_SC_R_USB_1 = 260, 279 + IMX_SC_R_USB_0_PHY = 261, 280 + IMX_SC_R_USB_2 = 262, 281 + IMX_SC_R_USB_2_PHY = 263, 282 + IMX_SC_R_DTCP = 264, 283 + IMX_SC_R_NAND = 265, 284 + IMX_SC_R_LVDS_0 = 266, 285 + IMX_SC_R_LVDS_0_PWM_0 = 267, 286 + IMX_SC_R_LVDS_0_I2C_0 = 268, 287 + IMX_SC_R_LVDS_0_I2C_1 = 269, 288 + IMX_SC_R_LVDS_1 = 270, 289 + IMX_SC_R_LVDS_1_PWM_0 = 271, 290 + IMX_SC_R_LVDS_1_I2C_0 = 272, 291 + IMX_SC_R_LVDS_1_I2C_1 = 273, 292 + IMX_SC_R_LVDS_2 = 274, 293 + IMX_SC_R_LVDS_2_PWM_0 = 275, 294 + IMX_SC_R_LVDS_2_I2C_0 = 276, 295 + IMX_SC_R_LVDS_2_I2C_1 = 277, 296 + IMX_SC_R_M4_0_PID0 = 278, 297 + IMX_SC_R_M4_0_PID1 = 279, 298 + IMX_SC_R_M4_0_PID2 = 280, 299 + IMX_SC_R_M4_0_PID3 = 281, 300 + IMX_SC_R_M4_0_PID4 = 282, 301 + IMX_SC_R_M4_0_RGPIO = 283, 302 + IMX_SC_R_M4_0_SEMA42 = 284, 303 + IMX_SC_R_M4_0_TPM = 285, 304 + IMX_SC_R_M4_0_PIT = 286, 305 + IMX_SC_R_M4_0_UART = 287, 306 + IMX_SC_R_M4_0_I2C = 288, 307 + IMX_SC_R_M4_0_INTMUX = 289, 308 + IMX_SC_R_M4_0_SIM = 290, 309 + IMX_SC_R_M4_0_WDOG = 291, 310 + IMX_SC_R_M4_0_MU_0B = 292, 311 + IMX_SC_R_M4_0_MU_0A0 = 293, 312 + IMX_SC_R_M4_0_MU_0A1 = 294, 313 + IMX_SC_R_M4_0_MU_0A2 = 295, 314 + IMX_SC_R_M4_0_MU_0A3 = 296, 315 + IMX_SC_R_M4_0_MU_1A = 297, 316 + IMX_SC_R_M4_1_PID0 = 298, 317 + IMX_SC_R_M4_1_PID1 = 299, 318 + IMX_SC_R_M4_1_PID2 = 300, 319 + IMX_SC_R_M4_1_PID3 = 301, 320 + IMX_SC_R_M4_1_PID4 = 302, 321 + IMX_SC_R_M4_1_RGPIO = 303, 322 + IMX_SC_R_M4_1_SEMA42 = 304, 323 + IMX_SC_R_M4_1_TPM = 305, 324 + IMX_SC_R_M4_1_PIT = 306, 325 + IMX_SC_R_M4_1_UART = 307, 326 + IMX_SC_R_M4_1_I2C = 308, 327 + IMX_SC_R_M4_1_INTMUX = 309, 328 + IMX_SC_R_M4_1_SIM = 310, 329 + IMX_SC_R_M4_1_WDOG = 311, 330 + IMX_SC_R_M4_1_MU_0B = 312, 331 + IMX_SC_R_M4_1_MU_0A0 = 313, 332 + IMX_SC_R_M4_1_MU_0A1 = 314, 333 + IMX_SC_R_M4_1_MU_0A2 = 315, 334 + IMX_SC_R_M4_1_MU_0A3 = 316, 335 + IMX_SC_R_M4_1_MU_1A = 317, 336 + IMX_SC_R_SAI_0 = 318, 337 + IMX_SC_R_SAI_1 = 319, 338 + IMX_SC_R_SAI_2 = 320, 339 + IMX_SC_R_IRQSTR_SCU2 = 321, 340 + IMX_SC_R_IRQSTR_DSP = 322, 341 + IMX_SC_R_UNUSED5 = 323, 342 + IMX_SC_R_UNUSED6 = 324, 343 + IMX_SC_R_AUDIO_PLL_0 = 325, 344 + IMX_SC_R_PI_0 = 326, 345 + IMX_SC_R_PI_0_PWM_0 = 327, 346 + IMX_SC_R_PI_0_PWM_1 = 328, 347 + IMX_SC_R_PI_0_I2C_0 = 329, 348 + IMX_SC_R_PI_0_PLL = 330, 349 + IMX_SC_R_PI_1 = 331, 350 + IMX_SC_R_PI_1_PWM_0 = 332, 351 + IMX_SC_R_PI_1_PWM_1 = 333, 352 + IMX_SC_R_PI_1_I2C_0 = 334, 353 + IMX_SC_R_PI_1_PLL = 335, 354 + IMX_SC_R_SC_PID0 = 336, 355 + IMX_SC_R_SC_PID1 = 337, 356 + IMX_SC_R_SC_PID2 = 338, 357 + IMX_SC_R_SC_PID3 = 339, 358 + IMX_SC_R_SC_PID4 = 340, 359 + IMX_SC_R_SC_SEMA42 = 341, 360 + IMX_SC_R_SC_TPM = 342, 361 + IMX_SC_R_SC_PIT = 343, 362 + IMX_SC_R_SC_UART = 344, 363 + IMX_SC_R_SC_I2C = 345, 364 + IMX_SC_R_SC_MU_0B = 346, 365 + IMX_SC_R_SC_MU_0A0 = 347, 366 + IMX_SC_R_SC_MU_0A1 = 348, 367 + IMX_SC_R_SC_MU_0A2 = 349, 368 + IMX_SC_R_SC_MU_0A3 = 350, 369 + IMX_SC_R_SC_MU_1A = 351, 370 + IMX_SC_R_SYSCNT_RD = 352, 371 + IMX_SC_R_SYSCNT_CMP = 353, 372 + IMX_SC_R_DEBUG = 354, 373 + IMX_SC_R_SYSTEM = 355, 374 + IMX_SC_R_SNVS = 356, 375 + IMX_SC_R_OTP = 357, 376 + IMX_SC_R_VPU_PID0 = 358, 377 + IMX_SC_R_VPU_PID1 = 359, 378 + IMX_SC_R_VPU_PID2 = 360, 379 + IMX_SC_R_VPU_PID3 = 361, 380 + IMX_SC_R_VPU_PID4 = 362, 381 + IMX_SC_R_VPU_PID5 = 363, 382 + IMX_SC_R_VPU_PID6 = 364, 383 + IMX_SC_R_VPU_PID7 = 365, 384 + IMX_SC_R_VPU_UART = 366, 385 + IMX_SC_R_VPUCORE = 367, 386 + IMX_SC_R_VPUCORE_0 = 368, 387 + IMX_SC_R_VPUCORE_1 = 369, 388 + IMX_SC_R_VPUCORE_2 = 370, 389 + IMX_SC_R_VPUCORE_3 = 371, 390 + IMX_SC_R_DMA_4_CH0 = 372, 391 + IMX_SC_R_DMA_4_CH1 = 373, 392 + IMX_SC_R_DMA_4_CH2 = 374, 393 + IMX_SC_R_DMA_4_CH3 = 375, 394 + IMX_SC_R_DMA_4_CH4 = 376, 395 + IMX_SC_R_ISI_CH0 = 377, 396 + IMX_SC_R_ISI_CH1 = 378, 397 + IMX_SC_R_ISI_CH2 = 379, 398 + IMX_SC_R_ISI_CH3 = 380, 399 + IMX_SC_R_ISI_CH4 = 381, 400 + IMX_SC_R_ISI_CH5 = 382, 401 + IMX_SC_R_ISI_CH6 = 383, 402 + IMX_SC_R_ISI_CH7 = 384, 403 + IMX_SC_R_MJPEG_DEC_S0 = 385, 404 + IMX_SC_R_MJPEG_DEC_S1 = 386, 405 + IMX_SC_R_MJPEG_DEC_S2 = 387, 406 + IMX_SC_R_MJPEG_DEC_S3 = 388, 407 + IMX_SC_R_MJPEG_ENC_S0 = 389, 408 + IMX_SC_R_MJPEG_ENC_S1 = 390, 409 + IMX_SC_R_MJPEG_ENC_S2 = 391, 410 + IMX_SC_R_MJPEG_ENC_S3 = 392, 411 + IMX_SC_R_MIPI_0 = 393, 412 + IMX_SC_R_MIPI_0_PWM_0 = 394, 413 + IMX_SC_R_MIPI_0_I2C_0 = 395, 414 + IMX_SC_R_MIPI_0_I2C_1 = 396, 415 + IMX_SC_R_MIPI_1 = 397, 416 + IMX_SC_R_MIPI_1_PWM_0 = 398, 417 + IMX_SC_R_MIPI_1_I2C_0 = 399, 418 + IMX_SC_R_MIPI_1_I2C_1 = 400, 419 + IMX_SC_R_CSI_0 = 401, 420 + IMX_SC_R_CSI_0_PWM_0 = 402, 421 + IMX_SC_R_CSI_0_I2C_0 = 403, 422 + IMX_SC_R_CSI_1 = 404, 423 + IMX_SC_R_CSI_1_PWM_0 = 405, 424 + IMX_SC_R_CSI_1_I2C_0 = 406, 425 + IMX_SC_R_HDMI = 407, 426 + IMX_SC_R_HDMI_I2S = 408, 427 + IMX_SC_R_HDMI_I2C_0 = 409, 428 + IMX_SC_R_HDMI_PLL_0 = 410, 429 + IMX_SC_R_HDMI_RX = 411, 430 + IMX_SC_R_HDMI_RX_BYPASS = 412, 431 + IMX_SC_R_HDMI_RX_I2C_0 = 413, 432 + IMX_SC_R_ASRC_0 = 414, 433 + IMX_SC_R_ESAI_0 = 415, 434 + IMX_SC_R_SPDIF_0 = 416, 435 + IMX_SC_R_SPDIF_1 = 417, 436 + IMX_SC_R_SAI_3 = 418, 437 + IMX_SC_R_SAI_4 = 419, 438 + IMX_SC_R_SAI_5 = 420, 439 + IMX_SC_R_GPT_5 = 421, 440 + IMX_SC_R_GPT_6 = 422, 441 + IMX_SC_R_GPT_7 = 423, 442 + IMX_SC_R_GPT_8 = 424, 443 + IMX_SC_R_GPT_9 = 425, 444 + IMX_SC_R_GPT_10 = 426, 445 + IMX_SC_R_DMA_2_CH5 = 427, 446 + IMX_SC_R_DMA_2_CH6 = 428, 447 + IMX_SC_R_DMA_2_CH7 = 429, 448 + IMX_SC_R_DMA_2_CH8 = 430, 449 + IMX_SC_R_DMA_2_CH9 = 431, 450 + IMX_SC_R_DMA_2_CH10 = 432, 451 + IMX_SC_R_DMA_2_CH11 = 433, 452 + IMX_SC_R_DMA_2_CH12 = 434, 453 + IMX_SC_R_DMA_2_CH13 = 435, 454 + IMX_SC_R_DMA_2_CH14 = 436, 455 + IMX_SC_R_DMA_2_CH15 = 437, 456 + IMX_SC_R_DMA_2_CH16 = 438, 457 + IMX_SC_R_DMA_2_CH17 = 439, 458 + IMX_SC_R_DMA_2_CH18 = 440, 459 + IMX_SC_R_DMA_2_CH19 = 441, 460 + IMX_SC_R_DMA_2_CH20 = 442, 461 + IMX_SC_R_DMA_2_CH21 = 443, 462 + IMX_SC_R_DMA_2_CH22 = 444, 463 + IMX_SC_R_DMA_2_CH23 = 445, 464 + IMX_SC_R_DMA_2_CH24 = 446, 465 + IMX_SC_R_DMA_2_CH25 = 447, 466 + IMX_SC_R_DMA_2_CH26 = 448, 467 + IMX_SC_R_DMA_2_CH27 = 449, 468 + IMX_SC_R_DMA_2_CH28 = 450, 469 + IMX_SC_R_DMA_2_CH29 = 451, 470 + IMX_SC_R_DMA_2_CH30 = 452, 471 + IMX_SC_R_DMA_2_CH31 = 453, 472 + IMX_SC_R_ASRC_1 = 454, 473 + IMX_SC_R_ESAI_1 = 455, 474 + IMX_SC_R_SAI_6 = 456, 475 + IMX_SC_R_SAI_7 = 457, 476 + IMX_SC_R_AMIX = 458, 477 + IMX_SC_R_MQS_0 = 459, 478 + IMX_SC_R_DMA_3_CH0 = 460, 479 + IMX_SC_R_DMA_3_CH1 = 461, 480 + IMX_SC_R_DMA_3_CH2 = 462, 481 + IMX_SC_R_DMA_3_CH3 = 463, 482 + IMX_SC_R_DMA_3_CH4 = 464, 483 + IMX_SC_R_DMA_3_CH5 = 465, 484 + IMX_SC_R_DMA_3_CH6 = 466, 485 + IMX_SC_R_DMA_3_CH7 = 467, 486 + IMX_SC_R_DMA_3_CH8 = 468, 487 + IMX_SC_R_DMA_3_CH9 = 469, 488 + IMX_SC_R_DMA_3_CH10 = 470, 489 + IMX_SC_R_DMA_3_CH11 = 471, 490 + IMX_SC_R_DMA_3_CH12 = 472, 491 + IMX_SC_R_DMA_3_CH13 = 473, 492 + IMX_SC_R_DMA_3_CH14 = 474, 493 + IMX_SC_R_DMA_3_CH15 = 475, 494 + IMX_SC_R_DMA_3_CH16 = 476, 495 + IMX_SC_R_DMA_3_CH17 = 477, 496 + IMX_SC_R_DMA_3_CH18 = 478, 497 + IMX_SC_R_DMA_3_CH19 = 479, 498 + IMX_SC_R_DMA_3_CH20 = 480, 499 + IMX_SC_R_DMA_3_CH21 = 481, 500 + IMX_SC_R_DMA_3_CH22 = 482, 501 + IMX_SC_R_DMA_3_CH23 = 483, 502 + IMX_SC_R_DMA_3_CH24 = 484, 503 + IMX_SC_R_DMA_3_CH25 = 485, 504 + IMX_SC_R_DMA_3_CH26 = 486, 505 + IMX_SC_R_DMA_3_CH27 = 487, 506 + IMX_SC_R_DMA_3_CH28 = 488, 507 + IMX_SC_R_DMA_3_CH29 = 489, 508 + IMX_SC_R_DMA_3_CH30 = 490, 509 + IMX_SC_R_DMA_3_CH31 = 491, 510 + IMX_SC_R_AUDIO_PLL_1 = 492, 511 + IMX_SC_R_AUDIO_CLK_0 = 493, 512 + IMX_SC_R_AUDIO_CLK_1 = 494, 513 + IMX_SC_R_MCLK_OUT_0 = 495, 514 + IMX_SC_R_MCLK_OUT_1 = 496, 515 + IMX_SC_R_PMIC_0 = 497, 516 + IMX_SC_R_PMIC_1 = 498, 517 + IMX_SC_R_SECO = 499, 518 + IMX_SC_R_CAAM_JR1 = 500, 519 + IMX_SC_R_CAAM_JR2 = 501, 520 + IMX_SC_R_CAAM_JR3 = 502, 521 + IMX_SC_R_SECO_MU_2 = 503, 522 + IMX_SC_R_SECO_MU_3 = 504, 523 + IMX_SC_R_SECO_MU_4 = 505, 524 + IMX_SC_R_HDMI_RX_PWM_0 = 506, 525 + IMX_SC_R_A35 = 507, 526 + IMX_SC_R_A35_0 = 508, 527 + IMX_SC_R_A35_1 = 509, 528 + IMX_SC_R_A35_2 = 510, 529 + IMX_SC_R_A35_3 = 511, 530 + IMX_SC_R_DSP = 512, 531 + IMX_SC_R_DSP_RAM = 513, 532 + IMX_SC_R_CAAM_JR1_OUT = 514, 533 + IMX_SC_R_CAAM_JR2_OUT = 515, 534 + IMX_SC_R_CAAM_JR3_OUT = 516, 535 + IMX_SC_R_VPU_DEC_0 = 517, 536 + IMX_SC_R_VPU_ENC_0 = 518, 537 + IMX_SC_R_CAAM_JR0 = 519, 538 + IMX_SC_R_CAAM_JR0_OUT = 520, 539 + IMX_SC_R_PMIC_2 = 521, 540 + IMX_SC_R_DBLOGIC = 522, 541 + IMX_SC_R_HDMI_PLL_1 = 523, 542 + IMX_SC_R_BOARD_R0 = 524, 543 + IMX_SC_R_BOARD_R1 = 525, 544 + IMX_SC_R_BOARD_R2 = 526, 545 + IMX_SC_R_BOARD_R3 = 527, 546 + IMX_SC_R_BOARD_R4 = 528, 547 + IMX_SC_R_BOARD_R5 = 529, 548 + IMX_SC_R_BOARD_R6 = 530, 549 + IMX_SC_R_BOARD_R7 = 531, 550 + IMX_SC_R_MJPEG_DEC_MP = 532, 551 + IMX_SC_R_MJPEG_ENC_MP = 533, 552 + IMX_SC_R_VPU_TS_0 = 534, 553 + IMX_SC_R_VPU_MU_0 = 535, 554 + IMX_SC_R_VPU_MU_1 = 536, 555 + IMX_SC_R_VPU_MU_2 = 537, 556 + IMX_SC_R_VPU_MU_3 = 538, 557 + IMX_SC_R_VPU_ENC_1 = 539, 558 + IMX_SC_R_VPU = 540, 559 + IMX_SC_R_LAST 560 + }; 561 + 562 + /* NOTE - please add by replacing some of the UNUSED from above! */ 563 + 564 + /* 565 + * This type is used to indicate a control. 566 + */ 567 + enum imx_sc_ctrl { 568 + IMX_SC_C_TEMP = 0, 569 + IMX_SC_C_TEMP_HI = 1, 570 + IMX_SC_C_TEMP_LOW = 2, 571 + IMX_SC_C_PXL_LINK_MST1_ADDR = 3, 572 + IMX_SC_C_PXL_LINK_MST2_ADDR = 4, 573 + IMX_SC_C_PXL_LINK_MST_ENB = 5, 574 + IMX_SC_C_PXL_LINK_MST1_ENB = 6, 575 + IMX_SC_C_PXL_LINK_MST2_ENB = 7, 576 + IMX_SC_C_PXL_LINK_SLV1_ADDR = 8, 577 + IMX_SC_C_PXL_LINK_SLV2_ADDR = 9, 578 + IMX_SC_C_PXL_LINK_MST_VLD = 10, 579 + IMX_SC_C_PXL_LINK_MST1_VLD = 11, 580 + IMX_SC_C_PXL_LINK_MST2_VLD = 12, 581 + IMX_SC_C_SINGLE_MODE = 13, 582 + IMX_SC_C_ID = 14, 583 + IMX_SC_C_PXL_CLK_POLARITY = 15, 584 + IMX_SC_C_LINESTATE = 16, 585 + IMX_SC_C_PCIE_G_RST = 17, 586 + IMX_SC_C_PCIE_BUTTON_RST = 18, 587 + IMX_SC_C_PCIE_PERST = 19, 588 + IMX_SC_C_PHY_RESET = 20, 589 + IMX_SC_C_PXL_LINK_RATE_CORRECTION = 21, 590 + IMX_SC_C_PANIC = 22, 591 + IMX_SC_C_PRIORITY_GROUP = 23, 592 + IMX_SC_C_TXCLK = 24, 593 + IMX_SC_C_CLKDIV = 25, 594 + IMX_SC_C_DISABLE_50 = 26, 595 + IMX_SC_C_DISABLE_125 = 27, 596 + IMX_SC_C_SEL_125 = 28, 597 + IMX_SC_C_MODE = 29, 598 + IMX_SC_C_SYNC_CTRL0 = 30, 599 + IMX_SC_C_KACHUNK_CNT = 31, 600 + IMX_SC_C_KACHUNK_SEL = 32, 601 + IMX_SC_C_SYNC_CTRL1 = 33, 602 + IMX_SC_C_DPI_RESET = 34, 603 + IMX_SC_C_MIPI_RESET = 35, 604 + IMX_SC_C_DUAL_MODE = 36, 605 + IMX_SC_C_VOLTAGE = 37, 606 + IMX_SC_C_PXL_LINK_SEL = 38, 607 + IMX_SC_C_OFS_SEL = 39, 608 + IMX_SC_C_OFS_AUDIO = 40, 609 + IMX_SC_C_OFS_PERIPH = 41, 610 + IMX_SC_C_OFS_IRQ = 42, 611 + IMX_SC_C_RST0 = 43, 612 + IMX_SC_C_RST1 = 44, 613 + IMX_SC_C_SEL0 = 45, 614 + IMX_SC_C_LAST 615 + }; 616 + 617 + #endif /* _SC_TYPES_H */
+1
include/linux/firmware/meson/meson_sm.h
··· 17 17 SM_EFUSE_READ, 18 18 SM_EFUSE_WRITE, 19 19 SM_EFUSE_USER_MAX, 20 + SM_GET_CHIP_ID, 20 21 }; 21 22 22 23 struct meson_sm_firmware;
+116
include/linux/firmware/xlnx-zynqmp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Xilinx Zynq MPSoC Firmware layer 4 + * 5 + * Copyright (C) 2014-2018 Xilinx 6 + * 7 + * Michal Simek <michal.simek@xilinx.com> 8 + * Davorin Mista <davorin.mista@aggios.com> 9 + * Jolly Shah <jollys@xilinx.com> 10 + * Rajan Vaja <rajanv@xilinx.com> 11 + */ 12 + 13 + #ifndef __FIRMWARE_ZYNQMP_H__ 14 + #define __FIRMWARE_ZYNQMP_H__ 15 + 16 + #define ZYNQMP_PM_VERSION_MAJOR 1 17 + #define ZYNQMP_PM_VERSION_MINOR 0 18 + 19 + #define ZYNQMP_PM_VERSION ((ZYNQMP_PM_VERSION_MAJOR << 16) | \ 20 + ZYNQMP_PM_VERSION_MINOR) 21 + 22 + #define ZYNQMP_TZ_VERSION_MAJOR 1 23 + #define ZYNQMP_TZ_VERSION_MINOR 0 24 + 25 + #define ZYNQMP_TZ_VERSION ((ZYNQMP_TZ_VERSION_MAJOR << 16) | \ 26 + ZYNQMP_TZ_VERSION_MINOR) 27 + 28 + /* SMC SIP service Call Function Identifier Prefix */ 29 + #define PM_SIP_SVC 0xC2000000 30 + #define PM_GET_TRUSTZONE_VERSION 0xa03 31 + 32 + /* Number of 32bits values in payload */ 33 + #define PAYLOAD_ARG_CNT 4U 34 + 35 + enum pm_api_id { 36 + PM_GET_API_VERSION = 1, 37 + PM_IOCTL = 34, 38 + PM_QUERY_DATA, 39 + PM_CLOCK_ENABLE, 40 + PM_CLOCK_DISABLE, 41 + PM_CLOCK_GETSTATE, 42 + PM_CLOCK_SETDIVIDER, 43 + PM_CLOCK_GETDIVIDER, 44 + PM_CLOCK_SETRATE, 45 + PM_CLOCK_GETRATE, 46 + PM_CLOCK_SETPARENT, 47 + PM_CLOCK_GETPARENT, 48 + }; 49 + 50 + /* PMU-FW return status codes */ 51 + enum pm_ret_status { 52 + XST_PM_SUCCESS = 0, 53 + XST_PM_INTERNAL = 2000, 54 + XST_PM_CONFLICT, 55 + XST_PM_NO_ACCESS, 56 + XST_PM_INVALID_NODE, 57 + XST_PM_DOUBLE_REQ, 58 + XST_PM_ABORT_SUSPEND, 59 + }; 60 + 61 + enum pm_ioctl_id { 62 + IOCTL_SET_PLL_FRAC_MODE = 8, 63 + IOCTL_GET_PLL_FRAC_MODE, 64 + IOCTL_SET_PLL_FRAC_DATA, 65 + IOCTL_GET_PLL_FRAC_DATA, 66 + }; 67 + 68 + enum pm_query_id { 69 + PM_QID_INVALID, 70 + PM_QID_CLOCK_GET_NAME, 71 + PM_QID_CLOCK_GET_TOPOLOGY, 72 + PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS, 73 + PM_QID_CLOCK_GET_PARENTS, 74 + PM_QID_CLOCK_GET_ATTRIBUTES, 75 + PM_QID_CLOCK_GET_NUM_CLOCKS = 12, 76 + }; 77 + 78 + /** 79 + * struct zynqmp_pm_query_data - PM query data 80 + * @qid: query ID 81 + * @arg1: Argument 1 of query data 82 + * @arg2: Argument 2 of query data 83 + * @arg3: Argument 3 of query data 84 + */ 85 + struct zynqmp_pm_query_data { 86 + u32 qid; 87 + u32 arg1; 88 + u32 arg2; 89 + u32 arg3; 90 + }; 91 + 92 + struct zynqmp_eemi_ops { 93 + int (*get_api_version)(u32 *version); 94 + int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out); 95 + int (*clock_enable)(u32 clock_id); 96 + int (*clock_disable)(u32 clock_id); 97 + int (*clock_getstate)(u32 clock_id, u32 *state); 98 + int (*clock_setdivider)(u32 clock_id, u32 divider); 99 + int (*clock_getdivider)(u32 clock_id, u32 *divider); 100 + int (*clock_setrate)(u32 clock_id, u64 rate); 101 + int (*clock_getrate)(u32 clock_id, u64 *rate); 102 + int (*clock_setparent)(u32 clock_id, u32 parent_id); 103 + int (*clock_getparent)(u32 clock_id, u32 *parent_id); 104 + int (*ioctl)(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, u32 *out); 105 + }; 106 + 107 + #if IS_REACHABLE(CONFIG_ARCH_ZYNQMP) 108 + const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void); 109 + #else 110 + static inline struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void) 111 + { 112 + return NULL; 113 + } 114 + #endif 115 + 116 + #endif /* __FIRMWARE_ZYNQMP_H__ */
-1
include/linux/platform_data/ti-sysc.h
··· 46 46 s8 emufree_shift; 47 47 }; 48 48 49 - #define SYSC_QUIRK_RESOURCE_PROVIDER BIT(9) 50 49 #define SYSC_QUIRK_LEGACY_IDLE BIT(8) 51 50 #define SYSC_QUIRK_RESET_STATUS BIT(7) 52 51 #define SYSC_QUIRK_NO_IDLE_ON_INIT BIT(6)
+1 -1
include/linux/reset.h
··· 116 116 * @id: reset line name 117 117 * 118 118 * Returns a struct reset_control or IS_ERR() condition containing errno. 119 - * If this function is called more then once for the same reset_control it will 119 + * If this function is called more than once for the same reset_control it will 120 120 * return -EBUSY. 121 121 * 122 122 * See reset_control_get_shared for details on shared references to
+4
include/linux/scmi_protocol.h
··· 91 91 * to sustained performance level mapping 92 92 * @freq_get: gets the frequency for a given device using sustained frequency 93 93 * to sustained performance level mapping 94 + * @est_power_get: gets the estimated power cost for a given performance domain 95 + * at a given frequency 94 96 */ 95 97 struct scmi_perf_ops { 96 98 int (*limits_set)(const struct scmi_handle *handle, u32 domain, ··· 112 110 unsigned long rate, bool poll); 113 111 int (*freq_get)(const struct scmi_handle *handle, u32 domain, 114 112 unsigned long *rate, bool poll); 113 + int (*est_power_get)(const struct scmi_handle *handle, u32 domain, 114 + unsigned long *rate, unsigned long *power); 115 115 }; 116 116 117 117 /**
+65
include/linux/soc/amlogic/meson-canvas.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Copyright (C) 2018 BayLibre, SAS 4 + */ 5 + #ifndef __SOC_MESON_CANVAS_H 6 + #define __SOC_MESON_CANVAS_H 7 + 8 + #include <linux/kernel.h> 9 + 10 + #define MESON_CANVAS_WRAP_NONE 0x00 11 + #define MESON_CANVAS_WRAP_X 0x01 12 + #define MESON_CANVAS_WRAP_Y 0x02 13 + 14 + #define MESON_CANVAS_BLKMODE_LINEAR 0x00 15 + #define MESON_CANVAS_BLKMODE_32x32 0x01 16 + #define MESON_CANVAS_BLKMODE_64x64 0x02 17 + 18 + #define MESON_CANVAS_ENDIAN_SWAP16 0x1 19 + #define MESON_CANVAS_ENDIAN_SWAP32 0x3 20 + #define MESON_CANVAS_ENDIAN_SWAP64 0x7 21 + #define MESON_CANVAS_ENDIAN_SWAP128 0xf 22 + 23 + struct meson_canvas; 24 + 25 + /** 26 + * meson_canvas_get() - get a canvas provider instance 27 + * 28 + * @dev: consumer device pointer 29 + */ 30 + struct meson_canvas *meson_canvas_get(struct device *dev); 31 + 32 + /** 33 + * meson_canvas_alloc() - take ownership of a canvas 34 + * 35 + * @canvas: canvas provider instance retrieved from meson_canvas_get() 36 + * @canvas_index: will be filled with the canvas ID 37 + */ 38 + int meson_canvas_alloc(struct meson_canvas *canvas, u8 *canvas_index); 39 + 40 + /** 41 + * meson_canvas_free() - remove ownership from a canvas 42 + * 43 + * @canvas: canvas provider instance retrieved from meson_canvas_get() 44 + * @canvas_index: canvas ID that was obtained via meson_canvas_alloc() 45 + */ 46 + int meson_canvas_free(struct meson_canvas *canvas, u8 canvas_index); 47 + 48 + /** 49 + * meson_canvas_config() - configure a canvas 50 + * 51 + * @canvas: canvas provider instance retrieved from meson_canvas_get() 52 + * @canvas_index: canvas ID that was obtained via meson_canvas_alloc() 53 + * @addr: physical address to the pixel buffer 54 + * @stride: width of the buffer 55 + * @height: height of the buffer 56 + * @wrap: undocumented 57 + * @blkmode: block mode (linear, 32x32, 64x64) 58 + * @endian: byte swapping (swap16, swap32, swap64, swap128) 59 + */ 60 + int meson_canvas_config(struct meson_canvas *canvas, u8 canvas_index, 61 + u32 addr, u32 stride, u32 height, 62 + unsigned int wrap, unsigned int blkmode, 63 + unsigned int endian); 64 + 65 + #endif
+28 -2
include/linux/soc/qcom/llcc-qcom.h
··· 70 70 /** 71 71 * llcc_drv_data - Data associated with the llcc driver 72 72 * @regmap: regmap associated with the llcc device 73 + * @bcast_regmap: regmap associated with llcc broadcast offset 73 74 * @cfg: pointer to the data structure for slice configuration 74 75 * @lock: mutex associated with each slice 75 76 * @cfg_size: size of the config data table 76 77 * @max_slices: max slices as read from device tree 77 - * @bcast_off: Offset of the broadcast bank 78 78 * @num_banks: Number of llcc banks 79 79 * @bitmap: Bit map to track the active slice ids 80 80 * @offsets: Pointer to the bank offsets array 81 + * @ecc_irq: interrupt for llcc cache error detection and reporting 81 82 */ 82 83 struct llcc_drv_data { 83 84 struct regmap *regmap; 85 + struct regmap *bcast_regmap; 84 86 const struct llcc_slice_config *cfg; 85 87 struct mutex lock; 86 88 u32 cfg_size; 87 89 u32 max_slices; 88 - u32 bcast_off; 89 90 u32 num_banks; 90 91 unsigned long *bitmap; 91 92 u32 *offsets; 93 + int ecc_irq; 94 + }; 95 + 96 + /** 97 + * llcc_edac_reg_data - llcc edac registers data for each error type 98 + * @name: Name of the error 99 + * @synd_reg: Syndrome register address 100 + * @count_status_reg: Status register address to read the error count 101 + * @ways_status_reg: Status register address to read the error ways 102 + * @reg_cnt: Number of registers 103 + * @count_mask: Mask value to get the error count 104 + * @ways_mask: Mask value to get the error ways 105 + * @count_shift: Shift value to get the error count 106 + * @ways_shift: Shift value to get the error ways 107 + */ 108 + struct llcc_edac_reg_data { 109 + char *name; 110 + u64 synd_reg; 111 + u64 count_status_reg; 112 + u64 ways_status_reg; 113 + u32 reg_cnt; 114 + u32 count_mask; 115 + u32 ways_mask; 116 + u8 count_shift; 117 + u8 ways_shift; 92 118 }; 93 119 94 120 #if IS_ENABLED(CONFIG_QCOM_LLCC)
+73
include/linux/tee_drv.h
··· 453 453 */ 454 454 struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id); 455 455 456 + /** 457 + * tee_client_open_context() - Open a TEE context 458 + * @start: if not NULL, continue search after this context 459 + * @match: function to check TEE device 460 + * @data: data for match function 461 + * @vers: if not NULL, version data of TEE device of the context returned 462 + * 463 + * This function does an operation similar to open("/dev/teeX") in user space. 464 + * A returned context must be released with tee_client_close_context(). 465 + * 466 + * Returns a TEE context of the first TEE device matched by the match() 467 + * callback or an ERR_PTR. 468 + */ 469 + struct tee_context * 470 + tee_client_open_context(struct tee_context *start, 471 + int (*match)(struct tee_ioctl_version_data *, 472 + const void *), 473 + const void *data, struct tee_ioctl_version_data *vers); 474 + 475 + /** 476 + * tee_client_close_context() - Close a TEE context 477 + * @ctx: TEE context to close 478 + * 479 + * Note that all sessions previously opened with this context will be 480 + * closed when this function is called. 481 + */ 482 + void tee_client_close_context(struct tee_context *ctx); 483 + 484 + /** 485 + * tee_client_get_version() - Query version of TEE 486 + * @ctx: TEE context to TEE to query 487 + * @vers: Pointer to version data 488 + */ 489 + void tee_client_get_version(struct tee_context *ctx, 490 + struct tee_ioctl_version_data *vers); 491 + 492 + /** 493 + * tee_client_open_session() - Open a session to a Trusted Application 494 + * @ctx: TEE context 495 + * @arg: Open session arguments, see description of 496 + * struct tee_ioctl_open_session_arg 497 + * @param: Parameters passed to the Trusted Application 498 + * 499 + * Returns < 0 on error else see @arg->ret for result. If @arg->ret 500 + * is TEEC_SUCCESS the session identifier is available in @arg->session. 501 + */ 502 + int tee_client_open_session(struct tee_context *ctx, 503 + struct tee_ioctl_open_session_arg *arg, 504 + struct tee_param *param); 505 + 506 + /** 507 + * tee_client_close_session() - Close a session to a Trusted Application 508 + * @ctx: TEE Context 509 + * @session: Session id 510 + * 511 + * Return < 0 on error else 0, regardless the session will not be 512 + * valid after this function has returned. 513 + */ 514 + int tee_client_close_session(struct tee_context *ctx, u32 session); 515 + 516 + /** 517 + * tee_client_invoke_func() - Invoke a function in a Trusted Application 518 + * @ctx: TEE Context 519 + * @arg: Invoke arguments, see description of 520 + * struct tee_ioctl_invoke_arg 521 + * @param: Parameters passed to the Trusted Application 522 + * 523 + * Returns < 0 on error else see @arg->ret for result. 524 + */ 525 + int tee_client_invoke_func(struct tee_context *ctx, 526 + struct tee_ioctl_invoke_arg *arg, 527 + struct tee_param *param); 528 + 456 529 static inline bool tee_param_is_memref(struct tee_param *param) 457 530 { 458 531 switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
+28
include/soc/fsl/qman.h
··· 1194 1194 */ 1195 1195 int qman_is_probed(void); 1196 1196 1197 + /** 1198 + * qman_dqrr_get_ithresh - Get coalesce interrupt threshold 1199 + * @portal: portal to get the value for 1200 + * @ithresh: threshold pointer 1201 + */ 1202 + void qman_dqrr_get_ithresh(struct qman_portal *portal, u8 *ithresh); 1203 + 1204 + /** 1205 + * qman_dqrr_set_ithresh - Set coalesce interrupt threshold 1206 + * @portal: portal to set the new value on 1207 + * @ithresh: new threshold value 1208 + */ 1209 + void qman_dqrr_set_ithresh(struct qman_portal *portal, u8 ithresh); 1210 + 1211 + /** 1212 + * qman_dqrr_get_iperiod - Get coalesce interrupt period 1213 + * @portal: portal to get the value for 1214 + * @iperiod: period pointer 1215 + */ 1216 + void qman_portal_get_iperiod(struct qman_portal *portal, u32 *iperiod); 1217 + 1218 + /** 1219 + * qman_dqrr_set_iperiod - Set coalesce interrupt period 1220 + * @portal: portal to set the new value on 1221 + * @ithresh: new period value 1222 + */ 1223 + void qman_portal_set_iperiod(struct qman_portal *portal, u32 iperiod); 1224 + 1197 1225 #endif /* __FSL_QMAN_H */
+1 -19
include/soc/tegra/pmc.h
··· 134 134 TEGRA_IO_PAD_USB2, 135 135 TEGRA_IO_PAD_USB3, 136 136 TEGRA_IO_PAD_USB_BIAS, 137 + TEGRA_IO_PAD_AO_HV, 137 138 }; 138 139 139 140 /* deprecated, use TEGRA_IO_PAD_{HDMI,LVDS} instead */ 140 141 #define TEGRA_IO_RAIL_HDMI TEGRA_IO_PAD_HDMI 141 142 #define TEGRA_IO_RAIL_LVDS TEGRA_IO_PAD_LVDS 142 - 143 - /** 144 - * enum tegra_io_pad_voltage - voltage level of the I/O pad's source rail 145 - * @TEGRA_IO_PAD_1800000UV: 1.8 V 146 - * @TEGRA_IO_PAD_3300000UV: 3.3 V 147 - */ 148 - enum tegra_io_pad_voltage { 149 - TEGRA_IO_PAD_1800000UV, 150 - TEGRA_IO_PAD_3300000UV, 151 - }; 152 143 153 144 #ifdef CONFIG_SOC_TEGRA_PMC 154 145 int tegra_powergate_is_powered(unsigned int id); ··· 153 162 154 163 int tegra_io_pad_power_enable(enum tegra_io_pad id); 155 164 int tegra_io_pad_power_disable(enum tegra_io_pad id); 156 - int tegra_io_pad_set_voltage(enum tegra_io_pad id, 157 - enum tegra_io_pad_voltage voltage); 158 - int tegra_io_pad_get_voltage(enum tegra_io_pad id); 159 165 160 166 /* deprecated, use tegra_io_pad_power_{enable,disable}() instead */ 161 167 int tegra_io_rail_power_on(unsigned int id); ··· 196 208 } 197 209 198 210 static inline int tegra_io_pad_power_disable(enum tegra_io_pad id) 199 - { 200 - return -ENOSYS; 201 - } 202 - 203 - static inline int tegra_io_pad_set_voltage(enum tegra_io_pad id, 204 - enum tegra_io_pad_voltage voltage) 205 211 { 206 212 return -ENOSYS; 207 213 }