diff options
| -rw-r--r-- | arch/arm/mach-at91/pm.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index c83f78000ab3..27264caa4ec6 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c | |||
| @@ -40,6 +40,9 @@ extern void at91_pinctrl_gpio_resume(void); | |||
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | struct at91_soc_pm { | 42 | struct at91_soc_pm { |
| 43 | int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity); | ||
| 44 | int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity); | ||
| 45 | const struct of_device_id *ws_ids; | ||
| 43 | struct at91_pm_data data; | 46 | struct at91_pm_data data; |
| 44 | }; | 47 | }; |
| 45 | 48 | ||
| @@ -122,7 +125,7 @@ static int at91_pm_config_ws(unsigned int pm_mode, bool set) | |||
| 122 | if (pm_mode != AT91_PM_ULP1) | 125 | if (pm_mode != AT91_PM_ULP1) |
| 123 | return 0; | 126 | return 0; |
| 124 | 127 | ||
| 125 | if (!soc_pm.data.pmc || !soc_pm.data.shdwc) | 128 | if (!soc_pm.data.pmc || !soc_pm.data.shdwc || !soc_pm.ws_ids) |
| 126 | return -EPERM; | 129 | return -EPERM; |
| 127 | 130 | ||
| 128 | if (!set) { | 131 | if (!set) { |
| @@ -130,16 +133,14 @@ static int at91_pm_config_ws(unsigned int pm_mode, bool set) | |||
| 130 | return 0; | 133 | return 0; |
| 131 | } | 134 | } |
| 132 | 135 | ||
| 133 | /* SHDWC.WUIR */ | 136 | if (soc_pm.config_shdwc_ws) |
| 134 | val = readl(soc_pm.data.shdwc + 0x0c); | 137 | soc_pm.config_shdwc_ws(soc_pm.data.shdwc, &mode, &polarity); |
| 135 | mode |= (val & 0x3ff); | ||
| 136 | polarity |= ((val >> 16) & 0x3ff); | ||
| 137 | 138 | ||
| 138 | /* SHDWC.MR */ | 139 | /* SHDWC.MR */ |
| 139 | val = readl(soc_pm.data.shdwc + 0x04); | 140 | val = readl(soc_pm.data.shdwc + 0x04); |
| 140 | 141 | ||
| 141 | /* Loop through defined wakeup sources. */ | 142 | /* Loop through defined wakeup sources. */ |
| 142 | for_each_matching_node_and_match(np, sama5d2_ws_ids, &match) { | 143 | for_each_matching_node_and_match(np, soc_pm.ws_ids, &match) { |
| 143 | pdev = of_find_device_by_node(np); | 144 | pdev = of_find_device_by_node(np); |
| 144 | if (!pdev) | 145 | if (!pdev) |
| 145 | continue; | 146 | continue; |
| @@ -161,8 +162,8 @@ put_device: | |||
| 161 | } | 162 | } |
| 162 | 163 | ||
| 163 | if (mode) { | 164 | if (mode) { |
| 164 | writel(mode, soc_pm.data.pmc + AT91_PMC_FSMR); | 165 | if (soc_pm.config_pmc_ws) |
| 165 | writel(polarity, soc_pm.data.pmc + AT91_PMC_FSPR); | 166 | soc_pm.config_pmc_ws(soc_pm.data.pmc, mode, polarity); |
| 166 | } else { | 167 | } else { |
| 167 | pr_err("AT91: PM: no ULP1 wakeup sources found!"); | 168 | pr_err("AT91: PM: no ULP1 wakeup sources found!"); |
| 168 | } | 169 | } |
| @@ -170,6 +171,27 @@ put_device: | |||
| 170 | return mode ? 0 : -EPERM; | 171 | return mode ? 0 : -EPERM; |
| 171 | } | 172 | } |
| 172 | 173 | ||
| 174 | static int at91_sama5d2_config_shdwc_ws(void __iomem *shdwc, u32 *mode, | ||
| 175 | u32 *polarity) | ||
| 176 | { | ||
| 177 | u32 val; | ||
| 178 | |||
| 179 | /* SHDWC.WUIR */ | ||
| 180 | val = readl(shdwc + 0x0c); | ||
| 181 | *mode |= (val & 0x3ff); | ||
| 182 | *polarity |= ((val >> 16) & 0x3ff); | ||
| 183 | |||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | static int at91_sama5d2_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity) | ||
| 188 | { | ||
| 189 | writel(mode, pmc + AT91_PMC_FSMR); | ||
| 190 | writel(polarity, pmc + AT91_PMC_FSPR); | ||
| 191 | |||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | |||
| 173 | /* | 195 | /* |
| 174 | * Called after processes are frozen, but before we shutdown devices. | 196 | * Called after processes are frozen, but before we shutdown devices. |
| 175 | */ | 197 | */ |
| @@ -796,6 +818,10 @@ void __init sama5d2_pm_init(void) | |||
| 796 | 818 | ||
| 797 | at91_pm_modes_init(); | 819 | at91_pm_modes_init(); |
| 798 | sama5_pm_init(); | 820 | sama5_pm_init(); |
| 821 | |||
| 822 | soc_pm.ws_ids = sama5d2_ws_ids; | ||
| 823 | soc_pm.config_shdwc_ws = at91_sama5d2_config_shdwc_ws; | ||
| 824 | soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws; | ||
| 799 | } | 825 | } |
| 800 | 826 | ||
| 801 | static int __init at91_pm_modes_select(char *str) | 827 | static int __init at91_pm_modes_select(char *str) |
