diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.c b/plat/rockchip/rk3399/drivers/dram/dfs.c new file mode 100644 index 000000000..4fdd3894d --- /dev/null +++ b/plat/rockchip/rk3399/drivers/dram/dfs.c @@ -0,0 +1,2339 @@ +/* + * 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 +#include +#include +#include "dfs.h" +#include "dram.h" +#include "dram_spec_timing.h" +#include "string.h" +#include "soc.h" +#include "pmu.h" + +#include + +#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; +}; + +static const struct pll_div dpll_rates_table[] = { + + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2 */ + {.mhz = 933, .refdiv = 3, .fbdiv = 350, .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}, + {.mhz = 600, .refdiv = 1, .fbdiv = 50, .postdiv1 = 2, .postdiv2 = 1}, + {.mhz = 528, .refdiv = 1, .fbdiv = 66, .postdiv1 = 3, .postdiv2 = 1}, + {.mhz = 400, .refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 1}, + {.mhz = 300, .refdiv = 1, .fbdiv = 50, .postdiv1 = 4, .postdiv2 = 1}, + {.mhz = 200, .refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 2}, +}; + +struct rk3399_dram_status { + uint32_t current_index; + uint32_t index_freq[2]; + 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 +}; + +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) +{ + struct rk3399_sdram_channel *ch = &sdram_config->ch[channel]; + uint32_t bandwidth; + uint32_t die_bandwidth; + uint32_t die; + uint32_t cs_cap; + uint32_t row; + + row = cs == 0 ? ch->cs0_row : ch->cs1_row; + bandwidth = 8 * (1 << ch->bw); + die_bandwidth = 8 * (1 << ch->dbw); + die = bandwidth / die_bandwidth; + cs_cap = (1 << (row + ((1 << ch->bk) / 4 + 1) + ch->col + + (bandwidth / 16))); + if (ch->row_3_4) + cs_cap = cs_cap * 3 / 4; + + return (cs_cap / die); +} + +static void drv_odt_lp_cfg_init(uint32_t dram_type, + struct ddr_dts_config_timing *dts_timing, + 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; + } + + 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)); + } + 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)); + } + 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; + }; + + 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; + } + + 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; + } + + 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; + break; + } +} + +static void sdram_timing_cfg_init(struct timing_related_config *ptiming_config, + struct rk3399_sdram_params *sdram_params, + struct drv_odt_lp_config *drv_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].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] = + get_cs_die_capability(sdram_params, i, j); + } + } + ptiming_config->dram_type = sdram_params->dramtype; + ptiming_config->ch_cnt = sdram_params->num_channels; + switch (sdram_params->dramtype) { + case DDR3: + ptiming_config->bl = ddr3_default_config.bl; + ptiming_config->ap = ddr3_default_config.ap; + break; + case LPDDR3: + ptiming_config->bl = lpddr3_default_config.bl; + ptiming_config->ap = lpddr3_default_config.ap; + break; + case LPDDR4: + ptiming_config->bl = lpddr4_default_config.bl; + ptiming_config->ap = lpddr4_default_config.ap; + ptiming_config->rdbi = 0; + ptiming_config->wdbi = 0; + break; + } + 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; +} + +struct lat_adj_pair { + uint32_t cl; + uint32_t rdlat_adj; + uint32_t cwl; + uint32_t wrlat_adj; +}; + +const struct lat_adj_pair ddr3_lat_adj[] = { + {6, 5, 5, 4}, + {8, 7, 6, 5}, + {10, 9, 7, 6}, + {11, 9, 8, 7}, + {13, 0xb, 9, 8}, + {14, 0xb, 0xa, 9} +}; + +const struct lat_adj_pair lpddr3_lat_adj[] = { + {3, 2, 1, 0}, + {6, 5, 3, 2}, + {8, 7, 4, 3}, + {9, 8, 5, 4}, + {10, 9, 6, 5}, + {11, 9, 6, 5}, + {12, 0xa, 6, 5}, + {14, 0xc, 8, 7}, + {16, 0xd, 8, 7} +}; + +const struct lat_adj_pair lpddr4_lat_adj[] = { + {6, 5, 4, 2}, + {10, 9, 6, 4}, + {14, 0xc, 8, 6}, + {20, 0x11, 0xa, 8}, + {24, 0x15, 0xc, 0xa}, + {28, 0x18, 0xe, 0xc}, + {32, 0x1b, 0x10, 0xe}, + {36, 0x1e, 0x12, 0x10} +}; + +static uint32_t get_rdlat_adj(uint32_t dram_type, uint32_t cl) +{ + const struct lat_adj_pair *p; + uint32_t cnt; + uint32_t i; + + if (dram_type == DDR3) { + p = ddr3_lat_adj; + cnt = ARRAY_SIZE(ddr3_lat_adj); + } else if (dram_type == LPDDR3) { + p = lpddr3_lat_adj; + cnt = ARRAY_SIZE(lpddr3_lat_adj); + } else { + p = lpddr4_lat_adj; + cnt = ARRAY_SIZE(lpddr4_lat_adj); + } + + for (i = 0; i < cnt; i++) { + if (cl == p[i].cl) + return p[i].rdlat_adj; + } + /* fail */ + return 0xff; +} + +static uint32_t get_wrlat_adj(uint32_t dram_type, uint32_t cwl) +{ + const struct lat_adj_pair *p; + uint32_t cnt; + uint32_t i; + + if (dram_type == DDR3) { + p = ddr3_lat_adj; + cnt = ARRAY_SIZE(ddr3_lat_adj); + } else if (dram_type == LPDDR3) { + p = lpddr3_lat_adj; + cnt = ARRAY_SIZE(lpddr3_lat_adj); + } else { + p = lpddr4_lat_adj; + cnt = ARRAY_SIZE(lpddr4_lat_adj); + } + + for (i = 0; i < cnt; i++) { + if (cwl == p[i].cwl) + return p[i].wrlat_adj; + } + /* fail */ + return 0xff; +} + +#define PI_REGS_DIMM_SUPPORT (0) +#define PI_ADD_LATENCY (0) +#define PI_DOUBLEFREEK (1) + +#define PI_PAD_DELAY_PS_VALUE (1000) +#define PI_IE_ENABLE_VALUE (3000) +#define PI_TSEL_ENABLE_VALUE (700) + +static uint32_t get_pi_rdlat_adj(struct dram_timing_t *pdram_timing) +{ + /*[DLLSUBTYPE2] == "STD_DENALI_HS" */ + uint32_t rdlat, delay_adder, ie_enable, hs_offset, tsel_adder, + extra_adder, tsel_enable; + + ie_enable = PI_IE_ENABLE_VALUE; + tsel_enable = PI_TSEL_ENABLE_VALUE; + + rdlat = pdram_timing->cl + PI_ADD_LATENCY; + delay_adder = ie_enable / (1000000 / pdram_timing->mhz); + if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) + delay_adder++; + hs_offset = 0; + tsel_adder = 0; + extra_adder = 0; + /* rdlat = rdlat - (PREAMBLE_SUPPORT & 0x1); */ + tsel_adder = tsel_enable / (1000000 / pdram_timing->mhz); + if ((tsel_enable % (1000000 / pdram_timing->mhz)) != 0) + tsel_adder++; + delay_adder = delay_adder - 1; + if (tsel_adder > delay_adder) + extra_adder = tsel_adder - delay_adder; + else + extra_adder = 0; + if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK) + hs_offset = 2; + else + hs_offset = 1; + + if (delay_adder > (rdlat - 1 - hs_offset)) { + rdlat = rdlat - tsel_adder; + } else { + if ((rdlat - delay_adder) < 2) + rdlat = 2; + else + rdlat = rdlat - delay_adder - extra_adder; + } + + return rdlat; +} + +static uint32_t get_pi_wrlat(struct dram_timing_t *pdram_timing, + struct timing_related_config *timing_config) +{ + uint32_t tmp; + + if (timing_config->dram_type == LPDDR3) { + tmp = pdram_timing->cl; + if (tmp >= 14) + tmp = 8; + else if (tmp >= 10) + tmp = 6; + else if (tmp == 9) + tmp = 5; + else if (tmp == 8) + tmp = 4; + else if (tmp == 6) + tmp = 3; + else + tmp = 1; + } else { + tmp = 1; + } + + return tmp; +} + +static uint32_t get_pi_wrlat_adj(struct dram_timing_t *pdram_timing, + struct timing_related_config *timing_config) +{ + return get_pi_wrlat(pdram_timing, timing_config) + PI_ADD_LATENCY - 1; +} + +static uint32_t get_pi_tdfi_phy_rdlat(struct dram_timing_t *pdram_timing, + struct timing_related_config *timing_config) +{ + /* [DLLSUBTYPE2] == "STD_DENALI_HS" */ + uint32_t cas_lat, delay_adder, ie_enable, hs_offset, ie_delay_adder; + uint32_t mem_delay_ps, round_trip_ps; + uint32_t phy_internal_delay, lpddr_adder, dfi_adder, rdlat_delay; + + ie_enable = PI_IE_ENABLE_VALUE; + + delay_adder = ie_enable / (1000000 / pdram_timing->mhz); + if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) + delay_adder++; + delay_adder = delay_adder - 1; + if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK) + hs_offset = 2; + else + hs_offset = 1; + + cas_lat = pdram_timing->cl + PI_ADD_LATENCY; + + if (delay_adder > (cas_lat - 1 - hs_offset)) { + ie_delay_adder = 0; + } else { + ie_delay_adder = ie_enable / (1000000 / pdram_timing->mhz); + if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) + ie_delay_adder++; + } + + if (timing_config->dram_type == DDR3) { + mem_delay_ps = 0; + } else if (timing_config->dram_type == LPDDR4) { + mem_delay_ps = 3600; + } else if (timing_config->dram_type == LPDDR3) { + mem_delay_ps = 5500; + } else { + printf("get_pi_tdfi_phy_rdlat:dramtype unsupport\n"); + return 0; + } + round_trip_ps = 1100 + 500 + mem_delay_ps + 500 + 600; + delay_adder = round_trip_ps / (1000000 / pdram_timing->mhz); + if ((round_trip_ps % (1000000 / pdram_timing->mhz)) != 0) + delay_adder++; + + phy_internal_delay = 5 + 2 + 4; + lpddr_adder = mem_delay_ps / (1000000 / pdram_timing->mhz); + if ((mem_delay_ps % (1000000 / pdram_timing->mhz)) != 0) + lpddr_adder++; + dfi_adder = 0; + phy_internal_delay = phy_internal_delay + 2; + rdlat_delay = delay_adder + phy_internal_delay + + ie_delay_adder + lpddr_adder + dfi_adder; + + rdlat_delay = rdlat_delay + 2; + return rdlat_delay; +} + +static uint32_t get_pi_todtoff_min(struct dram_timing_t *pdram_timing, + struct timing_related_config *timing_config) +{ + uint32_t tmp, todtoff_min_ps; + + if (timing_config->dram_type == LPDDR3) + todtoff_min_ps = 2500; + else if (timing_config->dram_type == LPDDR4) + todtoff_min_ps = 1500; + else + todtoff_min_ps = 0; + /* todtoff_min */ + tmp = todtoff_min_ps / (1000000 / pdram_timing->mhz); + if ((todtoff_min_ps % (1000000 / pdram_timing->mhz)) != 0) + tmp++; + return tmp; +} + +static uint32_t get_pi_todtoff_max(struct dram_timing_t *pdram_timing, + struct timing_related_config *timing_config) +{ + uint32_t tmp, todtoff_max_ps; + + if ((timing_config->dram_type == LPDDR4) + || (timing_config->dram_type == LPDDR3)) + todtoff_max_ps = 3500; + else + todtoff_max_ps = 0; + + /* todtoff_max */ + tmp = todtoff_max_ps / (1000000 / pdram_timing->mhz); + if ((todtoff_max_ps % (1000000 / pdram_timing->mhz)) != 0) + tmp++; + return tmp; +} + +static void gen_rk3399_ctl_params_f0(struct timing_related_config + *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t i; + uint32_t tmp, tmp1; + + for (i = 0; i < timing_config->ch_cnt; i++) { + if (timing_config->dram_type == DDR3) { + tmp = ((700000 + 10) * timing_config->freq + + 999) / 1000; + tmp += pdram_timing->txsnr + (pdram_timing->tmrd * 3) + + pdram_timing->tmod + pdram_timing->tzqinit; + mmio_write_32(CTL_REG(i, 5), tmp); + + mmio_clrsetbits_32(CTL_REG(i, 22), 0xffff, + pdram_timing->tdllk); + + mmio_write_32(CTL_REG(i, 32), + (pdram_timing->tmod << 8) | + pdram_timing->tmrd); + + mmio_clrsetbits_32(CTL_REG(i, 59), 0xffff << 16, + (pdram_timing->txsr - + pdram_timing->trcd) << 16); + } else if (timing_config->dram_type == LPDDR4) { + mmio_write_32(CTL_REG(i, 5), pdram_timing->tinit1 + + pdram_timing->tinit3); + mmio_write_32(CTL_REG(i, 32), + (pdram_timing->tmrd << 8) | + pdram_timing->tmrd); + mmio_clrsetbits_32(CTL_REG(i, 59), 0xffff << 16, + pdram_timing->txsr << 16); + } else { + mmio_write_32(CTL_REG(i, 5), pdram_timing->tinit1); + mmio_write_32(CTL_REG(i, 7), pdram_timing->tinit4); + mmio_write_32(CTL_REG(i, 32), + (pdram_timing->tmrd << 8) | + pdram_timing->tmrd); + mmio_clrsetbits_32(CTL_REG(i, 59), 0xffff << 16, + pdram_timing->txsr << 16); + } + mmio_write_32(CTL_REG(i, 6), pdram_timing->tinit3); + mmio_write_32(CTL_REG(i, 8), pdram_timing->tinit5); + mmio_clrsetbits_32(CTL_REG(i, 23), (0x7f << 16), + ((pdram_timing->cl * 2) << 16)); + mmio_clrsetbits_32(CTL_REG(i, 23), (0x1f << 24), + (pdram_timing->cwl << 24)); + mmio_clrsetbits_32(CTL_REG(i, 24), 0x3f, pdram_timing->al); + mmio_clrsetbits_32(CTL_REG(i, 26), 0xffff << 16, + (pdram_timing->trc << 24) | + (pdram_timing->trrd << 16)); + mmio_write_32(CTL_REG(i, 27), + (pdram_timing->tfaw << 24) | + (pdram_timing->trppb << 16) | + (pdram_timing->twtr << 8) | + pdram_timing->tras_min); + + mmio_clrsetbits_32(CTL_REG(i, 31), 0xff << 24, + max(4, pdram_timing->trtp) << 24); + mmio_write_32(CTL_REG(i, 33), (pdram_timing->tcke << 24) | + pdram_timing->tras_max); + mmio_clrsetbits_32(CTL_REG(i, 34), 0xff, + max(1, pdram_timing->tckesr)); + mmio_clrsetbits_32(CTL_REG(i, 39), + (0x3f << 16) | (0xff << 8), + (pdram_timing->twr << 16) | + (pdram_timing->trcd << 8)); + mmio_clrsetbits_32(CTL_REG(i, 42), 0x1f << 16, + pdram_timing->tmrz << 16); + tmp = pdram_timing->tdal ? pdram_timing->tdal : + (pdram_timing->twr + pdram_timing->trp); + mmio_clrsetbits_32(CTL_REG(i, 44), 0xff, tmp); + mmio_clrsetbits_32(CTL_REG(i, 45), 0xff, pdram_timing->trp); + mmio_write_32(CTL_REG(i, 48), + ((pdram_timing->trefi - 8) << 16) | + pdram_timing->trfc); + mmio_clrsetbits_32(CTL_REG(i, 52), 0xffff, pdram_timing->txp); + mmio_clrsetbits_32(CTL_REG(i, 53), 0xffff << 16, + pdram_timing->txpdll << 16); + mmio_clrsetbits_32(CTL_REG(i, 55), 0xf << 24, + pdram_timing->tcscke << 24); + mmio_clrsetbits_32(CTL_REG(i, 55), 0xff, pdram_timing->tmrri); + mmio_write_32(CTL_REG(i, 56), + (pdram_timing->tzqcke << 24) | + (pdram_timing->tmrwckel << 16) | + (pdram_timing->tckehcs << 8) | + pdram_timing->tckelcs); + mmio_clrsetbits_32(CTL_REG(i, 60), 0xffff, pdram_timing->txsnr); + mmio_clrsetbits_32(CTL_REG(i, 62), 0xffff << 16, + (pdram_timing->tckehcmd << 24) | + (pdram_timing->tckelcmd << 16)); + mmio_write_32(CTL_REG(i, 63), + (pdram_timing->tckelpd << 24) | + (pdram_timing->tescke << 16) | + (pdram_timing->tsr << 8) | + pdram_timing->tckckel); + mmio_clrsetbits_32(CTL_REG(i, 64), 0xfff, + (pdram_timing->tcmdcke << 8) | + pdram_timing->tcsckeh); + mmio_clrsetbits_32(CTL_REG(i, 92), 0xffff << 8, + (pdram_timing->tcksrx << 16) | + (pdram_timing->tcksre << 8)); + mmio_clrsetbits_32(CTL_REG(i, 108), 0x1 << 24, + (timing_config->dllbp << 24)); + mmio_clrsetbits_32(CTL_REG(i, 122), 0x3ff << 16, + (pdram_timing->tvrcg_enable << 16)); + mmio_write_32(CTL_REG(i, 123), (pdram_timing->tfc_long << 16) | + pdram_timing->tvrcg_disable); + mmio_write_32(CTL_REG(i, 124), + (pdram_timing->tvref_long << 16) | + (pdram_timing->tckfspx << 8) | + pdram_timing->tckfspe); + mmio_write_32(CTL_REG(i, 133), (pdram_timing->mr[1] << 16) | + pdram_timing->mr[0]); + mmio_clrsetbits_32(CTL_REG(i, 134), 0xffff, + pdram_timing->mr[2]); + mmio_clrsetbits_32(CTL_REG(i, 138), 0xffff, + pdram_timing->mr[3]); + mmio_clrsetbits_32(CTL_REG(i, 139), 0xff << 24, + pdram_timing->mr11 << 24); + mmio_write_32(CTL_REG(i, 147), + (pdram_timing->mr[1] << 16) | + pdram_timing->mr[0]); + mmio_clrsetbits_32(CTL_REG(i, 148), 0xffff, + pdram_timing->mr[2]); + mmio_clrsetbits_32(CTL_REG(i, 152), 0xffff, + pdram_timing->mr[3]); + mmio_clrsetbits_32(CTL_REG(i, 153), 0xff << 24, + pdram_timing->mr11 << 24); + if (timing_config->dram_type == LPDDR4) { + mmio_clrsetbits_32(CTL_REG(i, 140), 0xffff << 16, + pdram_timing->mr12 << 16); + mmio_clrsetbits_32(CTL_REG(i, 142), 0xffff << 16, + pdram_timing->mr14 << 16); + mmio_clrsetbits_32(CTL_REG(i, 145), 0xffff << 16, + pdram_timing->mr22 << 16); + mmio_clrsetbits_32(CTL_REG(i, 154), 0xffff << 16, + pdram_timing->mr12 << 16); + mmio_clrsetbits_32(CTL_REG(i, 156), 0xffff << 16, + pdram_timing->mr14 << 16); + mmio_clrsetbits_32(CTL_REG(i, 159), 0xffff << 16, + pdram_timing->mr22 << 16); + } + mmio_clrsetbits_32(CTL_REG(i, 179), 0xfff << 8, + pdram_timing->tzqinit << 8); + mmio_write_32(CTL_REG(i, 180), (pdram_timing->tzqcs << 16) | + (pdram_timing->tzqinit / 2)); + mmio_write_32(CTL_REG(i, 181), (pdram_timing->tzqlat << 16) | + pdram_timing->tzqcal); + mmio_clrsetbits_32(CTL_REG(i, 212), 0xff << 8, + pdram_timing->todton << 8); + + if (timing_config->odt) { + mmio_setbits_32(CTL_REG(i, 213), 1 << 16); + if (timing_config->freq < 400) + tmp = 4 << 24; + else + tmp = 8 << 24; + } else { + mmio_clrbits_32(CTL_REG(i, 213), 1 << 16); + tmp = 2 << 24; + } + + mmio_clrsetbits_32(CTL_REG(i, 216), 0x1f << 24, tmp); + mmio_clrsetbits_32(CTL_REG(i, 221), (0x3 << 16) | (0xf << 8), + (pdram_timing->tdqsck << 16) | + (pdram_timing->tdqsck_max << 8)); + tmp = + (get_wrlat_adj(timing_config->dram_type, pdram_timing->cwl) + << 8) | get_rdlat_adj(timing_config->dram_type, + pdram_timing->cl); + mmio_clrsetbits_32(CTL_REG(i, 284), 0xffff, tmp); + mmio_clrsetbits_32(CTL_REG(i, 82), 0xffff << 16, + (4 * pdram_timing->trefi) << 16); + + mmio_clrsetbits_32(CTL_REG(i, 83), 0xffff, + (2 * pdram_timing->trefi) & 0xffff); + + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + tmp = get_pi_wrlat(pdram_timing, timing_config); + tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); + tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; + } else { + tmp = 0; + } + mmio_clrsetbits_32(CTL_REG(i, 214), 0x3f << 16, + (tmp & 0x3f) << 16); + + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + /* min_rl_preamble = cl+TDQSCK_MIN -1 */ + tmp = pdram_timing->cl + + get_pi_todtoff_min(pdram_timing, timing_config) - 1; + /* todtoff_max */ + tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); + tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; + } else { + tmp = pdram_timing->cl - pdram_timing->cwl; + } + mmio_clrsetbits_32(CTL_REG(i, 215), 0x3f << 8, + (tmp & 0x3f) << 8); + + mmio_clrsetbits_32(CTL_REG(i, 275), 0xff << 16, + (get_pi_tdfi_phy_rdlat(pdram_timing, + timing_config) & + 0xff) << 16); + + mmio_clrsetbits_32(CTL_REG(i, 277), 0xffff, + (2 * pdram_timing->trefi) & 0xffff); + + mmio_clrsetbits_32(CTL_REG(i, 282), 0xffff, + (2 * pdram_timing->trefi) & 0xffff); + + mmio_write_32(CTL_REG(i, 283), 20 * pdram_timing->trefi); + + /* CTL_308 TDFI_CALVL_CAPTURE_F0:RW:16:10 */ + tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; + if ((20000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; + mmio_clrsetbits_32(CTL_REG(i, 308), 0x3ff << 16, tmp << 16); + + /* CTL_308 TDFI_CALVL_CC_F0:RW:0:10 */ + tmp = tmp + 18; + mmio_clrsetbits_32(CTL_REG(i, 308), 0x3ff, tmp); + + /* 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 (tmp1 == 0) + tmp = 0; + else if (tmp1 < 5) + tmp = tmp1 - 1; + else + tmp = tmp1 - 5; + } else { + tmp = tmp1 - 2; + } + 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) && + (pdram_timing->cl >= 5)) + tmp = pdram_timing->cl - 5; + else + tmp = pdram_timing->cl - 2; + mmio_clrsetbits_32(CTL_REG(i, 314), 0xff, tmp); + } +} + +static void gen_rk3399_ctl_params_f1(struct timing_related_config + *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t i; + uint32_t tmp, tmp1; + + for (i = 0; i < timing_config->ch_cnt; i++) { + if (timing_config->dram_type == DDR3) { + tmp = + ((700000 + 10) * timing_config->freq + 999) / 1000; + tmp += pdram_timing->txsnr + (pdram_timing->tmrd * 3) + + pdram_timing->tmod + pdram_timing->tzqinit; + mmio_write_32(CTL_REG(i, 9), tmp); + mmio_clrsetbits_32(CTL_REG(i, 22), 0xffff << 16, + pdram_timing->tdllk << 16); + mmio_clrsetbits_32(CTL_REG(i, 34), 0xffffff00, + (pdram_timing->tmod << 24) | + (pdram_timing->tmrd << 16) | + (pdram_timing->trtp << 8)); + mmio_clrsetbits_32(CTL_REG(i, 60), 0xffff << 16, + (pdram_timing->txsr - + pdram_timing->trcd) << 16); + } else if (timing_config->dram_type == LPDDR4) { + mmio_write_32(CTL_REG(i, 9), pdram_timing->tinit1 + + pdram_timing->tinit3); + mmio_clrsetbits_32(CTL_REG(i, 34), 0xffffff00, + (pdram_timing->tmrd << 24) | + (pdram_timing->tmrd << 16) | + (pdram_timing->trtp << 8)); + mmio_clrsetbits_32(CTL_REG(i, 60), 0xffff << 16, + pdram_timing->txsr << 16); + } else { + mmio_write_32(CTL_REG(i, 9), pdram_timing->tinit1); + mmio_write_32(CTL_REG(i, 11), pdram_timing->tinit4); + mmio_clrsetbits_32(CTL_REG(i, 34), 0xffffff00, + (pdram_timing->tmrd << 24) | + (pdram_timing->tmrd << 16) | + (pdram_timing->trtp << 8)); + mmio_clrsetbits_32(CTL_REG(i, 60), 0xffff << 16, + pdram_timing->txsr << 16); + } + mmio_write_32(CTL_REG(i, 10), pdram_timing->tinit3); + mmio_write_32(CTL_REG(i, 12), pdram_timing->tinit5); + mmio_clrsetbits_32(CTL_REG(i, 24), (0x7f << 8), + ((pdram_timing->cl * 2) << 8)); + mmio_clrsetbits_32(CTL_REG(i, 24), (0x1f << 16), + (pdram_timing->cwl << 16)); + mmio_clrsetbits_32(CTL_REG(i, 24), 0x3f << 24, + pdram_timing->al << 24); + mmio_clrsetbits_32(CTL_REG(i, 28), 0xffffff00, + (pdram_timing->tras_min << 24) | + (pdram_timing->trc << 16) | + (pdram_timing->trrd << 8)); + mmio_clrsetbits_32(CTL_REG(i, 29), 0xffffff, + (pdram_timing->tfaw << 16) | + (pdram_timing->trppb << 8) | + pdram_timing->twtr); + mmio_write_32(CTL_REG(i, 35), (pdram_timing->tcke << 24) | + pdram_timing->tras_max); + mmio_clrsetbits_32(CTL_REG(i, 36), 0xff, + max(1, pdram_timing->tckesr)); + mmio_clrsetbits_32(CTL_REG(i, 39), (0xff << 24), + (pdram_timing->trcd << 24)); + mmio_clrsetbits_32(CTL_REG(i, 40), 0x3f, pdram_timing->twr); + mmio_clrsetbits_32(CTL_REG(i, 42), 0x1f << 24, + pdram_timing->tmrz << 24); + tmp = pdram_timing->tdal ? pdram_timing->tdal : + (pdram_timing->twr + pdram_timing->trp); + mmio_clrsetbits_32(CTL_REG(i, 44), 0xff << 8, tmp << 8); + mmio_clrsetbits_32(CTL_REG(i, 45), 0xff << 8, + pdram_timing->trp << 8); + mmio_write_32(CTL_REG(i, 49), + ((pdram_timing->trefi - 8) << 16) | + pdram_timing->trfc); + mmio_clrsetbits_32(CTL_REG(i, 52), 0xffff << 16, + pdram_timing->txp << 16); + mmio_clrsetbits_32(CTL_REG(i, 54), 0xffff, + pdram_timing->txpdll); + mmio_clrsetbits_32(CTL_REG(i, 55), 0xff << 8, + pdram_timing->tmrri << 8); + mmio_write_32(CTL_REG(i, 57), (pdram_timing->tmrwckel << 24) | + (pdram_timing->tckehcs << 16) | + (pdram_timing->tckelcs << 8) | + pdram_timing->tcscke); + mmio_clrsetbits_32(CTL_REG(i, 58), 0xf, pdram_timing->tzqcke); + mmio_clrsetbits_32(CTL_REG(i, 61), 0xffff, pdram_timing->txsnr); + mmio_clrsetbits_32(CTL_REG(i, 64), 0xffff << 16, + (pdram_timing->tckehcmd << 24) | + (pdram_timing->tckelcmd << 16)); + mmio_write_32(CTL_REG(i, 65), (pdram_timing->tckelpd << 24) | + (pdram_timing->tescke << 16) | + (pdram_timing->tsr << 8) | + pdram_timing->tckckel); + mmio_clrsetbits_32(CTL_REG(i, 66), 0xfff, + (pdram_timing->tcmdcke << 8) | + pdram_timing->tcsckeh); + mmio_clrsetbits_32(CTL_REG(i, 92), (0xff << 24), + (pdram_timing->tcksre << 24)); + mmio_clrsetbits_32(CTL_REG(i, 93), 0xff, + pdram_timing->tcksrx); + mmio_clrsetbits_32(CTL_REG(i, 108), (0x1 << 25), + (timing_config->dllbp << 25)); + mmio_write_32(CTL_REG(i, 125), + (pdram_timing->tvrcg_disable << 16) | + pdram_timing->tvrcg_enable); + mmio_write_32(CTL_REG(i, 126), (pdram_timing->tckfspx << 24) | + (pdram_timing->tckfspe << 16) | + pdram_timing->tfc_long); + mmio_clrsetbits_32(CTL_REG(i, 127), 0xffff, + pdram_timing->tvref_long); + mmio_clrsetbits_32(CTL_REG(i, 134), 0xffff << 16, + pdram_timing->mr[0] << 16); + mmio_write_32(CTL_REG(i, 135), (pdram_timing->mr[2] << 16) | + pdram_timing->mr[1]); + mmio_clrsetbits_32(CTL_REG(i, 138), 0xffff << 16, + pdram_timing->mr[3] << 16); + mmio_clrsetbits_32(CTL_REG(i, 140), 0xff, pdram_timing->mr11); + mmio_clrsetbits_32(CTL_REG(i, 148), 0xffff << 16, + pdram_timing->mr[0] << 16); + mmio_write_32(CTL_REG(i, 149), (pdram_timing->mr[2] << 16) | + pdram_timing->mr[1]); + mmio_clrsetbits_32(CTL_REG(i, 152), 0xffff << 16, + pdram_timing->mr[3] << 16); + mmio_clrsetbits_32(CTL_REG(i, 154), 0xff, pdram_timing->mr11); + if (timing_config->dram_type == LPDDR4) { + mmio_clrsetbits_32(CTL_REG(i, 141), 0xffff, + pdram_timing->mr12); + mmio_clrsetbits_32(CTL_REG(i, 143), 0xffff, + pdram_timing->mr14); + mmio_clrsetbits_32(CTL_REG(i, 146), 0xffff, + pdram_timing->mr22); + mmio_clrsetbits_32(CTL_REG(i, 155), 0xffff, + pdram_timing->mr12); + mmio_clrsetbits_32(CTL_REG(i, 157), 0xffff, + pdram_timing->mr14); + mmio_clrsetbits_32(CTL_REG(i, 160), 0xffff, + pdram_timing->mr22); + } + mmio_write_32(CTL_REG(i, 182), + ((pdram_timing->tzqinit / 2) << 16) | + pdram_timing->tzqinit); + mmio_write_32(CTL_REG(i, 183), (pdram_timing->tzqcal << 16) | + pdram_timing->tzqcs); + mmio_clrsetbits_32(CTL_REG(i, 184), 0x3f, pdram_timing->tzqlat); + mmio_clrsetbits_32(CTL_REG(i, 188), 0xfff, + pdram_timing->tzqreset); + mmio_clrsetbits_32(CTL_REG(i, 212), 0xff << 16, + pdram_timing->todton << 16); + + if (timing_config->odt) { + mmio_setbits_32(CTL_REG(i, 213), (1 << 24)); + if (timing_config->freq < 400) + tmp = 4 << 24; + else + tmp = 8 << 24; + } else { + mmio_clrbits_32(CTL_REG(i, 213), (1 << 24)); + tmp = 2 << 24; + } + mmio_clrsetbits_32(CTL_REG(i, 217), 0x1f << 24, tmp); + mmio_clrsetbits_32(CTL_REG(i, 221), 0xf << 24, + (pdram_timing->tdqsck_max << 24)); + mmio_clrsetbits_32(CTL_REG(i, 222), 0x3, pdram_timing->tdqsck); + mmio_clrsetbits_32(CTL_REG(i, 291), 0xffff, + (get_wrlat_adj(timing_config->dram_type, + pdram_timing->cwl) << 8) | + get_rdlat_adj(timing_config->dram_type, + pdram_timing->cl)); + + mmio_clrsetbits_32(CTL_REG(i, 84), 0xffff, + (4 * pdram_timing->trefi) & 0xffff); + + mmio_clrsetbits_32(CTL_REG(i, 84), 0xffff << 16, + ((2 * pdram_timing->trefi) & 0xffff) << 16); + + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + tmp = get_pi_wrlat(pdram_timing, timing_config); + tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); + tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; + } else { + tmp = 0; + } + mmio_clrsetbits_32(CTL_REG(i, 214), 0x3f << 24, + (tmp & 0x3f) << 24); + + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + /* min_rl_preamble = cl + TDQSCK_MIN - 1 */ + tmp = pdram_timing->cl + + get_pi_todtoff_min(pdram_timing, timing_config); + tmp--; + /* todtoff_max */ + tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); + tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; + } else { + tmp = pdram_timing->cl - pdram_timing->cwl; + } + mmio_clrsetbits_32(CTL_REG(i, 215), 0x3f << 16, + (tmp & 0x3f) << 16); + + mmio_clrsetbits_32(CTL_REG(i, 275), 0xff << 24, + (get_pi_tdfi_phy_rdlat(pdram_timing, + timing_config) & + 0xff) << 24); + + mmio_clrsetbits_32(CTL_REG(i, 284), 0xffff << 16, + ((2 * pdram_timing->trefi) & 0xffff) << 16); + + mmio_clrsetbits_32(CTL_REG(i, 289), 0xffff, + (2 * pdram_timing->trefi) & 0xffff); + + mmio_write_32(CTL_REG(i, 290), 20 * pdram_timing->trefi); + + /* CTL_309 TDFI_CALVL_CAPTURE_F1:RW:16:10 */ + tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; + if ((20000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; + mmio_clrsetbits_32(CTL_REG(i, 309), 0x3ff << 16, tmp << 16); + + /* CTL_309 TDFI_CALVL_CC_F1:RW:0:10 */ + tmp = tmp + 18; + mmio_clrsetbits_32(CTL_REG(i, 309), 0x3ff, tmp); + + /* 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 (tmp1 == 0) + tmp = 0; + else if (tmp1 < 5) + tmp = tmp1 - 1; + else + tmp = tmp1 - 5; + } else { + tmp = tmp1 - 2; + } + + 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) && + (pdram_timing->cl >= 5)) + tmp = pdram_timing->cl - 5; + else + tmp = pdram_timing->cl - 2; + mmio_clrsetbits_32(CTL_REG(i, 314), 0xff << 16, tmp << 16); + } +} + +static void gen_rk3399_ctl_params(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing, + uint32_t fn) +{ + if (fn == 0) + 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, + struct dram_timing_t *pdram_timing) +{ + uint32_t tmp, tmp1, tmp2; + uint32_t i; + + for (i = 0; i < timing_config->ch_cnt; i++) { + /* PI_02 PI_TDFI_PHYMSTR_MAX_F0:RW:0:32 */ + tmp = 4 * pdram_timing->trefi; + mmio_write_32(PI_REG(i, 2), tmp); + /* PI_03 PI_TDFI_PHYMSTR_RESP_F0:RW:0:16 */ + tmp = 2 * pdram_timing->trefi; + mmio_clrsetbits_32(PI_REG(i, 3), 0xffff, tmp); + /* PI_07 PI_TDFI_PHYUPD_RESP_F0:RW:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 7), 0xffff << 16, tmp << 16); + + /* PI_42 PI_TDELAY_RDWR_2_BUS_IDLE_F0:RW:0:8 */ + if (timing_config->dram_type == LPDDR4) + tmp = 2; + else + tmp = 0; + tmp = (pdram_timing->bl / 2) + 4 + + (get_pi_rdlat_adj(pdram_timing) - 2) + tmp + + get_pi_tdfi_phy_rdlat(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 42), 0xff, tmp); + /* PI_43 PI_WRLAT_F0:RW:0:5 */ + if (timing_config->dram_type == LPDDR3) { + tmp = get_pi_wrlat(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 43), 0x1f, tmp); + } + /* PI_43 PI_ADDITIVE_LAT_F0:RW:8:6 */ + mmio_clrsetbits_32(PI_REG(i, 43), 0x3f << 8, + PI_ADD_LATENCY << 8); + + /* PI_43 PI_CASLAT_LIN_F0:RW:16:7 */ + mmio_clrsetbits_32(PI_REG(i, 43), 0x7f << 16, + (pdram_timing->cl * 2) << 16); + /* PI_46 PI_TREF_F0:RW:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 46), 0xffff << 16, + pdram_timing->trefi << 16); + /* PI_46 PI_TRFC_F0:RW:0:10 */ + mmio_clrsetbits_32(PI_REG(i, 46), 0x3ff, pdram_timing->trfc); + /* PI_66 PI_TODTL_2CMD_F0:RW:24:8 */ + if (timing_config->dram_type == LPDDR3) { + tmp = get_pi_todtoff_max(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 66), 0xff << 24, + tmp << 24); + } + /* PI_72 PI_WR_TO_ODTH_F0:RW:16:6 */ + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + tmp1 = get_pi_wrlat(pdram_timing, timing_config); + tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); + if (tmp1 > tmp2) + tmp = tmp1 - tmp2; + else + tmp = 0; + } else if (timing_config->dram_type == DDR3) { + tmp = 0; + } + mmio_clrsetbits_32(PI_REG(i, 72), 0x3f << 16, tmp << 16); + /* PI_73 PI_RD_TO_ODTH_F0:RW:8:6 */ + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + /* min_rl_preamble = cl + TDQSCK_MIN - 1 */ + tmp1 = pdram_timing->cl; + tmp1 += get_pi_todtoff_min(pdram_timing, timing_config); + tmp1--; + /* todtoff_max */ + tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); + if (tmp1 > tmp2) + tmp = tmp1 - tmp2; + else + tmp = 0; + } else if (timing_config->dram_type == DDR3) { + tmp = pdram_timing->cl - pdram_timing->cwl; + } + mmio_clrsetbits_32(PI_REG(i, 73), 0x3f << 8, tmp << 8); + /* PI_89 PI_RDLAT_ADJ_F0:RW:16:8 */ + tmp = get_pi_rdlat_adj(pdram_timing); + mmio_clrsetbits_32(PI_REG(i, 89), 0xff << 16, tmp << 16); + /* PI_90 PI_WRLAT_ADJ_F0:RW:16:8 */ + tmp = get_pi_wrlat_adj(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 90), 0xff << 16, tmp << 16); + /* PI_91 PI_TDFI_WRCSLAT_F0:RW:16:8 */ + tmp1 = tmp; + if (tmp1 == 0) + tmp = 0; + else if (tmp1 < 5) + tmp = tmp1 - 1; + else + tmp = tmp1 - 5; + mmio_clrsetbits_32(PI_REG(i, 91), 0xff << 16, tmp << 16); + /* PI_95 PI_TDFI_CALVL_CAPTURE_F0:RW:16:10 */ + tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; + if ((20000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; + mmio_clrsetbits_32(PI_REG(i, 95), 0x3ff << 16, tmp << 16); + /* PI_95 PI_TDFI_CALVL_CC_F0:RW:0:10 */ + mmio_clrsetbits_32(PI_REG(i, 95), 0x3ff, tmp + 18); + /* PI_102 PI_TMRZ_F0:RW:8:5 */ + mmio_clrsetbits_32(PI_REG(i, 102), 0x1f << 8, + pdram_timing->tmrz << 8); + /* PI_111 PI_TDFI_CALVL_STROBE_F0:RW:8:4 */ + tmp1 = 2 * 1000 / (1000000 / pdram_timing->mhz); + if ((2 * 1000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + /* pi_tdfi_calvl_strobe=tds_train+5 */ + tmp = tmp1 + 5; + mmio_clrsetbits_32(PI_REG(i, 111), 0xf << 8, tmp << 8); + /* PI_116 PI_TCKEHDQS_F0:RW:16:6 */ + tmp = 10000 / (1000000 / pdram_timing->mhz); + if ((10000 % (1000000 / pdram_timing->mhz)) != 0) + tmp++; + if (pdram_timing->mhz <= 100) + tmp = tmp + 1; + else + tmp = tmp + 8; + mmio_clrsetbits_32(PI_REG(i, 116), 0x3f << 16, tmp << 16); + /* PI_125 PI_MR1_DATA_F0_0:RW+:8:16 */ + mmio_clrsetbits_32(PI_REG(i, 125), 0xffff << 8, + pdram_timing->mr[1] << 8); + /* PI_133 PI_MR1_DATA_F0_1:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 133), 0xffff, pdram_timing->mr[1]); + /* PI_140 PI_MR1_DATA_F0_2:RW+:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 140), 0xffff << 16, + pdram_timing->mr[1] << 16); + /* PI_148 PI_MR1_DATA_F0_3:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 148), 0xffff, pdram_timing->mr[1]); + /* PI_126 PI_MR2_DATA_F0_0:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 126), 0xffff, pdram_timing->mr[2]); + /* PI_133 PI_MR2_DATA_F0_1:RW+:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 133), 0xffff << 16, + pdram_timing->mr[2] << 16); + /* PI_141 PI_MR2_DATA_F0_2:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 141), 0xffff, pdram_timing->mr[2]); + /* PI_148 PI_MR2_DATA_F0_3:RW+:16:16 */ + 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); + /* PI_158 PI_TWR_F0:RW:24:6 */ + mmio_clrsetbits_32(PI_REG(i, 158), 0x3f << 24, + pdram_timing->twr << 24); + /* PI_158 PI_TWTR_F0:RW:16:6 */ + mmio_clrsetbits_32(PI_REG(i, 158), 0x3f << 16, + pdram_timing->twtr << 16); + /* PI_158 PI_TRCD_F0:RW:8:8 */ + mmio_clrsetbits_32(PI_REG(i, 158), 0xff << 8, + pdram_timing->trcd << 8); + /* PI_158 PI_TRP_F0:RW:0:8 */ + mmio_clrsetbits_32(PI_REG(i, 158), 0xff, pdram_timing->trp); + /* PI_157 PI_TRTP_F0:RW:24:8 */ + mmio_clrsetbits_32(PI_REG(i, 157), 0xff << 24, + pdram_timing->trtp << 24); + /* PI_159 PI_TRAS_MIN_F0:RW:24:8 */ + mmio_clrsetbits_32(PI_REG(i, 159), 0xff << 24, + pdram_timing->tras_min << 24); + /* PI_159 PI_TRAS_MAX_F0:RW:0:17 */ + tmp = pdram_timing->tras_max * 99 / 100; + mmio_clrsetbits_32(PI_REG(i, 159), 0x1ffff, tmp); + /* PI_160 PI_TMRD_F0:RW:16:6 */ + mmio_clrsetbits_32(PI_REG(i, 160), 0x3f << 16, + pdram_timing->tmrd << 16); + /*PI_160 PI_TDQSCK_MAX_F0:RW:0:4 */ + mmio_clrsetbits_32(PI_REG(i, 160), 0xf, + pdram_timing->tdqsck_max); + /* PI_187 PI_TDFI_CTRLUPD_MAX_F0:RW:8:16 */ + mmio_clrsetbits_32(PI_REG(i, 187), 0xffff << 8, + (2 * pdram_timing->trefi) << 8); + /* PI_188 PI_TDFI_CTRLUPD_INTERVAL_F0:RW:0:32 */ + mmio_clrsetbits_32(PI_REG(i, 188), 0xffffffff, + 20 * pdram_timing->trefi); + } +} + +static void gen_rk3399_pi_params_f1(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t tmp, tmp1, tmp2; + uint32_t i; + + for (i = 0; i < timing_config->ch_cnt; i++) { + /* PI_04 PI_TDFI_PHYMSTR_MAX_F1:RW:0:32 */ + tmp = 4 * pdram_timing->trefi; + mmio_write_32(PI_REG(i, 4), tmp); + /* PI_05 PI_TDFI_PHYMSTR_RESP_F1:RW:0:16 */ + tmp = 2 * pdram_timing->trefi; + mmio_clrsetbits_32(PI_REG(i, 5), 0xffff, tmp); + /* PI_12 PI_TDFI_PHYUPD_RESP_F1:RW:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 12), 0xffff, tmp); + + /* PI_42 PI_TDELAY_RDWR_2_BUS_IDLE_F1:RW:8:8 */ + if (timing_config->dram_type == LPDDR4) + tmp = 2; + else + tmp = 0; + tmp = (pdram_timing->bl / 2) + 4 + + (get_pi_rdlat_adj(pdram_timing) - 2) + tmp + + get_pi_tdfi_phy_rdlat(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 42), 0xff << 8, tmp << 8); + /* PI_43 PI_WRLAT_F1:RW:24:5 */ + if (timing_config->dram_type == LPDDR3) { + tmp = get_pi_wrlat(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 43), 0x1f << 24, + tmp << 24); + } + /* PI_44 PI_ADDITIVE_LAT_F1:RW:0:6 */ + 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); + /* PI_47 PI_TREF_F1:RW:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 47), 0xffff << 16, + pdram_timing->trefi << 16); + /* PI_47 PI_TRFC_F1:RW:0:10 */ + mmio_clrsetbits_32(PI_REG(i, 47), 0x3ff, pdram_timing->trfc); + /* PI_67 PI_TODTL_2CMD_F1:RW:8:8 */ + if (timing_config->dram_type == LPDDR3) { + tmp = get_pi_todtoff_max(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 67), 0xff << 8, tmp << 8); + } + /* PI_72 PI_WR_TO_ODTH_F1:RW:24:6 */ + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + tmp1 = get_pi_wrlat(pdram_timing, timing_config); + tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); + if (tmp1 > tmp2) + tmp = tmp1 - tmp2; + else + tmp = 0; + } else if (timing_config->dram_type == DDR3) { + tmp = 0; + } + mmio_clrsetbits_32(PI_REG(i, 72), 0x3f << 24, tmp << 24); + /* PI_73 PI_RD_TO_ODTH_F1:RW:16:6 */ + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + /* min_rl_preamble = cl + TDQSCK_MIN - 1 */ + tmp1 = pdram_timing->cl + + get_pi_todtoff_min(pdram_timing, timing_config); + tmp1--; + /* todtoff_max */ + tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); + if (tmp1 > tmp2) + tmp = tmp1 - tmp2; + else + tmp = 0; + } else if (timing_config->dram_type == DDR3) + tmp = pdram_timing->cl - pdram_timing->cwl; + + mmio_clrsetbits_32(PI_REG(i, 73), 0x3f << 16, tmp << 16); + /*P I_89 PI_RDLAT_ADJ_F1:RW:24:8 */ + tmp = get_pi_rdlat_adj(pdram_timing); + mmio_clrsetbits_32(PI_REG(i, 89), 0xff << 24, tmp << 24); + /* PI_90 PI_WRLAT_ADJ_F1:RW:24:8 */ + tmp = get_pi_wrlat_adj(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 90), 0xff << 24, tmp << 24); + /* PI_91 PI_TDFI_WRCSLAT_F1:RW:24:8 */ + tmp1 = tmp; + if (tmp1 == 0) + tmp = 0; + else if (tmp1 < 5) + tmp = tmp1 - 1; + else + tmp = tmp1 - 5; + mmio_clrsetbits_32(PI_REG(i, 91), 0xff << 24, tmp << 24); + /*PI_96 PI_TDFI_CALVL_CAPTURE_F1:RW:16:10 */ + /* tadr=20ns */ + tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; + if ((20000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; + mmio_clrsetbits_32(PI_REG(i, 96), 0x3ff << 16, tmp << 16); + /* PI_96 PI_TDFI_CALVL_CC_F1:RW:0:10 */ + tmp = tmp + 18; + mmio_clrsetbits_32(PI_REG(i, 96), 0x3ff, tmp); + /*PI_103 PI_TMRZ_F1:RW:0:5 */ + mmio_clrsetbits_32(PI_REG(i, 103), 0x1f, pdram_timing->tmrz); + /*PI_111 PI_TDFI_CALVL_STROBE_F1:RW:16:4 */ + /* tds_train=ceil(2/ns) */ + tmp1 = 2 * 1000 / (1000000 / pdram_timing->mhz); + if ((2 * 1000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + /* pi_tdfi_calvl_strobe=tds_train+5 */ + tmp = tmp1 + 5; + mmio_clrsetbits_32(PI_REG(i, 111), 0xf << 16, + tmp << 16); + /* PI_116 PI_TCKEHDQS_F1:RW:24:6 */ + tmp = 10000 / (1000000 / pdram_timing->mhz); + if ((10000 % (1000000 / pdram_timing->mhz)) != 0) + tmp++; + if (pdram_timing->mhz <= 100) + tmp = tmp + 1; + else + tmp = tmp + 8; + mmio_clrsetbits_32(PI_REG(i, 116), 0x3f << 24, + tmp << 24); + /* PI_128 PI_MR1_DATA_F1_0:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 128), 0xffff, pdram_timing->mr[1]); + /* PI_135 PI_MR1_DATA_F1_1:RW+:8:16 */ + mmio_clrsetbits_32(PI_REG(i, 135), 0xffff << 8, + pdram_timing->mr[1] << 8); + /* PI_143 PI_MR1_DATA_F1_2:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 143), 0xffff, pdram_timing->mr[1]); + /* PI_150 PI_MR1_DATA_F1_3:RW+:8:16 */ + mmio_clrsetbits_32(PI_REG(i, 150), 0xffff << 8, + pdram_timing->mr[1] << 8); + /* PI_128 PI_MR2_DATA_F1_0:RW+:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 128), 0xffff << 16, + pdram_timing->mr[2] << 16); + /* PI_136 PI_MR2_DATA_F1_1:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 136), 0xffff, pdram_timing->mr[2]); + /* PI_143 PI_MR2_DATA_F1_2:RW+:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 143), 0xffff << 16, + pdram_timing->mr[2] << 16); + /* PI_151 PI_MR2_DATA_F1_3:RW+:0:16 */ + 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); + /* PI_162 PI_TWR_F1:RW:8:6 */ + mmio_clrsetbits_32(PI_REG(i, 162), 0x3f << 8, + pdram_timing->twr << 8); + /* PI_162 PI_TWTR_F1:RW:0:6 */ + mmio_clrsetbits_32(PI_REG(i, 162), 0x3f, pdram_timing->twtr); + /* PI_161 PI_TRCD_F1:RW:24:8 */ + mmio_clrsetbits_32(PI_REG(i, 161), 0xff << 24, + pdram_timing->trcd << 24); + /* PI_161 PI_TRP_F1:RW:16:8 */ + mmio_clrsetbits_32(PI_REG(i, 161), 0xff << 16, + pdram_timing->trp << 16); + /* PI_161 PI_TRTP_F1:RW:8:8 */ + mmio_clrsetbits_32(PI_REG(i, 161), 0xff << 8, + pdram_timing->trtp << 8); + /* PI_163 PI_TRAS_MIN_F1:RW:24:8 */ + mmio_clrsetbits_32(PI_REG(i, 163), 0xff << 24, + pdram_timing->tras_min << 24); + /* PI_163 PI_TRAS_MAX_F1:RW:0:17 */ + mmio_clrsetbits_32(PI_REG(i, 163), 0x1ffff, + pdram_timing->tras_max * 99 / 100); + /* PI_164 PI_TMRD_F1:RW:16:6 */ + mmio_clrsetbits_32(PI_REG(i, 164), 0x3f << 16, + pdram_timing->tmrd << 16); + /* PI_164 PI_TDQSCK_MAX_F1:RW:0:4 */ + mmio_clrsetbits_32(PI_REG(i, 164), 0xf, + pdram_timing->tdqsck_max); + /* PI_189 PI_TDFI_CTRLUPD_MAX_F1:RW:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 189), 0xffff, + 2 * pdram_timing->trefi); + /* PI_190 PI_TDFI_CTRLUPD_INTERVAL_F1:RW:0:32 */ + mmio_clrsetbits_32(PI_REG(i, 190), 0xffffffff, + 20 * pdram_timing->trefi); + } +} + +static void gen_rk3399_pi_params(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing, + uint32_t fn) +{ + if (fn == 0) + 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) +{ + uint32_t drv_odt_val; + uint32_t i; + + for (i = 0; i < rk3399_dram_status.timing_config.ch_cnt; i++) { + drv_odt_val = (odt_en | (0 << 1) | (0 << 2)) << 16; + mmio_clrsetbits_32(PHY_REG(i, 5), 0x7 << 16, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 133), 0x7 << 16, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 261), 0x7 << 16, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 389), 0x7 << 16, drv_odt_val); + drv_odt_val = (odt_en | (0 << 1) | (0 << 2)) << 24; + mmio_clrsetbits_32(PHY_REG(i, 6), 0x7 << 24, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 134), 0x7 << 24, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 262), 0x7 << 24, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 390), 0x7 << 24, drv_odt_val); + } +} + +static void gen_rk3399_set_ds_odt(struct timing_related_config *timing_config, + struct drv_odt_lp_config *drv_config) +{ + uint32_t i, drv_odt_val; + + 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); + } +} + +static void gen_rk3399_phy_params(struct timing_related_config *timing_config, + struct drv_odt_lp_config *drv_config, + struct dram_timing_t *pdram_timing, + uint32_t fn) +{ + uint32_t tmp, i, div, j; + uint32_t mem_delay_ps, pad_delay_ps, total_delay_ps, delay_frac_ps; + uint32_t trpre_min_ps, gate_delay_ps, gate_delay_frac_ps; + uint32_t ie_enable, tsel_enable, cas_lat, rddata_en_ie_dly, tsel_adder; + uint32_t extra_adder, delta, hs_offset; + + for (i = 0; i < timing_config->ch_cnt; i++) { + + pad_delay_ps = PI_PAD_DELAY_PS_VALUE; + ie_enable = PI_IE_ENABLE_VALUE; + tsel_enable = PI_TSEL_ENABLE_VALUE; + + mmio_clrsetbits_32(PHY_REG(i, 896), (0x3 << 8) | 1, fn << 8); + + /* PHY_LOW_FREQ_SEL */ + /* DENALI_PHY_913 1bit offset_0 */ + if (timing_config->freq > 400) + mmio_clrbits_32(PHY_REG(i, 913), 1); + else + mmio_setbits_32(PHY_REG(i, 913), 1); + + /* PHY_RPTR_UPDATE_x */ + /* DENALI_PHY_87/215/343/471 4bit offset_16 */ + tmp = 2500 / (1000000 / pdram_timing->mhz) + 3; + if ((2500 % (1000000 / pdram_timing->mhz)) != 0) + tmp++; + mmio_clrsetbits_32(PHY_REG(i, 87), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 215), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 343), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 471), 0xf << 16, tmp << 16); + + /* PHY_PLL_CTRL */ + /* 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); + mmio_clrsetbits_32(PHY_REG(i, 911), 0x1fff, tmp); + mmio_clrsetbits_32(PHY_REG(i, 919), 0x1fff, tmp); + + /* PHY_PLL_CTRL_CA */ + /* 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); + mmio_clrsetbits_32(PHY_REG(i, 911), 0x1fff << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 919), 0x1fff << 16, tmp << 16); + + /* PHY_TCKSRE_WAIT */ + /* DENALI_PHY_922 4bits offset_24 */ + if (pdram_timing->mhz <= 400) + tmp = 1; + else if (pdram_timing->mhz <= 800) + tmp = 3; + else if (pdram_timing->mhz <= 1000) + tmp = 4; + else + tmp = 5; + mmio_clrsetbits_32(PHY_REG(i, 922), 0xf << 24, tmp << 24); + /* PHY_CAL_CLK_SELECT_0:RW8:3 */ + div = pdram_timing->mhz / (2 * 20); + for (j = 2, tmp = 1; j <= 128; j <<= 1, tmp++) { + if (div < j) + 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; + trpre_min_ps = 1000; + } else if (timing_config->dram_type == LPDDR4) { + mem_delay_ps = 1500; + trpre_min_ps = 900; + } else if (timing_config->dram_type == LPDDR3) { + mem_delay_ps = 2500; + trpre_min_ps = 900; + } else { + ERROR("gen_rk3399_phy_params:dramtype unsupport\n"); + return; + } + total_delay_ps = mem_delay_ps + pad_delay_ps; + delay_frac_ps = 1000 * total_delay_ps / + (1000000 / pdram_timing->mhz); + 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); + mmio_clrsetbits_32(PHY_REG(i, 205), 0x2ff << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 333), 0x2ff << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 461), 0x2ff << 16, tmp << 16); + + tmp = gate_delay_ps / 1000; + /* PHY_LP4_BOOT_RDDQS_LATENCY_ADJUST */ + /* DENALI_PHY_10/138/266/394 4bit offset_0 */ + mmio_clrsetbits_32(PHY_REG(i, 10), 0xf, tmp); + 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; + mmio_clrsetbits_32(PHY_REG(i, 80), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 208), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 336), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 464), 0xf << 16, tmp << 16); + + cas_lat = pdram_timing->cl + PI_ADD_LATENCY; + rddata_en_ie_dly = ie_enable / (1000000 / pdram_timing->mhz); + if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) + rddata_en_ie_dly++; + rddata_en_ie_dly = rddata_en_ie_dly - 1; + tsel_adder = tsel_enable / (1000000 / pdram_timing->mhz); + if ((tsel_enable % (1000000 / pdram_timing->mhz)) != 0) + tsel_adder++; + if (rddata_en_ie_dly > tsel_adder) + extra_adder = rddata_en_ie_dly - tsel_adder; + else + extra_adder = 0; + delta = cas_lat - rddata_en_ie_dly; + if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK) + hs_offset = 2; + else + hs_offset = 1; + if (rddata_en_ie_dly > (cas_lat - 1 - hs_offset)) + tmp = 0; + else if ((delta == 2) || (delta == 1)) + tmp = rddata_en_ie_dly - 0 - extra_adder; + else + tmp = extra_adder; + /* PHY_LP4_BOOT_RDDATA_EN_TSEL_DLY */ + /* DENALI_PHY_9/137/265/393 4bit offset_16 */ + mmio_clrsetbits_32(PHY_REG(i, 9), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 137), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 265), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 393), 0xf << 16, tmp << 16); + /* PHY_RDDATA_EN_TSEL_DLY */ + /* DENALI_PHY_86/214/342/470 4bit offset_0 */ + mmio_clrsetbits_32(PHY_REG(i, 86), 0xf, tmp); + mmio_clrsetbits_32(PHY_REG(i, 214), 0xf, tmp); + mmio_clrsetbits_32(PHY_REG(i, 342), 0xf, tmp); + mmio_clrsetbits_32(PHY_REG(i, 470), 0xf, tmp); + + if (tsel_adder > rddata_en_ie_dly) + extra_adder = tsel_adder - rddata_en_ie_dly; + else + extra_adder = 0; + if (rddata_en_ie_dly > (cas_lat - 1 - hs_offset)) + tmp = tsel_adder; + else + tmp = rddata_en_ie_dly - 0 + extra_adder; + /* PHY_LP4_BOOT_RDDATA_EN_DLY */ + /* DENALI_PHY_9/137/265/393 4bit offset_8 */ + mmio_clrsetbits_32(PHY_REG(i, 9), 0xf << 8, tmp << 8); + mmio_clrsetbits_32(PHY_REG(i, 137), 0xf << 8, tmp << 8); + mmio_clrsetbits_32(PHY_REG(i, 265), 0xf << 8, tmp << 8); + mmio_clrsetbits_32(PHY_REG(i, 393), 0xf << 8, tmp << 8); + /* PHY_RDDATA_EN_DLY */ + /* DENALI_PHY_85/213/341/469 4bit offset_24 */ + mmio_clrsetbits_32(PHY_REG(i, 85), 0xf << 24, tmp << 24); + mmio_clrsetbits_32(PHY_REG(i, 213), 0xf << 24, tmp << 24); + mmio_clrsetbits_32(PHY_REG(i, 341), 0xf << 24, tmp << 24); + mmio_clrsetbits_32(PHY_REG(i, 469), 0xf << 24, tmp << 24); + + if (pdram_timing->mhz <= ENPER_CS_TRAINING_FREQ) { + /* + * Note:Per-CS Training is not compatible at speeds + * under 533 MHz. If the PHY is running at a speed + * less than 533MHz, all phy_per_cs_training_en_X + * parameters must be cleared to 0. + */ + + /*DENALI_PHY_84/212/340/468 1bit offset_16 */ + mmio_clrbits_32(PHY_REG(i, 84), 0x1 << 16); + mmio_clrbits_32(PHY_REG(i, 212), 0x1 << 16); + mmio_clrbits_32(PHY_REG(i, 340), 0x1 << 16); + mmio_clrbits_32(PHY_REG(i, 468), 0x1 << 16); + } else { + mmio_setbits_32(PHY_REG(i, 84), 0x1 << 16); + mmio_setbits_32(PHY_REG(i, 212), 0x1 << 16); + mmio_setbits_32(PHY_REG(i, 340), 0x1 << 16); + mmio_setbits_32(PHY_REG(i, 468), 0x1 << 16); + } + } +} + +static int to_get_clk_index(unsigned int mhz) +{ + int pll_cnt, i; + + pll_cnt = ARRAY_SIZE(dpll_rates_table); + + /* Assumming rate_table is in descending order */ + for (i = 0; i < pll_cnt; i++) { + if (mhz >= dpll_rates_table[i].mhz) + break; + } + + /* if mhz lower than lowest frequency in table, use lowest frequency */ + if (i == pll_cnt) + i = pll_cnt - 1; + + 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; + + refdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) & 0x3f; + fbdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 0)) & 0xfff; + postdiv1 = + (mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) >> 8) & 0x7; + postdiv2 = + (mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) >> 12) & 0x7; + + return (24 / refdiv * fbdiv / postdiv1 / postdiv2) * 1000 * 1000; +} + +/* + * return: bit12: channel 1, external self-refresh + * bit11: channel 1, stdby_mode + * bit10: channel 1, self-refresh with controller and memory clock gate + * bit9: channel 1, self-refresh + * bit8: channel 1, power-down + * + * bit4: channel 1, external self-refresh + * bit3: channel 0, stdby_mode + * bit2: channel 0, self-refresh with controller and memory clock gate + * bit1: channel 0, self-refresh + * bit0: channel 0, power-down + */ +uint32_t exit_low_power(void) +{ + uint32_t low_power = 0; + uint32_t channel_mask; + uint32_t tmp, i; + + channel_mask = (mmio_read_32(PMUGRF_BASE + PMUGRF_OSREG(2)) >> 28) & + 0x3; + for (i = 0; i < 2; i++) { + if (!(channel_mask & (1 << i))) + continue; + + /* exit stdby mode */ + mmio_write_32(CIC_BASE + CIC_CTRL1, + (1 << (i + 16)) | (0 << i)); + /* exit external self-refresh */ + tmp = i ? 12 : 8; + low_power |= ((mmio_read_32(PMU_BASE + PMU_SFT_CON) >> tmp) & + 0x1) << (4 + 8 * i); + mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 1 << tmp); + while (!(mmio_read_32(PMU_BASE + PMU_DDR_SREF_ST) & (1 << i))) + ; + /* exit auto low-power */ + mmio_clrbits_32(CTL_REG(i, 101), 0x7); + /* lp_cmd to exit */ + if (((mmio_read_32(CTL_REG(i, 100)) >> 24) & 0x7f) != + 0x40) { + while (mmio_read_32(CTL_REG(i, 200)) & 0x1) + ; + mmio_clrsetbits_32(CTL_REG(i, 93), 0xff << 24, + 0x69 << 24); + while (((mmio_read_32(CTL_REG(i, 100)) >> 24) & 0x7f) != + 0x40) + ; + } + } + return low_power; +} + +void resume_low_power(uint32_t low_power) +{ + uint32_t channel_mask; + uint32_t tmp, i, val; + + channel_mask = (mmio_read_32(PMUGRF_BASE + PMUGRF_OSREG(2)) >> 28) & + 0x3; + for (i = 0; i < 2; i++) { + if (!(channel_mask & (1 << i))) + continue; + + /* resume external self-refresh */ + tmp = i ? 12 : 8; + val = (low_power >> (4 + 8 * i)) & 0x1; + mmio_setbits_32(PMU_BASE + PMU_SFT_CON, val << tmp); + /* resume auto low-power */ + val = (low_power >> (8 * i)) & 0x7; + mmio_setbits_32(CTL_REG(i, 101), val); + /* resume stdby mode */ + val = (low_power >> (3 + 8 * i)) & 0x1; + mmio_write_32(CIC_BASE + CIC_CTRL1, + (1 << (i + 16)) | (val << i)); + } +} + +static void wait_dcf_done(void) +{ + while ((mmio_read_32(DCF_BASE + DCF_DCF_ISR) & (DCF_DONE)) == 0) + continue; +} + +void clr_dcf_irq(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 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; + else + tmp1 = (3 << 16) | (0x7 << 8) | 7; + + *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)); + } + + /* 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) { + mmio_write_32(GRF_BASE + GRF_DDRC1_CON1, + (((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(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); +} + + +static void dram_related_init(struct ddr_dts_config_timing *dts_timing) +{ + uint32_t trefi0, trefi1; + uint32_t i; + + dcf_code_init(); + + /* get sdram config for os reg */ + drv_odt_lp_cfg_init(sdram_config.dramtype, dts_timing, + &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); + + trefi0 = ((mmio_read_32(CTL_REG(0, 48)) >> 16) & 0xffff) + 8; + trefi1 = ((mmio_read_32(CTL_REG(0, 49)) >> 16) & 0xffff) + 8; + + rk3399_dram_status.index_freq[0] = trefi0 * 10 / 39; + rk3399_dram_status.index_freq[1] = trefi1 * 10 / 39; + rk3399_dram_status.current_index = + (mmio_read_32(CTL_REG(0, 111)) >> 16) & 0x3; + if (rk3399_dram_status.timing_config.dram_type == DDR3) { + 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; + + /* 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); + + 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); + } + + /* 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); +} + +static uint32_t prepare_ddr_timing(uint32_t mhz) +{ + uint32_t index; + struct dram_timing_t dram_timing; + + rk3399_dram_status.timing_config.freq = mhz; + + if (mhz < rk3399_dram_status.drv_odt_lp_cfg.ddr3_dll_dis_freq) + 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; + 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 + * target freq. + */ + dram_get_parameter(&rk3399_dram_status.timing_config, &dram_timing); + gen_rk3399_ctl_params(&rk3399_dram_status.timing_config, + &dram_timing, index); + gen_rk3399_pi_params(&rk3399_dram_status.timing_config, + &dram_timing, index); + gen_rk3399_phy_params(&rk3399_dram_status.timing_config, + &rk3399_dram_status.drv_odt_lp_cfg, + &dram_timing, index); + rk3399_dram_status.index_freq[index] = mhz; + + +out: + return index; +} + +void print_dram_status_info(void) +{ + uint32_t *p; + uint32_t i; + + p = (uint32_t *) &rk3399_dram_status.timing_config; + INFO("rk3399_dram_status.timing_config:\n"); + for (i = 0; i < sizeof(struct timing_related_config) / 4; i++) + tf_printf("%u\n", p[i]); + p = (uint32_t *) &rk3399_dram_status.drv_odt_lp_cfg; + INFO("rk3399_dram_status.drv_odt_lp_cfg:\n"); + for (i = 0; i < sizeof(struct drv_odt_lp_config) / 4; i++) + tf_printf("%u\n", p[i]); +} + +uint32_t ddr_set_rate(uint32_t hz) +{ + uint32_t low_power, index; + uint32_t mhz = hz / (1000 * 1000); + + if (mhz == + rk3399_dram_status.index_freq[rk3399_dram_status.current_index]) + goto out; + + 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) + goto out; + + dcf_start(mhz, index); + wait_dcf_done(); + 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; + + resume_low_power(low_power); +out: + return mhz; +} + +uint32_t ddr_round_rate(uint32_t hz) +{ + int index; + uint32_t mhz = hz / (1000 * 1000); + + index = to_get_clk_index(mhz); + + return dpll_rates_table[index].mhz * 1000 * 1000; +} + +uint32_t dts_timing_receive(uint32_t timing, uint32_t index) +{ + 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; + } + + /* receive all parameter */ + if (receive_nums == (sizeof(dts_parameter) / sizeof(uint32_t) - 1)) { + dts_parameter.available = 1; + receive_nums = 0; + } + + return index; +} + +void ddr_dfs_init(void) +{ + dram_related_init(&dts_parameter); +} diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.h b/plat/rockchip/rk3399/drivers/dram/dfs.h new file mode 100644 index 000000000..1da09032d --- /dev/null +++ b/plat/rockchip/rk3399/drivers/dram/dfs.h @@ -0,0 +1,112 @@ +/* + * 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 __SOC_ROCKCHIP_RK3399_DFS_H__ +#define __SOC_ROCKCHIP_RK3399_DFS_H__ + +struct rk3399_sdram_default_config { + unsigned char bl; + /* 1:auto precharge, 0:never auto precharge */ + unsigned char ap; + /* dram driver strength */ + unsigned char dramds; + /* dram ODT, if odt=0, this parameter invalid */ + unsigned char dramodt; + /* ca ODT, if odt=0, this parameter invalid + * only used by LPDDR4 + */ + unsigned char caodt; + unsigned char burst_ref_cnt; + /* zqcs period, unit(s) */ + 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 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); +#endif diff --git a/plat/rockchip/rk3399/drivers/dram/dram.c b/plat/rockchip/rk3399/drivers/dram/dram.c index 94aa0766d..5f6f0fc3e 100644 --- a/plat/rockchip/rk3399/drivers/dram/dram.c +++ b/plat/rockchip/rk3399/drivers/dram/dram.c @@ -28,2540 +28,49 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include +#include #include -#include "dram.h" -#include "dram_spec_timing.h" -#include "string.h" -#include "soc.h" -#include "pmu.h" +#include +#include -#include +__sramdata struct rk3399_sdram_params sdram_config; -#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; -}; - -static const struct pll_div dpll_rates_table[] = { - - /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2 */ - {.mhz = 933, .refdiv = 3, .fbdiv = 350, .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}, - {.mhz = 600, .refdiv = 1, .fbdiv = 50, .postdiv1 = 2, .postdiv2 = 1}, - {.mhz = 528, .refdiv = 1, .fbdiv = 66, .postdiv1 = 3, .postdiv2 = 1}, - {.mhz = 400, .refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 1}, - {.mhz = 300, .refdiv = 1, .fbdiv = 50, .postdiv1 = 4, .postdiv2 = 1}, - {.mhz = 200, .refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 2}, -}; - -static struct rk3399_ddr_cic_regs *const rk3399_ddr_cic = (void *)CIC_BASE; -static struct rk3399_ddr_pctl_regs *const rk3399_ddr_pctl[2] = { - (void *)DDRC0_BASE, (void *)DDRC1_BASE -}; - -static struct rk3399_ddr_pi_regs *const rk3399_ddr_pi[2] = { - (void *)DDRC0_PI_BASE, (void *)DDRC1_PI_BASE -}; - -static struct rk3399_ddr_publ_regs *const rk3399_ddr_publ[2] = { - (void *)DDRC0_PHY_BASE, (void *)DDRC1_PHY_BASE -}; - -struct rk3399_dram_status { - uint32_t current_index; - uint32_t index_freq[2]; - 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 -}; - -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 write_32(addr, value)\ - mmio_write_32((uintptr_t)(addr), (uint32_t)(value)) - -#define read_32(addr) \ - mmio_read_32((uintptr_t)(addr)) -#define clrbits_32(addr, clear)\ - mmio_clrbits_32((uintptr_t)(addr), (uint32_t)(clear)) -#define setbits_32(addr, set)\ - mmio_setbits_32((uintptr_t)(addr), (uint32_t)(set)) -#define clrsetbits_32(addr, clear, set)\ - mmio_clrsetbits_32((uintptr_t)(addr), (uint32_t)(clear),\ - (uint32_t)(set)) - -#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 unsigned int get_cs_die_capability(struct rk3399_sdram_config - *psdram_config, unsigned int channel, - unsigned int cs) -{ - unsigned int die; - unsigned int cs_cap; - unsigned int row[2]; - - row[0] = psdram_config->ch[channel].cs0_row; - row[1] = psdram_config->ch[channel].cs1_row; - die = psdram_config->ch[channel].bus_width / - psdram_config->ch[channel].each_die_bus_width; - cs_cap = (1 << (row[cs] + - (psdram_config->ch[channel].bank / 4 + 1) + - psdram_config->ch[channel].col + - (psdram_config->ch[channel].bus_width / 16))); - if (psdram_config->ch[channel].each_die_6gb_or_12gb) - cs_cap = cs_cap * 3 / 4; - - return (cs_cap / die); -} - -static void sdram_config_init(struct rk3399_sdram_config *psdram_config) +void dram_init(void) { uint32_t os_reg2_val, i; - os_reg2_val = read_32(PMUGRF_BASE + PMUGRF_OSREG(2)); + os_reg2_val = mmio_read_32(PMUGRF_BASE + PMUGRF_OSREG(2)); + sdram_config.dramtype = SYS_REG_DEC_DDRTYPE(os_reg2_val); + sdram_config.num_channels = SYS_REG_DEC_NUM_CH(os_reg2_val); + sdram_config.stride = (mmio_read_32(SGRF_BASE + SGRF_SOC_CON3_7(4)) >> + 10) & 0x1f; - for (i = 0; i < READ_CH_CNT(os_reg2_val); i++) { - psdram_config->ch[i].bank = 1 << READ_BK_INFO(os_reg2_val, i); - psdram_config->ch[i].bus_width = - 8 * (1 << READ_BW_INFO(os_reg2_val, i)); - psdram_config->ch[i].col = READ_COL_INFO(os_reg2_val, i); - psdram_config->ch[i].cs0_row = - READ_CS0_ROW_INFO(os_reg2_val, i); - psdram_config->ch[i].cs1_row = - READ_CS1_ROW_INFO(os_reg2_val, i); - psdram_config->ch[i].cs_cnt = READ_CS_INFO(os_reg2_val, i); - psdram_config->ch[i].each_die_6gb_or_12gb = - READ_CH_ROW_INFO(os_reg2_val, i); - psdram_config->ch[i].each_die_bus_width = - 8 * (1 << READ_DIE_BW_INFO(os_reg2_val, i)); - } - psdram_config->dramtype = READ_DRAMTYPE_INFO(os_reg2_val); - psdram_config->channal_num = READ_CH_CNT(os_reg2_val); -} + for (i = 0; i < 2; i++) { + struct rk3399_sdram_channel *ch = &sdram_config.ch[i]; + struct rk3399_msch_timings *noc = &ch->noc_timings; -static void drv_odt_lp_cfg_init(uint32_t dram_type, - struct ddr_dts_config_timing *dts_timing, - 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; - } - - 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)); - } - 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)); - } - 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; - }; - - 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; - } - - 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; - } - - 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; - break; - } -} - -static void sdram_timing_cfg_init(struct timing_related_config *ptiming_config, - struct rk3399_sdram_config *psdram_config, - struct drv_odt_lp_config *drv_config) -{ - uint32_t i, j; - - for (i = 0; i < psdram_config->channal_num; i++) { - ptiming_config->dram_info[i].speed_rate = - drv_config->ddr3_speed_bin; - ptiming_config->dram_info[i].cs_cnt = - psdram_config->ch[i].cs_cnt; - for (j = 0; j < psdram_config->ch[i].cs_cnt; j++) { - ptiming_config->dram_info[i].per_die_capability[j] = - get_cs_die_capability(psdram_config, i, j); - } - } - ptiming_config->dram_type = psdram_config->dramtype; - ptiming_config->ch_cnt = psdram_config->channal_num; - switch (psdram_config->dramtype) { - case DDR3: - ptiming_config->bl = ddr3_default_config.bl; - ptiming_config->ap = ddr3_default_config.ap; - break; - case LPDDR3: - ptiming_config->bl = lpddr3_default_config.bl; - ptiming_config->ap = lpddr3_default_config.ap; - break; - case LPDDR4: - ptiming_config->bl = lpddr4_default_config.bl; - ptiming_config->ap = lpddr4_default_config.ap; - ptiming_config->rdbi = 0; - ptiming_config->wdbi = 0; - break; - } - 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; -} - -struct lat_adj_pair { - uint32_t cl; - uint32_t rdlat_adj; - uint32_t cwl; - uint32_t wrlat_adj; -}; - -const struct lat_adj_pair ddr3_lat_adj[] = { - {6, 5, 5, 4}, - {8, 7, 6, 5}, - {10, 9, 7, 6}, - {11, 9, 8, 7}, - {13, 0xb, 9, 8}, - {14, 0xb, 0xa, 9} -}; - -const struct lat_adj_pair lpddr3_lat_adj[] = { - {3, 2, 1, 0}, - {6, 5, 3, 2}, - {8, 7, 4, 3}, - {9, 8, 5, 4}, - {10, 9, 6, 5}, - {11, 9, 6, 5}, - {12, 0xa, 6, 5}, - {14, 0xc, 8, 7}, - {16, 0xd, 8, 7} -}; - -const struct lat_adj_pair lpddr4_lat_adj[] = { - {6, 5, 4, 2}, - {10, 9, 6, 4}, - {14, 0xc, 8, 6}, - {20, 0x11, 0xa, 8}, - {24, 0x15, 0xc, 0xa}, - {28, 0x18, 0xe, 0xc}, - {32, 0x1b, 0x10, 0xe}, - {36, 0x1e, 0x12, 0x10} -}; - -static uint32_t get_rdlat_adj(uint32_t dram_type, uint32_t cl) -{ - const struct lat_adj_pair *p; - uint32_t cnt; - uint32_t i; - - if (dram_type == DDR3) { - p = ddr3_lat_adj; - cnt = ARRAY_SIZE(ddr3_lat_adj); - } else if (dram_type == LPDDR3) { - p = lpddr3_lat_adj; - cnt = ARRAY_SIZE(lpddr3_lat_adj); - } else { - p = lpddr4_lat_adj; - cnt = ARRAY_SIZE(lpddr4_lat_adj); - } - - for (i = 0; i < cnt; i++) { - if (cl == p[i].cl) - return p[i].rdlat_adj; - } - /* fail */ - return 0xff; -} - -static uint32_t get_wrlat_adj(uint32_t dram_type, uint32_t cwl) -{ - const struct lat_adj_pair *p; - uint32_t cnt; - uint32_t i; - - if (dram_type == DDR3) { - p = ddr3_lat_adj; - cnt = ARRAY_SIZE(ddr3_lat_adj); - } else if (dram_type == LPDDR3) { - p = lpddr3_lat_adj; - cnt = ARRAY_SIZE(lpddr3_lat_adj); - } else { - p = lpddr4_lat_adj; - cnt = ARRAY_SIZE(lpddr4_lat_adj); - } - - for (i = 0; i < cnt; i++) { - if (cwl == p[i].cwl) - return p[i].wrlat_adj; - } - /* fail */ - return 0xff; -} - -#define PI_REGS_DIMM_SUPPORT (0) -#define PI_ADD_LATENCY (0) -#define PI_DOUBLEFREEK (1) - -#define PI_PAD_DELAY_PS_VALUE (1000) -#define PI_IE_ENABLE_VALUE (3000) -#define PI_TSEL_ENABLE_VALUE (700) - -static uint32_t get_pi_rdlat_adj(struct dram_timing_t *pdram_timing) -{ - /*[DLLSUBTYPE2] == "STD_DENALI_HS" */ - uint32_t rdlat, delay_adder, ie_enable, hs_offset, tsel_adder, - extra_adder, tsel_enable; - - ie_enable = PI_IE_ENABLE_VALUE; - tsel_enable = PI_TSEL_ENABLE_VALUE; - - rdlat = pdram_timing->cl + PI_ADD_LATENCY; - delay_adder = ie_enable / (1000000 / pdram_timing->mhz); - if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) - delay_adder++; - hs_offset = 0; - tsel_adder = 0; - extra_adder = 0; - /* rdlat = rdlat - (PREAMBLE_SUPPORT & 0x1); */ - tsel_adder = tsel_enable / (1000000 / pdram_timing->mhz); - if ((tsel_enable % (1000000 / pdram_timing->mhz)) != 0) - tsel_adder++; - delay_adder = delay_adder - 1; - if (tsel_adder > delay_adder) - extra_adder = tsel_adder - delay_adder; - else - extra_adder = 0; - if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK) - hs_offset = 2; - else - hs_offset = 1; - - if (delay_adder > (rdlat - 1 - hs_offset)) { - rdlat = rdlat - tsel_adder; - } else { - if ((rdlat - delay_adder) < 2) - rdlat = 2; - else - rdlat = rdlat - delay_adder - extra_adder; - } - - return rdlat; -} - -static uint32_t get_pi_wrlat(struct dram_timing_t *pdram_timing, - struct timing_related_config *timing_config) -{ - uint32_t tmp; - - if (timing_config->dram_type == LPDDR3) { - tmp = pdram_timing->cl; - if (tmp >= 14) - tmp = 8; - else if (tmp >= 10) - tmp = 6; - else if (tmp == 9) - tmp = 5; - else if (tmp == 8) - tmp = 4; - else if (tmp == 6) - tmp = 3; - else - tmp = 1; - } else { - tmp = 1; - } - - return tmp; -} - -static uint32_t get_pi_wrlat_adj(struct dram_timing_t *pdram_timing, - struct timing_related_config *timing_config) -{ - return get_pi_wrlat(pdram_timing, timing_config) + PI_ADD_LATENCY - 1; -} - -static uint32_t get_pi_tdfi_phy_rdlat(struct dram_timing_t *pdram_timing, - struct timing_related_config *timing_config) -{ - /* [DLLSUBTYPE2] == "STD_DENALI_HS" */ - uint32_t cas_lat, delay_adder, ie_enable, hs_offset, ie_delay_adder; - uint32_t mem_delay_ps, round_trip_ps; - uint32_t phy_internal_delay, lpddr_adder, dfi_adder, rdlat_delay; - - ie_enable = PI_IE_ENABLE_VALUE; - - delay_adder = ie_enable / (1000000 / pdram_timing->mhz); - if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) - delay_adder++; - delay_adder = delay_adder - 1; - if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK) - hs_offset = 2; - else - hs_offset = 1; - - cas_lat = pdram_timing->cl + PI_ADD_LATENCY; - - if (delay_adder > (cas_lat - 1 - hs_offset)) { - ie_delay_adder = 0; - } else { - ie_delay_adder = ie_enable / (1000000 / pdram_timing->mhz); - if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) - ie_delay_adder++; - } - - if (timing_config->dram_type == DDR3) { - mem_delay_ps = 0; - } else if (timing_config->dram_type == LPDDR4) { - mem_delay_ps = 3600; - } else if (timing_config->dram_type == LPDDR3) { - mem_delay_ps = 5500; - } else { - printf("get_pi_tdfi_phy_rdlat:dramtype unsupport\n"); - return 0; - } - round_trip_ps = 1100 + 500 + mem_delay_ps + 500 + 600; - delay_adder = round_trip_ps / (1000000 / pdram_timing->mhz); - if ((round_trip_ps % (1000000 / pdram_timing->mhz)) != 0) - delay_adder++; - - phy_internal_delay = 5 + 2 + 4; - lpddr_adder = mem_delay_ps / (1000000 / pdram_timing->mhz); - if ((mem_delay_ps % (1000000 / pdram_timing->mhz)) != 0) - lpddr_adder++; - dfi_adder = 0; - phy_internal_delay = phy_internal_delay + 2; - rdlat_delay = delay_adder + phy_internal_delay + - ie_delay_adder + lpddr_adder + dfi_adder; - - rdlat_delay = rdlat_delay + 2; - return rdlat_delay; -} - -static uint32_t get_pi_todtoff_min(struct dram_timing_t *pdram_timing, - struct timing_related_config *timing_config) -{ - uint32_t tmp, todtoff_min_ps; - - if (timing_config->dram_type == LPDDR3) - todtoff_min_ps = 2500; - else if (timing_config->dram_type == LPDDR4) - todtoff_min_ps = 1500; - else - todtoff_min_ps = 0; - /* todtoff_min */ - tmp = todtoff_min_ps / (1000000 / pdram_timing->mhz); - if ((todtoff_min_ps % (1000000 / pdram_timing->mhz)) != 0) - tmp++; - return tmp; -} - -static uint32_t get_pi_todtoff_max(struct dram_timing_t *pdram_timing, - struct timing_related_config *timing_config) -{ - uint32_t tmp, todtoff_max_ps; - - if ((timing_config->dram_type == LPDDR4) - || (timing_config->dram_type == LPDDR3)) - todtoff_max_ps = 3500; - else - todtoff_max_ps = 0; - - /* todtoff_max */ - tmp = todtoff_max_ps / (1000000 / pdram_timing->mhz); - if ((todtoff_max_ps % (1000000 / pdram_timing->mhz)) != 0) - tmp++; - return tmp; -} - -static void gen_rk3399_ctl_params_f0(struct timing_related_config - *timing_config, - struct dram_timing_t *pdram_timing) -{ - uint32_t i; - uint32_t tmp, tmp1; - - for (i = 0; i < timing_config->ch_cnt; i++) { - if (timing_config->dram_type == DDR3) { - tmp = ((700000 + 10) * timing_config->freq + - 999) / 1000; - tmp += pdram_timing->txsnr + (pdram_timing->tmrd * 3) + - pdram_timing->tmod + pdram_timing->tzqinit; - write_32(&rk3399_ddr_pctl[i]->denali_ctl[5], tmp); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[22], - 0xffff, pdram_timing->tdllk); - - write_32(&rk3399_ddr_pctl[i]->denali_ctl[32], - (pdram_timing->tmod << 8) | - pdram_timing->tmrd); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[59], - 0xffff << 16, - (pdram_timing->txsr - - pdram_timing->trcd) << 16); - } else if (timing_config->dram_type == LPDDR4) { - write_32(&rk3399_ddr_pctl[i]->denali_ctl[5], - pdram_timing->tinit1 + pdram_timing->tinit3); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[32], - (pdram_timing->tmrd << 8) | - pdram_timing->tmrd); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[59], - 0xffff << 16, pdram_timing->txsr << 16); - } else { - write_32(&rk3399_ddr_pctl[i]->denali_ctl[5], - pdram_timing->tinit1); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[7], - pdram_timing->tinit4); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[32], - (pdram_timing->tmrd << 8) | - pdram_timing->tmrd); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[59], - 0xffff << 16, pdram_timing->txsr << 16); - } - write_32(&rk3399_ddr_pctl[i]->denali_ctl[6], - pdram_timing->tinit3); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[8], - pdram_timing->tinit5); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[23], (0x7f << 16), - ((pdram_timing->cl * 2) << 16)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[23], (0x1f << 24), - (pdram_timing->cwl << 24)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[24], 0x3f, - pdram_timing->al); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[26], 0xffff << 16, - (pdram_timing->trc << 24) | - (pdram_timing->trrd << 16)); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[27], - (pdram_timing->tfaw << 24) | - (pdram_timing->trppb << 16) | - (pdram_timing->twtr << 8) | pdram_timing->tras_min); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[31], 0xff << 24, - max(4, pdram_timing->trtp) << 24); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[33], - (pdram_timing->tcke << 24) | pdram_timing->tras_max); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[34], 0xff, - max(1, pdram_timing->tckesr)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[39], - (0x3f << 16) | (0xff << 8), - (pdram_timing->twr << 16) | - (pdram_timing->trcd << 8)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[42], 0x1f << 16, - pdram_timing->tmrz << 16); - tmp = pdram_timing->tdal ? pdram_timing->tdal : - (pdram_timing->twr + pdram_timing->trp); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[44], 0xff, tmp); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[45], 0xff, - pdram_timing->trp); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[48], - ((pdram_timing->trefi - 8) << 16) | - pdram_timing->trfc); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[52], 0xffff, - pdram_timing->txp); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[53], 0xffff << 16, - pdram_timing->txpdll << 16); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[55], 0xf << 24, - pdram_timing->tcscke << 24); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[55], 0xff, - pdram_timing->tmrri); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[56], - (pdram_timing->tzqcke << 24) | - (pdram_timing->tmrwckel << 16) | - (pdram_timing->tckehcs << 8) | pdram_timing->tckelcs); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[60], 0xffff, - pdram_timing->txsnr); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[62], 0xffff << 16, - (pdram_timing->tckehcmd << 24) | - (pdram_timing->tckelcmd << 16)); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[63], - (pdram_timing->tckelpd << 24) | - (pdram_timing->tescke << 16) | - (pdram_timing->tsr << 8) | pdram_timing->tckckel); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[64], 0xfff, - (pdram_timing->tcmdcke << 8) | - pdram_timing->tcsckeh); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[92], - (0xffff << 8), - (pdram_timing->tcksrx << 16) | - (pdram_timing->tcksre << 8)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[108], (0x1 << 24), - (timing_config->dllbp << 24)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[122], - (0x3FF << 16), - (pdram_timing->tvrcg_enable << 16)); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[123], - (pdram_timing->tfc_long << 16) | - pdram_timing->tvrcg_disable); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[124], - (pdram_timing->tvref_long << 16) | - (pdram_timing->tckfspx << 8) | - pdram_timing->tckfspe); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[133], - (pdram_timing->mr[1] << 16) | pdram_timing->mr[0]); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[134], 0xffff, - pdram_timing->mr[2]); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[138], 0xffff, - pdram_timing->mr[3]); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[139], 0xff << 24, - pdram_timing->mr11 << 24); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[147], - (pdram_timing->mr[1] << 16) | pdram_timing->mr[0]); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[148], 0xffff, - pdram_timing->mr[2]); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[152], 0xffff, - pdram_timing->mr[3]); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[153], 0xff << 24, - pdram_timing->mr11 << 24); - if (timing_config->dram_type == LPDDR4) { - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[140], - 0xffff << 16, pdram_timing->mr12 << 16); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[142], - 0xffff << 16, pdram_timing->mr14 << 16); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[145], - 0xffff << 16, pdram_timing->mr22 << 16); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[154], - 0xffff << 16, pdram_timing->mr12 << 16); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[156], - 0xffff << 16, pdram_timing->mr14 << 16); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[159], - 0xffff << 16, pdram_timing->mr22 << 16); - } - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[179], 0xfff << 8, - pdram_timing->tzqinit << 8); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[180], - (pdram_timing->tzqcs << 16) | - (pdram_timing->tzqinit / 2)); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[181], - (pdram_timing->tzqlat << 16) | pdram_timing->tzqcal); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[212], 0xff << 8, - pdram_timing->todton << 8); - - if (timing_config->odt) { - setbits_32(&rk3399_ddr_pctl[i]->denali_ctl[213], - 1 << 16); - if (timing_config->freq < 400) - tmp = 4 << 24; - else - tmp = 8 << 24; - } else { - clrbits_32(&rk3399_ddr_pctl[i]->denali_ctl[213], - 1 << 16); - tmp = 2 << 24; - } - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[216], - 0x1f << 24, tmp); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[221], - (0x3 << 16) | (0xf << 8), - (pdram_timing->tdqsck << 16) | - (pdram_timing->tdqsck_max << 8)); - tmp = - (get_wrlat_adj(timing_config->dram_type, pdram_timing->cwl) - << 8) | get_rdlat_adj(timing_config->dram_type, - pdram_timing->cl); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[284], 0xffff, - tmp); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[82], 0xffff << 16, - (4 * pdram_timing->trefi) << 16); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[83], 0xffff, - (2 * pdram_timing->trefi) & 0xffff); - - if ((timing_config->dram_type == LPDDR3) || - (timing_config->dram_type == LPDDR4)) { - tmp = get_pi_wrlat(pdram_timing, timing_config); - tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); - tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; - } else { - tmp = 0; - } - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[214], 0x3f << 16, - (tmp & 0x3f) << 16); - - if ((timing_config->dram_type == LPDDR3) || - (timing_config->dram_type == LPDDR4)) { - /* min_rl_preamble= cl+TDQSCK_MIN-1 */ - tmp = pdram_timing->cl + - get_pi_todtoff_min(pdram_timing, timing_config) - 1; - /* todtoff_max */ - tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); - tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; - } else { - tmp = pdram_timing->cl - pdram_timing->cwl; - } - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[215], 0x3f << 8, - (tmp & 0x3f) << 8); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[275], 0xff << 16, - (get_pi_tdfi_phy_rdlat - (pdram_timing, timing_config) - & 0xff) << 16); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[277], 0xffff, - (2 * pdram_timing->trefi) & 0xffff); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[282], 0xffff, - (2 * pdram_timing->trefi) & 0xffff); - - write_32(&rk3399_ddr_pctl[i]->denali_ctl[283], - 20 * pdram_timing->trefi); - - /* CTL_308 TDFI_CALVL_CAPTURE_F0:RW:16:10 */ - tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; - if ((20000 % (1000000 / pdram_timing->mhz)) != 0) - tmp1++; - tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[308], 0x3ff << 16, - tmp << 16); - - /* CTL_308 TDFI_CALVL_CC_F0:RW:0:10 */ - tmp = tmp + 18; - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[308], 0x3ff, - tmp); - - /* 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 (tmp1 < 5) { - if (tmp1 == 0) - tmp = 0; - else - tmp = tmp1 - 1; - } else { - tmp = tmp1 - 5; - } - } else { - tmp = tmp1 - 2; - } - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[314], 0xff << 8, - tmp << 8); - - /* CTL_314 TDFI_RDCSLAT_F0:RW:0:8 */ - if ((timing_config->freq <= ENPER_CS_TRAINING_FREQ) && - (pdram_timing->cl >= 5)) - tmp = pdram_timing->cl - 5; - else - tmp = pdram_timing->cl - 2; - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[314], 0xff, - tmp); - } -} - -static void gen_rk3399_ctl_params_f1(struct timing_related_config - *timing_config, - struct dram_timing_t *pdram_timing) -{ - uint32_t i; - uint32_t tmp, tmp1; - - for (i = 0; i < timing_config->ch_cnt; i++) { - if (timing_config->dram_type == DDR3) { - tmp = - ((700000 + 10) * timing_config->freq + - 999) / 1000; - tmp += - pdram_timing->txsnr + (pdram_timing->tmrd * 3) + - pdram_timing->tmod + pdram_timing->tzqinit; - write_32(&rk3399_ddr_pctl[i]->denali_ctl[9], tmp); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[22], - 0xffff << 16, pdram_timing->tdllk << 16); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[34], - 0xffffff00, - (pdram_timing->tmod << 24) | - (pdram_timing->tmrd << 16) | - (pdram_timing->trtp << 8)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[60], - 0xffff << 16, - (pdram_timing->txsr - - pdram_timing->trcd) << 16); - } else if (timing_config->dram_type == LPDDR4) { - write_32(&rk3399_ddr_pctl[i]->denali_ctl[9], - pdram_timing->tinit1 + pdram_timing->tinit3); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[34], - 0xffffff00, - (pdram_timing->tmrd << 24) | - (pdram_timing->tmrd << 16) | - (pdram_timing->trtp << 8)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[60], - 0xffff << 16, pdram_timing->txsr << 16); - } else { - write_32(&rk3399_ddr_pctl[i]->denali_ctl[9], - pdram_timing->tinit1); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[11], - pdram_timing->tinit4); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[34], - 0xffffff00, - (pdram_timing->tmrd << 24) | - (pdram_timing->tmrd << 16) | - (pdram_timing->trtp << 8)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[60], - 0xffff << 16, pdram_timing->txsr << 16); - } - write_32(&rk3399_ddr_pctl[i]->denali_ctl[10], - pdram_timing->tinit3); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[12], - pdram_timing->tinit5); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[24], (0x7f << 8), - ((pdram_timing->cl * 2) << 8)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[24], (0x1f << 16), - (pdram_timing->cwl << 16)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[24], 0x3f << 24, - pdram_timing->al << 24); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[28], 0xffffff00, - (pdram_timing->tras_min << 24) | - (pdram_timing->trc << 16) | - (pdram_timing->trrd << 8)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[29], 0xffffff, - (pdram_timing->tfaw << 16) | - (pdram_timing->trppb << 8) | pdram_timing->twtr); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[35], - (pdram_timing->tcke << 24) | pdram_timing->tras_max); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[36], 0xff, - max(1, pdram_timing->tckesr)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[39], - (0xff << 24), (pdram_timing->trcd << 24)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[40], - 0x3f, pdram_timing->twr); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[42], 0x1f << 24, - pdram_timing->tmrz << 24); - tmp = pdram_timing->tdal ? pdram_timing->tdal : - (pdram_timing->twr + pdram_timing->trp); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[44], 0xff << 8, - tmp << 8); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[45], 0xff << 8, - pdram_timing->trp << 8); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[49], - ((pdram_timing->trefi - 8) << 16) | - pdram_timing->trfc); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[52], 0xffff << 16, - pdram_timing->txp << 16); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[54], 0xffff, - pdram_timing->txpdll); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[55], 0xff << 8, - pdram_timing->tmrri << 8); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[57], - (pdram_timing->tmrwckel << 24) | - (pdram_timing->tckehcs << 16) | - (pdram_timing->tckelcs << 8) | pdram_timing->tcscke); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[58], 0xf, - pdram_timing->tzqcke); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[61], 0xffff, - pdram_timing->txsnr); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[64], 0xffff << 16, - (pdram_timing->tckehcmd << 24) | - (pdram_timing->tckelcmd << 16)); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[65], - (pdram_timing->tckelpd << 24) | - (pdram_timing->tescke << 16) | - (pdram_timing->tsr << 8) | pdram_timing->tckckel); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[66], 0xfff, - (pdram_timing->tcmdcke << 8) | - pdram_timing->tcsckeh); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[92], (0xff << 24), - (pdram_timing->tcksre << 24)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[93], 0xff, - pdram_timing->tcksrx); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[108], (0x1 << 25), - (timing_config->dllbp << 25)); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[125], - (pdram_timing->tvrcg_disable << 16) | - pdram_timing->tvrcg_enable); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[126], - (pdram_timing->tckfspx << 24) | - (pdram_timing->tckfspe << 16) | - pdram_timing->tfc_long); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[127], 0xffff, - pdram_timing->tvref_long); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[134], - 0xffff << 16, pdram_timing->mr[0] << 16); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[135], - (pdram_timing->mr[2] << 16) | pdram_timing->mr[1]); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[138], - 0xffff << 16, pdram_timing->mr[3] << 16); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[140], 0xff, - pdram_timing->mr11); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[148], - 0xffff << 16, pdram_timing->mr[0] << 16); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[149], - (pdram_timing->mr[2] << 16) | pdram_timing->mr[1]); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[152], - 0xffff << 16, pdram_timing->mr[3] << 16); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[154], 0xff, - pdram_timing->mr11); - if (timing_config->dram_type == LPDDR4) { - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[141], - 0xffff, pdram_timing->mr12); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[143], - 0xffff, pdram_timing->mr14); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[146], - 0xffff, pdram_timing->mr22); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[155], - 0xffff, pdram_timing->mr12); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[157], - 0xffff, pdram_timing->mr14); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[160], - 0xffff, pdram_timing->mr22); - } - write_32(&rk3399_ddr_pctl[i]->denali_ctl[182], - ((pdram_timing->tzqinit / 2) << 16) | - pdram_timing->tzqinit); - write_32(&rk3399_ddr_pctl[i]->denali_ctl[183], - (pdram_timing->tzqcal << 16) | pdram_timing->tzqcs); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[184], 0x3f, - pdram_timing->tzqlat); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[188], 0xfff, - pdram_timing->tzqreset); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[212], 0xff << 16, - pdram_timing->todton << 16); - - if (timing_config->odt) { - setbits_32(&rk3399_ddr_pctl[i]->denali_ctl[213], - (1 << 24)); - if (timing_config->freq < 400) - tmp = 4 << 24; - else - tmp = 8 << 24; - } else { - clrbits_32(&rk3399_ddr_pctl[i]->denali_ctl[213], - (1 << 24)); - tmp = 2 << 24; - } - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[217], 0x1f << 24, - tmp); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[221], 0xf << 24, - (pdram_timing->tdqsck_max << 24)); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[222], 0x3, - pdram_timing->tdqsck); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[291], 0xffff, - (get_wrlat_adj(timing_config->dram_type, - pdram_timing->cwl) << 8) | - get_rdlat_adj(timing_config->dram_type, - pdram_timing->cl)); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[84], 0xffff, - (4 * pdram_timing->trefi) & 0xffff); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[84], 0xffff << 16, - ((2 * pdram_timing->trefi) & 0xffff) << 16); - - if ((timing_config->dram_type == LPDDR3) || - (timing_config->dram_type == LPDDR4)) { - tmp = get_pi_wrlat(pdram_timing, timing_config); - tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); - tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; - } else { - tmp = 0; - } - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[214], 0x3f << 24, - (tmp & 0x3f) << 24); - - if ((timing_config->dram_type == LPDDR3) || - (timing_config->dram_type == LPDDR4)) { - /* min_rl_preamble= cl+TDQSCK_MIN-1 */ - tmp = pdram_timing->cl + - get_pi_todtoff_min(pdram_timing, timing_config) - 1; - /* todtoff_max */ - tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); - tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; - } else { - tmp = pdram_timing->cl - pdram_timing->cwl; - } - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[215], 0x3f << 16, - (tmp & 0x3f) << 16); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[275], 0xff << 24, - (get_pi_tdfi_phy_rdlat - (pdram_timing, timing_config) - & 0xff) << 24); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[284], - 0xffff << 16, - ((2 * pdram_timing->trefi) & 0xffff) << 16); - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[289], 0xffff, - (2 * pdram_timing->trefi) & 0xffff); - - write_32(&rk3399_ddr_pctl[i]->denali_ctl[290], - 20 * pdram_timing->trefi); - - /* CTL_309 TDFI_CALVL_CAPTURE_F1:RW:16:10 */ - tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; - if ((20000 % (1000000 / pdram_timing->mhz)) != 0) - tmp1++; - tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[309], 0x3ff << 16, - tmp << 16); - - /* CTL_309 TDFI_CALVL_CC_F1:RW:0:10 */ - tmp = tmp + 18; - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[309], 0x3ff, - tmp); - - /* 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 (tmp1 < 5) { - if (tmp1 == 0) - tmp = 0; - else - tmp = tmp1 - 1; - } else { - tmp = tmp1 - 5; - } - } else { - tmp = tmp1 - 2; - } - - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[314], 0xff << 24, - tmp << 24); - - /* CTL_314 TDFI_RDCSLAT_F1:RW:16:8 */ - if ((timing_config->freq <= ENPER_CS_TRAINING_FREQ) && - (pdram_timing->cl >= 5)) - tmp = pdram_timing->cl - 5; - else - tmp = pdram_timing->cl - 2; - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[314], 0xff << 16, - tmp << 16); - } -} - -static void gen_rk3399_ctl_params(struct timing_related_config *timing_config, - struct dram_timing_t *pdram_timing, - uint32_t fn) -{ - if (fn == 0) - 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) - setbits_32(&rk3399_ddr_pctl[i]->denali_ctl[305], - 1 << 16); - if (tmp0) - setbits_32(&rk3399_ddr_pctl[i]->denali_ctl[70], tmp0); - if (tmp1) - setbits_32(&rk3399_ddr_pctl[i]->denali_ctl[71], tmp1); - } -#endif -} - -static void gen_rk3399_pi_params_f0(struct timing_related_config *timing_config, - struct dram_timing_t *pdram_timing) -{ - uint32_t tmp, tmp1, tmp2; - uint32_t i; - - for (i = 0; i < timing_config->ch_cnt; i++) { - /* PI_02 PI_TDFI_PHYMSTR_MAX_F0:RW:0:32 */ - tmp = 4 * pdram_timing->trefi; - write_32(&rk3399_ddr_pi[i]->denali_pi[2], tmp); - /* PI_03 PI_TDFI_PHYMSTR_RESP_F0:RW:0:16 */ - tmp = 2 * pdram_timing->trefi; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[3], 0xffff, tmp); - /* PI_07 PI_TDFI_PHYUPD_RESP_F0:RW:16:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[7], 0xffff << 16, - tmp << 16); - - /* PI_42 PI_TDELAY_RDWR_2_BUS_IDLE_F0:RW:0:8 */ - if (timing_config->dram_type == LPDDR4) - tmp = 2; - else - tmp = 0; - tmp = (pdram_timing->bl / 2) + 4 + - (get_pi_rdlat_adj(pdram_timing) - 2) + tmp + - get_pi_tdfi_phy_rdlat(pdram_timing, timing_config); - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[42], 0xff, tmp); - /* PI_43 PI_WRLAT_F0:RW:0:5 */ - if (timing_config->dram_type == LPDDR3) { - tmp = get_pi_wrlat(pdram_timing, timing_config); - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[43], 0x1f, - tmp); - } - /* PI_43 PI_ADDITIVE_LAT_F0:RW:8:6 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[43], 0x3f << 8, - PI_ADD_LATENCY << 8); - - /* PI_43 PI_CASLAT_LIN_F0:RW:16:7 */ - tmp = pdram_timing->cl * 2; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[43], 0x7f << 16, - tmp << 16); - /* PI_46 PI_TREF_F0:RW:16:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[46], 0xffff << 16, - pdram_timing->trefi << 16); - /* PI_46 PI_TRFC_F0:RW:0:10 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[46], 0x3ff, - pdram_timing->trfc); - /* PI_66 PI_TODTL_2CMD_F0:RW:24:8 */ - if (timing_config->dram_type == LPDDR3) { - tmp = get_pi_todtoff_max(pdram_timing, timing_config); - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[66], - 0xff << 24, tmp << 24); - } - /* PI_72 PI_WR_TO_ODTH_F0:RW:16:6 */ - if ((timing_config->dram_type == LPDDR3) || - (timing_config->dram_type == LPDDR4)) { - tmp1 = get_pi_wrlat(pdram_timing, timing_config); - tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); - if (tmp1 > tmp2) - tmp = tmp1 - tmp2; - else - tmp = 0; - } else if (timing_config->dram_type == DDR3) { - tmp = 0; - } - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[72], 0x3f << 16, - tmp << 16); - /* PI_73 PI_RD_TO_ODTH_F0:RW:8:6 */ - if ((timing_config->dram_type == LPDDR3) || - (timing_config->dram_type == LPDDR4)) { - /* min_rl_preamble= cl+TDQSCK_MIN-1 */ - tmp1 = pdram_timing->cl + - get_pi_todtoff_min(pdram_timing, timing_config) - 1; - /* todtoff_max */ - tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); - if (tmp1 > tmp2) - tmp = tmp1 - tmp2; - else - tmp = 0; - } else if (timing_config->dram_type == DDR3) { - tmp = pdram_timing->cl - pdram_timing->cwl; - } - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[73], 0x3f << 8, - tmp << 8); - /* PI_89 PI_RDLAT_ADJ_F0:RW:16:8 */ - tmp = get_pi_rdlat_adj(pdram_timing); - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[89], 0xff << 16, - tmp << 16); - /* PI_90 PI_WRLAT_ADJ_F0:RW:16:8 */ - tmp = get_pi_wrlat_adj(pdram_timing, timing_config); - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[90], 0xff << 16, - tmp << 16); - /* PI_91 PI_TDFI_WRCSLAT_F0:RW:16:8 */ - tmp1 = tmp; - if (tmp1 < 5) { - if (tmp1 == 0) - tmp = 0; - else - tmp = tmp1 - 1; - } else { - tmp = tmp1 - 5; - } - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[91], 0xff << 16, - tmp << 16); - /* PI_95 PI_TDFI_CALVL_CAPTURE_F0:RW:16:10 */ - tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; - if ((20000 % (1000000 / pdram_timing->mhz)) != 0) - tmp1++; - tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[95], 0x3ff << 16, - tmp << 16); - /* PI_95 PI_TDFI_CALVL_CC_F0:RW:0:10 */ - tmp = tmp + 18; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[95], 0x3ff, tmp); - /* PI_102 PI_TMRZ_F0:RW:8:5 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[102], 0x1f << 8, - pdram_timing->tmrz << 8); - /* PI_111 PI_TDFI_CALVL_STROBE_F0:RW:8:4 */ - tmp1 = 2 * 1000 / (1000000 / pdram_timing->mhz); - if ((2 * 1000 % (1000000 / pdram_timing->mhz)) != 0) - tmp1++; - /* pi_tdfi_calvl_strobe=tds_train+5 */ - tmp = tmp1 + 5; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[111], 0xf << 8, - tmp << 8); - /* PI_116 PI_TCKEHDQS_F0:RW:16:6 */ - tmp = 10000 / (1000000 / pdram_timing->mhz); - if ((10000 % (1000000 / pdram_timing->mhz)) != 0) - tmp++; - if (pdram_timing->mhz <= 100) - tmp = tmp + 1; - else - tmp = tmp + 8; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[116], 0x3f << 16, - tmp << 16); - /* PI_125 PI_MR1_DATA_F0_0:RW+:8:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[125], 0xffff << 8, - pdram_timing->mr[1] << 8); - /* PI_133 PI_MR1_DATA_F0_1:RW+:0:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[133], 0xffff, - pdram_timing->mr[1]); - /* PI_140 PI_MR1_DATA_F0_2:RW+:16:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[140], 0xffff << 16, - pdram_timing->mr[1] << 16); - /* PI_148 PI_MR1_DATA_F0_3:RW+:0:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[148], 0xffff, - pdram_timing->mr[1]); - /* PI_126 PI_MR2_DATA_F0_0:RW+:0:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[126], 0xffff, - pdram_timing->mr[2]); - /* PI_133 PI_MR2_DATA_F0_1:RW+:16:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[133], 0xffff << 16, - pdram_timing->mr[2] << 16); - /* PI_141 PI_MR2_DATA_F0_2:RW+:0:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[141], 0xffff, - pdram_timing->mr[2]); - /* PI_148 PI_MR2_DATA_F0_3:RW+:16:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[148], 0xffff << 16, - pdram_timing->mr[2] << 16); - /* PI_156 PI_TFC_F0:RW:0:10 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[156], 0x3ff, - pdram_timing->trfc); - /* PI_158 PI_TWR_F0:RW:24:6 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[158], 0x3f << 24, - pdram_timing->twr << 24); - /* PI_158 PI_TWTR_F0:RW:16:6 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[158], 0x3f << 16, - pdram_timing->twtr << 16); - /* PI_158 PI_TRCD_F0:RW:8:8 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[158], 0xff << 8, - pdram_timing->trcd << 8); - /* PI_158 PI_TRP_F0:RW:0:8 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[158], 0xff, - pdram_timing->trp); - /* PI_157 PI_TRTP_F0:RW:24:8 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[157], 0xff << 24, - pdram_timing->trtp << 24); - /* PI_159 PI_TRAS_MIN_F0:RW:24:8 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[159], 0xff << 24, - pdram_timing->tras_min << 24); - /* PI_159 PI_TRAS_MAX_F0:RW:0:17 */ - tmp = pdram_timing->tras_max * 99 / 100; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[159], 0x1ffff, tmp); - /* PI_160 PI_TMRD_F0:RW:16:6 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[160], 0x3f << 16, - pdram_timing->tmrd << 16); - /*PI_160 PI_TDQSCK_MAX_F0:RW:0:4 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[160], 0xf, - pdram_timing->tdqsck_max); - /* PI_187 PI_TDFI_CTRLUPD_MAX_F0:RW:8:16 */ - tmp = 2 * pdram_timing->trefi; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[187], 0xffff << 8, - tmp << 8); - /* PI_188 PI_TDFI_CTRLUPD_INTERVAL_F0:RW:0:32 */ - tmp = 20 * pdram_timing->trefi; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[188], 0xffffffff, - tmp); - } -} - -static void gen_rk3399_pi_params_f1(struct timing_related_config *timing_config, - struct dram_timing_t *pdram_timing) -{ - uint32_t tmp, tmp1, tmp2; - uint32_t i; - - for (i = 0; i < timing_config->ch_cnt; i++) { - /* PI_04 PI_TDFI_PHYMSTR_MAX_F1:RW:0:32 */ - tmp = 4 * pdram_timing->trefi; - write_32(&rk3399_ddr_pi[i]->denali_pi[4], tmp); - /* PI_05 PI_TDFI_PHYMSTR_RESP_F1:RW:0:16 */ - tmp = 2 * pdram_timing->trefi; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[5], 0xffff, tmp); - /* PI_12 PI_TDFI_PHYUPD_RESP_F1:RW:0:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[12], 0xffff, tmp); - - /* PI_42 PI_TDELAY_RDWR_2_BUS_IDLE_F1:RW:8:8 */ - if (timing_config->dram_type == LPDDR4) - tmp = 2; - else - tmp = 0; - tmp = (pdram_timing->bl / 2) + 4 + - (get_pi_rdlat_adj(pdram_timing) - 2) + tmp + - get_pi_tdfi_phy_rdlat(pdram_timing, timing_config); - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[42], 0xff << 8, - tmp << 8); - /* PI_43 PI_WRLAT_F1:RW:24:5 */ - if (timing_config->dram_type == LPDDR3) { - tmp = get_pi_wrlat(pdram_timing, timing_config); - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[43], - 0x1f << 24, tmp << 24); - } - /* PI_44 PI_ADDITIVE_LAT_F1:RW:0:6 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[44], 0x3f, - PI_ADD_LATENCY); - /* PI_44 PI_CASLAT_LIN_F1:RW:8:7:=0x18 */ - tmp = pdram_timing->cl * 2; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[44], 0x7f << 8, - tmp << 8); - /* PI_47 PI_TREF_F1:RW:16:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[47], 0xffff << 16, - pdram_timing->trefi << 16); - /* PI_47 PI_TRFC_F1:RW:0:10 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[47], 0x3ff, - pdram_timing->trfc); - /* PI_67 PI_TODTL_2CMD_F1:RW:8:8 */ - if (timing_config->dram_type == LPDDR3) { - tmp = get_pi_todtoff_max(pdram_timing, timing_config); - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[67], - 0xff << 8, tmp << 8); - } - /* PI_72 PI_WR_TO_ODTH_F1:RW:24:6 */ - if ((timing_config->dram_type == LPDDR3) - || (timing_config->dram_type == LPDDR4)) { - tmp1 = get_pi_wrlat(pdram_timing, timing_config); - tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); - if (tmp1 > tmp2) - tmp = tmp1 - tmp2; - else - tmp = 0; - } else if (timing_config->dram_type == DDR3) { - tmp = 0; - } - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[72], 0x3f << 24, - tmp << 24); - /* PI_73 PI_RD_TO_ODTH_F1:RW:16:6 */ - if ((timing_config->dram_type == LPDDR3) - || (timing_config->dram_type == LPDDR4)) { - /* min_rl_preamble= cl+TDQSCK_MIN-1 */ - tmp1 = - pdram_timing->cl + get_pi_todtoff_min(pdram_timing, - timing_config) - - 1; - /* todtoff_max */ - tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); - if (tmp1 > tmp2) - tmp = tmp1 - tmp2; - else - tmp = 0; - } else if (timing_config->dram_type == DDR3) { - tmp = pdram_timing->cl - pdram_timing->cwl; - } - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[73], 0x3f << 16, - tmp << 16); - /*P I_89 PI_RDLAT_ADJ_F1:RW:24:8 */ - tmp = get_pi_rdlat_adj(pdram_timing); - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[89], 0xff << 24, - tmp << 24); - /* PI_90 PI_WRLAT_ADJ_F1:RW:24:8 */ - tmp = get_pi_wrlat_adj(pdram_timing, timing_config); - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[90], 0xff << 24, - tmp << 24); - /* PI_91 PI_TDFI_WRCSLAT_F1:RW:24:8 */ - tmp1 = tmp; - if (tmp1 < 5) { - if (tmp1 == 0) - tmp = 0; - else - tmp = tmp1 - 1; - } else { - tmp = tmp1 - 5; - } - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[91], 0xff << 24, - tmp << 24); - /*PI_96 PI_TDFI_CALVL_CAPTURE_F1:RW:16:10 */ - /* tadr=20ns */ - tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; - if ((20000 % (1000000 / pdram_timing->mhz)) != 0) - tmp1++; - tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[96], 0x3ff << 16, - tmp << 16); - /* PI_96 PI_TDFI_CALVL_CC_F1:RW:0:10 */ - tmp = tmp + 18; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[96], 0x3ff, tmp); - /*PI_103 PI_TMRZ_F1:RW:0:5 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[103], 0x1f, - pdram_timing->tmrz); - /*PI_111 PI_TDFI_CALVL_STROBE_F1:RW:16:4 */ - /* tds_train=ceil(2/ns) */ - tmp1 = 2 * 1000 / (1000000 / pdram_timing->mhz); - if ((2 * 1000 % (1000000 / pdram_timing->mhz)) != 0) - tmp1++; - /* pi_tdfi_calvl_strobe=tds_train+5 */ - tmp = tmp1 + 5; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[111], 0xf << 16, - tmp << 16); - /* PI_116 PI_TCKEHDQS_F1:RW:24:6 */ - tmp = 10000 / (1000000 / pdram_timing->mhz); - if ((10000 % (1000000 / pdram_timing->mhz)) != 0) - tmp++; - if (pdram_timing->mhz <= 100) - tmp = tmp + 1; - else - tmp = tmp + 8; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[116], 0x3f << 24, - tmp << 24); - /* PI_128 PI_MR1_DATA_F1_0:RW+:0:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[128], 0xffff, - pdram_timing->mr[1]); - /* PI_135 PI_MR1_DATA_F1_1:RW+:8:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[135], 0xffff << 8, - pdram_timing->mr[1] << 8); - /* PI_143 PI_MR1_DATA_F1_2:RW+:0:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[143], 0xffff, - pdram_timing->mr[1]); - /* PI_150 PI_MR1_DATA_F1_3:RW+:8:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[150], 0xffff << 8, - pdram_timing->mr[1] << 8); - /* PI_128 PI_MR2_DATA_F1_0:RW+:16:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[128], 0xffff << 16, - pdram_timing->mr[2] << 16); - /* PI_136 PI_MR2_DATA_F1_1:RW+:0:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[136], 0xffff, - pdram_timing->mr[2]); - /* PI_143 PI_MR2_DATA_F1_2:RW+:16:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[143], 0xffff << 16, - pdram_timing->mr[2] << 16); - /* PI_151 PI_MR2_DATA_F1_3:RW+:0:16 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[151], 0xffff, - pdram_timing->mr[2]); - /* PI_156 PI_TFC_F1:RW:16:10 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[156], 0x3ff << 16, - pdram_timing->trfc << 16); - /* PI_162 PI_TWR_F1:RW:8:6 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[162], 0x3f << 8, - pdram_timing->twr << 8); - /* PI_162 PI_TWTR_F1:RW:0:6 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[162], 0x3f, - pdram_timing->twtr); - /* PI_161 PI_TRCD_F1:RW:24:8 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[161], 0xff << 24, - pdram_timing->trcd << 24); - /* PI_161 PI_TRP_F1:RW:16:8 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[161], 0xff << 16, - pdram_timing->trp << 16); - /* PI_161 PI_TRTP_F1:RW:8:8 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[161], 0xff << 8, - pdram_timing->trtp << 8); - /* PI_163 PI_TRAS_MIN_F1:RW:24:8 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[163], 0xff << 24, - pdram_timing->tras_min << 24); - /* PI_163 PI_TRAS_MAX_F1:RW:0:17 */ - tmp = pdram_timing->tras_max * 99 / 100; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[163], 0x1ffff, tmp); - /* PI_164 PI_TMRD_F1:RW:16:6 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[164], 0x3f << 16, - pdram_timing->tmrd << 16); - /* PI_164 PI_TDQSCK_MAX_F1:RW:0:4 */ - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[164], 0xf, - pdram_timing->tdqsck_max); - /* PI_189 PI_TDFI_CTRLUPD_MAX_F1:RW:0:16 */ - tmp = 2 * pdram_timing->trefi; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[189], 0xffff, tmp); - /* PI_190 PI_TDFI_CTRLUPD_INTERVAL_F1:RW:0:32 */ - tmp = 20 * pdram_timing->trefi; - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[190], 0xffffffff, - tmp); - } -} - -static void gen_rk3399_pi_params(struct timing_related_config *timing_config, - struct dram_timing_t *pdram_timing, - uint32_t fn) -{ - if (fn == 0) - 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 - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[80], 3 << 24, - 2 << 24); -#endif - -#if EN_CA_TRAINING - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[100], 3 << 8, - 2 << 8); -#endif - -#if EN_WRITE_LEVELING - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[60], 3 << 8, - 2 << 8); -#endif - -#if EN_READ_LEVELING - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[80], 3 << 16, - 2 << 16); -#endif - -#if EN_WDQ_LEVELING - clrsetbits_32(&rk3399_ddr_pi[i]->denali_pi[124], 3 << 16, - 2 << 16); -#endif - } -#endif -} - -static void gen_rk3399_set_odt(uint32_t odt_en) -{ - uint32_t drv_odt_val; - uint32_t i; - - for (i = 0; i < rk3399_dram_status.timing_config.ch_cnt; i++) { - drv_odt_val = (odt_en | (0 << 1) | (0 << 2)) << 16; - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[5], - 0x7 << 16, drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[133], - 0x7 << 16, drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[261], - 0x7 << 16, drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[389], - 0x7 << 16, drv_odt_val); - drv_odt_val = (odt_en | (0 << 1) | (0 << 2)) << 24; - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[6], - 0x7 << 24, drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[134], - 0x7 << 24, drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[262], - 0x7 << 24, drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[390], - 0x7 << 24, drv_odt_val); - } -} - -static void gen_rk3399_set_ds_odt(struct timing_related_config *timing_config, - struct drv_odt_lp_config *drv_config) -{ - uint32_t i, drv_odt_val; - - 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 */ - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[6], 0xffffff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[134], 0xffffff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[262], 0xffffff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[390], 0xffffff, - drv_odt_val); - /* DQS drv odt set */ - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[7], 0xffffff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[135], 0xffffff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[263], 0xffffff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[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); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[544], 0xff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[672], 0xff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[800], 0xff, - drv_odt_val); - - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[928], 0xff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[937], 0xff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[935], 0xff, - drv_odt_val); - - drv_odt_val = drv_config->phy_side_ck_cs_drv | - (drv_config->phy_side_ck_cs_drv << 4); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[929], 0xff, - drv_odt_val); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[939], 0xff, - drv_odt_val); - } -} - -static void gen_rk3399_phy_params(struct timing_related_config *timing_config, - struct drv_odt_lp_config *drv_config, - struct dram_timing_t *pdram_timing, - uint32_t fn) -{ - uint32_t tmp, i, div, j; - uint32_t mem_delay_ps, pad_delay_ps, total_delay_ps, delay_frac_ps; - uint32_t trpre_min_ps, gate_delay_ps, gate_delay_frac_ps; - uint32_t ie_enable, tsel_enable, cas_lat, rddata_en_ie_dly, tsel_adder; - uint32_t extra_adder, delta, hs_offset; - - for (i = 0; i < timing_config->ch_cnt; i++) { - - pad_delay_ps = PI_PAD_DELAY_PS_VALUE; - ie_enable = PI_IE_ENABLE_VALUE; - tsel_enable = PI_TSEL_ENABLE_VALUE; - - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[896], - (0x3 << 8) | 1, fn << 8); - - /* PHY_LOW_FREQ_SEL */ - /* DENALI_PHY_913 1bit offset_0 */ - if (timing_config->freq > 400) - clrbits_32(&rk3399_ddr_publ[i]->denali_phy[913], 1); - else - setbits_32(&rk3399_ddr_publ[i]->denali_phy[913], 1); - - /* PHY_RPTR_UPDATE_x */ - /* DENALI_PHY_87/215/343/471 4bit offset_16 */ - tmp = 2500 / (1000000 / pdram_timing->mhz) + 3; - if ((2500 % (1000000 / pdram_timing->mhz)) != 0) - tmp++; - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[87], 0xf << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[215], 0xf << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[343], 0xf << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[471], 0xf << 16, - tmp << 16); - - /* PHY_PLL_CTRL */ - /* 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); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[911], 0x1fff, - tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[919], 0x1fff, - tmp); - - /* PHY_PLL_CTRL_CA */ - /* 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); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[911], - 0x1fff << 16, tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[919], - 0x1fff << 16, tmp << 16); - - /* PHY_TCKSRE_WAIT */ - /* DENALI_PHY_922 4bits offset_24 */ - if (pdram_timing->mhz <= 400) - tmp = 1; - else if (pdram_timing->mhz <= 800) - tmp = 3; - else if (pdram_timing->mhz <= 1000) - tmp = 4; - else - tmp = 5; - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[922], 0xf << 24, - tmp << 24); - /* PHY_CAL_CLK_SELECT_0:RW8:3 */ - div = pdram_timing->mhz / (2 * 20); - for (j = 2, tmp = 1; j <= 128; j <<= 1, tmp++) { - if (div < j) - break; - } - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[947], 0x7 << 8, - tmp << 8); - setbits_32(&rk3399_ddr_publ[i]->denali_phy[927], (1 << 22)); - - if (timing_config->dram_type == DDR3) { - mem_delay_ps = 0; - trpre_min_ps = 1000; - } else if (timing_config->dram_type == LPDDR4) { - mem_delay_ps = 1500; - trpre_min_ps = 900; - } else if (timing_config->dram_type == LPDDR3) { - mem_delay_ps = 2500; - trpre_min_ps = 900; - } else { - ERROR("gen_rk3399_phy_params:dramtype unsupport\n"); - return; - } - total_delay_ps = mem_delay_ps + pad_delay_ps; - delay_frac_ps = - 1000 * total_delay_ps / (1000000 / pdram_timing->mhz); - gate_delay_ps = delay_frac_ps + 1000 - (trpre_min_ps / 2); - gate_delay_frac_ps = - gate_delay_ps - gate_delay_ps / 1000 * 1000; - tmp = gate_delay_frac_ps * 0x200 / 1000; - /* PHY_RDDQS_GATE_BYPASS_SLAVE_DELAY */ - /* DENALI_PHY_2/130/258/386 10bits offset_0 */ - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[2], 0x2ff, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[130], 0x2ff, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[258], 0x2ff, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[386], 0x2ff, tmp); - /* PHY_RDDQS_GATE_SLAVE_DELAY */ - /* DENALI_PHY_77/205/333/461 10bits offset_16 */ - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[77], 0x2ff << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[205], 0x2ff << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[333], 0x2ff << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[461], 0x2ff << 16, - tmp << 16); - - tmp = gate_delay_ps / 1000; - /* PHY_LP4_BOOT_RDDQS_LATENCY_ADJUST */ - /* DENALI_PHY_10/138/266/394 4bit offset_0 */ - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[10], 0xf, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[138], 0xf, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[266], 0xf, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[394], 0xf, tmp); - /* PHY_RDDQS_LATENCY_ADJUST */ - /* DENALI_PHY_78/206/334/462 4bits offset_0 */ - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[78], 0xf, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[206], 0xf, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[334], 0xf, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[462], 0xf, tmp); - /* PHY_GTLVL_LAT_ADJ_START */ - /* DENALI_PHY_80/208/336/464 4bits offset_16 */ - tmp = delay_frac_ps / 1000; - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[80], 0xf << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[208], 0xf << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[336], 0xf << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[464], 0xf << 16, - tmp << 16); - - cas_lat = pdram_timing->cl + PI_ADD_LATENCY; - rddata_en_ie_dly = ie_enable / (1000000 / pdram_timing->mhz); - if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) - rddata_en_ie_dly++; - rddata_en_ie_dly = rddata_en_ie_dly - 1; - tsel_adder = tsel_enable / (1000000 / pdram_timing->mhz); - if ((tsel_enable % (1000000 / pdram_timing->mhz)) != 0) - tsel_adder++; - if (rddata_en_ie_dly > tsel_adder) - extra_adder = rddata_en_ie_dly - tsel_adder; - else - extra_adder = 0; - delta = cas_lat - rddata_en_ie_dly; - if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK) - hs_offset = 2; - else - hs_offset = 1; - if (rddata_en_ie_dly > (cas_lat - 1 - hs_offset)) { - tmp = 0; - } else { - if ((delta == 2) || (delta == 1)) - tmp = rddata_en_ie_dly - 0 - extra_adder; - else - tmp = extra_adder; - } - /* PHY_LP4_BOOT_RDDATA_EN_TSEL_DLY */ - /* DENALI_PHY_9/137/265/393 4bit offset_16 */ - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[9], 0xf << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[137], 0xf << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[265], 0xf << 16, - tmp << 16); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[393], 0xf << 16, - tmp << 16); - /* PHY_RDDATA_EN_TSEL_DLY */ - /* DENALI_PHY_86/214/342/470 4bit offset_0 */ - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[86], 0xf, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[214], 0xf, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[342], 0xf, tmp); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[470], 0xf, tmp); - - if (tsel_adder > rddata_en_ie_dly) - extra_adder = tsel_adder - rddata_en_ie_dly; - else - extra_adder = 0; - if (rddata_en_ie_dly > (cas_lat - 1 - hs_offset)) - tmp = tsel_adder; - else - tmp = rddata_en_ie_dly - 0 + extra_adder; - /* PHY_LP4_BOOT_RDDATA_EN_DLY */ - /* DENALI_PHY_9/137/265/393 4bit offset_8 */ - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[9], 0xf << 8, - tmp << 8); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[137], 0xf << 8, - tmp << 8); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[265], 0xf << 8, - tmp << 8); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[393], 0xf << 8, - tmp << 8); - /* PHY_RDDATA_EN_DLY */ - /* DENALI_PHY_85/213/341/469 4bit offset_24 */ - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[85], 0xf << 24, - tmp << 24); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[213], 0xf << 24, - tmp << 24); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[341], 0xf << 24, - tmp << 24); - clrsetbits_32(&rk3399_ddr_publ[i]->denali_phy[469], 0xf << 24, - tmp << 24); - - if (pdram_timing->mhz <= ENPER_CS_TRAINING_FREQ) { - - /* - * Note:Per-CS Training is not compatible at speeds - * under 533 MHz. If the PHY is running at a speed - * less than 533MHz, all phy_per_cs_training_en_X - * parameters must be cleared to 0. - */ - - /*DENALI_PHY_84/212/340/468 1bit offset_16 */ - clrbits_32(&rk3399_ddr_publ[i]->denali_phy[84], - 0x1 << 16); - clrbits_32(&rk3399_ddr_publ[i]->denali_phy[212], - 0x1 << 16); - clrbits_32(&rk3399_ddr_publ[i]->denali_phy[340], - 0x1 << 16); - clrbits_32(&rk3399_ddr_publ[i]->denali_phy[468], - 0x1 << 16); - } else { - setbits_32(&rk3399_ddr_publ[i]->denali_phy[84], - 0x1 << 16); - setbits_32(&rk3399_ddr_publ[i]->denali_phy[212], - 0x1 << 16); - setbits_32(&rk3399_ddr_publ[i]->denali_phy[340], - 0x1 << 16); - setbits_32(&rk3399_ddr_publ[i]->denali_phy[468], - 0x1 << 16); - } - } -} - -static int to_get_clk_index(unsigned int mhz) -{ - int pll_cnt, i; - - pll_cnt = ARRAY_SIZE(dpll_rates_table); - - /* Assumming rate_table is in descending order */ - for (i = 0; i < pll_cnt; i++) { - if (mhz >= dpll_rates_table[i].mhz) - break; - } - - /* if mhz lower than lowest frequency in table, use lowest frequency */ - if (i == pll_cnt) - i = pll_cnt - 1; - - 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; - write_32(DCF_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(fbdiv)); - 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; - - refdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) & 0x3f; - fbdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 0)) & 0xfff; - postdiv1 = - (mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) >> 8) & 0x7; - postdiv2 = - (mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) >> 12) & 0x7; - - return (24 / refdiv * fbdiv / postdiv1 / postdiv2) * 1000 * 1000; -} - -/* - * return: bit12: channel 1, external self-refresh - * bit11: channel 1, stdby_mode - * bit10: channel 1, self-refresh with controller and memory clock gate - * bit9: channel 1, self-refresh - * bit8: channel 1, power-down - * - * bit4: channel 1, external self-refresh - * bit3: channel 0, stdby_mode - * bit2: channel 0, self-refresh with controller and memory clock gate - * bit1: channel 0, self-refresh - * bit0: channel 0, power-down - */ -uint32_t exit_low_power(void) -{ - struct rk3399_ddr_pctl_regs *ddr_pctl_regs; - uint32_t low_power = 0; - uint32_t channel_mask; - uint32_t channel; - uint32_t tmp; - - channel_mask = (read_32(PMUGRF_BASE + PMUGRF_OSREG(2)) >> 28) & 0x3; - for (channel = 0; channel < 2; channel++) { - ddr_pctl_regs = rk3399_ddr_pctl[channel]; - if (!(channel_mask & (1 << channel))) + if (!(SYS_REG_DEC_CHINFO(os_reg2_val, i))) continue; - /* exit stdby mode */ - write_32(&rk3399_ddr_cic->cic_ctrl1, - (1 << (channel + 16)) | (0 << channel)); - /* exit external self-refresh */ - tmp = channel ? 12 : 8; - low_power |= ((read_32(PMU_BASE + PMU_SFT_CON) >> tmp) & 0x1) - << (4 + 8 * channel); - clrbits_32(PMU_BASE + PMU_SFT_CON, 1 << tmp); - while (!(read_32(PMU_BASE + PMU_DDR_SREF_ST) & - (1 << channel))) - ; - /* exit auto low-power */ - clrbits_32(&ddr_pctl_regs->denali_ctl[101], 0x7); - /* lp_cmd to exit */ - if (((read_32(&ddr_pctl_regs->denali_ctl[100]) >> 24) & - 0x7f) != 0x40) { - while (read_32(&ddr_pctl_regs->denali_ctl[200]) & 0x1) - ; - clrsetbits_32(&ddr_pctl_regs->denali_ctl[93], - 0xff << 24, 0x69 << 24); - while (((read_32(&ddr_pctl_regs->denali_ctl[100]) >> - 24) & 0x7f) != 0x40) - ; - } - } - return low_power; -} + ch->rank = SYS_REG_DEC_RANK(os_reg2_val, i); + ch->col = SYS_REG_DEC_COL(os_reg2_val, i); + ch->bk = SYS_REG_DEC_BK(os_reg2_val, i); + ch->bw = SYS_REG_DEC_BW(os_reg2_val, i); + ch->dbw = SYS_REG_DEC_DBW(os_reg2_val, i); + ch->row_3_4 = SYS_REG_DEC_ROW_3_4(os_reg2_val, i); + ch->cs0_row = SYS_REG_DEC_CS0_ROW(os_reg2_val, i); + ch->cs1_row = SYS_REG_DEC_CS1_ROW(os_reg2_val, i); + ch->ddrconfig = mmio_read_32(MSCH_BASE(i) + MSCH_DEVICECONF); -void resume_low_power(uint32_t low_power) -{ - struct rk3399_ddr_pctl_regs *ddr_pctl_regs; - uint32_t channel_mask; - uint32_t channel; - uint32_t tmp; - uint32_t val; - - channel_mask = (read_32(PMUGRF_BASE + PMUGRF_OSREG(2)) >> 28) & 0x3; - for (channel = 0; channel < 2; channel++) { - ddr_pctl_regs = rk3399_ddr_pctl[channel]; - if (!(channel_mask & (1 << channel))) - continue; - - /* resume external self-refresh */ - tmp = channel ? 12 : 8; - val = (low_power >> (4 + 8 * channel)) & 0x1; - setbits_32(PMU_BASE + PMU_SFT_CON, val << tmp); - /* resume auto low-power */ - val = (low_power >> (8 * channel)) & 0x7; - setbits_32(&ddr_pctl_regs->denali_ctl[101], val); - /* resume stdby mode */ - val = (low_power >> (3 + 8 * channel)) & 0x1; - write_32(&rk3399_ddr_cic->cic_ctrl1, - (1 << (channel + 16)) | (val << channel)); + noc->ddrtiminga0.d32 = mmio_read_32(MSCH_BASE(i) + + MSCH_DDRTIMINGA0); + noc->ddrtimingb0.d32 = mmio_read_32(MSCH_BASE(i) + + MSCH_DDRTIMINGB0); + noc->ddrtimingc0.d32 = mmio_read_32(MSCH_BASE(i) + + MSCH_DDRTIMINGC0); + noc->devtodev0.d32 = mmio_read_32(MSCH_BASE(i) + + MSCH_DEVTODEV0); + noc->ddrmode.d32 = mmio_read_32(MSCH_BASE(i) + MSCH_DDRMODE); + noc->agingx0 = mmio_read_32(MSCH_BASE(i) + MSCH_AGINGX0); } } - -static void wait_dcf_done(void) -{ - while ((read_32(DCF_BASE + DCF_DCF_ISR) & (DCF_DONE)) == 0) - continue; -} - -void clr_dcf_irq(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 */ - write_32(DCF_BASE + DCF_DCF_ADDR, dcf_addr); - /* wait dcf done */ - while (read_32(DCF_BASE + DCF_DCF_CTRL) & 1) - continue; - /* clear dcf irq status */ - write_32(DCF_BASE + DCF_DCF_ISR, DCF_TIMEOUT | DCF_ERR | DCF_DONE); - /* DCF start */ - 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 */ - write_32(SGRF_BASE + 0xe01c, ((0x3 << 0) << 16) | (0 << 0)); - write_32(DCF_BASE + DCF_DCF_TOSET, 0x80000000); -} - -static void dcf_start(uint32_t freq, uint32_t index) -{ - write_32(CRU_BASE + CRU_SOFTRST_CON(10), (0x1 << (1 + 16)) | (1 << 1)); - write_32(CRU_BASE + CRU_SOFTRST_CON(11), (0x1 << (0 + 16)) | (1 << 0)); - write_32(DCF_PARAM_ADDR + PARAM_FREQ_SELECT, index << 4); - - write_32(DCF_PARAM_ADDR + PARAM_DRAM_FREQ, freq); - - rkclk_prepare_pll_timing(freq); - udelay(10); - write_32(CRU_BASE + CRU_SOFTRST_CON(10), (0x1 << (1 + 16)) | (0 << 1)); - 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 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; - else - tmp1 = (3 << 16) | (0x7 << 8) | 7; - - *low_power = 0; - - for (i = 0; i < ch_cnt; i++) { - write_32(&rk3399_ddr_pctl[i]->denali_ctl[102], tmp); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[103], 0xffff, - (lp_config->sr_mc_gate_idle << 8) | - lp_config->sr_idle); - clrsetbits_32(&rk3399_ddr_pctl[i]->denali_ctl[101], - 0x70f0f, tmp1); - *low_power |= (7 << (8 * i)); - } - - /* standby idle */ - write_32(&rk3399_ddr_cic->cic_idle_th, lp_config->standby_idle); - write_32(&rk3399_ddr_cic->cic_cg_wait_th, 0x640008); - - if (ch_cnt == 2) { - write_32(GRF_BASE + GRF_DDRC1_CON1, - (((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; - } - write_32(&rk3399_ddr_cic->cic_ctrl1, tmp); - } - - 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; - } - write_32(&rk3399_ddr_cic->cic_ctrl1, tmp); -} - - -static void dram_related_init(struct ddr_dts_config_timing *dts_timing) -{ - uint32_t trefi0, trefi1; - uint32_t i; - struct rk3399_sdram_config sdram_config; - - dcf_code_init(); - - /* get sdram config for os reg */ - sdram_config_init(&sdram_config); - drv_odt_lp_cfg_init(sdram_config.dramtype, dts_timing, - &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); - - trefi0 = ((read_32(&rk3399_ddr_pctl[0]->denali_ctl[48]) >> - 16) & 0xffff) + 8; - trefi1 = ((read_32(&rk3399_ddr_pctl[0]->denali_ctl[49]) >> - 16) & 0xffff) + 8; - - rk3399_dram_status.index_freq[0] = trefi0 * 10 / 39; - rk3399_dram_status.index_freq[1] = trefi1 * 10 / 39; - rk3399_dram_status.current_index = - (read_32(&rk3399_ddr_pctl[0]->denali_ctl[111]) - >> 16) & 0x3; - if (rk3399_dram_status.timing_config.dram_type == DDR3) { - 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; - - /* disable all training by ctl and pi */ - for (i = 0; i < rk3399_dram_status.timing_config.ch_cnt; i++) { - clrbits_32(&rk3399_ddr_pctl[i]->denali_ctl[70], (1 << 24) | - (1 << 16) | (1 << 8) | 1); - clrbits_32(&rk3399_ddr_pctl[i]->denali_ctl[71], 1); - - clrbits_32(&rk3399_ddr_pi[i]->denali_pi[60], 0x3 << 8); - clrbits_32(&rk3399_ddr_pi[i]->denali_pi[80], (0x3 << 24) | - (0x3 << 16)); - clrbits_32(&rk3399_ddr_pi[i]->denali_pi[100], 0x3 << 8); - clrbits_32(&rk3399_ddr_pi[i]->denali_pi[124], 0x3 << 16); - } - - /* 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); -} - -static uint32_t prepare_ddr_timing(uint32_t mhz) -{ - uint32_t index; - struct dram_timing_t dram_timing; - - rk3399_dram_status.timing_config.freq = mhz; - - if (mhz < rk3399_dram_status.drv_odt_lp_cfg.ddr3_dll_dis_freq) - 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; - 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 - * target freq. - */ - dram_get_parameter(&rk3399_dram_status.timing_config, &dram_timing); - gen_rk3399_ctl_params(&rk3399_dram_status.timing_config, - &dram_timing, index); - gen_rk3399_pi_params(&rk3399_dram_status.timing_config, - &dram_timing, index); - gen_rk3399_phy_params(&rk3399_dram_status.timing_config, - &rk3399_dram_status.drv_odt_lp_cfg, - &dram_timing, index); - rk3399_dram_status.index_freq[index] = mhz; - - -out: - return index; -} - -void print_dram_status_info(void) -{ - uint32_t *p; - uint32_t i; - - p = (uint32_t *) &rk3399_dram_status.timing_config; - INFO("rk3399_dram_status.timing_config:\n"); - for (i = 0; i < sizeof(struct timing_related_config) / 4; i++) - tf_printf("%u\n", p[i]); - p = (uint32_t *) &rk3399_dram_status.drv_odt_lp_cfg; - INFO("rk3399_dram_status.drv_odt_lp_cfg:\n"); - for (i = 0; i < sizeof(struct drv_odt_lp_config) / 4; i++) - tf_printf("%u\n", p[i]); -} - -uint32_t ddr_set_rate(uint32_t hz) -{ - uint32_t low_power, index; - uint32_t mhz = hz / (1000 * 1000); - - if (mhz == - rk3399_dram_status.index_freq[rk3399_dram_status.current_index]) - goto out; - - 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) - goto out; - - dcf_start(mhz, index); - wait_dcf_done(); - 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; - - resume_low_power(low_power); -out: - return mhz; -} - -uint32_t ddr_round_rate(uint32_t hz) -{ - int index; - uint32_t mhz = hz / (1000 * 1000); - - index = to_get_clk_index(mhz); - - return dpll_rates_table[index].mhz * 1000 * 1000; -} - -uint32_t dts_timing_receive(uint32_t timing, uint32_t index) -{ - 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; - } - - /* receive all parameter */ - if (receive_nums == (sizeof(dts_parameter) / sizeof(uint32_t) - 1)) { - dts_parameter.available = 1; - receive_nums = 0; - } - - return index; -} - -void ddr_init(void) -{ - dram_related_init(&dts_parameter); -} diff --git a/plat/rockchip/rk3399/drivers/dram/dram.h b/plat/rockchip/rk3399/drivers/dram/dram.h index 4f9907049..44dfbbdca 100644 --- a/plat/rockchip/rk3399/drivers/dram/dram.h +++ b/plat/rockchip/rk3399/drivers/dram/dram.h @@ -28,49 +28,131 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __SOC_ROCKCHIP_RK3399_SDRAM_H__ -#define __SOC_ROCKCHIP_RK3399_SDRAM_H__ +#ifndef __SOC_ROCKCHIP_RK3399_DRAM_H__ +#define __SOC_ROCKCHIP_RK3399_DRAM_H__ +#include +#include -struct rk3399_ddr_cic_regs { - uint32_t cic_ctrl0; - uint32_t cic_ctrl1; - uint32_t cic_idle_th; - uint32_t cic_cg_wait_th; - uint32_t cic_status0; - uint32_t cic_status1; - uint32_t cic_ctrl2; - uint32_t cic_ctrl3; - uint32_t cic_ctrl4; -}; +#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) +#define START 1 /* DENALI_CTL_68 */ #define PWRUP_SREFRESH_EXIT (1 << 16) /* DENALI_CTL_274 */ -#define MEM_RST_VALID (1) +#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, + LPDDR3 = 6, + LPDDR4 = 7, + UNUSED = 0xff +}; struct rk3399_ddr_pctl_regs { - uint32_t denali_ctl[332]; + uint32_t denali_ctl[CTL_REG_NUM]; }; struct rk3399_ddr_publ_regs { - uint32_t denali_phy[959]; + uint32_t denali_phy[PHY_REG_NUM]; }; -#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) - struct rk3399_ddr_pi_regs { - uint32_t denali_pi[200]; + uint32_t denali_pi[PI_REG_NUM]; }; union noc_ddrtiminga0 { uint32_t d32; @@ -138,21 +220,6 @@ union noc_ddrmode { } b; }; -struct rk3399_msch_regs { - uint32_t coreid; - uint32_t revisionid; - uint32_t ddrconf; - uint32_t ddrsize; - union noc_ddrtiminga0 ddrtiminga0; - union noc_ddrtimingb0 ddrtimingb0; - union noc_ddrtimingc0 ddrtimingc0; - union noc_devtodev0 devtodev0; - uint32_t reserved0[(0x110-0x20)/4]; - union noc_ddrmode ddrmode; - uint32_t reserved1[(0x1000-0x114)/4]; - uint32_t agingx0; -}; - struct rk3399_msch_timings { union noc_ddrtiminga0 ddrtiminga0; union noc_ddrtimingb0 ddrtimingb0; @@ -161,7 +228,7 @@ struct rk3399_msch_timings { union noc_ddrmode ddrmode; uint32_t agingx0; }; -#if 1 + struct rk3399_sdram_channel { unsigned char rank; /* col = 0, means this channel is invalid */ @@ -193,137 +260,9 @@ struct rk3399_sdram_params { struct rk3399_ddr_pi_regs pi_regs; struct rk3399_ddr_publ_regs phy_regs; }; -#endif -struct rk3399_sdram_channel_config { - uint32_t bus_width; - uint32_t cs_cnt; - uint32_t cs0_row; - uint32_t cs1_row; - uint32_t bank; - uint32_t col; - uint32_t each_die_bus_width; - uint32_t each_die_6gb_or_12gb; -}; - -struct rk3399_sdram_config { - struct rk3399_sdram_channel_config ch[2]; - uint32_t dramtype; - uint32_t channal_num; -}; - -struct rk3399_sdram_default_config { - unsigned char bl; - /* 1:auto precharge, 0:never auto precharge */ - unsigned char ap; - /* dram driver strength */ - unsigned char dramds; - /* dram ODT, if odt=0, this parameter invalid */ - unsigned char dramodt; - /* ca ODT, if odt=0, this parameter invalid - * only used by LPDDR4 - */ - unsigned char caodt; - unsigned char burst_ref_cnt; - /* zqcs period, unit(s) */ - 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 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; -}; - -#define KHz (1000) -#define MHz (1000*KHz) -#define GHz (1000*MHz) - -#define PI_CA_TRAINING (1 << 0) -#define PI_WRITE_LEVELING (1 << 1) -#define PI_READ_GATE_TRAINING (1 << 2) -#define PI_READ_LEVELING (1 << 3) -#define PI_WDQ_LEVELING (1 << 4) -#define PI_FULL_TARINING (0xff) - -#define READ_CH_CNT(val) (1+((val>>12)&0x1)) -#define READ_CH_INFO(val) ((val>>28)&0x3) -/* row_3_4:0=normal, 1=6Gb or 12Gb */ -#define READ_CH_ROW_INFO(val, ch) ((val>>(30+(ch)))&0x1) - -#define READ_DRAMTYPE_INFO(val) ((val>>13)&0x7) -#define READ_CS_INFO(val, ch) ((((val)>>(11+(ch)*16))&0x1)+1) -#define READ_BW_INFO(val, ch) (2>>(((val)>>(2+(ch)*16))&0x3)) -#define READ_COL_INFO(val, ch) (9+(((val)>>(9+(ch)*16))&0x3)) -#define READ_BK_INFO(val, ch) (3-(((val)>>(8+(ch)*16))&0x1)) -#define READ_CS0_ROW_INFO(val, ch) (13+(((val)>>(6+(ch)*16))&0x3)) -#define READ_CS1_ROW_INFO(val, ch) (13+(((val)>>(4+(ch)*16))&0x3)) -#define READ_DIE_BW_INFO(val, ch) (2>>((val>>((ch)*16))&0x3)) - -#define __sramdata __attribute__((section(".sram.data"))) -#define __sramconst __attribute__((section(".sram.rodata"))) -#define __sramlocalfunc __attribute__((section(".sram.text"))) -#define __sramfunc __attribute__((section(".sram.text"))) \ - __attribute__((noinline)) - - -#define DDR_SAVE_SP(save_sp) (save_sp = ddr_save_sp(((uint32_t)\ - (SRAM_CODE_BASE + 0x2000) & (~7)))) - -#define DDR_RESTORE_SP(save_sp) ddr_save_sp(save_sp) - -void ddr_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); + +extern __sramdata struct rk3399_sdram_params sdram_config; + +void dram_init(void); + #endif diff --git a/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c index b015db740..fbf1d3978 100644 --- a/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c +++ b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c @@ -30,6 +30,7 @@ #include #include +#include #include "dram_spec_timing.h" static const uint8_t ddr3_cl_cwl[][7] = { diff --git a/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h index 2008332f7..662aeab40 100644 --- a/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h +++ b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h @@ -32,14 +32,6 @@ #define _DRAM_SPEC_TIMING_HEAD_ #include -enum { - DDR3 = 3, - LPDDR2 = 5, - LPDDR3 = 6, - LPDDR4 = 7, - UNUSED = 0xFF -}; - enum ddr3_speed_rate { /* 5-5-5 */ DDR3_800D = 0, diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.c b/plat/rockchip/rk3399/drivers/dram/suspend.c new file mode 100644 index 000000000..f408d676c --- /dev/null +++ b/plat/rockchip/rk3399/drivers/dram/suspend.c @@ -0,0 +1,758 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define PMUGRF_OS_REG0 0x300 +#define PMUGRF_OS_REG1 0x304 +#define PMUGRF_OS_REG2 0x308 +#define PMUGRF_OS_REG3 0x30c + +#define CRU_SFTRST_DDR_CTRL(ch, n) ((0x1 << (8 + 16 + (ch) * 4)) | \ + ((n) << (8 + (ch) * 4))) +#define CRU_SFTRST_DDR_PHY(ch, n) ((0x1 << (9 + 16 + (ch) * 4)) | \ + ((n) << (9 + (ch) * 4))) + +#define FBDIV_ENC(n) ((n) << 16) +#define FBDIV_DEC(n) (((n) >> 16) & 0xfff) +#define POSTDIV2_ENC(n) ((n) << 12) +#define POSTDIV2_DEC(n) (((n) >> 12) & 0x7) +#define POSTDIV1_ENC(n) ((n) << 8) +#define POSTDIV1_DEC(n) (((n) >> 8) & 0x7) +#define REFDIV_ENC(n) (n) +#define REFDIV_DEC(n) ((n) & 0x3f) + +/* PMU CRU */ +#define PMUCRU_RSTNHOLD_CON0 0x120 +#define PMUCRU_RSTNHOLD_CON1 0x124 + +#define PRESET_GPIO0_HOLD(n) (((n) << 7) | WMSK_BIT(7)) +#define PRESET_GPIO1_HOLD(n) (((n) << 8) | WMSK_BIT(8)) + +#define SYS_COUNTER_FREQ_IN_MHZ (SYS_COUNTER_FREQ_IN_TICKS / 1000000) + +/* + * Copy @num registers from @src to @dst + */ +__sramfunc void sram_regcpy(uintptr_t dst, uintptr_t src, uint32_t num) +{ + while (num--) { + mmio_write_32(dst, mmio_read_32(src)); + dst += sizeof(uint32_t); + src += sizeof(uint32_t); + } +} + +static __sramfunc uint32_t sram_get_timer_value(void) +{ + /* + * Generic delay timer implementation expects the timer to be a down + * counter. We apply bitwise NOT operator to the tick values returned + * by read_cntpct_el0() to simulate the down counter. + */ + return (uint32_t)(~read_cntpct_el0()); +} + +static __sramfunc void sram_udelay(uint32_t usec) +{ + uint32_t start, cnt, delta, delta_us; + + /* counter is decreasing */ + start = sram_get_timer_value(); + do { + cnt = sram_get_timer_value(); + if (cnt > start) { + delta = UINT32_MAX - cnt; + delta += start; + } else + delta = start - cnt; + delta_us = (delta * SYS_COUNTER_FREQ_IN_MHZ); + } while (delta_us < usec); +} + +static __sramfunc void configure_sgrf(void) +{ + /* + * SGRF_DDR_RGN_DPLL_CLK and SGRF_DDR_RGN_RTC_CLK: + * IC ECO bug, need to set this register. + * + * SGRF_DDR_RGN_BYPS: + * After the PD_CENTER suspend/resume, the DDR region + * related registers in the SGRF will be reset, we + * need to re-initialize them. + */ + mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16), + SGRF_DDR_RGN_DPLL_CLK | + SGRF_DDR_RGN_RTC_CLK | + SGRF_DDR_RGN_BYPS); +} + +static __sramfunc void rkclk_ddr_reset(uint32_t channel, uint32_t ctl, + uint32_t phy) +{ + channel &= 0x1; + ctl &= 0x1; + phy &= 0x1; + mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(4), + CRU_SFTRST_DDR_CTRL(channel, ctl) | + CRU_SFTRST_DDR_PHY(channel, phy)); +} + +static __sramfunc void phy_pctrl_reset(uint32_t ch) +{ + rkclk_ddr_reset(ch, 1, 1); + sram_udelay(10); + rkclk_ddr_reset(ch, 1, 0); + sram_udelay(10); + rkclk_ddr_reset(ch, 0, 0); + sram_udelay(10); +} + +static __sramfunc void phy_dll_bypass_set(uint32_t ch, uint32_t hz) +{ + if (hz <= 125 * MHz) { + /* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */ + mmio_setbits_32(PHY_REG(ch, 86), (0x3 << 2) << 8); + mmio_setbits_32(PHY_REG(ch, 214), (0x3 << 2) << 8); + mmio_setbits_32(PHY_REG(ch, 342), (0x3 << 2) << 8); + mmio_setbits_32(PHY_REG(ch, 470), (0x3 << 2) << 8); + /* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */ + mmio_setbits_32(PHY_REG(ch, 547), (0x3 << 2) << 16); + mmio_setbits_32(PHY_REG(ch, 675), (0x3 << 2) << 16); + mmio_setbits_32(PHY_REG(ch, 803), (0x3 << 2) << 16); + } else { + /* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */ + mmio_clrbits_32(PHY_REG(ch, 86), (0x3 << 2) << 8); + mmio_clrbits_32(PHY_REG(ch, 214), (0x3 << 2) << 8); + mmio_clrbits_32(PHY_REG(ch, 342), (0x3 << 2) << 8); + mmio_clrbits_32(PHY_REG(ch, 470), (0x3 << 2) << 8); + /* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */ + mmio_clrbits_32(PHY_REG(ch, 547), (0x3 << 2) << 16); + mmio_clrbits_32(PHY_REG(ch, 675), (0x3 << 2) << 16); + mmio_clrbits_32(PHY_REG(ch, 803), (0x3 << 2) << 16); + } +} + +static __sramfunc void set_cs_training_index(uint32_t ch, uint32_t rank) +{ + /* PHY_8/136/264/392 phy_per_cs_training_index_X 1bit offset_24 */ + mmio_clrsetbits_32(PHY_REG(ch, 8), 0x1 << 24, rank << 24); + mmio_clrsetbits_32(PHY_REG(ch, 136), 0x1 << 24, rank << 24); + mmio_clrsetbits_32(PHY_REG(ch, 264), 0x1 << 24, rank << 24); + mmio_clrsetbits_32(PHY_REG(ch, 392), 0x1 << 24, rank << 24); +} + +static __sramfunc void select_per_cs_training_index(uint32_t ch, uint32_t rank) +{ + /* PHY_84 PHY_PER_CS_TRAINING_EN_0 1bit offset_16 */ + if ((mmio_read_32(PHY_REG(ch, 84)) >> 16) & 1) + set_cs_training_index(ch, rank); +} + +static void override_write_leveling_value(uint32_t ch) +{ + uint32_t byte; + + /* PHY_896 PHY_FREQ_SEL_MULTICAST_EN 1bit offset_0 */ + mmio_setbits_32(PHY_REG(ch, 896), 1); + + /* + * PHY_8/136/264/392 + * phy_per_cs_training_multicast_en_X 1bit offset_16 + */ + mmio_clrsetbits_32(PHY_REG(ch, 8), 0x1 << 16, 1 << 16); + mmio_clrsetbits_32(PHY_REG(ch, 136), 0x1 << 16, 1 << 16); + mmio_clrsetbits_32(PHY_REG(ch, 264), 0x1 << 16, 1 << 16); + mmio_clrsetbits_32(PHY_REG(ch, 392), 0x1 << 16, 1 << 16); + + for (byte = 0; byte < 4; byte++) + mmio_clrsetbits_32(PHY_REG(ch, 63 + (128 * byte)), + 0xffff << 16, + 0x200 << 16); + + /* PHY_896 PHY_FREQ_SEL_MULTICAST_EN 1bit offset_0 */ + mmio_clrbits_32(PHY_REG(ch, 896), 1); + + /* CTL_200 ctrlupd_req 1bit offset_8 */ + mmio_clrsetbits_32(CTL_REG(ch, 200), 0x1 << 8, 0x1 << 8); +} + +static __sramfunc int data_training(uint32_t ch, + struct rk3399_sdram_params *sdram_params, + uint32_t training_flag) +{ + uint32_t obs_0, obs_1, obs_2, obs_3, obs_err = 0; + uint32_t rank = sdram_params->ch[ch].rank; + uint32_t rank_mask; + uint32_t i, tmp; + + if (sdram_params->dramtype == LPDDR4) + rank_mask = (rank == 1) ? 0x5 : 0xf; + else + rank_mask = (rank == 1) ? 0x1 : 0x3; + + /* PHY_927 PHY_PAD_DQS_DRIVE RPULL offset_22 */ + mmio_setbits_32(PHY_REG(ch, 927), (1 << 22)); + + if (training_flag == PI_FULL_TRAINING) { + if (sdram_params->dramtype == LPDDR4) { + training_flag = PI_WRITE_LEVELING | + PI_READ_GATE_TRAINING | + PI_READ_LEVELING | + PI_WDQ_LEVELING; + } else if (sdram_params->dramtype == LPDDR3) { + training_flag = PI_CA_TRAINING | PI_WRITE_LEVELING | + PI_READ_GATE_TRAINING; + } else if (sdram_params->dramtype == DDR3) { + training_flag = PI_WRITE_LEVELING | + PI_READ_GATE_TRAINING | + PI_READ_LEVELING; + } + } + + /* ca training(LPDDR4,LPDDR3 support) */ + if ((training_flag & PI_CA_TRAINING) == PI_CA_TRAINING) { + for (i = 0; i < 4; i++) { + if (!(rank_mask & (1 << i))) + continue; + + select_per_cs_training_index(ch, i); + /* PI_100 PI_CALVL_EN:RW:8:2 */ + mmio_clrsetbits_32(PI_REG(ch, 100), 0x3 << 8, 0x2 << 8); + + /* PI_92 PI_CALVL_REQ:WR:16:1,PI_CALVL_CS:RW:24:2 */ + mmio_clrsetbits_32(PI_REG(ch, 92), + (0x1 << 16) | (0x3 << 24), + (0x1 << 16) | (i << 24)); + while (1) { + /* PI_174 PI_INT_STATUS:RD:8:18 */ + tmp = mmio_read_32(PI_REG(ch, 174)) >> 8; + + /* + * check status obs + * PHY_532/660/788 phy_adr_calvl_obs1_:0:32 + */ + obs_0 = mmio_read_32(PHY_REG(ch, 532)); + obs_1 = mmio_read_32(PHY_REG(ch, 660)); + obs_2 = mmio_read_32(PHY_REG(ch, 788)); + if (((obs_0 >> 30) & 0x3) || + ((obs_1 >> 30) & 0x3) || + ((obs_2 >> 30) & 0x3)) + obs_err = 1; + if ((((tmp >> 11) & 0x1) == 0x1) && + (((tmp >> 13) & 0x1) == 0x1) && + (((tmp >> 5) & 0x1) == 0x0) && + (obs_err == 0)) + break; + else if ((((tmp >> 5) & 0x1) == 0x1) || + (obs_err == 1)) + return -1; + } + /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */ + mmio_write_32(PI_REG(ch, 175), 0x00003f7c); + } + mmio_clrbits_32(PI_REG(ch, 100), 0x3 << 8); + } + + /* write leveling(LPDDR4,LPDDR3,DDR3 support) */ + if ((training_flag & PI_WRITE_LEVELING) == PI_WRITE_LEVELING) { + for (i = 0; i < rank; i++) { + select_per_cs_training_index(ch, i); + /* PI_60 PI_WRLVL_EN:RW:8:2 */ + mmio_clrsetbits_32(PI_REG(ch, 60), 0x3 << 8, 0x2 << 8); + /* PI_59 PI_WRLVL_REQ:WR:8:1,PI_WRLVL_CS:RW:16:2 */ + mmio_clrsetbits_32(PI_REG(ch, 59), + (0x1 << 8) | (0x3 << 16), + (0x1 << 8) | (i << 16)); + + while (1) { + /* PI_174 PI_INT_STATUS:RD:8:18 */ + tmp = mmio_read_32(PI_REG(ch, 174)) >> 8; + + /* + * check status obs, if error maybe can not + * get leveling done PHY_40/168/296/424 + * phy_wrlvl_status_obs_X:0:13 + */ + obs_0 = mmio_read_32(PHY_REG(ch, 40)); + obs_1 = mmio_read_32(PHY_REG(ch, 168)); + obs_2 = mmio_read_32(PHY_REG(ch, 296)); + obs_3 = mmio_read_32(PHY_REG(ch, 424)); + if (((obs_0 >> 12) & 0x1) || + ((obs_1 >> 12) & 0x1) || + ((obs_2 >> 12) & 0x1) || + ((obs_3 >> 12) & 0x1)) + obs_err = 1; + if ((((tmp >> 10) & 0x1) == 0x1) && + (((tmp >> 13) & 0x1) == 0x1) && + (((tmp >> 4) & 0x1) == 0x0) && + (obs_err == 0)) + break; + else if ((((tmp >> 4) & 0x1) == 0x1) || + (obs_err == 1)) + return -1; + } + + /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */ + mmio_write_32(PI_REG(ch, 175), 0x00003f7c); + } + override_write_leveling_value(ch); + mmio_clrbits_32(PI_REG(ch, 60), 0x3 << 8); + } + + /* read gate training(LPDDR4,LPDDR3,DDR3 support) */ + if ((training_flag & PI_READ_GATE_TRAINING) == PI_READ_GATE_TRAINING) { + for (i = 0; i < rank; i++) { + select_per_cs_training_index(ch, i); + /* PI_80 PI_RDLVL_GATE_EN:RW:24:2 */ + mmio_clrsetbits_32(PI_REG(ch, 80), 0x3 << 24, + 0x2 << 24); + /* + * PI_74 PI_RDLVL_GATE_REQ:WR:16:1 + * PI_RDLVL_CS:RW:24:2 + */ + mmio_clrsetbits_32(PI_REG(ch, 74), + (0x1 << 16) | (0x3 << 24), + (0x1 << 16) | (i << 24)); + + while (1) { + /* PI_174 PI_INT_STATUS:RD:8:18 */ + tmp = mmio_read_32(PI_REG(ch, 174)) >> 8; + + /* + * check status obs + * PHY_43/171/299/427 + * PHY_GTLVL_STATUS_OBS_x:16:8 + */ + obs_0 = mmio_read_32(PHY_REG(ch, 43)); + obs_1 = mmio_read_32(PHY_REG(ch, 171)); + obs_2 = mmio_read_32(PHY_REG(ch, 299)); + obs_3 = mmio_read_32(PHY_REG(ch, 427)); + if (((obs_0 >> (16 + 6)) & 0x3) || + ((obs_1 >> (16 + 6)) & 0x3) || + ((obs_2 >> (16 + 6)) & 0x3) || + ((obs_3 >> (16 + 6)) & 0x3)) + obs_err = 1; + if ((((tmp >> 9) & 0x1) == 0x1) && + (((tmp >> 13) & 0x1) == 0x1) && + (((tmp >> 3) & 0x1) == 0x0) && + (obs_err == 0)) + break; + else if ((((tmp >> 3) & 0x1) == 0x1) || + (obs_err == 1)) + return -1; + } + /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */ + mmio_write_32(PI_REG(ch, 175), 0x00003f7c); + } + mmio_clrbits_32(PI_REG(ch, 80), 0x3 << 24); + } + + /* read leveling(LPDDR4,LPDDR3,DDR3 support) */ + if ((training_flag & PI_READ_LEVELING) == PI_READ_LEVELING) { + for (i = 0; i < rank; i++) { + select_per_cs_training_index(ch, i); + /* PI_80 PI_RDLVL_EN:RW:16:2 */ + mmio_clrsetbits_32(PI_REG(ch, 80), 0x3 << 16, + 0x2 << 16); + /* PI_74 PI_RDLVL_REQ:WR:8:1,PI_RDLVL_CS:RW:24:2 */ + mmio_clrsetbits_32(PI_REG(ch, 74), + (0x1 << 8) | (0x3 << 24), + (0x1 << 8) | (i << 24)); + while (1) { + /* PI_174 PI_INT_STATUS:RD:8:18 */ + tmp = mmio_read_32(PI_REG(ch, 174)) >> 8; + + /* + * make sure status obs not report error bit + * PHY_46/174/302/430 + * phy_rdlvl_status_obs_X:16:8 + */ + if ((((tmp >> 8) & 0x1) == 0x1) && + (((tmp >> 13) & 0x1) == 0x1) && + (((tmp >> 2) & 0x1) == 0x0)) + break; + else if (((tmp >> 2) & 0x1) == 0x1) + return -1; + } + /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */ + mmio_write_32(PI_REG(ch, 175), 0x00003f7c); + } + mmio_clrbits_32(PI_REG(ch, 80), 0x3 << 16); + } + + /* wdq leveling(LPDDR4 support) */ + if ((training_flag & PI_WDQ_LEVELING) == PI_WDQ_LEVELING) { + for (i = 0; i < 4; i++) { + if (!(rank_mask & (1 << i))) + continue; + + select_per_cs_training_index(ch, i); + /* + * disable PI_WDQLVL_VREF_EN before wdq leveling? + * PI_181 PI_WDQLVL_VREF_EN:RW:8:1 + */ + mmio_clrbits_32(PI_REG(ch, 181), 0x1 << 8); + /* PI_124 PI_WDQLVL_EN:RW:16:2 */ + mmio_clrsetbits_32(PI_REG(ch, 124), 0x3 << 16, + 0x2 << 16); + /* PI_121 PI_WDQLVL_REQ:WR:8:1,PI_WDQLVL_CS:RW:16:2 */ + mmio_clrsetbits_32(PI_REG(ch, 121), + (0x1 << 8) | (0x3 << 16), + (0x1 << 8) | (i << 16)); + while (1) { + /* PI_174 PI_INT_STATUS:RD:8:18 */ + tmp = mmio_read_32(PI_REG(ch, 174)) >> 8; + if ((((tmp >> 12) & 0x1) == 0x1) && + (((tmp >> 13) & 0x1) == 0x1) && + (((tmp >> 6) & 0x1) == 0x0)) + break; + else if (((tmp >> 6) & 0x1) == 0x1) + return -1; + } + /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */ + mmio_write_32(PI_REG(ch, 175), 0x00003f7c); + } + mmio_clrbits_32(PI_REG(ch, 124), 0x3 << 16); + } + + /* PHY_927 PHY_PAD_DQS_DRIVE RPULL offset_22 */ + mmio_clrbits_32(PHY_REG(ch, 927), (1 << 22)); + + return 0; +} + +static __sramfunc void set_ddrconfig(struct rk3399_sdram_params *sdram_params, + unsigned char channel, uint32_t ddrconfig) +{ + /* only need to set ddrconfig */ + struct rk3399_sdram_channel *ch = &sdram_params->ch[channel]; + unsigned int cs0_cap = 0; + unsigned int cs1_cap = 0; + + cs0_cap = (1 << (ch->cs0_row + ch->col + ch->bk + ch->bw - 20)); + if (ch->rank > 1) + cs1_cap = cs0_cap >> (ch->cs0_row - ch->cs1_row); + if (ch->row_3_4) { + cs0_cap = cs0_cap * 3 / 4; + cs1_cap = cs1_cap * 3 / 4; + } + + mmio_write_32(MSCH_BASE(channel) + MSCH_DEVICECONF, + ddrconfig | (ddrconfig << 6)); + mmio_write_32(MSCH_BASE(channel) + MSCH_DEVICESIZE, + ((cs0_cap / 32) & 0xff) | (((cs1_cap / 32) & 0xff) << 8)); +} + +static __sramfunc void dram_all_config(struct rk3399_sdram_params *sdram_params) +{ + unsigned int i; + + for (i = 0; i < 2; i++) { + struct rk3399_sdram_channel *info = &sdram_params->ch[i]; + struct rk3399_msch_timings *noc = &info->noc_timings; + + if (sdram_params->ch[i].col == 0) + continue; + + mmio_write_32(MSCH_BASE(i) + MSCH_DDRTIMINGA0, + noc->ddrtiminga0.d32); + mmio_write_32(MSCH_BASE(i) + MSCH_DDRTIMINGB0, + noc->ddrtimingb0.d32); + mmio_write_32(MSCH_BASE(i) + MSCH_DDRTIMINGC0, + noc->ddrtimingc0.d32); + mmio_write_32(MSCH_BASE(i) + MSCH_DEVTODEV0, + noc->devtodev0.d32); + mmio_write_32(MSCH_BASE(i) + MSCH_DDRMODE, noc->ddrmode.d32); + + /* rank 1 memory clock disable (dfi_dram_clk_disable = 1) */ + if (sdram_params->ch[i].rank == 1) + mmio_setbits_32(CTL_REG(i, 276), 1 << 17); + } + + DDR_STRIDE(sdram_params->stride); + + /* reboot hold register set */ + mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1), + CRU_PMU_SGRF_RST_RLS | + PRESET_GPIO0_HOLD(1) | + PRESET_GPIO1_HOLD(1)); + mmio_clrsetbits_32(CRU_BASE + CRU_GLB_RST_CON, 0x3, 0x3); +} + +static __sramfunc void pctl_cfg(uint32_t ch, + struct rk3399_sdram_params *sdram_params) +{ + const uint32_t *params_ctl = sdram_params->pctl_regs.denali_ctl; + const uint32_t *params_phy = sdram_params->phy_regs.denali_phy; + const uint32_t *params_pi = sdram_params->pi_regs.denali_pi; + uint32_t tmp, tmp1, tmp2; + + /* + * Workaround controller bug: + * Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed + */ + sram_regcpy(CTL_REG(ch, 1), (uintptr_t)¶ms_ctl[1], + CTL_REG_NUM - 1); + mmio_write_32(CTL_REG(ch, 0), params_ctl[0]); + sram_regcpy(PI_REG(ch, 0), (uintptr_t)¶ms_pi[0], + PI_REG_NUM); + + mmio_write_32(PHY_REG(ch, 910), params_phy[910]); + mmio_write_32(PHY_REG(ch, 911), params_phy[911]); + mmio_write_32(PHY_REG(ch, 912), params_phy[912]); + + mmio_clrsetbits_32(CTL_REG(ch, 68), PWRUP_SREFRESH_EXIT, + PWRUP_SREFRESH_EXIT); + + /* PHY_DLL_RST_EN */ + mmio_clrsetbits_32(PHY_REG(ch, 957), 0x3 << 24, 1 << 24); + dmbst(); + + mmio_setbits_32(PI_REG(ch, 0), START); + mmio_setbits_32(CTL_REG(ch, 0), START); + + /* wait lock */ + while (1) { + tmp = mmio_read_32(PHY_REG(ch, 920)); + tmp1 = mmio_read_32(PHY_REG(ch, 921)); + tmp2 = mmio_read_32(PHY_REG(ch, 922)); + if ((((tmp >> 16) & 0x1) == 0x1) && + (((tmp1 >> 16) & 0x1) == 0x1) && + (((tmp1 >> 0) & 0x1) == 0x1) && + (((tmp2 >> 0) & 0x1) == 0x1)) + break; + /* if PLL bypass,don't need wait lock */ + if (mmio_read_32(PHY_REG(ch, 911)) & 0x1) + break; + } + + sram_regcpy(PHY_REG(ch, 896), (uintptr_t)¶ms_phy[896], 63); + sram_regcpy(PHY_REG(ch, 0), (uintptr_t)¶ms_phy[0], 91); + sram_regcpy(PHY_REG(ch, 128), (uintptr_t)¶ms_phy[128], 91); + sram_regcpy(PHY_REG(ch, 256), (uintptr_t)¶ms_phy[256], 91); + sram_regcpy(PHY_REG(ch, 384), (uintptr_t)¶ms_phy[384], 91); + sram_regcpy(PHY_REG(ch, 512), (uintptr_t)¶ms_phy[512], 38); + sram_regcpy(PHY_REG(ch, 640), (uintptr_t)¶ms_phy[640], 38); + sram_regcpy(PHY_REG(ch, 768), (uintptr_t)¶ms_phy[768], 38); +} + +static __sramfunc int dram_switch_to_phy_index1( + struct rk3399_sdram_params *sdram_params) +{ + uint32_t ch, ch_count; + + mmio_write_32(CIC_BASE + CIC_CTRL0, + (((0x3 << 4) | (1 << 2) | 1) << 16) | + (1 << 4) | (1 << 2) | 1); + while (!(mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 2))) + ; + + mmio_write_32(CIC_BASE + CIC_CTRL0, 0x20002); + while (!(mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 0))) + ; + + ch_count = sdram_params->num_channels; + + /* 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); + + /* data_training failed */ + if (data_training(ch, sdram_params, PI_FULL_TRAINING)) + return -1; + } + + return 0; +} + +/* + * Needs to be done for both channels at once in case of a shared reset signal + * between channels. + */ +static __sramfunc int pctl_start(uint32_t channel_mask, + struct rk3399_sdram_params *sdram_params) +{ + uint32_t count; + + mmio_setbits_32(CTL_REG(0, 68), PWRUP_SREFRESH_EXIT); + mmio_setbits_32(CTL_REG(1, 68), PWRUP_SREFRESH_EXIT); + + /* need de-access IO retention before controller START */ + if (channel_mask & (1 << 0)) + mmio_setbits_32(PMU_BASE + PMU_PWRMODE_CON, (1 << 19)); + if (channel_mask & (1 << 1)) + mmio_setbits_32(PMU_BASE + PMU_PWRMODE_CON, (1 << 23)); + + /* PHY_DLL_RST_EN */ + if (channel_mask & (1 << 0)) + mmio_clrsetbits_32(PHY_REG(0, 957), 0x3 << 24, + 0x2 << 24); + if (channel_mask & (1 << 1)) + mmio_clrsetbits_32(PHY_REG(1, 957), 0x3 << 24, + 0x2 << 24); + + /* check ERROR bit */ + if (channel_mask & (1 << 0)) { + count = 0; + while (!(mmio_read_32(CTL_REG(0, 203)) & (1 << 3))) { + /* CKE is low, loop 10ms */ + if (count > 100) + return -1; + + sram_udelay(100); + count++; + } + + mmio_clrbits_32(CTL_REG(0, 68), PWRUP_SREFRESH_EXIT); + } + if (channel_mask & (1 << 1)) { + count = 0; + while (!(mmio_read_32(CTL_REG(1, 203)) & (1 << 3))) { + /* CKE is low, loop 10ms */ + if (count > 100) + return -1; + + sram_udelay(100); + count++; + } + + mmio_clrbits_32(CTL_REG(1, 68), PWRUP_SREFRESH_EXIT); + } + + return 0; +} + +void dmc_save(void) +{ + struct rk3399_sdram_params *sdram_params = &sdram_config; + uint32_t *params_ctl; + uint32_t *params_pi; + uint32_t *params_phy; + uint32_t refdiv, postdiv2, postdiv1, fbdiv; + uint32_t tmp; + + params_ctl = sdram_params->pctl_regs.denali_ctl; + params_pi = sdram_params->pi_regs.denali_pi; + params_phy = sdram_params->phy_regs.denali_phy; + + fbdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 0)) & 0xfff; + tmp = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)); + postdiv2 = POSTDIV2_DEC(tmp); + postdiv1 = POSTDIV1_DEC(tmp); + refdiv = REFDIV_DEC(tmp); + + sdram_params->ddr_freq = ((fbdiv * 24) / + (refdiv * postdiv1 * postdiv2)) * MHz; + + INFO("sdram_params->ddr_freq = %d\n", sdram_params->ddr_freq); + sdram_params->odt = (((mmio_read_32(PHY_REG(0, 5)) >> 16) & + 0x7) != 0) ? 1 : 0; + + /* copy the registers CTL PI and PHY */ + sram_regcpy((uintptr_t)¶ms_ctl[0], CTL_REG(0, 0), CTL_REG_NUM); + + /* mask DENALI_CTL_00_DATA.START, only copy here, will trigger later */ + params_ctl[0] &= ~(0x1 << 0); + + sram_regcpy((uintptr_t)¶ms_pi[0], PI_REG(0, 0), + PI_REG_NUM); + + /* mask DENALI_PI_00_DATA.START, only copy here, will trigger later*/ + params_pi[0] &= ~(0x1 << 0); + + sram_regcpy((uintptr_t)¶ms_phy[0], PHY_REG(0, 0), 91); + sram_regcpy((uintptr_t)¶ms_phy[128], PHY_REG(0, 128), 91); + sram_regcpy((uintptr_t)¶ms_phy[256], PHY_REG(0, 256), 91); + sram_regcpy((uintptr_t)¶ms_phy[384], PHY_REG(0, 384), 91); + sram_regcpy((uintptr_t)¶ms_phy[512], PHY_REG(0, 512), 38); + sram_regcpy((uintptr_t)¶ms_phy[640], PHY_REG(0, 640), 38); + sram_regcpy((uintptr_t)¶ms_phy[768], PHY_REG(0, 768), 38); + sram_regcpy((uintptr_t)¶ms_phy[896], PHY_REG(0, 896), 63); + + /* set DENALI_PHY_957_DATA.PHY_DLL_RST_EN = 0x1 */ + params_phy[957] &= ~(0x3 << 24); + params_phy[957] |= 1 << 24; + params_phy[896] |= 1; + params_phy[896] &= ~(0x3 << 8); +} + +__sramfunc void dmc_restore(void) +{ + struct rk3399_sdram_params *sdram_params = &sdram_config; + uint32_t channel_mask = 0; + uint32_t channel; + + configure_sgrf(); + +retry: + for (channel = 0; channel < sdram_params->num_channels; channel++) { + phy_pctrl_reset(channel); + phy_dll_bypass_set(channel, sdram_params->ddr_freq); + if (channel >= sdram_params->num_channels) + continue; + + pctl_cfg(channel, sdram_params); + } + + for (channel = 0; channel < 2; channel++) { + if (sdram_params->ch[channel].col) + channel_mask |= 1 << channel; + } + + if (pctl_start(channel_mask, sdram_params) < 0) + goto retry; + + for (channel = 0; channel < sdram_params->num_channels; channel++) { + /* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */ + if (sdram_params->dramtype == LPDDR3) + sram_udelay(10); + + /* If traning fail, retry to do it again. */ + if (data_training(channel, sdram_params, PI_FULL_TRAINING)) + goto retry; + + set_ddrconfig(sdram_params, channel, + sdram_params->ch[channel].ddrconfig); + } + + dram_all_config(sdram_params); + + /* Switch to index 1 and prepare for DDR frequency switch. */ + dram_switch_to_phy_index1(sdram_params); +} diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.h b/plat/rockchip/rk3399/drivers/dram/suspend.h new file mode 100644 index 000000000..215986180 --- /dev/null +++ b/plat/rockchip/rk3399/drivers/dram/suspend.h @@ -0,0 +1,50 @@ +/* + * 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 __SOC_ROCKCHIP_RK3399_SUSPEND_H__ +#define __SOC_ROCKCHIP_RK3399_SUSPEND_H__ +#include + +#define KHz (1000) +#define MHz (1000 * KHz) +#define GHz (1000 * MHz) + +#define PI_CA_TRAINING (1 << 0) +#define PI_WRITE_LEVELING (1 << 1) +#define PI_READ_GATE_TRAINING (1 << 2) +#define PI_READ_LEVELING (1 << 3) +#define PI_WDQ_LEVELING (1 << 4) +#define PI_FULL_TRAINING (0xff) + +void dmc_save(void); +__sramfunc void dmc_restore(void); +__sramfunc void sram_regcpy(uintptr_t dst, uintptr_t src, uint32_t num); + +#endif /* __DRAM_H__ */ diff --git a/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S index 72419648b..405e1d5e0 100644 --- a/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S +++ b/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S @@ -27,9 +27,25 @@ #include #include #include +#include .globl clst_warmboot_data + .macro sram_func _name + .section .sram.text, "ax" + .type \_name, %function + .func \_name + \_name: + .endm + +#define CRU_CLKSEL_CON6 0x118 + +#define DDRCTL0_C_SYSREQ_CFG 0x0100 +#define DDRCTL1_C_SYSREQ_CFG 0x1000 + +#define DDRC0_SREF_DONE_EXT 0x01 +#define DDRC1_SREF_DONE_EXT 0x04 + #define PLL_MODE_SHIFT (0x8) #define PLL_NORMAL_MODE ((0x3 << (PLL_MODE_SHIFT + 16)) | \ (0x1 << PLL_MODE_SHIFT)) @@ -65,3 +81,75 @@ clst_warmboot_data: .word 0 .endr .endm + + /* ----------------------------------------------- + * void sram_func_set_ddrctl_pll(uint32_t pll_src) + * Function to switch the PLL source for ddrctrl + * In: x0 - The PLL of the clk_ddrc clock source + * out: None + * Clobber list : x0 - x3, x5, x8 - x10 + * ----------------------------------------------- + */ + + .globl sram_func_set_ddrctl_pll + +sram_func sram_func_set_ddrctl_pll + /* backup parameter */ + mov x8, x0 + + /* disable the MMU at EL3 */ + mrs x9, sctlr_el3 + bic x10, x9, #(SCTLR_M_BIT) + msr sctlr_el3, x10 + isb + dsb sy + + /* enable ddrctl0_1 idle request */ + mov x5, PMU_BASE + ldr w0, [x5, #PMU_SFT_CON] + orr w0, w0, #DDRCTL0_C_SYSREQ_CFG + orr w0, w0, #DDRCTL1_C_SYSREQ_CFG + str w0, [x5, #PMU_SFT_CON] + +check_ddrc0_1_sref_enter: + ldr w1, [x5, #PMU_DDR_SREF_ST] + and w2, w1, #DDRC0_SREF_DONE_EXT + and w3, w1, #DDRC1_SREF_DONE_EXT + orr w2, w2, w3 + cmp w2, #(DDRC0_SREF_DONE_EXT | DDRC1_SREF_DONE_EXT) + b.eq check_ddrc0_1_sref_enter + + /* + * select a PLL for ddrctrl: + * x0 = 0: ALPLL + * x0 = 1: ABPLL + * x0 = 2: DPLL + * x0 = 3: GPLLL + */ + mov x5, CRU_BASE + lsl w0, w8, #4 + orr w0, w0, #0x00300000 + str w0, [x5, #CRU_CLKSEL_CON6] + + /* disable ddrctl0_1 idle request */ + mov x5, PMU_BASE + ldr w0, [x5, #PMU_SFT_CON] + bic w0, w0, #DDRCTL0_C_SYSREQ_CFG + bic w0, w0, #DDRCTL1_C_SYSREQ_CFG + str w0, [x5, #PMU_SFT_CON] + +check_ddrc0_1_sref_exit: + ldr w1, [x5, #PMU_DDR_SREF_ST] + and w2, w1, #DDRC0_SREF_DONE_EXT + and w3, w1, #DDRC1_SREF_DONE_EXT + orr w2, w2, w3 + cmp w2, #0x0 + b.eq check_ddrc0_1_sref_exit + + /* reenable the MMU at EL3 */ + msr sctlr_el3, x9 + isb + dsb sy + + ret +endfunc sram_func_set_ddrctl_pll diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c index 8d3f482f4..5a385cb34 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -46,9 +46,9 @@ #include #include #include -#include #include #include +#include DEFINE_BAKERY_LOCK(rockchip_pd_lock); @@ -102,7 +102,6 @@ static void pmu_bus_idle_req(uint32_t bus, uint32_t state) mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ACK), bus_ack); } - } struct pmu_slpdata_s pmu_slpdata; @@ -818,10 +817,19 @@ static void init_pmu_counts(void) mmio_write_32(PMU_BASE + PMU_GPU_PWRUP_CNT, CYCL_24M_CNT_US(1)); } +static uint32_t clk_ddrc_save; + static void sys_slp_config(void) { uint32_t slp_mode_cfg = 0; + /* keep enabling clk_ddrc_bpll_src_en gate for DDRC */ + clk_ddrc_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(3)); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3), WMSK_BIT(1)); + + prepare_abpll_for_ddrctrl(); + sram_func_set_ddrctl_pll(ABPLL_ID); + mmio_write_32(GRF_BASE + GRF_SOC_CON4, CCI_FORCE_WAKEUP); mmio_write_32(PMU_BASE + PMU_CCI500_CON, BIT_WITH_WMSK(PMU_CLR_PREQ_CCI500_HW) | @@ -849,6 +857,7 @@ static void sys_slp_config(void) BIT(PMU_DDRIO0_RET_EN) | BIT(PMU_DDRIO1_RET_EN) | BIT(PMU_DDRIO_RET_HW_DE_REQ) | + BIT(PMU_CENTER_PD_EN) | BIT(PMU_PLL_PD_EN) | BIT(PMU_CLK_CENTER_SRC_GATE_EN) | BIT(PMU_OSC_DIS) | @@ -857,7 +866,6 @@ static void sys_slp_config(void) mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, BIT(PMU_GPIO_WKUP_EN)); mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, slp_mode_cfg); - mmio_write_32(PMU_BASE + PMU_PLL_CON, PLL_PD_HW); mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON0, EXTERNAL_32K); mmio_write_32(PMUGRF_BASE, IOMUX_CLK_32K); /* 32k iomux */ @@ -1094,6 +1102,9 @@ static int sys_pwr_domain_suspend(void) uint32_t wait_cnt = 0; uint32_t status = 0; + dmc_save(); + pmu_scu_b_pwrdn(); + pmu_power_domains_suspend(); set_hw_idle(BIT(PMU_CLR_CENTER1) | BIT(PMU_CLR_ALIVE) | @@ -1114,8 +1125,6 @@ static int sys_pwr_domain_suspend(void) (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); - pmu_scu_b_pwrdn(); - mmio_write_32(PMU_BASE + PMU_ADB400_CON, BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_SW) | @@ -1134,6 +1143,7 @@ static int sys_pwr_domain_suspend(void) } } mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN)); + /* * Disabling PLLs/PWM/DVFS is approaching WFI which is * the last steps in suspend. @@ -1163,6 +1173,10 @@ static int sys_pwr_domain_resume(void) enable_dvfs_plls(); plls_resume_finish(); + /* restore clk_ddrc_bpll_src_en gate */ + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3), + BITS_WITH_WMASK(clk_ddrc_save, 0xff, 0)); + /* * The wakeup status is not cleared by itself, we need to clear it * manually. Otherwise we will alway query some interrupt next time. @@ -1209,8 +1223,12 @@ static int sys_pwr_domain_resume(void) pmu_sgrf_rst_hld_release(); pmu_scu_b_pwrup(); - pmu_power_domains_resume(); + + restore_dpll(); + sram_func_set_ddrctl_pll(DPLL_ID); + restore_abpll(); + clr_hw_idle(BIT(PMU_CLR_CENTER1) | BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_MSCH0) | @@ -1301,9 +1319,10 @@ void plat_rockchip_pmu_init(void) for (cpu = 0; cpu < PLATFORM_CLUSTER_COUNT; cpu++) clst_warmboot_data[cpu] = 0; - psram_sleep_cfg->ddr_func = 0x00; - psram_sleep_cfg->ddr_data = 0x00; - psram_sleep_cfg->ddr_flag = 0x00; + psram_sleep_cfg->ddr_func = (uint64_t)dmc_restore; + psram_sleep_cfg->ddr_data = (uint64_t)&sdram_config; + psram_sleep_cfg->ddr_flag = 0x01; + psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; /* config cpu's warm boot address */ diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.h b/plat/rockchip/rk3399/drivers/pmu/pmu.h index ab2896b13..22c8c6374 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.h +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.h @@ -31,6 +31,9 @@ #ifndef __PMU_H__ #define __PMU_H__ +#include +#include + /* Allocate sp reginon in pmusram */ #define PSRAM_SP_SIZE 0x80 #define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE) @@ -751,72 +754,7 @@ enum pmu_core_pwr_st { STANDBY_BY_WFIL2_CLUSTER_B, }; -#define PMU_WKUP_CFG0 0x00 -#define PMU_WKUP_CFG1 0x04 -#define PMU_WKUP_CFG2 0x08 -#define PMU_WKUP_CFG3 0x0c -#define PMU_WKUP_CFG4 0x10 -#define PMU_PWRDN_CON 0x14 -#define PMU_PWRDN_ST 0x18 -#define PMU_PLL_CON 0x1c -#define PMU_PWRMODE_CON 0x20 -#define PMU_SFT_CON 0x24 -#define PMU_INT_CON 0x28 -#define PMU_INT_ST 0x2c -#define PMU_GPIO0_POS_INT_CON 0x30 -#define PMU_GPIO0_NEG_INT_CON 0x34 -#define PMU_GPIO1_POS_INT_CON 0x38 -#define PMU_GPIO1_NEG_INT_CON 0x3c -#define PMU_GPIO0_POS_INT_ST 0x40 -#define PMU_GPIO0_NEG_INT_ST 0x44 -#define PMU_GPIO1_POS_INT_ST 0x48 -#define PMU_GPIO1_NEG_INT_ST 0x4c -#define PMU_PWRDN_INTEN 0x50 -#define PMU_PWRDN_STATUS 0x54 -#define PMU_WAKEUP_STATUS 0x58 -#define PMU_BUS_CLR 0x5c -#define PMU_BUS_IDLE_REQ 0x60 -#define PMU_BUS_IDLE_ST 0x64 -#define PMU_BUS_IDLE_ACK 0x68 -#define PMU_CCI500_CON 0x6c -#define PMU_ADB400_CON 0x70 -#define PMU_ADB400_ST 0x74 -#define PMU_POWER_ST 0x78 -#define PMU_CORE_PWR_ST 0x7c -#define PMU_OSC_CNT 0x80 -#define PMU_PLLLOCK_CNT 0x84 -#define PMU_PLLRST_CNT 0x88 -#define PMU_STABLE_CNT 0x8c -#define PMU_DDRIO_PWRON_CNT 0x90 -#define PMU_WAKEUP_RST_CLR_CNT 0x94 -#define PMU_DDR_SREF_ST 0x98 -#define PMU_SCU_L_PWRDN_CNT 0x9c -#define PMU_SCU_L_PWRUP_CNT 0xa0 -#define PMU_SCU_B_PWRDN_CNT 0xa4 -#define PMU_SCU_B_PWRUP_CNT 0xa8 -#define PMU_GPU_PWRDN_CNT 0xac -#define PMU_GPU_PWRUP_CNT 0xb0 -#define PMU_CENTER_PWRDN_CNT 0xb4 -#define PMU_CENTER_PWRUP_CNT 0xb8 -#define PMU_TIMEOUT_CNT 0xbc -#define PMU_CPU0APM_CON 0xc0 -#define PMU_CPU1APM_CON 0xc4 -#define PMU_CPU2APM_CON 0xc8 -#define PMU_CPU3APM_CON 0xcc -#define PMU_CPU0BPM_CON 0xd0 -#define PMU_CPU1BPM_CON 0xd4 -#define PMU_NOC_AUTO_ENA 0xd8 -#define PMU_PWRDN_CON1 0xdc - -#define PMUGRF_GPIO0A_IOMUX 0x00 -#define PMUGRF_GPIO1A_IOMUX 0x10 -#define PMUGRF_GPIO1C_IOMUX 0x18 - -#define PMUGRF_GPIO0A6_IOMUX_SHIFT 12 -#define PMUGRF_GPIO0A6_IOMUX_PWM 0x1 -#define PMUGRF_GPIO1C3_IOMUX_SHIFT 6 -#define PMUGRF_GPIO1C3_IOMUX_PWM 0x1 - +/* Specific features required */ #define AP_PWROFF 0x0a #define GPIO0A0_SMT_ENABLE BITS_WITH_WMASK(1, 3, 0) @@ -824,51 +762,6 @@ enum pmu_core_pwr_st { #define TSADC_INT_PIN 38 #define CORES_PM_DISABLE 0x0 -#define CPU_AXI_QOS_ID_COREID 0x00 -#define CPU_AXI_QOS_REVISIONID 0x04 -#define CPU_AXI_QOS_PRIORITY 0x08 -#define CPU_AXI_QOS_MODE 0x0c -#define CPU_AXI_QOS_BANDWIDTH 0x10 -#define CPU_AXI_QOS_SATURATION 0x14 -#define CPU_AXI_QOS_EXTCONTROL 0x18 -#define CPU_AXI_QOS_NUM_REGS 0x07 - -#define CPU_AXI_CCI_M0_QOS_BASE 0xffa50000 -#define CPU_AXI_CCI_M1_QOS_BASE 0xffad8000 -#define CPU_AXI_DMAC0_QOS_BASE 0xffa64200 -#define CPU_AXI_DMAC1_QOS_BASE 0xffa64280 -#define CPU_AXI_DCF_QOS_BASE 0xffa64180 -#define CPU_AXI_CRYPTO0_QOS_BASE 0xffa64100 -#define CPU_AXI_CRYPTO1_QOS_BASE 0xffa64080 -#define CPU_AXI_PMU_CM0_QOS_BASE 0xffa68000 -#define CPU_AXI_PERI_CM1_QOS_BASE 0xffa64300 -#define CPU_AXI_GIC_QOS_BASE 0xffa78000 -#define CPU_AXI_SDIO_QOS_BASE 0xffa76000 -#define CPU_AXI_SDMMC_QOS_BASE 0xffa74000 -#define CPU_AXI_EMMC_QOS_BASE 0xffa58000 -#define CPU_AXI_GMAC_QOS_BASE 0xffa5c000 -#define CPU_AXI_USB_OTG0_QOS_BASE 0xffa70000 -#define CPU_AXI_USB_OTG1_QOS_BASE 0xffa70080 -#define CPU_AXI_USB_HOST0_QOS_BASE 0xffa60100 -#define CPU_AXI_USB_HOST1_QOS_BASE 0xffa60180 -#define CPU_AXI_GPU_QOS_BASE 0xffae0000 -#define CPU_AXI_VIDEO_M0_QOS_BASE 0xffab8000 -#define CPU_AXI_VIDEO_M1_R_QOS_BASE 0xffac0000 -#define CPU_AXI_VIDEO_M1_W_QOS_BASE 0xffac0080 -#define CPU_AXI_RGA_R_QOS_BASE 0xffab0000 -#define CPU_AXI_RGA_W_QOS_BASE 0xffab0080 -#define CPU_AXI_IEP_QOS_BASE 0xffa98000 -#define CPU_AXI_VOP_BIG_R_QOS_BASE 0xffac8000 -#define CPU_AXI_VOP_BIG_W_QOS_BASE 0xffac8080 -#define CPU_AXI_VOP_LITTLE_QOS_BASE 0xffad0000 -#define CPU_AXI_ISP0_M0_QOS_BASE 0xffaa0000 -#define CPU_AXI_ISP0_M1_QOS_BASE 0xffaa0080 -#define CPU_AXI_ISP1_M0_QOS_BASE 0xffaa8000 -#define CPU_AXI_ISP1_M1_QOS_BASE 0xffaa8080 -#define CPU_AXI_HDCP_QOS_BASE 0xffa90000 -#define CPU_AXI_PERIHP_NSP_QOS_BASE 0xffad8080 -#define CPU_AXI_PERILP_NSP_QOS_BASE 0xffad8180 -#define CPU_AXI_PERILPSLV_NSP_QOS_BASE 0xffad8100 #define PD_CTR_LOOP 500 #define CHK_CPU_LOOP 500 @@ -876,32 +769,6 @@ enum pmu_core_pwr_st { #define GRF_SOC_CON4 0x0e210 -#define GRF_GPIO2A_IOMUX 0xe000 -#define GRF_GPIO2B_IOMUX 0xe004 -#define GRF_GPIO2C_IOMUX 0xe008 -#define GRF_GPIO2D_IOMUX 0xe00c -#define GRF_GPIO3A_IOMUX 0xe010 -#define GRF_GPIO3B_IOMUX 0xe014 -#define GRF_GPIO3C_IOMUX 0xe018 -#define GRF_GPIO3D_IOMUX 0xe01c -#define GRF_GPIO4A_IOMUX 0xe020 -#define GRF_GPIO4B_IOMUX 0xe024 -#define GRF_GPIO4C_IOMUX 0xe028 -#define GRF_GPIO4D_IOMUX 0xe02c - -#define GRF_GPIO2A_P 0xe040 -#define GRF_GPIO2B_P 0xe044 -#define GRF_GPIO2C_P 0xe048 -#define GRF_GPIO2D_P 0xe04C -#define GRF_GPIO3A_P 0xe050 -#define GRF_GPIO3B_P 0xe054 -#define GRF_GPIO3C_P 0xe058 -#define GRF_GPIO3D_P 0xe05C -#define GRF_GPIO4A_P 0xe060 -#define GRF_GPIO4B_P 0xe064 -#define GRF_GPIO4C_P 0xe068 -#define GRF_GPIO4D_P 0xe06C - #define PMUGRF_GPIO0A_SMT 0x0120 #define PMUGRF_SOC_CON0 0x0180 @@ -977,4 +844,7 @@ struct pmu_slpdata_s { }; extern uint32_t clst_warmboot_data[PLATFORM_CLUSTER_COUNT]; + +extern void sram_func_set_ddrctl_pll(uint32_t pll_src); + #endif /* __PMU_H__ */ diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu_regs.h b/plat/rockchip/rk3399/drivers/pmu/pmu_regs.h new file mode 100644 index 000000000..399d844c1 --- /dev/null +++ b/plat/rockchip/rk3399/drivers/pmu/pmu_regs.h @@ -0,0 +1,172 @@ +/* + * 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 __PMU_REGS_H__ +#define __PMU_REGS_H__ + +#define PMU_WKUP_CFG0 0x00 +#define PMU_WKUP_CFG1 0x04 +#define PMU_WKUP_CFG2 0x08 +#define PMU_WKUP_CFG3 0x0c +#define PMU_WKUP_CFG4 0x10 +#define PMU_PWRDN_CON 0x14 +#define PMU_PWRDN_ST 0x18 +#define PMU_PLL_CON 0x1c +#define PMU_PWRMODE_CON 0x20 +#define PMU_SFT_CON 0x24 +#define PMU_INT_CON 0x28 +#define PMU_INT_ST 0x2c +#define PMU_GPIO0_POS_INT_CON 0x30 +#define PMU_GPIO0_NEG_INT_CON 0x34 +#define PMU_GPIO1_POS_INT_CON 0x38 +#define PMU_GPIO1_NEG_INT_CON 0x3c +#define PMU_GPIO0_POS_INT_ST 0x40 +#define PMU_GPIO0_NEG_INT_ST 0x44 +#define PMU_GPIO1_POS_INT_ST 0x48 +#define PMU_GPIO1_NEG_INT_ST 0x4c +#define PMU_PWRDN_INTEN 0x50 +#define PMU_PWRDN_STATUS 0x54 +#define PMU_WAKEUP_STATUS 0x58 +#define PMU_BUS_CLR 0x5c +#define PMU_BUS_IDLE_REQ 0x60 +#define PMU_BUS_IDLE_ST 0x64 +#define PMU_BUS_IDLE_ACK 0x68 +#define PMU_CCI500_CON 0x6c +#define PMU_ADB400_CON 0x70 +#define PMU_ADB400_ST 0x74 +#define PMU_POWER_ST 0x78 +#define PMU_CORE_PWR_ST 0x7c +#define PMU_OSC_CNT 0x80 +#define PMU_PLLLOCK_CNT 0x84 +#define PMU_PLLRST_CNT 0x88 +#define PMU_STABLE_CNT 0x8c +#define PMU_DDRIO_PWRON_CNT 0x90 +#define PMU_WAKEUP_RST_CLR_CNT 0x94 +#define PMU_DDR_SREF_ST 0x98 +#define PMU_SCU_L_PWRDN_CNT 0x9c +#define PMU_SCU_L_PWRUP_CNT 0xa0 +#define PMU_SCU_B_PWRDN_CNT 0xa4 +#define PMU_SCU_B_PWRUP_CNT 0xa8 +#define PMU_GPU_PWRDN_CNT 0xac +#define PMU_GPU_PWRUP_CNT 0xb0 +#define PMU_CENTER_PWRDN_CNT 0xb4 +#define PMU_CENTER_PWRUP_CNT 0xb8 +#define PMU_TIMEOUT_CNT 0xbc +#define PMU_CPU0APM_CON 0xc0 +#define PMU_CPU1APM_CON 0xc4 +#define PMU_CPU2APM_CON 0xc8 +#define PMU_CPU3APM_CON 0xcc +#define PMU_CPU0BPM_CON 0xd0 +#define PMU_CPU1BPM_CON 0xd4 +#define PMU_NOC_AUTO_ENA 0xd8 +#define PMU_PWRDN_CON1 0xdc + +#define PMUGRF_GPIO0A_IOMUX 0x00 +#define PMUGRF_GPIO1A_IOMUX 0x10 +#define PMUGRF_GPIO1C_IOMUX 0x18 + +#define PMUGRF_GPIO0A6_IOMUX_SHIFT 12 +#define PMUGRF_GPIO0A6_IOMUX_PWM 0x1 +#define PMUGRF_GPIO1C3_IOMUX_SHIFT 6 +#define PMUGRF_GPIO1C3_IOMUX_PWM 0x1 + +#define CPU_AXI_QOS_ID_COREID 0x00 +#define CPU_AXI_QOS_REVISIONID 0x04 +#define CPU_AXI_QOS_PRIORITY 0x08 +#define CPU_AXI_QOS_MODE 0x0c +#define CPU_AXI_QOS_BANDWIDTH 0x10 +#define CPU_AXI_QOS_SATURATION 0x14 +#define CPU_AXI_QOS_EXTCONTROL 0x18 +#define CPU_AXI_QOS_NUM_REGS 0x07 + +#define CPU_AXI_CCI_M0_QOS_BASE 0xffa50000 +#define CPU_AXI_CCI_M1_QOS_BASE 0xffad8000 +#define CPU_AXI_DMAC0_QOS_BASE 0xffa64200 +#define CPU_AXI_DMAC1_QOS_BASE 0xffa64280 +#define CPU_AXI_DCF_QOS_BASE 0xffa64180 +#define CPU_AXI_CRYPTO0_QOS_BASE 0xffa64100 +#define CPU_AXI_CRYPTO1_QOS_BASE 0xffa64080 +#define CPU_AXI_PMU_CM0_QOS_BASE 0xffa68000 +#define CPU_AXI_PERI_CM1_QOS_BASE 0xffa64300 +#define CPU_AXI_GIC_QOS_BASE 0xffa78000 +#define CPU_AXI_SDIO_QOS_BASE 0xffa76000 +#define CPU_AXI_SDMMC_QOS_BASE 0xffa74000 +#define CPU_AXI_EMMC_QOS_BASE 0xffa58000 +#define CPU_AXI_GMAC_QOS_BASE 0xffa5c000 +#define CPU_AXI_USB_OTG0_QOS_BASE 0xffa70000 +#define CPU_AXI_USB_OTG1_QOS_BASE 0xffa70080 +#define CPU_AXI_USB_HOST0_QOS_BASE 0xffa60100 +#define CPU_AXI_USB_HOST1_QOS_BASE 0xffa60180 +#define CPU_AXI_GPU_QOS_BASE 0xffae0000 +#define CPU_AXI_VIDEO_M0_QOS_BASE 0xffab8000 +#define CPU_AXI_VIDEO_M1_R_QOS_BASE 0xffac0000 +#define CPU_AXI_VIDEO_M1_W_QOS_BASE 0xffac0080 +#define CPU_AXI_RGA_R_QOS_BASE 0xffab0000 +#define CPU_AXI_RGA_W_QOS_BASE 0xffab0080 +#define CPU_AXI_IEP_QOS_BASE 0xffa98000 +#define CPU_AXI_VOP_BIG_R_QOS_BASE 0xffac8000 +#define CPU_AXI_VOP_BIG_W_QOS_BASE 0xffac8080 +#define CPU_AXI_VOP_LITTLE_QOS_BASE 0xffad0000 +#define CPU_AXI_ISP0_M0_QOS_BASE 0xffaa0000 +#define CPU_AXI_ISP0_M1_QOS_BASE 0xffaa0080 +#define CPU_AXI_ISP1_M0_QOS_BASE 0xffaa8000 +#define CPU_AXI_ISP1_M1_QOS_BASE 0xffaa8080 +#define CPU_AXI_HDCP_QOS_BASE 0xffa90000 +#define CPU_AXI_PERIHP_NSP_QOS_BASE 0xffad8080 +#define CPU_AXI_PERILP_NSP_QOS_BASE 0xffad8180 +#define CPU_AXI_PERILPSLV_NSP_QOS_BASE 0xffad8100 + +#define GRF_GPIO2A_IOMUX 0xe000 +#define GRF_GPIO2B_IOMUX 0xe004 +#define GRF_GPIO2C_IOMUX 0xe008 +#define GRF_GPIO2D_IOMUX 0xe00c +#define GRF_GPIO3A_IOMUX 0xe010 +#define GRF_GPIO3B_IOMUX 0xe014 +#define GRF_GPIO3C_IOMUX 0xe018 +#define GRF_GPIO3D_IOMUX 0xe01c +#define GRF_GPIO4A_IOMUX 0xe020 +#define GRF_GPIO4B_IOMUX 0xe024 +#define GRF_GPIO4C_IOMUX 0xe028 +#define GRF_GPIO4D_IOMUX 0xe02c + +#define GRF_GPIO2A_P 0xe040 +#define GRF_GPIO2B_P 0xe044 +#define GRF_GPIO2C_P 0xe048 +#define GRF_GPIO2D_P 0xe04C +#define GRF_GPIO3A_P 0xe050 +#define GRF_GPIO3B_P 0xe054 +#define GRF_GPIO3C_P 0xe058 +#define GRF_GPIO3D_P 0xe05C +#define GRF_GPIO4A_P 0xe060 +#define GRF_GPIO4B_P 0xe064 +#define GRF_GPIO4C_P 0xe068 +#define GRF_GPIO4D_P 0xe06C + +#endif /* __PMU_REGS_H__ */ diff --git a/plat/rockchip/rk3399/drivers/soc/soc.c b/plat/rockchip/rk3399/drivers/soc/soc.c index e99db19c7..9529cb25f 100644 --- a/plat/rockchip/rk3399/drivers/soc/soc.c +++ b/plat/rockchip/rk3399/drivers/soc/soc.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,8 @@ const mmap_region_t plat_rk_mmap[] = { MAP_REGION_FLAT(RK3399_DEV_RNG0_BASE, RK3399_DEV_RNG0_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), { 0 } }; @@ -237,21 +240,105 @@ static void _pll_suspend(uint32_t pll_id) set_pll_bypass(pll_id); } +/** + * disable_dvfs_plls - To suspend the specific PLLs + * + * When we close the center logic, the DPLL will be closed, + * so we need to keep the ABPLL and switch to it to supply + * clock for DDR during suspend, then we should not close + * the ABPLL and exclude ABPLL_ID. + */ void disable_dvfs_plls(void) { _pll_suspend(CPLL_ID); _pll_suspend(NPLL_ID); _pll_suspend(VPLL_ID); _pll_suspend(GPLL_ID); - _pll_suspend(ABPLL_ID); _pll_suspend(ALPLL_ID); } +/** + * disable_nodvfs_plls - To suspend the PPLL + */ void disable_nodvfs_plls(void) { _pll_suspend(PPLL_ID); } +/** + * restore_pll - Copy PLL settings from memory to a PLL. + * + * This will copy PLL settings from an array in memory to the memory mapped + * registers for a PLL. + * + * Note that: above the PLL exclude PPLL. + * + * pll_id: One of the values from enum plls_id + * src: Pointer to the array of values to restore from + */ +static void restore_pll(int pll_id, uint32_t *src) +{ + /* Nice to have PLL off while configuring */ + mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE); + + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK); + + /* Do PLL_CON3 since that will enable things */ + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK); + + /* Wait for PLL lock done */ + while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) & + 0x80000000) == 0x0) + ; +} + +/** + * save_pll - Copy PLL settings a PLL to memory + * + * This will copy PLL settings from the memory mapped registers for a PLL to + * an array in memory. + * + * Note that: above the PLL exclude PPLL. + * + * pll_id: One of the values from enum plls_id + * src: Pointer to the array of values to save to. + */ +static void save_pll(uint32_t *dst, int pll_id) +{ + int i; + + for (i = 0; i < PLL_CON_COUNT; i++) + dst[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, i)); +} + +/** + * prepare_abpll_for_ddrctrl - Copy DPLL settings to ABPLL + * + * This will copy DPLL settings from the memory mapped registers for a PLL to + * an array in memory. + */ +void prepare_abpll_for_ddrctrl(void) +{ + save_pll(slp_data.plls_con[ABPLL_ID], ABPLL_ID); + save_pll(slp_data.plls_con[DPLL_ID], DPLL_ID); + + restore_pll(ABPLL_ID, slp_data.plls_con[DPLL_ID]); +} + +void restore_abpll(void) +{ + restore_pll(ABPLL_ID, slp_data.plls_con[ABPLL_ID]); +} + +void restore_dpll(void) +{ + restore_pll(DPLL_ID, slp_data.plls_con[DPLL_ID]); +} + void plls_suspend_prepare(void) { uint32_t i, pll_id; @@ -342,16 +429,25 @@ void plls_resume_finish(void) REG_SOC_WMSK | slp_data.pmucru_clksel_con[i]); } +/** + * enable_dvfs_plls - To resume the specific PLLs + * + * Please see the comment at the disable_dvfs_plls() + * we don't suspend the ABPLL, so don't need resume + * it too. + */ void enable_dvfs_plls(void) { _pll_resume(ALPLL_ID); - _pll_resume(ABPLL_ID); _pll_resume(GPLL_ID); _pll_resume(VPLL_ID); _pll_resume(NPLL_ID); _pll_resume(CPLL_ID); } +/** + * enable_nodvfs_plls - To resume the PPLL + */ void enable_nodvfs_plls(void) { _pll_resume(PPLL_ID); @@ -410,4 +506,5 @@ void plat_rockchip_soc_init(void) soc_global_soft_reset_init(); plat_rockchip_gpio_init(); soc_m0_init(); + dram_init(); } diff --git a/plat/rockchip/rk3399/drivers/soc/soc.h b/plat/rockchip/rk3399/drivers/soc/soc.h index 9693f57c4..16897cc5b 100644 --- a/plat/rockchip/rk3399/drivers/soc/soc.h +++ b/plat/rockchip/rk3399/drivers/soc/soc.h @@ -245,6 +245,8 @@ struct deepsleep_data_s { #define SGRF_PMU_SLV_CON1_CFG (SGRF_SLV_S_WMSK | \ SGRF_PMUSRAM_S) /* ddr region */ +#define SGRF_DDR_RGN_DPLL_CLK BIT_WITH_WMSK(15) /* DDR PLL output clock */ +#define SGRF_DDR_RGN_RTC_CLK BIT_WITH_WMSK(14) /* 32K clock for DDR PLL */ #define SGRF_DDR_RGN_BYPS BIT_WITH_WMSK(9) /* All of ddr rgn is ns */ /* The MST access the ddr rgn n with secure attribution */ @@ -334,7 +336,11 @@ void disable_nodvfs_plls(void); void plls_resume_finish(void); void enable_dvfs_plls(void); void enable_nodvfs_plls(void); +void prepare_abpll_for_ddrctrl(void); +void restore_abpll(void); +void restore_dpll(void); void clk_gate_con_save(void); void clk_gate_con_disable(void); void clk_gate_con_restore(void); +void sgrf_init(void); #endif /* __SOC_H__ */ diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c index a20ee2d89..dfda6da99 100644 --- a/plat/rockchip/rk3399/plat_sip_calls.c +++ b/plat/rockchip/rk3399/plat_sip_calls.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #define RK_SIP_DDR_CFG 0x82000008 #define DRAM_INIT 0x00 @@ -45,7 +45,7 @@ uint32_t ddr_smc_handler(uint64_t arg0, uint64_t arg1, uint64_t id) { switch (id) { case DRAM_INIT: - ddr_init(); + ddr_dfs_init(); break; case DRAM_SET_RATE: return ddr_set_rate((uint32_t)arg0); diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index 604de9c8c..1d53804b6 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -79,6 +79,8 @@ BL31_SOURCES += ${RK_GIC_SOURCES} ${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c \ ${RK_PLAT_SOC}/drivers/pwm/pwm.c \ ${RK_PLAT_SOC}/drivers/soc/soc.c \ + ${RK_PLAT_SOC}/drivers/dram/dfs.c \ + ${RK_PLAT_SOC}/drivers/dram/suspend.c \ ${RK_PLAT_SOC}/drivers/dram/dram.c \ ${RK_PLAT_SOC}/drivers/dram/dram_spec_timing.c