History

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 ...

Linus Torvalds committed 7 years ago

Commit 384d11f2 parents 6ad63de 8ceb820126 files · +7122 −744Browse files

Unified · Split

126 files
  1. Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt +6 −2
  2. Documentation/devicetree/bindings/bus/imx-weim.txt +29 −3
  3. Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt +46 −0
  4. Documentation/devicetree/bindings/opp/opp.txt +3 −0
  5. Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt +3 −0
  6. Documentation/devicetree/bindings/power/qcom,rpmpd.txt +145 −0
  7. Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt +25 −0
  8. Documentation/devicetree/bindings/power/xlnx,zynqmp-genpd.txt +34 −0
  9. Documentation/devicetree/bindings/reset/brcm,brcmstb-reset.txt +27 −0
  10. Documentation/devicetree/bindings/reset/fsl,imx7-src.txt +5 −2
  11. Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt +52 −0
  12. Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt +2 −0
  13. Documentation/devicetree/bindings/soc/bcm/brcm,bcm2835-pm.txt +46 −0
  14. Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt +1 −0
  15. MAINTAINERS +31 −7
  16. arch/arm/boot/dts/bcm2835-rpi.dtsi +0 −4
  17. arch/arm/boot/dts/bcm283x.dtsi +14 −3
  18. arch/arm/mach-bcm/Kconfig +1 −0
  19. arch/arm/mach-socfpga/socfpga.c +1 −2
  20. arch/arm/mach-sunxi/sunxi.c +1 −1
  21. drivers/bus/hisi_lpc.c +2 −3
  22. drivers/bus/imx-weim.c +57 −13
  23. drivers/char/hw_random/Kconfig +15 −0
  24. drivers/char/hw_random/Makefile +1 −0
  25. drivers/char/hw_random/optee-rng.c +306 −0
  26. drivers/clk/tegra/Kconfig +5 −0
  27. drivers/clk/tegra/Makefile +1 −1
  28. drivers/clk/tegra/clk-dfll.c +387 −72
  29. drivers/clk/tegra/clk-dfll.h +5 −1
  30. drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +504 −16
  31. drivers/clk/tegra/cvb.c +7 −5
  32. drivers/clk/tegra/cvb.h +4 −3
  33. drivers/cpufreq/Kconfig.arm +2 −2
  34. drivers/cpufreq/cpufreq-dt-platdev.c +1 −0
  35. drivers/cpufreq/tegra124-cpufreq.c +4 −40
  36. drivers/firmware/imx/misc.c +38 −0
  37. drivers/firmware/imx/scu-pd.c +1 −0
  38. drivers/firmware/raspberrypi.c +11 −0
  39. drivers/firmware/tegra/Makefile +3 −0
  40. drivers/firmware/tegra/bpmp-private.h +34 −0
  41. drivers/firmware/tegra/bpmp-tegra186.c +305 −0
  42. drivers/firmware/tegra/bpmp-tegra210.c +243 −0
  43. drivers/firmware/tegra/bpmp.c +150 −226
  44. drivers/firmware/ti_sci.c +2 −19
  45. drivers/firmware/xilinx/Kconfig +1 −0
  46. drivers/firmware/xilinx/zynqmp.c +166 −0
  47. drivers/mfd/Makefile +1 −0
  48. drivers/mfd/bcm2835-pm.c +92 −0
  49. drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +6 −1
  50. drivers/nvmem/Kconfig +10 −0
  51. drivers/nvmem/Makefile +2 −0
  52. drivers/nvmem/zynqmp_nvmem.c +86 −0
  53. drivers/opp/core.c +18 −0
  54. drivers/opp/of.c +2 −0
  55. drivers/opp/opp.h +2 −0
  56. drivers/reset/Kconfig +10 −2
  57. drivers/reset/Makefile +2 −0
  58. drivers/reset/reset-brcmstb.c +132 −0
  59. drivers/reset/reset-imx7.c +158 −14
  60. drivers/reset/reset-socfpga.c +1 −1
  61. drivers/reset/reset-sunxi.c +1 −0
  62. drivers/reset/reset-zynqmp.c +114 −0
  63. drivers/soc/amlogic/meson-canvas.c +16 −2
  64. drivers/soc/amlogic/meson-clk-measure.c +196 −0
  65. drivers/soc/bcm/Kconfig +12 −0
  66. drivers/soc/bcm/Makefile +1 −0
  67. drivers/soc/bcm/bcm2835-power.c +661 −0
  68. drivers/soc/fsl/Kconfig +1 −0
  69. drivers/soc/fsl/dpio/dpio-cmd.h +5 −0
  70. drivers/soc/fsl/dpio/dpio-driver.c +53 −1
  71. drivers/soc/fsl/dpio/dpio-service.c +3 −2
  72. drivers/soc/fsl/dpio/dpio.c +16 −0
  73. drivers/soc/fsl/dpio/dpio.h +5 −0
  74. drivers/soc/fsl/dpio/qbman-portal.c +3 −2
  75. drivers/soc/fsl/guts.c +5 −5
  76. drivers/soc/imx/Kconfig +1 −1
  77. drivers/soc/imx/gpcv2.c +74 −2
  78. drivers/soc/qcom/Kconfig +18 −0
  79. drivers/soc/qcom/Makefile +2 −0
  80. drivers/soc/qcom/llcc-sdm845.c +6 −0
  81. drivers/soc/qcom/llcc-slice.c +68 −33
  82. drivers/soc/qcom/qcom_gsbi.c +5 −2
  83. drivers/soc/qcom/rmtfs_mem.c +24 −8
  84. drivers/soc/qcom/rpmh.c +22 −15
  85. drivers/soc/qcom/rpmhpd.c +406 −0
  86. drivers/soc/qcom/rpmpd.c +315 −0
  87. drivers/soc/qcom/smd-rpm.c +1 −0
  88. drivers/soc/tegra/fuse/fuse-tegra.c +9 −3
  89. drivers/soc/tegra/fuse/speedo-tegra210.c +1 −1
  90. drivers/soc/tegra/pmc.c +288 −136
  91. drivers/soc/ti/knav_dma.c +1 −1
  92. drivers/soc/xilinx/Kconfig +20 −0
  93. drivers/soc/xilinx/Makefile +2 −0
  94. drivers/soc/xilinx/zynqmp_pm_domains.c +321 −0
  95. drivers/soc/xilinx/zynqmp_power.c +178 −0
  96. drivers/tee/optee/Makefile +1 −0
  97. drivers/tee/optee/core.c +4 −0
  98. drivers/tee/optee/device.c +160 −0
  99. drivers/tee/optee/optee_msg.h +2 −24
  100. drivers/tee/optee/optee_private.h +3 −0
  101. drivers/tee/optee/optee_smc.h +2 −24
  102. drivers/tee/optee/supp.c +9 −1
  103. drivers/tee/tee_core.c +74 −4
  104. drivers/watchdog/bcm2835_wdt.c +9 −17
  105. include/dt-bindings/power/qcom-rpmpd.h +39 −0
  106. include/dt-bindings/power/xlnx-zynqmp-power.h +39 −0
  107. include/dt-bindings/reset/amlogic,meson-g12a-reset.h +134 −0
  108. include/dt-bindings/reset/imx8mq-reset.h +64 −0
  109. include/dt-bindings/reset/xlnx-zynqmp-resets.h +130 −0
  110. include/dt-bindings/soc/bcm2835-pm.h +28 −0
  111. include/linux/firmware/imx/svc/misc.h +3 −0
  112. include/linux/firmware/xlnx-zynqmp.h +184 −0
  113. include/linux/fsl/guts.h +0 −2
  114. include/linux/mfd/bcm2835-pm.h +14 −0
  115. include/linux/mod_devicetable.h +9 −0
  116. include/linux/pm_opp.h +7 −0
  117. include/linux/reset/socfpga.h +7 −0
  118. include/linux/reset/sunxi.h +7 −0
  119. include/linux/soc/qcom/llcc-qcom.h +6 −0
  120. include/linux/tee_drv.h +49 −1
  121. include/soc/bcm2835/raspberrypi-firmware.h +4 −0
  122. include/soc/fsl/dpaa2-io.h +2 −2
  123. include/soc/tegra/bpmp.h +7 −6
  124. include/soc/tegra/pmc.h +0 −6
  125. scripts/mod/devicetable-offsets.c +3 −0
  126. scripts/mod/file2alias.c +19 −0
Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt+6−2
@@ -58,7 +58,11 @@ This binding for the SCU power domain providers uses the generic power · 57 unmodified lines
5858 domain binding[2].
5959
6060 Required 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+
6266 - #power-domain-cells: Must be 1. Contains the Resource ID used by
6367 SCU commands.
6468 See detailed Resource ID list from:
@@ -157,7 +161,7 @@ firmware { · 92 unmodified lines
157161 };
158162
159163 pd: imx8qx-pd {
160− compatible = "fsl,imx8qxp-scu-pd";
164+ compatible = "fsl,imx8qxp-scu-pd", "fsl,scu-pd";
161165 #power-domain-cells = <1>;
162166 };
163167
Documentation/devicetree/bindings/bus/imx-weim.txt+29−3
@@ -47,9 +47,9 @@ Optional properties: · 46 unmodified lines
4747 Timing property for child nodes. It is mandatory, not optional.
4848
4949 - fsl,weim-cs-timing: The timing array, contains timing values for the
50− child node. We can get the CS index from the child
51− node's "reg" property. The number of registers depends
52− on the selected chip.
50+ child node. We get the CS indexes from the address
51+ ranges in the child node's "reg" property.
52+ The number of registers depends on the selected chip:
5353 For i.MX1, i.MX21 ("fsl,imx1-weim") there are two
5454 registers: CSxU, CSxL.
5555 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: · 24 unmodified lines
8080 0x0000c000 0x1404a38e 0x00000000>;
8181 };
8282 };
83+
84+Example for an imx6q-based board, a multi-chipselect device connected to WEIM:
85+
86+In this case, both chip select 0 and 1 will be configured with the same timing
87+array 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+ };
Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt+46−0
@@ -0,0 +1,46 @@
1+--------------------------------------------------------------------------
2+= Zynq UltraScale+ MPSoC nvmem firmware driver binding =
3+--------------------------------------------------------------------------
4+The nvmem_firmware node provides access to the hardware related data
5+like soc revision, IDCODE... etc, By using the firmware interface.
6+
7+Required properties:
8+- compatible: should be "xlnx,zynqmp-nvmem-fw"
9+
10+= Data cells =
11+Are child nodes of silicon id, bindings of which as described in
12+bindings/nvmem/nvmem.txt
13+
14+-------
15+ Example
16+-------
17+firmware {
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 =
36+Are device nodes which consume nvmem data cells.
37+
38+For example:
39+ pcap {
40+ ...
41+
42+ nvmem-cells = <&soc_revision>;
43+ nvmem-cell-names = "soc_revision";
44+
45+ ...
46+ };
Documentation/devicetree/bindings/opp/opp.txt+3−0
@@ -129,6 +129,9 @@ Optional properties: · 128 unmodified lines
129129 - opp-microamp-<name>: Named opp-microamp property. Similar to
130130 opp-microvolt-<name> property, but for microamp instead.
131131
132+- opp-level: A value representing the performance level of the device,
133+ expressed as a 32-bit integer.
134+
132135 - clock-latency-ns: Specifies the maximum possible transition latency (in
133136 nanoseconds) for switching to this OPP from any other OPP.
134137
Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt+3−0
@@ -32,6 +32,9 @@ Required properties: · 31 unmodified lines
3232 Optional properties:
3333
3434 - 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
3538
3639 Example:
3740
Documentation/devicetree/bindings/power/qcom,rpmpd.txt+145−0
@@ -0,0 +1,145 @@
1+Qualcomm RPM/RPMh Power domains
2+
3+For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh
4+which then translates it into a corresponding voltage on a rail
5+
6+Required 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+
16+Refer to <dt-bindings/power/qcom-rpmpd.h> for the level values for
17+various OPPs for different platforms as well as Power domain indexes
18+
19+Example: rpmh power domain controller and OPP table
20+
21+#include <dt-bindings/power/qcom-rpmhpd.h>
22+
23+opp-level values specified in the OPP tables for RPMh power domains
24+should 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+
77+Example: 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+
113+Example: 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+ };
Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt+25−0
@@ -0,0 +1,25 @@
1+--------------------------------------------------------------------
2+Device Tree Bindings for the Xilinx Zynq MPSoC Power Management
3+--------------------------------------------------------------------
4+The zynqmp-power node describes the power management configurations.
5+It will control remote suspend/shutdown interfaces.
6+
7+Required properties:
8+ - compatible: Must contain: "xlnx,zynqmp-power"
9+ - interrupts: Interrupt specifier
10+
11+-------
12+Example
13+-------
14+
15+firmware {
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+};
Documentation/devicetree/bindings/power/xlnx,zynqmp-genpd.txt+34−0
@@ -0,0 +1,34 @@
1+-----------------------------------------------------------
2+Device Tree Bindings for the Xilinx Zynq MPSoC PM domains
3+-----------------------------------------------------------
4+The binding for zynqmp-power-controller follow the common
5+generic PM domain binding[1].
6+
7+[1] Documentation/devicetree/bindings/power/power_domain.txt
8+
9+== Zynq MPSoC Generic PM Domain Node ==
10+
11+Required 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+
15+Power domain ID indexes are mentioned in
16+include/dt-bindings/power/xlnx-zynqmp-power.h.
17+
18+-------
19+Example
20+-------
21+
22+firmware {
23+ zynqmp_firmware: zynqmp-firmware {
24+ ...
25+ #power-domain-cells = <1>;
26+ ...
27+ };
28+};
29+
30+sata {
31+ ...
32+ power-domains = <&zynqmp_firmware 28>;
33+ ...
34+};
Documentation/devicetree/bindings/reset/brcm,brcmstb-reset.txt+27−0
@@ -0,0 +1,27 @@
1+Broadcom STB SW_INIT-style reset controller
2+===========================================
3+
4+Broadcom STB SoCs have a SW_INIT-style reset controller with separate
5+SET/CLEAR/STATUS registers and possibly multiple banks, each of 32 bit
6+reset lines.
7+
8+Please also refer to reset.txt in this directory for common reset
9+controller binding usage.
10+
11+Required properties:
12+- compatible: should be brcm,brcmstb-reset
13+- reg: register base and length
14+- #reset-cells: must be set to 1
15+
16+Example:
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+ };
Documentation/devicetree/bindings/reset/fsl,imx7-src.txt+5−2
@@ -5,7 +5,9 @@ Please also refer to reset.txt in this directory for common reset · 4 unmodified lines
55 controller binding usage.
66
77 Required 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"
911 - reg: should be register base and length as documented in the
1012 datasheet
1113 - interrupts: Should contain SRC interrupt
@@ -44,4 +46,5 @@ Example: · 32 unmodified lines
4446
4547
4648 For 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
Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt+52−0
@@ -0,0 +1,52 @@
1+--------------------------------------------------------------------------
2+ = Zynq UltraScale+ MPSoC reset driver binding =
3+--------------------------------------------------------------------------
4+The Zynq UltraScale+ MPSoC has several different resets.
5+
6+See Chapter 36 of the Zynq UltraScale+ MPSoC TRM (UG) for more information
7+about zynqmp resets.
8+
9+Please also refer to reset.txt in this directory for common reset
10+controller binding usage.
11+
12+Required 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+-------
18+Example
19+-------
20+
21+firmware {
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+
33+Specifying reset lines connected to IP modules
34+==============================================
35+
36+Device nodes that need access to reset lines should
37+specify them as a reset phandle in their corresponding node as
38+specified in reset.txt.
39+
40+For list of all valid reset indicies see
41+<dt-bindings/reset/xlnx-zynqmp-resets.h>
42+
43+Example:
44+
45+serdes: zynqmp_phy@fd400000 {
46+ ...
47+
48+ resets = <&zynqmp_reset ZYNQMP_RESET_SATA>;
49+ reset-names = "sata_rst";
50+
51+ ...
52+};
Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt+2−0
@@ -9,6 +9,8 @@ Required properties: · 8 unmodified lines
99 "amlogic,meson-gx-clk-measure" for GX SoCs
1010 "amlogic,meson8-clk-measure" for Meson8 SoCs
1111 "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
1214 - reg: base address and size of the Clock Measurer register space.
1315
1416 Example:
Documentation/devicetree/bindings/soc/bcm/brcm,bcm2835-pm.txt+46−0
@@ -0,0 +1,46 @@
1+BCM2835 PM (Power domains, watchdog)
2+
3+The PM block controls power domains and some reset lines, and includes
4+a watchdog timer. This binding supersedes the brcm,bcm2835-pm-wdt
5+binding which covered some of PM's register range and functionality.
6+
7+Required 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+
22+Optional 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+
32+Example:
33+
34+pm {
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+};
Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt+1−0
@@ -23,6 +23,7 @@ resources. · 22 unmodified lines
2323 "qcom,rpm-msm8916"
2424 "qcom,rpm-msm8974"
2525 "qcom,rpm-msm8998"
26+ "qcom,rpm-sdm660"
2627 "qcom,rpm-qcs404"
2728
2829 - qcom,smd-channels:
MAINTAINERS+31−7
@@ -1940,19 +1940,37 @@ M: David Brown <david.brown@linaro.org> · 1939 unmodified lines
19401940 L: linux-arm-msm@vger.kernel.org
19411941 S: Maintained
19421942 F: Documentation/devicetree/bindings/soc/qcom/
1943+F: Documentation/devicetree/bindings/*/qcom*
19431944 F: arch/arm/boot/dts/qcom-*.dts
19441945 F: arch/arm/boot/dts/qcom-*.dtsi
19451946 F: arch/arm/mach-qcom/
1946−F: arch/arm64/boot/dts/qcom/*
1947+F: arch/arm64/boot/dts/qcom/
1948+F: drivers/*/qcom/
1949+F: drivers/*/qcom*
1950+F: drivers/*/*/qcom/
1951+F: drivers/*/*/qcom*
1952+F: drivers/*/pm8???-*
1953+F: drivers/bluetooth/btqcomsmd.c
1954+F: drivers/clocksource/timer-qcom.c
1955+F: drivers/extcon/extcon-qcom*
1956+F: drivers/iommu/msm*
19471957 F: drivers/i2c/busses/i2c-qup.c
1948−F: drivers/clk/qcom/
1949−F: drivers/dma/qcom/
1950−F: drivers/soc/qcom/
1958+F: drivers/i2c/busses/i2c-qcom-geni.c
1959+F: drivers/mfd/ssbi.c
1960+F: drivers/mmc/host/mmci_qcom*
1961+F: drivers/mmc/host/sdhci_msm.c
1962+F: drivers/pci/controller/dwc/pcie-qcom.c
1963+F: drivers/phy/qualcomm/
1964+F: drivers/power/*/msm*
1965+F: drivers/reset/reset-qcom-*
1966+F: drivers/scsi/ufs/ufs-qcom.*
19511967 F: drivers/spi/spi-qup.c
1968+F: drivers/spi/spi-geni-qcom.c
1969+F: drivers/spi/spi-qcom-qspi.c
19521970 F: drivers/tty/serial/msm_serial.c
1953−F: drivers/*/pm8???-*
1954−F: drivers/mfd/ssbi.c
1955−F: drivers/firmware/qcom_scm*
1971+F: drivers/usb/dwc3/dwc3-qcom.c
1972+F: include/dt-bindings/*/qcom*
1973+F: include/linux/*/qcom*
19561974 T: git git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git
19571975
19581976 ARM/RADISYS ENP2611 MACHINE SUPPORT
@@ -11314,6 +11332,11 @@ M: Jens Wiklander <jens.wiklander@linaro.org> · 9355 unmodified lines
1131411332 S: Maintained
1131511333 F: drivers/tee/optee/
1131611334
11335+OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER
11336+M: Sumit Garg <sumit.garg@linaro.org>
11337+S: Maintained
11338+F: drivers/char/hw_random/optee-rng.c
11339+
1131711340 OPA-VNIC DRIVER
1131811341 M: Dennis Dalessandro <dennis.dalessandro@intel.com>
1131911342 M: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
@@ -13017,6 +13040,7 @@ F: drivers/reset/ · 1697 unmodified lines
1301713040 F: Documentation/devicetree/bindings/reset/
1301813041 F: include/dt-bindings/reset/
1301913042 F: include/linux/reset.h
13043+F: include/linux/reset/
1302013044 F: include/linux/reset-controller.h
1302113045
1302213046 RESTARTABLE SEQUENCES SUPPORT
arch/arm/boot/dts/bcm2835-rpi.dtsi+0−4
@@ -85,10 +85,6 @@ · 84 unmodified lines
8585 power-domains = <&power RPI_POWER_DOMAIN_USB>;
8686 };
8787
88−&v3d {
89− power-domains = <&power RPI_POWER_DOMAIN_V3D>;
90−};
91−
9288 &hdmi {
9389 power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
9490 status = "okay";
arch/arm/boot/dts/bcm283x.dtsi+14−3
@@ -3,6 +3,7 @@ · 2 unmodified lines
33 #include <dt-bindings/clock/bcm2835-aux.h>
44 #include <dt-bindings/gpio/gpio.h>
55 #include <dt-bindings/interrupt-controller/irq.h>
6+#include <dt-bindings/soc/bcm2835-pm.h>
67
78 /* firmware-provided startup stubs live here, where the secondary CPUs are
89 * spinning.
@@ -120,9 +121,18 @@ · 111 unmodified lines
120121 #interrupt-cells = <2>;
121122 };
122123
123− watchdog@7e100000 {
124− compatible = "brcm,bcm2835-pm-wdt";
125− reg = <0x7e100000 0x28>;
124+ pm: watchdog@7e100000 {
125+ compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
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;
126136 };
127137
128138 clocks: cprman@7e101000 {
@@ -629,6 +639,7 @@ · 500 unmodified lines
629639 compatible = "brcm,bcm2835-v3d";
630640 reg = <0x7ec00000 0x1000>;
631641 interrupts = <1 10>;
642+ power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
632643 };
633644
634645 vc4: gpu {
arch/arm/mach-bcm/Kconfig+1−0
@@ -167,6 +167,7 @@ config ARCH_BCM2835 · 166 unmodified lines
167167 select BCM2835_TIMER
168168 select PINCTRL
169169 select PINCTRL_BCM2835
170+ select MFD_CORE
170171 help
171172 This enables support for the Broadcom BCM2835 and BCM2836 SoCs.
172173 This SoC is used in the Raspberry Pi and Roku 2 devices.
arch/arm/mach-socfpga/socfpga.c+1−2
@@ -19,6 +19,7 @@ · 18 unmodified lines
1919 #include <linux/of_irq.h>
2020 #include <linux/of_platform.h>
2121 #include <linux/reboot.h>
22+#include <linux/reset/socfpga.h>
2223
2324 #include <asm/hardware/cache-l2x0.h>
2425 #include <asm/mach/arch.h>
@@ -32,8 +33,6 @@ void __iomem *rst_manager_base_addr; · 7 unmodified lines
3233 void __iomem *sdr_ctl_base_addr;
3334 unsigned long socfpga_cpu1start_addr;
3435
35−extern void __init socfpga_reset_init(void);
36−
3736 static void __init socfpga_sysmgr_init(void)
3837 {
3938 struct device_node *np;
arch/arm/mach-sunxi/sunxi.c+1−1
@@ -14,6 +14,7 @@ · 13 unmodified lines
1414 #include <linux/clocksource.h>
1515 #include <linux/init.h>
1616 #include <linux/platform_device.h>
17+#include <linux/reset/sunxi.h>
1718
1819 #include <asm/mach/arch.h>
1920 #include <asm/secure_cntvoff.h>
@@ -37,7 +38,6 @@ static const char * const sun6i_board_dt_compat[] = { · 17 unmodified lines
3738 NULL,
3839 };
3940
40−extern void __init sun6i_reset_init(void);
4141 static void __init sun6i_timer_init(void)
4242 {
4343 of_clk_init(NULL);
drivers/bus/hisi_lpc.c+2−3
@@ -522,10 +522,9 @@ static int hisi_lpc_acpi_probe(struct device *hostdev) · 521 unmodified lines
522522
523523 if (!found) {
524524 dev_warn(hostdev,
525− "could not find cell for child device (%s)\n",
525+ "could not find cell for child device (%s), discarding\n",
526526 hid);
527− ret = -ENODEV;
528− goto fail;
527+ continue;
529528 }
530529
531530 pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO);
drivers/bus/imx-weim.c+57−13
@@ -46,6 +46,17 @@ static const struct imx_weim_devtype imx51_weim_devtype = { · 45 unmodified lines
4646 };
4747
4848 #define MAX_CS_REGS_COUNT 6
49+#define MAX_CS_COUNT 6
50+#define OF_REG_SIZE 3
51+
52+struct cs_timing {
53+ bool is_applied;
54+ u32 regs[MAX_CS_REGS_COUNT];
55+};
56+
57+struct cs_timing_state {
58+ struct cs_timing cs[MAX_CS_COUNT];
59+};
4960
5061 static const struct of_device_id weim_id_table[] = {
5162 /* i.MX1/21 */
@@ -111,21 +122,19 @@ err: · 59 unmodified lines
111122 }
112123
113124 /* Parse and set the timing for this device. */
114−static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
115− const struct imx_weim_devtype *devtype)
125+static int __init weim_timing_setup(struct device *dev,
126+ struct device_node *np, void __iomem *base,
127+ const struct imx_weim_devtype *devtype,
128+ struct cs_timing_state *ts)
116129 {
117130 u32 cs_idx, value[MAX_CS_REGS_COUNT];
118131 int i, ret;
132+ int reg_idx, num_regs;
133+ struct cs_timing *cst;
119134
120135 if (WARN_ON(devtype->cs_regs_count > MAX_CS_REGS_COUNT))
121136 return -EINVAL;
122−
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)
137+ if (WARN_ON(devtype->cs_count > MAX_CS_COUNT))
129138 return -EINVAL;
130139
131140 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, · 1 unmodified line
133142 if (ret)
134143 return ret;
135144
136− /* set the timing for WEIM */
137− for (i = 0; i < devtype->cs_regs_count; i++)
138− writel(value[i], base + cs_idx * devtype->cs_stride + i * 4);
145+ /*
146+ * the child node's "reg" property may contain multiple address ranges,
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+ }
139182
140183 return 0;
141184 }
@@ -148,6 +191,7 @@ static int __init weim_parse_dt(struct platform_device *pdev, · 6 unmodified lines
148191 const struct imx_weim_devtype *devtype = of_id->data;
149192 struct device_node *child;
150193 int ret, have_child = 0;
194+ struct cs_timing_state ts = {};
151195
152196 if (devtype == &imx50_weim_devtype) {
153197 ret = imx_weim_gpr_setup(pdev);
@@ -156,7 +200,7 @@ static int __init weim_parse_dt(struct platform_device *pdev, · 2 unmodified lines
156200 }
157201
158202 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);
160204 if (ret)
161205 dev_warn(&pdev->dev, "%pOF set timing failed.\n",
162206 child);
drivers/char/hw_random/Kconfig+15−0
@@ -424,6 +424,21 @@ config HW_RANDOM_EXYNOS · 423 unmodified lines
424424 will be called exynos-trng.
425425
426426 If unsure, say Y.
427+
428+config 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+
427442 endif # HW_RANDOM
428443
429444 config UML_RANDOM
drivers/char/hw_random/Makefile+1−0
@@ -38,3 +38,4 @@ obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o · 37 unmodified lines
3838 obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o
3939 obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o
4040 obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o
41+obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o
drivers/char/hw_random/optee-rng.c+306−0
@@ -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+ */
61+struct 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+
73+static 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+
115+static 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+
143+static 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+
160+static 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+
167+static 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+
176+static 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+
206+static 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+
214+static 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+
256+out_sess:
257+ tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
258+out_ctx:
259+ tee_client_close_context(pvt_data.ctx);
260+
261+ return err;
262+}
263+
264+static 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+
273+static 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+
279+MODULE_DEVICE_TABLE(tee, optee_rng_id_table);
280+
281+static 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+
291+static int __init optee_rng_mod_init(void)
292+{
293+ return driver_register(&optee_rng_driver.driver);
294+}
295+
296+static void __exit optee_rng_mod_exit(void)
297+{
298+ driver_unregister(&optee_rng_driver.driver);
299+}
300+
301+module_init(optee_rng_mod_init);
302+module_exit(optee_rng_mod_exit);
303+
304+MODULE_LICENSE("GPL v2");
305+MODULE_AUTHOR("Sumit Garg <sumit.garg@linaro.org>");
306+MODULE_DESCRIPTION("OP-TEE based random number generator driver");
drivers/clk/tegra/Kconfig+5−0
@@ -5,3 +5,8 @@ config TEGRA_CLK_EMC · 4 unmodified lines
55 config CLK_TEGRA_BPMP
66 def_bool y
77 depends on TEGRA_BPMP
8+
9+config TEGRA_CLK_DFLL
10+ depends on ARCH_TEGRA_124_SOC || ARCH_TEGRA_210_SOC
11+ select PM_OPP
12+ def_bool y
drivers/clk/tegra/Makefile+1−1
@@ -20,7 +20,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o · 19 unmodified lines
2020 obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
2121 obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
2222 obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
23−obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124-dfll-fcpu.o
23+obj-$(CONFIG_TEGRA_CLK_DFLL) += clk-tegra124-dfll-fcpu.o
2424 obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
2525 obj-y += cvb.o
2626 obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
drivers/clk/tegra/clk-dfll.c+387−72
@@ -1,7 +1,7 @@
11 /*
22 * clk-dfll.c - Tegra DFLL clock source common code
33 *
4− * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
4+ * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved.
55 *
66 * Aleksandr Frid <afrid@nvidia.com>
77 * Paul Walmsley <pwalmsley@nvidia.com>
@@ -47,6 +47,7 @@ · 39 unmodified lines
4747 #include <linux/kernel.h>
4848 #include <linux/module.h>
4949 #include <linux/of.h>
50+#include <linux/pinctrl/consumer.h>
5051 #include <linux/pm_opp.h>
5152 #include <linux/pm_runtime.h>
5253 #include <linux/regmap.h>
@@ -243,6 +244,12 @@ enum dfll_tune_range { · 190 unmodified lines
243244 DFLL_TUNE_LOW = 1,
244245 };
245246
247+
248+enum tegra_dfll_pmu_if {
249+ TEGRA_DFLL_PMU_I2C = 0,
250+ TEGRA_DFLL_PMU_PWM = 1,
251+};
252+
246253 /**
247254 * struct dfll_rate_req - target DFLL rate request data
248255 * @rate: target frequency, after the postscaling
@@ -300,10 +307,19 @@ struct tegra_dfll { · 51 unmodified lines
300307 u32 i2c_reg;
301308 u32 i2c_slave_addr;
302309
303− /* i2c_lut array entries are regulator framework selectors */
304− unsigned i2c_lut[MAX_DFLL_VOLTAGES];
305− int i2c_lut_size;
306− u8 lut_min, lut_max, lut_safe;
310+ /* lut array entries are regulator framework selectors or PWM values*/
311+ unsigned lut[MAX_DFLL_VOLTAGES];
312+ unsigned long lut_uv[MAX_DFLL_VOLTAGES];
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;
307323 };
308324
309325 #define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
@@ -489,6 +505,34 @@ static void dfll_set_mode(struct tegra_dfll *td, · 179 unmodified lines
489505 dfll_wmb(td);
490506 }
491507
508+/*
509+ * DVCO rate control
510+ */
511+
512+static 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+
492536 /*
493537 * DFLL-to-I2C controller interface
494538 */
@@ -518,6 +562,118 @@ static int dfll_i2c_set_output_enabled(struct tegra_dfll *td, bool enable) · 23 unmodified lines
518562 return 0;
519563 }
520564
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+ */
579+static 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+ */
623+static 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+ */
641+static 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+ */
661+static 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+
521677 /**
522678 * dfll_load_lut - load the voltage lookup table
523679 * @td: struct tegra_dfll *
@@ -539,7 +695,7 @@ static void dfll_load_i2c_lut(struct tegra_dfll *td) · 15 unmodified lines
539695 lut_index = i;
540696
541697 val = regulator_list_hardware_vsel(td->vdd_reg,
542− td->i2c_lut[lut_index]);
698+ td->lut[lut_index]);
543699 __raw_writel(val, td->lut_base + i * 4);
544700 }
545701
@@ -594,24 +750,41 @@ static void dfll_init_out_if(struct tegra_dfll *td) · 48 unmodified lines
594750 {
595751 u32 val;
596752
597− td->lut_min = 0;
598− td->lut_max = td->i2c_lut_size - 1;
599− td->lut_safe = td->lut_min + 1;
753+ td->lut_min = td->lut_bottom;
754+ td->lut_max = td->lut_size - 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);
600760
601− dfll_i2c_writel(td, 0, DFLL_OUTPUT_CFG);
602761 val = (td->lut_safe << DFLL_OUTPUT_CFG_SAFE_SHIFT) |
603− (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) |
604− (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT);
605− dfll_i2c_writel(td, val, DFLL_OUTPUT_CFG);
606− dfll_i2c_wmb(td);
762+ (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) |
763+ (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT);
764+ dfll_writel(td, val, DFLL_OUTPUT_CFG);
765+ dfll_wmb(td);
607766
608767 dfll_writel(td, 0, DFLL_OUTPUT_FORCE);
609768 dfll_i2c_writel(td, 0, DFLL_INTR_EN);
610769 dfll_i2c_writel(td, DFLL_INTR_MAX_MASK | DFLL_INTR_MIN_MASK,
611770 DFLL_INTR_STS);
612771
613− dfll_load_i2c_lut(td);
614− dfll_init_i2c_if(td);
772+ if (td->pmu_if == TEGRA_DFLL_PMU_PWM) {
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+ }
615788 }
616789
617790 /*
@@ -631,17 +804,17 @@ static void dfll_init_out_if(struct tegra_dfll *td) · 13 unmodified lines
631804 static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate)
632805 {
633806 struct dev_pm_opp *opp;
634− int i, uv;
807+ int i, align_step;
635808
636809 opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
637810 if (IS_ERR(opp))
638811 return PTR_ERR(opp);
639812
640− uv = dev_pm_opp_get_voltage(opp);
813+ align_step = dev_pm_opp_get_voltage(opp) / td->soc->alignment.step_uv;
641814 dev_pm_opp_put(opp);
642815
643− for (i = 0; i < td->i2c_lut_size; i++) {
644− if (regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) == uv)
816+ for (i = td->lut_bottom; i < td->lut_size; i++) {
817+ if ((td->lut_uv[i] / td->soc->alignment.step_uv) >= align_step)
645818 return i;
646819 }
647820
@@ -863,9 +1036,14 @@ static int dfll_lock(struct tegra_dfll *td) · 215 unmodified lines
8631036 return -EINVAL;
8641037 }
8651038
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+
8671044 dfll_set_mode(td, DFLL_CLOSED_LOOP);
8681045 dfll_set_frequency_request(td, req);
1046+ dfll_set_force_output_enabled(td, false);
8691047 return 0;
8701048
8711049 default:
@@ -889,7 +1067,10 @@ static int dfll_unlock(struct tegra_dfll *td) · 17 unmodified lines
8891067 case DFLL_CLOSED_LOOP:
8901068 dfll_set_open_loop_config(td);
8911069 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);
8931074 return 0;
8941075
8951076 case DFLL_OPEN_LOOP:
@@ -1171,15 +1352,17 @@ static int attr_registers_show(struct seq_file *s, void *data) · 275 unmodified lines
11711352 seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
11721353 dfll_i2c_readl(td, offs));
11731354
1174− seq_puts(s, "\nINTEGRATED I2C CONTROLLER REGISTERS:\n");
1175− offs = DFLL_I2C_CLK_DIVISOR;
1176− seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
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)
1355+ if (td->pmu_if == TEGRA_DFLL_PMU_I2C) {
1356+ seq_puts(s, "\nINTEGRATED I2C CONTROLLER REGISTERS:\n");
1357+ offs = DFLL_I2C_CLK_DIVISOR;
11811358 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+ }
11831366
11841367 return 0;
11851368 }
@@ -1349,15 +1532,21 @@ di_err1: · 163 unmodified lines
13491532 */
13501533 static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV)
13511534 {
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;
13531539
1540+ align_step = uV / td->soc->alignment.step_uv;
13541541 n_voltages = regulator_count_voltages(td->vdd_reg);
13551542 for (i = 0; i < n_voltages; i++) {
13561543 reg_uV = regulator_list_voltage(td->vdd_reg, i);
13571544 if (reg_uV < 0)
13581545 break;
13591546
1360− if (uV == reg_uV)
1547+ reg_volt_id = reg_uV / td->soc->alignment.step_uv;
1548+
1549+ if (align_step == reg_volt_id)
13611550 return i;
13621551 }
13631552
@@ -1371,15 +1560,21 @@ static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV) · 7 unmodified lines
13711560 * */
13721561 static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
13731562 {
1374− int i, n_voltages, reg_uV;
1563+ int i, n_voltages, reg_uV, reg_volt_id, align_step;
13751564
1565+ if (WARN_ON(td->pmu_if == TEGRA_DFLL_PMU_PWM))
1566+ return -EINVAL;
1567+
1568+ align_step = uV / td->soc->alignment.step_uv;
13761569 n_voltages = regulator_count_voltages(td->vdd_reg);
13771570 for (i = 0; i < n_voltages; i++) {
13781571 reg_uV = regulator_list_voltage(td->vdd_reg, i);
13791572 if (reg_uV < 0)
13801573 break;
13811574
1382− if (uV <= reg_uV)
1575+ reg_volt_id = reg_uV / td->soc->alignment.step_uv;
1576+
1577+ if (align_step <= reg_volt_id)
13831578 return i;
13841579 }
13851580
@@ -1387,9 +1582,61 @@ static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV) · 1 unmodified line
13871582 return -EINVAL;
13881583 }
13891584
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+ */
1594+static 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+
13901636 /**
13911637 * dfll_build_i2c_lut - build the I2C voltage register lookup table
13921638 * @td: DFLL instance
1639+ * @v_max: Vmax from OPP table
13931640 *
13941641 * The DFLL hardware has 33 bytes of look-up table RAM that must be filled with
13951642 * 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) · 1 unmodified line
13971644 * the soc-specific platform driver (td->soc->opp_dev) and the PMIC
13981645 * register-to-voltage mapping queried from the regulator framework.
13991646 *
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.
14011648 */
1402−static int dfll_build_i2c_lut(struct tegra_dfll *td)
1649+static int dfll_build_i2c_lut(struct tegra_dfll *td, unsigned long v_max)
14031650 {
1651+ unsigned long rate, v, v_opp;
14041652 int ret = -EINVAL;
1405− int j, v, v_max, v_opp;
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);
1653+ int j, selector, lut;
14191654
14201655 v = td->soc->cvb->min_millivolts * 1000;
14211656 lut = find_vdd_map_entry_exact(td, v);
14221657 if (lut < 0)
14231658 goto out;
1424− td->i2c_lut[0] = lut;
1659+ td->lut[0] = lut;
1660+ td->lut_bottom = 0;
14251661
14261662 for (j = 1, rate = 0; ; rate++) {
1663+ struct dev_pm_opp *opp;
1664+
14271665 opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
14281666 if (IS_ERR(opp))
14291667 break;
@@ -1435,39 +1673,64 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td) · 5 unmodified lines
14351673 dev_pm_opp_put(opp);
14361674
14371675 for (;;) {
1438− v += max(1, (v_max - v) / (MAX_DFLL_VOLTAGES - j));
1676+ v += max(1UL, (v_max - v) / (MAX_DFLL_VOLTAGES - j));
14391677 if (v >= v_opp)
14401678 break;
14411679
14421680 selector = find_vdd_map_entry_min(td, v);
14431681 if (selector < 0)
14441682 goto out;
1445− if (selector != td->i2c_lut[j - 1])
1446− td->i2c_lut[j++] = selector;
1683+ if (selector != td->lut[j - 1])
1684+ td->lut[j++] = selector;
14471685 }
14481686
14491687 v = (j == MAX_DFLL_VOLTAGES - 1) ? v_max : v_opp;
14501688 selector = find_vdd_map_entry_exact(td, v);
14511689 if (selector < 0)
14521690 goto out;
1453− if (selector != td->i2c_lut[j - 1])
1454− td->i2c_lut[j++] = selector;
1691+ if (selector != td->lut[j - 1])
1692+ td->lut[j++] = selector;
14551693
14561694 if (v >= v_max)
14571695 break;
14581696 }
1459− td->i2c_lut_size = j;
1697+ td->lut_size = j;
14601698
14611699 if (!td->dvco_rate_min)
14621700 dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
14631701 td->soc->cvb->min_millivolts);
1464− else
1702+ else {
14651703 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+ }
14661709
14671710 out:
14681711 return ret;
14691712 }
14701713
1714+static 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+
14711734 /**
14721735 * read_dt_param - helper function for reading required parameters from the DT
14731736 * @td: DFLL instance
@@ -1526,11 +1789,56 @@ static int dfll_fetch_i2c_params(struct tegra_dfll *td) · 52 unmodified lines
15261789 }
15271790 td->i2c_reg = vsel_reg;
15281791
1529− ret = dfll_build_i2c_lut(td);
1530− if (ret) {
1531− dev_err(td->dev, "couldn't build I2C LUT\n");
1792+ return 0;
1793+}
1794+
1795+static 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");
15321819 return ret;
15331820 }
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+ }
15341842
15351843 return 0;
15361844 }
@@ -1597,16 +1905,6 @@ int tegra_dfll_register(struct platform_device *pdev, · 60 unmodified lines
15971905
15981906 td->soc = soc;
15991907
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−
16101908 td->dvco_rst = devm_reset_control_get(td->dev, "dvco");
16111909 if (IS_ERR(td->dvco_rst)) {
16121910 dev_err(td->dev, "couldn't get dvco reset\n");
@@ -1619,10 +1917,27 @@ int tegra_dfll_register(struct platform_device *pdev, · 6 unmodified lines
16191917 return ret;
16201918 }
16211919
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+ }
16231932 if (ret)
16241933 return ret;
16251934
1935+ ret = dfll_build_lut(td);
1936+ if (ret) {
1937+ dev_err(td->dev, "couldn't build LUT\n");
1938+ return ret;
1939+ }
1940+
16261941 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
16271942 if (!mem) {
16281943 dev_err(td->dev, "no control register resource\n");
drivers/clk/tegra/clk-dfll.h+5−1
@@ -1,6 +1,6 @@
11 /*
22 * 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.
44 *
55 * Aleksandr Frid <afrid@nvidia.com>
66 * Paul Walmsley <pwalmsley@nvidia.com>
@@ -22,11 +22,14 @@ · 15 unmodified lines
2222 #include <linux/reset.h>
2323 #include <linux/types.h>
2424
25+#include "cvb.h"
26+
2527 /**
2628 * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver
2729 * @dev: struct device * that holds the OPP table for the DFLL
2830 * @max_freq: maximum frequency supported on this SoC
2931 * @cvb: CPU frequency table for this SoC
32+ * @alignment: parameters of the regulator step and offset
3033 * @init_clock_trimmers: callback to initialize clock trimmers
3134 * @set_clock_trimmers_high: callback to tune clock trimmers for high voltage
3235 * @set_clock_trimmers_low: callback to tune clock trimmers for low voltage
@@ -35,6 +38,7 @@ struct tegra_dfll_soc_data { · 2 unmodified lines
3538 struct device *dev;
3639 unsigned long max_freq;
3740 const struct cvb_table *cvb;
41+ struct rail_alignment alignment;
3842
3943 void (*init_clock_trimmers)(void);
4044 void (*set_clock_trimmers_high)(void);
drivers/clk/tegra/clk-tegra124-dfll-fcpu.c+504−16
@@ -1,7 +1,7 @@
11 /*
22 * Tegra124 DFLL FCPU clock source driver
33 *
4− * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
4+ * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved.
55 *
66 * Aleksandr Frid <afrid@nvidia.com>
77 * Paul Walmsley <pwalmsley@nvidia.com>
@@ -21,15 +21,24 @@ · 13 unmodified lines
2121 #include <linux/err.h>
2222 #include <linux/kernel.h>
2323 #include <linux/init.h>
24+#include <linux/of_device.h>
2425 #include <linux/platform_device.h>
26+#include <linux/regulator/consumer.h>
2527 #include <soc/tegra/fuse.h>
2628
2729 #include "clk.h"
2830 #include "clk-dfll.h"
2931 #include "cvb.h"
3032
33+struct 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+
3140 /* Maximum CPU frequency, indexed by CPU speedo id */
32−static const unsigned long cpu_max_freq_table[] = {
41+static const unsigned long tegra124_cpu_max_freq_table[] = {
3342 [0] = 2014500000UL,
3443 [1] = 2320500000UL,
3544 [2] = 2116500000UL,
@@ -42,9 +51,6 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = { · 6 unmodified lines
4251 .process_id = -1,
4352 .min_millivolts = 900,
4453 .max_millivolts = 1260,
45− .alignment = {
46− .step_uv = 10000, /* 10mV */
47− },
4854 .speedo_scale = 100,
4955 .voltage_scale = 1000,
5056 .entries = {
@@ -82,16 +88,493 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = { · 31 unmodified lines
8288 },
8389 };
8490
91+static 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+
244+static 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+
506+static 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+
513+static 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+
520+static 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+
532+static 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+
546+static 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+
85562 static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
86563 {
87564 int process_id, speedo_id, speedo_value, err;
88565 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;
89572
90573 process_id = tegra_sku_info.cpu_process_id;
91574 speedo_id = tegra_sku_info.cpu_speedo_id;
92575 speedo_value = tegra_sku_info.cpu_speedo_value;
93576
94− if (speedo_id >= ARRAY_SIZE(cpu_max_freq_table)) {
577+ if (speedo_id >= fcpu_data->cpu_max_freq_table_size) {
95578 dev_err(&pdev->dev, "unknown max CPU freq for speedo_id=%d\n",
96579 speedo_id);
97580 return -ENODEV;
@@ -107,12 +590,22 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) · 9 unmodified lines
107590 return -ENODEV;
108591 }
109592
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;
111608
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);
116609 if (IS_ERR(soc->cvb)) {
117610 dev_err(&pdev->dev, "couldn't add OPP table: %ld\n",
118611 PTR_ERR(soc->cvb));
@@ -144,11 +637,6 @@ static int tegra124_dfll_fcpu_remove(struct platform_device *pdev) · 25 unmodified lines
144637 return 0;
145638 }
146639
147−static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
148− { .compatible = "nvidia,tegra124-dfll", },
149− { },
150−};
151−
152640 static const struct dev_pm_ops tegra124_dfll_pm_ops = {
153641 SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
154642 tegra_dfll_runtime_resume, NULL)
drivers/clk/tegra/cvb.c+7−5
@@ -1,7 +1,7 @@
11 /*
22 * Utility functions for parsing Tegra CVB voltage tables
33 *
4− * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
4+ * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved.
55 *
66 * This program is free software; you can redistribute it and/or modify
77 * 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) · 54 unmodified lines
6262 }
6363
6464 static int build_opp_table(struct device *dev, const struct cvb_table *table,
65+ struct rail_alignment *align,
6566 int speedo_value, unsigned long max_freq)
6667 {
67− const struct rail_alignment *align = &table->alignment;
6868 int i, ret, dfll_mv, min_mv, max_mv;
6969
7070 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, · 38 unmodified lines
109109 */
110110 const struct cvb_table *
111111 tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
112− size_t count, int process_id, int speedo_id,
113− int speedo_value, unsigned long max_freq)
112+ size_t count, struct rail_alignment *align,
113+ int process_id, int speedo_id, int speedo_value,
114+ unsigned long max_freq)
114115 {
115116 size_t i;
116117 int ret;
@@ -124,7 +125,8 @@ tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables, · 7 unmodified lines
124125 if (table->process_id != -1 && table->process_id != process_id)
125126 continue;
126127
127− ret = build_opp_table(dev, table, speedo_value, max_freq);
128+ ret = build_opp_table(dev, table, align, speedo_value,
129+ max_freq);
128130 return ret ? ERR_PTR(ret) : table;
129131 }
130132
drivers/clk/tegra/cvb.h+4−3
@@ -41,6 +41,7 @@ struct cvb_cpu_dfll_data { · 40 unmodified lines
4141 u32 tune0_low;
4242 u32 tune0_high;
4343 u32 tune1;
44+ unsigned int tune_high_min_millivolts;
4445 };
4546
4647 struct cvb_table {
@@ -49,7 +50,6 @@ struct cvb_table { · 2 unmodified lines
4950
5051 int min_millivolts;
5152 int max_millivolts;
52− struct rail_alignment alignment;
5353
5454 int speedo_scale;
5555 int voltage_scale;
@@ -59,8 +59,9 @@ struct cvb_table { · 3 unmodified lines
5959
6060 const struct cvb_table *
6161 tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables,
62− size_t count, int process_id, int speedo_id,
63− int speedo_value, unsigned long max_freq);
62+ size_t count, struct rail_alignment *align,
63+ int process_id, int speedo_id, int speedo_value,
64+ unsigned long max_freq);
6465 void tegra_cvb_remove_opp_table(struct device *dev,
6566 const struct cvb_table *table,
6667 unsigned long max_freq);
drivers/cpufreq/Kconfig.arm+2−2
@@ -272,8 +272,8 @@ config ARM_TEGRA20_CPUFREQ · 271 unmodified lines
272272 This adds the CPUFreq driver support for Tegra20 SOCs.
273273
274274 config ARM_TEGRA124_CPUFREQ
275− tristate "Tegra124 CPUFreq support"
276− depends on ARCH_TEGRA && CPUFREQ_DT && REGULATOR
275+ bool "Tegra124 CPUFreq support"
276+ depends on ARCH_TEGRA && CPUFREQ_DT
277277 default y
278278 help
279279 This adds the CPUFreq driver support for Tegra124 SOCs.
drivers/cpufreq/cpufreq-dt-platdev.c+1−0
@@ -119,6 +119,7 @@ static const struct of_device_id blacklist[] __initconst = { · 118 unmodified lines
119119 { .compatible = "mediatek,mt8176", },
120120
121121 { .compatible = "nvidia,tegra124", },
122+ { .compatible = "nvidia,tegra210", },
122123
123124 { .compatible = "qcom,apq8096", },
124125 { .compatible = "qcom,msm8996", },
drivers/cpufreq/tegra124-cpufreq.c+4−40
@@ -22,11 +22,9 @@ · 21 unmodified lines
2222 #include <linux/of.h>
2323 #include <linux/platform_device.h>
2424 #include <linux/pm_opp.h>
25−#include <linux/regulator/consumer.h>
2625 #include <linux/types.h>
2726
2827 struct tegra124_cpufreq_priv {
29− struct regulator *vdd_cpu_reg;
3028 struct clk *cpu_clk;
3129 struct clk *pllp_clk;
3230 struct clk *pllx_clk;
@@ -60,14 +58,6 @@ out: · 27 unmodified lines
6058 return ret;
6159 }
6260
63−static 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−
7161 static int tegra124_cpufreq_probe(struct platform_device *pdev)
7262 {
7363 struct tegra124_cpufreq_priv *priv;
@@ -88,16 +78,10 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev) · 14 unmodified lines
8878 if (!np)
8979 return -ENODEV;
9080
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−
9781 priv->cpu_clk = of_clk_get_by_name(np, "cpu_g");
9882 if (IS_ERR(priv->cpu_clk)) {
9983 ret = PTR_ERR(priv->cpu_clk);
100− goto out_put_vdd_cpu_reg;
84+ goto out_put_np;
10185 }
10286
10387 priv->dfll_clk = of_clk_get_by_name(np, "dfll");
@@ -129,15 +113,13 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev) · 25 unmodified lines
129113 platform_device_register_full(&cpufreq_dt_devinfo);
130114 if (IS_ERR(priv->cpufreq_dt_pdev)) {
131115 ret = PTR_ERR(priv->cpufreq_dt_pdev);
132− goto out_switch_to_pllx;
116+ goto out_put_pllp_clk;
133117 }
134118
135119 platform_set_drvdata(pdev, priv);
136120
137121 return 0;
138122
139−out_switch_to_pllx:
140− tegra124_cpu_switch_to_pllx(priv);
141123 out_put_pllp_clk:
142124 clk_put(priv->pllp_clk);
143125 out_put_pllx_clk:
@@ -146,34 +128,15 @@ out_put_dfll_clk: · 2 unmodified lines
146128 clk_put(priv->dfll_clk);
147129 out_put_cpu_clk:
148130 clk_put(priv->cpu_clk);
149−out_put_vdd_cpu_reg:
150− regulator_put(priv->vdd_cpu_reg);
151131 out_put_np:
152132 of_node_put(np);
153133
154134 return ret;
155135 }
156136
157−static 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−
173137 static struct platform_driver tegra124_cpufreq_platdrv = {
174138 .driver.name = "cpufreq-tegra124",
175139 .probe = tegra124_cpufreq_probe,
176− .remove = tegra124_cpufreq_remove,
177140 };
178141
179142 static int __init tegra_cpufreq_init(void)
@@ -181,7 +144,8 @@ static int __init tegra_cpufreq_init(void) · 1 unmodified line
181144 int ret;
182145 struct platform_device *pdev;
183146
184− if (!of_machine_is_compatible("nvidia,tegra124"))
147+ if (!(of_machine_is_compatible("nvidia,tegra124") ||
148+ of_machine_is_compatible("nvidia,tegra210")))
185149 return -ENODEV;
186150
187151 /*
drivers/firmware/imx/misc.c+38−0
@@ -18,6 +18,14 @@ struct imx_sc_msg_req_misc_set_ctrl { · 17 unmodified lines
1818 u16 resource;
1919 } __packed;
2020
21+struct 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+
2129 struct imx_sc_msg_req_misc_get_ctrl {
2230 struct imx_sc_rpc_msg hdr;
2331 u32 ctrl;
@@ -97,3 +105,33 @@ int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource, · 73 unmodified lines
97105 return 0;
98106 }
99107 EXPORT_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+ */
119+int 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+}
137+EXPORT_SYMBOL(imx_sc_pm_cpu_start);
drivers/firmware/imx/scu-pd.c+1−0
@@ -322,6 +322,7 @@ static int imx_sc_pd_probe(struct platform_device *pdev) · 321 unmodified lines
322322
323323 static const struct of_device_id imx_sc_pd_match[] = {
324324 { .compatible = "fsl,imx8qxp-scu-pd", &imx8qxp_scu_pd},
325+ { .compatible = "fsl,scu-pd", &imx8qxp_scu_pd},
325326 { /* sentinel */ }
326327 };
327328
drivers/firmware/raspberrypi.c+11−0
@@ -238,6 +238,16 @@ static int rpi_firmware_probe(struct platform_device *pdev) · 237 unmodified lines
238238 return 0;
239239 }
240240
241+static 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+
241251 static int rpi_firmware_remove(struct platform_device *pdev)
242252 {
243253 struct rpi_firmware *fw = platform_get_drvdata(pdev);
@@ -278,6 +288,7 @@ static struct platform_driver rpi_firmware_driver = { · 34 unmodified lines
278288 .of_match_table = rpi_firmware_of_match,
279289 },
280290 .probe = rpi_firmware_probe,
291+ .shutdown = rpi_firmware_shutdown,
281292 .remove = rpi_firmware_remove,
282293 };
283294 module_platform_driver(rpi_firmware_driver);
drivers/firmware/tegra/Makefile+3−0
@@ -1,4 +1,7 @@
11 tegra-bpmp-y = bpmp.o
2+tegra-bpmp-$(CONFIG_ARCH_TEGRA_210_SOC) += bpmp-tegra210.o
3+tegra-bpmp-$(CONFIG_ARCH_TEGRA_186_SOC) += bpmp-tegra186.o
4+tegra-bpmp-$(CONFIG_ARCH_TEGRA_194_SOC) += bpmp-tegra186.o
25 tegra-bpmp-$(CONFIG_DEBUG_FS) += bpmp-debugfs.o
36 obj-$(CONFIG_TEGRA_BPMP) += tegra-bpmp.o
47 obj-$(CONFIG_TEGRA_IVC) += ivc.o
drivers/firmware/tegra/bpmp-private.h+34−0
@@ -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+
11+struct 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)
28+extern const struct tegra_bpmp_ops tegra186_bpmp_ops;
29+#endif
30+#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
31+extern const struct tegra_bpmp_ops tegra210_bpmp_ops;
32+#endif
33+
34+#endif
drivers/firmware/tegra/bpmp-tegra186.c+305−0
@@ -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+
16+struct 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+
31+static inline struct tegra_bpmp *
32+mbox_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+
41+static 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+
56+static 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+
71+static int tegra186_bpmp_ack_message(struct tegra_bpmp_channel *channel)
72+{
73+ return tegra_ivc_read_advance(channel->ivc);
74+}
75+
76+static int tegra186_bpmp_post_message(struct tegra_bpmp_channel *channel)
77+{
78+ return tegra_ivc_write_advance(channel->ivc);
79+}
80+
81+static 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+
95+static 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+
106+static 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+
141+static 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+
151+static void tegra186_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
152+{
153+ tegra_ivc_cleanup(channel->ivc);
154+}
155+
156+static 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+
163+static 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+
242+cleanup_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);
251+cleanup_tx_channel:
252+ tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
253+free_rx:
254+ gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
255+free_tx:
256+ gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
257+
258+ return err;
259+}
260+
261+static 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+
278+static 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+
292+const 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+};
drivers/firmware/tegra/bpmp-tegra210.c+243−0
@@ -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+
31+struct tegra210_bpmp {
32+ void __iomem *atomics;
33+ void __iomem *arb_sema;
34+ struct irq_data *tx_irq_data;
35+};
36+
37+static 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+
44+static 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+
51+static 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+
58+static bool
59+tegra210_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+
66+static bool
67+tegra210_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+
74+static 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+
83+static 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+
92+static 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+
102+static 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+
111+static 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+
126+static 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+
135+static 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+
161+static 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+
232+const 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+};
drivers/firmware/tegra/bpmp.c+150−226
@@ -26,6 +26,8 @@ · 25 unmodified lines
2626 #include <soc/tegra/bpmp-abi.h>
2727 #include <soc/tegra/ivc.h>
2828
29+#include "bpmp-private.h"
30+
2931 #define MSG_ACK BIT(0)
3032 #define MSG_RING BIT(1)
3133 #define TAG_SZ 32
@@ -36,6 +38,14 @@ mbox_client_to_bpmp(struct mbox_client *client) · 4 unmodified lines
3638 return container_of(client, struct tegra_bpmp, mbox.client);
3739 }
3840
41+static inline const struct tegra_bpmp_ops *
42+channel_to_ops(struct tegra_bpmp_channel *channel)
43+{
44+ struct tegra_bpmp *bpmp = channel->bpmp;
45+
46+ return bpmp->soc->ops;
47+}
48+
3949 struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
4050 {
4151 struct platform_device *pdev;
@@ -96,22 +106,21 @@ static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg) · 54 unmodified lines
96106 (msg->rx.size == 0 || msg->rx.data);
97107 }
98108
99−static bool tegra_bpmp_master_acked(struct tegra_bpmp_channel *channel)
109+static bool tegra_bpmp_is_response_ready(struct tegra_bpmp_channel *channel)
100110 {
101− void *frame;
111+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
102112
103− frame = tegra_ivc_read_get_next_frame(channel->ivc);
104− if (IS_ERR(frame)) {
105− channel->ib = NULL;
106− return false;
107− }
113+ return ops->is_response_ready(channel);
114+}
108115
109− channel->ib = frame;
116+static bool tegra_bpmp_is_request_ready(struct tegra_bpmp_channel *channel)
117+{
118+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
110119
111− return true;
120+ return ops->is_request_ready(channel);
112121 }
113122
114−static int tegra_bpmp_wait_ack(struct tegra_bpmp_channel *channel)
123+static int tegra_bpmp_wait_response(struct tegra_bpmp_channel *channel)
115124 {
116125 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
117126 ktime_t end;
@@ -119,29 +128,45 @@ static int tegra_bpmp_wait_ack(struct tegra_bpmp_channel *channel) · 1 unmodified line
119128 end = ktime_add_us(ktime_get(), timeout);
120129
121130 do {
122− if (tegra_bpmp_master_acked(channel))
131+ if (tegra_bpmp_is_response_ready(channel))
123132 return 0;
124133 } while (ktime_before(ktime_get(), end));
125134
126135 return -ETIMEDOUT;
127136 }
128137
129−static bool tegra_bpmp_master_free(struct tegra_bpmp_channel *channel)
138+static int tegra_bpmp_ack_response(struct tegra_bpmp_channel *channel)
130139 {
131− void *frame;
140+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
132141
133− frame = tegra_ivc_write_get_next_frame(channel->ivc);
134− if (IS_ERR(frame)) {
135− channel->ob = NULL;
136− return false;
137− }
142+ return ops->ack_response(channel);
143+}
138144
139− channel->ob = frame;
145+static int tegra_bpmp_ack_request(struct tegra_bpmp_channel *channel)
146+{
147+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
140148
141− return true;
149+ return ops->ack_request(channel);
142150 }
143151
144−static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel)
152+static bool
153+tegra_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+
160+static bool
161+tegra_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+
168+static int
169+tegra_bpmp_wait_request_channel_free(struct tegra_bpmp_channel *channel)
145170 {
146171 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
147172 ktime_t start, now;
@@ -149,7 +174,7 @@ static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel) · 1 unmodified line
149174 start = ns_to_ktime(local_clock());
150175
151176 do {
152− if (tegra_bpmp_master_free(channel))
177+ if (tegra_bpmp_is_request_channel_free(channel))
153178 return 0;
154179
155180 now = ns_to_ktime(local_clock());
@@ -158,6 +183,25 @@ static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel) · 2 unmodified lines
158183 return -ETIMEDOUT;
159184 }
160185
186+static 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+
193+static 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+
200+static int tegra_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
201+{
202+ return bpmp->soc->ops->ring_doorbell(bpmp);
203+}
204+
161205 static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
162206 void *data, size_t size, int *ret)
163207 {
@@ -166,7 +210,7 @@ static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, · 2 unmodified lines
166210 if (data && size > 0)
167211 memcpy(data, channel->ib->data, size);
168212
169− err = tegra_ivc_read_advance(channel->ivc);
213+ err = tegra_bpmp_ack_response(channel);
170214 if (err < 0)
171215 return err;
172216
@@ -210,7 +254,7 @@ static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel, · 37 unmodified lines
210254 if (data && size > 0)
211255 memcpy(channel->ob->data, data, size);
212256
213− return tegra_ivc_write_advance(channel->ivc);
257+ return tegra_bpmp_post_request(channel);
214258 }
215259
216260 static struct tegra_bpmp_channel *
@@ -238,7 +282,7 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq, · 21 unmodified lines
238282
239283 channel = &bpmp->threaded_channels[index];
240284
241− if (!tegra_bpmp_master_free(channel)) {
285+ if (!tegra_bpmp_is_request_channel_free(channel)) {
242286 err = -EBUSY;
243287 goto unlock;
244288 }
@@ -270,7 +314,7 @@ static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel, · 25 unmodified lines
270314 {
271315 int err;
272316
273− err = tegra_bpmp_wait_master_free(channel);
317+ err = tegra_bpmp_wait_request_channel_free(channel);
274318 if (err < 0)
275319 return err;
276320
@@ -302,13 +346,11 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp, · 25 unmodified lines
302346
303347 spin_unlock(&bpmp->atomic_tx_lock);
304348
305− err = mbox_send_message(bpmp->mbox.channel, NULL);
349+ err = tegra_bpmp_ring_doorbell(bpmp);
306350 if (err < 0)
307351 return err;
308352
309− mbox_client_txdone(bpmp->mbox.channel, 0);
310−
311− err = tegra_bpmp_wait_ack(channel);
353+ err = tegra_bpmp_wait_response(channel);
312354 if (err < 0)
313355 return err;
314356
@@ -335,12 +377,10 @@ int tegra_bpmp_transfer(struct tegra_bpmp *bpmp, · 20 unmodified lines
335377 if (IS_ERR(channel))
336378 return PTR_ERR(channel);
337379
338− err = mbox_send_message(bpmp->mbox.channel, NULL);
380+ err = tegra_bpmp_ring_doorbell(bpmp);
339381 if (err < 0)
340382 return err;
341383
342− mbox_client_txdone(bpmp->mbox.channel, 0);
343−
344384 timeout = usecs_to_jiffies(bpmp->soc->channels.thread.timeout);
345385
346386 err = wait_for_completion_timeout(&channel->completion, timeout);
@@ -369,38 +409,34 @@ void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code, · 22 unmodified lines
369409 {
370410 unsigned long flags = channel->ib->flags;
371411 struct tegra_bpmp *bpmp = channel->bpmp;
372− struct tegra_bpmp_mb_data *frame;
373412 int err;
374413
375414 if (WARN_ON(size > MSG_DATA_MIN_SZ))
376415 return;
377416
378− err = tegra_ivc_read_advance(channel->ivc);
417+ err = tegra_bpmp_ack_request(channel);
379418 if (WARN_ON(err < 0))
380419 return;
381420
382421 if ((flags & MSG_ACK) == 0)
383422 return;
384423
385− frame = tegra_ivc_write_get_next_frame(channel->ivc);
386− if (WARN_ON(IS_ERR(frame)))
424+ if (WARN_ON(!tegra_bpmp_is_response_channel_free(channel)))
387425 return;
388426
389− frame->code = code;
427+ channel->ob->code = code;
390428
391429 if (data && size > 0)
392− memcpy(frame->data, data, size);
430+ memcpy(channel->ob->data, data, size);
393431
394− err = tegra_ivc_write_advance(channel->ivc);
432+ err = tegra_bpmp_post_response(channel);
395433 if (WARN_ON(err < 0))
396434 return;
397435
398436 if (flags & MSG_RING) {
399− err = mbox_send_message(bpmp->mbox.channel, NULL);
437+ err = tegra_bpmp_ring_doorbell(bpmp);
400438 if (WARN_ON(err < 0))
401439 return;
402−
403− mbox_client_txdone(bpmp->mbox.channel, 0);
404440 }
405441 }
406442 EXPORT_SYMBOL_GPL(tegra_bpmp_mrq_return);
@@ -627,9 +663,8 @@ static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel) · 220 unmodified lines
627663 complete(&channel->completion);
628664 }
629665
630−static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
666+void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp)
631667 {
632− struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
633668 struct tegra_bpmp_channel *channel;
634669 unsigned int i, count;
635670 unsigned long *busy;
@@ -638,7 +673,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data) · 2 unmodified lines
638673 count = bpmp->soc->channels.thread.count;
639674 busy = bpmp->threaded.busy;
640675
641− if (tegra_bpmp_master_acked(channel))
676+ if (tegra_bpmp_is_request_ready(channel))
642677 tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel);
643678
644679 spin_lock(&bpmp->lock);
@@ -648,7 +683,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data) · 3 unmodified lines
648683
649684 channel = &bpmp->threaded_channels[i];
650685
651− if (tegra_bpmp_master_acked(channel)) {
686+ if (tegra_bpmp_is_response_ready(channel)) {
652687 tegra_bpmp_channel_signal(channel);
653688 clear_bit(i, busy);
654689 }
@@ -657,74 +692,9 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data) · 2 unmodified lines
657692 spin_unlock(&bpmp->lock);
658693 }
659694
660−static 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−
675−static 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−
709−static 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−
719−static void tegra_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
720−{
721− tegra_ivc_cleanup(channel->ivc);
722−}
723−
724695 static int tegra_bpmp_probe(struct platform_device *pdev)
725696 {
726697 struct tegra_bpmp *bpmp;
727− unsigned int i;
728698 char tag[TAG_SZ];
729699 size_t size;
730700 int err;
@@ -736,32 +706,6 @@ static int tegra_bpmp_probe(struct platform_device *pdev) · 5 unmodified lines
736706 bpmp->soc = of_device_get_match_data(&pdev->dev);
737707 bpmp->dev = &pdev->dev;
738708
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−
765709 INIT_LIST_HEAD(&bpmp->mrqs);
766710 spin_lock_init(&bpmp->lock);
767711
@@ -771,81 +715,38 @@ static int tegra_bpmp_probe(struct platform_device *pdev) · 3 unmodified lines
771715 size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long);
772716
773717 bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
774− if (!bpmp->threaded.allocated) {
775− err = -ENOMEM;
776− goto free_rx;
777− }
718+ if (!bpmp->threaded.allocated)
719+ return -ENOMEM;
778720
779721 bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
780− if (!bpmp->threaded.busy) {
781− err = -ENOMEM;
782− goto free_rx;
783− }
722+ if (!bpmp->threaded.busy)
723+ return -ENOMEM;
784724
785725 spin_lock_init(&bpmp->atomic_tx_lock);
786726 bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel),
787727 GFP_KERNEL);
788− if (!bpmp->tx_channel) {
789− err = -ENOMEM;
790− goto free_rx;
791− }
728+ if (!bpmp->tx_channel)
729+ return -ENOMEM;
792730
793731 bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel),
794732 GFP_KERNEL);
795− if (!bpmp->rx_channel) {
796− err = -ENOMEM;
797− goto free_rx;
798− }
733+ if (!bpmp->rx_channel)
734+ return -ENOMEM;
799735
800736 bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count,
801737 sizeof(*bpmp->threaded_channels),
802738 GFP_KERNEL);
803− if (!bpmp->threaded_channels) {
804− err = -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;
739+ if (!bpmp->threaded_channels)
740+ return -ENOMEM;
812741
813− err = tegra_bpmp_channel_init(bpmp->rx_channel, bpmp,
814− bpmp->soc->channels.cpu_rx.offset);
742+ err = bpmp->soc->ops->init(bpmp);
815743 if (err < 0)
816− goto cleanup_tx_channel;
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]);
744+ return err;
844745
845746 err = tegra_bpmp_request_mrq(bpmp, MRQ_PING,
846747 tegra_bpmp_mrq_handle_ping, bpmp);
847748 if (err < 0)
848− goto free_mbox;
749+ goto deinit;
849750
850751 err = tegra_bpmp_ping(bpmp);
851752 if (err < 0) {
@@ -867,17 +768,23 @@ static int tegra_bpmp_probe(struct platform_device *pdev) · 15 unmodified lines
867768 if (err < 0)
868769 goto free_mrq;
869770
870− err = tegra_bpmp_init_clocks(bpmp);
871− if (err < 0)
872− goto free_mrq;
771+ if (of_find_property(pdev->dev.of_node, "#clock-cells", NULL)) {
772+ err = tegra_bpmp_init_clocks(bpmp);
773+ if (err < 0)
774+ goto free_mrq;
775+ }
873776
874− err = tegra_bpmp_init_resets(bpmp);
875− if (err < 0)
876− goto free_mrq;
777+ if (of_find_property(pdev->dev.of_node, "#reset-cells", NULL)) {
778+ err = tegra_bpmp_init_resets(bpmp);
779+ if (err < 0)
780+ goto free_mrq;
781+ }
877782
878− err = tegra_bpmp_init_powergates(bpmp);
879− if (err < 0)
880− goto free_mrq;
783+ if (of_find_property(pdev->dev.of_node, "#power-domain-cells", NULL)) {
784+ err = tegra_bpmp_init_powergates(bpmp);
785+ if (err < 0)
786+ goto free_mrq;
787+ }
881788
882789 err = tegra_bpmp_init_debugfs(bpmp);
883790 if (err < 0)
@@ -887,41 +794,27 @@ static int tegra_bpmp_probe(struct platform_device *pdev) · 3 unmodified lines
887794
888795 free_mrq:
889796 tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp);
890−free_mbox:
891− mbox_free_channel(bpmp->mbox.channel);
892−cleanup_threaded_channels:
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− }
797+deinit:
798+ if (bpmp->soc->ops->deinit)
799+ bpmp->soc->ops->deinit(bpmp);
897800
898− tegra_bpmp_channel_cleanup(bpmp->rx_channel);
899−cleanup_tx_channel:
900− tegra_bpmp_channel_cleanup(bpmp->tx_channel);
901−free_rx:
902− gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096);
903−free_tx:
904− gen_pool_free(bpmp->tx.pool, (unsigned long)bpmp->tx.virt, 4096);
905801 return err;
906802 }
907803
908804 static int __maybe_unused tegra_bpmp_resume(struct device *dev)
909805 {
910806 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]);
919807
920− return 0;
808+ if (bpmp->soc->ops->resume)
809+ return bpmp->soc->ops->resume(bpmp);
810+ else
811+ return 0;
921812 }
922813
923814 static SIMPLE_DEV_PM_OPS(tegra_bpmp_pm_ops, NULL, tegra_bpmp_resume);
924815
816+#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
817+ IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
925818 static const struct tegra_bpmp_soc tegra186_soc = {
926819 .channels = {
927820 .cpu_tx = {
@@ -938,11 +831,42 @@ static const struct tegra_bpmp_soc tegra186_soc = { · 10 unmodified lines
938831 .timeout = 0,
939832 },
940833 },
834+ .ops = &tegra186_bpmp_ops,
941835 .num_resets = 193,
942836 };
837+#endif
838+
839+#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
840+static 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
943861
944862 static 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)
945865 { .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
946870 { }
947871 };
948872
drivers/firmware/ti_sci.c+2−19
@@ -146,25 +146,8 @@ static int ti_sci_debug_show(struct seq_file *s, void *unused) · 145 unmodified lines
146146 return 0;
147147 }
148148
149−/**
150− * ti_sci_debug_open() - debug file open
151− * @inode: inode pointer
152− * @file: file pointer
153− *
154− * Return: result of single_open
155− */
156−static 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 */
162−static 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−};
149+/* Provide the log file operations interface*/
150+DEFINE_SHOW_ATTRIBUTE(ti_sci_debug);
168151
169152 /**
170153 * ti_sci_debugfs_create() - Create log debug file
drivers/firmware/xilinx/Kconfig+1−0
@@ -6,6 +6,7 @@ menu "Zynq MPSoC Firmware Drivers" · 5 unmodified lines
66
77 config ZYNQMP_FIRMWARE
88 bool "Enable Xilinx Zynq MPSoC firmware interface"
9+ select MFD_CORE
910 help
1011 Firmware interface driver is used by different
1112 drivers to communicate with the firmware for
drivers/firmware/xilinx/zynqmp.c+166−0
@@ -14,6 +14,7 @@ · 13 unmodified lines
1414 #include <linux/compiler.h>
1515 #include <linux/device.h>
1616 #include <linux/init.h>
17+#include <linux/mfd/core.h>
1718 #include <linux/module.h>
1819 #include <linux/of.h>
1920 #include <linux/of_platform.h>
@@ -23,6 +24,12 @@ · 3 unmodified lines
2324 #include <linux/firmware/xlnx-zynqmp.h>
2425 #include "zynqmp-debug.h"
2526
27+static const struct mfd_cell firmware_devs[] = {
28+ {
29+ .name = "zynqmp_power_controller",
30+ },
31+};
32+
2633 /**
2734 * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
2835 * @ret_status: PMUFW return code
@@ -186,6 +193,29 @@ static int zynqmp_pm_get_api_version(u32 *version) · 157 unmodified lines
186193 return ret;
187194 }
188195
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+ */
204+static 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+
189219 /**
190220 * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
191221 * @version: Returned version value
@@ -469,8 +499,129 @@ static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, · 277 unmodified lines
469499 arg1, arg2, out);
470500 }
471501
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+ */
510+static 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+ */
524+static 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+ */
549+static 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+ */
562+static 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+ */
579+static 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+ */
597+static 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+ */
614+static 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+
472622 static const struct zynqmp_eemi_ops eemi_ops = {
473623 .get_api_version = zynqmp_pm_get_api_version,
624+ .get_chipid = zynqmp_pm_get_chipid,
474625 .query_data = zynqmp_pm_query_data,
475626 .clock_enable = zynqmp_pm_clock_enable,
476627 .clock_disable = zynqmp_pm_clock_disable,
@@ -482,6 +633,13 @@ static const struct zynqmp_eemi_ops eemi_ops = { · 5 unmodified lines
482633 .clock_setparent = zynqmp_pm_clock_setparent,
483634 .clock_getparent = zynqmp_pm_clock_getparent,
484635 .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,
485643 };
486644
487645 /**
@@ -538,11 +696,19 @@ static int zynqmp_firmware_probe(struct platform_device *pdev) · 50 unmodified lines
538696
539697 zynqmp_pm_api_debugfs_init();
540698
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+
541706 return of_platform_populate(dev->of_node, NULL, NULL, dev);
542707 }
543708
544709 static int zynqmp_firmware_remove(struct platform_device *pdev)
545710 {
711+ mfd_remove_devices(&pdev->dev);
546712 zynqmp_pm_api_debugfs_exit();
547713
548714 return 0;
drivers/mfd/Makefile+1−0
@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o · 9 unmodified lines
1010 obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
1111 obj-$(CONFIG_MFD_SM501) += sm501.o
1212 obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
13+obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
1314 obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
1415 obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
1516 cros_ec_core-objs := cros_ec.o
drivers/mfd/bcm2835-pm.c+92−0
@@ -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+
20+static const struct mfd_cell bcm2835_pm_devs[] = {
21+ { .name = "bcm2835-wdt" },
22+};
23+
24+static const struct mfd_cell bcm2835_power_devs[] = {
25+ { .name = "bcm2835-power" },
26+};
27+
28+static 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+
74+static const struct of_device_id bcm2835_pm_of_match[] = {
75+ { .compatible = "brcm,bcm2835-pm-wdt", },
76+ { .compatible = "brcm,bcm2835-pm", },
77+ {},
78+};
79+MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
80+
81+static 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+};
88+module_platform_driver(bcm2835_pm_driver);
89+
90+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
91+MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD");
92+MODULE_LICENSE("GPL");
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c+6−1
@@ -2468,9 +2468,14 @@ static int setup_rx_flow(struct dpaa2_eth_priv *priv, · 2467 unmodified lines
24682468 queue.destination.type = DPNI_DEST_DPCON;
24692469 queue.destination.priority = 1;
24702470 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;
24712475 err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
24722476 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,
24742479 &queue);
24752480 if (err) {
24762481 dev_err(dev, "dpni_set_queue(RX) failed\n");
drivers/nvmem/Kconfig+10−0
@@ -192,4 +192,14 @@ config SC27XX_EFUSE · 191 unmodified lines
192192 This driver can also be built as a module. If so, the module
193193 will be called nvmem-sc27xx-efuse.
194194
195+config 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+
195205 endif
drivers/nvmem/Makefile+2−0
@@ -41,3 +41,5 @@ obj-$(CONFIG_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o · 40 unmodified lines
4141 nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
4242 obj-$(CONFIG_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o
4343 nvmem-sc27xx-efuse-y := sc27xx-efuse.o
44+obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o
45+nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o
drivers/nvmem/zynqmp_nvmem.c+86−0
@@ -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+
14+struct zynqmp_nvmem_data {
15+ struct device *dev;
16+ struct nvmem_device *nvmem;
17+};
18+
19+static 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+
41+static 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+
49+static const struct of_device_id zynqmp_nvmem_match[] = {
50+ { .compatible = "xlnx,zynqmp-nvmem-fw", },
51+ { /* sentinel */ },
52+};
53+MODULE_DEVICE_TABLE(of, zynqmp_nvmem_match);
54+
55+static 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+
74+static 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+
82+module_platform_driver(zynqmp_nvmem_driver);
83+
84+MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>, Nava kishore Manne <navam@xilinx.com>");
85+MODULE_DESCRIPTION("ZynqMP NVMEM driver");
86+MODULE_LICENSE("GPL");
drivers/opp/core.c+18−0
@@ -130,6 +130,24 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp) · 129 unmodified lines
130130 }
131131 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
132132
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+ */
140+unsigned 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+}
149+EXPORT_SYMBOL_GPL(dev_pm_opp_get_level);
150+
133151 /**
134152 * dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not
135153 * @opp: opp for which turbo mode is being verified
drivers/opp/of.c+2−0
@@ -594,6 +594,8 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table, · 593 unmodified lines
594594 new_opp->rate = (unsigned long)rate;
595595 }
596596
597+ of_property_read_u32(np, "opp-level", &new_opp->level);
598+
597599 /* Check if the OPP supports hardware's hierarchy of versions or not */
598600 if (!_opp_is_supported(dev, opp_table, np)) {
599601 dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate);
drivers/opp/opp.h+2−0
@@ -60,6 +60,7 @@ extern struct list_head opp_tables; · 59 unmodified lines
6060 * @suspend: true if suspend OPP
6161 * @pstate: Device's power domain's performance state.
6262 * @rate: Frequency in hertz
63+ * @level: Performance level
6364 * @supplies: Power supplies voltage/current values
6465 * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
6566 * frequency from any other OPP's frequency.
@@ -80,6 +81,7 @@ struct dev_pm_opp { · 14 unmodified lines
8081 bool suspend;
8182 unsigned int pstate;
8283 unsigned long rate;
84+ unsigned int level;
8385
8486 struct dev_pm_opp_supply *supplies;
8587
drivers/reset/Kconfig+10−2
@@ -40,6 +40,14 @@ config RESET_BERLIN · 39 unmodified lines
4040 help
4141 This enables the reset controller driver for Marvell Berlin SoCs.
4242
43+config 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+
4351 config RESET_HSDK
4452 bool "Synopsys HSDK Reset Driver"
4553 depends on HAS_IOMEM
@@ -48,9 +56,9 @@ config RESET_HSDK · 2 unmodified lines
4856 This enables the reset controller driver for HSDK board.
4957
5058 config RESET_IMX7
51− bool "i.MX7 Reset Driver" if COMPILE_TEST
59+ bool "i.MX7/8 Reset Driver" if COMPILE_TEST
5260 depends on HAS_IOMEM
53− default SOC_IMX7D
61+ default SOC_IMX7D || (ARM64 && ARCH_MXC)
5462 select MFD_SYSCON
5563 help
5664 This enables the reset controller driver for i.MX7 SoCs.
drivers/reset/Makefile+2−0
@@ -7,6 +7,7 @@ obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o · 6 unmodified lines
77 obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
88 obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o
99 obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
10+obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
1011 obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
1112 obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
1213 obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
@@ -26,4 +27,5 @@ obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o · 13 unmodified lines
2627 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
2728 obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
2829 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
30+obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
2931
drivers/reset/reset-brcmstb.c+132−0
@@ -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+
17+struct 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+
34+static inline
35+struct brcmstb_reset *to_brcmstb(struct reset_controller_dev *rcdev)
36+{
37+ return container_of(rcdev, struct brcmstb_reset, rcdev);
38+}
39+
40+static 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+
51+static 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+
67+static 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+
77+static 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+
83+static 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+
116+static const struct of_device_id brcmstb_reset_of_match[] = {
117+ { .compatible = "brcm,brcmstb-reset" },
118+ { /* sentinel */ }
119+};
120+
121+static 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+};
128+module_platform_driver(brcmstb_reset_driver);
129+
130+MODULE_AUTHOR("Broadcom");
131+MODULE_DESCRIPTION("Broadcom STB reset controller");
132+MODULE_LICENSE("GPL");
drivers/reset/reset-imx7.c+158−14
@@ -17,14 +17,27 @@ · 16 unmodified lines
1717
1818 #include <linux/mfd/syscon.h>
1919 #include <linux/mod_devicetable.h>
20+#include <linux/of_device.h>
2021 #include <linux/platform_device.h>
2122 #include <linux/reset-controller.h>
2223 #include <linux/regmap.h>
2324 #include <dt-bindings/reset/imx7-reset.h>
25+#include <dt-bindings/reset/imx8mq-reset.h>
26+
27+struct imx7_src_signal {
28+ unsigned int offset, bit;
29+};
30+
31+struct imx7_src_variant {
32+ const struct imx7_src_signal *signals;
33+ unsigned int signals_num;
34+ struct reset_control_ops ops;
35+};
2436
2537 struct imx7_src {
2638 struct reset_controller_dev rcdev;
2739 struct regmap *regmap;
40+ const struct imx7_src_signal *signals;
2841 };
2942
3043 enum imx7_src_registers {
@@ -39,9 +52,14 @@ enum imx7_src_registers { · 8 unmodified lines
3952 SRC_DDRC_RCR = 0x1000,
4053 };
4154
42−struct imx7_src_signal {
43− unsigned int offset, bit;
44−};
55+static int imx7_reset_update(struct imx7_src *imx7src,
56+ unsigned long id, unsigned int value)
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+}
4563
4664 static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
4765 [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
@@ -81,8 +99,8 @@ static int imx7_reset_set(struct reset_controller_dev *rcdev, · 33 unmodified lines
8199 unsigned long id, bool assert)
82100 {
83101 struct imx7_src *imx7src = to_imx7_src(rcdev);
84− const struct imx7_src_signal *signal = &imx7_src_signals[id];
85− unsigned int value = assert ? signal->bit : 0;
102+ const unsigned int bit = imx7src->signals[id].bit;
103+ unsigned int value = assert ? bit : 0;
86104
87105 switch (id) {
88106 case IMX7_RESET_PCIEPHY:
@@ -95,12 +113,11 @@ static int imx7_reset_set(struct reset_controller_dev *rcdev, · 6 unmodified lines
95113 break;
96114
97115 case IMX7_RESET_PCIE_CTRL_APPS_EN:
98− value = (assert) ? 0 : signal->bit;
116+ value = assert ? 0 : bit;
99117 break;
100118 }
101119
102− return regmap_update_bits(imx7src->regmap,
103− signal->offset, signal->bit, value);
120+ return imx7_reset_update(imx7src, id, value);
104121 }
105122
106123 static int imx7_reset_assert(struct reset_controller_dev *rcdev,
@@ -115,9 +132,133 @@ static int imx7_reset_deassert(struct reset_controller_dev *rcdev, · 8 unmodified lines
115132 return imx7_reset_set(rcdev, id, false);
116133 }
117134
118−static const struct reset_control_ops imx7_reset_ops = {
119− .assert = imx7_reset_assert,
120− .deassert = imx7_reset_deassert,
135+static const struct imx7_src_variant variant_imx7 = {
136+ .signals = imx7_src_signals,
137+ .signals_num = ARRAY_SIZE(imx7_src_signals),
138+ .ops = {
139+ .assert = imx7_reset_assert,
140+ .deassert = imx7_reset_deassert,
141+ },
142+};
143+
144+enum 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+
156+static 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+
211+static 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+
243+static int imx8mq_reset_assert(struct reset_controller_dev *rcdev,
244+ unsigned long id)
245+{
246+ return imx8mq_reset_set(rcdev, id, true);
247+}
248+
249+static int imx8mq_reset_deassert(struct reset_controller_dev *rcdev,
250+ unsigned long id)
251+{
252+ return imx8mq_reset_set(rcdev, id, false);
253+}
254+
255+static 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+ },
121262 };
122263
123264 static int imx7_reset_probe(struct platform_device *pdev)
@@ -125,11 +266,13 @@ static int imx7_reset_probe(struct platform_device *pdev) · 1 unmodified line
125266 struct imx7_src *imx7src;
126267 struct device *dev = &pdev->dev;
127268 struct regmap_config config = { .name = "src" };
269+ const struct imx7_src_variant *variant = of_device_get_match_data(dev);
128270
129271 imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
130272 if (!imx7src)
131273 return -ENOMEM;
132274
275+ imx7src->signals = variant->signals;
133276 imx7src->regmap = syscon_node_to_regmap(dev->of_node);
134277 if (IS_ERR(imx7src->regmap)) {
135278 dev_err(dev, "Unable to get imx7-src regmap");
@@ -138,15 +281,16 @@ static int imx7_reset_probe(struct platform_device *pdev) · 2 unmodified lines
138281 regmap_attach_dev(dev, imx7src->regmap, &config);
139282
140283 imx7src->rcdev.owner = THIS_MODULE;
141− imx7src->rcdev.nr_resets = IMX7_RESET_NUM;
142− imx7src->rcdev.ops = &imx7_reset_ops;
284+ imx7src->rcdev.nr_resets = variant->signals_num;
285+ imx7src->rcdev.ops = &variant->ops;
143286 imx7src->rcdev.of_node = dev->of_node;
144287
145288 return devm_reset_controller_register(dev, &imx7src->rcdev);
146289 }
147290
148291 static 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 },
150294 { /* sentinel */ },
151295 };
152296
drivers/reset/reset-socfpga.c+1−1
@@ -11,6 +11,7 @@ · 10 unmodified lines
1111 #include <linux/of_address.h>
1212 #include <linux/platform_device.h>
1313 #include <linux/reset-controller.h>
14+#include <linux/reset/socfpga.h>
1415 #include <linux/slab.h>
1516 #include <linux/spinlock.h>
1617 #include <linux/types.h>
@@ -18,7 +19,6 @@ · 1 unmodified line
1819 #include "reset-simple.h"
1920
2021 #define SOCFPGA_NR_BANKS 8
21−void __init socfpga_reset_init(void);
2222
2323 static int a10_reset_init(struct device_node *np)
2424 {
drivers/reset/reset-sunxi.c+1−0
@@ -18,6 +18,7 @@ · 17 unmodified lines
1818 #include <linux/of_address.h>
1919 #include <linux/platform_device.h>
2020 #include <linux/reset-controller.h>
21+#include <linux/reset/sunxi.h>
2122 #include <linux/slab.h>
2223 #include <linux/spinlock.h>
2324 #include <linux/types.h>
drivers/reset/reset-zynqmp.c+114−0
@@ -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+
16+struct zynqmp_reset_data {
17+ struct reset_controller_dev rcdev;
18+ const struct zynqmp_eemi_ops *eemi_ops;
19+};
20+
21+static inline struct zynqmp_reset_data *
22+to_zynqmp_reset_data(struct reset_controller_dev *rcdev)
23+{
24+ return container_of(rcdev, struct zynqmp_reset_data, rcdev);
25+}
26+
27+static 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+
36+static 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+
45+static 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+
58+static 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+
67+static 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+
74+static 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+
96+static const struct of_device_id zynqmp_reset_dt_ids[] = {
97+ { .compatible = "xlnx,zynqmp-reset", },
98+ { /* sentinel */ },
99+};
100+
101+static 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+
109+static int __init zynqmp_reset_init(void)
110+{
111+ return platform_driver_register(&zynqmp_reset_driver);
112+}
113+
114+arch_initcall(zynqmp_reset_init);
drivers/soc/amlogic/meson-canvas.c+16−2
@@ -51,16 +51,30 @@ struct meson_canvas *meson_canvas_get(struct device *dev) · 50 unmodified lines
5151 {
5252 struct device_node *canvas_node;
5353 struct platform_device *canvas_pdev;
54+ struct meson_canvas *canvas;
5455
5556 canvas_node = of_parse_phandle(dev->of_node, "amlogic,canvas", 0);
5657 if (!canvas_node)
5758 return ERR_PTR(-ENODEV);
5859
5960 canvas_pdev = of_find_device_by_node(canvas_node);
60− if (!canvas_pdev)
61+ if (!canvas_pdev) {
62+ of_node_put(canvas_node);
6163 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);
6276
63− return dev_get_drvdata(&canvas_pdev->dev);
77+ return canvas;
6478 }
6579 EXPORT_SYMBOL_GPL(meson_canvas_get);
6680
drivers/soc/amlogic/meson-clk-measure.c+196−0
@@ -165,6 +165,194 @@ static struct meson_msr_id clk_msr_gx[CLK_MSR_MAX] = { · 164 unmodified lines
165165 CLK_MSR_ID(82, "ge2d"),
166166 };
167167
168+static 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+
242+static 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+
168356 static int meson_measure_id(struct meson_msr_id *clk_msr_id,
169357 unsigned int duration)
170358 {
@@ -337,6 +525,14 @@ static const struct of_device_id meson_msr_match_table[] = { · 166 unmodified lines
337525 .compatible = "amlogic,meson8b-clk-measure",
338526 .data = (void *)clk_msr_m8,
339527 },
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+ },
340536 { /* sentinel */ }
341537 };
342538
drivers/soc/bcm/Kconfig+12−0
@@ -1,5 +1,17 @@
11 menu "Broadcom SoC drivers"
22
3+config 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+
315 config RASPBERRYPI_POWER
416 bool "Raspberry Pi power domain driver"
517 depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
drivers/soc/bcm/Makefile+1−0
@@ -1,2 +1,3 @@
1+obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o
12 obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
23 obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
drivers/soc/bcm/bcm2835-power.c+661−0
@@ -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+
132+struct bcm2835_power_domain {
133+ struct generic_pm_domain base;
134+ struct bcm2835_power *power;
135+ u32 domain;
136+ struct clk *clk;
137+};
138+
139+struct 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+
151+static 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+
166+static 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+
181+static 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+
197+static 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+
256+err_disable_ispow:
257+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
258+err_disable_powup:
259+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
260+ return ret;
261+}
262+
263+static 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+
309+err_disable_asb_master:
310+ bcm2835_asb_disable(power, asb_m_reg);
311+err_disable_clk:
312+ clk_disable_unprepare(pd->clk);
313+err_enable_resets:
314+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
315+ return ret;
316+}
317+
318+static 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+
349+static 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+
415+static 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+
478+static void
479+bcm2835_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+ */
508+static 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+
538+static 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+
556+static const struct reset_control_ops bcm2835_reset_ops = {
557+ .reset = bcm2835_reset_reset,
558+ .status = bcm2835_reset_status,
559+};
560+
561+static 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+
579+static 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+
645+static int bcm2835_power_remove(struct platform_device *pdev)
646+{
647+ return 0;
648+}
649+
650+static struct platform_driver bcm2835_power_driver = {
651+ .probe = bcm2835_power_probe,
652+ .remove = bcm2835_power_remove,
653+ .driver = {
654+ .name = "bcm2835-power",
655+ },
656+};
657+module_platform_driver(bcm2835_power_driver);
658+
659+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
660+MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
661+MODULE_LICENSE("GPL");
drivers/soc/fsl/Kconfig+1−0
@@ -22,6 +22,7 @@ config FSL_GUTS · 21 unmodified lines
2222 config FSL_MC_DPIO
2323 tristate "QorIQ DPAA2 DPIO driver"
2424 depends on FSL_MC_BUS
25+ select SOC_BUS
2526 help
2627 Driver for the DPAA2 DPIO object. A DPIO provides queue and
2728 buffer management facilities for software to interact with
drivers/soc/fsl/dpio/dpio-cmd.h+5−0
@@ -26,6 +26,7 @@ · 25 unmodified lines
2626 #define DPIO_CMDID_DISABLE DPIO_CMD(0x003)
2727 #define DPIO_CMDID_GET_ATTR DPIO_CMD(0x004)
2828 #define DPIO_CMDID_RESET DPIO_CMD(0x005)
29+#define DPIO_CMDID_SET_STASHING_DEST DPIO_CMD(0x120)
2930
3031 struct dpio_cmd_open {
3132 __le32 dpio_id;
@@ -47,4 +48,8 @@ struct dpio_rsp_get_attr { · 15 unmodified lines
4748 __le32 qbman_version;
4849 };
4950
51+struct dpio_stashing_dest {
52+ u8 sdest;
53+};
54+
5055 #endif /* _FSL_DPIO_CMD_H */
drivers/soc/fsl/dpio/dpio-driver.c+53−1
@@ -14,6 +14,7 @@ · 13 unmodified lines
1414 #include <linux/dma-mapping.h>
1515 #include <linux/delay.h>
1616 #include <linux/io.h>
17+#include <linux/sys_soc.h>
1718
1819 #include <linux/fsl/mc.h>
1920 #include <soc/fsl/dpaa2-io.h>
@@ -32,6 +33,46 @@ struct dpio_priv { · 12 unmodified lines
3233
3334 static cpumask_var_t cpus_unused_mask;
3435
36+static const struct soc_device_attribute ls1088a_soc[] = {
37+ {.family = "QorIQ LS1088A"},
38+ { /* sentinel */ }
39+};
40+
41+static const struct soc_device_attribute ls2080a_soc[] = {
42+ {.family = "QorIQ LS2080A"},
43+ { /* sentinel */ }
44+};
45+
46+static const struct soc_device_attribute ls2088a_soc[] = {
47+ {.family = "QorIQ LS2088A"},
48+ { /* sentinel */ }
49+};
50+
51+static const struct soc_device_attribute lx2160a_soc[] = {
52+ {.family = "QorIQ LX2160A"},
53+ { /* sentinel */ }
54+};
55+
56+static 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+
3576 static irqreturn_t dpio_irq_handler(int irq_num, void *arg)
3677 {
3778 struct device *dev = (struct device *)arg;
@@ -89,6 +130,7 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) · 51 unmodified lines
89130 int err = -ENOMEM;
90131 struct device *dev = &dpio_dev->dev;
91132 int possible_next_cpu;
133+ int sdest;
92134
93135 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
94136 if (!priv)
@@ -145,6 +187,16 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) · 50 unmodified lines
145187 desc.cpu = possible_next_cpu;
146188 cpumask_clear_cpu(possible_next_cpu, cpus_unused_mask);
147189
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+
148200 /*
149201 * Set the CENA regs to be the cache inhibited area of the portal to
150202 * 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) · 69 unmodified lines
220272
221273 dev = &dpio_dev->dev;
222274 priv = dev_get_drvdata(dev);
275+ cpu = dpaa2_io_get_cpu(priv->io);
223276
224277 dpaa2_io_down(priv->io);
225278
226279 dpio_teardown_irqs(dpio_dev);
227280
228− cpu = dpaa2_io_get_cpu(priv->io);
229281 cpumask_set_cpu(cpu, cpus_unused_mask);
230282
231283 err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id,
drivers/soc/fsl/dpio/dpio-service.c+3−2
@@ -473,7 +473,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd); · 472 unmodified lines
473473 * Return 0 for success, and negative error code for failure.
474474 */
475475 int dpaa2_io_service_release(struct dpaa2_io *d,
476− u32 bpid,
476+ u16 bpid,
477477 const u64 *buffers,
478478 unsigned int num_buffers)
479479 {
@@ -502,7 +502,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_release); · 22 unmodified lines
502502 * Eg. if the buffer pool is empty, this will return zero.
503503 */
504504 int dpaa2_io_service_acquire(struct dpaa2_io *d,
505− u32 bpid,
505+ u16 bpid,
506506 u64 *buffers,
507507 unsigned int num_buffers)
508508 {
@@ -630,6 +630,7 @@ struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last) · 121 unmodified lines
630630 if (!(dpaa2_dq_flags(ret) & DPAA2_DQ_STAT_VALIDFRAME))
631631 ret = NULL;
632632 } else {
633+ prefetch(&s->vaddr[s->idx]);
633634 *is_last = 0;
634635 }
635636
drivers/soc/fsl/dpio/dpio.c+16−0
@@ -166,6 +166,22 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io, · 165 unmodified lines
166166 return 0;
167167 }
168168
169+int 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+
169185 /**
170186 * dpio_get_api_version - Get Data Path I/O API version
171187 * @mc_io: Pointer to MC portal's DPIO object
drivers/soc/fsl/dpio/dpio.h+5−0
@@ -75,6 +75,11 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io, · 74 unmodified lines
7575 u16 token,
7676 struct dpio_attr *attr);
7777
78+int dpio_set_stashing_destination(struct fsl_mc_io *mc_io,
79+ u32 cmd_flags,
80+ u16 token,
81+ u8 dest);
82+
7883 int dpio_get_api_version(struct fsl_mc_io *mc_io,
7984 u32 cmd_flags,
8085 u16 *major_ver,
drivers/soc/fsl/dpio/qbman-portal.c+3−2
@@ -169,9 +169,9 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) · 168 unmodified lines
169169 3, /* RPM: Valid bit mode, RCR in array mode */
170170 2, /* DCM: Discrete consumption ack mode */
171171 3, /* EPM: Valid bit mode, EQCR in array mode */
172− 0, /* mem stashing drop enable == FALSE */
172+ 1, /* mem stashing drop enable == TRUE */
173173 1, /* mem stashing priority == TRUE */
174− 0, /* mem stashing enable == FALSE */
174+ 1, /* mem stashing enable == TRUE */
175175 1, /* dequeue stashing priority == TRUE */
176176 0, /* dequeue stashing enable == FALSE */
177177 0); /* EQCR_CI stashing priority == FALSE */
@@ -180,6 +180,7 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) · 2 unmodified lines
180180 reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG);
181181 if (!reg) {
182182 pr_err("qbman: the portal is not enabled!\n");
183+ kfree(p);
183184 return NULL;
184185 }
185186
drivers/soc/fsl/guts.c+5−5
@@ -32,6 +32,7 @@ struct fsl_soc_die_attr { · 31 unmodified lines
3232 static struct guts *guts;
3333 static struct soc_device_attribute soc_dev_attr;
3434 static struct soc_device *soc_dev;
35+static struct device_node *root;
3536
3637
3738 /* SoC die attribute definition for QorIQ platform */
@@ -114,7 +115,7 @@ static const struct fsl_soc_die_attr *fsl_soc_die_match( · 76 unmodified lines
114115 return NULL;
115116 }
116117
117−u32 fsl_guts_get_svr(void)
118+static u32 fsl_guts_get_svr(void)
118119 {
119120 u32 svr = 0;
120121
@@ -128,11 +129,10 @@ u32 fsl_guts_get_svr(void) · 7 unmodified lines
128129
129130 return svr;
130131 }
131−EXPORT_SYMBOL(fsl_guts_get_svr);
132132
133133 static int fsl_guts_probe(struct platform_device *pdev)
134134 {
135− struct device_node *root, *np = pdev->dev.of_node;
135+ struct device_node *np = pdev->dev.of_node;
136136 struct device *dev = &pdev->dev;
137137 struct resource *res;
138138 const struct fsl_soc_die_attr *soc_die;
@@ -155,9 +155,8 @@ static int fsl_guts_probe(struct platform_device *pdev) · 16 unmodified lines
155155 root = of_find_node_by_path("/");
156156 if (of_property_read_string(root, "model", &machine))
157157 of_property_read_string_index(root, "compatible", 0, &machine);
158− of_node_put(root);
159158 if (machine)
160− soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL);
159+ soc_dev_attr.machine = machine;
161160
162161 svr = fsl_guts_get_svr();
163162 soc_die = fsl_soc_die_match(svr, fsl_soc_die);
@@ -192,6 +191,7 @@ static int fsl_guts_probe(struct platform_device *pdev) · 28 unmodified lines
192191 static int fsl_guts_remove(struct platform_device *dev)
193192 {
194193 soc_device_unregister(soc_dev);
194+ of_node_put(root);
195195 return 0;
196196 }
197197
drivers/soc/imx/Kconfig+1−1
@@ -2,7 +2,7 @@ menu "i.MX SoC drivers" · 1 unmodified line
22
33 config IMX_GPCV2_PM_DOMAINS
44 bool "i.MX GPCv2 PM domains"
5− depends on SOC_IMX7D || SOC_IMX8MQ || (COMPILE_TEST && OF)
5+ depends on ARCH_MXC || (COMPILE_TEST && OF)
66 depends on PM
77 select PM_GENERIC_DOMAINS
88 default y if SOC_IMX7D
drivers/soc/imx/gpcv2.c+74−2
@@ -8,6 +8,7 @@ · 7 unmodified lines
88 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
99 */
1010
11+#include <linux/clk.h>
1112 #include <linux/of_device.h>
1213 #include <linux/platform_device.h>
1314 #include <linux/pm_domain.h>
@@ -65,6 +66,12 @@ · 51 unmodified lines
6566
6667 #define GPC_M4_PU_PDN_FLG 0x1bc
6768
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+
6875 /*
6976 * The PGC offset values in Reference Manual
7077 * (Rev. 1, 01/2018 and the older ones) GPC chapter's
@@ -92,16 +99,21 @@ · 21 unmodified lines
9299
93100 #define GPC_PGC_CTRL_PCR BIT(0)
94101
102+#define GPC_CLK_MAX 6
103+
95104 struct imx_pgc_domain {
96105 struct generic_pm_domain genpd;
97106 struct regmap *regmap;
98107 struct regulator *regulator;
108+ struct clk *clk[GPC_CLK_MAX];
109+ int num_clks;
99110
100111 unsigned int pgc;
101112
102113 const struct {
103114 u32 pxx;
104115 u32 map;
116+ u32 hsk;
105117 } bits;
106118
107119 const int voltage;
@@ -125,7 +137,7 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, · 17 unmodified lines
125137 const bool enable_power_control = !on;
126138 const bool has_regulator = !IS_ERR(domain->regulator);
127139 unsigned long deadline;
128− int ret = 0;
140+ int i, ret = 0;
129141
130142 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
131143 domain->bits.map, domain->bits.map);
@@ -138,10 +150,18 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, · 6 unmodified lines
138150 }
139151 }
140152
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+
141157 if (enable_power_control)
142158 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
143159 GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
144160
161+ if (domain->bits.hsk)
162+ regmap_update_bits(domain->regmap, GPC_PU_PWRHSK,
163+ domain->bits.hsk, on ? domain->bits.hsk : 0);
164+
145165 regmap_update_bits(domain->regmap, offset,
146166 domain->bits.pxx, domain->bits.pxx);
147167
@@ -179,6 +199,10 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, · 31 unmodified lines
179199 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
180200 GPC_PGC_CTRL_PCR, 0);
181201
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+
182206 if (has_regulator && !on) {
183207 int err;
184208
@@ -328,6 +352,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { · 143 unmodified lines
328352 .bits = {
329353 .pxx = IMX8M_GPU_SW_Pxx_REQ,
330354 .map = IMX8M_GPU_A53_DOMAIN,
355+ .hsk = IMX8M_GPU_HSK_PWRDNREQN,
331356 },
332357 .pgc = IMX8M_PGC_GPU,
333358 },
@@ -339,6 +364,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { · 5 unmodified lines
339364 .bits = {
340365 .pxx = IMX8M_VPU_SW_Pxx_REQ,
341366 .map = IMX8M_VPU_A53_DOMAIN,
367+ .hsk = IMX8M_VPU_HSK_PWRDNREQN,
342368 },
343369 .pgc = IMX8M_PGC_VPU,
344370 },
@@ -350,6 +376,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { · 5 unmodified lines
350376 .bits = {
351377 .pxx = IMX8M_DISP_SW_Pxx_REQ,
352378 .map = IMX8M_DISP_A53_DOMAIN,
379+ .hsk = IMX8M_DISP_HSK_PWRDNREQN,
353380 },
354381 .pgc = IMX8M_PGC_DISP,
355382 },
@@ -390,7 +417,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { · 34 unmodified lines
390417
391418 static const struct regmap_range imx8m_yes_ranges[] = {
392419 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
393− GPC_M4_PU_PDN_FLG),
420+ GPC_PU_PWRHSK),
394421 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI),
395422 GPC_PGC_SR(IMX8M_PGC_MIPI)),
396423 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1),
@@ -426,6 +453,41 @@ static const struct imx_pgc_domain_data imx8m_pgc_domain_data = { · 29 unmodified lines
426453 .reg_access_table = &imx8m_access_table,
427454 };
428455
456+static 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+
476+clk_err:
477+ while (i--)
478+ clk_put(domain->clk[i]);
479+
480+ return ret;
481+}
482+
483+static 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+
429491 static int imx_pgc_domain_probe(struct platform_device *pdev)
430492 {
431493 struct imx_pgc_domain *domain = pdev->dev.platform_data;
@@ -445,9 +507,17 @@ static int imx_pgc_domain_probe(struct platform_device *pdev) · 13 unmodified lines
445507 domain->voltage, domain->voltage);
446508 }
447509
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+
448517 ret = pm_genpd_init(&domain->genpd, NULL, true);
449518 if (ret) {
450519 dev_err(domain->dev, "Failed to init power domain\n");
520+ imx_pgc_put_clocks(domain);
451521 return ret;
452522 }
453523
@@ -456,6 +526,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev) · 2 unmodified lines
456526 if (ret) {
457527 dev_err(domain->dev, "Failed to add genpd provider\n");
458528 pm_genpd_remove(&domain->genpd);
529+ imx_pgc_put_clocks(domain);
459530 }
460531
461532 return ret;
@@ -467,6 +538,7 @@ static int imx_pgc_domain_remove(struct platform_device *pdev) · 5 unmodified lines
467538
468539 of_genpd_del_provider(domain->dev->of_node);
469540 pm_genpd_remove(&domain->genpd);
541+ imx_pgc_put_clocks(domain);
470542
471543 return 0;
472544 }
drivers/soc/qcom/Kconfig+18−0
@@ -98,6 +98,24 @@ config QCOM_RPMH · 97 unmodified lines
9898 of hardware components aggregate requests for these resources and
9999 help apply the aggregated state on the resource.
100100
101+config 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+
110+config 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+
101119 config QCOM_SMEM
102120 tristate "Qualcomm Shared Memory Manager (SMEM)"
103121 depends on ARCH_QCOM || COMPILE_TEST
drivers/soc/qcom/Makefile+2−0
@@ -21,3 +21,5 @@ obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o · 20 unmodified lines
2121 obj-$(CONFIG_QCOM_APR) += apr.o
2222 obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
2323 obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
24+obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
25+obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
drivers/soc/qcom/llcc-sdm845.c+6−0
@@ -71,6 +71,11 @@ static struct llcc_slice_config sdm845_data[] = { · 70 unmodified lines
7171 SCT_ENTRY(LLCC_AUDHW, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0),
7272 };
7373
74+static int sdm845_qcom_llcc_remove(struct platform_device *pdev)
75+{
76+ return qcom_llcc_remove(pdev);
77+}
78+
7479 static int sdm845_qcom_llcc_probe(struct platform_device *pdev)
7580 {
7681 return qcom_llcc_probe(pdev, sdm845_data, ARRAY_SIZE(sdm845_data));
@@ -87,6 +92,7 @@ static struct platform_driver sdm845_qcom_llcc_driver = { · 10 unmodified lines
8792 .of_match_table = sdm845_qcom_llcc_of_match,
8893 },
8994 .probe = sdm845_qcom_llcc_probe,
95+ .remove = sdm845_qcom_llcc_remove,
9096 };
9197 module_platform_driver(sdm845_qcom_llcc_driver);
9298
drivers/soc/qcom/llcc-slice.c+68−33
@@ -46,7 +46,7 @@ · 45 unmodified lines
4646
4747 #define BANK_OFFSET_STRIDE 0x80000
4848
49−static struct llcc_drv_data *drv_data;
49+static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
5050
5151 static const struct regmap_config llcc_regmap_config = {
5252 .reg_bits = 32,
@@ -68,6 +68,9 @@ struct llcc_slice_desc *llcc_slice_getd(u32 uid) · 15 unmodified lines
6868 struct llcc_slice_desc *desc;
6969 u32 sz, count;
7070
71+ if (IS_ERR(drv_data))
72+ return ERR_CAST(drv_data);
73+
7174 cfg = drv_data->cfg;
7275 sz = drv_data->cfg_size;
7376
@@ -108,6 +111,9 @@ static int llcc_update_act_ctrl(u32 sid, · 34 unmodified lines
108111 u32 slice_status;
109112 int ret;
110113
114+ if (IS_ERR(drv_data))
115+ return PTR_ERR(drv_data);
116+
111117 act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid);
112118 status_reg = LLCC_TRP_STATUSn(sid);
113119
@@ -143,6 +149,9 @@ int llcc_slice_activate(struct llcc_slice_desc *desc) · 29 unmodified lines
143149 int ret;
144150 u32 act_ctrl_val;
145151
152+ if (IS_ERR(drv_data))
153+ return PTR_ERR(drv_data);
154+
146155 if (IS_ERR_OR_NULL(desc))
147156 return -EINVAL;
148157
@@ -180,6 +189,9 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc) · 31 unmodified lines
180189 u32 act_ctrl_val;
181190 int ret;
182191
192+ if (IS_ERR(drv_data))
193+ return PTR_ERR(drv_data);
194+
183195 if (IS_ERR_OR_NULL(desc))
184196 return -EINVAL;
185197
@@ -289,46 +301,62 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev) · 103 unmodified lines
289301 return ret;
290302 }
291303
304+int 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+}
310+EXPORT_SYMBOL_GPL(qcom_llcc_remove);
311+
312+static 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+
292329 int qcom_llcc_probe(struct platform_device *pdev,
293330 const struct llcc_slice_config *llcc_cfg, u32 sz)
294331 {
295332 u32 num_banks;
296333 struct device *dev = &pdev->dev;
297− struct resource *llcc_banks_res, *llcc_bcast_res;
298− void __iomem *llcc_banks_base, *llcc_bcast_base;
299334 int ret, i;
300335 struct platform_device *llcc_edac;
301336
302337 drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
303− if (!drv_data)
304− return -ENOMEM;
305−
306− llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
307− "llcc_base");
308− llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res);
309− if (IS_ERR(llcc_banks_base))
310− return PTR_ERR(llcc_banks_base);
311−
312− drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base,
313− &llcc_regmap_config);
314− if (IS_ERR(drv_data->regmap))
315− return PTR_ERR(drv_data->regmap);
316−
317− llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
318− "llcc_broadcast_base");
319− llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res);
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);
338+ if (!drv_data) {
339+ ret = -ENOMEM;
340+ goto err;
341+ }
342+
343+ drv_data->regmap = qcom_llcc_init_mmio(pdev, "llcc_base");
344+ if (IS_ERR(drv_data->regmap)) {
345+ ret = PTR_ERR(drv_data->regmap);
346+ goto err;
347+ }
348+
349+ drv_data->bcast_regmap =
350+ qcom_llcc_init_mmio(pdev, "llcc_broadcast_base");
351+ if (IS_ERR(drv_data->bcast_regmap)) {
352+ ret = PTR_ERR(drv_data->bcast_regmap);
353+ goto err;
354+ }
327355
328356 ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0,
329357 &num_banks);
330358 if (ret)
331− return ret;
359+ goto err;
332360
333361 num_banks &= LLCC_LB_CNT_MASK;
334362 num_banks >>= LLCC_LB_CNT_SHIFT;
@@ -340,8 +368,10 @@ int qcom_llcc_probe(struct platform_device *pdev, · 5 unmodified lines
340368
341369 drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32),
342370 GFP_KERNEL);
343− if (!drv_data->offsets)
344− return -ENOMEM;
371+ if (!drv_data->offsets) {
372+ ret = -ENOMEM;
373+ goto err;
374+ }
345375
346376 for (i = 0; i < num_banks; i++)
347377 drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
@@ -349,8 +379,10 @@ int qcom_llcc_probe(struct platform_device *pdev, · 1 unmodified line
349379 drv_data->bitmap = devm_kcalloc(dev,
350380 BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long),
351381 GFP_KERNEL);
352− if (!drv_data->bitmap)
353− return -ENOMEM;
382+ if (!drv_data->bitmap) {
383+ ret = -ENOMEM;
384+ goto err;
385+ }
354386
355387 drv_data->cfg = llcc_cfg;
356388 drv_data->cfg_size = sz;
@@ -359,7 +391,7 @@ int qcom_llcc_probe(struct platform_device *pdev, · 2 unmodified lines
359391
360392 ret = qcom_llcc_cfg_program(pdev);
361393 if (ret)
362− return ret;
394+ goto err;
363395
364396 drv_data->ecc_irq = platform_get_irq(pdev, 0);
365397 if (drv_data->ecc_irq >= 0) {
@@ -370,6 +402,9 @@ int qcom_llcc_probe(struct platform_device *pdev, · 4 unmodified lines
370402 dev_err(dev, "Failed to register llcc edac driver\n");
371403 }
372404
405+ return 0;
406+err:
407+ drv_data = ERR_PTR(-ENODEV);
373408 return ret;
374409 }
375410 EXPORT_SYMBOL_GPL(qcom_llcc_probe);
drivers/soc/qcom/qcom_gsbi.c+5−2
@@ -138,7 +138,7 @@ static int gsbi_probe(struct platform_device *pdev) · 137 unmodified lines
138138 struct resource *res;
139139 void __iomem *base;
140140 struct gsbi_info *gsbi;
141− int i;
141+ int i, ret;
142142 u32 mask, gsbi_num;
143143 const struct crci_config *config = NULL;
144144
@@ -221,7 +221,10 @@ static int gsbi_probe(struct platform_device *pdev) · 76 unmodified lines
221221
222222 platform_set_drvdata(pdev, gsbi);
223223
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;
225228 }
226229
227230 static int gsbi_remove(struct platform_device *pdev)
drivers/soc/qcom/rmtfs_mem.c+24−8
@@ -45,9 +45,9 @@ static ssize_t qcom_rmtfs_mem_show(struct device *dev, · 44 unmodified lines
4545 struct device_attribute *attr,
4646 char *buf);
4747
48−static DEVICE_ATTR(phys_addr, 0400, qcom_rmtfs_mem_show, NULL);
49−static DEVICE_ATTR(size, 0400, qcom_rmtfs_mem_show, NULL);
50−static DEVICE_ATTR(client_id, 0400, qcom_rmtfs_mem_show, NULL);
48+static DEVICE_ATTR(phys_addr, 0444, qcom_rmtfs_mem_show, NULL);
49+static DEVICE_ATTR(size, 0444, qcom_rmtfs_mem_show, NULL);
50+static DEVICE_ATTR(client_id, 0444, qcom_rmtfs_mem_show, NULL);
5151
5252 static ssize_t qcom_rmtfs_mem_show(struct device *dev,
5353 struct device_attribute *attr,
@@ -132,6 +132,11 @@ static int qcom_rmtfs_mem_release(struct inode *inode, struct file *filp) · 78 unmodified lines
132132 return 0;
133133 }
134134
135+static struct class rmtfs_class = {
136+ .owner = THIS_MODULE,
137+ .name = "rmtfs",
138+};
139+
135140 static const struct file_operations qcom_rmtfs_mem_fops = {
136141 .owner = THIS_MODULE,
137142 .open = qcom_rmtfs_mem_open,
@@ -199,6 +204,7 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev) · 61 unmodified lines
199204
200205 dev_set_name(&rmtfs_mem->dev, "qcom_rmtfs_mem%d", client_id);
201206 rmtfs_mem->dev.id = client_id;
207+ rmtfs_mem->dev.class = &rmtfs_class;
202208 rmtfs_mem->dev.devt = MKDEV(MAJOR(qcom_rmtfs_mem_major), client_id);
203209
204210 ret = cdev_device_add(&rmtfs_mem->cdev, &rmtfs_mem->dev);
@@ -277,32 +283,42 @@ static struct platform_driver qcom_rmtfs_mem_driver = { · 72 unmodified lines
277283 },
278284 };
279285
280−static int qcom_rmtfs_mem_init(void)
286+static int __init qcom_rmtfs_mem_init(void)
281287 {
282288 int ret;
283289
290+ ret = class_register(&rmtfs_class);
291+ if (ret)
292+ return ret;
293+
284294 ret = alloc_chrdev_region(&qcom_rmtfs_mem_major, 0,
285295 QCOM_RMTFS_MEM_DEV_MAX, "qcom_rmtfs_mem");
286296 if (ret < 0) {
287297 pr_err("qcom_rmtfs_mem: failed to allocate char dev region\n");
288− return ret;
298+ goto unregister_class;
289299 }
290300
291301 ret = platform_driver_register(&qcom_rmtfs_mem_driver);
292302 if (ret < 0) {
293303 pr_err("qcom_rmtfs_mem: failed to register rmtfs_mem driver\n");
294− unregister_chrdev_region(qcom_rmtfs_mem_major,
295− QCOM_RMTFS_MEM_DEV_MAX);
304+ goto unregister_chrdev;
296305 }
297306
307+ return 0;
308+
309+unregister_chrdev:
310+ unregister_chrdev_region(qcom_rmtfs_mem_major, QCOM_RMTFS_MEM_DEV_MAX);
311+unregister_class:
312+ class_unregister(&rmtfs_class);
298313 return ret;
299314 }
300315 module_init(qcom_rmtfs_mem_init);
301316
302−static void qcom_rmtfs_mem_exit(void)
317+static void __exit qcom_rmtfs_mem_exit(void)
303318 {
304319 platform_driver_unregister(&qcom_rmtfs_mem_driver);
305320 unregister_chrdev_region(qcom_rmtfs_mem_major, QCOM_RMTFS_MEM_DEV_MAX);
321+ class_unregister(&rmtfs_class);
306322 }
307323 module_exit(qcom_rmtfs_mem_exit);
308324
drivers/soc/qcom/rpmh.c+22−15
@@ -80,6 +80,7 @@ void rpmh_tx_done(const struct tcs_request *msg, int r) · 79 unmodified lines
8080 struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
8181 msg);
8282 struct completion *compl = rpm_msg->completion;
83+ bool free = rpm_msg->needs_free;
8384
8485 rpm_msg->err = r;
8586
@@ -94,7 +95,7 @@ void rpmh_tx_done(const struct tcs_request *msg, int r) · 8 unmodified lines
9495 complete(compl);
9596
9697 exit:
97− if (rpm_msg->needs_free)
98+ if (free)
9899 kfree(rpm_msg);
99100 }
100101
@@ -192,9 +193,8 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state, · 91 unmodified lines
192193 WARN_ON(irqs_disabled());
193194 ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg);
194195 } else {
195− ret = rpmh_rsc_write_ctrl_data(ctrlr_to_drv(ctrlr),
196− &rpm_msg->msg);
197196 /* Clean up our call by spoofing tx_done */
197+ ret = 0;
198198 rpmh_tx_done(&rpm_msg->msg, ret);
199199 }
200200
@@ -348,11 +348,12 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state, · 147 unmodified lines
348348 {
349349 struct batch_cache_req *req;
350350 struct rpmh_request *rpm_msgs;
351− DECLARE_COMPLETION_ONSTACK(compl);
351+ struct completion *compls;
352352 struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
353353 unsigned long time_left;
354354 int count = 0;
355− int ret, i, j;
355+ int ret, i;
356+ void *ptr;
356357
357358 if (!cmd || !n)
358359 return -EINVAL;
@@ -362,10 +363,15 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state, · 3 unmodified lines
362363 if (!count)
363364 return -EINVAL;
364365
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)),
366368 GFP_ATOMIC);
367− if (!req)
369+ if (!ptr)
368370 return -ENOMEM;
371+
372+ req = ptr;
373+ compls = ptr + sizeof(*req) + count * sizeof(*rpm_msgs);
374+
369375 req->count = count;
370376 rpm_msgs = req->rpm_msgs;
371377
@@ -380,25 +386,26 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state, · 8 unmodified lines
380386 }
381387
382388 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;
384393 ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msgs[i].msg);
385394 if (ret) {
386395 pr_err("Error(%d) sending RPMH message addr=%#x\n",
387396 ret, rpm_msgs[i].msg.cmds[0].addr);
388− for (j = i; j < count; j++)
389− rpmh_tx_done(&rpm_msgs[j].msg, ret);
390397 break;
391398 }
392399 }
393400
394401 time_left = RPMH_TIMEOUT_MS;
395− for (i = 0; i < count; i++) {
396− time_left = wait_for_completion_timeout(&compl, time_left);
402+ while (i--) {
403+ time_left = wait_for_completion_timeout(&compls[i], time_left);
397404 if (!time_left) {
398405 /*
399406 * Better hope they never finish because they'll signal
400− * the completion on our stack and that's bad once
401− * we've returned from the function.
407+ * the completion that we're going to free once
408+ * we've returned from this function.
402409 */
403410 WARN_ON(1);
404411 ret = -ETIMEDOUT;
@@ -407,7 +414,7 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state, · 2 unmodified lines
407414 }
408415
409416 exit:
410− kfree(req);
417+ kfree(ptr);
411418
412419 return ret;
413420 }
drivers/soc/qcom/rpmhpd.c+406−0
@@ -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+ */
38+struct 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+
53+struct rpmhpd_desc {
54+ struct rpmhpd **rpmhpds;
55+ size_t num_pds;
56+};
57+
58+static DEFINE_MUTEX(rpmhpd_lock);
59+
60+/* SDM845 RPMH powerdomains */
61+
62+static struct rpmhpd sdm845_ebi = {
63+ .pd = { .name = "ebi", },
64+ .res_name = "ebi.lvl",
65+};
66+
67+static struct rpmhpd sdm845_lmx = {
68+ .pd = { .name = "lmx", },
69+ .res_name = "lmx.lvl",
70+};
71+
72+static struct rpmhpd sdm845_lcx = {
73+ .pd = { .name = "lcx", },
74+ .res_name = "lcx.lvl",
75+};
76+
77+static struct rpmhpd sdm845_gfx = {
78+ .pd = { .name = "gfx", },
79+ .res_name = "gfx.lvl",
80+};
81+
82+static struct rpmhpd sdm845_mss = {
83+ .pd = { .name = "mss", },
84+ .res_name = "mss.lvl",
85+};
86+
87+static struct rpmhpd sdm845_mx_ao;
88+static struct rpmhpd sdm845_mx = {
89+ .pd = { .name = "mx", },
90+ .peer = &sdm845_mx_ao,
91+ .res_name = "mx.lvl",
92+};
93+
94+static struct rpmhpd sdm845_mx_ao = {
95+ .pd = { .name = "mx_ao", },
96+ .peer = &sdm845_mx,
97+ .res_name = "mx.lvl",
98+};
99+
100+static struct rpmhpd sdm845_cx_ao;
101+static 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+
108+static 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+
115+static 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+
127+static const struct rpmhpd_desc sdm845_desc = {
128+ .rpmhpds = sdm845_rpmhpds,
129+ .num_pds = ARRAY_SIZE(sdm845_rpmhpds),
130+};
131+
132+static const struct of_device_id rpmhpd_match_table[] = {
133+ { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },
134+ { }
135+};
136+
137+static 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+
155+static 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+ */
175+static 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+
215+static 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+
233+static 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+
250+static 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;
276+out:
277+ mutex_unlock(&rpmhpd_lock);
278+
279+ return ret;
280+}
281+
282+static 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+
288+static 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+
321+static 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+
393+static 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+
402+static int __init rpmhpd_init(void)
403+{
404+ return platform_driver_register(&rpmhpd_driver);
405+}
406+core_initcall(rpmhpd_init);
drivers/soc/qcom/rpmpd.c+315−0
@@ -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+
70+struct rpmpd_req {
71+ __le32 key;
72+ __le32 nbytes;
73+ __le32 value;
74+};
75+
76+struct 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+
89+struct rpmpd_desc {
90+ struct rpmpd **rpmpds;
91+ size_t num_pds;
92+};
93+
94+static DEFINE_MUTEX(rpmpd_lock);
95+
96+/* msm8996 RPM Power domains */
97+DEFINE_RPMPD_CORNER_SMPA(msm8996, vddcx, vddcx_ao, 1);
98+DEFINE_RPMPD_CORNER_SMPA(msm8996, vddmx, vddmx_ao, 2);
99+DEFINE_RPMPD_CORNER_LDOA(msm8996, vddsscx, 26);
100+
101+DEFINE_RPMPD_VFC_SMPA(msm8996, vddcx_vfc, 1);
102+DEFINE_RPMPD_VFC_LDOA(msm8996, vddsscx_vfc, 26);
103+
104+static 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+
114+static const struct rpmpd_desc msm8996_desc = {
115+ .rpmpds = msm8996_rpmpds,
116+ .num_pds = ARRAY_SIZE(msm8996_rpmpds),
117+};
118+
119+static const struct of_device_id rpmpd_match_table[] = {
120+ { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
121+ { }
122+};
123+
124+static 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+
136+static 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+
148+static 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+
159+static 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+
184+static 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+
200+out:
201+ mutex_unlock(&rpmpd_lock);
202+
203+ return ret;
204+}
205+
206+static 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+
222+static 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+
240+out:
241+ mutex_unlock(&rpmpd_lock);
242+
243+ return ret;
244+}
245+
246+static 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+
252+static 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+
302+static 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+
311+static int __init rpmpd_init(void)
312+{
313+ return platform_driver_register(&rpmpd_driver);
314+}
315+core_initcall(rpmpd_init);
drivers/soc/qcom/smd-rpm.c+1−0
@@ -227,6 +227,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = { · 226 unmodified lines
227227 { .compatible = "qcom,rpm-msm8974" },
228228 { .compatible = "qcom,rpm-msm8996" },
229229 { .compatible = "qcom,rpm-msm8998" },
230+ { .compatible = "qcom,rpm-sdm660" },
230231 { .compatible = "qcom,rpm-qcs404" },
231232 {}
232233 };
drivers/soc/tegra/fuse/fuse-tegra.c+9−3
@@ -137,13 +137,17 @@ static int tegra_fuse_probe(struct platform_device *pdev) · 136 unmodified lines
137137 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
138138 fuse->phys = res->start;
139139 fuse->base = devm_ioremap_resource(&pdev->dev, res);
140− if (IS_ERR(fuse->base))
141− return PTR_ERR(fuse->base);
140+ if (IS_ERR(fuse->base)) {
141+ err = PTR_ERR(fuse->base);
142+ fuse->base = base;
143+ return err;
144+ }
142145
143146 fuse->clk = devm_clk_get(&pdev->dev, "fuse");
144147 if (IS_ERR(fuse->clk)) {
145148 dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
146149 PTR_ERR(fuse->clk));
150+ fuse->base = base;
147151 return PTR_ERR(fuse->clk);
148152 }
149153
@@ -152,8 +156,10 @@ static int tegra_fuse_probe(struct platform_device *pdev) · 2 unmodified lines
152156
153157 if (fuse->soc->probe) {
154158 err = fuse->soc->probe(fuse);
155− if (err < 0)
159+ if (err < 0) {
160+ fuse->base = base;
156161 return err;
162+ }
157163 }
158164
159165 if (tegra_fuse_create_sysfs(&pdev->dev, fuse->soc->info->size,
drivers/soc/tegra/fuse/speedo-tegra210.c+1−1
@@ -131,7 +131,7 @@ void __init tegra210_init_speedo_data(struct tegra_sku_info *sku_info) · 130 unmodified lines
131131
132132 soc_speedo[0] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0);
133133 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);
135135
136136 cpu_iddq = tegra_fuse_read_early(FUSE_CPU_IDDQ) * 4;
137137 soc_iddq = tegra_fuse_read_early(FUSE_SOC_IDDQ) * 4;
drivers/soc/tegra/pmc.c+288−136
@@ -20,7 +20,7 @@ · 19 unmodified lines
2020
2121 #define pr_fmt(fmt) "tegra-pmc: " fmt
2222
23−#include <linux/kernel.h>
23+#include <linux/arm-smccc.h>
2424 #include <linux/clk.h>
2525 #include <linux/clk/tegra.h>
2626 #include <linux/debugfs.h>
@@ -30,16 +30,17 @@ · 3 unmodified lines
3030 #include <linux/init.h>
3131 #include <linux/io.h>
3232 #include <linux/iopoll.h>
33−#include <linux/irq.h>
3433 #include <linux/irqdomain.h>
35−#include <linux/of.h>
34+#include <linux/irq.h>
35+#include <linux/kernel.h>
3636 #include <linux/of_address.h>
3737 #include <linux/of_clk.h>
38+#include <linux/of.h>
3839 #include <linux/of_irq.h>
3940 #include <linux/of_platform.h>
40−#include <linux/pinctrl/pinctrl.h>
41−#include <linux/pinctrl/pinconf.h>
4241 #include <linux/pinctrl/pinconf-generic.h>
42+#include <linux/pinctrl/pinconf.h>
43+#include <linux/pinctrl/pinctrl.h>
4344 #include <linux/platform_device.h>
4445 #include <linux/pm_domain.h>
4546 #include <linux/reboot.h>
@@ -145,6 +146,11 @@ · 99 unmodified lines
145146 #define WAKE_AOWAKE_CTRL 0x4f4
146147 #define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
147148
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+
148154 struct tegra_powergate {
149155 struct generic_pm_domain genpd;
150156 struct tegra_pmc *pmc;
@@ -216,6 +222,7 @@ struct tegra_pmc_soc { · 65 unmodified lines
216222 bool has_gpu_clamps;
217223 bool needs_mbist_war;
218224 bool has_impl_33v_pwr;
225+ bool maybe_tz_only;
219226
220227 const struct tegra_io_pad_soc *io_pads;
221228 unsigned int num_io_pads;
@@ -273,8 +280,12 @@ static const char * const tegra30_reset_sources[] = { · 51 unmodified lines
273280 * struct tegra_pmc - NVIDIA Tegra PMC
274281 * @dev: pointer to PMC device structure
275282 * @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
276286 * @clk: pointer to pclk clock
277287 * @soc: pointer to SoC data structure
288+ * @tz_only: flag specifying if the PMC can only be accessed via TrustZone
278289 * @debugfs: pointer to debugfs entry
279290 * @rate: currently configured rate of pclk
280291 * @suspend_mode: lowest suspend mode available
@@ -291,6 +302,9 @@ static const char * const tegra30_reset_sources[] = { · 10 unmodified lines
291302 * @lp0_vec_size: size of the LP0 warm boot code
292303 * @powergates_available: Bitmap of available power gates
293304 * @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
294308 */
295309 struct tegra_pmc {
296310 struct device *dev;
@@ -302,6 +316,7 @@ struct tegra_pmc { · 5 unmodified lines
302316 struct dentry *debugfs;
303317
304318 const struct tegra_pmc_soc *soc;
319+ bool tz_only;
305320
306321 unsigned long rate;
307322
@@ -338,30 +353,85 @@ to_powergate(struct generic_pm_domain *domain) · 30 unmodified lines
338353 return container_of(domain, struct tegra_powergate, genpd);
339354 }
340355
341−static u32 tegra_pmc_readl(unsigned long offset)
356+static u32 tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset)
342357 {
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+
343375 return readl(pmc->base + offset);
344376 }
345377
346−static void tegra_pmc_writel(u32 value, unsigned long offset)
378+static void tegra_pmc_writel(struct tegra_pmc *pmc, u32 value,
379+ unsigned long offset)
347380 {
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+ }
349397 }
350398
399+static 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+
407+static 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+ */
351421 static inline bool tegra_powergate_state(int id)
352422 {
353423 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;
355425 else
356− return (tegra_pmc_readl(PWRGATE_STATUS) & BIT(id)) != 0;
426+ return (tegra_pmc_readl(pmc, PWRGATE_STATUS) & BIT(id)) != 0;
357427 }
358428
359−static inline bool tegra_powergate_is_valid(int id)
429+static inline bool tegra_powergate_is_valid(struct tegra_pmc *pmc, int id)
360430 {
361431 return (pmc->soc && pmc->soc->powergates[id]);
362432 }
363433
364−static inline bool tegra_powergate_is_available(int id)
434+static inline bool tegra_powergate_is_available(struct tegra_pmc *pmc, int id)
365435 {
366436 return test_bit(id, pmc->powergates_available);
367437 }
@@ -374,7 +444,7 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name) · 6 unmodified lines
374444 return -EINVAL;
375445
376446 for (i = 0; i < pmc->soc->num_powergates; i++) {
377− if (!tegra_powergate_is_valid(i))
447+ if (!tegra_powergate_is_valid(pmc, i))
378448 continue;
379449
380450 if (!strcmp(name, pmc->soc->powergates[i]))
@@ -386,10 +456,12 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name) · 5 unmodified lines
386456
387457 /**
388458 * tegra_powergate_set() - set the state of a partition
459+ * @pmc: power management controller
389460 * @id: partition ID
390461 * @new_state: new state of the partition
391462 */
392−static int tegra_powergate_set(unsigned int id, bool new_state)
463+static int tegra_powergate_set(struct tegra_pmc *pmc, unsigned int id,
464+ bool new_state)
393465 {
394466 bool status;
395467 int err;
@@ -404,7 +476,7 @@ static int tegra_powergate_set(unsigned int id, bool new_state) · 8 unmodified lines
404476 return 0;
405477 }
406478
407− tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
479+ tegra_pmc_writel(pmc, PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
408480
409481 err = readx_poll_timeout(tegra_powergate_state, id, status,
410482 status == new_state, 10, 100000);
@@ -414,7 +486,8 @@ static int tegra_powergate_set(unsigned int id, bool new_state) · 3 unmodified lines
414486 return err;
415487 }
416488
417−static int __tegra_powergate_remove_clamping(unsigned int id)
489+static int __tegra_powergate_remove_clamping(struct tegra_pmc *pmc,
490+ unsigned int id)
418491 {
419492 u32 mask;
420493
@@ -426,7 +499,7 @@ static int __tegra_powergate_remove_clamping(unsigned int id) · 5 unmodified lines
426499 */
427500 if (id == TEGRA_POWERGATE_3D) {
428501 if (pmc->soc->has_gpu_clamps) {
429− tegra_pmc_writel(0, GPU_RG_CNTRL);
502+ tegra_pmc_writel(pmc, 0, GPU_RG_CNTRL);
430503 goto out;
431504 }
432505 }
@@ -442,7 +515,7 @@ static int __tegra_powergate_remove_clamping(unsigned int id) · 9 unmodified lines
442515 else
443516 mask = (1 << id);
444517
445− tegra_pmc_writel(mask, REMOVE_CLAMPING);
518+ tegra_pmc_writel(pmc, mask, REMOVE_CLAMPING);
446519
447520 out:
448521 mutex_unlock(&pmc->powergates_lock);
@@ -494,7 +567,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg, · 45 unmodified lines
494567
495568 usleep_range(10, 20);
496569
497− err = tegra_powergate_set(pg->id, true);
570+ err = tegra_powergate_set(pg->pmc, pg->id, true);
498571 if (err < 0)
499572 return err;
500573
@@ -506,7 +579,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg, · 5 unmodified lines
506579
507580 usleep_range(10, 20);
508581
509− err = __tegra_powergate_remove_clamping(pg->id);
582+ err = __tegra_powergate_remove_clamping(pg->pmc, pg->id);
510583 if (err)
511584 goto disable_clks;
512585
@@ -533,7 +606,7 @@ disable_clks: · 20 unmodified lines
533606 usleep_range(10, 20);
534607
535608 powergate_off:
536− tegra_powergate_set(pg->id, false);
609+ tegra_powergate_set(pg->pmc, pg->id, false);
537610
538611 return err;
539612 }
@@ -558,7 +631,7 @@ static int tegra_powergate_power_down(struct tegra_powergate *pg) · 18 unmodified lines
558631
559632 usleep_range(10, 20);
560633
561− err = tegra_powergate_set(pg->id, false);
634+ err = tegra_powergate_set(pg->pmc, pg->id, false);
562635 if (err)
563636 goto assert_resets;
564637
@@ -579,12 +652,13 @@ disable_clks: · 14 unmodified lines
579652 static int tegra_genpd_power_on(struct generic_pm_domain *domain)
580653 {
581654 struct tegra_powergate *pg = to_powergate(domain);
655+ struct device *dev = pg->pmc->dev;
582656 int err;
583657
584658 err = tegra_powergate_power_up(pg, true);
585659 if (err)
586− pr_err("failed to turn on PM domain %s: %d\n", pg->genpd.name,
587− err);
660+ dev_err(dev, "failed to turn on PM domain %s: %d\n",
661+ pg->genpd.name, err);
588662
589663 return err;
590664 }
@@ -592,12 +666,13 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain) · 1 unmodified line
592666 static int tegra_genpd_power_off(struct generic_pm_domain *domain)
593667 {
594668 struct tegra_powergate *pg = to_powergate(domain);
669+ struct device *dev = pg->pmc->dev;
595670 int err;
596671
597672 err = tegra_powergate_power_down(pg);
598673 if (err)
599− pr_err("failed to turn off PM domain %s: %d\n",
600− pg->genpd.name, err);
674+ dev_err(dev, "failed to turn off PM domain %s: %d\n",
675+ pg->genpd.name, err);
601676
602677 return err;
603678 }
@@ -608,10 +683,10 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain) · 4 unmodified lines
608683 */
609684 int tegra_powergate_power_on(unsigned int id)
610685 {
611− if (!tegra_powergate_is_available(id))
686+ if (!tegra_powergate_is_available(pmc, id))
612687 return -EINVAL;
613688
614− return tegra_powergate_set(id, true);
689+ return tegra_powergate_set(pmc, id, true);
615690 }
616691
617692 /**
@@ -620,20 +695,21 @@ int tegra_powergate_power_on(unsigned int id) · 2 unmodified lines
620695 */
621696 int tegra_powergate_power_off(unsigned int id)
622697 {
623− if (!tegra_powergate_is_available(id))
698+ if (!tegra_powergate_is_available(pmc, id))
624699 return -EINVAL;
625700
626− return tegra_powergate_set(id, false);
701+ return tegra_powergate_set(pmc, id, false);
627702 }
628703 EXPORT_SYMBOL(tegra_powergate_power_off);
629704
630705 /**
631706 * tegra_powergate_is_powered() - check if partition is powered
707+ * @pmc: power management controller
632708 * @id: partition ID
633709 */
634−int tegra_powergate_is_powered(unsigned int id)
710+static int tegra_powergate_is_powered(struct tegra_pmc *pmc, unsigned int id)
635711 {
636− if (!tegra_powergate_is_valid(id))
712+ if (!tegra_powergate_is_valid(pmc, id))
637713 return -EINVAL;
638714
639715 return tegra_powergate_state(id);
@@ -645,10 +721,10 @@ int tegra_powergate_is_powered(unsigned int id) · 5 unmodified lines
645721 */
646722 int tegra_powergate_remove_clamping(unsigned int id)
647723 {
648− if (!tegra_powergate_is_available(id))
724+ if (!tegra_powergate_is_available(pmc, id))
649725 return -EINVAL;
650726
651− return __tegra_powergate_remove_clamping(id);
727+ return __tegra_powergate_remove_clamping(pmc, id);
652728 }
653729 EXPORT_SYMBOL(tegra_powergate_remove_clamping);
654730
@@ -666,7 +742,7 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk, · 11 unmodified lines
666742 struct tegra_powergate *pg;
667743 int err;
668744
669− if (!tegra_powergate_is_available(id))
745+ if (!tegra_powergate_is_available(pmc, id))
670746 return -EINVAL;
671747
672748 pg = kzalloc(sizeof(*pg), GFP_KERNEL);
@@ -681,7 +757,8 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk, · 8 unmodified lines
681757
682758 err = tegra_powergate_power_up(pg, false);
683759 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);
685762
686763 kfree(pg);
687764
@@ -691,12 +768,14 @@ EXPORT_SYMBOL(tegra_powergate_sequence_power_up); · 3 unmodified lines
691768
692769 /**
693770 * tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
771+ * @pmc: power management controller
694772 * @cpuid: CPU partition ID
695773 *
696774 * Returns the partition ID corresponding to the CPU partition ID or a
697775 * negative error code on failure.
698776 */
699−static int tegra_get_cpu_powergate_id(unsigned int cpuid)
777+static int tegra_get_cpu_powergate_id(struct tegra_pmc *pmc,
778+ unsigned int cpuid)
700779 {
701780 if (pmc->soc && cpuid < pmc->soc->num_cpu_powergates)
702781 return pmc->soc->cpu_powergates[cpuid];
@@ -712,11 +791,11 @@ bool tegra_pmc_cpu_is_powered(unsigned int cpuid) · 9 unmodified lines
712791 {
713792 int id;
714793
715− id = tegra_get_cpu_powergate_id(cpuid);
794+ id = tegra_get_cpu_powergate_id(pmc, cpuid);
716795 if (id < 0)
717796 return false;
718797
719− return tegra_powergate_is_powered(id);
798+ return tegra_powergate_is_powered(pmc, id);
720799 }
721800
722801 /**
@@ -727,11 +806,11 @@ int tegra_pmc_cpu_power_on(unsigned int cpuid) · 4 unmodified lines
727806 {
728807 int id;
729808
730− id = tegra_get_cpu_powergate_id(cpuid);
809+ id = tegra_get_cpu_powergate_id(pmc, cpuid);
731810 if (id < 0)
732811 return id;
733812
734− return tegra_powergate_set(id, true);
813+ return tegra_powergate_set(pmc, id, true);
735814 }
736815
737816 /**
@@ -742,7 +821,7 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid) · 4 unmodified lines
742821 {
743822 int id;
744823
745− id = tegra_get_cpu_powergate_id(cpuid);
824+ id = tegra_get_cpu_powergate_id(pmc, cpuid);
746825 if (id < 0)
747826 return id;
748827
@@ -755,7 +834,7 @@ static int tegra_pmc_restart_notify(struct notifier_block *this, · 6 unmodified lines
755834 const char *cmd = data;
756835 u32 value;
757836
758− value = readl(pmc->scratch + pmc->soc->regs->scratch0);
837+ value = tegra_pmc_scratch_readl(pmc, pmc->soc->regs->scratch0);
759838 value &= ~PMC_SCRATCH0_MODE_MASK;
760839
761840 if (cmd) {
@@ -769,12 +848,12 @@ static int tegra_pmc_restart_notify(struct notifier_block *this, · 7 unmodified lines
769848 value |= PMC_SCRATCH0_MODE_RCM;
770849 }
771850
772− writel(value, pmc->scratch + pmc->soc->regs->scratch0);
851+ tegra_pmc_scratch_writel(pmc, value, pmc->soc->regs->scratch0);
773852
774853 /* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */
775− value = tegra_pmc_readl(PMC_CNTRL);
854+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
776855 value |= PMC_CNTRL_MAIN_RST;
777− tegra_pmc_writel(value, PMC_CNTRL);
856+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
778857
779858 return NOTIFY_DONE;
780859 }
@@ -793,7 +872,7 @@ static int powergate_show(struct seq_file *s, void *data) · 12 unmodified lines
793872 seq_printf(s, "------------------\n");
794873
795874 for (i = 0; i < pmc->soc->num_powergates; i++) {
796− status = tegra_powergate_is_powered(i);
875+ status = tegra_powergate_is_powered(pmc, i);
797876 if (status < 0)
798877 continue;
799878
@@ -855,12 +934,13 @@ err: · 55 unmodified lines
855934 static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
856935 struct device_node *np, bool off)
857936 {
937+ struct device *dev = pg->pmc->dev;
858938 int err;
859939
860940 pg->reset = of_reset_control_array_get_exclusive(np);
861941 if (IS_ERR(pg->reset)) {
862942 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);
864944 return err;
865945 }
866946
@@ -877,6 +957,7 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg, · 10 unmodified lines
877957
878958 static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
879959 {
960+ struct device *dev = pmc->dev;
880961 struct tegra_powergate *pg;
881962 int id, err;
882963 bool off;
@@ -887,7 +968,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np) · 4 unmodified lines
887968
888969 id = tegra_powergate_lookup(pmc, np->name);
889970 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);
891972 goto free_mem;
892973 }
893974
@@ -903,17 +984,17 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np) · 9 unmodified lines
903984 pg->genpd.power_on = tegra_genpd_power_on;
904985 pg->pmc = pmc;
905986
906− off = !tegra_powergate_is_powered(pg->id);
987+ off = !tegra_powergate_is_powered(pmc, pg->id);
907988
908989 err = tegra_powergate_of_get_clks(pg, np);
909990 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);
911992 goto set_available;
912993 }
913994
914995 err = tegra_powergate_of_get_resets(pg, np, off);
915996 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);
917998 goto remove_clks;
918999 }
9191000
@@ -926,19 +1007,19 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np) · 6 unmodified lines
9261007
9271008 err = pm_genpd_init(&pg->genpd, NULL, off);
9281009 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,
9301011 err);
9311012 goto remove_resets;
9321013 }
9331014
9341015 err = of_genpd_add_provider_simple(np, &pg->genpd);
9351016 if (err < 0) {
936− pr_err("failed to add PM domain provider for %pOFn: %d\n",
937− np, err);
1017+ dev_err(dev, "failed to add PM domain provider for %pOFn: %d\n",
1018+ np, err);
9381019 goto remove_genpd;
9391020 }
9401021
941− pr_debug("added PM domain %s\n", pg->genpd.name);
1022+ dev_dbg(dev, "added PM domain %s\n", pg->genpd.name);
9421023
9431024 return;
9441025
@@ -994,7 +1075,8 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id) · 49 unmodified lines
9941075 return NULL;
9951076 }
9961077
997−static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
1078+static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
1079+ enum tegra_io_pad id,
9981080 unsigned long *request,
9991081 unsigned long *status,
10001082 u32 *mask)
@@ -1003,7 +1085,7 @@ static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id, · 2 unmodified lines
10031085
10041086 pad = tegra_io_pad_find(pmc, id);
10051087 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);
10071089 return -ENOENT;
10081090 }
10091091
@@ -1023,43 +1105,44 @@ static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id, · 13 unmodified lines
10231105 return 0;
10241106 }
10251107
1026−static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
1027− unsigned long *status, u32 *mask)
1108+static int tegra_io_pad_prepare(struct tegra_pmc *pmc, enum tegra_io_pad id,
1109+ unsigned long *request, unsigned long *status,
1110+ u32 *mask)
10281111 {
10291112 unsigned long rate, value;
10301113 int err;
10311114
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);
10331116 if (err)
10341117 return err;
10351118
10361119 if (pmc->clk) {
10371120 rate = clk_get_rate(pmc->clk);
10381121 if (!rate) {
1039− pr_err("failed to get clock rate\n");
1122+ dev_err(pmc->dev, "failed to get clock rate\n");
10401123 return -ENODEV;
10411124 }
10421125
1043− tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
1126+ tegra_pmc_writel(pmc, DPD_SAMPLE_ENABLE, DPD_SAMPLE);
10441127
10451128 /* must be at least 200 ns, in APB (PCLK) clock cycles */
10461129 value = DIV_ROUND_UP(1000000000, rate);
10471130 value = DIV_ROUND_UP(200, value);
1048− tegra_pmc_writel(value, SEL_DPD_TIM);
1131+ tegra_pmc_writel(pmc, value, SEL_DPD_TIM);
10491132 }
10501133
10511134 return 0;
10521135 }
10531136
1054−static int tegra_io_pad_poll(unsigned long offset, u32 mask,
1055− u32 val, unsigned long timeout)
1137+static int tegra_io_pad_poll(struct tegra_pmc *pmc, unsigned long offset,
1138+ u32 mask, u32 val, unsigned long timeout)
10561139 {
10571140 u32 value;
10581141
10591142 timeout = jiffies + msecs_to_jiffies(timeout);
10601143
10611144 while (time_after(timeout, jiffies)) {
1062− value = tegra_pmc_readl(offset);
1145+ value = tegra_pmc_readl(pmc, offset);
10631146 if ((value & mask) == val)
10641147 return 0;
10651148
@@ -1069,10 +1152,10 @@ static int tegra_io_pad_poll(unsigned long offset, u32 mask, · 3 unmodified lines
10691152 return -ETIMEDOUT;
10701153 }
10711154
1072−static void tegra_io_pad_unprepare(void)
1155+static void tegra_io_pad_unprepare(struct tegra_pmc *pmc)
10731156 {
10741157 if (pmc->clk)
1075− tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
1158+ tegra_pmc_writel(pmc, DPD_SAMPLE_DISABLE, DPD_SAMPLE);
10761159 }
10771160
10781161 /**
@@ -1089,21 +1172,21 @@ int tegra_io_pad_power_enable(enum tegra_io_pad id) · 10 unmodified lines
10891172
10901173 mutex_lock(&pmc->powergates_lock);
10911174
1092− err = tegra_io_pad_prepare(id, &request, &status, &mask);
1175+ err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
10931176 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);
10951178 goto unlock;
10961179 }
10971180
1098− tegra_pmc_writel(IO_DPD_REQ_CODE_OFF | mask, request);
1181+ tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_OFF | mask, request);
10991182
1100− err = tegra_io_pad_poll(status, mask, 0, 250);
1183+ err = tegra_io_pad_poll(pmc, status, mask, 0, 250);
11011184 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);
11031186 goto unlock;
11041187 }
11051188
1106− tegra_io_pad_unprepare();
1189+ tegra_io_pad_unprepare(pmc);
11071190
11081191 unlock:
11091192 mutex_unlock(&pmc->powergates_lock);
@@ -1125,21 +1208,21 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id) · 15 unmodified lines
11251208
11261209 mutex_lock(&pmc->powergates_lock);
11271210
1128− err = tegra_io_pad_prepare(id, &request, &status, &mask);
1211+ err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
11291212 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);
11311214 goto unlock;
11321215 }
11331216
1134− tegra_pmc_writel(IO_DPD_REQ_CODE_ON | mask, request);
1217+ tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_ON | mask, request);
11351218
1136− err = tegra_io_pad_poll(status, mask, mask, 250);
1219+ err = tegra_io_pad_poll(pmc, status, mask, mask, 250);
11371220 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);
11391222 goto unlock;
11401223 }
11411224
1142− tegra_io_pad_unprepare();
1225+ tegra_io_pad_unprepare(pmc);
11431226
11441227 unlock:
11451228 mutex_unlock(&pmc->powergates_lock);
@@ -1147,22 +1230,24 @@ unlock: · 1 unmodified line
11471230 }
11481231 EXPORT_SYMBOL(tegra_io_pad_power_disable);
11491232
1150−static int tegra_io_pad_is_powered(enum tegra_io_pad id)
1233+static int tegra_io_pad_is_powered(struct tegra_pmc *pmc, enum tegra_io_pad id)
11511234 {
11521235 unsigned long request, status;
11531236 u32 mask, value;
11541237 int err;
11551238
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);
11571241 if (err)
11581242 return err;
11591243
1160− value = tegra_pmc_readl(status);
1244+ value = tegra_pmc_readl(pmc, status);
11611245
11621246 return !(value & mask);
11631247 }
11641248
1165−static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
1249+static int tegra_io_pad_set_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id,
1250+ int voltage)
11661251 {
11671252 const struct tegra_io_pad_soc *pad;
11681253 u32 value;
@@ -1177,29 +1262,29 @@ static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage) · 8 unmodified lines
11771262 mutex_lock(&pmc->powergates_lock);
11781263
11791264 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);
11811266
11821267 if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
11831268 value &= ~BIT(pad->voltage);
11841269 else
11851270 value |= BIT(pad->voltage);
11861271
1187− tegra_pmc_writel(value, PMC_IMPL_E_33V_PWR);
1272+ tegra_pmc_writel(pmc, value, PMC_IMPL_E_33V_PWR);
11881273 } else {
11891274 /* 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);
11911276 value |= BIT(pad->voltage);
1192− tegra_pmc_writel(value, PMC_PWR_DET);
1277+ tegra_pmc_writel(pmc, value, PMC_PWR_DET);
11931278
11941279 /* update I/O voltage */
1195− value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
1280+ value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
11961281
11971282 if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
11981283 value &= ~BIT(pad->voltage);
11991284 else
12001285 value |= BIT(pad->voltage);
12011286
1202− tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
1287+ tegra_pmc_writel(pmc, value, PMC_PWR_DET_VALUE);
12031288 }
12041289
12051290 mutex_unlock(&pmc->powergates_lock);
@@ -1209,7 +1294,7 @@ static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage) · 3 unmodified lines
12091294 return 0;
12101295 }
12111296
1212−static int tegra_io_pad_get_voltage(enum tegra_io_pad id)
1297+static int tegra_io_pad_get_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id)
12131298 {
12141299 const struct tegra_io_pad_soc *pad;
12151300 u32 value;
@@ -1222,9 +1307,9 @@ static int tegra_io_pad_get_voltage(enum tegra_io_pad id) · 6 unmodified lines
12221307 return -ENOTSUPP;
12231308
12241309 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);
12261311 else
1227− value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
1312+ value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
12281313
12291314 if ((value & BIT(pad->voltage)) == 0)
12301315 return TEGRA_IO_PAD_VOLTAGE_1V8;
@@ -1296,21 +1381,21 @@ void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode) · 65 unmodified lines
12961381
12971382 ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
12981383 do_div(ticks, USEC_PER_SEC);
1299− tegra_pmc_writel(ticks, PMC_CPUPWRGOOD_TIMER);
1384+ tegra_pmc_writel(pmc, ticks, PMC_CPUPWRGOOD_TIMER);
13001385
13011386 ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
13021387 do_div(ticks, USEC_PER_SEC);
1303− tegra_pmc_writel(ticks, PMC_CPUPWROFF_TIMER);
1388+ tegra_pmc_writel(pmc, ticks, PMC_CPUPWROFF_TIMER);
13041389
13051390 wmb();
13061391
13071392 pmc->rate = rate;
13081393 }
13091394
1310− value = tegra_pmc_readl(PMC_CNTRL);
1395+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
13111396 value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
13121397 value |= PMC_CNTRL_CPU_PWRREQ_OE;
1313− tegra_pmc_writel(value, PMC_CNTRL);
1398+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
13141399 }
13151400 #endif
13161401
@@ -1432,13 +1517,13 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) · 115 unmodified lines
14321517 if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux))
14331518 pinmux = 0;
14341519
1435− value = tegra_pmc_readl(PMC_SENSOR_CTRL);
1520+ value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
14361521 value |= PMC_SENSOR_CTRL_SCRATCH_WRITE;
1437− tegra_pmc_writel(value, PMC_SENSOR_CTRL);
1522+ tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
14381523
14391524 value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) |
14401525 (reg_addr << PMC_SCRATCH54_ADDR_SHIFT);
1441− tegra_pmc_writel(value, PMC_SCRATCH54);
1526+ tegra_pmc_writel(pmc, value, PMC_SCRATCH54);
14421527
14431528 value = PMC_SCRATCH55_RESET_TEGRA;
14441529 value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT;
@@ -1456,11 +1541,11 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) · 11 unmodified lines
14561541
14571542 value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT;
14581543
1459− tegra_pmc_writel(value, PMC_SCRATCH55);
1544+ tegra_pmc_writel(pmc, value, PMC_SCRATCH55);
14601545
1461− value = tegra_pmc_readl(PMC_SENSOR_CTRL);
1546+ value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
14621547 value |= PMC_SENSOR_CTRL_ENABLE_RST;
1463− tegra_pmc_writel(value, PMC_SENSOR_CTRL);
1548+ tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
14641549
14651550 dev_info(pmc->dev, "emergency thermal reset enabled\n");
14661551
@@ -1470,12 +1555,16 @@ out: · 3 unmodified lines
14701555
14711556 static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
14721557 {
1558+ struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1559+
14731560 return pmc->soc->num_io_pads;
14741561 }
14751562
1476−static const char *tegra_io_pad_pinctrl_get_group_name(
1477− struct pinctrl_dev *pctl, unsigned int group)
1563+static const char *tegra_io_pad_pinctrl_get_group_name(struct pinctrl_dev *pctl,
1564+ unsigned int group)
14781565 {
1566+ struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl);
1567+
14791568 return pmc->soc->io_pads[group].name;
14801569 }
14811570
@@ -1484,8 +1573,11 @@ static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev, · 2 unmodified lines
14841573 const unsigned int **pins,
14851574 unsigned int *num_pins)
14861575 {
1576+ struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1577+
14871578 *pins = &pmc->soc->io_pads[group].id;
14881579 *num_pins = 1;
1580+
14891581 return 0;
14901582 }
14911583
@@ -1500,27 +1592,33 @@ static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = { · 8 unmodified lines
15001592 static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
15011593 unsigned int pin, unsigned long *config)
15021594 {
1503− const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
15041595 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;
15051598 int ret;
15061599 u32 arg;
15071600
1601+ pad = tegra_io_pad_find(pmc, pin);
15081602 if (!pad)
15091603 return -EINVAL;
15101604
15111605 switch (param) {
15121606 case PIN_CONFIG_POWER_SOURCE:
1513− ret = tegra_io_pad_get_voltage(pad->id);
1607+ ret = tegra_io_pad_get_voltage(pmc, pad->id);
15141608 if (ret < 0)
15151609 return ret;
1610+
15161611 arg = ret;
15171612 break;
1613+
15181614 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);
15201616 if (ret < 0)
15211617 return ret;
1618+
15221619 arg = !ret;
15231620 break;
1621+
15241622 default:
15251623 return -EINVAL;
15261624 }
@@ -1534,12 +1632,14 @@ static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev, · 7 unmodified lines
15341632 unsigned int pin, unsigned long *configs,
15351633 unsigned int num_configs)
15361634 {
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;
15381637 enum pin_config_param param;
15391638 unsigned int i;
15401639 int err;
15411640 u32 arg;
15421641
1642+ pad = tegra_io_pad_find(pmc, pin);
15431643 if (!pad)
15441644 return -EINVAL;
15451645
@@ -1560,7 +1660,7 @@ static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev, · 14 unmodified lines
15601660 if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
15611661 arg != TEGRA_IO_PAD_VOLTAGE_3V3)
15621662 return -EINVAL;
1563− err = tegra_io_pad_set_voltage(pad->id, arg);
1663+ err = tegra_io_pad_set_voltage(pmc, pad->id, arg);
15641664 if (err)
15651665 return err;
15661666 break;
@@ -1585,7 +1685,7 @@ static struct pinctrl_desc tegra_pmc_pctl_desc = { · 18 unmodified lines
15851685
15861686 static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
15871687 {
1588− int err = 0;
1688+ int err;
15891689
15901690 if (!pmc->soc->num_pin_descs)
15911691 return 0;
@@ -1598,18 +1698,20 @@ static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc) · 6 unmodified lines
15981698 pmc);
15991699 if (IS_ERR(pmc->pctl_dev)) {
16001700 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;
16021704 }
16031705
1604− return err;
1706+ return 0;
16051707 }
16061708
16071709 static ssize_t reset_reason_show(struct device *dev,
1608− struct device_attribute *attr, char *buf)
1710+ struct device_attribute *attr, char *buf)
16091711 {
16101712 u32 value, rst_src;
16111713
1612− value = tegra_pmc_readl(pmc->soc->regs->rst_status);
1714+ value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
16131715 rst_src = (value & pmc->soc->regs->rst_source_mask) >>
16141716 pmc->soc->regs->rst_source_shift;
16151717
@@ -1619,11 +1721,11 @@ static ssize_t reset_reason_show(struct device *dev, · 3 unmodified lines
16191721 static DEVICE_ATTR_RO(reset_reason);
16201722
16211723 static ssize_t reset_level_show(struct device *dev,
1622− struct device_attribute *attr, char *buf)
1724+ struct device_attribute *attr, char *buf)
16231725 {
16241726 u32 value, rst_lvl;
16251727
1626− value = tegra_pmc_readl(pmc->soc->regs->rst_status);
1728+ value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
16271729 rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
16281730 pmc->soc->regs->rst_level_shift;
16291731
@@ -1641,16 +1743,16 @@ static void tegra_pmc_reset_sysfs_init(struct tegra_pmc *pmc) · 11 unmodified lines
16411743 err = device_create_file(dev, &dev_attr_reset_reason);
16421744 if (err < 0)
16431745 dev_warn(dev,
1644− "failed to create attr \"reset_reason\": %d\n",
1645− err);
1746+ "failed to create attr \"reset_reason\": %d\n",
1747+ err);
16461748 }
16471749
16481750 if (pmc->soc->reset_levels) {
16491751 err = device_create_file(dev, &dev_attr_reset_level);
16501752 if (err < 0)
16511753 dev_warn(dev,
1652− "failed to create attr \"reset_level\": %d\n",
1653− err);
1754+ "failed to create attr \"reset_level\": %d\n",
1755+ err);
16541756 }
16551757 }
16561758
@@ -1920,6 +2022,8 @@ static int tegra_pmc_probe(struct platform_device *pdev) · 263 unmodified lines
19202022 pmc->base = base;
19212023 mutex_unlock(&pmc->powergates_lock);
19222024
2025+ platform_set_drvdata(pdev, pmc);
2026+
19232027 return 0;
19242028
19252029 cleanup_restart_handler:
@@ -1932,14 +2036,18 @@ cleanup_debugfs: · 6 unmodified lines
19322036 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
19332037 static int tegra_pmc_suspend(struct device *dev)
19342038 {
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);
19362042
19372043 return 0;
19382044 }
19392045
19402046 static int tegra_pmc_resume(struct device *dev)
19412047 {
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);
19432051
19442052 return 0;
19452053 }
@@ -1976,11 +2084,11 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc) · 30 unmodified lines
19762084 u32 value;
19772085
19782086 /* Always enable CPU power request */
1979− value = tegra_pmc_readl(PMC_CNTRL);
2087+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
19802088 value |= PMC_CNTRL_CPU_PWRREQ_OE;
1981− tegra_pmc_writel(value, PMC_CNTRL);
2089+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
19822090
1983− value = tegra_pmc_readl(PMC_CNTRL);
2091+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
19842092
19852093 if (pmc->sysclkreq_high)
19862094 value &= ~PMC_CNTRL_SYSCLK_POLARITY;
@@ -1988,12 +2096,12 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc) · 1 unmodified line
19882096 value |= PMC_CNTRL_SYSCLK_POLARITY;
19892097
19902098 /* configure the output polarity while the request is tristated */
1991− tegra_pmc_writel(value, PMC_CNTRL);
2099+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
19922100
19932101 /* now enable the request */
1994− value = tegra_pmc_readl(PMC_CNTRL);
2102+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
19952103 value |= PMC_CNTRL_SYSCLK_OE;
1996− tegra_pmc_writel(value, PMC_CNTRL);
2104+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
19972105 }
19982106
19992107 static 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, · 2 unmodified lines
20022110 {
20032111 u32 value;
20042112
2005− value = tegra_pmc_readl(PMC_CNTRL);
2113+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
20062114
20072115 if (invert)
20082116 value |= PMC_CNTRL_INTR_POLARITY;
20092117 else
20102118 value &= ~PMC_CNTRL_INTR_POLARITY;
20112119
2012− tegra_pmc_writel(value, PMC_CNTRL);
2120+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
20132121 }
20142122
20152123 static const struct tegra_pmc_soc tegra20_pmc_soc = {
@@ -2019,6 +2127,9 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = { · 3 unmodified lines
20192127 .cpu_powergates = NULL,
20202128 .has_tsense_reset = false,
20212129 .has_gpu_clamps = false,
2130+ .needs_mbist_war = false,
2131+ .has_impl_33v_pwr = false,
2132+ .maybe_tz_only = false,
20222133 .num_io_pads = 0,
20232134 .io_pads = NULL,
20242135 .num_pin_descs = 0,
@@ -2063,7 +2174,9 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = { · 38 unmodified lines
20632174 .cpu_powergates = tegra30_cpu_powergates,
20642175 .has_tsense_reset = true,
20652176 .has_gpu_clamps = false,
2177+ .needs_mbist_war = false,
20662178 .has_impl_33v_pwr = false,
2179+ .maybe_tz_only = false,
20672180 .num_io_pads = 0,
20682181 .io_pads = NULL,
20692182 .num_pin_descs = 0,
@@ -2112,7 +2225,9 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = { · 42 unmodified lines
21122225 .cpu_powergates = tegra114_cpu_powergates,
21132226 .has_tsense_reset = true,
21142227 .has_gpu_clamps = false,
2228+ .needs_mbist_war = false,
21152229 .has_impl_33v_pwr = false,
2230+ .maybe_tz_only = false,
21162231 .num_io_pads = 0,
21172232 .io_pads = NULL,
21182233 .num_pin_descs = 0,
@@ -2221,7 +2336,9 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = { · 102 unmodified lines
22212336 .cpu_powergates = tegra124_cpu_powergates,
22222337 .has_tsense_reset = true,
22232338 .has_gpu_clamps = true,
2339+ .needs_mbist_war = false,
22242340 .has_impl_33v_pwr = false,
2341+ .maybe_tz_only = false,
22252342 .num_io_pads = ARRAY_SIZE(tegra124_io_pads),
22262343 .io_pads = tegra124_io_pads,
22272344 .num_pin_descs = ARRAY_SIZE(tegra124_pin_descs),
@@ -2325,8 +2442,9 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = { · 97 unmodified lines
23252442 .cpu_powergates = tegra210_cpu_powergates,
23262443 .has_tsense_reset = true,
23272444 .has_gpu_clamps = true,
2328− .has_impl_33v_pwr = false,
23292445 .needs_mbist_war = true,
2446+ .has_impl_33v_pwr = false,
2447+ .maybe_tz_only = true,
23302448 .num_io_pads = ARRAY_SIZE(tegra210_io_pads),
23312449 .io_pads = tegra210_io_pads,
23322450 .num_pin_descs = ARRAY_SIZE(tegra210_pin_descs),
@@ -2413,7 +2531,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc, · 80 unmodified lines
24132531
24142532 index = of_property_match_string(np, "reg-names", "wake");
24152533 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");
24172535 return;
24182536 }
24192537
@@ -2421,7 +2539,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc, · 1 unmodified line
24212539
24222540 wake = ioremap_nocache(regs.start, resource_size(&regs));
24232541 if (!wake) {
2424− pr_err("failed to map PMC wake registers\n");
2542+ dev_err(pmc->dev, "failed to map PMC wake registers\n");
24252543 return;
24262544 }
24272545
@@ -2438,7 +2556,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc, · 10 unmodified lines
24382556 }
24392557
24402558 static 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)),
24422560 TEGRA_WAKE_IRQ("rtc", 73, 10),
24432561 };
24442562
@@ -2449,7 +2567,9 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = { · 4 unmodified lines
24492567 .cpu_powergates = NULL,
24502568 .has_tsense_reset = false,
24512569 .has_gpu_clamps = false,
2570+ .needs_mbist_war = false,
24522571 .has_impl_33v_pwr = true,
2572+ .maybe_tz_only = false,
24532573 .num_io_pads = ARRAY_SIZE(tegra186_io_pads),
24542574 .io_pads = tegra186_io_pads,
24552575 .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs),
@@ -2527,6 +2647,9 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = { · 71 unmodified lines
25272647 .cpu_powergates = NULL,
25282648 .has_tsense_reset = false,
25292649 .has_gpu_clamps = false,
2650+ .needs_mbist_war = false,
2651+ .has_impl_33v_pwr = false,
2652+ .maybe_tz_only = false,
25302653 .num_io_pads = ARRAY_SIZE(tegra194_io_pads),
25312654 .io_pads = tegra194_io_pads,
25322655 .regs = &tegra186_pmc_regs,
@@ -2561,6 +2684,32 @@ static struct platform_driver tegra_pmc_driver = { · 28 unmodified lines
25612684 };
25622685 builtin_platform_driver(tegra_pmc_driver);
25632686
2687+static 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+
25642713 /*
25652714 * Early initialization to allow access to registers in the very early boot
25662715 * process.
@@ -2623,6 +2772,9 @@ static int __init tegra_pmc_early_init(void) · 56 unmodified lines
26232772 if (np) {
26242773 pmc->soc = match->data;
26252774
2775+ if (pmc->soc->maybe_tz_only)
2776+ pmc->tz_only = tegra_pmc_detect_tz_only(pmc);
2777+
26262778 tegra_powergate_init(pmc, np);
26272779
26282780 /*
drivers/soc/ti/knav_dma.c+1−1
@@ -598,7 +598,7 @@ static int pktdma_init_chan(struct knav_dma_device *dma, · 597 unmodified lines
598598
599599 INIT_LIST_HEAD(&chan->list);
600600 chan->dma = dma;
601− chan->direction = DMA_NONE;
601+ chan->direction = DMA_TRANS_NONE;
602602 atomic_set(&chan->ref_count, 0);
603603 spin_lock_init(&chan->lock);
604604
drivers/soc/xilinx/Kconfig+20−0
@@ -17,4 +17,24 @@ config XILINX_VCU · 16 unmodified lines
1717 To compile this driver as a module, choose M here: the
1818 module will be called xlnx_vcu.
1919
20+config 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+
31+config 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+
2040 endmenu
drivers/soc/xilinx/Makefile+2−0
@@ -1,2 +1,4 @@
11 # SPDX-License-Identifier: GPL-2.0
22 obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o
3+obj-$(CONFIG_ZYNQMP_POWER) += zynqmp_power.o
4+obj-$(CONFIG_ZYNQMP_PM_DOMAINS) += zynqmp_pm_domains.o
drivers/soc/xilinx/zynqmp_pm_domains.c+321−0
@@ -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+ */
32+struct 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+ */
49+static 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+ */
70+static 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+ */
103+static 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+ */
158+static 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+ */
195+static 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+
225+static 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+
254+done:
255+ if (!genpd_data->domains[i] || i == ZYNQMP_NUM_DOMAINS)
256+ return ERR_PTR(-ENOENT);
257+
258+ return genpd_data->domains[i];
259+}
260+
261+static 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+
305+static 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+
312+static 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+};
319+module_platform_driver(zynqmp_power_domain_driver);
320+
321+MODULE_ALIAS("platform:zynqmp_power_controller");
drivers/soc/xilinx/zynqmp_power.c+178−0
@@ -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+
20+enum 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+
28+static const char *const suspend_modes[] = {
29+ [PM_SUSPEND_MODE_STD] = "standard",
30+ [PM_SUSPEND_MODE_POWER_OFF] = "power-off",
31+};
32+
33+static enum pm_suspend_mode suspend_mode = PM_SUSPEND_MODE_STD;
34+
35+enum pm_api_cb_id {
36+ PM_INIT_SUSPEND_CB = 30,
37+ PM_ACKNOWLEDGE_CB,
38+ PM_NOTIFY_CB,
39+};
40+
41+static void zynqmp_pm_get_callback_data(u32 *buf)
42+{
43+ zynqmp_pm_invoke_fn(GET_CALLBACK_DATA, 0, 0, 0, 0, buf);
44+}
45+
46+static 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+
70+static 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+
90+static 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+
116+static DEVICE_ATTR_RW(suspend_mode);
117+
118+static 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+
157+static 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+
164+static const struct of_device_id pm_of_match[] = {
165+ { .compatible = "xlnx,zynqmp-power", },
166+ { /* end of table */ },
167+};
168+MODULE_DEVICE_TABLE(of, pm_of_match);
169+
170+static 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+};
178+module_platform_driver(zynqmp_pm_platform_driver);
drivers/tee/optee/Makefile+1−0
@@ -5,3 +5,4 @@ optee-objs += call.o · 4 unmodified lines
55 optee-objs += rpc.o
66 optee-objs += supp.o
77 optee-objs += shm_pool.o
8+optee-objs += device.o
drivers/tee/optee/core.c+4−0
@@ -634,6 +634,10 @@ static struct optee *optee_probe(struct device_node *np) · 633 unmodified lines
634634 if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
635635 pr_info("dynamic shared memory is enabled\n");
636636
637+ rc = optee_enumerate_devices();
638+ if (rc)
639+ goto err;
640+
637641 pr_info("initialized driver\n");
638642 return optee;
639643 err:
drivers/tee/optee/device.c+160−0
@@ -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+
26+static 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+
34+static 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+
68+static 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+
90+int 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+
152+out_shm:
153+ tee_shm_free(device_shm);
154+out_sess:
155+ tee_client_close_session(ctx, sess_arg.session);
156+out_ctx:
157+ tee_client_close_context(ctx);
158+
159+ return rc;
160+}
drivers/tee/optee/optee_msg.h+2−24
@@ -1,28 +1,6 @@
1+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
12 /*
2− * Copyright (c) 2015-2016, 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.
3+ * Copyright (c) 2015-2019, Linaro Limited
264 */
275 #ifndef _OPTEE_MSG_H
286 #define _OPTEE_MSG_H
drivers/tee/optee/optee_private.h+3−0
@@ -28,6 +28,7 @@ · 27 unmodified lines
2828 #define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006
2929 #define TEEC_ERROR_COMMUNICATION 0xFFFF000E
3030 #define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
31+#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
3132
3233 #define TEEC_ORIGIN_COMMS 0x00000002
3334
@@ -181,6 +182,8 @@ void optee_free_pages_list(void *array, size_t num_entries); · 147 unmodified lines
181182 void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
182183 size_t page_offset);
183184
185+int optee_enumerate_devices(void);
186+
184187 /*
185188 * Small helpers
186189 */
drivers/tee/optee/optee_smc.h+2−24
@@ -1,28 +1,6 @@
1+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
12 /*
2− * Copyright (c) 2015-2016, 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.
3+ * Copyright (c) 2015-2019, Linaro Limited
264 */
275 #ifndef OPTEE_SMC_H
286 #define OPTEE_SMC_H
drivers/tee/optee/supp.c+9−1
@@ -88,10 +88,18 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, · 87 unmodified lines
8888 {
8989 struct optee *optee = tee_get_drvdata(ctx->teedev);
9090 struct optee_supp *supp = &optee->supp;
91− struct optee_supp_req *req = kzalloc(sizeof(*req), GFP_KERNEL);
91+ struct optee_supp_req *req;
9292 bool interruptable;
9393 u32 ret;
9494
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);
95103 if (!req)
96104 return TEEC_ERROR_OUT_OF_MEMORY;
97105
drivers/tee/tee_core.c+74−4
@@ -15,7 +15,6 @@ · 14 unmodified lines
1515 #define pr_fmt(fmt) "%s: " fmt, __func__
1616
1717 #include <linux/cdev.h>
18−#include <linux/device.h>
1918 #include <linux/fs.h>
2019 #include <linux/idr.h>
2120 #include <linux/module.h>
@@ -106,6 +105,11 @@ static int tee_open(struct inode *inode, struct file *filp) · 84 unmodified lines
106105 if (IS_ERR(ctx))
107106 return PTR_ERR(ctx);
108107
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;
109113 filp->private_data = ctx;
110114 return 0;
111115 }
@@ -982,6 +986,16 @@ tee_client_open_context(struct tee_context *start, · 870 unmodified lines
982986 } while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM);
983987
984988 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+
985999 return ctx;
9861000 }
9871001 EXPORT_SYMBOL_GPL(tee_client_open_context);
@@ -1027,6 +1041,48 @@ int tee_client_invoke_func(struct tee_context *ctx, · 39 unmodified lines
10271041 }
10281042 EXPORT_SYMBOL_GPL(tee_client_invoke_func);
10291043
1044+int 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+
1053+static 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+
1071+static 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+
1079+struct bus_type tee_bus_type = {
1080+ .name = "tee",
1081+ .match = tee_client_device_match,
1082+ .uevent = tee_client_device_uevent,
1083+};
1084+EXPORT_SYMBOL_GPL(tee_bus_type);
1085+
10301086 static int __init tee_init(void)
10311087 {
10321088 int rc;
@@ -1040,18 +1096,32 @@ static int __init tee_init(void) · 7 unmodified lines
10401096 rc = alloc_chrdev_region(&tee_devt, 0, TEE_NUM_DEVICES, "tee");
10411097 if (rc) {
10421098 pr_err("failed to allocate char dev region\n");
1043− class_destroy(tee_class);
1044− tee_class = NULL;
1099+ goto out_unreg_class;
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;
10451106 }
10461107
1108+ return 0;
1109+
1110+out_unreg_chrdev:
1111+ unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
1112+out_unreg_class:
1113+ class_destroy(tee_class);
1114+ tee_class = NULL;
1115+
10471116 return rc;
10481117 }
10491118
10501119 static void __exit tee_exit(void)
10511120 {
1121+ bus_unregister(&tee_bus_type);
1122+ unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
10521123 class_destroy(tee_class);
10531124 tee_class = NULL;
1054− unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
10551125 }
10561126
10571127 subsys_initcall(tee_init);
drivers/watchdog/bcm2835_wdt.c+9−17
@@ -12,6 +12,7 @@ · 11 unmodified lines
1212
1313 #include <linux/delay.h>
1414 #include <linux/types.h>
15+#include <linux/mfd/bcm2835-pm.h>
1516 #include <linux/module.h>
1617 #include <linux/io.h>
1718 #include <linux/watchdog.h>
@@ -47,6 +48,8 @@ struct bcm2835_wdt { · 29 unmodified lines
4748 spinlock_t lock;
4849 };
4950
51+static struct bcm2835_wdt *bcm2835_power_off_wdt;
52+
5053 static unsigned int heartbeat;
5154 static bool nowayout = WATCHDOG_NOWAYOUT;
5255
@@ -148,10 +151,7 @@ static struct watchdog_device bcm2835_wdt_wdd = { · 95 unmodified lines
148151 */
149152 static void bcm2835_power_off(void)
150153 {
151− struct device_node *np =
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);
154+ struct bcm2835_wdt *wdt = bcm2835_power_off_wdt;
155155 u32 val;
156156
157157 /*
@@ -169,7 +169,7 @@ static void bcm2835_power_off(void) · 11 unmodified lines
169169
170170 static int bcm2835_wdt_probe(struct platform_device *pdev)
171171 {
172− struct resource *res;
172+ struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
173173 struct device *dev = &pdev->dev;
174174 struct bcm2835_wdt *wdt;
175175 int err;
@@ -181,10 +181,7 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) · 5 unmodified lines
181181
182182 spin_lock_init(&wdt->lock);
183183
184− res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
185− wdt->base = devm_ioremap_resource(dev, res);
186− if (IS_ERR(wdt->base))
187− return PTR_ERR(wdt->base);
184+ wdt->base = pm->base;
188185
189186 watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt);
190187 watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
@@ -211,8 +208,10 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) · 20 unmodified lines
211208 return err;
212209 }
213210
214− if (pm_power_off == NULL)
211+ if (pm_power_off == NULL) {
215212 pm_power_off = bcm2835_power_off;
213+ bcm2835_power_off_wdt = wdt;
214+ }
216215
217216 dev_info(dev, "Broadcom BCM2835 watchdog timer");
218217 return 0;
@@ -226,18 +225,11 @@ static int bcm2835_wdt_remove(struct platform_device *pdev) · 7 unmodified lines
226225 return 0;
227226 }
228227
229−static const struct of_device_id bcm2835_wdt_of_match[] = {
230− { .compatible = "brcm,bcm2835-pm-wdt", },
231− {},
232−};
233−MODULE_DEVICE_TABLE(of, bcm2835_wdt_of_match);
234−
235228 static struct platform_driver bcm2835_wdt_driver = {
236229 .probe = bcm2835_wdt_probe,
237230 .remove = bcm2835_wdt_remove,
238231 .driver = {
239232 .name = "bcm2835-wdt",
240− .of_match_table = bcm2835_wdt_of_match,
241233 },
242234 };
243235 module_platform_driver(bcm2835_wdt_driver);
include/dt-bindings/power/qcom-rpmpd.h+39−0
@@ -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
include/dt-bindings/power/xlnx-zynqmp-power.h+39−0
@@ -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
include/dt-bindings/reset/amlogic,meson-g12a-reset.h+134−0
@@ -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
include/dt-bindings/reset/imx8mq-reset.h+64−0
@@ -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
include/dt-bindings/reset/xlnx-zynqmp-resets.h+130−0
@@ -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
include/dt-bindings/soc/bcm2835-pm.h+28−0
@@ -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 */
include/linux/firmware/imx/svc/misc.h+3−0
@@ -52,4 +52,7 @@ int imx_sc_misc_set_control(struct imx_sc_ipc *ipc, u32 resource, · 51 unmodified lines
5252 int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource,
5353 u8 ctrl, u32 *val);
5454
55+int imx_sc_pm_cpu_start(struct imx_sc_ipc *ipc, u32 resource,
56+ bool enable, u64 phys_addr);
57+
5558 #endif /* _SC_MISC_API_H */
include/linux/firmware/xlnx-zynqmp.h+184−0
@@ -28,12 +28,35 @@ · 27 unmodified lines
2828 /* SMC SIP service Call Function Identifier Prefix */
2929 #define PM_SIP_SVC 0xC2000000
3030 #define PM_GET_TRUSTZONE_VERSION 0xa03
31+#define PM_SET_SUSPEND_MODE 0xa02
32+#define GET_CALLBACK_DATA 0xa01
3133
3234 /* Number of 32bits values in payload */
3335 #define PAYLOAD_ARG_CNT 4U
3436
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+
3551 enum pm_api_id {
3652 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,
3760 PM_IOCTL = 34,
3861 PM_QUERY_DATA,
3962 PM_CLOCK_ENABLE,
@@ -75,6 +98,149 @@ enum pm_query_id { · 35 unmodified lines
7598 PM_QID_CLOCK_GET_NUM_CLOCKS = 12,
7699 };
77100
101+enum zynqmp_pm_reset_action {
102+ PM_RESET_ACTION_RELEASE,
103+ PM_RESET_ACTION_ASSERT,
104+ PM_RESET_ACTION_PULSE,
105+};
106+
107+enum 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+
232+enum zynqmp_pm_suspend_reason {
233+ SUSPEND_POWER_REQUEST = 201,
234+ SUSPEND_ALERT,
235+ SUSPEND_SYSTEM_SHUTDOWN,
236+};
237+
238+enum 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+
78244 /**
79245 * struct zynqmp_pm_query_data - PM query data
80246 * @qid: query ID
@@ -91,6 +257,7 @@ struct zynqmp_pm_query_data { · 10 unmodified lines
91257
92258 struct zynqmp_eemi_ops {
93259 int (*get_api_version)(u32 *version);
260+ int (*get_chipid)(u32 *idcode, u32 *version);
94261 int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out);
95262 int (*clock_enable)(u32 clock_id);
96263 int (*clock_disable)(u32 clock_id);
@@ -102,8 +269,25 @@ struct zynqmp_eemi_ops { · 5 unmodified lines
102269 int (*clock_setparent)(u32 clock_id, u32 parent_id);
103270 int (*clock_getparent)(u32 clock_id, u32 *parent_id);
104271 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);
105286 };
106287
288+int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
289+ u32 arg2, u32 arg3, u32 *ret_payload);
290+
107291 #if IS_REACHABLE(CONFIG_ARCH_ZYNQMP)
108292 const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void);
109293 #else
include/linux/fsl/guts.h+0−2
@@ -135,8 +135,6 @@ struct ccsr_guts { · 134 unmodified lines
135135 u32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */
136136 } __attribute__ ((packed));
137137
138−u32 fsl_guts_get_svr(void);
139−
140138 /* Alternate function signal multiplex control */
141139 #define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
142140
include/linux/mfd/bcm2835-pm.h+14−0
@@ -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+
8+struct bcm2835_pm {
9+ struct device *dev;
10+ void __iomem *base;
11+ void __iomem *asb;
12+};
13+
14+#endif /* BCM2835_MFD_PM_H */
include/linux/mod_devicetable.h+9−0
@@ -779,4 +779,13 @@ struct typec_device_id { · 778 unmodified lines
779779 kernel_ulong_t driver_data;
780780 };
781781
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+ */
787+struct tee_client_device_id {
788+ uuid_t uuid;
789+};
790+
782791 #endif /* LINUX_MOD_DEVICETABLE_H */
include/linux/pm_opp.h+7−0
@@ -86,6 +86,8 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp); · 85 unmodified lines
8686
8787 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
8888
89+unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp);
90+
8991 bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp);
9092
9193 int 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) · 66 unmodified lines
158160 return 0;
159161 }
160162
163+static inline unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp)
164+{
165+ return 0;
166+}
167+
161168 static inline bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
162169 {
163170 return false;
include/linux/reset/socfpga.h+7−0
@@ -0,0 +1,7 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+#ifndef __LINUX_RESET_SOCFPGA_H__
3+#define __LINUX_RESET_SOCFPGA_H__
4+
5+void __init socfpga_reset_init(void);
6+
7+#endif /* __LINUX_RESET_SOCFPGA_H__ */
include/linux/reset/sunxi.h+7−0
@@ -0,0 +1,7 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+#ifndef __LINUX_RESET_SUNXI_H__
3+#define __LINUX_RESET_SUNXI_H__
4+
5+void __init sun6i_reset_init(void);
6+
7+#endif /* __LINUX_RESET_SUNXI_H__ */
include/linux/soc/qcom/llcc-qcom.h+6−0
@@ -162,6 +162,12 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc); · 161 unmodified lines
162162 */
163163 int qcom_llcc_probe(struct platform_device *pdev,
164164 const struct llcc_slice_config *table, u32 sz);
165+
166+/**
167+ * qcom_llcc_remove - remove the sct table
168+ * @pdev: Platform device pointer
169+ */
170+int qcom_llcc_remove(struct platform_device *pdev);
165171 #else
166172 static inline struct llcc_slice_desc *llcc_slice_getd(u32 uid)
167173 {
include/linux/tee_drv.h+49−1
@@ -15,11 +15,14 @@ · 14 unmodified lines
1515 #ifndef __TEE_DRV_H
1616 #define __TEE_DRV_H
1717
18−#include <linux/types.h>
18+#include <linux/device.h>
1919 #include <linux/idr.h>
2020 #include <linux/kref.h>
2121 #include <linux/list.h>
22+#include <linux/mod_devicetable.h>
2223 #include <linux/tee.h>
24+#include <linux/types.h>
25+#include <linux/uuid.h>
2326
2427 /*
2528 * The file describes the API provided by the generic TEE driver to the
@@ -47,6 +50,11 @@ struct tee_shm_pool; · 21 unmodified lines
4750 * @releasing: flag that indicates if context is being released right now.
4851 * It is needed to break circular dependency on context during
4952 * 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.
5058 */
5159 struct tee_context {
5260 struct tee_device *teedev;
@@ -54,6 +62,7 @@ struct tee_context { · 1 unmodified line
5462 void *data;
5563 struct kref refcount;
5664 bool releasing;
65+ bool supp_nowait;
5766 };
5867
5968 struct tee_param_memref {
@@ -526,6 +535,18 @@ int tee_client_invoke_func(struct tee_context *ctx, · 466 unmodified lines
526535 struct tee_ioctl_invoke_arg *arg,
527536 struct tee_param *param);
528537
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+ */
547+int tee_client_cancel_req(struct tee_context *ctx,
548+ struct tee_ioctl_cancel_arg *arg);
549+
529550 static inline bool tee_param_is_memref(struct tee_param *param)
530551 {
531552 switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
@@ -538,4 +559,31 @@ static inline bool tee_param_is_memref(struct tee_param *param) · 6 unmodified lines
538559 }
539560 }
540561
562+extern 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+ */
569+struct 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+ */
581+struct 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+
541589 #endif /*__TEE_DRV_H*/
include/soc/bcm2835/raspberrypi-firmware.h+4−0
@@ -73,6 +73,8 @@ enum rpi_firmware_property_tag { · 72 unmodified lines
7373 RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
7474 RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
7575 RPI_FIRMWARE_GET_THROTTLED = 0x00030046,
76+ RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047,
77+ RPI_FIRMWARE_NOTIFY_REBOOT = 0x00030048,
7678 RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001,
7779 RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002,
7880 RPI_FIRMWARE_SET_VOLTAGE = 0x00038003,
@@ -86,6 +88,8 @@ enum rpi_firmware_property_tag { · 7 unmodified lines
8688 RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043,
8789 RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045,
8890 RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045,
91+ RPI_FIRMWARE_GET_POE_HAT_VAL = 0x00030049,
92+ RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050,
8993
9094
9195 /* Dispmanx TAGS */
include/soc/fsl/dpaa2-io.h+2−2
@@ -111,9 +111,9 @@ int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid, · 110 unmodified lines
111111 const struct dpaa2_fd *fd);
112112 int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
113113 u16 qdbin, const struct dpaa2_fd *fd);
114−int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid,
114+int dpaa2_io_service_release(struct dpaa2_io *d, u16 bpid,
115115 const u64 *buffers, unsigned int num_buffers);
116−int dpaa2_io_service_acquire(struct dpaa2_io *d, u32 bpid,
116+int dpaa2_io_service_acquire(struct dpaa2_io *d, u16 bpid,
117117 u64 *buffers, unsigned int num_buffers);
118118
119119 struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
include/soc/tegra/bpmp.h+7−6
@@ -23,6 +23,7 @@ · 22 unmodified lines
2323 #include <soc/tegra/bpmp-abi.h>
2424
2525 struct tegra_bpmp_clk;
26+struct tegra_bpmp_ops;
2627
2728 struct tegra_bpmp_soc {
2829 struct {
@@ -32,6 +33,8 @@ struct tegra_bpmp_soc { · 3 unmodified lines
3233 unsigned int timeout;
3334 } cpu_tx, thread, cpu_rx;
3435 } channels;
36+
37+ const struct tegra_bpmp_ops *ops;
3538 unsigned int num_resets;
3639 };
3740
@@ -47,6 +50,7 @@ struct tegra_bpmp_channel { · 9 unmodified lines
4750 struct tegra_bpmp_mb_data *ob;
4851 struct completion completion;
4952 struct tegra_ivc *ivc;
53+ unsigned int index;
5054 };
5155
5256 typedef void (*tegra_bpmp_mrq_handler_t)(unsigned int mrq,
@@ -63,12 +67,7 @@ struct tegra_bpmp_mrq { · 10 unmodified lines
6367 struct tegra_bpmp {
6468 const struct tegra_bpmp_soc *soc;
6569 struct device *dev;
66−
67− struct {
68− struct gen_pool *pool;
69− dma_addr_t phys;
70− void *virt;
71− } tx, rx;
70+ void *priv;
7271
7372 struct {
7473 struct mbox_client client;
@@ -173,6 +172,8 @@ static inline bool tegra_bpmp_mrq_is_supported(struct tegra_bpmp *bpmp, · 98 unmodified lines
173172 }
174173 #endif
175174
175+void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp);
176+
176177 #if IS_ENABLED(CONFIG_CLK_TEGRA_BPMP)
177178 int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp);
178179 #else
include/soc/tegra/pmc.h+0−6
@@ -161,7 +161,6 @@ enum tegra_io_pad { · 160 unmodified lines
161161 #define TEGRA_IO_RAIL_LVDS TEGRA_IO_PAD_LVDS
162162
163163 #ifdef CONFIG_SOC_TEGRA_PMC
164−int tegra_powergate_is_powered(unsigned int id);
165164 int tegra_powergate_power_on(unsigned int id);
166165 int tegra_powergate_power_off(unsigned int id);
167166 int tegra_powergate_remove_clamping(unsigned int id);
@@ -182,11 +181,6 @@ void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode); · 14 unmodified lines
182181 void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
183182
184183 #else
185−static inline int tegra_powergate_is_powered(unsigned int id)
186−{
187− return -ENOSYS;
188−}
189−
190184 static inline int tegra_powergate_power_on(unsigned int id)
191185 {
192186 return -ENOSYS;
scripts/mod/devicetable-offsets.c+3−0
@@ -225,5 +225,8 @@ int main(void) · 224 unmodified lines
225225 DEVID_FIELD(typec_device_id, svid);
226226 DEVID_FIELD(typec_device_id, mode);
227227
228+ DEVID(tee_client_device_id);
229+ DEVID_FIELD(tee_client_device_id, uuid);
230+
228231 return 0;
229232 }
scripts/mod/file2alias.c+19−0
@@ -37,6 +37,9 @@ typedef unsigned char __u8; · 36 unmodified lines
3737 typedef struct {
3838 __u8 b[16];
3939 } uuid_le;
40+typedef struct {
41+ __u8 b[16];
42+} uuid_t;
4043
4144 /* Big exception to the "don't include kernel headers into userspace, which
4245 * 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) · 1244 unmodified lines
12871290 return 1;
12881291 }
12891292
1293+/* Looks like: tee:uuid */
1294+static 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+
12901308 /* Does namelen bytes of name exactly match the symbol? */
12911309 static bool sym_is(const char *name, unsigned namelen, const char *symbol)
12921310 {
@@ -1357,6 +1375,7 @@ static const struct devtable devtable[] = { · 64 unmodified lines
13571375 {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry},
13581376 {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry},
13591377 {"typec", SIZE_typec_device_id, do_typec_entry},
1378+ {"tee", SIZE_tee_client_device_id, do_tee_entry},
13601379 };
13611380
13621381 /* Create MODULE_ALIAS() statements.