| .. | .. |
|---|
| 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", }, |
|---|