mtk-pm-domains.c 17 KB

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