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