^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * arch/arm/mach-at91/pm.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * AT91 Power Management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2005 David Brownell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/genalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/parser.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/clk/at91_pmc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/platform_data/atmel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/fncpy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/system_misc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "generic.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "pm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * FIXME: this is needed to communicate between the pinctrl driver and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * the PM implementation in the machine. Possibly part of the PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * implementation should be moved down into the pinctrl driver and get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * called as part of the generic suspend/resume path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #ifdef CONFIG_PINCTRL_AT91
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) extern void at91_pinctrl_gpio_suspend(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) extern void at91_pinctrl_gpio_resume(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct at91_soc_pm {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) const struct of_device_id *ws_ids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct at91_pm_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static struct at91_soc_pm soc_pm = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .standby_mode = AT91_PM_STANDBY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .suspend_mode = AT91_PM_ULP0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static const match_table_t pm_modes __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { AT91_PM_STANDBY, "standby" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { AT91_PM_ULP0, "ulp0" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { AT91_PM_ULP0_FAST, "ulp0-fast" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { AT91_PM_ULP1, "ulp1" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { AT91_PM_BACKUP, "backup" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { -1, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define at91_ramc_read(id, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) __raw_readl(soc_pm.data.ramc[id] + field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define at91_ramc_write(id, field, value) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) __raw_writel(value, soc_pm.data.ramc[id] + field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int at91_pm_valid_state(suspend_state_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case PM_SUSPEND_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) case PM_SUSPEND_STANDBY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) case PM_SUSPEND_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int canary = 0xA5A5A5A5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static struct at91_pm_bu {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int suspended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned long reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) phys_addr_t canary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) phys_addr_t resume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) } *pm_bu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct wakeup_source_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned int pmc_fsmr_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned int shdwc_mr_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) bool set_polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static const struct wakeup_source_info ws_info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) { .pmc_fsmr_bit = AT91_PMC_FSTT(10), .set_polarity = true },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { .pmc_fsmr_bit = AT91_PMC_RTCAL, .shdwc_mr_bit = BIT(17) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) { .pmc_fsmr_bit = AT91_PMC_USBAL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) { .pmc_fsmr_bit = AT91_PMC_SDMMC_CD },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { .pmc_fsmr_bit = AT91_PMC_RTTAL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { .pmc_fsmr_bit = AT91_PMC_RXLP_MCE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static const struct of_device_id sama5d2_ws_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) { .compatible = "atmel,sama5d2-gem", .data = &ws_info[0] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) { .compatible = "atmel,at91rm9200-rtc", .data = &ws_info[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { .compatible = "atmel,sama5d3-udc", .data = &ws_info[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) { .compatible = "atmel,at91rm9200-ohci", .data = &ws_info[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) { .compatible = "usb-ohci", .data = &ws_info[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) { .compatible = "atmel,at91sam9g45-ehci", .data = &ws_info[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) { .compatible = "usb-ehci", .data = &ws_info[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { .compatible = "atmel,sama5d2-sdhci", .data = &ws_info[3] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static const struct of_device_id sam9x60_ws_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { .compatible = "atmel,at91sam9x5-rtc", .data = &ws_info[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) { .compatible = "atmel,at91rm9200-ohci", .data = &ws_info[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) { .compatible = "usb-ohci", .data = &ws_info[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) { .compatible = "atmel,at91sam9g45-ehci", .data = &ws_info[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) { .compatible = "usb-ehci", .data = &ws_info[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) { .compatible = "atmel,at91sam9260-rtt", .data = &ws_info[4] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) { .compatible = "cdns,sam9x60-macb", .data = &ws_info[5] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int at91_pm_config_ws(unsigned int pm_mode, bool set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) const struct wakeup_source_info *wsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) unsigned int mode = 0, polarity = 0, val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (pm_mode != AT91_PM_ULP1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!soc_pm.data.pmc || !soc_pm.data.shdwc || !soc_pm.ws_ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (!set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) writel(mode, soc_pm.data.pmc + AT91_PMC_FSMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (soc_pm.config_shdwc_ws)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) soc_pm.config_shdwc_ws(soc_pm.data.shdwc, &mode, &polarity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* SHDWC.MR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) val = readl(soc_pm.data.shdwc + 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* Loop through defined wakeup sources. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) for_each_matching_node_and_match(np, soc_pm.ws_ids, &match) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) pdev = of_find_device_by_node(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (!pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (device_may_wakeup(&pdev->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) wsi = match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Check if enabled on SHDWC. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (wsi->shdwc_mr_bit && !(val & wsi->shdwc_mr_bit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) goto put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) mode |= wsi->pmc_fsmr_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (wsi->set_polarity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) polarity |= wsi->pmc_fsmr_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) put_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) put_device(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (soc_pm.config_pmc_ws)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) soc_pm.config_pmc_ws(soc_pm.data.pmc, mode, polarity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) pr_err("AT91: PM: no ULP1 wakeup sources found!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return mode ? 0 : -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int at91_sama5d2_config_shdwc_ws(void __iomem *shdwc, u32 *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) u32 *polarity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* SHDWC.WUIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) val = readl(shdwc + 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) *mode |= (val & 0x3ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) *polarity |= ((val >> 16) & 0x3ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int at91_sama5d2_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) writel(mode, pmc + AT91_PMC_FSMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) writel(polarity, pmc + AT91_PMC_FSPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int at91_sam9x60_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) writel(mode, pmc + AT91_PMC_FSMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * Called after processes are frozen, but before we shutdown devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static int at91_pm_begin(suspend_state_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case PM_SUSPEND_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) soc_pm.data.mode = soc_pm.data.suspend_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) case PM_SUSPEND_STANDBY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) soc_pm.data.mode = soc_pm.data.standby_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) soc_pm.data.mode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return at91_pm_config_ws(soc_pm.data.mode, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * Verify that all the clocks are correct before entering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * slow-clock mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static int at91_pm_verify_clocks(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) unsigned long scsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) scsr = readl(soc_pm.data.pmc + AT91_PMC_SCSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* USB must not be using PLLB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if ((scsr & soc_pm.data.uhp_udp_mask) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* PCK0..PCK3 must be disabled, or configured to use clk32k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u32 css;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) css = readl(soc_pm.data.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (css != AT91_PMC_CSS_SLOW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * Call this from platform driver suspend() to see how deeply to suspend.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * For example, some controllers (like OHCI) need one of the PLL clocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * in order to act as a wakeup source, and those are not available when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * going into slow clock mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * REVISIT: generalize as clk_will_be_available(clk)? Other platforms have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * the very same problem (but not using at91 main_clk), and it'd be better
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * to add one generic API rather than lots of platform-specific ones.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) int at91_suspend_entering_slow_clock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return (soc_pm.data.mode >= AT91_PM_ULP0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static void (*at91_suspend_sram_fn)(struct at91_pm_data *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) extern void at91_pm_suspend_in_sram(struct at91_pm_data *pm_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) extern u32 at91_pm_suspend_in_sram_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int at91_suspend_finish(unsigned long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) flush_cache_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) outer_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) at91_suspend_sram_fn(&soc_pm.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static void at91_pm_suspend(suspend_state_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (soc_pm.data.mode == AT91_PM_BACKUP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) pm_bu->suspended = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) cpu_suspend(0, at91_suspend_finish);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* The SRAM is lost between suspend cycles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) &at91_pm_suspend_in_sram,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) at91_pm_suspend_in_sram_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) at91_suspend_finish(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) outer_resume();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * STANDBY mode has *all* drivers suspended; ignores irqs not marked as 'wakeup'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * event sources; and reduces DRAM power. But otherwise it's identical to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * PM_SUSPEND_ON: cpu idle, and nothing fancy done with main or cpu clocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * AT91_PM_ULP0 is like STANDBY plus slow clock mode, so drivers must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * suspend more deeply, the master clock switches to the clk32k and turns off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * the main oscillator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * AT91_PM_BACKUP turns off the whole SoC after placing the DDR in self refresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static int at91_pm_enter(suspend_state_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) #ifdef CONFIG_PINCTRL_AT91
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) at91_pinctrl_gpio_suspend();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) case PM_SUSPEND_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) case PM_SUSPEND_STANDBY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * Ensure that clocks are in a valid state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (soc_pm.data.mode >= AT91_PM_ULP0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) !at91_pm_verify_clocks())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) at91_pm_suspend(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case PM_SUSPEND_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) cpu_do_idle();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) pr_debug("AT91: PM - bogus suspend state %d\n", state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) #ifdef CONFIG_PINCTRL_AT91
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) at91_pinctrl_gpio_resume();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * Called right prior to thawing processes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static void at91_pm_end(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) at91_pm_config_ws(soc_pm.data.mode, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static const struct platform_suspend_ops at91_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .valid = at91_pm_valid_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .begin = at91_pm_begin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .enter = at91_pm_enter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) .end = at91_pm_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static struct platform_device at91_cpuidle_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .name = "cpuidle-at91",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * The AT91RM9200 goes into self-refresh mode with this command, and will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * terminate self-refresh automatically on the next SDRAM access.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * Self-refresh mode is exited as soon as a memory access is made, but we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * know for sure when that happens. However, we need to restore the low-power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * mode if it was enabled before going idle. Restoring low-power mode while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * still in self-refresh is "not recommended", but seems to work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static void at91rm9200_standby(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) "b 1f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) ".align 5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) "1: mcr p15, 0, %0, c7, c10, 4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) " str %2, [%1, %3]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) " mcr p15, 0, %0, c7, c0, 4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) : "r" (0), "r" (soc_pm.data.ramc[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) "r" (1), "r" (AT91_MC_SDRAMC_SRR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* We manage both DDRAM/SDRAM controllers, we need more than one value to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * remember.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static void at91_ddr_standby(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /* Those two values allow us to delay self-refresh activation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * to the maximum. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) u32 lpr0, lpr1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) u32 mdr, saved_mdr0, saved_mdr1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) u32 saved_lpr0, saved_lpr1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* LPDDR1 --> force DDR2 mode during self-refresh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) saved_mdr0 = at91_ramc_read(0, AT91_DDRSDRC_MDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if ((saved_mdr0 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) mdr = saved_mdr0 & ~AT91_DDRSDRC_MD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) mdr |= AT91_DDRSDRC_MD_DDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) at91_ramc_write(0, AT91_DDRSDRC_MDR, mdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (soc_pm.data.ramc[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) saved_mdr1 = at91_ramc_read(1, AT91_DDRSDRC_MDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if ((saved_mdr1 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) mdr = saved_mdr1 & ~AT91_DDRSDRC_MD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) mdr |= AT91_DDRSDRC_MD_DDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) at91_ramc_write(1, AT91_DDRSDRC_MDR, mdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) lpr0 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* self-refresh mode now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (soc_pm.data.ramc[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) cpu_do_idle();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (soc_pm.data.ramc[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static void sama5d3_ddr_standby(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) u32 lpr0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) u32 saved_lpr0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) lpr0 |= AT91_DDRSDRC_LPCB_POWER_DOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) cpu_do_idle();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* We manage both DDRAM/SDRAM controllers, we need more than one value to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * remember.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static void at91sam9_sdram_standby(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) u32 lpr0, lpr1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) u32 saved_lpr0, saved_lpr1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (soc_pm.data.ramc[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) saved_lpr0 = at91_ramc_read(0, AT91_SDRAMC_LPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) lpr0 = saved_lpr0 & ~AT91_SDRAMC_LPCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) lpr0 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /* self-refresh mode now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (soc_pm.data.ramc[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) cpu_do_idle();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (soc_pm.data.ramc[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct ramc_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) void (*idle)(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) unsigned int memctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static const struct ramc_info ramc_infos[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) { .idle = at91rm9200_standby, .memctrl = AT91_MEMCTRL_MC},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) { .idle = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) { .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) { .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static const struct of_device_id ramc_ids[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) { .compatible = "atmel,at91rm9200-sdramc", .data = &ramc_infos[0] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) { .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) { .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) { .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) { /*sentinel*/ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) static __init int at91_dt_ramc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) const struct of_device_id *of_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) int idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) void *standby = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) const struct ramc_info *ramc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) for_each_matching_node_and_match(np, ramc_ids, &of_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) soc_pm.data.ramc[idx] = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (!soc_pm.data.ramc[idx]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) pr_err("unable to map ramc[%d] cpu registers\n", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) goto unmap_ramc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ramc = of_id->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!standby)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) standby = ramc->idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) soc_pm.data.memctrl = ramc->memctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (!idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) pr_err("unable to find compatible ram controller node in dtb\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) goto unmap_ramc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (!standby) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) pr_warn("ramc no standby function available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) at91_cpuidle_device.dev.platform_data = standby;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) unmap_ramc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) while (idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) iounmap(soc_pm.data.ramc[--idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static void at91rm9200_idle(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * Disable the processor clock. The processor will be automatically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * re-enabled by an interrupt or by a reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) writel(AT91_PMC_PCK, soc_pm.data.pmc + AT91_PMC_SCDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) static void at91sam9_idle(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) writel(AT91_PMC_PCK, soc_pm.data.pmc + AT91_PMC_SCDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) cpu_do_idle();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static void __init at91_pm_sram_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct gen_pool *sram_pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) phys_addr_t sram_pbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) unsigned long sram_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) struct platform_device *pdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) for_each_compatible_node(node, NULL, "mmio-sram") {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) pdev = of_find_device_by_node(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (!pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) pr_warn("%s: failed to find sram device!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) sram_pool = gen_pool_get(&pdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (!sram_pool) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) pr_warn("%s: sram pool unavailable!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) goto out_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) sram_base = gen_pool_alloc(sram_pool, at91_pm_suspend_in_sram_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (!sram_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) pr_warn("%s: unable to alloc sram!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) goto out_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) at91_suspend_sram_fn = __arm_ioremap_exec(sram_pbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) at91_pm_suspend_in_sram_sz, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (!at91_suspend_sram_fn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) pr_warn("SRAM: Could not map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) goto out_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /* Copy the pm suspend handler to SRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) out_put_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) put_device(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) static bool __init at91_is_pm_mode_active(int pm_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return (soc_pm.data.standby_mode == pm_mode ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) soc_pm.data.suspend_mode == pm_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static int __init at91_pm_backup_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) struct gen_pool *sram_pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct platform_device *pdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) int ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) pr_warn("%s: failed to find sfrbu!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) soc_pm.data.sfrbu = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (!np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) goto securam_fail_no_ref_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) pdev = of_find_device_by_node(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (!pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) pr_warn("%s: failed to find securam device!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) goto securam_fail_no_ref_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) sram_pool = gen_pool_get(&pdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (!sram_pool) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) pr_warn("%s: securam pool unavailable!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) goto securam_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (!pm_bu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) pr_warn("%s: unable to alloc securam!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) goto securam_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) pm_bu->suspended = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) pm_bu->canary = __pa_symbol(&canary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) pm_bu->resume = __pa_symbol(cpu_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) securam_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) put_device(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) securam_fail_no_ref_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) iounmap(soc_pm.data.sfrbu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) soc_pm.data.sfrbu = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static void __init at91_pm_use_default_mode(int pm_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (soc_pm.data.standby_mode == pm_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) soc_pm.data.standby_mode = AT91_PM_ULP0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (soc_pm.data.suspend_mode == pm_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) soc_pm.data.suspend_mode = AT91_PM_ULP0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) static const struct of_device_id atmel_shdwc_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) { .compatible = "atmel,sama5d2-shdwc" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) { .compatible = "microchip,sam9x60-shdwc" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) { /* sentinel. */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static void __init at91_pm_modes_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) !at91_is_pm_mode_active(AT91_PM_ULP1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) np = of_find_matching_node(NULL, atmel_shdwc_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) pr_warn("%s: failed to find shdwc!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) goto ulp1_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) soc_pm.data.shdwc = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ret = at91_pm_backup_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (!at91_is_pm_mode_active(AT91_PM_ULP1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) goto unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) goto backup_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) iounmap(soc_pm.data.shdwc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) soc_pm.data.shdwc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) ulp1_default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) at91_pm_use_default_mode(AT91_PM_ULP1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) backup_default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) at91_pm_use_default_mode(AT91_PM_BACKUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct pmc_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) unsigned long uhp_udp_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) unsigned long mckr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) unsigned long version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static const struct pmc_info pmc_infos[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) .uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) .mckr = 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) .version = AT91_PMC_V1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) .mckr = 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .version = AT91_PMC_V1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .uhp_udp_mask = AT91SAM926x_PMC_UHP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) .mckr = 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .version = AT91_PMC_V1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) { .uhp_udp_mask = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) .mckr = 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .version = AT91_PMC_V1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) .mckr = 0x28,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) .version = AT91_PMC_V2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) static const struct of_device_id atmel_pmc_ids[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) { .compatible = "atmel,at91rm9200-pmc", .data = &pmc_infos[0] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) { .compatible = "atmel,at91sam9260-pmc", .data = &pmc_infos[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) { .compatible = "atmel,at91sam9261-pmc", .data = &pmc_infos[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) { .compatible = "atmel,at91sam9263-pmc", .data = &pmc_infos[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) { .compatible = "atmel,at91sam9g45-pmc", .data = &pmc_infos[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) { .compatible = "atmel,at91sam9n12-pmc", .data = &pmc_infos[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) { .compatible = "atmel,at91sam9rl-pmc", .data = &pmc_infos[3] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) { .compatible = "atmel,at91sam9x5-pmc", .data = &pmc_infos[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) { .compatible = "atmel,sama5d3-pmc", .data = &pmc_infos[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) { .compatible = "atmel,sama5d4-pmc", .data = &pmc_infos[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) { .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) { .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[4] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) { /* sentinel */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) static void __init at91_pm_modes_validate(const int *modes, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) u8 i, standby = 0, suspend = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (standby && suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (modes[i] == soc_pm.data.standby_mode && !standby) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) standby = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (modes[i] == soc_pm.data.suspend_mode && !suspend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) suspend = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (!standby) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (soc_pm.data.suspend_mode == AT91_PM_STANDBY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) mode = AT91_PM_ULP0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) mode = AT91_PM_STANDBY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) pr_warn("AT91: PM: %s mode not supported! Using %s.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) pm_modes[soc_pm.data.standby_mode].pattern,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) pm_modes[mode].pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) soc_pm.data.standby_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (!suspend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (soc_pm.data.standby_mode == AT91_PM_ULP0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) mode = AT91_PM_STANDBY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) mode = AT91_PM_ULP0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) pr_warn("AT91: PM: %s mode not supported! Using %s.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) pm_modes[soc_pm.data.suspend_mode].pattern,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) pm_modes[mode].pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) soc_pm.data.suspend_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static void __init at91_pm_init(void (*pm_idle)(void))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct device_node *pmc_np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) const struct of_device_id *of_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) const struct pmc_info *pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (at91_cpuidle_device.dev.platform_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) platform_device_register(&at91_cpuidle_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) soc_pm.data.pmc = of_iomap(pmc_np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) of_node_put(pmc_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (!soc_pm.data.pmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) pr_err("AT91: PM not supported, PMC not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) pmc = of_id->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) soc_pm.data.uhp_udp_mask = pmc->uhp_udp_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) soc_pm.data.pmc_mckr_offset = pmc->mckr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) soc_pm.data.pmc_version = pmc->version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (pm_idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) arm_pm_idle = pm_idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) at91_pm_sram_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (at91_suspend_sram_fn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) suspend_set_ops(&at91_pm_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) pr_info("AT91: PM: standby: %s, suspend: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) pm_modes[soc_pm.data.standby_mode].pattern,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) pm_modes[soc_pm.data.suspend_mode].pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) pr_info("AT91: PM not supported, due to no SRAM allocated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) void __init at91rm9200_pm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (!IS_ENABLED(CONFIG_SOC_AT91RM9200))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) * Force STANDBY and ULP0 mode to avoid calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) * at91_pm_modes_validate() which may increase booting time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * Platform supports anyway only STANDBY and ULP0 modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) soc_pm.data.standby_mode = AT91_PM_STANDBY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) soc_pm.data.suspend_mode = AT91_PM_ULP0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) ret = at91_dt_ramc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) * AT91RM9200 SDRAM low-power mode cannot be used with self-refresh.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) at91_ramc_write(0, AT91_MC_SDRAMC_LPR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) at91_pm_init(at91rm9200_idle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) void __init sam9x60_pm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static const int modes[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (!IS_ENABLED(CONFIG_SOC_SAM9X60))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) at91_pm_modes_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) ret = at91_dt_ramc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) at91_pm_init(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) soc_pm.ws_ids = sam9x60_ws_ids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) void __init at91sam9_pm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (!IS_ENABLED(CONFIG_SOC_AT91SAM9))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) * Force STANDBY and ULP0 mode to avoid calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * at91_pm_modes_validate() which may increase booting time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) * Platform supports anyway only STANDBY and ULP0 modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) soc_pm.data.standby_mode = AT91_PM_STANDBY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) soc_pm.data.suspend_mode = AT91_PM_ULP0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ret = at91_dt_ramc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) at91_pm_init(at91sam9_idle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) void __init sama5_pm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) static const int modes[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (!IS_ENABLED(CONFIG_SOC_SAMA5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) ret = at91_dt_ramc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) at91_pm_init(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) void __init sama5d2_pm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) static const int modes[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) AT91_PM_BACKUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) at91_pm_modes_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) ret = at91_dt_ramc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) at91_pm_init(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) soc_pm.ws_ids = sama5d2_ws_ids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) soc_pm.config_shdwc_ws = at91_sama5d2_config_shdwc_ws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) static int __init at91_pm_modes_select(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) substring_t args[MAX_OPT_ARGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) int standby, suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (!str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) s = strsep(&str, ",");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) standby = match_token(s, pm_modes, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (standby < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) suspend = match_token(str, pm_modes, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (suspend < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) soc_pm.data.standby_mode = standby;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) soc_pm.data.suspend_mode = suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) early_param("atmel.pm_modes", at91_pm_modes_select);