hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/power/reset/at91-poweroff.c
....@@ -51,14 +51,16 @@
5151 [AT91_SHDW_WKMODE0_ANYLEVEL] = "any",
5252 };
5353
54
-static void __iomem *at91_shdwc_base;
55
-static struct clk *sclk;
56
-static void __iomem *mpddrc_base;
54
+static struct shdwc {
55
+ struct clk *sclk;
56
+ void __iomem *shdwc_base;
57
+ void __iomem *mpddrc_base;
58
+} at91_shdwc;
5759
5860 static void __init at91_wakeup_status(struct platform_device *pdev)
5961 {
6062 const char *reason;
61
- u32 reg = readl(at91_shdwc_base + AT91_SHDW_SR);
63
+ u32 reg = readl(at91_shdwc.shdwc_base + AT91_SHDW_SR);
6264
6365 /* Simple power-on, just bail out */
6466 if (!reg)
....@@ -76,11 +78,6 @@
7678
7779 static void at91_poweroff(void)
7880 {
79
- writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR);
80
-}
81
-
82
-static void at91_lpddr_poweroff(void)
83
-{
8481 asm volatile(
8582 /* Align to cache lines */
8683 ".balign 32\n\t"
....@@ -89,15 +86,17 @@
8986 " ldr r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
9087
9188 /* Power down SDRAM0 */
89
+ " tst %0, #0\n\t"
90
+ " beq 1f\n\t"
9291 " str %1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"
9392 /* Shutdown CPU */
94
- " str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
93
+ "1: str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
9594
9695 " b .\n\t"
9796 :
98
- : "r" (mpddrc_base),
97
+ : "r" (at91_shdwc.mpddrc_base),
9998 "r" cpu_to_le32(AT91_DDRSDRC_LPDDR2_PWOFF),
100
- "r" (at91_shdwc_base),
99
+ "r" (at91_shdwc.shdwc_base),
101100 "r" cpu_to_le32(AT91_SHDW_KEY | AT91_SHDW_SHDW)
102101 : "r6");
103102 }
....@@ -147,7 +146,7 @@
147146 if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
148147 mode |= AT91_SHDW_RTTWKEN;
149148
150
- writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR);
149
+ writel(wakeup_mode | mode, at91_shdwc.shdwc_base + AT91_SHDW_MR);
151150 }
152151
153152 static int __init at91_poweroff_probe(struct platform_device *pdev)
....@@ -158,15 +157,15 @@
158157 int ret;
159158
160159 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
161
- at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res);
162
- if (IS_ERR(at91_shdwc_base))
163
- return PTR_ERR(at91_shdwc_base);
160
+ at91_shdwc.shdwc_base = devm_ioremap_resource(&pdev->dev, res);
161
+ if (IS_ERR(at91_shdwc.shdwc_base))
162
+ return PTR_ERR(at91_shdwc.shdwc_base);
164163
165
- sclk = devm_clk_get(&pdev->dev, NULL);
166
- if (IS_ERR(sclk))
167
- return PTR_ERR(sclk);
164
+ at91_shdwc.sclk = devm_clk_get(&pdev->dev, NULL);
165
+ if (IS_ERR(at91_shdwc.sclk))
166
+ return PTR_ERR(at91_shdwc.sclk);
168167
169
- ret = clk_prepare_enable(sclk);
168
+ ret = clk_prepare_enable(at91_shdwc.sclk);
170169 if (ret) {
171170 dev_err(&pdev->dev, "Could not enable slow clock\n");
172171 return ret;
....@@ -177,43 +176,46 @@
177176 if (pdev->dev.of_node)
178177 at91_poweroff_dt_set_wakeup_mode(pdev);
179178
179
+ np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc");
180
+ if (np) {
181
+ at91_shdwc.mpddrc_base = of_iomap(np, 0);
182
+ of_node_put(np);
183
+
184
+ if (!at91_shdwc.mpddrc_base) {
185
+ ret = -ENOMEM;
186
+ goto clk_disable;
187
+ }
188
+
189
+ ddr_type = readl(at91_shdwc.mpddrc_base + AT91_DDRSDRC_MDR) &
190
+ AT91_DDRSDRC_MD;
191
+ if (ddr_type != AT91_DDRSDRC_MD_LPDDR2 &&
192
+ ddr_type != AT91_DDRSDRC_MD_LPDDR3) {
193
+ iounmap(at91_shdwc.mpddrc_base);
194
+ at91_shdwc.mpddrc_base = NULL;
195
+ }
196
+ }
197
+
180198 pm_power_off = at91_poweroff;
181199
182
- np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc");
183
- if (!np)
184
- return 0;
185
-
186
- mpddrc_base = of_iomap(np, 0);
187
- of_node_put(np);
188
-
189
- if (!mpddrc_base)
190
- return 0;
191
-
192
- ddr_type = readl(mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD;
193
- if ((ddr_type == AT91_DDRSDRC_MD_LPDDR2) ||
194
- (ddr_type == AT91_DDRSDRC_MD_LPDDR3))
195
- pm_power_off = at91_lpddr_poweroff;
196
- else
197
- iounmap(mpddrc_base);
198
-
199200 return 0;
201
+
202
+clk_disable:
203
+ clk_disable_unprepare(at91_shdwc.sclk);
204
+ return ret;
200205 }
201206
202207 static int __exit at91_poweroff_remove(struct platform_device *pdev)
203208 {
204
- if (pm_power_off == at91_poweroff ||
205
- pm_power_off == at91_lpddr_poweroff)
209
+ if (pm_power_off == at91_poweroff)
206210 pm_power_off = NULL;
207211
208
- clk_disable_unprepare(sclk);
212
+ if (at91_shdwc.mpddrc_base)
213
+ iounmap(at91_shdwc.mpddrc_base);
214
+
215
+ clk_disable_unprepare(at91_shdwc.sclk);
209216
210217 return 0;
211218 }
212
-
213
-static const struct of_device_id at91_ramc_of_match[] = {
214
- { .compatible = "atmel,sama5d3-ddramc", },
215
- { /* sentinel */ }
216
-};
217219
218220 static const struct of_device_id at91_poweroff_of_match[] = {
219221 { .compatible = "atmel,at91sam9260-shdwc", },