]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/soc/mediatek/mtk-scpsys.c
soc: mediatek: avoid using fixed spm power status defines
[mirror_ubuntu-hirsute-kernel.git] / drivers / soc / mediatek / mtk-scpsys.c
CommitLineData
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>
c84e3587
SH
24#include <dt-bindings/power/mt8173-power.h>
25
26#define SPM_VDE_PWR_CON 0x0210
27#define SPM_MFG_PWR_CON 0x0214
28#define SPM_VEN_PWR_CON 0x0230
29#define SPM_ISP_PWR_CON 0x0238
30#define SPM_DIS_PWR_CON 0x023c
112ef188 31#define SPM_CONN_PWR_CON 0x0280
c84e3587 32#define SPM_VEN2_PWR_CON 0x0298
112ef188
SW
33#define SPM_AUDIO_PWR_CON 0x029c /* MT8173 */
34#define SPM_BDP_PWR_CON 0x029c /* MT2701 */
35#define SPM_ETH_PWR_CON 0x02a0
36#define SPM_HIF_PWR_CON 0x02a4
37#define SPM_IFR_MSC_PWR_CON 0x02a8
c84e3587
SH
38#define SPM_MFG_2D_PWR_CON 0x02c0
39#define SPM_MFG_ASYNC_PWR_CON 0x02c4
40#define SPM_USB_PWR_CON 0x02cc
6078c651 41
c84e3587
SH
42#define SPM_PWR_STATUS 0x060c
43#define SPM_PWR_STATUS_2ND 0x0610
44
45#define PWR_RST_B_BIT BIT(0)
46#define PWR_ISO_BIT BIT(1)
47#define PWR_ON_BIT BIT(2)
48#define PWR_ON_2ND_BIT BIT(3)
49#define PWR_CLK_DIS_BIT BIT(4)
50
112ef188 51#define PWR_STATUS_CONN BIT(1)
c84e3587
SH
52#define PWR_STATUS_DISP BIT(3)
53#define PWR_STATUS_MFG BIT(4)
54#define PWR_STATUS_ISP BIT(5)
55#define PWR_STATUS_VDEC BIT(7)
112ef188
SW
56#define PWR_STATUS_BDP BIT(14)
57#define PWR_STATUS_ETH BIT(15)
58#define PWR_STATUS_HIF BIT(16)
59#define PWR_STATUS_IFR_MSC BIT(17)
c84e3587
SH
60#define PWR_STATUS_VENC_LT BIT(20)
61#define PWR_STATUS_VENC BIT(21)
62#define PWR_STATUS_MFG_2D BIT(22)
63#define PWR_STATUS_MFG_ASYNC BIT(23)
64#define PWR_STATUS_AUDIO BIT(24)
65#define PWR_STATUS_USB BIT(25)
66
67enum clk_id {
6078c651
JL
68 CLK_NONE,
69 CLK_MM,
70 CLK_MFG,
71 CLK_VENC,
72 CLK_VENC_LT,
112ef188 73 CLK_ETHIF,
6078c651
JL
74 CLK_MAX,
75};
76
77static const char * const clk_names[] = {
78 NULL,
79 "mm",
80 "mfg",
81 "venc",
82 "venc_lt",
112ef188 83 "ethif",
6078c651 84 NULL,
c84e3587
SH
85};
86
41b3e0f0
JL
87#define MAX_CLKS 2
88
c84e3587
SH
89struct scp_domain_data {
90 const char *name;
91 u32 sta_mask;
92 int ctl_offs;
93 u32 sram_pdn_bits;
94 u32 sram_pdn_ack_bits;
95 u32 bus_prot_mask;
41b3e0f0 96 enum clk_id clk_id[MAX_CLKS];
47e90154 97 bool active_wakeup;
c84e3587
SH
98};
99
c84e3587
SH
100struct scp;
101
102struct scp_domain {
103 struct generic_pm_domain genpd;
104 struct scp *scp;
41b3e0f0 105 struct clk *clk[MAX_CLKS];
be29523d 106 const struct scp_domain_data *data;
4688f385 107 struct regulator *supply;
c84e3587
SH
108};
109
f1be4c4e
MC
110struct scp_ctrl_reg {
111 int pwr_sta_offs;
112 int pwr_sta2nd_offs;
113};
114
c84e3587 115struct scp {
6078c651 116 struct scp_domain *domains;
c84e3587
SH
117 struct genpd_onecell_data pd_data;
118 struct device *dev;
119 void __iomem *base;
120 struct regmap *infracfg;
f1be4c4e 121 struct scp_ctrl_reg ctrl_reg;
c84e3587
SH
122};
123
124static int scpsys_domain_is_on(struct scp_domain *scpd)
125{
126 struct scp *scp = scpd->scp;
127
f1be4c4e
MC
128 u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) &
129 scpd->data->sta_mask;
130 u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) &
131 scpd->data->sta_mask;
c84e3587
SH
132
133 /*
134 * A domain is on when both status bits are set. If only one is set
135 * return an error. This happens while powering up a domain
136 */
137
138 if (status && status2)
139 return true;
140 if (!status && !status2)
141 return false;
142
143 return -EINVAL;
144}
145
146static int scpsys_power_on(struct generic_pm_domain *genpd)
147{
148 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
149 struct scp *scp = scpd->scp;
150 unsigned long timeout;
151 bool expired;
be29523d
MB
152 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
153 u32 sram_pdn_ack = scpd->data->sram_pdn_ack_bits;
c84e3587
SH
154 u32 val;
155 int ret;
41b3e0f0
JL
156 int i;
157
4688f385
SH
158 if (scpd->supply) {
159 ret = regulator_enable(scpd->supply);
160 if (ret)
161 return ret;
162 }
163
41b3e0f0
JL
164 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) {
165 ret = clk_prepare_enable(scpd->clk[i]);
166 if (ret) {
167 for (--i; i >= 0; i--)
168 clk_disable_unprepare(scpd->clk[i]);
c84e3587 169
c84e3587 170 goto err_clk;
41b3e0f0 171 }
c84e3587
SH
172 }
173
174 val = readl(ctl_addr);
175 val |= PWR_ON_BIT;
176 writel(val, ctl_addr);
177 val |= PWR_ON_2ND_BIT;
178 writel(val, ctl_addr);
179
180 /* wait until PWR_ACK = 1 */
181 timeout = jiffies + HZ;
182 expired = false;
183 while (1) {
184 ret = scpsys_domain_is_on(scpd);
185 if (ret > 0)
186 break;
187
188 if (expired) {
189 ret = -ETIMEDOUT;
190 goto err_pwr_ack;
191 }
192
193 cpu_relax();
194
195 if (time_after(jiffies, timeout))
196 expired = true;
197 }
198
199 val &= ~PWR_CLK_DIS_BIT;
200 writel(val, ctl_addr);
201
202 val &= ~PWR_ISO_BIT;
203 writel(val, ctl_addr);
204
205 val |= PWR_RST_B_BIT;
206 writel(val, ctl_addr);
207
be29523d 208 val &= ~scpd->data->sram_pdn_bits;
c84e3587
SH
209 writel(val, ctl_addr);
210
211 /* wait until SRAM_PDN_ACK all 0 */
212 timeout = jiffies + HZ;
213 expired = false;
214 while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) {
215
216 if (expired) {
217 ret = -ETIMEDOUT;
218 goto err_pwr_ack;
219 }
220
221 cpu_relax();
222
223 if (time_after(jiffies, timeout))
224 expired = true;
225 }
226
be29523d 227 if (scpd->data->bus_prot_mask) {
c84e3587 228 ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
be29523d 229 scpd->data->bus_prot_mask);
c84e3587
SH
230 if (ret)
231 goto err_pwr_ack;
232 }
233
234 return 0;
235
236err_pwr_ack:
41b3e0f0
JL
237 for (i = MAX_CLKS - 1; i >= 0; i--) {
238 if (scpd->clk[i])
239 clk_disable_unprepare(scpd->clk[i]);
240 }
c84e3587 241err_clk:
4688f385
SH
242 if (scpd->supply)
243 regulator_disable(scpd->supply);
244
c84e3587
SH
245 dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
246
247 return ret;
248}
249
250static int scpsys_power_off(struct generic_pm_domain *genpd)
251{
252 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
253 struct scp *scp = scpd->scp;
254 unsigned long timeout;
255 bool expired;
be29523d
MB
256 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
257 u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
c84e3587
SH
258 u32 val;
259 int ret;
41b3e0f0 260 int i;
c84e3587 261
be29523d 262 if (scpd->data->bus_prot_mask) {
c84e3587 263 ret = mtk_infracfg_set_bus_protection(scp->infracfg,
be29523d 264 scpd->data->bus_prot_mask);
c84e3587
SH
265 if (ret)
266 goto out;
267 }
268
269 val = readl(ctl_addr);
be29523d 270 val |= scpd->data->sram_pdn_bits;
c84e3587
SH
271 writel(val, ctl_addr);
272
273 /* wait until SRAM_PDN_ACK all 1 */
274 timeout = jiffies + HZ;
275 expired = false;
276 while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) {
277 if (expired) {
278 ret = -ETIMEDOUT;
279 goto out;
280 }
281
282 cpu_relax();
283
284 if (time_after(jiffies, timeout))
285 expired = true;
286 }
287
288 val |= PWR_ISO_BIT;
289 writel(val, ctl_addr);
290
291 val &= ~PWR_RST_B_BIT;
292 writel(val, ctl_addr);
293
294 val |= PWR_CLK_DIS_BIT;
295 writel(val, ctl_addr);
296
297 val &= ~PWR_ON_BIT;
298 writel(val, ctl_addr);
299
300 val &= ~PWR_ON_2ND_BIT;
301 writel(val, ctl_addr);
302
303 /* wait until PWR_ACK = 0 */
304 timeout = jiffies + HZ;
305 expired = false;
306 while (1) {
307 ret = scpsys_domain_is_on(scpd);
308 if (ret == 0)
309 break;
310
311 if (expired) {
312 ret = -ETIMEDOUT;
313 goto out;
314 }
315
316 cpu_relax();
317
318 if (time_after(jiffies, timeout))
319 expired = true;
320 }
321
41b3e0f0
JL
322 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
323 clk_disable_unprepare(scpd->clk[i]);
c84e3587 324
4688f385
SH
325 if (scpd->supply)
326 regulator_disable(scpd->supply);
327
c84e3587
SH
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
47e90154
EH
336static bool scpsys_active_wakeup(struct device *dev)
337{
338 struct generic_pm_domain *genpd;
339 struct scp_domain *scpd;
340
341 genpd = pd_to_genpd(dev->pm_domain);
342 scpd = container_of(genpd, struct scp_domain, genpd);
343
be29523d 344 return scpd->data->active_wakeup;
47e90154
EH
345}
346
6078c651
JL
347static void init_clks(struct platform_device *pdev, struct clk **clk)
348{
349 int i;
350
351 for (i = CLK_NONE + 1; i < CLK_MAX; i++)
352 clk[i] = devm_clk_get(&pdev->dev, clk_names[i]);
353}
354
355static struct scp *init_scp(struct platform_device *pdev,
f1be4c4e
MC
356 const struct scp_domain_data *scp_domain_data, int num,
357 struct scp_ctrl_reg *scp_ctrl_reg)
c84e3587
SH
358{
359 struct genpd_onecell_data *pd_data;
360 struct resource *res;
6078c651 361 int i, j;
c84e3587 362 struct scp *scp;
6078c651 363 struct clk *clk[CLK_MAX];
c84e3587
SH
364
365 scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
366 if (!scp)
6078c651 367 return ERR_PTR(-ENOMEM);
c84e3587 368
f1be4c4e
MC
369 scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
370 scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
371
c84e3587
SH
372 scp->dev = &pdev->dev;
373
374 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
375 scp->base = devm_ioremap_resource(&pdev->dev, res);
376 if (IS_ERR(scp->base))
6078c651
JL
377 return ERR_CAST(scp->base);
378
379 scp->domains = devm_kzalloc(&pdev->dev,
380 sizeof(*scp->domains) * num, GFP_KERNEL);
381 if (!scp->domains)
382 return ERR_PTR(-ENOMEM);
c84e3587
SH
383
384 pd_data = &scp->pd_data;
385
386 pd_data->domains = devm_kzalloc(&pdev->dev,
6078c651 387 sizeof(*pd_data->domains) * num, GFP_KERNEL);
c84e3587 388 if (!pd_data->domains)
6078c651 389 return ERR_PTR(-ENOMEM);
41b3e0f0 390
c84e3587
SH
391 scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
392 "infracfg");
393 if (IS_ERR(scp->infracfg)) {
394 dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
395 PTR_ERR(scp->infracfg));
6078c651 396 return ERR_CAST(scp->infracfg);
c84e3587
SH
397 }
398
6078c651 399 for (i = 0; i < num; i++) {
4688f385
SH
400 struct scp_domain *scpd = &scp->domains[i];
401 const struct scp_domain_data *data = &scp_domain_data[i];
402
403 scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name);
404 if (IS_ERR(scpd->supply)) {
405 if (PTR_ERR(scpd->supply) == -ENODEV)
406 scpd->supply = NULL;
407 else
6078c651 408 return ERR_CAST(scpd->supply);
4688f385
SH
409 }
410 }
411
6078c651 412 pd_data->num_domains = num;
c84e3587 413
6078c651
JL
414 init_clks(pdev, clk);
415
416 for (i = 0; i < num; i++) {
c84e3587
SH
417 struct scp_domain *scpd = &scp->domains[i];
418 struct generic_pm_domain *genpd = &scpd->genpd;
419 const struct scp_domain_data *data = &scp_domain_data[i];
420
421 pd_data->domains[i] = genpd;
422 scpd->scp = scp;
423
be29523d 424 scpd->data = data;
6078c651
JL
425
426 for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
427 struct clk *c = clk[data->clk_id[j]];
428
429 if (IS_ERR(c)) {
430 dev_err(&pdev->dev, "%s: clk unavailable\n",
431 data->name);
432 return ERR_CAST(c);
433 }
434
435 scpd->clk[j] = c;
436 }
c84e3587
SH
437
438 genpd->name = data->name;
439 genpd->power_off = scpsys_power_off;
440 genpd->power_on = scpsys_power_on;
47e90154 441 genpd->dev_ops.active_wakeup = scpsys_active_wakeup;
6078c651
JL
442 }
443
444 return scp;
445}
446
447static void mtk_register_power_domains(struct platform_device *pdev,
448 struct scp *scp, int num)
449{
450 struct genpd_onecell_data *pd_data;
451 int i, ret;
452
453 for (i = 0; i < num; i++) {
454 struct scp_domain *scpd = &scp->domains[i];
455 struct generic_pm_domain *genpd = &scpd->genpd;
c84e3587
SH
456
457 /*
d9c9f3b8
JL
458 * Initially turn on all domains to make the domains usable
459 * with !CONFIG_PM and to get the hardware in sync with the
460 * software. The unused domains will be switched off during
461 * late_init time.
c84e3587 462 */
d9c9f3b8 463 genpd->power_on(genpd);
c84e3587 464
d9c9f3b8 465 pm_genpd_init(genpd, NULL, false);
c84e3587
SH
466 }
467
468 /*
469 * We are not allowed to fail here since there is no way to unregister
470 * a power domain. Once registered above we have to keep the domains
471 * valid.
472 */
473
6078c651
JL
474 pd_data = &scp->pd_data;
475
476 ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
477 if (ret)
478 dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
479}
480
112ef188
SW
481/*
482 * MT2701 power domain support
483 */
484
485static const struct scp_domain_data scp_domain_data_mt2701[] = {
486 [MT2701_POWER_DOMAIN_CONN] = {
487 .name = "conn",
488 .sta_mask = PWR_STATUS_CONN,
489 .ctl_offs = SPM_CONN_PWR_CON,
490 .bus_prot_mask = 0x0104,
491 .clk_id = {CLK_NONE},
492 .active_wakeup = true,
493 },
494 [MT2701_POWER_DOMAIN_DISP] = {
495 .name = "disp",
496 .sta_mask = PWR_STATUS_DISP,
497 .ctl_offs = SPM_DIS_PWR_CON,
498 .sram_pdn_bits = GENMASK(11, 8),
499 .clk_id = {CLK_MM},
500 .bus_prot_mask = 0x0002,
501 .active_wakeup = true,
502 },
503 [MT2701_POWER_DOMAIN_MFG] = {
504 .name = "mfg",
505 .sta_mask = PWR_STATUS_MFG,
506 .ctl_offs = SPM_MFG_PWR_CON,
507 .sram_pdn_bits = GENMASK(11, 8),
508 .sram_pdn_ack_bits = GENMASK(12, 12),
509 .clk_id = {CLK_MFG},
510 .active_wakeup = true,
511 },
512 [MT2701_POWER_DOMAIN_VDEC] = {
513 .name = "vdec",
514 .sta_mask = PWR_STATUS_VDEC,
515 .ctl_offs = SPM_VDE_PWR_CON,
516 .sram_pdn_bits = GENMASK(11, 8),
517 .sram_pdn_ack_bits = GENMASK(12, 12),
518 .clk_id = {CLK_MM},
519 .active_wakeup = true,
520 },
521 [MT2701_POWER_DOMAIN_ISP] = {
522 .name = "isp",
523 .sta_mask = PWR_STATUS_ISP,
524 .ctl_offs = SPM_ISP_PWR_CON,
525 .sram_pdn_bits = GENMASK(11, 8),
526 .sram_pdn_ack_bits = GENMASK(13, 12),
527 .clk_id = {CLK_MM},
528 .active_wakeup = true,
529 },
530 [MT2701_POWER_DOMAIN_BDP] = {
531 .name = "bdp",
532 .sta_mask = PWR_STATUS_BDP,
533 .ctl_offs = SPM_BDP_PWR_CON,
534 .sram_pdn_bits = GENMASK(11, 8),
535 .clk_id = {CLK_NONE},
536 .active_wakeup = true,
537 },
538 [MT2701_POWER_DOMAIN_ETH] = {
539 .name = "eth",
540 .sta_mask = PWR_STATUS_ETH,
541 .ctl_offs = SPM_ETH_PWR_CON,
542 .sram_pdn_bits = GENMASK(11, 8),
543 .sram_pdn_ack_bits = GENMASK(15, 12),
544 .clk_id = {CLK_ETHIF},
545 .active_wakeup = true,
546 },
547 [MT2701_POWER_DOMAIN_HIF] = {
548 .name = "hif",
549 .sta_mask = PWR_STATUS_HIF,
550 .ctl_offs = SPM_HIF_PWR_CON,
551 .sram_pdn_bits = GENMASK(11, 8),
552 .sram_pdn_ack_bits = GENMASK(15, 12),
553 .clk_id = {CLK_ETHIF},
554 .active_wakeup = true,
555 },
556 [MT2701_POWER_DOMAIN_IFR_MSC] = {
557 .name = "ifr_msc",
558 .sta_mask = PWR_STATUS_IFR_MSC,
559 .ctl_offs = SPM_IFR_MSC_PWR_CON,
560 .clk_id = {CLK_NONE},
561 .active_wakeup = true,
562 },
563};
564
565#define NUM_DOMAINS_MT2701 ARRAY_SIZE(scp_domain_data_mt2701)
566
567static int __init scpsys_probe_mt2701(struct platform_device *pdev)
568{
569 struct scp *scp;
f1be4c4e 570 struct scp_ctrl_reg scp_reg;
112ef188 571
f1be4c4e
MC
572 scp_reg.pwr_sta_offs = SPM_PWR_STATUS;
573 scp_reg.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND;
574
575 scp = init_scp(pdev, scp_domain_data_mt2701, NUM_DOMAINS_MT2701,
576 &scp_reg);
112ef188
SW
577 if (IS_ERR(scp))
578 return PTR_ERR(scp);
579
580 mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT2701);
581
582 return 0;
583}
584
6078c651
JL
585/*
586 * MT8173 power domain support
587 */
588
589static const struct scp_domain_data scp_domain_data_mt8173[] = {
590 [MT8173_POWER_DOMAIN_VDEC] = {
591 .name = "vdec",
592 .sta_mask = PWR_STATUS_VDEC,
593 .ctl_offs = SPM_VDE_PWR_CON,
594 .sram_pdn_bits = GENMASK(11, 8),
595 .sram_pdn_ack_bits = GENMASK(12, 12),
596 .clk_id = {CLK_MM},
597 },
598 [MT8173_POWER_DOMAIN_VENC] = {
599 .name = "venc",
600 .sta_mask = PWR_STATUS_VENC,
601 .ctl_offs = SPM_VEN_PWR_CON,
602 .sram_pdn_bits = GENMASK(11, 8),
603 .sram_pdn_ack_bits = GENMASK(15, 12),
604 .clk_id = {CLK_MM, CLK_VENC},
605 },
606 [MT8173_POWER_DOMAIN_ISP] = {
607 .name = "isp",
608 .sta_mask = PWR_STATUS_ISP,
609 .ctl_offs = SPM_ISP_PWR_CON,
610 .sram_pdn_bits = GENMASK(11, 8),
611 .sram_pdn_ack_bits = GENMASK(13, 12),
612 .clk_id = {CLK_MM},
613 },
614 [MT8173_POWER_DOMAIN_MM] = {
615 .name = "mm",
616 .sta_mask = PWR_STATUS_DISP,
617 .ctl_offs = SPM_DIS_PWR_CON,
618 .sram_pdn_bits = GENMASK(11, 8),
619 .sram_pdn_ack_bits = GENMASK(12, 12),
620 .clk_id = {CLK_MM},
621 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
622 MT8173_TOP_AXI_PROT_EN_MM_M1,
623 },
624 [MT8173_POWER_DOMAIN_VENC_LT] = {
625 .name = "venc_lt",
626 .sta_mask = PWR_STATUS_VENC_LT,
627 .ctl_offs = SPM_VEN2_PWR_CON,
628 .sram_pdn_bits = GENMASK(11, 8),
629 .sram_pdn_ack_bits = GENMASK(15, 12),
630 .clk_id = {CLK_MM, CLK_VENC_LT},
631 },
632 [MT8173_POWER_DOMAIN_AUDIO] = {
633 .name = "audio",
634 .sta_mask = PWR_STATUS_AUDIO,
635 .ctl_offs = SPM_AUDIO_PWR_CON,
636 .sram_pdn_bits = GENMASK(11, 8),
637 .sram_pdn_ack_bits = GENMASK(15, 12),
638 .clk_id = {CLK_NONE},
639 },
640 [MT8173_POWER_DOMAIN_USB] = {
641 .name = "usb",
642 .sta_mask = PWR_STATUS_USB,
643 .ctl_offs = SPM_USB_PWR_CON,
644 .sram_pdn_bits = GENMASK(11, 8),
645 .sram_pdn_ack_bits = GENMASK(15, 12),
646 .clk_id = {CLK_NONE},
647 .active_wakeup = true,
648 },
649 [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
650 .name = "mfg_async",
651 .sta_mask = PWR_STATUS_MFG_ASYNC,
652 .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
653 .sram_pdn_bits = GENMASK(11, 8),
654 .sram_pdn_ack_bits = 0,
655 .clk_id = {CLK_MFG},
656 },
657 [MT8173_POWER_DOMAIN_MFG_2D] = {
658 .name = "mfg_2d",
659 .sta_mask = PWR_STATUS_MFG_2D,
660 .ctl_offs = SPM_MFG_2D_PWR_CON,
661 .sram_pdn_bits = GENMASK(11, 8),
662 .sram_pdn_ack_bits = GENMASK(13, 12),
663 .clk_id = {CLK_NONE},
664 },
665 [MT8173_POWER_DOMAIN_MFG] = {
666 .name = "mfg",
667 .sta_mask = PWR_STATUS_MFG,
668 .ctl_offs = SPM_MFG_PWR_CON,
669 .sram_pdn_bits = GENMASK(13, 8),
670 .sram_pdn_ack_bits = GENMASK(21, 16),
671 .clk_id = {CLK_NONE},
672 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
673 MT8173_TOP_AXI_PROT_EN_MFG_M0 |
674 MT8173_TOP_AXI_PROT_EN_MFG_M1 |
675 MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
676 },
677};
678
679#define NUM_DOMAINS_MT8173 ARRAY_SIZE(scp_domain_data_mt8173)
680
681static int __init scpsys_probe_mt8173(struct platform_device *pdev)
682{
683 struct scp *scp;
684 struct genpd_onecell_data *pd_data;
685 int ret;
f1be4c4e
MC
686 struct scp_ctrl_reg scp_reg;
687
688 scp_reg.pwr_sta_offs = SPM_PWR_STATUS;
689 scp_reg.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND;
6078c651 690
f1be4c4e
MC
691 scp = init_scp(pdev, scp_domain_data_mt8173, NUM_DOMAINS_MT8173,
692 &scp_reg);
6078c651
JL
693 if (IS_ERR(scp))
694 return PTR_ERR(scp);
695
696 mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT8173);
697
698 pd_data = &scp->pd_data;
699
c84e3587
SH
700 ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC],
701 pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]);
702 if (ret && IS_ENABLED(CONFIG_PM))
703 dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
704
705 ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D],
706 pd_data->domains[MT8173_POWER_DOMAIN_MFG]);
707 if (ret && IS_ENABLED(CONFIG_PM))
708 dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
709
c84e3587
SH
710 return 0;
711}
712
6078c651
JL
713/*
714 * scpsys driver init
715 */
716
c84e3587
SH
717static const struct of_device_id of_scpsys_match_tbl[] = {
718 {
112ef188
SW
719 .compatible = "mediatek,mt2701-scpsys",
720 .data = scpsys_probe_mt2701,
721 }, {
c84e3587 722 .compatible = "mediatek,mt8173-scpsys",
6078c651 723 .data = scpsys_probe_mt8173,
c84e3587
SH
724 }, {
725 /* sentinel */
726 }
727};
728
6078c651
JL
729static int scpsys_probe(struct platform_device *pdev)
730{
731 int (*probe)(struct platform_device *);
732 const struct of_device_id *of_id;
733
734 of_id = of_match_node(of_scpsys_match_tbl, pdev->dev.of_node);
735 if (!of_id || !of_id->data)
736 return -EINVAL;
737
738 probe = of_id->data;
739
740 return probe(pdev);
741}
742
c84e3587 743static struct platform_driver scpsys_drv = {
be29523d 744 .probe = scpsys_probe,
c84e3587
SH
745 .driver = {
746 .name = "mtk-scpsys",
be29523d 747 .suppress_bind_attrs = true,
c84e3587
SH
748 .owner = THIS_MODULE,
749 .of_match_table = of_match_ptr(of_scpsys_match_tbl),
750 },
751};
be29523d 752builtin_platform_driver(scpsys_drv);