diff options
author | Yen Lin <yelin@nvidia.com> | 2015-07-21 11:52:12 -0700 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2015-07-29 19:29:03 +0200 |
commit | dec2751847a0385bbcbdb14c929b91605e7dc2db (patch) | |
tree | d17ef3a8aac582fc88715efe94da71c2c00c5ada /src/soc/nvidia | |
parent | dd7e59892d3125e891271039f931d03c6036ab09 (diff) |
t210: lp0_resume: implement MBIST workaround
As in cold boot path, implement MBIST workaround in lp0
resume path.
BUG=chrome-os-partner:40741
BRANCH=None
TEST=Tested on Smaug; able to suspend/resume
Change-Id: I997009ecb0f52fb5a47c62b8daea33e472ec2664
Signed-off-by: Patrick Georgi <pgeorgi@google.com>
Original-Commit-Id: 4b1f80ea4c1d3782eb9f2c90c2a8d7b2e97ba050
Original-Change-Id: Ib4944401e1df02bf0aab1e78db7e14ef56c7f829
Original-Reviewed-on: https://chromium-review.googlesource.com/287287
Original-Tested-by: Yen Lin <yelin@nvidia.com>
Original-Reviewed-by: Tom Warren <twarren@nvidia.com>
Original-Reviewed-by: Benson Leung <bleung@chromium.org>
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Original-Commit-Queue: Yen Lin <yelin@nvidia.com>
Reviewed-on: http://review.coreboot.org/11071
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/soc/nvidia')
-rw-r--r-- | src/soc/nvidia/tegra210/lp0/tegra_lp0_resume.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/soc/nvidia/tegra210/lp0/tegra_lp0_resume.c b/src/soc/nvidia/tegra210/lp0/tegra_lp0_resume.c index fdd25dd8ca..5ef03d0126 100644 --- a/src/soc/nvidia/tegra210/lp0/tegra_lp0_resume.c +++ b/src/soc/nvidia/tegra210/lp0/tegra_lp0_resume.c @@ -194,6 +194,12 @@ enum { CLK_M_DIVISOR_BY_2 = 0x1 << 2 }; +static uint32_t *clk_rst_lvl2_clk_gate_ovra_ptr = (void *)(CLK_RST_BASE + 0xf8); +static uint32_t *clk_rst_lvl2_clk_gate_ovrb_ptr = (void *)(CLK_RST_BASE + 0xfc); +static uint32_t *clk_rst_lvl2_clk_gate_ovrc_ptr = (void *)(CLK_RST_BASE + 0x3a0); +static uint32_t *clk_rst_lvl2_clk_gate_ovrd_ptr = (void *)(CLK_RST_BASE + 0x3a4); +static uint32_t *clk_rst_lvl2_clk_gate_ovre_ptr = (void *)(CLK_RST_BASE + 0x554); + static uint32_t *clk_rst_clk_out_enb_l_ptr = (void *)(CLK_RST_BASE + 0x10); static uint32_t *clk_rst_clk_out_enb_h_ptr = (void *)(CLK_RST_BASE + 0x14); static uint32_t *clk_rst_clk_out_enb_u_ptr = (void *)(CLK_RST_BASE + 0x18); @@ -210,6 +216,14 @@ static uint32_t *clk_rst_clk_enb_w_clr_ptr = (void *)(CLK_RST_BASE + 0x44c); static uint32_t *clk_rst_clk_enb_x_clr_ptr = (void *)(CLK_RST_BASE + 0x288); static uint32_t *clk_rst_clk_enb_y_clr_ptr = (void *)(CLK_RST_BASE + 0x2a0); +#define MBIST_CLK_ENB_L_0 0x80000130 +#define MBIST_CLK_ENB_H_0 0x020000C1 +#define MBIST_CLK_ENB_U_0 0x01F00200 +#define MBIST_CLK_ENB_V_0 0x80400008 +#define MBIST_CLK_ENB_W_0 0x002000FC +#define MBIST_CLK_ENB_X_0 0x23004780 +#define MBIST_CLK_ENB_Y_0 0x00000300 + static uint32_t *clk_rst_clk_enb_v_ptr = (void *)(CLK_RST_BASE + 0x440); enum { CLK_ENB_MSELECT = 0x1 << 3 @@ -368,6 +382,11 @@ enum { TRAINING_E_WRPTR = 0x1 << 3 }; +static uint32_t *fbio_cfg7_ptr = (void *)(EMC_BASE + 0x584); +enum { + CH1_ENABLE = 0x1 << 2 +}; + /* I2C5 registers */ static uint32_t *i2c5_cnfg_ptr = (void *)(I2C5_BASE + 0x0); enum { @@ -685,6 +704,49 @@ static void set_pmacro_training_wrptr(void) write32(pmacro_cfg_pm_global, ENABLE_CFG_BYTES); } +static void mbist_workaround(void) +{ + uint32_t clks_to_be_cleared; + + write32(clk_rst_lvl2_clk_gate_ovra_ptr, 0); + write32(clk_rst_lvl2_clk_gate_ovrb_ptr, 0); + write32(clk_rst_lvl2_clk_gate_ovrc_ptr, 0); + write32(clk_rst_lvl2_clk_gate_ovrd_ptr, 0x01000000); /* QSPI OVR=1 */ + write32(clk_rst_lvl2_clk_gate_ovre_ptr, 0); + + clks_to_be_cleared = read32(clk_rst_clk_out_enb_l_ptr); + clks_to_be_cleared &= ~MBIST_CLK_ENB_L_0; + write32(clk_rst_clk_enb_l_clr_ptr, clks_to_be_cleared); + + clks_to_be_cleared = read32(clk_rst_clk_out_enb_h_ptr); + clks_to_be_cleared &= ~MBIST_CLK_ENB_H_0; + write32(clk_rst_clk_enb_h_clr_ptr, clks_to_be_cleared); + + clks_to_be_cleared = read32(clk_rst_clk_out_enb_u_ptr); + clks_to_be_cleared &= ~MBIST_CLK_ENB_U_0; + write32(clk_rst_clk_enb_u_clr_ptr, clks_to_be_cleared); + + clks_to_be_cleared = read32(clk_rst_clk_out_enb_v_ptr); + clks_to_be_cleared &= ~MBIST_CLK_ENB_V_0; + write32(clk_rst_clk_enb_v_clr_ptr, clks_to_be_cleared); + + clks_to_be_cleared = read32(clk_rst_clk_out_enb_w_ptr); + clks_to_be_cleared &= ~MBIST_CLK_ENB_W_0; + write32(clk_rst_clk_enb_w_clr_ptr, clks_to_be_cleared); + + clks_to_be_cleared = read32(clk_rst_clk_out_enb_x_ptr); + clks_to_be_cleared &= ~MBIST_CLK_ENB_X_0; + write32(clk_rst_clk_enb_x_clr_ptr, clks_to_be_cleared); + + clks_to_be_cleared = read32(clk_rst_clk_out_enb_y_ptr); + clks_to_be_cleared &= ~MBIST_CLK_ENB_Y_0; + write32(clk_rst_clk_enb_y_clr_ptr, clks_to_be_cleared); + + if (read32(fbio_cfg7_ptr) & CH1_ENABLE) + /* if Dual Channel enable MC1 clock */ + write32(clk_rst_clk_enb_w_set_ptr, CLK_ENB_MC1); +} + static void config_mselect(void) { /* Set MSELECT clock source to PLL_P with 1:4 divider */ @@ -767,6 +829,9 @@ void lp0_resume(void) /* Bad qpop value on cmd pad macros removes clock gating from IB path */ set_pmacro_training_wrptr(); + /* Restore CAR CE's, SLCG overrides */ + mbist_workaround(); + /* * Find out which CPU (slow or fast) to wake up. The default setting * in flow controller is to wake up GCPU |