Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);