ath25: switch default kernel to 5.15
[openwrt/openwrt.git] / target / linux / at91 / patches-5.10 / 228-ARM-at91-pm-switch-backup-area-to-vbat-in-backup-mod.patch
1 From 2cd84ddf0e9623c6bc723b1df368cd8b16a3a8e2 Mon Sep 17 00:00:00 2001
2 From: Claudiu Beznea <claudiu.beznea@microchip.com>
3 Date: Mon, 30 Aug 2021 13:09:27 +0300
4 Subject: [PATCH 228/247] ARM: at91: pm: switch backup area to vbat in backup
5 mode
6
7 Backup area is now switched to VDDIN33 at boot (with the help of
8 bootloader). When switching to backup mode we need to switch backup area
9 to VBAT as all the other power sources are cut off. The resuming from
10 backup mode is done with the help of bootloader, so there is no need to
11 do something particular in Linux to restore backup area power source.
12
13 Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
14 Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
15 Link: https://lore.kernel.org/r/20210830100927.22711-1-claudiu.beznea@microchip.com
16 ---
17 arch/arm/mach-at91/pm.c | 52 +++++++++++++++++++++++++++++++++++++++++
18 1 file changed, 52 insertions(+)
19
20 --- a/arch/arm/mach-at91/pm.c
21 +++ b/arch/arm/mach-at91/pm.c
22 @@ -47,12 +47,26 @@ struct at91_pm_bu {
23 unsigned long ddr_phy_calibration[BACKUP_DDR_PHY_CALIBRATION];
24 };
25
26 +/*
27 + * struct at91_pm_sfrbu_offsets: registers mapping for SFRBU
28 + * @pswbu: power switch BU control registers
29 + */
30 +struct at91_pm_sfrbu_regs {
31 + struct {
32 + u32 key;
33 + u32 ctrl;
34 + u32 state;
35 + u32 softsw;
36 + } pswbu;
37 +};
38 +
39 /**
40 * struct at91_soc_pm - AT91 SoC power management data structure
41 * @config_shdwc_ws: wakeup sources configuration function for SHDWC
42 * @config_pmc_ws: wakeup srouces configuration function for PMC
43 * @ws_ids: wakup sources of_device_id array
44 * @data: PM data to be used on last phase of suspend
45 + * @sfrbu_regs: SFRBU registers mapping
46 * @bu: backup unit mapped data (for backup mode)
47 * @memcs: memory chip select
48 */
49 @@ -62,6 +76,7 @@ struct at91_soc_pm {
50 const struct of_device_id *ws_ids;
51 struct at91_pm_bu *bu;
52 struct at91_pm_data data;
53 + struct at91_pm_sfrbu_regs sfrbu_regs;
54 void *memcs;
55 };
56
57 @@ -356,9 +371,36 @@ static int at91_suspend_finish(unsigned
58 return 0;
59 }
60
61 +static void at91_pm_switch_ba_to_vbat(void)
62 +{
63 + unsigned int offset = offsetof(struct at91_pm_sfrbu_regs, pswbu);
64 + unsigned int val;
65 +
66 + /* Just for safety. */
67 + if (!soc_pm.data.sfrbu)
68 + return;
69 +
70 + val = readl(soc_pm.data.sfrbu + offset);
71 +
72 + /* Already on VBAT. */
73 + if (!(val & soc_pm.sfrbu_regs.pswbu.state))
74 + return;
75 +
76 + val &= ~soc_pm.sfrbu_regs.pswbu.softsw;
77 + val |= soc_pm.sfrbu_regs.pswbu.key | soc_pm.sfrbu_regs.pswbu.ctrl;
78 + writel(val, soc_pm.data.sfrbu + offset);
79 +
80 + /* Wait for update. */
81 + val = readl(soc_pm.data.sfrbu + offset);
82 + while (val & soc_pm.sfrbu_regs.pswbu.state)
83 + val = readl(soc_pm.data.sfrbu + offset);
84 +}
85 +
86 static void at91_pm_suspend(suspend_state_t state)
87 {
88 if (soc_pm.data.mode == AT91_PM_BACKUP) {
89 + at91_pm_switch_ba_to_vbat();
90 +
91 cpu_suspend(0, at91_suspend_finish);
92
93 /* The SRAM is lost between suspend cycles */
94 @@ -1155,6 +1197,11 @@ void __init sama5d2_pm_init(void)
95 soc_pm.ws_ids = sama5d2_ws_ids;
96 soc_pm.config_shdwc_ws = at91_sama5d2_config_shdwc_ws;
97 soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws;
98 +
99 + soc_pm.sfrbu_regs.pswbu.key = (0x4BD20C << 8);
100 + soc_pm.sfrbu_regs.pswbu.ctrl = BIT(0);
101 + soc_pm.sfrbu_regs.pswbu.softsw = BIT(1);
102 + soc_pm.sfrbu_regs.pswbu.state = BIT(3);
103 }
104
105 void __init sama7_pm_init(void)
106 @@ -1185,6 +1232,11 @@ void __init sama7_pm_init(void)
107
108 soc_pm.ws_ids = sama7g5_ws_ids;
109 soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
110 +
111 + soc_pm.sfrbu_regs.pswbu.key = (0x4BD20C << 8);
112 + soc_pm.sfrbu_regs.pswbu.ctrl = BIT(0);
113 + soc_pm.sfrbu_regs.pswbu.softsw = BIT(1);
114 + soc_pm.sfrbu_regs.pswbu.state = BIT(2);
115 }
116
117 static int __init at91_pm_modes_select(char *str)