summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-06 12:41:12 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-06 12:41:12 -0500
commit384d11fa0e2ca15a3e7e52db34a4e43bedf0dc70 (patch)
treeb68ecd9458fb77d6b80e1389fc3705ca360a7def
parent6ad63dec9c2c80710896edd1996e56c54a230870 (diff)
parent8ceb820b69fe6ff58234ff604146a9e88e6c1974 (diff)
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC driver updates from Arnd Bergmann: "As usual, the drivers/tee and drivers/reset subsystems get merged here, with the expected set of smaller updates and some new hardware support. The tee subsystem now supports device drivers to be attached to a tee, the first example here is a random number driver with its implementation in the secure world. Three new power domain drivers get added for specific chip families: - Broadcom BCM283x chips (used in Raspberry Pi) - Qualcomm Snapdragon phone chips - Xilinx ZynqMP FPGA SoCs One new driver is added to talk to the BPMP firmware on NVIDIA Tegra210 Existing drivers are extended for new SoC variants from NXP, NVIDIA, Amlogic and Qualcomm" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (113 commits) tee: optee: update optee_msg.h and optee_smc.h to dual license tee: add cancellation support to client interface dpaa2-eth: configure the cache stashing amount on a queue soc: fsl: dpio: configure cache stashing destination soc: fsl: dpio: enable frame data cache stashing per software portal soc: fsl: guts: make fsl_guts_get_svr() static hwrng: make symbol 'optee_rng_id_table' static tee: optee: Fix unsigned comparison with less than zero hwrng: Fix unsigned comparison with less than zero tee: fix possible error pointer ctx dereferencing hwrng: optee: Initialize some structs using memset instead of braces tee: optee: Initialize some structs using memset instead of braces soc: fsl: dpio: fix memory leak of a struct qbman on error exit path clk: tegra: dfll: Make symbol 'tegra210_cpu_cvb_tables' static soc: qcom: llcc-slice: Fix typos qcom: soc: llcc-slice: Consolidate some code qcom: soc: llcc-slice: Clear the global drv_data pointer on error drivers: soc: xilinx: Add ZynqMP power domain driver firmware: xilinx: Add APIs to control node status/power dt-bindings: power: Add ZynqMP power domain bindings ...
-rw-r--r--Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt8
-rw-r--r--Documentation/devicetree/bindings/bus/imx-weim.txt32
-rw-r--r--Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt46
-rw-r--r--Documentation/devicetree/bindings/opp/opp.txt3
-rw-r--r--Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt3
-rw-r--r--Documentation/devicetree/bindings/power/qcom,rpmpd.txt145
-rw-r--r--Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt25
-rw-r--r--Documentation/devicetree/bindings/power/xlnx,zynqmp-genpd.txt34
-rw-r--r--Documentation/devicetree/bindings/reset/brcm,brcmstb-reset.txt27
-rw-r--r--Documentation/devicetree/bindings/reset/fsl,imx7-src.txt7
-rw-r--r--Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt52
-rw-r--r--Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt2
-rw-r--r--Documentation/devicetree/bindings/soc/bcm/brcm,bcm2835-pm.txt46
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt1
-rw-r--r--MAINTAINERS38
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi.dtsi4
-rw-r--r--arch/arm/boot/dts/bcm283x.dtsi17
-rw-r--r--arch/arm/mach-bcm/Kconfig1
-rw-r--r--arch/arm/mach-socfpga/socfpga.c3
-rw-r--r--arch/arm/mach-sunxi/sunxi.c2
-rw-r--r--drivers/bus/hisi_lpc.c5
-rw-r--r--drivers/bus/imx-weim.c70
-rw-r--r--drivers/char/hw_random/Kconfig15
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/optee-rng.c306
-rw-r--r--drivers/clk/tegra/Kconfig5
-rw-r--r--drivers/clk/tegra/Makefile2
-rw-r--r--drivers/clk/tegra/clk-dfll.c459
-rw-r--r--drivers/clk/tegra/clk-dfll.h6
-rw-r--r--drivers/clk/tegra/clk-tegra124-dfll-fcpu.c520
-rw-r--r--drivers/clk/tegra/cvb.c12
-rw-r--r--drivers/clk/tegra/cvb.h7
-rw-r--r--drivers/cpufreq/Kconfig.arm4
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c1
-rw-r--r--drivers/cpufreq/tegra124-cpufreq.c44
-rw-r--r--drivers/firmware/imx/misc.c38
-rw-r--r--drivers/firmware/imx/scu-pd.c1
-rw-r--r--drivers/firmware/raspberrypi.c11
-rw-r--r--drivers/firmware/tegra/Makefile3
-rw-r--r--drivers/firmware/tegra/bpmp-private.h34
-rw-r--r--drivers/firmware/tegra/bpmp-tegra186.c305
-rw-r--r--drivers/firmware/tegra/bpmp-tegra210.c243
-rw-r--r--drivers/firmware/tegra/bpmp.c376
-rw-r--r--drivers/firmware/ti_sci.c21
-rw-r--r--drivers/firmware/xilinx/Kconfig1
-rw-r--r--drivers/firmware/xilinx/zynqmp.c166
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/bcm2835-pm.c92
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c7
-rw-r--r--drivers/nvmem/Kconfig10
-rw-r--r--drivers/nvmem/Makefile2
-rw-r--r--drivers/nvmem/zynqmp_nvmem.c86
-rw-r--r--drivers/opp/core.c18
-rw-r--r--drivers/opp/of.c2
-rw-r--r--drivers/opp/opp.h2
-rw-r--r--drivers/reset/Kconfig12
-rw-r--r--drivers/reset/Makefile2
-rw-r--r--drivers/reset/reset-brcmstb.c132
-rw-r--r--drivers/reset/reset-imx7.c172
-rw-r--r--drivers/reset/reset-socfpga.c2
-rw-r--r--drivers/reset/reset-sunxi.c1
-rw-r--r--drivers/reset/reset-zynqmp.c114
-rw-r--r--drivers/soc/amlogic/meson-canvas.c18
-rw-r--r--drivers/soc/amlogic/meson-clk-measure.c196
-rw-r--r--drivers/soc/bcm/Kconfig12
-rw-r--r--drivers/soc/bcm/Makefile1
-rw-r--r--drivers/soc/bcm/bcm2835-power.c661
-rw-r--r--drivers/soc/fsl/Kconfig1
-rw-r--r--drivers/soc/fsl/dpio/dpio-cmd.h5
-rw-r--r--drivers/soc/fsl/dpio/dpio-driver.c54
-rw-r--r--drivers/soc/fsl/dpio/dpio-service.c5
-rw-r--r--drivers/soc/fsl/dpio/dpio.c16
-rw-r--r--drivers/soc/fsl/dpio/dpio.h5
-rw-r--r--drivers/soc/fsl/dpio/qbman-portal.c5
-rw-r--r--drivers/soc/fsl/guts.c10
-rw-r--r--drivers/soc/imx/Kconfig2
-rw-r--r--drivers/soc/imx/gpcv2.c76
-rw-r--r--drivers/soc/qcom/Kconfig18
-rw-r--r--drivers/soc/qcom/Makefile2
-rw-r--r--drivers/soc/qcom/llcc-sdm845.c6
-rw-r--r--drivers/soc/qcom/llcc-slice.c101
-rw-r--r--drivers/soc/qcom/qcom_gsbi.c7
-rw-r--r--drivers/soc/qcom/rmtfs_mem.c32
-rw-r--r--drivers/soc/qcom/rpmh.c37
-rw-r--r--drivers/soc/qcom/rpmhpd.c406
-rw-r--r--drivers/soc/qcom/rpmpd.c315
-rw-r--r--drivers/soc/qcom/smd-rpm.c1
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra.c12
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra210.c2
-rw-r--r--drivers/soc/tegra/pmc.c424
-rw-r--r--drivers/soc/ti/knav_dma.c2
-rw-r--r--drivers/soc/xilinx/Kconfig20
-rw-r--r--drivers/soc/xilinx/Makefile2
-rw-r--r--drivers/soc/xilinx/zynqmp_pm_domains.c321
-rw-r--r--drivers/soc/xilinx/zynqmp_power.c178
-rw-r--r--drivers/tee/optee/Makefile1
-rw-r--r--drivers/tee/optee/core.c4
-rw-r--r--drivers/tee/optee/device.c160
-rw-r--r--drivers/tee/optee/optee_msg.h26
-rw-r--r--drivers/tee/optee/optee_private.h3
-rw-r--r--drivers/tee/optee/optee_smc.h26
-rw-r--r--drivers/tee/optee/supp.c10
-rw-r--r--drivers/tee/tee_core.c78
-rw-r--r--drivers/watchdog/bcm2835_wdt.c26
-rw-r--r--include/dt-bindings/power/qcom-rpmpd.h39
-rw-r--r--include/dt-bindings/power/xlnx-zynqmp-power.h39
-rw-r--r--include/dt-bindings/reset/amlogic,meson-g12a-reset.h134
-rw-r--r--include/dt-bindings/reset/imx8mq-reset.h64
-rw-r--r--include/dt-bindings/reset/xlnx-zynqmp-resets.h130
-rw-r--r--include/dt-bindings/soc/bcm2835-pm.h28
-rw-r--r--include/linux/firmware/imx/svc/misc.h3
-rw-r--r--include/linux/firmware/xlnx-zynqmp.h184
-rw-r--r--include/linux/fsl/guts.h2
-rw-r--r--include/linux/mfd/bcm2835-pm.h14
-rw-r--r--include/linux/mod_devicetable.h9
-rw-r--r--include/linux/pm_opp.h7
-rw-r--r--include/linux/reset/socfpga.h7
-rw-r--r--include/linux/reset/sunxi.h7
-rw-r--r--include/linux/soc/qcom/llcc-qcom.h6
-rw-r--r--include/linux/tee_drv.h50
-rw-r--r--include/soc/bcm2835/raspberrypi-firmware.h4
-rw-r--r--include/soc/fsl/dpaa2-io.h4
-rw-r--r--include/soc/tegra/bpmp.h13
-rw-r--r--include/soc/tegra/pmc.h6
-rw-r--r--scripts/mod/devicetable-offsets.c3
-rw-r--r--scripts/mod/file2alias.c19
126 files changed, 7122 insertions, 744 deletions
diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
index cef5ee83fbc1..72d481c8dd48 100644
--- a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
+++ b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
@@ -58,7 +58,11 @@ This binding for the SCU power domain providers uses the generic power
58domain binding[2]. 58domain binding[2].
59 59
60Required properties: 60Required properties:
61- compatible: Should be "fsl,imx8qxp-scu-pd". 61- compatible: Should be one of:
62 "fsl,imx8qm-scu-pd",
63 "fsl,imx8qxp-scu-pd"
64 followed by "fsl,scu-pd"
65
62- #power-domain-cells: Must be 1. Contains the Resource ID used by 66- #power-domain-cells: Must be 1. Contains the Resource ID used by
63 SCU commands. 67 SCU commands.
64 See detailed Resource ID list from: 68 See detailed Resource ID list from:
@@ -157,7 +161,7 @@ firmware {
157 }; 161 };
158 162
159 pd: imx8qx-pd { 163 pd: imx8qx-pd {
160 compatible = "fsl,imx8qxp-scu-pd"; 164 compatible = "fsl,imx8qxp-scu-pd", "fsl,scu-pd";
161 #power-domain-cells = <1>; 165 #power-domain-cells = <1>;
162 }; 166 };
163 167
diff --git a/Documentation/devicetree/bindings/bus/imx-weim.txt b/Documentation/devicetree/bindings/bus/imx-weim.txt
index 683eaf3aed79..dda7d6d66479 100644
--- a/Documentation/devicetree/bindings/bus/imx-weim.txt
+++ b/Documentation/devicetree/bindings/bus/imx-weim.txt
@@ -47,9 +47,9 @@ Optional properties:
47Timing property for child nodes. It is mandatory, not optional. 47Timing property for child nodes. It is mandatory, not optional.
48 48
49 - fsl,weim-cs-timing: The timing array, contains timing values for the 49 - fsl,weim-cs-timing: The timing array, contains timing values for the
50 child node. We can get the CS index from the child 50 child node. We get the CS indexes from the address
51 node's "reg" property. The number of registers depends 51 ranges in the child node's "reg" property.
52 on the selected chip. 52 The number of registers depends on the selected chip:
53 For i.MX1, i.MX21 ("fsl,imx1-weim") there are two 53 For i.MX1, i.MX21 ("fsl,imx1-weim") there are two
54 registers: CSxU, CSxL. 54 registers: CSxU, CSxL.
55 For i.MX25, i.MX27, i.MX31 and i.MX35 ("fsl,imx27-weim") 55 For i.MX25, i.MX27, i.MX31 and i.MX35 ("fsl,imx27-weim")
@@ -80,3 +80,29 @@ Example for an imx6q-sabreauto board, the NOR flash connected to the WEIM:
80 0x0000c000 0x1404a38e 0x00000000>; 80 0x0000c000 0x1404a38e 0x00000000>;
81 }; 81 };
82 }; 82 };
83
84Example for an imx6q-based board, a multi-chipselect device connected to WEIM:
85
86In this case, both chip select 0 and 1 will be configured with the same timing
87array values.
88
89 weim: weim@21b8000 {
90 compatible = "fsl,imx6q-weim";
91 reg = <0x021b8000 0x4000>;
92 clocks = <&clks 196>;
93 #address-cells = <2>;
94 #size-cells = <1>;
95 ranges = <0 0 0x08000000 0x02000000
96 1 0 0x0a000000 0x02000000
97 2 0 0x0c000000 0x02000000
98 3 0 0x0e000000 0x02000000>;
99 fsl,weim-cs-gpr = <&gpr>;
100
101 acme@0 {
102 compatible = "acme,whatever";
103 reg = <0 0 0x100>, <0 0x400000 0x800>,
104 <1 0x400000 0x800>;
105 fsl,weim-cs-timing = <0x024400b1 0x00001010 0x20081100
106 0x00000000 0xa0000240 0x00000000>;
107 };
108 };
diff --git a/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt b/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt
new file mode 100644
index 000000000000..4881561b3a02
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt
@@ -0,0 +1,46 @@
1--------------------------------------------------------------------------
2= Zynq UltraScale+ MPSoC nvmem firmware driver binding =
3--------------------------------------------------------------------------
4The nvmem_firmware node provides access to the hardware related data
5like soc revision, IDCODE... etc, By using the firmware interface.
6
7Required properties:
8- compatible: should be "xlnx,zynqmp-nvmem-fw"
9
10= Data cells =
11Are child nodes of silicon id, bindings of which as described in
12bindings/nvmem/nvmem.txt
13
14-------
15 Example
16-------
17firmware {
18 zynqmp_firmware: zynqmp-firmware {
19 compatible = "xlnx,zynqmp-firmware";
20 method = "smc";
21
22 nvmem_firmware {
23 compatible = "xlnx,zynqmp-nvmem-fw";
24 #address-cells = <1>;
25 #size-cells = <1>;
26
27 /* Data cells */
28 soc_revision: soc_revision {
29 reg = <0x0 0x4>;
30 };
31 };
32 };
33};
34
35= Data consumers =
36Are device nodes which consume nvmem data cells.
37
38For example:
39 pcap {
40 ...
41
42 nvmem-cells = <&soc_revision>;
43 nvmem-cell-names = "soc_revision";
44
45 ...
46 };
diff --git a/Documentation/devicetree/bindings/opp/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
index c396c4c0af92..76b6c79604a5 100644
--- a/Documentation/devicetree/bindings/opp/opp.txt
+++ b/Documentation/devicetree/bindings/opp/opp.txt
@@ -129,6 +129,9 @@ Optional properties:
129- opp-microamp-<name>: Named opp-microamp property. Similar to 129- opp-microamp-<name>: Named opp-microamp property. Similar to
130 opp-microvolt-<name> property, but for microamp instead. 130 opp-microvolt-<name> property, but for microamp instead.
131 131
132- opp-level: A value representing the performance level of the device,
133 expressed as a 32-bit integer.
134
132- clock-latency-ns: Specifies the maximum possible transition latency (in 135- clock-latency-ns: Specifies the maximum possible transition latency (in
133 nanoseconds) for switching to this OPP from any other OPP. 136 nanoseconds) for switching to this OPP from any other OPP.
134 137
diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt
index 7c947a996df1..7c7e972aaa42 100644
--- a/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt
+++ b/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt
@@ -32,6 +32,9 @@ Required properties:
32Optional properties: 32Optional properties:
33 33
34- power-supply: Power supply used to power the domain 34- power-supply: Power supply used to power the domain
35- clocks: a number of phandles to clocks that need to be enabled during
36 domain power-up sequencing to ensure reset propagation into devices
37 located inside this power domain
35 38
36Example: 39Example:
37 40
diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt
new file mode 100644
index 000000000000..980e5413d18f
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt
@@ -0,0 +1,145 @@
1Qualcomm RPM/RPMh Power domains
2
3For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh
4which then translates it into a corresponding voltage on a rail
5
6Required Properties:
7 - compatible: Should be one of the following
8 * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC
9 * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC
10 - #power-domain-cells: number of cells in Power domain specifier
11 must be 1.
12 - operating-points-v2: Phandle to the OPP table for the Power domain.
13 Refer to Documentation/devicetree/bindings/power/power_domain.txt
14 and Documentation/devicetree/bindings/opp/opp.txt for more details
15
16Refer to <dt-bindings/power/qcom-rpmpd.h> for the level values for
17various OPPs for different platforms as well as Power domain indexes
18
19Example: rpmh power domain controller and OPP table
20
21#include <dt-bindings/power/qcom-rpmhpd.h>
22
23opp-level values specified in the OPP tables for RPMh power domains
24should use the RPMH_REGULATOR_LEVEL_* constants from
25<dt-bindings/power/qcom-rpmhpd.h>
26
27 rpmhpd: power-controller {
28 compatible = "qcom,sdm845-rpmhpd";
29 #power-domain-cells = <1>;
30 operating-points-v2 = <&rpmhpd_opp_table>;
31
32 rpmhpd_opp_table: opp-table {
33 compatible = "operating-points-v2";
34
35 rpmhpd_opp_ret: opp1 {
36 opp-level = <RPMH_REGULATOR_LEVEL_RETENTION>;
37 };
38
39 rpmhpd_opp_min_svs: opp2 {
40 opp-level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
41 };
42
43 rpmhpd_opp_low_svs: opp3 {
44 opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
45 };
46
47 rpmhpd_opp_svs: opp4 {
48 opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
49 };
50
51 rpmhpd_opp_svs_l1: opp5 {
52 opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
53 };
54
55 rpmhpd_opp_nom: opp6 {
56 opp-level = <RPMH_REGULATOR_LEVEL_NOM>;
57 };
58
59 rpmhpd_opp_nom_l1: opp7 {
60 opp-level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
61 };
62
63 rpmhpd_opp_nom_l2: opp8 {
64 opp-level = <RPMH_REGULATOR_LEVEL_NOM_L2>;
65 };
66
67 rpmhpd_opp_turbo: opp9 {
68 opp-level = <RPMH_REGULATOR_LEVEL_TURBO>;
69 };
70
71 rpmhpd_opp_turbo_l1: opp10 {
72 opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
73 };
74 };
75 };
76
77Example: rpm power domain controller and OPP table
78
79 rpmpd: power-controller {
80 compatible = "qcom,msm8996-rpmpd";
81 #power-domain-cells = <1>;
82 operating-points-v2 = <&rpmpd_opp_table>;
83
84 rpmpd_opp_table: opp-table {
85 compatible = "operating-points-v2";
86
87 rpmpd_opp_low: opp1 {
88 opp-level = <1>;
89 };
90
91 rpmpd_opp_ret: opp2 {
92 opp-level = <2>;
93 };
94
95 rpmpd_opp_svs: opp3 {
96 opp-level = <3>;
97 };
98
99 rpmpd_opp_normal: opp4 {
100 opp-level = <4>;
101 };
102
103 rpmpd_opp_high: opp5 {
104 opp-level = <5>;
105 };
106
107 rpmpd_opp_turbo: opp6 {
108 opp-level = <6>;
109 };
110 };
111 };
112
113Example: Client/Consumer device using OPP table
114
115 leaky-device0@12350000 {
116 compatible = "foo,i-leak-current";
117 reg = <0x12350000 0x1000>;
118 power-domains = <&rpmhpd SDM845_MX>;
119 operating-points-v2 = <&leaky_opp_table>;
120 };
121
122
123 leaky_opp_table: opp-table {
124 compatible = "operating-points-v2";
125
126 opp1 {
127 opp-hz = /bits/ 64 <144000>;
128 required-opps = <&rpmhpd_opp_low>;
129 };
130
131 opp2 {
132 opp-hz = /bits/ 64 <400000>;
133 required-opps = <&rpmhpd_opp_ret>;
134 };
135
136 opp3 {
137 opp-hz = /bits/ 64 <20000000>;
138 required-opps = <&rpmpd_opp_svs>;
139 };
140
141 opp4 {
142 opp-hz = /bits/ 64 <25000000>;
143 required-opps = <&rpmpd_opp_normal>;
144 };
145 };
diff --git a/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt b/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt
new file mode 100644
index 000000000000..d366f1eb623a
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt
@@ -0,0 +1,25 @@
1--------------------------------------------------------------------
2Device Tree Bindings for the Xilinx Zynq MPSoC Power Management
3--------------------------------------------------------------------
4The zynqmp-power node describes the power management configurations.
5It will control remote suspend/shutdown interfaces.
6
7Required properties:
8 - compatible: Must contain: "xlnx,zynqmp-power"
9 - interrupts: Interrupt specifier
10
11-------
12Example
13-------
14
15firmware {
16 zynqmp_firmware: zynqmp-firmware {
17 compatible = "xlnx,zynqmp-firmware";
18 method = "smc";
19
20 zynqmp_power: zynqmp-power {
21 compatible = "xlnx,zynqmp-power";
22 interrupts = <0 35 4>;
23 };
24 };
25};
diff --git a/Documentation/devicetree/bindings/power/xlnx,zynqmp-genpd.txt b/Documentation/devicetree/bindings/power/xlnx,zynqmp-genpd.txt
new file mode 100644
index 000000000000..8d1b8200ebd0
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/xlnx,zynqmp-genpd.txt
@@ -0,0 +1,34 @@
1-----------------------------------------------------------
2Device Tree Bindings for the Xilinx Zynq MPSoC PM domains
3-----------------------------------------------------------
4The binding for zynqmp-power-controller follow the common
5generic PM domain binding[1].
6
7[1] Documentation/devicetree/bindings/power/power_domain.txt
8
9== Zynq MPSoC Generic PM Domain Node ==
10
11Required property:
12 - Below property should be in zynqmp-firmware node.
13 - #power-domain-cells: Number of cells in a PM domain specifier. Must be 1.
14
15Power domain ID indexes are mentioned in
16include/dt-bindings/power/xlnx-zynqmp-power.h.
17
18-------
19Example
20-------
21
22firmware {
23 zynqmp_firmware: zynqmp-firmware {
24 ...
25 #power-domain-cells = <1>;
26 ...
27 };
28};
29
30sata {
31 ...
32 power-domains = <&zynqmp_firmware 28>;
33 ...
34};
diff --git a/Documentation/devicetree/bindings/reset/brcm,brcmstb-reset.txt b/Documentation/devicetree/bindings/reset/brcm,brcmstb-reset.txt
new file mode 100644
index 000000000000..6e5341b4f891
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/brcm,brcmstb-reset.txt
@@ -0,0 +1,27 @@
1Broadcom STB SW_INIT-style reset controller
2===========================================
3
4Broadcom STB SoCs have a SW_INIT-style reset controller with separate
5SET/CLEAR/STATUS registers and possibly multiple banks, each of 32 bit
6reset lines.
7
8Please also refer to reset.txt in this directory for common reset
9controller binding usage.
10
11Required properties:
12- compatible: should be brcm,brcmstb-reset
13- reg: register base and length
14- #reset-cells: must be set to 1
15
16Example:
17
18 reset: reset-controller@8404318 {
19 compatible = "brcm,brcmstb-reset";
20 reg = <0x8404318 0x30>;
21 #reset-cells = <1>;
22 };
23
24 &ethernet_switch {
25 resets = <&reset>;
26 reset-names = "switch";
27 };
diff --git a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
index 1ab1d109318e..2ecf33815d18 100644
--- a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
+++ b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
@@ -5,7 +5,9 @@ Please also refer to reset.txt in this directory for common reset
5controller binding usage. 5controller binding usage.
6 6
7Required properties: 7Required properties:
8- compatible: Should be "fsl,imx7d-src", "syscon" 8- compatible:
9 - For i.MX7 SoCs should be "fsl,imx7d-src", "syscon"
10 - For i.MX8MQ SoCs should be "fsl,imx8mq-src", "syscon"
9- reg: should be register base and length as documented in the 11- reg: should be register base and length as documented in the
10 datasheet 12 datasheet
11- interrupts: Should contain SRC interrupt 13- interrupts: Should contain SRC interrupt
@@ -44,4 +46,5 @@ Example:
44 46
45 47
46For list of all valid reset indicies see 48For list of all valid reset indicies see
47<dt-bindings/reset/imx7-reset.h> 49<dt-bindings/reset/imx7-reset.h> for i.MX7 and
50<dt-bindings/reset/imx8mq-reset.h> for i.MX8MQ
diff --git a/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt b/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt
new file mode 100644
index 000000000000..27a45fe5ecf1
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt
@@ -0,0 +1,52 @@
1--------------------------------------------------------------------------
2 = Zynq UltraScale+ MPSoC reset driver binding =
3--------------------------------------------------------------------------
4The Zynq UltraScale+ MPSoC has several different resets.
5
6See Chapter 36 of the Zynq UltraScale+ MPSoC TRM (UG) for more information
7about zynqmp resets.
8
9Please also refer to reset.txt in this directory for common reset
10controller binding usage.
11
12Required Properties:
13- compatible: "xlnx,zynqmp-reset"
14- #reset-cells: Specifies the number of cells needed to encode reset
15 line, should be 1
16
17-------
18Example
19-------
20
21firmware {
22 zynqmp_firmware: zynqmp-firmware {
23 compatible = "xlnx,zynqmp-firmware";
24 method = "smc";
25
26 zynqmp_reset: reset-controller {
27 compatible = "xlnx,zynqmp-reset";
28 #reset-cells = <1>;
29 };
30 };
31};
32
33Specifying reset lines connected to IP modules
34==============================================
35
36Device nodes that need access to reset lines should
37specify them as a reset phandle in their corresponding node as
38specified in reset.txt.
39
40For list of all valid reset indicies see
41<dt-bindings/reset/xlnx-zynqmp-resets.h>
42
43Example:
44
45serdes: zynqmp_phy@fd400000 {
46 ...
47
48 resets = <&zynqmp_reset ZYNQMP_RESET_SATA>;
49 reset-names = "sata_rst";
50
51 ...
52};
diff --git a/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt b/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt
index 205a54bcd7c7..6bf6b43f8dd8 100644
--- a/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt
+++ b/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt
@@ -9,6 +9,8 @@ Required properties:
9 "amlogic,meson-gx-clk-measure" for GX SoCs 9 "amlogic,meson-gx-clk-measure" for GX SoCs
10 "amlogic,meson8-clk-measure" for Meson8 SoCs 10 "amlogic,meson8-clk-measure" for Meson8 SoCs
11 "amlogic,meson8b-clk-measure" for Meson8b SoCs 11 "amlogic,meson8b-clk-measure" for Meson8b SoCs
12 "amlogic,meson-axg-clk-measure" for AXG SoCs
13 "amlogic,meson-g12a-clk-measure" for G12a SoCs
12- reg: base address and size of the Clock Measurer register space. 14- reg: base address and size of the Clock Measurer register space.
13 15
14Example: 16Example:
diff --git a/Documentation/devicetree/bindings/soc/bcm/brcm,bcm2835-pm.txt b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm2835-pm.txt
new file mode 100644
index 000000000000..3b7d32956391
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm2835-pm.txt
@@ -0,0 +1,46 @@
1BCM2835 PM (Power domains, watchdog)
2
3The PM block controls power domains and some reset lines, and includes
4a watchdog timer. This binding supersedes the brcm,bcm2835-pm-wdt
5binding which covered some of PM's register range and functionality.
6
7Required properties:
8
9- compatible: Should be "brcm,bcm2835-pm"
10- reg: Specifies base physical address and size of the two
11 register ranges ("PM" and "ASYNC_BRIDGE" in that
12 order)
13- clocks: a) v3d: The V3D clock from CPRMAN
14 b) peri_image: The PERI_IMAGE clock from CPRMAN
15 c) h264: The H264 clock from CPRMAN
16 d) isp: The ISP clock from CPRMAN
17- #reset-cells: Should be 1. This property follows the reset controller
18 bindings[1].
19- #power-domain-cells: Should be 1. This property follows the power domain
20 bindings[2].
21
22Optional properties:
23
24- timeout-sec: Contains the watchdog timeout in seconds
25- system-power-controller: Whether the watchdog is controlling the
26 system power. This node follows the power controller bindings[3].
27
28[1] Documentation/devicetree/bindings/reset/reset.txt
29[2] Documentation/devicetree/bindings/power/power_domain.txt
30[3] Documentation/devicetree/bindings/power/power-controller.txt
31
32Example:
33
34pm {
35 compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
36 #power-domain-cells = <1>;
37 #reset-cells = <1>;
38 reg = <0x7e100000 0x114>,
39 <0x7e00a000 0x24>;
40 clocks = <&clocks BCM2835_CLOCK_V3D>,
41 <&clocks BCM2835_CLOCK_PERI_IMAGE>,
42 <&clocks BCM2835_CLOCK_H264>,
43 <&clocks BCM2835_CLOCK_ISP>;
44 clock-names = "v3d", "peri_image", "h264", "isp";
45 system-power-controller;
46};
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt
index ec95705ba692..f3fa313963d5 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt
@@ -23,6 +23,7 @@ resources.
23 "qcom,rpm-msm8916" 23 "qcom,rpm-msm8916"
24 "qcom,rpm-msm8974" 24 "qcom,rpm-msm8974"
25 "qcom,rpm-msm8998" 25 "qcom,rpm-msm8998"
26 "qcom,rpm-sdm660"
26 "qcom,rpm-qcs404" 27 "qcom,rpm-qcs404"
27 28
28- qcom,smd-channels: 29- qcom,smd-channels:
diff --git a/MAINTAINERS b/MAINTAINERS
index 49f7d49c2d6e..d5a4b63d13ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1940,19 +1940,37 @@ M: David Brown <david.brown@linaro.org>
1940L: linux-arm-msm@vger.kernel.org 1940L: linux-arm-msm@vger.kernel.org
1941S: Maintained 1941S: Maintained
1942F: Documentation/devicetree/bindings/soc/qcom/ 1942F: Documentation/devicetree/bindings/soc/qcom/
1943F: Documentation/devicetree/bindings/*/qcom*
1943F: arch/arm/boot/dts/qcom-*.dts 1944F: arch/arm/boot/dts/qcom-*.dts
1944F: arch/arm/boot/dts/qcom-*.dtsi 1945F: arch/arm/boot/dts/qcom-*.dtsi
1945F: arch/arm/mach-qcom/ 1946F: arch/arm/mach-qcom/
1946F: arch/arm64/boot/dts/qcom/* 1947F: arch/arm64/boot/dts/qcom/
1948F: drivers/*/qcom/
1949F: drivers/*/qcom*
1950F: drivers/*/*/qcom/
1951F: drivers/*/*/qcom*
1952F: drivers/*/pm8???-*
1953F: drivers/bluetooth/btqcomsmd.c
1954F: drivers/clocksource/timer-qcom.c
1955F: drivers/extcon/extcon-qcom*
1956F: drivers/iommu/msm*
1947F: drivers/i2c/busses/i2c-qup.c 1957F: drivers/i2c/busses/i2c-qup.c
1948F: drivers/clk/qcom/ 1958F: drivers/i2c/busses/i2c-qcom-geni.c
1949F: drivers/dma/qcom/ 1959F: drivers/mfd/ssbi.c
1950F: drivers/soc/qcom/ 1960F: drivers/mmc/host/mmci_qcom*
1961F: drivers/mmc/host/sdhci_msm.c
1962F: drivers/pci/controller/dwc/pcie-qcom.c
1963F: drivers/phy/qualcomm/
1964F: drivers/power/*/msm*
1965F: drivers/reset/reset-qcom-*
1966F: drivers/scsi/ufs/ufs-qcom.*
1951F: drivers/spi/spi-qup.c 1967F: drivers/spi/spi-qup.c
1968F: drivers/spi/spi-geni-qcom.c
1969F: drivers/spi/spi-qcom-qspi.c
1952F: drivers/tty/serial/msm_serial.c 1970F: drivers/tty/serial/msm_serial.c
1953F: drivers/*/pm8???-* 1971F: drivers/usb/dwc3/dwc3-qcom.c
1954F: drivers/mfd/ssbi.c 1972F: include/dt-bindings/*/qcom*
1955F: drivers/firmware/qcom_scm* 1973F: include/linux/*/qcom*
1956T: git git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git 1974T: git git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git
1957 1975
1958ARM/RADISYS ENP2611 MACHINE SUPPORT 1976ARM/RADISYS ENP2611 MACHINE SUPPORT
@@ -11314,6 +11332,11 @@ M: Jens Wiklander <jens.wiklander@linaro.org>
11314S: Maintained 11332S: Maintained
11315F: drivers/tee/optee/ 11333F: drivers/tee/optee/
11316 11334
11335OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER
11336M: Sumit Garg <sumit.garg@linaro.org>
11337S: Maintained
11338F: drivers/char/hw_random/optee-rng.c
11339
11317OPA-VNIC DRIVER 11340OPA-VNIC DRIVER
11318M: Dennis Dalessandro <dennis.dalessandro@intel.com> 11341M: Dennis Dalessandro <dennis.dalessandro@intel.com>
11319M: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com> 11342M: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
@@ -13017,6 +13040,7 @@ F: drivers/reset/
13017F: Documentation/devicetree/bindings/reset/ 13040F: Documentation/devicetree/bindings/reset/
13018F: include/dt-bindings/reset/ 13041F: include/dt-bindings/reset/
13019F: include/linux/reset.h 13042F: include/linux/reset.h
13043F: include/linux/reset/
13020F: include/linux/reset-controller.h 13044F: include/linux/reset-controller.h
13021 13045
13022RESTARTABLE SEQUENCES SUPPORT 13046RESTARTABLE SEQUENCES SUPPORT
diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi
index 9d11cb759b5b..715d50c64529 100644
--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
@@ -85,10 +85,6 @@
85 power-domains = <&power RPI_POWER_DOMAIN_USB>; 85 power-domains = <&power RPI_POWER_DOMAIN_USB>;
86}; 86};
87 87
88&v3d {
89 power-domains = <&power RPI_POWER_DOMAIN_V3D>;
90};
91
92&hdmi { 88&hdmi {
93 power-domains = <&power RPI_POWER_DOMAIN_HDMI>; 89 power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
94 status = "okay"; 90 status = "okay";
diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index 31b29646b14c..9777644c6c2b 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -3,6 +3,7 @@
3#include <dt-bindings/clock/bcm2835-aux.h> 3#include <dt-bindings/clock/bcm2835-aux.h>
4#include <dt-bindings/gpio/gpio.h> 4#include <dt-bindings/gpio/gpio.h>
5#include <dt-bindings/interrupt-controller/irq.h> 5#include <dt-bindings/interrupt-controller/irq.h>
6#include <dt-bindings/soc/bcm2835-pm.h>
6 7
7/* firmware-provided startup stubs live here, where the secondary CPUs are 8/* firmware-provided startup stubs live here, where the secondary CPUs are
8 * spinning. 9 * spinning.
@@ -120,9 +121,18 @@
120 #interrupt-cells = <2>; 121 #interrupt-cells = <2>;
121 }; 122 };
122 123
123 watchdog@7e100000 { 124 pm: watchdog@7e100000 {
124 compatible = "brcm,bcm2835-pm-wdt"; 125 compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
125 reg = <0x7e100000 0x28>; 126 #power-domain-cells = <1>;
127 #reset-cells = <1>;
128 reg = <0x7e100000 0x114>,
129 <0x7e00a000 0x24>;
130 clocks = <&clocks BCM2835_CLOCK_V3D>,
131 <&clocks BCM2835_CLOCK_PERI_IMAGE>,
132 <&clocks BCM2835_CLOCK_H264>,
133 <&clocks BCM2835_CLOCK_ISP>;
134 clock-names = "v3d", "peri_image", "h264", "isp";
135 system-power-controller;
126 }; 136 };
127 137
128 clocks: cprman@7e101000 { 138 clocks: cprman@7e101000 {
@@ -629,6 +639,7 @@
629 compatible = "brcm,bcm2835-v3d"; 639 compatible = "brcm,bcm2835-v3d";
630 reg = <0x7ec00000 0x1000>; 640 reg = <0x7ec00000 0x1000>;
631 interrupts = <1 10>; 641 interrupts = <1 10>;
642 power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
632 }; 643 };
633 644
634 vc4: gpu { 645 vc4: gpu {
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index a067adf9f1ee..4ef1e55f4a0b 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -167,6 +167,7 @@ config ARCH_BCM2835
167 select BCM2835_TIMER 167 select BCM2835_TIMER
168 select PINCTRL 168 select PINCTRL
169 select PINCTRL_BCM2835 169 select PINCTRL_BCM2835
170 select MFD_CORE
170 help 171 help
171 This enables support for the Broadcom BCM2835 and BCM2836 SoCs. 172 This enables support for the Broadcom BCM2835 and BCM2836 SoCs.
172 This SoC is used in the Raspberry Pi and Roku 2 devices. 173 This SoC is used in the Raspberry Pi and Roku 2 devices.
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index afd98971d903..816da0eb6616 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -19,6 +19,7 @@
19#include <linux/of_irq.h> 19#include <linux/of_irq.h>
20#include <linux/of_platform.h> 20#include <linux/of_platform.h>
21#include <linux/reboot.h> 21#include <linux/reboot.h>
22#include <linux/reset/socfpga.h>
22 23
23#include <asm/hardware/cache-l2x0.h> 24#include <asm/hardware/cache-l2x0.h>
24#include <asm/mach/arch.h> 25#include <asm/mach/arch.h>
@@ -32,8 +33,6 @@ void __iomem *rst_manager_base_addr;
32void __iomem *sdr_ctl_base_addr; 33void __iomem *sdr_ctl_base_addr;
33unsigned long socfpga_cpu1start_addr; 34unsigned long socfpga_cpu1start_addr;
34 35
35extern void __init socfpga_reset_init(void);
36
37static void __init socfpga_sysmgr_init(void) 36static void __init socfpga_sysmgr_init(void)
38{ 37{
39 struct device_node *np; 38 struct device_node *np;
diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
index 8a7f301839c2..933b6930f024 100644
--- a/arch/arm/mach-sunxi/sunxi.c
+++ b/arch/arm/mach-sunxi/sunxi.c
@@ -14,6 +14,7 @@
14#include <linux/clocksource.h> 14#include <linux/clocksource.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/reset/sunxi.h>
17 18
18#include <asm/mach/arch.h> 19#include <asm/mach/arch.h>
19#include <asm/secure_cntvoff.h> 20#include <asm/secure_cntvoff.h>
@@ -37,7 +38,6 @@ static const char * const sun6i_board_dt_compat[] = {
37 NULL, 38 NULL,
38}; 39};
39 40
40extern void __init sun6i_reset_init(void);
41static void __init sun6i_timer_init(void) 41static void __init sun6i_timer_init(void)
42{ 42{
43 of_clk_init(NULL); 43 of_clk_init(NULL);
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index d5f85455fa62..19d7b6ff2f17 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -522,10 +522,9 @@ static int hisi_lpc_acpi_probe(struct device *hostdev)
522 522
523 if (!found) { 523 if (!found) {
524 dev_warn(hostdev, 524 dev_warn(hostdev,
525 "could not find cell for child device (%s)\n", 525 "could not find cell for child device (%s), discarding\n",
526 hid); 526 hid);
527 ret = -ENODEV; 527 continue;
528 goto fail;
529 } 528 }
530 529
531 pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO); 530 pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO);
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index d84996a4528e..db74334ca5ef 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -46,6 +46,17 @@ static const struct imx_weim_devtype imx51_weim_devtype = {
46}; 46};
47 47
48#define MAX_CS_REGS_COUNT 6 48#define MAX_CS_REGS_COUNT 6
49#define MAX_CS_COUNT 6
50#define OF_REG_SIZE 3
51
52struct cs_timing {
53 bool is_applied;
54 u32 regs[MAX_CS_REGS_COUNT];
55};
56
57struct cs_timing_state {
58 struct cs_timing cs[MAX_CS_COUNT];
59};
49 60
50static const struct of_device_id weim_id_table[] = { 61static const struct of_device_id weim_id_table[] = {
51 /* i.MX1/21 */ 62 /* i.MX1/21 */
@@ -111,21 +122,19 @@ err:
111} 122}
112 123
113/* Parse and set the timing for this device. */ 124/* Parse and set the timing for this device. */
114static int __init weim_timing_setup(struct device_node *np, void __iomem *base, 125static int __init weim_timing_setup(struct device *dev,
115 const struct imx_weim_devtype *devtype) 126 struct device_node *np, void __iomem *base,
127 const struct imx_weim_devtype *devtype,
128 struct cs_timing_state *ts)
116{ 129{
117 u32 cs_idx, value[MAX_CS_REGS_COUNT]; 130 u32 cs_idx, value[MAX_CS_REGS_COUNT];
118 int i, ret; 131 int i, ret;
132 int reg_idx, num_regs;
133 struct cs_timing *cst;
119 134
120 if (WARN_ON(devtype->cs_regs_count > MAX_CS_REGS_COUNT)) 135 if (WARN_ON(devtype->cs_regs_count > MAX_CS_REGS_COUNT))
121 return -EINVAL; 136 return -EINVAL;
122 137 if (WARN_ON(devtype->cs_count > MAX_CS_COUNT))
123 /* get the CS index from this child node's "reg" property. */
124 ret = of_property_read_u32(np, "reg", &cs_idx);
125 if (ret)
126 return ret;
127
128 if (cs_idx >= devtype->cs_count)
129 return -EINVAL; 138 return -EINVAL;
130 139
131 ret = of_property_read_u32_array(np, "fsl,weim-cs-timing", 140 ret = of_property_read_u32_array(np, "fsl,weim-cs-timing",
@@ -133,9 +142,43 @@ static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
133 if (ret) 142 if (ret)
134 return ret; 143 return ret;
135 144
136 /* set the timing for WEIM */ 145 /*
137 for (i = 0; i < devtype->cs_regs_count; i++) 146 * the child node's "reg" property may contain multiple address ranges,
138 writel(value[i], base + cs_idx * devtype->cs_stride + i * 4); 147 * extract the chip select for each.
148 */
149 num_regs = of_property_count_elems_of_size(np, "reg", OF_REG_SIZE);
150 if (num_regs < 0)
151 return num_regs;
152 if (!num_regs)
153 return -EINVAL;
154 for (reg_idx = 0; reg_idx < num_regs; reg_idx++) {
155 /* get the CS index from this child node's "reg" property. */
156 ret = of_property_read_u32_index(np, "reg",
157 reg_idx * OF_REG_SIZE, &cs_idx);
158 if (ret)
159 break;
160
161 if (cs_idx >= devtype->cs_count)
162 return -EINVAL;
163
164 /* prevent re-configuring a CS that's already been configured */
165 cst = &ts->cs[cs_idx];
166 if (cst->is_applied && memcmp(value, cst->regs,
167 devtype->cs_regs_count * sizeof(u32))) {
168 dev_err(dev, "fsl,weim-cs-timing conflict on %pOF", np);
169 return -EINVAL;
170 }
171
172 /* set the timing for WEIM */
173 for (i = 0; i < devtype->cs_regs_count; i++)
174 writel(value[i],
175 base + cs_idx * devtype->cs_stride + i * 4);
176 if (!cst->is_applied) {
177 cst->is_applied = true;
178 memcpy(cst->regs, value,
179 devtype->cs_regs_count * sizeof(u32));
180 }
181 }
139 182
140 return 0; 183 return 0;
141} 184}
@@ -148,6 +191,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
148 const struct imx_weim_devtype *devtype = of_id->data; 191 const struct imx_weim_devtype *devtype = of_id->data;
149 struct device_node *child; 192 struct device_node *child;
150 int ret, have_child = 0; 193 int ret, have_child = 0;
194 struct cs_timing_state ts = {};
151 195
152 if (devtype == &imx50_weim_devtype) { 196 if (devtype == &imx50_weim_devtype) {
153 ret = imx_weim_gpr_setup(pdev); 197 ret = imx_weim_gpr_setup(pdev);
@@ -156,7 +200,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
156 } 200 }
157 201
158 for_each_available_child_of_node(pdev->dev.of_node, child) { 202 for_each_available_child_of_node(pdev->dev.of_node, child) {
159 ret = weim_timing_setup(child, base, devtype); 203 ret = weim_timing_setup(&pdev->dev, child, base, devtype, &ts);
160 if (ret) 204 if (ret)
161 dev_warn(&pdev->dev, "%pOF set timing failed.\n", 205 dev_warn(&pdev->dev, "%pOF set timing failed.\n",
162 child); 206 child);
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index dac895dc01b9..25a7d8ffdb5d 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -424,6 +424,21 @@ config HW_RANDOM_EXYNOS
424 will be called exynos-trng. 424 will be called exynos-trng.
425 425
426 If unsure, say Y. 426 If unsure, say Y.
427
428config HW_RANDOM_OPTEE
429 tristate "OP-TEE based Random Number Generator support"
430 depends on OPTEE
431 default HW_RANDOM
432 help
433 This driver provides support for OP-TEE based Random Number
434 Generator on ARM SoCs where hardware entropy sources are not
435 accessible to normal world (Linux).
436
437 To compile this driver as a module, choose M here: the module
438 will be called optee-rng.
439
440 If unsure, say Y.
441
427endif # HW_RANDOM 442endif # HW_RANDOM
428 443
429config UML_RANDOM 444config UML_RANDOM
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index e35ec3ce3a20..7c9ef4a7667f 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -38,3 +38,4 @@ obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
38obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o 38obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o
39obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o 39obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o
40obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o 40obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o
41obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o
diff --git a/drivers/char/hw_random/optee-rng.c b/drivers/char/hw_random/optee-rng.c
new file mode 100644
index 000000000000..ddfbabaa5f8f
--- /dev/null
+++ b/drivers/char/hw_random/optee-rng.c
@@ -0,0 +1,306 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2018-2019 Linaro Ltd.
4 */
5
6#include <linux/delay.h>
7#include <linux/of.h>
8#include <linux/hw_random.h>
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/slab.h>
12#include <linux/tee_drv.h>
13#include <linux/uuid.h>
14
15#define DRIVER_NAME "optee-rng"
16
17#define TEE_ERROR_HEALTH_TEST_FAIL 0x00000001
18
19/*
20 * TA_CMD_GET_ENTROPY - Get Entropy from RNG
21 *
22 * param[0] (inout memref) - Entropy buffer memory reference
23 * param[1] unused
24 * param[2] unused
25 * param[3] unused
26 *
27 * Result:
28 * TEE_SUCCESS - Invoke command success
29 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
30 * TEE_ERROR_NOT_SUPPORTED - Requested entropy size greater than size of pool
31 * TEE_ERROR_HEALTH_TEST_FAIL - Continuous health testing failed
32 */
33#define TA_CMD_GET_ENTROPY 0x0
34
35/*
36 * TA_CMD_GET_RNG_INFO - Get RNG information
37 *
38 * param[0] (out value) - value.a: RNG data-rate in bytes per second
39 * value.b: Quality/Entropy per 1024 bit of data
40 * param[1] unused
41 * param[2] unused
42 * param[3] unused
43 *
44 * Result:
45 * TEE_SUCCESS - Invoke command success
46 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
47 */
48#define TA_CMD_GET_RNG_INFO 0x1
49
50#define MAX_ENTROPY_REQ_SZ (4 * 1024)
51
52/**
53 * struct optee_rng_private - OP-TEE Random Number Generator private data
54 * @dev: OP-TEE based RNG device.
55 * @ctx: OP-TEE context handler.
56 * @session_id: RNG TA session identifier.
57 * @data_rate: RNG data rate.
58 * @entropy_shm_pool: Memory pool shared with RNG device.
59 * @optee_rng: OP-TEE RNG driver structure.
60 */
61struct optee_rng_private {
62 struct device *dev;
63 struct tee_context *ctx;
64 u32 session_id;
65 u32 data_rate;
66 struct tee_shm *entropy_shm_pool;
67 struct hwrng optee_rng;
68};
69
70#define to_optee_rng_private(r) \
71 container_of(r, struct optee_rng_private, optee_rng)
72
73static size_t get_optee_rng_data(struct optee_rng_private *pvt_data,
74 void *buf, size_t req_size)
75{
76 int ret = 0;
77 u8 *rng_data = NULL;
78 size_t rng_size = 0;
79 struct tee_ioctl_invoke_arg inv_arg;
80 struct tee_param param[4];
81
82 memset(&inv_arg, 0, sizeof(inv_arg));
83 memset(&param, 0, sizeof(param));
84
85 /* Invoke TA_CMD_GET_ENTROPY function of Trusted App */
86 inv_arg.func = TA_CMD_GET_ENTROPY;
87 inv_arg.session = pvt_data->session_id;
88 inv_arg.num_params = 4;
89
90 /* Fill invoke cmd params */
91 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
92 param[0].u.memref.shm = pvt_data->entropy_shm_pool;
93 param[0].u.memref.size = req_size;
94 param[0].u.memref.shm_offs = 0;
95
96 ret = tee_client_invoke_func(pvt_data->ctx, &inv_arg, param);
97 if ((ret < 0) || (inv_arg.ret != 0)) {
98 dev_err(pvt_data->dev, "TA_CMD_GET_ENTROPY invoke err: %x\n",
99 inv_arg.ret);
100 return 0;
101 }
102
103 rng_data = tee_shm_get_va(pvt_data->entropy_shm_pool, 0);
104 if (IS_ERR(rng_data)) {
105 dev_err(pvt_data->dev, "tee_shm_get_va failed\n");
106 return 0;
107 }
108
109 rng_size = param[0].u.memref.size;
110 memcpy(buf, rng_data, rng_size);
111
112 return rng_size;
113}
114
115static int optee_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
116{
117 struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
118 size_t read = 0, rng_size = 0;
119 int timeout = 1;
120 u8 *data = buf;
121
122 if (max > MAX_ENTROPY_REQ_SZ)
123 max = MAX_ENTROPY_REQ_SZ;
124
125 while (read == 0) {
126 rng_size = get_optee_rng_data(pvt_data, data, (max - read));
127
128 data += rng_size;
129 read += rng_size;
130
131 if (wait) {
132 if (timeout-- == 0)
133 return read;
134 msleep((1000 * (max - read)) / pvt_data->data_rate);
135 } else {
136 return read;
137 }
138 }
139
140 return read;
141}
142
143static int optee_rng_init(struct hwrng *rng)
144{
145 struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
146 struct tee_shm *entropy_shm_pool = NULL;
147
148 entropy_shm_pool = tee_shm_alloc(pvt_data->ctx, MAX_ENTROPY_REQ_SZ,
149 TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
150 if (IS_ERR(entropy_shm_pool)) {
151 dev_err(pvt_data->dev, "tee_shm_alloc failed\n");
152 return PTR_ERR(entropy_shm_pool);
153 }
154
155 pvt_data->entropy_shm_pool = entropy_shm_pool;
156
157 return 0;
158}
159
160static void optee_rng_cleanup(struct hwrng *rng)
161{
162 struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
163
164 tee_shm_free(pvt_data->entropy_shm_pool);
165}
166
167static struct optee_rng_private pvt_data = {
168 .optee_rng = {
169 .name = DRIVER_NAME,
170 .init = optee_rng_init,
171 .cleanup = optee_rng_cleanup,
172 .read = optee_rng_read,
173 }
174};
175
176static int get_optee_rng_info(struct device *dev)
177{
178 int ret = 0;
179 struct tee_ioctl_invoke_arg inv_arg;
180 struct tee_param param[4];
181
182 memset(&inv_arg, 0, sizeof(inv_arg));
183 memset(&param, 0, sizeof(param));
184
185 /* Invoke TA_CMD_GET_RNG_INFO function of Trusted App */
186 inv_arg.func = TA_CMD_GET_RNG_INFO;
187 inv_arg.session = pvt_data.session_id;
188 inv_arg.num_params = 4;
189
190 /* Fill invoke cmd params */
191 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
192
193 ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
194 if ((ret < 0) || (inv_arg.ret != 0)) {
195 dev_err(dev, "TA_CMD_GET_RNG_INFO invoke err: %x\n",
196 inv_arg.ret);
197 return -EINVAL;
198 }
199
200 pvt_data.data_rate = param[0].u.value.a;
201 pvt_data.optee_rng.quality = param[0].u.value.b;
202
203 return 0;
204}
205
206static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
207{
208 if (ver->impl_id == TEE_IMPL_ID_OPTEE)
209 return 1;
210 else
211 return 0;
212}
213
214static int optee_rng_probe(struct device *dev)
215{
216 struct tee_client_device *rng_device = to_tee_client_device(dev);
217 int ret = 0, err = -ENODEV;
218 struct tee_ioctl_open_session_arg sess_arg;
219
220 memset(&sess_arg, 0, sizeof(sess_arg));
221
222 /* Open context with TEE driver */
223 pvt_data.ctx = tee_client_open_context(NULL, optee_ctx_match, NULL,
224 NULL);
225 if (IS_ERR(pvt_data.ctx))
226 return -ENODEV;
227
228 /* Open session with hwrng Trusted App */
229 memcpy(sess_arg.uuid, rng_device->id.uuid.b, TEE_IOCTL_UUID_LEN);
230 sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
231 sess_arg.num_params = 0;
232
233 ret = tee_client_open_session(pvt_data.ctx, &sess_arg, NULL);
234 if ((ret < 0) || (sess_arg.ret != 0)) {
235 dev_err(dev, "tee_client_open_session failed, err: %x\n",
236 sess_arg.ret);
237 err = -EINVAL;
238 goto out_ctx;
239 }
240 pvt_data.session_id = sess_arg.session;
241
242 err = get_optee_rng_info(dev);
243 if (err)
244 goto out_sess;
245
246 err = hwrng_register(&pvt_data.optee_rng);
247 if (err) {
248 dev_err(dev, "hwrng registration failed (%d)\n", err);
249 goto out_sess;
250 }
251
252 pvt_data.dev = dev;
253
254 return 0;
255
256out_sess:
257 tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
258out_ctx:
259 tee_client_close_context(pvt_data.ctx);
260
261 return err;
262}
263
264static int optee_rng_remove(struct device *dev)
265{
266 hwrng_unregister(&pvt_data.optee_rng);
267 tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
268 tee_client_close_context(pvt_data.ctx);
269
270 return 0;
271}
272
273static const struct tee_client_device_id optee_rng_id_table[] = {
274 {UUID_INIT(0xab7a617c, 0xb8e7, 0x4d8f,
275 0x83, 0x01, 0xd0, 0x9b, 0x61, 0x03, 0x6b, 0x64)},
276 {}
277};
278
279MODULE_DEVICE_TABLE(tee, optee_rng_id_table);
280
281static struct tee_client_driver optee_rng_driver = {
282 .id_table = optee_rng_id_table,
283 .driver = {
284 .name = DRIVER_NAME,
285 .bus = &tee_bus_type,
286 .probe = optee_rng_probe,
287 .remove = optee_rng_remove,
288 },
289};
290
291static int __init optee_rng_mod_init(void)
292{
293 return driver_register(&optee_rng_driver.driver);
294}
295
296static void __exit optee_rng_mod_exit(void)
297{
298 driver_unregister(&optee_rng_driver.driver);
299}
300
301module_init(optee_rng_mod_init);
302module_exit(optee_rng_mod_exit);
303
304MODULE_LICENSE("GPL v2");
305MODULE_AUTHOR("Sumit Garg <sumit.garg@linaro.org>");
306MODULE_DESCRIPTION("OP-TEE based random number generator driver");
diff --git a/drivers/clk/tegra/Kconfig b/drivers/clk/tegra/Kconfig
index 7ddacae5d0b1..1adcccfa7829 100644
--- a/drivers/clk/tegra/Kconfig
+++ b/drivers/clk/tegra/Kconfig
@@ -5,3 +5,8 @@ config TEGRA_CLK_EMC
5config CLK_TEGRA_BPMP 5config CLK_TEGRA_BPMP
6 def_bool y 6 def_bool y
7 depends on TEGRA_BPMP 7 depends on TEGRA_BPMP
8
9config TEGRA_CLK_DFLL
10 depends on ARCH_TEGRA_124_SOC || ARCH_TEGRA_210_SOC
11 select PM_OPP
12 def_bool y
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 6507acc843c7..4812e45c2214 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -20,7 +20,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
20obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o 20obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
21obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o 21obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
22obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o 22obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
23obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124-dfll-fcpu.o 23obj-$(CONFIG_TEGRA_CLK_DFLL) += clk-tegra124-dfll-fcpu.o
24obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o 24obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
25obj-y += cvb.o 25obj-y += cvb.o
26obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o 26obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
index 609e363dabf8..0400e5b1d627 100644
--- a/drivers/clk/tegra/clk-dfll.c
+++ b/drivers/clk/tegra/clk-dfll.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * clk-dfll.c - Tegra DFLL clock source common code 2 * clk-dfll.c - Tegra DFLL clock source common code
3 * 3 *
4 * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved. 4 * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved.
5 * 5 *
6 * Aleksandr Frid <afrid@nvidia.com> 6 * Aleksandr Frid <afrid@nvidia.com>
7 * Paul Walmsley <pwalmsley@nvidia.com> 7 * Paul Walmsley <pwalmsley@nvidia.com>
@@ -47,6 +47,7 @@
47#include <linux/kernel.h> 47#include <linux/kernel.h>
48#include <linux/module.h> 48#include <linux/module.h>
49#include <linux/of.h> 49#include <linux/of.h>
50#include <linux/pinctrl/consumer.h>
50#include <linux/pm_opp.h> 51#include <linux/pm_opp.h>
51#include <linux/pm_runtime.h> 52#include <linux/pm_runtime.h>
52#include <linux/regmap.h> 53#include <linux/regmap.h>
@@ -243,6 +244,12 @@ enum dfll_tune_range {
243 DFLL_TUNE_LOW = 1, 244 DFLL_TUNE_LOW = 1,
244}; 245};
245 246
247
248enum tegra_dfll_pmu_if {
249 TEGRA_DFLL_PMU_I2C = 0,
250 TEGRA_DFLL_PMU_PWM = 1,
251};
252
246/** 253/**
247 * struct dfll_rate_req - target DFLL rate request data 254 * struct dfll_rate_req - target DFLL rate request data
248 * @rate: target frequency, after the postscaling 255 * @rate: target frequency, after the postscaling
@@ -300,10 +307,19 @@ struct tegra_dfll {
300 u32 i2c_reg; 307 u32 i2c_reg;
301 u32 i2c_slave_addr; 308 u32 i2c_slave_addr;
302 309
303 /* i2c_lut array entries are regulator framework selectors */ 310 /* lut array entries are regulator framework selectors or PWM values*/
304 unsigned i2c_lut[MAX_DFLL_VOLTAGES]; 311 unsigned lut[MAX_DFLL_VOLTAGES];
305 int i2c_lut_size; 312 unsigned long lut_uv[MAX_DFLL_VOLTAGES];
306 u8 lut_min, lut_max, lut_safe; 313 int lut_size;
314 u8 lut_bottom, lut_min, lut_max, lut_safe;
315
316 /* PWM interface */
317 enum tegra_dfll_pmu_if pmu_if;
318 unsigned long pwm_rate;
319 struct pinctrl *pwm_pin;
320 struct pinctrl_state *pwm_enable_state;
321 struct pinctrl_state *pwm_disable_state;
322 u32 reg_init_uV;
307}; 323};
308 324
309#define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw) 325#define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
@@ -490,6 +506,34 @@ static void dfll_set_mode(struct tegra_dfll *td,
490} 506}
491 507
492/* 508/*
509 * DVCO rate control
510 */
511
512static unsigned long get_dvco_rate_below(struct tegra_dfll *td, u8 out_min)
513{
514 struct dev_pm_opp *opp;
515 unsigned long rate, prev_rate;
516 unsigned long uv, min_uv;
517
518 min_uv = td->lut_uv[out_min];
519 for (rate = 0, prev_rate = 0; ; rate++) {
520 opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
521 if (IS_ERR(opp))
522 break;
523
524 uv = dev_pm_opp_get_voltage(opp);
525 dev_pm_opp_put(opp);
526
527 if (uv && uv > min_uv)
528 return prev_rate;
529
530 prev_rate = rate;
531 }
532
533 return prev_rate;
534}
535
536/*
493 * DFLL-to-I2C controller interface 537 * DFLL-to-I2C controller interface
494 */ 538 */
495 539
@@ -518,6 +562,118 @@ static int dfll_i2c_set_output_enabled(struct tegra_dfll *td, bool enable)
518 return 0; 562 return 0;
519} 563}
520 564
565
566/*
567 * DFLL-to-PWM controller interface
568 */
569
570/**
571 * dfll_pwm_set_output_enabled - enable/disable PWM voltage requests
572 * @td: DFLL instance
573 * @enable: whether to enable or disable the PWM voltage requests
574 *
575 * Set the master enable control for PWM control value updates. If disabled,
576 * then the PWM signal is not driven. Also configure the PWM output pad
577 * to the appropriate state.
578 */
579static int dfll_pwm_set_output_enabled(struct tegra_dfll *td, bool enable)
580{
581 int ret;
582 u32 val, div;
583
584 if (enable) {
585 ret = pinctrl_select_state(td->pwm_pin, td->pwm_enable_state);
586 if (ret < 0) {
587 dev_err(td->dev, "setting enable state failed\n");
588 return -EINVAL;
589 }
590 val = dfll_readl(td, DFLL_OUTPUT_CFG);
591 val &= ~DFLL_OUTPUT_CFG_PWM_DIV_MASK;
592 div = DIV_ROUND_UP(td->ref_rate, td->pwm_rate);
593 val |= (div << DFLL_OUTPUT_CFG_PWM_DIV_SHIFT)
594 & DFLL_OUTPUT_CFG_PWM_DIV_MASK;
595 dfll_writel(td, val, DFLL_OUTPUT_CFG);
596 dfll_wmb(td);
597
598 val |= DFLL_OUTPUT_CFG_PWM_ENABLE;
599 dfll_writel(td, val, DFLL_OUTPUT_CFG);
600 dfll_wmb(td);
601 } else {
602 ret = pinctrl_select_state(td->pwm_pin, td->pwm_disable_state);
603 if (ret < 0)
604 dev_warn(td->dev, "setting disable state failed\n");
605
606 val = dfll_readl(td, DFLL_OUTPUT_CFG);
607 val &= ~DFLL_OUTPUT_CFG_PWM_ENABLE;
608 dfll_writel(td, val, DFLL_OUTPUT_CFG);
609 dfll_wmb(td);
610 }
611
612 return 0;
613}
614
615/**
616 * dfll_set_force_output_value - set fixed value for force output
617 * @td: DFLL instance
618 * @out_val: value to force output
619 *
620 * Set the fixed value for force output, DFLL will output this value when
621 * force output is enabled.
622 */
623static u32 dfll_set_force_output_value(struct tegra_dfll *td, u8 out_val)
624{
625 u32 val = dfll_readl(td, DFLL_OUTPUT_FORCE);
626
627 val = (val & DFLL_OUTPUT_FORCE_ENABLE) | (out_val & OUT_MASK);
628 dfll_writel(td, val, DFLL_OUTPUT_FORCE);
629 dfll_wmb(td);
630
631 return dfll_readl(td, DFLL_OUTPUT_FORCE);
632}
633
634/**
635 * dfll_set_force_output_enabled - enable/disable force output
636 * @td: DFLL instance
637 * @enable: whether to enable or disable the force output
638 *
639 * Set the enable control for fouce output with fixed value.
640 */
641static void dfll_set_force_output_enabled(struct tegra_dfll *td, bool enable)
642{
643 u32 val = dfll_readl(td, DFLL_OUTPUT_FORCE);
644
645 if (enable)
646 val |= DFLL_OUTPUT_FORCE_ENABLE;
647 else
648 val &= ~DFLL_OUTPUT_FORCE_ENABLE;
649
650 dfll_writel(td, val, DFLL_OUTPUT_FORCE);
651 dfll_wmb(td);
652}
653
654/**
655 * dfll_force_output - force output a fixed value
656 * @td: DFLL instance
657 * @out_sel: value to force output
658 *
659 * Set the fixed value for force output, DFLL will output this value.
660 */
661static int dfll_force_output(struct tegra_dfll *td, unsigned int out_sel)
662{
663 u32 val;
664
665 if (out_sel > OUT_MASK)
666 return -EINVAL;
667
668 val = dfll_set_force_output_value(td, out_sel);
669 if ((td->mode < DFLL_CLOSED_LOOP) &&
670 !(val & DFLL_OUTPUT_FORCE_ENABLE)) {
671 dfll_set_force_output_enabled(td, true);
672 }
673
674 return 0;
675}
676
521/** 677/**
522 * dfll_load_lut - load the voltage lookup table 678 * dfll_load_lut - load the voltage lookup table
523 * @td: struct tegra_dfll * 679 * @td: struct tegra_dfll *
@@ -539,7 +695,7 @@ static void dfll_load_i2c_lut(struct tegra_dfll *td)
539 lut_index = i; 695 lut_index = i;
540 696
541 val = regulator_list_hardware_vsel(td->vdd_reg, 697 val = regulator_list_hardware_vsel(td->vdd_reg,
542 td->i2c_lut[lut_index]); 698 td->lut[lut_index]);
543 __raw_writel(val, td->lut_base + i * 4); 699 __raw_writel(val, td->lut_base + i * 4);
544 } 700 }
545 701
@@ -594,24 +750,41 @@ static void dfll_init_out_if(struct tegra_dfll *td)
594{ 750{
595 u32 val; 751 u32 val;
596 752
597 td->lut_min = 0; 753 td->lut_min = td->lut_bottom;
598 td->lut_max = td->i2c_lut_size - 1; 754 td->lut_max = td->lut_size - 1;
599 td->lut_safe = td->lut_min + 1; 755 td->lut_safe = td->lut_min + (td->lut_min < td->lut_max ? 1 : 0);
756
757 /* clear DFLL_OUTPUT_CFG before setting new value */
758 dfll_writel(td, 0, DFLL_OUTPUT_CFG);
759 dfll_wmb(td);
600 760
601 dfll_i2c_writel(td, 0, DFLL_OUTPUT_CFG);
602 val = (td->lut_safe << DFLL_OUTPUT_CFG_SAFE_SHIFT) | 761 val = (td->lut_safe << DFLL_OUTPUT_CFG_SAFE_SHIFT) |
603 (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) | 762 (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) |
604 (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT); 763 (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT);
605 dfll_i2c_writel(td, val, DFLL_OUTPUT_CFG); 764 dfll_writel(td, val, DFLL_OUTPUT_CFG);
606 dfll_i2c_wmb(td); 765 dfll_wmb(td);
607 766
608 dfll_writel(td, 0, DFLL_OUTPUT_FORCE); 767 dfll_writel(td, 0, DFLL_OUTPUT_FORCE);
609 dfll_i2c_writel(td, 0, DFLL_INTR_EN); 768 dfll_i2c_writel(td, 0, DFLL_INTR_EN);
610 dfll_i2c_writel(td, DFLL_INTR_MAX_MASK | DFLL_INTR_MIN_MASK, 769 dfll_i2c_writel(td, DFLL_INTR_MAX_MASK | DFLL_INTR_MIN_MASK,
611 DFLL_INTR_STS); 770 DFLL_INTR_STS);
612 771
613 dfll_load_i2c_lut(td); 772 if (td->pmu_if == TEGRA_DFLL_PMU_PWM) {
614 dfll_init_i2c_if(td); 773 u32 vinit = td->reg_init_uV;
774 int vstep = td->soc->alignment.step_uv;
775 unsigned long vmin = td->lut_uv[0];
776
777 /* set initial voltage */
778 if ((vinit >= vmin) && vstep) {
779 unsigned int vsel;
780
781 vsel = DIV_ROUND_UP((vinit - vmin), vstep);
782 dfll_force_output(td, vsel);
783 }
784 } else {
785 dfll_load_i2c_lut(td);
786 dfll_init_i2c_if(td);
787 }
615} 788}
616 789
617/* 790/*
@@ -631,17 +804,17 @@ static void dfll_init_out_if(struct tegra_dfll *td)
631static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate) 804static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate)
632{ 805{
633 struct dev_pm_opp *opp; 806 struct dev_pm_opp *opp;
634 int i, uv; 807 int i, align_step;
635 808
636 opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate); 809 opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
637 if (IS_ERR(opp)) 810 if (IS_ERR(opp))
638 return PTR_ERR(opp); 811 return PTR_ERR(opp);
639 812
640 uv = dev_pm_opp_get_voltage(opp); 813 align_step = dev_pm_opp_get_voltage(opp) / td->soc->alignment.step_uv;
641 dev_pm_opp_put(opp); 814 dev_pm_opp_put(opp);
642 815
643 for (i = 0; i < td->i2c_lut_size; i++) { 816 for (i = td->lut_bottom; i < td->lut_size; i++) {
644 if (regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) == uv) 817 if ((td->lut_uv[i] / td->soc->alignment.step_uv) >= align_step)
645 return i; 818 return i;
646 } 819 }
647 820
@@ -863,9 +1036,14 @@ static int dfll_lock(struct tegra_dfll *td)
863 return -EINVAL; 1036 return -EINVAL;
864 } 1037 }
865 1038
866 dfll_i2c_set_output_enabled(td, true); 1039 if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
1040 dfll_pwm_set_output_enabled(td, true);
1041 else
1042 dfll_i2c_set_output_enabled(td, true);
1043
867 dfll_set_mode(td, DFLL_CLOSED_LOOP); 1044 dfll_set_mode(td, DFLL_CLOSED_LOOP);
868 dfll_set_frequency_request(td, req); 1045 dfll_set_frequency_request(td, req);
1046 dfll_set_force_output_enabled(td, false);
869 return 0; 1047 return 0;
870 1048
871 default: 1049 default:
@@ -889,7 +1067,10 @@ static int dfll_unlock(struct tegra_dfll *td)
889 case DFLL_CLOSED_LOOP: 1067 case DFLL_CLOSED_LOOP:
890 dfll_set_open_loop_config(td); 1068 dfll_set_open_loop_config(td);
891 dfll_set_mode(td, DFLL_OPEN_LOOP); 1069 dfll_set_mode(td, DFLL_OPEN_LOOP);
892 dfll_i2c_set_output_enabled(td, false); 1070 if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
1071 dfll_pwm_set_output_enabled(td, false);
1072 else
1073 dfll_i2c_set_output_enabled(td, false);
893 return 0; 1074 return 0;
894 1075
895 case DFLL_OPEN_LOOP: 1076 case DFLL_OPEN_LOOP:
@@ -1171,15 +1352,17 @@ static int attr_registers_show(struct seq_file *s, void *data)
1171 seq_printf(s, "[0x%02x] = 0x%08x\n", offs, 1352 seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
1172 dfll_i2c_readl(td, offs)); 1353 dfll_i2c_readl(td, offs));
1173 1354
1174 seq_puts(s, "\nINTEGRATED I2C CONTROLLER REGISTERS:\n"); 1355 if (td->pmu_if == TEGRA_DFLL_PMU_I2C) {
1175 offs = DFLL_I2C_CLK_DIVISOR; 1356 seq_puts(s, "\nINTEGRATED I2C CONTROLLER REGISTERS:\n");
1176 seq_printf(s, "[0x%02x] = 0x%08x\n", offs, 1357 offs = DFLL_I2C_CLK_DIVISOR;
1177 __raw_readl(td->i2c_controller_base + offs));
1178
1179 seq_puts(s, "\nLUT:\n");
1180 for (offs = 0; offs < 4 * MAX_DFLL_VOLTAGES; offs += 4)
1181 seq_printf(s, "[0x%02x] = 0x%08x\n", offs, 1358 seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
1182 __raw_readl(td->lut_base + offs)); 1359 __raw_readl(td->i2c_controller_base + offs));
1360
1361 seq_puts(s, "\nLUT:\n");
1362 for (offs = 0; offs < 4 * MAX_DFLL_VOLTAGES; offs += 4)
1363 seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
1364 __raw_readl(td->lut_base + offs));
1365 }
1183 1366
1184 return 0; 1367 return 0;
1185} 1368}
@@ -1349,15 +1532,21 @@ di_err1:
1349 */ 1532 */
1350static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV) 1533static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV)
1351{ 1534{
1352 int i, n_voltages, reg_uV; 1535 int i, n_voltages, reg_uV,reg_volt_id, align_step;
1536
1537 if (WARN_ON(td->pmu_if == TEGRA_DFLL_PMU_PWM))
1538 return -EINVAL;
1353 1539
1540 align_step = uV / td->soc->alignment.step_uv;
1354 n_voltages = regulator_count_voltages(td->vdd_reg); 1541 n_voltages = regulator_count_voltages(td->vdd_reg);
1355 for (i = 0; i < n_voltages; i++) { 1542 for (i = 0; i < n_voltages; i++) {
1356 reg_uV = regulator_list_voltage(td->vdd_reg, i); 1543 reg_uV = regulator_list_voltage(td->vdd_reg, i);
1357 if (reg_uV < 0) 1544 if (reg_uV < 0)
1358 break; 1545 break;
1359 1546
1360 if (uV == reg_uV) 1547 reg_volt_id = reg_uV / td->soc->alignment.step_uv;
1548
1549 if (align_step == reg_volt_id)
1361 return i; 1550 return i;
1362 } 1551 }
1363 1552
@@ -1371,15 +1560,21 @@ static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV)
1371 * */ 1560 * */
1372static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV) 1561static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
1373{ 1562{
1374 int i, n_voltages, reg_uV; 1563 int i, n_voltages, reg_uV, reg_volt_id, align_step;
1375 1564
1565 if (WARN_ON(td->pmu_if == TEGRA_DFLL_PMU_PWM))
1566 return -EINVAL;
1567
1568 align_step = uV / td->soc->alignment.step_uv;
1376 n_voltages = regulator_count_voltages(td->vdd_reg); 1569 n_voltages = regulator_count_voltages(td->vdd_reg);
1377 for (i = 0; i < n_voltages; i++) { 1570 for (i = 0; i < n_voltages; i++) {
1378 reg_uV = regulator_list_voltage(td->vdd_reg, i); 1571 reg_uV = regulator_list_voltage(td->vdd_reg, i);
1379 if (reg_uV < 0) 1572 if (reg_uV < 0)
1380 break; 1573 break;
1381 1574
1382 if (uV <= reg_uV) 1575 reg_volt_id = reg_uV / td->soc->alignment.step_uv;
1576
1577 if (align_step <= reg_volt_id)
1383 return i; 1578 return i;
1384 } 1579 }
1385 1580
@@ -1387,9 +1582,61 @@ static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
1387 return -EINVAL; 1582 return -EINVAL;
1388} 1583}
1389 1584
1585/*
1586 * dfll_build_pwm_lut - build the PWM regulator lookup table
1587 * @td: DFLL instance
1588 * @v_max: Vmax from OPP table
1589 *
1590 * Look-up table in h/w is ignored when PWM is used as DFLL interface to PMIC.
1591 * In this case closed loop output is controlling duty cycle directly. The s/w
1592 * look-up that maps PWM duty cycle to voltage is still built by this function.
1593 */
1594static int dfll_build_pwm_lut(struct tegra_dfll *td, unsigned long v_max)
1595{
1596 int i;
1597 unsigned long rate, reg_volt;
1598 u8 lut_bottom = MAX_DFLL_VOLTAGES;
1599 int v_min = td->soc->cvb->min_millivolts * 1000;
1600
1601 for (i = 0; i < MAX_DFLL_VOLTAGES; i++) {
1602 reg_volt = td->lut_uv[i];
1603
1604 /* since opp voltage is exact mv */
1605 reg_volt = (reg_volt / 1000) * 1000;
1606 if (reg_volt > v_max)
1607 break;
1608
1609 td->lut[i] = i;
1610 if ((lut_bottom == MAX_DFLL_VOLTAGES) && (reg_volt >= v_min))
1611 lut_bottom = i;
1612 }
1613
1614 /* determine voltage boundaries */
1615 td->lut_size = i;
1616 if ((lut_bottom == MAX_DFLL_VOLTAGES) ||
1617 (lut_bottom + 1 >= td->lut_size)) {
1618 dev_err(td->dev, "no voltage above DFLL minimum %d mV\n",
1619 td->soc->cvb->min_millivolts);
1620 return -EINVAL;
1621 }
1622 td->lut_bottom = lut_bottom;
1623
1624 /* determine rate boundaries */
1625 rate = get_dvco_rate_below(td, td->lut_bottom);
1626 if (!rate) {
1627 dev_err(td->dev, "no opp below DFLL minimum voltage %d mV\n",
1628 td->soc->cvb->min_millivolts);
1629 return -EINVAL;
1630 }
1631 td->dvco_rate_min = rate;
1632
1633 return 0;
1634}
1635
1390/** 1636/**
1391 * dfll_build_i2c_lut - build the I2C voltage register lookup table 1637 * dfll_build_i2c_lut - build the I2C voltage register lookup table
1392 * @td: DFLL instance 1638 * @td: DFLL instance
1639 * @v_max: Vmax from OPP table
1393 * 1640 *
1394 * The DFLL hardware has 33 bytes of look-up table RAM that must be filled with 1641 * The DFLL hardware has 33 bytes of look-up table RAM that must be filled with
1395 * PMIC voltage register values that span the entire DFLL operating range. 1642 * PMIC voltage register values that span the entire DFLL operating range.
@@ -1397,33 +1644,24 @@ static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
1397 * the soc-specific platform driver (td->soc->opp_dev) and the PMIC 1644 * the soc-specific platform driver (td->soc->opp_dev) and the PMIC
1398 * register-to-voltage mapping queried from the regulator framework. 1645 * register-to-voltage mapping queried from the regulator framework.
1399 * 1646 *
1400 * On success, fills in td->i2c_lut and returns 0, or -err on failure. 1647 * On success, fills in td->lut and returns 0, or -err on failure.
1401 */ 1648 */
1402static int dfll_build_i2c_lut(struct tegra_dfll *td) 1649static int dfll_build_i2c_lut(struct tegra_dfll *td, unsigned long v_max)
1403{ 1650{
1651 unsigned long rate, v, v_opp;
1404 int ret = -EINVAL; 1652 int ret = -EINVAL;
1405 int j, v, v_max, v_opp; 1653 int j, selector, lut;
1406 int selector;
1407 unsigned long rate;
1408 struct dev_pm_opp *opp;
1409 int lut;
1410
1411 rate = ULONG_MAX;
1412 opp = dev_pm_opp_find_freq_floor(td->soc->dev, &rate);
1413 if (IS_ERR(opp)) {
1414 dev_err(td->dev, "couldn't get vmax opp, empty opp table?\n");
1415 goto out;
1416 }
1417 v_max = dev_pm_opp_get_voltage(opp);
1418 dev_pm_opp_put(opp);
1419 1654
1420 v = td->soc->cvb->min_millivolts * 1000; 1655 v = td->soc->cvb->min_millivolts * 1000;
1421 lut = find_vdd_map_entry_exact(td, v); 1656 lut = find_vdd_map_entry_exact(td, v);
1422 if (lut < 0) 1657 if (lut < 0)
1423 goto out; 1658 goto out;
1424 td->i2c_lut[0] = lut; 1659 td->lut[0] = lut;
1660 td->lut_bottom = 0;
1425 1661
1426 for (j = 1, rate = 0; ; rate++) { 1662 for (j = 1, rate = 0; ; rate++) {
1663 struct dev_pm_opp *opp;
1664
1427 opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate); 1665 opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
1428 if (IS_ERR(opp)) 1666 if (IS_ERR(opp))
1429 break; 1667 break;
@@ -1435,39 +1673,64 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
1435 dev_pm_opp_put(opp); 1673 dev_pm_opp_put(opp);
1436 1674
1437 for (;;) { 1675 for (;;) {
1438 v += max(1, (v_max - v) / (MAX_DFLL_VOLTAGES - j)); 1676 v += max(1UL, (v_max - v) / (MAX_DFLL_VOLTAGES - j));
1439 if (v >= v_opp) 1677 if (v >= v_opp)
1440 break; 1678 break;
1441 1679
1442 selector = find_vdd_map_entry_min(td, v); 1680 selector = find_vdd_map_entry_min(td, v);
1443 if (selector < 0) 1681 if (selector < 0)
1444 goto out; 1682 goto out;
1445 if (selector != td->i2c_lut[j - 1]) 1683 if (selector != td->lut[j - 1])
1446 td->i2c_lut[j++] = selector; 1684 td->lut[j++] = selector;
1447 } 1685 }
1448 1686
1449 v = (j == MAX_DFLL_VOLTAGES - 1) ? v_max : v_opp; 1687 v = (j == MAX_DFLL_VOLTAGES - 1) ? v_max : v_opp;
1450 selector = find_vdd_map_entry_exact(td, v); 1688 selector = find_vdd_map_entry_exact(td, v);
1451 if (selector < 0) 1689 if (selector < 0)
1452 goto out; 1690 goto out;
1453 if (selector != td->i2c_lut[j - 1]) 1691 if (selector != td->lut[j - 1])
1454 td->i2c_lut[j++] = selector; 1692 td->lut[j++] = selector;
1455 1693
1456 if (v >= v_max) 1694 if (v >= v_max)
1457 break; 1695 break;
1458 } 1696 }
1459 td->i2c_lut_size = j; 1697 td->lut_size = j;
1460 1698
1461 if (!td->dvco_rate_min) 1699 if (!td->dvco_rate_min)
1462 dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n", 1700 dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
1463 td->soc->cvb->min_millivolts); 1701 td->soc->cvb->min_millivolts);
1464 else 1702 else {
1465 ret = 0; 1703 ret = 0;
1704 for (j = 0; j < td->lut_size; j++)
1705 td->lut_uv[j] =
1706 regulator_list_voltage(td->vdd_reg,
1707 td->lut[j]);
1708 }
1466 1709
1467out: 1710out:
1468 return ret; 1711 return ret;
1469} 1712}
1470 1713
1714static int dfll_build_lut(struct tegra_dfll *td)
1715{
1716 unsigned long rate, v_max;
1717 struct dev_pm_opp *opp;
1718
1719 rate = ULONG_MAX;
1720 opp = dev_pm_opp_find_freq_floor(td->soc->dev, &rate);
1721 if (IS_ERR(opp)) {
1722 dev_err(td->dev, "couldn't get vmax opp, empty opp table?\n");
1723 return -EINVAL;
1724 }
1725 v_max = dev_pm_opp_get_voltage(opp);
1726 dev_pm_opp_put(opp);
1727
1728 if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
1729 return dfll_build_pwm_lut(td, v_max);
1730 else
1731 return dfll_build_i2c_lut(td, v_max);
1732}
1733
1471/** 1734/**
1472 * read_dt_param - helper function for reading required parameters from the DT 1735 * read_dt_param - helper function for reading required parameters from the DT
1473 * @td: DFLL instance 1736 * @td: DFLL instance
@@ -1526,11 +1789,56 @@ static int dfll_fetch_i2c_params(struct tegra_dfll *td)
1526 } 1789 }
1527 td->i2c_reg = vsel_reg; 1790 td->i2c_reg = vsel_reg;
1528 1791
1529 ret = dfll_build_i2c_lut(td); 1792 return 0;
1530 if (ret) { 1793}
1531 dev_err(td->dev, "couldn't build I2C LUT\n"); 1794
1795static int dfll_fetch_pwm_params(struct tegra_dfll *td)
1796{
1797 int ret, i;
1798 u32 pwm_period;
1799
1800 if (!td->soc->alignment.step_uv || !td->soc->alignment.offset_uv) {
1801 dev_err(td->dev,
1802 "Missing step or alignment info for PWM regulator");
1803 return -EINVAL;
1804 }
1805 for (i = 0; i < MAX_DFLL_VOLTAGES; i++)
1806 td->lut_uv[i] = td->soc->alignment.offset_uv +
1807 i * td->soc->alignment.step_uv;
1808
1809 ret = read_dt_param(td, "nvidia,pwm-tristate-microvolts",
1810 &td->reg_init_uV);
1811 if (!ret) {
1812 dev_err(td->dev, "couldn't get initialized voltage\n");
1813 return ret;
1814 }
1815
1816 ret = read_dt_param(td, "nvidia,pwm-period-nanoseconds", &pwm_period);
1817 if (!ret) {
1818 dev_err(td->dev, "couldn't get PWM period\n");
1532 return ret; 1819 return ret;
1533 } 1820 }
1821 td->pwm_rate = (NSEC_PER_SEC / pwm_period) * (MAX_DFLL_VOLTAGES - 1);
1822
1823 td->pwm_pin = devm_pinctrl_get(td->dev);
1824 if (IS_ERR(td->pwm_pin)) {
1825 dev_err(td->dev, "DT: missing pinctrl device\n");
1826 return PTR_ERR(td->pwm_pin);
1827 }
1828
1829 td->pwm_enable_state = pinctrl_lookup_state(td->pwm_pin,
1830 "dvfs_pwm_enable");
1831 if (IS_ERR(td->pwm_enable_state)) {
1832 dev_err(td->dev, "DT: missing pwm enabled state\n");
1833 return PTR_ERR(td->pwm_enable_state);
1834 }
1835
1836 td->pwm_disable_state = pinctrl_lookup_state(td->pwm_pin,
1837 "dvfs_pwm_disable");
1838 if (IS_ERR(td->pwm_disable_state)) {
1839 dev_err(td->dev, "DT: missing pwm disabled state\n");
1840 return PTR_ERR(td->pwm_disable_state);
1841 }
1534 1842
1535 return 0; 1843 return 0;
1536} 1844}
@@ -1597,16 +1905,6 @@ int tegra_dfll_register(struct platform_device *pdev,
1597 1905
1598 td->soc = soc; 1906 td->soc = soc;
1599 1907
1600 td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu");
1601 if (IS_ERR(td->vdd_reg)) {
1602 ret = PTR_ERR(td->vdd_reg);
1603 if (ret != -EPROBE_DEFER)
1604 dev_err(td->dev, "couldn't get vdd_cpu regulator: %d\n",
1605 ret);
1606
1607 return ret;
1608 }
1609
1610 td->dvco_rst = devm_reset_control_get(td->dev, "dvco"); 1908 td->dvco_rst = devm_reset_control_get(td->dev, "dvco");
1611 if (IS_ERR(td->dvco_rst)) { 1909 if (IS_ERR(td->dvco_rst)) {
1612 dev_err(td->dev, "couldn't get dvco reset\n"); 1910 dev_err(td->dev, "couldn't get dvco reset\n");
@@ -1619,10 +1917,27 @@ int tegra_dfll_register(struct platform_device *pdev,
1619 return ret; 1917 return ret;
1620 } 1918 }
1621 1919
1622 ret = dfll_fetch_i2c_params(td); 1920 if (of_property_read_bool(td->dev->of_node, "nvidia,pwm-to-pmic")) {
1921 td->pmu_if = TEGRA_DFLL_PMU_PWM;
1922 ret = dfll_fetch_pwm_params(td);
1923 } else {
1924 td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu");
1925 if (IS_ERR(td->vdd_reg)) {
1926 dev_err(td->dev, "couldn't get vdd_cpu regulator\n");
1927 return PTR_ERR(td->vdd_reg);
1928 }
1929 td->pmu_if = TEGRA_DFLL_PMU_I2C;
1930 ret = dfll_fetch_i2c_params(td);
1931 }
1623 if (ret) 1932 if (ret)
1624 return ret; 1933 return ret;
1625 1934
1935 ret = dfll_build_lut(td);
1936 if (ret) {
1937 dev_err(td->dev, "couldn't build LUT\n");
1938 return ret;
1939 }
1940
1626 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1941 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1627 if (!mem) { 1942 if (!mem) {
1628 dev_err(td->dev, "no control register resource\n"); 1943 dev_err(td->dev, "no control register resource\n");
diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h
index 83352c8078f2..85d0d95223f3 100644
--- a/drivers/clk/tegra/clk-dfll.h
+++ b/drivers/clk/tegra/clk-dfll.h
@@ -1,6 +1,6 @@
1/* 1/*
2 * clk-dfll.h - prototypes and macros for the Tegra DFLL clocksource driver 2 * clk-dfll.h - prototypes and macros for the Tegra DFLL clocksource driver
3 * Copyright (C) 2013 NVIDIA Corporation. All rights reserved. 3 * Copyright (C) 2013-2019 NVIDIA Corporation. All rights reserved.
4 * 4 *
5 * Aleksandr Frid <afrid@nvidia.com> 5 * Aleksandr Frid <afrid@nvidia.com>
6 * Paul Walmsley <pwalmsley@nvidia.com> 6 * Paul Walmsley <pwalmsley@nvidia.com>
@@ -22,11 +22,14 @@
22#include <linux/reset.h> 22#include <linux/reset.h>
23#include <linux/types.h> 23#include <linux/types.h>
24 24
25#include "cvb.h"
26
25/** 27/**
26 * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver 28 * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver
27 * @dev: struct device * that holds the OPP table for the DFLL 29 * @dev: struct device * that holds the OPP table for the DFLL
28 * @max_freq: maximum frequency supported on this SoC 30 * @max_freq: maximum frequency supported on this SoC
29 * @cvb: CPU frequency table for this SoC 31 * @cvb: CPU frequency table for this SoC
32 * @alignment: parameters of the regulator step and offset
30 * @init_clock_trimmers: callback to initialize clock trimmers 33 * @init_clock_trimmers: callback to initialize clock trimmers
31 * @set_clock_trimmers_high: callback to tune clock trimmers for high voltage 34 * @set_clock_trimmers_high: callback to tune clock trimmers for high voltage
32 * @set_clock_trimmers_low: callback to tune clock trimmers for low voltage 35 * @set_clock_trimmers_low: callback to tune clock trimmers for low voltage
@@ -35,6 +38,7 @@ struct tegra_dfll_soc_data {
35 struct device *dev; 38 struct device *dev;
36 unsigned long max_freq; 39 unsigned long max_freq;
37 const struct cvb_table *cvb; 40 const struct cvb_table *cvb;
41 struct rail_alignment alignment;
38 42
39 void (*init_clock_trimmers)(void); 43 void (*init_clock_trimmers)(void);
40 void (*set_clock_trimmers_high)(void); 44 void (*set_clock_trimmers_high)(void);
diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
index edc31bb56674..e8ec42bf8638 100644
--- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
+++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Tegra124 DFLL FCPU clock source driver 2 * Tegra124 DFLL FCPU clock source driver
3 * 3 *
4 * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved. 4 * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved.
5 * 5 *
6 * Aleksandr Frid <afrid@nvidia.com> 6 * Aleksandr Frid <afrid@nvidia.com>
7 * Paul Walmsley <pwalmsley@nvidia.com> 7 * Paul Walmsley <pwalmsley@nvidia.com>
@@ -21,15 +21,24 @@
21#include <linux/err.h> 21#include <linux/err.h>
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/of_device.h>
24#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/regulator/consumer.h>
25#include <soc/tegra/fuse.h> 27#include <soc/tegra/fuse.h>
26 28
27#include "clk.h" 29#include "clk.h"
28#include "clk-dfll.h" 30#include "clk-dfll.h"
29#include "cvb.h" 31#include "cvb.h"
30 32
33struct dfll_fcpu_data {
34 const unsigned long *cpu_max_freq_table;
35 unsigned int cpu_max_freq_table_size;
36 const struct cvb_table *cpu_cvb_tables;
37 unsigned int cpu_cvb_tables_size;
38};
39
31/* Maximum CPU frequency, indexed by CPU speedo id */ 40/* Maximum CPU frequency, indexed by CPU speedo id */
32static const unsigned long cpu_max_freq_table[] = { 41static const unsigned long tegra124_cpu_max_freq_table[] = {
33 [0] = 2014500000UL, 42 [0] = 2014500000UL,
34 [1] = 2320500000UL, 43 [1] = 2320500000UL,
35 [2] = 2116500000UL, 44 [2] = 2116500000UL,
@@ -42,9 +51,6 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
42 .process_id = -1, 51 .process_id = -1,
43 .min_millivolts = 900, 52 .min_millivolts = 900,
44 .max_millivolts = 1260, 53 .max_millivolts = 1260,
45 .alignment = {
46 .step_uv = 10000, /* 10mV */
47 },
48 .speedo_scale = 100, 54 .speedo_scale = 100,
49 .voltage_scale = 1000, 55 .voltage_scale = 1000,
50 .entries = { 56 .entries = {
@@ -82,16 +88,493 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
82 }, 88 },
83}; 89};
84 90
91static const unsigned long tegra210_cpu_max_freq_table[] = {
92 [0] = 1912500000UL,
93 [1] = 1912500000UL,
94 [2] = 2218500000UL,
95 [3] = 1785000000UL,
96 [4] = 1632000000UL,
97 [5] = 1912500000UL,
98 [6] = 2014500000UL,
99 [7] = 1734000000UL,
100 [8] = 1683000000UL,
101 [9] = 1555500000UL,
102 [10] = 1504500000UL,
103};
104
105#define CPU_CVB_TABLE \
106 .speedo_scale = 100, \
107 .voltage_scale = 1000, \
108 .entries = { \
109 { 204000000UL, { 1007452, -23865, 370 } }, \
110 { 306000000UL, { 1052709, -24875, 370 } }, \
111 { 408000000UL, { 1099069, -25895, 370 } }, \
112 { 510000000UL, { 1146534, -26905, 370 } }, \
113 { 612000000UL, { 1195102, -27915, 370 } }, \
114 { 714000000UL, { 1244773, -28925, 370 } }, \
115 { 816000000UL, { 1295549, -29935, 370 } }, \
116 { 918000000UL, { 1347428, -30955, 370 } }, \
117 { 1020000000UL, { 1400411, -31965, 370 } }, \
118 { 1122000000UL, { 1454497, -32975, 370 } }, \
119 { 1224000000UL, { 1509687, -33985, 370 } }, \
120 { 1326000000UL, { 1565981, -35005, 370 } }, \
121 { 1428000000UL, { 1623379, -36015, 370 } }, \
122 { 1530000000UL, { 1681880, -37025, 370 } }, \
123 { 1632000000UL, { 1741485, -38035, 370 } }, \
124 { 1734000000UL, { 1802194, -39055, 370 } }, \
125 { 1836000000UL, { 1864006, -40065, 370 } }, \
126 { 1912500000UL, { 1910780, -40815, 370 } }, \
127 { 2014500000UL, { 1227000, 0, 0 } }, \
128 { 2218500000UL, { 1227000, 0, 0 } }, \
129 { 0UL, { 0, 0, 0 } }, \
130 }
131
132#define CPU_CVB_TABLE_XA \
133 .speedo_scale = 100, \
134 .voltage_scale = 1000, \
135 .entries = { \
136 { 204000000UL, { 1250024, -39785, 565 } }, \
137 { 306000000UL, { 1297556, -41145, 565 } }, \
138 { 408000000UL, { 1346718, -42505, 565 } }, \
139 { 510000000UL, { 1397511, -43855, 565 } }, \
140 { 612000000UL, { 1449933, -45215, 565 } }, \
141 { 714000000UL, { 1503986, -46575, 565 } }, \
142 { 816000000UL, { 1559669, -47935, 565 } }, \
143 { 918000000UL, { 1616982, -49295, 565 } }, \
144 { 1020000000UL, { 1675926, -50645, 565 } }, \
145 { 1122000000UL, { 1736500, -52005, 565 } }, \
146 { 1224000000UL, { 1798704, -53365, 565 } }, \
147 { 1326000000UL, { 1862538, -54725, 565 } }, \
148 { 1428000000UL, { 1928003, -56085, 565 } }, \
149 { 1530000000UL, { 1995097, -57435, 565 } }, \
150 { 1606500000UL, { 2046149, -58445, 565 } }, \
151 { 1632000000UL, { 2063822, -58795, 565 } }, \
152 { 0UL, { 0, 0, 0 } }, \
153 }
154
155#define CPU_CVB_TABLE_EUCM1 \
156 .speedo_scale = 100, \
157 .voltage_scale = 1000, \
158 .entries = { \
159 { 204000000UL, { 734429, 0, 0 } }, \
160 { 306000000UL, { 768191, 0, 0 } }, \
161 { 408000000UL, { 801953, 0, 0 } }, \
162 { 510000000UL, { 835715, 0, 0 } }, \
163 { 612000000UL, { 869477, 0, 0 } }, \
164 { 714000000UL, { 903239, 0, 0 } }, \
165 { 816000000UL, { 937001, 0, 0 } }, \
166 { 918000000UL, { 970763, 0, 0 } }, \
167 { 1020000000UL, { 1004525, 0, 0 } }, \
168 { 1122000000UL, { 1038287, 0, 0 } }, \
169 { 1224000000UL, { 1072049, 0, 0 } }, \
170 { 1326000000UL, { 1105811, 0, 0 } }, \
171 { 1428000000UL, { 1130000, 0, 0 } }, \
172 { 1555500000UL, { 1130000, 0, 0 } }, \
173 { 1632000000UL, { 1170000, 0, 0 } }, \
174 { 1734000000UL, { 1227500, 0, 0 } }, \
175 { 0UL, { 0, 0, 0 } }, \
176 }
177
178#define CPU_CVB_TABLE_EUCM2 \
179 .speedo_scale = 100, \
180 .voltage_scale = 1000, \
181 .entries = { \
182 { 204000000UL, { 742283, 0, 0 } }, \
183 { 306000000UL, { 776249, 0, 0 } }, \
184 { 408000000UL, { 810215, 0, 0 } }, \
185 { 510000000UL, { 844181, 0, 0 } }, \
186 { 612000000UL, { 878147, 0, 0 } }, \
187 { 714000000UL, { 912113, 0, 0 } }, \
188 { 816000000UL, { 946079, 0, 0 } }, \
189 { 918000000UL, { 980045, 0, 0 } }, \
190 { 1020000000UL, { 1014011, 0, 0 } }, \
191 { 1122000000UL, { 1047977, 0, 0 } }, \
192 { 1224000000UL, { 1081943, 0, 0 } }, \
193 { 1326000000UL, { 1090000, 0, 0 } }, \
194 { 1479000000UL, { 1090000, 0, 0 } }, \
195 { 1555500000UL, { 1162000, 0, 0 } }, \
196 { 1683000000UL, { 1195000, 0, 0 } }, \
197 { 0UL, { 0, 0, 0 } }, \
198 }
199
200#define CPU_CVB_TABLE_EUCM2_JOINT_RAIL \
201 .speedo_scale = 100, \
202 .voltage_scale = 1000, \
203 .entries = { \
204 { 204000000UL, { 742283, 0, 0 } }, \
205 { 306000000UL, { 776249, 0, 0 } }, \
206 { 408000000UL, { 810215, 0, 0 } }, \
207 { 510000000UL, { 844181, 0, 0 } }, \
208 { 612000000UL, { 878147, 0, 0 } }, \
209 { 714000000UL, { 912113, 0, 0 } }, \
210 { 816000000UL, { 946079, 0, 0 } }, \
211 { 918000000UL, { 980045, 0, 0 } }, \
212 { 1020000000UL, { 1014011, 0, 0 } }, \
213 { 1122000000UL, { 1047977, 0, 0 } }, \
214 { 1224000000UL, { 1081943, 0, 0 } }, \
215 { 1326000000UL, { 1090000, 0, 0 } }, \
216 { 1479000000UL, { 1090000, 0, 0 } }, \
217 { 1504500000UL, { 1120000, 0, 0 } }, \
218 { 0UL, { 0, 0, 0 } }, \
219 }
220
221#define CPU_CVB_TABLE_ODN \
222 .speedo_scale = 100, \
223 .voltage_scale = 1000, \
224 .entries = { \
225 { 204000000UL, { 721094, 0, 0 } }, \
226 { 306000000UL, { 754040, 0, 0 } }, \
227 { 408000000UL, { 786986, 0, 0 } }, \
228 { 510000000UL, { 819932, 0, 0 } }, \
229 { 612000000UL, { 852878, 0, 0 } }, \
230 { 714000000UL, { 885824, 0, 0 } }, \
231 { 816000000UL, { 918770, 0, 0 } }, \
232 { 918000000UL, { 915716, 0, 0 } }, \
233 { 1020000000UL, { 984662, 0, 0 } }, \
234 { 1122000000UL, { 1017608, 0, 0 } }, \
235 { 1224000000UL, { 1050554, 0, 0 } }, \
236 { 1326000000UL, { 1083500, 0, 0 } }, \
237 { 1428000000UL, { 1116446, 0, 0 } }, \
238 { 1581000000UL, { 1130000, 0, 0 } }, \
239 { 1683000000UL, { 1168000, 0, 0 } }, \
240 { 1785000000UL, { 1227500, 0, 0 } }, \
241 { 0UL, { 0, 0, 0 } }, \
242 }
243
244static struct cvb_table tegra210_cpu_cvb_tables[] = {
245 {
246 .speedo_id = 10,
247 .process_id = 0,
248 .min_millivolts = 840,
249 .max_millivolts = 1120,
250 CPU_CVB_TABLE_EUCM2_JOINT_RAIL,
251 .cpu_dfll_data = {
252 .tune0_low = 0xffead0ff,
253 .tune0_high = 0xffead0ff,
254 .tune1 = 0x20091d9,
255 .tune_high_min_millivolts = 864,
256 }
257 },
258 {
259 .speedo_id = 10,
260 .process_id = 1,
261 .min_millivolts = 840,
262 .max_millivolts = 1120,
263 CPU_CVB_TABLE_EUCM2_JOINT_RAIL,
264 .cpu_dfll_data = {
265 .tune0_low = 0xffead0ff,
266 .tune0_high = 0xffead0ff,
267 .tune1 = 0x20091d9,
268 .tune_high_min_millivolts = 864,
269 }
270 },
271 {
272 .speedo_id = 9,
273 .process_id = 0,
274 .min_millivolts = 900,
275 .max_millivolts = 1162,
276 CPU_CVB_TABLE_EUCM2,
277 .cpu_dfll_data = {
278 .tune0_low = 0xffead0ff,
279 .tune0_high = 0xffead0ff,
280 .tune1 = 0x20091d9,
281 }
282 },
283 {
284 .speedo_id = 9,
285 .process_id = 1,
286 .min_millivolts = 900,
287 .max_millivolts = 1162,
288 CPU_CVB_TABLE_EUCM2,
289 .cpu_dfll_data = {
290 .tune0_low = 0xffead0ff,
291 .tune0_high = 0xffead0ff,
292 .tune1 = 0x20091d9,
293 }
294 },
295 {
296 .speedo_id = 8,
297 .process_id = 0,
298 .min_millivolts = 900,
299 .max_millivolts = 1195,
300 CPU_CVB_TABLE_EUCM2,
301 .cpu_dfll_data = {
302 .tune0_low = 0xffead0ff,
303 .tune0_high = 0xffead0ff,
304 .tune1 = 0x20091d9,
305 }
306 },
307 {
308 .speedo_id = 8,
309 .process_id = 1,
310 .min_millivolts = 900,
311 .max_millivolts = 1195,
312 CPU_CVB_TABLE_EUCM2,
313 .cpu_dfll_data = {
314 .tune0_low = 0xffead0ff,
315 .tune0_high = 0xffead0ff,
316 .tune1 = 0x20091d9,
317 }
318 },
319 {
320 .speedo_id = 7,
321 .process_id = 0,
322 .min_millivolts = 841,
323 .max_millivolts = 1227,
324 CPU_CVB_TABLE_EUCM1,
325 .cpu_dfll_data = {
326 .tune0_low = 0xffead0ff,
327 .tune0_high = 0xffead0ff,
328 .tune1 = 0x20091d9,
329 .tune_high_min_millivolts = 864,
330 }
331 },
332 {
333 .speedo_id = 7,
334 .process_id = 1,
335 .min_millivolts = 841,
336 .max_millivolts = 1227,
337 CPU_CVB_TABLE_EUCM1,
338 .cpu_dfll_data = {
339 .tune0_low = 0xffead0ff,
340 .tune0_high = 0xffead0ff,
341 .tune1 = 0x20091d9,
342 .tune_high_min_millivolts = 864,
343 }
344 },
345 {
346 .speedo_id = 6,
347 .process_id = 0,
348 .min_millivolts = 870,
349 .max_millivolts = 1150,
350 CPU_CVB_TABLE,
351 .cpu_dfll_data = {
352 .tune0_low = 0xffead0ff,
353 .tune1 = 0x20091d9,
354 }
355 },
356 {
357 .speedo_id = 6,
358 .process_id = 1,
359 .min_millivolts = 870,
360 .max_millivolts = 1150,
361 CPU_CVB_TABLE,
362 .cpu_dfll_data = {
363 .tune0_low = 0xffead0ff,
364 .tune1 = 0x25501d0,
365 }
366 },
367 {
368 .speedo_id = 5,
369 .process_id = 0,
370 .min_millivolts = 818,
371 .max_millivolts = 1227,
372 CPU_CVB_TABLE,
373 .cpu_dfll_data = {
374 .tune0_low = 0xffead0ff,
375 .tune0_high = 0xffead0ff,
376 .tune1 = 0x20091d9,
377 .tune_high_min_millivolts = 864,
378 }
379 },
380 {
381 .speedo_id = 5,
382 .process_id = 1,
383 .min_millivolts = 818,
384 .max_millivolts = 1227,
385 CPU_CVB_TABLE,
386 .cpu_dfll_data = {
387 .tune0_low = 0xffead0ff,
388 .tune0_high = 0xffead0ff,
389 .tune1 = 0x25501d0,
390 .tune_high_min_millivolts = 864,
391 }
392 },
393 {
394 .speedo_id = 4,
395 .process_id = -1,
396 .min_millivolts = 918,
397 .max_millivolts = 1113,
398 CPU_CVB_TABLE_XA,
399 .cpu_dfll_data = {
400 .tune0_low = 0xffead0ff,
401 .tune1 = 0x17711BD,
402 }
403 },
404 {
405 .speedo_id = 3,
406 .process_id = 0,
407 .min_millivolts = 825,
408 .max_millivolts = 1227,
409 CPU_CVB_TABLE_ODN,
410 .cpu_dfll_data = {
411 .tune0_low = 0xffead0ff,
412 .tune0_high = 0xffead0ff,
413 .tune1 = 0x20091d9,
414 .tune_high_min_millivolts = 864,
415 }
416 },
417 {
418 .speedo_id = 3,
419 .process_id = 1,
420 .min_millivolts = 825,
421 .max_millivolts = 1227,
422 CPU_CVB_TABLE_ODN,
423 .cpu_dfll_data = {
424 .tune0_low = 0xffead0ff,
425 .tune0_high = 0xffead0ff,
426 .tune1 = 0x25501d0,
427 .tune_high_min_millivolts = 864,
428 }
429 },
430 {
431 .speedo_id = 2,
432 .process_id = 0,
433 .min_millivolts = 870,
434 .max_millivolts = 1227,
435 CPU_CVB_TABLE,
436 .cpu_dfll_data = {
437 .tune0_low = 0xffead0ff,
438 .tune1 = 0x20091d9,
439 }
440 },
441 {
442 .speedo_id = 2,
443 .process_id = 1,
444 .min_millivolts = 870,
445 .max_millivolts = 1227,
446 CPU_CVB_TABLE,
447 .cpu_dfll_data = {
448 .tune0_low = 0xffead0ff,
449 .tune1 = 0x25501d0,
450 }
451 },
452 {
453 .speedo_id = 1,
454 .process_id = 0,
455 .min_millivolts = 837,
456 .max_millivolts = 1227,
457 CPU_CVB_TABLE,
458 .cpu_dfll_data = {
459 .tune0_low = 0xffead0ff,
460 .tune0_high = 0xffead0ff,
461 .tune1 = 0x20091d9,
462 .tune_high_min_millivolts = 864,
463 }
464 },
465 {
466 .speedo_id = 1,
467 .process_id = 1,
468 .min_millivolts = 837,
469 .max_millivolts = 1227,
470 CPU_CVB_TABLE,
471 .cpu_dfll_data = {
472 .tune0_low = 0xffead0ff,
473 .tune0_high = 0xffead0ff,
474 .tune1 = 0x25501d0,
475 .tune_high_min_millivolts = 864,
476 }
477 },
478 {
479 .speedo_id = 0,
480 .process_id = 0,
481 .min_millivolts = 850,
482 .max_millivolts = 1170,
483 CPU_CVB_TABLE,
484 .cpu_dfll_data = {
485 .tune0_low = 0xffead0ff,
486 .tune0_high = 0xffead0ff,
487 .tune1 = 0x20091d9,
488 .tune_high_min_millivolts = 864,
489 }
490 },
491 {
492 .speedo_id = 0,
493 .process_id = 1,
494 .min_millivolts = 850,
495 .max_millivolts = 1170,
496 CPU_CVB_TABLE,
497 .cpu_dfll_data = {
498 .tune0_low = 0xffead0ff,
499 .tune0_high = 0xffead0ff,
500 .tune1 = 0x25501d0,
501 .tune_high_min_millivolts = 864,
502 }
503 },
504};
505
506static const struct dfll_fcpu_data tegra124_dfll_fcpu_data = {
507 .cpu_max_freq_table = tegra124_cpu_max_freq_table,
508 .cpu_max_freq_table_size = ARRAY_SIZE(tegra124_cpu_max_freq_table),
509 .cpu_cvb_tables = tegra124_cpu_cvb_tables,
510 .cpu_cvb_tables_size = ARRAY_SIZE(tegra124_cpu_cvb_tables)
511};
512
513static const struct dfll_fcpu_data tegra210_dfll_fcpu_data = {
514 .cpu_max_freq_table = tegra210_cpu_max_freq_table,
515 .cpu_max_freq_table_size = ARRAY_SIZE(tegra210_cpu_max_freq_table),
516 .cpu_cvb_tables = tegra210_cpu_cvb_tables,
517 .cpu_cvb_tables_size = ARRAY_SIZE(tegra210_cpu_cvb_tables),
518};
519
520static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
521 {
522 .compatible = "nvidia,tegra124-dfll",
523 .data = &tegra124_dfll_fcpu_data,
524 },
525 {
526 .compatible = "nvidia,tegra210-dfll",
527 .data = &tegra210_dfll_fcpu_data
528 },
529 { },
530};
531
532static void get_alignment_from_dt(struct device *dev,
533 struct rail_alignment *align)
534{
535 if (of_property_read_u32(dev->of_node,
536 "nvidia,pwm-voltage-step-microvolts",
537 &align->step_uv))
538 align->step_uv = 0;
539
540 if (of_property_read_u32(dev->of_node,
541 "nvidia,pwm-min-microvolts",
542 &align->offset_uv))
543 align->offset_uv = 0;
544}
545
546static int get_alignment_from_regulator(struct device *dev,
547 struct rail_alignment *align)
548{
549 struct regulator *reg = devm_regulator_get(dev, "vdd-cpu");
550
551 if (IS_ERR(reg))
552 return PTR_ERR(reg);
553
554 align->offset_uv = regulator_list_voltage(reg, 0);
555 align->step_uv = regulator_get_linear_step(reg);
556
557 devm_regulator_put(reg);
558
559 return 0;
560}
561
85static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) 562static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
86{ 563{
87 int process_id, speedo_id, speedo_value, err; 564 int process_id, speedo_id, speedo_value, err;
88 struct tegra_dfll_soc_data *soc; 565 struct tegra_dfll_soc_data *soc;
566 const struct dfll_fcpu_data *fcpu_data;
567 struct rail_alignment align;
568
569 fcpu_data = of_device_get_match_data(&pdev->dev);
570 if (!fcpu_data)
571 return -ENODEV;
89 572
90 process_id = tegra_sku_info.cpu_process_id; 573 process_id = tegra_sku_info.cpu_process_id;
91 speedo_id = tegra_sku_info.cpu_speedo_id; 574 speedo_id = tegra_sku_info.cpu_speedo_id;
92 speedo_value = tegra_sku_info.cpu_speedo_value; 575 speedo_value = tegra_sku_info.cpu_speedo_value;
93 576
94 if (speedo_id >= ARRAY_SIZE(cpu_max_freq_table)) { 577 if (speedo_id >= fcpu_data->cpu_max_freq_table_size) {
95 dev_err(&pdev->dev, "unknown max CPU freq for speedo_id=%d\n", 578 dev_err(&pdev->dev, "unknown max CPU freq for speedo_id=%d\n",
96 speedo_id); 579 speedo_id);
97 return -ENODEV; 580 return -ENODEV;
@@ -107,12 +590,22 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
107 return -ENODEV; 590 return -ENODEV;
108 } 591 }
109 592
110 soc->max_freq = cpu_max_freq_table[speedo_id]; 593 if (of_property_read_bool(pdev->dev.of_node, "nvidia,pwm-to-pmic")) {
594 get_alignment_from_dt(&pdev->dev, &align);
595 } else {
596 err = get_alignment_from_regulator(&pdev->dev, &align);
597 if (err)
598 return err;
599 }
600
601 soc->max_freq = fcpu_data->cpu_max_freq_table[speedo_id];
602
603 soc->cvb = tegra_cvb_add_opp_table(soc->dev, fcpu_data->cpu_cvb_tables,
604 fcpu_data->cpu_cvb_tables_size,
605 &align, process_id, speedo_id,
606 speedo_value, soc->max_freq);
607 soc->alignment = align;
111 608
112 soc->cvb = tegra_cvb_add_opp_table(soc->dev, tegra124_cpu_cvb_tables,
113 ARRAY_SIZE(tegra124_cpu_cvb_tables),
114 process_id, speedo_id, speedo_value,
115 soc->max_freq);
116 if (IS_ERR(soc->cvb)) { 609 if (IS_ERR(soc->cvb)) {
117 dev_err(&pdev->dev, "couldn't add OPP table: %ld\n", 610 dev_err(&pdev->dev, "couldn't add OPP table: %ld\n",
118 PTR_ERR(soc->cvb)); 611 PTR_ERR(soc->cvb));
@@ -144,11 +637,6 @@ static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
144 return 0; 637 return 0;
145} 638}
146 639
147static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
148 { .compatible = "nvidia,tegra124-dfll", },
149 { },
150};
151
152static const struct dev_pm_ops tegra124_dfll_pm_ops = { 640static const struct dev_pm_ops tegra124_dfll_pm_ops = {
153 SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend, 641 SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
154 tegra_dfll_runtime_resume, NULL) 642 tegra_dfll_runtime_resume, NULL)
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
index da9e8e7b5ce5..35eeb6adc68e 100644
--- a/drivers/clk/tegra/cvb.c
+++ b/drivers/clk/tegra/cvb.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Utility functions for parsing Tegra CVB voltage tables 2 * Utility functions for parsing Tegra CVB voltage tables
3 * 3 *
4 * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved. 4 * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License version 2 as
@@ -62,9 +62,9 @@ static int round_voltage(int mv, const struct rail_alignment *align, int up)
62} 62}
63 63
64static int build_opp_table(struct device *dev, const struct cvb_table *table, 64static int build_opp_table(struct device *dev, const struct cvb_table *table,
65 struct rail_alignment *align,
65 int speedo_value, unsigned long max_freq) 66 int speedo_value, unsigned long max_freq)
66{ 67{
67 const struct rail_alignment *align = &table->alignment;
68 int i, ret, dfll_mv, min_mv, max_mv; 68 int i, ret, dfll_mv, min_mv, max_mv;
69 69
70 min_mv = round_voltage(table->min_millivolts, align, UP); 70 min_mv = round_voltage(table->min_millivolts, align, UP);
@@ -109,8 +109,9 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table,
109 */ 109 */
110const struct cvb_table * 110const struct cvb_table *
111tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables, 111tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
112 size_t count, int process_id, int speedo_id, 112 size_t count, struct rail_alignment *align,
113 int speedo_value, unsigned long max_freq) 113 int process_id, int speedo_id, int speedo_value,
114 unsigned long max_freq)
114{ 115{
115 size_t i; 116 size_t i;
116 int ret; 117 int ret;
@@ -124,7 +125,8 @@ tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
124 if (table->process_id != -1 && table->process_id != process_id) 125 if (table->process_id != -1 && table->process_id != process_id)
125 continue; 126 continue;
126 127
127 ret = build_opp_table(dev, table, speedo_value, max_freq); 128 ret = build_opp_table(dev, table, align, speedo_value,
129 max_freq);
128 return ret ? ERR_PTR(ret) : table; 130 return ret ? ERR_PTR(ret) : table;
129 } 131 }
130 132
diff --git a/drivers/clk/tegra/cvb.h b/drivers/clk/tegra/cvb.h
index c1f077993b2a..91a1941c21ef 100644
--- a/drivers/clk/tegra/cvb.h
+++ b/drivers/clk/tegra/cvb.h
@@ -41,6 +41,7 @@ struct cvb_cpu_dfll_data {
41 u32 tune0_low; 41 u32 tune0_low;
42 u32 tune0_high; 42 u32 tune0_high;
43 u32 tune1; 43 u32 tune1;
44 unsigned int tune_high_min_millivolts;
44}; 45};
45 46
46struct cvb_table { 47struct cvb_table {
@@ -49,7 +50,6 @@ struct cvb_table {
49 50
50 int min_millivolts; 51 int min_millivolts;
51 int max_millivolts; 52 int max_millivolts;
52 struct rail_alignment alignment;
53 53
54 int speedo_scale; 54 int speedo_scale;
55 int voltage_scale; 55 int voltage_scale;
@@ -59,8 +59,9 @@ struct cvb_table {
59 59
60const struct cvb_table * 60const struct cvb_table *
61tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables, 61tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables,
62 size_t count, int process_id, int speedo_id, 62 size_t count, struct rail_alignment *align,
63 int speedo_value, unsigned long max_freq); 63 int process_id, int speedo_id, int speedo_value,
64 unsigned long max_freq);
64void tegra_cvb_remove_opp_table(struct device *dev, 65void tegra_cvb_remove_opp_table(struct device *dev,
65 const struct cvb_table *table, 66 const struct cvb_table *table,
66 unsigned long max_freq); 67 unsigned long max_freq);
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 688f10227793..1a6778e81f90 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -272,8 +272,8 @@ config ARM_TEGRA20_CPUFREQ
272 This adds the CPUFreq driver support for Tegra20 SOCs. 272 This adds the CPUFreq driver support for Tegra20 SOCs.
273 273
274config ARM_TEGRA124_CPUFREQ 274config ARM_TEGRA124_CPUFREQ
275 tristate "Tegra124 CPUFreq support" 275 bool "Tegra124 CPUFreq support"
276 depends on ARCH_TEGRA && CPUFREQ_DT && REGULATOR 276 depends on ARCH_TEGRA && CPUFREQ_DT
277 default y 277 default y
278 help 278 help
279 This adds the CPUFreq driver support for Tegra124 SOCs. 279 This adds the CPUFreq driver support for Tegra124 SOCs.
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index b1c5468dca16..47729a22c159 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -119,6 +119,7 @@ static const struct of_device_id blacklist[] __initconst = {
119 { .compatible = "mediatek,mt8176", }, 119 { .compatible = "mediatek,mt8176", },
120 120
121 { .compatible = "nvidia,tegra124", }, 121 { .compatible = "nvidia,tegra124", },
122 { .compatible = "nvidia,tegra210", },
122 123
123 { .compatible = "qcom,apq8096", }, 124 { .compatible = "qcom,apq8096", },
124 { .compatible = "qcom,msm8996", }, 125 { .compatible = "qcom,msm8996", },
diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c
index 43530254201a..ba3795e13ac6 100644
--- a/drivers/cpufreq/tegra124-cpufreq.c
+++ b/drivers/cpufreq/tegra124-cpufreq.c
@@ -22,11 +22,9 @@
22#include <linux/of.h> 22#include <linux/of.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/pm_opp.h> 24#include <linux/pm_opp.h>
25#include <linux/regulator/consumer.h>
26#include <linux/types.h> 25#include <linux/types.h>
27 26
28struct tegra124_cpufreq_priv { 27struct tegra124_cpufreq_priv {
29 struct regulator *vdd_cpu_reg;
30 struct clk *cpu_clk; 28 struct clk *cpu_clk;
31 struct clk *pllp_clk; 29 struct clk *pllp_clk;
32 struct clk *pllx_clk; 30 struct clk *pllx_clk;
@@ -60,14 +58,6 @@ out:
60 return ret; 58 return ret;
61} 59}
62 60
63static void tegra124_cpu_switch_to_pllx(struct tegra124_cpufreq_priv *priv)
64{
65 clk_set_parent(priv->cpu_clk, priv->pllp_clk);
66 clk_disable_unprepare(priv->dfll_clk);
67 regulator_sync_voltage(priv->vdd_cpu_reg);
68 clk_set_parent(priv->cpu_clk, priv->pllx_clk);
69}
70
71static int tegra124_cpufreq_probe(struct platform_device *pdev) 61static int tegra124_cpufreq_probe(struct platform_device *pdev)
72{ 62{
73 struct tegra124_cpufreq_priv *priv; 63 struct tegra124_cpufreq_priv *priv;
@@ -88,16 +78,10 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
88 if (!np) 78 if (!np)
89 return -ENODEV; 79 return -ENODEV;
90 80
91 priv->vdd_cpu_reg = regulator_get(cpu_dev, "vdd-cpu");
92 if (IS_ERR(priv->vdd_cpu_reg)) {
93 ret = PTR_ERR(priv->vdd_cpu_reg);
94 goto out_put_np;
95 }
96
97 priv->cpu_clk = of_clk_get_by_name(np, "cpu_g"); 81 priv->cpu_clk = of_clk_get_by_name(np, "cpu_g");
98 if (IS_ERR(priv->cpu_clk)) { 82 if (IS_ERR(priv->cpu_clk)) {
99 ret = PTR_ERR(priv->cpu_clk); 83 ret = PTR_ERR(priv->cpu_clk);
100 goto out_put_vdd_cpu_reg; 84 goto out_put_np;
101 } 85 }
102 86
103 priv->dfll_clk = of_clk_get_by_name(np, "dfll"); 87 priv->dfll_clk = of_clk_get_by_name(np, "dfll");
@@ -129,15 +113,13 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
129 platform_device_register_full(&cpufreq_dt_devinfo); 113 platform_device_register_full(&cpufreq_dt_devinfo);
130 if (IS_ERR(priv->cpufreq_dt_pdev)) { 114 if (IS_ERR(priv->cpufreq_dt_pdev)) {
131 ret = PTR_ERR(priv->cpufreq_dt_pdev); 115 ret = PTR_ERR(priv->cpufreq_dt_pdev);
132 goto out_switch_to_pllx; 116 goto out_put_pllp_clk;
133 } 117 }
134 118
135 platform_set_drvdata(pdev, priv); 119 platform_set_drvdata(pdev, priv);
136 120
137 return 0; 121 return 0;
138 122
139out_switch_to_pllx:
140 tegra124_cpu_switch_to_pllx(priv);
141out_put_pllp_clk: 123out_put_pllp_clk:
142 clk_put(priv->pllp_clk); 124 clk_put(priv->pllp_clk);
143out_put_pllx_clk: 125out_put_pllx_clk:
@@ -146,34 +128,15 @@ out_put_dfll_clk:
146 clk_put(priv->dfll_clk); 128 clk_put(priv->dfll_clk);
147out_put_cpu_clk: 129out_put_cpu_clk:
148 clk_put(priv->cpu_clk); 130 clk_put(priv->cpu_clk);
149out_put_vdd_cpu_reg:
150 regulator_put(priv->vdd_cpu_reg);
151out_put_np: 131out_put_np:
152 of_node_put(np); 132 of_node_put(np);
153 133
154 return ret; 134 return ret;
155} 135}
156 136
157static int tegra124_cpufreq_remove(struct platform_device *pdev)
158{
159 struct tegra124_cpufreq_priv *priv = platform_get_drvdata(pdev);
160
161 platform_device_unregister(priv->cpufreq_dt_pdev);
162 tegra124_cpu_switch_to_pllx(priv);
163
164 clk_put(priv->pllp_clk);
165 clk_put(priv->pllx_clk);
166 clk_put(priv->dfll_clk);
167 clk_put(priv->cpu_clk);
168 regulator_put(priv->vdd_cpu_reg);
169
170 return 0;
171}
172
173static struct platform_driver tegra124_cpufreq_platdrv = { 137static struct platform_driver tegra124_cpufreq_platdrv = {
174 .driver.name = "cpufreq-tegra124", 138 .driver.name = "cpufreq-tegra124",
175 .probe = tegra124_cpufreq_probe, 139 .probe = tegra124_cpufreq_probe,
176 .remove = tegra124_cpufreq_remove,
177}; 140};
178 141
179static int __init tegra_cpufreq_init(void) 142static int __init tegra_cpufreq_init(void)
@@ -181,7 +144,8 @@ static int __init tegra_cpufreq_init(void)
181 int ret; 144 int ret;
182 struct platform_device *pdev; 145 struct platform_device *pdev;
183 146
184 if (!of_machine_is_compatible("nvidia,tegra124")) 147 if (!(of_machine_is_compatible("nvidia,tegra124") ||
148 of_machine_is_compatible("nvidia,tegra210")))
185 return -ENODEV; 149 return -ENODEV;
186 150
187 /* 151 /*
diff --git a/drivers/firmware/imx/misc.c b/drivers/firmware/imx/misc.c
index 97f5424dbac9..4b56a587dacd 100644
--- a/drivers/firmware/imx/misc.c
+++ b/drivers/firmware/imx/misc.c
@@ -18,6 +18,14 @@ struct imx_sc_msg_req_misc_set_ctrl {
18 u16 resource; 18 u16 resource;
19} __packed; 19} __packed;
20 20
21struct imx_sc_msg_req_cpu_start {
22 struct imx_sc_rpc_msg hdr;
23 u32 address_hi;
24 u32 address_lo;
25 u16 resource;
26 u8 enable;
27} __packed;
28
21struct imx_sc_msg_req_misc_get_ctrl { 29struct imx_sc_msg_req_misc_get_ctrl {
22 struct imx_sc_rpc_msg hdr; 30 struct imx_sc_rpc_msg hdr;
23 u32 ctrl; 31 u32 ctrl;
@@ -97,3 +105,33 @@ int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource,
97 return 0; 105 return 0;
98} 106}
99EXPORT_SYMBOL(imx_sc_misc_get_control); 107EXPORT_SYMBOL(imx_sc_misc_get_control);
108
109/*
110 * This function starts/stops a CPU identified by @resource
111 *
112 * @param[in] ipc IPC handle
113 * @param[in] resource resource the control is associated with
114 * @param[in] enable true for start, false for stop
115 * @param[in] phys_addr initial instruction address to be executed
116 *
117 * @return Returns 0 for success and < 0 for errors.
118 */
119int imx_sc_pm_cpu_start(struct imx_sc_ipc *ipc, u32 resource,
120 bool enable, u64 phys_addr)
121{
122 struct imx_sc_msg_req_cpu_start msg;
123 struct imx_sc_rpc_msg *hdr = &msg.hdr;
124
125 hdr->ver = IMX_SC_RPC_VERSION;
126 hdr->svc = IMX_SC_RPC_SVC_PM;
127 hdr->func = IMX_SC_PM_FUNC_CPU_START;
128 hdr->size = 4;
129
130 msg.address_hi = phys_addr >> 32;
131 msg.address_lo = phys_addr;
132 msg.resource = resource;
133 msg.enable = enable;
134
135 return imx_scu_call_rpc(ipc, &msg, true);
136}
137EXPORT_SYMBOL(imx_sc_pm_cpu_start);
diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c
index 407245f2efd0..39a94c7177fc 100644
--- a/drivers/firmware/imx/scu-pd.c
+++ b/drivers/firmware/imx/scu-pd.c
@@ -322,6 +322,7 @@ static int imx_sc_pd_probe(struct platform_device *pdev)
322 322
323static const struct of_device_id imx_sc_pd_match[] = { 323static const struct of_device_id imx_sc_pd_match[] = {
324 { .compatible = "fsl,imx8qxp-scu-pd", &imx8qxp_scu_pd}, 324 { .compatible = "fsl,imx8qxp-scu-pd", &imx8qxp_scu_pd},
325 { .compatible = "fsl,scu-pd", &imx8qxp_scu_pd},
325 { /* sentinel */ } 326 { /* sentinel */ }
326}; 327};
327 328
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index a13558154ac3..61be15d9df7d 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -238,6 +238,16 @@ static int rpi_firmware_probe(struct platform_device *pdev)
238 return 0; 238 return 0;
239} 239}
240 240
241static void rpi_firmware_shutdown(struct platform_device *pdev)
242{
243 struct rpi_firmware *fw = platform_get_drvdata(pdev);
244
245 if (!fw)
246 return;
247
248 rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_REBOOT, NULL, 0);
249}
250
241static int rpi_firmware_remove(struct platform_device *pdev) 251static int rpi_firmware_remove(struct platform_device *pdev)
242{ 252{
243 struct rpi_firmware *fw = platform_get_drvdata(pdev); 253 struct rpi_firmware *fw = platform_get_drvdata(pdev);
@@ -278,6 +288,7 @@ static struct platform_driver rpi_firmware_driver = {
278 .of_match_table = rpi_firmware_of_match, 288 .of_match_table = rpi_firmware_of_match,
279 }, 289 },
280 .probe = rpi_firmware_probe, 290 .probe = rpi_firmware_probe,
291 .shutdown = rpi_firmware_shutdown,
281 .remove = rpi_firmware_remove, 292 .remove = rpi_firmware_remove,
282}; 293};
283module_platform_driver(rpi_firmware_driver); 294module_platform_driver(rpi_firmware_driver);
diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile
index 1b826dcca719..676b01caff05 100644
--- a/drivers/firmware/tegra/Makefile
+++ b/drivers/firmware/tegra/Makefile
@@ -1,4 +1,7 @@
1tegra-bpmp-y = bpmp.o 1tegra-bpmp-y = bpmp.o
2tegra-bpmp-$(CONFIG_ARCH_TEGRA_210_SOC) += bpmp-tegra210.o
3tegra-bpmp-$(CONFIG_ARCH_TEGRA_186_SOC) += bpmp-tegra186.o
4tegra-bpmp-$(CONFIG_ARCH_TEGRA_194_SOC) += bpmp-tegra186.o
2tegra-bpmp-$(CONFIG_DEBUG_FS) += bpmp-debugfs.o 5tegra-bpmp-$(CONFIG_DEBUG_FS) += bpmp-debugfs.o
3obj-$(CONFIG_TEGRA_BPMP) += tegra-bpmp.o 6obj-$(CONFIG_TEGRA_BPMP) += tegra-bpmp.o
4obj-$(CONFIG_TEGRA_IVC) += ivc.o 7obj-$(CONFIG_TEGRA_IVC) += ivc.o
diff --git a/drivers/firmware/tegra/bpmp-private.h b/drivers/firmware/tegra/bpmp-private.h
new file mode 100644
index 000000000000..54d560c48398
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-private.h
@@ -0,0 +1,34 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2018, NVIDIA CORPORATION.
4 */
5
6#ifndef __FIRMWARE_TEGRA_BPMP_PRIVATE_H
7#define __FIRMWARE_TEGRA_BPMP_PRIVATE_H
8
9#include <soc/tegra/bpmp.h>
10
11struct tegra_bpmp_ops {
12 int (*init)(struct tegra_bpmp *bpmp);
13 void (*deinit)(struct tegra_bpmp *bpmp);
14 bool (*is_response_ready)(struct tegra_bpmp_channel *channel);
15 bool (*is_request_ready)(struct tegra_bpmp_channel *channel);
16 int (*ack_response)(struct tegra_bpmp_channel *channel);
17 int (*ack_request)(struct tegra_bpmp_channel *channel);
18 bool (*is_response_channel_free)(struct tegra_bpmp_channel *channel);
19 bool (*is_request_channel_free)(struct tegra_bpmp_channel *channel);
20 int (*post_response)(struct tegra_bpmp_channel *channel);
21 int (*post_request)(struct tegra_bpmp_channel *channel);
22 int (*ring_doorbell)(struct tegra_bpmp *bpmp);
23 int (*resume)(struct tegra_bpmp *bpmp);
24};
25
26#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
27 IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
28extern const struct tegra_bpmp_ops tegra186_bpmp_ops;
29#endif
30#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
31extern const struct tegra_bpmp_ops tegra210_bpmp_ops;
32#endif
33
34#endif
diff --git a/drivers/firmware/tegra/bpmp-tegra186.c b/drivers/firmware/tegra/bpmp-tegra186.c
new file mode 100644
index 000000000000..ea308751635f
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-tegra186.c
@@ -0,0 +1,305 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018, NVIDIA CORPORATION.
4 */
5
6#include <linux/genalloc.h>
7#include <linux/mailbox_client.h>
8#include <linux/platform_device.h>
9
10#include <soc/tegra/bpmp.h>
11#include <soc/tegra/bpmp-abi.h>
12#include <soc/tegra/ivc.h>
13
14#include "bpmp-private.h"
15
16struct tegra186_bpmp {
17 struct tegra_bpmp *parent;
18
19 struct {
20 struct gen_pool *pool;
21 dma_addr_t phys;
22 void *virt;
23 } tx, rx;
24
25 struct {
26 struct mbox_client client;
27 struct mbox_chan *channel;
28 } mbox;
29};
30
31static inline struct tegra_bpmp *
32mbox_client_to_bpmp(struct mbox_client *client)
33{
34 struct tegra186_bpmp *priv;
35
36 priv = container_of(client, struct tegra186_bpmp, mbox.client);
37
38 return priv->parent;
39}
40
41static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel *channel)
42{
43 void *frame;
44
45 frame = tegra_ivc_read_get_next_frame(channel->ivc);
46 if (IS_ERR(frame)) {
47 channel->ib = NULL;
48 return false;
49 }
50
51 channel->ib = frame;
52
53 return true;
54}
55
56static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel *channel)
57{
58 void *frame;
59
60 frame = tegra_ivc_write_get_next_frame(channel->ivc);
61 if (IS_ERR(frame)) {
62 channel->ob = NULL;
63 return false;
64 }
65
66 channel->ob = frame;
67
68 return true;
69}
70
71static int tegra186_bpmp_ack_message(struct tegra_bpmp_channel *channel)
72{
73 return tegra_ivc_read_advance(channel->ivc);
74}
75
76static int tegra186_bpmp_post_message(struct tegra_bpmp_channel *channel)
77{
78 return tegra_ivc_write_advance(channel->ivc);
79}
80
81static int tegra186_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
82{
83 struct tegra186_bpmp *priv = bpmp->priv;
84 int err;
85
86 err = mbox_send_message(priv->mbox.channel, NULL);
87 if (err < 0)
88 return err;
89
90 mbox_client_txdone(priv->mbox.channel, 0);
91
92 return 0;
93}
94
95static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
96{
97 struct tegra_bpmp *bpmp = data;
98 struct tegra186_bpmp *priv = bpmp->priv;
99
100 if (WARN_ON(priv->mbox.channel == NULL))
101 return;
102
103 tegra186_bpmp_ring_doorbell(bpmp);
104}
105
106static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
107 struct tegra_bpmp *bpmp,
108 unsigned int index)
109{
110 struct tegra186_bpmp *priv = bpmp->priv;
111 size_t message_size, queue_size;
112 unsigned int offset;
113 int err;
114
115 channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
116 GFP_KERNEL);
117 if (!channel->ivc)
118 return -ENOMEM;
119
120 message_size = tegra_ivc_align(MSG_MIN_SZ);
121 queue_size = tegra_ivc_total_queue_size(message_size);
122 offset = queue_size * index;
123
124 err = tegra_ivc_init(channel->ivc, NULL,
125 priv->rx.virt + offset, priv->rx.phys + offset,
126 priv->tx.virt + offset, priv->tx.phys + offset,
127 1, message_size, tegra186_bpmp_ivc_notify,
128 bpmp);
129 if (err < 0) {
130 dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
131 index, err);
132 return err;
133 }
134
135 init_completion(&channel->completion);
136 channel->bpmp = bpmp;
137
138 return 0;
139}
140
141static void tegra186_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
142{
143 /* reset the channel state */
144 tegra_ivc_reset(channel->ivc);
145
146 /* sync the channel state with BPMP */
147 while (tegra_ivc_notified(channel->ivc))
148 ;
149}
150
151static void tegra186_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
152{
153 tegra_ivc_cleanup(channel->ivc);
154}
155
156static void mbox_handle_rx(struct mbox_client *client, void *data)
157{
158 struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
159
160 tegra_bpmp_handle_rx(bpmp);
161}
162
163static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
164{
165 struct tegra186_bpmp *priv;
166 unsigned int i;
167 int err;
168
169 priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
170 if (!priv)
171 return -ENOMEM;
172
173 bpmp->priv = priv;
174 priv->parent = bpmp;
175
176 priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0);
177 if (!priv->tx.pool) {
178 dev_err(bpmp->dev, "TX shmem pool not found\n");
179 return -ENOMEM;
180 }
181
182 priv->tx.virt = gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
183 if (!priv->tx.virt) {
184 dev_err(bpmp->dev, "failed to allocate from TX pool\n");
185 return -ENOMEM;
186 }
187
188 priv->rx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 1);
189 if (!priv->rx.pool) {
190 dev_err(bpmp->dev, "RX shmem pool not found\n");
191 err = -ENOMEM;
192 goto free_tx;
193 }
194
195 priv->rx.virt = gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
196 if (!priv->rx.virt) {
197 dev_err(bpmp->dev, "failed to allocate from RX pool\n");
198 err = -ENOMEM;
199 goto free_tx;
200 }
201
202 err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp,
203 bpmp->soc->channels.cpu_tx.offset);
204 if (err < 0)
205 goto free_rx;
206
207 err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp,
208 bpmp->soc->channels.cpu_rx.offset);
209 if (err < 0)
210 goto cleanup_tx_channel;
211
212 for (i = 0; i < bpmp->threaded.count; i++) {
213 unsigned int index = bpmp->soc->channels.thread.offset + i;
214
215 err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i],
216 bpmp, index);
217 if (err < 0)
218 goto cleanup_channels;
219 }
220
221 /* mbox registration */
222 priv->mbox.client.dev = bpmp->dev;
223 priv->mbox.client.rx_callback = mbox_handle_rx;
224 priv->mbox.client.tx_block = false;
225 priv->mbox.client.knows_txdone = false;
226
227 priv->mbox.channel = mbox_request_channel(&priv->mbox.client, 0);
228 if (IS_ERR(priv->mbox.channel)) {
229 err = PTR_ERR(priv->mbox.channel);
230 dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err);
231 goto cleanup_channels;
232 }
233
234 tegra186_bpmp_channel_reset(bpmp->tx_channel);
235 tegra186_bpmp_channel_reset(bpmp->rx_channel);
236
237 for (i = 0; i < bpmp->threaded.count; i++)
238 tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
239
240 return 0;
241
242cleanup_channels:
243 for (i = 0; i < bpmp->threaded.count; i++) {
244 if (!bpmp->threaded_channels[i].bpmp)
245 continue;
246
247 tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
248 }
249
250 tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
251cleanup_tx_channel:
252 tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
253free_rx:
254 gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
255free_tx:
256 gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
257
258 return err;
259}
260
261static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp)
262{
263 struct tegra186_bpmp *priv = bpmp->priv;
264 unsigned int i;
265
266 mbox_free_channel(priv->mbox.channel);
267
268 for (i = 0; i < bpmp->threaded.count; i++)
269 tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
270
271 tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
272 tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
273
274 gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
275 gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
276}
277
278static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp)
279{
280 unsigned int i;
281
282 /* reset message channels */
283 tegra186_bpmp_channel_reset(bpmp->tx_channel);
284 tegra186_bpmp_channel_reset(bpmp->rx_channel);
285
286 for (i = 0; i < bpmp->threaded.count; i++)
287 tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
288
289 return 0;
290}
291
292const struct tegra_bpmp_ops tegra186_bpmp_ops = {
293 .init = tegra186_bpmp_init,
294 .deinit = tegra186_bpmp_deinit,
295 .is_response_ready = tegra186_bpmp_is_message_ready,
296 .is_request_ready = tegra186_bpmp_is_message_ready,
297 .ack_response = tegra186_bpmp_ack_message,
298 .ack_request = tegra186_bpmp_ack_message,
299 .is_response_channel_free = tegra186_bpmp_is_channel_free,
300 .is_request_channel_free = tegra186_bpmp_is_channel_free,
301 .post_response = tegra186_bpmp_post_message,
302 .post_request = tegra186_bpmp_post_message,
303 .ring_doorbell = tegra186_bpmp_ring_doorbell,
304 .resume = tegra186_bpmp_resume,
305};
diff --git a/drivers/firmware/tegra/bpmp-tegra210.c b/drivers/firmware/tegra/bpmp-tegra210.c
new file mode 100644
index 000000000000..ae15940a078e
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-tegra210.c
@@ -0,0 +1,243 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018, NVIDIA CORPORATION.
4 */
5
6#include <linux/interrupt.h>
7#include <linux/irq.h>
8#include <linux/io.h>
9#include <linux/of.h>
10#include <linux/platform_device.h>
11
12#include <soc/tegra/bpmp.h>
13
14#include "bpmp-private.h"
15
16#define TRIGGER_OFFSET 0x000
17#define RESULT_OFFSET(id) (0xc00 + id * 4)
18#define TRIGGER_ID_SHIFT 16
19#define TRIGGER_CMD_GET 4
20
21#define STA_OFFSET 0
22#define SET_OFFSET 4
23#define CLR_OFFSET 8
24
25#define CH_MASK(ch) (0x3 << ((ch) * 2))
26#define SL_SIGL(ch) (0x0 << ((ch) * 2))
27#define SL_QUED(ch) (0x1 << ((ch) * 2))
28#define MA_FREE(ch) (0x2 << ((ch) * 2))
29#define MA_ACKD(ch) (0x3 << ((ch) * 2))
30
31struct tegra210_bpmp {
32 void __iomem *atomics;
33 void __iomem *arb_sema;
34 struct irq_data *tx_irq_data;
35};
36
37static u32 bpmp_channel_status(struct tegra_bpmp *bpmp, unsigned int index)
38{
39 struct tegra210_bpmp *priv = bpmp->priv;
40
41 return __raw_readl(priv->arb_sema + STA_OFFSET) & CH_MASK(index);
42}
43
44static bool tegra210_bpmp_is_response_ready(struct tegra_bpmp_channel *channel)
45{
46 unsigned int index = channel->index;
47
48 return bpmp_channel_status(channel->bpmp, index) == MA_ACKD(index);
49}
50
51static bool tegra210_bpmp_is_request_ready(struct tegra_bpmp_channel *channel)
52{
53 unsigned int index = channel->index;
54
55 return bpmp_channel_status(channel->bpmp, index) == SL_SIGL(index);
56}
57
58static bool
59tegra210_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel)
60{
61 unsigned int index = channel->index;
62
63 return bpmp_channel_status(channel->bpmp, index) == MA_FREE(index);
64}
65
66static bool
67tegra210_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel)
68{
69 unsigned int index = channel->index;
70
71 return bpmp_channel_status(channel->bpmp, index) == SL_QUED(index);
72}
73
74static int tegra210_bpmp_post_request(struct tegra_bpmp_channel *channel)
75{
76 struct tegra210_bpmp *priv = channel->bpmp->priv;
77
78 __raw_writel(CH_MASK(channel->index), priv->arb_sema + CLR_OFFSET);
79
80 return 0;
81}
82
83static int tegra210_bpmp_post_response(struct tegra_bpmp_channel *channel)
84{
85 struct tegra210_bpmp *priv = channel->bpmp->priv;
86
87 __raw_writel(MA_ACKD(channel->index), priv->arb_sema + SET_OFFSET);
88
89 return 0;
90}
91
92static int tegra210_bpmp_ack_response(struct tegra_bpmp_channel *channel)
93{
94 struct tegra210_bpmp *priv = channel->bpmp->priv;
95
96 __raw_writel(MA_ACKD(channel->index) ^ MA_FREE(channel->index),
97 priv->arb_sema + CLR_OFFSET);
98
99 return 0;
100}
101
102static int tegra210_bpmp_ack_request(struct tegra_bpmp_channel *channel)
103{
104 struct tegra210_bpmp *priv = channel->bpmp->priv;
105
106 __raw_writel(SL_QUED(channel->index), priv->arb_sema + SET_OFFSET);
107
108 return 0;
109}
110
111static int tegra210_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
112{
113 struct tegra210_bpmp *priv = bpmp->priv;
114 struct irq_data *irq_data = priv->tx_irq_data;
115
116 /*
117 * Tegra Legacy Interrupt Controller (LIC) is used to notify BPMP of
118 * available messages
119 */
120 if (irq_data->chip->irq_retrigger)
121 return irq_data->chip->irq_retrigger(irq_data);
122
123 return -EINVAL;
124}
125
126static irqreturn_t rx_irq(int irq, void *data)
127{
128 struct tegra_bpmp *bpmp = data;
129
130 tegra_bpmp_handle_rx(bpmp);
131
132 return IRQ_HANDLED;
133}
134
135static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel,
136 struct tegra_bpmp *bpmp,
137 unsigned int index)
138{
139 struct tegra210_bpmp *priv = bpmp->priv;
140 u32 address;
141 void *p;
142
143 /* Retrieve channel base address from BPMP */
144 writel(index << TRIGGER_ID_SHIFT | TRIGGER_CMD_GET,
145 priv->atomics + TRIGGER_OFFSET);
146 address = readl(priv->atomics + RESULT_OFFSET(index));
147
148 p = devm_ioremap(bpmp->dev, address, 0x80);
149 if (!p)
150 return -ENOMEM;
151
152 channel->ib = p;
153 channel->ob = p;
154 channel->index = index;
155 init_completion(&channel->completion);
156 channel->bpmp = bpmp;
157
158 return 0;
159}
160
161static int tegra210_bpmp_init(struct tegra_bpmp *bpmp)
162{
163 struct platform_device *pdev = to_platform_device(bpmp->dev);
164 struct tegra210_bpmp *priv;
165 struct resource *res;
166 unsigned int i;
167 int err;
168
169 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
170 if (!priv)
171 return -ENOMEM;
172
173 bpmp->priv = priv;
174
175 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
176 priv->atomics = devm_ioremap_resource(&pdev->dev, res);
177 if (IS_ERR(priv->atomics))
178 return PTR_ERR(priv->atomics);
179
180 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
181 priv->arb_sema = devm_ioremap_resource(&pdev->dev, res);
182 if (IS_ERR(priv->arb_sema))
183 return PTR_ERR(priv->arb_sema);
184
185 err = tegra210_bpmp_channel_init(bpmp->tx_channel, bpmp,
186 bpmp->soc->channels.cpu_tx.offset);
187 if (err < 0)
188 return err;
189
190 err = tegra210_bpmp_channel_init(bpmp->rx_channel, bpmp,
191 bpmp->soc->channels.cpu_rx.offset);
192 if (err < 0)
193 return err;
194
195 for (i = 0; i < bpmp->threaded.count; i++) {
196 unsigned int index = bpmp->soc->channels.thread.offset + i;
197
198 err = tegra210_bpmp_channel_init(&bpmp->threaded_channels[i],
199 bpmp, index);
200 if (err < 0)
201 return err;
202 }
203
204 err = platform_get_irq_byname(pdev, "tx");
205 if (err < 0) {
206 dev_err(&pdev->dev, "failed to get TX IRQ: %d\n", err);
207 return err;
208 }
209
210 priv->tx_irq_data = irq_get_irq_data(err);
211 if (!priv->tx_irq_data) {
212 dev_err(&pdev->dev, "failed to get IRQ data for TX IRQ\n");
213 return err;
214 }
215
216 err = platform_get_irq_byname(pdev, "rx");
217 if (err < 0) {
218 dev_err(&pdev->dev, "failed to get rx IRQ: %d\n", err);
219 return err;
220 }
221
222 err = devm_request_irq(&pdev->dev, err, rx_irq,
223 IRQF_NO_SUSPEND, dev_name(&pdev->dev), bpmp);
224 if (err < 0) {
225 dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
226 return err;
227 }
228
229 return 0;
230}
231
232const struct tegra_bpmp_ops tegra210_bpmp_ops = {
233 .init = tegra210_bpmp_init,
234 .is_response_ready = tegra210_bpmp_is_response_ready,
235 .is_request_ready = tegra210_bpmp_is_request_ready,
236 .ack_response = tegra210_bpmp_ack_response,
237 .ack_request = tegra210_bpmp_ack_request,
238 .is_response_channel_free = tegra210_bpmp_is_response_channel_free,
239 .is_request_channel_free = tegra210_bpmp_is_request_channel_free,
240 .post_response = tegra210_bpmp_post_response,
241 .post_request = tegra210_bpmp_post_request,
242 .ring_doorbell = tegra210_bpmp_ring_doorbell,
243};
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index 689478b92bce..dd775e8ba5a0 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -26,6 +26,8 @@
26#include <soc/tegra/bpmp-abi.h> 26#include <soc/tegra/bpmp-abi.h>
27#include <soc/tegra/ivc.h> 27#include <soc/tegra/ivc.h>
28 28
29#include "bpmp-private.h"
30
29#define MSG_ACK BIT(0) 31#define MSG_ACK BIT(0)
30#define MSG_RING BIT(1) 32#define MSG_RING BIT(1)
31#define TAG_SZ 32 33#define TAG_SZ 32
@@ -36,6 +38,14 @@ mbox_client_to_bpmp(struct mbox_client *client)
36 return container_of(client, struct tegra_bpmp, mbox.client); 38 return container_of(client, struct tegra_bpmp, mbox.client);
37} 39}
38 40
41static inline const struct tegra_bpmp_ops *
42channel_to_ops(struct tegra_bpmp_channel *channel)
43{
44 struct tegra_bpmp *bpmp = channel->bpmp;
45
46 return bpmp->soc->ops;
47}
48
39struct tegra_bpmp *tegra_bpmp_get(struct device *dev) 49struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
40{ 50{
41 struct platform_device *pdev; 51 struct platform_device *pdev;
@@ -96,22 +106,21 @@ static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg)
96 (msg->rx.size == 0 || msg->rx.data); 106 (msg->rx.size == 0 || msg->rx.data);
97} 107}
98 108
99static bool tegra_bpmp_master_acked(struct tegra_bpmp_channel *channel) 109static bool tegra_bpmp_is_response_ready(struct tegra_bpmp_channel *channel)
100{ 110{
101 void *frame; 111 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
102 112
103 frame = tegra_ivc_read_get_next_frame(channel->ivc); 113 return ops->is_response_ready(channel);
104 if (IS_ERR(frame)) { 114}
105 channel->ib = NULL;
106 return false;
107 }
108 115
109 channel->ib = frame; 116static bool tegra_bpmp_is_request_ready(struct tegra_bpmp_channel *channel)
117{
118 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
110 119
111 return true; 120 return ops->is_request_ready(channel);
112} 121}
113 122
114static int tegra_bpmp_wait_ack(struct tegra_bpmp_channel *channel) 123static int tegra_bpmp_wait_response(struct tegra_bpmp_channel *channel)
115{ 124{
116 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout; 125 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
117 ktime_t end; 126 ktime_t end;
@@ -119,29 +128,45 @@ static int tegra_bpmp_wait_ack(struct tegra_bpmp_channel *channel)
119 end = ktime_add_us(ktime_get(), timeout); 128 end = ktime_add_us(ktime_get(), timeout);
120 129
121 do { 130 do {
122 if (tegra_bpmp_master_acked(channel)) 131 if (tegra_bpmp_is_response_ready(channel))
123 return 0; 132 return 0;
124 } while (ktime_before(ktime_get(), end)); 133 } while (ktime_before(ktime_get(), end));
125 134
126 return -ETIMEDOUT; 135 return -ETIMEDOUT;
127} 136}
128 137
129static bool tegra_bpmp_master_free(struct tegra_bpmp_channel *channel) 138static int tegra_bpmp_ack_response(struct tegra_bpmp_channel *channel)
130{ 139{
131 void *frame; 140 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
132 141
133 frame = tegra_ivc_write_get_next_frame(channel->ivc); 142 return ops->ack_response(channel);
134 if (IS_ERR(frame)) { 143}
135 channel->ob = NULL;
136 return false;
137 }
138 144
139 channel->ob = frame; 145static int tegra_bpmp_ack_request(struct tegra_bpmp_channel *channel)
146{
147 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
140 148
141 return true; 149 return ops->ack_request(channel);
142} 150}
143 151
144static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel) 152static bool
153tegra_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel)
154{
155 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
156
157 return ops->is_request_channel_free(channel);
158}
159
160static bool
161tegra_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel)
162{
163 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
164
165 return ops->is_response_channel_free(channel);
166}
167
168static int
169tegra_bpmp_wait_request_channel_free(struct tegra_bpmp_channel *channel)
145{ 170{
146 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout; 171 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
147 ktime_t start, now; 172 ktime_t start, now;
@@ -149,7 +174,7 @@ static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel)
149 start = ns_to_ktime(local_clock()); 174 start = ns_to_ktime(local_clock());
150 175
151 do { 176 do {
152 if (tegra_bpmp_master_free(channel)) 177 if (tegra_bpmp_is_request_channel_free(channel))
153 return 0; 178 return 0;
154 179
155 now = ns_to_ktime(local_clock()); 180 now = ns_to_ktime(local_clock());
@@ -158,6 +183,25 @@ static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel)
158 return -ETIMEDOUT; 183 return -ETIMEDOUT;
159} 184}
160 185
186static int tegra_bpmp_post_request(struct tegra_bpmp_channel *channel)
187{
188 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
189
190 return ops->post_request(channel);
191}
192
193static int tegra_bpmp_post_response(struct tegra_bpmp_channel *channel)
194{
195 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
196
197 return ops->post_response(channel);
198}
199
200static int tegra_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
201{
202 return bpmp->soc->ops->ring_doorbell(bpmp);
203}
204
161static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, 205static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
162 void *data, size_t size, int *ret) 206 void *data, size_t size, int *ret)
163{ 207{
@@ -166,7 +210,7 @@ static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
166 if (data && size > 0) 210 if (data && size > 0)
167 memcpy(data, channel->ib->data, size); 211 memcpy(data, channel->ib->data, size);
168 212
169 err = tegra_ivc_read_advance(channel->ivc); 213 err = tegra_bpmp_ack_response(channel);
170 if (err < 0) 214 if (err < 0)
171 return err; 215 return err;
172 216
@@ -210,7 +254,7 @@ static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
210 if (data && size > 0) 254 if (data && size > 0)
211 memcpy(channel->ob->data, data, size); 255 memcpy(channel->ob->data, data, size);
212 256
213 return tegra_ivc_write_advance(channel->ivc); 257 return tegra_bpmp_post_request(channel);
214} 258}
215 259
216static struct tegra_bpmp_channel * 260static struct tegra_bpmp_channel *
@@ -238,7 +282,7 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq,
238 282
239 channel = &bpmp->threaded_channels[index]; 283 channel = &bpmp->threaded_channels[index];
240 284
241 if (!tegra_bpmp_master_free(channel)) { 285 if (!tegra_bpmp_is_request_channel_free(channel)) {
242 err = -EBUSY; 286 err = -EBUSY;
243 goto unlock; 287 goto unlock;
244 } 288 }
@@ -270,7 +314,7 @@ static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
270{ 314{
271 int err; 315 int err;
272 316
273 err = tegra_bpmp_wait_master_free(channel); 317 err = tegra_bpmp_wait_request_channel_free(channel);
274 if (err < 0) 318 if (err < 0)
275 return err; 319 return err;
276 320
@@ -302,13 +346,11 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
302 346
303 spin_unlock(&bpmp->atomic_tx_lock); 347 spin_unlock(&bpmp->atomic_tx_lock);
304 348
305 err = mbox_send_message(bpmp->mbox.channel, NULL); 349 err = tegra_bpmp_ring_doorbell(bpmp);
306 if (err < 0) 350 if (err < 0)
307 return err; 351 return err;
308 352
309 mbox_client_txdone(bpmp->mbox.channel, 0); 353 err = tegra_bpmp_wait_response(channel);
310
311 err = tegra_bpmp_wait_ack(channel);
312 if (err < 0) 354 if (err < 0)
313 return err; 355 return err;
314 356
@@ -335,12 +377,10 @@ int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
335 if (IS_ERR(channel)) 377 if (IS_ERR(channel))
336 return PTR_ERR(channel); 378 return PTR_ERR(channel);
337 379
338 err = mbox_send_message(bpmp->mbox.channel, NULL); 380 err = tegra_bpmp_ring_doorbell(bpmp);
339 if (err < 0) 381 if (err < 0)
340 return err; 382 return err;
341 383
342 mbox_client_txdone(bpmp->mbox.channel, 0);
343
344 timeout = usecs_to_jiffies(bpmp->soc->channels.thread.timeout); 384 timeout = usecs_to_jiffies(bpmp->soc->channels.thread.timeout);
345 385
346 err = wait_for_completion_timeout(&channel->completion, timeout); 386 err = wait_for_completion_timeout(&channel->completion, timeout);
@@ -369,38 +409,34 @@ void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code,
369{ 409{
370 unsigned long flags = channel->ib->flags; 410 unsigned long flags = channel->ib->flags;
371 struct tegra_bpmp *bpmp = channel->bpmp; 411 struct tegra_bpmp *bpmp = channel->bpmp;
372 struct tegra_bpmp_mb_data *frame;
373 int err; 412 int err;
374 413
375 if (WARN_ON(size > MSG_DATA_MIN_SZ)) 414 if (WARN_ON(size > MSG_DATA_MIN_SZ))
376 return; 415 return;
377 416
378 err = tegra_ivc_read_advance(channel->ivc); 417 err = tegra_bpmp_ack_request(channel);
379 if (WARN_ON(err < 0)) 418 if (WARN_ON(err < 0))
380 return; 419 return;
381 420
382 if ((flags & MSG_ACK) == 0) 421 if ((flags & MSG_ACK) == 0)
383 return; 422 return;
384 423
385 frame = tegra_ivc_write_get_next_frame(channel->ivc); 424 if (WARN_ON(!tegra_bpmp_is_response_channel_free(channel)))
386 if (WARN_ON(IS_ERR(frame)))
387 return; 425 return;
388 426
389 frame->code = code; 427 channel->ob->code = code;
390 428
391 if (data && size > 0) 429 if (data && size > 0)
392 memcpy(frame->data, data, size); 430 memcpy(channel->ob->data, data, size);
393 431
394 err = tegra_ivc_write_advance(channel->ivc); 432 err = tegra_bpmp_post_response(channel);
395 if (WARN_ON(err < 0)) 433 if (WARN_ON(err < 0))
396 return; 434 return;
397 435
398 if (flags & MSG_RING) { 436 if (flags & MSG_RING) {
399 err = mbox_send_message(bpmp->mbox.channel, NULL); 437 err = tegra_bpmp_ring_doorbell(bpmp);
400 if (WARN_ON(err < 0)) 438 if (WARN_ON(err < 0))
401 return; 439 return;
402
403 mbox_client_txdone(bpmp->mbox.channel, 0);
404 } 440 }
405} 441}
406EXPORT_SYMBOL_GPL(tegra_bpmp_mrq_return); 442EXPORT_SYMBOL_GPL(tegra_bpmp_mrq_return);
@@ -627,9 +663,8 @@ static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel)
627 complete(&channel->completion); 663 complete(&channel->completion);
628} 664}
629 665
630static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data) 666void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp)
631{ 667{
632 struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
633 struct tegra_bpmp_channel *channel; 668 struct tegra_bpmp_channel *channel;
634 unsigned int i, count; 669 unsigned int i, count;
635 unsigned long *busy; 670 unsigned long *busy;
@@ -638,7 +673,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
638 count = bpmp->soc->channels.thread.count; 673 count = bpmp->soc->channels.thread.count;
639 busy = bpmp->threaded.busy; 674 busy = bpmp->threaded.busy;
640 675
641 if (tegra_bpmp_master_acked(channel)) 676 if (tegra_bpmp_is_request_ready(channel))
642 tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel); 677 tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel);
643 678
644 spin_lock(&bpmp->lock); 679 spin_lock(&bpmp->lock);
@@ -648,7 +683,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
648 683
649 channel = &bpmp->threaded_channels[i]; 684 channel = &bpmp->threaded_channels[i];
650 685
651 if (tegra_bpmp_master_acked(channel)) { 686 if (tegra_bpmp_is_response_ready(channel)) {
652 tegra_bpmp_channel_signal(channel); 687 tegra_bpmp_channel_signal(channel);
653 clear_bit(i, busy); 688 clear_bit(i, busy);
654 } 689 }
@@ -657,74 +692,9 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
657 spin_unlock(&bpmp->lock); 692 spin_unlock(&bpmp->lock);
658} 693}
659 694
660static void tegra_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
661{
662 struct tegra_bpmp *bpmp = data;
663 int err;
664
665 if (WARN_ON(bpmp->mbox.channel == NULL))
666 return;
667
668 err = mbox_send_message(bpmp->mbox.channel, NULL);
669 if (err < 0)
670 return;
671
672 mbox_client_txdone(bpmp->mbox.channel, 0);
673}
674
675static int tegra_bpmp_channel_init(struct tegra_bpmp_channel *channel,
676 struct tegra_bpmp *bpmp,
677 unsigned int index)
678{
679 size_t message_size, queue_size;
680 unsigned int offset;
681 int err;
682
683 channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
684 GFP_KERNEL);
685 if (!channel->ivc)
686 return -ENOMEM;
687
688 message_size = tegra_ivc_align(MSG_MIN_SZ);
689 queue_size = tegra_ivc_total_queue_size(message_size);
690 offset = queue_size * index;
691
692 err = tegra_ivc_init(channel->ivc, NULL,
693 bpmp->rx.virt + offset, bpmp->rx.phys + offset,
694 bpmp->tx.virt + offset, bpmp->tx.phys + offset,
695 1, message_size, tegra_bpmp_ivc_notify,
696 bpmp);
697 if (err < 0) {
698 dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
699 index, err);
700 return err;
701 }
702
703 init_completion(&channel->completion);
704 channel->bpmp = bpmp;
705
706 return 0;
707}
708
709static void tegra_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
710{
711 /* reset the channel state */
712 tegra_ivc_reset(channel->ivc);
713
714 /* sync the channel state with BPMP */
715 while (tegra_ivc_notified(channel->ivc))
716 ;
717}
718
719static void tegra_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
720{
721 tegra_ivc_cleanup(channel->ivc);
722}
723
724static int tegra_bpmp_probe(struct platform_device *pdev) 695static int tegra_bpmp_probe(struct platform_device *pdev)
725{ 696{
726 struct tegra_bpmp *bpmp; 697 struct tegra_bpmp *bpmp;
727 unsigned int i;
728 char tag[TAG_SZ]; 698 char tag[TAG_SZ];
729 size_t size; 699 size_t size;
730 int err; 700 int err;
@@ -736,32 +706,6 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
736 bpmp->soc = of_device_get_match_data(&pdev->dev); 706 bpmp->soc = of_device_get_match_data(&pdev->dev);
737 bpmp->dev = &pdev->dev; 707 bpmp->dev = &pdev->dev;
738 708
739 bpmp->tx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 0);
740 if (!bpmp->tx.pool) {
741 dev_err(&pdev->dev, "TX shmem pool not found\n");
742 return -ENOMEM;
743 }
744
745 bpmp->tx.virt = gen_pool_dma_alloc(bpmp->tx.pool, 4096, &bpmp->tx.phys);
746 if (!bpmp->tx.virt) {
747 dev_err(&pdev->dev, "failed to allocate from TX pool\n");
748 return -ENOMEM;
749 }
750
751 bpmp->rx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 1);
752 if (!bpmp->rx.pool) {
753 dev_err(&pdev->dev, "RX shmem pool not found\n");
754 err = -ENOMEM;
755 goto free_tx;
756 }
757
758 bpmp->rx.virt = gen_pool_dma_alloc(bpmp->rx.pool, 4096, &bpmp->rx.phys);
759 if (!bpmp->rx.virt) {
760 dev_err(&pdev->dev, "failed to allocate from RX pool\n");
761 err = -ENOMEM;
762 goto free_tx;
763 }
764
765 INIT_LIST_HEAD(&bpmp->mrqs); 709 INIT_LIST_HEAD(&bpmp->mrqs);
766 spin_lock_init(&bpmp->lock); 710 spin_lock_init(&bpmp->lock);
767 711
@@ -771,81 +715,38 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
771 size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long); 715 size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long);
772 716
773 bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); 717 bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
774 if (!bpmp->threaded.allocated) { 718 if (!bpmp->threaded.allocated)
775 err = -ENOMEM; 719 return -ENOMEM;
776 goto free_rx;
777 }
778 720
779 bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); 721 bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
780 if (!bpmp->threaded.busy) { 722 if (!bpmp->threaded.busy)
781 err = -ENOMEM; 723 return -ENOMEM;
782 goto free_rx;
783 }
784 724
785 spin_lock_init(&bpmp->atomic_tx_lock); 725 spin_lock_init(&bpmp->atomic_tx_lock);
786 bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel), 726 bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel),
787 GFP_KERNEL); 727 GFP_KERNEL);
788 if (!bpmp->tx_channel) { 728 if (!bpmp->tx_channel)
789 err = -ENOMEM; 729 return -ENOMEM;
790 goto free_rx;
791 }
792 730
793 bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel), 731 bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel),
794 GFP_KERNEL); 732 GFP_KERNEL);
795 if (!bpmp->rx_channel) { 733 if (!bpmp->rx_channel)
796 err = -ENOMEM; 734 return -ENOMEM;
797 goto free_rx;
798 }
799 735
800 bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count, 736 bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count,
801 sizeof(*bpmp->threaded_channels), 737 sizeof(*bpmp->threaded_channels),
802 GFP_KERNEL); 738 GFP_KERNEL);
803 if (!bpmp->threaded_channels) { 739 if (!bpmp->threaded_channels)
804 err = -ENOMEM; 740 return -ENOMEM;
805 goto free_rx;
806 }
807
808 err = tegra_bpmp_channel_init(bpmp->tx_channel, bpmp,
809 bpmp->soc->channels.cpu_tx.offset);
810 if (err < 0)
811 goto free_rx;
812 741
813 err = tegra_bpmp_channel_init(bpmp->rx_channel, bpmp, 742 err = bpmp->soc->ops->init(bpmp);
814 bpmp->soc->channels.cpu_rx.offset);
815 if (err < 0) 743 if (err < 0)
816 goto cleanup_tx_channel; 744 return err;
817
818 for (i = 0; i < bpmp->threaded.count; i++) {
819 err = tegra_bpmp_channel_init(
820 &bpmp->threaded_channels[i], bpmp,
821 bpmp->soc->channels.thread.offset + i);
822 if (err < 0)
823 goto cleanup_threaded_channels;
824 }
825
826 /* mbox registration */
827 bpmp->mbox.client.dev = &pdev->dev;
828 bpmp->mbox.client.rx_callback = tegra_bpmp_handle_rx;
829 bpmp->mbox.client.tx_block = false;
830 bpmp->mbox.client.knows_txdone = false;
831
832 bpmp->mbox.channel = mbox_request_channel(&bpmp->mbox.client, 0);
833 if (IS_ERR(bpmp->mbox.channel)) {
834 err = PTR_ERR(bpmp->mbox.channel);
835 dev_err(&pdev->dev, "failed to get HSP mailbox: %d\n", err);
836 goto cleanup_threaded_channels;
837 }
838
839 /* reset message channels */
840 tegra_bpmp_channel_reset(bpmp->tx_channel);
841 tegra_bpmp_channel_reset(bpmp->rx_channel);
842 for (i = 0; i < bpmp->threaded.count; i++)
843 tegra_bpmp_channel_reset(&bpmp->threaded_channels[i]);
844 745
845 err = tegra_bpmp_request_mrq(bpmp, MRQ_PING, 746 err = tegra_bpmp_request_mrq(bpmp, MRQ_PING,
846 tegra_bpmp_mrq_handle_ping, bpmp); 747 tegra_bpmp_mrq_handle_ping, bpmp);
847 if (err < 0) 748 if (err < 0)
848 goto free_mbox; 749 goto deinit;
849 750
850 err = tegra_bpmp_ping(bpmp); 751 err = tegra_bpmp_ping(bpmp);
851 if (err < 0) { 752 if (err < 0) {
@@ -867,17 +768,23 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
867 if (err < 0) 768 if (err < 0)
868 goto free_mrq; 769 goto free_mrq;
869 770
870 err = tegra_bpmp_init_clocks(bpmp); 771 if (of_find_property(pdev->dev.of_node, "#clock-cells", NULL)) {
871 if (err < 0) 772 err = tegra_bpmp_init_clocks(bpmp);
872 goto free_mrq; 773 if (err < 0)
774 goto free_mrq;
775 }
873 776
874 err = tegra_bpmp_init_resets(bpmp); 777 if (of_find_property(pdev->dev.of_node, "#reset-cells", NULL)) {
875 if (err < 0) 778 err = tegra_bpmp_init_resets(bpmp);
876 goto free_mrq; 779 if (err < 0)
780 goto free_mrq;
781 }
877 782
878 err = tegra_bpmp_init_powergates(bpmp); 783 if (of_find_property(pdev->dev.of_node, "#power-domain-cells", NULL)) {
879 if (err < 0) 784 err = tegra_bpmp_init_powergates(bpmp);
880 goto free_mrq; 785 if (err < 0)
786 goto free_mrq;
787 }
881 788
882 err = tegra_bpmp_init_debugfs(bpmp); 789 err = tegra_bpmp_init_debugfs(bpmp);
883 if (err < 0) 790 if (err < 0)
@@ -887,41 +794,27 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
887 794
888free_mrq: 795free_mrq:
889 tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp); 796 tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp);
890free_mbox: 797deinit:
891 mbox_free_channel(bpmp->mbox.channel); 798 if (bpmp->soc->ops->deinit)
892cleanup_threaded_channels: 799 bpmp->soc->ops->deinit(bpmp);
893 for (i = 0; i < bpmp->threaded.count; i++) {
894 if (bpmp->threaded_channels[i].bpmp)
895 tegra_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
896 }
897 800
898 tegra_bpmp_channel_cleanup(bpmp->rx_channel);
899cleanup_tx_channel:
900 tegra_bpmp_channel_cleanup(bpmp->tx_channel);
901free_rx:
902 gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096);
903free_tx:
904 gen_pool_free(bpmp->tx.pool, (unsigned long)bpmp->tx.virt, 4096);
905 return err; 801 return err;
906} 802}
907 803
908static int __maybe_unused tegra_bpmp_resume(struct device *dev) 804static int __maybe_unused tegra_bpmp_resume(struct device *dev)
909{ 805{
910 struct tegra_bpmp *bpmp = dev_get_drvdata(dev); 806 struct tegra_bpmp *bpmp = dev_get_drvdata(dev);
911 unsigned int i;
912
913 /* reset message channels */
914 tegra_bpmp_channel_reset(bpmp->tx_channel);
915 tegra_bpmp_channel_reset(bpmp->rx_channel);
916
917 for (i = 0; i < bpmp->threaded.count; i++)
918 tegra_bpmp_channel_reset(&bpmp->threaded_channels[i]);
919 807
920 return 0; 808 if (bpmp->soc->ops->resume)
809 return bpmp->soc->ops->resume(bpmp);
810 else
811 return 0;
921} 812}
922 813
923static SIMPLE_DEV_PM_OPS(tegra_bpmp_pm_ops, NULL, tegra_bpmp_resume); 814static SIMPLE_DEV_PM_OPS(tegra_bpmp_pm_ops, NULL, tegra_bpmp_resume);
924 815
816#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
817 IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
925static const struct tegra_bpmp_soc tegra186_soc = { 818static const struct tegra_bpmp_soc tegra186_soc = {
926 .channels = { 819 .channels = {
927 .cpu_tx = { 820 .cpu_tx = {
@@ -938,11 +831,42 @@ static const struct tegra_bpmp_soc tegra186_soc = {
938 .timeout = 0, 831 .timeout = 0,
939 }, 832 },
940 }, 833 },
834 .ops = &tegra186_bpmp_ops,
941 .num_resets = 193, 835 .num_resets = 193,
942}; 836};
837#endif
838
839#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
840static const struct tegra_bpmp_soc tegra210_soc = {
841 .channels = {
842 .cpu_tx = {
843 .offset = 0,
844 .count = 1,
845 .timeout = 60 * USEC_PER_SEC,
846 },
847 .thread = {
848 .offset = 4,
849 .count = 1,
850 .timeout = 600 * USEC_PER_SEC,
851 },
852 .cpu_rx = {
853 .offset = 8,
854 .count = 1,
855 .timeout = 0,
856 },
857 },
858 .ops = &tegra210_bpmp_ops,
859};
860#endif
943 861
944static const struct of_device_id tegra_bpmp_match[] = { 862static const struct of_device_id tegra_bpmp_match[] = {
863#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
864 IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
945 { .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc }, 865 { .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc },
866#endif
867#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
868 { .compatible = "nvidia,tegra210-bpmp", .data = &tegra210_soc },
869#endif
946 { } 870 { }
947}; 871};
948 872
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 69ed1464175c..3fbbb61012c4 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -146,25 +146,8 @@ static int ti_sci_debug_show(struct seq_file *s, void *unused)
146 return 0; 146 return 0;
147} 147}
148 148
149/** 149/* Provide the log file operations interface*/
150 * ti_sci_debug_open() - debug file open 150DEFINE_SHOW_ATTRIBUTE(ti_sci_debug);
151 * @inode: inode pointer
152 * @file: file pointer
153 *
154 * Return: result of single_open
155 */
156static int ti_sci_debug_open(struct inode *inode, struct file *file)
157{
158 return single_open(file, ti_sci_debug_show, inode->i_private);
159}
160
161/* log file operations */
162static const struct file_operations ti_sci_debug_fops = {
163 .open = ti_sci_debug_open,
164 .read = seq_read,
165 .llseek = seq_lseek,
166 .release = single_release,
167};
168 151
169/** 152/**
170 * ti_sci_debugfs_create() - Create log debug file 153 * ti_sci_debugfs_create() - Create log debug file
diff --git a/drivers/firmware/xilinx/Kconfig b/drivers/firmware/xilinx/Kconfig
index 8f44b9cd295a..bd33bbf70daf 100644
--- a/drivers/firmware/xilinx/Kconfig
+++ b/drivers/firmware/xilinx/Kconfig
@@ -6,6 +6,7 @@ menu "Zynq MPSoC Firmware Drivers"
6 6
7config ZYNQMP_FIRMWARE 7config ZYNQMP_FIRMWARE
8 bool "Enable Xilinx Zynq MPSoC firmware interface" 8 bool "Enable Xilinx Zynq MPSoC firmware interface"
9 select MFD_CORE
9 help 10 help
10 Firmware interface driver is used by different 11 Firmware interface driver is used by different
11 drivers to communicate with the firmware for 12 drivers to communicate with the firmware for
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 9a1c72a9280f..98f936125643 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -14,6 +14,7 @@
14#include <linux/compiler.h> 14#include <linux/compiler.h>
15#include <linux/device.h> 15#include <linux/device.h>
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/mfd/core.h>
17#include <linux/module.h> 18#include <linux/module.h>
18#include <linux/of.h> 19#include <linux/of.h>
19#include <linux/of_platform.h> 20#include <linux/of_platform.h>
@@ -23,6 +24,12 @@
23#include <linux/firmware/xlnx-zynqmp.h> 24#include <linux/firmware/xlnx-zynqmp.h>
24#include "zynqmp-debug.h" 25#include "zynqmp-debug.h"
25 26
27static const struct mfd_cell firmware_devs[] = {
28 {
29 .name = "zynqmp_power_controller",
30 },
31};
32
26/** 33/**
27 * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes 34 * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
28 * @ret_status: PMUFW return code 35 * @ret_status: PMUFW return code
@@ -187,6 +194,29 @@ static int zynqmp_pm_get_api_version(u32 *version)
187} 194}
188 195
189/** 196/**
197 * zynqmp_pm_get_chipid - Get silicon ID registers
198 * @idcode: IDCODE register
199 * @version: version register
200 *
201 * Return: Returns the status of the operation and the idcode and version
202 * registers in @idcode and @version.
203 */
204static int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
205{
206 u32 ret_payload[PAYLOAD_ARG_CNT];
207 int ret;
208
209 if (!idcode || !version)
210 return -EINVAL;
211
212 ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
213 *idcode = ret_payload[1];
214 *version = ret_payload[2];
215
216 return ret;
217}
218
219/**
190 * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version 220 * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
191 * @version: Returned version value 221 * @version: Returned version value
192 * 222 *
@@ -469,8 +499,129 @@ static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2,
469 arg1, arg2, out); 499 arg1, arg2, out);
470} 500}
471 501
502/**
503 * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
504 * @reset: Reset to be configured
505 * @assert_flag: Flag stating should reset be asserted (1) or
506 * released (0)
507 *
508 * Return: Returns status, either success or error+reason
509 */
510static int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
511 const enum zynqmp_pm_reset_action assert_flag)
512{
513 return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
514 0, 0, NULL);
515}
516
517/**
518 * zynqmp_pm_reset_get_status - Get status of the reset
519 * @reset: Reset whose status should be returned
520 * @status: Returned status
521 *
522 * Return: Returns status, either success or error+reason
523 */
524static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
525 u32 *status)
526{
527 u32 ret_payload[PAYLOAD_ARG_CNT];
528 int ret;
529
530 if (!status)
531 return -EINVAL;
532
533 ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
534 0, 0, ret_payload);
535 *status = ret_payload[1];
536
537 return ret;
538}
539
540/**
541 * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
542 * master has initialized its own power management
543 *
544 * This API function is to be used for notify the power management controller
545 * about the completed power management initialization.
546 *
547 * Return: Returns status, either success or error+reason
548 */
549static int zynqmp_pm_init_finalize(void)
550{
551 return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
552}
553
554/**
555 * zynqmp_pm_set_suspend_mode() - Set system suspend mode
556 * @mode: Mode to set for system suspend
557 *
558 * This API function is used to set mode of system suspend.
559 *
560 * Return: Returns status, either success or error+reason
561 */
562static int zynqmp_pm_set_suspend_mode(u32 mode)
563{
564 return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
565}
566
567/**
568 * zynqmp_pm_request_node() - Request a node with specific capabilities
569 * @node: Node ID of the slave
570 * @capabilities: Requested capabilities of the slave
571 * @qos: Quality of service (not supported)
572 * @ack: Flag to specify whether acknowledge is requested
573 *
574 * This function is used by master to request particular node from firmware.
575 * Every master must request node before using it.
576 *
577 * Return: Returns status, either success or error+reason
578 */
579static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
580 const u32 qos,
581 const enum zynqmp_pm_request_ack ack)
582{
583 return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
584 qos, ack, NULL);
585}
586
587/**
588 * zynqmp_pm_release_node() - Release a node
589 * @node: Node ID of the slave
590 *
591 * This function is used by master to inform firmware that master
592 * has released node. Once released, master must not use that node
593 * without re-request.
594 *
595 * Return: Returns status, either success or error+reason
596 */
597static int zynqmp_pm_release_node(const u32 node)
598{
599 return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
600}
601
602/**
603 * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
604 * @node: Node ID of the slave
605 * @capabilities: Requested capabilities of the slave
606 * @qos: Quality of service (not supported)
607 * @ack: Flag to specify whether acknowledge is requested
608 *
609 * This API function is to be used for slaves a PU already has requested
610 * to change its capabilities.
611 *
612 * Return: Returns status, either success or error+reason
613 */
614static int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
615 const u32 qos,
616 const enum zynqmp_pm_request_ack ack)
617{
618 return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
619 qos, ack, NULL);
620}
621
472static const struct zynqmp_eemi_ops eemi_ops = { 622static const struct zynqmp_eemi_ops eemi_ops = {
473 .get_api_version = zynqmp_pm_get_api_version, 623 .get_api_version = zynqmp_pm_get_api_version,
624 .get_chipid = zynqmp_pm_get_chipid,
474 .query_data = zynqmp_pm_query_data, 625 .query_data = zynqmp_pm_query_data,
475 .clock_enable = zynqmp_pm_clock_enable, 626 .clock_enable = zynqmp_pm_clock_enable,
476 .clock_disable = zynqmp_pm_clock_disable, 627 .clock_disable = zynqmp_pm_clock_disable,
@@ -482,6 +633,13 @@ static const struct zynqmp_eemi_ops eemi_ops = {
482 .clock_setparent = zynqmp_pm_clock_setparent, 633 .clock_setparent = zynqmp_pm_clock_setparent,
483 .clock_getparent = zynqmp_pm_clock_getparent, 634 .clock_getparent = zynqmp_pm_clock_getparent,
484 .ioctl = zynqmp_pm_ioctl, 635 .ioctl = zynqmp_pm_ioctl,
636 .reset_assert = zynqmp_pm_reset_assert,
637 .reset_get_status = zynqmp_pm_reset_get_status,
638 .init_finalize = zynqmp_pm_init_finalize,
639 .set_suspend_mode = zynqmp_pm_set_suspend_mode,
640 .request_node = zynqmp_pm_request_node,
641 .release_node = zynqmp_pm_release_node,
642 .set_requirement = zynqmp_pm_set_requirement,
485}; 643};
486 644
487/** 645/**
@@ -538,11 +696,19 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
538 696
539 zynqmp_pm_api_debugfs_init(); 697 zynqmp_pm_api_debugfs_init();
540 698
699 ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
700 ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
701 if (ret) {
702 dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
703 return ret;
704 }
705
541 return of_platform_populate(dev->of_node, NULL, NULL, dev); 706 return of_platform_populate(dev->of_node, NULL, NULL, dev);
542} 707}
543 708
544static int zynqmp_firmware_remove(struct platform_device *pdev) 709static int zynqmp_firmware_remove(struct platform_device *pdev)
545{ 710{
711 mfd_remove_devices(&pdev->dev);
546 zynqmp_pm_api_debugfs_exit(); 712 zynqmp_pm_api_debugfs_exit();
547 713
548 return 0; 714 return 0;
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 12980a4ad460..ee6fb6af655e 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
10obj-$(CONFIG_MFD_ACT8945A) += act8945a.o 10obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
11obj-$(CONFIG_MFD_SM501) += sm501.o 11obj-$(CONFIG_MFD_SM501) += sm501.o
12obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o 12obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
13obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
13obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o 14obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
14obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o 15obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
15cros_ec_core-objs := cros_ec.o 16cros_ec_core-objs := cros_ec.o
diff --git a/drivers/mfd/bcm2835-pm.c b/drivers/mfd/bcm2835-pm.c
new file mode 100644
index 000000000000..42fe67f1538e
--- /dev/null
+++ b/drivers/mfd/bcm2835-pm.c
@@ -0,0 +1,92 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * PM MFD driver for Broadcom BCM2835
4 *
5 * This driver binds to the PM block and creates the MFD device for
6 * the WDT and power drivers.
7 */
8
9#include <linux/delay.h>
10#include <linux/io.h>
11#include <linux/mfd/bcm2835-pm.h>
12#include <linux/mfd/core.h>
13#include <linux/module.h>
14#include <linux/of_address.h>
15#include <linux/of_platform.h>
16#include <linux/platform_device.h>
17#include <linux/types.h>
18#include <linux/watchdog.h>
19
20static const struct mfd_cell bcm2835_pm_devs[] = {
21 { .name = "bcm2835-wdt" },
22};
23
24static const struct mfd_cell bcm2835_power_devs[] = {
25 { .name = "bcm2835-power" },
26};
27
28static int bcm2835_pm_probe(struct platform_device *pdev)
29{
30 struct resource *res;
31 struct device *dev = &pdev->dev;
32 struct bcm2835_pm *pm;
33 int ret;
34
35 pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
36 if (!pm)
37 return -ENOMEM;
38 platform_set_drvdata(pdev, pm);
39
40 pm->dev = dev;
41
42 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
43 pm->base = devm_ioremap_resource(dev, res);
44 if (IS_ERR(pm->base))
45 return PTR_ERR(pm->base);
46
47 ret = devm_mfd_add_devices(dev, -1,
48 bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
49 NULL, 0, NULL);
50 if (ret)
51 return ret;
52
53 /* We'll use the presence of the AXI ASB regs in the
54 * bcm2835-pm binding as the key for whether we can reference
55 * the full PM register range and support power domains.
56 */
57 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
58 if (res) {
59 pm->asb = devm_ioremap_resource(dev, res);
60 if (IS_ERR(pm->asb))
61 return PTR_ERR(pm->asb);
62
63 ret = devm_mfd_add_devices(dev, -1,
64 bcm2835_power_devs,
65 ARRAY_SIZE(bcm2835_power_devs),
66 NULL, 0, NULL);
67 if (ret)
68 return ret;
69 }
70
71 return 0;
72}
73
74static const struct of_device_id bcm2835_pm_of_match[] = {
75 { .compatible = "brcm,bcm2835-pm-wdt", },
76 { .compatible = "brcm,bcm2835-pm", },
77 {},
78};
79MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
80
81static struct platform_driver bcm2835_pm_driver = {
82 .probe = bcm2835_pm_probe,
83 .driver = {
84 .name = "bcm2835-pm",
85 .of_match_table = bcm2835_pm_of_match,
86 },
87};
88module_platform_driver(bcm2835_pm_driver);
89
90MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
91MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD");
92MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 02bf20f51349..2ba49e959c3f 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -2468,9 +2468,14 @@ static int setup_rx_flow(struct dpaa2_eth_priv *priv,
2468 queue.destination.type = DPNI_DEST_DPCON; 2468 queue.destination.type = DPNI_DEST_DPCON;
2469 queue.destination.priority = 1; 2469 queue.destination.priority = 1;
2470 queue.user_context = (u64)(uintptr_t)fq; 2470 queue.user_context = (u64)(uintptr_t)fq;
2471 queue.flc.stash_control = 1;
2472 queue.flc.value &= 0xFFFFFFFFFFFFFFC0;
2473 /* 01 01 00 - data, annotation, flow context */
2474 queue.flc.value |= 0x14;
2471 err = dpni_set_queue(priv->mc_io, 0, priv->mc_token, 2475 err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
2472 DPNI_QUEUE_RX, 0, fq->flowid, 2476 DPNI_QUEUE_RX, 0, fq->flowid,
2473 DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST, 2477 DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST |
2478 DPNI_QUEUE_OPT_FLC,
2474 &queue); 2479 &queue);
2475 if (err) { 2480 if (err) {
2476 dev_err(dev, "dpni_set_queue(RX) failed\n"); 2481 dev_err(dev, "dpni_set_queue(RX) failed\n");
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 0a7a470ee859..4ad846ceac7c 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -192,4 +192,14 @@ config SC27XX_EFUSE
192 This driver can also be built as a module. If so, the module 192 This driver can also be built as a module. If so, the module
193 will be called nvmem-sc27xx-efuse. 193 will be called nvmem-sc27xx-efuse.
194 194
195config NVMEM_ZYNQMP
196 bool "Xilinx ZYNQMP SoC nvmem firmware support"
197 depends on ARCH_ZYNQMP
198 help
199 This is a driver to access hardware related data like
200 soc revision, IDCODE... etc by using the firmware
201 interface.
202
203 If sure, say yes. If unsure, say no.
204
195endif 205endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 4e8c61628f1a..2ece8ffffdda 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -41,3 +41,5 @@ obj-$(CONFIG_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
41nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o 41nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
42obj-$(CONFIG_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o 42obj-$(CONFIG_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o
43nvmem-sc27xx-efuse-y := sc27xx-efuse.o 43nvmem-sc27xx-efuse-y := sc27xx-efuse.o
44obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o
45nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o
diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c
new file mode 100644
index 000000000000..490c8fcaec80
--- /dev/null
+++ b/drivers/nvmem/zynqmp_nvmem.c
@@ -0,0 +1,86 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2019 Xilinx, Inc.
4 */
5
6#include <linux/module.h>
7#include <linux/nvmem-provider.h>
8#include <linux/of.h>
9#include <linux/platform_device.h>
10#include <linux/firmware/xlnx-zynqmp.h>
11
12#define SILICON_REVISION_MASK 0xF
13
14struct zynqmp_nvmem_data {
15 struct device *dev;
16 struct nvmem_device *nvmem;
17};
18
19static int zynqmp_nvmem_read(void *context, unsigned int offset,
20 void *val, size_t bytes)
21{
22 int ret;
23 int idcode, version;
24 struct zynqmp_nvmem_data *priv = context;
25
26 const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
27
28 if (!eemi_ops || !eemi_ops->get_chipid)
29 return -ENXIO;
30
31 ret = eemi_ops->get_chipid(&idcode, &version);
32 if (ret < 0)
33 return ret;
34
35 dev_dbg(priv->dev, "Read chipid val %x %x\n", idcode, version);
36 *(int *)val = version & SILICON_REVISION_MASK;
37
38 return 0;
39}
40
41static struct nvmem_config econfig = {
42 .name = "zynqmp-nvmem",
43 .owner = THIS_MODULE,
44 .word_size = 1,
45 .size = 1,
46 .read_only = true,
47};
48
49static const struct of_device_id zynqmp_nvmem_match[] = {
50 { .compatible = "xlnx,zynqmp-nvmem-fw", },
51 { /* sentinel */ },
52};
53MODULE_DEVICE_TABLE(of, zynqmp_nvmem_match);
54
55static int zynqmp_nvmem_probe(struct platform_device *pdev)
56{
57 struct device *dev = &pdev->dev;
58 struct zynqmp_nvmem_data *priv;
59
60 priv = devm_kzalloc(dev, sizeof(struct zynqmp_nvmem_data), GFP_KERNEL);
61 if (!priv)
62 return -ENOMEM;
63
64 priv->dev = dev;
65 econfig.dev = dev;
66 econfig.reg_read = zynqmp_nvmem_read;
67 econfig.priv = priv;
68
69 priv->nvmem = devm_nvmem_register(dev, &econfig);
70
71 return PTR_ERR_OR_ZERO(priv->nvmem);
72}
73
74static struct platform_driver zynqmp_nvmem_driver = {
75 .probe = zynqmp_nvmem_probe,
76 .driver = {
77 .name = "zynqmp-nvmem",
78 .of_match_table = zynqmp_nvmem_match,
79 },
80};
81
82module_platform_driver(zynqmp_nvmem_driver);
83
84MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>, Nava kishore Manne <navam@xilinx.com>");
85MODULE_DESCRIPTION("ZynqMP NVMEM driver");
86MODULE_LICENSE("GPL");
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 18f1639dbc4a..e06a0ab05ad6 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -131,6 +131,24 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
131EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq); 131EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
132 132
133/** 133/**
134 * dev_pm_opp_get_level() - Gets the level corresponding to an available opp
135 * @opp: opp for which level value has to be returned for
136 *
137 * Return: level read from device tree corresponding to the opp, else
138 * return 0.
139 */
140unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp)
141{
142 if (IS_ERR_OR_NULL(opp) || !opp->available) {
143 pr_err("%s: Invalid parameters\n", __func__);
144 return 0;
145 }
146
147 return opp->level;
148}
149EXPORT_SYMBOL_GPL(dev_pm_opp_get_level);
150
151/**
134 * dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not 152 * dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not
135 * @opp: opp for which turbo mode is being verified 153 * @opp: opp for which turbo mode is being verified
136 * 154 *
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 06f0f632ec47..1779f2c93291 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -594,6 +594,8 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
594 new_opp->rate = (unsigned long)rate; 594 new_opp->rate = (unsigned long)rate;
595 } 595 }
596 596
597 of_property_read_u32(np, "opp-level", &new_opp->level);
598
597 /* Check if the OPP supports hardware's hierarchy of versions or not */ 599 /* Check if the OPP supports hardware's hierarchy of versions or not */
598 if (!_opp_is_supported(dev, opp_table, np)) { 600 if (!_opp_is_supported(dev, opp_table, np)) {
599 dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate); 601 dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate);
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
index e24d81497375..4458175aa661 100644
--- a/drivers/opp/opp.h
+++ b/drivers/opp/opp.h
@@ -60,6 +60,7 @@ extern struct list_head opp_tables;
60 * @suspend: true if suspend OPP 60 * @suspend: true if suspend OPP
61 * @pstate: Device's power domain's performance state. 61 * @pstate: Device's power domain's performance state.
62 * @rate: Frequency in hertz 62 * @rate: Frequency in hertz
63 * @level: Performance level
63 * @supplies: Power supplies voltage/current values 64 * @supplies: Power supplies voltage/current values
64 * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's 65 * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
65 * frequency from any other OPP's frequency. 66 * frequency from any other OPP's frequency.
@@ -80,6 +81,7 @@ struct dev_pm_opp {
80 bool suspend; 81 bool suspend;
81 unsigned int pstate; 82 unsigned int pstate;
82 unsigned long rate; 83 unsigned long rate;
84 unsigned int level;
83 85
84 struct dev_pm_opp_supply *supplies; 86 struct dev_pm_opp_supply *supplies;
85 87
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 2e01bd833ffd..2c8c23db92fb 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -40,6 +40,14 @@ config RESET_BERLIN
40 help 40 help
41 This enables the reset controller driver for Marvell Berlin SoCs. 41 This enables the reset controller driver for Marvell Berlin SoCs.
42 42
43config RESET_BRCMSTB
44 tristate "Broadcom STB reset controller"
45 depends on ARCH_BRCMSTB || COMPILE_TEST
46 default ARCH_BRCMSTB
47 help
48 This enables the reset controller driver for Broadcom STB SoCs using
49 a SUN_TOP_CTRL_SW_INIT style controller.
50
43config RESET_HSDK 51config RESET_HSDK
44 bool "Synopsys HSDK Reset Driver" 52 bool "Synopsys HSDK Reset Driver"
45 depends on HAS_IOMEM 53 depends on HAS_IOMEM
@@ -48,9 +56,9 @@ config RESET_HSDK
48 This enables the reset controller driver for HSDK board. 56 This enables the reset controller driver for HSDK board.
49 57
50config RESET_IMX7 58config RESET_IMX7
51 bool "i.MX7 Reset Driver" if COMPILE_TEST 59 bool "i.MX7/8 Reset Driver" if COMPILE_TEST
52 depends on HAS_IOMEM 60 depends on HAS_IOMEM
53 default SOC_IMX7D 61 default SOC_IMX7D || (ARM64 && ARCH_MXC)
54 select MFD_SYSCON 62 select MFD_SYSCON
55 help 63 help
56 This enables the reset controller driver for i.MX7 SoCs. 64 This enables the reset controller driver for i.MX7 SoCs.
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index dc7874df78d9..61456b8f659c 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
7obj-$(CONFIG_RESET_ATH79) += reset-ath79.o 7obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
8obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o 8obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o
9obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o 9obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
10obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
10obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o 11obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
11obj-$(CONFIG_RESET_IMX7) += reset-imx7.o 12obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
12obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o 13obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
@@ -26,4 +27,5 @@ obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
26obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o 27obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
27obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o 28obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
28obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o 29obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
30obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
29 31
diff --git a/drivers/reset/reset-brcmstb.c b/drivers/reset/reset-brcmstb.c
new file mode 100644
index 000000000000..a608f445dad6
--- /dev/null
+++ b/drivers/reset/reset-brcmstb.c
@@ -0,0 +1,132 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Broadcom STB generic reset controller for SW_INIT style reset controller
4 *
5 * Author: Florian Fainelli <f.fainelli@gmail.com>
6 * Copyright (C) 2018 Broadcom
7 */
8#include <linux/delay.h>
9#include <linux/device.h>
10#include <linux/io.h>
11#include <linux/module.h>
12#include <linux/of.h>
13#include <linux/platform_device.h>
14#include <linux/reset-controller.h>
15#include <linux/types.h>
16
17struct brcmstb_reset {
18 void __iomem *base;
19 struct reset_controller_dev rcdev;
20};
21
22#define SW_INIT_SET 0x00
23#define SW_INIT_CLEAR 0x04
24#define SW_INIT_STATUS 0x08
25
26#define SW_INIT_BIT(id) BIT((id) & 0x1f)
27#define SW_INIT_BANK(id) ((id) >> 5)
28
29/* A full bank contains extra registers that we are not utilizing but still
30 * qualify as a single bank.
31 */
32#define SW_INIT_BANK_SIZE 0x18
33
34static inline
35struct brcmstb_reset *to_brcmstb(struct reset_controller_dev *rcdev)
36{
37 return container_of(rcdev, struct brcmstb_reset, rcdev);
38}
39
40static int brcmstb_reset_assert(struct reset_controller_dev *rcdev,
41 unsigned long id)
42{
43 unsigned int off = SW_INIT_BANK(id) * SW_INIT_BANK_SIZE;
44 struct brcmstb_reset *priv = to_brcmstb(rcdev);
45
46 writel_relaxed(SW_INIT_BIT(id), priv->base + off + SW_INIT_SET);
47
48 return 0;
49}
50
51static int brcmstb_reset_deassert(struct reset_controller_dev *rcdev,
52 unsigned long id)
53{
54 unsigned int off = SW_INIT_BANK(id) * SW_INIT_BANK_SIZE;
55 struct brcmstb_reset *priv = to_brcmstb(rcdev);
56
57 writel_relaxed(SW_INIT_BIT(id), priv->base + off + SW_INIT_CLEAR);
58 /* Maximum reset delay after de-asserting a line and seeing block
59 * operation is typically 14us for the worst case, build some slack
60 * here.
61 */
62 usleep_range(100, 200);
63
64 return 0;
65}
66
67static int brcmstb_reset_status(struct reset_controller_dev *rcdev,
68 unsigned long id)
69{
70 unsigned int off = SW_INIT_BANK(id) * SW_INIT_BANK_SIZE;
71 struct brcmstb_reset *priv = to_brcmstb(rcdev);
72
73 return readl_relaxed(priv->base + off + SW_INIT_STATUS) &
74 SW_INIT_BIT(id);
75}
76
77static const struct reset_control_ops brcmstb_reset_ops = {
78 .assert = brcmstb_reset_assert,
79 .deassert = brcmstb_reset_deassert,
80 .status = brcmstb_reset_status,
81};
82
83static int brcmstb_reset_probe(struct platform_device *pdev)
84{
85 struct device *kdev = &pdev->dev;
86 struct brcmstb_reset *priv;
87 struct resource *res;
88
89 priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL);
90 if (!priv)
91 return -ENOMEM;
92
93 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
94 if (!IS_ALIGNED(res->start, SW_INIT_BANK_SIZE) ||
95 !IS_ALIGNED(resource_size(res), SW_INIT_BANK_SIZE)) {
96 dev_err(kdev, "incorrect register range\n");
97 return -EINVAL;
98 }
99
100 priv->base = devm_ioremap_resource(kdev, res);
101 if (IS_ERR(priv->base))
102 return PTR_ERR(priv->base);
103
104 dev_set_drvdata(kdev, priv);
105
106 priv->rcdev.owner = THIS_MODULE;
107 priv->rcdev.nr_resets = DIV_ROUND_DOWN_ULL(resource_size(res),
108 SW_INIT_BANK_SIZE) * 32;
109 priv->rcdev.ops = &brcmstb_reset_ops;
110 priv->rcdev.of_node = kdev->of_node;
111 /* Use defaults: 1 cell and simple xlate function */
112
113 return devm_reset_controller_register(kdev, &priv->rcdev);
114}
115
116static const struct of_device_id brcmstb_reset_of_match[] = {
117 { .compatible = "brcm,brcmstb-reset" },
118 { /* sentinel */ }
119};
120
121static struct platform_driver brcmstb_reset_driver = {
122 .probe = brcmstb_reset_probe,
123 .driver = {
124 .name = "brcmstb-reset",
125 .of_match_table = brcmstb_reset_of_match,
126 },
127};
128module_platform_driver(brcmstb_reset_driver);
129
130MODULE_AUTHOR("Broadcom");
131MODULE_DESCRIPTION("Broadcom STB reset controller");
132MODULE_LICENSE("GPL");
diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
index 77911fa8f31d..aed76e33a0a9 100644
--- a/drivers/reset/reset-imx7.c
+++ b/drivers/reset/reset-imx7.c
@@ -17,14 +17,27 @@
17 17
18#include <linux/mfd/syscon.h> 18#include <linux/mfd/syscon.h>
19#include <linux/mod_devicetable.h> 19#include <linux/mod_devicetable.h>
20#include <linux/of_device.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include <linux/reset-controller.h> 22#include <linux/reset-controller.h>
22#include <linux/regmap.h> 23#include <linux/regmap.h>
23#include <dt-bindings/reset/imx7-reset.h> 24#include <dt-bindings/reset/imx7-reset.h>
25#include <dt-bindings/reset/imx8mq-reset.h>
26
27struct imx7_src_signal {
28 unsigned int offset, bit;
29};
30
31struct imx7_src_variant {
32 const struct imx7_src_signal *signals;
33 unsigned int signals_num;
34 struct reset_control_ops ops;
35};
24 36
25struct imx7_src { 37struct imx7_src {
26 struct reset_controller_dev rcdev; 38 struct reset_controller_dev rcdev;
27 struct regmap *regmap; 39 struct regmap *regmap;
40 const struct imx7_src_signal *signals;
28}; 41};
29 42
30enum imx7_src_registers { 43enum imx7_src_registers {
@@ -39,9 +52,14 @@ enum imx7_src_registers {
39 SRC_DDRC_RCR = 0x1000, 52 SRC_DDRC_RCR = 0x1000,
40}; 53};
41 54
42struct imx7_src_signal { 55static int imx7_reset_update(struct imx7_src *imx7src,
43 unsigned int offset, bit; 56 unsigned long id, unsigned int value)
44}; 57{
58 const struct imx7_src_signal *signal = &imx7src->signals[id];
59
60 return regmap_update_bits(imx7src->regmap,
61 signal->offset, signal->bit, value);
62}
45 63
46static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = { 64static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
47 [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) }, 65 [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
@@ -81,8 +99,8 @@ static int imx7_reset_set(struct reset_controller_dev *rcdev,
81 unsigned long id, bool assert) 99 unsigned long id, bool assert)
82{ 100{
83 struct imx7_src *imx7src = to_imx7_src(rcdev); 101 struct imx7_src *imx7src = to_imx7_src(rcdev);
84 const struct imx7_src_signal *signal = &imx7_src_signals[id]; 102 const unsigned int bit = imx7src->signals[id].bit;
85 unsigned int value = assert ? signal->bit : 0; 103 unsigned int value = assert ? bit : 0;
86 104
87 switch (id) { 105 switch (id) {
88 case IMX7_RESET_PCIEPHY: 106 case IMX7_RESET_PCIEPHY:
@@ -95,12 +113,11 @@ static int imx7_reset_set(struct reset_controller_dev *rcdev,
95 break; 113 break;
96 114
97 case IMX7_RESET_PCIE_CTRL_APPS_EN: 115 case IMX7_RESET_PCIE_CTRL_APPS_EN:
98 value = (assert) ? 0 : signal->bit; 116 value = assert ? 0 : bit;
99 break; 117 break;
100 } 118 }
101 119
102 return regmap_update_bits(imx7src->regmap, 120 return imx7_reset_update(imx7src, id, value);
103 signal->offset, signal->bit, value);
104} 121}
105 122
106static int imx7_reset_assert(struct reset_controller_dev *rcdev, 123static int imx7_reset_assert(struct reset_controller_dev *rcdev,
@@ -115,9 +132,133 @@ static int imx7_reset_deassert(struct reset_controller_dev *rcdev,
115 return imx7_reset_set(rcdev, id, false); 132 return imx7_reset_set(rcdev, id, false);
116} 133}
117 134
118static const struct reset_control_ops imx7_reset_ops = { 135static const struct imx7_src_variant variant_imx7 = {
119 .assert = imx7_reset_assert, 136 .signals = imx7_src_signals,
120 .deassert = imx7_reset_deassert, 137 .signals_num = ARRAY_SIZE(imx7_src_signals),
138 .ops = {
139 .assert = imx7_reset_assert,
140 .deassert = imx7_reset_deassert,
141 },
142};
143
144enum imx8mq_src_registers {
145 SRC_A53RCR0 = 0x0004,
146 SRC_HDMI_RCR = 0x0030,
147 SRC_DISP_RCR = 0x0034,
148 SRC_GPU_RCR = 0x0040,
149 SRC_VPU_RCR = 0x0044,
150 SRC_PCIE2_RCR = 0x0048,
151 SRC_MIPIPHY1_RCR = 0x004c,
152 SRC_MIPIPHY2_RCR = 0x0050,
153 SRC_DDRC2_RCR = 0x1004,
154};
155
156static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = {
157 [IMX8MQ_RESET_A53_CORE_POR_RESET0] = { SRC_A53RCR0, BIT(0) },
158 [IMX8MQ_RESET_A53_CORE_POR_RESET1] = { SRC_A53RCR0, BIT(1) },
159 [IMX8MQ_RESET_A53_CORE_POR_RESET2] = { SRC_A53RCR0, BIT(2) },
160 [IMX8MQ_RESET_A53_CORE_POR_RESET3] = { SRC_A53RCR0, BIT(3) },
161 [IMX8MQ_RESET_A53_CORE_RESET0] = { SRC_A53RCR0, BIT(4) },
162 [IMX8MQ_RESET_A53_CORE_RESET1] = { SRC_A53RCR0, BIT(5) },
163 [IMX8MQ_RESET_A53_CORE_RESET2] = { SRC_A53RCR0, BIT(6) },
164 [IMX8MQ_RESET_A53_CORE_RESET3] = { SRC_A53RCR0, BIT(7) },
165 [IMX8MQ_RESET_A53_DBG_RESET0] = { SRC_A53RCR0, BIT(8) },
166 [IMX8MQ_RESET_A53_DBG_RESET1] = { SRC_A53RCR0, BIT(9) },
167 [IMX8MQ_RESET_A53_DBG_RESET2] = { SRC_A53RCR0, BIT(10) },
168 [IMX8MQ_RESET_A53_DBG_RESET3] = { SRC_A53RCR0, BIT(11) },
169 [IMX8MQ_RESET_A53_ETM_RESET0] = { SRC_A53RCR0, BIT(12) },
170 [IMX8MQ_RESET_A53_ETM_RESET1] = { SRC_A53RCR0, BIT(13) },
171 [IMX8MQ_RESET_A53_ETM_RESET2] = { SRC_A53RCR0, BIT(14) },
172 [IMX8MQ_RESET_A53_ETM_RESET3] = { SRC_A53RCR0, BIT(15) },
173 [IMX8MQ_RESET_A53_SOC_DBG_RESET] = { SRC_A53RCR0, BIT(20) },
174 [IMX8MQ_RESET_A53_L2RESET] = { SRC_A53RCR0, BIT(21) },
175 [IMX8MQ_RESET_SW_NON_SCLR_M4C_RST] = { SRC_M4RCR, BIT(0) },
176 [IMX8MQ_RESET_OTG1_PHY_RESET] = { SRC_USBOPHY1_RCR, BIT(0) },
177 [IMX8MQ_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) },
178 [IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N] = { SRC_MIPIPHY_RCR, BIT(1) },
179 [IMX8MQ_RESET_MIPI_DSI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(2) },
180 [IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(3) },
181 [IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N] = { SRC_MIPIPHY_RCR, BIT(4) },
182 [IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N] = { SRC_MIPIPHY_RCR, BIT(5) },
183 [IMX8MQ_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR,
184 BIT(2) | BIT(1) },
185 [IMX8MQ_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) },
186 [IMX8MQ_RESET_PCIE_CTRL_APPS_EN] = { SRC_PCIEPHY_RCR, BIT(6) },
187 [IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF] = { SRC_PCIEPHY_RCR, BIT(11) },
188 [IMX8MQ_RESET_HDMI_PHY_APB_RESET] = { SRC_HDMI_RCR, BIT(0) },
189 [IMX8MQ_RESET_DISP_RESET] = { SRC_DISP_RCR, BIT(0) },
190 [IMX8MQ_RESET_GPU_RESET] = { SRC_GPU_RCR, BIT(0) },
191 [IMX8MQ_RESET_VPU_RESET] = { SRC_VPU_RCR, BIT(0) },
192 [IMX8MQ_RESET_PCIEPHY2] = { SRC_PCIE2_RCR,
193 BIT(2) | BIT(1) },
194 [IMX8MQ_RESET_PCIEPHY2_PERST] = { SRC_PCIE2_RCR, BIT(3) },
195 [IMX8MQ_RESET_PCIE2_CTRL_APPS_EN] = { SRC_PCIE2_RCR, BIT(6) },
196 [IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF] = { SRC_PCIE2_RCR, BIT(11) },
197 [IMX8MQ_RESET_MIPI_CSI1_CORE_RESET] = { SRC_MIPIPHY1_RCR, BIT(0) },
198 [IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET] = { SRC_MIPIPHY1_RCR, BIT(1) },
199 [IMX8MQ_RESET_MIPI_CSI1_ESC_RESET] = { SRC_MIPIPHY1_RCR, BIT(2) },
200 [IMX8MQ_RESET_MIPI_CSI2_CORE_RESET] = { SRC_MIPIPHY2_RCR, BIT(0) },
201 [IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET] = { SRC_MIPIPHY2_RCR, BIT(1) },
202 [IMX8MQ_RESET_MIPI_CSI2_ESC_RESET] = { SRC_MIPIPHY2_RCR, BIT(2) },
203 [IMX8MQ_RESET_DDRC1_PRST] = { SRC_DDRC_RCR, BIT(0) },
204 [IMX8MQ_RESET_DDRC1_CORE_RESET] = { SRC_DDRC_RCR, BIT(1) },
205 [IMX8MQ_RESET_DDRC1_PHY_RESET] = { SRC_DDRC_RCR, BIT(2) },
206 [IMX8MQ_RESET_DDRC2_PHY_RESET] = { SRC_DDRC2_RCR, BIT(0) },
207 [IMX8MQ_RESET_DDRC2_CORE_RESET] = { SRC_DDRC2_RCR, BIT(1) },
208 [IMX8MQ_RESET_DDRC2_PRST] = { SRC_DDRC2_RCR, BIT(2) },
209};
210
211static int imx8mq_reset_set(struct reset_controller_dev *rcdev,
212 unsigned long id, bool assert)
213{
214 struct imx7_src *imx7src = to_imx7_src(rcdev);
215 const unsigned int bit = imx7src->signals[id].bit;
216 unsigned int value = assert ? bit : 0;
217
218 switch (id) {
219 case IMX8MQ_RESET_PCIEPHY:
220 case IMX8MQ_RESET_PCIEPHY2: /* fallthrough */
221 /*
222 * wait for more than 10us to release phy g_rst and
223 * btnrst
224 */
225 if (!assert)
226 udelay(10);
227 break;
228
229 case IMX8MQ_RESET_PCIE_CTRL_APPS_EN:
230 case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN: /* fallthrough */
231 case IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N: /* fallthrough */
232 case IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N: /* fallthrough */
233 case IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N: /* fallthrough */
234 case IMX8MQ_RESET_MIPI_DSI_RESET_N: /* fallthrough */
235 case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N: /* fallthrough */
236 value = assert ? 0 : bit;
237 break;
238 }
239
240 return imx7_reset_update(imx7src, id, value);
241}
242
243static int imx8mq_reset_assert(struct reset_controller_dev *rcdev,
244 unsigned long id)
245{
246 return imx8mq_reset_set(rcdev, id, true);
247}
248
249static int imx8mq_reset_deassert(struct reset_controller_dev *rcdev,
250 unsigned long id)
251{
252 return imx8mq_reset_set(rcdev, id, false);
253}
254
255static const struct imx7_src_variant variant_imx8mq = {
256 .signals = imx8mq_src_signals,
257 .signals_num = ARRAY_SIZE(imx8mq_src_signals),
258 .ops = {
259 .assert = imx8mq_reset_assert,
260 .deassert = imx8mq_reset_deassert,
261 },
121}; 262};
122 263
123static int imx7_reset_probe(struct platform_device *pdev) 264static int imx7_reset_probe(struct platform_device *pdev)
@@ -125,11 +266,13 @@ static int imx7_reset_probe(struct platform_device *pdev)
125 struct imx7_src *imx7src; 266 struct imx7_src *imx7src;
126 struct device *dev = &pdev->dev; 267 struct device *dev = &pdev->dev;
127 struct regmap_config config = { .name = "src" }; 268 struct regmap_config config = { .name = "src" };
269 const struct imx7_src_variant *variant = of_device_get_match_data(dev);
128 270
129 imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL); 271 imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
130 if (!imx7src) 272 if (!imx7src)
131 return -ENOMEM; 273 return -ENOMEM;
132 274
275 imx7src->signals = variant->signals;
133 imx7src->regmap = syscon_node_to_regmap(dev->of_node); 276 imx7src->regmap = syscon_node_to_regmap(dev->of_node);
134 if (IS_ERR(imx7src->regmap)) { 277 if (IS_ERR(imx7src->regmap)) {
135 dev_err(dev, "Unable to get imx7-src regmap"); 278 dev_err(dev, "Unable to get imx7-src regmap");
@@ -138,15 +281,16 @@ static int imx7_reset_probe(struct platform_device *pdev)
138 regmap_attach_dev(dev, imx7src->regmap, &config); 281 regmap_attach_dev(dev, imx7src->regmap, &config);
139 282
140 imx7src->rcdev.owner = THIS_MODULE; 283 imx7src->rcdev.owner = THIS_MODULE;
141 imx7src->rcdev.nr_resets = IMX7_RESET_NUM; 284 imx7src->rcdev.nr_resets = variant->signals_num;
142 imx7src->rcdev.ops = &imx7_reset_ops; 285 imx7src->rcdev.ops = &variant->ops;
143 imx7src->rcdev.of_node = dev->of_node; 286 imx7src->rcdev.of_node = dev->of_node;
144 287
145 return devm_reset_controller_register(dev, &imx7src->rcdev); 288 return devm_reset_controller_register(dev, &imx7src->rcdev);
146} 289}
147 290
148static const struct of_device_id imx7_reset_dt_ids[] = { 291static const struct of_device_id imx7_reset_dt_ids[] = {
149 { .compatible = "fsl,imx7d-src", }, 292 { .compatible = "fsl,imx7d-src", .data = &variant_imx7 },
293 { .compatible = "fsl,imx8mq-src", .data = &variant_imx8mq },
150 { /* sentinel */ }, 294 { /* sentinel */ },
151}; 295};
152 296
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
index 318cfc51c441..96953992c2bb 100644
--- a/drivers/reset/reset-socfpga.c
+++ b/drivers/reset/reset-socfpga.c
@@ -11,6 +11,7 @@
11#include <linux/of_address.h> 11#include <linux/of_address.h>
12#include <linux/platform_device.h> 12#include <linux/platform_device.h>
13#include <linux/reset-controller.h> 13#include <linux/reset-controller.h>
14#include <linux/reset/socfpga.h>
14#include <linux/slab.h> 15#include <linux/slab.h>
15#include <linux/spinlock.h> 16#include <linux/spinlock.h>
16#include <linux/types.h> 17#include <linux/types.h>
@@ -18,7 +19,6 @@
18#include "reset-simple.h" 19#include "reset-simple.h"
19 20
20#define SOCFPGA_NR_BANKS 8 21#define SOCFPGA_NR_BANKS 8
21void __init socfpga_reset_init(void);
22 22
23static int a10_reset_init(struct device_node *np) 23static int a10_reset_init(struct device_node *np)
24{ 24{
diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
index db9a1a75523f..b06d724d8f21 100644
--- a/drivers/reset/reset-sunxi.c
+++ b/drivers/reset/reset-sunxi.c
@@ -18,6 +18,7 @@
18#include <linux/of_address.h> 18#include <linux/of_address.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/reset-controller.h> 20#include <linux/reset-controller.h>
21#include <linux/reset/sunxi.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22#include <linux/spinlock.h> 23#include <linux/spinlock.h>
23#include <linux/types.h> 24#include <linux/types.h>
diff --git a/drivers/reset/reset-zynqmp.c b/drivers/reset/reset-zynqmp.c
new file mode 100644
index 000000000000..2ef1f13aa47b
--- /dev/null
+++ b/drivers/reset/reset-zynqmp.c
@@ -0,0 +1,114 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018 Xilinx, Inc.
4 *
5 */
6
7#include <linux/err.h>
8#include <linux/of.h>
9#include <linux/platform_device.h>
10#include <linux/reset-controller.h>
11#include <linux/firmware/xlnx-zynqmp.h>
12
13#define ZYNQMP_NR_RESETS (ZYNQMP_PM_RESET_END - ZYNQMP_PM_RESET_START)
14#define ZYNQMP_RESET_ID ZYNQMP_PM_RESET_START
15
16struct zynqmp_reset_data {
17 struct reset_controller_dev rcdev;
18 const struct zynqmp_eemi_ops *eemi_ops;
19};
20
21static inline struct zynqmp_reset_data *
22to_zynqmp_reset_data(struct reset_controller_dev *rcdev)
23{
24 return container_of(rcdev, struct zynqmp_reset_data, rcdev);
25}
26
27static int zynqmp_reset_assert(struct reset_controller_dev *rcdev,
28 unsigned long id)
29{
30 struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
31
32 return priv->eemi_ops->reset_assert(ZYNQMP_RESET_ID + id,
33 PM_RESET_ACTION_ASSERT);
34}
35
36static int zynqmp_reset_deassert(struct reset_controller_dev *rcdev,
37 unsigned long id)
38{
39 struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
40
41 return priv->eemi_ops->reset_assert(ZYNQMP_RESET_ID + id,
42 PM_RESET_ACTION_RELEASE);
43}
44
45static int zynqmp_reset_status(struct reset_controller_dev *rcdev,
46 unsigned long id)
47{
48 struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
49 int val, err;
50
51 err = priv->eemi_ops->reset_get_status(ZYNQMP_RESET_ID + id, &val);
52 if (err)
53 return err;
54
55 return val;
56}
57
58static int zynqmp_reset_reset(struct reset_controller_dev *rcdev,
59 unsigned long id)
60{
61 struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
62
63 return priv->eemi_ops->reset_assert(ZYNQMP_RESET_ID + id,
64 PM_RESET_ACTION_PULSE);
65}
66
67static struct reset_control_ops zynqmp_reset_ops = {
68 .reset = zynqmp_reset_reset,
69 .assert = zynqmp_reset_assert,
70 .deassert = zynqmp_reset_deassert,
71 .status = zynqmp_reset_status,
72};
73
74static int zynqmp_reset_probe(struct platform_device *pdev)
75{
76 struct zynqmp_reset_data *priv;
77
78 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
79 if (!priv)
80 return -ENOMEM;
81
82 platform_set_drvdata(pdev, priv);
83
84 priv->eemi_ops = zynqmp_pm_get_eemi_ops();
85 if (!priv->eemi_ops)
86 return -ENXIO;
87
88 priv->rcdev.ops = &zynqmp_reset_ops;
89 priv->rcdev.owner = THIS_MODULE;
90 priv->rcdev.of_node = pdev->dev.of_node;
91 priv->rcdev.nr_resets = ZYNQMP_NR_RESETS;
92
93 return devm_reset_controller_register(&pdev->dev, &priv->rcdev);
94}
95
96static const struct of_device_id zynqmp_reset_dt_ids[] = {
97 { .compatible = "xlnx,zynqmp-reset", },
98 { /* sentinel */ },
99};
100
101static struct platform_driver zynqmp_reset_driver = {
102 .probe = zynqmp_reset_probe,
103 .driver = {
104 .name = KBUILD_MODNAME,
105 .of_match_table = zynqmp_reset_dt_ids,
106 },
107};
108
109static int __init zynqmp_reset_init(void)
110{
111 return platform_driver_register(&zynqmp_reset_driver);
112}
113
114arch_initcall(zynqmp_reset_init);
diff --git a/drivers/soc/amlogic/meson-canvas.c b/drivers/soc/amlogic/meson-canvas.c
index fce33ca76bb6..be95a37c3fec 100644
--- a/drivers/soc/amlogic/meson-canvas.c
+++ b/drivers/soc/amlogic/meson-canvas.c
@@ -51,16 +51,30 @@ struct meson_canvas *meson_canvas_get(struct device *dev)
51{ 51{
52 struct device_node *canvas_node; 52 struct device_node *canvas_node;
53 struct platform_device *canvas_pdev; 53 struct platform_device *canvas_pdev;
54 struct meson_canvas *canvas;
54 55
55 canvas_node = of_parse_phandle(dev->of_node, "amlogic,canvas", 0); 56 canvas_node = of_parse_phandle(dev->of_node, "amlogic,canvas", 0);
56 if (!canvas_node) 57 if (!canvas_node)
57 return ERR_PTR(-ENODEV); 58 return ERR_PTR(-ENODEV);
58 59
59 canvas_pdev = of_find_device_by_node(canvas_node); 60 canvas_pdev = of_find_device_by_node(canvas_node);
60 if (!canvas_pdev) 61 if (!canvas_pdev) {
62 of_node_put(canvas_node);
61 return ERR_PTR(-EPROBE_DEFER); 63 return ERR_PTR(-EPROBE_DEFER);
64 }
65
66 of_node_put(canvas_node);
67
68 /*
69 * If priv is NULL, it's probably because the canvas hasn't
70 * properly initialized. Bail out with -EINVAL because, in the
71 * current state, this driver probe cannot return -EPROBE_DEFER
72 */
73 canvas = dev_get_drvdata(&canvas_pdev->dev);
74 if (!canvas)
75 return ERR_PTR(-EINVAL);
62 76
63 return dev_get_drvdata(&canvas_pdev->dev); 77 return canvas;
64} 78}
65EXPORT_SYMBOL_GPL(meson_canvas_get); 79EXPORT_SYMBOL_GPL(meson_canvas_get);
66 80
diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c
index daea191a66fa..19d4cbc93a17 100644
--- a/drivers/soc/amlogic/meson-clk-measure.c
+++ b/drivers/soc/amlogic/meson-clk-measure.c
@@ -165,6 +165,194 @@ static struct meson_msr_id clk_msr_gx[CLK_MSR_MAX] = {
165 CLK_MSR_ID(82, "ge2d"), 165 CLK_MSR_ID(82, "ge2d"),
166}; 166};
167 167
168static struct meson_msr_id clk_msr_axg[CLK_MSR_MAX] = {
169 CLK_MSR_ID(0, "ring_osc_out_ee_0"),
170 CLK_MSR_ID(1, "ring_osc_out_ee_1"),
171 CLK_MSR_ID(2, "ring_osc_out_ee_2"),
172 CLK_MSR_ID(3, "a53_ring_osc"),
173 CLK_MSR_ID(4, "gp0_pll"),
174 CLK_MSR_ID(5, "gp1_pll"),
175 CLK_MSR_ID(7, "clk81"),
176 CLK_MSR_ID(9, "encl"),
177 CLK_MSR_ID(17, "sys_pll_div16"),
178 CLK_MSR_ID(18, "sys_cpu_div16"),
179 CLK_MSR_ID(20, "rtc_osc_out"),
180 CLK_MSR_ID(23, "mmc_clk"),
181 CLK_MSR_ID(28, "sar_adc"),
182 CLK_MSR_ID(31, "mpll_test_out"),
183 CLK_MSR_ID(40, "mod_eth_tx_clk"),
184 CLK_MSR_ID(41, "mod_eth_rx_clk_rmii"),
185 CLK_MSR_ID(42, "mp0_out"),
186 CLK_MSR_ID(43, "fclk_div5"),
187 CLK_MSR_ID(44, "pwm_b"),
188 CLK_MSR_ID(45, "pwm_a"),
189 CLK_MSR_ID(46, "vpu"),
190 CLK_MSR_ID(47, "ddr_dpll_pt"),
191 CLK_MSR_ID(48, "mp1_out"),
192 CLK_MSR_ID(49, "mp2_out"),
193 CLK_MSR_ID(50, "mp3_out"),
194 CLK_MSR_ID(51, "sd_emmm_c"),
195 CLK_MSR_ID(52, "sd_emmc_b"),
196 CLK_MSR_ID(61, "gpio_msr"),
197 CLK_MSR_ID(66, "audio_slv_lrclk_c"),
198 CLK_MSR_ID(67, "audio_slv_lrclk_b"),
199 CLK_MSR_ID(68, "audio_slv_lrclk_a"),
200 CLK_MSR_ID(69, "audio_slv_sclk_c"),
201 CLK_MSR_ID(70, "audio_slv_sclk_b"),
202 CLK_MSR_ID(71, "audio_slv_sclk_a"),
203 CLK_MSR_ID(72, "pwm_d"),
204 CLK_MSR_ID(73, "pwm_c"),
205 CLK_MSR_ID(74, "wifi_beacon"),
206 CLK_MSR_ID(75, "tdmin_lb_lrcl"),
207 CLK_MSR_ID(76, "tdmin_lb_sclk"),
208 CLK_MSR_ID(77, "rng_ring_osc_0"),
209 CLK_MSR_ID(78, "rng_ring_osc_1"),
210 CLK_MSR_ID(79, "rng_ring_osc_2"),
211 CLK_MSR_ID(80, "rng_ring_osc_3"),
212 CLK_MSR_ID(81, "vapb"),
213 CLK_MSR_ID(82, "ge2d"),
214 CLK_MSR_ID(84, "audio_resample"),
215 CLK_MSR_ID(85, "audio_pdm_sys"),
216 CLK_MSR_ID(86, "audio_spdifout"),
217 CLK_MSR_ID(87, "audio_spdifin"),
218 CLK_MSR_ID(88, "audio_lrclk_f"),
219 CLK_MSR_ID(89, "audio_lrclk_e"),
220 CLK_MSR_ID(90, "audio_lrclk_d"),
221 CLK_MSR_ID(91, "audio_lrclk_c"),
222 CLK_MSR_ID(92, "audio_lrclk_b"),
223 CLK_MSR_ID(93, "audio_lrclk_a"),
224 CLK_MSR_ID(94, "audio_sclk_f"),
225 CLK_MSR_ID(95, "audio_sclk_e"),
226 CLK_MSR_ID(96, "audio_sclk_d"),
227 CLK_MSR_ID(97, "audio_sclk_c"),
228 CLK_MSR_ID(98, "audio_sclk_b"),
229 CLK_MSR_ID(99, "audio_sclk_a"),
230 CLK_MSR_ID(100, "audio_mclk_f"),
231 CLK_MSR_ID(101, "audio_mclk_e"),
232 CLK_MSR_ID(102, "audio_mclk_d"),
233 CLK_MSR_ID(103, "audio_mclk_c"),
234 CLK_MSR_ID(104, "audio_mclk_b"),
235 CLK_MSR_ID(105, "audio_mclk_a"),
236 CLK_MSR_ID(106, "pcie_refclk_n"),
237 CLK_MSR_ID(107, "pcie_refclk_p"),
238 CLK_MSR_ID(108, "audio_locker_out"),
239 CLK_MSR_ID(109, "audio_locker_in"),
240};
241
242static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = {
243 CLK_MSR_ID(0, "ring_osc_out_ee_0"),
244 CLK_MSR_ID(1, "ring_osc_out_ee_1"),
245 CLK_MSR_ID(2, "ring_osc_out_ee_2"),
246 CLK_MSR_ID(3, "sys_cpu_ring_osc"),
247 CLK_MSR_ID(4, "gp0_pll"),
248 CLK_MSR_ID(6, "enci"),
249 CLK_MSR_ID(7, "clk81"),
250 CLK_MSR_ID(8, "encp"),
251 CLK_MSR_ID(9, "encl"),
252 CLK_MSR_ID(10, "vdac"),
253 CLK_MSR_ID(11, "eth_tx"),
254 CLK_MSR_ID(12, "hifi_pll"),
255 CLK_MSR_ID(13, "mod_tcon"),
256 CLK_MSR_ID(14, "fec_0"),
257 CLK_MSR_ID(15, "fec_1"),
258 CLK_MSR_ID(16, "fec_2"),
259 CLK_MSR_ID(17, "sys_pll_div16"),
260 CLK_MSR_ID(18, "sys_cpu_div16"),
261 CLK_MSR_ID(19, "lcd_an_ph2"),
262 CLK_MSR_ID(20, "rtc_osc_out"),
263 CLK_MSR_ID(21, "lcd_an_ph3"),
264 CLK_MSR_ID(22, "eth_phy_ref"),
265 CLK_MSR_ID(23, "mpll_50m"),
266 CLK_MSR_ID(24, "eth_125m"),
267 CLK_MSR_ID(25, "eth_rmii"),
268 CLK_MSR_ID(26, "sc_int"),
269 CLK_MSR_ID(27, "in_mac"),
270 CLK_MSR_ID(28, "sar_adc"),
271 CLK_MSR_ID(29, "pcie_inp"),
272 CLK_MSR_ID(30, "pcie_inn"),
273 CLK_MSR_ID(31, "mpll_test_out"),
274 CLK_MSR_ID(32, "vdec"),
275 CLK_MSR_ID(33, "sys_cpu_ring_osc_1"),
276 CLK_MSR_ID(34, "eth_mpll_50m"),
277 CLK_MSR_ID(35, "mali"),
278 CLK_MSR_ID(36, "hdmi_tx_pixel"),
279 CLK_MSR_ID(37, "cdac"),
280 CLK_MSR_ID(38, "vdin_meas"),
281 CLK_MSR_ID(39, "bt656"),
282 CLK_MSR_ID(41, "eth_rx_or_rmii"),
283 CLK_MSR_ID(42, "mp0_out"),
284 CLK_MSR_ID(43, "fclk_div5"),
285 CLK_MSR_ID(44, "pwm_b"),
286 CLK_MSR_ID(45, "pwm_a"),
287 CLK_MSR_ID(46, "vpu"),
288 CLK_MSR_ID(47, "ddr_dpll_pt"),
289 CLK_MSR_ID(48, "mp1_out"),
290 CLK_MSR_ID(49, "mp2_out"),
291 CLK_MSR_ID(50, "mp3_out"),
292 CLK_MSR_ID(51, "sd_emmc_c"),
293 CLK_MSR_ID(52, "sd_emmc_b"),
294 CLK_MSR_ID(53, "sd_emmc_a"),
295 CLK_MSR_ID(54, "vpu_clkc"),
296 CLK_MSR_ID(55, "vid_pll_div_out"),
297 CLK_MSR_ID(56, "wave420l_a"),
298 CLK_MSR_ID(57, "wave420l_c"),
299 CLK_MSR_ID(58, "wave420l_b"),
300 CLK_MSR_ID(59, "hcodec"),
301 CLK_MSR_ID(61, "gpio_msr"),
302 CLK_MSR_ID(62, "hevcb"),
303 CLK_MSR_ID(63, "dsi_meas"),
304 CLK_MSR_ID(64, "spicc_1"),
305 CLK_MSR_ID(65, "spicc_0"),
306 CLK_MSR_ID(66, "vid_lock"),
307 CLK_MSR_ID(67, "dsi_phy"),
308 CLK_MSR_ID(68, "hdcp22_esm"),
309 CLK_MSR_ID(69, "hdcp22_skp"),
310 CLK_MSR_ID(70, "pwm_f"),
311 CLK_MSR_ID(71, "pwm_e"),
312 CLK_MSR_ID(72, "pwm_d"),
313 CLK_MSR_ID(73, "pwm_c"),
314 CLK_MSR_ID(75, "hevcf"),
315 CLK_MSR_ID(77, "rng_ring_osc_0"),
316 CLK_MSR_ID(78, "rng_ring_osc_1"),
317 CLK_MSR_ID(79, "rng_ring_osc_2"),
318 CLK_MSR_ID(80, "rng_ring_osc_3"),
319 CLK_MSR_ID(81, "vapb"),
320 CLK_MSR_ID(82, "ge2d"),
321 CLK_MSR_ID(83, "co_rx"),
322 CLK_MSR_ID(84, "co_tx"),
323 CLK_MSR_ID(89, "hdmi_todig"),
324 CLK_MSR_ID(90, "hdmitx_sys"),
325 CLK_MSR_ID(94, "eth_phy_rx"),
326 CLK_MSR_ID(95, "eth_phy_pll"),
327 CLK_MSR_ID(96, "vpu_b"),
328 CLK_MSR_ID(97, "cpu_b_tmp"),
329 CLK_MSR_ID(98, "ts"),
330 CLK_MSR_ID(99, "ring_osc_out_ee_3"),
331 CLK_MSR_ID(100, "ring_osc_out_ee_4"),
332 CLK_MSR_ID(101, "ring_osc_out_ee_5"),
333 CLK_MSR_ID(102, "ring_osc_out_ee_6"),
334 CLK_MSR_ID(103, "ring_osc_out_ee_7"),
335 CLK_MSR_ID(104, "ring_osc_out_ee_8"),
336 CLK_MSR_ID(105, "ring_osc_out_ee_9"),
337 CLK_MSR_ID(106, "ephy_test"),
338 CLK_MSR_ID(107, "au_dac_g128x"),
339 CLK_MSR_ID(108, "audio_locker_out"),
340 CLK_MSR_ID(109, "audio_locker_in"),
341 CLK_MSR_ID(110, "audio_tdmout_c_sclk"),
342 CLK_MSR_ID(111, "audio_tdmout_b_sclk"),
343 CLK_MSR_ID(112, "audio_tdmout_a_sclk"),
344 CLK_MSR_ID(113, "audio_tdmin_lb_sclk"),
345 CLK_MSR_ID(114, "audio_tdmin_c_sclk"),
346 CLK_MSR_ID(115, "audio_tdmin_b_sclk"),
347 CLK_MSR_ID(116, "audio_tdmin_a_sclk"),
348 CLK_MSR_ID(117, "audio_resample"),
349 CLK_MSR_ID(118, "audio_pdm_sys"),
350 CLK_MSR_ID(119, "audio_spdifout_b"),
351 CLK_MSR_ID(120, "audio_spdifout"),
352 CLK_MSR_ID(121, "audio_spdifin"),
353 CLK_MSR_ID(122, "audio_pdm_dclk"),
354};
355
168static int meson_measure_id(struct meson_msr_id *clk_msr_id, 356static int meson_measure_id(struct meson_msr_id *clk_msr_id,
169 unsigned int duration) 357 unsigned int duration)
170{ 358{
@@ -337,6 +525,14 @@ static const struct of_device_id meson_msr_match_table[] = {
337 .compatible = "amlogic,meson8b-clk-measure", 525 .compatible = "amlogic,meson8b-clk-measure",
338 .data = (void *)clk_msr_m8, 526 .data = (void *)clk_msr_m8,
339 }, 527 },
528 {
529 .compatible = "amlogic,meson-axg-clk-measure",
530 .data = (void *)clk_msr_axg,
531 },
532 {
533 .compatible = "amlogic,meson-g12a-clk-measure",
534 .data = (void *)clk_msr_g12a,
535 },
340 { /* sentinel */ } 536 { /* sentinel */ }
341}; 537};
342 538
diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig
index 055a845ed979..03fa91fbe2da 100644
--- a/drivers/soc/bcm/Kconfig
+++ b/drivers/soc/bcm/Kconfig
@@ -1,5 +1,17 @@
1menu "Broadcom SoC drivers" 1menu "Broadcom SoC drivers"
2 2
3config BCM2835_POWER
4 bool "BCM2835 power domain driver"
5 depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
6 default y if ARCH_BCM2835
7 select PM_GENERIC_DOMAINS if PM
8 select RESET_CONTROLLER
9 help
10 This enables support for the BCM2835 power domains and reset
11 controller. Any usage of power domains by the Raspberry Pi
12 firmware means that Linux usage of the same power domain
13 must be accessed using the RASPBERRYPI_POWER driver
14
3config RASPBERRYPI_POWER 15config RASPBERRYPI_POWER
4 bool "Raspberry Pi power domain driver" 16 bool "Raspberry Pi power domain driver"
5 depends on ARCH_BCM2835 || (COMPILE_TEST && OF) 17 depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile
index dc4fced72d21..c81df4b2403c 100644
--- a/drivers/soc/bcm/Makefile
+++ b/drivers/soc/bcm/Makefile
@@ -1,2 +1,3 @@
1obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o
1obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o 2obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
2obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ 3obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
diff --git a/drivers/soc/bcm/bcm2835-power.c b/drivers/soc/bcm/bcm2835-power.c
new file mode 100644
index 000000000000..9351349cf0a9
--- /dev/null
+++ b/drivers/soc/bcm/bcm2835-power.c
@@ -0,0 +1,661 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Power domain driver for Broadcom BCM2835
4 *
5 * Copyright (C) 2018 Broadcom
6 */
7
8#include <dt-bindings/soc/bcm2835-pm.h>
9#include <linux/clk.h>
10#include <linux/delay.h>
11#include <linux/io.h>
12#include <linux/mfd/bcm2835-pm.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/pm_domain.h>
16#include <linux/reset-controller.h>
17#include <linux/types.h>
18
19#define PM_GNRIC 0x00
20#define PM_AUDIO 0x04
21#define PM_STATUS 0x18
22#define PM_RSTC 0x1c
23#define PM_RSTS 0x20
24#define PM_WDOG 0x24
25#define PM_PADS0 0x28
26#define PM_PADS2 0x2c
27#define PM_PADS3 0x30
28#define PM_PADS4 0x34
29#define PM_PADS5 0x38
30#define PM_PADS6 0x3c
31#define PM_CAM0 0x44
32#define PM_CAM0_LDOHPEN BIT(2)
33#define PM_CAM0_LDOLPEN BIT(1)
34#define PM_CAM0_CTRLEN BIT(0)
35
36#define PM_CAM1 0x48
37#define PM_CAM1_LDOHPEN BIT(2)
38#define PM_CAM1_LDOLPEN BIT(1)
39#define PM_CAM1_CTRLEN BIT(0)
40
41#define PM_CCP2TX 0x4c
42#define PM_CCP2TX_LDOEN BIT(1)
43#define PM_CCP2TX_CTRLEN BIT(0)
44
45#define PM_DSI0 0x50
46#define PM_DSI0_LDOHPEN BIT(2)
47#define PM_DSI0_LDOLPEN BIT(1)
48#define PM_DSI0_CTRLEN BIT(0)
49
50#define PM_DSI1 0x54
51#define PM_DSI1_LDOHPEN BIT(2)
52#define PM_DSI1_LDOLPEN BIT(1)
53#define PM_DSI1_CTRLEN BIT(0)
54
55#define PM_HDMI 0x58
56#define PM_HDMI_RSTDR BIT(19)
57#define PM_HDMI_LDOPD BIT(1)
58#define PM_HDMI_CTRLEN BIT(0)
59
60#define PM_USB 0x5c
61/* The power gates must be enabled with this bit before enabling the LDO in the
62 * USB block.
63 */
64#define PM_USB_CTRLEN BIT(0)
65
66#define PM_PXLDO 0x60
67#define PM_PXBG 0x64
68#define PM_DFT 0x68
69#define PM_SMPS 0x6c
70#define PM_XOSC 0x70
71#define PM_SPAREW 0x74
72#define PM_SPARER 0x78
73#define PM_AVS_RSTDR 0x7c
74#define PM_AVS_STAT 0x80
75#define PM_AVS_EVENT 0x84
76#define PM_AVS_INTEN 0x88
77#define PM_DUMMY 0xfc
78
79#define PM_IMAGE 0x108
80#define PM_GRAFX 0x10c
81#define PM_PROC 0x110
82#define PM_ENAB BIT(12)
83#define PM_ISPRSTN BIT(8)
84#define PM_H264RSTN BIT(7)
85#define PM_PERIRSTN BIT(6)
86#define PM_V3DRSTN BIT(6)
87#define PM_ISFUNC BIT(5)
88#define PM_MRDONE BIT(4)
89#define PM_MEMREP BIT(3)
90#define PM_ISPOW BIT(2)
91#define PM_POWOK BIT(1)
92#define PM_POWUP BIT(0)
93#define PM_INRUSH_SHIFT 13
94#define PM_INRUSH_3_5_MA 0
95#define PM_INRUSH_5_MA 1
96#define PM_INRUSH_10_MA 2
97#define PM_INRUSH_20_MA 3
98#define PM_INRUSH_MASK (3 << PM_INRUSH_SHIFT)
99
100#define PM_PASSWORD 0x5a000000
101
102#define PM_WDOG_TIME_SET 0x000fffff
103#define PM_RSTC_WRCFG_CLR 0xffffffcf
104#define PM_RSTS_HADWRH_SET 0x00000040
105#define PM_RSTC_WRCFG_SET 0x00000030
106#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
107#define PM_RSTC_RESET 0x00000102
108
109#define PM_READ(reg) readl(power->base + (reg))
110#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
111
112#define ASB_BRDG_VERSION 0x00
113#define ASB_CPR_CTRL 0x04
114
115#define ASB_V3D_S_CTRL 0x08
116#define ASB_V3D_M_CTRL 0x0c
117#define ASB_ISP_S_CTRL 0x10
118#define ASB_ISP_M_CTRL 0x14
119#define ASB_H264_S_CTRL 0x18
120#define ASB_H264_M_CTRL 0x1c
121
122#define ASB_REQ_STOP BIT(0)
123#define ASB_ACK BIT(1)
124#define ASB_EMPTY BIT(2)
125#define ASB_FULL BIT(3)
126
127#define ASB_AXI_BRDG_ID 0x20
128
129#define ASB_READ(reg) readl(power->asb + (reg))
130#define ASB_WRITE(reg, val) writel(PM_PASSWORD | (val), power->asb + (reg))
131
132struct bcm2835_power_domain {
133 struct generic_pm_domain base;
134 struct bcm2835_power *power;
135 u32 domain;
136 struct clk *clk;
137};
138
139struct bcm2835_power {
140 struct device *dev;
141 /* PM registers. */
142 void __iomem *base;
143 /* AXI Async bridge registers. */
144 void __iomem *asb;
145
146 struct genpd_onecell_data pd_xlate;
147 struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
148 struct reset_controller_dev reset;
149};
150
151static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
152{
153 u64 start = ktime_get_ns();
154
155 /* Enable the module's async AXI bridges. */
156 ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
157 while (ASB_READ(reg) & ASB_ACK) {
158 cpu_relax();
159 if (ktime_get_ns() - start >= 1000)
160 return -ETIMEDOUT;
161 }
162
163 return 0;
164}
165
166static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
167{
168 u64 start = ktime_get_ns();
169
170 /* Enable the module's async AXI bridges. */
171 ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
172 while (!(ASB_READ(reg) & ASB_ACK)) {
173 cpu_relax();
174 if (ktime_get_ns() - start >= 1000)
175 return -ETIMEDOUT;
176 }
177
178 return 0;
179}
180
181static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
182{
183 struct bcm2835_power *power = pd->power;
184
185 /* Enable functional isolation */
186 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
187
188 /* Enable electrical isolation */
189 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
190
191 /* Open the power switches. */
192 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
193
194 return 0;
195}
196
197static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
198{
199 struct bcm2835_power *power = pd->power;
200 struct device *dev = power->dev;
201 u64 start;
202 int ret;
203 int inrush;
204 bool powok;
205
206 /* If it was already powered on by the fw, leave it that way. */
207 if (PM_READ(pm_reg) & PM_POWUP)
208 return 0;
209
210 /* Enable power. Allowing too much current at once may result
211 * in POWOK never getting set, so start low and ramp it up as
212 * necessary to succeed.
213 */
214 powok = false;
215 for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
216 PM_WRITE(pm_reg,
217 (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
218 (inrush << PM_INRUSH_SHIFT) |
219 PM_POWUP);
220
221 start = ktime_get_ns();
222 while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
223 cpu_relax();
224 if (ktime_get_ns() - start >= 3000)
225 break;
226 }
227 }
228 if (!powok) {
229 dev_err(dev, "Timeout waiting for %s power OK\n",
230 pd->base.name);
231 ret = -ETIMEDOUT;
232 goto err_disable_powup;
233 }
234
235 /* Disable electrical isolation */
236 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
237
238 /* Repair memory */
239 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
240 start = ktime_get_ns();
241 while (!(PM_READ(pm_reg) & PM_MRDONE)) {
242 cpu_relax();
243 if (ktime_get_ns() - start >= 1000) {
244 dev_err(dev, "Timeout waiting for %s memory repair\n",
245 pd->base.name);
246 ret = -ETIMEDOUT;
247 goto err_disable_ispow;
248 }
249 }
250
251 /* Disable functional isolation */
252 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
253
254 return 0;
255
256err_disable_ispow:
257 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
258err_disable_powup:
259 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
260 return ret;
261}
262
263static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
264 u32 pm_reg,
265 u32 asb_m_reg,
266 u32 asb_s_reg,
267 u32 reset_flags)
268{
269 struct bcm2835_power *power = pd->power;
270 int ret;
271
272 ret = clk_prepare_enable(pd->clk);
273 if (ret) {
274 dev_err(power->dev, "Failed to enable clock for %s\n",
275 pd->base.name);
276 return ret;
277 }
278
279 /* Wait 32 clocks for reset to propagate, 1 us will be enough */
280 udelay(1);
281
282 clk_disable_unprepare(pd->clk);
283
284 /* Deassert the resets. */
285 PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
286
287 ret = clk_prepare_enable(pd->clk);
288 if (ret) {
289 dev_err(power->dev, "Failed to enable clock for %s\n",
290 pd->base.name);
291 goto err_enable_resets;
292 }
293
294 ret = bcm2835_asb_enable(power, asb_m_reg);
295 if (ret) {
296 dev_err(power->dev, "Failed to enable ASB master for %s\n",
297 pd->base.name);
298 goto err_disable_clk;
299 }
300 ret = bcm2835_asb_enable(power, asb_s_reg);
301 if (ret) {
302 dev_err(power->dev, "Failed to enable ASB slave for %s\n",
303 pd->base.name);
304 goto err_disable_asb_master;
305 }
306
307 return 0;
308
309err_disable_asb_master:
310 bcm2835_asb_disable(power, asb_m_reg);
311err_disable_clk:
312 clk_disable_unprepare(pd->clk);
313err_enable_resets:
314 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
315 return ret;
316}
317
318static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
319 u32 pm_reg,
320 u32 asb_m_reg,
321 u32 asb_s_reg,
322 u32 reset_flags)
323{
324 struct bcm2835_power *power = pd->power;
325 int ret;
326
327 ret = bcm2835_asb_disable(power, asb_s_reg);
328 if (ret) {
329 dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
330 pd->base.name);
331 return ret;
332 }
333 ret = bcm2835_asb_disable(power, asb_m_reg);
334 if (ret) {
335 dev_warn(power->dev, "Failed to disable ASB master for %s\n",
336 pd->base.name);
337 bcm2835_asb_enable(power, asb_s_reg);
338 return ret;
339 }
340
341 clk_disable_unprepare(pd->clk);
342
343 /* Assert the resets. */
344 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
345
346 return 0;
347}
348
349static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
350{
351 struct bcm2835_power_domain *pd =
352 container_of(domain, struct bcm2835_power_domain, base);
353 struct bcm2835_power *power = pd->power;
354
355 switch (pd->domain) {
356 case BCM2835_POWER_DOMAIN_GRAFX:
357 return bcm2835_power_power_on(pd, PM_GRAFX);
358
359 case BCM2835_POWER_DOMAIN_GRAFX_V3D:
360 return bcm2835_asb_power_on(pd, PM_GRAFX,
361 ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
362 PM_V3DRSTN);
363
364 case BCM2835_POWER_DOMAIN_IMAGE:
365 return bcm2835_power_power_on(pd, PM_IMAGE);
366
367 case BCM2835_POWER_DOMAIN_IMAGE_PERI:
368 return bcm2835_asb_power_on(pd, PM_IMAGE,
369 0, 0,
370 PM_PERIRSTN);
371
372 case BCM2835_POWER_DOMAIN_IMAGE_ISP:
373 return bcm2835_asb_power_on(pd, PM_IMAGE,
374 ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
375 PM_ISPRSTN);
376
377 case BCM2835_POWER_DOMAIN_IMAGE_H264:
378 return bcm2835_asb_power_on(pd, PM_IMAGE,
379 ASB_H264_M_CTRL, ASB_H264_S_CTRL,
380 PM_H264RSTN);
381
382 case BCM2835_POWER_DOMAIN_USB:
383 PM_WRITE(PM_USB, PM_USB_CTRLEN);
384 return 0;
385
386 case BCM2835_POWER_DOMAIN_DSI0:
387 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
388 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
389 return 0;
390
391 case BCM2835_POWER_DOMAIN_DSI1:
392 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
393 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
394 return 0;
395
396 case BCM2835_POWER_DOMAIN_CCP2TX:
397 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
398 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
399 return 0;
400
401 case BCM2835_POWER_DOMAIN_HDMI:
402 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
403 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
404 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
405 usleep_range(100, 200);
406 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
407 return 0;
408
409 default:
410 dev_err(power->dev, "Invalid domain %d\n", pd->domain);
411 return -EINVAL;
412 }
413}
414
415static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
416{
417 struct bcm2835_power_domain *pd =
418 container_of(domain, struct bcm2835_power_domain, base);
419 struct bcm2835_power *power = pd->power;
420
421 switch (pd->domain) {
422 case BCM2835_POWER_DOMAIN_GRAFX:
423 return bcm2835_power_power_off(pd, PM_GRAFX);
424
425 case BCM2835_POWER_DOMAIN_GRAFX_V3D:
426 return bcm2835_asb_power_off(pd, PM_GRAFX,
427 ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
428 PM_V3DRSTN);
429
430 case BCM2835_POWER_DOMAIN_IMAGE:
431 return bcm2835_power_power_off(pd, PM_IMAGE);
432
433 case BCM2835_POWER_DOMAIN_IMAGE_PERI:
434 return bcm2835_asb_power_off(pd, PM_IMAGE,
435 0, 0,
436 PM_PERIRSTN);
437
438 case BCM2835_POWER_DOMAIN_IMAGE_ISP:
439 return bcm2835_asb_power_off(pd, PM_IMAGE,
440 ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
441 PM_ISPRSTN);
442
443 case BCM2835_POWER_DOMAIN_IMAGE_H264:
444 return bcm2835_asb_power_off(pd, PM_IMAGE,
445 ASB_H264_M_CTRL, ASB_H264_S_CTRL,
446 PM_H264RSTN);
447
448 case BCM2835_POWER_DOMAIN_USB:
449 PM_WRITE(PM_USB, 0);
450 return 0;
451
452 case BCM2835_POWER_DOMAIN_DSI0:
453 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
454 PM_WRITE(PM_DSI0, 0);
455 return 0;
456
457 case BCM2835_POWER_DOMAIN_DSI1:
458 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
459 PM_WRITE(PM_DSI1, 0);
460 return 0;
461
462 case BCM2835_POWER_DOMAIN_CCP2TX:
463 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
464 PM_WRITE(PM_CCP2TX, 0);
465 return 0;
466
467 case BCM2835_POWER_DOMAIN_HDMI:
468 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
469 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
470 return 0;
471
472 default:
473 dev_err(power->dev, "Invalid domain %d\n", pd->domain);
474 return -EINVAL;
475 }
476}
477
478static void
479bcm2835_init_power_domain(struct bcm2835_power *power,
480 int pd_xlate_index, const char *name)
481{
482 struct device *dev = power->dev;
483 struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
484
485 dom->clk = devm_clk_get(dev->parent, name);
486
487 dom->base.name = name;
488 dom->base.power_on = bcm2835_power_pd_power_on;
489 dom->base.power_off = bcm2835_power_pd_power_off;
490
491 dom->domain = pd_xlate_index;
492 dom->power = power;
493
494 /* XXX: on/off at boot? */
495 pm_genpd_init(&dom->base, NULL, true);
496
497 power->pd_xlate.domains[pd_xlate_index] = &dom->base;
498}
499
500/** bcm2835_reset_reset - Resets a block that has a reset line in the
501 * PM block.
502 *
503 * The consumer of the reset controller must have the power domain up
504 * -- there's no reset ability with the power domain down. To reset
505 * the sub-block, we just disable its access to memory through the
506 * ASB, reset, and re-enable.
507 */
508static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
509 unsigned long id)
510{
511 struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
512 reset);
513 struct bcm2835_power_domain *pd;
514 int ret;
515
516 switch (id) {
517 case BCM2835_RESET_V3D:
518 pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
519 break;
520 case BCM2835_RESET_H264:
521 pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
522 break;
523 case BCM2835_RESET_ISP:
524 pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
525 break;
526 default:
527 dev_err(power->dev, "Bad reset id %ld\n", id);
528 return -EINVAL;
529 }
530
531 ret = bcm2835_power_pd_power_off(&pd->base);
532 if (ret)
533 return ret;
534
535 return bcm2835_power_pd_power_on(&pd->base);
536}
537
538static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
539 unsigned long id)
540{
541 struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
542 reset);
543
544 switch (id) {
545 case BCM2835_RESET_V3D:
546 return !PM_READ(PM_GRAFX & PM_V3DRSTN);
547 case BCM2835_RESET_H264:
548 return !PM_READ(PM_IMAGE & PM_H264RSTN);
549 case BCM2835_RESET_ISP:
550 return !PM_READ(PM_IMAGE & PM_ISPRSTN);
551 default:
552 return -EINVAL;
553 }
554}
555
556static const struct reset_control_ops bcm2835_reset_ops = {
557 .reset = bcm2835_reset_reset,
558 .status = bcm2835_reset_status,
559};
560
561static const char *const power_domain_names[] = {
562 [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
563 [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
564
565 [BCM2835_POWER_DOMAIN_IMAGE] = "image",
566 [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
567 [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
568 [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
569
570 [BCM2835_POWER_DOMAIN_USB] = "usb",
571 [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
572 [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
573 [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
574 [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
575 [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
576 [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
577};
578
579static int bcm2835_power_probe(struct platform_device *pdev)
580{
581 struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
582 struct device *dev = &pdev->dev;
583 struct bcm2835_power *power;
584 static const struct {
585 int parent, child;
586 } domain_deps[] = {
587 { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
588 { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
589 { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
590 { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
591 { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
592 { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
593 { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
594 };
595 int ret, i;
596 u32 id;
597
598 power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
599 if (!power)
600 return -ENOMEM;
601 platform_set_drvdata(pdev, power);
602
603 power->dev = dev;
604 power->base = pm->base;
605 power->asb = pm->asb;
606
607 id = ASB_READ(ASB_AXI_BRDG_ID);
608 if (id != 0x62726467 /* "BRDG" */) {
609 dev_err(dev, "ASB register ID returned 0x%08x\n", id);
610 return -ENODEV;
611 }
612
613 power->pd_xlate.domains = devm_kcalloc(dev,
614 ARRAY_SIZE(power_domain_names),
615 sizeof(*power->pd_xlate.domains),
616 GFP_KERNEL);
617 if (!power->pd_xlate.domains)
618 return -ENOMEM;
619
620 power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
621
622 for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
623 bcm2835_init_power_domain(power, i, power_domain_names[i]);
624
625 for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
626 pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
627 &power->domains[domain_deps[i].child].base);
628 }
629
630 power->reset.owner = THIS_MODULE;
631 power->reset.nr_resets = BCM2835_RESET_COUNT;
632 power->reset.ops = &bcm2835_reset_ops;
633 power->reset.of_node = dev->parent->of_node;
634
635 ret = devm_reset_controller_register(dev, &power->reset);
636 if (ret)
637 return ret;
638
639 of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
640
641 dev_info(dev, "Broadcom BCM2835 power domains driver");
642 return 0;
643}
644
645static int bcm2835_power_remove(struct platform_device *pdev)
646{
647 return 0;
648}
649
650static struct platform_driver bcm2835_power_driver = {
651 .probe = bcm2835_power_probe,
652 .remove = bcm2835_power_remove,
653 .driver = {
654 .name = "bcm2835-power",
655 },
656};
657module_platform_driver(bcm2835_power_driver);
658
659MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
660MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
661MODULE_LICENSE("GPL");
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
index 8f80e8bbf29e..61f8e1433d0a 100644
--- a/drivers/soc/fsl/Kconfig
+++ b/drivers/soc/fsl/Kconfig
@@ -22,6 +22,7 @@ config FSL_GUTS
22config FSL_MC_DPIO 22config FSL_MC_DPIO
23 tristate "QorIQ DPAA2 DPIO driver" 23 tristate "QorIQ DPAA2 DPIO driver"
24 depends on FSL_MC_BUS 24 depends on FSL_MC_BUS
25 select SOC_BUS
25 help 26 help
26 Driver for the DPAA2 DPIO object. A DPIO provides queue and 27 Driver for the DPAA2 DPIO object. A DPIO provides queue and
27 buffer management facilities for software to interact with 28 buffer management facilities for software to interact with
diff --git a/drivers/soc/fsl/dpio/dpio-cmd.h b/drivers/soc/fsl/dpio/dpio-cmd.h
index 5814d2f395a4..e13fd3ac1939 100644
--- a/drivers/soc/fsl/dpio/dpio-cmd.h
+++ b/drivers/soc/fsl/dpio/dpio-cmd.h
@@ -26,6 +26,7 @@
26#define DPIO_CMDID_DISABLE DPIO_CMD(0x003) 26#define DPIO_CMDID_DISABLE DPIO_CMD(0x003)
27#define DPIO_CMDID_GET_ATTR DPIO_CMD(0x004) 27#define DPIO_CMDID_GET_ATTR DPIO_CMD(0x004)
28#define DPIO_CMDID_RESET DPIO_CMD(0x005) 28#define DPIO_CMDID_RESET DPIO_CMD(0x005)
29#define DPIO_CMDID_SET_STASHING_DEST DPIO_CMD(0x120)
29 30
30struct dpio_cmd_open { 31struct dpio_cmd_open {
31 __le32 dpio_id; 32 __le32 dpio_id;
@@ -47,4 +48,8 @@ struct dpio_rsp_get_attr {
47 __le32 qbman_version; 48 __le32 qbman_version;
48}; 49};
49 50
51struct dpio_stashing_dest {
52 u8 sdest;
53};
54
50#endif /* _FSL_DPIO_CMD_H */ 55#endif /* _FSL_DPIO_CMD_H */
diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c
index 2d4af32a0dec..c0cdc8946031 100644
--- a/drivers/soc/fsl/dpio/dpio-driver.c
+++ b/drivers/soc/fsl/dpio/dpio-driver.c
@@ -14,6 +14,7 @@
14#include <linux/dma-mapping.h> 14#include <linux/dma-mapping.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/sys_soc.h>
17 18
18#include <linux/fsl/mc.h> 19#include <linux/fsl/mc.h>
19#include <soc/fsl/dpaa2-io.h> 20#include <soc/fsl/dpaa2-io.h>
@@ -32,6 +33,46 @@ struct dpio_priv {
32 33
33static cpumask_var_t cpus_unused_mask; 34static cpumask_var_t cpus_unused_mask;
34 35
36static const struct soc_device_attribute ls1088a_soc[] = {
37 {.family = "QorIQ LS1088A"},
38 { /* sentinel */ }
39};
40
41static const struct soc_device_attribute ls2080a_soc[] = {
42 {.family = "QorIQ LS2080A"},
43 { /* sentinel */ }
44};
45
46static const struct soc_device_attribute ls2088a_soc[] = {
47 {.family = "QorIQ LS2088A"},
48 { /* sentinel */ }
49};
50
51static const struct soc_device_attribute lx2160a_soc[] = {
52 {.family = "QorIQ LX2160A"},
53 { /* sentinel */ }
54};
55
56static int dpaa2_dpio_get_cluster_sdest(struct fsl_mc_device *dpio_dev, int cpu)
57{
58 int cluster_base, cluster_size;
59
60 if (soc_device_match(ls1088a_soc)) {
61 cluster_base = 2;
62 cluster_size = 4;
63 } else if (soc_device_match(ls2080a_soc) ||
64 soc_device_match(ls2088a_soc) ||
65 soc_device_match(lx2160a_soc)) {
66 cluster_base = 0;
67 cluster_size = 2;
68 } else {
69 dev_err(&dpio_dev->dev, "unknown SoC version\n");
70 return -1;
71 }
72
73 return cluster_base + cpu / cluster_size;
74}
75
35static irqreturn_t dpio_irq_handler(int irq_num, void *arg) 76static irqreturn_t dpio_irq_handler(int irq_num, void *arg)
36{ 77{
37 struct device *dev = (struct device *)arg; 78 struct device *dev = (struct device *)arg;
@@ -89,6 +130,7 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
89 int err = -ENOMEM; 130 int err = -ENOMEM;
90 struct device *dev = &dpio_dev->dev; 131 struct device *dev = &dpio_dev->dev;
91 int possible_next_cpu; 132 int possible_next_cpu;
133 int sdest;
92 134
93 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 135 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
94 if (!priv) 136 if (!priv)
@@ -145,6 +187,16 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
145 desc.cpu = possible_next_cpu; 187 desc.cpu = possible_next_cpu;
146 cpumask_clear_cpu(possible_next_cpu, cpus_unused_mask); 188 cpumask_clear_cpu(possible_next_cpu, cpus_unused_mask);
147 189
190 sdest = dpaa2_dpio_get_cluster_sdest(dpio_dev, desc.cpu);
191 if (sdest >= 0) {
192 err = dpio_set_stashing_destination(dpio_dev->mc_io, 0,
193 dpio_dev->mc_handle,
194 sdest);
195 if (err)
196 dev_err(dev, "dpio_set_stashing_destination failed for cpu%d\n",
197 desc.cpu);
198 }
199
148 /* 200 /*
149 * Set the CENA regs to be the cache inhibited area of the portal to 201 * Set the CENA regs to be the cache inhibited area of the portal to
150 * avoid coherency issues if a user migrates to another core. 202 * avoid coherency issues if a user migrates to another core.
@@ -220,12 +272,12 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
220 272
221 dev = &dpio_dev->dev; 273 dev = &dpio_dev->dev;
222 priv = dev_get_drvdata(dev); 274 priv = dev_get_drvdata(dev);
275 cpu = dpaa2_io_get_cpu(priv->io);
223 276
224 dpaa2_io_down(priv->io); 277 dpaa2_io_down(priv->io);
225 278
226 dpio_teardown_irqs(dpio_dev); 279 dpio_teardown_irqs(dpio_dev);
227 280
228 cpu = dpaa2_io_get_cpu(priv->io);
229 cpumask_set_cpu(cpu, cpus_unused_mask); 281 cpumask_set_cpu(cpu, cpus_unused_mask);
230 282
231 err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, 283 err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id,
diff --git a/drivers/soc/fsl/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c
index bc801934602a..b9539ef2c3cd 100644
--- a/drivers/soc/fsl/dpio/dpio-service.c
+++ b/drivers/soc/fsl/dpio/dpio-service.c
@@ -473,7 +473,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd);
473 * Return 0 for success, and negative error code for failure. 473 * Return 0 for success, and negative error code for failure.
474 */ 474 */
475int dpaa2_io_service_release(struct dpaa2_io *d, 475int dpaa2_io_service_release(struct dpaa2_io *d,
476 u32 bpid, 476 u16 bpid,
477 const u64 *buffers, 477 const u64 *buffers,
478 unsigned int num_buffers) 478 unsigned int num_buffers)
479{ 479{
@@ -502,7 +502,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_release);
502 * Eg. if the buffer pool is empty, this will return zero. 502 * Eg. if the buffer pool is empty, this will return zero.
503 */ 503 */
504int dpaa2_io_service_acquire(struct dpaa2_io *d, 504int dpaa2_io_service_acquire(struct dpaa2_io *d,
505 u32 bpid, 505 u16 bpid,
506 u64 *buffers, 506 u64 *buffers,
507 unsigned int num_buffers) 507 unsigned int num_buffers)
508{ 508{
@@ -630,6 +630,7 @@ struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last)
630 if (!(dpaa2_dq_flags(ret) & DPAA2_DQ_STAT_VALIDFRAME)) 630 if (!(dpaa2_dq_flags(ret) & DPAA2_DQ_STAT_VALIDFRAME))
631 ret = NULL; 631 ret = NULL;
632 } else { 632 } else {
633 prefetch(&s->vaddr[s->idx]);
633 *is_last = 0; 634 *is_last = 0;
634 } 635 }
635 636
diff --git a/drivers/soc/fsl/dpio/dpio.c b/drivers/soc/fsl/dpio/dpio.c
index 521bc6946317..af74c597a675 100644
--- a/drivers/soc/fsl/dpio/dpio.c
+++ b/drivers/soc/fsl/dpio/dpio.c
@@ -166,6 +166,22 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io,
166 return 0; 166 return 0;
167} 167}
168 168
169int dpio_set_stashing_destination(struct fsl_mc_io *mc_io,
170 u32 cmd_flags,
171 u16 token,
172 u8 sdest)
173{
174 struct fsl_mc_command cmd = { 0 };
175 struct dpio_stashing_dest *dpio_cmd;
176
177 cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_STASHING_DEST,
178 cmd_flags, token);
179 dpio_cmd = (struct dpio_stashing_dest *)cmd.params;
180 dpio_cmd->sdest = sdest;
181
182 return mc_send_command(mc_io, &cmd);
183}
184
169/** 185/**
170 * dpio_get_api_version - Get Data Path I/O API version 186 * dpio_get_api_version - Get Data Path I/O API version
171 * @mc_io: Pointer to MC portal's DPIO object 187 * @mc_io: Pointer to MC portal's DPIO object
diff --git a/drivers/soc/fsl/dpio/dpio.h b/drivers/soc/fsl/dpio/dpio.h
index b2ac4ba4fb8e..da06f7258098 100644
--- a/drivers/soc/fsl/dpio/dpio.h
+++ b/drivers/soc/fsl/dpio/dpio.h
@@ -75,6 +75,11 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io,
75 u16 token, 75 u16 token,
76 struct dpio_attr *attr); 76 struct dpio_attr *attr);
77 77
78int dpio_set_stashing_destination(struct fsl_mc_io *mc_io,
79 u32 cmd_flags,
80 u16 token,
81 u8 dest);
82
78int dpio_get_api_version(struct fsl_mc_io *mc_io, 83int dpio_get_api_version(struct fsl_mc_io *mc_io,
79 u32 cmd_flags, 84 u32 cmd_flags,
80 u16 *major_ver, 85 u16 *major_ver,
diff --git a/drivers/soc/fsl/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c
index 0bddb85c0ae5..d02013556a1b 100644
--- a/drivers/soc/fsl/dpio/qbman-portal.c
+++ b/drivers/soc/fsl/dpio/qbman-portal.c
@@ -169,9 +169,9 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
169 3, /* RPM: Valid bit mode, RCR in array mode */ 169 3, /* RPM: Valid bit mode, RCR in array mode */
170 2, /* DCM: Discrete consumption ack mode */ 170 2, /* DCM: Discrete consumption ack mode */
171 3, /* EPM: Valid bit mode, EQCR in array mode */ 171 3, /* EPM: Valid bit mode, EQCR in array mode */
172 0, /* mem stashing drop enable == FALSE */ 172 1, /* mem stashing drop enable == TRUE */
173 1, /* mem stashing priority == TRUE */ 173 1, /* mem stashing priority == TRUE */
174 0, /* mem stashing enable == FALSE */ 174 1, /* mem stashing enable == TRUE */
175 1, /* dequeue stashing priority == TRUE */ 175 1, /* dequeue stashing priority == TRUE */
176 0, /* dequeue stashing enable == FALSE */ 176 0, /* dequeue stashing enable == FALSE */
177 0); /* EQCR_CI stashing priority == FALSE */ 177 0); /* EQCR_CI stashing priority == FALSE */
@@ -180,6 +180,7 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
180 reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG); 180 reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG);
181 if (!reg) { 181 if (!reg) {
182 pr_err("qbman: the portal is not enabled!\n"); 182 pr_err("qbman: the portal is not enabled!\n");
183 kfree(p);
183 return NULL; 184 return NULL;
184 } 185 }
185 186
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
index 302e0c8d69d9..63f6df86f9e5 100644
--- a/drivers/soc/fsl/guts.c
+++ b/drivers/soc/fsl/guts.c
@@ -32,6 +32,7 @@ struct fsl_soc_die_attr {
32static struct guts *guts; 32static struct guts *guts;
33static struct soc_device_attribute soc_dev_attr; 33static struct soc_device_attribute soc_dev_attr;
34static struct soc_device *soc_dev; 34static struct soc_device *soc_dev;
35static struct device_node *root;
35 36
36 37
37/* SoC die attribute definition for QorIQ platform */ 38/* SoC die attribute definition for QorIQ platform */
@@ -114,7 +115,7 @@ static const struct fsl_soc_die_attr *fsl_soc_die_match(
114 return NULL; 115 return NULL;
115} 116}
116 117
117u32 fsl_guts_get_svr(void) 118static u32 fsl_guts_get_svr(void)
118{ 119{
119 u32 svr = 0; 120 u32 svr = 0;
120 121
@@ -128,11 +129,10 @@ u32 fsl_guts_get_svr(void)
128 129
129 return svr; 130 return svr;
130} 131}
131EXPORT_SYMBOL(fsl_guts_get_svr);
132 132
133static int fsl_guts_probe(struct platform_device *pdev) 133static int fsl_guts_probe(struct platform_device *pdev)
134{ 134{
135 struct device_node *root, *np = pdev->dev.of_node; 135 struct device_node *np = pdev->dev.of_node;
136 struct device *dev = &pdev->dev; 136 struct device *dev = &pdev->dev;
137 struct resource *res; 137 struct resource *res;
138 const struct fsl_soc_die_attr *soc_die; 138 const struct fsl_soc_die_attr *soc_die;
@@ -155,9 +155,8 @@ static int fsl_guts_probe(struct platform_device *pdev)
155 root = of_find_node_by_path("/"); 155 root = of_find_node_by_path("/");
156 if (of_property_read_string(root, "model", &machine)) 156 if (of_property_read_string(root, "model", &machine))
157 of_property_read_string_index(root, "compatible", 0, &machine); 157 of_property_read_string_index(root, "compatible", 0, &machine);
158 of_node_put(root);
159 if (machine) 158 if (machine)
160 soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL); 159 soc_dev_attr.machine = machine;
161 160
162 svr = fsl_guts_get_svr(); 161 svr = fsl_guts_get_svr();
163 soc_die = fsl_soc_die_match(svr, fsl_soc_die); 162 soc_die = fsl_soc_die_match(svr, fsl_soc_die);
@@ -192,6 +191,7 @@ static int fsl_guts_probe(struct platform_device *pdev)
192static int fsl_guts_remove(struct platform_device *dev) 191static int fsl_guts_remove(struct platform_device *dev)
193{ 192{
194 soc_device_unregister(soc_dev); 193 soc_device_unregister(soc_dev);
194 of_node_put(root);
195 return 0; 195 return 0;
196} 196}
197 197
diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
index 2112d18dbb7b..d80f899d22f9 100644
--- a/drivers/soc/imx/Kconfig
+++ b/drivers/soc/imx/Kconfig
@@ -2,7 +2,7 @@ menu "i.MX SoC drivers"
2 2
3config IMX_GPCV2_PM_DOMAINS 3config IMX_GPCV2_PM_DOMAINS
4 bool "i.MX GPCv2 PM domains" 4 bool "i.MX GPCv2 PM domains"
5 depends on SOC_IMX7D || SOC_IMX8MQ || (COMPILE_TEST && OF) 5 depends on ARCH_MXC || (COMPILE_TEST && OF)
6 depends on PM 6 depends on PM
7 select PM_GENERIC_DOMAINS 7 select PM_GENERIC_DOMAINS
8 default y if SOC_IMX7D 8 default y if SOC_IMX7D
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index 8b4f48a2ca57..176f473127b6 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -8,6 +8,7 @@
8 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> 8 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
9 */ 9 */
10 10
11#include <linux/clk.h>
11#include <linux/of_device.h> 12#include <linux/of_device.h>
12#include <linux/platform_device.h> 13#include <linux/platform_device.h>
13#include <linux/pm_domain.h> 14#include <linux/pm_domain.h>
@@ -65,6 +66,12 @@
65 66
66#define GPC_M4_PU_PDN_FLG 0x1bc 67#define GPC_M4_PU_PDN_FLG 0x1bc
67 68
69#define GPC_PU_PWRHSK 0x1fc
70
71#define IMX8M_GPU_HSK_PWRDNREQN BIT(6)
72#define IMX8M_VPU_HSK_PWRDNREQN BIT(5)
73#define IMX8M_DISP_HSK_PWRDNREQN BIT(4)
74
68/* 75/*
69 * The PGC offset values in Reference Manual 76 * The PGC offset values in Reference Manual
70 * (Rev. 1, 01/2018 and the older ones) GPC chapter's 77 * (Rev. 1, 01/2018 and the older ones) GPC chapter's
@@ -92,16 +99,21 @@
92 99
93#define GPC_PGC_CTRL_PCR BIT(0) 100#define GPC_PGC_CTRL_PCR BIT(0)
94 101
102#define GPC_CLK_MAX 6
103
95struct imx_pgc_domain { 104struct imx_pgc_domain {
96 struct generic_pm_domain genpd; 105 struct generic_pm_domain genpd;
97 struct regmap *regmap; 106 struct regmap *regmap;
98 struct regulator *regulator; 107 struct regulator *regulator;
108 struct clk *clk[GPC_CLK_MAX];
109 int num_clks;
99 110
100 unsigned int pgc; 111 unsigned int pgc;
101 112
102 const struct { 113 const struct {
103 u32 pxx; 114 u32 pxx;
104 u32 map; 115 u32 map;
116 u32 hsk;
105 } bits; 117 } bits;
106 118
107 const int voltage; 119 const int voltage;
@@ -125,7 +137,7 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
125 const bool enable_power_control = !on; 137 const bool enable_power_control = !on;
126 const bool has_regulator = !IS_ERR(domain->regulator); 138 const bool has_regulator = !IS_ERR(domain->regulator);
127 unsigned long deadline; 139 unsigned long deadline;
128 int ret = 0; 140 int i, ret = 0;
129 141
130 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING, 142 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
131 domain->bits.map, domain->bits.map); 143 domain->bits.map, domain->bits.map);
@@ -138,10 +150,18 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
138 } 150 }
139 } 151 }
140 152
153 /* Enable reset clocks for all devices in the domain */
154 for (i = 0; i < domain->num_clks; i++)
155 clk_prepare_enable(domain->clk[i]);
156
141 if (enable_power_control) 157 if (enable_power_control)
142 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc), 158 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
143 GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR); 159 GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
144 160
161 if (domain->bits.hsk)
162 regmap_update_bits(domain->regmap, GPC_PU_PWRHSK,
163 domain->bits.hsk, on ? domain->bits.hsk : 0);
164
145 regmap_update_bits(domain->regmap, offset, 165 regmap_update_bits(domain->regmap, offset,
146 domain->bits.pxx, domain->bits.pxx); 166 domain->bits.pxx, domain->bits.pxx);
147 167
@@ -179,6 +199,10 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
179 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc), 199 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
180 GPC_PGC_CTRL_PCR, 0); 200 GPC_PGC_CTRL_PCR, 0);
181 201
202 /* Disable reset clocks for all devices in the domain */
203 for (i = 0; i < domain->num_clks; i++)
204 clk_disable_unprepare(domain->clk[i]);
205
182 if (has_regulator && !on) { 206 if (has_regulator && !on) {
183 int err; 207 int err;
184 208
@@ -328,6 +352,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
328 .bits = { 352 .bits = {
329 .pxx = IMX8M_GPU_SW_Pxx_REQ, 353 .pxx = IMX8M_GPU_SW_Pxx_REQ,
330 .map = IMX8M_GPU_A53_DOMAIN, 354 .map = IMX8M_GPU_A53_DOMAIN,
355 .hsk = IMX8M_GPU_HSK_PWRDNREQN,
331 }, 356 },
332 .pgc = IMX8M_PGC_GPU, 357 .pgc = IMX8M_PGC_GPU,
333 }, 358 },
@@ -339,6 +364,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
339 .bits = { 364 .bits = {
340 .pxx = IMX8M_VPU_SW_Pxx_REQ, 365 .pxx = IMX8M_VPU_SW_Pxx_REQ,
341 .map = IMX8M_VPU_A53_DOMAIN, 366 .map = IMX8M_VPU_A53_DOMAIN,
367 .hsk = IMX8M_VPU_HSK_PWRDNREQN,
342 }, 368 },
343 .pgc = IMX8M_PGC_VPU, 369 .pgc = IMX8M_PGC_VPU,
344 }, 370 },
@@ -350,6 +376,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
350 .bits = { 376 .bits = {
351 .pxx = IMX8M_DISP_SW_Pxx_REQ, 377 .pxx = IMX8M_DISP_SW_Pxx_REQ,
352 .map = IMX8M_DISP_A53_DOMAIN, 378 .map = IMX8M_DISP_A53_DOMAIN,
379 .hsk = IMX8M_DISP_HSK_PWRDNREQN,
353 }, 380 },
354 .pgc = IMX8M_PGC_DISP, 381 .pgc = IMX8M_PGC_DISP,
355 }, 382 },
@@ -390,7 +417,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
390 417
391static const struct regmap_range imx8m_yes_ranges[] = { 418static const struct regmap_range imx8m_yes_ranges[] = {
392 regmap_reg_range(GPC_LPCR_A_CORE_BSC, 419 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
393 GPC_M4_PU_PDN_FLG), 420 GPC_PU_PWRHSK),
394 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI), 421 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI),
395 GPC_PGC_SR(IMX8M_PGC_MIPI)), 422 GPC_PGC_SR(IMX8M_PGC_MIPI)),
396 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1), 423 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1),
@@ -426,6 +453,41 @@ static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
426 .reg_access_table = &imx8m_access_table, 453 .reg_access_table = &imx8m_access_table,
427}; 454};
428 455
456static int imx_pgc_get_clocks(struct imx_pgc_domain *domain)
457{
458 int i, ret;
459
460 for (i = 0; ; i++) {
461 struct clk *clk = of_clk_get(domain->dev->of_node, i);
462 if (IS_ERR(clk))
463 break;
464 if (i >= GPC_CLK_MAX) {
465 dev_err(domain->dev, "more than %d clocks\n",
466 GPC_CLK_MAX);
467 ret = -EINVAL;
468 goto clk_err;
469 }
470 domain->clk[i] = clk;
471 }
472 domain->num_clks = i;
473
474 return 0;
475
476clk_err:
477 while (i--)
478 clk_put(domain->clk[i]);
479
480 return ret;
481}
482
483static void imx_pgc_put_clocks(struct imx_pgc_domain *domain)
484{
485 int i;
486
487 for (i = domain->num_clks - 1; i >= 0; i--)
488 clk_put(domain->clk[i]);
489}
490
429static int imx_pgc_domain_probe(struct platform_device *pdev) 491static int imx_pgc_domain_probe(struct platform_device *pdev)
430{ 492{
431 struct imx_pgc_domain *domain = pdev->dev.platform_data; 493 struct imx_pgc_domain *domain = pdev->dev.platform_data;
@@ -445,9 +507,17 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
445 domain->voltage, domain->voltage); 507 domain->voltage, domain->voltage);
446 } 508 }
447 509
510 ret = imx_pgc_get_clocks(domain);
511 if (ret) {
512 if (ret != -EPROBE_DEFER)
513 dev_err(domain->dev, "Failed to get domain's clocks\n");
514 return ret;
515 }
516
448 ret = pm_genpd_init(&domain->genpd, NULL, true); 517 ret = pm_genpd_init(&domain->genpd, NULL, true);
449 if (ret) { 518 if (ret) {
450 dev_err(domain->dev, "Failed to init power domain\n"); 519 dev_err(domain->dev, "Failed to init power domain\n");
520 imx_pgc_put_clocks(domain);
451 return ret; 521 return ret;
452 } 522 }
453 523
@@ -456,6 +526,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
456 if (ret) { 526 if (ret) {
457 dev_err(domain->dev, "Failed to add genpd provider\n"); 527 dev_err(domain->dev, "Failed to add genpd provider\n");
458 pm_genpd_remove(&domain->genpd); 528 pm_genpd_remove(&domain->genpd);
529 imx_pgc_put_clocks(domain);
459 } 530 }
460 531
461 return ret; 532 return ret;
@@ -467,6 +538,7 @@ static int imx_pgc_domain_remove(struct platform_device *pdev)
467 538
468 of_genpd_del_provider(domain->dev->of_node); 539 of_genpd_del_provider(domain->dev->of_node);
469 pm_genpd_remove(&domain->genpd); 540 pm_genpd_remove(&domain->genpd);
541 imx_pgc_put_clocks(domain);
470 542
471 return 0; 543 return 0;
472} 544}
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index fcbf8a2e4080..1ee298f6bf17 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -98,6 +98,24 @@ config QCOM_RPMH
98 of hardware components aggregate requests for these resources and 98 of hardware components aggregate requests for these resources and
99 help apply the aggregated state on the resource. 99 help apply the aggregated state on the resource.
100 100
101config QCOM_RPMHPD
102 bool "Qualcomm RPMh Power domain driver"
103 depends on QCOM_RPMH && QCOM_COMMAND_DB
104 help
105 QCOM RPMh Power domain driver to support power-domains with
106 performance states. The driver communicates a performance state
107 value to RPMh which then translates it into corresponding voltage
108 for the voltage rail.
109
110config QCOM_RPMPD
111 bool "Qualcomm RPM Power domain driver"
112 depends on QCOM_SMD_RPM=y
113 help
114 QCOM RPM Power domain driver to support power-domains with
115 performance states. The driver communicates a performance state
116 value to RPM which then translates it into corresponding voltage
117 for the voltage rail.
118
101config QCOM_SMEM 119config QCOM_SMEM
102 tristate "Qualcomm Shared Memory Manager (SMEM)" 120 tristate "Qualcomm Shared Memory Manager (SMEM)"
103 depends on ARCH_QCOM || COMPILE_TEST 121 depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index f25b54cd6cf8..ffe519b0cb66 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -21,3 +21,5 @@ obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
21obj-$(CONFIG_QCOM_APR) += apr.o 21obj-$(CONFIG_QCOM_APR) += apr.o
22obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o 22obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
23obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o 23obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
24obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
25obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
index 2e1e4f0a5db8..86600d97c36d 100644
--- a/drivers/soc/qcom/llcc-sdm845.c
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -71,6 +71,11 @@ static struct llcc_slice_config sdm845_data[] = {
71 SCT_ENTRY(LLCC_AUDHW, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0), 71 SCT_ENTRY(LLCC_AUDHW, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0),
72}; 72};
73 73
74static int sdm845_qcom_llcc_remove(struct platform_device *pdev)
75{
76 return qcom_llcc_remove(pdev);
77}
78
74static int sdm845_qcom_llcc_probe(struct platform_device *pdev) 79static int sdm845_qcom_llcc_probe(struct platform_device *pdev)
75{ 80{
76 return qcom_llcc_probe(pdev, sdm845_data, ARRAY_SIZE(sdm845_data)); 81 return qcom_llcc_probe(pdev, sdm845_data, ARRAY_SIZE(sdm845_data));
@@ -87,6 +92,7 @@ static struct platform_driver sdm845_qcom_llcc_driver = {
87 .of_match_table = sdm845_qcom_llcc_of_match, 92 .of_match_table = sdm845_qcom_llcc_of_match,
88 }, 93 },
89 .probe = sdm845_qcom_llcc_probe, 94 .probe = sdm845_qcom_llcc_probe,
95 .remove = sdm845_qcom_llcc_remove,
90}; 96};
91module_platform_driver(sdm845_qcom_llcc_driver); 97module_platform_driver(sdm845_qcom_llcc_driver);
92 98
diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c
index 80667f7be52c..9090ea12eaf3 100644
--- a/drivers/soc/qcom/llcc-slice.c
+++ b/drivers/soc/qcom/llcc-slice.c
@@ -46,7 +46,7 @@
46 46
47#define BANK_OFFSET_STRIDE 0x80000 47#define BANK_OFFSET_STRIDE 0x80000
48 48
49static struct llcc_drv_data *drv_data; 49static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
50 50
51static const struct regmap_config llcc_regmap_config = { 51static const struct regmap_config llcc_regmap_config = {
52 .reg_bits = 32, 52 .reg_bits = 32,
@@ -68,6 +68,9 @@ struct llcc_slice_desc *llcc_slice_getd(u32 uid)
68 struct llcc_slice_desc *desc; 68 struct llcc_slice_desc *desc;
69 u32 sz, count; 69 u32 sz, count;
70 70
71 if (IS_ERR(drv_data))
72 return ERR_CAST(drv_data);
73
71 cfg = drv_data->cfg; 74 cfg = drv_data->cfg;
72 sz = drv_data->cfg_size; 75 sz = drv_data->cfg_size;
73 76
@@ -108,6 +111,9 @@ static int llcc_update_act_ctrl(u32 sid,
108 u32 slice_status; 111 u32 slice_status;
109 int ret; 112 int ret;
110 113
114 if (IS_ERR(drv_data))
115 return PTR_ERR(drv_data);
116
111 act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid); 117 act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid);
112 status_reg = LLCC_TRP_STATUSn(sid); 118 status_reg = LLCC_TRP_STATUSn(sid);
113 119
@@ -143,6 +149,9 @@ int llcc_slice_activate(struct llcc_slice_desc *desc)
143 int ret; 149 int ret;
144 u32 act_ctrl_val; 150 u32 act_ctrl_val;
145 151
152 if (IS_ERR(drv_data))
153 return PTR_ERR(drv_data);
154
146 if (IS_ERR_OR_NULL(desc)) 155 if (IS_ERR_OR_NULL(desc))
147 return -EINVAL; 156 return -EINVAL;
148 157
@@ -180,6 +189,9 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc)
180 u32 act_ctrl_val; 189 u32 act_ctrl_val;
181 int ret; 190 int ret;
182 191
192 if (IS_ERR(drv_data))
193 return PTR_ERR(drv_data);
194
183 if (IS_ERR_OR_NULL(desc)) 195 if (IS_ERR_OR_NULL(desc))
184 return -EINVAL; 196 return -EINVAL;
185 197
@@ -289,46 +301,62 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev)
289 return ret; 301 return ret;
290} 302}
291 303
304int qcom_llcc_remove(struct platform_device *pdev)
305{
306 /* Set the global pointer to a error code to avoid referencing it */
307 drv_data = ERR_PTR(-ENODEV);
308 return 0;
309}
310EXPORT_SYMBOL_GPL(qcom_llcc_remove);
311
312static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
313 const char *name)
314{
315 struct resource *res;
316 void __iomem *base;
317
318 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
319 if (!res)
320 return ERR_PTR(-ENODEV);
321
322 base = devm_ioremap_resource(&pdev->dev, res);
323 if (IS_ERR(base))
324 return ERR_CAST(base);
325
326 return devm_regmap_init_mmio(&pdev->dev, base, &llcc_regmap_config);
327}
328
292int qcom_llcc_probe(struct platform_device *pdev, 329int qcom_llcc_probe(struct platform_device *pdev,
293 const struct llcc_slice_config *llcc_cfg, u32 sz) 330 const struct llcc_slice_config *llcc_cfg, u32 sz)
294{ 331{
295 u32 num_banks; 332 u32 num_banks;
296 struct device *dev = &pdev->dev; 333 struct device *dev = &pdev->dev;
297 struct resource *llcc_banks_res, *llcc_bcast_res;
298 void __iomem *llcc_banks_base, *llcc_bcast_base;
299 int ret, i; 334 int ret, i;
300 struct platform_device *llcc_edac; 335 struct platform_device *llcc_edac;
301 336
302 drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); 337 drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
303 if (!drv_data) 338 if (!drv_data) {
304 return -ENOMEM; 339 ret = -ENOMEM;
305 340 goto err;
306 llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 341 }
307 "llcc_base"); 342
308 llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res); 343 drv_data->regmap = qcom_llcc_init_mmio(pdev, "llcc_base");
309 if (IS_ERR(llcc_banks_base)) 344 if (IS_ERR(drv_data->regmap)) {
310 return PTR_ERR(llcc_banks_base); 345 ret = PTR_ERR(drv_data->regmap);
311 346 goto err;
312 drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base, 347 }
313 &llcc_regmap_config); 348
314 if (IS_ERR(drv_data->regmap)) 349 drv_data->bcast_regmap =
315 return PTR_ERR(drv_data->regmap); 350 qcom_llcc_init_mmio(pdev, "llcc_broadcast_base");
316 351 if (IS_ERR(drv_data->bcast_regmap)) {
317 llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 352 ret = PTR_ERR(drv_data->bcast_regmap);
318 "llcc_broadcast_base"); 353 goto err;
319 llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res); 354 }
320 if (IS_ERR(llcc_bcast_base))
321 return PTR_ERR(llcc_bcast_base);
322
323 drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base,
324 &llcc_regmap_config);
325 if (IS_ERR(drv_data->bcast_regmap))
326 return PTR_ERR(drv_data->bcast_regmap);
327 355
328 ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, 356 ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0,
329 &num_banks); 357 &num_banks);
330 if (ret) 358 if (ret)
331 return ret; 359 goto err;
332 360
333 num_banks &= LLCC_LB_CNT_MASK; 361 num_banks &= LLCC_LB_CNT_MASK;
334 num_banks >>= LLCC_LB_CNT_SHIFT; 362 num_banks >>= LLCC_LB_CNT_SHIFT;
@@ -340,8 +368,10 @@ int qcom_llcc_probe(struct platform_device *pdev,
340 368
341 drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32), 369 drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32),
342 GFP_KERNEL); 370 GFP_KERNEL);
343 if (!drv_data->offsets) 371 if (!drv_data->offsets) {
344 return -ENOMEM; 372 ret = -ENOMEM;
373 goto err;
374 }
345 375
346 for (i = 0; i < num_banks; i++) 376 for (i = 0; i < num_banks; i++)
347 drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; 377 drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
@@ -349,8 +379,10 @@ int qcom_llcc_probe(struct platform_device *pdev,
349 drv_data->bitmap = devm_kcalloc(dev, 379 drv_data->bitmap = devm_kcalloc(dev,
350 BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), 380 BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long),
351 GFP_KERNEL); 381 GFP_KERNEL);
352 if (!drv_data->bitmap) 382 if (!drv_data->bitmap) {
353 return -ENOMEM; 383 ret = -ENOMEM;
384 goto err;
385 }
354 386
355 drv_data->cfg = llcc_cfg; 387 drv_data->cfg = llcc_cfg;
356 drv_data->cfg_size = sz; 388 drv_data->cfg_size = sz;
@@ -359,7 +391,7 @@ int qcom_llcc_probe(struct platform_device *pdev,
359 391
360 ret = qcom_llcc_cfg_program(pdev); 392 ret = qcom_llcc_cfg_program(pdev);
361 if (ret) 393 if (ret)
362 return ret; 394 goto err;
363 395
364 drv_data->ecc_irq = platform_get_irq(pdev, 0); 396 drv_data->ecc_irq = platform_get_irq(pdev, 0);
365 if (drv_data->ecc_irq >= 0) { 397 if (drv_data->ecc_irq >= 0) {
@@ -370,6 +402,9 @@ int qcom_llcc_probe(struct platform_device *pdev,
370 dev_err(dev, "Failed to register llcc edac driver\n"); 402 dev_err(dev, "Failed to register llcc edac driver\n");
371 } 403 }
372 404
405 return 0;
406err:
407 drv_data = ERR_PTR(-ENODEV);
373 return ret; 408 return ret;
374} 409}
375EXPORT_SYMBOL_GPL(qcom_llcc_probe); 410EXPORT_SYMBOL_GPL(qcom_llcc_probe);
diff --git a/drivers/soc/qcom/qcom_gsbi.c b/drivers/soc/qcom/qcom_gsbi.c
index 09c669e70d63..038abc377fdb 100644
--- a/drivers/soc/qcom/qcom_gsbi.c
+++ b/drivers/soc/qcom/qcom_gsbi.c
@@ -138,7 +138,7 @@ static int gsbi_probe(struct platform_device *pdev)
138 struct resource *res; 138 struct resource *res;
139 void __iomem *base; 139 void __iomem *base;
140 struct gsbi_info *gsbi; 140 struct gsbi_info *gsbi;
141 int i; 141 int i, ret;
142 u32 mask, gsbi_num; 142 u32 mask, gsbi_num;
143 const struct crci_config *config = NULL; 143 const struct crci_config *config = NULL;
144 144
@@ -221,7 +221,10 @@ static int gsbi_probe(struct platform_device *pdev)
221 221
222 platform_set_drvdata(pdev, gsbi); 222 platform_set_drvdata(pdev, gsbi);
223 223
224 return of_platform_populate(node, NULL, NULL, &pdev->dev); 224 ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
225 if (ret)
226 clk_disable_unprepare(gsbi->hclk);
227 return ret;
225} 228}
226 229
227static int gsbi_remove(struct platform_device *pdev) 230static int gsbi_remove(struct platform_device *pdev)
diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c
index 97bb5989aa21..7200d762a951 100644
--- a/drivers/soc/qcom/rmtfs_mem.c
+++ b/drivers/soc/qcom/rmtfs_mem.c
@@ -45,9 +45,9 @@ static ssize_t qcom_rmtfs_mem_show(struct device *dev,
45 struct device_attribute *attr, 45 struct device_attribute *attr,
46 char *buf); 46 char *buf);
47 47
48static DEVICE_ATTR(phys_addr, 0400, qcom_rmtfs_mem_show, NULL); 48static DEVICE_ATTR(phys_addr, 0444, qcom_rmtfs_mem_show, NULL);
49static DEVICE_ATTR(size, 0400, qcom_rmtfs_mem_show, NULL); 49static DEVICE_ATTR(size, 0444, qcom_rmtfs_mem_show, NULL);
50static DEVICE_ATTR(client_id, 0400, qcom_rmtfs_mem_show, NULL); 50static DEVICE_ATTR(client_id, 0444, qcom_rmtfs_mem_show, NULL);
51 51
52static ssize_t qcom_rmtfs_mem_show(struct device *dev, 52static ssize_t qcom_rmtfs_mem_show(struct device *dev,
53 struct device_attribute *attr, 53 struct device_attribute *attr,
@@ -132,6 +132,11 @@ static int qcom_rmtfs_mem_release(struct inode *inode, struct file *filp)
132 return 0; 132 return 0;
133} 133}
134 134
135static struct class rmtfs_class = {
136 .owner = THIS_MODULE,
137 .name = "rmtfs",
138};
139
135static const struct file_operations qcom_rmtfs_mem_fops = { 140static const struct file_operations qcom_rmtfs_mem_fops = {
136 .owner = THIS_MODULE, 141 .owner = THIS_MODULE,
137 .open = qcom_rmtfs_mem_open, 142 .open = qcom_rmtfs_mem_open,
@@ -199,6 +204,7 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
199 204
200 dev_set_name(&rmtfs_mem->dev, "qcom_rmtfs_mem%d", client_id); 205 dev_set_name(&rmtfs_mem->dev, "qcom_rmtfs_mem%d", client_id);
201 rmtfs_mem->dev.id = client_id; 206 rmtfs_mem->dev.id = client_id;
207 rmtfs_mem->dev.class = &rmtfs_class;
202 rmtfs_mem->dev.devt = MKDEV(MAJOR(qcom_rmtfs_mem_major), client_id); 208 rmtfs_mem->dev.devt = MKDEV(MAJOR(qcom_rmtfs_mem_major), client_id);
203 209
204 ret = cdev_device_add(&rmtfs_mem->cdev, &rmtfs_mem->dev); 210 ret = cdev_device_add(&rmtfs_mem->cdev, &rmtfs_mem->dev);
@@ -277,32 +283,42 @@ static struct platform_driver qcom_rmtfs_mem_driver = {
277 }, 283 },
278}; 284};
279 285
280static int qcom_rmtfs_mem_init(void) 286static int __init qcom_rmtfs_mem_init(void)
281{ 287{
282 int ret; 288 int ret;
283 289
290 ret = class_register(&rmtfs_class);
291 if (ret)
292 return ret;
293
284 ret = alloc_chrdev_region(&qcom_rmtfs_mem_major, 0, 294 ret = alloc_chrdev_region(&qcom_rmtfs_mem_major, 0,
285 QCOM_RMTFS_MEM_DEV_MAX, "qcom_rmtfs_mem"); 295 QCOM_RMTFS_MEM_DEV_MAX, "qcom_rmtfs_mem");
286 if (ret < 0) { 296 if (ret < 0) {
287 pr_err("qcom_rmtfs_mem: failed to allocate char dev region\n"); 297 pr_err("qcom_rmtfs_mem: failed to allocate char dev region\n");
288 return ret; 298 goto unregister_class;
289 } 299 }
290 300
291 ret = platform_driver_register(&qcom_rmtfs_mem_driver); 301 ret = platform_driver_register(&qcom_rmtfs_mem_driver);
292 if (ret < 0) { 302 if (ret < 0) {
293 pr_err("qcom_rmtfs_mem: failed to register rmtfs_mem driver\n"); 303 pr_err("qcom_rmtfs_mem: failed to register rmtfs_mem driver\n");
294 unregister_chrdev_region(qcom_rmtfs_mem_major, 304 goto unregister_chrdev;
295 QCOM_RMTFS_MEM_DEV_MAX);
296 } 305 }
297 306
307 return 0;
308
309unregister_chrdev:
310 unregister_chrdev_region(qcom_rmtfs_mem_major, QCOM_RMTFS_MEM_DEV_MAX);
311unregister_class:
312 class_unregister(&rmtfs_class);
298 return ret; 313 return ret;
299} 314}
300module_init(qcom_rmtfs_mem_init); 315module_init(qcom_rmtfs_mem_init);
301 316
302static void qcom_rmtfs_mem_exit(void) 317static void __exit qcom_rmtfs_mem_exit(void)
303{ 318{
304 platform_driver_unregister(&qcom_rmtfs_mem_driver); 319 platform_driver_unregister(&qcom_rmtfs_mem_driver);
305 unregister_chrdev_region(qcom_rmtfs_mem_major, QCOM_RMTFS_MEM_DEV_MAX); 320 unregister_chrdev_region(qcom_rmtfs_mem_major, QCOM_RMTFS_MEM_DEV_MAX);
321 class_unregister(&rmtfs_class);
306} 322}
307module_exit(qcom_rmtfs_mem_exit); 323module_exit(qcom_rmtfs_mem_exit);
308 324
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index c7beb6841289..035091fd44b8 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -80,6 +80,7 @@ void rpmh_tx_done(const struct tcs_request *msg, int r)
80 struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request, 80 struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
81 msg); 81 msg);
82 struct completion *compl = rpm_msg->completion; 82 struct completion *compl = rpm_msg->completion;
83 bool free = rpm_msg->needs_free;
83 84
84 rpm_msg->err = r; 85 rpm_msg->err = r;
85 86
@@ -94,7 +95,7 @@ void rpmh_tx_done(const struct tcs_request *msg, int r)
94 complete(compl); 95 complete(compl);
95 96
96exit: 97exit:
97 if (rpm_msg->needs_free) 98 if (free)
98 kfree(rpm_msg); 99 kfree(rpm_msg);
99} 100}
100 101
@@ -192,9 +193,8 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state,
192 WARN_ON(irqs_disabled()); 193 WARN_ON(irqs_disabled());
193 ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg); 194 ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg);
194 } else { 195 } else {
195 ret = rpmh_rsc_write_ctrl_data(ctrlr_to_drv(ctrlr),
196 &rpm_msg->msg);
197 /* Clean up our call by spoofing tx_done */ 196 /* Clean up our call by spoofing tx_done */
197 ret = 0;
198 rpmh_tx_done(&rpm_msg->msg, ret); 198 rpmh_tx_done(&rpm_msg->msg, ret);
199 } 199 }
200 200
@@ -348,11 +348,12 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
348{ 348{
349 struct batch_cache_req *req; 349 struct batch_cache_req *req;
350 struct rpmh_request *rpm_msgs; 350 struct rpmh_request *rpm_msgs;
351 DECLARE_COMPLETION_ONSTACK(compl); 351 struct completion *compls;
352 struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); 352 struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
353 unsigned long time_left; 353 unsigned long time_left;
354 int count = 0; 354 int count = 0;
355 int ret, i, j; 355 int ret, i;
356 void *ptr;
356 357
357 if (!cmd || !n) 358 if (!cmd || !n)
358 return -EINVAL; 359 return -EINVAL;
@@ -362,10 +363,15 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
362 if (!count) 363 if (!count)
363 return -EINVAL; 364 return -EINVAL;
364 365
365 req = kzalloc(sizeof(*req) + count * sizeof(req->rpm_msgs[0]), 366 ptr = kzalloc(sizeof(*req) +
367 count * (sizeof(req->rpm_msgs[0]) + sizeof(*compls)),
366 GFP_ATOMIC); 368 GFP_ATOMIC);
367 if (!req) 369 if (!ptr)
368 return -ENOMEM; 370 return -ENOMEM;
371
372 req = ptr;
373 compls = ptr + sizeof(*req) + count * sizeof(*rpm_msgs);
374
369 req->count = count; 375 req->count = count;
370 rpm_msgs = req->rpm_msgs; 376 rpm_msgs = req->rpm_msgs;
371 377
@@ -380,25 +386,26 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
380 } 386 }
381 387
382 for (i = 0; i < count; i++) { 388 for (i = 0; i < count; i++) {
383 rpm_msgs[i].completion = &compl; 389 struct completion *compl = &compls[i];
390
391 init_completion(compl);
392 rpm_msgs[i].completion = compl;
384 ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msgs[i].msg); 393 ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msgs[i].msg);
385 if (ret) { 394 if (ret) {
386 pr_err("Error(%d) sending RPMH message addr=%#x\n", 395 pr_err("Error(%d) sending RPMH message addr=%#x\n",
387 ret, rpm_msgs[i].msg.cmds[0].addr); 396 ret, rpm_msgs[i].msg.cmds[0].addr);
388 for (j = i; j < count; j++)
389 rpmh_tx_done(&rpm_msgs[j].msg, ret);
390 break; 397 break;
391 } 398 }
392 } 399 }
393 400
394 time_left = RPMH_TIMEOUT_MS; 401 time_left = RPMH_TIMEOUT_MS;
395 for (i = 0; i < count; i++) { 402 while (i--) {
396 time_left = wait_for_completion_timeout(&compl, time_left); 403 time_left = wait_for_completion_timeout(&compls[i], time_left);
397 if (!time_left) { 404 if (!time_left) {
398 /* 405 /*
399 * Better hope they never finish because they'll signal 406 * Better hope they never finish because they'll signal
400 * the completion on our stack and that's bad once 407 * the completion that we're going to free once
401 * we've returned from the function. 408 * we've returned from this function.
402 */ 409 */
403 WARN_ON(1); 410 WARN_ON(1);
404 ret = -ETIMEDOUT; 411 ret = -ETIMEDOUT;
@@ -407,7 +414,7 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
407 } 414 }
408 415
409exit: 416exit:
410 kfree(req); 417 kfree(ptr);
411 418
412 return ret; 419 return ret;
413} 420}
diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
new file mode 100644
index 000000000000..5741ec3fa814
--- /dev/null
+++ b/drivers/soc/qcom/rpmhpd.c
@@ -0,0 +1,406 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2018, The Linux Foundation. All rights reserved.*/
3
4#include <linux/err.h>
5#include <linux/init.h>
6#include <linux/kernel.h>
7#include <linux/mutex.h>
8#include <linux/pm_domain.h>
9#include <linux/slab.h>
10#include <linux/of.h>
11#include <linux/of_device.h>
12#include <linux/platform_device.h>
13#include <linux/pm_opp.h>
14#include <soc/qcom/cmd-db.h>
15#include <soc/qcom/rpmh.h>
16#include <dt-bindings/power/qcom-rpmpd.h>
17
18#define domain_to_rpmhpd(domain) container_of(domain, struct rpmhpd, pd)
19
20#define RPMH_ARC_MAX_LEVELS 16
21
22/**
23 * struct rpmhpd - top level RPMh power domain resource data structure
24 * @dev: rpmh power domain controller device
25 * @pd: generic_pm_domain corrresponding to the power domain
26 * @peer: A peer power domain in case Active only Voting is
27 * supported
28 * @active_only: True if it represents an Active only peer
29 * @level: An array of level (vlvl) to corner (hlvl) mappings
30 * derived from cmd-db
31 * @level_count: Number of levels supported by the power domain. max
32 * being 16 (0 - 15)
33 * @enabled: true if the power domain is enabled
34 * @res_name: Resource name used for cmd-db lookup
35 * @addr: Resource address as looped up using resource name from
36 * cmd-db
37 */
38struct rpmhpd {
39 struct device *dev;
40 struct generic_pm_domain pd;
41 struct generic_pm_domain *parent;
42 struct rpmhpd *peer;
43 const bool active_only;
44 unsigned int corner;
45 unsigned int active_corner;
46 u32 level[RPMH_ARC_MAX_LEVELS];
47 size_t level_count;
48 bool enabled;
49 const char *res_name;
50 u32 addr;
51};
52
53struct rpmhpd_desc {
54 struct rpmhpd **rpmhpds;
55 size_t num_pds;
56};
57
58static DEFINE_MUTEX(rpmhpd_lock);
59
60/* SDM845 RPMH powerdomains */
61
62static struct rpmhpd sdm845_ebi = {
63 .pd = { .name = "ebi", },
64 .res_name = "ebi.lvl",
65};
66
67static struct rpmhpd sdm845_lmx = {
68 .pd = { .name = "lmx", },
69 .res_name = "lmx.lvl",
70};
71
72static struct rpmhpd sdm845_lcx = {
73 .pd = { .name = "lcx", },
74 .res_name = "lcx.lvl",
75};
76
77static struct rpmhpd sdm845_gfx = {
78 .pd = { .name = "gfx", },
79 .res_name = "gfx.lvl",
80};
81
82static struct rpmhpd sdm845_mss = {
83 .pd = { .name = "mss", },
84 .res_name = "mss.lvl",
85};
86
87static struct rpmhpd sdm845_mx_ao;
88static struct rpmhpd sdm845_mx = {
89 .pd = { .name = "mx", },
90 .peer = &sdm845_mx_ao,
91 .res_name = "mx.lvl",
92};
93
94static struct rpmhpd sdm845_mx_ao = {
95 .pd = { .name = "mx_ao", },
96 .peer = &sdm845_mx,
97 .res_name = "mx.lvl",
98};
99
100static struct rpmhpd sdm845_cx_ao;
101static struct rpmhpd sdm845_cx = {
102 .pd = { .name = "cx", },
103 .peer = &sdm845_cx_ao,
104 .parent = &sdm845_mx.pd,
105 .res_name = "cx.lvl",
106};
107
108static struct rpmhpd sdm845_cx_ao = {
109 .pd = { .name = "cx_ao", },
110 .peer = &sdm845_cx,
111 .parent = &sdm845_mx_ao.pd,
112 .res_name = "cx.lvl",
113};
114
115static struct rpmhpd *sdm845_rpmhpds[] = {
116 [SDM845_EBI] = &sdm845_ebi,
117 [SDM845_MX] = &sdm845_mx,
118 [SDM845_MX_AO] = &sdm845_mx_ao,
119 [SDM845_CX] = &sdm845_cx,
120 [SDM845_CX_AO] = &sdm845_cx_ao,
121 [SDM845_LMX] = &sdm845_lmx,
122 [SDM845_LCX] = &sdm845_lcx,
123 [SDM845_GFX] = &sdm845_gfx,
124 [SDM845_MSS] = &sdm845_mss,
125};
126
127static const struct rpmhpd_desc sdm845_desc = {
128 .rpmhpds = sdm845_rpmhpds,
129 .num_pds = ARRAY_SIZE(sdm845_rpmhpds),
130};
131
132static const struct of_device_id rpmhpd_match_table[] = {
133 { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },
134 { }
135};
136
137static int rpmhpd_send_corner(struct rpmhpd *pd, int state,
138 unsigned int corner, bool sync)
139{
140 struct tcs_cmd cmd = {
141 .addr = pd->addr,
142 .data = corner,
143 };
144
145 /*
146 * Wait for an ack only when we are increasing the
147 * perf state of the power domain
148 */
149 if (sync)
150 return rpmh_write(pd->dev, state, &cmd, 1);
151 else
152 return rpmh_write_async(pd->dev, state, &cmd, 1);
153}
154
155static void to_active_sleep(struct rpmhpd *pd, unsigned int corner,
156 unsigned int *active, unsigned int *sleep)
157{
158 *active = corner;
159
160 if (pd->active_only)
161 *sleep = 0;
162 else
163 *sleep = *active;
164}
165
166/*
167 * This function is used to aggregate the votes across the active only
168 * resources and its peers. The aggregated votes are sent to RPMh as
169 * ACTIVE_ONLY votes (which take effect immediately), as WAKE_ONLY votes
170 * (applied by RPMh on system wakeup) and as SLEEP votes (applied by RPMh
171 * on system sleep).
172 * We send ACTIVE_ONLY votes for resources without any peers. For others,
173 * which have an active only peer, all 3 votes are sent.
174 */
175static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner)
176{
177 int ret;
178 struct rpmhpd *peer = pd->peer;
179 unsigned int active_corner, sleep_corner;
180 unsigned int this_active_corner = 0, this_sleep_corner = 0;
181 unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
182
183 to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner);
184
185 if (peer && peer->enabled)
186 to_active_sleep(peer, peer->corner, &peer_active_corner,
187 &peer_sleep_corner);
188
189 active_corner = max(this_active_corner, peer_active_corner);
190
191 ret = rpmhpd_send_corner(pd, RPMH_ACTIVE_ONLY_STATE, active_corner,
192 active_corner > pd->active_corner);
193 if (ret)
194 return ret;
195
196 pd->active_corner = active_corner;
197
198 if (peer) {
199 peer->active_corner = active_corner;
200
201 ret = rpmhpd_send_corner(pd, RPMH_WAKE_ONLY_STATE,
202 active_corner, false);
203 if (ret)
204 return ret;
205
206 sleep_corner = max(this_sleep_corner, peer_sleep_corner);
207
208 return rpmhpd_send_corner(pd, RPMH_SLEEP_STATE, sleep_corner,
209 false);
210 }
211
212 return ret;
213}
214
215static int rpmhpd_power_on(struct generic_pm_domain *domain)
216{
217 struct rpmhpd *pd = domain_to_rpmhpd(domain);
218 int ret = 0;
219
220 mutex_lock(&rpmhpd_lock);
221
222 if (pd->corner)
223 ret = rpmhpd_aggregate_corner(pd, pd->corner);
224
225 if (!ret)
226 pd->enabled = true;
227
228 mutex_unlock(&rpmhpd_lock);
229
230 return ret;
231}
232
233static int rpmhpd_power_off(struct generic_pm_domain *domain)
234{
235 struct rpmhpd *pd = domain_to_rpmhpd(domain);
236 int ret = 0;
237
238 mutex_lock(&rpmhpd_lock);
239
240 ret = rpmhpd_aggregate_corner(pd, pd->level[0]);
241
242 if (!ret)
243 pd->enabled = false;
244
245 mutex_unlock(&rpmhpd_lock);
246
247 return ret;
248}
249
250static int rpmhpd_set_performance_state(struct generic_pm_domain *domain,
251 unsigned int level)
252{
253 struct rpmhpd *pd = domain_to_rpmhpd(domain);
254 int ret = 0, i;
255
256 mutex_lock(&rpmhpd_lock);
257
258 for (i = 0; i < pd->level_count; i++)
259 if (level <= pd->level[i])
260 break;
261
262 /*
263 * If the level requested is more than that supported by the
264 * max corner, just set it to max anyway.
265 */
266 if (i == pd->level_count)
267 i--;
268
269 if (pd->enabled) {
270 ret = rpmhpd_aggregate_corner(pd, i);
271 if (ret)
272 goto out;
273 }
274
275 pd->corner = i;
276out:
277 mutex_unlock(&rpmhpd_lock);
278
279 return ret;
280}
281
282static unsigned int rpmhpd_get_performance_state(struct generic_pm_domain *genpd,
283 struct dev_pm_opp *opp)
284{
285 return dev_pm_opp_get_level(opp);
286}
287
288static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
289{
290 int i;
291 const u16 *buf;
292
293 buf = cmd_db_read_aux_data(rpmhpd->res_name, &rpmhpd->level_count);
294 if (IS_ERR(buf))
295 return PTR_ERR(buf);
296
297 /* 2 bytes used for each command DB aux data entry */
298 rpmhpd->level_count >>= 1;
299
300 if (rpmhpd->level_count > RPMH_ARC_MAX_LEVELS)
301 return -EINVAL;
302
303 for (i = 0; i < rpmhpd->level_count; i++) {
304 rpmhpd->level[i] = buf[i];
305
306 /*
307 * The AUX data may be zero padded. These 0 valued entries at
308 * the end of the map must be ignored.
309 */
310 if (i > 0 && rpmhpd->level[i] == 0) {
311 rpmhpd->level_count = i;
312 break;
313 }
314 pr_debug("%s: ARC hlvl=%2d --> vlvl=%4u\n", rpmhpd->res_name, i,
315 rpmhpd->level[i]);
316 }
317
318 return 0;
319}
320
321static int rpmhpd_probe(struct platform_device *pdev)
322{
323 int i, ret;
324 size_t num_pds;
325 struct device *dev = &pdev->dev;
326 struct genpd_onecell_data *data;
327 struct rpmhpd **rpmhpds;
328 const struct rpmhpd_desc *desc;
329
330 desc = of_device_get_match_data(dev);
331 if (!desc)
332 return -EINVAL;
333
334 rpmhpds = desc->rpmhpds;
335 num_pds = desc->num_pds;
336
337 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
338 if (!data)
339 return -ENOMEM;
340
341 data->domains = devm_kcalloc(dev, num_pds, sizeof(*data->domains),
342 GFP_KERNEL);
343 if (!data->domains)
344 return -ENOMEM;
345
346 data->num_domains = num_pds;
347
348 for (i = 0; i < num_pds; i++) {
349 if (!rpmhpds[i]) {
350 dev_warn(dev, "rpmhpds[%d] is empty\n", i);
351 continue;
352 }
353
354 rpmhpds[i]->dev = dev;
355 rpmhpds[i]->addr = cmd_db_read_addr(rpmhpds[i]->res_name);
356 if (!rpmhpds[i]->addr) {
357 dev_err(dev, "Could not find RPMh address for resource %s\n",
358 rpmhpds[i]->res_name);
359 return -ENODEV;
360 }
361
362 ret = cmd_db_read_slave_id(rpmhpds[i]->res_name);
363 if (ret != CMD_DB_HW_ARC) {
364 dev_err(dev, "RPMh slave ID mismatch\n");
365 return -EINVAL;
366 }
367
368 ret = rpmhpd_update_level_mapping(rpmhpds[i]);
369 if (ret)
370 return ret;
371
372 rpmhpds[i]->pd.power_off = rpmhpd_power_off;
373 rpmhpds[i]->pd.power_on = rpmhpd_power_on;
374 rpmhpds[i]->pd.set_performance_state = rpmhpd_set_performance_state;
375 rpmhpds[i]->pd.opp_to_performance_state = rpmhpd_get_performance_state;
376 pm_genpd_init(&rpmhpds[i]->pd, NULL, true);
377
378 data->domains[i] = &rpmhpds[i]->pd;
379 }
380
381 /* Add subdomains */
382 for (i = 0; i < num_pds; i++) {
383 if (!rpmhpds[i])
384 continue;
385 if (rpmhpds[i]->parent)
386 pm_genpd_add_subdomain(rpmhpds[i]->parent,
387 &rpmhpds[i]->pd);
388 }
389
390 return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
391}
392
393static struct platform_driver rpmhpd_driver = {
394 .driver = {
395 .name = "qcom-rpmhpd",
396 .of_match_table = rpmhpd_match_table,
397 .suppress_bind_attrs = true,
398 },
399 .probe = rpmhpd_probe,
400};
401
402static int __init rpmhpd_init(void)
403{
404 return platform_driver_register(&rpmhpd_driver);
405}
406core_initcall(rpmhpd_init);
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
new file mode 100644
index 000000000000..005326050c23
--- /dev/null
+++ b/drivers/soc/qcom/rpmpd.c
@@ -0,0 +1,315 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */
3
4#include <linux/err.h>
5#include <linux/init.h>
6#include <linux/kernel.h>
7#include <linux/mutex.h>
8#include <linux/pm_domain.h>
9#include <linux/of.h>
10#include <linux/of_device.h>
11#include <linux/platform_device.h>
12#include <linux/pm_opp.h>
13#include <linux/soc/qcom/smd-rpm.h>
14
15#include <dt-bindings/power/qcom-rpmpd.h>
16
17#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
18
19/* Resource types */
20#define RPMPD_SMPA 0x61706d73
21#define RPMPD_LDOA 0x616f646c
22
23/* Operation Keys */
24#define KEY_CORNER 0x6e726f63 /* corn */
25#define KEY_ENABLE 0x6e657773 /* swen */
26#define KEY_FLOOR_CORNER 0x636676 /* vfc */
27
28#define MAX_RPMPD_STATE 6
29
30#define DEFINE_RPMPD_CORNER_SMPA(_platform, _name, _active, r_id) \
31 static struct rpmpd _platform##_##_active; \
32 static struct rpmpd _platform##_##_name = { \
33 .pd = { .name = #_name, }, \
34 .peer = &_platform##_##_active, \
35 .res_type = RPMPD_SMPA, \
36 .res_id = r_id, \
37 .key = KEY_CORNER, \
38 }; \
39 static struct rpmpd _platform##_##_active = { \
40 .pd = { .name = #_active, }, \
41 .peer = &_platform##_##_name, \
42 .active_only = true, \
43 .res_type = RPMPD_SMPA, \
44 .res_id = r_id, \
45 .key = KEY_CORNER, \
46 }
47
48#define DEFINE_RPMPD_CORNER_LDOA(_platform, _name, r_id) \
49 static struct rpmpd _platform##_##_name = { \
50 .pd = { .name = #_name, }, \
51 .res_type = RPMPD_LDOA, \
52 .res_id = r_id, \
53 .key = KEY_CORNER, \
54 }
55
56#define DEFINE_RPMPD_VFC(_platform, _name, r_id, r_type) \
57 static struct rpmpd _platform##_##_name = { \
58 .pd = { .name = #_name, }, \
59 .res_type = r_type, \
60 .res_id = r_id, \
61 .key = KEY_FLOOR_CORNER, \
62 }
63
64#define DEFINE_RPMPD_VFC_SMPA(_platform, _name, r_id) \
65 DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_SMPA)
66
67#define DEFINE_RPMPD_VFC_LDOA(_platform, _name, r_id) \
68 DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_LDOA)
69
70struct rpmpd_req {
71 __le32 key;
72 __le32 nbytes;
73 __le32 value;
74};
75
76struct rpmpd {
77 struct generic_pm_domain pd;
78 struct rpmpd *peer;
79 const bool active_only;
80 unsigned int corner;
81 bool enabled;
82 const char *res_name;
83 const int res_type;
84 const int res_id;
85 struct qcom_smd_rpm *rpm;
86 __le32 key;
87};
88
89struct rpmpd_desc {
90 struct rpmpd **rpmpds;
91 size_t num_pds;
92};
93
94static DEFINE_MUTEX(rpmpd_lock);
95
96/* msm8996 RPM Power domains */
97DEFINE_RPMPD_CORNER_SMPA(msm8996, vddcx, vddcx_ao, 1);
98DEFINE_RPMPD_CORNER_SMPA(msm8996, vddmx, vddmx_ao, 2);
99DEFINE_RPMPD_CORNER_LDOA(msm8996, vddsscx, 26);
100
101DEFINE_RPMPD_VFC_SMPA(msm8996, vddcx_vfc, 1);
102DEFINE_RPMPD_VFC_LDOA(msm8996, vddsscx_vfc, 26);
103
104static struct rpmpd *msm8996_rpmpds[] = {
105 [MSM8996_VDDCX] = &msm8996_vddcx,
106 [MSM8996_VDDCX_AO] = &msm8996_vddcx_ao,
107 [MSM8996_VDDCX_VFC] = &msm8996_vddcx_vfc,
108 [MSM8996_VDDMX] = &msm8996_vddmx,
109 [MSM8996_VDDMX_AO] = &msm8996_vddmx_ao,
110 [MSM8996_VDDSSCX] = &msm8996_vddsscx,
111 [MSM8996_VDDSSCX_VFC] = &msm8996_vddsscx_vfc,
112};
113
114static const struct rpmpd_desc msm8996_desc = {
115 .rpmpds = msm8996_rpmpds,
116 .num_pds = ARRAY_SIZE(msm8996_rpmpds),
117};
118
119static const struct of_device_id rpmpd_match_table[] = {
120 { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
121 { }
122};
123
124static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
125{
126 struct rpmpd_req req = {
127 .key = KEY_ENABLE,
128 .nbytes = cpu_to_le32(sizeof(u32)),
129 .value = cpu_to_le32(enable),
130 };
131
132 return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
133 pd->res_type, pd->res_id, &req, sizeof(req));
134}
135
136static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
137{
138 struct rpmpd_req req = {
139 .key = pd->key,
140 .nbytes = cpu_to_le32(sizeof(u32)),
141 .value = cpu_to_le32(corner),
142 };
143
144 return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
145 &req, sizeof(req));
146};
147
148static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
149 unsigned int *active, unsigned int *sleep)
150{
151 *active = corner;
152
153 if (pd->active_only)
154 *sleep = 0;
155 else
156 *sleep = *active;
157}
158
159static int rpmpd_aggregate_corner(struct rpmpd *pd)
160{
161 int ret;
162 struct rpmpd *peer = pd->peer;
163 unsigned int active_corner, sleep_corner;
164 unsigned int this_active_corner = 0, this_sleep_corner = 0;
165 unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
166
167 to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
168
169 if (peer && peer->enabled)
170 to_active_sleep(peer, peer->corner, &peer_active_corner,
171 &peer_sleep_corner);
172
173 active_corner = max(this_active_corner, peer_active_corner);
174
175 ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner);
176 if (ret)
177 return ret;
178
179 sleep_corner = max(this_sleep_corner, peer_sleep_corner);
180
181 return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner);
182}
183
184static int rpmpd_power_on(struct generic_pm_domain *domain)
185{
186 int ret;
187 struct rpmpd *pd = domain_to_rpmpd(domain);
188
189 mutex_lock(&rpmpd_lock);
190
191 ret = rpmpd_send_enable(pd, true);
192 if (ret)
193 goto out;
194
195 pd->enabled = true;
196
197 if (pd->corner)
198 ret = rpmpd_aggregate_corner(pd);
199
200out:
201 mutex_unlock(&rpmpd_lock);
202
203 return ret;
204}
205
206static int rpmpd_power_off(struct generic_pm_domain *domain)
207{
208 int ret;
209 struct rpmpd *pd = domain_to_rpmpd(domain);
210
211 mutex_lock(&rpmpd_lock);
212
213 ret = rpmpd_send_enable(pd, false);
214 if (!ret)
215 pd->enabled = false;
216
217 mutex_unlock(&rpmpd_lock);
218
219 return ret;
220}
221
222static int rpmpd_set_performance(struct generic_pm_domain *domain,
223 unsigned int state)
224{
225 int ret = 0;
226 struct rpmpd *pd = domain_to_rpmpd(domain);
227
228 if (state > MAX_RPMPD_STATE)
229 goto out;
230
231 mutex_lock(&rpmpd_lock);
232
233 pd->corner = state;
234
235 if (!pd->enabled && pd->key != KEY_FLOOR_CORNER)
236 goto out;
237
238 ret = rpmpd_aggregate_corner(pd);
239
240out:
241 mutex_unlock(&rpmpd_lock);
242
243 return ret;
244}
245
246static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd,
247 struct dev_pm_opp *opp)
248{
249 return dev_pm_opp_get_level(opp);
250}
251
252static int rpmpd_probe(struct platform_device *pdev)
253{
254 int i;
255 size_t num;
256 struct genpd_onecell_data *data;
257 struct qcom_smd_rpm *rpm;
258 struct rpmpd **rpmpds;
259 const struct rpmpd_desc *desc;
260
261 rpm = dev_get_drvdata(pdev->dev.parent);
262 if (!rpm) {
263 dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
264 return -ENODEV;
265 }
266
267 desc = of_device_get_match_data(&pdev->dev);
268 if (!desc)
269 return -EINVAL;
270
271 rpmpds = desc->rpmpds;
272 num = desc->num_pds;
273
274 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
275 if (!data)
276 return -ENOMEM;
277
278 data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
279 GFP_KERNEL);
280 data->num_domains = num;
281
282 for (i = 0; i < num; i++) {
283 if (!rpmpds[i]) {
284 dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
285 i);
286 continue;
287 }
288
289 rpmpds[i]->rpm = rpm;
290 rpmpds[i]->pd.power_off = rpmpd_power_off;
291 rpmpds[i]->pd.power_on = rpmpd_power_on;
292 rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
293 rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance;
294 pm_genpd_init(&rpmpds[i]->pd, NULL, true);
295
296 data->domains[i] = &rpmpds[i]->pd;
297 }
298
299 return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
300}
301
302static struct platform_driver rpmpd_driver = {
303 .driver = {
304 .name = "qcom-rpmpd",
305 .of_match_table = rpmpd_match_table,
306 .suppress_bind_attrs = true,
307 },
308 .probe = rpmpd_probe,
309};
310
311static int __init rpmpd_init(void)
312{
313 return platform_driver_register(&rpmpd_driver);
314}
315core_initcall(rpmpd_init);
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index b8e63724a49d..9956bb2c63f2 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -227,6 +227,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
227 { .compatible = "qcom,rpm-msm8974" }, 227 { .compatible = "qcom,rpm-msm8974" },
228 { .compatible = "qcom,rpm-msm8996" }, 228 { .compatible = "qcom,rpm-msm8996" },
229 { .compatible = "qcom,rpm-msm8998" }, 229 { .compatible = "qcom,rpm-msm8998" },
230 { .compatible = "qcom,rpm-sdm660" },
230 { .compatible = "qcom,rpm-qcs404" }, 231 { .compatible = "qcom,rpm-qcs404" },
231 {} 232 {}
232}; 233};
diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index a33ee8ef8b6b..51625703399e 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -137,13 +137,17 @@ static int tegra_fuse_probe(struct platform_device *pdev)
137 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 137 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
138 fuse->phys = res->start; 138 fuse->phys = res->start;
139 fuse->base = devm_ioremap_resource(&pdev->dev, res); 139 fuse->base = devm_ioremap_resource(&pdev->dev, res);
140 if (IS_ERR(fuse->base)) 140 if (IS_ERR(fuse->base)) {
141 return PTR_ERR(fuse->base); 141 err = PTR_ERR(fuse->base);
142 fuse->base = base;
143 return err;
144 }
142 145
143 fuse->clk = devm_clk_get(&pdev->dev, "fuse"); 146 fuse->clk = devm_clk_get(&pdev->dev, "fuse");
144 if (IS_ERR(fuse->clk)) { 147 if (IS_ERR(fuse->clk)) {
145 dev_err(&pdev->dev, "failed to get FUSE clock: %ld", 148 dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
146 PTR_ERR(fuse->clk)); 149 PTR_ERR(fuse->clk));
150 fuse->base = base;
147 return PTR_ERR(fuse->clk); 151 return PTR_ERR(fuse->clk);
148 } 152 }
149 153
@@ -152,8 +156,10 @@ static int tegra_fuse_probe(struct platform_device *pdev)
152 156
153 if (fuse->soc->probe) { 157 if (fuse->soc->probe) {
154 err = fuse->soc->probe(fuse); 158 err = fuse->soc->probe(fuse);
155 if (err < 0) 159 if (err < 0) {
160 fuse->base = base;
156 return err; 161 return err;
162 }
157 } 163 }
158 164
159 if (tegra_fuse_create_sysfs(&pdev->dev, fuse->soc->info->size, 165 if (tegra_fuse_create_sysfs(&pdev->dev, fuse->soc->info->size,
diff --git a/drivers/soc/tegra/fuse/speedo-tegra210.c b/drivers/soc/tegra/fuse/speedo-tegra210.c
index 5373f4c16b54..8ed35d9851f8 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra210.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra210.c
@@ -131,7 +131,7 @@ void __init tegra210_init_speedo_data(struct tegra_sku_info *sku_info)
131 131
132 soc_speedo[0] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0); 132 soc_speedo[0] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0);
133 soc_speedo[1] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_1); 133 soc_speedo[1] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_1);
134 soc_speedo[2] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2); 134 soc_speedo[2] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_2);
135 135
136 cpu_iddq = tegra_fuse_read_early(FUSE_CPU_IDDQ) * 4; 136 cpu_iddq = tegra_fuse_read_early(FUSE_CPU_IDDQ) * 4;
137 soc_iddq = tegra_fuse_read_early(FUSE_SOC_IDDQ) * 4; 137 soc_iddq = tegra_fuse_read_early(FUSE_SOC_IDDQ) * 4;
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 7ea3280279ff..0df258518693 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -20,7 +20,7 @@
20 20
21#define pr_fmt(fmt) "tegra-pmc: " fmt 21#define pr_fmt(fmt) "tegra-pmc: " fmt
22 22
23#include <linux/kernel.h> 23#include <linux/arm-smccc.h>
24#include <linux/clk.h> 24#include <linux/clk.h>
25#include <linux/clk/tegra.h> 25#include <linux/clk/tegra.h>
26#include <linux/debugfs.h> 26#include <linux/debugfs.h>
@@ -30,16 +30,17 @@
30#include <linux/init.h> 30#include <linux/init.h>
31#include <linux/io.h> 31#include <linux/io.h>
32#include <linux/iopoll.h> 32#include <linux/iopoll.h>
33#include <linux/irq.h>
34#include <linux/irqdomain.h> 33#include <linux/irqdomain.h>
35#include <linux/of.h> 34#include <linux/irq.h>
35#include <linux/kernel.h>
36#include <linux/of_address.h> 36#include <linux/of_address.h>
37#include <linux/of_clk.h> 37#include <linux/of_clk.h>
38#include <linux/of.h>
38#include <linux/of_irq.h> 39#include <linux/of_irq.h>
39#include <linux/of_platform.h> 40#include <linux/of_platform.h>
40#include <linux/pinctrl/pinctrl.h>
41#include <linux/pinctrl/pinconf.h>
42#include <linux/pinctrl/pinconf-generic.h> 41#include <linux/pinctrl/pinconf-generic.h>
42#include <linux/pinctrl/pinconf.h>
43#include <linux/pinctrl/pinctrl.h>
43#include <linux/platform_device.h> 44#include <linux/platform_device.h>
44#include <linux/pm_domain.h> 45#include <linux/pm_domain.h>
45#include <linux/reboot.h> 46#include <linux/reboot.h>
@@ -145,6 +146,11 @@
145#define WAKE_AOWAKE_CTRL 0x4f4 146#define WAKE_AOWAKE_CTRL 0x4f4
146#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0) 147#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
147 148
149/* for secure PMC */
150#define TEGRA_SMC_PMC 0xc2fffe00
151#define TEGRA_SMC_PMC_READ 0xaa
152#define TEGRA_SMC_PMC_WRITE 0xbb
153
148struct tegra_powergate { 154struct tegra_powergate {
149 struct generic_pm_domain genpd; 155 struct generic_pm_domain genpd;
150 struct tegra_pmc *pmc; 156 struct tegra_pmc *pmc;
@@ -216,6 +222,7 @@ struct tegra_pmc_soc {
216 bool has_gpu_clamps; 222 bool has_gpu_clamps;
217 bool needs_mbist_war; 223 bool needs_mbist_war;
218 bool has_impl_33v_pwr; 224 bool has_impl_33v_pwr;
225 bool maybe_tz_only;
219 226
220 const struct tegra_io_pad_soc *io_pads; 227 const struct tegra_io_pad_soc *io_pads;
221 unsigned int num_io_pads; 228 unsigned int num_io_pads;
@@ -273,8 +280,12 @@ static const char * const tegra30_reset_sources[] = {
273 * struct tegra_pmc - NVIDIA Tegra PMC 280 * struct tegra_pmc - NVIDIA Tegra PMC
274 * @dev: pointer to PMC device structure 281 * @dev: pointer to PMC device structure
275 * @base: pointer to I/O remapped register region 282 * @base: pointer to I/O remapped register region
283 * @wake: pointer to I/O remapped region for WAKE registers
284 * @aotag: pointer to I/O remapped region for AOTAG registers
285 * @scratch: pointer to I/O remapped region for scratch registers
276 * @clk: pointer to pclk clock 286 * @clk: pointer to pclk clock
277 * @soc: pointer to SoC data structure 287 * @soc: pointer to SoC data structure
288 * @tz_only: flag specifying if the PMC can only be accessed via TrustZone
278 * @debugfs: pointer to debugfs entry 289 * @debugfs: pointer to debugfs entry
279 * @rate: currently configured rate of pclk 290 * @rate: currently configured rate of pclk
280 * @suspend_mode: lowest suspend mode available 291 * @suspend_mode: lowest suspend mode available
@@ -291,6 +302,9 @@ static const char * const tegra30_reset_sources[] = {
291 * @lp0_vec_size: size of the LP0 warm boot code 302 * @lp0_vec_size: size of the LP0 warm boot code
292 * @powergates_available: Bitmap of available power gates 303 * @powergates_available: Bitmap of available power gates
293 * @powergates_lock: mutex for power gate register access 304 * @powergates_lock: mutex for power gate register access
305 * @pctl_dev: pin controller exposed by the PMC
306 * @domain: IRQ domain provided by the PMC
307 * @irq: chip implementation for the IRQ domain
294 */ 308 */
295struct tegra_pmc { 309struct tegra_pmc {
296 struct device *dev; 310 struct device *dev;
@@ -302,6 +316,7 @@ struct tegra_pmc {
302 struct dentry *debugfs; 316 struct dentry *debugfs;
303 317
304 const struct tegra_pmc_soc *soc; 318 const struct tegra_pmc_soc *soc;
319 bool tz_only;
305 320
306 unsigned long rate; 321 unsigned long rate;
307 322
@@ -338,30 +353,85 @@ to_powergate(struct generic_pm_domain *domain)
338 return container_of(domain, struct tegra_powergate, genpd); 353 return container_of(domain, struct tegra_powergate, genpd);
339} 354}
340 355
341static u32 tegra_pmc_readl(unsigned long offset) 356static u32 tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset)
342{ 357{
358 struct arm_smccc_res res;
359
360 if (pmc->tz_only) {
361 arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_READ, offset, 0, 0,
362 0, 0, 0, &res);
363 if (res.a0) {
364 if (pmc->dev)
365 dev_warn(pmc->dev, "%s(): SMC failed: %lu\n",
366 __func__, res.a0);
367 else
368 pr_warn("%s(): SMC failed: %lu\n", __func__,
369 res.a0);
370 }
371
372 return res.a1;
373 }
374
343 return readl(pmc->base + offset); 375 return readl(pmc->base + offset);
344} 376}
345 377
346static void tegra_pmc_writel(u32 value, unsigned long offset) 378static void tegra_pmc_writel(struct tegra_pmc *pmc, u32 value,
379 unsigned long offset)
347{ 380{
348 writel(value, pmc->base + offset); 381 struct arm_smccc_res res;
382
383 if (pmc->tz_only) {
384 arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_WRITE, offset,
385 value, 0, 0, 0, 0, &res);
386 if (res.a0) {
387 if (pmc->dev)
388 dev_warn(pmc->dev, "%s(): SMC failed: %lu\n",
389 __func__, res.a0);
390 else
391 pr_warn("%s(): SMC failed: %lu\n", __func__,
392 res.a0);
393 }
394 } else {
395 writel(value, pmc->base + offset);
396 }
349} 397}
350 398
399static u32 tegra_pmc_scratch_readl(struct tegra_pmc *pmc, unsigned long offset)
400{
401 if (pmc->tz_only)
402 return tegra_pmc_readl(pmc, offset);
403
404 return readl(pmc->scratch + offset);
405}
406
407static void tegra_pmc_scratch_writel(struct tegra_pmc *pmc, u32 value,
408 unsigned long offset)
409{
410 if (pmc->tz_only)
411 tegra_pmc_writel(pmc, value, offset);
412 else
413 writel(value, pmc->scratch + offset);
414}
415
416/*
417 * TODO Figure out a way to call this with the struct tegra_pmc * passed in.
418 * This currently doesn't work because readx_poll_timeout() can only operate
419 * on functions that take a single argument.
420 */
351static inline bool tegra_powergate_state(int id) 421static inline bool tegra_powergate_state(int id)
352{ 422{
353 if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps) 423 if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
354 return (tegra_pmc_readl(GPU_RG_CNTRL) & 0x1) == 0; 424 return (tegra_pmc_readl(pmc, GPU_RG_CNTRL) & 0x1) == 0;
355 else 425 else
356 return (tegra_pmc_readl(PWRGATE_STATUS) & BIT(id)) != 0; 426 return (tegra_pmc_readl(pmc, PWRGATE_STATUS) & BIT(id)) != 0;
357} 427}
358 428
359static inline bool tegra_powergate_is_valid(int id) 429static inline bool tegra_powergate_is_valid(struct tegra_pmc *pmc, int id)
360{ 430{
361 return (pmc->soc && pmc->soc->powergates[id]); 431 return (pmc->soc && pmc->soc->powergates[id]);
362} 432}
363 433
364static inline bool tegra_powergate_is_available(int id) 434static inline bool tegra_powergate_is_available(struct tegra_pmc *pmc, int id)
365{ 435{
366 return test_bit(id, pmc->powergates_available); 436 return test_bit(id, pmc->powergates_available);
367} 437}
@@ -374,7 +444,7 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name)
374 return -EINVAL; 444 return -EINVAL;
375 445
376 for (i = 0; i < pmc->soc->num_powergates; i++) { 446 for (i = 0; i < pmc->soc->num_powergates; i++) {
377 if (!tegra_powergate_is_valid(i)) 447 if (!tegra_powergate_is_valid(pmc, i))
378 continue; 448 continue;
379 449
380 if (!strcmp(name, pmc->soc->powergates[i])) 450 if (!strcmp(name, pmc->soc->powergates[i]))
@@ -386,10 +456,12 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name)
386 456
387/** 457/**
388 * tegra_powergate_set() - set the state of a partition 458 * tegra_powergate_set() - set the state of a partition
459 * @pmc: power management controller
389 * @id: partition ID 460 * @id: partition ID
390 * @new_state: new state of the partition 461 * @new_state: new state of the partition
391 */ 462 */
392static int tegra_powergate_set(unsigned int id, bool new_state) 463static int tegra_powergate_set(struct tegra_pmc *pmc, unsigned int id,
464 bool new_state)
393{ 465{
394 bool status; 466 bool status;
395 int err; 467 int err;
@@ -404,7 +476,7 @@ static int tegra_powergate_set(unsigned int id, bool new_state)
404 return 0; 476 return 0;
405 } 477 }
406 478
407 tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); 479 tegra_pmc_writel(pmc, PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
408 480
409 err = readx_poll_timeout(tegra_powergate_state, id, status, 481 err = readx_poll_timeout(tegra_powergate_state, id, status,
410 status == new_state, 10, 100000); 482 status == new_state, 10, 100000);
@@ -414,7 +486,8 @@ static int tegra_powergate_set(unsigned int id, bool new_state)
414 return err; 486 return err;
415} 487}
416 488
417static int __tegra_powergate_remove_clamping(unsigned int id) 489static int __tegra_powergate_remove_clamping(struct tegra_pmc *pmc,
490 unsigned int id)
418{ 491{
419 u32 mask; 492 u32 mask;
420 493
@@ -426,7 +499,7 @@ static int __tegra_powergate_remove_clamping(unsigned int id)
426 */ 499 */
427 if (id == TEGRA_POWERGATE_3D) { 500 if (id == TEGRA_POWERGATE_3D) {
428 if (pmc->soc->has_gpu_clamps) { 501 if (pmc->soc->has_gpu_clamps) {
429 tegra_pmc_writel(0, GPU_RG_CNTRL); 502 tegra_pmc_writel(pmc, 0, GPU_RG_CNTRL);
430 goto out; 503 goto out;
431 } 504 }
432 } 505 }
@@ -442,7 +515,7 @@ static int __tegra_powergate_remove_clamping(unsigned int id)
442 else 515 else
443 mask = (1 << id); 516 mask = (1 << id);
444 517
445 tegra_pmc_writel(mask, REMOVE_CLAMPING); 518 tegra_pmc_writel(pmc, mask, REMOVE_CLAMPING);
446 519
447out: 520out:
448 mutex_unlock(&pmc->powergates_lock); 521 mutex_unlock(&pmc->powergates_lock);
@@ -494,7 +567,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg,
494 567
495 usleep_range(10, 20); 568 usleep_range(10, 20);
496 569
497 err = tegra_powergate_set(pg->id, true); 570 err = tegra_powergate_set(pg->pmc, pg->id, true);
498 if (err < 0) 571 if (err < 0)
499 return err; 572 return err;
500 573
@@ -506,7 +579,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg,
506 579
507 usleep_range(10, 20); 580 usleep_range(10, 20);
508 581
509 err = __tegra_powergate_remove_clamping(pg->id); 582 err = __tegra_powergate_remove_clamping(pg->pmc, pg->id);
510 if (err) 583 if (err)
511 goto disable_clks; 584 goto disable_clks;
512 585
@@ -533,7 +606,7 @@ disable_clks:
533 usleep_range(10, 20); 606 usleep_range(10, 20);
534 607
535powergate_off: 608powergate_off:
536 tegra_powergate_set(pg->id, false); 609 tegra_powergate_set(pg->pmc, pg->id, false);
537 610
538 return err; 611 return err;
539} 612}
@@ -558,7 +631,7 @@ static int tegra_powergate_power_down(struct tegra_powergate *pg)
558 631
559 usleep_range(10, 20); 632 usleep_range(10, 20);
560 633
561 err = tegra_powergate_set(pg->id, false); 634 err = tegra_powergate_set(pg->pmc, pg->id, false);
562 if (err) 635 if (err)
563 goto assert_resets; 636 goto assert_resets;
564 637
@@ -579,12 +652,13 @@ disable_clks:
579static int tegra_genpd_power_on(struct generic_pm_domain *domain) 652static int tegra_genpd_power_on(struct generic_pm_domain *domain)
580{ 653{
581 struct tegra_powergate *pg = to_powergate(domain); 654 struct tegra_powergate *pg = to_powergate(domain);
655 struct device *dev = pg->pmc->dev;
582 int err; 656 int err;
583 657
584 err = tegra_powergate_power_up(pg, true); 658 err = tegra_powergate_power_up(pg, true);
585 if (err) 659 if (err)
586 pr_err("failed to turn on PM domain %s: %d\n", pg->genpd.name, 660 dev_err(dev, "failed to turn on PM domain %s: %d\n",
587 err); 661 pg->genpd.name, err);
588 662
589 return err; 663 return err;
590} 664}
@@ -592,12 +666,13 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain)
592static int tegra_genpd_power_off(struct generic_pm_domain *domain) 666static int tegra_genpd_power_off(struct generic_pm_domain *domain)
593{ 667{
594 struct tegra_powergate *pg = to_powergate(domain); 668 struct tegra_powergate *pg = to_powergate(domain);
669 struct device *dev = pg->pmc->dev;
595 int err; 670 int err;
596 671
597 err = tegra_powergate_power_down(pg); 672 err = tegra_powergate_power_down(pg);
598 if (err) 673 if (err)
599 pr_err("failed to turn off PM domain %s: %d\n", 674 dev_err(dev, "failed to turn off PM domain %s: %d\n",
600 pg->genpd.name, err); 675 pg->genpd.name, err);
601 676
602 return err; 677 return err;
603} 678}
@@ -608,10 +683,10 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain)
608 */ 683 */
609int tegra_powergate_power_on(unsigned int id) 684int tegra_powergate_power_on(unsigned int id)
610{ 685{
611 if (!tegra_powergate_is_available(id)) 686 if (!tegra_powergate_is_available(pmc, id))
612 return -EINVAL; 687 return -EINVAL;
613 688
614 return tegra_powergate_set(id, true); 689 return tegra_powergate_set(pmc, id, true);
615} 690}
616 691
617/** 692/**
@@ -620,20 +695,21 @@ int tegra_powergate_power_on(unsigned int id)
620 */ 695 */
621int tegra_powergate_power_off(unsigned int id) 696int tegra_powergate_power_off(unsigned int id)
622{ 697{
623 if (!tegra_powergate_is_available(id)) 698 if (!tegra_powergate_is_available(pmc, id))
624 return -EINVAL; 699 return -EINVAL;
625 700
626 return tegra_powergate_set(id, false); 701 return tegra_powergate_set(pmc, id, false);
627} 702}
628EXPORT_SYMBOL(tegra_powergate_power_off); 703EXPORT_SYMBOL(tegra_powergate_power_off);
629 704
630/** 705/**
631 * tegra_powergate_is_powered() - check if partition is powered 706 * tegra_powergate_is_powered() - check if partition is powered
707 * @pmc: power management controller
632 * @id: partition ID 708 * @id: partition ID
633 */ 709 */
634int tegra_powergate_is_powered(unsigned int id) 710static int tegra_powergate_is_powered(struct tegra_pmc *pmc, unsigned int id)
635{ 711{
636 if (!tegra_powergate_is_valid(id)) 712 if (!tegra_powergate_is_valid(pmc, id))
637 return -EINVAL; 713 return -EINVAL;
638 714
639 return tegra_powergate_state(id); 715 return tegra_powergate_state(id);
@@ -645,10 +721,10 @@ int tegra_powergate_is_powered(unsigned int id)
645 */ 721 */
646int tegra_powergate_remove_clamping(unsigned int id) 722int tegra_powergate_remove_clamping(unsigned int id)
647{ 723{
648 if (!tegra_powergate_is_available(id)) 724 if (!tegra_powergate_is_available(pmc, id))
649 return -EINVAL; 725 return -EINVAL;
650 726
651 return __tegra_powergate_remove_clamping(id); 727 return __tegra_powergate_remove_clamping(pmc, id);
652} 728}
653EXPORT_SYMBOL(tegra_powergate_remove_clamping); 729EXPORT_SYMBOL(tegra_powergate_remove_clamping);
654 730
@@ -666,7 +742,7 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
666 struct tegra_powergate *pg; 742 struct tegra_powergate *pg;
667 int err; 743 int err;
668 744
669 if (!tegra_powergate_is_available(id)) 745 if (!tegra_powergate_is_available(pmc, id))
670 return -EINVAL; 746 return -EINVAL;
671 747
672 pg = kzalloc(sizeof(*pg), GFP_KERNEL); 748 pg = kzalloc(sizeof(*pg), GFP_KERNEL);
@@ -681,7 +757,8 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
681 757
682 err = tegra_powergate_power_up(pg, false); 758 err = tegra_powergate_power_up(pg, false);
683 if (err) 759 if (err)
684 pr_err("failed to turn on partition %d: %d\n", id, err); 760 dev_err(pmc->dev, "failed to turn on partition %d: %d\n", id,
761 err);
685 762
686 kfree(pg); 763 kfree(pg);
687 764
@@ -691,12 +768,14 @@ EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
691 768
692/** 769/**
693 * tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID 770 * tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
771 * @pmc: power management controller
694 * @cpuid: CPU partition ID 772 * @cpuid: CPU partition ID
695 * 773 *
696 * Returns the partition ID corresponding to the CPU partition ID or a 774 * Returns the partition ID corresponding to the CPU partition ID or a
697 * negative error code on failure. 775 * negative error code on failure.
698 */ 776 */
699static int tegra_get_cpu_powergate_id(unsigned int cpuid) 777static int tegra_get_cpu_powergate_id(struct tegra_pmc *pmc,
778 unsigned int cpuid)
700{ 779{
701 if (pmc->soc && cpuid < pmc->soc->num_cpu_powergates) 780 if (pmc->soc && cpuid < pmc->soc->num_cpu_powergates)
702 return pmc->soc->cpu_powergates[cpuid]; 781 return pmc->soc->cpu_powergates[cpuid];
@@ -712,11 +791,11 @@ bool tegra_pmc_cpu_is_powered(unsigned int cpuid)
712{ 791{
713 int id; 792 int id;
714 793
715 id = tegra_get_cpu_powergate_id(cpuid); 794 id = tegra_get_cpu_powergate_id(pmc, cpuid);
716 if (id < 0) 795 if (id < 0)
717 return false; 796 return false;
718 797
719 return tegra_powergate_is_powered(id); 798 return tegra_powergate_is_powered(pmc, id);
720} 799}
721 800
722/** 801/**
@@ -727,11 +806,11 @@ int tegra_pmc_cpu_power_on(unsigned int cpuid)
727{ 806{
728 int id; 807 int id;
729 808
730 id = tegra_get_cpu_powergate_id(cpuid); 809 id = tegra_get_cpu_powergate_id(pmc, cpuid);
731 if (id < 0) 810 if (id < 0)
732 return id; 811 return id;
733 812
734 return tegra_powergate_set(id, true); 813 return tegra_powergate_set(pmc, id, true);
735} 814}
736 815
737/** 816/**
@@ -742,7 +821,7 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid)
742{ 821{
743 int id; 822 int id;
744 823
745 id = tegra_get_cpu_powergate_id(cpuid); 824 id = tegra_get_cpu_powergate_id(pmc, cpuid);
746 if (id < 0) 825 if (id < 0)
747 return id; 826 return id;
748 827
@@ -755,7 +834,7 @@ static int tegra_pmc_restart_notify(struct notifier_block *this,
755 const char *cmd = data; 834 const char *cmd = data;
756 u32 value; 835 u32 value;
757 836
758 value = readl(pmc->scratch + pmc->soc->regs->scratch0); 837 value = tegra_pmc_scratch_readl(pmc, pmc->soc->regs->scratch0);
759 value &= ~PMC_SCRATCH0_MODE_MASK; 838 value &= ~PMC_SCRATCH0_MODE_MASK;
760 839
761 if (cmd) { 840 if (cmd) {
@@ -769,12 +848,12 @@ static int tegra_pmc_restart_notify(struct notifier_block *this,
769 value |= PMC_SCRATCH0_MODE_RCM; 848 value |= PMC_SCRATCH0_MODE_RCM;
770 } 849 }
771 850
772 writel(value, pmc->scratch + pmc->soc->regs->scratch0); 851 tegra_pmc_scratch_writel(pmc, value, pmc->soc->regs->scratch0);
773 852
774 /* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */ 853 /* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */
775 value = tegra_pmc_readl(PMC_CNTRL); 854 value = tegra_pmc_readl(pmc, PMC_CNTRL);
776 value |= PMC_CNTRL_MAIN_RST; 855 value |= PMC_CNTRL_MAIN_RST;
777 tegra_pmc_writel(value, PMC_CNTRL); 856 tegra_pmc_writel(pmc, value, PMC_CNTRL);
778 857
779 return NOTIFY_DONE; 858 return NOTIFY_DONE;
780} 859}
@@ -793,7 +872,7 @@ static int powergate_show(struct seq_file *s, void *data)
793 seq_printf(s, "------------------\n"); 872 seq_printf(s, "------------------\n");
794 873
795 for (i = 0; i < pmc->soc->num_powergates; i++) { 874 for (i = 0; i < pmc->soc->num_powergates; i++) {
796 status = tegra_powergate_is_powered(i); 875 status = tegra_powergate_is_powered(pmc, i);
797 if (status < 0) 876 if (status < 0)
798 continue; 877 continue;
799 878
@@ -855,12 +934,13 @@ err:
855static int tegra_powergate_of_get_resets(struct tegra_powergate *pg, 934static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
856 struct device_node *np, bool off) 935 struct device_node *np, bool off)
857{ 936{
937 struct device *dev = pg->pmc->dev;
858 int err; 938 int err;
859 939
860 pg->reset = of_reset_control_array_get_exclusive(np); 940 pg->reset = of_reset_control_array_get_exclusive(np);
861 if (IS_ERR(pg->reset)) { 941 if (IS_ERR(pg->reset)) {
862 err = PTR_ERR(pg->reset); 942 err = PTR_ERR(pg->reset);
863 pr_err("failed to get device resets: %d\n", err); 943 dev_err(dev, "failed to get device resets: %d\n", err);
864 return err; 944 return err;
865 } 945 }
866 946
@@ -877,6 +957,7 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
877 957
878static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np) 958static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
879{ 959{
960 struct device *dev = pmc->dev;
880 struct tegra_powergate *pg; 961 struct tegra_powergate *pg;
881 int id, err; 962 int id, err;
882 bool off; 963 bool off;
@@ -887,7 +968,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
887 968
888 id = tegra_powergate_lookup(pmc, np->name); 969 id = tegra_powergate_lookup(pmc, np->name);
889 if (id < 0) { 970 if (id < 0) {
890 pr_err("powergate lookup failed for %pOFn: %d\n", np, id); 971 dev_err(dev, "powergate lookup failed for %pOFn: %d\n", np, id);
891 goto free_mem; 972 goto free_mem;
892 } 973 }
893 974
@@ -903,17 +984,17 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
903 pg->genpd.power_on = tegra_genpd_power_on; 984 pg->genpd.power_on = tegra_genpd_power_on;
904 pg->pmc = pmc; 985 pg->pmc = pmc;
905 986
906 off = !tegra_powergate_is_powered(pg->id); 987 off = !tegra_powergate_is_powered(pmc, pg->id);
907 988
908 err = tegra_powergate_of_get_clks(pg, np); 989 err = tegra_powergate_of_get_clks(pg, np);
909 if (err < 0) { 990 if (err < 0) {
910 pr_err("failed to get clocks for %pOFn: %d\n", np, err); 991 dev_err(dev, "failed to get clocks for %pOFn: %d\n", np, err);
911 goto set_available; 992 goto set_available;
912 } 993 }
913 994
914 err = tegra_powergate_of_get_resets(pg, np, off); 995 err = tegra_powergate_of_get_resets(pg, np, off);
915 if (err < 0) { 996 if (err < 0) {
916 pr_err("failed to get resets for %pOFn: %d\n", np, err); 997 dev_err(dev, "failed to get resets for %pOFn: %d\n", np, err);
917 goto remove_clks; 998 goto remove_clks;
918 } 999 }
919 1000
@@ -926,19 +1007,19 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
926 1007
927 err = pm_genpd_init(&pg->genpd, NULL, off); 1008 err = pm_genpd_init(&pg->genpd, NULL, off);
928 if (err < 0) { 1009 if (err < 0) {
929 pr_err("failed to initialise PM domain %pOFn: %d\n", np, 1010 dev_err(dev, "failed to initialise PM domain %pOFn: %d\n", np,
930 err); 1011 err);
931 goto remove_resets; 1012 goto remove_resets;
932 } 1013 }
933 1014
934 err = of_genpd_add_provider_simple(np, &pg->genpd); 1015 err = of_genpd_add_provider_simple(np, &pg->genpd);
935 if (err < 0) { 1016 if (err < 0) {
936 pr_err("failed to add PM domain provider for %pOFn: %d\n", 1017 dev_err(dev, "failed to add PM domain provider for %pOFn: %d\n",
937 np, err); 1018 np, err);
938 goto remove_genpd; 1019 goto remove_genpd;
939 } 1020 }
940 1021
941 pr_debug("added PM domain %s\n", pg->genpd.name); 1022 dev_dbg(dev, "added PM domain %s\n", pg->genpd.name);
942 1023
943 return; 1024 return;
944 1025
@@ -994,7 +1075,8 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
994 return NULL; 1075 return NULL;
995} 1076}
996 1077
997static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id, 1078static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
1079 enum tegra_io_pad id,
998 unsigned long *request, 1080 unsigned long *request,
999 unsigned long *status, 1081 unsigned long *status,
1000 u32 *mask) 1082 u32 *mask)
@@ -1003,7 +1085,7 @@ static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
1003 1085
1004 pad = tegra_io_pad_find(pmc, id); 1086 pad = tegra_io_pad_find(pmc, id);
1005 if (!pad) { 1087 if (!pad) {
1006 pr_err("invalid I/O pad ID %u\n", id); 1088 dev_err(pmc->dev, "invalid I/O pad ID %u\n", id);
1007 return -ENOENT; 1089 return -ENOENT;
1008 } 1090 }
1009 1091
@@ -1023,43 +1105,44 @@ static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
1023 return 0; 1105 return 0;
1024} 1106}
1025 1107
1026static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request, 1108static int tegra_io_pad_prepare(struct tegra_pmc *pmc, enum tegra_io_pad id,
1027 unsigned long *status, u32 *mask) 1109 unsigned long *request, unsigned long *status,
1110 u32 *mask)
1028{ 1111{
1029 unsigned long rate, value; 1112 unsigned long rate, value;
1030 int err; 1113 int err;
1031 1114
1032 err = tegra_io_pad_get_dpd_register_bit(id, request, status, mask); 1115 err = tegra_io_pad_get_dpd_register_bit(pmc, id, request, status, mask);
1033 if (err) 1116 if (err)
1034 return err; 1117 return err;
1035 1118
1036 if (pmc->clk) { 1119 if (pmc->clk) {
1037 rate = clk_get_rate(pmc->clk); 1120 rate = clk_get_rate(pmc->clk);
1038 if (!rate) { 1121 if (!rate) {
1039 pr_err("failed to get clock rate\n"); 1122 dev_err(pmc->dev, "failed to get clock rate\n");
1040 return -ENODEV; 1123 return -ENODEV;
1041 } 1124 }
1042 1125
1043 tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE); 1126 tegra_pmc_writel(pmc, DPD_SAMPLE_ENABLE, DPD_SAMPLE);
1044 1127
1045 /* must be at least 200 ns, in APB (PCLK) clock cycles */ 1128 /* must be at least 200 ns, in APB (PCLK) clock cycles */
1046 value = DIV_ROUND_UP(1000000000, rate); 1129 value = DIV_ROUND_UP(1000000000, rate);
1047 value = DIV_ROUND_UP(200, value); 1130 value = DIV_ROUND_UP(200, value);
1048 tegra_pmc_writel(value, SEL_DPD_TIM); 1131 tegra_pmc_writel(pmc, value, SEL_DPD_TIM);
1049 } 1132 }
1050 1133
1051 return 0; 1134 return 0;
1052} 1135}
1053 1136
1054static int tegra_io_pad_poll(unsigned long offset, u32 mask, 1137static int tegra_io_pad_poll(struct tegra_pmc *pmc, unsigned long offset,
1055 u32 val, unsigned long timeout) 1138 u32 mask, u32 val, unsigned long timeout)
1056{ 1139{
1057 u32 value; 1140 u32 value;
1058 1141
1059 timeout = jiffies + msecs_to_jiffies(timeout); 1142 timeout = jiffies + msecs_to_jiffies(timeout);
1060 1143
1061 while (time_after(timeout, jiffies)) { 1144 while (time_after(timeout, jiffies)) {
1062 value = tegra_pmc_readl(offset); 1145 value = tegra_pmc_readl(pmc, offset);
1063 if ((value & mask) == val) 1146 if ((value & mask) == val)
1064 return 0; 1147 return 0;
1065 1148
@@ -1069,10 +1152,10 @@ static int tegra_io_pad_poll(unsigned long offset, u32 mask,
1069 return -ETIMEDOUT; 1152 return -ETIMEDOUT;
1070} 1153}
1071 1154
1072static void tegra_io_pad_unprepare(void) 1155static void tegra_io_pad_unprepare(struct tegra_pmc *pmc)
1073{ 1156{
1074 if (pmc->clk) 1157 if (pmc->clk)
1075 tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE); 1158 tegra_pmc_writel(pmc, DPD_SAMPLE_DISABLE, DPD_SAMPLE);
1076} 1159}
1077 1160
1078/** 1161/**
@@ -1089,21 +1172,21 @@ int tegra_io_pad_power_enable(enum tegra_io_pad id)
1089 1172
1090 mutex_lock(&pmc->powergates_lock); 1173 mutex_lock(&pmc->powergates_lock);
1091 1174
1092 err = tegra_io_pad_prepare(id, &request, &status, &mask); 1175 err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
1093 if (err < 0) { 1176 if (err < 0) {
1094 pr_err("failed to prepare I/O pad: %d\n", err); 1177 dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err);
1095 goto unlock; 1178 goto unlock;
1096 } 1179 }
1097 1180
1098 tegra_pmc_writel(IO_DPD_REQ_CODE_OFF | mask, request); 1181 tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_OFF | mask, request);
1099 1182
1100 err = tegra_io_pad_poll(status, mask, 0, 250); 1183 err = tegra_io_pad_poll(pmc, status, mask, 0, 250);
1101 if (err < 0) { 1184 if (err < 0) {
1102 pr_err("failed to enable I/O pad: %d\n", err); 1185 dev_err(pmc->dev, "failed to enable I/O pad: %d\n", err);
1103 goto unlock; 1186 goto unlock;
1104 } 1187 }
1105 1188
1106 tegra_io_pad_unprepare(); 1189 tegra_io_pad_unprepare(pmc);
1107 1190
1108unlock: 1191unlock:
1109 mutex_unlock(&pmc->powergates_lock); 1192 mutex_unlock(&pmc->powergates_lock);
@@ -1125,21 +1208,21 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id)
1125 1208
1126 mutex_lock(&pmc->powergates_lock); 1209 mutex_lock(&pmc->powergates_lock);
1127 1210
1128 err = tegra_io_pad_prepare(id, &request, &status, &mask); 1211 err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
1129 if (err < 0) { 1212 if (err < 0) {
1130 pr_err("failed to prepare I/O pad: %d\n", err); 1213 dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err);
1131 goto unlock; 1214 goto unlock;
1132 } 1215 }
1133 1216
1134 tegra_pmc_writel(IO_DPD_REQ_CODE_ON | mask, request); 1217 tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_ON | mask, request);
1135 1218
1136 err = tegra_io_pad_poll(status, mask, mask, 250); 1219 err = tegra_io_pad_poll(pmc, status, mask, mask, 250);
1137 if (err < 0) { 1220 if (err < 0) {
1138 pr_err("failed to disable I/O pad: %d\n", err); 1221 dev_err(pmc->dev, "failed to disable I/O pad: %d\n", err);
1139 goto unlock; 1222 goto unlock;
1140 } 1223 }
1141 1224
1142 tegra_io_pad_unprepare(); 1225 tegra_io_pad_unprepare(pmc);
1143 1226
1144unlock: 1227unlock:
1145 mutex_unlock(&pmc->powergates_lock); 1228 mutex_unlock(&pmc->powergates_lock);
@@ -1147,22 +1230,24 @@ unlock:
1147} 1230}
1148EXPORT_SYMBOL(tegra_io_pad_power_disable); 1231EXPORT_SYMBOL(tegra_io_pad_power_disable);
1149 1232
1150static int tegra_io_pad_is_powered(enum tegra_io_pad id) 1233static int tegra_io_pad_is_powered(struct tegra_pmc *pmc, enum tegra_io_pad id)
1151{ 1234{
1152 unsigned long request, status; 1235 unsigned long request, status;
1153 u32 mask, value; 1236 u32 mask, value;
1154 int err; 1237 int err;
1155 1238
1156 err = tegra_io_pad_get_dpd_register_bit(id, &request, &status, &mask); 1239 err = tegra_io_pad_get_dpd_register_bit(pmc, id, &request, &status,
1240 &mask);
1157 if (err) 1241 if (err)
1158 return err; 1242 return err;
1159 1243
1160 value = tegra_pmc_readl(status); 1244 value = tegra_pmc_readl(pmc, status);
1161 1245
1162 return !(value & mask); 1246 return !(value & mask);
1163} 1247}
1164 1248
1165static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage) 1249static int tegra_io_pad_set_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id,
1250 int voltage)
1166{ 1251{
1167 const struct tegra_io_pad_soc *pad; 1252 const struct tegra_io_pad_soc *pad;
1168 u32 value; 1253 u32 value;
@@ -1177,29 +1262,29 @@ static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
1177 mutex_lock(&pmc->powergates_lock); 1262 mutex_lock(&pmc->powergates_lock);
1178 1263
1179 if (pmc->soc->has_impl_33v_pwr) { 1264 if (pmc->soc->has_impl_33v_pwr) {
1180 value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR); 1265 value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR);
1181 1266
1182 if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) 1267 if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
1183 value &= ~BIT(pad->voltage); 1268 value &= ~BIT(pad->voltage);
1184 else 1269 else
1185 value |= BIT(pad->voltage); 1270 value |= BIT(pad->voltage);
1186 1271
1187 tegra_pmc_writel(value, PMC_IMPL_E_33V_PWR); 1272 tegra_pmc_writel(pmc, value, PMC_IMPL_E_33V_PWR);
1188 } else { 1273 } else {
1189 /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */ 1274 /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
1190 value = tegra_pmc_readl(PMC_PWR_DET); 1275 value = tegra_pmc_readl(pmc, PMC_PWR_DET);
1191 value |= BIT(pad->voltage); 1276 value |= BIT(pad->voltage);
1192 tegra_pmc_writel(value, PMC_PWR_DET); 1277 tegra_pmc_writel(pmc, value, PMC_PWR_DET);
1193 1278
1194 /* update I/O voltage */ 1279 /* update I/O voltage */
1195 value = tegra_pmc_readl(PMC_PWR_DET_VALUE); 1280 value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
1196 1281
1197 if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) 1282 if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
1198 value &= ~BIT(pad->voltage); 1283 value &= ~BIT(pad->voltage);
1199 else 1284 else
1200 value |= BIT(pad->voltage); 1285 value |= BIT(pad->voltage);
1201 1286
1202 tegra_pmc_writel(value, PMC_PWR_DET_VALUE); 1287 tegra_pmc_writel(pmc, value, PMC_PWR_DET_VALUE);
1203 } 1288 }
1204 1289
1205 mutex_unlock(&pmc->powergates_lock); 1290 mutex_unlock(&pmc->powergates_lock);
@@ -1209,7 +1294,7 @@ static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
1209 return 0; 1294 return 0;
1210} 1295}
1211 1296
1212static int tegra_io_pad_get_voltage(enum tegra_io_pad id) 1297static int tegra_io_pad_get_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id)
1213{ 1298{
1214 const struct tegra_io_pad_soc *pad; 1299 const struct tegra_io_pad_soc *pad;
1215 u32 value; 1300 u32 value;
@@ -1222,9 +1307,9 @@ static int tegra_io_pad_get_voltage(enum tegra_io_pad id)
1222 return -ENOTSUPP; 1307 return -ENOTSUPP;
1223 1308
1224 if (pmc->soc->has_impl_33v_pwr) 1309 if (pmc->soc->has_impl_33v_pwr)
1225 value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR); 1310 value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR);
1226 else 1311 else
1227 value = tegra_pmc_readl(PMC_PWR_DET_VALUE); 1312 value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
1228 1313
1229 if ((value & BIT(pad->voltage)) == 0) 1314 if ((value & BIT(pad->voltage)) == 0)
1230 return TEGRA_IO_PAD_VOLTAGE_1V8; 1315 return TEGRA_IO_PAD_VOLTAGE_1V8;
@@ -1296,21 +1381,21 @@ void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
1296 1381
1297 ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1; 1382 ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
1298 do_div(ticks, USEC_PER_SEC); 1383 do_div(ticks, USEC_PER_SEC);
1299 tegra_pmc_writel(ticks, PMC_CPUPWRGOOD_TIMER); 1384 tegra_pmc_writel(pmc, ticks, PMC_CPUPWRGOOD_TIMER);
1300 1385
1301 ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1; 1386 ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
1302 do_div(ticks, USEC_PER_SEC); 1387 do_div(ticks, USEC_PER_SEC);
1303 tegra_pmc_writel(ticks, PMC_CPUPWROFF_TIMER); 1388 tegra_pmc_writel(pmc, ticks, PMC_CPUPWROFF_TIMER);
1304 1389
1305 wmb(); 1390 wmb();
1306 1391
1307 pmc->rate = rate; 1392 pmc->rate = rate;
1308 } 1393 }
1309 1394
1310 value = tegra_pmc_readl(PMC_CNTRL); 1395 value = tegra_pmc_readl(pmc, PMC_CNTRL);
1311 value &= ~PMC_CNTRL_SIDE_EFFECT_LP0; 1396 value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
1312 value |= PMC_CNTRL_CPU_PWRREQ_OE; 1397 value |= PMC_CNTRL_CPU_PWRREQ_OE;
1313 tegra_pmc_writel(value, PMC_CNTRL); 1398 tegra_pmc_writel(pmc, value, PMC_CNTRL);
1314} 1399}
1315#endif 1400#endif
1316 1401
@@ -1432,13 +1517,13 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
1432 if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux)) 1517 if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux))
1433 pinmux = 0; 1518 pinmux = 0;
1434 1519
1435 value = tegra_pmc_readl(PMC_SENSOR_CTRL); 1520 value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
1436 value |= PMC_SENSOR_CTRL_SCRATCH_WRITE; 1521 value |= PMC_SENSOR_CTRL_SCRATCH_WRITE;
1437 tegra_pmc_writel(value, PMC_SENSOR_CTRL); 1522 tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
1438 1523
1439 value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) | 1524 value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) |
1440 (reg_addr << PMC_SCRATCH54_ADDR_SHIFT); 1525 (reg_addr << PMC_SCRATCH54_ADDR_SHIFT);
1441 tegra_pmc_writel(value, PMC_SCRATCH54); 1526 tegra_pmc_writel(pmc, value, PMC_SCRATCH54);
1442 1527
1443 value = PMC_SCRATCH55_RESET_TEGRA; 1528 value = PMC_SCRATCH55_RESET_TEGRA;
1444 value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT; 1529 value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT;
@@ -1456,11 +1541,11 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
1456 1541
1457 value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT; 1542 value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT;
1458 1543
1459 tegra_pmc_writel(value, PMC_SCRATCH55); 1544 tegra_pmc_writel(pmc, value, PMC_SCRATCH55);
1460 1545
1461 value = tegra_pmc_readl(PMC_SENSOR_CTRL); 1546 value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
1462 value |= PMC_SENSOR_CTRL_ENABLE_RST; 1547 value |= PMC_SENSOR_CTRL_ENABLE_RST;
1463 tegra_pmc_writel(value, PMC_SENSOR_CTRL); 1548 tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
1464 1549
1465 dev_info(pmc->dev, "emergency thermal reset enabled\n"); 1550 dev_info(pmc->dev, "emergency thermal reset enabled\n");
1466 1551
@@ -1470,12 +1555,16 @@ out:
1470 1555
1471static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev) 1556static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
1472{ 1557{
1558 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1559
1473 return pmc->soc->num_io_pads; 1560 return pmc->soc->num_io_pads;
1474} 1561}
1475 1562
1476static const char *tegra_io_pad_pinctrl_get_group_name( 1563static const char *tegra_io_pad_pinctrl_get_group_name(struct pinctrl_dev *pctl,
1477 struct pinctrl_dev *pctl, unsigned int group) 1564 unsigned int group)
1478{ 1565{
1566 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl);
1567
1479 return pmc->soc->io_pads[group].name; 1568 return pmc->soc->io_pads[group].name;
1480} 1569}
1481 1570
@@ -1484,8 +1573,11 @@ static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev,
1484 const unsigned int **pins, 1573 const unsigned int **pins,
1485 unsigned int *num_pins) 1574 unsigned int *num_pins)
1486{ 1575{
1576 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1577
1487 *pins = &pmc->soc->io_pads[group].id; 1578 *pins = &pmc->soc->io_pads[group].id;
1488 *num_pins = 1; 1579 *num_pins = 1;
1580
1489 return 0; 1581 return 0;
1490} 1582}
1491 1583
@@ -1500,27 +1592,33 @@ static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = {
1500static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev, 1592static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
1501 unsigned int pin, unsigned long *config) 1593 unsigned int pin, unsigned long *config)
1502{ 1594{
1503 const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
1504 enum pin_config_param param = pinconf_to_config_param(*config); 1595 enum pin_config_param param = pinconf_to_config_param(*config);
1596 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1597 const struct tegra_io_pad_soc *pad;
1505 int ret; 1598 int ret;
1506 u32 arg; 1599 u32 arg;
1507 1600
1601 pad = tegra_io_pad_find(pmc, pin);
1508 if (!pad) 1602 if (!pad)
1509 return -EINVAL; 1603 return -EINVAL;
1510 1604
1511 switch (param) { 1605 switch (param) {
1512 case PIN_CONFIG_POWER_SOURCE: 1606 case PIN_CONFIG_POWER_SOURCE:
1513 ret = tegra_io_pad_get_voltage(pad->id); 1607 ret = tegra_io_pad_get_voltage(pmc, pad->id);
1514 if (ret < 0) 1608 if (ret < 0)
1515 return ret; 1609 return ret;
1610
1516 arg = ret; 1611 arg = ret;
1517 break; 1612 break;
1613
1518 case PIN_CONFIG_LOW_POWER_MODE: 1614 case PIN_CONFIG_LOW_POWER_MODE:
1519 ret = tegra_io_pad_is_powered(pad->id); 1615 ret = tegra_io_pad_is_powered(pmc, pad->id);
1520 if (ret < 0) 1616 if (ret < 0)
1521 return ret; 1617 return ret;
1618
1522 arg = !ret; 1619 arg = !ret;
1523 break; 1620 break;
1621
1524 default: 1622 default:
1525 return -EINVAL; 1623 return -EINVAL;
1526 } 1624 }
@@ -1534,12 +1632,14 @@ static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
1534 unsigned int pin, unsigned long *configs, 1632 unsigned int pin, unsigned long *configs,
1535 unsigned int num_configs) 1633 unsigned int num_configs)
1536{ 1634{
1537 const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin); 1635 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1636 const struct tegra_io_pad_soc *pad;
1538 enum pin_config_param param; 1637 enum pin_config_param param;
1539 unsigned int i; 1638 unsigned int i;
1540 int err; 1639 int err;
1541 u32 arg; 1640 u32 arg;
1542 1641
1642 pad = tegra_io_pad_find(pmc, pin);
1543 if (!pad) 1643 if (!pad)
1544 return -EINVAL; 1644 return -EINVAL;
1545 1645
@@ -1560,7 +1660,7 @@ static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
1560 if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 && 1660 if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
1561 arg != TEGRA_IO_PAD_VOLTAGE_3V3) 1661 arg != TEGRA_IO_PAD_VOLTAGE_3V3)
1562 return -EINVAL; 1662 return -EINVAL;
1563 err = tegra_io_pad_set_voltage(pad->id, arg); 1663 err = tegra_io_pad_set_voltage(pmc, pad->id, arg);
1564 if (err) 1664 if (err)
1565 return err; 1665 return err;
1566 break; 1666 break;
@@ -1585,7 +1685,7 @@ static struct pinctrl_desc tegra_pmc_pctl_desc = {
1585 1685
1586static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc) 1686static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
1587{ 1687{
1588 int err = 0; 1688 int err;
1589 1689
1590 if (!pmc->soc->num_pin_descs) 1690 if (!pmc->soc->num_pin_descs)
1591 return 0; 1691 return 0;
@@ -1598,18 +1698,20 @@ static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
1598 pmc); 1698 pmc);
1599 if (IS_ERR(pmc->pctl_dev)) { 1699 if (IS_ERR(pmc->pctl_dev)) {
1600 err = PTR_ERR(pmc->pctl_dev); 1700 err = PTR_ERR(pmc->pctl_dev);
1601 dev_err(pmc->dev, "unable to register pinctrl, %d\n", err); 1701 dev_err(pmc->dev, "failed to register pin controller: %d\n",
1702 err);
1703 return err;
1602 } 1704 }
1603 1705
1604 return err; 1706 return 0;
1605} 1707}
1606 1708
1607static ssize_t reset_reason_show(struct device *dev, 1709static ssize_t reset_reason_show(struct device *dev,
1608 struct device_attribute *attr, char *buf) 1710 struct device_attribute *attr, char *buf)
1609{ 1711{
1610 u32 value, rst_src; 1712 u32 value, rst_src;
1611 1713
1612 value = tegra_pmc_readl(pmc->soc->regs->rst_status); 1714 value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
1613 rst_src = (value & pmc->soc->regs->rst_source_mask) >> 1715 rst_src = (value & pmc->soc->regs->rst_source_mask) >>
1614 pmc->soc->regs->rst_source_shift; 1716 pmc->soc->regs->rst_source_shift;
1615 1717
@@ -1619,11 +1721,11 @@ static ssize_t reset_reason_show(struct device *dev,
1619static DEVICE_ATTR_RO(reset_reason); 1721static DEVICE_ATTR_RO(reset_reason);
1620 1722
1621static ssize_t reset_level_show(struct device *dev, 1723static ssize_t reset_level_show(struct device *dev,
1622 struct device_attribute *attr, char *buf) 1724 struct device_attribute *attr, char *buf)
1623{ 1725{
1624 u32 value, rst_lvl; 1726 u32 value, rst_lvl;
1625 1727
1626 value = tegra_pmc_readl(pmc->soc->regs->rst_status); 1728 value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
1627 rst_lvl = (value & pmc->soc->regs->rst_level_mask) >> 1729 rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
1628 pmc->soc->regs->rst_level_shift; 1730 pmc->soc->regs->rst_level_shift;
1629 1731
@@ -1641,16 +1743,16 @@ static void tegra_pmc_reset_sysfs_init(struct tegra_pmc *pmc)
1641 err = device_create_file(dev, &dev_attr_reset_reason); 1743 err = device_create_file(dev, &dev_attr_reset_reason);
1642 if (err < 0) 1744 if (err < 0)
1643 dev_warn(dev, 1745 dev_warn(dev,
1644 "failed to create attr \"reset_reason\": %d\n", 1746 "failed to create attr \"reset_reason\": %d\n",
1645 err); 1747 err);
1646 } 1748 }
1647 1749
1648 if (pmc->soc->reset_levels) { 1750 if (pmc->soc->reset_levels) {
1649 err = device_create_file(dev, &dev_attr_reset_level); 1751 err = device_create_file(dev, &dev_attr_reset_level);
1650 if (err < 0) 1752 if (err < 0)
1651 dev_warn(dev, 1753 dev_warn(dev,
1652 "failed to create attr \"reset_level\": %d\n", 1754 "failed to create attr \"reset_level\": %d\n",
1653 err); 1755 err);
1654 } 1756 }
1655} 1757}
1656 1758
@@ -1920,6 +2022,8 @@ static int tegra_pmc_probe(struct platform_device *pdev)
1920 pmc->base = base; 2022 pmc->base = base;
1921 mutex_unlock(&pmc->powergates_lock); 2023 mutex_unlock(&pmc->powergates_lock);
1922 2024
2025 platform_set_drvdata(pdev, pmc);
2026
1923 return 0; 2027 return 0;
1924 2028
1925cleanup_restart_handler: 2029cleanup_restart_handler:
@@ -1932,14 +2036,18 @@ cleanup_debugfs:
1932#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) 2036#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
1933static int tegra_pmc_suspend(struct device *dev) 2037static int tegra_pmc_suspend(struct device *dev)
1934{ 2038{
1935 tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41); 2039 struct tegra_pmc *pmc = dev_get_drvdata(dev);
2040
2041 tegra_pmc_writel(pmc, virt_to_phys(tegra_resume), PMC_SCRATCH41);
1936 2042
1937 return 0; 2043 return 0;
1938} 2044}
1939 2045
1940static int tegra_pmc_resume(struct device *dev) 2046static int tegra_pmc_resume(struct device *dev)
1941{ 2047{
1942 tegra_pmc_writel(0x0, PMC_SCRATCH41); 2048 struct tegra_pmc *pmc = dev_get_drvdata(dev);
2049
2050 tegra_pmc_writel(pmc, 0x0, PMC_SCRATCH41);
1943 2051
1944 return 0; 2052 return 0;
1945} 2053}
@@ -1976,11 +2084,11 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
1976 u32 value; 2084 u32 value;
1977 2085
1978 /* Always enable CPU power request */ 2086 /* Always enable CPU power request */
1979 value = tegra_pmc_readl(PMC_CNTRL); 2087 value = tegra_pmc_readl(pmc, PMC_CNTRL);
1980 value |= PMC_CNTRL_CPU_PWRREQ_OE; 2088 value |= PMC_CNTRL_CPU_PWRREQ_OE;
1981 tegra_pmc_writel(value, PMC_CNTRL); 2089 tegra_pmc_writel(pmc, value, PMC_CNTRL);
1982 2090
1983 value = tegra_pmc_readl(PMC_CNTRL); 2091 value = tegra_pmc_readl(pmc, PMC_CNTRL);
1984 2092
1985 if (pmc->sysclkreq_high) 2093 if (pmc->sysclkreq_high)
1986 value &= ~PMC_CNTRL_SYSCLK_POLARITY; 2094 value &= ~PMC_CNTRL_SYSCLK_POLARITY;
@@ -1988,12 +2096,12 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
1988 value |= PMC_CNTRL_SYSCLK_POLARITY; 2096 value |= PMC_CNTRL_SYSCLK_POLARITY;
1989 2097
1990 /* configure the output polarity while the request is tristated */ 2098 /* configure the output polarity while the request is tristated */
1991 tegra_pmc_writel(value, PMC_CNTRL); 2099 tegra_pmc_writel(pmc, value, PMC_CNTRL);
1992 2100
1993 /* now enable the request */ 2101 /* now enable the request */
1994 value = tegra_pmc_readl(PMC_CNTRL); 2102 value = tegra_pmc_readl(pmc, PMC_CNTRL);
1995 value |= PMC_CNTRL_SYSCLK_OE; 2103 value |= PMC_CNTRL_SYSCLK_OE;
1996 tegra_pmc_writel(value, PMC_CNTRL); 2104 tegra_pmc_writel(pmc, value, PMC_CNTRL);
1997} 2105}
1998 2106
1999static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc, 2107static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
@@ -2002,14 +2110,14 @@ static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
2002{ 2110{
2003 u32 value; 2111 u32 value;
2004 2112
2005 value = tegra_pmc_readl(PMC_CNTRL); 2113 value = tegra_pmc_readl(pmc, PMC_CNTRL);
2006 2114
2007 if (invert) 2115 if (invert)
2008 value |= PMC_CNTRL_INTR_POLARITY; 2116 value |= PMC_CNTRL_INTR_POLARITY;
2009 else 2117 else
2010 value &= ~PMC_CNTRL_INTR_POLARITY; 2118 value &= ~PMC_CNTRL_INTR_POLARITY;
2011 2119
2012 tegra_pmc_writel(value, PMC_CNTRL); 2120 tegra_pmc_writel(pmc, value, PMC_CNTRL);
2013} 2121}
2014 2122
2015static const struct tegra_pmc_soc tegra20_pmc_soc = { 2123static const struct tegra_pmc_soc tegra20_pmc_soc = {
@@ -2019,6 +2127,9 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
2019 .cpu_powergates = NULL, 2127 .cpu_powergates = NULL,
2020 .has_tsense_reset = false, 2128 .has_tsense_reset = false,
2021 .has_gpu_clamps = false, 2129 .has_gpu_clamps = false,
2130 .needs_mbist_war = false,
2131 .has_impl_33v_pwr = false,
2132 .maybe_tz_only = false,
2022 .num_io_pads = 0, 2133 .num_io_pads = 0,
2023 .io_pads = NULL, 2134 .io_pads = NULL,
2024 .num_pin_descs = 0, 2135 .num_pin_descs = 0,
@@ -2063,7 +2174,9 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
2063 .cpu_powergates = tegra30_cpu_powergates, 2174 .cpu_powergates = tegra30_cpu_powergates,
2064 .has_tsense_reset = true, 2175 .has_tsense_reset = true,
2065 .has_gpu_clamps = false, 2176 .has_gpu_clamps = false,
2177 .needs_mbist_war = false,
2066 .has_impl_33v_pwr = false, 2178 .has_impl_33v_pwr = false,
2179 .maybe_tz_only = false,
2067 .num_io_pads = 0, 2180 .num_io_pads = 0,
2068 .io_pads = NULL, 2181 .io_pads = NULL,
2069 .num_pin_descs = 0, 2182 .num_pin_descs = 0,
@@ -2112,7 +2225,9 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
2112 .cpu_powergates = tegra114_cpu_powergates, 2225 .cpu_powergates = tegra114_cpu_powergates,
2113 .has_tsense_reset = true, 2226 .has_tsense_reset = true,
2114 .has_gpu_clamps = false, 2227 .has_gpu_clamps = false,
2228 .needs_mbist_war = false,
2115 .has_impl_33v_pwr = false, 2229 .has_impl_33v_pwr = false,
2230 .maybe_tz_only = false,
2116 .num_io_pads = 0, 2231 .num_io_pads = 0,
2117 .io_pads = NULL, 2232 .io_pads = NULL,
2118 .num_pin_descs = 0, 2233 .num_pin_descs = 0,
@@ -2221,7 +2336,9 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
2221 .cpu_powergates = tegra124_cpu_powergates, 2336 .cpu_powergates = tegra124_cpu_powergates,
2222 .has_tsense_reset = true, 2337 .has_tsense_reset = true,
2223 .has_gpu_clamps = true, 2338 .has_gpu_clamps = true,
2339 .needs_mbist_war = false,
2224 .has_impl_33v_pwr = false, 2340 .has_impl_33v_pwr = false,
2341 .maybe_tz_only = false,
2225 .num_io_pads = ARRAY_SIZE(tegra124_io_pads), 2342 .num_io_pads = ARRAY_SIZE(tegra124_io_pads),
2226 .io_pads = tegra124_io_pads, 2343 .io_pads = tegra124_io_pads,
2227 .num_pin_descs = ARRAY_SIZE(tegra124_pin_descs), 2344 .num_pin_descs = ARRAY_SIZE(tegra124_pin_descs),
@@ -2325,8 +2442,9 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
2325 .cpu_powergates = tegra210_cpu_powergates, 2442 .cpu_powergates = tegra210_cpu_powergates,
2326 .has_tsense_reset = true, 2443 .has_tsense_reset = true,
2327 .has_gpu_clamps = true, 2444 .has_gpu_clamps = true,
2328 .has_impl_33v_pwr = false,
2329 .needs_mbist_war = true, 2445 .needs_mbist_war = true,
2446 .has_impl_33v_pwr = false,
2447 .maybe_tz_only = true,
2330 .num_io_pads = ARRAY_SIZE(tegra210_io_pads), 2448 .num_io_pads = ARRAY_SIZE(tegra210_io_pads),
2331 .io_pads = tegra210_io_pads, 2449 .io_pads = tegra210_io_pads,
2332 .num_pin_descs = ARRAY_SIZE(tegra210_pin_descs), 2450 .num_pin_descs = ARRAY_SIZE(tegra210_pin_descs),
@@ -2413,7 +2531,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
2413 2531
2414 index = of_property_match_string(np, "reg-names", "wake"); 2532 index = of_property_match_string(np, "reg-names", "wake");
2415 if (index < 0) { 2533 if (index < 0) {
2416 pr_err("failed to find PMC wake registers\n"); 2534 dev_err(pmc->dev, "failed to find PMC wake registers\n");
2417 return; 2535 return;
2418 } 2536 }
2419 2537
@@ -2421,7 +2539,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
2421 2539
2422 wake = ioremap_nocache(regs.start, resource_size(&regs)); 2540 wake = ioremap_nocache(regs.start, resource_size(&regs));
2423 if (!wake) { 2541 if (!wake) {
2424 pr_err("failed to map PMC wake registers\n"); 2542 dev_err(pmc->dev, "failed to map PMC wake registers\n");
2425 return; 2543 return;
2426 } 2544 }
2427 2545
@@ -2438,7 +2556,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
2438} 2556}
2439 2557
2440static const struct tegra_wake_event tegra186_wake_events[] = { 2558static const struct tegra_wake_event tegra186_wake_events[] = {
2441 TEGRA_WAKE_GPIO("power", 29, 1, TEGRA_AON_GPIO(FF, 0)), 2559 TEGRA_WAKE_GPIO("power", 29, 1, TEGRA186_AON_GPIO(FF, 0)),
2442 TEGRA_WAKE_IRQ("rtc", 73, 10), 2560 TEGRA_WAKE_IRQ("rtc", 73, 10),
2443}; 2561};
2444 2562
@@ -2449,7 +2567,9 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
2449 .cpu_powergates = NULL, 2567 .cpu_powergates = NULL,
2450 .has_tsense_reset = false, 2568 .has_tsense_reset = false,
2451 .has_gpu_clamps = false, 2569 .has_gpu_clamps = false,
2570 .needs_mbist_war = false,
2452 .has_impl_33v_pwr = true, 2571 .has_impl_33v_pwr = true,
2572 .maybe_tz_only = false,
2453 .num_io_pads = ARRAY_SIZE(tegra186_io_pads), 2573 .num_io_pads = ARRAY_SIZE(tegra186_io_pads),
2454 .io_pads = tegra186_io_pads, 2574 .io_pads = tegra186_io_pads,
2455 .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs), 2575 .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs),
@@ -2527,6 +2647,9 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = {
2527 .cpu_powergates = NULL, 2647 .cpu_powergates = NULL,
2528 .has_tsense_reset = false, 2648 .has_tsense_reset = false,
2529 .has_gpu_clamps = false, 2649 .has_gpu_clamps = false,
2650 .needs_mbist_war = false,
2651 .has_impl_33v_pwr = false,
2652 .maybe_tz_only = false,
2530 .num_io_pads = ARRAY_SIZE(tegra194_io_pads), 2653 .num_io_pads = ARRAY_SIZE(tegra194_io_pads),
2531 .io_pads = tegra194_io_pads, 2654 .io_pads = tegra194_io_pads,
2532 .regs = &tegra186_pmc_regs, 2655 .regs = &tegra186_pmc_regs,
@@ -2561,6 +2684,32 @@ static struct platform_driver tegra_pmc_driver = {
2561}; 2684};
2562builtin_platform_driver(tegra_pmc_driver); 2685builtin_platform_driver(tegra_pmc_driver);
2563 2686
2687static bool __init tegra_pmc_detect_tz_only(struct tegra_pmc *pmc)
2688{
2689 u32 value, saved;
2690
2691 saved = readl(pmc->base + pmc->soc->regs->scratch0);
2692 value = saved ^ 0xffffffff;
2693
2694 if (value == 0xffffffff)
2695 value = 0xdeadbeef;
2696
2697 /* write pattern and read it back */
2698 writel(value, pmc->base + pmc->soc->regs->scratch0);
2699 value = readl(pmc->base + pmc->soc->regs->scratch0);
2700
2701 /* if we read all-zeroes, access is restricted to TZ only */
2702 if (value == 0) {
2703 pr_info("access to PMC is restricted to TZ\n");
2704 return true;
2705 }
2706
2707 /* restore original value */
2708 writel(saved, pmc->base + pmc->soc->regs->scratch0);
2709
2710 return false;
2711}
2712
2564/* 2713/*
2565 * Early initialization to allow access to registers in the very early boot 2714 * Early initialization to allow access to registers in the very early boot
2566 * process. 2715 * process.
@@ -2623,6 +2772,9 @@ static int __init tegra_pmc_early_init(void)
2623 if (np) { 2772 if (np) {
2624 pmc->soc = match->data; 2773 pmc->soc = match->data;
2625 2774
2775 if (pmc->soc->maybe_tz_only)
2776 pmc->tz_only = tegra_pmc_detect_tz_only(pmc);
2777
2626 tegra_powergate_init(pmc, np); 2778 tegra_powergate_init(pmc, np);
2627 2779
2628 /* 2780 /*
diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c
index e05ab16d9a9e..6285cd8efb21 100644
--- a/drivers/soc/ti/knav_dma.c
+++ b/drivers/soc/ti/knav_dma.c
@@ -598,7 +598,7 @@ static int pktdma_init_chan(struct knav_dma_device *dma,
598 598
599 INIT_LIST_HEAD(&chan->list); 599 INIT_LIST_HEAD(&chan->list);
600 chan->dma = dma; 600 chan->dma = dma;
601 chan->direction = DMA_NONE; 601 chan->direction = DMA_TRANS_NONE;
602 atomic_set(&chan->ref_count, 0); 602 atomic_set(&chan->ref_count, 0);
603 spin_lock_init(&chan->lock); 603 spin_lock_init(&chan->lock);
604 604
diff --git a/drivers/soc/xilinx/Kconfig b/drivers/soc/xilinx/Kconfig
index 687c8f3cd955..01e76b58dd78 100644
--- a/drivers/soc/xilinx/Kconfig
+++ b/drivers/soc/xilinx/Kconfig
@@ -17,4 +17,24 @@ config XILINX_VCU
17 To compile this driver as a module, choose M here: the 17 To compile this driver as a module, choose M here: the
18 module will be called xlnx_vcu. 18 module will be called xlnx_vcu.
19 19
20config ZYNQMP_POWER
21 bool "Enable Xilinx Zynq MPSoC Power Management driver"
22 depends on PM && ARCH_ZYNQMP
23 default y
24 help
25 Say yes to enable power management support for ZyqnMP SoC.
26 This driver uses firmware driver as an interface for power
27 management request to firmware. It registers isr to handle
28 power management callbacks from firmware.
29 If in doubt, say N.
30
31config ZYNQMP_PM_DOMAINS
32 bool "Enable Zynq MPSoC generic PM domains"
33 default y
34 depends on PM && ARCH_ZYNQMP && ZYNQMP_FIRMWARE
35 select PM_GENERIC_DOMAINS
36 help
37 Say yes to enable device power management through PM domains
38 If in doubt, say N.
39
20endmenu 40endmenu
diff --git a/drivers/soc/xilinx/Makefile b/drivers/soc/xilinx/Makefile
index dee8fd51e303..f66bfea5de17 100644
--- a/drivers/soc/xilinx/Makefile
+++ b/drivers/soc/xilinx/Makefile
@@ -1,2 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o 2obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o
3obj-$(CONFIG_ZYNQMP_POWER) += zynqmp_power.o
4obj-$(CONFIG_ZYNQMP_PM_DOMAINS) += zynqmp_pm_domains.o
diff --git a/drivers/soc/xilinx/zynqmp_pm_domains.c b/drivers/soc/xilinx/zynqmp_pm_domains.c
new file mode 100644
index 000000000000..354d256e6e00
--- /dev/null
+++ b/drivers/soc/xilinx/zynqmp_pm_domains.c
@@ -0,0 +1,321 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * ZynqMP Generic PM domain support
4 *
5 * Copyright (C) 2015-2018 Xilinx, Inc.
6 *
7 * Davorin Mista <davorin.mista@aggios.com>
8 * Jolly Shah <jollys@xilinx.com>
9 * Rajan Vaja <rajan.vaja@xilinx.com>
10 */
11
12#include <linux/err.h>
13#include <linux/list.h>
14#include <linux/module.h>
15#include <linux/of_platform.h>
16#include <linux/platform_device.h>
17#include <linux/pm_domain.h>
18#include <linux/slab.h>
19
20#include <linux/firmware/xlnx-zynqmp.h>
21
22#define ZYNQMP_NUM_DOMAINS (100)
23/* Flag stating if PM nodes mapped to the PM domain has been requested */
24#define ZYNQMP_PM_DOMAIN_REQUESTED BIT(0)
25
26/**
27 * struct zynqmp_pm_domain - Wrapper around struct generic_pm_domain
28 * @gpd: Generic power domain
29 * @node_id: PM node ID corresponding to device inside PM domain
30 * @flags: ZynqMP PM domain flags
31 */
32struct zynqmp_pm_domain {
33 struct generic_pm_domain gpd;
34 u32 node_id;
35 u8 flags;
36};
37
38/**
39 * zynqmp_gpd_is_active_wakeup_path() - Check if device is in wakeup source
40 * path
41 * @dev: Device to check for wakeup source path
42 * @not_used: Data member (not required)
43 *
44 * This function is checks device's child hierarchy and checks if any device is
45 * set as wakeup source.
46 *
47 * Return: 1 if device is in wakeup source path else 0
48 */
49static int zynqmp_gpd_is_active_wakeup_path(struct device *dev, void *not_used)
50{
51 int may_wakeup;
52
53 may_wakeup = device_may_wakeup(dev);
54 if (may_wakeup)
55 return may_wakeup;
56
57 return device_for_each_child(dev, NULL,
58 zynqmp_gpd_is_active_wakeup_path);
59}
60
61/**
62 * zynqmp_gpd_power_on() - Power on PM domain
63 * @domain: Generic PM domain
64 *
65 * This function is called before devices inside a PM domain are resumed, to
66 * power on PM domain.
67 *
68 * Return: 0 on success, error code otherwise
69 */
70static int zynqmp_gpd_power_on(struct generic_pm_domain *domain)
71{
72 int ret;
73 struct zynqmp_pm_domain *pd;
74 const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
75
76 if (!eemi_ops || !eemi_ops->set_requirement)
77 return -ENXIO;
78
79 pd = container_of(domain, struct zynqmp_pm_domain, gpd);
80 ret = eemi_ops->set_requirement(pd->node_id,
81 ZYNQMP_PM_CAPABILITY_ACCESS,
82 ZYNQMP_PM_MAX_QOS,
83 ZYNQMP_PM_REQUEST_ACK_BLOCKING);
84 if (ret) {
85 pr_err("%s() %s set requirement for node %d failed: %d\n",
86 __func__, domain->name, pd->node_id, ret);
87 return ret;
88 }
89
90 pr_debug("%s() Powered on %s domain\n", __func__, domain->name);
91 return 0;
92}
93
94/**
95 * zynqmp_gpd_power_off() - Power off PM domain
96 * @domain: Generic PM domain
97 *
98 * This function is called after devices inside a PM domain are suspended, to
99 * power off PM domain.
100 *
101 * Return: 0 on success, error code otherwise
102 */
103static int zynqmp_gpd_power_off(struct generic_pm_domain *domain)
104{
105 int ret;
106 struct pm_domain_data *pdd, *tmp;
107 struct zynqmp_pm_domain *pd;
108 u32 capabilities = 0;
109 bool may_wakeup;
110 const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
111
112 if (!eemi_ops || !eemi_ops->set_requirement)
113 return -ENXIO;
114
115 pd = container_of(domain, struct zynqmp_pm_domain, gpd);
116
117 /* If domain is already released there is nothing to be done */
118 if (!(pd->flags & ZYNQMP_PM_DOMAIN_REQUESTED)) {
119 pr_debug("%s() %s domain is already released\n",
120 __func__, domain->name);
121 return 0;
122 }
123
124 list_for_each_entry_safe(pdd, tmp, &domain->dev_list, list_node) {
125 /* If device is in wakeup path, set capability to WAKEUP */
126 may_wakeup = zynqmp_gpd_is_active_wakeup_path(pdd->dev, NULL);
127 if (may_wakeup) {
128 dev_dbg(pdd->dev, "device is in wakeup path in %s\n",
129 domain->name);
130 capabilities = ZYNQMP_PM_CAPABILITY_WAKEUP;
131 break;
132 }
133 }
134
135 ret = eemi_ops->set_requirement(pd->node_id, capabilities, 0,
136 ZYNQMP_PM_REQUEST_ACK_NO);
137 /**
138 * If powering down of any node inside this domain fails,
139 * report and return the error
140 */
141 if (ret) {
142 pr_err("%s() %s set requirement for node %d failed: %d\n",
143 __func__, domain->name, pd->node_id, ret);
144 return ret;
145 }
146
147 pr_debug("%s() Powered off %s domain\n", __func__, domain->name);
148 return 0;
149}
150
151/**
152 * zynqmp_gpd_attach_dev() - Attach device to the PM domain
153 * @domain: Generic PM domain
154 * @dev: Device to attach
155 *
156 * Return: 0 on success, error code otherwise
157 */
158static int zynqmp_gpd_attach_dev(struct generic_pm_domain *domain,
159 struct device *dev)
160{
161 int ret;
162 struct zynqmp_pm_domain *pd;
163 const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
164
165 if (!eemi_ops || !eemi_ops->request_node)
166 return -ENXIO;
167
168 pd = container_of(domain, struct zynqmp_pm_domain, gpd);
169
170 /* If this is not the first device to attach there is nothing to do */
171 if (domain->device_count)
172 return 0;
173
174 ret = eemi_ops->request_node(pd->node_id, 0, 0,
175 ZYNQMP_PM_REQUEST_ACK_BLOCKING);
176 /* If requesting a node fails print and return the error */
177 if (ret) {
178 pr_err("%s() %s request failed for node %d: %d\n",
179 __func__, domain->name, pd->node_id, ret);
180 return ret;
181 }
182
183 pd->flags |= ZYNQMP_PM_DOMAIN_REQUESTED;
184
185 pr_debug("%s() %s attached to %s domain\n", __func__,
186 dev_name(dev), domain->name);
187 return 0;
188}
189
190/**
191 * zynqmp_gpd_detach_dev() - Detach device from the PM domain
192 * @domain: Generic PM domain
193 * @dev: Device to detach
194 */
195static void zynqmp_gpd_detach_dev(struct generic_pm_domain *domain,
196 struct device *dev)
197{
198 int ret;
199 struct zynqmp_pm_domain *pd;
200 const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
201
202 if (!eemi_ops || !eemi_ops->release_node)
203 return;
204
205 pd = container_of(domain, struct zynqmp_pm_domain, gpd);
206
207 /* If this is not the last device to detach there is nothing to do */
208 if (domain->device_count)
209 return;
210
211 ret = eemi_ops->release_node(pd->node_id);
212 /* If releasing a node fails print the error and return */
213 if (ret) {
214 pr_err("%s() %s release failed for node %d: %d\n",
215 __func__, domain->name, pd->node_id, ret);
216 return;
217 }
218
219 pd->flags &= ~ZYNQMP_PM_DOMAIN_REQUESTED;
220
221 pr_debug("%s() %s detached from %s domain\n", __func__,
222 dev_name(dev), domain->name);
223}
224
225static struct generic_pm_domain *zynqmp_gpd_xlate
226 (struct of_phandle_args *genpdspec, void *data)
227{
228 struct genpd_onecell_data *genpd_data = data;
229 unsigned int i, idx = genpdspec->args[0];
230 struct zynqmp_pm_domain *pd;
231
232 pd = container_of(genpd_data->domains[0], struct zynqmp_pm_domain, gpd);
233
234 if (genpdspec->args_count != 1)
235 return ERR_PTR(-EINVAL);
236
237 /* Check for existing pm domains */
238 for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) {
239 if (pd[i].node_id == idx)
240 goto done;
241 }
242
243 /**
244 * Add index in empty node_id of power domain list as no existing
245 * power domain found for current index.
246 */
247 for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) {
248 if (pd[i].node_id == 0) {
249 pd[i].node_id = idx;
250 break;
251 }
252 }
253
254done:
255 if (!genpd_data->domains[i] || i == ZYNQMP_NUM_DOMAINS)
256 return ERR_PTR(-ENOENT);
257
258 return genpd_data->domains[i];
259}
260
261static int zynqmp_gpd_probe(struct platform_device *pdev)
262{
263 int i;
264 struct genpd_onecell_data *zynqmp_pd_data;
265 struct generic_pm_domain **domains;
266 struct zynqmp_pm_domain *pd;
267 struct device *dev = &pdev->dev;
268
269 pd = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*pd), GFP_KERNEL);
270 if (!pd)
271 return -ENOMEM;
272
273 zynqmp_pd_data = devm_kzalloc(dev, sizeof(*zynqmp_pd_data), GFP_KERNEL);
274 if (!zynqmp_pd_data)
275 return -ENOMEM;
276
277 zynqmp_pd_data->xlate = zynqmp_gpd_xlate;
278
279 domains = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*domains),
280 GFP_KERNEL);
281 if (!domains)
282 return -ENOMEM;
283
284 for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++, pd++) {
285 pd->node_id = 0;
286 pd->gpd.name = kasprintf(GFP_KERNEL, "domain%d", i);
287 pd->gpd.power_off = zynqmp_gpd_power_off;
288 pd->gpd.power_on = zynqmp_gpd_power_on;
289 pd->gpd.attach_dev = zynqmp_gpd_attach_dev;
290 pd->gpd.detach_dev = zynqmp_gpd_detach_dev;
291
292 domains[i] = &pd->gpd;
293
294 /* Mark all PM domains as initially powered off */
295 pm_genpd_init(&pd->gpd, NULL, true);
296 }
297
298 zynqmp_pd_data->domains = domains;
299 zynqmp_pd_data->num_domains = ZYNQMP_NUM_DOMAINS;
300 of_genpd_add_provider_onecell(dev->parent->of_node, zynqmp_pd_data);
301
302 return 0;
303}
304
305static int zynqmp_gpd_remove(struct platform_device *pdev)
306{
307 of_genpd_del_provider(pdev->dev.parent->of_node);
308
309 return 0;
310}
311
312static struct platform_driver zynqmp_power_domain_driver = {
313 .driver = {
314 .name = "zynqmp_power_controller",
315 },
316 .probe = zynqmp_gpd_probe,
317 .remove = zynqmp_gpd_remove,
318};
319module_platform_driver(zynqmp_power_domain_driver);
320
321MODULE_ALIAS("platform:zynqmp_power_controller");
diff --git a/drivers/soc/xilinx/zynqmp_power.c b/drivers/soc/xilinx/zynqmp_power.c
new file mode 100644
index 000000000000..771cb59b9d22
--- /dev/null
+++ b/drivers/soc/xilinx/zynqmp_power.c
@@ -0,0 +1,178 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Xilinx Zynq MPSoC Power Management
4 *
5 * Copyright (C) 2014-2018 Xilinx, Inc.
6 *
7 * Davorin Mista <davorin.mista@aggios.com>
8 * Jolly Shah <jollys@xilinx.com>
9 * Rajan Vaja <rajan.vaja@xilinx.com>
10 */
11
12#include <linux/mailbox_client.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/reboot.h>
16#include <linux/suspend.h>
17
18#include <linux/firmware/xlnx-zynqmp.h>
19
20enum pm_suspend_mode {
21 PM_SUSPEND_MODE_FIRST = 0,
22 PM_SUSPEND_MODE_STD = PM_SUSPEND_MODE_FIRST,
23 PM_SUSPEND_MODE_POWER_OFF,
24};
25
26#define PM_SUSPEND_MODE_FIRST PM_SUSPEND_MODE_STD
27
28static const char *const suspend_modes[] = {
29 [PM_SUSPEND_MODE_STD] = "standard",
30 [PM_SUSPEND_MODE_POWER_OFF] = "power-off",
31};
32
33static enum pm_suspend_mode suspend_mode = PM_SUSPEND_MODE_STD;
34
35enum pm_api_cb_id {
36 PM_INIT_SUSPEND_CB = 30,
37 PM_ACKNOWLEDGE_CB,
38 PM_NOTIFY_CB,
39};
40
41static void zynqmp_pm_get_callback_data(u32 *buf)
42{
43 zynqmp_pm_invoke_fn(GET_CALLBACK_DATA, 0, 0, 0, 0, buf);
44}
45
46static irqreturn_t zynqmp_pm_isr(int irq, void *data)
47{
48 u32 payload[CB_PAYLOAD_SIZE];
49
50 zynqmp_pm_get_callback_data(payload);
51
52 /* First element is callback API ID, others are callback arguments */
53 if (payload[0] == PM_INIT_SUSPEND_CB) {
54 switch (payload[1]) {
55 case SUSPEND_SYSTEM_SHUTDOWN:
56 orderly_poweroff(true);
57 break;
58 case SUSPEND_POWER_REQUEST:
59 pm_suspend(PM_SUSPEND_MEM);
60 break;
61 default:
62 pr_err("%s Unsupported InitSuspendCb reason "
63 "code %d\n", __func__, payload[1]);
64 }
65 }
66
67 return IRQ_HANDLED;
68}
69
70static ssize_t suspend_mode_show(struct device *dev,
71 struct device_attribute *attr, char *buf)
72{
73 char *s = buf;
74 int md;
75
76 for (md = PM_SUSPEND_MODE_FIRST; md < ARRAY_SIZE(suspend_modes); md++)
77 if (suspend_modes[md]) {
78 if (md == suspend_mode)
79 s += sprintf(s, "[%s] ", suspend_modes[md]);
80 else
81 s += sprintf(s, "%s ", suspend_modes[md]);
82 }
83
84 /* Convert last space to newline */
85 if (s != buf)
86 *(s - 1) = '\n';
87 return (s - buf);
88}
89
90static ssize_t suspend_mode_store(struct device *dev,
91 struct device_attribute *attr,
92 const char *buf, size_t count)
93{
94 int md, ret = -EINVAL;
95 const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
96
97 if (!eemi_ops || !eemi_ops->set_suspend_mode)
98 return ret;
99
100 for (md = PM_SUSPEND_MODE_FIRST; md < ARRAY_SIZE(suspend_modes); md++)
101 if (suspend_modes[md] &&
102 sysfs_streq(suspend_modes[md], buf)) {
103 ret = 0;
104 break;
105 }
106
107 if (!ret && md != suspend_mode) {
108 ret = eemi_ops->set_suspend_mode(md);
109 if (likely(!ret))
110 suspend_mode = md;
111 }
112
113 return ret ? ret : count;
114}
115
116static DEVICE_ATTR_RW(suspend_mode);
117
118static int zynqmp_pm_probe(struct platform_device *pdev)
119{
120 int ret, irq;
121 u32 pm_api_version;
122
123 const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
124
125 if (!eemi_ops || !eemi_ops->get_api_version || !eemi_ops->init_finalize)
126 return -ENXIO;
127
128 eemi_ops->init_finalize();
129 eemi_ops->get_api_version(&pm_api_version);
130
131 /* Check PM API version number */
132 if (pm_api_version < ZYNQMP_PM_VERSION)
133 return -ENODEV;
134
135 irq = platform_get_irq(pdev, 0);
136 if (irq <= 0)
137 return -ENXIO;
138
139 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, zynqmp_pm_isr,
140 IRQF_NO_SUSPEND | IRQF_ONESHOT,
141 dev_name(&pdev->dev), &pdev->dev);
142 if (ret) {
143 dev_err(&pdev->dev, "devm_request_threaded_irq '%d' failed "
144 "with %d\n", irq, ret);
145 return ret;
146 }
147
148 ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_suspend_mode.attr);
149 if (ret) {
150 dev_err(&pdev->dev, "unable to create sysfs interface\n");
151 return ret;
152 }
153
154 return 0;
155}
156
157static int zynqmp_pm_remove(struct platform_device *pdev)
158{
159 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_suspend_mode.attr);
160
161 return 0;
162}
163
164static const struct of_device_id pm_of_match[] = {
165 { .compatible = "xlnx,zynqmp-power", },
166 { /* end of table */ },
167};
168MODULE_DEVICE_TABLE(of, pm_of_match);
169
170static struct platform_driver zynqmp_pm_platform_driver = {
171 .probe = zynqmp_pm_probe,
172 .remove = zynqmp_pm_remove,
173 .driver = {
174 .name = "zynqmp_power",
175 .of_match_table = pm_of_match,
176 },
177};
178module_platform_driver(zynqmp_pm_platform_driver);
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
index 48d262ae2f04..56263ae3b1d7 100644
--- a/drivers/tee/optee/Makefile
+++ b/drivers/tee/optee/Makefile
@@ -5,3 +5,4 @@ optee-objs += call.o
5optee-objs += rpc.o 5optee-objs += rpc.o
6optee-objs += supp.o 6optee-objs += supp.o
7optee-objs += shm_pool.o 7optee-objs += shm_pool.o
8optee-objs += device.o
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index 947f9b28de9e..0842b6e6af82 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -634,6 +634,10 @@ static struct optee *optee_probe(struct device_node *np)
634 if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) 634 if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
635 pr_info("dynamic shared memory is enabled\n"); 635 pr_info("dynamic shared memory is enabled\n");
636 636
637 rc = optee_enumerate_devices();
638 if (rc)
639 goto err;
640
637 pr_info("initialized driver\n"); 641 pr_info("initialized driver\n");
638 return optee; 642 return optee;
639err: 643err:
diff --git a/drivers/tee/optee/device.c b/drivers/tee/optee/device.c
new file mode 100644
index 000000000000..e3a148521ec1
--- /dev/null
+++ b/drivers/tee/optee/device.c
@@ -0,0 +1,160 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2019 Linaro Ltd.
4 */
5
6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7
8#include <linux/kernel.h>
9#include <linux/slab.h>
10#include <linux/tee_drv.h>
11#include <linux/uuid.h>
12#include "optee_private.h"
13
14/*
15 * Get device UUIDs
16 *
17 * [out] memref[0] Array of device UUIDs
18 *
19 * Return codes:
20 * TEE_SUCCESS - Invoke command success
21 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
22 * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required
23 */
24#define PTA_CMD_GET_DEVICES 0x0
25
26static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
27{
28 if (ver->impl_id == TEE_IMPL_ID_OPTEE)
29 return 1;
30 else
31 return 0;
32}
33
34static int get_devices(struct tee_context *ctx, u32 session,
35 struct tee_shm *device_shm, u32 *shm_size)
36{
37 int ret = 0;
38 struct tee_ioctl_invoke_arg inv_arg;
39 struct tee_param param[4];
40
41 memset(&inv_arg, 0, sizeof(inv_arg));
42 memset(&param, 0, sizeof(param));
43
44 /* Invoke PTA_CMD_GET_DEVICES function */
45 inv_arg.func = PTA_CMD_GET_DEVICES;
46 inv_arg.session = session;
47 inv_arg.num_params = 4;
48
49 /* Fill invoke cmd params */
50 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
51 param[0].u.memref.shm = device_shm;
52 param[0].u.memref.size = *shm_size;
53 param[0].u.memref.shm_offs = 0;
54
55 ret = tee_client_invoke_func(ctx, &inv_arg, param);
56 if ((ret < 0) || ((inv_arg.ret != TEEC_SUCCESS) &&
57 (inv_arg.ret != TEEC_ERROR_SHORT_BUFFER))) {
58 pr_err("PTA_CMD_GET_DEVICES invoke function err: %x\n",
59 inv_arg.ret);
60 return -EINVAL;
61 }
62
63 *shm_size = param[0].u.memref.size;
64
65 return 0;
66}
67
68static int optee_register_device(const uuid_t *device_uuid, u32 device_id)
69{
70 struct tee_client_device *optee_device = NULL;
71 int rc;
72
73 optee_device = kzalloc(sizeof(*optee_device), GFP_KERNEL);
74 if (!optee_device)
75 return -ENOMEM;
76
77 optee_device->dev.bus = &tee_bus_type;
78 dev_set_name(&optee_device->dev, "optee-clnt%u", device_id);
79 uuid_copy(&optee_device->id.uuid, device_uuid);
80
81 rc = device_register(&optee_device->dev);
82 if (rc) {
83 pr_err("device registration failed, err: %d\n", rc);
84 kfree(optee_device);
85 }
86
87 return rc;
88}
89
90int optee_enumerate_devices(void)
91{
92 const uuid_t pta_uuid =
93 UUID_INIT(0x7011a688, 0xddde, 0x4053,
94 0xa5, 0xa9, 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8);
95 struct tee_ioctl_open_session_arg sess_arg;
96 struct tee_shm *device_shm = NULL;
97 const uuid_t *device_uuid = NULL;
98 struct tee_context *ctx = NULL;
99 u32 shm_size = 0, idx, num_devices = 0;
100 int rc;
101
102 memset(&sess_arg, 0, sizeof(sess_arg));
103
104 /* Open context with OP-TEE driver */
105 ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
106 if (IS_ERR(ctx))
107 return -ENODEV;
108
109 /* Open session with device enumeration pseudo TA */
110 memcpy(sess_arg.uuid, pta_uuid.b, TEE_IOCTL_UUID_LEN);
111 sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
112 sess_arg.num_params = 0;
113
114 rc = tee_client_open_session(ctx, &sess_arg, NULL);
115 if ((rc < 0) || (sess_arg.ret != TEEC_SUCCESS)) {
116 /* Device enumeration pseudo TA not found */
117 rc = 0;
118 goto out_ctx;
119 }
120
121 rc = get_devices(ctx, sess_arg.session, NULL, &shm_size);
122 if (rc < 0 || !shm_size)
123 goto out_sess;
124
125 device_shm = tee_shm_alloc(ctx, shm_size,
126 TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
127 if (IS_ERR(device_shm)) {
128 pr_err("tee_shm_alloc failed\n");
129 rc = PTR_ERR(device_shm);
130 goto out_sess;
131 }
132
133 rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size);
134 if (rc < 0)
135 goto out_shm;
136
137 device_uuid = tee_shm_get_va(device_shm, 0);
138 if (IS_ERR(device_uuid)) {
139 pr_err("tee_shm_get_va failed\n");
140 rc = PTR_ERR(device_uuid);
141 goto out_shm;
142 }
143
144 num_devices = shm_size / sizeof(uuid_t);
145
146 for (idx = 0; idx < num_devices; idx++) {
147 rc = optee_register_device(&device_uuid[idx], idx);
148 if (rc)
149 goto out_shm;
150 }
151
152out_shm:
153 tee_shm_free(device_shm);
154out_sess:
155 tee_client_close_session(ctx, sess_arg.session);
156out_ctx:
157 tee_client_close_context(ctx);
158
159 return rc;
160}
diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
index 30504901be80..795bc19ae17a 100644
--- a/drivers/tee/optee/optee_msg.h
+++ b/drivers/tee/optee/optee_msg.h
@@ -1,28 +1,6 @@
1/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
1/* 2/*
2 * Copyright (c) 2015-2016, Linaro Limited 3 * Copyright (c) 2015-2019, Linaro Limited
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */ 4 */
27#ifndef _OPTEE_MSG_H 5#ifndef _OPTEE_MSG_H
28#define _OPTEE_MSG_H 6#define _OPTEE_MSG_H
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index 35e79386c556..a5e84afd5013 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -28,6 +28,7 @@
28#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006 28#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006
29#define TEEC_ERROR_COMMUNICATION 0xFFFF000E 29#define TEEC_ERROR_COMMUNICATION 0xFFFF000E
30#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C 30#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
31#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
31 32
32#define TEEC_ORIGIN_COMMS 0x00000002 33#define TEEC_ORIGIN_COMMS 0x00000002
33 34
@@ -181,6 +182,8 @@ void optee_free_pages_list(void *array, size_t num_entries);
181void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages, 182void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
182 size_t page_offset); 183 size_t page_offset);
183 184
185int optee_enumerate_devices(void);
186
184/* 187/*
185 * Small helpers 188 * Small helpers
186 */ 189 */
diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h
index bbf0cf028c16..c72122d9c997 100644
--- a/drivers/tee/optee/optee_smc.h
+++ b/drivers/tee/optee/optee_smc.h
@@ -1,28 +1,6 @@
1/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
1/* 2/*
2 * Copyright (c) 2015-2016, Linaro Limited 3 * Copyright (c) 2015-2019, Linaro Limited
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */ 4 */
27#ifndef OPTEE_SMC_H 5#ifndef OPTEE_SMC_H
28#define OPTEE_SMC_H 6#define OPTEE_SMC_H
diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
index 43626e15703a..92f56b8645e3 100644
--- a/drivers/tee/optee/supp.c
+++ b/drivers/tee/optee/supp.c
@@ -88,10 +88,18 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
88{ 88{
89 struct optee *optee = tee_get_drvdata(ctx->teedev); 89 struct optee *optee = tee_get_drvdata(ctx->teedev);
90 struct optee_supp *supp = &optee->supp; 90 struct optee_supp *supp = &optee->supp;
91 struct optee_supp_req *req = kzalloc(sizeof(*req), GFP_KERNEL); 91 struct optee_supp_req *req;
92 bool interruptable; 92 bool interruptable;
93 u32 ret; 93 u32 ret;
94 94
95 /*
96 * Return in case there is no supplicant available and
97 * non-blocking request.
98 */
99 if (!supp->ctx && ctx->supp_nowait)
100 return TEEC_ERROR_COMMUNICATION;
101
102 req = kzalloc(sizeof(*req), GFP_KERNEL);
95 if (!req) 103 if (!req)
96 return TEEC_ERROR_OUT_OF_MEMORY; 104 return TEEC_ERROR_OUT_OF_MEMORY;
97 105
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index 7b2bb4c50058..17c64fccbb10 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -15,7 +15,6 @@
15#define pr_fmt(fmt) "%s: " fmt, __func__ 15#define pr_fmt(fmt) "%s: " fmt, __func__
16 16
17#include <linux/cdev.h> 17#include <linux/cdev.h>
18#include <linux/device.h>
19#include <linux/fs.h> 18#include <linux/fs.h>
20#include <linux/idr.h> 19#include <linux/idr.h>
21#include <linux/module.h> 20#include <linux/module.h>
@@ -106,6 +105,11 @@ static int tee_open(struct inode *inode, struct file *filp)
106 if (IS_ERR(ctx)) 105 if (IS_ERR(ctx))
107 return PTR_ERR(ctx); 106 return PTR_ERR(ctx);
108 107
108 /*
109 * Default user-space behaviour is to wait for tee-supplicant
110 * if not present for any requests in this context.
111 */
112 ctx->supp_nowait = false;
109 filp->private_data = ctx; 113 filp->private_data = ctx;
110 return 0; 114 return 0;
111} 115}
@@ -982,6 +986,16 @@ tee_client_open_context(struct tee_context *start,
982 } while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM); 986 } while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM);
983 987
984 put_device(put_dev); 988 put_device(put_dev);
989 /*
990 * Default behaviour for in kernel client is to not wait for
991 * tee-supplicant if not present for any requests in this context.
992 * Also this flag could be configured again before call to
993 * tee_client_open_session() if any in kernel client requires
994 * different behaviour.
995 */
996 if (!IS_ERR(ctx))
997 ctx->supp_nowait = true;
998
985 return ctx; 999 return ctx;
986} 1000}
987EXPORT_SYMBOL_GPL(tee_client_open_context); 1001EXPORT_SYMBOL_GPL(tee_client_open_context);
@@ -1027,6 +1041,48 @@ int tee_client_invoke_func(struct tee_context *ctx,
1027} 1041}
1028EXPORT_SYMBOL_GPL(tee_client_invoke_func); 1042EXPORT_SYMBOL_GPL(tee_client_invoke_func);
1029 1043
1044int tee_client_cancel_req(struct tee_context *ctx,
1045 struct tee_ioctl_cancel_arg *arg)
1046{
1047 if (!ctx->teedev->desc->ops->cancel_req)
1048 return -EINVAL;
1049 return ctx->teedev->desc->ops->cancel_req(ctx, arg->cancel_id,
1050 arg->session);
1051}
1052
1053static int tee_client_device_match(struct device *dev,
1054 struct device_driver *drv)
1055{
1056 const struct tee_client_device_id *id_table;
1057 struct tee_client_device *tee_device;
1058
1059 id_table = to_tee_client_driver(drv)->id_table;
1060 tee_device = to_tee_client_device(dev);
1061
1062 while (!uuid_is_null(&id_table->uuid)) {
1063 if (uuid_equal(&tee_device->id.uuid, &id_table->uuid))
1064 return 1;
1065 id_table++;
1066 }
1067
1068 return 0;
1069}
1070
1071static int tee_client_device_uevent(struct device *dev,
1072 struct kobj_uevent_env *env)
1073{
1074 uuid_t *dev_id = &to_tee_client_device(dev)->id.uuid;
1075
1076 return add_uevent_var(env, "MODALIAS=tee:%pUb", dev_id);
1077}
1078
1079struct bus_type tee_bus_type = {
1080 .name = "tee",
1081 .match = tee_client_device_match,
1082 .uevent = tee_client_device_uevent,
1083};
1084EXPORT_SYMBOL_GPL(tee_bus_type);
1085
1030static int __init tee_init(void) 1086static int __init tee_init(void)
1031{ 1087{
1032 int rc; 1088 int rc;
@@ -1040,18 +1096,32 @@ static int __init tee_init(void)
1040 rc = alloc_chrdev_region(&tee_devt, 0, TEE_NUM_DEVICES, "tee"); 1096 rc = alloc_chrdev_region(&tee_devt, 0, TEE_NUM_DEVICES, "tee");
1041 if (rc) { 1097 if (rc) {
1042 pr_err("failed to allocate char dev region\n"); 1098 pr_err("failed to allocate char dev region\n");
1043 class_destroy(tee_class); 1099 goto out_unreg_class;
1044 tee_class = NULL; 1100 }
1101
1102 rc = bus_register(&tee_bus_type);
1103 if (rc) {
1104 pr_err("failed to register tee bus\n");
1105 goto out_unreg_chrdev;
1045 } 1106 }
1046 1107
1108 return 0;
1109
1110out_unreg_chrdev:
1111 unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
1112out_unreg_class:
1113 class_destroy(tee_class);
1114 tee_class = NULL;
1115
1047 return rc; 1116 return rc;
1048} 1117}
1049 1118
1050static void __exit tee_exit(void) 1119static void __exit tee_exit(void)
1051{ 1120{
1121 bus_unregister(&tee_bus_type);
1122 unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
1052 class_destroy(tee_class); 1123 class_destroy(tee_class);
1053 tee_class = NULL; 1124 tee_class = NULL;
1054 unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
1055} 1125}
1056 1126
1057subsys_initcall(tee_init); 1127subsys_initcall(tee_init);
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
index ed05514cc2dc..1834524ae373 100644
--- a/drivers/watchdog/bcm2835_wdt.c
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -12,6 +12,7 @@
12 12
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/types.h> 14#include <linux/types.h>
15#include <linux/mfd/bcm2835-pm.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/io.h> 17#include <linux/io.h>
17#include <linux/watchdog.h> 18#include <linux/watchdog.h>
@@ -47,6 +48,8 @@ struct bcm2835_wdt {
47 spinlock_t lock; 48 spinlock_t lock;
48}; 49};
49 50
51static struct bcm2835_wdt *bcm2835_power_off_wdt;
52
50static unsigned int heartbeat; 53static unsigned int heartbeat;
51static bool nowayout = WATCHDOG_NOWAYOUT; 54static bool nowayout = WATCHDOG_NOWAYOUT;
52 55
@@ -148,10 +151,7 @@ static struct watchdog_device bcm2835_wdt_wdd = {
148 */ 151 */
149static void bcm2835_power_off(void) 152static void bcm2835_power_off(void)
150{ 153{
151 struct device_node *np = 154 struct bcm2835_wdt *wdt = bcm2835_power_off_wdt;
152 of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt");
153 struct platform_device *pdev = of_find_device_by_node(np);
154 struct bcm2835_wdt *wdt = platform_get_drvdata(pdev);
155 u32 val; 155 u32 val;
156 156
157 /* 157 /*
@@ -169,7 +169,7 @@ static void bcm2835_power_off(void)
169 169
170static int bcm2835_wdt_probe(struct platform_device *pdev) 170static int bcm2835_wdt_probe(struct platform_device *pdev)
171{ 171{
172 struct resource *res; 172 struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
173 struct device *dev = &pdev->dev; 173 struct device *dev = &pdev->dev;
174 struct bcm2835_wdt *wdt; 174 struct bcm2835_wdt *wdt;
175 int err; 175 int err;
@@ -181,10 +181,7 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
181 181
182 spin_lock_init(&wdt->lock); 182 spin_lock_init(&wdt->lock);
183 183
184 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 184 wdt->base = pm->base;
185 wdt->base = devm_ioremap_resource(dev, res);
186 if (IS_ERR(wdt->base))
187 return PTR_ERR(wdt->base);
188 185
189 watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt); 186 watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt);
190 watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev); 187 watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
@@ -211,8 +208,10 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
211 return err; 208 return err;
212 } 209 }
213 210
214 if (pm_power_off == NULL) 211 if (pm_power_off == NULL) {
215 pm_power_off = bcm2835_power_off; 212 pm_power_off = bcm2835_power_off;
213 bcm2835_power_off_wdt = wdt;
214 }
216 215
217 dev_info(dev, "Broadcom BCM2835 watchdog timer"); 216 dev_info(dev, "Broadcom BCM2835 watchdog timer");
218 return 0; 217 return 0;
@@ -226,18 +225,11 @@ static int bcm2835_wdt_remove(struct platform_device *pdev)
226 return 0; 225 return 0;
227} 226}
228 227
229static const struct of_device_id bcm2835_wdt_of_match[] = {
230 { .compatible = "brcm,bcm2835-pm-wdt", },
231 {},
232};
233MODULE_DEVICE_TABLE(of, bcm2835_wdt_of_match);
234
235static struct platform_driver bcm2835_wdt_driver = { 228static struct platform_driver bcm2835_wdt_driver = {
236 .probe = bcm2835_wdt_probe, 229 .probe = bcm2835_wdt_probe,
237 .remove = bcm2835_wdt_remove, 230 .remove = bcm2835_wdt_remove,
238 .driver = { 231 .driver = {
239 .name = "bcm2835-wdt", 232 .name = "bcm2835-wdt",
240 .of_match_table = bcm2835_wdt_of_match,
241 }, 233 },
242}; 234};
243module_platform_driver(bcm2835_wdt_driver); 235module_platform_driver(bcm2835_wdt_driver);
diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
new file mode 100644
index 000000000000..87d9c6611682
--- /dev/null
+++ b/include/dt-bindings/power/qcom-rpmpd.h
@@ -0,0 +1,39 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/* Copyright (c) 2018, The Linux Foundation. All rights reserved. */
3
4#ifndef _DT_BINDINGS_POWER_QCOM_RPMPD_H
5#define _DT_BINDINGS_POWER_QCOM_RPMPD_H
6
7/* SDM845 Power Domain Indexes */
8#define SDM845_EBI 0
9#define SDM845_MX 1
10#define SDM845_MX_AO 2
11#define SDM845_CX 3
12#define SDM845_CX_AO 4
13#define SDM845_LMX 5
14#define SDM845_LCX 6
15#define SDM845_GFX 7
16#define SDM845_MSS 8
17
18/* SDM845 Power Domain performance levels */
19#define RPMH_REGULATOR_LEVEL_RETENTION 16
20#define RPMH_REGULATOR_LEVEL_MIN_SVS 48
21#define RPMH_REGULATOR_LEVEL_LOW_SVS 64
22#define RPMH_REGULATOR_LEVEL_SVS 128
23#define RPMH_REGULATOR_LEVEL_SVS_L1 192
24#define RPMH_REGULATOR_LEVEL_NOM 256
25#define RPMH_REGULATOR_LEVEL_NOM_L1 320
26#define RPMH_REGULATOR_LEVEL_NOM_L2 336
27#define RPMH_REGULATOR_LEVEL_TURBO 384
28#define RPMH_REGULATOR_LEVEL_TURBO_L1 416
29
30/* MSM8996 Power Domain Indexes */
31#define MSM8996_VDDCX 0
32#define MSM8996_VDDCX_AO 1
33#define MSM8996_VDDCX_VFC 2
34#define MSM8996_VDDMX 3
35#define MSM8996_VDDMX_AO 4
36#define MSM8996_VDDSSCX 5
37#define MSM8996_VDDSSCX_VFC 6
38
39#endif
diff --git a/include/dt-bindings/power/xlnx-zynqmp-power.h b/include/dt-bindings/power/xlnx-zynqmp-power.h
new file mode 100644
index 000000000000..0d9a412fd5e0
--- /dev/null
+++ b/include/dt-bindings/power/xlnx-zynqmp-power.h
@@ -0,0 +1,39 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2018 Xilinx, Inc.
4 */
5
6#ifndef _DT_BINDINGS_ZYNQMP_POWER_H
7#define _DT_BINDINGS_ZYNQMP_POWER_H
8
9#define PD_USB_0 22
10#define PD_USB_1 23
11#define PD_TTC_0 24
12#define PD_TTC_1 25
13#define PD_TTC_2 26
14#define PD_TTC_3 27
15#define PD_SATA 28
16#define PD_ETH_0 29
17#define PD_ETH_1 30
18#define PD_ETH_2 31
19#define PD_ETH_3 32
20#define PD_UART_0 33
21#define PD_UART_1 34
22#define PD_SPI_0 35
23#define PD_SPI_1 36
24#define PD_I2C_0 37
25#define PD_I2C_1 38
26#define PD_SD_0 39
27#define PD_SD_1 40
28#define PD_DP 41
29#define PD_GDMA 42
30#define PD_ADMA 43
31#define PD_NAND 44
32#define PD_QSPI 45
33#define PD_GPIO 46
34#define PD_CAN_0 47
35#define PD_CAN_1 48
36#define PD_GPU 58
37#define PD_PCIE 59
38
39#endif
diff --git a/include/dt-bindings/reset/amlogic,meson-g12a-reset.h b/include/dt-bindings/reset/amlogic,meson-g12a-reset.h
new file mode 100644
index 000000000000..8063e8314eef
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-g12a-reset.h
@@ -0,0 +1,134 @@
1/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
2/*
3 * Copyright (c) 2019 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 *
6 */
7
8#ifndef _DT_BINDINGS_AMLOGIC_MESON_G12A_RESET_H
9#define _DT_BINDINGS_AMLOGIC_MESON_G12A_RESET_H
10
11/* RESET0 */
12#define RESET_HIU 0
13/* 1 */
14#define RESET_DOS 2
15/* 3-4 */
16#define RESET_VIU 5
17#define RESET_AFIFO 6
18#define RESET_VID_PLL_DIV 7
19/* 8-9 */
20#define RESET_VENC 10
21#define RESET_ASSIST 11
22#define RESET_PCIE_CTRL_A 12
23#define RESET_VCBUS 13
24#define RESET_PCIE_PHY 14
25#define RESET_PCIE_APB 15
26#define RESET_GIC 16
27#define RESET_CAPB3_DECODE 17
28/* 18 */
29#define RESET_HDMITX_CAPB3 19
30#define RESET_DVALIN_CAPB3 20
31#define RESET_DOS_CAPB3 21
32/* 22 */
33#define RESET_CBUS_CAPB3 23
34#define RESET_AHB_CNTL 24
35#define RESET_AHB_DATA 25
36#define RESET_VCBUS_CLK81 26
37/* 27-31 */
38/* RESET1 */
39/* 32 */
40#define RESET_DEMUX 33
41#define RESET_USB 34
42#define RESET_DDR 35
43/* 36 */
44#define RESET_BT656 37
45#define RESET_AHB_SRAM 38
46/* 39 */
47#define RESET_PARSER 40
48/* 41 */
49#define RESET_ISA 42
50#define RESET_ETHERNET 43
51#define RESET_SD_EMMC_A 44
52#define RESET_SD_EMMC_B 45
53#define RESET_SD_EMMC_C 46
54/* 47-60 */
55#define RESET_AUDIO_CODEC 61
56/* 62-63 */
57/* RESET2 */
58/* 64 */
59#define RESET_AUDIO 65
60#define RESET_HDMITX_PHY 66
61/* 67 */
62#define RESET_MIPI_DSI_HOST 68
63#define RESET_ALOCKER 69
64#define RESET_GE2D 70
65#define RESET_PARSER_REG 71
66#define RESET_PARSER_FETCH 72
67#define RESET_CTL 73
68#define RESET_PARSER_TOP 74
69/* 75-77 */
70#define RESET_DVALIN 78
71#define RESET_HDMITX 79
72/* 80-95 */
73/* RESET3 */
74/* 96-95 */
75#define RESET_DEMUX_TOP 105
76#define RESET_DEMUX_DES_PL 106
77#define RESET_DEMUX_S2P_0 107
78#define RESET_DEMUX_S2P_1 108
79#define RESET_DEMUX_0 109
80#define RESET_DEMUX_1 110
81#define RESET_DEMUX_2 111
82/* 112-127 */
83/* RESET4 */
84/* 128-129 */
85#define RESET_MIPI_DSI_PHY 130
86/* 131-132 */
87#define RESET_RDMA 133
88#define RESET_VENCI 134
89#define RESET_VENCP 135
90/* 136 */
91#define RESET_VDAC 137
92/* 138-139 */
93#define RESET_VDI6 140
94#define RESET_VENCL 141
95#define RESET_I2C_M1 142
96#define RESET_I2C_M2 143
97/* 144-159 */
98/* RESET5 */
99/* 160-191 */
100/* RESET6 */
101#define RESET_GEN 192
102#define RESET_SPICC0 193
103#define RESET_SC 194
104#define RESET_SANA_3 195
105#define RESET_I2C_M0 196
106#define RESET_TS_PLL 197
107#define RESET_SPICC1 198
108#define RESET_STREAM 199
109#define RESET_TS_CPU 200
110#define RESET_UART0 201
111#define RESET_UART1_2 202
112#define RESET_ASYNC0 203
113#define RESET_ASYNC1 204
114#define RESET_SPIFC0 205
115#define RESET_I2C_M3 206
116/* 207-223 */
117/* RESET7 */
118#define RESET_USB_DDR_0 224
119#define RESET_USB_DDR_1 225
120#define RESET_USB_DDR_2 226
121#define RESET_USB_DDR_3 227
122#define RESET_TS_GPU 228
123#define RESET_DEVICE_MMC_ARB 229
124#define RESET_DVALIN_DMC_PIPL 230
125#define RESET_VID_LOCK 231
126#define RESET_NIC_DMC_PIPL 232
127#define RESET_DMC_VPU_PIPL 233
128#define RESET_GE2D_DMC_PIPL 234
129#define RESET_HCODEC_DMC_PIPL 235
130#define RESET_WAVE420_DMC_PIPL 236
131#define RESET_HEVCF_DMC_PIPL 237
132/* 238-255 */
133
134#endif
diff --git a/include/dt-bindings/reset/imx8mq-reset.h b/include/dt-bindings/reset/imx8mq-reset.h
new file mode 100644
index 000000000000..57c592498aa0
--- /dev/null
+++ b/include/dt-bindings/reset/imx8mq-reset.h
@@ -0,0 +1,64 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2018 Zodiac Inflight Innovations
4 *
5 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
6 */
7
8#ifndef DT_BINDING_RESET_IMX8MQ_H
9#define DT_BINDING_RESET_IMX8MQ_H
10
11#define IMX8MQ_RESET_A53_CORE_POR_RESET0 0
12#define IMX8MQ_RESET_A53_CORE_POR_RESET1 1
13#define IMX8MQ_RESET_A53_CORE_POR_RESET2 2
14#define IMX8MQ_RESET_A53_CORE_POR_RESET3 3
15#define IMX8MQ_RESET_A53_CORE_RESET0 4
16#define IMX8MQ_RESET_A53_CORE_RESET1 5
17#define IMX8MQ_RESET_A53_CORE_RESET2 6
18#define IMX8MQ_RESET_A53_CORE_RESET3 7
19#define IMX8MQ_RESET_A53_DBG_RESET0 8
20#define IMX8MQ_RESET_A53_DBG_RESET1 9
21#define IMX8MQ_RESET_A53_DBG_RESET2 10
22#define IMX8MQ_RESET_A53_DBG_RESET3 11
23#define IMX8MQ_RESET_A53_ETM_RESET0 12
24#define IMX8MQ_RESET_A53_ETM_RESET1 13
25#define IMX8MQ_RESET_A53_ETM_RESET2 14
26#define IMX8MQ_RESET_A53_ETM_RESET3 15
27#define IMX8MQ_RESET_A53_SOC_DBG_RESET 16
28#define IMX8MQ_RESET_A53_L2RESET 17
29#define IMX8MQ_RESET_SW_NON_SCLR_M4C_RST 18
30#define IMX8MQ_RESET_OTG1_PHY_RESET 19
31#define IMX8MQ_RESET_OTG2_PHY_RESET 20
32#define IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N 21
33#define IMX8MQ_RESET_MIPI_DSI_RESET_N 22
34#define IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N 23
35#define IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N 24
36#define IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N 25
37#define IMX8MQ_RESET_PCIEPHY 26
38#define IMX8MQ_RESET_PCIEPHY_PERST 27
39#define IMX8MQ_RESET_PCIE_CTRL_APPS_EN 28
40#define IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF 29
41#define IMX8MQ_RESET_HDMI_PHY_APB_RESET 30
42#define IMX8MQ_RESET_DISP_RESET 31
43#define IMX8MQ_RESET_GPU_RESET 32
44#define IMX8MQ_RESET_VPU_RESET 33
45#define IMX8MQ_RESET_PCIEPHY2 34
46#define IMX8MQ_RESET_PCIEPHY2_PERST 35
47#define IMX8MQ_RESET_PCIE2_CTRL_APPS_EN 36
48#define IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF 37
49#define IMX8MQ_RESET_MIPI_CSI1_CORE_RESET 38
50#define IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET 39
51#define IMX8MQ_RESET_MIPI_CSI1_ESC_RESET 40
52#define IMX8MQ_RESET_MIPI_CSI2_CORE_RESET 41
53#define IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET 42
54#define IMX8MQ_RESET_MIPI_CSI2_ESC_RESET 43
55#define IMX8MQ_RESET_DDRC1_PRST 44
56#define IMX8MQ_RESET_DDRC1_CORE_RESET 45
57#define IMX8MQ_RESET_DDRC1_PHY_RESET 46
58#define IMX8MQ_RESET_DDRC2_PRST 47
59#define IMX8MQ_RESET_DDRC2_CORE_RESET 48
60#define IMX8MQ_RESET_DDRC2_PHY_RESET 49
61
62#define IMX8MQ_RESET_NUM 50
63
64#endif
diff --git a/include/dt-bindings/reset/xlnx-zynqmp-resets.h b/include/dt-bindings/reset/xlnx-zynqmp-resets.h
new file mode 100644
index 000000000000..d44525b9f8db
--- /dev/null
+++ b/include/dt-bindings/reset/xlnx-zynqmp-resets.h
@@ -0,0 +1,130 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2018 Xilinx, Inc.
4 */
5
6#ifndef _DT_BINDINGS_ZYNQMP_RESETS_H
7#define _DT_BINDINGS_ZYNQMP_RESETS_H
8
9#define ZYNQMP_RESET_PCIE_CFG 0
10#define ZYNQMP_RESET_PCIE_BRIDGE 1
11#define ZYNQMP_RESET_PCIE_CTRL 2
12#define ZYNQMP_RESET_DP 3
13#define ZYNQMP_RESET_SWDT_CRF 4
14#define ZYNQMP_RESET_AFI_FM5 5
15#define ZYNQMP_RESET_AFI_FM4 6
16#define ZYNQMP_RESET_AFI_FM3 7
17#define ZYNQMP_RESET_AFI_FM2 8
18#define ZYNQMP_RESET_AFI_FM1 9
19#define ZYNQMP_RESET_AFI_FM0 10
20#define ZYNQMP_RESET_GDMA 11
21#define ZYNQMP_RESET_GPU_PP1 12
22#define ZYNQMP_RESET_GPU_PP0 13
23#define ZYNQMP_RESET_GPU 14
24#define ZYNQMP_RESET_GT 15
25#define ZYNQMP_RESET_SATA 16
26#define ZYNQMP_RESET_ACPU3_PWRON 17
27#define ZYNQMP_RESET_ACPU2_PWRON 18
28#define ZYNQMP_RESET_ACPU1_PWRON 19
29#define ZYNQMP_RESET_ACPU0_PWRON 20
30#define ZYNQMP_RESET_APU_L2 21
31#define ZYNQMP_RESET_ACPU3 22
32#define ZYNQMP_RESET_ACPU2 23
33#define ZYNQMP_RESET_ACPU1 24
34#define ZYNQMP_RESET_ACPU0 25
35#define ZYNQMP_RESET_DDR 26
36#define ZYNQMP_RESET_APM_FPD 27
37#define ZYNQMP_RESET_SOFT 28
38#define ZYNQMP_RESET_GEM0 29
39#define ZYNQMP_RESET_GEM1 30
40#define ZYNQMP_RESET_GEM2 31
41#define ZYNQMP_RESET_GEM3 32
42#define ZYNQMP_RESET_QSPI 33
43#define ZYNQMP_RESET_UART0 34
44#define ZYNQMP_RESET_UART1 35
45#define ZYNQMP_RESET_SPI0 36
46#define ZYNQMP_RESET_SPI1 37
47#define ZYNQMP_RESET_SDIO0 38
48#define ZYNQMP_RESET_SDIO1 39
49#define ZYNQMP_RESET_CAN0 40
50#define ZYNQMP_RESET_CAN1 41
51#define ZYNQMP_RESET_I2C0 42
52#define ZYNQMP_RESET_I2C1 43
53#define ZYNQMP_RESET_TTC0 44
54#define ZYNQMP_RESET_TTC1 45
55#define ZYNQMP_RESET_TTC2 46
56#define ZYNQMP_RESET_TTC3 47
57#define ZYNQMP_RESET_SWDT_CRL 48
58#define ZYNQMP_RESET_NAND 49
59#define ZYNQMP_RESET_ADMA 50
60#define ZYNQMP_RESET_GPIO 51
61#define ZYNQMP_RESET_IOU_CC 52
62#define ZYNQMP_RESET_TIMESTAMP 53
63#define ZYNQMP_RESET_RPU_R50 54
64#define ZYNQMP_RESET_RPU_R51 55
65#define ZYNQMP_RESET_RPU_AMBA 56
66#define ZYNQMP_RESET_OCM 57
67#define ZYNQMP_RESET_RPU_PGE 58
68#define ZYNQMP_RESET_USB0_CORERESET 59
69#define ZYNQMP_RESET_USB1_CORERESET 60
70#define ZYNQMP_RESET_USB0_HIBERRESET 61
71#define ZYNQMP_RESET_USB1_HIBERRESET 62
72#define ZYNQMP_RESET_USB0_APB 63
73#define ZYNQMP_RESET_USB1_APB 64
74#define ZYNQMP_RESET_IPI 65
75#define ZYNQMP_RESET_APM_LPD 66
76#define ZYNQMP_RESET_RTC 67
77#define ZYNQMP_RESET_SYSMON 68
78#define ZYNQMP_RESET_AFI_FM6 69
79#define ZYNQMP_RESET_LPD_SWDT 70
80#define ZYNQMP_RESET_FPD 71
81#define ZYNQMP_RESET_RPU_DBG1 72
82#define ZYNQMP_RESET_RPU_DBG0 73
83#define ZYNQMP_RESET_DBG_LPD 74
84#define ZYNQMP_RESET_DBG_FPD 75
85#define ZYNQMP_RESET_APLL 76
86#define ZYNQMP_RESET_DPLL 77
87#define ZYNQMP_RESET_VPLL 78
88#define ZYNQMP_RESET_IOPLL 79
89#define ZYNQMP_RESET_RPLL 80
90#define ZYNQMP_RESET_GPO3_PL_0 81
91#define ZYNQMP_RESET_GPO3_PL_1 82
92#define ZYNQMP_RESET_GPO3_PL_2 83
93#define ZYNQMP_RESET_GPO3_PL_3 84
94#define ZYNQMP_RESET_GPO3_PL_4 85
95#define ZYNQMP_RESET_GPO3_PL_5 86
96#define ZYNQMP_RESET_GPO3_PL_6 87
97#define ZYNQMP_RESET_GPO3_PL_7 88
98#define ZYNQMP_RESET_GPO3_PL_8 89
99#define ZYNQMP_RESET_GPO3_PL_9 90
100#define ZYNQMP_RESET_GPO3_PL_10 91
101#define ZYNQMP_RESET_GPO3_PL_11 92
102#define ZYNQMP_RESET_GPO3_PL_12 93
103#define ZYNQMP_RESET_GPO3_PL_13 94
104#define ZYNQMP_RESET_GPO3_PL_14 95
105#define ZYNQMP_RESET_GPO3_PL_15 96
106#define ZYNQMP_RESET_GPO3_PL_16 97
107#define ZYNQMP_RESET_GPO3_PL_17 98
108#define ZYNQMP_RESET_GPO3_PL_18 99
109#define ZYNQMP_RESET_GPO3_PL_19 100
110#define ZYNQMP_RESET_GPO3_PL_20 101
111#define ZYNQMP_RESET_GPO3_PL_21 102
112#define ZYNQMP_RESET_GPO3_PL_22 103
113#define ZYNQMP_RESET_GPO3_PL_23 104
114#define ZYNQMP_RESET_GPO3_PL_24 105
115#define ZYNQMP_RESET_GPO3_PL_25 106
116#define ZYNQMP_RESET_GPO3_PL_26 107
117#define ZYNQMP_RESET_GPO3_PL_27 108
118#define ZYNQMP_RESET_GPO3_PL_28 109
119#define ZYNQMP_RESET_GPO3_PL_29 110
120#define ZYNQMP_RESET_GPO3_PL_30 111
121#define ZYNQMP_RESET_GPO3_PL_31 112
122#define ZYNQMP_RESET_RPU_LS 113
123#define ZYNQMP_RESET_PS_ONLY 114
124#define ZYNQMP_RESET_PL 115
125#define ZYNQMP_RESET_PS_PL0 116
126#define ZYNQMP_RESET_PS_PL1 117
127#define ZYNQMP_RESET_PS_PL2 118
128#define ZYNQMP_RESET_PS_PL3 119
129
130#endif
diff --git a/include/dt-bindings/soc/bcm2835-pm.h b/include/dt-bindings/soc/bcm2835-pm.h
new file mode 100644
index 000000000000..153d75b8d99f
--- /dev/null
+++ b/include/dt-bindings/soc/bcm2835-pm.h
@@ -0,0 +1,28 @@
1/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
2
3#ifndef _DT_BINDINGS_ARM_BCM2835_PM_H
4#define _DT_BINDINGS_ARM_BCM2835_PM_H
5
6#define BCM2835_POWER_DOMAIN_GRAFX 0
7#define BCM2835_POWER_DOMAIN_GRAFX_V3D 1
8#define BCM2835_POWER_DOMAIN_IMAGE 2
9#define BCM2835_POWER_DOMAIN_IMAGE_PERI 3
10#define BCM2835_POWER_DOMAIN_IMAGE_ISP 4
11#define BCM2835_POWER_DOMAIN_IMAGE_H264 5
12#define BCM2835_POWER_DOMAIN_USB 6
13#define BCM2835_POWER_DOMAIN_DSI0 7
14#define BCM2835_POWER_DOMAIN_DSI1 8
15#define BCM2835_POWER_DOMAIN_CAM0 9
16#define BCM2835_POWER_DOMAIN_CAM1 10
17#define BCM2835_POWER_DOMAIN_CCP2TX 11
18#define BCM2835_POWER_DOMAIN_HDMI 12
19
20#define BCM2835_POWER_DOMAIN_COUNT 13
21
22#define BCM2835_RESET_V3D 0
23#define BCM2835_RESET_ISP 1
24#define BCM2835_RESET_H264 2
25
26#define BCM2835_RESET_COUNT 3
27
28#endif /* _DT_BINDINGS_ARM_BCM2835_PM_H */
diff --git a/include/linux/firmware/imx/svc/misc.h b/include/linux/firmware/imx/svc/misc.h
index e21c49aba92f..031dd4d3c766 100644
--- a/include/linux/firmware/imx/svc/misc.h
+++ b/include/linux/firmware/imx/svc/misc.h
@@ -52,4 +52,7 @@ int imx_sc_misc_set_control(struct imx_sc_ipc *ipc, u32 resource,
52int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource, 52int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource,
53 u8 ctrl, u32 *val); 53 u8 ctrl, u32 *val);
54 54
55int imx_sc_pm_cpu_start(struct imx_sc_ipc *ipc, u32 resource,
56 bool enable, u64 phys_addr);
57
55#endif /* _SC_MISC_API_H */ 58#endif /* _SC_MISC_API_H */
diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h
index 3c3c28eff56a..642dab10f65d 100644
--- a/include/linux/firmware/xlnx-zynqmp.h
+++ b/include/linux/firmware/xlnx-zynqmp.h
@@ -28,12 +28,35 @@
28/* SMC SIP service Call Function Identifier Prefix */ 28/* SMC SIP service Call Function Identifier Prefix */
29#define PM_SIP_SVC 0xC2000000 29#define PM_SIP_SVC 0xC2000000
30#define PM_GET_TRUSTZONE_VERSION 0xa03 30#define PM_GET_TRUSTZONE_VERSION 0xa03
31#define PM_SET_SUSPEND_MODE 0xa02
32#define GET_CALLBACK_DATA 0xa01
31 33
32/* Number of 32bits values in payload */ 34/* Number of 32bits values in payload */
33#define PAYLOAD_ARG_CNT 4U 35#define PAYLOAD_ARG_CNT 4U
34 36
37/* Number of arguments for a callback */
38#define CB_ARG_CNT 4
39
40/* Payload size (consists of callback API ID + arguments) */
41#define CB_PAYLOAD_SIZE (CB_ARG_CNT + 1)
42
43#define ZYNQMP_PM_MAX_QOS 100U
44
45/* Node capabilities */
46#define ZYNQMP_PM_CAPABILITY_ACCESS 0x1U
47#define ZYNQMP_PM_CAPABILITY_CONTEXT 0x2U
48#define ZYNQMP_PM_CAPABILITY_WAKEUP 0x4U
49#define ZYNQMP_PM_CAPABILITY_POWER 0x8U
50
35enum pm_api_id { 51enum pm_api_id {
36 PM_GET_API_VERSION = 1, 52 PM_GET_API_VERSION = 1,
53 PM_REQUEST_NODE = 13,
54 PM_RELEASE_NODE,
55 PM_SET_REQUIREMENT,
56 PM_RESET_ASSERT = 17,
57 PM_RESET_GET_STATUS,
58 PM_PM_INIT_FINALIZE = 21,
59 PM_GET_CHIPID = 24,
37 PM_IOCTL = 34, 60 PM_IOCTL = 34,
38 PM_QUERY_DATA, 61 PM_QUERY_DATA,
39 PM_CLOCK_ENABLE, 62 PM_CLOCK_ENABLE,
@@ -75,6 +98,149 @@ enum pm_query_id {
75 PM_QID_CLOCK_GET_NUM_CLOCKS = 12, 98 PM_QID_CLOCK_GET_NUM_CLOCKS = 12,
76}; 99};
77 100
101enum zynqmp_pm_reset_action {
102 PM_RESET_ACTION_RELEASE,
103 PM_RESET_ACTION_ASSERT,
104 PM_RESET_ACTION_PULSE,
105};
106
107enum zynqmp_pm_reset {
108 ZYNQMP_PM_RESET_START = 1000,
109 ZYNQMP_PM_RESET_PCIE_CFG = ZYNQMP_PM_RESET_START,
110 ZYNQMP_PM_RESET_PCIE_BRIDGE,
111 ZYNQMP_PM_RESET_PCIE_CTRL,
112 ZYNQMP_PM_RESET_DP,
113 ZYNQMP_PM_RESET_SWDT_CRF,
114 ZYNQMP_PM_RESET_AFI_FM5,
115 ZYNQMP_PM_RESET_AFI_FM4,
116 ZYNQMP_PM_RESET_AFI_FM3,
117 ZYNQMP_PM_RESET_AFI_FM2,
118 ZYNQMP_PM_RESET_AFI_FM1,
119 ZYNQMP_PM_RESET_AFI_FM0,
120 ZYNQMP_PM_RESET_GDMA,
121 ZYNQMP_PM_RESET_GPU_PP1,
122 ZYNQMP_PM_RESET_GPU_PP0,
123 ZYNQMP_PM_RESET_GPU,
124 ZYNQMP_PM_RESET_GT,
125 ZYNQMP_PM_RESET_SATA,
126 ZYNQMP_PM_RESET_ACPU3_PWRON,
127 ZYNQMP_PM_RESET_ACPU2_PWRON,
128 ZYNQMP_PM_RESET_ACPU1_PWRON,
129 ZYNQMP_PM_RESET_ACPU0_PWRON,
130 ZYNQMP_PM_RESET_APU_L2,
131 ZYNQMP_PM_RESET_ACPU3,
132 ZYNQMP_PM_RESET_ACPU2,
133 ZYNQMP_PM_RESET_ACPU1,
134 ZYNQMP_PM_RESET_ACPU0,
135 ZYNQMP_PM_RESET_DDR,
136 ZYNQMP_PM_RESET_APM_FPD,
137 ZYNQMP_PM_RESET_SOFT,
138 ZYNQMP_PM_RESET_GEM0,
139 ZYNQMP_PM_RESET_GEM1,
140 ZYNQMP_PM_RESET_GEM2,
141 ZYNQMP_PM_RESET_GEM3,
142 ZYNQMP_PM_RESET_QSPI,
143 ZYNQMP_PM_RESET_UART0,
144 ZYNQMP_PM_RESET_UART1,
145 ZYNQMP_PM_RESET_SPI0,
146 ZYNQMP_PM_RESET_SPI1,
147 ZYNQMP_PM_RESET_SDIO0,
148 ZYNQMP_PM_RESET_SDIO1,
149 ZYNQMP_PM_RESET_CAN0,
150 ZYNQMP_PM_RESET_CAN1,
151 ZYNQMP_PM_RESET_I2C0,
152 ZYNQMP_PM_RESET_I2C1,
153 ZYNQMP_PM_RESET_TTC0,
154 ZYNQMP_PM_RESET_TTC1,
155 ZYNQMP_PM_RESET_TTC2,
156 ZYNQMP_PM_RESET_TTC3,
157 ZYNQMP_PM_RESET_SWDT_CRL,
158 ZYNQMP_PM_RESET_NAND,
159 ZYNQMP_PM_RESET_ADMA,
160 ZYNQMP_PM_RESET_GPIO,
161 ZYNQMP_PM_RESET_IOU_CC,
162 ZYNQMP_PM_RESET_TIMESTAMP,
163 ZYNQMP_PM_RESET_RPU_R50,
164 ZYNQMP_PM_RESET_RPU_R51,
165 ZYNQMP_PM_RESET_RPU_AMBA,
166 ZYNQMP_PM_RESET_OCM,
167 ZYNQMP_PM_RESET_RPU_PGE,
168 ZYNQMP_PM_RESET_USB0_CORERESET,
169 ZYNQMP_PM_RESET_USB1_CORERESET,
170 ZYNQMP_PM_RESET_USB0_HIBERRESET,
171 ZYNQMP_PM_RESET_USB1_HIBERRESET,
172 ZYNQMP_PM_RESET_USB0_APB,
173 ZYNQMP_PM_RESET_USB1_APB,
174 ZYNQMP_PM_RESET_IPI,
175 ZYNQMP_PM_RESET_APM_LPD,
176 ZYNQMP_PM_RESET_RTC,
177 ZYNQMP_PM_RESET_SYSMON,
178 ZYNQMP_PM_RESET_AFI_FM6,
179 ZYNQMP_PM_RESET_LPD_SWDT,
180 ZYNQMP_PM_RESET_FPD,
181 ZYNQMP_PM_RESET_RPU_DBG1,
182 ZYNQMP_PM_RESET_RPU_DBG0,
183 ZYNQMP_PM_RESET_DBG_LPD,
184 ZYNQMP_PM_RESET_DBG_FPD,
185 ZYNQMP_PM_RESET_APLL,
186 ZYNQMP_PM_RESET_DPLL,
187 ZYNQMP_PM_RESET_VPLL,
188 ZYNQMP_PM_RESET_IOPLL,
189 ZYNQMP_PM_RESET_RPLL,
190 ZYNQMP_PM_RESET_GPO3_PL_0,
191 ZYNQMP_PM_RESET_GPO3_PL_1,
192 ZYNQMP_PM_RESET_GPO3_PL_2,
193 ZYNQMP_PM_RESET_GPO3_PL_3,
194 ZYNQMP_PM_RESET_GPO3_PL_4,
195 ZYNQMP_PM_RESET_GPO3_PL_5,
196 ZYNQMP_PM_RESET_GPO3_PL_6,
197 ZYNQMP_PM_RESET_GPO3_PL_7,
198 ZYNQMP_PM_RESET_GPO3_PL_8,
199 ZYNQMP_PM_RESET_GPO3_PL_9,
200 ZYNQMP_PM_RESET_GPO3_PL_10,
201 ZYNQMP_PM_RESET_GPO3_PL_11,
202 ZYNQMP_PM_RESET_GPO3_PL_12,
203 ZYNQMP_PM_RESET_GPO3_PL_13,
204 ZYNQMP_PM_RESET_GPO3_PL_14,
205 ZYNQMP_PM_RESET_GPO3_PL_15,
206 ZYNQMP_PM_RESET_GPO3_PL_16,
207 ZYNQMP_PM_RESET_GPO3_PL_17,
208 ZYNQMP_PM_RESET_GPO3_PL_18,
209 ZYNQMP_PM_RESET_GPO3_PL_19,
210 ZYNQMP_PM_RESET_GPO3_PL_20,
211 ZYNQMP_PM_RESET_GPO3_PL_21,
212 ZYNQMP_PM_RESET_GPO3_PL_22,
213 ZYNQMP_PM_RESET_GPO3_PL_23,
214 ZYNQMP_PM_RESET_GPO3_PL_24,
215 ZYNQMP_PM_RESET_GPO3_PL_25,
216 ZYNQMP_PM_RESET_GPO3_PL_26,
217 ZYNQMP_PM_RESET_GPO3_PL_27,
218 ZYNQMP_PM_RESET_GPO3_PL_28,
219 ZYNQMP_PM_RESET_GPO3_PL_29,
220 ZYNQMP_PM_RESET_GPO3_PL_30,
221 ZYNQMP_PM_RESET_GPO3_PL_31,
222 ZYNQMP_PM_RESET_RPU_LS,
223 ZYNQMP_PM_RESET_PS_ONLY,
224 ZYNQMP_PM_RESET_PL,
225 ZYNQMP_PM_RESET_PS_PL0,
226 ZYNQMP_PM_RESET_PS_PL1,
227 ZYNQMP_PM_RESET_PS_PL2,
228 ZYNQMP_PM_RESET_PS_PL3,
229 ZYNQMP_PM_RESET_END = ZYNQMP_PM_RESET_PS_PL3
230};
231
232enum zynqmp_pm_suspend_reason {
233 SUSPEND_POWER_REQUEST = 201,
234 SUSPEND_ALERT,
235 SUSPEND_SYSTEM_SHUTDOWN,
236};
237
238enum zynqmp_pm_request_ack {
239 ZYNQMP_PM_REQUEST_ACK_NO = 1,
240 ZYNQMP_PM_REQUEST_ACK_BLOCKING,
241 ZYNQMP_PM_REQUEST_ACK_NON_BLOCKING,
242};
243
78/** 244/**
79 * struct zynqmp_pm_query_data - PM query data 245 * struct zynqmp_pm_query_data - PM query data
80 * @qid: query ID 246 * @qid: query ID
@@ -91,6 +257,7 @@ struct zynqmp_pm_query_data {
91 257
92struct zynqmp_eemi_ops { 258struct zynqmp_eemi_ops {
93 int (*get_api_version)(u32 *version); 259 int (*get_api_version)(u32 *version);
260 int (*get_chipid)(u32 *idcode, u32 *version);
94 int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out); 261 int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out);
95 int (*clock_enable)(u32 clock_id); 262 int (*clock_enable)(u32 clock_id);
96 int (*clock_disable)(u32 clock_id); 263 int (*clock_disable)(u32 clock_id);
@@ -102,8 +269,25 @@ struct zynqmp_eemi_ops {
102 int (*clock_setparent)(u32 clock_id, u32 parent_id); 269 int (*clock_setparent)(u32 clock_id, u32 parent_id);
103 int (*clock_getparent)(u32 clock_id, u32 *parent_id); 270 int (*clock_getparent)(u32 clock_id, u32 *parent_id);
104 int (*ioctl)(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, u32 *out); 271 int (*ioctl)(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, u32 *out);
272 int (*reset_assert)(const enum zynqmp_pm_reset reset,
273 const enum zynqmp_pm_reset_action assert_flag);
274 int (*reset_get_status)(const enum zynqmp_pm_reset reset, u32 *status);
275 int (*init_finalize)(void);
276 int (*set_suspend_mode)(u32 mode);
277 int (*request_node)(const u32 node,
278 const u32 capabilities,
279 const u32 qos,
280 const enum zynqmp_pm_request_ack ack);
281 int (*release_node)(const u32 node);
282 int (*set_requirement)(const u32 node,
283 const u32 capabilities,
284 const u32 qos,
285 const enum zynqmp_pm_request_ack ack);
105}; 286};
106 287
288int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
289 u32 arg2, u32 arg3, u32 *ret_payload);
290
107#if IS_REACHABLE(CONFIG_ARCH_ZYNQMP) 291#if IS_REACHABLE(CONFIG_ARCH_ZYNQMP)
108const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void); 292const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void);
109#else 293#else
diff --git a/include/linux/fsl/guts.h b/include/linux/fsl/guts.h
index 941b11811f85..1fc0edd71c52 100644
--- a/include/linux/fsl/guts.h
+++ b/include/linux/fsl/guts.h
@@ -135,8 +135,6 @@ struct ccsr_guts {
135 u32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */ 135 u32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */
136} __attribute__ ((packed)); 136} __attribute__ ((packed));
137 137
138u32 fsl_guts_get_svr(void);
139
140/* Alternate function signal multiplex control */ 138/* Alternate function signal multiplex control */
141#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x)) 139#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
142 140
diff --git a/include/linux/mfd/bcm2835-pm.h b/include/linux/mfd/bcm2835-pm.h
new file mode 100644
index 000000000000..ed37dc40e82a
--- /dev/null
+++ b/include/linux/mfd/bcm2835-pm.h
@@ -0,0 +1,14 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2
3#ifndef BCM2835_MFD_PM_H
4#define BCM2835_MFD_PM_H
5
6#include <linux/regmap.h>
7
8struct bcm2835_pm {
9 struct device *dev;
10 void __iomem *base;
11 void __iomem *asb;
12};
13
14#endif /* BCM2835_MFD_PM_H */
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index f9bd2f34b99f..14eaeeb46f41 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -779,4 +779,13 @@ struct typec_device_id {
779 kernel_ulong_t driver_data; 779 kernel_ulong_t driver_data;
780}; 780};
781 781
782/**
783 * struct tee_client_device_id - tee based device identifier
784 * @uuid: For TEE based client devices we use the device uuid as
785 * the identifier.
786 */
787struct tee_client_device_id {
788 uuid_t uuid;
789};
790
782#endif /* LINUX_MOD_DEVICETABLE_H */ 791#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index b895f4e79868..900359342965 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -86,6 +86,8 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
86 86
87unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp); 87unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
88 88
89unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp);
90
89bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp); 91bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp);
90 92
91int dev_pm_opp_get_opp_count(struct device *dev); 93int dev_pm_opp_get_opp_count(struct device *dev);
@@ -158,6 +160,11 @@ static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
158 return 0; 160 return 0;
159} 161}
160 162
163static inline unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp)
164{
165 return 0;
166}
167
161static inline bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp) 168static inline bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
162{ 169{
163 return false; 170 return false;
diff --git a/include/linux/reset/socfpga.h b/include/linux/reset/socfpga.h
new file mode 100644
index 000000000000..b11a2047c342
--- /dev/null
+++ b/include/linux/reset/socfpga.h
@@ -0,0 +1,7 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __LINUX_RESET_SOCFPGA_H__
3#define __LINUX_RESET_SOCFPGA_H__
4
5void __init socfpga_reset_init(void);
6
7#endif /* __LINUX_RESET_SOCFPGA_H__ */
diff --git a/include/linux/reset/sunxi.h b/include/linux/reset/sunxi.h
new file mode 100644
index 000000000000..1ad7fffb413e
--- /dev/null
+++ b/include/linux/reset/sunxi.h
@@ -0,0 +1,7 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __LINUX_RESET_SUNXI_H__
3#define __LINUX_RESET_SUNXI_H__
4
5void __init sun6i_reset_init(void);
6
7#endif /* __LINUX_RESET_SUNXI_H__ */
diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
index 69c285b1c990..eb71a50b8afc 100644
--- a/include/linux/soc/qcom/llcc-qcom.h
+++ b/include/linux/soc/qcom/llcc-qcom.h
@@ -162,6 +162,12 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc);
162 */ 162 */
163int qcom_llcc_probe(struct platform_device *pdev, 163int qcom_llcc_probe(struct platform_device *pdev,
164 const struct llcc_slice_config *table, u32 sz); 164 const struct llcc_slice_config *table, u32 sz);
165
166/**
167 * qcom_llcc_remove - remove the sct table
168 * @pdev: Platform device pointer
169 */
170int qcom_llcc_remove(struct platform_device *pdev);
165#else 171#else
166static inline struct llcc_slice_desc *llcc_slice_getd(u32 uid) 172static inline struct llcc_slice_desc *llcc_slice_getd(u32 uid)
167{ 173{
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index 6cfe05893a76..4a49f80e7f71 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -15,11 +15,14 @@
15#ifndef __TEE_DRV_H 15#ifndef __TEE_DRV_H
16#define __TEE_DRV_H 16#define __TEE_DRV_H
17 17
18#include <linux/types.h> 18#include <linux/device.h>
19#include <linux/idr.h> 19#include <linux/idr.h>
20#include <linux/kref.h> 20#include <linux/kref.h>
21#include <linux/list.h> 21#include <linux/list.h>
22#include <linux/mod_devicetable.h>
22#include <linux/tee.h> 23#include <linux/tee.h>
24#include <linux/types.h>
25#include <linux/uuid.h>
23 26
24/* 27/*
25 * The file describes the API provided by the generic TEE driver to the 28 * The file describes the API provided by the generic TEE driver to the
@@ -47,6 +50,11 @@ struct tee_shm_pool;
47 * @releasing: flag that indicates if context is being released right now. 50 * @releasing: flag that indicates if context is being released right now.
48 * It is needed to break circular dependency on context during 51 * It is needed to break circular dependency on context during
49 * shared memory release. 52 * shared memory release.
53 * @supp_nowait: flag that indicates that requests in this context should not
54 * wait for tee-supplicant daemon to be started if not present
55 * and just return with an error code. It is needed for requests
56 * that arises from TEE based kernel drivers that should be
57 * non-blocking in nature.
50 */ 58 */
51struct tee_context { 59struct tee_context {
52 struct tee_device *teedev; 60 struct tee_device *teedev;
@@ -54,6 +62,7 @@ struct tee_context {
54 void *data; 62 void *data;
55 struct kref refcount; 63 struct kref refcount;
56 bool releasing; 64 bool releasing;
65 bool supp_nowait;
57}; 66};
58 67
59struct tee_param_memref { 68struct tee_param_memref {
@@ -526,6 +535,18 @@ int tee_client_invoke_func(struct tee_context *ctx,
526 struct tee_ioctl_invoke_arg *arg, 535 struct tee_ioctl_invoke_arg *arg,
527 struct tee_param *param); 536 struct tee_param *param);
528 537
538/**
539 * tee_client_cancel_req() - Request cancellation of the previous open-session
540 * or invoke-command operations in a Trusted Application
541 * @ctx: TEE Context
542 * @arg: Cancellation arguments, see description of
543 * struct tee_ioctl_cancel_arg
544 *
545 * Returns < 0 on error else 0 if the cancellation was successfully requested.
546 */
547int tee_client_cancel_req(struct tee_context *ctx,
548 struct tee_ioctl_cancel_arg *arg);
549
529static inline bool tee_param_is_memref(struct tee_param *param) 550static inline bool tee_param_is_memref(struct tee_param *param)
530{ 551{
531 switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { 552 switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
@@ -538,4 +559,31 @@ static inline bool tee_param_is_memref(struct tee_param *param)
538 } 559 }
539} 560}
540 561
562extern struct bus_type tee_bus_type;
563
564/**
565 * struct tee_client_device - tee based device
566 * @id: device identifier
567 * @dev: device structure
568 */
569struct tee_client_device {
570 struct tee_client_device_id id;
571 struct device dev;
572};
573
574#define to_tee_client_device(d) container_of(d, struct tee_client_device, dev)
575
576/**
577 * struct tee_client_driver - tee client driver
578 * @id_table: device id table supported by this driver
579 * @driver: driver structure
580 */
581struct tee_client_driver {
582 const struct tee_client_device_id *id_table;
583 struct device_driver driver;
584};
585
586#define to_tee_client_driver(d) \
587 container_of(d, struct tee_client_driver, driver)
588
541#endif /*__TEE_DRV_H*/ 589#endif /*__TEE_DRV_H*/
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index 4be1aa4435ae..7800e12ee042 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -73,6 +73,8 @@ enum rpi_firmware_property_tag {
73 RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021, 73 RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
74 RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030, 74 RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
75 RPI_FIRMWARE_GET_THROTTLED = 0x00030046, 75 RPI_FIRMWARE_GET_THROTTLED = 0x00030046,
76 RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047,
77 RPI_FIRMWARE_NOTIFY_REBOOT = 0x00030048,
76 RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, 78 RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001,
77 RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, 79 RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002,
78 RPI_FIRMWARE_SET_VOLTAGE = 0x00038003, 80 RPI_FIRMWARE_SET_VOLTAGE = 0x00038003,
@@ -86,6 +88,8 @@ enum rpi_firmware_property_tag {
86 RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043, 88 RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043,
87 RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045, 89 RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045,
88 RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045, 90 RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045,
91 RPI_FIRMWARE_GET_POE_HAT_VAL = 0x00030049,
92 RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050,
89 93
90 94
91 /* Dispmanx TAGS */ 95 /* Dispmanx TAGS */
diff --git a/include/soc/fsl/dpaa2-io.h b/include/soc/fsl/dpaa2-io.h
index 3447fd10a3e6..672cfb58046f 100644
--- a/include/soc/fsl/dpaa2-io.h
+++ b/include/soc/fsl/dpaa2-io.h
@@ -111,9 +111,9 @@ int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid,
111 const struct dpaa2_fd *fd); 111 const struct dpaa2_fd *fd);
112int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio, 112int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
113 u16 qdbin, const struct dpaa2_fd *fd); 113 u16 qdbin, const struct dpaa2_fd *fd);
114int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid, 114int dpaa2_io_service_release(struct dpaa2_io *d, u16 bpid,
115 const u64 *buffers, unsigned int num_buffers); 115 const u64 *buffers, unsigned int num_buffers);
116int dpaa2_io_service_acquire(struct dpaa2_io *d, u32 bpid, 116int dpaa2_io_service_acquire(struct dpaa2_io *d, u16 bpid,
117 u64 *buffers, unsigned int num_buffers); 117 u64 *buffers, unsigned int num_buffers);
118 118
119struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames, 119struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
diff --git a/include/soc/tegra/bpmp.h b/include/soc/tegra/bpmp.h
index b02f926a0216..45960aa08f4a 100644
--- a/include/soc/tegra/bpmp.h
+++ b/include/soc/tegra/bpmp.h
@@ -23,6 +23,7 @@
23#include <soc/tegra/bpmp-abi.h> 23#include <soc/tegra/bpmp-abi.h>
24 24
25struct tegra_bpmp_clk; 25struct tegra_bpmp_clk;
26struct tegra_bpmp_ops;
26 27
27struct tegra_bpmp_soc { 28struct tegra_bpmp_soc {
28 struct { 29 struct {
@@ -32,6 +33,8 @@ struct tegra_bpmp_soc {
32 unsigned int timeout; 33 unsigned int timeout;
33 } cpu_tx, thread, cpu_rx; 34 } cpu_tx, thread, cpu_rx;
34 } channels; 35 } channels;
36
37 const struct tegra_bpmp_ops *ops;
35 unsigned int num_resets; 38 unsigned int num_resets;
36}; 39};
37 40
@@ -47,6 +50,7 @@ struct tegra_bpmp_channel {
47 struct tegra_bpmp_mb_data *ob; 50 struct tegra_bpmp_mb_data *ob;
48 struct completion completion; 51 struct completion completion;
49 struct tegra_ivc *ivc; 52 struct tegra_ivc *ivc;
53 unsigned int index;
50}; 54};
51 55
52typedef void (*tegra_bpmp_mrq_handler_t)(unsigned int mrq, 56typedef void (*tegra_bpmp_mrq_handler_t)(unsigned int mrq,
@@ -63,12 +67,7 @@ struct tegra_bpmp_mrq {
63struct tegra_bpmp { 67struct tegra_bpmp {
64 const struct tegra_bpmp_soc *soc; 68 const struct tegra_bpmp_soc *soc;
65 struct device *dev; 69 struct device *dev;
66 70 void *priv;
67 struct {
68 struct gen_pool *pool;
69 dma_addr_t phys;
70 void *virt;
71 } tx, rx;
72 71
73 struct { 72 struct {
74 struct mbox_client client; 73 struct mbox_client client;
@@ -173,6 +172,8 @@ static inline bool tegra_bpmp_mrq_is_supported(struct tegra_bpmp *bpmp,
173} 172}
174#endif 173#endif
175 174
175void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp);
176
176#if IS_ENABLED(CONFIG_CLK_TEGRA_BPMP) 177#if IS_ENABLED(CONFIG_CLK_TEGRA_BPMP)
177int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp); 178int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp);
178#else 179#else
diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
index a9db1b501de1..b32ee5d82dd4 100644
--- a/include/soc/tegra/pmc.h
+++ b/include/soc/tegra/pmc.h
@@ -161,7 +161,6 @@ enum tegra_io_pad {
161#define TEGRA_IO_RAIL_LVDS TEGRA_IO_PAD_LVDS 161#define TEGRA_IO_RAIL_LVDS TEGRA_IO_PAD_LVDS
162 162
163#ifdef CONFIG_SOC_TEGRA_PMC 163#ifdef CONFIG_SOC_TEGRA_PMC
164int tegra_powergate_is_powered(unsigned int id);
165int tegra_powergate_power_on(unsigned int id); 164int tegra_powergate_power_on(unsigned int id);
166int tegra_powergate_power_off(unsigned int id); 165int tegra_powergate_power_off(unsigned int id);
167int tegra_powergate_remove_clamping(unsigned int id); 166int tegra_powergate_remove_clamping(unsigned int id);
@@ -182,11 +181,6 @@ void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
182void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode); 181void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
183 182
184#else 183#else
185static inline int tegra_powergate_is_powered(unsigned int id)
186{
187 return -ENOSYS;
188}
189
190static inline int tegra_powergate_power_on(unsigned int id) 184static inline int tegra_powergate_power_on(unsigned int id)
191{ 185{
192 return -ENOSYS; 186 return -ENOSYS;
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index 293004499b4d..160718383a71 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -225,5 +225,8 @@ int main(void)
225 DEVID_FIELD(typec_device_id, svid); 225 DEVID_FIELD(typec_device_id, svid);
226 DEVID_FIELD(typec_device_id, mode); 226 DEVID_FIELD(typec_device_id, mode);
227 227
228 DEVID(tee_client_device_id);
229 DEVID_FIELD(tee_client_device_id, uuid);
230
228 return 0; 231 return 0;
229} 232}
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index a37af7d71973..d0e41723627f 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -37,6 +37,9 @@ typedef unsigned char __u8;
37typedef struct { 37typedef struct {
38 __u8 b[16]; 38 __u8 b[16];
39} uuid_le; 39} uuid_le;
40typedef struct {
41 __u8 b[16];
42} uuid_t;
40 43
41/* Big exception to the "don't include kernel headers into userspace, which 44/* Big exception to the "don't include kernel headers into userspace, which
42 * even potentially has different endianness and word sizes, since 45 * even potentially has different endianness and word sizes, since
@@ -1287,6 +1290,21 @@ static int do_typec_entry(const char *filename, void *symval, char *alias)
1287 return 1; 1290 return 1;
1288} 1291}
1289 1292
1293/* Looks like: tee:uuid */
1294static int do_tee_entry(const char *filename, void *symval, char *alias)
1295{
1296 DEF_FIELD(symval, tee_client_device_id, uuid);
1297
1298 sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1299 uuid.b[0], uuid.b[1], uuid.b[2], uuid.b[3], uuid.b[4],
1300 uuid.b[5], uuid.b[6], uuid.b[7], uuid.b[8], uuid.b[9],
1301 uuid.b[10], uuid.b[11], uuid.b[12], uuid.b[13], uuid.b[14],
1302 uuid.b[15]);
1303
1304 add_wildcard(alias);
1305 return 1;
1306}
1307
1290/* Does namelen bytes of name exactly match the symbol? */ 1308/* Does namelen bytes of name exactly match the symbol? */
1291static bool sym_is(const char *name, unsigned namelen, const char *symbol) 1309static bool sym_is(const char *name, unsigned namelen, const char *symbol)
1292{ 1310{
@@ -1357,6 +1375,7 @@ static const struct devtable devtable[] = {
1357 {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry}, 1375 {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry},
1358 {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry}, 1376 {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry},
1359 {"typec", SIZE_typec_device_id, do_typec_entry}, 1377 {"typec", SIZE_typec_device_id, do_typec_entry},
1378 {"tee", SIZE_tee_client_device_id, do_tee_entry},
1360}; 1379};
1361 1380
1362/* Create MODULE_ALIAS() statements. 1381/* Create MODULE_ALIAS() statements.