200-ARM-at91-pm-check-for-different-controllers-in-at91_.patch 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. From 0c4cbd38a705bdeab11de4c84ad0ce8c3de8a81d Mon Sep 17 00:00:00 2001
  2. From: Claudiu Beznea <[email protected]>
  3. Date: Thu, 15 Apr 2021 13:49:50 +0300
  4. Subject: [PATCH 200/247] ARM: at91: pm: check for different controllers in
  5. at91_pm_modes_init()
  6. at91_pm_modes_init() checks for proper nodes in device tree and maps
  7. them accordingly. Up to SAMA7G5 all AT91 SoCs had the same mapping
  8. b/w power saving modes and different controllers needed in the
  9. final/first steps of suspend/resume. SAMA7G5 is not aligned with the
  10. old SoCs thus the code is adapted for this. This patch prepares
  11. the field for next commits.
  12. Signed-off-by: Claudiu Beznea <[email protected]>
  13. Signed-off-by: Nicolas Ferre <[email protected]>
  14. Link: https://lore.kernel.org/r/[email protected]
  15. ---
  16. arch/arm/mach-at91/pm.c | 143 +++++++++++++++++++++++++---------------
  17. 1 file changed, 91 insertions(+), 52 deletions(-)
  18. --- a/arch/arm/mach-at91/pm.c
  19. +++ b/arch/arm/mach-at91/pm.c
  20. @@ -57,6 +57,18 @@ struct at91_soc_pm {
  21. struct at91_pm_data data;
  22. };
  23. +/**
  24. + * enum at91_pm_iomaps: IOs that needs to be mapped for different PM modes
  25. + * @AT91_PM_IOMAP_SHDWC: SHDWC controller
  26. + * @AT91_PM_IOMAP_SFRBU: SFRBU controller
  27. + */
  28. +enum at91_pm_iomaps {
  29. + AT91_PM_IOMAP_SHDWC,
  30. + AT91_PM_IOMAP_SFRBU,
  31. +};
  32. +
  33. +#define AT91_PM_IOMAP(name) BIT(AT91_PM_IOMAP_##name)
  34. +
  35. static struct at91_soc_pm soc_pm = {
  36. .data = {
  37. .standby_mode = AT91_PM_STANDBY,
  38. @@ -671,24 +683,15 @@ static int __init at91_pm_backup_init(vo
  39. if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
  40. return 0;
  41. - np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
  42. - if (!np) {
  43. - pr_warn("%s: failed to find sfrbu!\n", __func__);
  44. - return ret;
  45. - }
  46. -
  47. - soc_pm.data.sfrbu = of_iomap(np, 0);
  48. - of_node_put(np);
  49. -
  50. np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
  51. if (!np)
  52. - goto securam_fail_no_ref_dev;
  53. + return ret;
  54. pdev = of_find_device_by_node(np);
  55. of_node_put(np);
  56. if (!pdev) {
  57. pr_warn("%s: failed to find securam device!\n", __func__);
  58. - goto securam_fail_no_ref_dev;
  59. + return ret;
  60. }
  61. sram_pool = gen_pool_get(&pdev->dev, NULL);
  62. @@ -712,64 +715,92 @@ static int __init at91_pm_backup_init(vo
  63. securam_fail:
  64. put_device(&pdev->dev);
  65. -securam_fail_no_ref_dev:
  66. - iounmap(soc_pm.data.sfrbu);
  67. - soc_pm.data.sfrbu = NULL;
  68. return ret;
  69. }
  70. -static void __init at91_pm_use_default_mode(int pm_mode)
  71. -{
  72. - if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
  73. - return;
  74. -
  75. - if (soc_pm.data.standby_mode == pm_mode)
  76. - soc_pm.data.standby_mode = AT91_PM_ULP0;
  77. - if (soc_pm.data.suspend_mode == pm_mode)
  78. - soc_pm.data.suspend_mode = AT91_PM_ULP0;
  79. -}
  80. -
  81. static const struct of_device_id atmel_shdwc_ids[] = {
  82. { .compatible = "atmel,sama5d2-shdwc" },
  83. { .compatible = "microchip,sam9x60-shdwc" },
  84. { /* sentinel. */ }
  85. };
  86. -static void __init at91_pm_modes_init(void)
  87. +static void __init at91_pm_modes_init(const u32 *maps, int len)
  88. {
  89. struct device_node *np;
  90. - int ret;
  91. + int ret, mode;
  92. - if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
  93. - !at91_is_pm_mode_active(AT91_PM_ULP1))
  94. - return;
  95. + ret = at91_pm_backup_init();
  96. + if (ret) {
  97. + if (soc_pm.data.standby_mode == AT91_PM_BACKUP)
  98. + soc_pm.data.standby_mode = AT91_PM_ULP0;
  99. + if (soc_pm.data.suspend_mode == AT91_PM_BACKUP)
  100. + soc_pm.data.suspend_mode = AT91_PM_ULP0;
  101. + }
  102. +
  103. + if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
  104. + maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC)) {
  105. + np = of_find_matching_node(NULL, atmel_shdwc_ids);
  106. + if (!np) {
  107. + pr_warn("%s: failed to find shdwc!\n", __func__);
  108. +
  109. + /* Use ULP0 if it doesn't needs SHDWC.*/
  110. + if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)))
  111. + mode = AT91_PM_ULP0;
  112. + else
  113. + mode = AT91_PM_STANDBY;
  114. +
  115. + if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC))
  116. + soc_pm.data.standby_mode = mode;
  117. + if (maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC))
  118. + soc_pm.data.suspend_mode = mode;
  119. + } else {
  120. + soc_pm.data.shdwc = of_iomap(np, 0);
  121. + of_node_put(np);
  122. + }
  123. + }
  124. - np = of_find_matching_node(NULL, atmel_shdwc_ids);
  125. - if (!np) {
  126. - pr_warn("%s: failed to find shdwc!\n", __func__);
  127. - goto ulp1_default;
  128. + if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU) ||
  129. + maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU)) {
  130. + np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
  131. + if (!np) {
  132. + pr_warn("%s: failed to find sfrbu!\n", __func__);
  133. +
  134. + /*
  135. + * Use ULP0 if it doesn't need SHDWC or if SHDWC
  136. + * was already located.
  137. + */
  138. + if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)) ||
  139. + soc_pm.data.shdwc)
  140. + mode = AT91_PM_ULP0;
  141. + else
  142. + mode = AT91_PM_STANDBY;
  143. +
  144. + if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU))
  145. + soc_pm.data.standby_mode = mode;
  146. + if (maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU))
  147. + soc_pm.data.suspend_mode = mode;
  148. + } else {
  149. + soc_pm.data.sfrbu = of_iomap(np, 0);
  150. + of_node_put(np);
  151. + }
  152. }
  153. - soc_pm.data.shdwc = of_iomap(np, 0);
  154. - of_node_put(np);
  155. + /* Unmap all unnecessary. */
  156. + if (soc_pm.data.shdwc &&
  157. + !(maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
  158. + maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC))) {
  159. + iounmap(soc_pm.data.shdwc);
  160. + soc_pm.data.shdwc = NULL;
  161. + }
  162. - ret = at91_pm_backup_init();
  163. - if (ret) {
  164. - if (!at91_is_pm_mode_active(AT91_PM_ULP1))
  165. - goto unmap;
  166. - else
  167. - goto backup_default;
  168. + if (soc_pm.data.sfrbu &&
  169. + !(maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU) ||
  170. + maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU))) {
  171. + iounmap(soc_pm.data.sfrbu);
  172. + soc_pm.data.sfrbu = NULL;
  173. }
  174. return;
  175. -
  176. -unmap:
  177. - iounmap(soc_pm.data.shdwc);
  178. - soc_pm.data.shdwc = NULL;
  179. -ulp1_default:
  180. - at91_pm_use_default_mode(AT91_PM_ULP1);
  181. -backup_default:
  182. - at91_pm_use_default_mode(AT91_PM_BACKUP);
  183. }
  184. struct pmc_info {
  185. @@ -936,13 +967,16 @@ void __init sam9x60_pm_init(void)
  186. static const int modes[] __initconst = {
  187. AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
  188. };
  189. + static const int iomaps[] __initconst = {
  190. + [AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
  191. + };
  192. int ret;
  193. if (!IS_ENABLED(CONFIG_SOC_SAM9X60))
  194. return;
  195. at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
  196. - at91_pm_modes_init();
  197. + at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
  198. ret = at91_dt_ramc();
  199. if (ret)
  200. return;
  201. @@ -999,13 +1033,18 @@ void __init sama5d2_pm_init(void)
  202. AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
  203. AT91_PM_BACKUP,
  204. };
  205. + static const u32 iomaps[] __initconst = {
  206. + [AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
  207. + [AT91_PM_BACKUP] = AT91_PM_IOMAP(SHDWC) |
  208. + AT91_PM_IOMAP(SFRBU),
  209. + };
  210. int ret;
  211. if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
  212. return;
  213. at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
  214. - at91_pm_modes_init();
  215. + at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
  216. ret = at91_dt_ramc();
  217. if (ret)
  218. return;