Commit d6845d3d authored by davidcunado-arm's avatar davidcunado-arm Committed by GitHub
Browse files

Merge pull request #835 from rockchip-linux/rk3399-atf-cleanup-20170210

RK3399 ARM TF clean up 20170210
parents 86a3b266 ccdc044a
......@@ -44,6 +44,7 @@
extern uint32_t __bl31_sram_text_start, __bl31_sram_text_end;
extern uint32_t __bl31_sram_data_start, __bl31_sram_data_end;
extern uint32_t __sram_incbin_start, __sram_incbin_end;
/******************************************************************************
* For rockchip socs pm ops
......
......@@ -62,6 +62,12 @@ void rockchip_plat_sram_mmu_el3(void)
mmap_add_region((unsigned long)&__bl31_sram_data_start,
(unsigned long)&__bl31_sram_data_start,
sram_size, MT_MEMORY | MT_RW | MT_SECURE);
/* sram.incbin size */
sram_size = (char *)&__sram_incbin_end - (char *)&__sram_incbin_start;
mmap_add_region((unsigned long)&__sram_incbin_start,
(unsigned long)&__sram_incbin_start,
sram_size, MT_NON_CACHEABLE | MT_RW | MT_SECURE);
#else
/* TODO: Support other SoCs, Just support RK3399 now */
return;
......
0x0 ,
0x4f8c120c ,
0x0 ,
0x4f8c1210 ,
0x100000 ,
0x1f310019 ,
0x0 ,
0xb0000001 ,
0x58 ,
0xd0000000 ,
0x1300 ,
0x1f760329 ,
0x0 ,
0xb0000001 ,
0x40 ,
0xd0000000 ,
0xc ,
0x1f760371 ,
0x0 ,
0xb0000001 ,
0x28 ,
0xd0000000 ,
0x400000 ,
0x1f900009 ,
0x0 ,
0xb0000001 ,
0x10 ,
0xd0000000 ,
0x1 ,
0x4f8c120c ,
0x100000 ,
0x1f310019 ,
0x0 ,
0xb0000001 ,
0x58 ,
0xd0000000 ,
0x2c00 ,
0x1f760329 ,
0x0 ,
0xb0000001 ,
0x40 ,
0xd0000000 ,
0xc0 ,
0x1f760371 ,
0x0 ,
0xb0000001 ,
0x28 ,
0xd0000000 ,
0x400000 ,
0x1f8f0009 ,
0x0 ,
0xb0000001 ,
0x10 ,
0xd0000000 ,
0x1 ,
0x4f8c1210 ,
0x0 ,
0x4f8c1220 ,
0x0 ,
0x4f8c121c ,
0x0 ,
0xaf8c120d ,
0x108 ,
0xd0000000 ,
0x2000 ,
0x1f900009 ,
0x0 ,
0xa0000001 ,
0x30 ,
0xd0000000 ,
0x0 ,
0x4f8c1220 ,
0x0 ,
0x4f8c121c ,
0x0 ,
0x10000001 ,
0x0 ,
0xa0000001 ,
0xb0 ,
0xd0000000 ,
0x8000 ,
0x1f900009 ,
0x0 ,
0xa0000001 ,
0x30 ,
0xd0000000 ,
0x1 ,
0x4f8c1220 ,
0x1 ,
0x4f8c121c ,
0x0 ,
0x10000001 ,
0x0 ,
0xa0000001 ,
0x70 ,
0xd0000000 ,
0x4000 ,
0x1f900009 ,
0x0 ,
0xa0000001 ,
0x30 ,
0xd0000000 ,
0x0 ,
0x4f8c1220 ,
0x1 ,
0x4f8c121c ,
0x0 ,
0x10000001 ,
0x0 ,
0xa0000001 ,
0x30 ,
0xd0000000 ,
0x1000 ,
0x1f900009 ,
0x0 ,
0xa0000001 ,
0x18 ,
0xd0000000 ,
0x0 ,
0x4f8c1220 ,
0x1 ,
0x4f8c121c ,
0x0 ,
0x10000001 ,
0x0 ,
0xa0000001 ,
0x100 ,
0xd0000000 ,
0x0 ,
0xaf8c1211 ,
0xf0 ,
0xd0000000 ,
0x2000 ,
0x1f8f0009 ,
0x0 ,
0xa0000001 ,
0x30 ,
0xd0000000 ,
0x0 ,
0x4f8c1220 ,
0x0 ,
0x4f8c121c ,
0x0 ,
0x10000001 ,
0x0 ,
0xa0000001 ,
0xb0 ,
0xd0000000 ,
0x8000 ,
0x1f8f0009 ,
0x0 ,
0xa0000001 ,
0x30 ,
0xd0000000 ,
0x1 ,
0x4f8c1220 ,
0x1 ,
0x4f8c121c ,
0x0 ,
0x10000001 ,
0x0 ,
0xa0000001 ,
0x70 ,
0xd0000000 ,
0x4000 ,
0x1f8f0009 ,
0x0 ,
0xa0000001 ,
0x30 ,
0xd0000000 ,
0x0 ,
0x4f8c1220 ,
0x1 ,
0x4f8c121c ,
0x0 ,
0x10000001 ,
0x0 ,
0xa0000001 ,
0x30 ,
0xd0000000 ,
0x1000 ,
0x1f8f0009 ,
0x0 ,
0xa0000001 ,
0x18 ,
0xd0000000 ,
0x0 ,
0x4f8c1220 ,
0x1 ,
0x4f8c121c ,
0x0 ,
0xaf8c120d ,
0x40 ,
0xd0000000 ,
0x80008000 ,
0x7f900284 ,
0x1 ,
0x0 ,
0x8000 ,
0x1f90028d ,
0x0 ,
0x60000001 ,
0x0 ,
0x10000001 ,
0x0 ,
0xa0000001 ,
0x38 ,
0xd0000000 ,
0x0 ,
0xaf8c1211 ,
0x28 ,
0xd0000000 ,
0x80008000 ,
0x7f8f0284 ,
0x1 ,
0x0 ,
0x8000 ,
0x1f8f028d ,
0x0 ,
0x60000001 ,
0xffffffff ,
0x4f77e200 ,
0xffffffff ,
0x4f77e204 ,
0xffffffff ,
0x4f77e208 ,
0xffffffff ,
0x4f77e20c ,
0x70007000 ,
0x4f77e210 ,
0x3fffffff ,
0x7f750130 ,
0x0 ,
0x2f310061 ,
0xc0000 ,
0x20000001 ,
0x0 ,
0x4f310061 ,
0xc0000 ,
0x1f310065 ,
0xc0000 ,
0xb0000001 ,
0x10 ,
0xc0000000 ,
0x0 ,
0xaf8c121d ,
0x48 ,
0xd0000000 ,
0x0 ,
0xaf8c120d ,
0x18 ,
0xd0000000 ,
0x80000000 ,
0x2f90000d ,
0x0 ,
0x4f90000d ,
0x0 ,
0xaf8c1211 ,
0x18 ,
0xd0000000 ,
0x80000000 ,
0x2f90000d ,
0x0 ,
0x4f8f000d ,
0x0 ,
0x2f8c101d ,
0x350005 ,
0x20000001 ,
0x0 ,
0x4f620001 ,
0x1 ,
0x0 ,
0x4 ,
0x1f620011 ,
0x0 ,
0x60000001 ,
0x3000000 ,
0x7f76004c ,
0x18 ,
0x0 ,
0x10001 ,
0x7f76004c ,
0x0 ,
0x2f8c1005 ,
0x0 ,
0x4f760041 ,
0x0 ,
0x2f8c1009 ,
0x0 ,
0x4f760045 ,
0x10000 ,
0x7f76004c ,
0x18 ,
0x0 ,
0x1 ,
0x0 ,
0x80000000 ,
0x1f760049 ,
0x0 ,
0x60000001 ,
0x3000100 ,
0x7f76004c ,
0x3e8 ,
0x0 ,
0x20002 ,
0x4f620000 ,
0x1 ,
0x0 ,
0x1 ,
0x1f620011 ,
0x0 ,
0x60000001 ,
0x0 ,
0xaf8c121d ,
0x48 ,
0xd0000000 ,
0x0 ,
0xaf8c120d ,
0x18 ,
0xd0000000 ,
0x7fffffff ,
0x1f90000d ,
0x0 ,
0x4f90000d ,
0x0 ,
0xaf8c1211 ,
0x18 ,
0xd0000000 ,
0x7fffffff ,
0x1f90000d ,
0x0 ,
0x4f8f000d ,
0xfff3ffff ,
0x1f310061 ,
0x0 ,
0x7f310061 ,
0xc0000 ,
0x1f310065 ,
0x0 ,
0xb0000001 ,
0x10 ,
0xc0000000 ,
0x0 ,
0x7f750130 ,
0x1 ,
0x0 ,
0x1 ,
0x0 ,
0x1 ,
0x0 ,
0x1 ,
0x0 ,
0x1 ,
0x0 ,
0x1 ,
0x0 ,
0x1 ,
0x0 ,
0x1 ,
0x0 ,
0x1 ,
0x0 ,
0x0 ,
0xe0000000 ,
......@@ -28,8 +28,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch_helpers.h>
#include <debug.h>
#include <mmio.h>
#include <m0_ctl.h>
#include <plat_private.h>
#include "dfs.h"
#include "dram.h"
......@@ -40,31 +42,14 @@
#include <delay_timer.h>
#define CTL_TRAINING (1)
#define PI_TRAINING (!CTL_TRAINING)
#define EN_READ_GATE_TRAINING (1)
#define EN_CA_TRAINING (0)
#define EN_WRITE_LEVELING (0)
#define EN_READ_LEVELING (0)
#define EN_WDQ_LEVELING (0)
#define ENPER_CS_TRAINING_FREQ (933)
struct pll_div {
unsigned int mhz;
unsigned int refdiv;
unsigned int fbdiv;
unsigned int postdiv1;
unsigned int postdiv2;
unsigned int frac;
unsigned int freq;
};
#define ENPER_CS_TRAINING_FREQ (666)
#define TDFI_LAT_THRESHOLD_FREQ (928)
#define PHY_DLL_BYPASS_FREQ (260)
static const struct pll_div dpll_rates_table[] = {
/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2 */
{.mhz = 933, .refdiv = 3, .fbdiv = 350, .postdiv1 = 3, .postdiv2 = 1},
{.mhz = 928, .refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1},
{.mhz = 800, .refdiv = 1, .fbdiv = 100, .postdiv1 = 3, .postdiv2 = 1},
{.mhz = 732, .refdiv = 1, .fbdiv = 61, .postdiv1 = 2, .postdiv2 = 1},
{.mhz = 666, .refdiv = 1, .fbdiv = 111, .postdiv1 = 4, .postdiv2 = 1},
......@@ -78,128 +63,44 @@ static const struct pll_div dpll_rates_table[] = {
struct rk3399_dram_status {
uint32_t current_index;
uint32_t index_freq[2];
uint32_t boot_freq;
uint32_t low_power_stat;
struct timing_related_config timing_config;
struct drv_odt_lp_config drv_odt_lp_cfg;
};
static struct rk3399_dram_status rk3399_dram_status;
static struct ddr_dts_config_timing dts_parameter = {
.available = 0
struct rk3399_saved_status {
uint32_t freq;
uint32_t low_power_stat;
uint32_t odt;
};
static struct rk3399_dram_status rk3399_dram_status;
static struct rk3399_saved_status rk3399_suspend_status;
static uint32_t wrdqs_delay_val[2][2][4];
static struct rk3399_sdram_default_config ddr3_default_config = {
.bl = 8,
.ap = 0,
.dramds = 40,
.dramodt = 120,
.burst_ref_cnt = 1,
.zqcsi = 0
};
static struct drv_odt_lp_config ddr3_drv_odt_default_config = {
.ddr3_speed_bin = DDR3_DEFAULT,
.pd_idle = 0,
.sr_idle = 0,
.sr_mc_gate_idle = 0,
.srpd_lite_idle = 0,
.standby_idle = 0,
.ddr3_dll_dis_freq = 300,
.phy_dll_dis_freq = 125,
.odt_dis_freq = 933,
.dram_side_drv = 40,
.dram_side_dq_odt = 120,
.dram_side_ca_odt = 120,
.phy_side_ca_drv = 40,
.phy_side_ck_cs_drv = 40,
.phy_side_dq_drv = 40,
.phy_side_odt = 240,
};
static struct rk3399_sdram_default_config lpddr3_default_config = {
.bl = 8,
.ap = 0,
.dramds = 34,
.dramodt = 240,
.burst_ref_cnt = 1,
.zqcsi = 0
};
static struct drv_odt_lp_config lpddr3_drv_odt_default_config = {
.ddr3_speed_bin = DDR3_DEFAULT,
.pd_idle = 0,
.sr_idle = 0,
.sr_mc_gate_idle = 0,
.srpd_lite_idle = 0,
.standby_idle = 0,
.ddr3_dll_dis_freq = 300,
.phy_dll_dis_freq = 125,
.odt_dis_freq = 666,
.dram_side_drv = 40,
.dram_side_dq_odt = 120,
.dram_side_ca_odt = 120,
.phy_side_ca_drv = 40,
.phy_side_ck_cs_drv = 40,
.phy_side_dq_drv = 40,
.phy_side_odt = 240,
};
static struct rk3399_sdram_default_config lpddr4_default_config = {
.bl = 16,
.ap = 0,
.dramds = 40,
.dramodt = 240,
.caodt = 240,
.burst_ref_cnt = 1,
.zqcsi = 0
};
static struct drv_odt_lp_config lpddr4_drv_odt_default_config = {
.ddr3_speed_bin = DDR3_DEFAULT,
.pd_idle = 0,
.sr_idle = 0,
.sr_mc_gate_idle = 0,
.srpd_lite_idle = 0,
.standby_idle = 0,
.ddr3_dll_dis_freq = 300,
.phy_dll_dis_freq = 125,
.odt_dis_freq = 933,
.dram_side_drv = 60,
.dram_side_dq_odt = 40,
.dram_side_ca_odt = 40,
.phy_side_ca_drv = 40,
.phy_side_ck_cs_drv = 80,
.phy_side_dq_drv = 80,
.phy_side_odt = 60,
};
uint32_t dcf_code[] = {
#include "dcf_code.inc"
};
#define DCF_START_ADDR (SRAM_BASE + 0x1400)
#define DCF_PARAM_ADDR (SRAM_BASE + 0x1000)
/* DCF_PAMET */
#define PARAM_DRAM_FREQ (0)
#define PARAM_DPLL_CON0 (4)
#define PARAM_DPLL_CON1 (8)
#define PARAM_DPLL_CON2 (0xc)
#define PARAM_DPLL_CON3 (0x10)
#define PARAM_DPLL_CON4 (0x14)
#define PARAM_DPLL_CON5 (0x18)
/* equal to fn<<4 */
#define PARAM_FREQ_SELECT (0x1c)
static uint32_t get_cs_die_capability(struct rk3399_sdram_params *sdram_config,
uint8_t channel, uint8_t cs)
{
......@@ -222,176 +123,79 @@ static uint32_t get_cs_die_capability(struct rk3399_sdram_params *sdram_config,
return (cs_cap / die);
}
static void drv_odt_lp_cfg_init(uint32_t dram_type,
struct ddr_dts_config_timing *dts_timing,
static void get_dram_drv_odt_val(uint32_t dram_type,
struct drv_odt_lp_config *drv_config)
{
if ((dts_timing) && (dts_timing->available)) {
drv_config->ddr3_speed_bin = dts_timing->ddr3_speed_bin;
drv_config->pd_idle = dts_timing->pd_idle;
drv_config->sr_idle = dts_timing->sr_idle;
drv_config->sr_mc_gate_idle = dts_timing->sr_mc_gate_idle;
drv_config->srpd_lite_idle = dts_timing->srpd_lite_idle;
drv_config->standby_idle = dts_timing->standby_idle;
drv_config->ddr3_dll_dis_freq = dts_timing->ddr3_dll_dis_freq;
drv_config->phy_dll_dis_freq = dts_timing->phy_dll_dis_freq;
}
uint32_t tmp;
uint32_t mr1_val, mr3_val, mr11_val;
switch (dram_type) {
case DDR3:
if ((dts_timing) && (dts_timing->available)) {
drv_config->odt_dis_freq =
dts_timing->ddr3_odt_dis_freq;
drv_config->dram_side_drv = dts_timing->ddr3_drv;
drv_config->dram_side_dq_odt = dts_timing->ddr3_odt;
drv_config->phy_side_ca_drv =
dts_timing->phy_ddr3_ca_drv;
drv_config->phy_side_ck_cs_drv =
dts_timing->phy_ddr3_ca_drv;
drv_config->phy_side_dq_drv =
dts_timing->phy_ddr3_dq_drv;
drv_config->phy_side_odt = dts_timing->phy_ddr3_odt;
} else {
memcpy(drv_config, &ddr3_drv_odt_default_config,
sizeof(struct drv_odt_lp_config));
}
mr1_val = (mmio_read_32(CTL_REG(0, 133)) >> 16) & 0xffff;
tmp = ((mr1_val >> 1) & 1) | ((mr1_val >> 4) & 1);
if (tmp)
drv_config->dram_side_drv = 34;
else
drv_config->dram_side_drv = 40;
tmp = ((mr1_val >> 2) & 1) | ((mr1_val >> 5) & 1) |
((mr1_val >> 7) & 1);
if (tmp == 0)
drv_config->dram_side_dq_odt = 0;
else if (tmp == 1)
drv_config->dram_side_dq_odt = 60;
else if (tmp == 3)
drv_config->dram_side_dq_odt = 40;
else
drv_config->dram_side_dq_odt = 120;
break;
case LPDDR3:
if ((dts_timing) && (dts_timing->available)) {
drv_config->odt_dis_freq =
dts_timing->lpddr3_odt_dis_freq;
drv_config->dram_side_drv = dts_timing->lpddr3_drv;
drv_config->dram_side_dq_odt = dts_timing->lpddr3_odt;
drv_config->phy_side_ca_drv =
dts_timing->phy_lpddr3_ca_drv;
drv_config->phy_side_ck_cs_drv =
dts_timing->phy_lpddr3_ca_drv;
drv_config->phy_side_dq_drv =
dts_timing->phy_lpddr3_dq_drv;
drv_config->phy_side_odt = dts_timing->phy_lpddr3_odt;
} else {
memcpy(drv_config, &lpddr3_drv_odt_default_config,
sizeof(struct drv_odt_lp_config));
}
mr3_val = mmio_read_32(CTL_REG(0, 138)) & 0xf;
mr11_val = (mmio_read_32(CTL_REG(0, 139)) >> 24) & 0x3;
if (mr3_val == 0xb)
drv_config->dram_side_drv = 3448;
else if (mr3_val == 0xa)
drv_config->dram_side_drv = 4048;
else if (mr3_val == 0x9)
drv_config->dram_side_drv = 3440;
else if (mr3_val == 0x4)
drv_config->dram_side_drv = 60;
else if (mr3_val == 0x3)
drv_config->dram_side_drv = 48;
else if (mr3_val == 0x2)
drv_config->dram_side_drv = 40;
else
drv_config->dram_side_drv = 34;
if (mr11_val == 1)
drv_config->dram_side_dq_odt = 60;
else if (mr11_val == 2)
drv_config->dram_side_dq_odt = 120;
else if (mr11_val == 0)
drv_config->dram_side_dq_odt = 0;
else
drv_config->dram_side_dq_odt = 240;
break;
case LPDDR4:
default:
if ((dts_timing) && (dts_timing->available)) {
drv_config->odt_dis_freq =
dts_timing->lpddr4_odt_dis_freq;
drv_config->dram_side_drv = dts_timing->lpddr4_drv;
drv_config->dram_side_dq_odt =
dts_timing->lpddr4_dq_odt;
drv_config->dram_side_ca_odt =
dts_timing->lpddr4_ca_odt;
drv_config->phy_side_ca_drv =
dts_timing->phy_lpddr4_ca_drv;
drv_config->phy_side_ck_cs_drv =
dts_timing->phy_lpddr4_ck_cs_drv;
drv_config->phy_side_dq_drv =
dts_timing->phy_lpddr4_dq_drv;
drv_config->phy_side_odt = dts_timing->phy_lpddr4_odt;
} else {
memcpy(drv_config, &lpddr4_drv_odt_default_config,
sizeof(struct drv_odt_lp_config));
}
break;
}
switch (drv_config->phy_side_ca_drv) {
case 240:
drv_config->phy_side_ca_drv = PHY_DRV_ODT_240;
break;
case 120:
drv_config->phy_side_ca_drv = PHY_DRV_ODT_120;
break;
case 80:
drv_config->phy_side_ca_drv = PHY_DRV_ODT_80;
break;
case 60:
drv_config->phy_side_ca_drv = PHY_DRV_ODT_60;
break;
case 48:
drv_config->phy_side_ca_drv = PHY_DRV_ODT_48;
break;
case 40:
drv_config->phy_side_ca_drv = PHY_DRV_ODT_40;
break;
default:
drv_config->phy_side_ca_drv = PHY_DRV_ODT_34_3;
break;
};
mr3_val = (mmio_read_32(CTL_REG(0, 138)) >> 3) & 0x7;
mr11_val = (mmio_read_32(CTL_REG(0, 139)) >> 24) & 0xff;
switch (drv_config->phy_side_ck_cs_drv) {
case 240:
drv_config->phy_side_ck_cs_drv = PHY_DRV_ODT_240;
break;
case 120:
drv_config->phy_side_ck_cs_drv = PHY_DRV_ODT_120;
break;
case 80:
drv_config->phy_side_ck_cs_drv = PHY_DRV_ODT_80;
break;
case 60:
drv_config->phy_side_ck_cs_drv = PHY_DRV_ODT_60;
break;
case 48:
drv_config->phy_side_ck_cs_drv = PHY_DRV_ODT_48;
break;
case 40:
drv_config->phy_side_ck_cs_drv = PHY_DRV_ODT_40;
break;
default:
drv_config->phy_side_ck_cs_drv = PHY_DRV_ODT_34_3;
break;
}
if ((mr3_val == 0) || (mr3_val == 7))
drv_config->dram_side_drv = 40;
else
drv_config->dram_side_drv = 240 / mr3_val;
switch (drv_config->phy_side_dq_drv) {
case 240:
drv_config->phy_side_dq_drv = PHY_DRV_ODT_240;
break;
case 120:
drv_config->phy_side_dq_drv = PHY_DRV_ODT_120;
break;
case 80:
drv_config->phy_side_dq_drv = PHY_DRV_ODT_80;
break;
case 60:
drv_config->phy_side_dq_drv = PHY_DRV_ODT_60;
break;
case 48:
drv_config->phy_side_dq_drv = PHY_DRV_ODT_48;
break;
case 40:
drv_config->phy_side_dq_drv = PHY_DRV_ODT_40;
break;
default:
drv_config->phy_side_dq_drv = PHY_DRV_ODT_34_3;
break;
}
tmp = mr11_val & 0x7;
if ((tmp == 7) || (tmp == 0))
drv_config->dram_side_dq_odt = 0;
else
drv_config->dram_side_dq_odt = 240 / tmp;
switch (drv_config->phy_side_odt) {
case 240:
drv_config->phy_side_odt = PHY_DRV_ODT_240;
break;
case 120:
drv_config->phy_side_odt = PHY_DRV_ODT_120;
break;
case 80:
drv_config->phy_side_odt = PHY_DRV_ODT_80;
break;
case 60:
drv_config->phy_side_odt = PHY_DRV_ODT_60;
break;
case 48:
drv_config->phy_side_odt = PHY_DRV_ODT_48;
break;
case 40:
drv_config->phy_side_odt = PHY_DRV_ODT_40;
break;
default:
drv_config->phy_side_odt = PHY_DRV_ODT_34_3;
tmp = (mr11_val >> 4) & 0x7;
if ((tmp == 7) || (tmp == 0))
drv_config->dram_side_ca_odt = 0;
else
drv_config->dram_side_ca_odt = 240 / tmp;
break;
}
}
......@@ -403,8 +207,7 @@ static void sdram_timing_cfg_init(struct timing_related_config *ptiming_config,
uint32_t i, j;
for (i = 0; i < sdram_params->num_channels; i++) {
ptiming_config->dram_info[i].speed_rate =
drv_config->ddr3_speed_bin;
ptiming_config->dram_info[i].speed_rate = DDR3_DEFAULT;
ptiming_config->dram_info[i].cs_cnt = sdram_params->ch[i].rank;
for (j = 0; j < sdram_params->ch[i].rank; j++) {
ptiming_config->dram_info[i].per_die_capability[j] =
......@@ -432,6 +235,7 @@ static void sdram_timing_cfg_init(struct timing_related_config *ptiming_config,
ptiming_config->dramds = drv_config->dram_side_drv;
ptiming_config->dramodt = drv_config->dram_side_dq_odt;
ptiming_config->caodt = drv_config->dram_side_ca_odt;
ptiming_config->odt = (mmio_read_32(PHY_REG(0, 5)) >> 16) & 0x1;
}
struct lat_adj_pair {
......@@ -928,7 +732,7 @@ static void gen_rk3399_ctl_params_f0(struct timing_related_config
/* CTL_314 TDFI_WRCSLAT_F0:RW:8:8 */
tmp1 = get_pi_wrlat_adj(pdram_timing, timing_config);
if (timing_config->freq <= ENPER_CS_TRAINING_FREQ) {
if (timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) {
if (tmp1 == 0)
tmp = 0;
else if (tmp1 < 5)
......@@ -941,7 +745,7 @@ static void gen_rk3399_ctl_params_f0(struct timing_related_config
mmio_clrsetbits_32(CTL_REG(i, 314), 0xff << 8, tmp << 8);
/* CTL_314 TDFI_RDCSLAT_F0:RW:0:8 */
if ((timing_config->freq <= ENPER_CS_TRAINING_FREQ) &&
if ((timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) &&
(pdram_timing->cl >= 5))
tmp = pdram_timing->cl - 5;
else
......@@ -1178,7 +982,7 @@ static void gen_rk3399_ctl_params_f1(struct timing_related_config
/* CTL_314 TDFI_WRCSLAT_F1:RW:24:8 */
tmp1 = get_pi_wrlat_adj(pdram_timing, timing_config);
if (timing_config->freq <= ENPER_CS_TRAINING_FREQ) {
if (timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) {
if (tmp1 == 0)
tmp = 0;
else if (tmp1 < 5)
......@@ -1192,7 +996,7 @@ static void gen_rk3399_ctl_params_f1(struct timing_related_config
mmio_clrsetbits_32(CTL_REG(i, 314), 0xff << 24, tmp << 24);
/* CTL_314 TDFI_RDCSLAT_F1:RW:16:8 */
if ((timing_config->freq <= ENPER_CS_TRAINING_FREQ) &&
if ((timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) &&
(pdram_timing->cl >= 5))
tmp = pdram_timing->cl - 5;
else
......@@ -1201,6 +1005,33 @@ static void gen_rk3399_ctl_params_f1(struct timing_related_config
}
}
static void gen_rk3399_enable_training(uint32_t ch_cnt, uint32_t nmhz)
{
uint32_t i, tmp;
if (nmhz <= PHY_DLL_BYPASS_FREQ)
tmp = 0;
else
tmp = 1;
for (i = 0; i < ch_cnt; i++) {
mmio_clrsetbits_32(CTL_REG(i, 305), 1 << 16, tmp << 16);
mmio_clrsetbits_32(CTL_REG(i, 71), 1, tmp);
mmio_clrsetbits_32(CTL_REG(i, 70), 1 << 8, 1 << 8);
}
}
static void gen_rk3399_disable_training(uint32_t ch_cnt)
{
uint32_t i;
for (i = 0; i < ch_cnt; i++) {
mmio_clrbits_32(CTL_REG(i, 305), 1 << 16);
mmio_clrbits_32(CTL_REG(i, 71), 1);
mmio_clrbits_32(CTL_REG(i, 70), 1 << 8);
}
}
static void gen_rk3399_ctl_params(struct timing_related_config *timing_config,
struct dram_timing_t *pdram_timing,
uint32_t fn)
......@@ -1209,35 +1040,6 @@ static void gen_rk3399_ctl_params(struct timing_related_config *timing_config,
gen_rk3399_ctl_params_f0(timing_config, pdram_timing);
else
gen_rk3399_ctl_params_f1(timing_config, pdram_timing);
#if CTL_TRAINING
uint32_t i, tmp0, tmp1;
tmp0 = tmp1 = 0;
#if EN_READ_GATE_TRAINING
tmp1 = 1;
#endif
#if EN_CA_TRAINING
tmp0 |= (1 << 8);
#endif
#if EN_WRITE_LEVELING
tmp0 |= (1 << 16);
#endif
#if EN_READ_LEVELING
tmp0 |= (1 << 24);
#endif
for (i = 0; i < timing_config->ch_cnt; i++) {
if (tmp0 | tmp1)
mmio_setbits_32(CTL_REG(i, 305), 1 << 16);
if (tmp0)
mmio_setbits_32(CTL_REG(i, 70), tmp0);
if (tmp1)
mmio_setbits_32(CTL_REG(i, 71), tmp1);
}
#endif
}
static void gen_rk3399_pi_params_f0(struct timing_related_config *timing_config,
......@@ -1381,7 +1183,8 @@ static void gen_rk3399_pi_params_f0(struct timing_related_config *timing_config,
mmio_clrsetbits_32(PI_REG(i, 148), 0xffff << 16,
pdram_timing->mr[2] << 16);
/* PI_156 PI_TFC_F0:RW:0:10 */
mmio_clrsetbits_32(PI_REG(i, 156), 0x3ff, pdram_timing->trfc);
mmio_clrsetbits_32(PI_REG(i, 156), 0x3ff,
pdram_timing->tfc_long);
/* PI_158 PI_TWR_F0:RW:24:6 */
mmio_clrsetbits_32(PI_REG(i, 158), 0x3f << 24,
pdram_timing->twr << 24);
......@@ -1452,7 +1255,7 @@ static void gen_rk3399_pi_params_f1(struct timing_related_config *timing_config,
mmio_clrsetbits_32(PI_REG(i, 44), 0x3f, PI_ADD_LATENCY);
/* PI_44 PI_CASLAT_LIN_F1:RW:8:7:=0x18 */
mmio_clrsetbits_32(PI_REG(i, 44), 0x7f << 8,
pdram_timing->cl * 2);
(pdram_timing->cl * 2) << 8);
/* PI_47 PI_TREF_F1:RW:16:16 */
mmio_clrsetbits_32(PI_REG(i, 47), 0xffff << 16,
pdram_timing->trefi << 16);
......@@ -1561,7 +1364,7 @@ static void gen_rk3399_pi_params_f1(struct timing_related_config *timing_config,
mmio_clrsetbits_32(PI_REG(i, 151), 0xffff, pdram_timing->mr[2]);
/* PI_156 PI_TFC_F1:RW:16:10 */
mmio_clrsetbits_32(PI_REG(i, 156), 0x3ff << 16,
pdram_timing->trfc << 16);
pdram_timing->tfc_long << 16);
/* PI_162 PI_TWR_F1:RW:8:6 */
mmio_clrsetbits_32(PI_REG(i, 162), 0x3f << 8,
pdram_timing->twr << 8);
......@@ -1605,32 +1408,6 @@ static void gen_rk3399_pi_params(struct timing_related_config *timing_config,
gen_rk3399_pi_params_f0(timing_config, pdram_timing);
else
gen_rk3399_pi_params_f1(timing_config, pdram_timing);
#if PI_TRAINING
uint32_t i;
for (i = 0; i < timing_config->ch_cnt; i++) {
#if EN_READ_GATE_TRAINING
mmio_clrsetbits_32(PI_REG(i, 80), 3 << 24, 2 << 24);
#endif
#if EN_CA_TRAINING
mmio_clrsetbits_32(PI_REG(i, 100), 3 << 8, 2 << 8);
#endif
#if EN_WRITE_LEVELING
mmio_clrsetbits_32(PI_REG(i, 60), 3 << 8, 2 << 8);
#endif
#if EN_READ_LEVELING
mmio_clrsetbits_32(PI_REG(i, 80), 3 << 16, 2 << 16);
#endif
#if EN_WDQ_LEVELING
mmio_clrsetbits_32(PI_REG(i, 124), 3 << 16, 2 << 16);
#endif
}
#endif
}
static void gen_rk3399_set_odt(uint32_t odt_en)
......@@ -1652,57 +1429,92 @@ static void gen_rk3399_set_odt(uint32_t odt_en)
}
}
static void gen_rk3399_set_ds_odt(struct timing_related_config *timing_config,
struct drv_odt_lp_config *drv_config)
static void gen_rk3399_phy_dll_bypass(uint32_t mhz, uint32_t ch,
uint32_t index, uint32_t dram_type)
{
uint32_t i, drv_odt_val;
uint32_t sw_master_mode = 0;
uint32_t rddqs_gate_delay, rddqs_latency, total_delay;
uint32_t i;
for (i = 0; i < timing_config->ch_cnt; i++) {
if (timing_config->dram_type == LPDDR4)
drv_odt_val = drv_config->phy_side_odt |
(PHY_DRV_ODT_Hi_Z << 4) |
(drv_config->phy_side_dq_drv << 8) |
(drv_config->phy_side_dq_drv << 12);
else if (timing_config->dram_type == LPDDR3)
drv_odt_val = PHY_DRV_ODT_Hi_Z |
(drv_config->phy_side_odt << 4) |
(drv_config->phy_side_dq_drv << 8) |
(drv_config->phy_side_dq_drv << 12);
else
drv_odt_val = drv_config->phy_side_odt |
(drv_config->phy_side_odt << 4) |
(drv_config->phy_side_dq_drv << 8) |
(drv_config->phy_side_dq_drv << 12);
/* DQ drv odt set */
mmio_clrsetbits_32(PHY_REG(i, 6), 0xffffff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 134), 0xffffff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 262), 0xffffff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 390), 0xffffff, drv_odt_val);
/* DQS drv odt set */
mmio_clrsetbits_32(PHY_REG(i, 7), 0xffffff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 135), 0xffffff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 263), 0xffffff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 391), 0xffffff, drv_odt_val);
gen_rk3399_set_odt(timing_config->odt);
/* CA drv set */
drv_odt_val = drv_config->phy_side_ca_drv |
(drv_config->phy_side_ca_drv << 4);
mmio_clrsetbits_32(PHY_REG(i, 544), 0xff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 672), 0xff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 800), 0xff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 928), 0xff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 937), 0xff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 935), 0xff, drv_odt_val);
drv_odt_val = drv_config->phy_side_ck_cs_drv |
(drv_config->phy_side_ck_cs_drv << 4);
mmio_clrsetbits_32(PHY_REG(i, 929), 0xff, drv_odt_val);
mmio_clrsetbits_32(PHY_REG(i, 939), 0xff, drv_odt_val);
if (dram_type == DDR3)
total_delay = PI_PAD_DELAY_PS_VALUE;
else if (dram_type == LPDDR3)
total_delay = PI_PAD_DELAY_PS_VALUE + 2500;
else
total_delay = PI_PAD_DELAY_PS_VALUE + 1500;
/* total_delay + 0.55tck */
total_delay += (55 * 10000)/mhz;
rddqs_latency = total_delay * mhz / 1000000;
total_delay -= rddqs_latency * 1000000 / mhz;
rddqs_gate_delay = total_delay * 0x200 * mhz / 1000000;
if (mhz <= PHY_DLL_BYPASS_FREQ) {
sw_master_mode = 0xc;
mmio_setbits_32(PHY_REG(ch, 514), 1);
mmio_setbits_32(PHY_REG(ch, 642), 1);
mmio_setbits_32(PHY_REG(ch, 770), 1);
/* setting bypass mode slave delay */
for (i = 0; i < 4; i++) {
/* wr dq delay = -180deg + (0x60 / 4) * 20ps */
mmio_clrsetbits_32(PHY_REG(ch, 1 + 128 * i), 0x7ff << 8,
0x4a0 << 8);
/* rd dqs/dq delay = (0x60 / 4) * 20ps */
mmio_clrsetbits_32(PHY_REG(ch, 11 + 128 * i), 0x3ff,
0xa0);
/* rd rddqs_gate delay */
mmio_clrsetbits_32(PHY_REG(ch, 2 + 128 * i), 0x3ff,
rddqs_gate_delay);
mmio_clrsetbits_32(PHY_REG(ch, 78 + 128 * i), 0xf,
rddqs_latency);
}
for (i = 0; i < 3; i++)
/* adr delay */
mmio_clrsetbits_32(PHY_REG(ch, 513 + 128 * i),
0x7ff << 16, 0x80 << 16);
if ((mmio_read_32(PHY_REG(ch, 86)) & 0xc00) == 0) {
/*
* old status is normal mode,
* and saving the wrdqs slave delay
*/
for (i = 0; i < 4; i++) {
/* save and clear wr dqs slave delay */
wrdqs_delay_val[ch][index][i] = 0x3ff &
(mmio_read_32(PHY_REG(ch, 63 + i * 128))
>> 16);
mmio_clrsetbits_32(PHY_REG(ch, 63 + i * 128),
0x03ff << 16, 0 << 16);
/*
* in normal mode the cmd may delay 1cycle by
* wrlvl and in bypass mode making dqs also
* delay 1cycle.
*/
mmio_clrsetbits_32(PHY_REG(ch, 78 + i * 128),
0x07 << 8, 0x1 << 8);
}
}
} else if (mmio_read_32(PHY_REG(ch, 86)) & 0xc00) {
/* old status is bypass mode and restore wrlvl resume */
for (i = 0; i < 4; i++) {
mmio_clrsetbits_32(PHY_REG(ch, 63 + i * 128),
0x03ff << 16,
(wrdqs_delay_val[ch][index][i] &
0x3ff) << 16);
/* resume phy_write_path_lat_add */
mmio_clrbits_32(PHY_REG(ch, 78 + i * 128), 0x07 << 8);
}
}
/* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */
mmio_clrsetbits_32(PHY_REG(ch, 86), 0xf << 8, sw_master_mode << 8);
mmio_clrsetbits_32(PHY_REG(ch, 214), 0xf << 8, sw_master_mode << 8);
mmio_clrsetbits_32(PHY_REG(ch, 342), 0xf << 8, sw_master_mode << 8);
mmio_clrsetbits_32(PHY_REG(ch, 470), 0xf << 8, sw_master_mode << 8);
/* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */
mmio_clrsetbits_32(PHY_REG(ch, 547), 0xf << 16, sw_master_mode << 16);
mmio_clrsetbits_32(PHY_REG(ch, 675), 0xf << 16, sw_master_mode << 16);
mmio_clrsetbits_32(PHY_REG(ch, 803), 0xf << 16, sw_master_mode << 16);
}
static void gen_rk3399_phy_params(struct timing_related_config *timing_config,
......@@ -1745,15 +1557,7 @@ static void gen_rk3399_phy_params(struct timing_related_config *timing_config,
/* DENALI_PHY_911 13bits offset_0 */
/* PHY_LP4_BOOT_PLL_CTRL */
/* DENALI_PHY_919 13bits offset_0 */
if (pdram_timing->mhz <= 150)
tmp = 3;
else if (pdram_timing->mhz <= 300)
tmp = 2;
else if (pdram_timing->mhz <= 600)
tmp = 1;
else
tmp = 0;
tmp = (1 << 12) | (tmp << 9) | (2 << 7) | (1 << 1);
tmp = (1 << 12) | (2 << 7) | (1 << 1);
mmio_clrsetbits_32(PHY_REG(i, 911), 0x1fff, tmp);
mmio_clrsetbits_32(PHY_REG(i, 919), 0x1fff, tmp);
......@@ -1761,15 +1565,7 @@ static void gen_rk3399_phy_params(struct timing_related_config *timing_config,
/* DENALI_PHY_911 13bits offset_16 */
/* PHY_LP4_BOOT_PLL_CTRL_CA */
/* DENALI_PHY_919 13bits offset_16 */
if (pdram_timing->mhz <= 150)
tmp = 3;
else if (pdram_timing->mhz <= 300)
tmp = 2;
else if (pdram_timing->mhz <= 600)
tmp = 1;
else
tmp = 0;
tmp = (tmp << 9) | (2 << 7) | (1 << 5) | (1 << 1);
tmp = (2 << 7) | (1 << 5) | (1 << 1);
mmio_clrsetbits_32(PHY_REG(i, 911), 0x1fff << 16, tmp << 16);
mmio_clrsetbits_32(PHY_REG(i, 919), 0x1fff << 16, tmp << 16);
......@@ -1791,7 +1587,6 @@ static void gen_rk3399_phy_params(struct timing_related_config *timing_config,
break;
}
mmio_clrsetbits_32(PHY_REG(i, 947), 0x7 << 8, tmp << 8);
mmio_setbits_32(PHY_REG(i, 927), (1 << 22));
if (timing_config->dram_type == DDR3) {
mem_delay_ps = 0;
......@@ -1812,12 +1607,6 @@ static void gen_rk3399_phy_params(struct timing_related_config *timing_config,
gate_delay_ps = delay_frac_ps + 1000 - (trpre_min_ps / 2);
gate_delay_frac_ps = gate_delay_ps % 1000;
tmp = gate_delay_frac_ps * 0x200 / 1000;
/* PHY_RDDQS_GATE_BYPASS_SLAVE_DELAY */
/* DENALI_PHY_2/130/258/386 10bits offset_0 */
mmio_clrsetbits_32(PHY_REG(i, 2), 0x2ff, tmp);
mmio_clrsetbits_32(PHY_REG(i, 130), 0x2ff, tmp);
mmio_clrsetbits_32(PHY_REG(i, 258), 0x2ff, tmp);
mmio_clrsetbits_32(PHY_REG(i, 386), 0x2ff, tmp);
/* PHY_RDDQS_GATE_SLAVE_DELAY */
/* DENALI_PHY_77/205/333/461 10bits offset_16 */
mmio_clrsetbits_32(PHY_REG(i, 77), 0x2ff << 16, tmp << 16);
......@@ -1832,12 +1621,6 @@ static void gen_rk3399_phy_params(struct timing_related_config *timing_config,
mmio_clrsetbits_32(PHY_REG(i, 138), 0xf, tmp);
mmio_clrsetbits_32(PHY_REG(i, 266), 0xf, tmp);
mmio_clrsetbits_32(PHY_REG(i, 394), 0xf, tmp);
/* PHY_RDDQS_LATENCY_ADJUST */
/* DENALI_PHY_78/206/334/462 4bits offset_0 */
mmio_clrsetbits_32(PHY_REG(i, 78), 0xf, tmp);
mmio_clrsetbits_32(PHY_REG(i, 206), 0xf, tmp);
mmio_clrsetbits_32(PHY_REG(i, 334), 0xf, tmp);
mmio_clrsetbits_32(PHY_REG(i, 462), 0xf, tmp);
/* PHY_GTLVL_LAT_ADJ_START */
/* DENALI_PHY_80/208/336/464 4bits offset_16 */
tmp = delay_frac_ps / 1000;
......@@ -1922,6 +1705,8 @@ static void gen_rk3399_phy_params(struct timing_related_config *timing_config,
mmio_setbits_32(PHY_REG(i, 340), 0x1 << 16);
mmio_setbits_32(PHY_REG(i, 468), 0x1 << 16);
}
gen_rk3399_phy_dll_bypass(pdram_timing->mhz, i, fn,
timing_config->dram_type);
}
}
......@@ -1944,22 +1729,6 @@ static int to_get_clk_index(unsigned int mhz)
return i;
}
uint32_t rkclk_prepare_pll_timing(unsigned int mhz)
{
unsigned int refdiv, postdiv1, fbdiv, postdiv2;
int index;
index = to_get_clk_index(mhz);
refdiv = dpll_rates_table[index].refdiv;
fbdiv = dpll_rates_table[index].fbdiv;
postdiv1 = dpll_rates_table[index].postdiv1;
postdiv2 = dpll_rates_table[index].postdiv2;
mmio_write_32(DCF_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(fbdiv));
mmio_write_32(DCF_PARAM_ADDR + PARAM_DPLL_CON1,
POSTDIV2(postdiv2) | POSTDIV1(postdiv1) | REFDIV(refdiv));
return (24 * fbdiv) / refdiv / postdiv1 / postdiv2;
}
uint32_t ddr_get_rate(void)
{
uint32_t refdiv, postdiv1, fbdiv, postdiv2;
......@@ -2051,90 +1820,21 @@ void resume_low_power(uint32_t low_power)
}
}
static void wait_dcf_done(void)
{
while ((mmio_read_32(DCF_BASE + DCF_DCF_ISR) & (DCF_DONE)) == 0)
continue;
}
void clr_dcf_irq(void)
static void dram_low_power_config(void)
{
/* clear dcf irq status */
mmio_write_32(DCF_BASE + DCF_DCF_ISR, DCF_TIMEOUT | DCF_ERR | DCF_DONE);
}
static void enable_dcf(uint32_t dcf_addr)
{
/* config DCF start addr */
mmio_write_32(DCF_BASE + DCF_DCF_ADDR, dcf_addr);
/* wait dcf done */
while (mmio_read_32(DCF_BASE + DCF_DCF_CTRL) & 1)
continue;
/* clear dcf irq status */
mmio_write_32(DCF_BASE + DCF_DCF_ISR, DCF_TIMEOUT | DCF_ERR | DCF_DONE);
/* DCF start */
mmio_setbits_32(DCF_BASE + DCF_DCF_CTRL, DCF_START);
}
void dcf_code_init(void)
{
memcpy((void *)DCF_START_ADDR, (void *)dcf_code, sizeof(dcf_code));
/* set dcf master secure */
mmio_write_32(SGRF_BASE + 0xe01c, ((0x3 << 0) << 16) | (0 << 0));
mmio_write_32(DCF_BASE + DCF_DCF_TOSET, 0x80000000);
}
static void dcf_start(uint32_t freq, uint32_t index)
{
mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
(0x1 << (1 + 16)) | (1 << 1));
mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(11),
(0x1 << (0 + 16)) | (1 << 0));
mmio_write_32(DCF_PARAM_ADDR + PARAM_FREQ_SELECT, index << 4);
mmio_write_32(DCF_PARAM_ADDR + PARAM_DRAM_FREQ, freq);
rkclk_prepare_pll_timing(freq);
udelay(10);
mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
(0x1 << (1 + 16)) | (0 << 1));
mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(11),
(0x1 << (0 + 16)) | (0 << 0));
udelay(10);
enable_dcf(DCF_START_ADDR);
}
static void dram_low_power_config(struct drv_odt_lp_config *lp_config)
{
uint32_t tmp, tmp1, i;
uint32_t tmp, i;
uint32_t ch_cnt = rk3399_dram_status.timing_config.ch_cnt;
uint32_t dram_type = rk3399_dram_status.timing_config.dram_type;
uint32_t *low_power = &rk3399_dram_status.low_power_stat;
if (dram_type == LPDDR4)
tmp = (lp_config->srpd_lite_idle << 16) |
lp_config->pd_idle;
else
tmp = lp_config->pd_idle;
if (dram_type == DDR3)
tmp1 = (2 << 16) | (0x7 << 8) | 7;
tmp = (2 << 16) | (0x7 << 8);
else
tmp1 = (3 << 16) | (0x7 << 8) | 7;
tmp = (3 << 16) | (0x7 << 8);
*low_power = 0;
for (i = 0; i < ch_cnt; i++) {
mmio_write_32(CTL_REG(i, 102), tmp);
mmio_clrsetbits_32(CTL_REG(i, 103), 0xffff,
(lp_config->sr_mc_gate_idle << 8) |
lp_config->sr_idle);
mmio_clrsetbits_32(CTL_REG(i, 101), 0x70f0f, tmp1);
*low_power |= (7 << (8 * i));
}
for (i = 0; i < ch_cnt; i++)
mmio_clrsetbits_32(CTL_REG(i, 101), 0x70f0f, tmp);
/* standby idle */
mmio_write_32(CIC_BASE + CIC_IDLE_TH, lp_config->standby_idle);
mmio_write_32(CIC_BASE + CIC_CG_WAIT_TH, 0x640008);
if (ch_cnt == 2) {
......@@ -2142,36 +1842,22 @@ static void dram_low_power_config(struct drv_odt_lp_config *lp_config)
(((0x1<<4) | (0x1<<5) | (0x1<<6) |
(0x1<<7)) << 16) |
((0x1<<4) | (0x0<<5) | (0x1<<6) | (0x1<<7)));
if (lp_config->standby_idle) {
tmp = 0x002a002a;
*low_power |= (1 << 11);
} else
tmp = 0;
mmio_write_32(CIC_BASE + CIC_CTRL1, tmp);
mmio_write_32(CIC_BASE + CIC_CTRL1, 0x002a0028);
}
mmio_write_32(GRF_BASE + GRF_DDRC0_CON1,
(((0x1<<4) | (0x1<<5) | (0x1<<6) | (0x1<<7)) << 16) |
((0x1<<4) | (0x0<<5) | (0x1<<6) | (0x1<<7)));
if (lp_config->standby_idle) {
tmp = 0x00150015;
*low_power |= (1 << 3);
} else
tmp = 0;
mmio_write_32(CIC_BASE + CIC_CTRL1, tmp);
mmio_write_32(CIC_BASE + CIC_CTRL1, 0x00150014);
}
static void dram_related_init(struct ddr_dts_config_timing *dts_timing)
void dram_dfs_init(void)
{
uint32_t trefi0, trefi1;
uint32_t i;
dcf_code_init();
uint32_t trefi0, trefi1, boot_freq;
/* get sdram config for os reg */
drv_odt_lp_cfg_init(sdram_config.dramtype, dts_timing,
&rk3399_dram_status.drv_odt_lp_cfg);
get_dram_drv_odt_val(sdram_config.dramtype,
&rk3399_dram_status.drv_odt_lp_cfg);
sdram_timing_cfg_init(&rk3399_dram_status.timing_config,
&sdram_config,
&rk3399_dram_status.drv_odt_lp_cfg);
......@@ -2187,30 +1873,106 @@ static void dram_related_init(struct ddr_dts_config_timing *dts_timing)
rk3399_dram_status.index_freq[0] /= 2;
rk3399_dram_status.index_freq[1] /= 2;
}
rk3399_dram_status.index_freq[(rk3399_dram_status.current_index + 1)
& 0x1] = 0;
boot_freq =
rk3399_dram_status.index_freq[rk3399_dram_status.current_index];
boot_freq = dpll_rates_table[to_get_clk_index(boot_freq)].mhz;
rk3399_dram_status.boot_freq = boot_freq;
rk3399_dram_status.index_freq[rk3399_dram_status.current_index] =
boot_freq;
rk3399_dram_status.index_freq[(rk3399_dram_status.current_index + 1) &
0x1] = 0;
rk3399_dram_status.low_power_stat = 0;
/*
* following register decide if NOC stall the access request
* or return error when NOC being idled. when doing ddr frequency
* scaling in M0 or DCF, we need to make sure noc stall the access
* request, if return error cpu may data abort when ddr frequency
* changing. it don't need to set this register every times,
* so we init this register in function dram_dfs_init().
*/
mmio_write_32(GRF_BASE + GRF_SOC_CON(0), 0xffffffff);
mmio_write_32(GRF_BASE + GRF_SOC_CON(1), 0xffffffff);
mmio_write_32(GRF_BASE + GRF_SOC_CON(2), 0xffffffff);
mmio_write_32(GRF_BASE + GRF_SOC_CON(3), 0xffffffff);
mmio_write_32(GRF_BASE + GRF_SOC_CON(4), 0x70007000);
/* disable all training by ctl and pi */
for (i = 0; i < rk3399_dram_status.timing_config.ch_cnt; i++) {
mmio_clrbits_32(CTL_REG(i, 70), (1 << 24) |
(1 << 16) | (1 << 8) | 1);
mmio_clrbits_32(CTL_REG(i, 71), 1);
/* Disable multicast */
mmio_clrbits_32(PHY_REG(0, 896), 1);
mmio_clrbits_32(PHY_REG(1, 896), 1);
dram_low_power_config();
}
/*
* arg0: bit0-7: sr_idle; bit8-15:sr_mc_gate_idle; bit16-31: standby idle
* arg1: bit0-11: pd_idle; bit 16-27: srpd_lite_idle
* arg2: bit0: if odt en
*/
uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2)
{
struct drv_odt_lp_config *lp_cfg = &rk3399_dram_status.drv_odt_lp_cfg;
uint32_t *low_power = &rk3399_dram_status.low_power_stat;
uint32_t dram_type, ch_count, pd_tmp, sr_tmp, i;
dram_type = rk3399_dram_status.timing_config.dram_type;
ch_count = rk3399_dram_status.timing_config.ch_cnt;
lp_cfg->sr_idle = arg0 & 0xff;
lp_cfg->sr_mc_gate_idle = (arg0 >> 8) & 0xff;
lp_cfg->standby_idle = (arg0 >> 16) & 0xffff;
lp_cfg->pd_idle = arg1 & 0xfff;
lp_cfg->srpd_lite_idle = (arg1 >> 16) & 0xfff;
rk3399_dram_status.timing_config.odt = arg2 & 0x1;
exit_low_power();
*low_power = 0;
mmio_clrbits_32(PI_REG(i, 60), 0x3 << 8);
mmio_clrbits_32(PI_REG(i, 80), (0x3 << 24) | (0x3 << 16));
mmio_clrbits_32(PI_REG(i, 100), 0x3 << 8);
mmio_clrbits_32(PI_REG(i, 124), 0x3 << 16);
/* pd_idle en */
if (lp_cfg->pd_idle)
*low_power |= ((1 << 0) | (1 << 8));
/* sr_idle en srpd_lite_idle */
if (lp_cfg->sr_idle | lp_cfg->srpd_lite_idle)
*low_power |= ((1 << 1) | (1 << 9));
/* sr_mc_gate_idle */
if (lp_cfg->sr_mc_gate_idle)
*low_power |= ((1 << 2) | (1 << 10));
/* standbyidle */
if (lp_cfg->standby_idle) {
if (rk3399_dram_status.timing_config.ch_cnt == 2)
*low_power |= ((1 << 3) | (1 << 11));
else
*low_power |= (1 << 3);
}
/* init drv odt */
if (rk3399_dram_status.index_freq[rk3399_dram_status.current_index] <
rk3399_dram_status.drv_odt_lp_cfg.odt_dis_freq)
rk3399_dram_status.timing_config.odt = 0;
else
rk3399_dram_status.timing_config.odt = 1;
gen_rk3399_set_ds_odt(&rk3399_dram_status.timing_config,
&rk3399_dram_status.drv_odt_lp_cfg);
dram_low_power_config(&rk3399_dram_status.drv_odt_lp_cfg);
pd_tmp = arg1;
if (dram_type != LPDDR4)
pd_tmp = arg1 & 0xfff;
sr_tmp = arg0 & 0xffff;
for (i = 0; i < ch_count; i++) {
mmio_write_32(CTL_REG(i, 102), pd_tmp);
mmio_clrsetbits_32(CTL_REG(i, 103), 0xffff, sr_tmp);
}
mmio_write_32(CIC_BASE + CIC_IDLE_TH, (arg0 >> 16) & 0xffff);
return 0;
}
static void m0_configure_ddr(struct pll_div pll_div, uint32_t ddr_index)
{
/* set PARAM to M0_FUNC_DRAM */
mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_DRAM);
mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(pll_div.fbdiv));
mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON1,
POSTDIV2(pll_div.postdiv2) | POSTDIV1(pll_div.postdiv1) |
REFDIV(pll_div.refdiv));
mmio_write_32(M0_PARAM_ADDR + PARAM_DRAM_FREQ, pll_div.mhz);
mmio_write_32(M0_PARAM_ADDR + PARAM_FREQ_SELECT, ddr_index << 4);
dmbst();
}
static uint32_t prepare_ddr_timing(uint32_t mhz)
......@@ -2220,20 +1982,15 @@ static uint32_t prepare_ddr_timing(uint32_t mhz)
rk3399_dram_status.timing_config.freq = mhz;
if (mhz < rk3399_dram_status.drv_odt_lp_cfg.ddr3_dll_dis_freq)
if (mhz < 300)
rk3399_dram_status.timing_config.dllbp = 1;
else
rk3399_dram_status.timing_config.dllbp = 0;
if (mhz < rk3399_dram_status.drv_odt_lp_cfg.odt_dis_freq) {
rk3399_dram_status.timing_config.odt = 0;
} else {
rk3399_dram_status.timing_config.odt = 1;
if (rk3399_dram_status.timing_config.odt == 1)
gen_rk3399_set_odt(1);
}
index = (rk3399_dram_status.current_index + 1) & 0x1;
if (rk3399_dram_status.index_freq[index] == mhz)
goto out;
/*
* checking if having available gate traiing timing for
......@@ -2249,8 +2006,6 @@ static uint32_t prepare_ddr_timing(uint32_t mhz)
&dram_timing, index);
rk3399_dram_status.index_freq[index] = mhz;
out:
return index;
}
......@@ -2271,33 +2026,39 @@ void print_dram_status_info(void)
uint32_t ddr_set_rate(uint32_t hz)
{
uint32_t low_power, index;
uint32_t low_power, index, ddr_index;
uint32_t mhz = hz / (1000 * 1000);
if (mhz ==
rk3399_dram_status.index_freq[rk3399_dram_status.current_index])
goto out;
return mhz;
index = to_get_clk_index(mhz);
mhz = dpll_rates_table[index].mhz;
low_power = exit_low_power();
index = prepare_ddr_timing(mhz);
if (index > 1)
ddr_index = prepare_ddr_timing(mhz);
gen_rk3399_enable_training(rk3399_dram_status.timing_config.ch_cnt,
mhz);
if (ddr_index > 1)
goto out;
dcf_start(mhz, index);
wait_dcf_done();
/*
* Make sure the clock is enabled. The M0 clocks should be on all of the
* time during S0.
*/
m0_configure_ddr(dpll_rates_table[index], ddr_index);
m0_start();
m0_wait_done();
m0_stop();
if (rk3399_dram_status.timing_config.odt == 0)
gen_rk3399_set_odt(0);
rk3399_dram_status.current_index = index;
if (mhz < dts_parameter.auto_pd_dis_freq)
low_power |= rk3399_dram_status.low_power_stat;
rk3399_dram_status.current_index = ddr_index;
low_power = rk3399_dram_status.low_power_stat;
resume_low_power(low_power);
out:
gen_rk3399_disable_training(rk3399_dram_status.timing_config.ch_cnt);
return mhz;
}
......@@ -2311,29 +2072,56 @@ uint32_t ddr_round_rate(uint32_t hz)
return dpll_rates_table[index].mhz * 1000 * 1000;
}
uint32_t dts_timing_receive(uint32_t timing, uint32_t index)
void ddr_prepare_for_sys_suspend(void)
{
uint32_t *p = (uint32_t *) &dts_parameter;
static uint32_t receive_nums;
if (index < (sizeof(dts_parameter) / sizeof(uint32_t) - 1)) {
p[index] = (uint32_t)timing;
receive_nums++;
} else {
dts_parameter.available = 0;
return -1;
}
uint32_t mhz =
rk3399_dram_status.index_freq[rk3399_dram_status.current_index];
/* receive all parameter */
if (receive_nums == (sizeof(dts_parameter) / sizeof(uint32_t) - 1)) {
dts_parameter.available = 1;
receive_nums = 0;
}
/*
* If we're not currently at the boot (assumed highest) frequency, we
* need to change frequencies to configure out current index.
*/
rk3399_suspend_status.freq = mhz;
exit_low_power();
rk3399_suspend_status.low_power_stat =
rk3399_dram_status.low_power_stat;
rk3399_suspend_status.odt = rk3399_dram_status.timing_config.odt;
rk3399_dram_status.low_power_stat = 0;
rk3399_dram_status.timing_config.odt = 1;
if (mhz != rk3399_dram_status.boot_freq)
ddr_set_rate(rk3399_dram_status.boot_freq * 1000 * 1000);
return index;
/*
* This will configure the other index to be the same frequency as the
* current one. We retrain both indices on resume, so both have to be
* setup for the same frequency.
*/
prepare_ddr_timing(rk3399_dram_status.boot_freq);
}
void ddr_dfs_init(void)
void ddr_prepare_for_sys_resume(void)
{
dram_related_init(&dts_parameter);
/* Disable multicast */
mmio_clrbits_32(PHY_REG(0, 896), 1);
mmio_clrbits_32(PHY_REG(1, 896), 1);
/* The suspend code changes the current index, so reset it now. */
rk3399_dram_status.current_index =
(mmio_read_32(CTL_REG(0, 111)) >> 16) & 0x3;
rk3399_dram_status.low_power_stat =
rk3399_suspend_status.low_power_stat;
rk3399_dram_status.timing_config.odt = rk3399_suspend_status.odt;
/*
* Set the saved frequency from suspend if it's different than the
* current frequency.
*/
if (rk3399_suspend_status.freq !=
rk3399_dram_status.index_freq[rk3399_dram_status.current_index]) {
ddr_set_rate(rk3399_suspend_status.freq * 1000 * 1000);
return;
}
gen_rk3399_set_odt(rk3399_dram_status.timing_config.odt);
resume_low_power(rk3399_dram_status.low_power_stat);
}
......@@ -48,65 +48,25 @@ struct rk3399_sdram_default_config {
unsigned char zqcsi;
};
struct ddr_dts_config_timing {
unsigned int ddr3_speed_bin;
unsigned int pd_idle;
unsigned int sr_idle;
unsigned int sr_mc_gate_idle;
unsigned int srpd_lite_idle;
unsigned int standby_idle;
unsigned int auto_pd_dis_freq;
unsigned int ddr3_dll_dis_freq;
unsigned int phy_dll_dis_freq;
unsigned int ddr3_odt_dis_freq;
unsigned int ddr3_drv;
unsigned int ddr3_odt;
unsigned int phy_ddr3_ca_drv;
unsigned int phy_ddr3_dq_drv;
unsigned int phy_ddr3_odt;
unsigned int lpddr3_odt_dis_freq;
unsigned int lpddr3_drv;
unsigned int lpddr3_odt;
unsigned int phy_lpddr3_ca_drv;
unsigned int phy_lpddr3_dq_drv;
unsigned int phy_lpddr3_odt;
unsigned int lpddr4_odt_dis_freq;
unsigned int lpddr4_drv;
unsigned int lpddr4_dq_odt;
unsigned int lpddr4_ca_odt;
unsigned int phy_lpddr4_ca_drv;
unsigned int phy_lpddr4_ck_cs_drv;
unsigned int phy_lpddr4_dq_drv;
unsigned int phy_lpddr4_odt;
uint32_t available;
};
struct drv_odt_lp_config {
uint32_t ddr3_speed_bin;
uint32_t pd_idle;
uint32_t sr_idle;
uint32_t sr_mc_gate_idle;
uint32_t srpd_lite_idle;
uint32_t standby_idle;
uint32_t ddr3_dll_dis_freq;/* for ddr3 only */
uint32_t phy_dll_dis_freq;
uint32_t odt_dis_freq;
uint32_t odt_en;
uint32_t dram_side_drv;
uint32_t dram_side_dq_odt;
uint32_t dram_side_ca_odt;
uint32_t phy_side_ca_drv;
uint32_t phy_side_ck_cs_drv;
uint32_t phy_side_dq_drv;
uint32_t phy_side_odt;
};
void ddr_dfs_init(void);
uint32_t ddr_set_rate(uint32_t hz);
uint32_t ddr_round_rate(uint32_t hz);
uint32_t ddr_get_rate(void);
void clr_dcf_irq(void);
uint32_t dts_timing_receive(uint32_t timing, uint32_t index);
uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2);
void dram_dfs_init(void);
void ddr_prepare_for_sys_suspend(void);
void ddr_prepare_for_sys_resume(void);
#endif
......@@ -30,6 +30,7 @@
#include <dram.h>
#include <plat_private.h>
#include <secure.h>
#include <soc.h>
#include <rk3399_def.h>
......
......@@ -30,111 +30,11 @@
#ifndef __SOC_ROCKCHIP_RK3399_DRAM_H__
#define __SOC_ROCKCHIP_RK3399_DRAM_H__
#include <dram_regs.h>
#include <plat_private.h>
#include <stdint.h>
#define CTL_BASE(ch) (0xffa80000 + (ch) * 0x8000)
#define CTL_REG(ch, n) (CTL_BASE(ch) + (n) * 0x4)
#define PI_OFFSET 0x800
#define PI_BASE(ch) (CTL_BASE(ch) + PI_OFFSET)
#define PI_REG(ch, n) (PI_BASE(ch) + (n) * 0x4)
#define PHY_OFFSET 0x2000
#define PHY_BASE(ch) (CTL_BASE(ch) + PHY_OFFSET)
#define PHY_REG(ch, n) (PHY_BASE(ch) + (n) * 0x4)
#define MSCH_BASE(ch) (0xffa84000 + (ch) * 0x8000)
#define MSCH_ID_COREID 0x0
#define MSCH_ID_REVISIONID 0x4
#define MSCH_DEVICECONF 0x8
#define MSCH_DEVICESIZE 0xc
#define MSCH_DDRTIMINGA0 0x10
#define MSCH_DDRTIMINGB0 0x14
#define MSCH_DDRTIMINGC0 0x18
#define MSCH_DEVTODEV0 0x1c
#define MSCH_DDRMODE 0x110
#define MSCH_AGINGX0 0x1000
#define CIC_CTRL0 0x0
#define CIC_CTRL1 0x4
#define CIC_IDLE_TH 0x8
#define CIC_CG_WAIT_TH 0xc
#define CIC_STATUS0 0x10
#define CIC_STATUS1 0x14
#define CIC_CTRL2 0x18
#define CIC_CTRL3 0x1c
#define CIC_CTRL4 0x20
/* DENALI_CTL_00 */
#define START 1
/* DENALI_CTL_68 */
#define PWRUP_SREFRESH_EXIT (1 << 16)
/* DENALI_CTL_274 */
#define MEM_RST_VALID 1
#define PHY_DRV_ODT_Hi_Z 0x0
#define PHY_DRV_ODT_240 0x1
#define PHY_DRV_ODT_120 0x8
#define PHY_DRV_ODT_80 0x9
#define PHY_DRV_ODT_60 0xc
#define PHY_DRV_ODT_48 0xd
#define PHY_DRV_ODT_40 0xe
#define PHY_DRV_ODT_34_3 0xf
/*
* sys_reg bitfield struct
* [31] row_3_4_ch1
* [30] row_3_4_ch0
* [29:28] chinfo
* [27] rank_ch1
* [26:25] col_ch1
* [24] bk_ch1
* [23:22] cs0_row_ch1
* [21:20] cs1_row_ch1
* [19:18] bw_ch1
* [17:16] dbw_ch1;
* [15:13] ddrtype
* [12] channelnum
* [11] rank_ch0
* [10:9] col_ch0
* [8] bk_ch0
* [7:6] cs0_row_ch0
* [5:4] cs1_row_ch0
* [3:2] bw_ch0
* [1:0] dbw_ch0
*/
#define SYS_REG_ENC_ROW_3_4(n, ch) ((n) << (30 + (ch)))
#define SYS_REG_DEC_ROW_3_4(n, ch) (((n) >> (30 + (ch))) & 0x1)
#define SYS_REG_ENC_CHINFO(ch) (1 << (28 + (ch)))
#define SYS_REG_DEC_CHINFO(n, ch) (((n) >> (28 + (ch))) & 0x1)
#define SYS_REG_ENC_DDRTYPE(n) ((n) << 13)
#define SYS_REG_DEC_DDRTYPE(n) (((n) >> 13) & 0x7)
#define SYS_REG_ENC_NUM_CH(n) (((n) - 1) << 12)
#define SYS_REG_DEC_NUM_CH(n) (1 + (((n) >> 12) & 0x1))
#define SYS_REG_ENC_RANK(n, ch) (((n) - 1) << (11 + (ch) * 16))
#define SYS_REG_DEC_RANK(n, ch) (1 + (((n) >> (11 + (ch) * 16)) & 0x1))
#define SYS_REG_ENC_COL(n, ch) (((n) - 9) << (9 + (ch) * 16))
#define SYS_REG_DEC_COL(n, ch) (9 + (((n) >> (9 + (ch) * 16)) & 0x3))
#define SYS_REG_ENC_BK(n, ch) (((n) == 3 ? 0 : 1) << (8 + (ch) * 16))
#define SYS_REG_DEC_BK(n, ch) (3 - (((n) >> (8 + (ch) * 16)) & 0x1))
#define SYS_REG_ENC_CS0_ROW(n, ch) (((n) - 13) << (6 + (ch) * 16))
#define SYS_REG_DEC_CS0_ROW(n, ch) (13 + (((n) >> (6 + (ch) * 16)) & 0x3))
#define SYS_REG_ENC_CS1_ROW(n, ch) (((n) - 13) << (4 + (ch) * 16))
#define SYS_REG_DEC_CS1_ROW(n, ch) (13 + (((n) >> (4 + (ch) * 16)) & 0x3))
#define SYS_REG_ENC_BW(n, ch) ((2 >> (n)) << (2 + (ch) * 16))
#define SYS_REG_DEC_BW(n, ch) (2 >> (((n) >> (2 + (ch) * 16)) & 0x3))
#define SYS_REG_ENC_DBW(n, ch) ((2 >> (n)) << (0 + (ch) * 16))
#define SYS_REG_DEC_DBW(n, ch) (2 >> (((n) >> (0 + (ch) * 16)) & 0x3))
#define DDR_STRIDE(n) mmio_write_32(SGRF_BASE + SGRF_SOC_CON3_7(4), \
(0x1f<<(10+16))|((n)<<10))
#define CTL_REG_NUM 332
#define PHY_REG_NUM 959
#define PI_REG_NUM 200
enum {
DDR3 = 3,
LPDDR2 = 5,
......@@ -259,6 +159,7 @@ struct rk3399_sdram_params {
struct rk3399_ddr_pctl_regs pctl_regs;
struct rk3399_ddr_pi_regs pi_regs;
struct rk3399_ddr_publ_regs phy_regs;
uint32_t rx_cal_dqs[2][4];
};
extern __sramdata struct rk3399_sdram_params sdram_config;
......
......@@ -267,21 +267,24 @@ static void ddr3_get_parameter(struct timing_related_config *timing_config,
break;
}
switch (timing_config->dramodt) {
case 60:
pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_60;
break;
case 40:
pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_40;
break;
case 120:
pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_120;
break;
case 0:
default:
if (timing_config->odt)
switch (timing_config->dramodt) {
case 60:
pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_60;
break;
case 40:
pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_40;
break;
case 120:
pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_120;
break;
case 0:
default:
pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_DIS;
break;
}
else
pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_DIS;
break;
}
pdram_timing->mr[2] = DDR3_MR2_CWL(pdram_timing->cwl);
pdram_timing->mr[3] = 0;
......@@ -664,6 +667,9 @@ static void lpddr2_get_parameter(struct timing_related_config *timing_config,
#define LPDDR3_TADR (20) /* ns */
#define LPDDR3_TMRZ (3) /* ns */
/* FSP */
#define LPDDR3_TFC_LONG (250) /* ns */
/*
* Description: depend on input parameter "timing_config",
* and calculate all lpddr3
......@@ -751,18 +757,21 @@ static void lpddr3_get_parameter(struct timing_related_config *timing_config,
break;
}
pdram_timing->mr[0] = 0;
switch (timing_config->dramodt) {
case 60:
pdram_timing->mr11 = LPDDR3_ODT_60;
break;
case 120:
pdram_timing->mr11 = LPDDR3_ODT_120;
break;
case 240:
default:
pdram_timing->mr11 = LPDDR3_ODT_240;
break;
}
if (timing_config->odt)
switch (timing_config->dramodt) {
case 60:
pdram_timing->mr11 = LPDDR3_ODT_60;
break;
case 120:
pdram_timing->mr11 = LPDDR3_ODT_120;
break;
case 240:
default:
pdram_timing->mr11 = LPDDR3_ODT_240;
break;
}
else
pdram_timing->mr11 = LPDDR3_ODT_DIS;
pdram_timing->tinit1 = (LPDDR3_TINIT1 * nmhz + 999) / 1000;
pdram_timing->tinit2 = LPDDR3_TINIT2;
......@@ -874,6 +883,9 @@ static void lpddr3_get_parameter(struct timing_related_config *timing_config,
pdram_timing->tadr = (LPDDR3_TADR * nmhz + 999) / 1000;
pdram_timing->tmrz = (LPDDR3_TMRZ * nmhz + 999) / 1000;
pdram_timing->tcacd = pdram_timing->tadr + 2;
/* FSP */
pdram_timing->tfc_long = (LPDDR3_TFC_LONG * nmhz + 999) / 1000;
}
#define LPDDR4_TINIT1 (200000) /* 200us */
......@@ -1113,47 +1125,52 @@ static void lpddr4_get_parameter(struct timing_related_config *timing_config,
break;
}
pdram_timing->mr[0] = 0;
switch (timing_config->dramodt) {
case 240:
tmp = LPDDR4_DQODT_240;
break;
case 120:
tmp = LPDDR4_DQODT_120;
break;
case 80:
tmp = LPDDR4_DQODT_80;
break;
case 60:
tmp = LPDDR4_DQODT_60;
break;
case 48:
tmp = LPDDR4_DQODT_48;
break;
case 40:
default:
tmp = LPDDR4_DQODT_40;
break;
}
switch (timing_config->caodt) {
case 240:
pdram_timing->mr11 = LPDDR4_CAODT_240 | tmp;
break;
case 120:
pdram_timing->mr11 = LPDDR4_CAODT_120 | tmp;
break;
case 80:
pdram_timing->mr11 = LPDDR4_CAODT_80 | tmp;
break;
case 60:
pdram_timing->mr11 = LPDDR4_CAODT_60 | tmp;
break;
case 48:
pdram_timing->mr11 = LPDDR4_CAODT_48 | tmp;
break;
case 40:
default:
pdram_timing->mr11 = LPDDR4_CAODT_40 | tmp;
break;
if (timing_config->odt) {
switch (timing_config->dramodt) {
case 240:
tmp = LPDDR4_DQODT_240;
break;
case 120:
tmp = LPDDR4_DQODT_120;
break;
case 80:
tmp = LPDDR4_DQODT_80;
break;
case 60:
tmp = LPDDR4_DQODT_60;
break;
case 48:
tmp = LPDDR4_DQODT_48;
break;
case 40:
default:
tmp = LPDDR4_DQODT_40;
break;
}
switch (timing_config->caodt) {
case 240:
pdram_timing->mr11 = LPDDR4_CAODT_240 | tmp;
break;
case 120:
pdram_timing->mr11 = LPDDR4_CAODT_120 | tmp;
break;
case 80:
pdram_timing->mr11 = LPDDR4_CAODT_80 | tmp;
break;
case 60:
pdram_timing->mr11 = LPDDR4_CAODT_60 | tmp;
break;
case 48:
pdram_timing->mr11 = LPDDR4_CAODT_48 | tmp;
break;
case 40:
default:
pdram_timing->mr11 = LPDDR4_CAODT_40 | tmp;
break;
}
} else {
pdram_timing->mr11 = LPDDR4_CAODT_DIS | tmp;
}
pdram_timing->tinit1 = (LPDDR4_TINIT1 * nmhz + 999) / 1000;
......
......@@ -34,6 +34,7 @@
#include <dram.h>
#include <pmu_regs.h>
#include <rk3399_def.h>
#include <secure.h>
#include <soc.h>
#include <suspend.h>
......@@ -571,14 +572,15 @@ static __sramfunc void pctl_cfg(uint32_t ch,
sram_regcpy(PHY_REG(ch, 768), (uintptr_t)&params_phy[768], 38);
}
static __sramfunc int dram_switch_to_phy_index1(
static __sramfunc int dram_switch_to_next_index(
struct rk3399_sdram_params *sdram_params)
{
uint32_t ch, ch_count;
uint32_t fn = ((mmio_read_32(CTL_REG(0, 111)) >> 16) + 1) & 0x1;
mmio_write_32(CIC_BASE + CIC_CTRL0,
(((0x3 << 4) | (1 << 2) | 1) << 16) |
(1 << 4) | (1 << 2) | 1);
(fn << 4) | (1 << 2) | 1);
while (!(mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 2)))
;
......@@ -591,7 +593,7 @@ static __sramfunc int dram_switch_to_phy_index1(
/* LPDDR4 f2 cann't do training, all training will fail */
for (ch = 0; ch < ch_count; ch++) {
mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1,
1 << 8);
fn << 8);
/* data_training failed */
if (data_training(ch, sdram_params, PI_FULL_TRAINING))
......@@ -609,6 +611,7 @@ static __sramfunc int pctl_start(uint32_t channel_mask,
struct rk3399_sdram_params *sdram_params)
{
uint32_t count;
uint32_t byte;
mmio_setbits_32(CTL_REG(0, 68), PWRUP_SREFRESH_EXIT);
mmio_setbits_32(CTL_REG(1, 68), PWRUP_SREFRESH_EXIT);
......@@ -640,6 +643,12 @@ static __sramfunc int pctl_start(uint32_t channel_mask,
}
mmio_clrbits_32(CTL_REG(0, 68), PWRUP_SREFRESH_EXIT);
/* Restore the PHY_RX_CAL_DQS value */
for (byte = 0; byte < 4; byte++)
mmio_clrsetbits_32(PHY_REG(0, 57 + 128 * byte),
0xfff << 16,
sdram_params->rx_cal_dqs[0][byte]);
}
if (channel_mask & (1 << 1)) {
count = 0;
......@@ -653,6 +662,12 @@ static __sramfunc int pctl_start(uint32_t channel_mask,
}
mmio_clrbits_32(CTL_REG(1, 68), PWRUP_SREFRESH_EXIT);
/* Restore the PHY_RX_CAL_DQS value */
for (byte = 0; byte < 4; byte++)
mmio_clrsetbits_32(PHY_REG(1, 57 + 128 * byte),
0xfff << 16,
sdram_params->rx_cal_dqs[1][byte]);
}
return 0;
......@@ -665,7 +680,7 @@ void dmc_save(void)
uint32_t *params_pi;
uint32_t *params_phy;
uint32_t refdiv, postdiv2, postdiv1, fbdiv;
uint32_t tmp;
uint32_t tmp, ch, byte;
params_ctl = sdram_params->pctl_regs.denali_ctl;
params_pi = sdram_params->pi_regs.denali_pi;
......@@ -705,6 +720,12 @@ void dmc_save(void)
sram_regcpy((uintptr_t)&params_phy[768], PHY_REG(0, 768), 38);
sram_regcpy((uintptr_t)&params_phy[896], PHY_REG(0, 896), 63);
for (ch = 0; ch < sdram_params->num_channels; ch++) {
for (byte = 0; byte < 4; byte++)
sdram_params->rx_cal_dqs[ch][byte] = (0xfff << 16) &
mmio_read_32(PHY_REG(ch, 57 + byte * 128));
}
/* set DENALI_PHY_957_DATA.PHY_DLL_RST_EN = 0x1 */
params_phy[957] &= ~(0x3 << 24);
params_phy[957] |= 1 << 24;
......@@ -754,5 +775,5 @@ retry:
dram_all_config(sdram_params);
/* Switch to index 1 and prepare for DDR frequency switch. */
dram_switch_to_phy_index1(sdram_params);
dram_switch_to_next_index(sdram_params);
}
......@@ -46,32 +46,29 @@ export Q
.SUFFIXES:
INCLUDES += -Iinclude/
INCLUDES += -Iinclude/ \
-I../../include/shared/
# NOTE: Add C source files here
C_SOURCES := src/startup.c \
src/main.c
src/main.c \
src/suspend.c \
src/dram.c \
src/stopwatch.c
# Flags definition
CFLAGS := -g
ASFLAGS := -g -Wa,--gdwarf-2
ASFLAGS += -mcpu=$(ARCH) -mthumb -Wall -ffunction-sections -O3
CFLAGS += -mcpu=$(ARCH) -mthumb -Wall -ffunction-sections -O3
LDFLAGS := -mcpu=$(ARCH) -mthumb -g -nostartfiles -nostdlib -O3
LDFLAGS += -Wl,--gc-sections -Wl,--build-id=none
COMMON_FLAGS := -g -mcpu=$(ARCH) -mthumb -Wall -O3 -nostdlib -mfloat-abi=soft
CFLAGS := -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-common
ASFLAGS := -Wa,--gdwarf-2
LDFLAGS := -Wl,--gc-sections -Wl,--build-id=none
# Cross tool
CC := ${M0_CROSS_COMPILE}gcc
CPP := ${M0_CROSS_COMPILE}cpp
AS := ${M0_CROSS_COMPILE}gcc
AR := ${M0_CROSS_COMPILE}ar
LD := ${M0_CROSS_COMPILE}ld
OC := ${M0_CROSS_COMPILE}objcopy
OD := ${M0_CROSS_COMPILE}objdump
NM := ${M0_CROSS_COMPILE}nm
PP := ${M0_CROSS_COMPILE}gcc -E ${CFLAGS}
# NOTE: The line continuation '\' is required in the next define otherwise we
# end up with a line-feed characer at the end of the last c filename.
......@@ -83,10 +80,11 @@ endef
SOURCES := $(C_SOURCES)
OBJS := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES)))
LINKERFILE := src/rk3399m0.ld
LINKERFILE := $(BUILD)/$(PLAT_M0).ld
MAPFILE := $(BUILD)/$(PLAT_M0).map
ELF := $(BUILD)/$(PLAT_M0).elf
BIN := $(BUILD)/$(PLAT_M0).bin
LINKERFILE_SRC := src/$(PLAT_M0).ld.S
# Function definition related compilation
define MAKE_C
......@@ -95,7 +93,7 @@ $(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2))))
$(OBJ) : $(2)
@echo " CC $$<"
$$(Q)$$(CC) $$(CFLAGS) $$(INCLUDES) -MMD -MT $$@ -c $$< -o $$@
$$(Q)$$(CC) $$(COMMON_FLAGS) $$(CFLAGS) $$(INCLUDES) -MMD -MT $$@ -c $$< -o $$@
endef
define MAKE_S
......@@ -103,7 +101,7 @@ $(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2))))
$(OBJ) : $(2)
@echo " AS $$<"
$$(Q)$$(AS) $$(ASFLAGS) -c $$< -o $$@
$$(Q)$$(CC) -x assembler-with-cpp $$(COMMON_FLAGS) $$(ASFLAGS) -c $$< -o $$@
endef
define MAKE_OBJS
......@@ -118,13 +116,15 @@ define MAKE_OBJS
$(and $(REMAIN),$(error Unexpected source files present: $(REMAIN)))
endef
.PHONY: all
all: $(BIN)
.DEFAULT_GOAL := $(BIN)
$(LINKERFILE): $(LINKERFILE_SRC)
$(CC) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF $@.d -MT $@ -o $@ $<
-include $(LINKERFILE).d
$(ELF) : $(OBJS) $(LINKERFILE)
@echo " LD $@"
$(Q)$(CC) -o $@ $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) \
$(OBJS)
$(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS)
$(BIN) : $(ELF)
@echo " BIN $@"
......
......@@ -28,13 +28,12 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __RK3399M0_H__
#define __RK3399M0_H__
#ifndef __ROCKCHIP_RK3399_M0_INCLUDE_SHARED_ADDRESSMAP_H__
#define __ROCKCHIP_RK3399_M0_INCLUDE_SHARED_ADDRESSMAP_H__
/* pmu_fw.c */
extern char rk3399m0_bin[];
extern char rk3399m0_bin_end[];
#include <addressmap_shared.h>
#define M0_BINCODE_BASE ((uintptr_t)rk3399m0_bin)
/* Registers base address for M0 */
#define MMIO_BASE 0x40000000
#endif /* __RK3399M0_H__ */
#endif /* __ROCKCHIP_RK3399_M0_INCLUDE_SHARED_ADDRESSMAP_H__ */
......@@ -31,11 +31,28 @@
#ifndef __RK3399_MCU_H__
#define __RK3399_MCU_H__
#define readl(c) ({unsigned int __v = \
#include <addressmap.h>
typedef unsigned int uint32_t;
#define mmio_read_32(c) ({unsigned int __v = \
(*(volatile unsigned int *)(c)); __v; })
#define writel(v, c) ((*(volatile unsigned int *) (c)) = (v))
#define mmio_write_32(c, v) ((*(volatile unsigned int *)(c)) = (v))
#define mmio_clrbits_32(addr, clear) \
mmio_write_32(addr, (mmio_read_32(addr) & ~(clear)))
#define mmio_setbits_32(addr, set) \
mmio_write_32(addr, (mmio_read_32(addr)) | (set))
#define mmio_clrsetbits_32(addr, clear, set) \
mmio_write_32(addr, (mmio_read_32(addr) & ~(clear)) | (set))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MCU_BASE 0x40000000
#define PMU_BASE (MCU_BASE + 0x07310000)
void handle_suspend(void);
void handle_dram(void);
void stopwatch_init_usecs_expire(unsigned int usecs);
int stopwatch_expired(void);
void stopwatch_reset(void);
#endif /* __RK3399_MCU_H__ */
/*
* Copyright (c) 2016, ARM Limited and Contributors. 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 following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 <dram_regs.h>
#include <m0_param.h>
#include <pmu_bits.h>
#include <pmu_regs.h>
#include "misc_regs.h"
#include "rk3399_mcu.h"
static uint32_t gatedis_con0;
static void idle_port(void)
{
gatedis_con0 = mmio_read_32(PMUCRU_BASE + PMU_CRU_GATEDIS_CON0);
mmio_write_32(PMUCRU_BASE + PMU_CRU_GATEDIS_CON0, 0x3fffffff);
mmio_setbits_32(PMU_BASE + PMU_BUS_IDLE_REQ,
(1 << PMU_IDLE_REQ_MSCH0) | (1 << PMU_IDLE_REQ_MSCH1));
while ((mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) &
((1 << PMU_IDLE_ST_MSCH1) | (1 << PMU_IDLE_ST_MSCH0))) !=
((1 << PMU_IDLE_ST_MSCH1) | (1 << PMU_IDLE_ST_MSCH0)))
continue;
}
static void deidle_port(void)
{
mmio_clrbits_32(PMU_BASE + PMU_BUS_IDLE_REQ,
(1 << PMU_IDLE_REQ_MSCH0) | (1 << PMU_IDLE_REQ_MSCH1));
while (mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) &
((1 << PMU_IDLE_ST_MSCH1) | (1 << PMU_IDLE_ST_MSCH0)))
continue;
/* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */
mmio_write_32(PMUCRU_BASE + PMU_CRU_GATEDIS_CON0, gatedis_con0);
}
static void ddr_set_pll(void)
{
mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_SLOW_MODE));
mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_POWER_DOWN(1));
mmio_write_32(CRU_BASE + CRU_DPLL_CON0,
mmio_read_32(PARAM_ADDR + PARAM_DPLL_CON0));
mmio_write_32(CRU_BASE + CRU_DPLL_CON1,
mmio_read_32(PARAM_ADDR + PARAM_DPLL_CON1));
mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_POWER_DOWN(0));
while ((mmio_read_32(CRU_BASE + CRU_DPLL_CON2) & (1u << 31)) == 0)
continue;
mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_NORMAL_MODE));
}
void handle_dram(void)
{
mmio_setbits_32(PHY_REG(0, 927), (1 << 22));
mmio_setbits_32(PHY_REG(1, 927), (1 << 22));
idle_port();
mmio_write_32(CIC_BASE + CIC_CTRL0,
(((0x3 << 4) | (1 << 2) | 1) << 16) |
(1 << 2) | 1 |
mmio_read_32(PARAM_ADDR + PARAM_FREQ_SELECT));
while ((mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 2)) == 0)
continue;
ddr_set_pll();
mmio_write_32(CIC_BASE + CIC_CTRL0, 0x20002);
while ((mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 0)) == 0)
continue;
deidle_port();
mmio_clrbits_32(PHY_REG(0, 927), (1 << 22));
mmio_clrbits_32(PHY_REG(1, 927), (1 << 22));
}
......@@ -28,44 +28,24 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <m0_param.h>
#include "rk3399_mcu.h"
#define PMU_PWRMODE_CON 0x20
#define PMU_POWER_ST 0x78
#define M0_SCR 0xe000ed10 /* System Control Register (SCR) */
#define SCR_SLEEPDEEP_SHIFT (1 << 2)
static void system_wakeup(void)
__attribute__((noreturn)) void main(void)
{
unsigned int status_value;
unsigned int mode_con;
while (1) {
status_value = readl(PMU_BASE + PMU_POWER_ST);
if (status_value) {
mode_con = readl(PMU_BASE + PMU_PWRMODE_CON);
writel(mode_con & (~0x01),
PMU_BASE + PMU_PWRMODE_CON);
return;
}
switch (mmio_read_32(PARAM_ADDR + PARAM_M0_FUNC)) {
case M0_FUNC_SUSPEND:
handle_suspend();
break;
case M0_FUNC_DRAM:
handle_dram();
break;
default:
break;
}
}
int main(void)
{
unsigned int reg_src;
system_wakeup();
reg_src = readl(M0_SCR);
/* m0 enter deep sleep mode */
writel(reg_src | SCR_SLEEPDEEP_SHIFT, M0_SCR);
mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG);
for (;;)
__asm volatile("wfi");
return 0;
__asm__ volatile ("wfi");
}
......@@ -28,12 +28,16 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <m0_param.h>
OUTPUT_FORMAT("elf32-littlearm")
SECTIONS {
.m0_bin 0 : {
KEEP(*(.isr_vector))
ASSERT(. == 0xc0, "ISR vector has the wrong size.");
ASSERT(. == PARAM_ADDR, "M0 params should go right behind ISR table.");
. += PARAM_M0_SIZE;
*(.text*)
*(.rodata*)
*(.data*)
......
/*
* Copyright (c) 2016, ARM Limited and Contributors. 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 following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 <m0_param.h>
#include "rk3399_mcu.h"
/* use 24MHz SysTick */
#define US_TO_CYCLE(US) (US * 24)
#define SYST_CST 0xe000e010
/* enable counter */
#define ENABLE (1 << 0)
/* count down to 0 does not cause SysTick exception to pend */
#define TICKINT (1 << 1)
/* core clock used for SysTick */
#define CLKSOURCE (1 << 2)
#define COUNTFLAG (1 << 16)
#define SYST_RVR 0xe000e014
#define MAX_VALUE 0xffffff
#define MAX_USECS (MAX_VALUE / US_TO_CYCLE(1))
#define SYST_CVR 0xe000e018
#define SYST_CALIB 0xe000e01c
unsigned int remaining_usecs;
static inline void stopwatch_set_usecs(void)
{
unsigned int cycle;
unsigned int usecs = MIN(MAX_USECS, remaining_usecs);
remaining_usecs -= usecs;
cycle = US_TO_CYCLE(usecs);
mmio_write_32(SYST_RVR, cycle);
mmio_write_32(SYST_CVR, 0);
mmio_write_32(SYST_CST, ENABLE | TICKINT | CLKSOURCE);
}
void stopwatch_init_usecs_expire(unsigned int usecs)
{
/*
* Enter an inifite loop if the stopwatch is in use. This will allow the
* state to be analyzed with a debugger.
*/
if (mmio_read_32(SYST_CST) & ENABLE)
while (1)
;
remaining_usecs = usecs;
stopwatch_set_usecs();
}
int stopwatch_expired(void)
{
int val = mmio_read_32(SYST_CST);
if ((val & COUNTFLAG) || !(val & ENABLE)) {
if (!remaining_usecs)
return 1;
stopwatch_set_usecs();
}
return 0;
}
void stopwatch_reset(void)
{
mmio_clrbits_32(SYST_CST, ENABLE);
remaining_usecs = 0;
}
/*
* Copyright (c) 2016, ARM Limited and Contributors. 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 following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 <pmu_regs.h>
#include "rk3399_mcu.h"
#define M0_SCR 0xe000ed10 /* System Control Register (SCR) */
#define SCR_SLEEPDEEP_SHIFT (1 << 2)
void handle_suspend(void)
{
unsigned int status_value;
while (1) {
status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
if (status_value) {
mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01);
return;
}
}
/* m0 enter deep sleep mode */
mmio_setbits_32(M0_SCR, SCR_SLEEPDEEP_SHIFT);
}
/*
* Copyright (c) 2016, ARM Limited and Contributors. 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 following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 <arch_helpers.h>
#include <assert.h>
#include <debug.h>
#include <delay_timer.h>
#include <mmio.h>
#include <m0_ctl.h>
#include <plat_private.h>
#include <rk3399_def.h>
#include <secure.h>
#include <soc.h>
void m0_init(void)
{
/* secure config for M0 */
mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7));
mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), WMSK_BIT(12));
/* set the execute address for M0 */
mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3),
BITS_WITH_WMASK((M0_BINCODE_BASE >> 12) & 0xffff,
0xffff, 0));
mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7),
BITS_WITH_WMASK((M0_BINCODE_BASE >> 28) & 0xf,
0xf, 0));
/* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */
mmio_setbits_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, 0x02);
/*
* To switch the parent to xin24M and div == 1,
*
* We need to close most of the PLLs and clocks except the OSC 24MHz
* durning suspend, and this should be enough to supplies the ddrfreq,
* For the simple handle, we just keep the fixed 24MHz to supply the
* suspend and ddrfreq directly.
*/
mmio_write_32(PMUCRU_BASE + PMUCRU_CLKSEL_CON0,
BIT_WITH_WMSK(15) | BITS_WITH_WMASK(0x0, 0x1f, 8));
mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, WMSK_BIT(5));
}
void m0_start(void)
{
/* enable clocks for M0 */
mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2,
BITS_WITH_WMASK(0x0, 0xf, 0));
/* clean the PARAM_M0_DONE flag, mean that M0 will start working */
mmio_write_32(M0_PARAM_ADDR + PARAM_M0_DONE, 0);
dmbst();
mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
BITS_WITH_WMASK(0x0, 0x4, 0));
udelay(5);
/* start M0 */
mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
BITS_WITH_WMASK(0x0, 0x20, 0));
dmbst();
}
void m0_stop(void)
{
/* stop M0 */
mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
BITS_WITH_WMASK(0x24, 0x24, 0));
/* disable clocks for M0 */
mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2,
BITS_WITH_WMASK(0xf, 0xf, 0));
}
void m0_wait_done(void)
{
do {
/*
* Don't starve the M0 for access to SRAM, so delay before
* reading the PARAM_M0_DONE value again.
*/
udelay(5);
dsb();
} while (mmio_read_32(M0_PARAM_ADDR + PARAM_M0_DONE) != M0_DONE_FLAG);
/*
* Let the M0 settle into WFI before we leave. This is so we don't reset
* the M0 in a bad spot which can cause problems with the M0.
*/
udelay(10);
dsb();
}
/*
* Copyright (c) 2016, ARM Limited and Contributors. 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 following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 __M0_CTL_H__
#define __M0_CTL_H__
#include <m0_param.h>
#define M0_BINCODE_BASE ((uintptr_t)rk3399m0_bin)
#define M0_PARAM_ADDR (M0_BINCODE_BASE + PARAM_ADDR)
/* pmu_fw.c */
extern char rk3399m0_bin[];
extern char rk3399m0_bin_end[];
extern void m0_init(void);
extern void m0_start(void);
extern void m0_stop(void);
extern void m0_wait_done(void);
#endif /* __M0_CTL_H__ */
......@@ -33,21 +33,23 @@
#include <bakery_lock.h>
#include <debug.h>
#include <delay_timer.h>
#include <dfs.h>
#include <errno.h>
#include <gpio.h>
#include <mmio.h>
#include <m0_ctl.h>
#include <platform.h>
#include <platform_def.h>
#include <plat_params.h>
#include <plat_private.h>
#include <rk3399_def.h>
#include <pmu_sram.h>
#include <secure.h>
#include <soc.h>
#include <pmu.h>
#include <pmu_com.h>
#include <pwm.h>
#include <bl31.h>
#include <rk3399m0.h>
#include <suspend.h>
DEFINE_BAKERY_LOCK(rockchip_pd_lock);
......@@ -1065,36 +1067,10 @@ static void resume_gpio(void)
}
}
static void m0_clock_init(void)
static void m0_configure_suspend(void)
{
/* enable clocks for M0 */
mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2,
BITS_WITH_WMASK(0x0, 0x2f, 0));
/* switch the parent to xin24M and div == 1 */
mmio_write_32(PMUCRU_BASE + PMUCRU_CLKSEL_CON0,
BIT_WITH_WMSK(15) | BITS_WITH_WMASK(0x0, 0x1f, 8));
/* start M0 */
mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
BITS_WITH_WMASK(0x0, 0x24, 0));
/* gating disable for M0 */
mmio_write_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, BIT_WITH_WMSK(1));
}
static void m0_reset(void)
{
/* stop M0 */
mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
BITS_WITH_WMASK(0x24, 0x24, 0));
/* recover gating bit for M0 */
mmio_write_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, WMSK_BIT(1));
/* disable clocks for M0 */
mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2,
BITS_WITH_WMASK(0x2f, 0x2f, 0));
/* set PARAM to M0_FUNC_SUSPEND */
mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_SUSPEND);
}
static int sys_pwr_domain_suspend(void)
......@@ -1102,6 +1078,7 @@ static int sys_pwr_domain_suspend(void)
uint32_t wait_cnt = 0;
uint32_t status = 0;
ddr_prepare_for_sys_suspend();
dmc_save();
pmu_scu_b_pwrdn();
......@@ -1117,11 +1094,12 @@ static int sys_pwr_domain_suspend(void)
sys_slp_config();
m0_clock_init();
m0_configure_suspend();
m0_start();
pmu_sgrf_rst_hld();
mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1),
mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
(PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) |
CPU_BOOT_ADDR_WMASK);
......@@ -1173,7 +1151,7 @@ static int sys_pwr_domain_resume(void)
udelay(300);
enable_dvfs_plls();
secure_watchdog_restore();
secure_watchdog_enable();
/* restore clk_ddrc_bpll_src_en gate */
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3),
......@@ -1189,7 +1167,7 @@ static int sys_pwr_domain_resume(void)
mmio_write_32(PMU_BASE + PMU_WAKEUP_STATUS, 0xffffffff);
mmio_write_32(PMU_BASE + PMU_WKUP_CFG4, 0x00);
mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1),
mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
(cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) |
CPU_BOOT_ADDR_WMASK);
......@@ -1241,8 +1219,9 @@ static int sys_pwr_domain_resume(void)
BIT(PMU_CLR_GIC));
plat_rockchip_gic_cpuif_enable();
m0_stop();
m0_reset();
ddr_prepare_for_sys_resume();
return 0;
}
......@@ -1328,7 +1307,7 @@ void plat_rockchip_pmu_init(void)
psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
/* config cpu's warm boot address */
mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1),
mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
(cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) |
CPU_BOOT_ADDR_WMASK);
mmio_write_32(PMU_BASE + PMU_NOC_AUTO_ENA, NOC_AUTO_ENABLE);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment