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