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