Merge pull request #750 from jwerner-chromium/m0_build
RK3399 M0 build system improvements
diff --git a/Makefile b/Makefile
index b73a4dd..abfc156 100644
--- a/Makefile
+++ b/Makefile
@@ -666,7 +666,7 @@
checkpatch: locate-checkpatch
@echo " CHECKING STYLE"
- ${Q}git log -p ${BASE_COMMIT}..HEAD -- ${CHECK_PATHS} | ${CHECKPATCH} - || true
+ ${Q}git format-patch --stdout ${BASE_COMMIT}..HEAD -- ${CHECK_PATHS} | ${CHECKPATCH} - || true
certtool: ${CRTTOOL}
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index aa014f1..7534e39 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -1087,13 +1087,15 @@
Argument : uintptr_t mem_base, unsigned int mem_size,
unsigned int flags
- Return : void
+ Return : int
BL1 calls this function while handling FWU copy and authenticate SMCs. The
platform must ensure that the provided `mem_base` and `mem_size` are mapped into
BL1, and that this memory corresponds to either a secure or non-secure memory
region as indicated by the security state of the `flags` argument.
+This function must return 0 on success, a non-null error code otherwise.
+
The default implementation of this function asserts therefore platforms must
override it when using the FWU feature.
diff --git a/docs/user-guide.md b/docs/user-guide.md
index 5b73b66..140977e 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -466,6 +466,12 @@
Note: `TRUSTED_BOARD_BOOT` is currently not supported when `LOAD_IMAGE_V2`
is enabled.
+* `ENABLE_RUNTIME_INSTRUMENTATION`: Boolean option to enable runtime
+ instrumentation which injects timestamp collection points into
+ Trusted Firmware to allow runtime performance to be measured.
+ Currently, only PSCI is instrumented. Enabling this option enables
+ the `ENABLE_PMF` build option as well. Default is 0.
+
#### ARM development platform specific build options
* `ARM_TSP_RAM_LOCATION`: location of the TSP binary. Options:
diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.c b/plat/rockchip/rk3399/drivers/dram/dfs.c
new file mode 100644
index 0000000..4fdd389
--- /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 <debug.h>
+#include <mmio.h>
+#include <plat_private.h>
+#include "dfs.h"
+#include "dram.h"
+#include "dram_spec_timing.h"
+#include "string.h"
+#include "soc.h"
+#include "pmu.h"
+
+#include <delay_timer.h>
+
+#define CTL_TRAINING (1)
+#define PI_TRAINING (!CTL_TRAINING)
+
+#define EN_READ_GATE_TRAINING (1)
+#define EN_CA_TRAINING (0)
+#define EN_WRITE_LEVELING (0)
+#define EN_READ_LEVELING (0)
+#define EN_WDQ_LEVELING (0)
+
+#define ENPER_CS_TRAINING_FREQ (933)
+
+struct pll_div {
+ unsigned int mhz;
+ unsigned int refdiv;
+ unsigned int fbdiv;
+ unsigned int postdiv1;
+ unsigned int postdiv2;
+ unsigned int frac;
+ unsigned int freq;
+};
+
+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 0000000..1da0903
--- /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 94aa076..5f6f0fc 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 <debug.h>
-#include <mmio.h>
+#include <dram.h>
#include <plat_private.h>
-#include "dram.h"
-#include "dram_spec_timing.h"
-#include "string.h"
-#include "soc.h"
-#include "pmu.h"
+#include <soc.h>
+#include <rk3399_def.h>
-#include <delay_timer.h>
+__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));
-
- 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);
-}
-
-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)
+ 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;
-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;
+ for (i = 0; i < 2; i++) {
+ struct rk3399_sdram_channel *ch = &sdram_config.ch[i];
+ struct rk3399_msch_timings *noc = &ch->noc_timings;
- 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)))
- 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;
-}
-
-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)))
+ if (!(SYS_REG_DEC_CHINFO(os_reg2_val, i)))
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));
- }
-}
-
-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;
+ 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);
- 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;
+ 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);
}
- 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 4f99070..44dfbbd 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 <plat_private.h>
+#include <stdint.h>
-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 @@
} 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 @@
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_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))))
+extern __sramdata struct rk3399_sdram_params sdram_config;
-#define DDR_RESTORE_SP(save_sp) ddr_save_sp(save_sp)
+void dram_init(void);
-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);
#endif
diff --git a/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c
index b015db7..fbf1d39 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 <string.h>
#include <stdint.h>
+#include <dram.h>
#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 2008332..662aeab 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 <stdint.h>
-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 0000000..f408d67
--- /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 <debug.h>
+#include <arch_helpers.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <dram.h>
+#include <pmu_regs.h>
+#include <rk3399_def.h>
+#include <soc.h>
+#include <suspend.h>
+
+#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 0000000..2159861
--- /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 <dram.h>
+
+#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 7241964..405e1d5 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 <arch.h>
#include <asm_macros.S>
#include <platform_def.h>
+#include <pmu_regs.h>
.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 @@
.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 8d3f482..5a385cb 100644
--- a/plat/rockchip/rk3399/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c
@@ -46,9 +46,9 @@
#include <pmu.h>
#include <pmu_com.h>
#include <pwm.h>
-#include <soc.h>
#include <bl31.h>
#include <rk3399m0.h>
+#include <suspend.h>
DEFINE_BAKERY_LOCK(rockchip_pd_lock);
@@ -102,7 +102,6 @@
mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ACK),
bus_ack);
}
-
}
struct pmu_slpdata_s pmu_slpdata;
@@ -818,10 +817,19 @@
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 @@
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 @@
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 @@
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 @@
(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 @@
}
}
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 @@
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 @@
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 @@
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 ab2896b..22c8c63 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 <pmu_regs.h>
+#include <soc.h>
+
/* Allocate sp reginon in pmusram */
#define PSRAM_SP_SIZE 0x80
#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE)
@@ -751,72 +754,7 @@
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 @@
#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 @@
#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 @@
};
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 0000000..399d844
--- /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 e99db19..9529cb2 100644
--- a/plat/rockchip/rk3399/drivers/soc/soc.c
+++ b/plat/rockchip/rk3399/drivers/soc/soc.c
@@ -34,6 +34,7 @@
#include <mmio.h>
#include <platform_def.h>
#include <plat_private.h>
+#include <dram.h>
#include <rk3399_def.h>
#include <rk3399m0.h>
#include <soc.h>
@@ -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 @@
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 @@
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 @@
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 9693f57..16897cc 100644
--- a/plat/rockchip/rk3399/drivers/soc/soc.h
+++ b/plat/rockchip/rk3399/drivers/soc/soc.h
@@ -245,6 +245,8 @@
#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 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 a20ee2d..dfda6da 100644
--- a/plat/rockchip/rk3399/plat_sip_calls.c
+++ b/plat/rockchip/rk3399/plat_sip_calls.c
@@ -29,7 +29,7 @@
#include <plat_sip_calls.h>
#include <rockchip_sip_svc.h>
#include <runtime_svc.h>
-#include <dram.h>
+#include <dfs.h>
#define RK_SIP_DDR_CFG 0x82000008
#define DRAM_INIT 0x00
@@ -45,7 +45,7 @@
{
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 059ee7b..3628dc3 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -79,6 +79,8 @@
${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
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index 97a9fbd..010bb8f 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -81,9 +81,14 @@
uint64_t ret;
#if ENABLE_RUNTIME_INSTRUMENTATION
+
+ /*
+ * Flush cache line so that even if CPU power down happens
+ * the timestamp update is reflected in memory.
+ */
PMF_WRITE_TIMESTAMP(rt_instr_svc,
RT_INSTR_ENTER_PSCI,
- PMF_NO_CACHE_MAINT,
+ PMF_CACHE_MAINT,
get_cpu_data(cpu_data_pmf_ts[CPU_DATA_PMF_TS0_IDX]));
#endif