.. | .. |
---|
51 | 51 | [AT91_SHDW_WKMODE0_ANYLEVEL] = "any", |
---|
52 | 52 | }; |
---|
53 | 53 | |
---|
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; |
---|
57 | 59 | |
---|
58 | 60 | static void __init at91_wakeup_status(struct platform_device *pdev) |
---|
59 | 61 | { |
---|
60 | 62 | const char *reason; |
---|
61 | | - u32 reg = readl(at91_shdwc_base + AT91_SHDW_SR); |
---|
| 63 | + u32 reg = readl(at91_shdwc.shdwc_base + AT91_SHDW_SR); |
---|
62 | 64 | |
---|
63 | 65 | /* Simple power-on, just bail out */ |
---|
64 | 66 | if (!reg) |
---|
.. | .. |
---|
76 | 78 | |
---|
77 | 79 | static void at91_poweroff(void) |
---|
78 | 80 | { |
---|
79 | | - writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR); |
---|
80 | | -} |
---|
81 | | - |
---|
82 | | -static void at91_lpddr_poweroff(void) |
---|
83 | | -{ |
---|
84 | 81 | asm volatile( |
---|
85 | 82 | /* Align to cache lines */ |
---|
86 | 83 | ".balign 32\n\t" |
---|
.. | .. |
---|
89 | 86 | " ldr r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t" |
---|
90 | 87 | |
---|
91 | 88 | /* Power down SDRAM0 */ |
---|
| 89 | + " tst %0, #0\n\t" |
---|
| 90 | + " beq 1f\n\t" |
---|
92 | 91 | " str %1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t" |
---|
93 | 92 | /* Shutdown CPU */ |
---|
94 | | - " str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t" |
---|
| 93 | + "1: str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t" |
---|
95 | 94 | |
---|
96 | 95 | " b .\n\t" |
---|
97 | 96 | : |
---|
98 | | - : "r" (mpddrc_base), |
---|
| 97 | + : "r" (at91_shdwc.mpddrc_base), |
---|
99 | 98 | "r" cpu_to_le32(AT91_DDRSDRC_LPDDR2_PWOFF), |
---|
100 | | - "r" (at91_shdwc_base), |
---|
| 99 | + "r" (at91_shdwc.shdwc_base), |
---|
101 | 100 | "r" cpu_to_le32(AT91_SHDW_KEY | AT91_SHDW_SHDW) |
---|
102 | 101 | : "r6"); |
---|
103 | 102 | } |
---|
.. | .. |
---|
147 | 146 | if (of_property_read_bool(np, "atmel,wakeup-rtt-timer")) |
---|
148 | 147 | mode |= AT91_SHDW_RTTWKEN; |
---|
149 | 148 | |
---|
150 | | - writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR); |
---|
| 149 | + writel(wakeup_mode | mode, at91_shdwc.shdwc_base + AT91_SHDW_MR); |
---|
151 | 150 | } |
---|
152 | 151 | |
---|
153 | 152 | static int __init at91_poweroff_probe(struct platform_device *pdev) |
---|
.. | .. |
---|
158 | 157 | int ret; |
---|
159 | 158 | |
---|
160 | 159 | 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); |
---|
164 | 163 | |
---|
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); |
---|
168 | 167 | |
---|
169 | | - ret = clk_prepare_enable(sclk); |
---|
| 168 | + ret = clk_prepare_enable(at91_shdwc.sclk); |
---|
170 | 169 | if (ret) { |
---|
171 | 170 | dev_err(&pdev->dev, "Could not enable slow clock\n"); |
---|
172 | 171 | return ret; |
---|
.. | .. |
---|
177 | 176 | if (pdev->dev.of_node) |
---|
178 | 177 | at91_poweroff_dt_set_wakeup_mode(pdev); |
---|
179 | 178 | |
---|
| 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 | + |
---|
180 | 198 | pm_power_off = at91_poweroff; |
---|
181 | 199 | |
---|
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 | | - |
---|
199 | 200 | return 0; |
---|
| 201 | + |
---|
| 202 | +clk_disable: |
---|
| 203 | + clk_disable_unprepare(at91_shdwc.sclk); |
---|
| 204 | + return ret; |
---|
200 | 205 | } |
---|
201 | 206 | |
---|
202 | 207 | static int __exit at91_poweroff_remove(struct platform_device *pdev) |
---|
203 | 208 | { |
---|
204 | | - if (pm_power_off == at91_poweroff || |
---|
205 | | - pm_power_off == at91_lpddr_poweroff) |
---|
| 209 | + if (pm_power_off == at91_poweroff) |
---|
206 | 210 | pm_power_off = NULL; |
---|
207 | 211 | |
---|
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); |
---|
209 | 216 | |
---|
210 | 217 | return 0; |
---|
211 | 218 | } |
---|
212 | | - |
---|
213 | | -static const struct of_device_id at91_ramc_of_match[] = { |
---|
214 | | - { .compatible = "atmel,sama5d3-ddramc", }, |
---|
215 | | - { /* sentinel */ } |
---|
216 | | -}; |
---|
217 | 219 | |
---|
218 | 220 | static const struct of_device_id at91_poweroff_of_match[] = { |
---|
219 | 221 | { .compatible = "atmel,at91sam9260-shdwc", }, |
---|