mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	ARM: at91: pm: add self-refresh support for sama7g5
Add self-refresh support for SAMA7G5. Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com> Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com> Link: https://lore.kernel.org/r/20210415105010.569620-13-claudiu.beznea@microchip.com
This commit is contained in:
		
							parent
							
								
									d8c7983f31
								
							
						
					
					
						commit
						f0bbf17958
					
				
					 3 changed files with 203 additions and 0 deletions
				
			
		| 
						 | 
					@ -12,6 +12,7 @@
 | 
				
			||||||
#include <linux/mfd/syscon/atmel-mc.h>
 | 
					#include <linux/mfd/syscon/atmel-mc.h>
 | 
				
			||||||
#include <soc/at91/at91sam9_ddrsdr.h>
 | 
					#include <soc/at91/at91sam9_ddrsdr.h>
 | 
				
			||||||
#include <soc/at91/at91sam9_sdramc.h>
 | 
					#include <soc/at91/at91sam9_sdramc.h>
 | 
				
			||||||
 | 
					#include <soc/at91/sama7-ddr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define AT91_MEMCTRL_MC		0
 | 
					#define AT91_MEMCTRL_MC		0
 | 
				
			||||||
#define AT91_MEMCTRL_SDRAMC	1
 | 
					#define AT91_MEMCTRL_SDRAMC	1
 | 
				
			||||||
| 
						 | 
					@ -27,6 +28,7 @@
 | 
				
			||||||
struct at91_pm_data {
 | 
					struct at91_pm_data {
 | 
				
			||||||
	void __iomem *pmc;
 | 
						void __iomem *pmc;
 | 
				
			||||||
	void __iomem *ramc[2];
 | 
						void __iomem *ramc[2];
 | 
				
			||||||
 | 
						void __iomem *ramc_phy;
 | 
				
			||||||
	unsigned long uhp_udp_mask;
 | 
						unsigned long uhp_udp_mask;
 | 
				
			||||||
	unsigned int memctrl;
 | 
						unsigned int memctrl;
 | 
				
			||||||
	unsigned int mode;
 | 
						unsigned int mode;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,8 @@ int main(void)
 | 
				
			||||||
	DEFINE(PM_DATA_PMC,		offsetof(struct at91_pm_data, pmc));
 | 
						DEFINE(PM_DATA_PMC,		offsetof(struct at91_pm_data, pmc));
 | 
				
			||||||
	DEFINE(PM_DATA_RAMC0,		offsetof(struct at91_pm_data, ramc[0]));
 | 
						DEFINE(PM_DATA_RAMC0,		offsetof(struct at91_pm_data, ramc[0]));
 | 
				
			||||||
	DEFINE(PM_DATA_RAMC1,		offsetof(struct at91_pm_data, ramc[1]));
 | 
						DEFINE(PM_DATA_RAMC1,		offsetof(struct at91_pm_data, ramc[1]));
 | 
				
			||||||
 | 
						DEFINE(PM_DATA_RAMC_PHY,	offsetof(struct at91_pm_data,
 | 
				
			||||||
 | 
											 ramc_phy));
 | 
				
			||||||
	DEFINE(PM_DATA_MEMCTRL,	offsetof(struct at91_pm_data, memctrl));
 | 
						DEFINE(PM_DATA_MEMCTRL,	offsetof(struct at91_pm_data, memctrl));
 | 
				
			||||||
	DEFINE(PM_DATA_MODE,		offsetof(struct at91_pm_data, mode));
 | 
						DEFINE(PM_DATA_MODE,		offsetof(struct at91_pm_data, mode));
 | 
				
			||||||
	DEFINE(PM_DATA_SHDWC,		offsetof(struct at91_pm_data, shdwc));
 | 
						DEFINE(PM_DATA_SHDWC,		offsetof(struct at91_pm_data, shdwc));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,6 +87,200 @@ tmp3	.req	r6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.arm
 | 
						.arm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_SOC_SAMA7
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Enable self-refresh
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3, r7
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					.macro at91_sramc_self_refresh_ena
 | 
				
			||||||
 | 
						ldr	r2, .sramc_base
 | 
				
			||||||
 | 
						ldr	r3, .sramc_phy_base
 | 
				
