mtk-pm-domains.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2020 Collabora Ltd.
  4. */
  5. #include <linux/clk.h>
  6. #include <linux/clk-provider.h>
  7. #include <linux/init.h>
  8. #include <linux/io.h>
  9. #include <linux/iopoll.h>
  10. #include <linux/mfd/syscon.h>
  11. #include <linux/of.h>
  12. #include <linux/of_clk.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/pm_domain.h>
  15. #include <linux/regmap.h>
  16. #include <linux/regulator/consumer.h>
  17. #include <linux/soc/mediatek/infracfg.h>
  18. #include "mt6795-pm-domains.h"
  19. #include "mt8167-pm-domains.h"
  20. #include "mt8173-pm-domains.h"
  21. #include "mt8183-pm-domains.h"
  22. #include "mt8186-pm-domains.h"
  23. #include "mt8188-pm-domains.h"
  24. #include "mt8192-pm-domains.h"
  25. #include "mt8195-pm-domains.h"
  26. #include "mt8365-pm-domains.h"
  27. #define MTK_POLL_DELAY_US 10
  28. #define MTK_POLL_TIMEOUT USEC_PER_SEC
  29. #define PWR_RST_B_BIT BIT(0)
  30. #define PWR_ISO_BIT BIT(1)
  31. #define PWR_ON_BIT BIT(2)
  32. #define PWR_ON_2ND_BIT BIT(3)
  33. #define PWR_CLK_DIS_BIT BIT(4)
  34. #define PWR_SRAM_CLKISO_BIT BIT(5)
  35. #define PWR_SRAM_ISOINT_B_BIT BIT(6)
  36. struct scpsys_domain {
  37. struct generic_pm_domain genpd;
  38. const struct scpsys_domain_data *data;
  39. struct scpsys *scpsys;
  40. int num_clks;
  41. struct clk_bulk_data *clks;
  42. int num_subsys_clks;
  43. struct clk_bulk_data *subsys_clks;
  44. struct regmap *infracfg_nao;
  45. struct regmap *infracfg;
  46. struct regmap *smi;
  47. struct regulator *supply;
  48. };
  49. struct scpsys {
  50. struct device *dev;
  51. struct regmap *base;
  52. const struct scpsys_soc_data *soc_data;
  53. struct genpd_onecell_data pd_data;
  54. struct generic_pm_domain *domains[];
  55. };
  56. #define to_scpsys_domain(gpd) container_of(gpd, struct scpsys_domain, genpd)
  57. static bool scpsys_domain_is_on(struct scpsys_domain *pd)
  58. {
  59. struct scpsys *scpsys = pd->scpsys;
  60. u32 status, status2;
  61. regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status);
  62. status &= pd->data->sta_mask;
  63. regmap_read(scpsys->base, pd->data->pwr_sta2nd_offs, &status2);
  64. status2 &= pd->data->sta_mask;
  65. /* A domain is on when both status bits are set. */
  66. return status && status2;
  67. }
  68. static int scpsys_sram_enable(struct scpsys_domain *pd)
  69. {
  70. u32 pdn_ack = pd->data->sram_pdn_ack_bits;
  71. struct scpsys *scpsys = pd->scpsys;
  72. unsigned int tmp;
  73. int ret;
  74. regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
  75. /* Either wait until SRAM_PDN_ACK all 1 or 0 */
  76. ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
  77. (tmp & pdn_ack) == 0, MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
  78. if (ret < 0)
  79. return ret;
  80. if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
  81. regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
  82. udelay(1);
  83. regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
  84. }
  85. return 0;
  86. }
  87. static int scpsys_sram_disable(struct scpsys_domain *pd)
  88. {
  89. u32 pdn_ack = pd->data->sram_pdn_ack_bits;
  90. struct scpsys *scpsys = pd->scpsys;
  91. unsigned int tmp;
  92. if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
  93. regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
  94. udelay(1);
  95. regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
  96. }
  97. regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
  98. /* Either wait until SRAM_PDN_ACK all 1 or 0 */
  99. return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
  100. (tmp & pdn_ack) == pdn_ack, MTK_POLL_DELAY_US,
  101. MTK_POLL_TIMEOUT);
  102. }
  103. static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd,
  104. const struct scpsys_bus_prot_data *bpd)
  105. {
  106. if (bpd->flags & BUS_PROT_COMPONENT_SMI)
  107. return pd->smi;
  108. else
  109. return pd->infracfg;
  110. }
  111. static struct regmap *scpsys_bus_protect_get_sta_regmap(struct scpsys_domain *pd,
  112. const struct scpsys_bus_prot_data *bpd)
  113. {
  114. if (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO)
  115. return pd->infracfg_nao;
  116. else
  117. return scpsys_bus_protect_get_regmap(pd, bpd);
  118. }
  119. static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
  120. const struct scpsys_bus_prot_data *bpd)
  121. {
  122. struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
  123. struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
  124. u32 sta_mask = bpd->bus_prot_sta_mask;
  125. u32 expected_ack;
  126. u32 val;
  127. expected_ack = (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO ? sta_mask : 0);
  128. if (bpd->flags & BUS_PROT_REG_UPDATE)
  129. regmap_clear_bits(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask);
  130. else
  131. regmap_write(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask);
  132. if (bpd->flags & BUS_PROT_IGNORE_CLR_ACK)
  133. return 0;
  134. return regmap_read_poll_timeout(sta_regmap, bpd->bus_prot_sta,
  135. val, (val & sta_mask) == expected_ack,
  136. MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
  137. }
  138. static int scpsys_bus_protect_set(struct scpsys_domain *pd,
  139. const struct scpsys_bus_prot_data *bpd)
  140. {
  141. struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
  142. struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
  143. u32 sta_mask = bpd->bus_prot_sta_mask;
  144. u32 val;
  145. if (bpd->flags & BUS_PROT_REG_UPDATE)
  146. regmap_set_bits(regmap, bpd->bus_prot_set, bpd->bus_prot_set_clr_mask);
  147. else
  148. regmap_write(regmap, bpd->bus_prot_set, bpd->bus_prot_set_clr_mask);
  149. return regmap_read_poll_timeout(sta_regmap, bpd->bus_prot_sta,
  150. val, (val & sta_mask) == sta_mask,
  151. MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
  152. }
  153. static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
  154. {
  155. for (int i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) {
  156. const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i];
  157. int ret;
  158. if (!bpd->bus_prot_set_clr_mask)
  159. break;
  160. if (bpd->flags & BUS_PROT_INVERTED)
  161. ret = scpsys_bus_protect_clear(pd, bpd);
  162. else
  163. ret = scpsys_bus_protect_set(pd, bpd);
  164. if (ret)
  165. return ret;
  166. }
  167. return 0;
  168. }
  169. static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
  170. {
  171. for (int i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) {
  172. const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i];
  173. int ret;
  174. if (!bpd->bus_prot_set_clr_mask)
  175. continue;
  176. if (bpd->flags & BUS_PROT_INVERTED)
  177. ret = scpsys_bus_protect_set(pd, bpd);
  178. else
  179. ret = scpsys_bus_protect_clear(pd, bpd);
  180. if (ret)
  181. return ret;
  182. }
  183. return 0;
  184. }
  185. static int scpsys_regulator_enable(struct regulator *supply)
  186. {
  187. return supply ? regulator_enable(supply) : 0;
  188. }
  189. static int scpsys_regulator_disable(struct regulator *supply)
  190. {
  191. return supply ? regulator_disable(supply) : 0;
  192. }
  193. static int scpsys_power_on(struct generic_pm_domain *genpd)
  194. {
  195. struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
  196. struct scpsys *scpsys = pd->scpsys;
  197. bool tmp;
  198. int ret;
  199. ret = scpsys_regulator_enable(pd->supply);
  200. if (ret)
  201. return ret;
  202. ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks);
  203. if (ret)
  204. goto err_reg;
  205. if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
  206. regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs,
  207. pd->data->ext_buck_iso_mask);
  208. /* subsys power on */
  209. regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
  210. regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
  211. /* wait until PWR_ACK = 1 */
  212. ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US,
  213. MTK_POLL_TIMEOUT);
  214. if (ret < 0)
  215. goto err_pwr_ack;
  216. regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
  217. regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
  218. regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
  219. /*
  220. * In few Mediatek platforms(e.g. MT6779), the bus protect policy is
  221. * stricter, which leads to bus protect release must be prior to bus
  222. * access.
  223. */
  224. if (!MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION)) {
  225. ret = clk_bulk_prepare_enable(pd->num_subsys_clks,
  226. pd->subsys_clks);
  227. if (ret)
  228. goto err_pwr_ack;
  229. }
  230. ret = scpsys_sram_enable(pd);
  231. if (ret < 0)
  232. goto err_disable_subsys_clks;
  233. ret = scpsys_bus_protect_disable(pd);
  234. if (ret < 0)
  235. goto err_disable_sram;
  236. if (MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION)) {
  237. ret = clk_bulk_prepare_enable(pd->num_subsys_clks,
  238. pd->subsys_clks);
  239. if (ret)
  240. goto err_enable_bus_protect;
  241. }
  242. return 0;
  243. err_enable_bus_protect:
  244. scpsys_bus_protect_enable(pd);
  245. err_disable_sram:
  246. scpsys_sram_disable(pd);
  247. err_disable_subsys_clks:
  248. if (!MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION))
  249. clk_bulk_disable_unprepare(pd->num_subsys_clks,
  250. pd->subsys_clks);
  251. err_pwr_ack:
  252. clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
  253. err_reg:
  254. scpsys_regulator_disable(pd->supply);
  255. return ret;
  256. }
  257. static int scpsys_power_off(struct generic_pm_domain *genpd)
  258. {
  259. struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
  260. struct scpsys *scpsys = pd->scpsys;
  261. bool tmp;
  262. int ret;
  263. ret = scpsys_bus_protect_enable(pd);
  264. if (ret < 0)
  265. return ret;
  266. ret = scpsys_sram_disable(pd);
  267. if (ret < 0)
  268. return ret;
  269. if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
  270. regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs,
  271. pd->data->ext_buck_iso_mask);
  272. clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
  273. /* subsys power off */
  274. regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
  275. regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
  276. regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
  277. regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
  278. regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
  279. /* wait until PWR_ACK = 0 */
  280. ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
  281. MTK_POLL_TIMEOUT);
  282. if (ret < 0)
  283. return ret;
  284. clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
  285. scpsys_regulator_disable(pd->supply);
  286. return 0;
  287. }
  288. static struct
  289. generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node)
  290. {
  291. const struct scpsys_domain_data *domain_data;
  292. struct scpsys_domain *pd;
  293. struct device_node *root_node = scpsys->dev->of_node;
  294. struct device_node *smi_node;
  295. struct property *prop;
  296. const char *clk_name;
  297. int i, ret, num_clks;
  298. struct clk *clk;
  299. int clk_ind = 0;
  300. u32 id;
  301. ret = of_property_read_u32(node, "reg", &id);
  302. if (ret) {
  303. dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n",
  304. node, ret);
  305. return ERR_PTR(-EINVAL);
  306. }
  307. if (id >= scpsys->soc_data->num_domains) {
  308. dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id);
  309. return ERR_PTR(-EINVAL);
  310. }
  311. domain_data = &scpsys->soc_data->domains_data[id];
  312. if (domain_data->sta_mask == 0) {
  313. dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id);
  314. return ERR_PTR(-EINVAL);
  315. }
  316. pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL);
  317. if (!pd)
  318. return ERR_PTR(-ENOMEM);
  319. pd->data = domain_data;
  320. pd->scpsys = scpsys;
  321. if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) {
  322. /*
  323. * Find regulator in current power domain node.
  324. * devm_regulator_get() finds regulator in a node and its child
  325. * node, so set of_node to current power domain node then change
  326. * back to original node after regulator is found for current
  327. * power domain node.
  328. */
  329. scpsys->dev->of_node = node;
  330. pd->supply = devm_regulator_get(scpsys->dev, "domain");
  331. scpsys->dev->of_node = root_node;
  332. if (IS_ERR(pd->supply))
  333. return dev_err_cast_probe(scpsys->dev, pd->supply,
  334. "%pOF: failed to get power supply.\n",
  335. node);
  336. }
  337. pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg");
  338. if (IS_ERR(pd->infracfg))
  339. return ERR_CAST(pd->infracfg);
  340. smi_node = of_parse_phandle(node, "mediatek,smi", 0);
  341. if (smi_node) {
  342. pd->smi = device_node_to_regmap(smi_node);
  343. of_node_put(smi_node);
  344. if (IS_ERR(pd->smi))
  345. return ERR_CAST(pd->smi);
  346. }
  347. if (MTK_SCPD_CAPS(pd, MTK_SCPD_HAS_INFRA_NAO)) {
  348. pd->infracfg_nao = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
  349. if (IS_ERR(pd->infracfg_nao))
  350. return ERR_CAST(pd->infracfg_nao);
  351. } else {
  352. pd->infracfg_nao = NULL;
  353. }
  354. num_clks = of_clk_get_parent_count(node);
  355. if (num_clks > 0) {
  356. /* Calculate number of subsys_clks */
  357. of_property_for_each_string(node, "clock-names", prop, clk_name) {
  358. char *subsys;
  359. subsys = strchr(clk_name, '-');
  360. if (subsys)
  361. pd->num_subsys_clks++;
  362. else
  363. pd->num_clks++;
  364. }
  365. pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL);
  366. if (!pd->clks)
  367. return ERR_PTR(-ENOMEM);
  368. pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks,
  369. sizeof(*pd->subsys_clks), GFP_KERNEL);
  370. if (!pd->subsys_clks)
  371. return ERR_PTR(-ENOMEM);
  372. }
  373. for (i = 0; i < pd->num_clks; i++) {
  374. clk = of_clk_get(node, i);
  375. if (IS_ERR(clk)) {
  376. ret = PTR_ERR(clk);
  377. dev_err_probe(scpsys->dev, ret,
  378. "%pOF: failed to get clk at index %d\n", node, i);
  379. goto err_put_clocks;
  380. }
  381. pd->clks[clk_ind++].clk = clk;
  382. }
  383. for (i = 0; i < pd->num_subsys_clks; i++) {
  384. clk = of_clk_get(node, i + clk_ind);
  385. if (IS_ERR(clk)) {
  386. ret = PTR_ERR(clk);
  387. dev_err_probe(scpsys->dev, ret,
  388. "%pOF: failed to get clk at index %d\n", node,
  389. i + clk_ind);
  390. goto err_put_subsys_clocks;
  391. }
  392. pd->subsys_clks[i].clk = clk;
  393. }
  394. /*
  395. * Initially turn on all domains to make the domains usable
  396. * with !CONFIG_PM and to get the hardware in sync with the
  397. * software. The unused domains will be switched off during
  398. * late_init time.
  399. */
  400. if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) {
  401. if (scpsys_domain_is_on(pd))
  402. dev_warn(scpsys->dev,
  403. "%pOF: A default off power domain has been ON\n", node);
  404. } else {
  405. ret = scpsys_power_on(&pd->genpd);
  406. if (ret < 0) {
  407. dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret);
  408. goto err_put_subsys_clocks;
  409. }
  410. if (MTK_SCPD_CAPS(pd, MTK_SCPD_ALWAYS_ON))
  411. pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
  412. }
  413. if (scpsys->domains[id]) {
  414. ret = -EINVAL;
  415. dev_err(scpsys->dev,
  416. "power domain with id %d already exists, check your device-tree\n", id);
  417. goto err_put_subsys_clocks;
  418. }
  419. if (!pd->data->name)
  420. pd->genpd.name = node->name;
  421. else
  422. pd->genpd.name = pd->data->name;
  423. pd->genpd.power_off = scpsys_power_off;
  424. pd->genpd.power_on = scpsys_power_on;
  425. if (MTK_SCPD_CAPS(pd, MTK_SCPD_ACTIVE_WAKEUP))
  426. pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
  427. if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF))
  428. pm_genpd_init(&pd->genpd, NULL, true);
  429. else
  430. pm_genpd_init(&pd->genpd, NULL, false);
  431. scpsys->domains[id] = &pd->genpd;
  432. return scpsys->pd_data.domains[id];
  433. err_put_subsys_clocks:
  434. clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
  435. err_put_clocks:
  436. clk_bulk_put(pd->num_clks, pd->clks);
  437. return ERR_PTR(ret);
  438. }
  439. static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent)
  440. {
  441. struct generic_pm_domain *child_pd, *parent_pd;
  442. struct device_node *child;
  443. int ret;
  444. for_each_child_of_node(parent, child) {
  445. u32 id;
  446. ret = of_property_read_u32(parent, "reg", &id);
  447. if (ret) {
  448. dev_err(scpsys->dev, "%pOF: failed to get parent domain id\n", child);
  449. goto err_put_node;
  450. }
  451. if (!scpsys->pd_data.domains[id]) {
  452. ret = -EINVAL;
  453. dev_err(scpsys->dev, "power domain with id %d does not exist\n", id);
  454. goto err_put_node;
  455. }
  456. parent_pd = scpsys->pd_data.domains[id];
  457. child_pd = scpsys_add_one_domain(scpsys, child);
  458. if (IS_ERR(child_pd)) {
  459. ret = PTR_ERR(child_pd);
  460. dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n",
  461. child);
  462. goto err_put_node;
  463. }
  464. /* recursive call to add all subdomains */
  465. ret = scpsys_add_subdomain(scpsys, child);
  466. if (ret)
  467. goto err_put_node;
  468. ret = pm_genpd_add_subdomain(parent_pd, child_pd);
  469. if (ret) {
  470. dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n",
  471. child_pd->name, parent_pd->name);
  472. goto err_put_node;
  473. } else {
  474. dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name,
  475. child_pd->name);
  476. }
  477. }
  478. return 0;
  479. err_put_node:
  480. of_node_put(child);
  481. return ret;
  482. }
  483. static void scpsys_remove_one_domain(struct scpsys_domain *pd)
  484. {
  485. int ret;
  486. /*
  487. * We're in the error cleanup already, so we only complain,
  488. * but won't emit another error on top of the original one.
  489. */
  490. ret = pm_genpd_remove(&pd->genpd);
  491. if (ret < 0)
  492. dev_err(pd->scpsys->dev,
  493. "failed to remove domain '%s' : %d - state may be inconsistent\n",
  494. pd->genpd.name, ret);
  495. if (scpsys_domain_is_on(pd))
  496. scpsys_power_off(&pd->genpd);
  497. clk_bulk_put(pd->num_clks, pd->clks);
  498. clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
  499. }
  500. static void scpsys_domain_cleanup(struct scpsys *scpsys)
  501. {
  502. struct generic_pm_domain *genpd;
  503. struct scpsys_domain *pd;
  504. int i;
  505. for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) {
  506. genpd = scpsys->pd_data.domains[i];
  507. if (genpd) {
  508. pd = to_scpsys_domain(genpd);
  509. scpsys_remove_one_domain(pd);
  510. }
  511. }
  512. }
  513. static const struct of_device_id scpsys_of_match[] = {
  514. {
  515. .compatible = "mediatek,mt6795-power-controller",
  516. .data = &mt6795_scpsys_data,
  517. },
  518. {
  519. .compatible = "mediatek,mt8167-power-controller",
  520. .data = &mt8167_scpsys_data,
  521. },
  522. {
  523. .compatible = "mediatek,mt8173-power-controller",
  524. .data = &mt8173_scpsys_data,
  525. },
  526. {
  527. .compatible = "mediatek,mt8183-power-controller",
  528. .data = &mt8183_scpsys_data,
  529. },
  530. {
  531. .compatible = "mediatek,mt8186-power-controller",
  532. .data = &mt8186_scpsys_data,
  533. },
  534. {
  535. .compatible = "mediatek,mt8188-power-controller",
  536. .data = &mt8188_scpsys_data,
  537. },
  538. {
  539. .compatible = "mediatek,mt8192-power-controller",
  540. .data = &mt8192_scpsys_data,
  541. },
  542. {
  543. .compatible = "mediatek,mt8195-power-controller",
  544. .data = &mt8195_scpsys_data,
  545. },
  546. {
  547. .compatible = "mediatek,mt8365-power-controller",
  548. .data = &mt8365_scpsys_data,
  549. },
  550. { }
  551. };
  552. static int scpsys_probe(struct platform_device *pdev)
  553. {
  554. struct device *dev = &pdev->dev;
  555. struct device_node *np = dev->of_node;
  556. const struct scpsys_soc_data *soc;
  557. struct device_node *node;
  558. struct device *parent;
  559. struct scpsys *scpsys;
  560. int ret;
  561. soc = of_device_get_match_data(&pdev->dev);
  562. if (!soc) {
  563. dev_err(&pdev->dev, "no power controller data\n");
  564. return -EINVAL;
  565. }
  566. scpsys = devm_kzalloc(dev, struct_size(scpsys, domains, soc->num_domains), GFP_KERNEL);
  567. if (!scpsys)
  568. return -ENOMEM;
  569. scpsys->dev = dev;
  570. scpsys->soc_data = soc;
  571. scpsys->pd_data.domains = scpsys->domains;
  572. scpsys->pd_data.num_domains = soc->num_domains;
  573. parent = dev->parent;
  574. if (!parent) {
  575. dev_err(dev, "no parent for syscon devices\n");
  576. return -ENODEV;
  577. }
  578. scpsys->base = syscon_node_to_regmap(parent->of_node);
  579. if (IS_ERR(scpsys->base)) {
  580. dev_err(dev, "no regmap available\n");
  581. return PTR_ERR(scpsys->base);
  582. }
  583. ret = -ENODEV;
  584. for_each_available_child_of_node(np, node) {
  585. struct generic_pm_domain *domain;
  586. domain = scpsys_add_one_domain(scpsys, node);
  587. if (IS_ERR(domain)) {
  588. ret = PTR_ERR(domain);
  589. of_node_put(node);
  590. goto err_cleanup_domains;
  591. }
  592. ret = scpsys_add_subdomain(scpsys, node);
  593. if (ret) {
  594. of_node_put(node);
  595. goto err_cleanup_domains;
  596. }
  597. }
  598. if (ret) {
  599. dev_dbg(dev, "no power domains present\n");
  600. return ret;
  601. }
  602. ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data);
  603. if (ret) {
  604. dev_err(dev, "failed to add provider: %d\n", ret);
  605. goto err_cleanup_domains;
  606. }
  607. return 0;
  608. err_cleanup_domains:
  609. scpsys_domain_cleanup(scpsys);
  610. return ret;
  611. }
  612. static struct platform_driver scpsys_pm_domain_driver = {
  613. .probe = scpsys_probe,
  614. .driver = {
  615. .name = "mtk-power-controller",
  616. .suppress_bind_attrs = true,
  617. .of_match_table = scpsys_of_match,
  618. },
  619. };
  620. builtin_platform_driver(scpsys_pm_domain_driver);