Skip to content

Commit

Permalink
Merge pull request linux4sam#51 from alexandrebelloni/backup_mode
Browse files Browse the repository at this point in the history
Backup mode
  • Loading branch information
wenyouya authored Apr 26, 2017
2 parents e451e0b + fa3c5af commit 50fe79d
Show file tree
Hide file tree
Showing 9 changed files with 305 additions and 97 deletions.
9 changes: 9 additions & 0 deletions Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,15 @@ config CONFIG_PM_PMIC

endmenu

config CONFIG_BACKUP_MODE
bool "Enable Backup Mode"
default n
help
Enables "Backup mode". Starting with sama5d2, it is possible to put
use DDR Self Refresh and shutdown the core. Resuming from that state
requires support in the bootloader.


menu "Board's Workaround Options"
depends on CONFIG_HAS_PMIC_ACT8865

Expand Down
86 changes: 86 additions & 0 deletions driver/backup.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "backup.h"
#include "debug.h"
#include "hardware.h"
#include "rstc.h"
#include "arch/at91_sfrbu.h"

static struct at91_pm_bu {
int suspended;
unsigned long *reserved;
unsigned long *canary;
unsigned long resume;
} *pm_bu;

static int resuming = -1;

static int backup_mode(void)
{
int ret;

resuming = 0;

ret = readl(AT91C_BASE_SFRBU + SFRBU_DDRBUMCR);
if (ret == 0)
return 0;

do {
ret = readl(AT91C_BASE_SECUMOD + 0x14);
} while (ret == 0);

pm_bu = (struct at91_pm_bu *)AT91C_BASE_SECURAM;
if (!pm_bu->suspended)
return 0;

resuming = 1;
return 1;
}

int backup_resume(void)
{
if (resuming == -1)
backup_mode();

return resuming;
}

