552 lines
18 KiB
C
552 lines
18 KiB
C
/*
|
|
* Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "ddr.h"
|
|
#include "common.h"
|
|
#include "register.h"
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "soc.h"
|
|
#include "suspend_debug_ddr.h"
|
|
#include "../timer_source/timer_source.h"
|
|
|
|
#define DDR_SUSPEND_VERSION "AML_T5W_DDR_1_2"
|
|
//#define ENABLE_DMC_DDR_TEST
|
|
#ifdef ENABLE_DMC_DDR_TEST
|
|
#define TEST_START_ADDRESS 0x10000000
|
|
#define TEST_END_ADDRESS 0x20000000
|
|
#endif
|
|
|
|
#define timere_read() REG32(TIMERE_LOW_REG)
|
|
/* io defines */
|
|
#define wr_reg(addr, val) ((*((volatile uint32_t *)(addr))) = (val))
|
|
#define rd_reg(addr) (*((volatile uint32_t *)(addr)))
|
|
|
|
/*clear [mask] 0 bits in [addr], set these 0 bits with [value] corresponding bits*/
|
|
#define modify_reg(addr, value, mask) wr_reg(addr, ((rd_reg(addr) & (mask)) | (value)))
|
|
#define wait_set(addr, loc) \
|
|
do { \
|
|
} while (0 == (rd_reg(addr) & (1 << loc)))
|
|
#define wait_clr(addr, loc) \
|
|
do { \
|
|
} while ((1U << loc) == (rd_reg(addr) & (1U << loc)))
|
|
#define wait_equal(addr, data) \
|
|
do { \
|
|
} while (data != (rd_reg(addr)))
|
|
|
|
//#define _udelay(tim) vTaskDelay(tim)
|
|
void _udelay(uint32_t delay_us)
|
|
{
|
|
unsigned int time1;
|
|
unsigned int time2;
|
|
|
|
time1 = timere_read();
|
|
do {
|
|
time2 = timere_read();
|
|
} while ((time2 - time1) < delay_us);
|
|
}
|
|
|
|
//#define udelay(tim) _udelay(tim)
|
|
//unsigned int g_nAPDSet = 0;
|
|
#ifdef ENABLE_DMC_DDR_TEST
|
|
static unsigned int dmc_ddr_test(unsigned int start_add, unsigned int write_enable,
|
|
unsigned int read_enable, unsigned int read_compare, unsigned int test_end_add,
|
|
unsigned int pattern, unsigned int seed)
|
|
{
|
|
seed = 2;
|
|
#define DATA_LOOP_PATTERN_INDEX (4 + 32) //0xff
|
|
unsigned int dmc_test_sts = 0;
|
|
unsigned int dmc_error = 0;
|
|
//unsigned int pattern_select = 0;
|
|
unsigned int pattern_value = 0;
|
|
unsigned int pattern_inv_value = 0;
|
|
|
|
dmc_error = 0;
|
|
{
|
|
test_end_add = test_end_add - 4; //sha must bit 0-6 ==ff;
|
|
}
|
|
wr_reg(DMC_TEST_STA, start_add); // RESET FIFOS //0x03d81e3f
|
|
wr_reg(DMC_TEST_EDA, test_end_add); //0x07d81e3f
|
|
if (pattern == 0) {
|
|
wr_reg(DMC_TEST_WD0, 0xaa5555aa);
|
|
wr_reg(DMC_TEST_WD1, 0x55aaaa55);
|
|
wr_reg(DMC_TEST_WD2, 0);
|
|
wr_reg(DMC_TEST_WD3, 0xffffffff);
|
|
wr_reg(DMC_TEST_WD4, 0);
|
|
wr_reg(DMC_TEST_WD5, 0x0000ffff);
|
|
wr_reg(DMC_TEST_WD6, 0xffff0000);
|
|
wr_reg(DMC_TEST_WD7, 0x33cccc33);
|
|
wr_reg(DMC_TEST_WD0 + 32, 0xaa5555aa);
|
|
wr_reg(DMC_TEST_WD1 + 32, 0x55aaaa55);
|
|
wr_reg(DMC_TEST_WD2 + 32, 0);
|
|
wr_reg(DMC_TEST_WD3 + 32, 0xffffffff);
|
|
wr_reg(DMC_TEST_WD4 + 32, 0);
|
|
wr_reg(DMC_TEST_WD5 + 32, 0x0000ffff);
|
|
wr_reg(DMC_TEST_WD6 + 32, 0xffff0000);
|
|
wr_reg(DMC_TEST_WD7 + 32, 0x33cccc33);
|
|
} else if (pattern < 33) {
|
|
wr_reg(DMC_TEST_WD0, ((1 << (pattern - 1)) + seed));
|
|
wr_reg(DMC_TEST_WD1, ((2 << (pattern - 1)) + seed));
|
|
wr_reg(DMC_TEST_WD2, ((3 << (pattern - 1)) + seed));
|
|
wr_reg(DMC_TEST_WD3, ((4 << (pattern - 1)) + seed));
|
|
wr_reg(DMC_TEST_WD4, ((4 << (pattern - 1))));
|
|
wr_reg(DMC_TEST_WD5, ((4 << (pattern - 1))));
|
|
wr_reg(DMC_TEST_WD6, ((4 << (pattern - 1))));
|
|
wr_reg(DMC_TEST_WD7, ((4 << (pattern - 1))));
|
|
if (pattern > 16) {
|
|
wr_reg(DMC_TEST_WD4, ((4 << (pattern - 1)) + 0x01010101));
|
|
wr_reg(DMC_TEST_WD5, ((4 << (pattern - 1)) + 0x01010101));
|
|
wr_reg(DMC_TEST_WD6, ((4 << (pattern - 1)) + 0x01010101));
|
|
wr_reg(DMC_TEST_WD7, ((4 << (pattern - 1)) + 0x01010101));
|
|
} else if (pattern > 1) {
|
|
wr_reg(DMC_TEST_WD4, ((4 << (pattern - 1)) + 0x01010101));
|
|
wr_reg(DMC_TEST_WD5, ((4 << (pattern - 1)) + 0x01010101));
|
|
wr_reg(DMC_TEST_WD6, ((4 << (pattern - 1)) + 0x01010101));
|
|
wr_reg(DMC_TEST_WD7, ((4 << (pattern - 1)) + 0x01010101));
|
|
}
|
|
} else {
|
|
//pattern_select = pattern - 33;
|
|
pattern_value = 1;// cpu_ddr_test_init_pattern_generator(pattern_select, 0);
|
|
pattern_inv_value = ~pattern_value;
|
|
for (char counter = 0; counter < 32; ) {
|
|
wr_reg((DMC_TEST_WD0 + counter), pattern_value);
|
|
counter = counter + 4;
|
|
wr_reg((DMC_TEST_WD0 + counter), pattern_inv_value);
|
|
if (counter == 16)
|
|
wr_reg((DMC_TEST_WD0 + counter), 0);
|
|
counter = counter + 4;
|
|
}
|
|
for (char counter = 0; counter < 32; ) { //for g12b-revb register not continuous
|
|
wr_reg((DMC_TEST_WD8 + counter), pattern_value);
|
|
counter = counter + 4;
|
|
wr_reg((DMC_TEST_WD8 + counter), pattern_inv_value);
|
|
if (counter == 16)
|
|
wr_reg((DMC_TEST_WD0 + counter), ~0);
|
|
counter = counter + 4;
|
|
}
|
|
}
|
|
|
|
//must clear watchdog and done flag jiaxing debug 2016_12_07
|
|
wr_reg(DMC_TEST_STS, 0x8000001f);
|
|
//wdg should >rfc value ,use dmc clk count.
|
|
wr_reg(DMC_TEST_WDG, 0xf000f000);
|
|
//should repeat 1 times for read ,all will fail when data increase jiaxing debug 20180322
|
|
if ((pattern == 1) || ((pattern < 33) && pattern))
|
|
wr_reg(DMC_TEST_CTRL, (1 << 31) | (read_compare << 27) | (0 << 28) | (0 << 25) |
|
|
(1 << 24) | (0 << 20) | (1 << 23) | (0x0 << 16) | (0 << 8) | (0x428) |
|
|
(3 << 18) | (write_enable << 30) | (read_enable << 29));
|
|
else
|
|
wr_reg(DMC_TEST_CTRL, (1 << 31) | (read_compare << 27) | (0 << 28) | (1 << 24) |
|
|
(0x0 << 16) | (0 << 18) | (0x0 << 0) | (0 << 8) | (0x428) | (3 << 18) |
|
|
(write_enable << 30) | (read_enable << 29));
|
|
|
|
do {
|
|
mdelay(100);
|
|
dmc_test_sts = (rd_reg(DMC_TEST_STS));
|
|
printf("\n dmc_test_sts %08x\n", dmc_test_sts);
|
|
} while (!(dmc_test_sts & 0xc0000000));
|
|
|
|
wr_reg(DMC_TEST_CTRL, 0x00000000);
|
|
|
|
if ((dmc_test_sts & 0x40000000))
|
|
dmc_error = 1;
|
|
else
|
|
//can not deter write trigger ,or can not quickly recover dmc with phy? 2016_12_12
|
|
if (dmc_test_sts & 0x1)
|
|
dmc_error = 1;
|
|
|
|
dmc_error = dmc_error + (rd_reg(DMC_TEST_ERR_CNT));
|
|
dmc_test_sts = (rd_reg(DMC_TEST_STS));
|
|
wr_reg(DMC_TEST_STS, dmc_test_sts);
|
|
//must write sts value to clear watchdog and done flag
|
|
|
|
if (dmc_error) {
|
|
for (unsigned int counter1 = 0; counter1 < (DMC_TEST_RDRSP_ADDR + 4 - DMC_TEST_STA);) {
|
|
printf("\n counter %08x %08x", counter1, (rd_reg(DMC_TEST_STA + (counter1))));
|
|
counter1 = counter1 + 4;
|
|
}
|
|
//clear read buffer dmc test reset
|
|
wr_reg(DMC_SOFT_RST, (rd_reg(DMC_SOFT_RST)) & (~((1 << 29) | (1 << 24))));
|
|
udelay(1);
|
|
wr_reg(DMC_SOFT_RST, (rd_reg(DMC_SOFT_RST)) | ((1 << 29)) | (1 << 24));
|
|
udelay(1);
|
|
}
|
|
return dmc_error;
|
|
}
|
|
|
|
//unsigned int apb_sec_ctrl = 0;
|
|
//#define DDR_APB_SEC_CTRL ((0x00f0 << 2) + 0xff639000)
|
|
#endif
|
|
#define DDR_SUSPEND_MODE_MANUAL_TRIGGER_DFI_INIT_START 2
|
|
unsigned int test_loops;
|
|
unsigned int apd_value;
|
|
|
|
#define PHY_T5_PHY_DDR_TYPE_ADD 0xfe002000
|
|
//bit4:1 1 ddr3 2 ddr4 4 lpddr3 8 lpddr4
|
|
#define PHY_T5_DDR4_MR2_ADD 0xfe000108
|
|
//BIT0-13 mr2
|
|
#define DMC_DDR_CTRL_ADD ((0x0100 << 2) + 0xff639000)
|
|
//bit 24:22 3'b000 : ddr3 mode.
|
|
//3'b001 : ddr4 mode.
|
|
//3'b010 : lpddr3 mode.
|
|
//3'b011 : lpddr4 mode.
|
|
|
|
#define CONFIG_DDR_TYPE_DDR3 0
|
|
#define CONFIG_DDR_TYPE_DDR4 1
|
|
#define CONFIG_DDR_TYPE_LPDDR4 2
|
|
#define CONFIG_DDR_TYPE_LPDDR3 3
|
|
#define CONFIG_DDR_TYPE_LPDDR2 4
|
|
#define CONFIG_DDR_TYPE_LPDDR4X 5
|
|
|
|
#define ENABLE_SET_MR2_REFRESH_RATE 1
|
|
|
|
#ifdef ENABLE_SET_MR2_REFRESH_RATE
|
|
unsigned int global_ddr4_mr2_value;
|
|
|
|
enum ddr4_mr2_fresh {
|
|
DDR4_MR2_FRESH_1X = 0, //
|
|
DDR4_MR2_FRESH_0_5X = 1, //
|
|
DDR4_MR2_FRESH_2X = 2, //
|
|
DDR4_MR2_FRESH_AUTO_MODE = 3 //0_25X
|
|
};
|
|
|
|
static char get_dram_type(void)
|
|
{
|
|
unsigned int ddr_ctrl_value = rd_reg(PHY_T5_PHY_DDR_TYPE_ADD);
|
|
|
|
ddr_ctrl_value = (ddr_ctrl_value >> 1) & 0xf;
|
|
if (ddr_ctrl_value == 1)
|
|
return CONFIG_DDR_TYPE_DDR3;
|
|
else if (ddr_ctrl_value == 2)
|
|
return CONFIG_DDR_TYPE_DDR4;
|
|
else if (ddr_ctrl_value == 4)
|
|
return CONFIG_DDR_TYPE_LPDDR3;
|
|
else if (ddr_ctrl_value == 8)
|
|
return CONFIG_DDR_TYPE_LPDDR4;
|
|
else
|
|
return CONFIG_DDR_TYPE_DDR4;
|
|
}
|
|
|
|
static unsigned int update_and_get_ddr4_mr2_refresh_value(void)
|
|
{
|
|
unsigned int ddr4_mr2_value = rd_reg(PHY_T5_DDR4_MR2_ADD);
|
|
|
|
global_ddr4_mr2_value = ddr4_mr2_value;
|
|
ddr4_mr2_value = (ddr4_mr2_value >> 0) & 0x3fff;
|
|
return ddr4_mr2_value;
|
|
}
|
|
|
|
static void set_dram_mrs(char rank_index, char mrs_index, uint16_t reg_value, char ddr_type)
|
|
{
|
|
wr_reg(DMC_DRAM_CMD_TIME, 0xa000a);
|
|
char calc_mrs_index = 0;
|
|
char calc_data_cycles = 2;
|
|
|
|
if ((ddr_type == CONFIG_DDR_TYPE_DDR3) || (ddr_type == CONFIG_DDR_TYPE_LPDDR3)) {
|
|
calc_mrs_index = ((mrs_index));
|
|
calc_data_cycles = 2;
|
|
}
|
|
if (ddr_type == CONFIG_DDR_TYPE_DDR4) {
|
|
calc_mrs_index = ((mrs_index & 0x3) << 0) | (((mrs_index >> 2) & 0x3) << 3);
|
|
calc_data_cycles = 2;
|
|
}
|
|
if (ddr_type == CONFIG_DDR_TYPE_LPDDR4) {
|
|
calc_mrs_index = ((mrs_index));
|
|
calc_data_cycles = 4;
|
|
}
|
|
|
|
wr_reg(DMC_DRAM_CMD_CODE, ((rank_index + 1) << 24) |
|
|
((calc_data_cycles - 1) << 26) |
|
|
((calc_mrs_index) << 16) |
|
|
(reg_value));
|
|
wr_reg(DMC_DRAM_CMD, 0);
|
|
wr_reg(DMC_DRAM_CMD, 1);
|
|
while ((((rd_reg(DMC_DRAM_CMD) >> 31) & 0x1) != 1))
|
|
;
|
|
printf("aml log : DDR suspend.mrs_index = %x\n", mrs_index);
|
|
printf("aml log : DDR suspend.reg_value = %x\n", reg_value);
|
|
} /* set_dram_mrs */
|
|
#endif
|
|
|
|
void vDDR_suspend(uint32_t st_f)
|
|
{
|
|
(void)st_f;
|
|
|
|
#ifdef ENABLE_DMC_DDR_TEST
|
|
unsigned int ddr_bist_test_error = 0;
|
|
|
|
ddr_bist_test_error = dmc_ddr_test(TEST_START_ADDRESS, 1, 0, 0, TEST_END_ADDRESS, 1, 0);
|
|
ddr_bist_test_error = dmc_ddr_test(TEST_START_ADDRESS, 0, 1, 1, TEST_END_ADDRESS, 1, 0);
|
|
if (ddr_bist_test_error) {
|
|
ddr_bist_test_error =
|
|
dmc_ddr_test(TEST_START_ADDRESS, 0, 1, 1, TEST_END_ADDRESS, 1, 0) +
|
|
ddr_bist_test_error;
|
|
ddr_bist_test_error =
|
|
dmc_ddr_test(TEST_START_ADDRESS, 0, 1, 1, TEST_END_ADDRESS, 1, 0) +
|
|
ddr_bist_test_error;
|
|
}
|
|
printf("suspend dmc full test result = %d\n", ddr_bist_test_error);
|
|
#endif
|
|
printf("aml log : DDR suspend...test2\n");
|
|
apd_value = rd_reg(DMC_DRAM_APD_CTRL);
|
|
udelay(1);
|
|
wr_reg(DMC_DRAM_APD_CTRL, 0);
|
|
udelay(1);
|
|
//ddr_suspend_resume_test((1024<<20), 5000, 100, 100, 0, 0);
|
|
//return;
|
|
//st_f = st_f;
|
|
//unsigned int time_start, time_end;
|
|
printf("Enter ddr suspend test_loops = %d\n", test_loops);
|
|
//if (test_loops == 0) {
|
|
// dmc_ddr_test(0x10000000, 1, 0, 0, 0x30000000, 1, 0);
|
|
//test_loops++;
|
|
//}
|
|
test_loops++;
|
|
//some address will be protect by bl30
|
|
//return ;
|
|
|
|
while (0xfffffff != rd_reg(DMC_CHAN_STS)) {
|
|
printf("DMC_CHAN_STS: 0x%x\n", rd_reg(DMC_CHAN_STS));
|
|
#if BL30_SUSPEND_DEBUG_EN
|
|
/* ddr suspend debug : print vio reg and clear */
|
|
dmc_status_print_clear();
|
|
#endif
|
|
//vTaskDelay(pdMS_TO_TICKS(100000));
|
|
udelay(1);
|
|
}
|
|
|
|
#if BL30_SUSPEND_DEBUG_EN
|
|
/* ddr suspend debug : print vio before REQ_CTRL disabled*/
|
|
dmc_status_disable_print();
|
|
#endif
|
|
|
|
//time_start = rd_reg(P_ISA_TIMERE);
|
|
|
|
/* open DMC reg access for M3 */
|
|
//apb_sec_ctrl = rd_reg(DDR_APB_SEC_CTRL);
|
|
//wr_reg(DDR_APB_SEC_CTRL,0x91911);
|
|
printf("DMC_DRAM_MCFG: 0x%x\n", rd_reg(DMC_DRAM_MCFG));
|
|
udelay(1);
|
|
wr_reg(DMC_REQ_CTRL, 0); //bit0: A53.
|
|
udelay(1);
|
|
//return;
|
|
/* suspend flow */
|
|
//while ((((rd_reg(DMC_DRAM_STAT))&0xf0) != 0) && ((rd_reg(DMC_DRAM_STAT))&0xf0) != 0x40) {
|
|
// printf("DMC_DRAM_STAT11: 0x%x\n", rd_reg(DMC_DRAM_STAT));
|
|
// //vTaskDelay(pdMS_TO_TICKS(1));
|
|
// udelay(1);
|
|
//}
|
|
#ifdef DDR_SUSPEND_MODE_DMC_TRIGGER_SUSPEND_1
|
|
//bit 18 will auto trigger dfi init start cmd when scfg set to value 2
|
|
wr_reg(DMC_DRAM_ASR_CTRL, (1 << 18));
|
|
udelay(1);
|
|
wr_reg(DMC_DRAM_SCFG, 2);
|
|
udelay(1);
|
|
|
|
while (((((rd_reg(DMC_DRAM_STAT))>>4)&0xf) != 3)) {
|
|
//printf("DMC_DRAM_STAT22: 0x%x\n", readl(DMC_DRAM_STAT));
|
|
_udelay(1);//do not add any delay,since use ao cpu maybe speed too slow
|
|
}
|
|
|
|
#endif
|
|
#ifdef ENABLE_SET_MR2_REFRESH_RATE
|
|
char rank_index = 2;
|
|
char mrs_index = 2;
|
|
char ddr_type = get_dram_type();
|
|
unsigned int ddr4_mr2_value = update_and_get_ddr4_mr2_refresh_value();
|
|
|
|
printf("aml log : ddr_type = %x\n", ddr_type);
|
|
printf("aml log : ddr4_mr2_value = %x\n", ddr4_mr2_value);
|
|
ddr4_mr2_value = ((ddr4_mr2_value & 0x3fff) & ~(3 << 6)) |
|
|
(DDR4_MR2_FRESH_AUTO_MODE << 6);
|
|
#endif
|
|
#ifdef DDR_SUSPEND_MODE_MANUAL_TRIGGER_DFI_INIT_START
|
|
#ifdef ENABLE_SET_MR2_REFRESH_RATE
|
|
wr_reg(DMC_DRAM_SCFG, 1);
|
|
while (((((rd_reg(DMC_DRAM_STAT)) >> 4) & 0xf) != 1))
|
|
;
|
|
if (ddr_type == CONFIG_DDR_TYPE_DDR4)
|
|
set_dram_mrs(rank_index, mrs_index, ddr4_mr2_value, ddr_type);
|
|
#endif
|
|
wr_reg(DMC_DRAM_SCFG, 2);
|
|
udelay(2);
|
|
while (((((rd_reg(DMC_DRAM_STAT))>>4)&0xf) != 3)) {
|
|
//printf("DMC_DRAM_STAT22: 0x%x\n", readl(DMC_DRAM_STAT));
|
|
//_udelay(2);//do not add any delay,since use ao cpu maybe speed too slow
|
|
}
|
|
udelay(2);
|
|
wr_reg(DMC_DRAM_SCFG, 1);
|
|
udelay(2);
|
|
//wr_reg(DMC_DRAM_MCFG, (1 << 9) | rd_reg(DMC_DRAM_MCFG));
|
|
while (((((rd_reg(DMC_DRAM_STAT))>>4)&0xf) != 1)) {
|
|
//printf("DMC_DRAM_STAT22: 0x%x\n", readl(DMC_DRAM_STAT));
|
|
_udelay(1);//do not add any delay,since use ao cpu maybe speed too slow
|
|
}
|
|
|
|
wr_reg(DMC_DRAM_DFIINITCFG, (1 | (0 << 1) | (0 << 6) | (0 << 14) | (1 << 8)));
|
|
//vTaskDelay(pdMS_TO_TICKS(1));
|
|
udelay(1);
|
|
wait_clr(DMC_DRAM_DFIINITCFG, 31);
|
|
#endif//final version, wait_clr
|
|
//vTaskDelay(pdMS_TO_TICKS(3));
|
|
udelay(3);
|
|
//return;
|
|
wr_reg(AM_DDR_PLL_CNTL0, (rd_reg(AM_DDR_PLL_CNTL0) & (~(0xf << 28))) | (1 << 29));
|
|
udelay(1);
|
|
|
|
/* print time consumption */
|
|
//time_end = rd_reg(P_ISA_TIMERE);
|
|
//printf("ddr suspend time: %dus\n", time_end - time_start);
|
|
printf("\nddr suspend is done\n");
|
|
//ddr_suspend_resume_test((1024<<20), 100, 3, 3, 0, 0);
|
|
//ddr_suspend_resume_test((80<<20), 10000000, 0, 3, 0, 0);
|
|
}
|
|
|
|
//#if 1
|
|
static unsigned int pll_lock(void)
|
|
{
|
|
unsigned int lock_cnt = 1000;
|
|
|
|
//wr_reg(AM_DDR_PLL_CNTL0, (rd_reg(AM_DDR_PLL_CNTL0) & (~(0xf << 28))) | (1 << 29));
|
|
//vTaskDelay(pdMS_TO_TICKS(1));
|
|
//udelay(100);
|
|
//wr_reg(AM_DDR_PLL_CNTL0, (rd_reg(AM_DDR_PLL_CNTL0) & (~(0x1 << 29))) | (1 << 28));
|
|
do {
|
|
//vTaskDelay(pdMS_TO_TICKS(1));
|
|
udelay(1);
|
|
wr_reg(AM_DDR_PLL_CNTL0, (rd_reg(AM_DDR_PLL_CNTL0) & (~(0xf << 28))) | (1 << 29));
|
|
//vTaskDelay(pdMS_TO_TICKS(1));
|
|
udelay(1);
|
|
wr_reg(AM_DDR_PLL_CNTL0, (rd_reg(AM_DDR_PLL_CNTL0) & (~(0x1 << 29))) | (1 << 28));
|
|
udelay(200);
|
|
} while ((0 == ((rd_reg(AM_DDR_PLL_CNTL0) >> 31) & 0x1)) && (lock_cnt--));
|
|
udelay(1000);
|
|
return lock_cnt;
|
|
|
|
}
|
|
//#endif
|
|
|
|
void vDDR_resume(uint32_t st_f)
|
|
{
|
|
//unsigned int time_start, time_end;
|
|
if (st_f)
|
|
return;
|
|
//st_f = st_f;
|
|
mdelay(30);
|
|
printf("Enter ddr resume\n");
|
|
uint32_t last_time = timere_read();
|
|
unsigned int cost_time = 0;
|
|
|
|
udelay(100);
|
|
cost_time = timere_read() - last_time;
|
|
printf("ddr test delay 100us = %d us\n", cost_time);
|
|
//return;
|
|
|
|
//time_start = rd_reg(P_ISA_TIMERE);
|
|
/* resume flow */
|
|
//#if 1
|
|
unsigned int ret = 0;
|
|
//unsigned int cost_time = 0;
|
|
last_time = timere_read();
|
|
ret = pll_lock();
|
|
if (!ret) {
|
|
printf("ddr pll lock r1\n");
|
|
wr_reg(AM_DDR_PLL_CNTL3, rd_reg(AM_DDR_PLL_CNTL3)|(1<<31));
|
|
udelay(1);
|
|
ret = pll_lock();
|
|
if (!ret) {
|
|
printf("ddr pll lock r2\n");
|
|
wr_reg(AM_DDR_PLL_CNTL6, 0x55540000);
|
|
udelay(1);
|
|
ret = pll_lock();
|
|
if (!ret) {
|
|
printf("ddr pll lock r2\n");
|
|
do {
|
|
} while (1);
|
|
}
|
|
}
|
|
}
|
|
cost_time = timere_read() - last_time;
|
|
printf("ddr resume pll done %d us\n", cost_time);
|
|
//#endif
|
|
//#if 1
|
|
#ifdef DDR_SUSPEND_MODE_DMC_TRIGGER_SUSPEND_1
|
|
|
|
#endif
|
|
|
|
#ifdef DDR_SUSPEND_MODE_MANUAL_TRIGGER_DFI_INIT_START
|
|
wr_reg(DMC_DRAM_DFIINITCFG, (0 | (0 << 1) | (0 << 6) | (0 << 14) | (1 << 8)));
|
|
//vTaskDelay(pdMS_TO_TICKS(1));
|
|
//printf("aml log : DDR suspend...dfi\n");
|
|
udelay(1);
|
|
wait_set(DMC_DRAM_DFIINITCFG, 31);
|
|
//vTaskDelay(pdMS_TO_TICKS(1));
|
|
udelay(1);
|
|
#endif
|
|
#ifdef ENABLE_SET_MR2_REFRESH_RATE
|
|
char rank_index = 2;
|
|
char mrs_index = 2;
|
|
char ddr_type = get_dram_type();
|
|
|
|
if (ddr_type == CONFIG_DDR_TYPE_DDR4)
|
|
set_dram_mrs(rank_index, mrs_index, global_ddr4_mr2_value, ddr_type);
|
|
#endif
|
|
wr_reg(DMC_DRAM_SCFG, 4);
|
|
udelay(1);
|
|
while (((((rd_reg(DMC_DRAM_STAT))>>4)&0xf) != 2)) {
|
|
//printf("DMC_DRAM_STAT22: 0x%x\n", readl(DMC_DRAM_STAT));
|
|
_udelay(1);//do not add any delay,since use ao cpu maybe speed too slow
|
|
}
|
|
//vTaskDelay(pdMS_TO_TICKS(1));
|
|
mdelay(10);//at least a refresh time to update zq dll
|
|
last_time = timere_read();
|
|
#if BL30_SUSPEND_DEBUG_EN
|
|
/* ddr suspend debug : print vio reg and channel status before resume */
|
|
show_dmc_port_status();
|
|
#endif
|
|
|
|
wr_reg(DMC_REQ_CTRL, 0xffffffff);
|
|
udelay(1);
|
|
//wr_reg(DDR_APB_SEC_CTRL, apb_sec_ctrl);
|
|
/* print time consumption */
|
|
//time_end = readl(P_ISA_TIMERE);
|
|
//printf("ddr resume time: %dus\n", time_end - time_start);
|
|
// unsigned int ddr_bist_test_error = 0;
|
|
//ddr_bist_test_error = dmc_ddr_test(dram_base, 0, 1, 1, test_size, 1, 0) + ddr_bist_test_error;
|
|
//ddr_bist_test_error = dmc_ddr_test(0, 0, 1, 1, (80<<20), 1, 0) + ddr_bist_test_error;
|
|
//printf("ddr_bist_test_error = %d\n", ddr_bist_test_error);
|
|
//wr_reg(0xfe002440, 2);
|
|
// wr_reg(0xfe002440, 0);
|
|
// _udelay(300);
|
|
//ddr_bist_test_error = dmc_ddr_test(0, 1, 0, 0, (1<<20), 1, 0) + ddr_bist_test_error;
|
|
//ddr_bist_test_error = dmc_ddr_test(0, 0, 1, 1, (1<<20), 1, 0) + ddr_bist_test_error;
|
|
// printf("ddr_bist_test_error = %d\n", ddr_bist_test_error);
|
|
//ddr_suspend_resume_test((1<<20), 2, 1, 3, 0, 0);
|
|
//ddr_suspend_resume_test((1<<20), 0, 1, 3, 0, 0);
|
|
//_udelay(300);
|
|
// wr_reg(DMC_REQ_CTRL, 0xffffffff);
|
|
cost_time = timere_read() - last_time;
|
|
printf("ddr resume done %d us\n", cost_time);
|
|
|
|
#ifdef ENABLE_DMC_DDR_TEST
|
|
unsigned int ddr_bist_test_error = 0;
|
|
//ddr_bist_test_error = dmc_ddr_test(TEST_START_ADDRESS, 1, 0, 0, TEST_END_ADDRESS, 1, 0);
|
|
ddr_bist_test_error = dmc_ddr_test(TEST_START_ADDRESS, 0, 1, 1, TEST_END_ADDRESS, 1, 0);
|
|
if (ddr_bist_test_error) {
|
|
ddr_bist_test_error =
|
|
dmc_ddr_test(TEST_START_ADDRESS, 0, 1, 1, TEST_END_ADDRESS, 1, 0) +
|
|
ddr_bist_test_error;
|
|
ddr_bist_test_error =
|
|
dmc_ddr_test(TEST_START_ADDRESS, 0, 1, 1, TEST_END_ADDRESS, 1, 0) +
|
|
ddr_bist_test_error;
|
|
}
|
|
printf("resume dmc full test result = %d\n", ddr_bist_test_error);
|
|
#endif
|
|
wr_reg(DMC_DRAM_APD_CTRL, apd_value);
|
|
wr_reg(DMC_DRAM_ASR_CTRL, (0 << 18));
|
|
}
|