]>
Commit | Line | Data |
---|---|---|
c84e3587 SH |
1 | /* |
2 | * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de> | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License version 2 as | |
6 | * published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | */ | |
13 | #include <linux/clk.h> | |
6078c651 | 14 | #include <linux/init.h> |
c84e3587 | 15 | #include <linux/io.h> |
c84e3587 SH |
16 | #include <linux/mfd/syscon.h> |
17 | #include <linux/of_device.h> | |
18 | #include <linux/platform_device.h> | |
19 | #include <linux/pm_domain.h> | |
4688f385 | 20 | #include <linux/regulator/consumer.h> |
6078c651 JL |
21 | #include <linux/soc/mediatek/infracfg.h> |
22 | ||
112ef188 | 23 | #include <dt-bindings/power/mt2701-power.h> |
320f4ced | 24 | #include <dt-bindings/power/mt2712-power.h> |
36c310f5 | 25 | #include <dt-bindings/power/mt6797-power.h> |
52510ee9 | 26 | #include <dt-bindings/power/mt7622-power.h> |
c84e3587 SH |
27 | #include <dt-bindings/power/mt8173-power.h> |
28 | ||
29 | #define SPM_VDE_PWR_CON 0x0210 | |
30 | #define SPM_MFG_PWR_CON 0x0214 | |
31 | #define SPM_VEN_PWR_CON 0x0230 | |
32 | #define SPM_ISP_PWR_CON 0x0238 | |
33 | #define SPM_DIS_PWR_CON 0x023c | |
112ef188 | 34 | #define SPM_CONN_PWR_CON 0x0280 |
c84e3587 | 35 | #define SPM_VEN2_PWR_CON 0x0298 |
320f4ced | 36 | #define SPM_AUDIO_PWR_CON 0x029c /* MT8173, MT2712 */ |
112ef188 SW |
37 | #define SPM_BDP_PWR_CON 0x029c /* MT2701 */ |
38 | #define SPM_ETH_PWR_CON 0x02a0 | |
39 | #define SPM_HIF_PWR_CON 0x02a4 | |
40 | #define SPM_IFR_MSC_PWR_CON 0x02a8 | |
c84e3587 SH |
41 | #define SPM_MFG_2D_PWR_CON 0x02c0 |
42 | #define SPM_MFG_ASYNC_PWR_CON 0x02c4 | |
43 | #define SPM_USB_PWR_CON 0x02cc | |
320f4ced | 44 | #define SPM_USB2_PWR_CON 0x02d4 /* MT2712 */ |
52510ee9 SW |
45 | #define SPM_ETHSYS_PWR_CON 0x02e0 /* MT7622 */ |
46 | #define SPM_HIF0_PWR_CON 0x02e4 /* MT7622 */ | |
47 | #define SPM_HIF1_PWR_CON 0x02e8 /* MT7622 */ | |
48 | #define SPM_WB_PWR_CON 0x02ec /* MT7622 */ | |
49 | ||
c84e3587 SH |
50 | #define SPM_PWR_STATUS 0x060c |
51 | #define SPM_PWR_STATUS_2ND 0x0610 | |
52 | ||
53 | #define PWR_RST_B_BIT BIT(0) | |
54 | #define PWR_ISO_BIT BIT(1) | |
55 | #define PWR_ON_BIT BIT(2) | |
56 | #define PWR_ON_2ND_BIT BIT(3) | |
57 | #define PWR_CLK_DIS_BIT BIT(4) | |
58 | ||
112ef188 | 59 | #define PWR_STATUS_CONN BIT(1) |
c84e3587 SH |
60 | #define PWR_STATUS_DISP BIT(3) |
61 | #define PWR_STATUS_MFG BIT(4) | |
62 | #define PWR_STATUS_ISP BIT(5) | |
63 | #define PWR_STATUS_VDEC BIT(7) | |
112ef188 SW |
64 | #define PWR_STATUS_BDP BIT(14) |
65 | #define PWR_STATUS_ETH BIT(15) | |
66 | #define PWR_STATUS_HIF BIT(16) | |
67 | #define PWR_STATUS_IFR_MSC BIT(17) | |
320f4ced | 68 | #define PWR_STATUS_USB2 BIT(19) /* MT2712 */ |
c84e3587 SH |
69 | #define PWR_STATUS_VENC_LT BIT(20) |
70 | #define PWR_STATUS_VENC BIT(21) | |
320f4ced | 71 | #define PWR_STATUS_MFG_2D BIT(22) /* MT8173 */ |
72 | #define PWR_STATUS_MFG_ASYNC BIT(23) /* MT8173 */ | |
73 | #define PWR_STATUS_AUDIO BIT(24) /* MT8173, MT2712 */ | |
74 | #define PWR_STATUS_USB BIT(25) /* MT8173, MT2712 */ | |
52510ee9 SW |
75 | #define PWR_STATUS_ETHSYS BIT(24) /* MT7622 */ |
76 | #define PWR_STATUS_HIF0 BIT(25) /* MT7622 */ | |
77 | #define PWR_STATUS_HIF1 BIT(26) /* MT7622 */ | |
78 | #define PWR_STATUS_WB BIT(27) /* MT7622 */ | |
c84e3587 SH |
79 | |
80 | enum clk_id { | |
6078c651 JL |
81 | CLK_NONE, |
82 | CLK_MM, | |
83 | CLK_MFG, | |
84 | CLK_VENC, | |
85 | CLK_VENC_LT, | |
112ef188 | 86 | CLK_ETHIF, |
a3acbbf4 | 87 | CLK_VDEC, |
52510ee9 | 88 | CLK_HIFSEL, |
d1fb29fa | 89 | CLK_JPGDEC, |
90 | CLK_AUDIO, | |
6078c651 JL |
91 | CLK_MAX, |
92 | }; | |
93 | ||
94 | static const char * const clk_names[] = { | |
95 | NULL, | |
96 | "mm", | |
97 | "mfg", | |
98 | "venc", | |
99 | "venc_lt", | |
112ef188 | 100 | "ethif", |
a3acbbf4 | 101 | "vdec", |
52510ee9 | 102 | "hif_sel", |
d1fb29fa | 103 | "jpgdec", |
104 | "audio", | |
6078c651 | 105 | NULL, |
c84e3587 SH |
106 | }; |
107 | ||
d1fb29fa | 108 | #define MAX_CLKS 3 |
41b3e0f0 | 109 | |
c84e3587 SH |
110 | struct scp_domain_data { |
111 | const char *name; | |
112 | u32 sta_mask; | |
113 | int ctl_offs; | |
114 | u32 sram_pdn_bits; | |
115 | u32 sram_pdn_ack_bits; | |
116 | u32 bus_prot_mask; | |
41b3e0f0 | 117 | enum clk_id clk_id[MAX_CLKS]; |
47e90154 | 118 | bool active_wakeup; |
c84e3587 SH |
119 | }; |
120 | ||
c84e3587 SH |
121 | struct scp; |
122 | ||
123 | struct scp_domain { | |
124 | struct generic_pm_domain genpd; | |
125 | struct scp *scp; | |
41b3e0f0 | 126 | struct clk *clk[MAX_CLKS]; |
be29523d | 127 | const struct scp_domain_data *data; |
4688f385 | 128 | struct regulator *supply; |
c84e3587 SH |
129 | }; |
130 | ||
f1be4c4e MC |
131 | struct scp_ctrl_reg { |
132 | int pwr_sta_offs; | |
133 | int pwr_sta2nd_offs; | |
134 | }; | |
135 | ||
c84e3587 | 136 | struct scp { |
6078c651 | 137 | struct scp_domain *domains; |
c84e3587 SH |
138 | struct genpd_onecell_data pd_data; |
139 | struct device *dev; | |
140 | void __iomem *base; | |
141 | struct regmap *infracfg; | |
f1be4c4e | 142 | struct scp_ctrl_reg ctrl_reg; |
fa7e843a | 143 | bool bus_prot_reg_update; |
c84e3587 SH |
144 | }; |
145 | ||
53fddb1a SW |
146 | struct scp_subdomain { |
147 | int origin; | |
148 | int subdomain; | |
149 | }; | |
150 | ||
151 | struct scp_soc_data { | |
152 | const struct scp_domain_data *domains; | |
153 | int num_domains; | |
154 | const struct scp_subdomain *subdomains; | |
155 | int num_subdomains; | |
156 | const struct scp_ctrl_reg regs; | |
fa7e843a | 157 | bool bus_prot_reg_update; |
53fddb1a SW |
158 | }; |
159 | ||
c84e3587 SH |
160 | static int scpsys_domain_is_on(struct scp_domain *scpd) |
161 | { | |
162 | struct scp *scp = scpd->scp; | |
163 | ||
f1be4c4e MC |
164 | u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) & |
165 | scpd->data->sta_mask; | |
166 | u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) & | |
167 | scpd->data->sta_mask; | |
c84e3587 SH |
168 | |
169 | /* | |
170 | * A domain is on when both status bits are set. If only one is set | |
171 | * return an error. This happens while powering up a domain | |
172 | */ | |
173 | ||
174 | if (status && status2) | |
175 | return true; | |
176 | if (!status && !status2) | |
177 | return false; | |
178 | ||
179 | return -EINVAL; | |
180 | } | |
181 | ||
182 | static int scpsys_power_on(struct generic_pm_domain *genpd) | |
183 | { | |
184 | struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); | |
185 | struct scp *scp = scpd->scp; | |
186 | unsigned long timeout; | |
187 | bool expired; | |
be29523d MB |
188 | void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; |
189 | u32 sram_pdn_ack = scpd->data->sram_pdn_ack_bits; | |
c84e3587 SH |
190 | u32 val; |
191 | int ret; | |
41b3e0f0 JL |
192 | int i; |
193 | ||
4688f385 SH |
194 | if (scpd->supply) { |
195 | ret = regulator_enable(scpd->supply); | |
196 | if (ret) | |
197 | return ret; | |
198 | } | |
199 | ||
41b3e0f0 JL |
200 | for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) { |
201 | ret = clk_prepare_enable(scpd->clk[i]); | |
202 | if (ret) { | |
203 | for (--i; i >= 0; i--) | |
204 | clk_disable_unprepare(scpd->clk[i]); | |
c84e3587 | 205 | |
c84e3587 | 206 | goto err_clk; |
41b3e0f0 | 207 | } |
c84e3587 SH |
208 | } |
209 | ||
210 | val = readl(ctl_addr); | |
211 | val |= PWR_ON_BIT; | |
212 | writel(val, ctl_addr); | |
213 | val |= PWR_ON_2ND_BIT; | |
214 | writel(val, ctl_addr); | |
215 | ||
216 | /* wait until PWR_ACK = 1 */ | |
217 | timeout = jiffies + HZ; | |
218 | expired = false; | |
219 | while (1) { | |
220 | ret = scpsys_domain_is_on(scpd); | |
221 | if (ret > 0) | |
222 | break; | |
223 | ||
224 | if (expired) { | |
225 | ret = -ETIMEDOUT; | |
226 | goto err_pwr_ack; | |
227 | } | |
228 | ||
229 | cpu_relax(); | |
230 | ||
231 | if (time_after(jiffies, timeout)) | |
232 | expired = true; | |
233 | } | |
234 | ||
235 | val &= ~PWR_CLK_DIS_BIT; | |
236 | writel(val, ctl_addr); | |
237 | ||
238 | val &= ~PWR_ISO_BIT; | |
239 | writel(val, ctl_addr); | |
240 | ||
241 | val |= PWR_RST_B_BIT; | |
242 | writel(val, ctl_addr); | |
243 | ||
be29523d | 244 | val &= ~scpd->data->sram_pdn_bits; |
c84e3587 SH |
245 | writel(val, ctl_addr); |
246 | ||
247 | /* wait until SRAM_PDN_ACK all 0 */ | |
248 | timeout = jiffies + HZ; | |
249 | expired = false; | |
250 | while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) { | |
251 | ||
252 | if (expired) { | |
253 | ret = -ETIMEDOUT; | |
254 | goto err_pwr_ack; | |
255 | } | |
256 | ||
257 | cpu_relax(); | |
258 | ||
259 | if (time_after(jiffies, timeout)) | |
260 | expired = true; | |
261 | } | |
262 | ||
be29523d | 263 | if (scpd->data->bus_prot_mask) { |
c84e3587 | 264 | ret = mtk_infracfg_clear_bus_protection(scp->infracfg, |
fa7e843a | 265 | scpd->data->bus_prot_mask, |
266 | scp->bus_prot_reg_update); | |
c84e3587 SH |
267 | if (ret) |
268 | goto err_pwr_ack; | |
269 | } | |
270 | ||
271 | return 0; | |
272 | ||
273 | err_pwr_ack: | |
41b3e0f0 JL |
274 | for (i = MAX_CLKS - 1; i >= 0; i--) { |
275 | if (scpd->clk[i]) | |
276 | clk_disable_unprepare(scpd->clk[i]); | |
277 | } | |
c84e3587 | 278 | err_clk: |
4688f385 SH |
279 | if (scpd->supply) |
280 | regulator_disable(scpd->supply); | |
281 | ||
c84e3587 SH |
282 | dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); |
283 | ||
284 | return ret; | |
285 | } | |
286 | ||
287 | static int scpsys_power_off(struct generic_pm_domain *genpd) | |
288 | { | |
289 | struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); | |
290 | struct scp *scp = scpd->scp; | |
291 | unsigned long timeout; | |
292 | bool expired; | |
be29523d MB |
293 | void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; |
294 | u32 pdn_ack = scpd->data->sram_pdn_ack_bits; | |
c84e3587 SH |
295 | u32 val; |
296 | int ret; | |
41b3e0f0 | 297 | int i; |
c84e3587 | 298 | |
be29523d | 299 | if (scpd->data->bus_prot_mask) { |
c84e3587 | 300 | ret = mtk_infracfg_set_bus_protection(scp->infracfg, |
fa7e843a | 301 | scpd->data->bus_prot_mask, |
302 | scp->bus_prot_reg_update); | |
c84e3587 SH |
303 | if (ret) |
304 | goto out; | |
305 | } | |
306 | ||
307 | val = readl(ctl_addr); | |
be29523d | 308 | val |= scpd->data->sram_pdn_bits; |
c84e3587 SH |
309 | writel(val, ctl_addr); |
310 | ||
311 | /* wait until SRAM_PDN_ACK all 1 */ | |
312 | timeout = jiffies + HZ; | |
313 | expired = false; | |
314 | while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) { | |
315 | if (expired) { | |
316 | ret = -ETIMEDOUT; | |
317 | goto out; | |
318 | } | |
319 | ||
320 | cpu_relax(); | |
321 | ||
322 | if (time_after(jiffies, timeout)) | |
323 | expired = true; | |
324 | } | |
325 | ||
326 | val |= PWR_ISO_BIT; | |
327 | writel(val, ctl_addr); | |
328 | ||
329 | val &= ~PWR_RST_B_BIT; | |
330 | writel(val, ctl_addr); | |
331 | ||
332 | val |= PWR_CLK_DIS_BIT; | |
333 | writel(val, ctl_addr); | |
334 | ||
335 | val &= ~PWR_ON_BIT; | |
336 | writel(val, ctl_addr); | |
337 | ||
338 | val &= ~PWR_ON_2ND_BIT; | |
339 | writel(val, ctl_addr); | |
340 | ||
341 | /* wait until PWR_ACK = 0 */ | |
342 | timeout = jiffies + HZ; | |
343 | expired = false; | |
344 | while (1) { | |
345 | ret = scpsys_domain_is_on(scpd); | |
346 | if (ret == 0) | |
347 | break; | |
348 | ||
349 | if (expired) { | |
350 | ret = -ETIMEDOUT; | |
351 | goto out; | |
352 | } | |
353 | ||
354 | cpu_relax(); | |
355 | ||
356 | if (time_after(jiffies, timeout)) | |
357 | expired = true; | |
358 | } | |
359 | ||
41b3e0f0 JL |
360 | for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) |
361 | clk_disable_unprepare(scpd->clk[i]); | |
c84e3587 | 362 | |
4688f385 SH |
363 | if (scpd->supply) |
364 | regulator_disable(scpd->supply); | |
365 | ||
c84e3587 SH |
366 | return 0; |
367 | ||
368 | out: | |
369 | dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name); | |
370 | ||
371 | return ret; | |
372 | } | |
373 | ||
6078c651 JL |
374 | static void init_clks(struct platform_device *pdev, struct clk **clk) |
375 | { | |
376 | int i; | |
377 | ||
378 | for (i = CLK_NONE + 1; i < CLK_MAX; i++) | |
379 | clk[i] = devm_clk_get(&pdev->dev, clk_names[i]); | |
380 | } | |
381 | ||
382 | static struct scp *init_scp(struct platform_device *pdev, | |
f1be4c4e | 383 | const struct scp_domain_data *scp_domain_data, int num, |
fa7e843a | 384 | const struct scp_ctrl_reg *scp_ctrl_reg, |
385 | bool bus_prot_reg_update) | |
c84e3587 SH |
386 | { |
387 | struct genpd_onecell_data *pd_data; | |
388 | struct resource *res; | |
6078c651 | 389 | int i, j; |
c84e3587 | 390 | struct scp *scp; |
6078c651 | 391 | struct clk *clk[CLK_MAX]; |
c84e3587 SH |
392 | |
393 | scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL); | |
394 | if (!scp) | |
6078c651 | 395 | return ERR_PTR(-ENOMEM); |
c84e3587 | 396 | |
f1be4c4e MC |
397 | scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs; |
398 | scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs; | |
399 | ||
fa7e843a | 400 | scp->bus_prot_reg_update = bus_prot_reg_update; |
401 | ||
c84e3587 SH |
402 | scp->dev = &pdev->dev; |
403 | ||
404 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
405 | scp->base = devm_ioremap_resource(&pdev->dev, res); | |
406 | if (IS_ERR(scp->base)) | |
6078c651 JL |
407 | return ERR_CAST(scp->base); |
408 | ||
409 | scp->domains = devm_kzalloc(&pdev->dev, | |
410 | sizeof(*scp->domains) * num, GFP_KERNEL); | |
411 | if (!scp->domains) | |
412 | return ERR_PTR(-ENOMEM); | |
c84e3587 SH |
413 | |
414 | pd_data = &scp->pd_data; | |
415 | ||
416 | pd_data->domains = devm_kzalloc(&pdev->dev, | |
6078c651 | 417 | sizeof(*pd_data->domains) * num, GFP_KERNEL); |
c84e3587 | 418 | if (!pd_data->domains) |
6078c651 | 419 | return ERR_PTR(-ENOMEM); |
41b3e0f0 | 420 | |
c84e3587 SH |
421 | scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, |
422 | "infracfg"); | |
423 | if (IS_ERR(scp->infracfg)) { | |
424 | dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", | |
425 | PTR_ERR(scp->infracfg)); | |
6078c651 | 426 | return ERR_CAST(scp->infracfg); |
c84e3587 SH |
427 | } |
428 | ||
6078c651 | 429 | for (i = 0; i < num; i++) { |
4688f385 SH |
430 | struct scp_domain *scpd = &scp->domains[i]; |
431 | const struct scp_domain_data *data = &scp_domain_data[i]; | |
432 | ||
433 | scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name); | |
434 | if (IS_ERR(scpd->supply)) { | |
435 | if (PTR_ERR(scpd->supply) == -ENODEV) | |
436 | scpd->supply = NULL; | |
437 | else | |
6078c651 | 438 | return ERR_CAST(scpd->supply); |
4688f385 SH |
439 | } |
440 | } | |
441 | ||
6078c651 | 442 | pd_data->num_domains = num; |
c84e3587 | 443 | |
6078c651 JL |
444 | init_clks(pdev, clk); |
445 | ||
446 | for (i = 0; i < num; i++) { | |
c84e3587 SH |
447 | struct scp_domain *scpd = &scp->domains[i]; |
448 | struct generic_pm_domain *genpd = &scpd->genpd; | |
449 | const struct scp_domain_data *data = &scp_domain_data[i]; | |
450 | ||
451 | pd_data->domains[i] = genpd; | |
452 | scpd->scp = scp; | |
453 | ||
be29523d | 454 | scpd->data = data; |
6078c651 JL |
455 | |
456 | for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) { | |
457 | struct clk *c = clk[data->clk_id[j]]; | |
458 | ||
459 | if (IS_ERR(c)) { | |
460 | dev_err(&pdev->dev, "%s: clk unavailable\n", | |
461 | data->name); | |
462 | return ERR_CAST(c); | |
463 | } | |
464 | ||
465 | scpd->clk[j] = c; | |
466 | } | |
c84e3587 SH |
467 | |
468 | genpd->name = data->name; | |
469 | genpd->power_off = scpsys_power_off; | |
470 | genpd->power_on = scpsys_power_on; | |
7534d181 GU |
471 | if (scpd->data->active_wakeup) |
472 | genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP; | |
6078c651 JL |
473 | } |
474 | ||
475 | return scp; | |
476 | } | |
477 | ||
478 | static void mtk_register_power_domains(struct platform_device *pdev, | |
479 | struct scp *scp, int num) | |
480 | { | |
481 | struct genpd_onecell_data *pd_data; | |
482 | int i, ret; | |
483 | ||
484 | for (i = 0; i < num; i++) { | |
485 | struct scp_domain *scpd = &scp->domains[i]; | |
486 | struct generic_pm_domain *genpd = &scpd->genpd; | |
c84e3587 SH |
487 | |
488 | /* | |
d9c9f3b8 JL |
489 | * Initially turn on all domains to make the domains usable |
490 | * with !CONFIG_PM and to get the hardware in sync with the | |
491 | * software. The unused domains will be switched off during | |
492 | * late_init time. | |
c84e3587 | 493 | */ |
d9c9f3b8 | 494 | genpd->power_on(genpd); |
c84e3587 | 495 | |
d9c9f3b8 | 496 | pm_genpd_init(genpd, NULL, false); |
c84e3587 SH |
497 | } |
498 | ||
499 | /* | |
500 | * We are not allowed to fail here since there is no way to unregister | |
501 | * a power domain. Once registered above we have to keep the domains | |
502 | * valid. | |
503 | */ | |
504 | ||
6078c651 JL |
505 | pd_data = &scp->pd_data; |
506 | ||
507 | ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); | |
508 | if (ret) | |
509 | dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); | |
510 | } | |
511 | ||
112ef188 SW |
512 | /* |
513 | * MT2701 power domain support | |
514 | */ | |
515 | ||
516 | static const struct scp_domain_data scp_domain_data_mt2701[] = { | |
517 | [MT2701_POWER_DOMAIN_CONN] = { | |
518 | .name = "conn", | |
519 | .sta_mask = PWR_STATUS_CONN, | |
520 | .ctl_offs = SPM_CONN_PWR_CON, | |
521 | .bus_prot_mask = 0x0104, | |
522 | .clk_id = {CLK_NONE}, | |
523 | .active_wakeup = true, | |
524 | }, | |
525 | [MT2701_POWER_DOMAIN_DISP] = { | |
526 | .name = "disp", | |
527 | .sta_mask = PWR_STATUS_DISP, | |
528 | .ctl_offs = SPM_DIS_PWR_CON, | |
529 | .sram_pdn_bits = GENMASK(11, 8), | |
530 | .clk_id = {CLK_MM}, | |
531 | .bus_prot_mask = 0x0002, | |
532 | .active_wakeup = true, | |
533 | }, | |
534 | [MT2701_POWER_DOMAIN_MFG] = { | |
535 | .name = "mfg", | |
536 | .sta_mask = PWR_STATUS_MFG, | |
537 | .ctl_offs = SPM_MFG_PWR_CON, | |
538 | .sram_pdn_bits = GENMASK(11, 8), | |
539 | .sram_pdn_ack_bits = GENMASK(12, 12), | |
540 | .clk_id = {CLK_MFG}, | |
541 | .active_wakeup = true, | |
542 | }, | |
543 | [MT2701_POWER_DOMAIN_VDEC] = { | |
544 | .name = "vdec", | |
545 | .sta_mask = PWR_STATUS_VDEC, | |
546 | .ctl_offs = SPM_VDE_PWR_CON, | |
547 | .sram_pdn_bits = GENMASK(11, 8), | |
548 | .sram_pdn_ack_bits = GENMASK(12, 12), | |
549 | .clk_id = {CLK_MM}, | |
550 | .active_wakeup = true, | |
551 | }, | |
552 | [MT2701_POWER_DOMAIN_ISP] = { | |
553 | .name = "isp", | |
554 | .sta_mask = PWR_STATUS_ISP, | |
555 | .ctl_offs = SPM_ISP_PWR_CON, | |
556 | .sram_pdn_bits = GENMASK(11, 8), | |
557 | .sram_pdn_ack_bits = GENMASK(13, 12), | |
558 | .clk_id = {CLK_MM}, | |
559 | .active_wakeup = true, | |
560 | }, | |
561 | [MT2701_POWER_DOMAIN_BDP] = { | |
562 | .name = "bdp", | |
563 | .sta_mask = PWR_STATUS_BDP, | |
564 | .ctl_offs = SPM_BDP_PWR_CON, | |
565 | .sram_pdn_bits = GENMASK(11, 8), | |
566 | .clk_id = {CLK_NONE}, | |
567 | .active_wakeup = true, | |
568 | }, | |
569 | [MT2701_POWER_DOMAIN_ETH] = { | |
570 | .name = "eth", | |
571 | .sta_mask = PWR_STATUS_ETH, | |
572 | .ctl_offs = SPM_ETH_PWR_CON, | |
573 | .sram_pdn_bits = GENMASK(11, 8), | |
574 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
575 | .clk_id = {CLK_ETHIF}, | |
576 | .active_wakeup = true, | |
577 | }, | |
578 | [MT2701_POWER_DOMAIN_HIF] = { | |
579 | .name = "hif", | |
580 | .sta_mask = PWR_STATUS_HIF, | |
581 | .ctl_offs = SPM_HIF_PWR_CON, | |
582 | .sram_pdn_bits = GENMASK(11, 8), | |
583 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
584 | .clk_id = {CLK_ETHIF}, | |
585 | .active_wakeup = true, | |
586 | }, | |
587 | [MT2701_POWER_DOMAIN_IFR_MSC] = { | |
588 | .name = "ifr_msc", | |
589 | .sta_mask = PWR_STATUS_IFR_MSC, | |
590 | .ctl_offs = SPM_IFR_MSC_PWR_CON, | |
591 | .clk_id = {CLK_NONE}, | |
592 | .active_wakeup = true, | |
593 | }, | |
594 | }; | |
595 | ||
320f4ced | 596 | /* |
597 | * MT2712 power domain support | |
598 | */ | |
599 | static const struct scp_domain_data scp_domain_data_mt2712[] = { | |
600 | [MT2712_POWER_DOMAIN_MM] = { | |
601 | .name = "mm", | |
602 | .sta_mask = PWR_STATUS_DISP, | |
603 | .ctl_offs = SPM_DIS_PWR_CON, | |
604 | .sram_pdn_bits = GENMASK(8, 8), | |
605 | .sram_pdn_ack_bits = GENMASK(12, 12), | |
606 | .clk_id = {CLK_MM}, | |
607 | .active_wakeup = true, | |
608 | }, | |
609 | [MT2712_POWER_DOMAIN_VDEC] = { | |
610 | .name = "vdec", | |
611 | .sta_mask = PWR_STATUS_VDEC, | |
612 | .ctl_offs = SPM_VDE_PWR_CON, | |
613 | .sram_pdn_bits = GENMASK(8, 8), | |
614 | .sram_pdn_ack_bits = GENMASK(12, 12), | |
615 | .clk_id = {CLK_MM, CLK_VDEC}, | |
616 | .active_wakeup = true, | |
617 | }, | |
618 | [MT2712_POWER_DOMAIN_VENC] = { | |
619 | .name = "venc", | |
620 | .sta_mask = PWR_STATUS_VENC, | |
621 | .ctl_offs = SPM_VEN_PWR_CON, | |
622 | .sram_pdn_bits = GENMASK(11, 8), | |
623 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
624 | .clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC}, | |
625 | .active_wakeup = true, | |
626 | }, | |
627 | [MT2712_POWER_DOMAIN_ISP] = { | |
628 | .name = "isp", | |
629 | .sta_mask = PWR_STATUS_ISP, | |
630 | .ctl_offs = SPM_ISP_PWR_CON, | |
631 | .sram_pdn_bits = GENMASK(11, 8), | |
632 | .sram_pdn_ack_bits = GENMASK(13, 12), | |
633 | .clk_id = {CLK_MM}, | |
634 | .active_wakeup = true, | |
635 | }, | |
636 | [MT2712_POWER_DOMAIN_AUDIO] = { | |
637 | .name = "audio", | |
638 | .sta_mask = PWR_STATUS_AUDIO, | |
639 | .ctl_offs = SPM_AUDIO_PWR_CON, | |
640 | .sram_pdn_bits = GENMASK(11, 8), | |
641 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
642 | .clk_id = {CLK_AUDIO}, | |
643 | .active_wakeup = true, | |
644 | }, | |
645 | [MT2712_POWER_DOMAIN_USB] = { | |
646 | .name = "usb", | |
647 | .sta_mask = PWR_STATUS_USB, | |
648 | .ctl_offs = SPM_USB_PWR_CON, | |
649 | .sram_pdn_bits = GENMASK(10, 8), | |
650 | .sram_pdn_ack_bits = GENMASK(14, 12), | |
651 | .clk_id = {CLK_NONE}, | |
652 | .active_wakeup = true, | |
653 | }, | |
654 | [MT2712_POWER_DOMAIN_USB2] = { | |
655 | .name = "usb2", | |
656 | .sta_mask = PWR_STATUS_USB2, | |
657 | .ctl_offs = SPM_USB2_PWR_CON, | |
658 | .sram_pdn_bits = GENMASK(10, 8), | |
659 | .sram_pdn_ack_bits = GENMASK(14, 12), | |
660 | .clk_id = {CLK_NONE}, | |
661 | .active_wakeup = true, | |
662 | }, | |
663 | [MT2712_POWER_DOMAIN_MFG] = { | |
664 | .name = "mfg", | |
665 | .sta_mask = PWR_STATUS_MFG, | |
666 | .ctl_offs = SPM_MFG_PWR_CON, | |
667 | .sram_pdn_bits = GENMASK(11, 8), | |
668 | .sram_pdn_ack_bits = GENMASK(19, 16), | |
669 | .clk_id = {CLK_MFG}, | |
670 | .bus_prot_mask = BIT(14) | BIT(21) | BIT(23), | |
671 | .active_wakeup = true, | |
672 | }, | |
673 | }; | |
674 | ||
36c310f5 MC |
675 | /* |
676 | * MT6797 power domain support | |
677 | */ | |
678 | ||
679 | static const struct scp_domain_data scp_domain_data_mt6797[] = { | |
680 | [MT6797_POWER_DOMAIN_VDEC] = { | |
681 | .name = "vdec", | |
682 | .sta_mask = BIT(7), | |
683 | .ctl_offs = 0x300, | |
684 | .sram_pdn_bits = GENMASK(8, 8), | |
685 | .sram_pdn_ack_bits = GENMASK(12, 12), | |
686 | .clk_id = {CLK_VDEC}, | |
687 | }, | |
688 | [MT6797_POWER_DOMAIN_VENC] = { | |
689 | .name = "venc", | |
690 | .sta_mask = BIT(21), | |
691 | .ctl_offs = 0x304, | |
692 | .sram_pdn_bits = GENMASK(11, 8), | |
693 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
694 | .clk_id = {CLK_NONE}, | |
695 | }, | |
696 | [MT6797_POWER_DOMAIN_ISP] = { | |
697 | .name = "isp", | |
698 | .sta_mask = BIT(5), | |
699 | .ctl_offs = 0x308, | |
700 | .sram_pdn_bits = GENMASK(9, 8), | |
701 | .sram_pdn_ack_bits = GENMASK(13, 12), | |
702 | .clk_id = {CLK_NONE}, | |
703 | }, | |
704 | [MT6797_POWER_DOMAIN_MM] = { | |
705 | .name = "mm", | |
706 | .sta_mask = BIT(3), | |
707 | .ctl_offs = 0x30C, | |
708 | .sram_pdn_bits = GENMASK(8, 8), | |
709 | .sram_pdn_ack_bits = GENMASK(12, 12), | |
710 | .clk_id = {CLK_MM}, | |
711 | .bus_prot_mask = (BIT(1) | BIT(2)), | |
712 | }, | |
713 | [MT6797_POWER_DOMAIN_AUDIO] = { | |
714 | .name = "audio", | |
715 | .sta_mask = BIT(24), | |
716 | .ctl_offs = 0x314, | |
717 | .sram_pdn_bits = GENMASK(11, 8), | |
718 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
719 | .clk_id = {CLK_NONE}, | |
720 | }, | |
721 | [MT6797_POWER_DOMAIN_MFG_ASYNC] = { | |
722 | .name = "mfg_async", | |
723 | .sta_mask = BIT(13), | |
724 | .ctl_offs = 0x334, | |
725 | .sram_pdn_bits = 0, | |
726 | .sram_pdn_ack_bits = 0, | |
727 | .clk_id = {CLK_MFG}, | |
728 | }, | |
729 | [MT6797_POWER_DOMAIN_MJC] = { | |
730 | .name = "mjc", | |
731 | .sta_mask = BIT(20), | |
732 | .ctl_offs = 0x310, | |
733 | .sram_pdn_bits = GENMASK(8, 8), | |
734 | .sram_pdn_ack_bits = GENMASK(12, 12), | |
735 | .clk_id = {CLK_NONE}, | |
736 | }, | |
737 | }; | |
738 | ||
36c310f5 MC |
739 | #define SPM_PWR_STATUS_MT6797 0x0180 |
740 | #define SPM_PWR_STATUS_2ND_MT6797 0x0184 | |
741 | ||
53fddb1a SW |
742 | static const struct scp_subdomain scp_subdomain_mt6797[] = { |
743 | {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC}, | |
744 | {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP}, | |
745 | {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC}, | |
746 | {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC}, | |
747 | }; | |
36c310f5 | 748 | |
52510ee9 SW |
749 | /* |
750 | * MT7622 power domain support | |
751 | */ | |
752 | ||
753 | static const struct scp_domain_data scp_domain_data_mt7622[] = { | |
754 | [MT7622_POWER_DOMAIN_ETHSYS] = { | |
755 | .name = "ethsys", | |
756 | .sta_mask = PWR_STATUS_ETHSYS, | |
757 | .ctl_offs = SPM_ETHSYS_PWR_CON, | |
758 | .sram_pdn_bits = GENMASK(11, 8), | |
759 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
760 | .clk_id = {CLK_NONE}, | |
761 | .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS, | |
762 | .active_wakeup = true, | |
763 | }, | |
764 | [MT7622_POWER_DOMAIN_HIF0] = { | |
765 | .name = "hif0", | |
766 | .sta_mask = PWR_STATUS_HIF0, | |
767 | .ctl_offs = SPM_HIF0_PWR_CON, | |
768 | .sram_pdn_bits = GENMASK(11, 8), | |
769 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
770 | .clk_id = {CLK_HIFSEL}, | |
771 | .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0, | |
772 | .active_wakeup = true, | |
773 | }, | |
774 | [MT7622_POWER_DOMAIN_HIF1] = { | |
775 | .name = "hif1", | |
776 | .sta_mask = PWR_STATUS_HIF1, | |
777 | .ctl_offs = SPM_HIF1_PWR_CON, | |
778 | .sram_pdn_bits = GENMASK(11, 8), | |
779 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
780 | .clk_id = {CLK_HIFSEL}, | |
781 | .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1, | |
782 | .active_wakeup = true, | |
783 | }, | |
784 | [MT7622_POWER_DOMAIN_WB] = { | |
785 | .name = "wb", | |
786 | .sta_mask = PWR_STATUS_WB, | |
787 | .ctl_offs = SPM_WB_PWR_CON, | |
788 | .sram_pdn_bits = 0, | |
789 | .sram_pdn_ack_bits = 0, | |
790 | .clk_id = {CLK_NONE}, | |
791 | .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB, | |
792 | .active_wakeup = true, | |
793 | }, | |
794 | }; | |
795 | ||
6078c651 JL |
796 | /* |
797 | * MT8173 power domain support | |
798 | */ | |
799 | ||
800 | static const struct scp_domain_data scp_domain_data_mt8173[] = { | |
801 | [MT8173_POWER_DOMAIN_VDEC] = { | |
802 | .name = "vdec", | |
803 | .sta_mask = PWR_STATUS_VDEC, | |
804 | .ctl_offs = SPM_VDE_PWR_CON, | |
805 | .sram_pdn_bits = GENMASK(11, 8), | |
806 | .sram_pdn_ack_bits = GENMASK(12, 12), | |
807 | .clk_id = {CLK_MM}, | |
808 | }, | |
809 | [MT8173_POWER_DOMAIN_VENC] = { | |
810 | .name = "venc", | |
811 | .sta_mask = PWR_STATUS_VENC, | |
812 | .ctl_offs = SPM_VEN_PWR_CON, | |
813 | .sram_pdn_bits = GENMASK(11, 8), | |
814 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
815 | .clk_id = {CLK_MM, CLK_VENC}, | |
816 | }, | |
817 | [MT8173_POWER_DOMAIN_ISP] = { | |
818 | .name = "isp", | |
819 | .sta_mask = PWR_STATUS_ISP, | |
820 | .ctl_offs = SPM_ISP_PWR_CON, | |
821 | .sram_pdn_bits = GENMASK(11, 8), | |
822 | .sram_pdn_ack_bits = GENMASK(13, 12), | |
823 | .clk_id = {CLK_MM}, | |
824 | }, | |
825 | [MT8173_POWER_DOMAIN_MM] = { | |
826 | .name = "mm", | |
827 | .sta_mask = PWR_STATUS_DISP, | |
828 | .ctl_offs = SPM_DIS_PWR_CON, | |
829 | .sram_pdn_bits = GENMASK(11, 8), | |
830 | .sram_pdn_ack_bits = GENMASK(12, 12), | |
831 | .clk_id = {CLK_MM}, | |
832 | .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | | |
833 | MT8173_TOP_AXI_PROT_EN_MM_M1, | |
834 | }, | |
835 | [MT8173_POWER_DOMAIN_VENC_LT] = { | |
836 | .name = "venc_lt", | |
837 | .sta_mask = PWR_STATUS_VENC_LT, | |
838 | .ctl_offs = SPM_VEN2_PWR_CON, | |
839 | .sram_pdn_bits = GENMASK(11, 8), | |
840 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
841 | .clk_id = {CLK_MM, CLK_VENC_LT}, | |
842 | }, | |
843 | [MT8173_POWER_DOMAIN_AUDIO] = { | |
844 | .name = "audio", | |
845 | .sta_mask = PWR_STATUS_AUDIO, | |
846 | .ctl_offs = SPM_AUDIO_PWR_CON, | |
847 | .sram_pdn_bits = GENMASK(11, 8), | |
848 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
849 | .clk_id = {CLK_NONE}, | |
850 | }, | |
851 | [MT8173_POWER_DOMAIN_USB] = { | |
852 | .name = "usb", | |
853 | .sta_mask = PWR_STATUS_USB, | |
854 | .ctl_offs = SPM_USB_PWR_CON, | |
855 | .sram_pdn_bits = GENMASK(11, 8), | |
856 | .sram_pdn_ack_bits = GENMASK(15, 12), | |
857 | .clk_id = {CLK_NONE}, | |
858 | .active_wakeup = true, | |
859 | }, | |
860 | [MT8173_POWER_DOMAIN_MFG_ASYNC] = { | |
861 | .name = "mfg_async", | |
862 | .sta_mask = PWR_STATUS_MFG_ASYNC, | |
863 | .ctl_offs = SPM_MFG_ASYNC_PWR_CON, | |
864 | .sram_pdn_bits = GENMASK(11, 8), | |
865 | .sram_pdn_ack_bits = 0, | |
866 | .clk_id = {CLK_MFG}, | |
867 | }, | |
868 | [MT8173_POWER_DOMAIN_MFG_2D] = { | |
869 | .name = "mfg_2d", | |
870 | .sta_mask = PWR_STATUS_MFG_2D, | |
871 | .ctl_offs = SPM_MFG_2D_PWR_CON, | |
872 | .sram_pdn_bits = GENMASK(11, 8), | |
873 | .sram_pdn_ack_bits = GENMASK(13, 12), | |
874 | .clk_id = {CLK_NONE}, | |
875 | }, | |
876 | [MT8173_POWER_DOMAIN_MFG] = { | |
877 | .name = "mfg", | |
878 | .sta_mask = PWR_STATUS_MFG, | |
879 | .ctl_offs = SPM_MFG_PWR_CON, | |
880 | .sram_pdn_bits = GENMASK(13, 8), | |
881 | .sram_pdn_ack_bits = GENMASK(21, 16), | |
882 | .clk_id = {CLK_NONE}, | |
883 | .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | | |
884 | MT8173_TOP_AXI_PROT_EN_MFG_M0 | | |
885 | MT8173_TOP_AXI_PROT_EN_MFG_M1 | | |
886 | MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, | |
887 | }, | |
888 | }; | |
889 | ||
53fddb1a SW |
890 | static const struct scp_subdomain scp_subdomain_mt8173[] = { |
891 | {MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D}, | |
892 | {MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG}, | |
893 | }; | |
6078c651 | 894 | |
53fddb1a SW |
895 | static const struct scp_soc_data mt2701_data = { |
896 | .domains = scp_domain_data_mt2701, | |
897 | .num_domains = ARRAY_SIZE(scp_domain_data_mt2701), | |
898 | .regs = { | |
899 | .pwr_sta_offs = SPM_PWR_STATUS, | |
900 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND | |
fa7e843a | 901 | }, |
902 | .bus_prot_reg_update = true, | |
53fddb1a | 903 | }; |
c84e3587 | 904 | |
320f4ced | 905 | static const struct scp_soc_data mt2712_data = { |
906 | .domains = scp_domain_data_mt2712, | |
907 | .num_domains = ARRAY_SIZE(scp_domain_data_mt2712), | |
908 | .regs = { | |
909 | .pwr_sta_offs = SPM_PWR_STATUS, | |
910 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND | |
911 | }, | |
912 | .bus_prot_reg_update = false, | |
913 | }; | |
914 | ||
53fddb1a SW |
915 | static const struct scp_soc_data mt6797_data = { |
916 | .domains = scp_domain_data_mt6797, | |
917 | .num_domains = ARRAY_SIZE(scp_domain_data_mt6797), | |
918 | .subdomains = scp_subdomain_mt6797, | |
919 | .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797), | |
920 | .regs = { | |
921 | .pwr_sta_offs = SPM_PWR_STATUS_MT6797, | |
922 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797 | |
fa7e843a | 923 | }, |
924 | .bus_prot_reg_update = true, | |
53fddb1a | 925 | }; |
c84e3587 | 926 | |
52510ee9 SW |
927 | static const struct scp_soc_data mt7622_data = { |
928 | .domains = scp_domain_data_mt7622, | |
929 | .num_domains = ARRAY_SIZE(scp_domain_data_mt7622), | |
930 | .regs = { | |
931 | .pwr_sta_offs = SPM_PWR_STATUS, | |
932 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND | |
fa7e843a | 933 | }, |
934 | .bus_prot_reg_update = true, | |
52510ee9 SW |
935 | }; |
936 | ||
53fddb1a SW |
937 | static const struct scp_soc_data mt8173_data = { |
938 | .domains = scp_domain_data_mt8173, | |
939 | .num_domains = ARRAY_SIZE(scp_domain_data_mt8173), | |
940 | .subdomains = scp_subdomain_mt8173, | |
941 | .num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173), | |
942 | .regs = { | |
943 | .pwr_sta_offs = SPM_PWR_STATUS, | |
944 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND | |
fa7e843a | 945 | }, |
946 | .bus_prot_reg_update = true, | |
53fddb1a | 947 | }; |
c84e3587 | 948 | |
6078c651 JL |
949 | /* |
950 | * scpsys driver init | |
951 | */ | |
952 | ||
c84e3587 SH |
953 | static const struct of_device_id of_scpsys_match_tbl[] = { |
954 | { | |
112ef188 | 955 | .compatible = "mediatek,mt2701-scpsys", |
53fddb1a | 956 | .data = &mt2701_data, |
320f4ced | 957 | }, { |
958 | .compatible = "mediatek,mt2712-scpsys", | |
959 | .data = &mt2712_data, | |
36c310f5 MC |
960 | }, { |
961 | .compatible = "mediatek,mt6797-scpsys", | |
53fddb1a | 962 | .data = &mt6797_data, |
52510ee9 SW |
963 | }, { |
964 | .compatible = "mediatek,mt7622-scpsys", | |
965 | .data = &mt7622_data, | |
112ef188 | 966 | }, { |
c84e3587 | 967 | .compatible = "mediatek,mt8173-scpsys", |
53fddb1a | 968 | .data = &mt8173_data, |
c84e3587 SH |
969 | }, { |
970 | /* sentinel */ | |
971 | } | |
972 | }; | |
973 | ||
6078c651 JL |
974 | static int scpsys_probe(struct platform_device *pdev) |
975 | { | |
53fddb1a SW |
976 | const struct of_device_id *match; |
977 | const struct scp_subdomain *sd; | |
978 | const struct scp_soc_data *soc; | |
979 | struct scp *scp; | |
980 | struct genpd_onecell_data *pd_data; | |
981 | int i, ret; | |
6078c651 | 982 | |
53fddb1a SW |
983 | match = of_match_device(of_scpsys_match_tbl, &pdev->dev); |
984 | soc = (const struct scp_soc_data *)match->data; | |
6078c651 | 985 | |
fa7e843a | 986 | scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs, |
987 | soc->bus_prot_reg_update); | |
53fddb1a SW |
988 | if (IS_ERR(scp)) |
989 | return PTR_ERR(scp); | |
990 | ||
991 | mtk_register_power_domains(pdev, scp, soc->num_domains); | |
992 | ||
993 | pd_data = &scp->pd_data; | |
994 | ||
995 | for (i = 0, sd = soc->subdomains ; i < soc->num_subdomains ; i++) { | |
996 | ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin], | |
997 | pd_data->domains[sd->subdomain]); | |
998 | if (ret && IS_ENABLED(CONFIG_PM)) | |
999 | dev_err(&pdev->dev, "Failed to add subdomain: %d\n", | |
1000 | ret); | |
1001 | } | |
6078c651 | 1002 | |
53fddb1a | 1003 | return 0; |
6078c651 JL |
1004 | } |
1005 | ||
c84e3587 | 1006 | static struct platform_driver scpsys_drv = { |
be29523d | 1007 | .probe = scpsys_probe, |
c84e3587 SH |
1008 | .driver = { |
1009 | .name = "mtk-scpsys", | |
be29523d | 1010 | .suppress_bind_attrs = true, |
c84e3587 SH |
1011 | .owner = THIS_MODULE, |
1012 | .of_match_table = of_match_ptr(of_scpsys_match_tbl), | |
1013 | }, | |
1014 | }; | |
be29523d | 1015 | builtin_platform_driver(scpsys_drv); |