unsigned long backup_mode_resume(void)
{
if (!backup_resume())
return 0;

writel(0, AT91C_BASE_SFRBU + SFRBU_DDRBUMCR);

if (*pm_bu->canary != 0xa5a5a5a5) {
cpu_reset();
return 0;
}

return pm_bu->resume;
}
203 changes: 106 additions & 97 deletions driver/ddramc.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "hardware.h"
#include "arch/at91_ddrsdrc.h"
#include "arch/at91_sfr.h"
#include "backup.h"
#include "debug.h"
#include "ddramc.h"
#include "timer.h"
Expand Down Expand Up @@ -712,107 +713,115 @@ int ddr3_sdram_initialize(unsigned int base_address,
write_ddramc(base_address, HDDRSDRC2_T1PR, ddramc_config->t1pr);
write_ddramc(base_address, HDDRSDRC2_T2PR, ddramc_config->t2pr);

/*
* Step 3: A NOP command is issued to the DDR3-SRAM.
* Program the NOP command in the MPDDRC Mode Register (MPDDRC_MR).
* The application must write a one to the MODE field in the MPDDRC_MR
* Perform a write access to any DDR3-SDRAM address to acknowledge this command.
* The clock which drive the DDR3-SDRAM device are now enabled.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_NOP_CMD);
*((unsigned volatile int *)ram_address) = 0;

/*
* Step 4: A pause of at least 500us must be observed before a single toggle.
*/
udelay(500);

/*
* Step 5: A NOP command is issued to the DDR3-SDRAM
* Program the NOP command in the MPDDRC_MR.
* The application must write a one to the MODE field in the MPDDRC_MR.
* Perform a write access to any DDR3-SDRAM address to acknowledge this command.
* CKE is now driven high.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_NOP_CMD);
*((unsigned volatile int *)ram_address) = 0;

/*
* Step 6: An Extended Mode Register Set (EMRS2) cycle is issued to choose
* between commercial or high temperature operations. The application must
* write a five to the MODE field in the MPDDRC_MR and perform a write
* access to the DDR3-SDRAM to acknowledge this command.
* The write address must be chosen so that signal BA[2] is set to 0,
* BA[1] is set to 1 and signal BA[0] is set to 0.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_EXT_LMR_CMD);
*((unsigned int *)(ram_address + (0x2 << ba_offset))) = 0;

/*
* Step 7: An Extended Mode Register Set (EMRS3) cycle is issued to set
* the Extended Mode Register to 0. The application must write a five
* to the MODE field in the MPDDRC_MR and perform a write access to the
* DDR3-SDRAM to acknowledge this command. The write address must be
* chosen so that signal BA[2] is set to 0, BA[1] is set to 1 and signal
* BA[0] is set to 1.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_EXT_LMR_CMD);
*((unsigned int *)(ram_address + (0x3 << ba_offset))) = 0;

/*
* Step 8: An Extended Mode Register Set (EMRS1) cycle is issued to
* disable and to program O.D.S. (Output Driver Strength).
* The application must write a five to the MODE field in the MPDDRC_MR
* and perform a write access to the DDR3-SDRAM to acknowledge this command.
* The write address must be chosen so that signal BA[2:1] is set to 0
* and signal BA[0] is set to 1.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_EXT_LMR_CMD);
*((unsigned int *)(ram_address + (0x1 << ba_offset))) = 0;

/*
* Step 9: Write a one to the DLL bit (enable DLL reset) in the MPDDRC
* Configuration Register (MPDDRC_CR)
*/
if (!backup_resume()) {
/*
* Step 3: A NOP command is issued to the DDR3-SRAM.
* Program the NOP command in the MPDDRC Mode Register (MPDDRC_MR).
* The application must write a one to the MODE field in the MPDDRC_MR
* Perform a write access to any DDR3-SDRAM address to acknowledge this command.
* The clock which drive the DDR3-SDRAM device are now enabled.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_NOP_CMD);
*((unsigned volatile int *)ram_address) = 0;

/*
* Step 4: A pause of at least 500us must be observed before a single toggle.
*/
udelay(500);

/*
* Step 5: A NOP command is issued to the DDR3-SDRAM
* Program the NOP command in the MPDDRC_MR.
* The application must write a one to the MODE field in the MPDDRC_MR.
* Perform a write access to any DDR3-SDRAM address to acknowledge this command.
* CKE is now driven high.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_NOP_CMD);
*((unsigned volatile int *)ram_address) = 0;

/*
* Step 6: An Extended Mode Register Set (EMRS2) cycle is issued to choose
* between commercial or high temperature operations. The application must
* write a five to the MODE field in the MPDDRC_MR and perform a write
* access to the DDR3-SDRAM to acknowledge this command.
* The write address must be chosen so that signal BA[2] is set to 0,
* BA[1] is set to 1 and signal BA[0] is set to 0.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_EXT_LMR_CMD);
*((unsigned int *)(ram_address + (0x2 << ba_offset))) = 0;

/*
* Step 7: An Extended Mode Register Set (EMRS3) cycle is issued to set
* the Extended Mode Register to 0. The application must write a five
* to the MODE field in the MPDDRC_MR and perform a write access to the
* DDR3-SDRAM to acknowledge this command. The write address must be
* chosen so that signal BA[2] is set to 0, BA[1] is set to 1 and signal
* BA[0] is set to 1.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_EXT_LMR_CMD);
*((unsigned int *)(ram_address + (0x3 << ba_offset))) = 0;

/*
* Step 8: An Extended Mode Register Set (EMRS1) cycle is issued to
* disable and to program O.D.S. (Output Driver Strength).
* The application must write a five to the MODE field in the MPDDRC_MR
* and perform a write access to the DDR3-SDRAM to acknowledge this command.
* The write address must be chosen so that signal BA[2:1] is set to 0
* and signal BA[0] is set to 1.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_EXT_LMR_CMD);
*((unsigned int *)(ram_address + (0x1 << ba_offset))) = 0;

/*
* Step 9: Write a one to the DLL bit (enable DLL reset) in the MPDDRC
* Configuration Register (MPDDRC_CR)
*/
#if 0
cr = read_ddramc(base_address, HDDRSDRC2_CR);
write_ddramc(base_address, HDDRSDRC2_CR, cr | AT91C_DDRC2_DLL_RESET_ENABLED);
cr = read_ddramc(base_address, HDDRSDRC2_CR);
write_ddramc(base_address, HDDRSDRC2_CR, cr | AT91C_DDRC2_DLL_RESET_ENABLED);
#endif

/*
* Step 10: A Mode Register Set (MRS) cycle is issued to reset DLL.
* The application must write a three to the MODE field in the MPDDRC_MR
* and perform a write access to the DDR3-SDRAM to acknowledge this command.
* The write address must be chosen so that signals BA[2:0] are set to 0
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_LMR_CMD);
*((unsigned int *)ram_address) = 0;

udelay(50);

/*
* Step 11: A Calibration command (MRS) is issued to calibrate RTT and
* RON values for the Process Voltage Temperature (PVT).
* The application must write a six to the MODE field in the MPDDRC_MR
* and perform a write access to the DDR3-SDRAM to acknowledge this command.
* The write address must be chosen so that signals BA[2:0] are set to 0.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_DEEP_CMD);
*((unsigned int *)ram_address) = 0;

/*
* Step 12: A Normal Mode command is provided.
* Program the Normal mode in the MPDDRC_MR and perform a write access
* to any DDR3-SDRAM address to acknowledge this command.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_NORMAL_CMD);
*((unsigned int *)ram_address) = 0;

/*
* Step 13: Perform a write access to any DDR3-SDRAM address.
*/
*((unsigned int *)ram_address) = 0;

/*
* Step 10: A Mode Register Set (MRS) cycle is issued to reset DLL.
* The application must write a three to the MODE field in the MPDDRC_MR
* and perform a write access to the DDR3-SDRAM to acknowledge this command.
* The write address must be chosen so that signals BA[2:0] are set to 0
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_LMR_CMD);
*((unsigned int *)ram_address) = 0;

udelay(50);

/*
* Step 11: A Calibration command (MRS) is issued to calibrate RTT and
* RON values for the Process Voltage Temperature (PVT).
* The application must write a six to the MODE field in the MPDDRC_MR
* and perform a write access to the DDR3-SDRAM to acknowledge this command.
* The write address must be chosen so that signals BA[2:0] are set to 0.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_DEEP_CMD);
*((unsigned int *)ram_address) = 0;

/*
* Step 12: A Normal Mode command is provided.
* Program the Normal mode in the MPDDRC_MR and perform a write access
* to any DDR3-SDRAM address to acknowledge this command.
*/
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_NORMAL_CMD);
*((unsigned int *)ram_address) = 0;

/*
* Step 13: Perform a write access to any DDR3-SDRAM address.
*/
*((unsigned int *)ram_address) = 0;
}
else
{
write_ddramc(base_address, HDDRSDRC2_MR, AT91C_DDRC2_MODE_NORMAL_CMD);
write_ddramc(base_address,
HDDRSDRC2_LPR, 0x10001);
}
/*
* Step 14: Write the refresh rate into the COUNT field in the MPDDRC
* Refresh Timer Register (MPDDRC_RTR):
Expand Down
2 changes: 2 additions & 0 deletions driver/driver.mk
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,6 @@ COBJS-$(CONFIG_WM8904) += $(DRIVERS_SRC)/wm8904.o
COBJS-$(CONFIG_AES) += $(DRIVERS_SRC)/at91_aes.o
COBJS-$(CONFIG_SECURE) += $(DRIVERS_SRC)/secure.o

COBJS-$(CONFIG_BACKUP_MODE) += $(DRIVERS_SRC)/backup.o

COBJS-$(CONFIG_REDIRECT_ALL_INTS_AIC) += $(DRIVERS_SRC)/at91_aicredir.o
4 changes: 4 additions & 0 deletions driver/driver_cpp.mk
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,10 @@ ifeq ($(CONFIG_SECURE), y)
CPPFLAGS += -DCONFIG_SECURE
endif

ifeq ($(CONFIG_BACKUP_MODE), y)
CPPFLAGS += -DCONFIG_BACKUP_MODE
endif

ifeq ($(CPU_HAS_PIO4), y)
CPPFLAGS += -DCPU_HAS_PIO4
endif
Expand Down
43 changes: 43 additions & 0 deletions include/arch/at91_sfrbu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __AT91_SFRBU_H__
#define __AT91_SFRBU_H__

/*
* Register Offset
*/
#define SFRBU_DDRBUMCR 0x10 /* DDR BU Mode Control Register */

/*
* Register Fields
*/

/*--- SFRBU_DDRMCR: (offset: 0x10) DDR BU Mode Control Register ---*/
#define AT91C_DDRBUMCR_BUMEN (0x01 /* Force DDR_DQ Input Buffer Always On */

#endif /* #ifndef __AT91_SFRBU_H__ */
Loading

0 comments on commit 50fe79d

Please sign in to comment.