gpcv2.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2017 Impinj, Inc
  4. * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
  5. *
  6. * Based on the code of analogus driver:
  7. *
  8. * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
  9. */
  10. #include <linux/of_device.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/pm_domain.h>
  13. #include <linux/regmap.h>
  14. #include <linux/regulator/consumer.h>
  15. #include <dt-bindings/power/imx7-power.h>
  16. #define GPC_LPCR_A_CORE_BSC 0x000
  17. #define GPC_PGC_CPU_MAPPING 0x0ec
  18. #define USB_HSIC_PHY_A_CORE_DOMAIN BIT(6)
  19. #define USB_OTG2_PHY_A_CORE_DOMAIN BIT(5)
  20. #define USB_OTG1_PHY_A_CORE_DOMAIN BIT(4)
  21. #define PCIE_PHY_A_CORE_DOMAIN BIT(3)
  22. #define MIPI_PHY_A_CORE_DOMAIN BIT(2)
  23. #define GPC_PU_PGC_SW_PUP_REQ 0x0f8
  24. #define GPC_PU_PGC_SW_PDN_REQ 0x104
  25. #define USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
  26. #define USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
  27. #define USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
  28. #define PCIE_PHY_SW_Pxx_REQ BIT(1)
  29. #define MIPI_PHY_SW_Pxx_REQ BIT(0)
  30. #define GPC_M4_PU_PDN_FLG 0x1bc
  31. /*
  32. * The PGC offset values in Reference Manual
  33. * (Rev. 1, 01/2018 and the older ones) GPC chapter's
  34. * GPC_PGC memory map are incorrect, below offset
  35. * values are from design RTL.
  36. */
  37. #define PGC_MIPI 16
  38. #define PGC_PCIE 17
  39. #define PGC_USB_HSIC 20
  40. #define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40)
  41. #define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc)
  42. #define GPC_PGC_CTRL_PCR BIT(0)
  43. struct imx_pgc_domain {
  44. struct generic_pm_domain genpd;
  45. struct regmap *regmap;
  46. struct regulator *regulator;
  47. unsigned int pgc;
  48. const struct {
  49. u32 pxx;
  50. u32 map;
  51. } bits;
  52. const int voltage;
  53. struct device *dev;
  54. };
  55. struct imx_pgc_domain_data {
  56. const struct imx_pgc_domain *domains;
  57. size_t domains_num;
  58. };
  59. static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
  60. bool on)
  61. {
  62. struct imx_pgc_domain *domain = container_of(genpd,
  63. struct imx_pgc_domain,
  64. genpd);
  65. unsigned int offset = on ?
  66. GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
  67. const bool enable_power_control = !on;
  68. const bool has_regulator = !IS_ERR(domain->regulator);
  69. unsigned long deadline;
  70. int ret = 0;
  71. regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
  72. domain->bits.map, domain->bits.map);
  73. if (has_regulator && on) {
  74. ret = regulator_enable(domain->regulator);
  75. if (ret) {
  76. dev_err(domain->dev, "failed to enable regulator\n");
  77. goto unmap;
  78. }
  79. }
  80. if (enable_power_control)
  81. regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
  82. GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
  83. regmap_update_bits(domain->regmap, offset,
  84. domain->bits.pxx, domain->bits.pxx);
  85. /*
  86. * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
  87. * for PUP_REQ/PDN_REQ bit to be cleared
  88. */
  89. deadline = jiffies + msecs_to_jiffies(1);
  90. while (true) {
  91. u32 pxx_req;
  92. regmap_read(domain->regmap, offset, &pxx_req);
  93. if (!(pxx_req & domain->bits.pxx))
  94. break;
  95. if (time_after(jiffies, deadline)) {
  96. dev_err(domain->dev, "falied to command PGC\n");
  97. ret = -ETIMEDOUT;
  98. /*
  99. * If we were in a process of enabling a
  100. * domain and failed we might as well disable
  101. * the regulator we just enabled. And if it
  102. * was the opposite situation and we failed to
  103. * power down -- keep the regulator on
  104. */
  105. on = !on;
  106. break;
  107. }
  108. cpu_relax();
  109. }
  110. if (enable_power_control)
  111. regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
  112. GPC_PGC_CTRL_PCR, 0);
  113. if (has_regulator && !on) {
  114. int err;
  115. err = regulator_disable(domain->regulator);
  116. if (err)
  117. dev_err(domain->dev,
  118. "failed to disable regulator: %d\n", ret);
  119. /* Preserve earlier error code */
  120. ret = ret ?: err;
  121. }
  122. unmap:
  123. regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
  124. domain->bits.map, 0);
  125. return ret;
  126. }
  127. static int imx_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd)
  128. {
  129. return imx_gpc_pu_pgc_sw_pxx_req(genpd, true);
  130. }
  131. static int imx_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd)
  132. {
  133. return imx_gpc_pu_pgc_sw_pxx_req(genpd, false);
  134. }
  135. static const struct imx_pgc_domain imx7_pgc_domains[] = {
  136. [IMX7_POWER_DOMAIN_MIPI_PHY] = {
  137. .genpd = {
  138. .name = "mipi-phy",
  139. },
  140. .bits = {
  141. .pxx = MIPI_PHY_SW_Pxx_REQ,
  142. .map = MIPI_PHY_A_CORE_DOMAIN,
  143. },
  144. .voltage = 1000000,
  145. .pgc = PGC_MIPI,
  146. },
  147. [IMX7_POWER_DOMAIN_PCIE_PHY] = {
  148. .genpd = {
  149. .name = "pcie-phy",
  150. },
  151. .bits = {
  152. .pxx = PCIE_PHY_SW_Pxx_REQ,
  153. .map = PCIE_PHY_A_CORE_DOMAIN,
  154. },
  155. .voltage = 1000000,
  156. .pgc = PGC_PCIE,
  157. },
  158. [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
  159. .genpd = {
  160. .name = "usb-hsic-phy",
  161. },
  162. .bits = {
  163. .pxx = USB_HSIC_PHY_SW_Pxx_REQ,
  164. .map = USB_HSIC_PHY_A_CORE_DOMAIN,
  165. },
  166. .voltage = 1200000,
  167. .pgc = PGC_USB_HSIC,
  168. },
  169. };
  170. static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
  171. .domains = imx7_pgc_domains,
  172. .domains_num = ARRAY_SIZE(imx7_pgc_domains),
  173. };
  174. static int imx_pgc_domain_probe(struct platform_device *pdev)
  175. {
  176. struct imx_pgc_domain *domain = pdev->dev.platform_data;
  177. int ret;
  178. domain->dev = &pdev->dev;
  179. domain->regulator = devm_regulator_get_optional(domain->dev, "power");
  180. if (IS_ERR(domain->regulator)) {
  181. if (PTR_ERR(domain->regulator) != -ENODEV) {
  182. if (PTR_ERR(domain->regulator) != -EPROBE_DEFER)
  183. dev_err(domain->dev, "Failed to get domain's regulator\n");
  184. return PTR_ERR(domain->regulator);
  185. }
  186. } else {
  187. regulator_set_voltage(domain->regulator,
  188. domain->voltage, domain->voltage);
  189. }
  190. ret = pm_genpd_init(&domain->genpd, NULL, true);
  191. if (ret) {
  192. dev_err(domain->dev, "Failed to init power domain\n");
  193. return ret;
  194. }
  195. ret = of_genpd_add_provider_simple(domain->dev->of_node,
  196. &domain->genpd);
  197. if (ret) {
  198. dev_err(domain->dev, "Failed to add genpd provider\n");
  199. pm_genpd_remove(&domain->genpd);
  200. }
  201. return ret;
  202. }
  203. static int imx_pgc_domain_remove(struct platform_device *pdev)
  204. {
  205. struct imx_pgc_domain *domain = pdev->dev.platform_data;
  206. of_genpd_del_provider(domain->dev->of_node);
  207. pm_genpd_remove(&domain->genpd);
  208. return 0;
  209. }
  210. static const struct platform_device_id imx_pgc_domain_id[] = {
  211. { "imx-pgc-domain", },
  212. { },
  213. };
  214. static struct platform_driver imx_pgc_domain_driver = {
  215. .driver = {
  216. .name = "imx-pgc",
  217. },
  218. .probe = imx_pgc_domain_probe,
  219. .remove = imx_pgc_domain_remove,
  220. .id_table = imx_pgc_domain_id,
  221. };
  222. builtin_platform_driver(imx_pgc_domain_driver)
  223. static int imx_gpcv2_probe(struct platform_device *pdev)
  224. {
  225. static const struct imx_pgc_domain_data *domain_data;
  226. static const struct regmap_range yes_ranges[] = {
  227. regmap_reg_range(GPC_LPCR_A_CORE_BSC,
  228. GPC_M4_PU_PDN_FLG),
  229. regmap_reg_range(GPC_PGC_CTRL(PGC_MIPI),
  230. GPC_PGC_SR(PGC_MIPI)),
  231. regmap_reg_range(GPC_PGC_CTRL(PGC_PCIE),
  232. GPC_PGC_SR(PGC_PCIE)),
  233. regmap_reg_range(GPC_PGC_CTRL(PGC_USB_HSIC),
  234. GPC_PGC_SR(PGC_USB_HSIC)),
  235. };
  236. static const struct regmap_access_table access_table = {
  237. .yes_ranges = yes_ranges,
  238. .n_yes_ranges = ARRAY_SIZE(yes_ranges),
  239. };
  240. static const struct regmap_config regmap_config = {
  241. .reg_bits = 32,
  242. .val_bits = 32,
  243. .reg_stride = 4,
  244. .rd_table = &access_table,
  245. .wr_table = &access_table,
  246. .max_register = SZ_4K,
  247. };
  248. struct device *dev = &pdev->dev;
  249. struct device_node *pgc_np, *np;
  250. struct regmap *regmap;
  251. struct resource *res;
  252. void __iomem *base;
  253. int ret;
  254. pgc_np = of_get_child_by_name(dev->of_node, "pgc");
  255. if (!pgc_np) {
  256. dev_err(dev, "No power domains specified in DT\n");
  257. return -EINVAL;
  258. }
  259. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  260. base = devm_ioremap_resource(dev, res);
  261. if (IS_ERR(base))
  262. return PTR_ERR(base);
  263. regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
  264. if (IS_ERR(regmap)) {
  265. ret = PTR_ERR(regmap);
  266. dev_err(dev, "failed to init regmap (%d)\n", ret);
  267. return ret;
  268. }
  269. domain_data = of_device_get_match_data(&pdev->dev);
  270. for_each_child_of_node(pgc_np, np) {
  271. struct platform_device *pd_pdev;
  272. struct imx_pgc_domain *domain;
  273. u32 domain_index;
  274. ret = of_property_read_u32(np, "reg", &domain_index);
  275. if (ret) {
  276. dev_err(dev, "Failed to read 'reg' property\n");
  277. of_node_put(np);
  278. return ret;
  279. }
  280. if (domain_index >= domain_data->domains_num) {
  281. dev_warn(dev,
  282. "Domain index %d is out of bounds\n",
  283. domain_index);
  284. continue;
  285. }
  286. pd_pdev = platform_device_alloc("imx-pgc-domain",
  287. domain_index);
  288. if (!pd_pdev) {
  289. dev_err(dev, "Failed to allocate platform device\n");
  290. of_node_put(np);
  291. return -ENOMEM;
  292. }
  293. ret = platform_device_add_data(pd_pdev,
  294. &domain_data->domains[domain_index],
  295. sizeof(domain_data->domains[domain_index]));
  296. if (ret) {
  297. platform_device_put(pd_pdev);
  298. of_node_put(np);
  299. return ret;
  300. }
  301. domain = pd_pdev->dev.platform_data;
  302. domain->regmap = regmap;
  303. domain->genpd.power_on = imx_gpc_pu_pgc_sw_pup_req;
  304. domain->genpd.power_off = imx_gpc_pu_pgc_sw_pdn_req;
  305. pd_pdev->dev.parent = dev;
  306. pd_pdev->dev.of_node = np;
  307. ret = platform_device_add(pd_pdev);
  308. if (ret) {
  309. platform_device_put(pd_pdev);
  310. of_node_put(np);
  311. return ret;
  312. }
  313. }
  314. return 0;
  315. }
  316. static const struct of_device_id imx_gpcv2_dt_ids[] = {
  317. { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, },
  318. { }
  319. };
  320. static struct platform_driver imx_gpc_driver = {
  321. .driver = {
  322. .name = "imx-gpcv2",
  323. .of_match_table = imx_gpcv2_dt_ids,
  324. },
  325. .probe = imx_gpcv2_probe,
  326. };
  327. builtin_platform_driver(imx_gpc_driver)