Lines Matching +full:suspend +full:- +full:mode

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * arch/arm/mach-at91/pm.c
16 #include <linux/suspend.h>
25 #include <asm/suspend.h>
34 * struct at91_pm_bu - AT91 power management backup unit data structure
35 * @suspended: true if suspended to backup mode
37 * @canary: canary data for memory checking after exit from backup mode
51 * struct at91_pm_sfrbu_regs - registers mapping for SFRBU
64 * enum at91_pm_eth_clk - Ethernet clock indexes
76 * enum at91_pm_eth - Ethernet controller indexes
88 * struct at91_pm_quirk_eth - AT91 PM Ethernet quirks
92 * @modes: power management mode that this quirk applies to
93 * @dns_modes: do not suspend modes: stop suspending if Ethernet is configured
106 * struct at91_pm_quirks - AT91 PM quirks
114 * struct at91_soc_pm - AT91 SoC power management data structure
118 * @bu: backup unit mapped data (for backup mode)
120 * @data: PM data to be used on last phase of suspend
125 int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
126 int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
136 * enum at91_pm_iomaps - IOs that needs to be mapped for different PM modes
159 { AT91_PM_ULP0_FAST, "ulp0-fast" },
162 { -1, NULL },
202 { .compatible = "atmel,sama5d2-gem", .data = &ws_info[0] },
203 { .compatible = "atmel,sama5d2-rtc", .data = &ws_info[1] },
204 { .compatible = "atmel,sama5d3-udc", .data = &ws_info[2] },
205 { .compatible = "atmel,at91rm9200-ohci", .data = &ws_info[2] },
206 { .compatible = "usb-ohci", .data = &ws_info[2] },
207 { .compatible = "atmel,at91sam9g45-ehci", .data = &ws_info[2] },
208 { .compatible = "usb-ehci", .data = &ws_info[2] },
209 { .compatible = "atmel,sama5d2-sdhci", .data = &ws_info[3] },
214 { .compatible = "microchip,sam9x60-rtc", .data = &ws_info[1] },
215 { .compatible = "atmel,at91rm9200-ohci", .data = &ws_info[2] },
216 { .compatible = "usb-ohci", .data = &ws_info[2] },
217 { .compatible = "atmel,at91sam9g45-ehci", .data = &ws_info[2] },
218 { .compatible = "usb-ehci", .data = &ws_info[2] },
219 { .compatible = "microchip,sam9x60-rtt", .data = &ws_info[4] },
220 { .compatible = "cdns,sam9x60-macb", .data = &ws_info[5] },
225 { .compatible = "microchip,sama7g5-rtc", .data = &ws_info[1] },
226 { .compatible = "microchip,sama7g5-ohci", .data = &ws_info[2] },
227 { .compatible = "usb-ohci", .data = &ws_info[2] },
228 { .compatible = "atmel,at91sam9g45-ehci", .data = &ws_info[2] },
229 { .compatible = "usb-ehci", .data = &ws_info[2] },
230 { .compatible = "microchip,sama7g5-sdhci", .data = &ws_info[3] },
231 { .compatible = "microchip,sama7g5-rtt", .data = &ws_info[4] },
241 unsigned int mode = 0, polarity = 0, val = 0; in at91_pm_config_ws() local
247 return -EPERM; in at91_pm_config_ws()
250 writel(mode, soc_pm.data.pmc + AT91_PMC_FSMR); in at91_pm_config_ws()
255 soc_pm.config_shdwc_ws(soc_pm.data.shdwc, &mode, &polarity); in at91_pm_config_ws()
266 if (device_may_wakeup(&pdev->dev)) { in at91_pm_config_ws()
267 wsi = match->data; in at91_pm_config_ws()
270 if (wsi->shdwc_mr_bit && !(val & wsi->shdwc_mr_bit)) in at91_pm_config_ws()
273 mode |= wsi->pmc_fsmr_bit; in at91_pm_config_ws()
274 if (wsi->set_polarity) in at91_pm_config_ws()
275 polarity |= wsi->pmc_fsmr_bit; in at91_pm_config_ws()
279 put_device(&pdev->dev); in at91_pm_config_ws()
282 if (mode) { in at91_pm_config_ws()
284 soc_pm.config_pmc_ws(soc_pm.data.pmc, mode, polarity); in at91_pm_config_ws()
289 return mode ? 0 : -EPERM; in at91_pm_config_ws()
292 static int at91_sama5d2_config_shdwc_ws(void __iomem *shdwc, u32 *mode, in at91_sama5d2_config_shdwc_ws() argument
299 *mode |= (val & 0x3ff); in at91_sama5d2_config_shdwc_ws()
305 static int at91_sama5d2_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity) in at91_sama5d2_config_pmc_ws() argument
307 writel(mode, pmc + AT91_PMC_FSMR); in at91_sama5d2_config_pmc_ws()
313 static int at91_sam9x60_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity) in at91_sam9x60_config_pmc_ws() argument
315 writel(mode, pmc + AT91_PMC_FSMR); in at91_sam9x60_config_pmc_ws()
325 if (!eth->np) in at91_pm_eth_quirk_is_valid()
328 /* No quirks for this interface and current suspend mode. */ in at91_pm_eth_quirk_is_valid()
329 if (!(eth->modes & BIT(soc_pm.data.mode))) in at91_pm_eth_quirk_is_valid()
332 if (!eth->dev) { in at91_pm_eth_quirk_is_valid()
334 pdev = of_find_device_by_node(eth->np); in at91_pm_eth_quirk_is_valid()
337 eth->dev = &pdev->dev; in at91_pm_eth_quirk_is_valid()
341 if (!device_may_wakeup(eth->dev)) { in at91_pm_eth_quirk_is_valid()
342 put_device(eth->dev); in at91_pm_eth_quirk_is_valid()
346 /* put_device(eth->dev) is called at the end of suspend. */ in at91_pm_eth_quirk_is_valid()
350 static int at91_pm_config_quirks(bool suspend) in at91_pm_config_quirks() argument
362 * here, in this file, if we suspend to ULP0 or ULP1 mode. Thus handle in at91_pm_config_quirks()
377 if (suspend && eth->dns_modes & BIT(soc_pm.data.mode)) { in at91_pm_config_quirks()
383 if (ws->dev == eth->dev) in at91_pm_config_quirks()
398 ret = -EPERM; in at91_pm_config_quirks()
399 put_device(eth->dev); in at91_pm_config_quirks()
400 eth->dev = NULL; in at91_pm_config_quirks()
402 i--; in at91_pm_config_quirks()
407 if (suspend) { in at91_pm_config_quirks()
408 clk_bulk_disable_unprepare(AT91_PM_ETH_MAX_CLK, eth->clks); in at91_pm_config_quirks()
411 eth->clks); in at91_pm_config_quirks()
415 * Release the reference to eth->dev taken in in at91_pm_config_quirks()
418 put_device(eth->dev); in at91_pm_config_quirks()
419 eth->dev = NULL; in at91_pm_config_quirks()
431 for (j = i; j >= 0; j--) { in at91_pm_config_quirks()
433 if (suspend) { in at91_pm_config_quirks()
437 tmp = clk_bulk_prepare_enable(AT91_PM_ETH_MAX_CLK, eth->clks); in at91_pm_config_quirks()
444 * Release the reference to eth->dev taken in in at91_pm_config_quirks()
447 put_device(eth->dev); in at91_pm_config_quirks()
448 eth->dev = NULL; in at91_pm_config_quirks()
464 soc_pm.data.mode = soc_pm.data.suspend_mode; in at91_pm_begin()
468 soc_pm.data.mode = soc_pm.data.standby_mode; in at91_pm_begin()
472 soc_pm.data.mode = -1; in at91_pm_begin()
475 ret = at91_pm_config_ws(soc_pm.data.mode, true); in at91_pm_begin()
479 if (soc_pm.data.mode == AT91_PM_BACKUP) in at91_pm_begin()
480 soc_pm.bu->suspended = 1; in at91_pm_begin()
482 soc_pm.bu->suspended = 0; in at91_pm_begin()
489 * slow-clock mode.
500 pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); in at91_pm_verify_clocks()
512 pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); in at91_pm_verify_clocks()
521 * Call this from platform driver suspend() to see how deeply to suspend.
524 * going into slow clock mode.
528 * to add one generic API rather than lots of platform-specific ones.
532 return (soc_pm.data.mode >= AT91_PM_ULP0); in at91_suspend_entering_slow_clock()
551 if (soc_pm.data.mode == AT91_PM_BACKUP && soc_pm.data.ramc_phy) { in at91_suspend_finish()
561 /* Store pull-down output impedance select. */ in at91_suspend_finish()
563 soc_pm.bu->ddr_phy_calibration[0] = modified_gray_code[index]; in at91_suspend_finish()
565 /* Store pull-up output impedance select. */ in at91_suspend_finish()
567 soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index]; in at91_suspend_finish()
569 /* Store pull-down on-die termination impedance select. */ in at91_suspend_finish()
571 soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index]; in at91_suspend_finish()
573 /* Store pull-up on-die termination impedance select. */ in at91_suspend_finish()
575 soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index]; in at91_suspend_finish()
583 soc_pm.bu->ddr_phy_calibration[i] = in at91_suspend_finish()
584 *((unsigned int *)soc_pm.memcs + (i - 1)); in at91_suspend_finish()
622 if (soc_pm.data.mode == AT91_PM_BACKUP) { in at91_pm_suspend()
627 /* The SRAM is lost between suspend cycles */ in at91_pm_suspend()
639 * STANDBY mode has *all* drivers suspended; ignores irqs not marked as 'wakeup'
643 * AT91_PM_ULP0 is like STANDBY plus slow clock mode, so drivers must
644 * suspend more deeply, the master clock switches to the clk32k and turns off
663 if (soc_pm.data.mode >= AT91_PM_ULP0 && in at91_pm_enter()
676 pr_debug("AT91: PM - bogus suspend state %d\n", state); in at91_pm_enter()
690 at91_pm_config_ws(soc_pm.data.mode, false); in at91_pm_end()
702 .name = "cpuidle-at91",
706 * The AT91RM9200 goes into self-refresh mode with this command, and will
707 * terminate self-refresh automatically on the next SDRAM access.
709 * Self-refresh mode is exited as soon as a memory access is made, but we don't
710 * know for sure when that happens. However, we need to restore the low-power
711 * mode if it was enabled before going idle. Restoring low-power mode while
712 * still in self-refresh is "not recommended", but seems to work.
732 /* Those two values allow us to delay self-refresh activation in at91_ddr_standby()
738 /* LPDDR1 --> force DDR2 mode during self-refresh */ in at91_ddr_standby()
762 /* self-refresh mode now */ in at91_ddr_standby()
811 /* self-refresh mode now */ in at91sam9_sdram_standby()
831 * Place RAM into self-refresh after a maximum idle clocks. The maximum in sama7g5_standby()
861 { .compatible = "atmel,at91rm9200-sdramc", .data = &ramc_infos[0] },
862 { .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] },
863 { .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] },
864 { .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] },
865 { .compatible = "microchip,sama7g5-uddrc", .data = &ramc_infos[4], },
870 { .compatible = "microchip,sama7g5-ddr3phy", },
887 ret = -ENOMEM; in at91_dt_ramc()
892 ramc = of_id->data; in at91_dt_ramc()
895 standby = ramc->idle; in at91_dt_ramc()
896 soc_pm.data.memctrl = ramc->memctrl; in at91_dt_ramc()
904 ret = -ENODEV; in at91_dt_ramc()
913 ret = -ENOMEM; in at91_dt_ramc()
921 ret = -ENODEV; in at91_dt_ramc()
936 iounmap(soc_pm.data.ramc[--idx]); in at91_dt_ramc()
945 * re-enabled by an interrupt or by a reset. in at91rm9200_idle()
964 for_each_compatible_node(node, NULL, "mmio-sram") { in at91_pm_sram_init()
977 sram_pool = gen_pool_get(&pdev->dev, NULL); in at91_pm_sram_init()
997 /* Copy the pm suspend handler to SRAM */ in at91_pm_sram_init()
1003 put_device(&pdev->dev); in at91_pm_sram_init()
1046 int ret = -ENODEV, located = 0; in at91_pm_backup_init()
1050 return -EPERM; in at91_pm_backup_init()
1055 np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam"); in at91_pm_backup_init()
1066 sram_pool = gen_pool_get(&pdev->dev, NULL); in at91_pm_backup_init()
1075 ret = -ENOMEM; in at91_pm_backup_init()
1079 soc_pm.bu->suspended = 0; in at91_pm_backup_init()
1080 soc_pm.bu->canary = __pa_symbol(&canary); in at91_pm_backup_init()
1081 soc_pm.bu->resume = __pa_symbol(cpu_resume); in at91_pm_backup_init()
1091 put_device(&pdev->dev); in at91_pm_backup_init()
1105 pr_info("AT91: Secure PM: suspend mode set to %s\n", in at91_pm_secure_init()
1110 pr_warn("AT91: Secure PM: %s mode not supported !\n", in at91_pm_secure_init()
1115 pr_warn("AT91: Secure PM: failed to get default mode\n"); in at91_pm_secure_init()
1119 pr_info("AT91: Secure PM: using default suspend mode %s\n", in at91_pm_secure_init()
1125 { .compatible = "atmel,sama5d2-shdwc" },
1126 { .compatible = "microchip,sam9x60-shdwc" },
1127 { .compatible = "microchip,sama7g5-shdwc" },
1132 { .compatible = "atmel,sama5d3-gem" },
1133 { .compatible = "atmel,sama5d2-gem" },
1134 { .compatible = "atmel,sama5d29-gem" },
1135 { .compatible = "microchip,sama7g5-gem" },
1140 { .compatible = "atmel,sama5d3-macb" },
1141 { .compatible = "microchip,sama7g5-emac" },
1146 * Replaces _mode_to_replace with a supported mode that doesn't depend
1149 * PM mode
1157 * PM mode
1181 * Replaces standby and suspend modes with default supported modes:
1183 * @_maps: u32 array indexed by AT91 PM mode containing AT91_PM_IOMAP()
1185 * @_map: controller specific name; standby and suspend mode need to be
1247 np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu"); in at91_pm_modes_init()
1270 gmac->np = np; in at91_pm_modes_init()
1271 at91_pm_get_eth_clks(np, gmac->clks); in at91_pm_modes_init()
1276 if (at91_pm_eth_clks_empty(gmac->clks)) in at91_pm_modes_init()
1280 emac->np = np; in at91_pm_modes_init()
1281 ret = at91_pm_get_eth_clks(np, emac->clks); in at91_pm_modes_init()
1282 if (ret && at91_pm_eth_clks_empty(gmac->clks)) { in at91_pm_modes_init()
1283 of_node_put(gmac->np); in at91_pm_modes_init()
1284 of_node_put(emac->np); in at91_pm_modes_init()
1285 gmac->np = NULL; in at91_pm_modes_init()
1286 emac->np = NULL; in at91_pm_modes_init()
1350 { .compatible = "atmel,at91rm9200-pmc", .data = &pmc_infos[0] },
1351 { .compatible = "atmel,at91sam9260-pmc", .data = &pmc_infos[1] },
1352 { .compatible = "atmel,at91sam9261-pmc", .data = &pmc_infos[1] },
1353 { .compatible = "atmel,at91sam9263-pmc", .data = &pmc_infos[1] },
1354 { .compatible = "atmel,at91sam9g45-pmc", .data = &pmc_infos[2] },
1355 { .compatible = "atmel,at91sam9n12-pmc", .data = &pmc_infos[1] },
1356 { .compatible = "atmel,at91sam9rl-pmc", .data = &pmc_infos[3] },
1357 { .compatible = "atmel,at91sam9x5-pmc", .data = &pmc_infos[1] },
1358 { .compatible = "atmel,sama5d3-pmc", .data = &pmc_infos[1] },
1359 { .compatible = "atmel,sama5d4-pmc", .data = &pmc_infos[1] },
1360 { .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
1361 { .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[4] },
1362 { .compatible = "microchip,sama7g5-pmc", .data = &pmc_infos[5] },
1368 u8 i, standby = 0, suspend = 0; in at91_pm_modes_validate() local
1369 int mode; in at91_pm_modes_validate() local
1372 if (standby && suspend) in at91_pm_modes_validate()
1380 if (modes[i] == soc_pm.data.suspend_mode && !suspend) { in at91_pm_modes_validate()
1381 suspend = 1; in at91_pm_modes_validate()
1388 mode = AT91_PM_ULP0; in at91_pm_modes_validate()
1390 mode = AT91_PM_STANDBY; in at91_pm_modes_validate()
1392 pr_warn("AT91: PM: %s mode not supported! Using %s.\n", in at91_pm_modes_validate()
1394 pm_modes[mode].pattern); in at91_pm_modes_validate()
1395 soc_pm.data.standby_mode = mode; in at91_pm_modes_validate()
1398 if (!suspend) { in at91_pm_modes_validate()
1400 mode = AT91_PM_STANDBY; in at91_pm_modes_validate()
1402 mode = AT91_PM_ULP0; in at91_pm_modes_validate()
1404 pr_warn("AT91: PM: %s mode not supported! Using %s.\n", in at91_pm_modes_validate()
1406 pm_modes[mode].pattern); in at91_pm_modes_validate()
1407 soc_pm.data.suspend_mode = mode; in at91_pm_modes_validate()
1428 pmc = of_id->data; in at91_pm_init()
1429 soc_pm.data.uhp_udp_mask = pmc->uhp_udp_mask; in at91_pm_init()
1430 soc_pm.data.pmc_mckr_offset = pmc->mckr; in at91_pm_init()
1431 soc_pm.data.pmc_version = pmc->version; in at91_pm_init()
1440 pr_info("AT91: PM: standby: %s, suspend: %s\n", in at91_pm_init()
1456 * Force STANDBY and ULP0 mode to avoid calling in at91rm9200_pm_init()
1468 * AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. in at91rm9200_pm_init()
1508 * Force STANDBY and ULP0 mode to avoid calling in at91sam9_pm_init()
1548 /* Do not suspend in ULP0, ULP0 fast if GETH is the only wakeup source. */ in sama5_pm_init()
1573 pr_warn("AT91: Secure PM: ignoring standby mode\n"); in sama5d2_pm_init()
1600 * Do not suspend in ULP0, ULP0 fast if GETH is the only wakeup in sama5d2_pm_init()
1651 int standby, suspend; in at91_pm_modes_select() local
1661 suspend = match_token(str, pm_modes, args); in at91_pm_modes_select()
1662 if (suspend < 0) in at91_pm_modes_select()
1666 soc_pm.data.suspend_mode = suspend; in at91_pm_modes_select()