mtk-scpsys.c 27 KB

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