diff options
author | Yen Lin <yelin@nvidia.com> | 2015-09-08 15:13:13 -0700 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2015-09-17 14:17:16 +0000 |
commit | 741537e1d99ed7465f5a7e74089667ef1d3a5bfc (patch) | |
tree | 4d3e728fa61a6e06a9552a02affe61d59a54ba7f /src | |
parent | b090a268a2e993fc7fa719ab3b9b7283034c9d10 (diff) | |
download | coreboot-741537e1d99ed7465f5a7e74089667ef1d3a5bfc.tar.gz coreboot-741537e1d99ed7465f5a7e74089667ef1d3a5bfc.tar.bz2 coreboot-741537e1d99ed7465f5a7e74089667ef1d3a5bfc.zip |
t210: lp0_resume: Configure unused SDMMC1/3 pads for low power leakage
In LP0 resume, a couple of SDMMCx pad settings need to be set to 0 to
reduce power leakage.
BUG=None
BRANCH=None
TEST=Tested on Smaug; able to suspend/resume >100 times
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 9f35a90a8af2180443db2c4be75d4566d0990de5
Original-Change-Id: Ifc946b0cea437ef0807cea0c11609d8e09387e8e
Original-Signed-off-by: Yen Lin <yelin@nvidia.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/298195
Original-Reviewed-by: Andrew Bresticker <abrestic@chromium.org>
Original-Reviewed-by: Tom Warren <twarren@nvidia.com>
Original-Tested-by: Joseph Lo <josephl@nvidia.com>
Original-(cherry picked from commit be3ac49a6bc4c9088d3799555d69c87c8ce1693c)
Original-Reviewed-on: https://chromium-review.googlesource.com/298154
Original-Commit-Ready: Furquan Shaikh <furquan@chromium.org>
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Change-Id: If5d5cebc89b8220480b3c72293a410e782eb437e
Reviewed-on: http://review.coreboot.org/11656
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Diffstat (limited to 'src')
-rw-r--r-- | src/soc/nvidia/tegra210/lp0/tegra_lp0_resume.c | 50 |
1 files changed, 50 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 956e8c585660..87e42e361124 100644 --- a/src/soc/nvidia/tegra210/lp0/tegra_lp0_resume.c +++ b/src/soc/nvidia/tegra210/lp0/tegra_lp0_resume.c @@ -30,6 +30,8 @@ enum { PMC_CTLR_BASE = 0x7000e400, MC_CTLR_BASE = 0x70019000, FUSE_BASE = 0x7000F800, + TEGRA_SDMMC1_BASE = 0x700b0000, + TEGRA_SDMMC3_BASE = 0x700b0400, EMC_BASE = 0x7001B000, I2C5_BASE = 0x7000D000, I2S_BASE = 0x702d1000 @@ -79,6 +81,8 @@ enum { SWR_TRIG_SYS_RST = 0x1 << 2 }; +static uint32_t *clk_rst_rst_devices_u_ptr = (void *)(CLK_RST_BASE + 0xc); + static uint32_t *clk_rst_cclkg_burst_policy_ptr = (void *)(CLK_RST_BASE + 0x368); enum { CCLKG_PLLP_BURST_POLICY = 0x20004444 @@ -810,6 +814,49 @@ static void mbist_workaround(void) write32(clk_rst_clk_enb_w_set_ptr, CLK_ENB_MC1); } +static uint32_t *sdmmc1_vendor_io_trim = (void *)(TEGRA_SDMMC1_BASE + 0x1ac); +static uint32_t *sdmmc3_vendor_io_trim = (void *)(TEGRA_SDMMC3_BASE + 0x1ac); +static uint32_t *sdmmc1_comppadctrl = (void *)(TEGRA_SDMMC1_BASE + 0x1e0); +static uint32_t *sdmmc3_comppadctrl = (void *)(TEGRA_SDMMC3_BASE + 0x1e0); + +enum { + SDMMC1_DEV_L = 0x1 << 14, + SDMMC3_DEV_U = 0x1 << 5, + PAD_E_INPUT_COMPPADCTRL = 0x1 << 31, + SEL_VREG_VENDOR_IO_TRIM = 0x1 << 2 +}; + +static void low_power_sdmmc_pads(void) +{ + /* Enable SDMMC1 clock */ + setbits32(SDMMC1_DEV_L, clk_rst_clk_out_enb_l_ptr); + udelay(2); + /* Unreset SDMMC1 */ + clrbits32(SDMMC1_DEV_L, clk_rst_rst_devices_l_ptr); + + /* Clear SEL_VREG bit and PAD_E_INPUT bit of SDMMC1 */ + clrbits32(SEL_VREG_VENDOR_IO_TRIM, sdmmc1_vendor_io_trim); + clrbits32(PAD_E_INPUT_COMPPADCTRL, sdmmc1_comppadctrl); + /* Read the last accessed SDMMC1 register then disable SDMMC1 clock */ + read32(sdmmc1_comppadctrl); + /* Disable SDMMC1 clock, but keep SDMMC1 un-reset */ + clrbits32(SDMMC1_DEV_L, clk_rst_clk_out_enb_l_ptr); + + /* Enable SDMMC3 clock */ + setbits32(SDMMC3_DEV_U, clk_rst_clk_out_enb_u_ptr); + udelay(2); + /* Unreset SDMMC3 */ + clrbits32(SDMMC3_DEV_U, clk_rst_rst_devices_u_ptr); + + /* Clear SEL_VREG bit and PAD_E_INPUT bit of SDMMC3 */ + clrbits32(SEL_VREG_VENDOR_IO_TRIM, sdmmc3_vendor_io_trim); + clrbits32(PAD_E_INPUT_COMPPADCTRL, sdmmc3_comppadctrl); + /* Read the last accessed SDMMC3 register then disable SDMMC3 clock */ + read32(sdmmc3_comppadctrl); + /* Disable SDMMC3 clock, but keep SDMMC3 un-reset */ + clrbits32(SDMMC3_DEV_U, clk_rst_clk_out_enb_u_ptr); +} + static void config_mselect(void) { /* Set MSELECT clock source to PLL_P with 1:4 divider */ @@ -895,6 +942,9 @@ void lp0_resume(void) /* Restore CAR CE's, SLCG overrides */ mbist_workaround(); + /* Configure unused SDMMC1/3 pads for low power leakage */ + low_power_sdmmc_pads(); + /* * Find out which CPU (slow or fast) to wake up. The default setting * in flow controller is to wake up GCPU |