1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Copyright 2017 Impinj, Inc |
4 | * Author: Andrey Smirnov <andrew.smirnov@gmail.com> |
5 | * |
6 | * Based on the code of analogus driver: |
7 | * |
8 | * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> |
9 | */ |
10 | |
11 | #include <linux/clk.h> |
12 | #include <linux/of.h> |
13 | #include <linux/platform_device.h> |
14 | #include <linux/pm_domain.h> |
15 | #include <linux/pm_runtime.h> |
16 | #include <linux/regmap.h> |
17 | #include <linux/regulator/consumer.h> |
18 | #include <linux/reset.h> |
19 | #include <linux/sizes.h> |
20 | #include <dt-bindings/power/imx7-power.h> |
21 | #include <dt-bindings/power/imx8mq-power.h> |
22 | #include <dt-bindings/power/imx8mm-power.h> |
23 | #include <dt-bindings/power/imx8mn-power.h> |
24 | #include <dt-bindings/power/imx8mp-power.h> |
25 | |
26 | #define GPC_LPCR_A_CORE_BSC 0x000 |
27 | |
28 | #define GPC_PGC_CPU_MAPPING 0x0ec |
29 | #define IMX8MP_GPC_PGC_CPU_MAPPING 0x1cc |
30 | |
31 | #define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN BIT(6) |
32 | #define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN BIT(5) |
33 | #define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN BIT(4) |
34 | #define IMX7_PCIE_PHY_A_CORE_DOMAIN BIT(3) |
35 | #define IMX7_MIPI_PHY_A_CORE_DOMAIN BIT(2) |
36 | |
37 | #define IMX8M_PCIE2_A53_DOMAIN BIT(15) |
38 | #define IMX8M_MIPI_CSI2_A53_DOMAIN BIT(14) |
39 | #define IMX8M_MIPI_CSI1_A53_DOMAIN BIT(13) |
40 | #define IMX8M_DISP_A53_DOMAIN BIT(12) |
41 | #define IMX8M_HDMI_A53_DOMAIN BIT(11) |
42 | #define IMX8M_VPU_A53_DOMAIN BIT(10) |
43 | #define IMX8M_GPU_A53_DOMAIN BIT(9) |
44 | #define IMX8M_DDR2_A53_DOMAIN BIT(8) |
45 | #define IMX8M_DDR1_A53_DOMAIN BIT(7) |
46 | #define IMX8M_OTG2_A53_DOMAIN BIT(5) |
47 | #define IMX8M_OTG1_A53_DOMAIN BIT(4) |
48 | #define IMX8M_PCIE1_A53_DOMAIN BIT(3) |
49 | #define IMX8M_MIPI_A53_DOMAIN BIT(2) |
50 | |
51 | #define IMX8MM_VPUH1_A53_DOMAIN BIT(15) |
52 | #define IMX8MM_VPUG2_A53_DOMAIN BIT(14) |
53 | #define IMX8MM_VPUG1_A53_DOMAIN BIT(13) |
54 | #define IMX8MM_DISPMIX_A53_DOMAIN BIT(12) |
55 | #define IMX8MM_VPUMIX_A53_DOMAIN BIT(10) |
56 | #define IMX8MM_GPUMIX_A53_DOMAIN BIT(9) |
57 | #define IMX8MM_GPU_A53_DOMAIN (BIT(8) | BIT(11)) |
58 | #define IMX8MM_DDR1_A53_DOMAIN BIT(7) |
59 | #define IMX8MM_OTG2_A53_DOMAIN BIT(5) |
60 | #define IMX8MM_OTG1_A53_DOMAIN BIT(4) |
61 | #define IMX8MM_PCIE_A53_DOMAIN BIT(3) |
62 | #define IMX8MM_MIPI_A53_DOMAIN BIT(2) |
63 | |
64 | #define IMX8MN_DISPMIX_A53_DOMAIN BIT(12) |
65 | #define IMX8MN_GPUMIX_A53_DOMAIN BIT(9) |
66 | #define IMX8MN_DDR1_A53_DOMAIN BIT(7) |
67 | #define IMX8MN_OTG1_A53_DOMAIN BIT(4) |
68 | #define IMX8MN_MIPI_A53_DOMAIN BIT(2) |
69 | |
70 | #define IMX8MP_MEDIA_ISPDWP_A53_DOMAIN BIT(20) |
71 | #define IMX8MP_HSIOMIX_A53_DOMAIN BIT(19) |
72 | #define IMX8MP_MIPI_PHY2_A53_DOMAIN BIT(18) |
73 | #define IMX8MP_HDMI_PHY_A53_DOMAIN BIT(17) |
74 | #define IMX8MP_HDMIMIX_A53_DOMAIN BIT(16) |
75 | #define IMX8MP_VPU_VC8000E_A53_DOMAIN BIT(15) |
76 | #define IMX8MP_VPU_G2_A53_DOMAIN BIT(14) |
77 | #define IMX8MP_VPU_G1_A53_DOMAIN BIT(13) |
78 | #define IMX8MP_MEDIAMIX_A53_DOMAIN BIT(12) |
79 | #define IMX8MP_GPU3D_A53_DOMAIN BIT(11) |
80 | #define IMX8MP_VPUMIX_A53_DOMAIN BIT(10) |
81 | #define IMX8MP_GPUMIX_A53_DOMAIN BIT(9) |
82 | #define IMX8MP_GPU2D_A53_DOMAIN BIT(8) |
83 | #define IMX8MP_AUDIOMIX_A53_DOMAIN BIT(7) |
84 | #define IMX8MP_MLMIX_A53_DOMAIN BIT(6) |
85 | #define IMX8MP_USB2_PHY_A53_DOMAIN BIT(5) |
86 | #define IMX8MP_USB1_PHY_A53_DOMAIN BIT(4) |
87 | #define IMX8MP_PCIE_PHY_A53_DOMAIN BIT(3) |
88 | #define IMX8MP_MIPI_PHY1_A53_DOMAIN BIT(2) |
89 | |
90 | #define IMX8MP_GPC_PU_PGC_SW_PUP_REQ 0x0d8 |
91 | #define IMX8MP_GPC_PU_PGC_SW_PDN_REQ 0x0e4 |
92 | |
93 | #define GPC_PU_PGC_SW_PUP_REQ 0x0f8 |
94 | #define GPC_PU_PGC_SW_PDN_REQ 0x104 |
95 | |
96 | #define IMX7_USB_HSIC_PHY_SW_Pxx_REQ BIT(4) |
97 | #define IMX7_USB_OTG2_PHY_SW_Pxx_REQ BIT(3) |
98 | #define IMX7_USB_OTG1_PHY_SW_Pxx_REQ BIT(2) |
99 | #define IMX7_PCIE_PHY_SW_Pxx_REQ BIT(1) |
100 | #define IMX7_MIPI_PHY_SW_Pxx_REQ BIT(0) |
101 | |
102 | #define IMX8M_PCIE2_SW_Pxx_REQ BIT(13) |
103 | #define IMX8M_MIPI_CSI2_SW_Pxx_REQ BIT(12) |
104 | #define IMX8M_MIPI_CSI1_SW_Pxx_REQ BIT(11) |
105 | #define IMX8M_DISP_SW_Pxx_REQ BIT(10) |
106 | #define IMX8M_HDMI_SW_Pxx_REQ BIT(9) |
107 | #define IMX8M_VPU_SW_Pxx_REQ BIT(8) |
108 | #define IMX8M_GPU_SW_Pxx_REQ BIT(7) |
109 | #define IMX8M_DDR2_SW_Pxx_REQ BIT(6) |
110 | #define IMX8M_DDR1_SW_Pxx_REQ BIT(5) |
111 | #define IMX8M_OTG2_SW_Pxx_REQ BIT(3) |
112 | #define IMX8M_OTG1_SW_Pxx_REQ BIT(2) |
113 | #define IMX8M_PCIE1_SW_Pxx_REQ BIT(1) |
114 | #define IMX8M_MIPI_SW_Pxx_REQ BIT(0) |
115 | |
116 | #define IMX8MM_VPUH1_SW_Pxx_REQ BIT(13) |
117 | #define IMX8MM_VPUG2_SW_Pxx_REQ BIT(12) |
118 | #define IMX8MM_VPUG1_SW_Pxx_REQ BIT(11) |
119 | #define IMX8MM_DISPMIX_SW_Pxx_REQ BIT(10) |
120 | #define IMX8MM_VPUMIX_SW_Pxx_REQ BIT(8) |
121 | #define IMX8MM_GPUMIX_SW_Pxx_REQ BIT(7) |
122 | #define IMX8MM_GPU_SW_Pxx_REQ (BIT(6) | BIT(9)) |
123 | #define IMX8MM_DDR1_SW_Pxx_REQ BIT(5) |
124 | #define IMX8MM_OTG2_SW_Pxx_REQ BIT(3) |
125 | #define IMX8MM_OTG1_SW_Pxx_REQ BIT(2) |
126 | #define IMX8MM_PCIE_SW_Pxx_REQ BIT(1) |
127 | #define IMX8MM_MIPI_SW_Pxx_REQ BIT(0) |
128 | |
129 | #define IMX8MN_DISPMIX_SW_Pxx_REQ BIT(10) |
130 | #define IMX8MN_GPUMIX_SW_Pxx_REQ BIT(7) |
131 | #define IMX8MN_DDR1_SW_Pxx_REQ BIT(5) |
132 | #define IMX8MN_OTG1_SW_Pxx_REQ BIT(2) |
133 | #define IMX8MN_MIPI_SW_Pxx_REQ BIT(0) |
134 | |
135 | #define IMX8MP_DDRMIX_Pxx_REQ BIT(19) |
136 | #define IMX8MP_MEDIA_ISP_DWP_Pxx_REQ BIT(18) |
137 | #define IMX8MP_HSIOMIX_Pxx_REQ BIT(17) |
138 | #define IMX8MP_MIPI_PHY2_Pxx_REQ BIT(16) |
139 | #define IMX8MP_HDMI_PHY_Pxx_REQ BIT(15) |
140 | #define IMX8MP_HDMIMIX_Pxx_REQ BIT(14) |
141 | #define IMX8MP_VPU_VC8K_Pxx_REQ BIT(13) |
142 | #define IMX8MP_VPU_G2_Pxx_REQ BIT(12) |
143 | #define IMX8MP_VPU_G1_Pxx_REQ BIT(11) |
144 | #define IMX8MP_MEDIMIX_Pxx_REQ BIT(10) |
145 | #define IMX8MP_GPU_3D_Pxx_REQ BIT(9) |
146 | #define IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ BIT(8) |
147 | #define IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ BIT(7) |
148 | #define IMX8MP_GPU_2D_Pxx_REQ BIT(6) |
149 | #define IMX8MP_AUDIOMIX_Pxx_REQ BIT(5) |
150 | #define IMX8MP_MLMIX_Pxx_REQ BIT(4) |
151 | #define IMX8MP_USB2_PHY_Pxx_REQ BIT(3) |
152 | #define IMX8MP_USB1_PHY_Pxx_REQ BIT(2) |
153 | #define IMX8MP_PCIE_PHY_SW_Pxx_REQ BIT(1) |
154 | #define IMX8MP_MIPI_PHY1_SW_Pxx_REQ BIT(0) |
155 | |
156 | #define GPC_M4_PU_PDN_FLG 0x1bc |
157 | |
158 | #define IMX8MP_GPC_PU_PWRHSK 0x190 |
159 | #define GPC_PU_PWRHSK 0x1fc |
160 | |
161 | #define IMX8M_GPU_HSK_PWRDNACKN BIT(26) |
162 | #define IMX8M_VPU_HSK_PWRDNACKN BIT(25) |
163 | #define IMX8M_DISP_HSK_PWRDNACKN BIT(24) |
164 | #define IMX8M_GPU_HSK_PWRDNREQN BIT(6) |
165 | #define IMX8M_VPU_HSK_PWRDNREQN BIT(5) |
166 | #define IMX8M_DISP_HSK_PWRDNREQN BIT(4) |
167 | |
168 | #define IMX8MM_GPUMIX_HSK_PWRDNACKN BIT(29) |
169 | #define IMX8MM_GPU_HSK_PWRDNACKN (BIT(27) | BIT(28)) |
170 | #define IMX8MM_VPUMIX_HSK_PWRDNACKN BIT(26) |
171 | #define IMX8MM_DISPMIX_HSK_PWRDNACKN BIT(25) |
172 | #define IMX8MM_HSIO_HSK_PWRDNACKN (BIT(23) | BIT(24)) |
173 | #define IMX8MM_GPUMIX_HSK_PWRDNREQN BIT(11) |
174 | #define IMX8MM_GPU_HSK_PWRDNREQN (BIT(9) | BIT(10)) |
175 | #define IMX8MM_VPUMIX_HSK_PWRDNREQN BIT(8) |
176 | #define IMX8MM_DISPMIX_HSK_PWRDNREQN BIT(7) |
177 | #define IMX8MM_HSIO_HSK_PWRDNREQN (BIT(5) | BIT(6)) |
178 | |
179 | #define IMX8MN_GPUMIX_HSK_PWRDNACKN (BIT(29) | BIT(27)) |
180 | #define IMX8MN_DISPMIX_HSK_PWRDNACKN BIT(25) |
181 | #define IMX8MN_HSIO_HSK_PWRDNACKN BIT(23) |
182 | #define IMX8MN_GPUMIX_HSK_PWRDNREQN (BIT(11) | BIT(9)) |
183 | #define IMX8MN_DISPMIX_HSK_PWRDNREQN BIT(7) |
184 | #define IMX8MN_HSIO_HSK_PWRDNREQN BIT(5) |
185 | |
186 | #define IMX8MP_MEDIAMIX_PWRDNACKN BIT(30) |
187 | #define IMX8MP_HDMIMIX_PWRDNACKN BIT(29) |
188 | #define IMX8MP_HSIOMIX_PWRDNACKN BIT(28) |
189 | #define IMX8MP_VPUMIX_PWRDNACKN BIT(26) |
190 | #define IMX8MP_GPUMIX_PWRDNACKN BIT(25) |
191 | #define IMX8MP_MLMIX_PWRDNACKN (BIT(23) | BIT(24)) |
192 | #define IMX8MP_AUDIOMIX_PWRDNACKN (BIT(20) | BIT(31)) |
193 | #define IMX8MP_MEDIAMIX_PWRDNREQN BIT(14) |
194 | #define IMX8MP_HDMIMIX_PWRDNREQN BIT(13) |
195 | #define IMX8MP_HSIOMIX_PWRDNREQN BIT(12) |
196 | #define IMX8MP_VPUMIX_PWRDNREQN BIT(10) |
197 | #define IMX8MP_GPUMIX_PWRDNREQN BIT(9) |
198 | #define IMX8MP_MLMIX_PWRDNREQN (BIT(7) | BIT(8)) |
199 | #define IMX8MP_AUDIOMIX_PWRDNREQN (BIT(4) | BIT(15)) |
200 | |
201 | /* |
202 | * The PGC offset values in Reference Manual |
203 | * (Rev. 1, 01/2018 and the older ones) GPC chapter's |
204 | * GPC_PGC memory map are incorrect, below offset |
205 | * values are from design RTL. |
206 | */ |
207 | #define IMX7_PGC_MIPI 16 |
208 | #define IMX7_PGC_PCIE 17 |
209 | #define IMX7_PGC_USB_HSIC 20 |
210 | |
211 | #define IMX8M_PGC_MIPI 16 |
212 | #define IMX8M_PGC_PCIE1 17 |
213 | #define IMX8M_PGC_OTG1 18 |
214 | #define IMX8M_PGC_OTG2 19 |
215 | #define IMX8M_PGC_DDR1 21 |
216 | #define IMX8M_PGC_GPU 23 |
217 | #define IMX8M_PGC_VPU 24 |
218 | #define IMX8M_PGC_DISP 26 |
219 | #define IMX8M_PGC_MIPI_CSI1 27 |
220 | #define IMX8M_PGC_MIPI_CSI2 28 |
221 | #define IMX8M_PGC_PCIE2 29 |
222 | |
223 | #define IMX8MM_PGC_MIPI 16 |
224 | #define IMX8MM_PGC_PCIE 17 |
225 | #define IMX8MM_PGC_OTG1 18 |
226 | #define IMX8MM_PGC_OTG2 19 |
227 | #define IMX8MM_PGC_DDR1 21 |
228 | #define IMX8MM_PGC_GPU2D 22 |
229 | #define IMX8MM_PGC_GPUMIX 23 |
230 | #define IMX8MM_PGC_VPUMIX 24 |
231 | #define IMX8MM_PGC_GPU3D 25 |
232 | #define IMX8MM_PGC_DISPMIX 26 |
233 | #define IMX8MM_PGC_VPUG1 27 |
234 | #define IMX8MM_PGC_VPUG2 28 |
235 | #define IMX8MM_PGC_VPUH1 29 |
236 | |
237 | #define IMX8MN_PGC_MIPI 16 |
238 | #define IMX8MN_PGC_OTG1 18 |
239 | #define IMX8MN_PGC_DDR1 21 |
240 | #define IMX8MN_PGC_GPUMIX 23 |
241 | #define IMX8MN_PGC_DISPMIX 26 |
242 | |
243 | #define IMX8MP_PGC_NOC 9 |
244 | #define IMX8MP_PGC_MIPI1 12 |
245 | #define IMX8MP_PGC_PCIE 13 |
246 | #define IMX8MP_PGC_USB1 14 |
247 | #define IMX8MP_PGC_USB2 15 |
248 | #define IMX8MP_PGC_MLMIX 16 |
249 | #define IMX8MP_PGC_AUDIOMIX 17 |
250 | #define IMX8MP_PGC_GPU2D 18 |
251 | #define IMX8MP_PGC_GPUMIX 19 |
252 | #define IMX8MP_PGC_VPUMIX 20 |
253 | #define IMX8MP_PGC_GPU3D 21 |
254 | #define IMX8MP_PGC_MEDIAMIX 22 |
255 | #define IMX8MP_PGC_VPU_G1 23 |
256 | #define IMX8MP_PGC_VPU_G2 24 |
257 | #define IMX8MP_PGC_VPU_VC8000E 25 |
258 | #define IMX8MP_PGC_HDMIMIX 26 |
259 | #define IMX8MP_PGC_HDMI 27 |
260 | #define IMX8MP_PGC_MIPI2 28 |
261 | #define IMX8MP_PGC_HSIOMIX 29 |
262 | #define IMX8MP_PGC_MEDIA_ISP_DWP 30 |
263 | #define IMX8MP_PGC_DDRMIX 31 |
264 | |
265 | #define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40) |
266 | #define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc) |
267 | |
268 | #define GPC_PGC_CTRL_PCR BIT(0) |
269 | |
270 | struct imx_pgc_regs { |
271 | u16 map; |
272 | u16 pup; |
273 | u16 pdn; |
274 | u16 hsk; |
275 | }; |
276 | |
277 | struct imx_pgc_domain { |
278 | struct generic_pm_domain genpd; |
279 | struct regmap *regmap; |
280 | const struct imx_pgc_regs *regs; |
281 | struct regulator *regulator; |
282 | struct reset_control *reset; |
283 | struct clk_bulk_data *clks; |
284 | int num_clks; |
285 | |
286 | unsigned long pgc; |
287 | |
288 | const struct { |
289 | u32 pxx; |
290 | u32 map; |
291 | u32 hskreq; |
292 | u32 hskack; |
293 | } bits; |
294 | |
295 | const int voltage; |
296 | const bool keep_clocks; |
297 | struct device *dev; |
298 | |
299 | unsigned int pgc_sw_pup_reg; |
300 | unsigned int pgc_sw_pdn_reg; |
301 | }; |
302 | |
303 | struct imx_pgc_domain_data { |
304 | const struct imx_pgc_domain *domains; |
305 | size_t domains_num; |
306 | const struct regmap_access_table *reg_access_table; |
307 | const struct imx_pgc_regs *pgc_regs; |
308 | }; |
309 | |
310 | static inline struct imx_pgc_domain * |
311 | to_imx_pgc_domain(struct generic_pm_domain *genpd) |
312 | { |
313 | return container_of(genpd, struct imx_pgc_domain, genpd); |
314 | } |
315 | |
316 | static int imx_pgc_power_up(struct generic_pm_domain *genpd) |
317 | { |
318 | struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd); |
319 | u32 reg_val, pgc; |
320 | int ret; |
321 | |
322 | ret = pm_runtime_get_sync(dev: domain->dev); |
323 | if (ret < 0) { |
324 | pm_runtime_put_noidle(dev: domain->dev); |
325 | return ret; |
326 | } |
327 | |
328 | if (!IS_ERR(ptr: domain->regulator)) { |
329 | ret = regulator_enable(regulator: domain->regulator); |
330 | if (ret) { |
331 | dev_err(domain->dev, |
332 | "failed to enable regulator: %pe\n" , |
333 | ERR_PTR(ret)); |
334 | goto out_put_pm; |
335 | } |
336 | } |
337 | |
338 | reset_control_assert(rstc: domain->reset); |
339 | |
340 | /* Enable reset clocks for all devices in the domain */ |
341 | ret = clk_bulk_prepare_enable(num_clks: domain->num_clks, clks: domain->clks); |
342 | if (ret) { |
343 | dev_err(domain->dev, "failed to enable reset clocks\n" ); |
344 | goto out_regulator_disable; |
345 | } |
346 | |
347 | /* delays for reset to propagate */ |
348 | udelay(5); |
349 | |
350 | if (domain->bits.pxx) { |
351 | /* request the domain to power up */ |
352 | regmap_update_bits(map: domain->regmap, reg: domain->regs->pup, |
353 | mask: domain->bits.pxx, val: domain->bits.pxx); |
354 | /* |
355 | * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait |
356 | * for PUP_REQ/PDN_REQ bit to be cleared |
357 | */ |
358 | ret = regmap_read_poll_timeout(domain->regmap, |
359 | domain->regs->pup, reg_val, |
360 | !(reg_val & domain->bits.pxx), |
361 | 0, USEC_PER_MSEC); |
362 | if (ret) { |
363 | dev_err(domain->dev, "failed to command PGC\n" ); |
364 | goto out_clk_disable; |
365 | } |
366 | |
367 | /* disable power control */ |
368 | for_each_set_bit(pgc, &domain->pgc, 32) { |
369 | regmap_clear_bits(map: domain->regmap, GPC_PGC_CTRL(pgc), |
370 | GPC_PGC_CTRL_PCR); |
371 | } |
372 | } |
373 | |
374 | /* delay for reset to propagate */ |
375 | udelay(5); |
376 | |
377 | reset_control_deassert(rstc: domain->reset); |
378 | |
379 | /* request the ADB400 to power up */ |
380 | if (domain->bits.hskreq) { |
381 | regmap_update_bits(map: domain->regmap, reg: domain->regs->hsk, |
382 | mask: domain->bits.hskreq, val: domain->bits.hskreq); |
383 | |
384 | /* |
385 | * ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, reg_val, |
386 | * (reg_val & domain->bits.hskack), 0, |
387 | * USEC_PER_MSEC); |
388 | * Technically we need the commented code to wait handshake. But that needs |
389 | * the BLK-CTL module BUS clk-en bit being set. |
390 | * |
391 | * There is a separate BLK-CTL module and we will have such a driver for it, |
392 | * that driver will set the BUS clk-en bit and handshake will be triggered |
393 | * automatically there. Just add a delay and suppose the handshake finish |
394 | * after that. |
395 | */ |
396 | } |
397 | |
398 | /* Disable reset clocks for all devices in the domain */ |
399 | if (!domain->keep_clocks) |
400 | clk_bulk_disable_unprepare(num_clks: domain->num_clks, clks: domain->clks); |
401 | |
402 | return 0; |
403 | |
404 | out_clk_disable: |
405 | clk_bulk_disable_unprepare(num_clks: domain->num_clks, clks: domain->clks); |
406 | out_regulator_disable: |
407 | if (!IS_ERR(ptr: domain->regulator)) |
408 | regulator_disable(regulator: domain->regulator); |
409 | out_put_pm: |
410 | pm_runtime_put(dev: domain->dev); |
411 | |
412 | return ret; |
413 | } |
414 | |
415 | static int imx_pgc_power_down(struct generic_pm_domain *genpd) |
416 | { |
417 | struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd); |
418 | u32 reg_val, pgc; |
419 | int ret; |
420 | |
421 | /* Enable reset clocks for all devices in the domain */ |
422 | if (!domain->keep_clocks) { |
423 | ret = clk_bulk_prepare_enable(num_clks: domain->num_clks, clks: domain->clks); |
424 | if (ret) { |
425 | dev_err(domain->dev, "failed to enable reset clocks\n" ); |
426 | return ret; |
427 | } |
428 | } |
429 | |
430 | /* request the ADB400 to power down */ |
431 | if (domain->bits.hskreq) { |
432 | regmap_clear_bits(map: domain->regmap, reg: domain->regs->hsk, |
433 | bits: domain->bits.hskreq); |
434 | |
435 | ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, |
436 | reg_val, |
437 | !(reg_val & domain->bits.hskack), |
438 | 0, USEC_PER_MSEC); |
439 | if (ret) { |
440 | dev_err(domain->dev, "failed to power down ADB400\n" ); |
441 | goto out_clk_disable; |
442 | } |
443 | } |
444 | |
445 | if (domain->bits.pxx) { |
446 | /* enable power control */ |
447 | for_each_set_bit(pgc, &domain->pgc, 32) { |
448 | regmap_update_bits(map: domain->regmap, GPC_PGC_CTRL(pgc), |
449 | GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR); |
450 | } |
451 | |
452 | /* request the domain to power down */ |
453 | regmap_update_bits(map: domain->regmap, reg: domain->regs->pdn, |
454 | mask: domain->bits.pxx, val: domain->bits.pxx); |
455 | /* |
456 | * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait |
457 | * for PUP_REQ/PDN_REQ bit to be cleared |
458 | */ |
459 | ret = regmap_read_poll_timeout(domain->regmap, |
460 | domain->regs->pdn, reg_val, |
461 | !(reg_val & domain->bits.pxx), |
462 | 0, USEC_PER_MSEC); |
463 | if (ret) { |
464 | dev_err(domain->dev, "failed to command PGC\n" ); |
465 | goto out_clk_disable; |
466 | } |
467 | } |
468 | |
469 | /* Disable reset clocks for all devices in the domain */ |
470 | clk_bulk_disable_unprepare(num_clks: domain->num_clks, clks: domain->clks); |
471 | |
472 | if (!IS_ERR(ptr: domain->regulator)) { |
473 | ret = regulator_disable(regulator: domain->regulator); |
474 | if (ret) { |
475 | dev_err(domain->dev, |
476 | "failed to disable regulator: %pe\n" , |
477 | ERR_PTR(ret)); |
478 | return ret; |
479 | } |
480 | } |
481 | |
482 | pm_runtime_put_sync_suspend(dev: domain->dev); |
483 | |
484 | return 0; |
485 | |
486 | out_clk_disable: |
487 | if (!domain->keep_clocks) |
488 | clk_bulk_disable_unprepare(num_clks: domain->num_clks, clks: domain->clks); |
489 | |
490 | return ret; |
491 | } |
492 | |
493 | static const struct imx_pgc_domain imx7_pgc_domains[] = { |
494 | [IMX7_POWER_DOMAIN_MIPI_PHY] = { |
495 | .genpd = { |
496 | .name = "mipi-phy" , |
497 | }, |
498 | .bits = { |
499 | .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ, |
500 | .map = IMX7_MIPI_PHY_A_CORE_DOMAIN, |
501 | }, |
502 | .voltage = 1000000, |
503 | .pgc = BIT(IMX7_PGC_MIPI), |
504 | }, |
505 | |
506 | [IMX7_POWER_DOMAIN_PCIE_PHY] = { |
507 | .genpd = { |
508 | .name = "pcie-phy" , |
509 | }, |
510 | .bits = { |
511 | .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ, |
512 | .map = IMX7_PCIE_PHY_A_CORE_DOMAIN, |
513 | }, |
514 | .voltage = 1000000, |
515 | .pgc = BIT(IMX7_PGC_PCIE), |
516 | }, |
517 | |
518 | [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = { |
519 | .genpd = { |
520 | .name = "usb-hsic-phy" , |
521 | }, |
522 | .bits = { |
523 | .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ, |
524 | .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN, |
525 | }, |
526 | .voltage = 1200000, |
527 | .pgc = BIT(IMX7_PGC_USB_HSIC), |
528 | }, |
529 | }; |
530 | |
531 | static const struct regmap_range imx7_yes_ranges[] = { |
532 | regmap_reg_range(GPC_LPCR_A_CORE_BSC, |
533 | GPC_M4_PU_PDN_FLG), |
534 | regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI), |
535 | GPC_PGC_SR(IMX7_PGC_MIPI)), |
536 | regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE), |
537 | GPC_PGC_SR(IMX7_PGC_PCIE)), |
538 | regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC), |
539 | GPC_PGC_SR(IMX7_PGC_USB_HSIC)), |
540 | }; |
541 | |
542 | static const struct regmap_access_table imx7_access_table = { |
543 | .yes_ranges = imx7_yes_ranges, |
544 | .n_yes_ranges = ARRAY_SIZE(imx7_yes_ranges), |
545 | }; |
546 | |
547 | static const struct imx_pgc_regs imx7_pgc_regs = { |
548 | .map = GPC_PGC_CPU_MAPPING, |
549 | .pup = GPC_PU_PGC_SW_PUP_REQ, |
550 | .pdn = GPC_PU_PGC_SW_PDN_REQ, |
551 | .hsk = GPC_PU_PWRHSK, |
552 | }; |
553 | |
554 | static const struct imx_pgc_domain_data imx7_pgc_domain_data = { |
555 | .domains = imx7_pgc_domains, |
556 | .domains_num = ARRAY_SIZE(imx7_pgc_domains), |
557 | .reg_access_table = &imx7_access_table, |
558 | .pgc_regs = &imx7_pgc_regs, |
559 | }; |
560 | |
561 | static const struct imx_pgc_domain imx8m_pgc_domains[] = { |
562 | [IMX8M_POWER_DOMAIN_MIPI] = { |
563 | .genpd = { |
564 | .name = "mipi" , |
565 | }, |
566 | .bits = { |
567 | .pxx = IMX8M_MIPI_SW_Pxx_REQ, |
568 | .map = IMX8M_MIPI_A53_DOMAIN, |
569 | }, |
570 | .pgc = BIT(IMX8M_PGC_MIPI), |
571 | }, |
572 | |
573 | [IMX8M_POWER_DOMAIN_PCIE1] = { |
574 | .genpd = { |
575 | .name = "pcie1" , |
576 | }, |
577 | .bits = { |
578 | .pxx = IMX8M_PCIE1_SW_Pxx_REQ, |
579 | .map = IMX8M_PCIE1_A53_DOMAIN, |
580 | }, |
581 | .pgc = BIT(IMX8M_PGC_PCIE1), |
582 | }, |
583 | |
584 | [IMX8M_POWER_DOMAIN_USB_OTG1] = { |
585 | .genpd = { |
586 | .name = "usb-otg1" , |
587 | }, |
588 | .bits = { |
589 | .pxx = IMX8M_OTG1_SW_Pxx_REQ, |
590 | .map = IMX8M_OTG1_A53_DOMAIN, |
591 | }, |
592 | .pgc = BIT(IMX8M_PGC_OTG1), |
593 | }, |
594 | |
595 | [IMX8M_POWER_DOMAIN_USB_OTG2] = { |
596 | .genpd = { |
597 | .name = "usb-otg2" , |
598 | }, |
599 | .bits = { |
600 | .pxx = IMX8M_OTG2_SW_Pxx_REQ, |
601 | .map = IMX8M_OTG2_A53_DOMAIN, |
602 | }, |
603 | .pgc = BIT(IMX8M_PGC_OTG2), |
604 | }, |
605 | |
606 | [IMX8M_POWER_DOMAIN_DDR1] = { |
607 | .genpd = { |
608 | .name = "ddr1" , |
609 | }, |
610 | .bits = { |
611 | .pxx = IMX8M_DDR1_SW_Pxx_REQ, |
612 | .map = IMX8M_DDR2_A53_DOMAIN, |
613 | }, |
614 | .pgc = BIT(IMX8M_PGC_DDR1), |
615 | }, |
616 | |
617 | [IMX8M_POWER_DOMAIN_GPU] = { |
618 | .genpd = { |
619 | .name = "gpu" , |
620 | }, |
621 | .bits = { |
622 | .pxx = IMX8M_GPU_SW_Pxx_REQ, |
623 | .map = IMX8M_GPU_A53_DOMAIN, |
624 | .hskreq = IMX8M_GPU_HSK_PWRDNREQN, |
625 | .hskack = IMX8M_GPU_HSK_PWRDNACKN, |
626 | }, |
627 | .pgc = BIT(IMX8M_PGC_GPU), |
628 | }, |
629 | |
630 | [IMX8M_POWER_DOMAIN_VPU] = { |
631 | .genpd = { |
632 | .name = "vpu" , |
633 | }, |
634 | .bits = { |
635 | .pxx = IMX8M_VPU_SW_Pxx_REQ, |
636 | .map = IMX8M_VPU_A53_DOMAIN, |
637 | .hskreq = IMX8M_VPU_HSK_PWRDNREQN, |
638 | .hskack = IMX8M_VPU_HSK_PWRDNACKN, |
639 | }, |
640 | .pgc = BIT(IMX8M_PGC_VPU), |
641 | .keep_clocks = true, |
642 | }, |
643 | |
644 | [IMX8M_POWER_DOMAIN_DISP] = { |
645 | .genpd = { |
646 | .name = "disp" , |
647 | }, |
648 | .bits = { |
649 | .pxx = IMX8M_DISP_SW_Pxx_REQ, |
650 | .map = IMX8M_DISP_A53_DOMAIN, |
651 | .hskreq = IMX8M_DISP_HSK_PWRDNREQN, |
652 | .hskack = IMX8M_DISP_HSK_PWRDNACKN, |
653 | }, |
654 | .pgc = BIT(IMX8M_PGC_DISP), |
655 | }, |
656 | |
657 | [IMX8M_POWER_DOMAIN_MIPI_CSI1] = { |
658 | .genpd = { |
659 | .name = "mipi-csi1" , |
660 | }, |
661 | .bits = { |
662 | .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ, |
663 | .map = IMX8M_MIPI_CSI1_A53_DOMAIN, |
664 | }, |
665 | .pgc = BIT(IMX8M_PGC_MIPI_CSI1), |
666 | }, |
667 | |
668 | [IMX8M_POWER_DOMAIN_MIPI_CSI2] = { |
669 | .genpd = { |
670 | .name = "mipi-csi2" , |
671 | }, |
672 | .bits = { |
673 | .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ, |
674 | .map = IMX8M_MIPI_CSI2_A53_DOMAIN, |
675 | }, |
676 | .pgc = BIT(IMX8M_PGC_MIPI_CSI2), |
677 | }, |
678 | |
679 | [IMX8M_POWER_DOMAIN_PCIE2] = { |
680 | .genpd = { |
681 | .name = "pcie2" , |
682 | }, |
683 | .bits = { |
684 | .pxx = IMX8M_PCIE2_SW_Pxx_REQ, |
685 | .map = IMX8M_PCIE2_A53_DOMAIN, |
686 | }, |
687 | .pgc = BIT(IMX8M_PGC_PCIE2), |
688 | }, |
689 | }; |
690 | |
691 | static const struct regmap_range imx8m_yes_ranges[] = { |
692 | regmap_reg_range(GPC_LPCR_A_CORE_BSC, |
693 | GPC_PU_PWRHSK), |
694 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI), |
695 | GPC_PGC_SR(IMX8M_PGC_MIPI)), |
696 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1), |
697 | GPC_PGC_SR(IMX8M_PGC_PCIE1)), |
698 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1), |
699 | GPC_PGC_SR(IMX8M_PGC_OTG1)), |
700 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2), |
701 | GPC_PGC_SR(IMX8M_PGC_OTG2)), |
702 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1), |
703 | GPC_PGC_SR(IMX8M_PGC_DDR1)), |
704 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU), |
705 | GPC_PGC_SR(IMX8M_PGC_GPU)), |
706 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU), |
707 | GPC_PGC_SR(IMX8M_PGC_VPU)), |
708 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP), |
709 | GPC_PGC_SR(IMX8M_PGC_DISP)), |
710 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1), |
711 | GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)), |
712 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2), |
713 | GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)), |
714 | regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2), |
715 | GPC_PGC_SR(IMX8M_PGC_PCIE2)), |
716 | }; |
717 | |
718 | static const struct regmap_access_table imx8m_access_table = { |
719 | .yes_ranges = imx8m_yes_ranges, |
720 | .n_yes_ranges = ARRAY_SIZE(imx8m_yes_ranges), |
721 | }; |
722 | |
723 | static const struct imx_pgc_domain_data imx8m_pgc_domain_data = { |
724 | .domains = imx8m_pgc_domains, |
725 | .domains_num = ARRAY_SIZE(imx8m_pgc_domains), |
726 | .reg_access_table = &imx8m_access_table, |
727 | .pgc_regs = &imx7_pgc_regs, |
728 | }; |
729 | |
730 | static const struct imx_pgc_domain imx8mm_pgc_domains[] = { |
731 | [IMX8MM_POWER_DOMAIN_HSIOMIX] = { |
732 | .genpd = { |
733 | .name = "hsiomix" , |
734 | }, |
735 | .bits = { |
736 | .pxx = 0, /* no power sequence control */ |
737 | .map = 0, /* no power sequence control */ |
738 | .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN, |
739 | .hskack = IMX8MM_HSIO_HSK_PWRDNACKN, |
740 | }, |
741 | .keep_clocks = true, |
742 | }, |
743 | |
744 | [IMX8MM_POWER_DOMAIN_PCIE] = { |
745 | .genpd = { |
746 | .name = "pcie" , |
747 | }, |
748 | .bits = { |
749 | .pxx = IMX8MM_PCIE_SW_Pxx_REQ, |
750 | .map = IMX8MM_PCIE_A53_DOMAIN, |
751 | }, |
752 | .pgc = BIT(IMX8MM_PGC_PCIE), |
753 | }, |
754 | |
755 | [IMX8MM_POWER_DOMAIN_OTG1] = { |
756 | .genpd = { |
757 | .name = "usb-otg1" , |
758 | .flags = GENPD_FLAG_ACTIVE_WAKEUP, |
759 | }, |
760 | .bits = { |
761 | .pxx = IMX8MM_OTG1_SW_Pxx_REQ, |
762 | .map = IMX8MM_OTG1_A53_DOMAIN, |
763 | }, |
764 | .pgc = BIT(IMX8MM_PGC_OTG1), |
765 | }, |
766 | |
767 | [IMX8MM_POWER_DOMAIN_OTG2] = { |
768 | .genpd = { |
769 | .name = "usb-otg2" , |
770 | .flags = GENPD_FLAG_ACTIVE_WAKEUP, |
771 | }, |
772 | .bits = { |
773 | .pxx = IMX8MM_OTG2_SW_Pxx_REQ, |
774 | .map = IMX8MM_OTG2_A53_DOMAIN, |
775 | }, |
776 | .pgc = BIT(IMX8MM_PGC_OTG2), |
777 | }, |
778 | |
779 | [IMX8MM_POWER_DOMAIN_GPUMIX] = { |
780 | .genpd = { |
781 | .name = "gpumix" , |
782 | }, |
783 | .bits = { |
784 | .pxx = IMX8MM_GPUMIX_SW_Pxx_REQ, |
785 | .map = IMX8MM_GPUMIX_A53_DOMAIN, |
786 | .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN, |
787 | .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN, |
788 | }, |
789 | .pgc = BIT(IMX8MM_PGC_GPUMIX), |
790 | .keep_clocks = true, |
791 | }, |
792 | |
793 | [IMX8MM_POWER_DOMAIN_GPU] = { |
794 | .genpd = { |
795 | .name = "gpu" , |
796 | }, |
797 | .bits = { |
798 | .pxx = IMX8MM_GPU_SW_Pxx_REQ, |
799 | .map = IMX8MM_GPU_A53_DOMAIN, |
800 | .hskreq = IMX8MM_GPU_HSK_PWRDNREQN, |
801 | .hskack = IMX8MM_GPU_HSK_PWRDNACKN, |
802 | }, |
803 | .pgc = BIT(IMX8MM_PGC_GPU2D) | BIT(IMX8MM_PGC_GPU3D), |
804 | }, |
805 | |
806 | [IMX8MM_POWER_DOMAIN_VPUMIX] = { |
807 | .genpd = { |
808 | .name = "vpumix" , |
809 | }, |
810 | .bits = { |
811 | .pxx = IMX8MM_VPUMIX_SW_Pxx_REQ, |
812 | .map = IMX8MM_VPUMIX_A53_DOMAIN, |
813 | .hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN, |
814 | .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN, |
815 | }, |
816 | .pgc = BIT(IMX8MM_PGC_VPUMIX), |
817 | .keep_clocks = true, |
818 | }, |
819 | |
820 | [IMX8MM_POWER_DOMAIN_VPUG1] = { |
821 | .genpd = { |
822 | .name = "vpu-g1" , |
823 | }, |
824 | .bits = { |
825 | .pxx = IMX8MM_VPUG1_SW_Pxx_REQ, |
826 | .map = IMX8MM_VPUG1_A53_DOMAIN, |
827 | }, |
828 | .pgc = BIT(IMX8MM_PGC_VPUG1), |
829 | }, |
830 | |
831 | [IMX8MM_POWER_DOMAIN_VPUG2] = { |
832 | .genpd = { |
833 | .name = "vpu-g2" , |
834 | }, |
835 | .bits = { |
836 | .pxx = IMX8MM_VPUG2_SW_Pxx_REQ, |
837 | .map = IMX8MM_VPUG2_A53_DOMAIN, |
838 | }, |
839 | .pgc = BIT(IMX8MM_PGC_VPUG2), |
840 | }, |
841 | |
842 | [IMX8MM_POWER_DOMAIN_VPUH1] = { |
843 | .genpd = { |
844 | .name = "vpu-h1" , |
845 | }, |
846 | .bits = { |
847 | .pxx = IMX8MM_VPUH1_SW_Pxx_REQ, |
848 | .map = IMX8MM_VPUH1_A53_DOMAIN, |
849 | }, |
850 | .pgc = BIT(IMX8MM_PGC_VPUH1), |
851 | .keep_clocks = true, |
852 | }, |
853 | |
854 | [IMX8MM_POWER_DOMAIN_DISPMIX] = { |
855 | .genpd = { |
856 | .name = "dispmix" , |
857 | }, |
858 | .bits = { |
859 | .pxx = IMX8MM_DISPMIX_SW_Pxx_REQ, |
860 | .map = IMX8MM_DISPMIX_A53_DOMAIN, |
861 | .hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN, |
862 | .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN, |
863 | }, |
864 | .pgc = BIT(IMX8MM_PGC_DISPMIX), |
865 | .keep_clocks = true, |
866 | }, |
867 | |
868 | [IMX8MM_POWER_DOMAIN_MIPI] = { |
869 | .genpd = { |
870 | .name = "mipi" , |
871 | }, |
872 | .bits = { |
873 | .pxx = IMX8MM_MIPI_SW_Pxx_REQ, |
874 | .map = IMX8MM_MIPI_A53_DOMAIN, |
875 | }, |
876 | .pgc = BIT(IMX8MM_PGC_MIPI), |
877 | }, |
878 | }; |
879 | |
880 | static const struct regmap_range imx8mm_yes_ranges[] = { |
881 | regmap_reg_range(GPC_LPCR_A_CORE_BSC, |
882 | GPC_PU_PWRHSK), |
883 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_MIPI), |
884 | GPC_PGC_SR(IMX8MM_PGC_MIPI)), |
885 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_PCIE), |
886 | GPC_PGC_SR(IMX8MM_PGC_PCIE)), |
887 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG1), |
888 | GPC_PGC_SR(IMX8MM_PGC_OTG1)), |
889 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG2), |
890 | GPC_PGC_SR(IMX8MM_PGC_OTG2)), |
891 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DDR1), |
892 | GPC_PGC_SR(IMX8MM_PGC_DDR1)), |
893 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU2D), |
894 | GPC_PGC_SR(IMX8MM_PGC_GPU2D)), |
895 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPUMIX), |
896 | GPC_PGC_SR(IMX8MM_PGC_GPUMIX)), |
897 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUMIX), |
898 | GPC_PGC_SR(IMX8MM_PGC_VPUMIX)), |
899 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU3D), |
900 | GPC_PGC_SR(IMX8MM_PGC_GPU3D)), |
901 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DISPMIX), |
902 | GPC_PGC_SR(IMX8MM_PGC_DISPMIX)), |
903 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG1), |
904 | GPC_PGC_SR(IMX8MM_PGC_VPUG1)), |
905 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG2), |
906 | GPC_PGC_SR(IMX8MM_PGC_VPUG2)), |
907 | regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUH1), |
908 | GPC_PGC_SR(IMX8MM_PGC_VPUH1)), |
909 | }; |
910 | |
911 | static const struct regmap_access_table imx8mm_access_table = { |
912 | .yes_ranges = imx8mm_yes_ranges, |
913 | .n_yes_ranges = ARRAY_SIZE(imx8mm_yes_ranges), |
914 | }; |
915 | |
916 | static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = { |
917 | .domains = imx8mm_pgc_domains, |
918 | .domains_num = ARRAY_SIZE(imx8mm_pgc_domains), |
919 | .reg_access_table = &imx8mm_access_table, |
920 | .pgc_regs = &imx7_pgc_regs, |
921 | }; |
922 | |
923 | static const struct imx_pgc_domain imx8mp_pgc_domains[] = { |
924 | [IMX8MP_POWER_DOMAIN_MIPI_PHY1] = { |
925 | .genpd = { |
926 | .name = "mipi-phy1" , |
927 | }, |
928 | .bits = { |
929 | .pxx = IMX8MP_MIPI_PHY1_SW_Pxx_REQ, |
930 | .map = IMX8MP_MIPI_PHY1_A53_DOMAIN, |
931 | }, |
932 | .pgc = BIT(IMX8MP_PGC_MIPI1), |
933 | }, |
934 | |
935 | [IMX8MP_POWER_DOMAIN_PCIE_PHY] = { |
936 | .genpd = { |
937 | .name = "pcie-phy1" , |
938 | }, |
939 | .bits = { |
940 | .pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ, |
941 | .map = IMX8MP_PCIE_PHY_A53_DOMAIN, |
942 | }, |
943 | .pgc = BIT(IMX8MP_PGC_PCIE), |
944 | }, |
945 | |
946 | [IMX8MP_POWER_DOMAIN_USB1_PHY] = { |
947 | .genpd = { |
948 | .name = "usb-otg1" , |
949 | }, |
950 | .bits = { |
951 | .pxx = IMX8MP_USB1_PHY_Pxx_REQ, |
952 | .map = IMX8MP_USB1_PHY_A53_DOMAIN, |
953 | }, |
954 | .pgc = BIT(IMX8MP_PGC_USB1), |
955 | }, |
956 | |
957 | [IMX8MP_POWER_DOMAIN_USB2_PHY] = { |
958 | .genpd = { |
959 | .name = "usb-otg2" , |
960 | }, |
961 | .bits = { |
962 | .pxx = IMX8MP_USB2_PHY_Pxx_REQ, |
963 | .map = IMX8MP_USB2_PHY_A53_DOMAIN, |
964 | }, |
965 | .pgc = BIT(IMX8MP_PGC_USB2), |
966 | }, |
967 | |
968 | [IMX8MP_POWER_DOMAIN_MLMIX] = { |
969 | .genpd = { |
970 | .name = "mlmix" , |
971 | }, |
972 | .bits = { |
973 | .pxx = IMX8MP_MLMIX_Pxx_REQ, |
974 | .map = IMX8MP_MLMIX_A53_DOMAIN, |
975 | .hskreq = IMX8MP_MLMIX_PWRDNREQN, |
976 | .hskack = IMX8MP_MLMIX_PWRDNACKN, |
977 | }, |
978 | .pgc = BIT(IMX8MP_PGC_MLMIX), |
979 | .keep_clocks = true, |
980 | }, |
981 | |
982 | [IMX8MP_POWER_DOMAIN_AUDIOMIX] = { |
983 | .genpd = { |
984 | .name = "audiomix" , |
985 | }, |
986 | .bits = { |
987 | .pxx = IMX8MP_AUDIOMIX_Pxx_REQ, |
988 | .map = IMX8MP_AUDIOMIX_A53_DOMAIN, |
989 | .hskreq = IMX8MP_AUDIOMIX_PWRDNREQN, |
990 | .hskack = IMX8MP_AUDIOMIX_PWRDNACKN, |
991 | }, |
992 | .pgc = BIT(IMX8MP_PGC_AUDIOMIX), |
993 | .keep_clocks = true, |
994 | }, |
995 | |
996 | [IMX8MP_POWER_DOMAIN_GPU2D] = { |
997 | .genpd = { |
998 | .name = "gpu2d" , |
999 | }, |
1000 | .bits = { |
1001 | .pxx = IMX8MP_GPU_2D_Pxx_REQ, |
1002 | .map = IMX8MP_GPU2D_A53_DOMAIN, |
1003 | }, |
1004 | .pgc = BIT(IMX8MP_PGC_GPU2D), |
1005 | }, |
1006 | |
1007 | [IMX8MP_POWER_DOMAIN_GPUMIX] = { |
1008 | .genpd = { |
1009 | .name = "gpumix" , |
1010 | }, |
1011 | .bits = { |
1012 | .pxx = IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ, |
1013 | .map = IMX8MP_GPUMIX_A53_DOMAIN, |
1014 | .hskreq = IMX8MP_GPUMIX_PWRDNREQN, |
1015 | .hskack = IMX8MP_GPUMIX_PWRDNACKN, |
1016 | }, |
1017 | .pgc = BIT(IMX8MP_PGC_GPUMIX), |
1018 | .keep_clocks = true, |
1019 | }, |
1020 | |
1021 | [IMX8MP_POWER_DOMAIN_VPUMIX] = { |
1022 | .genpd = { |
1023 | .name = "vpumix" , |
1024 | }, |
1025 | .bits = { |
1026 | .pxx = IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ, |
1027 | .map = IMX8MP_VPUMIX_A53_DOMAIN, |
1028 | .hskreq = IMX8MP_VPUMIX_PWRDNREQN, |
1029 | .hskack = IMX8MP_VPUMIX_PWRDNACKN, |
1030 | }, |
1031 | .pgc = BIT(IMX8MP_PGC_VPUMIX), |
1032 | .keep_clocks = true, |
1033 | }, |
1034 | |
1035 | [IMX8MP_POWER_DOMAIN_GPU3D] = { |
1036 | .genpd = { |
1037 | .name = "gpu3d" , |
1038 | }, |
1039 | .bits = { |
1040 | .pxx = IMX8MP_GPU_3D_Pxx_REQ, |
1041 | .map = IMX8MP_GPU3D_A53_DOMAIN, |
1042 | }, |
1043 | .pgc = BIT(IMX8MP_PGC_GPU3D), |
1044 | }, |
1045 | |
1046 | [IMX8MP_POWER_DOMAIN_MEDIAMIX] = { |
1047 | .genpd = { |
1048 | .name = "mediamix" , |
1049 | }, |
1050 | .bits = { |
1051 | .pxx = IMX8MP_MEDIMIX_Pxx_REQ, |
1052 | .map = IMX8MP_MEDIAMIX_A53_DOMAIN, |
1053 | .hskreq = IMX8MP_MEDIAMIX_PWRDNREQN, |
1054 | .hskack = IMX8MP_MEDIAMIX_PWRDNACKN, |
1055 | }, |
1056 | .pgc = BIT(IMX8MP_PGC_MEDIAMIX), |
1057 | .keep_clocks = true, |
1058 | }, |
1059 | |
1060 | [IMX8MP_POWER_DOMAIN_VPU_G1] = { |
1061 | .genpd = { |
1062 | .name = "vpu-g1" , |
1063 | }, |
1064 | .bits = { |
1065 | .pxx = IMX8MP_VPU_G1_Pxx_REQ, |
1066 | .map = IMX8MP_VPU_G1_A53_DOMAIN, |
1067 | }, |
1068 | .pgc = BIT(IMX8MP_PGC_VPU_G1), |
1069 | }, |
1070 | |
1071 | [IMX8MP_POWER_DOMAIN_VPU_G2] = { |
1072 | .genpd = { |
1073 | .name = "vpu-g2" , |
1074 | }, |
1075 | .bits = { |
1076 | .pxx = IMX8MP_VPU_G2_Pxx_REQ, |
1077 | .map = IMX8MP_VPU_G2_A53_DOMAIN |
1078 | }, |
1079 | .pgc = BIT(IMX8MP_PGC_VPU_G2), |
1080 | }, |
1081 | |
1082 | [IMX8MP_POWER_DOMAIN_VPU_VC8000E] = { |
1083 | .genpd = { |
1084 | .name = "vpu-h1" , |
1085 | }, |
1086 | .bits = { |
1087 | .pxx = IMX8MP_VPU_VC8K_Pxx_REQ, |
1088 | .map = IMX8MP_VPU_VC8000E_A53_DOMAIN, |
1089 | }, |
1090 | .pgc = BIT(IMX8MP_PGC_VPU_VC8000E), |
1091 | }, |
1092 | |
1093 | [IMX8MP_POWER_DOMAIN_HDMIMIX] = { |
1094 | .genpd = { |
1095 | .name = "hdmimix" , |
1096 | }, |
1097 | .bits = { |
1098 | .pxx = IMX8MP_HDMIMIX_Pxx_REQ, |
1099 | .map = IMX8MP_HDMIMIX_A53_DOMAIN, |
1100 | .hskreq = IMX8MP_HDMIMIX_PWRDNREQN, |
1101 | .hskack = IMX8MP_HDMIMIX_PWRDNACKN, |
1102 | }, |
1103 | .pgc = BIT(IMX8MP_PGC_HDMIMIX), |
1104 | .keep_clocks = true, |
1105 | }, |
1106 | |
1107 | [IMX8MP_POWER_DOMAIN_HDMI_PHY] = { |
1108 | .genpd = { |
1109 | .name = "hdmi-phy" , |
1110 | }, |
1111 | .bits = { |
1112 | .pxx = IMX8MP_HDMI_PHY_Pxx_REQ, |
1113 | .map = IMX8MP_HDMI_PHY_A53_DOMAIN, |
1114 | }, |
1115 | .pgc = BIT(IMX8MP_PGC_HDMI), |
1116 | }, |
1117 | |
1118 | [IMX8MP_POWER_DOMAIN_MIPI_PHY2] = { |
1119 | .genpd = { |
1120 | .name = "mipi-phy2" , |
1121 | }, |
1122 | .bits = { |
1123 | .pxx = IMX8MP_MIPI_PHY2_Pxx_REQ, |
1124 | .map = IMX8MP_MIPI_PHY2_A53_DOMAIN, |
1125 | }, |
1126 | .pgc = BIT(IMX8MP_PGC_MIPI2), |
1127 | }, |
1128 | |
1129 | [IMX8MP_POWER_DOMAIN_HSIOMIX] = { |
1130 | .genpd = { |
1131 | .name = "hsiomix" , |
1132 | }, |
1133 | .bits = { |
1134 | .pxx = IMX8MP_HSIOMIX_Pxx_REQ, |
1135 | .map = IMX8MP_HSIOMIX_A53_DOMAIN, |
1136 | .hskreq = IMX8MP_HSIOMIX_PWRDNREQN, |
1137 | .hskack = IMX8MP_HSIOMIX_PWRDNACKN, |
1138 | }, |
1139 | .pgc = BIT(IMX8MP_PGC_HSIOMIX), |
1140 | .keep_clocks = true, |
1141 | }, |
1142 | |
1143 | [IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP] = { |
1144 | .genpd = { |
1145 | .name = "mediamix-isp-dwp" , |
1146 | }, |
1147 | .bits = { |
1148 | .pxx = IMX8MP_MEDIA_ISP_DWP_Pxx_REQ, |
1149 | .map = IMX8MP_MEDIA_ISPDWP_A53_DOMAIN, |
1150 | }, |
1151 | .pgc = BIT(IMX8MP_PGC_MEDIA_ISP_DWP), |
1152 | }, |
1153 | }; |
1154 | |
1155 | static const struct regmap_range imx8mp_yes_ranges[] = { |
1156 | regmap_reg_range(GPC_LPCR_A_CORE_BSC, |
1157 | IMX8MP_GPC_PGC_CPU_MAPPING), |
1158 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_NOC), |
1159 | GPC_PGC_SR(IMX8MP_PGC_NOC)), |
1160 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI1), |
1161 | GPC_PGC_SR(IMX8MP_PGC_MIPI1)), |
1162 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_PCIE), |
1163 | GPC_PGC_SR(IMX8MP_PGC_PCIE)), |
1164 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB1), |
1165 | GPC_PGC_SR(IMX8MP_PGC_USB1)), |
1166 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB2), |
1167 | GPC_PGC_SR(IMX8MP_PGC_USB2)), |
1168 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MLMIX), |
1169 | GPC_PGC_SR(IMX8MP_PGC_MLMIX)), |
1170 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_AUDIOMIX), |
1171 | GPC_PGC_SR(IMX8MP_PGC_AUDIOMIX)), |
1172 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU2D), |
1173 | GPC_PGC_SR(IMX8MP_PGC_GPU2D)), |
1174 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPUMIX), |
1175 | GPC_PGC_SR(IMX8MP_PGC_GPUMIX)), |
1176 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPUMIX), |
1177 | GPC_PGC_SR(IMX8MP_PGC_VPUMIX)), |
1178 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU3D), |
1179 | GPC_PGC_SR(IMX8MP_PGC_GPU3D)), |
1180 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIAMIX), |
1181 | GPC_PGC_SR(IMX8MP_PGC_MEDIAMIX)), |
1182 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G1), |
1183 | GPC_PGC_SR(IMX8MP_PGC_VPU_G1)), |
1184 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G2), |
1185 | GPC_PGC_SR(IMX8MP_PGC_VPU_G2)), |
1186 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_VC8000E), |
1187 | GPC_PGC_SR(IMX8MP_PGC_VPU_VC8000E)), |
1188 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMIMIX), |
1189 | GPC_PGC_SR(IMX8MP_PGC_HDMIMIX)), |
1190 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMI), |
1191 | GPC_PGC_SR(IMX8MP_PGC_HDMI)), |
1192 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI2), |
1193 | GPC_PGC_SR(IMX8MP_PGC_MIPI2)), |
1194 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HSIOMIX), |
1195 | GPC_PGC_SR(IMX8MP_PGC_HSIOMIX)), |
1196 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIA_ISP_DWP), |
1197 | GPC_PGC_SR(IMX8MP_PGC_MEDIA_ISP_DWP)), |
1198 | regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_DDRMIX), |
1199 | GPC_PGC_SR(IMX8MP_PGC_DDRMIX)), |
1200 | }; |
1201 | |
1202 | static const struct regmap_access_table imx8mp_access_table = { |
1203 | .yes_ranges = imx8mp_yes_ranges, |
1204 | .n_yes_ranges = ARRAY_SIZE(imx8mp_yes_ranges), |
1205 | }; |
1206 | |
1207 | static const struct imx_pgc_regs imx8mp_pgc_regs = { |
1208 | .map = IMX8MP_GPC_PGC_CPU_MAPPING, |
1209 | .pup = IMX8MP_GPC_PU_PGC_SW_PUP_REQ, |
1210 | .pdn = IMX8MP_GPC_PU_PGC_SW_PDN_REQ, |
1211 | .hsk = IMX8MP_GPC_PU_PWRHSK, |
1212 | }; |
1213 | static const struct imx_pgc_domain_data imx8mp_pgc_domain_data = { |
1214 | .domains = imx8mp_pgc_domains, |
1215 | .domains_num = ARRAY_SIZE(imx8mp_pgc_domains), |
1216 | .reg_access_table = &imx8mp_access_table, |
1217 | .pgc_regs = &imx8mp_pgc_regs, |
1218 | }; |
1219 | |
1220 | static const struct imx_pgc_domain imx8mn_pgc_domains[] = { |
1221 | [IMX8MN_POWER_DOMAIN_HSIOMIX] = { |
1222 | .genpd = { |
1223 | .name = "hsiomix" , |
1224 | }, |
1225 | .bits = { |
1226 | .pxx = 0, /* no power sequence control */ |
1227 | .map = 0, /* no power sequence control */ |
1228 | .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN, |
1229 | .hskack = IMX8MN_HSIO_HSK_PWRDNACKN, |
1230 | }, |
1231 | .keep_clocks = true, |
1232 | }, |
1233 | |
1234 | [IMX8MN_POWER_DOMAIN_OTG1] = { |
1235 | .genpd = { |
1236 | .name = "usb-otg1" , |
1237 | .flags = GENPD_FLAG_ACTIVE_WAKEUP, |
1238 | }, |
1239 | .bits = { |
1240 | .pxx = IMX8MN_OTG1_SW_Pxx_REQ, |
1241 | .map = IMX8MN_OTG1_A53_DOMAIN, |
1242 | }, |
1243 | .pgc = BIT(IMX8MN_PGC_OTG1), |
1244 | }, |
1245 | |
1246 | [IMX8MN_POWER_DOMAIN_GPUMIX] = { |
1247 | .genpd = { |
1248 | .name = "gpumix" , |
1249 | }, |
1250 | .bits = { |
1251 | .pxx = IMX8MN_GPUMIX_SW_Pxx_REQ, |
1252 | .map = IMX8MN_GPUMIX_A53_DOMAIN, |
1253 | .hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN, |
1254 | .hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN, |
1255 | }, |
1256 | .pgc = BIT(IMX8MN_PGC_GPUMIX), |
1257 | .keep_clocks = true, |
1258 | }, |
1259 | |
1260 | [IMX8MN_POWER_DOMAIN_DISPMIX] = { |
1261 | .genpd = { |
1262 | .name = "dispmix" , |
1263 | }, |
1264 | .bits = { |
1265 | .pxx = IMX8MN_DISPMIX_SW_Pxx_REQ, |
1266 | .map = IMX8MN_DISPMIX_A53_DOMAIN, |
1267 | .hskreq = IMX8MN_DISPMIX_HSK_PWRDNREQN, |
1268 | .hskack = IMX8MN_DISPMIX_HSK_PWRDNACKN, |
1269 | }, |
1270 | .pgc = BIT(IMX8MN_PGC_DISPMIX), |
1271 | .keep_clocks = true, |
1272 | }, |
1273 | |
1274 | [IMX8MN_POWER_DOMAIN_MIPI] = { |
1275 | .genpd = { |
1276 | .name = "mipi" , |
1277 | }, |
1278 | .bits = { |
1279 | .pxx = IMX8MN_MIPI_SW_Pxx_REQ, |
1280 | .map = IMX8MN_MIPI_A53_DOMAIN, |
1281 | }, |
1282 | .pgc = BIT(IMX8MN_PGC_MIPI), |
1283 | }, |
1284 | }; |
1285 | |
1286 | static const struct regmap_range imx8mn_yes_ranges[] = { |
1287 | regmap_reg_range(GPC_LPCR_A_CORE_BSC, |
1288 | GPC_PU_PWRHSK), |
1289 | regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_MIPI), |
1290 | GPC_PGC_SR(IMX8MN_PGC_MIPI)), |
1291 | regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_OTG1), |
1292 | GPC_PGC_SR(IMX8MN_PGC_OTG1)), |
1293 | regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DDR1), |
1294 | GPC_PGC_SR(IMX8MN_PGC_DDR1)), |
1295 | regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_GPUMIX), |
1296 | GPC_PGC_SR(IMX8MN_PGC_GPUMIX)), |
1297 | regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DISPMIX), |
1298 | GPC_PGC_SR(IMX8MN_PGC_DISPMIX)), |
1299 | }; |
1300 | |
1301 | static const struct regmap_access_table imx8mn_access_table = { |
1302 | .yes_ranges = imx8mn_yes_ranges, |
1303 | .n_yes_ranges = ARRAY_SIZE(imx8mn_yes_ranges), |
1304 | }; |
1305 | |
1306 | static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = { |
1307 | .domains = imx8mn_pgc_domains, |
1308 | .domains_num = ARRAY_SIZE(imx8mn_pgc_domains), |
1309 | .reg_access_table = &imx8mn_access_table, |
1310 | .pgc_regs = &imx7_pgc_regs, |
1311 | }; |
1312 | |
1313 | static int imx_pgc_domain_probe(struct platform_device *pdev) |
1314 | { |
1315 | struct imx_pgc_domain *domain = pdev->dev.platform_data; |
1316 | int ret; |
1317 | |
1318 | domain->dev = &pdev->dev; |
1319 | |
1320 | domain->regulator = devm_regulator_get_optional(dev: domain->dev, id: "power" ); |
1321 | if (IS_ERR(ptr: domain->regulator)) { |
1322 | if (PTR_ERR(ptr: domain->regulator) != -ENODEV) |
1323 | return dev_err_probe(dev: domain->dev, err: PTR_ERR(ptr: domain->regulator), |
1324 | fmt: "Failed to get domain's regulator\n" ); |
1325 | } else if (domain->voltage) { |
1326 | regulator_set_voltage(regulator: domain->regulator, |
1327 | min_uV: domain->voltage, max_uV: domain->voltage); |
1328 | } |
1329 | |
1330 | domain->num_clks = devm_clk_bulk_get_all(dev: domain->dev, clks: &domain->clks); |
1331 | if (domain->num_clks < 0) |
1332 | return dev_err_probe(dev: domain->dev, err: domain->num_clks, |
1333 | fmt: "Failed to get domain's clocks\n" ); |
1334 | |
1335 | domain->reset = devm_reset_control_array_get_optional_exclusive(dev: domain->dev); |
1336 | if (IS_ERR(ptr: domain->reset)) |
1337 | return dev_err_probe(dev: domain->dev, err: PTR_ERR(ptr: domain->reset), |
1338 | fmt: "Failed to get domain's resets\n" ); |
1339 | |
1340 | pm_runtime_enable(dev: domain->dev); |
1341 | |
1342 | if (domain->bits.map) |
1343 | regmap_update_bits(map: domain->regmap, reg: domain->regs->map, |
1344 | mask: domain->bits.map, val: domain->bits.map); |
1345 | |
1346 | ret = pm_genpd_init(genpd: &domain->genpd, NULL, is_off: true); |
1347 | if (ret) { |
1348 | dev_err(domain->dev, "Failed to init power domain\n" ); |
1349 | goto out_domain_unmap; |
1350 | } |
1351 | |
1352 | if (IS_ENABLED(CONFIG_LOCKDEP) && |
1353 | of_property_read_bool(np: domain->dev->of_node, propname: "power-domains" )) |
1354 | lockdep_set_subclass(&domain->genpd.mlock, 1); |
1355 | |
1356 | ret = of_genpd_add_provider_simple(np: domain->dev->of_node, |
1357 | genpd: &domain->genpd); |
1358 | if (ret) { |
1359 | dev_err(domain->dev, "Failed to add genpd provider\n" ); |
1360 | goto out_genpd_remove; |
1361 | } |
1362 | |
1363 | return 0; |
1364 | |
1365 | out_genpd_remove: |
1366 | pm_genpd_remove(genpd: &domain->genpd); |
1367 | out_domain_unmap: |
1368 | if (domain->bits.map) |
1369 | regmap_update_bits(map: domain->regmap, reg: domain->regs->map, |
1370 | mask: domain->bits.map, val: 0); |
1371 | pm_runtime_disable(dev: domain->dev); |
1372 | |
1373 | return ret; |
1374 | } |
1375 | |
1376 | static void imx_pgc_domain_remove(struct platform_device *pdev) |
1377 | { |
1378 | struct imx_pgc_domain *domain = pdev->dev.platform_data; |
1379 | |
1380 | of_genpd_del_provider(np: domain->dev->of_node); |
1381 | pm_genpd_remove(genpd: &domain->genpd); |
1382 | |
1383 | if (domain->bits.map) |
1384 | regmap_update_bits(map: domain->regmap, reg: domain->regs->map, |
1385 | mask: domain->bits.map, val: 0); |
1386 | |
1387 | pm_runtime_disable(dev: domain->dev); |
1388 | } |
1389 | |
1390 | #ifdef CONFIG_PM_SLEEP |
1391 | static int imx_pgc_domain_suspend(struct device *dev) |
1392 | { |
1393 | int ret; |
1394 | |
1395 | /* |
1396 | * This may look strange, but is done so the generic PM_SLEEP code |
1397 | * can power down our domain and more importantly power it up again |
1398 | * after resume, without tripping over our usage of runtime PM to |
1399 | * power up/down the nested domains. |
1400 | */ |
1401 | ret = pm_runtime_get_sync(dev); |
1402 | if (ret < 0) { |
1403 | pm_runtime_put_noidle(dev); |
1404 | return ret; |
1405 | } |
1406 | |
1407 | return 0; |
1408 | } |
1409 | |
1410 | static int imx_pgc_domain_resume(struct device *dev) |
1411 | { |
1412 | return pm_runtime_put(dev); |
1413 | } |
1414 | #endif |
1415 | |
1416 | static const struct dev_pm_ops imx_pgc_domain_pm_ops = { |
1417 | SET_SYSTEM_SLEEP_PM_OPS(imx_pgc_domain_suspend, imx_pgc_domain_resume) |
1418 | }; |
1419 | |
1420 | static const struct platform_device_id imx_pgc_domain_id[] = { |
1421 | { "imx-pgc-domain" , }, |
1422 | { }, |
1423 | }; |
1424 | |
1425 | static struct platform_driver imx_pgc_domain_driver = { |
1426 | .driver = { |
1427 | .name = "imx-pgc" , |
1428 | .pm = &imx_pgc_domain_pm_ops, |
1429 | }, |
1430 | .probe = imx_pgc_domain_probe, |
1431 | .remove_new = imx_pgc_domain_remove, |
1432 | .id_table = imx_pgc_domain_id, |
1433 | }; |
1434 | builtin_platform_driver(imx_pgc_domain_driver) |
1435 | |
1436 | static int imx_gpcv2_probe(struct platform_device *pdev) |
1437 | { |
1438 | const struct imx_pgc_domain_data *domain_data = |
1439 | of_device_get_match_data(dev: &pdev->dev); |
1440 | |
1441 | struct regmap_config regmap_config = { |
1442 | .reg_bits = 32, |
1443 | .val_bits = 32, |
1444 | .reg_stride = 4, |
1445 | .rd_table = domain_data->reg_access_table, |
1446 | .wr_table = domain_data->reg_access_table, |
1447 | .max_register = SZ_4K, |
1448 | }; |
1449 | struct device *dev = &pdev->dev; |
1450 | struct device_node *pgc_np, *np; |
1451 | struct regmap *regmap; |
1452 | void __iomem *base; |
1453 | int ret; |
1454 | |
1455 | pgc_np = of_get_child_by_name(node: dev->of_node, name: "pgc" ); |
1456 | if (!pgc_np) { |
1457 | dev_err(dev, "No power domains specified in DT\n" ); |
1458 | return -EINVAL; |
1459 | } |
1460 | |
1461 | base = devm_platform_ioremap_resource(pdev, index: 0); |
1462 | if (IS_ERR(ptr: base)) |
1463 | return PTR_ERR(ptr: base); |
1464 | |
1465 | regmap = devm_regmap_init_mmio(dev, base, ®map_config); |
1466 | if (IS_ERR(ptr: regmap)) { |
1467 | ret = PTR_ERR(ptr: regmap); |
1468 | dev_err(dev, "failed to init regmap (%d)\n" , ret); |
1469 | return ret; |
1470 | } |
1471 | |
1472 | for_each_child_of_node(pgc_np, np) { |
1473 | struct platform_device *pd_pdev; |
1474 | struct imx_pgc_domain *domain; |
1475 | u32 domain_index; |
1476 | |
1477 | if (!of_device_is_available(device: np)) |
1478 | continue; |
1479 | |
1480 | ret = of_property_read_u32(np, propname: "reg" , out_value: &domain_index); |
1481 | if (ret) { |
1482 | dev_err(dev, "Failed to read 'reg' property\n" ); |
1483 | of_node_put(node: np); |
1484 | return ret; |
1485 | } |
1486 | |
1487 | if (domain_index >= domain_data->domains_num) { |
1488 | dev_warn(dev, |
1489 | "Domain index %d is out of bounds\n" , |
1490 | domain_index); |
1491 | continue; |
1492 | } |
1493 | |
1494 | pd_pdev = platform_device_alloc(name: "imx-pgc-domain" , |
1495 | id: domain_index); |
1496 | if (!pd_pdev) { |
1497 | dev_err(dev, "Failed to allocate platform device\n" ); |
1498 | of_node_put(node: np); |
1499 | return -ENOMEM; |
1500 | } |
1501 | |
1502 | ret = platform_device_add_data(pdev: pd_pdev, |
1503 | data: &domain_data->domains[domain_index], |
1504 | size: sizeof(domain_data->domains[domain_index])); |
1505 | if (ret) { |
1506 | platform_device_put(pdev: pd_pdev); |
1507 | of_node_put(node: np); |
1508 | return ret; |
1509 | } |
1510 | |
1511 | domain = pd_pdev->dev.platform_data; |
1512 | domain->regmap = regmap; |
1513 | domain->regs = domain_data->pgc_regs; |
1514 | |
1515 | domain->genpd.power_on = imx_pgc_power_up; |
1516 | domain->genpd.power_off = imx_pgc_power_down; |
1517 | |
1518 | pd_pdev->dev.parent = dev; |
1519 | device_set_node(dev: &pd_pdev->dev, of_fwnode_handle(np)); |
1520 | |
1521 | ret = platform_device_add(pdev: pd_pdev); |
1522 | if (ret) { |
1523 | platform_device_put(pdev: pd_pdev); |
1524 | of_node_put(node: np); |
1525 | return ret; |
1526 | } |
1527 | } |
1528 | |
1529 | return 0; |
1530 | } |
1531 | |
1532 | static const struct of_device_id imx_gpcv2_dt_ids[] = { |
1533 | { .compatible = "fsl,imx7d-gpc" , .data = &imx7_pgc_domain_data, }, |
1534 | { .compatible = "fsl,imx8mm-gpc" , .data = &imx8mm_pgc_domain_data, }, |
1535 | { .compatible = "fsl,imx8mn-gpc" , .data = &imx8mn_pgc_domain_data, }, |
1536 | { .compatible = "fsl,imx8mp-gpc" , .data = &imx8mp_pgc_domain_data, }, |
1537 | { .compatible = "fsl,imx8mq-gpc" , .data = &imx8m_pgc_domain_data, }, |
1538 | { } |
1539 | }; |
1540 | |
1541 | static struct platform_driver imx_gpc_driver = { |
1542 | .driver = { |
1543 | .name = "imx-gpcv2" , |
1544 | .of_match_table = imx_gpcv2_dt_ids, |
1545 | }, |
1546 | .probe = imx_gpcv2_probe, |
1547 | }; |
1548 | builtin_platform_driver(imx_gpc_driver) |
1549 | |