Skip to content

Commit f0bbf17

Browse files
claudiubezneanoglitch
authored andcommitted
ARM: at91: pm: add self-refresh support for sama7g5
Add self-refresh support for SAMA7G5. Signed-off-by: Claudiu Beznea <[email protected]> Signed-off-by: Nicolas Ferre <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d8c7983 commit f0bbf17

File tree

3 files changed

+203
-0
lines changed

3 files changed

+203
-0
lines changed

arch/arm/mach-at91/pm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/mfd/syscon/atmel-mc.h>
1313
#include <soc/at91/at91sam9_ddrsdr.h>
1414
#include <soc/at91/at91sam9_sdramc.h>
15+
#include <soc/at91/sama7-ddr.h>
1516

1617
#define AT91_MEMCTRL_MC 0
1718
#define AT91_MEMCTRL_SDRAMC 1
@@ -27,6 +28,7 @@
2728
struct at91_pm_data {
2829
void __iomem *pmc;
2930
void __iomem *ramc[2];
31+
void __iomem *ramc_phy;
3032
unsigned long uhp_udp_mask;
3133
unsigned int memctrl;
3234
unsigned int mode;

arch/arm/mach-at91/pm_data-offsets.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ int main(void)
88
DEFINE(PM_DATA_PMC, offsetof(struct at91_pm_data, pmc));
99
DEFINE(PM_DATA_RAMC0, offsetof(struct at91_pm_data, ramc[0]));
1010
DEFINE(PM_DATA_RAMC1, offsetof(struct at91_pm_data, ramc[1]));
11+
DEFINE(PM_DATA_RAMC_PHY, offsetof(struct at91_pm_data,
12+
ramc_phy));
1113
DEFINE(PM_DATA_MEMCTRL, offsetof(struct at91_pm_data, memctrl));
1214
DEFINE(PM_DATA_MODE, offsetof(struct at91_pm_data, mode));
1315
DEFINE(PM_DATA_SHDWC, offsetof(struct at91_pm_data, shdwc));

arch/arm/mach-at91/pm_suspend.S

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,200 @@ tmp3 .req r6
8787

8888
.arm
8989

90+
#ifdef CONFIG_SOC_SAMA7
91+
/**
92+
* Enable self-refresh
93+
*
94+
* Side effects: overwrites r2, r3, tmp1, tmp2, tmp3, r7
95+
*/
96+
.macro at91_sramc_self_refresh_ena
97+
ldr r2, .sramc_base
98+
ldr r3, .sramc_phy_base
99+
ldr r7, .pm_mode
100+
101+
dsb
102+
103+
/* Disable all AXI ports. */
104+
ldr tmp1, [r2, #UDDRC_PCTRL_0]
105+
bic tmp1, tmp1, #0x1
106+
str tmp1, [r2, #UDDRC_PCTRL_0]
107+
108+
ldr tmp1, [r2, #UDDRC_PCTRL_1]
109+
bic tmp1, tmp1, #0x1
110+
str tmp1, [r2, #UDDRC_PCTRL_1]
111+
112+
ldr tmp1, [r2, #UDDRC_PCTRL_2]
113+
bic tmp1, tmp1, #0x1
114+
str tmp1, [r2, #UDDRC_PCTRL_2]
115+
116+
ldr tmp1, [r2, #UDDRC_PCTRL_3]
117+
bic tmp1, tmp1, #0x1
118+
str tmp1, [r2, #UDDRC_PCTRL_3]
119+
120+
ldr tmp1, [r2, #UDDRC_PCTRL_4]
121+
bic tmp1, tmp1, #0x1
122+
str tmp1, [r2, #UDDRC_PCTRL_4]
123+
124+
sr_ena_1:
125+
/* Wait for all ports to disable. */
126+
ldr tmp1, [r2, #UDDRC_PSTAT]
127+
ldr tmp2, =UDDRC_PSTAT_ALL_PORTS
128+
tst tmp1, tmp2
129+
bne sr_ena_1
130+
131+
/* Switch to self-refresh. */
132+
ldr tmp1, [r2, #UDDRC_PWRCTL]
133+
orr tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
134+
str tmp1, [r2, #UDDRC_PWRCTL]
135+
136+
sr_ena_2:
137+
/* Wait for self-refresh enter. */
138+
ldr tmp1, [r2, #UDDRC_STAT]
139+
bic tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK
140+
cmp tmp1, #UDDRC_STAT_SELFREF_TYPE_SW
141+
bne sr_ena_2
142+
143+
/* Put DDR PHY's DLL in bypass mode for non-backup modes. */
144+
cmp r7, #AT91_PM_BACKUP
145+
beq sr_ena_3
146+
ldr tmp1, [r3, #DDR3PHY_PIR]
147+
orr tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
148+
str tmp1, [r3, #DDR3PHY_PIR]
149+
150+
sr_ena_3:
151+
/* Power down DDR PHY data receivers. */
152+
ldr tmp1, [r3, #DDR3PHY_DXCCR]
153+
orr tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
154+
str tmp1, [r3, #DDR3PHY_DXCCR]
155+
156+
/* Power down ADDR/CMD IO. */
157+
ldr tmp1, [r3, #DDR3PHY_ACIOCR]
158+
orr tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
159+
orr tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
160+
orr tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
161+
str tmp1, [r3, #DDR3PHY_ACIOCR]
162+
163+
/* Power down ODT. */
164+
ldr tmp1, [r3, #DDR3PHY_DSGCR]
165+
orr tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
166+
str tmp1, [r3, #DDR3PHY_DSGCR]
167+
.endm
168+
169+
/**
170+
* Disable self-refresh
171+
*
172+
* Side effects: overwrites r2, r3, tmp1, tmp2, tmp3
173+
*/
174+
.macro at91_sramc_self_refresh_dis
175+
ldr r2, .sramc_base
176+
ldr r3, .sramc_phy_base
177+
178+
/* Power up DDR PHY data receivers. */
179+
ldr tmp1, [r3, #DDR3PHY_DXCCR]
180+
bic tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
181+
str tmp1, [r3, #DDR3PHY_DXCCR]
182+
183+
/* Power up the output of CK and CS pins. */
184+
ldr tmp1, [r3, #DDR3PHY_ACIOCR]
185+
bic tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
186+
bic tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
187+
bic tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
188+
str tmp1, [r3, #DDR3PHY_ACIOCR]
189+
190+
/* Power up ODT. */
191+
ldr tmp1, [r3, #DDR3PHY_DSGCR]
192+
bic tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
193+
str tmp1, [r3, #DDR3PHY_DSGCR]
194+
195+
/* Take DDR PHY's DLL out of bypass mode. */
196+
ldr tmp1, [r3, #DDR3PHY_PIR]
197+
bic tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
198+
str tmp1, [r3, #DDR3PHY_PIR]
199+
200+
/* Enable quasi-dynamic programming. */
201+
mov tmp1, #0
202+
str tmp1, [r2, #UDDRC_SWCTRL]
203+
204+
/* De-assert SDRAM initialization. */
205+
ldr tmp1, [r2, #UDDRC_DFIMISC]
206+
bic tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
207+
str tmp1, [r2, #UDDRC_DFIMISC]
208+
209+
/* Quasi-dynamic programming done. */
210+
mov tmp1, #UDDRC_SWCTRL_SW_DONE
211+
str tmp1, [r2, #UDDRC_SWCTRL]
212+
213+
sr_dis_1:
214+
ldr tmp1, [r2, #UDDRC_SWSTAT]
215+
tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
216+
beq sr_dis_1
217+
218+
/* DLL soft-reset + DLL lock wait + ITM reset */
219+
mov tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \
220+
DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST)
221+
str tmp1, [r3, #DDR3PHY_PIR]
222+
223+
sr_dis_4:
224+
/* Wait for it. */
225+
ldr tmp1, [r3, #DDR3PHY_PGSR]
226+
tst tmp1, #DDR3PHY_PGSR_IDONE
227+
beq sr_dis_4
228+
229+
/* Enable quasi-dynamic programming. */
230+
mov tmp1, #0
231+
str tmp1, [r2, #UDDRC_SWCTRL]
232+
233+
/* Assert PHY init complete enable signal. */
234+
ldr tmp1, [r2, #UDDRC_DFIMISC]
235+
orr tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
236+
str tmp1, [r2, #UDDRC_DFIMISC]
237+
238+
/* Programming is done. Set sw_done. */
239+
mov tmp1, #UDDRC_SWCTRL_SW_DONE
240+
str tmp1, [r2, #UDDRC_SWCTRL]
241+
242+
sr_dis_5:
243+
/* Wait for it. */
244+
ldr tmp1, [r2, #UDDRC_SWSTAT]
245+
tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
246+
beq sr_dis_5
247+
248+
/* Trigger self-refresh exit. */
249+
ldr tmp1, [r2, #UDDRC_PWRCTL]
250+
bic tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
251+
str tmp1, [r2, #UDDRC_PWRCTL]
252+
253+
sr_dis_6:
254+
/* Wait for self-refresh exit done. */
255+
ldr tmp1, [r2, #UDDRC_STAT]
256+
bic tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK
257+
cmp tmp1, #UDDRC_STAT_OPMODE_NORMAL
258+
bne sr_dis_6
259+
260+
/* Enable all AXI ports. */
261+
ldr tmp1, [r2, #UDDRC_PCTRL_0]
262+
orr tmp1, tmp1, #0x1
263+
str tmp1, [r2, #UDDRC_PCTRL_0]
264+
265+
ldr tmp1, [r2, #UDDRC_PCTRL_1]
266+
orr tmp1, tmp1, #0x1
267+
str tmp1, [r2, #UDDRC_PCTRL_1]
268+
269+
ldr tmp1, [r2, #UDDRC_PCTRL_2]
270+
orr tmp1, tmp1, #0x1
271+
str tmp1, [r2, #UDDRC_PCTRL_2]
272+
273+
ldr tmp1, [r2, #UDDRC_PCTRL_3]
274+
orr tmp1, tmp1, #0x1
275+
str tmp1, [r2, #UDDRC_PCTRL_3]
276+
277+
ldr tmp1, [r2, #UDDRC_PCTRL_4]
278+
orr tmp1, tmp1, #0x1
279+
str tmp1, [r2, #UDDRC_PCTRL_4]
280+
281+
dsb
282+
.endm
283+
#else
90284
/**
91285
* Enable self-refresh
92286
*
@@ -228,6 +422,7 @@ sdramc_exit_sf:
228422

229423
sr_dis_exit:
230424
.endm
425+
#endif
231426

232427
.macro at91_pm_ulp0_mode
233428
ldr pmc, .pmc_base
@@ -668,6 +863,8 @@ ENTRY(at91_pm_suspend_in_sram)
668863
str tmp1, .sramc_base
669864
ldr tmp1, [r0, #PM_DATA_RAMC1]
670865
str tmp1, .sramc1_base
866+
ldr tmp1, [r0, #PM_DATA_RAMC_PHY]
867+
str tmp1, .sramc_phy_base
671868
ldr tmp1, [r0, #PM_DATA_MEMCTRL]
672869
str tmp1, .memtype
673870
ldr tmp1, [r0, #PM_DATA_MODE]
@@ -721,6 +918,8 @@ ENDPROC(at91_pm_suspend_in_sram)
721918
.word 0
722919
.sramc1_base:
723920
.word 0
921+
.sramc_phy_base:
922+
.word 0
724923
.shdwc:
725924
.word 0
726925
.sfrbu:

0 commit comments

Comments
 (0)