			||||||
 | 
						ldr	r7, .pm_mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dsb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Disable all AXI ports. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PCTRL_0]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #0x1
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PCTRL_0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PCTRL_1]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #0x1
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PCTRL_1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PCTRL_2]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #0x1
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PCTRL_2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PCTRL_3]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #0x1
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PCTRL_3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PCTRL_4]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #0x1
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PCTRL_4]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sr_ena_1:
 | 
				
			||||||
 | 
						/* Wait for all ports to disable. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PSTAT]
 | 
				
			||||||
 | 
						ldr	tmp2, =UDDRC_PSTAT_ALL_PORTS
 | 
				
			||||||
 | 
						tst	tmp1, tmp2
 | 
				
			||||||
 | 
						bne	sr_ena_1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Switch to self-refresh. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PWRCTL]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PWRCTL]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sr_ena_2:
 | 
				
			||||||
 | 
						/* Wait for self-refresh enter. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_STAT]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK
 | 
				
			||||||
 | 
						cmp	tmp1, #UDDRC_STAT_SELFREF_TYPE_SW
 | 
				
			||||||
 | 
						bne	sr_ena_2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Put DDR PHY's DLL in bypass mode for non-backup modes. */
 | 
				
			||||||
 | 
						cmp	r7, #AT91_PM_BACKUP
 | 
				
			||||||
 | 
						beq	sr_ena_3
 | 
				
			||||||
 | 
						ldr	tmp1, [r3, #DDR3PHY_PIR]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
 | 
				
			||||||
 | 
						str	tmp1, [r3, #DDR3PHY_PIR]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sr_ena_3:
 | 
				
			||||||
 | 
						/* Power down DDR PHY data receivers. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r3, #DDR3PHY_DXCCR]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
 | 
				
			||||||
 | 
						str	tmp1, [r3, #DDR3PHY_DXCCR]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Power down ADDR/CMD IO. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r3, #DDR3PHY_ACIOCR]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
 | 
				
			||||||
 | 
						str	tmp1, [r3, #DDR3PHY_ACIOCR]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Power down ODT. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r3, #DDR3PHY_DSGCR]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
 | 
				
			||||||
 | 
						str	tmp1, [r3, #DDR3PHY_DSGCR]
 | 
				
			||||||
 | 
					.endm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Disable self-refresh
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					.macro at91_sramc_self_refresh_dis
 | 
				
			||||||
 | 
						ldr	r2, .sramc_base
 | 
				
			||||||
 | 
						ldr	r3, .sramc_phy_base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Power up DDR PHY data receivers. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r3, #DDR3PHY_DXCCR]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
 | 
				
			||||||
 | 
						str	tmp1, [r3, #DDR3PHY_DXCCR]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Power up the output of CK and CS pins. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r3, #DDR3PHY_ACIOCR]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
 | 
				
			||||||
 | 
						str	tmp1, [r3, #DDR3PHY_ACIOCR]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Power up ODT. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r3, #DDR3PHY_DSGCR]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
 | 
				
			||||||
 | 
						str	tmp1, [r3, #DDR3PHY_DSGCR]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Take DDR PHY's DLL out of bypass mode. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r3, #DDR3PHY_PIR]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
 | 
				
			||||||
 | 
						str	tmp1, [r3, #DDR3PHY_PIR]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Enable quasi-dynamic programming. */
 | 
				
			||||||
 | 
						mov	tmp1, #0
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_SWCTRL]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* De-assert SDRAM initialization. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_DFIMISC]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_DFIMISC]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Quasi-dynamic programming done. */
 | 
				
			||||||
 | 
						mov	tmp1, #UDDRC_SWCTRL_SW_DONE
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_SWCTRL]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sr_dis_1:
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_SWSTAT]
 | 
				
			||||||
 | 
						tst	tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
 | 
				
			||||||
 | 
						beq	sr_dis_1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* DLL soft-reset + DLL lock wait + ITM reset */
 | 
				
			||||||
 | 
						mov	tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \
 | 
				
			||||||
 | 
								DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST)
 | 
				
			||||||
 | 
						str	tmp1, [r3, #DDR3PHY_PIR]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sr_dis_4:
 | 
				
			||||||
 | 
						/* Wait for it. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r3, #DDR3PHY_PGSR]
 | 
				
			||||||
 | 
						tst	tmp1, #DDR3PHY_PGSR_IDONE
 | 
				
			||||||
 | 
						beq	sr_dis_4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Enable quasi-dynamic programming. */
 | 
				
			||||||
 | 
						mov	tmp1, #0
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_SWCTRL]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Assert PHY init complete enable signal. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_DFIMISC]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_DFIMISC]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Programming is done. Set sw_done. */
 | 
				
			||||||
 | 
						mov	tmp1, #UDDRC_SWCTRL_SW_DONE
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_SWCTRL]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sr_dis_5:
 | 
				
			||||||
 | 
						/* Wait for it. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_SWSTAT]
 | 
				
			||||||
 | 
						tst	tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
 | 
				
			||||||
 | 
						beq	sr_dis_5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Trigger self-refresh exit. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PWRCTL]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PWRCTL]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sr_dis_6:
 | 
				
			||||||
 | 
						/* Wait for self-refresh exit done. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_STAT]
 | 
				
			||||||
 | 
						bic	tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK
 | 
				
			||||||
 | 
						cmp	tmp1, #UDDRC_STAT_OPMODE_NORMAL
 | 
				
			||||||
 | 
						bne	sr_dis_6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Enable all AXI ports. */
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PCTRL_0]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #0x1
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PCTRL_0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PCTRL_1]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #0x1
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PCTRL_1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PCTRL_2]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #0x1
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PCTRL_2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PCTRL_3]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #0x1
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PCTRL_3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ldr	tmp1, [r2, #UDDRC_PCTRL_4]
 | 
				
			||||||
 | 
						orr	tmp1, tmp1, #0x1
 | 
				
			||||||
 | 
						str	tmp1, [r2, #UDDRC_PCTRL_4]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dsb
 | 
				
			||||||
 | 
					.endm
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Enable self-refresh
 | 
					 * Enable self-refresh
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -228,6 +422,7 @@ sdramc_exit_sf:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sr_dis_exit:
 | 
					sr_dis_exit:
 | 
				
			||||||
.endm
 | 
					.endm
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.macro at91_pm_ulp0_mode
 | 
					.macro at91_pm_ulp0_mode
 | 
				
			||||||
	ldr	pmc, .pmc_base
 | 
						ldr	pmc, .pmc_base
 | 
				
			||||||
| 
						 | 
					@ -668,6 +863,8 @@ ENTRY(at91_pm_suspend_in_sram)
 | 
				
			||||||
	str	tmp1, .sramc_base
 | 
						str	tmp1, .sramc_base
 | 
				
			||||||
	ldr	tmp1, [r0, #PM_DATA_RAMC1]
 | 
						ldr	tmp1, [r0, #PM_DATA_RAMC1]
 | 
				
			||||||
	str	tmp1, .sramc1_base
 | 
						str	tmp1, .sramc1_base
 | 
				
			||||||
 | 
						ldr	tmp1, [r0, #PM_DATA_RAMC_PHY]
 | 
				
			||||||
 | 
						str	tmp1, .sramc_phy_base
 | 
				
			||||||
	ldr	tmp1, [r0, #PM_DATA_MEMCTRL]
 | 
						ldr	tmp1, [r0, #PM_DATA_MEMCTRL]
 | 
				
			||||||
	str	tmp1, .memtype
 | 
						str	tmp1, .memtype
 | 
				
			||||||
	ldr	tmp1, [r0, #PM_DATA_MODE]
 | 
						ldr	tmp1, [r0, #PM_DATA_MODE]
 | 
				
			||||||
| 
						 | 
					@ -721,6 +918,8 @@ ENDPROC(at91_pm_suspend_in_sram)
 | 
				
			||||||
	.word 0
 | 
						.word 0
 | 
				
			||||||
.sramc1_base:
 | 
					.sramc1_base:
 | 
				
			||||||
	.word 0
 | 
						.word 0
 | 
				
			||||||
 | 
					.sramc_phy_base:
 | 
				
			||||||
 | 
						.word 0
 | 
				
			||||||
.shdwc:
 | 
					.shdwc:
 | 
				
			||||||
	.word 0
 | 
						.word 0
 | 
				
			||||||
.sfrbu:
 | 
					.sfrbu:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue