diff options
author | Andrew Bresticker <abrestic@chromium.org> | 2013-12-18 22:41:34 -0800 |
---|---|---|
committer | Isaac Christensen <isaac.christensen@se-eng.com> | 2014-09-22 19:00:19 +0200 |
commit | 24d4f7f8defca9c68d4a96ba5cbedf5b01ca6e53 (patch) | |
tree | a38ef152b5381a72d68cef5e1860daffd1198227 /src/soc | |
parent | d65e214d666269d0bd20d88ba2bc83349810c668 (diff) |
tegra124/nyan: memory and display updates
tegra124: use pll_c_out1 as sclk parent
Reviewed-on: https://chromium-review.googlesource.com/180865
(cherry picked from commit 418337a5bde70df6a770222201c51bf3e8892d5f)
tegra124: take LP cluster out of reset
Reviewed-on: https://chromium-review.googlesource.com/180866
(cherry picked from commit 74cdc68ea9b29da9af313635787e82bacb9e23e3)
tegra124: norrin: display code clean up
Reviewed-on: https://chromium-review.googlesource.com/181003
(cherry picked from commit 63843ec61b3b47ffc985edcb589771591c5c9f17)
tegra124: Change the display hack to use window A
Reviewed-on: https://chromium-review.googlesource.com/182001
(cherry picked from commit ef245e42eb17b2eb0e8712f252353a95ee6fc01a)
tegra124: norrin: Initialize frame buffer
Reviewed-on: https://chromium-review.googlesource.com/182090
(cherry picked from commit b7c1d1b3c9519cbbe1615737aed4c4c0efed2167)
nyan: do not enable pull-ups on SPI1 (EC) data pins
Reviewed-on: https://chromium-review.googlesource.com/181063
(cherry picked from commit 2f55188501ebcae9e01b12831f152d4520c7047c)
tegra124: Add source for the LP0 resume blob.
Reviewed-on: https://chromium-review.googlesource.com/183152
(cherry picked from commit a00d099bf710c297320d7edff7f7c608283d1b0b)
tegra124: Revise Memory Controller registers structure definition.
Reviewed-on: https://chromium-review.googlesource.com/182992
(cherry picked from commit ae83564cdd1d46c8166df1a95703e8cb1060c0a1)
tegra124: Add more PMC register details.
Reviewed-on: https://chromium-review.googlesource.com/183231
(cherry picked from commit d62ed2c19693284f10c2a12f4295091de3ace829)
tegra124: Add SDRAM configuration header file from cbootimage.
Reviewed-on: https://chromium-review.googlesource.com/182613
(cherry picked from commit 193ed2a104af38f6c41a332a649ce06a3238e0a4)
tegra124: Revise sdram_param.h for Coreboot.
Reviewed-on: https://chromium-review.googlesource.com/182614
(cherry picked from commit 311b0568c5de627435a5b035a7a1e40ecc2672f8)
tegra124: Fix EMC base address.
Reviewed-on: https://chromium-review.googlesource.com/183602
(cherry picked from commit 587c8969292ccecfa29c7720bcf24c704ed4ac4e)
tegra124: Add EMC registers definition.
Reviewed-on: https://chromium-review.googlesource.com/183622
(cherry picked from commit 67a8e5c7e87a1cc6bf006ad806751b549ffd3d5a)
tegra124: Never touch MEM(MC)/EMC clocks in ramstage.
Reviewed-on: https://chromium-review.googlesource.com/183623
(cherry picked from commit 8e3bb34d4ae37feae89b4a39850b2988a334d023)
tegra124: use RAM_CODE[3:2] for ram code
Reviewed-on: https://chromium-review.googlesource.com/183833
(cherry picked from commit 0154239467064ffcbdb82fc4c6b629f5d0c3568d)
tegra124: Allow setting PLLM (clock for SDRAM).
Reviewed-on: https://chromium-review.googlesource.com/183621
(cherry picked from commit a534e5b7c61d655eedd409dbd7780a4f90d40683)
tegra124: SDRAM Initialization.
Reviewed-on: https://chromium-review.googlesource.com/182615
(cherry picked from commit 5a60ae93b0603ee0d4806132be0360f3b1612bce)
tegra124: Get RAM_CODE for SDRAM initialization.
Reviewed-on: https://chromium-review.googlesource.com/183781
(cherry picked from commit a5b7ce70525d7ffef3fac90b8eb14b3f3787f4d8)
Squashed 18 nyan/tegra commits for memory and display.
Change-Id: I59a781ee8dc2fd9c9085373f5a9bb7c8108b094c
Signed-off-by: Isaac Christensen <isaac.christensen@se-eng.com>
Reviewed-on: http://review.coreboot.org/6914
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Tested-by: build bot (Jenkins)
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/nvidia/tegra124/Makefile.inc | 2 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/clk_rst.h | 25 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/clock.c | 74 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/display.c | 15 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/displayhack.c | 303 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/dp.c | 197 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/emc.h | 323 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/include/soc/addressmap.h | 2 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/include/soc/clock.h | 3 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/include/soc/display.h | 17 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/lp0/Makefile | 58 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.c | 627 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.ld | 73 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/mc.h | 127 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/pmc.h | 206 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/sdram.c | 611 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/sdram.h | 28 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/sdram_param.h | 816 |
18 files changed, 3146 insertions, 361 deletions
diff --git a/src/soc/nvidia/tegra124/Makefile.inc b/src/soc/nvidia/tegra124/Makefile.inc index b743570cbf..7a6bcedbe0 100644 --- a/src/soc/nvidia/tegra124/Makefile.inc +++ b/src/soc/nvidia/tegra124/Makefile.inc @@ -20,10 +20,12 @@ endif romstage-y += cbfs.c romstage-y += cbmem.c +romstage-y += clock.c romstage-y += early_display.c romstage-y += dma.c romstage-y += i2c.c romstage-y += monotonic_timer.c +romstage-y += sdram.c romstage-y += spi.c romstage-y += ../tegra/gpio.c romstage-y += ../tegra/i2c.c diff --git a/src/soc/nvidia/tegra124/clk_rst.h b/src/soc/nvidia/tegra124/clk_rst.h index 156e9a69fa..efceec5f31 100644 --- a/src/soc/nvidia/tegra124/clk_rst.h +++ b/src/soc/nvidia/tegra124/clk_rst.h @@ -352,10 +352,20 @@ check_member(clk_rst_ctlr, clk_src_soc_therm, 0x644); #define PLL_BASE_DIVM_MASK (0x1f << PLL_BASE_DIVM_SHIFT) /* SPECIAL CASE: PLLM, PLLC and PLLX use different-sized fields here */ -#define PLLCMX_BASE_DIVP_MASK (0xfU << PLL_BASE_DIVP_SHIFT) +#define PLLCX_BASE_DIVP_MASK (0xfU << PLL_BASE_DIVP_SHIFT) +#define PLLM_BASE_DIVP_MASK (0x1U << PLL_BASE_DIVP_SHIFT) #define PLLCMX_BASE_DIVN_MASK (0xffU << PLL_BASE_DIVN_SHIFT) #define PLLCMX_BASE_DIVM_MASK (0xffU << PLL_BASE_DIVM_SHIFT) +/* PLLM specific registers */ +#define PLLM_MISC1_SETUP_SHIFT 0 +#define PLLM_MISC1_PD_LSHIFT_PH45_SHIFT 28 +#define PLLM_MISC1_PD_LSHIFT_PH90_SHIFT 29 +#define PLLM_MISC1_PD_LSHIFT_PH135_SHIFT 30 +#define PLLM_MISC2_KCP_SHIFT 1 +#define PLLM_MISC2_KVCO_SHIFT 0 +#define PLLM_OUT1_RSTN_RESET_DISABLE (1 << 0) + /* Generic, indiscriminate divisor mask. May catch some innocent bystander bits * on the side that we don't particularly care about. */ #define PLL_BASE_DIV_MASK (0xffffff) @@ -414,6 +424,8 @@ check_member(clk_rst_ctlr, clk_src_soc_therm, 0x644); #define CLK_SOURCE_SHIFT 29 #define CLK_SOURCE_MASK (0x7 << CLK_SOURCE_SHIFT) +#define CLK_SOURCE_EMC_MC_EMC_SAME_FREQ (1 << 16) + #define CLK_UART_DIV_OVERRIDE (1 << 24) /* CLK_RST_CONTROLLER_SCLK_BURST_POLICY */ @@ -525,4 +537,15 @@ enum { CRC_RST_CPUG_CLR_PDBG = 0x1 << 30, }; +// RST_CPULP_CMPLX_CLR +enum { + CRC_RST_CPULP_CLR_CPU0 = 0x1 << 0, + CRC_RST_CPULP_CLR_DBG0 = 0x1 << 12, + CRC_RST_CPULP_CLR_CORE0 = 0x1 << 16, + CRC_RST_CPULP_CLR_CX0 = 0x1 << 20, + CRC_RST_CPULP_CLR_L2 = 0x1 << 24, + CRC_RST_CPULP_CLR_NONCPU = 0x1 << 29, + CRC_RST_CPULP_CLR_PDBG = 0x1 << 30, +}; + #endif /* _TEGRA124_CLK_RST_H_ */ diff --git a/src/soc/nvidia/tegra124/clock.c b/src/soc/nvidia/tegra124/clock.c index d98da29469..a642a7bcd4 100644 --- a/src/soc/nvidia/tegra124/clock.c +++ b/src/soc/nvidia/tegra124/clock.c @@ -327,6 +327,63 @@ void clock_external_output(int clk_id) } } +/* Start PLLM for SDRAM. */ +void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, + u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source, + u32 same_freq) +{ + u32 misc1 = ((setup << PLLM_MISC1_SETUP_SHIFT) | + (ph45 << PLLM_MISC1_PD_LSHIFT_PH45_SHIFT) | + (ph90 << PLLM_MISC1_PD_LSHIFT_PH90_SHIFT) | + (ph135 << PLLM_MISC1_PD_LSHIFT_PH135_SHIFT)), + misc2 = ((kvco << PLLM_MISC2_KVCO_SHIFT) | + (kcp << PLLM_MISC2_KCP_SHIFT)), + base; + + if (same_freq) + emc_source |= CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; + else + emc_source &= ~CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; + + /* + * Note PLLM_BASE.PLLM_OUT1_RSTN must be in RESET_ENABLE mode, and + * PLLM_BASE.ENABLE must be in DISABLE state (both are the default + * values after coldboot reset). + */ + + writel(misc1, &clk_rst->pllm_misc1); + writel(misc2, &clk_rst->pllm_misc2); + + /* PLLM.BASE needs BYPASS=0, different from general init_pll */ + base = readl(&clk_rst->pllm_base); + base &= ~(PLLCMX_BASE_DIVN_MASK | PLLCMX_BASE_DIVM_MASK | + PLLM_BASE_DIVP_MASK | PLL_BASE_BYPASS); + base |= ((m << PLL_BASE_DIVM_SHIFT) | (n << PLL_BASE_DIVN_SHIFT) | + (p << PLL_BASE_DIVP_SHIFT)); + writel(base, &clk_rst->pllm_base); + + setbits_le32(&clk_rst->pllm_base, PLL_BASE_ENABLE); + /* stable_time is required, before we can start to check lock. */ + udelay(stable_time); + + while (!(readl(&clk_rst->pllm_base) & PLL_BASE_LOCK)) { + udelay(1); + } + /* + * After PLLM reports being locked, we have to delay 10us before + * enabling PLLM_OUT. + */ + udelay(10); + + /* Put OUT1 out of reset state (start to output). */ + setbits_le32(&clk_rst->pllm_out, PLLM_OUT1_RSTN_RESET_DISABLE); + + /* Enable and start MEM(MC) and EMC. */ + clock_enable_clear_reset(0, CLK_H_MEM | CLK_H_EMC, 0, 0, 0, 0); + writel(emc_source, &clk_rst->clk_src_emc); + udelay(IO_STABILIZATION_DELAY); +} + void clock_cpu0_config_and_reset(void *entry) { void * const evp_cpu_reset = (uint8_t *)TEGRA_EVP_BASE + 0x100; @@ -357,6 +414,7 @@ void clock_cpu0_config_and_reset(void *entry) // Enable other CPU related clocks. setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_CPU); setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPUG); + setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPULP); // Disable the reset on the non-CPU parts of the fast cluster. write32(CRC_RST_CPUG_CLR_NONCPU, @@ -372,6 +430,15 @@ void clock_cpu0_config_and_reset(void *entry) CRC_RST_CPUG_CLR_CX2 | CRC_RST_CPUG_CLR_CX3 | CRC_RST_CPUG_CLR_L2 | CRC_RST_CPUG_CLR_PDBG, &clk_rst->rst_cpug_cmplx_clr); + + // Disable the reset on the non-CPU parts of the slow cluster. + write32(CRC_RST_CPULP_CLR_NONCPU, + &clk_rst->rst_cpulp_cmplx_clr); + // Disable the various resets on the LP CPU. + write32(CRC_RST_CPULP_CLR_CPU0 | CRC_RST_CPULP_CLR_DBG0 | + CRC_RST_CPULP_CLR_CORE0 | CRC_RST_CPULP_CLR_CX0 | + CRC_RST_CPULP_CLR_L2 | CRC_RST_CPULP_CLR_PDBG, + &clk_rst->rst_cpulp_cmplx_clr); } void clock_halt_avp(void) @@ -401,11 +468,10 @@ void clock_init(void) * features section in the TRM). */ write32(1 << HCLK_DIVISOR_SHIFT | 0 << PCLK_DIVISOR_SHIFT, &clk_rst->clk_sys_rate); /* pclk = hclk = sclk/2 */ - write32(0 << SCLK_DIVIDEND_SHIFT | - (CEIL_DIV(TEGRA_PLLC_KHZ, 300000) - 1) << SCLK_DIVISOR_SHIFT - | SCLK_DIV_ENB, &clk_rst->super_sclk_div); + write32(CLK_DIVIDER(TEGRA_PLLC_KHZ, 300000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_CLKEN | PLL_OUT_RSTN, &clk_rst->pllc_out); write32(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT | - SCLK_SOURCE_PLLC_OUT0 << SCLK_RUN_SHIFT, + SCLK_SOURCE_PLLC_OUT1 << SCLK_RUN_SHIFT, &clk_rst->sclk_brst_pol); /* sclk = 300 MHz */ /* Change the oscillator drive strength (from U-Boot -- why?) */ diff --git a/src/soc/nvidia/tegra124/display.c b/src/soc/nvidia/tegra124/display.c index 0572ce3181..ba357fd245 100644 --- a/src/soc/nvidia/tegra124/display.c +++ b/src/soc/nvidia/tegra124/display.c @@ -301,11 +301,6 @@ void display_startup(device_t dev) /* init dc_a */ init_dca_regs(); - /* init sor */ - init_sor_regs(); - - /* init dpaux */ - init_dpaux_regs(); /* power up perip */ dp_io_powerup(); @@ -313,13 +308,9 @@ void display_startup(device_t dev) /* bringup dp */ dp_bringup(framebuffer_base_mb*MiB); - { u16 *cp = (void *)(framebuffer_base_mb*MiB); - for(i = 0; i < 1048576*8; i++) - if (i % (1376 / 2) < 688 / 2) - cp[i] = 0x222; - else - cp[i] = 0x888; - } + /* init frame buffer */ + memset((void *)(framebuffer_base_mb*MiB), 0x00, + framebuffer_size_mb*MiB); /* tell depthcharge ... */ diff --git a/src/soc/nvidia/tegra124/displayhack.c b/src/soc/nvidia/tegra124/displayhack.c index 0f70e928c7..af0ac16673 100644 --- a/src/soc/nvidia/tegra124/displayhack.c +++ b/src/soc/nvidia/tegra124/displayhack.c @@ -46,11 +46,6 @@ void debug_dpaux_print(u32 addr, u32 size); int dpaux_write(u32 addr, u32 size, u32 data); int dpaux_read(u32 addr, u32 size, u8 * data); -void init_dca_regs(void) -{ - printk(BIOS_SPEW, "%s: entry\n", __func__); - -#if 1 #define DCA_WRITE(reg, val) \ { \ WRITEL(val, (void *)(TEGRA_ARM_DISPLAYA + (reg<<2))); \ @@ -63,17 +58,31 @@ void init_dca_regs(void) _reg_val |= val; \ WRITEL(_reg_val, (void *)(TEGRA_ARM_DISPLAYA + (reg<<2))); \ } -#else // read back -#define DCA_WRITE(reg, val) \ + +#define SOR_WRITE(reg, val) \ + { \ + WRITEL(val, (void *)(TEGRA_ARM_SOR + (reg<<2))); \ + } + +#define SOR_READ(reg) READL((void *)(TEGRA_ARM_SOR + (reg<<2))) + +#define SOR_READ_M_WRITE(reg, mask, val) \ + { \ + u32 _reg_val; \ + _reg_val = READL((void *)(TEGRA_ARM_SOR + (reg<<2))); \ + _reg_val &= ~mask; \ + _reg_val |= val; \ + WRITEL(_reg_val, (void *)(TEGRA_ARM_SOR + (reg<<2))); \ + } + +#define DPAUX_WRITE(reg, val) \ { \ - printk(BIOS_SPEW,"DCA_WRITE: addr %#x = %#x\n", - (unsigned int) (TEGRA_ARM_DISPLAYA + (reg<<2)), val); \ - WRITEL(val, (void *)(TEGRA_ARM_DISPLAYA + (reg<<2))); \ - printk(BIOS_SPEW,"reads as %#x\n", \ - (unsigned int)READL( (void *)(TEGRA_ARM_DISPLAYA + (reg<<2)))); \ + WRITEL(val, (void *)(TEGRA_ARM_DPAUX + (reg<<2))); \ } -#endif +#define DPAUX_READ(reg) READL((void *)(TEGRA_ARM_DPAUX + (reg<<2))) +void init_dca_regs(void) +{ DCA_WRITE (DC_CMD_DISPLAY_WINDOW_HEADER_0, 0x000000F0); DCA_WRITE (DC_WIN_A_WIN_OPTIONS_0, 0x00000000); DCA_WRITE (DC_WIN_A_BYTE_SWAP_0, 0x00000000); @@ -105,86 +114,20 @@ void init_dca_regs(void) DCA_WRITE (DC_COM_PIN_OUTPUT_ENABLE1_0, 0x00000000); DCA_WRITE (DC_COM_PIN_OUTPUT_ENABLE2_0, 0x00510104); DCA_WRITE (DC_COM_PIN_OUTPUT_ENABLE3_0, 0x00000555); - - printk(BIOS_SPEW, "initial DCA done\n"); -} - -void init_sor_regs(void) -{ - - printk(BIOS_SPEW, "JZ: %s: entry\n", __func__); - -#if 1 -#define SOR_WRITE(reg, val) \ - { \ - WRITEL(val, (void *)(TEGRA_ARM_SOR + (reg<<2))); \ - } - -#define SOR_READ(reg) READL( (void *)(TEGRA_ARM_SOR + (reg<<2))) - -#else // read back -#define SOR_WRITE(reg, val) \ - { \ - printk(BIOS_SPEW,"SOR_WRITE: addr %#x = %#x\n", - (unsigned int) (TEGRA_ARM_SOR + (reg<<2)), val); \ - WRITEL(val, (void *)(TEGRA_ARM_SOR + (reg<<2))); \ - printk(BIOS_SPEW,"= %#x\n", \ - (unsigned int)READL( (void *)(TEGRA_ARM_SOR + (reg<<2)))); \ - } -#endif -#define SOR_READ_M_WRITE(reg, mask, val) \ - { \ - u32 _reg_val; \ - _reg_val = READL( (void *)(TEGRA_ARM_SOR + (reg<<2))); \ - _reg_val &= ~mask; \ - _reg_val |= val; \ - WRITEL(_reg_val, (void *)(TEGRA_ARM_SOR + (reg<<2))); \ - } - - printk(BIOS_SPEW, "initial SOR done\n"); -} - -void init_dpaux_regs(void) -{ - - printk(BIOS_SPEW, "%s: entry\n", __func__); - -#if 1 -#define DPAUX_WRITE(reg, val) \ - { \ - WRITEL(val, (void *)(TEGRA_ARM_DPAUX + (reg<<2))); \ - } -#define DPAUX_READ(reg) READL( (void *)(TEGRA_ARM_DPAUX + (reg<<2))) - -#else // read back -#define DPAUX_WRITE(reg, val) \ - { \ - printk(BIOS_SPEW,"DPAUX_WRITE: addr %#x = %#x\n", (unsigned int) - (TEGRA_ARM_DPAUX + (reg<<2)), val); \ - WRITEL(val, (void *)(TEGRA_ARM_DPAUX + (reg<<2))); \ - printk(BIOS_SPEW,"= %#x\n", \ - (unsigned int)READL( (void *)(TEGRA_ARM_DPAUX + (reg<<2)))); \ - } -#endif - - printk(BIOS_SPEW, "initial DPAUX done\n"); } static int dp_poll_register(void *addr, u32 exp_val, u32 mask, u32 timeout_ms) { - u32 reg_val = 0; - printk(BIOS_SPEW, "JZ: %s: enter, addr %#x: exp_val: %#x, mask: %#x\n", - __func__, (unsigned int)addr, exp_val, mask); do { - udelay(1); + udelay(1000); reg_val = READL(addr); } while (((reg_val & mask) != exp_val) && (--timeout_ms > 0)); if ((reg_val & mask) == exp_val) return 0; /* success */ - printk(BIOS_SPEW, "poll_register %p: timeout\n", addr); + printk(BIOS_WARNING, "poll_register %p: timeout\n", addr); return timeout_ms; } @@ -196,15 +139,10 @@ static void dp_io_set_dpd(u32 power_down) * 1: into deep power down */ u32 val_reg; -#define DP_LVDS_SHIFT 25 -#define DP_LVDS (1 << DP_LVDS_SHIFT) val_reg = READL((void *)(0x7000e400 + 0x1c4)); /* APBDEV_PMC_IO_DPD2_STATUS_0 */ - printk(BIOS_SPEW, "JZ: %s: enter, into dpd %d, cur_status: %#x\n", - __func__, power_down, val_reg); - if ((((val_reg & DP_LVDS) >> DP_LVDS_SHIFT) & 1) == power_down) { - printk(BIOS_SPEW, "PAD already POWER=%d\n", 1 - power_down); + printk(BIOS_DEBUG, "PAD already POWER=%d\n", 1 - power_down); return; } @@ -212,14 +150,11 @@ static void dp_io_set_dpd(u32 power_down) WRITEL((DP_LVDS | ((1 + power_down) << 30)), (void *)(0x7000e400 + 0x1c0)); dp_poll_register((void *)(0x7000e400 + 0x1C4), 0, DP_LVDS, 1000); - //APBDEV_PMC_IO_DPD2_STATUS_0 + /* APBDEV_PMC_IO_DPD2_STATUS_0 */ } void dp_io_powerup(void) { - - printk(BIOS_SPEW, "%s: entry\n", __func__); - SOR_WRITE(SOR_NV_PDISP_SOR_CLK_CNTRL_0, (6 << 2) | 2);//select PLLDP, lowest speed(6x) SOR_WRITE(SOR_NV_PDISP_SOR_DP_PADCTL0_0, 0x00800000); //set PDCAL SOR_WRITE(SOR_NV_PDISP_SOR_PLL0_0, 0x050003D5); //set PWR,VCOPD @@ -227,14 +162,21 @@ void dp_io_powerup(void) SOR_WRITE(SOR_NV_PDISP_SOR_PLL2_0, 0x01C20000); //set AUX1,6,7,8; clr AUX2 SOR_WRITE(SOR_NV_PDISP_SOR_PLL3_0, 0x38002220); + /* Deassert E_DPD to enable core logic circuits, and wait for > 5us */ dp_io_set_dpd(0); - udelay(1); //Deassert E_DPD to enable core logic circuits, and wait for > 5us + udelay(10); + /* Deassert PDBG to enable bandgap, and wait for > 20us. */ SOR_READ_M_WRITE(SOR_NV_PDISP_SOR_PLL2_0, SOR_NV_PDISP_SOR_PLL2_0_AUX6_FIELD, (0 << SOR_NV_PDISP_SOR_PLL2_0_AUX6_SHIFT)); - udelay(20); //Deassert PDBG to enable bandgap, and wait for > 20us. + udelay(25); + /* + * Enable the PLL/charge-pump/VCO, and wait for >200us for the PLL to + * lock. Input Clock must be running and stable before PDPLL + * de-assertion. + */ SOR_READ_M_WRITE(SOR_NV_PDISP_SOR_PLL0_0, SOR_NV_PDISP_SOR_PLL0_0_PWR_FIELD, (0 << SOR_NV_PDISP_SOR_PLL0_0_PWR_SHIFT)); @@ -244,10 +186,8 @@ void dp_io_powerup(void) SOR_READ_M_WRITE(SOR_NV_PDISP_SOR_PLL2_0, SOR_NV_PDISP_SOR_PLL2_0_AUX8_FIELD, (0 << SOR_NV_PDISP_SOR_PLL2_0_AUX8_SHIFT)); - udelay(200); - //Enable the PLL/charge-pump/VCO, and wait for >200us for the PLL to - //lock. Input Clock must be running and stable before PDPLL - //de-assertion. + udelay(210); + SOR_READ_M_WRITE(SOR_NV_PDISP_SOR_PLL2_0, SOR_NV_PDISP_SOR_PLL2_0_AUX7_FIELD, (0 << SOR_NV_PDISP_SOR_PLL2_0_AUX7_SHIFT)); @@ -256,7 +196,6 @@ void dp_io_powerup(void) (1 << SOR_NV_PDISP_SOR_PLL2_0_AUX9_SHIFT)); udelay(100); - printk(BIOS_SPEW, "%s: exit\n", __func__); } static int dpaux_check(u32 bytes, u32 data, u32 mask) @@ -268,18 +207,19 @@ static int dpaux_check(u32 bytes, u32 data, u32 mask) DPAUX_WRITE(DPAUX_DP_AUXDATA_READ_W0, 0); status = dpaux_read(0x202, bytes, buf); if (status != 0) - printk(BIOS_SPEW, "******AuxRead Error:%04x: status %08x\n", 0x202, - status); + printk(BIOS_ERR, "******AuxRead Error:%04x: status %08x\n", + 0x202, status); else { temp = DPAUX_READ(DPAUX_DP_AUXDATA_READ_W0); if ((temp & mask) != (data & mask)) { - printk(BIOS_SPEW, "AuxCheck ERROR:(r_data) %08x & (mask) %08x != " - "(data) %08x & (mask) %08x\n", temp, mask, data, mask); + printk(BIOS_ERR, "AuxCheck ERROR:(r_data) %08x &" + " (mask) %08x != (data) %08x & (mask) %08x\n", + temp, mask, data, mask); return -1; } else { - printk(BIOS_SPEW, - "AuxCheck PASS:(bytes=%d,data=%08x,mask=%08x):0x%08x\n", - bytes, data, mask, temp); + printk(BIOS_DEBUG, "AuxCheck PASS:(bytes=%d, " + "data=%08x, mask=%08x):0x%08x\n", + bytes, data, mask, temp); return 0; } } @@ -304,8 +244,6 @@ static int dpaux_check(u32 bytes, u32 data, u32 mask) */ static void pattern_level(u32 current, u32 preemph, u32 postcur) { - printk(BIOS_SPEW, "set level:%d %d %d\n", current, preemph, postcur); - //calibrating required if (current == 0) SOR_WRITE(SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0, 0x20202020); @@ -355,7 +293,7 @@ static int dp_training(u32 level, u32 check, u32 speed) wcfg = wcfg | 0x20; wcfg = wcfg | (wcfg << 8) | (wcfg << 16) | (wcfg << 24); dpaux_write(0x103, 4, wcfg); - udelay(50); //100us + udelay(100); DPAUX_WRITE(DPAUX_DP_AUXDATA_READ_W0, 0); if (!dpaux_check(2, check, check)) cnt = 100; @@ -366,7 +304,7 @@ static int dp_training(u32 level, u32 check, u32 speed) if (cfg == cfg_d) { ++cnt; if (cnt > 5) - printk(BIOS_SPEW, "link training FAILED\n"); + printk(BIOS_ERR, "Error: link training FAILED\n"); } else { cnt = 0; cfg_d = cfg; @@ -396,10 +334,7 @@ void dp_link_training(u32 lanes, u32 speed) u32 mask, level; u32 reg_val; - printk(BIOS_SPEW, "%s: entry, lanes: %d, speed: %d\n", __func__, lanes, - speed); - - printk(BIOS_SPEW, "\nLink training start\n"); + printk(BIOS_DEBUG, "\nLink training start\n"); switch (lanes) { case 1: @@ -412,21 +347,22 @@ void dp_link_training(u32 lanes, u32 speed) lane_on = 0x0f; break; default: - printk(BIOS_SPEW, "dp: invalid lane count: %d\n", lanes); + printk(BIOS_DEBUG, "dp: invalid lane count: %d\n", + lanes); return; } SOR_WRITE(SOR_NV_PDISP_SOR_DP_PADCTL0_0, (0x008000000 | lane_on)); SOR_READ_M_WRITE(SOR_NV_PDISP_SOR_DP_PADCTL0_0, - SOR_NV_PDISP_SOR_DP_PADCTL0_0_TX_PU_VALUE_FIELD, - (6 << SOR_NV_PDISP_SOR_DP_PADCTL0_0_TX_PU_VALUE_SHIFT)); + SOR_NV_PDISP_SOR_DP_PADCTL0_0_TX_PU_VALUE_FIELD, + (6 << SOR_NV_PDISP_SOR_DP_PADCTL0_0_TX_PU_VALUE_SHIFT)); SOR_READ_M_WRITE(SOR_NV_PDISP_SOR_DP_PADCTL0_0, - SOR_NV_PDISP_SOR_DP_PADCTL0_0_TX_PU_FIELD, - (1 << SOR_NV_PDISP_SOR_DP_PADCTL0_0_TX_PU_SHIFT)); + SOR_NV_PDISP_SOR_DP_PADCTL0_0_TX_PU_FIELD, + (1 << SOR_NV_PDISP_SOR_DP_PADCTL0_0_TX_PU_SHIFT)); SOR_WRITE(SOR_NV_PDISP_SOR_LVDS_0, 0); SOR_WRITE(SOR_NV_PDISP_SOR_CLK_CNTRL_0, ((speed << 2) | 2)); - udelay(100); + udelay(100 * 1000); sor_clock_start(); @@ -434,34 +370,34 @@ void dp_link_training(u32 lanes, u32 speed) (((0xF >> (4 - lanes)) << 16) | 1)); SOR_WRITE(SOR_NV_PDISP_SOR_LANE_SEQ_CTL_0, 0x80100000); - printk(BIOS_SPEW, "Polling SOR_NV_PDISP_SOR_LANE_SEQ_CTL_0.DONE\n"); + printk(BIOS_DEBUG, "Polling SOR_NV_PDISP_SOR_LANE_SEQ_CTL_0.DONE\n"); dp_poll_register((void *)0x54540084, 0x00000000, 0x80000000, 1000); debug_dpaux_print(0x202, 4); - printk(BIOS_SPEW, "set link rate and lane number: %dMHz, %d lanes\n", + printk(BIOS_DEBUG, "set link rate and lane number: %dMHz, %d lanes\n", (speed * 27), lanes); dpaux_write(0x100, 2, ((lanes << 8) | speed)); - printk(BIOS_SPEW, "precharge lane 10us\n"); + printk(BIOS_DEBUG, "precharge lane 10us\n"); reg_val = SOR_READ(SOR_NV_PDISP_SOR_DP_PADCTL0_0); SOR_WRITE(SOR_NV_PDISP_SOR_DP_PADCTL0_0, (0x000000f0 | reg_val)); - udelay(100); + udelay(100 * 1000); SOR_WRITE(SOR_NV_PDISP_SOR_DP_PADCTL0_0, reg_val); - printk(BIOS_SPEW, "link training cr start\n"); + printk(BIOS_DEBUG, "link training cr start\n"); SOR_WRITE(SOR_NV_PDISP_SOR_DP_TPG_0, 0x41414141); dpaux_write(0x102, 1, 0x21); mask = 0x0000ffff >> ((4 - lanes) * 4); level = 0; level = dp_training(level, 0x1111 & mask, speed); - printk(BIOS_SPEW, "level:%x\n", level); + printk(BIOS_DEBUG, "level:%x\n", level); debug_dpaux_print(0x210, 16); - printk(BIOS_SPEW, "link training eq start\n"); + printk(BIOS_DEBUG, "link training eq start\n"); if (speed == 20) { SOR_WRITE(SOR_NV_PDISP_SOR_DP_TPG_0, 0x43434343); dpaux_write(0x102, 1, 0x23); @@ -471,7 +407,7 @@ void dp_link_training(u32 lanes, u32 speed) } level = dp_training(level, (0x7777 & mask) | 0x10000, speed); - printk(BIOS_SPEW, "level:%x\n", level); + printk(BIOS_DEBUG, "level:%x\n", level); debug_dpaux_print(0x210, 16); @@ -482,8 +418,7 @@ void dp_link_training(u32 lanes, u32 speed) debug_dpaux_print(0x200, 16); debug_dpaux_print(0x210, 16); - printk(BIOS_SPEW, "Link training done\n\n"); - printk(BIOS_SPEW, "%s: exit\n", __func__); + printk(BIOS_DEBUG, "Link training done\n\n"); } static u32 div_f(u32 a, u32 b, u32 one) @@ -492,23 +427,10 @@ static u32 div_f(u32 a, u32 b, u32 one) return (d); } -u32 dp_setup_timing(u32 panel_id, u32 width, u32 height); -u32 dp_setup_timing(u32 panel_id, u32 width, u32 height) +u32 dp_setup_timing(u32 width, u32 height) { u32 pclk_freq = 0; - /////////////////////////////////////////// - // set up clocks, using PLLD2 - // format: pclk , PLL , panel - //2560x1440: 241.5 , 483/2, dp VESA.red. - //1920x1080: 148.5 , 594/4, dp CEA - //1600x1200: 161.0 , 483/3, dp VESA - //1280x 720: 74.25 , 594/8, dp CEA - // 1024x768: 63.5 , 508/8, dp VESA - // 800x600: 38.25 , 459/12, dp VESA - // 720x480: 27.00 , 594/22, dp CEA - // 640x480: 23.75 , 475/20, dp VESA - u32 PLL_FREQ = (12 / 12 * 283) / 1 / 2; /* 141.5 */ u32 PLL_DIV = 2; u32 SYNC_WIDTH = (8 << 16) | 46; @@ -529,14 +451,6 @@ u32 dp_setup_timing(u32 panel_id, u32 width, u32 height) u32 PCLK_FREQ_I, PCLK_FREQ_F; u32 FRATE_I, FRATE_F; - printk(BIOS_SPEW, "%s: entry\n", __func__); - - if (panel_id != 5) { - printk(BIOS_SPEW, "%s: Unsupported panel_id: %d, format=%dx%d\n", - __func__, panel_id, width, height); - return pclk_freq; - } - PLL_FREQ = PLL_FREQ * 1000000; pclk_freq = PLL_FREQ / PLL_DIV; PLL_FREQ_I = PLL_FREQ / 1000000; @@ -545,19 +459,19 @@ u32 dp_setup_timing(u32 panel_id, u32 width, u32 height) PCLK_FREQ_F = div_f(PLL_FREQ, PLL_DIV * 1000000, 100); FRATE_I = PLL_FREQ / (PLL_DIV * TOTAL_PIXELS); FRATE_F = div_f(PLL_FREQ, (PLL_DIV * TOTAL_PIXELS), 100); - //bug 1021453 + /* nv_bug 1021453 */ BACK_PORCH = BACK_PORCH - 0x10000; FRONT_PORCH = FRONT_PORCH + 0x10000; - printk(BIOS_SPEW, "ACTIVE: %dx%d\n", (DISP_ACTIVE & 0xFFFF), + printk(BIOS_DEBUG, "ACTIVE: %dx%d\n", (DISP_ACTIVE & 0xFFFF), (DISP_ACTIVE >> 16)); - printk(BIOS_SPEW, "TOTAL: %dx%d\n", (DISP_TOTAL & 0xffff), + printk(BIOS_DEBUG, "TOTAL: %dx%d\n", (DISP_TOTAL & 0xffff), (DISP_TOTAL >> 16)); - printk(BIOS_SPEW, "PLL Freq: %d.%d MHz\n", PLL_FREQ_I, PLL_FREQ_F); - printk(BIOS_SPEW, "Pclk Freq: %d.%d MHz\n", PCLK_FREQ_I, + printk(BIOS_DEBUG, "PLL Freq: %d.%d MHz\n", PLL_FREQ_I, PLL_FREQ_F); + printk(BIOS_DEBUG, "Pclk Freq: %d.%d MHz\n", PCLK_FREQ_I, PCLK_FREQ_F); - printk(BIOS_SPEW, "Frame Rate: %d.%d Hz\n", FRATE_I, FRATE_F); - printk(BIOS_SPEW, "\n"); + printk(BIOS_DEBUG, "Frame Rate: %d.%d Hz\n", FRATE_I, FRATE_F); + printk(BIOS_DEBUG, "\n"); DCA_WRITE(DC_CMD_STATE_ACCESS_0, 0x00000004); DCA_WRITE(DC_DISP_DISP_CLOCK_CONTROL_0, SHIFT_CLK_DIVIDER); @@ -569,9 +483,6 @@ u32 dp_setup_timing(u32 panel_id, u32 width, u32 height) DCA_WRITE(DC_DISP_DISP_ACTIVE_0, DISP_ACTIVE); DCA_WRITE(DC_DISP_FRONT_PORCH_0, FRONT_PORCH); - printk(BIOS_SPEW, - "JZ: sync_width: %d, back_porch: %d, disp_active: %d, front_porch: %d\n", - SYNC_WIDTH, BACK_PORCH, DISP_ACTIVE, FRONT_PORCH); //REG(DC_DISP_DISP_WIN_OPTIONS_0, SOR_ENABLE , 1) DCA_READ_M_WRITE(DC_DISP_DISP_WIN_OPTIONS_0, DC_DISP_DISP_WIN_OPTIONS_0_SOR_ENABLE_FIELD, @@ -611,7 +522,6 @@ u32 dp_setup_timing(u32 panel_id, u32 width, u32 height) SOR_NV_PDISP_SOR_STATE1_0_ASY_OWNER_FIELD, (SOR_NV_PDISP_SOR_STATE1_0_ASY_OWNER_HEAD0 << SOR_NV_PDISP_SOR_STATE1_0_ASY_OWNER_SHIFT)); - printk(BIOS_SPEW, "%s: exit\n", __func__); return pclk_freq; } @@ -623,7 +533,9 @@ static u32 calc_config(u32 ts, u32 a, u32 b, u32 bpp) u32 act_frac; u32 err; u32 water_mark; - printk(BIOS_SPEW, "calc_config ts %d a %d b %d bpp %d\n", ts, a, b, bpp); + + printk(BIOS_DEBUG, "calc_config ts %d a %d b %d bpp %d\n", + ts, a, b, bpp); if (diff != 0) { if (diff > (b / 2)) { diff = b - diff; @@ -669,7 +581,7 @@ static u32 calc_config(u32 ts, u32 a, u32 b, u32 bpp) (water_mark << SOR_NV_PDISP_SOR_DP_CONFIG0_0_WATERMARK_SHIFT)); - printk(BIOS_SPEW, + printk(BIOS_DEBUG, "SOR_DP_CONFIG0:TU,CNT,POL,FRAC,WMK,ERR=%d,%d,%d,%d,%d,%d/%d\n", ts, act_cnt, act_pol, act_frac, water_mark, err, b); } @@ -687,7 +599,8 @@ static u32 dp_buf_config(u32 pclkfreq, u32 linkfreq, u32 lanes, u32 bpp) u32 min_err = 1000000000; u32 ts = 64; u32 c_err; - printk(BIOS_SPEW, "dp buf config pclkfreq %d linkfreq %d lanes %d bpp %d\n", + + printk(BIOS_DEBUG, "dp buf config pclkfreq %d linkfreq %d lanes %d bpp %d\n", pclkfreq, linkfreq, lanes, bpp); for (i = 2; i <= 7; ++i) { while (((pf / i * i) == pf) && ((lf / i * i) == lf)) { @@ -698,9 +611,9 @@ static u32 dp_buf_config(u32 pclkfreq, u32 linkfreq, u32 lanes, u32 bpp) a = pf * bpp / 8; b = lf * lanes; - printk(BIOS_SPEW, "ratio:%d/%d\n", a, b); + printk(BIOS_DEBUG, "ratio:%d/%d\n", a, b); if (a > (b * 98 / 100)) - printk(BIOS_SPEW, "Error:link speed not enough\n"); + printk(BIOS_ERR, "Error:link speed not enough\n"); //search best tusize //min_err = 1000000000; @@ -727,10 +640,11 @@ static u32 dp_buf_config(u32 pclkfreq, u32 linkfreq, u32 lanes, u32 bpp) return (tusize); } +/* void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr, u32 lane_count, u32 enhanced_framing, u32 panel_edp, u32 pclkfreq, u32 linkfreq); - +*/ void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr, u32 lane_count, u32 enhanced_framing, u32 panel_edp, u32 pclkfreq, u32 linkfreq) @@ -738,8 +652,8 @@ void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr, u32 tusize; u32 linkctl; - printk(BIOS_SPEW, "%s: entry, winb: 0x%08x ", __func__, winb_addr); - printk(BIOS_SPEW, " panel_bpp %d\n", panel_bpp); + printk(BIOS_DEBUG, "%s: winb: 0x%08x, panel_bpp %d ", + __func__, winb_addr, panel_bpp); if (panel_bpp == 18) { //0x54540010 @@ -755,37 +669,25 @@ void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr, SOR_NV_PDISP_SOR_STATE1_0_ASY_PIXELDEPTH_SHIFT)); } -#define SRC_BPP 16 -#define COLORDEPTH 0x6 - -#define BLUE 0xFF0000 -#define GREEN 0x00FF00 -#define RED 0x0000FF -#define YELLOW 0x00FFFF -#define BLACK 0x000000 -#define WHITE 0xFFFFFF -#define GREY 0x55aa00 - - DCA_WRITE(DC_B_WIN_BD_SIZE_0, ((height << 16) | width)); - DCA_WRITE(DC_B_WIN_BD_PRESCALED_SIZE_0, + DCA_WRITE(DC_CMD_DISPLAY_WINDOW_HEADER_0, 0x00000010); + DCA_WRITE(DC_WIN_A_SIZE_0, ((height << 16) | width)); + DCA_WRITE(DC_WIN_A_PRESCALED_SIZE_0, ((height << 16) | (width * SRC_BPP / 8))); - DCA_WRITE(DC_B_WIN_BD_LINE_STRIDE_0, + DCA_WRITE(DC_WIN_A_LINE_STRIDE_0, ((width * SRC_BPP / 8 + 31) / 32 * 32)); - DCA_WRITE(DC_B_WIN_BD_COLOR_DEPTH_0, COLORDEPTH); - DCA_WRITE(DC_B_WINBUF_BD_START_ADDR_0, winb_addr); - DCA_WRITE(DC_B_WIN_BD_DDA_INCREMENT_0, 0x10001000); + DCA_WRITE(DC_WIN_A_COLOR_DEPTH_0, COLORDEPTH); + DCA_WRITE(DC_WINBUF_A_START_ADDR_LO_0, winb_addr); + DCA_WRITE(DC_WIN_A_DDA_INCREMENT_0, 0x10001000); SOR_WRITE(SOR_NV_PDISP_SOR_CRC_CNTRL_0, 0x00000001); DCA_WRITE(DC_COM_CRC_CONTROL_0, 0x00000009); //CRC_ALWAYS+CRC_ENABLE DCA_WRITE(DC_COM_PIN_OUTPUT_ENABLE2_0, 0x00000000); DCA_WRITE(DC_COM_PIN_OUTPUT_ENABLE3_0, 0x00000000); DCA_WRITE(DC_DISP_DISP_SIGNAL_OPTIONS0_0, 0x00000000); - // DCA_WRITE (DC_DISP_BLEND_BACKGROUND_COLOR_0 ,WHITE ); - DCA_WRITE(DC_DISP_BLEND_BACKGROUND_COLOR_0, YELLOW); + DCA_WRITE(DC_DISP_BLEND_BACKGROUND_COLOR_0, COLOR_WHITE); DCA_WRITE(DC_CMD_DISPLAY_COMMAND_0, 0x00000020); SOR_WRITE(SOR_NV_PDISP_SOR_DP_AUDIO_VBLANK_SYMBOLS_0, 0x00000e48); - dpaux_write(0x101, 1, (enhanced_framing << 7) | lane_count); if (panel_edp) dpaux_write(0x10A, 1, 1); @@ -793,8 +695,6 @@ void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr, tusize = dp_buf_config(pclkfreq, (linkfreq * 1000000), lane_count, panel_bpp); - printk(BIOS_SPEW, "JZ, after dp_buf_config, tusize: 0x%08x\n", tusize); - linkctl = ((0xF >> (4 - lane_count)) << 16) | (enhanced_framing << 14) | (tusize << 2) | @@ -804,7 +704,7 @@ void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr, SOR_WRITE(SOR_NV_PDISP_SOR_DP_SPARE0_0, ((panel_edp << 1) | 0x05)); SOR_WRITE(SOR_NV_PDISP_SOR_PWR_0, 0x80000001); - printk(BIOS_SPEW, "Polling SOR_NV_PDISP_SOR_PWR_0.DONE\n"); + printk(BIOS_DEBUG, "Polling SOR_NV_PDISP_SOR_PWR_0.DONE\n"); dp_poll_register((void *)0x54540054, 0x00000000, 0x80000000, 1000); //SOR_NV_PDISP_SOR_PWR_0 //sor_update @@ -815,7 +715,7 @@ void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr, SOR_WRITE(SOR_NV_PDISP_SOR_SUPER_STATE1_0, 0x0000000e); //sor_super_update SOR_WRITE(SOR_NV_PDISP_SOR_SUPER_STATE0_0, 0x00000000); - printk(BIOS_SPEW, "Polling SOR_NV_PDISP_SOR_TEST_0.ATTACHED\n"); + printk(BIOS_DEBUG, "Polling SOR_NV_PDISP_SOR_TEST_0.ATTACHED\n"); dp_poll_register((void *)0x54540058, 0x00000400, 0x00000400, 1000); //SOR_NV_PDISP_SOR_TEST_0 @@ -823,21 +723,16 @@ void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr, DCA_WRITE(DC_CMD_STATE_CONTROL_0, 0x0000009f); DCA_WRITE(DC_CMD_DISPLAY_POWER_CONTROL_0, 0x00050155); - printk(BIOS_SPEW, "Polling SOR_NV_PDISP_SOR_TEST_0.AWAKE\n"); + printk(BIOS_DEBUG, "Polling SOR_NV_PDISP_SOR_TEST_0.AWAKE\n"); dp_poll_register((void *)0x54540058, 0x00000200, 0x00000300, 1000); //SOR_NV_PDISP_SOR_TEST_0 // DCA_WRITE (DC_CMD_STATE_ACCESS_0 ,0); DCA_WRITE(DC_CMD_STATE_ACCESS_0, 4); DCA_WRITE(DC_CMD_STATE_CONTROL_0, 0x0000ffff); - /* enable win_b */ - - DCA_READ_M_WRITE(DC_B_WIN_BD_WIN_OPTIONS_0, - DC_B_WIN_BD_WIN_OPTIONS_0_BD_WIN_ENABLE_FIELD, - (DC_B_WIN_BD_WIN_OPTIONS_0_BD_WIN_ENABLE_ENABLE << - DC_B_WIN_BD_WIN_OPTIONS_0_BD_WIN_ENABLE_SHIFT)); - - printk(BIOS_SPEW, "JZ: %s: f_ret @ line %d\n", __func__, __LINE__); + DCA_READ_M_WRITE(DC_WIN_A_WIN_OPTIONS_0, + DC_WIN_A_WIN_OPTIONS_0_A_WIN_ENABLE_FIELD, + (DC_WIN_A_WIN_OPTIONS_0_A_WIN_ENABLE_ENABLE << + DC_WIN_A_WIN_OPTIONS_0_A_WIN_ENABLE_SHIFT)); } - diff --git a/src/soc/nvidia/tegra124/dp.c b/src/soc/nvidia/tegra124/dp.c index 32056991fb..6b0f4c8698 100644 --- a/src/soc/nvidia/tegra124/dp.c +++ b/src/soc/nvidia/tegra124/dp.c @@ -39,33 +39,36 @@ static inline u32 tegra_dpaux_readl(struct tegra_dc_dp_data *dp, u32 reg) } static inline void tegra_dpaux_writel(struct tegra_dc_dp_data *dp, - u32 reg, u32 val) + u32 reg, u32 val) { void *addr = dp->aux_base + (u32) (reg << 2); WRITEL(val, addr); } static inline u32 tegra_dc_dpaux_poll_register(struct tegra_dc_dp_data *dp, - u32 reg, u32 mask, u32 exp_val, - u32 poll_interval_us, - u32 timeout_ms) + u32 reg, u32 mask, u32 exp_val, + u32 poll_interval_us, + u32 timeout_us) { u32 reg_val = 0; + u32 temp = timeout_us; - printk(BIOS_SPEW, "JZ: %s: enter, poll_reg: %#x: timeout: 0x%x\n", - __func__, reg * 4, timeout_ms); do { - udelay(1); + udelay(poll_interval_us); reg_val = tegra_dpaux_readl(dp, reg); - } while (((reg_val & mask) != exp_val) && (--timeout_ms > 0)); + if (timeout_us > poll_interval_us) + timeout_us -= poll_interval_us; + else + break; + } while ((reg_val & mask) != exp_val); if ((reg_val & mask) == exp_val) return 0; /* success */ - printk(BIOS_SPEW, + printk(BIOS_ERR, "dpaux_poll_register 0x%x: timeout: " "(reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n", reg, reg_val, mask, exp_val); - return timeout_ms; + return temp; } static inline int tegra_dpaux_wait_transaction(struct tegra_dc_dp_data *dp) @@ -73,18 +76,18 @@ static inline int tegra_dpaux_wait_transaction(struct tegra_dc_dp_data *dp) /* According to DP spec, each aux transaction needs to finish within 40ms. */ if (tegra_dc_dpaux_poll_register(dp, DPAUX_DP_AUXCTL, - DPAUX_DP_AUXCTL_TRANSACTREQ_MASK, - DPAUX_DP_AUXCTL_TRANSACTREQ_DONE, - 100, DP_AUX_TIMEOUT_MS * 1000) != 0) { - printk(BIOS_SPEW, "dp: DPAUX transaction timeout\n"); + DPAUX_DP_AUXCTL_TRANSACTREQ_MASK, + DPAUX_DP_AUXCTL_TRANSACTREQ_DONE, + 100, DP_AUX_TIMEOUT_MS * 1000) != 0) { + printk(BIOS_INFO, "dp: DPAUX transaction timeout\n"); return -1; } return 0; } static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd, - u32 addr, u8 * data, u32 * size, - u32 * aux_stat) + u32 addr, u8 *data, u32 *size, + u32 *aux_stat) { int i; u32 reg_val; @@ -102,21 +105,11 @@ static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd, case DPAUX_DP_AUXCTL_CMD_AUXWR: break; default: - printk(BIOS_SPEW, "dp: aux write cmd 0x%x is invalid\n", cmd); + printk(BIOS_ERR, "dp: aux write cmd 0x%x is invalid\n", + cmd); return -1; } -#if 0 -/* interesting. */ - if (tegra_platform_is_silicon()) { - *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); - if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) { - printk(BIOS_SPEW, "dp: HPD is not detected\n"); - return -EFAULT; - } - } -#endif - tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr); for (i = 0; i < DP_AUX_MAX_BYTES / 4; ++i) { memcpy(&temp_data, data, 4); @@ -139,7 +132,7 @@ static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd, tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val); if (tegra_dpaux_wait_transaction(dp)) - printk(BIOS_SPEW, "dp: aux write transaction timeout\n"); + printk(BIOS_ERR, "dp: aux write transaction timeout\n"); *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); @@ -148,13 +141,13 @@ static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd, (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) || (*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) { if (timeout_retries-- > 0) { - printk(BIOS_SPEW, "dp: aux write retry (0x%x) -- %d\n", + printk(BIOS_INFO, "dp: aux write retry (0x%x) -- %d\n", *aux_stat, timeout_retries); /* clear the error bits */ tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, *aux_stat); continue; } else { - printk(BIOS_SPEW, "dp: aux write got error (0x%x)\n", + printk(BIOS_ERR, "dp: aux write got error (0x%x)\n", *aux_stat); return -1; } @@ -163,13 +156,13 @@ static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd, if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) || (*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) { if (defer_retries-- > 0) { - printk(BIOS_SPEW, "dp: aux write defer (0x%x) -- %d\n", + printk(BIOS_INFO, "dp: aux write defer (0x%x) -- %d\n", *aux_stat, defer_retries); /* clear the error bits */ tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, *aux_stat); continue; } else { - printk(BIOS_SPEW, "dp: aux write defer exceeds max retries " + printk(BIOS_ERR, "dp: aux write defer exceeds max retries " "(0x%x)\n", *aux_stat); return -1; } @@ -180,7 +173,8 @@ static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd, *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK); return 0; } else { - printk(BIOS_SPEW, "dp: aux write failed (0x%x)\n", *aux_stat); + printk(BIOS_ERR, "dp: aux write failed (0x%x)\n", + *aux_stat); return -1; } } @@ -189,7 +183,7 @@ static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd, } static int tegra_dc_dpaux_write(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr, - u8 * data, u32 * size, u32 * aux_stat) + u8 *data, u32 *size, u32 *aux_stat) { u32 cur_size = 0; u32 finished = 0; @@ -202,7 +196,7 @@ static int tegra_dc_dpaux_write(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr, cur_size = DP_AUX_MAX_BYTES; cur_left = cur_size; ret = tegra_dc_dpaux_write_chunk(dp, cmd, addr, - data, &cur_left, aux_stat); + data, &cur_left, aux_stat); cur_size -= cur_left; finished += cur_size; @@ -218,8 +212,8 @@ static int tegra_dc_dpaux_write(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr, } static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd, - u32 addr, u8 * data, u32 * size, - u32 * aux_stat) + u32 addr, u8 *data, u32 *size, + u32 *aux_stat) { u32 reg_val; u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES; @@ -236,7 +230,8 @@ static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd, case DPAUX_DP_AUXCTL_CMD_AUXRD: break; default: - printk(BIOS_SPEW, "dp: aux read cmd 0x%x is invalid\n", cmd); + printk(BIOS_ERR, "dp: aux read cmd 0x%x is invalid\n", + cmd); return -1; } @@ -253,37 +248,38 @@ static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd, reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL); reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK; reg_val |= cmd; - printk(BIOS_SPEW, "cmd = %08x\n", reg_val); reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD; reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT); - printk(BIOS_SPEW, "cmd = %08x\n", reg_val); while ((timeout_retries > 0) && (defer_retries > 0)) { if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) || (defer_retries != DP_AUX_DEFER_MAX_TRIES)) udelay(DP_DPCP_RETRY_SLEEP_NS * 2); reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING; - printk(BIOS_SPEW, "cmd = %08x\n", reg_val); tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val); if (tegra_dpaux_wait_transaction(dp)) - printk(BIOS_SPEW, "dp: aux read transaction timeout\n"); + printk(BIOS_INFO, "dp: aux read transaction timeout\n"); *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); - printk(BIOS_SPEW, "dp: %s: aux stat: 0x%08x\n", __func__, *aux_stat); + printk(BIOS_DEBUG, "dp: %s: aux stat: 0x%08x\n", __func__, + *aux_stat); if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) || (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) || (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) || (*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) { if (timeout_retries-- > 0) { - printk(BIOS_SPEW, "dp: aux read retry (0x%x) -- %d\n", - *aux_stat, timeout_retries); + printk(BIOS_INFO, "dp: aux read retry (0x%x)" + " -- %d\n", *aux_stat, + timeout_retries); /* clear the error bits */ - tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, *aux_stat); + tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, + *aux_stat); continue; /* retry */ } else { - printk(BIOS_SPEW, "dp: aux read got error (0x%x)\n", *aux_stat); + printk(BIOS_ERR, "dp: aux read got error" + " (0x%x)\n", *aux_stat); return -1; } } @@ -291,13 +287,13 @@ static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd, if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) || (*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) { if (defer_retries-- > 0) { - printk(BIOS_SPEW, "dp: aux read defer (0x%x) -- %d\n", + printk(BIOS_INFO, "dp: aux read defer (0x%x) -- %d\n", *aux_stat, defer_retries); /* clear the error bits */ tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, *aux_stat); continue; } else { - printk(BIOS_SPEW, "dp: aux read defer exceeds max retries " + printk(BIOS_INFO, "dp: aux read defer exceeds max retries " "(0x%x)\n", *aux_stat); return -1; } @@ -310,20 +306,22 @@ static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd, for (i = 0; i < DP_AUX_MAX_BYTES / 4; ++i) temp_data[i] = tegra_dpaux_readl(dp, - DPAUX_DP_AUXDATA_READ_W(i)); + DPAUX_DP_AUXDATA_READ_W(i)); *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK); - printk(BIOS_SPEW, "dp: aux read data %d bytes\n", *size); + printk(BIOS_INFO, "dp: aux read data %d bytes\n", + *size); memcpy(data, temp_data, *size); return 0; } else { - printk(BIOS_SPEW, "dp: aux read failed (0x%x\n", *aux_stat); + printk(BIOS_ERR, "dp: aux read failed (0x%x\n", + *aux_stat); return -1; } } /* Should never come to here */ - printk(BIOS_SPEW, "%s: can't\n", __func__); + printk(BIOS_ERR, "%s: can't\n", __func__); return -1; } @@ -340,7 +338,7 @@ int tegra_dc_dpaux_read(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr, cur_size = DP_AUX_MAX_BYTES; ret = tegra_dc_dpaux_read_chunk(dp, cmd, addr, - data, &cur_size, aux_stat); + data, &cur_size, aux_stat); /* cur_size should be the real size returned */ addr += cur_size; @@ -350,12 +348,6 @@ int tegra_dc_dpaux_read(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr, if (ret) break; -#if 0 - if (cur_size == 0) { - printk(BIOS_SPEW, "JZ: no data found, ret\n"); - break; - } -#endif } while (*size > finished); *size = finished; @@ -372,7 +364,7 @@ static int tegra_dc_dp_dpcd_read(struct tegra_dc_dp_data *dp, u32 cmd, ret = tegra_dc_dpaux_read_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, cmd, data_ptr, &size, &status); if (ret) - printk(BIOS_SPEW, + printk(BIOS_ERR, "dp: Failed to read DPCD data. CMD 0x%x, Status 0x%x\n", cmd, status); @@ -380,7 +372,7 @@ static int tegra_dc_dp_dpcd_read(struct tegra_dc_dp_data *dp, u32 cmd, } static int tegra_dc_dp_init_max_link_cfg(struct tegra_dc_dp_data *dp, - struct tegra_dc_dp_link_config *cfg) + struct tegra_dc_dp_link_config *cfg) { u8 dpcd_data; int ret; @@ -390,27 +382,26 @@ static int tegra_dc_dp_init_max_link_cfg(struct tegra_dc_dp_data *dp, return ret; cfg->max_lane_count = dpcd_data & NV_DPCD_MAX_LANE_COUNT_MASK; - printk(BIOS_SPEW, "JZ: %s: max_lane_count: %d\n", __func__, + printk(BIOS_INFO, "%s: max_lane_count: %d\n", __func__, cfg->max_lane_count); cfg->support_enhanced_framing = (dpcd_data & NV_DPCD_MAX_LANE_COUNT_ENHANCED_FRAMING_YES) ? 1 : 0; - printk(BIOS_SPEW, "JZ: %s: enh-framing: %d\n", __func__, + printk(BIOS_INFO, "%s: enh-framing: %d\n", __func__, cfg->support_enhanced_framing); ret = tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_DOWNSPREAD, &dpcd_data); if (ret) return ret; cfg->downspread = (dpcd_data & NV_DPCD_MAX_DOWNSPREAD_VAL_0_5_PCT) ? 1 : 0; - printk(BIOS_SPEW, "JZ: %s: downspread: %d\n", __func__, cfg->downspread); + printk(BIOS_INFO, "%s: downspread: %d\n", __func__, cfg->downspread); ret = tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LINK_BANDWIDTH, &cfg->max_link_bw); if (ret) return ret; - printk(BIOS_SPEW, "JZ: %s: max_link_bw: %d\n", __func__, cfg->max_link_bw); + printk(BIOS_INFO, "%s: max_link_bw: %d\n", __func__, cfg->max_link_bw); - // jz, changed // cfg->bits_per_pixel = dp->dc->pdata->default_out->depth; cfg->bits_per_pixel = 18; @@ -427,7 +418,7 @@ static int tegra_dc_dp_init_max_link_cfg(struct tegra_dc_dp_data *dp, (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_ASC_RESET_YES) ? 1 : 0; cfg->only_enhanced_framing = (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_YES) ? 1 : 0; - printk(BIOS_SPEW, "JZ: %s: alt_reset_cap: %d, only_enh_framing: %d\n", + printk(BIOS_DEBUG, "%s: alt_reset_cap: %d, only_enh_framing: %d\n", __func__, cfg->alt_scramber_reset_cap, cfg->only_enhanced_framing); cfg->lane_count = cfg->max_lane_count; @@ -448,13 +439,13 @@ static int tegra_dc_dpcd_read_rev(struct tegra_dc_dp_data *dp, u8 * rev) ret = tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, NV_DPCD_REV, rev, &size, &status); if (ret) { - printk(BIOS_SPEW, "dp: Failed to read NV_DPCD_REV\n"); + printk(BIOS_WARNING, "dp: Failed to read NV_DPCD_REV\n"); return ret; } return 0; } -u32 dp_setup_timing(u32 panel_id, u32 width, u32 height); +u32 dp_setup_timing(u32 width, u32 height); void dp_bringup(u32 winb_addr) { struct tegra_dc_dp_data *dp = &dp_data; @@ -465,40 +456,40 @@ void dp_bringup(u32 winb_addr) u32 xres = 1366; /* norrin display */ u32 yres = 768; - printk(BIOS_SPEW, "JZ: %s: entry\n", __func__); - dp->sor.base = (void *)TEGRA_ARM_SOR; dp->sor.portnum = 0; dp->aux_base = (void *)TEGRA_ARM_DPAUX; /* read panel info */ - if (!tegra_dc_dpcd_read_rev(dp, (u8 *) & dpcd_rev)) { - printk(BIOS_SPEW, "PANEL info: \n"); - printk(BIOS_SPEW, "--DPCP version(%#x): %d.%d\n", - dpcd_rev, (dpcd_rev >> 4) & 0x0f, (dpcd_rev & 0x0f)); + if (!tegra_dc_dpcd_read_rev(dp, (u8 *)&dpcd_rev)) { + printk(BIOS_INFO, "PANEL info:\n"); + printk(BIOS_INFO, "--DPCP version(%#x): %d.%d\n", + dpcd_rev, (dpcd_rev >> 4) & 0x0f, + (dpcd_rev & 0x0f)); } if (tegra_dc_dp_init_max_link_cfg(dp, &dp->link_cfg)) - printk(BIOS_SPEW, "dp: failed to init link configuration\n"); + printk(BIOS_ERR, "dp: failed to init link configuration\n"); dp_link_training((u32) (dp->link_cfg.lane_count), (u32) (dp->link_cfg.link_bw)); - pclk_freq = dp_setup_timing(5, xres, yres); - printk(BIOS_SPEW, "JZ: %s: pclk_freq: %d\n", __func__, pclk_freq); + pclk_freq = dp_setup_timing(xres, yres); + printk(BIOS_DEBUG, "%s: pclk_freq: %d\n", __func__, pclk_freq); - void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr, - u32 lane_count, u32 enhanced_framing, u32 panel_edp, - u32 pclkfreq, u32 linkfreq); - dp_misc_setting(dp->link_cfg.bits_per_pixel, - xres, yres, winb_addr, - (u32) dp->link_cfg.lane_count, - (u32) dp->link_cfg.enhanced_framing, - (u32) dp->link_cfg.alt_scramber_reset_cap, - pclk_freq, dp->link_cfg.link_bw * 27); + void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, + u32 winb_addr, u32 lane_count, + u32 enhanced_framing, u32 panel_edp, + u32 pclkfreq, u32 linkfreq); + dp_misc_setting(dp->link_cfg.bits_per_pixel, + xres, yres, winb_addr, + (u32) dp->link_cfg.lane_count, + (u32) dp->link_cfg.enhanced_framing, + (u32) dp->link_cfg.alt_scramber_reset_cap, + pclk_freq, dp->link_cfg.link_bw * 27); } void debug_dpaux_print(u32 addr, u32 size) @@ -509,21 +500,22 @@ void debug_dpaux_print(u32 addr, u32 size) int i; if ((size == 0) || (size > 16)) { - printk(BIOS_SPEW, "dp: %s: invalid size %d\n", __func__, size); + printk(BIOS_ERR, "dp: %s: invalid size %d\n", __func__, size); return; } if (tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, - addr, buf, &size, &status)) { - printk(BIOS_SPEW, "******AuxRead Error: 0x%04x: status 0x%08x\n", addr, - status); + addr, buf, &size, &status)) { + printk(BIOS_ERR, "******AuxRead Error: 0x%04x: status 0x%08x\n", + addr, status); return; } - printk(BIOS_SPEW, "%s: addr: 0x%04x, size: %d\n", __func__, addr, size); + printk(BIOS_DEBUG, "%s: addr: 0x%04x, size: %d\n", __func__, + addr, size); for (i = 0; i < size; ++i) - printk(BIOS_SPEW, " %02x", buf[i]); + printk(BIOS_DEBUG, " %02x", buf[i]); - printk(BIOS_SPEW, "\n"); + printk(BIOS_DEBUG, "\n"); } int dpaux_read(u32 addr, u32 size, u8 * data) @@ -533,14 +525,14 @@ int dpaux_read(u32 addr, u32 size, u8 * data) u32 status = 0; if ((size == 0) || (size > 16)) { - printk(BIOS_SPEW, "dp: %s: invalid size %d\n", __func__, size); + printk(BIOS_ERR, "dp: %s: invalid size %d\n", __func__, size); return -1; } if (tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, - addr, data, &size, &status)) { - printk(BIOS_SPEW, "dp: Failed to read reg %#x, status: %#x\n", addr, - status); + addr, data, &size, &status)) { + printk(BIOS_ERR, "dp: Failed to read reg %#x, status: %#x\n", + addr, status); return -1; } @@ -553,13 +545,10 @@ int dpaux_write(u32 addr, u32 size, u32 data) u32 status = 0; int ret; - printk(BIOS_SPEW, "JZ: %s: entry, addr: 0x%08x, size: 0x%08x, data: %#x\n", - __func__, addr, size, data); - ret = tegra_dc_dpaux_write(dp, DPAUX_DP_AUXCTL_CMD_AUXWR, addr, (u8 *) & data, &size, &status); if (ret) - printk(BIOS_SPEW, "dp: Failed to write to reg %#x, status: 0x%x\n", + printk(BIOS_ERR, "dp: Failed to write to reg %#x, status: 0x%x\n", addr, status); return ret; } diff --git a/src/soc/nvidia/tegra124/emc.h b/src/soc/nvidia/tegra124/emc.h new file mode 100644 index 0000000000..f9d415bcef --- /dev/null +++ b/src/soc/nvidia/tegra124/emc.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __SOC_NVIDIA_TEGRA124_EMC_H__ +#define __SOC_NVIDIA_TEGRA124_EMC_H__ + +#include <stddef.h> +#include <stdint.h> + +enum { + EMC_PIN_RESET_MASK = 1 << 8, + EMC_PIN_RESET_ACTIVE = 0 << 8, + EMC_PIN_RESET_INACTIVE = 1 << 8, + EMC_PIN_DQM_MASK = 1 << 4, + EMC_PIN_DQM_NORMAL = 0 << 4, + EMC_PIN_DQM_INACTIVE = 1 << 4, + EMC_PIN_CKE_MASK = 1 << 0, + EMC_PIN_CKE_POWERDOWN = 0 << 0, + EMC_PIN_CKE_NORMAL = 1 << 0, + + EMC_REF_CMD_MASK = 1 << 0, + EMC_REF_CMD_REFRESH = 1 << 0, + EMC_REF_NORMAL_MASK = 1 << 1, + EMC_REF_NORMAL_INIT = 0 << 1, + EMC_REF_NORMAL_ENABLED = 1 << 1, + EMC_REF_NUM_SHIFT = 8, + EMC_REF_NUM_MASK = 0xFF << EMC_REF_NUM_SHIFT, + EMC_REF_DEV_SELECTN_SHIFT = 30, + EMC_REF_DEV_SELECTN_MASK = 3 << EMC_REF_DEV_SELECTN_SHIFT, + + EMC_REFCTRL_REF_VALID_MASK = 1 << 31, + EMC_REFCTRL_REF_VALID_DISABLED = 0 << 31, + EMC_REFCTRL_REF_VALID_ENABLED = 1 << 31, + + EMC_CFG_EMC2PMACRO_CFG_BYPASS_ADDRPIPE_MASK = 1 << 1, + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE1_MASK = 1 << 2, + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE2_MASK = 1 << 3, + + EMC_NOP_NOP_CMD_SHIFT = 0, + EMC_NOP_NOP_CMD_MASK = 1 << EMC_NOP_NOP_CMD_SHIFT, + EMC_NOP_NOP_DEV_SELECTN_SHIFT = 30, + EMC_NOP_NOP_DEV_SELECTN_MASK = 3 << EMC_NOP_NOP_DEV_SELECTN_SHIFT, + + EMC_TIMING_CONTROL_TIMING_UPDATE = 1, +}; + +struct tegra_emc_regs { + uint32_t intstatus; /* 0x0 */ + uint32_t intmask; /* 0x4 */ + uint32_t dbg; /* 0x8 */ + uint32_t cfg; /* 0xc */ + uint32_t adr_cfg; /* 0x10 */ + uint32_t rsvd_0x14[3]; /* 0x14 */ + + uint32_t refctrl; /* 0x20 */ + uint32_t pin; /* 0x24 */ + uint32_t timing_control; /* 0x28 */ + uint32_t rc; /* 0x2c */ + uint32_t rfc; /* 0x30 */ + uint32_t ras; /* 0x34 */ + uint32_t rp; /* 0x38 */ + uint32_t r2w; /* 0x3c */ + uint32_t w2r; /* 0x40 */ + uint32_t r2p; /* 0x44 */ + uint32_t w2p; /* 0x48 */ + uint32_t rd_rcd; /* 0x4c */ + uint32_t wr_rcd; /* 0x50 */ + uint32_t rrd; /* 0x54 */ + uint32_t rext; /* 0x58 */ + uint32_t wdv; /* 0x5c */ + uint32_t quse; /* 0x60 */ + uint32_t qrst; /* 0x64 */ + uint32_t qsafe; /* 0x68 */ + uint32_t rdv; /* 0x6c */ + uint32_t refresh; /* 0x70 */ + uint32_t burst_refresh_num; /* 0x74 */ + uint32_t pdex2wr; /* 0x78 */ + uint32_t pdex2rd; /* 0x7c */ + uint32_t pchg2pden; /* 0x80 */ + uint32_t act2pden; /* 0x84 */ + uint32_t ar2pden; /* 0x88 */ + uint32_t rw2pden; /* 0x8c */ + uint32_t txsr; /* 0x90 */ + uint32_t tcke; /* 0x94 */ + uint32_t tfaw; /* 0x98 */ + uint32_t trpab; /* 0x9c */ + uint32_t tclkstable; /* 0xa0 */ + uint32_t tclkstop; /* 0xa4 */ + uint32_t trefbw; /* 0xa8 */ + uint32_t rsvd_0xac[1]; /* 0xac */ + uint32_t odt_write; /* 0xb0 */ + uint32_t odt_read; /* 0xb4 */ + uint32_t wext; /* 0xb8 */ + uint32_t ctt; /* 0xbc */ + uint32_t rfc_slr; /* 0xc0 */ + uint32_t mrs_wait_cnt2; /* 0xc4 */ + uint32_t mrs_wait_cnt; /* 0xc8 */ + uint32_t mrs; /* 0xcc */ + uint32_t emrs; /* 0xd0 */ + uint32_t ref; /* 0xd4 */ + uint32_t pre; /* 0xd8 */ + uint32_t nop; /* 0xdc */ + uint32_t self_ref; /* 0xe0 */ + uint32_t dpd; /* 0xe4 */ + uint32_t mrw; /* 0xe8 */ + uint32_t mrr; /* 0xec */ + uint32_t cmdq; /* 0xf0 */ + uint32_t mc2emcq; /* 0xf4 */ + uint32_t xm2dqspadctrl3; /* 0xf8 */ + uint32_t rsvd_0xfc[1]; /* 0xfc */ + uint32_t fbio_spare; /* 0x100 */ + uint32_t fbio_cfg5; /* 0x104 */ + uint32_t fbio_wrptr_eq_2; /* 0x108 */ + uint32_t rsvd_0x10c[2]; /* 0x10c */ + + uint32_t fbio_cfg6; /* 0x114 */ + uint32_t rsvd_0x118[2]; /* 0x118 */ + + uint32_t cfg_rsv; /* 0x120 */ + uint32_t acpd_control; /* 0x124 */ + uint32_t rsvd_0x128[1]; /* 0x128 */ + uint32_t emrs2; /* 0x12c */ + uint32_t emrs3; /* 0x130 */ + uint32_t mrw2; /* 0x134 */ + uint32_t mrw3; /* 0x138 */ + uint32_t mrw4; /* 0x13c */ + uint32_t clken_override; /* 0x140 */ + uint32_t r2r; /* 0x144 */ + uint32_t w2w; /* 0x148 */ + uint32_t einput; /* 0x14c */ + uint32_t einput_duration; /* 0x150 */ + uint32_t puterm_extra; /* 0x154 */ + uint32_t tckesr; /* 0x158 */ + uint32_t tpd; /* 0x15c */ + uint32_t rsvd_0x160[81]; /* 0x160 */ + + uint32_t auto_cal_config; /* 0x2a4 */ + uint32_t auto_cal_interval; /* 0x2a8 */ + uint32_t auto_cal_status; /* 0x2ac */ + uint32_t req_ctrl; /* 0x2b0 */ + uint32_t status; /* 0x2b4 */ + uint32_t cfg_2; /* 0x2b8 */ + uint32_t cfg_dig_dll; /* 0x2bc */ + uint32_t cfg_dig_dll_period; /* 0x2c0 */ + uint32_t rsvd_0x2c4[1]; /* 0x2c4 */ + uint32_t dig_dll_status; /* 0x2c8 */ + uint32_t rdv_mask; /* 0x2cc */ + uint32_t wdv_mask; /* 0x2d0 */ + uint32_t rsvd_0x2d4[1]; /* 0x2d4 */ + uint32_t ctt_duration; /* 0x2d8 */ + uint32_t ctt_term_ctrl; /* 0x2dc */ + uint32_t zcal_interval; /* 0x2e0 */ + uint32_t zcal_wait_cnt; /* 0x2e4 */ + uint32_t zcal_mrw_cmd; /* 0x2e8 */ + uint32_t zq_cal; /* 0x2ec */ + uint32_t xm2cmdpadctrl; /* 0x2f0 */ + uint32_t xm2cmdpadctrl2; /* 0x2f4 */ + uint32_t xm2dqspadctrl; /* 0x2f8 */ + uint32_t xm2dqspadctrl2; /* 0x2fc */ + uint32_t xm2dqpadctrl; /* 0x300 */ + uint32_t xm2dqpadctrl2; /* 0x304 */ + uint32_t xm2clkpadctrl; /* 0x308 */ + uint32_t xm2comppadctrl; /* 0x30c */ + uint32_t xm2vttgenpadctrl; /* 0x310 */ + uint32_t xm2vttgenpadctrl2; /* 0x314 */ + uint32_t xm2vttgenpadctrl3; /* 0x318 */ + uint32_t emcpaden; /* 0x31c */ + uint32_t xm2dqspadctrl4; /* 0x320 */ + uint32_t scratch0; /* 0x324 */ + uint32_t dll_xform_dqs0; /* 0x328 */ + uint32_t dll_xform_dqs1; /* 0x32c */ + uint32_t dll_xform_dqs2; /* 0x330 */ + uint32_t dll_xform_dqs3; /* 0x334 */ + uint32_t dll_xform_dqs4; /* 0x338 */ + uint32_t dll_xform_dqs5; /* 0x33c */ + uint32_t dll_xform_dqs6; /* 0x340 */ + uint32_t dll_xform_dqs7; /* 0x344 */ + uint32_t dll_xform_quse0; /* 0x348 */ + uint32_t dll_xform_quse1; /* 0x34c */ + uint32_t dll_xform_quse2; /* 0x350 */ + uint32_t dll_xform_quse3; /* 0x354 */ + uint32_t dll_xform_quse4; /* 0x358 */ + uint32_t dll_xform_quse5; /* 0x35c */ + uint32_t dll_xform_quse6; /* 0x360 */ + uint32_t dll_xform_quse7; /* 0x364 */ + uint32_t dll_xform_dq0; /* 0x368 */ + uint32_t dll_xform_dq1; /* 0x36c */ + uint32_t dll_xform_dq2; /* 0x370 */ + uint32_t dll_xform_dq3; /* 0x374 */ + uint32_t dli_rx_trim0; /* 0x378 */ + uint32_t dli_rx_trim1; /* 0x37c */ + uint32_t dli_rx_trim2; /* 0x380 */ + uint32_t dli_rx_trim3; /* 0x384 */ + uint32_t dli_rx_trim4; /* 0x388 */ + uint32_t dli_rx_trim5; /* 0x38c */ + uint32_t dli_rx_trim6; /* 0x390 */ + uint32_t dli_rx_trim7; /* 0x394 */ + uint32_t dli_tx_trim0; /* 0x398 */ + uint32_t dli_tx_trim1; /* 0x39c */ + uint32_t dli_tx_trim2; /* 0x3a0 */ + uint32_t dli_tx_trim3; /* 0x3a4 */ + uint32_t dli_trim_txdqs0; /* 0x3a8 */ + uint32_t dli_trim_txdqs1; /* 0x3ac */ + uint32_t dli_trim_txdqs2; /* 0x3b0 */ + uint32_t dli_trim_txdqs3; /* 0x3b4 */ + uint32_t dli_trim_txdqs4; /* 0x3b8 */ + uint32_t dli_trim_txdqs5; /* 0x3bc */ + uint32_t dli_trim_txdqs6; /* 0x3c0 */ + uint32_t dli_trim_txdqs7; /* 0x3c4 */ + uint32_t rsvd_0x3c8[1]; /* 0x3c8 */ + uint32_t stall_then_exe_after_clkchange; /* 0x3cc */ + uint32_t rsvd_0x3d0[1]; /* 0x3d0 */ + uint32_t auto_cal_clk_status; /* 0x3d4 */ + uint32_t sel_dpd_ctrl; /* 0x3d8 */ + uint32_t pre_refresh_req_cnt; /* 0x3dc */ + uint32_t dyn_self_ref_control; /* 0x3e0 */ + uint32_t txsrdll; /* 0x3e4 */ + uint32_t ccfifo_addr; /* 0x3e8 */ + uint32_t ccfifo_data; /* 0x3ec */ + uint32_t ccfifo_status; /* 0x3f0 */ + uint32_t cdb_cntl_1; /* 0x3f4 */ + uint32_t cdb_cntl_2; /* 0x3f8 */ + uint32_t xm2clkpadctrl2; /* 0x3fc */ + uint32_t swizzle_rank0_byte_cfg; /* 0x400 */ + uint32_t swizzle_rank0_byte0; /* 0x404 */ + uint32_t swizzle_rank0_byte1; /* 0x408 */ + uint32_t swizzle_rank0_byte2; /* 0x40c */ + uint32_t swizzle_rank0_byte3; /* 0x410 */ + uint32_t swizzle_rank1_byte_cfg; /* 0x414 */ + uint32_t swizzle_rank1_byte0; /* 0x418 */ + uint32_t swizzle_rank1_byte1; /* 0x41c */ + uint32_t swizzle_rank1_byte2; /* 0x420 */ + uint32_t swizzle_rank1_byte3; /* 0x424 */ + uint32_t ca_training_start; /* 0x428 */ + uint32_t ca_training_busy; /* 0x42c */ + uint32_t ca_training_cfg; /* 0x430 */ + uint32_t ca_training_timing_cntl1; /* 0x434 */ + uint32_t ca_training_timing_cntl2; /* 0x438 */ + uint32_t ca_training_ca_lead_in; /* 0x43c */ + uint32_t ca_training_ca; /* 0x440 */ + uint32_t ca_training_ca_lead_out; /* 0x444 */ + uint32_t ca_training_result1; /* 0x448 */ + uint32_t ca_training_result2; /* 0x44c */ + uint32_t ca_training_result3; /* 0x450 */ + uint32_t ca_training_result4; /* 0x454 */ + uint32_t auto_cal_config2; /* 0x458 */ + uint32_t auto_cal_config3; /* 0x45c */ + uint32_t auto_cal_status2; /* 0x460 */ + uint32_t xm2cmdpadctrl3; /* 0x464 */ + uint32_t ibdly; /* 0x468 */ + uint32_t dll_xform_addr0; /* 0x46c */ + uint32_t dll_xform_addr1; /* 0x470 */ + uint32_t dll_xform_addr2; /* 0x474 */ + uint32_t dli_addr_trim; /* 0x478 */ + uint32_t dsr_vttgen_drv; /* 0x47c */ + uint32_t txdsrvttgen; /* 0x480 */ + uint32_t xm2cmdpadctrl4; /* 0x484 */ + uint32_t xm2cmdpadctrl5; /* 0x488 */ + uint32_t rsvd_0x48c[5]; /* 0x48c */ + + uint32_t dll_xform_dqs8; /* 0x4a0 */ + uint32_t dll_xform_dqs9; /* 0x4a4 */ + uint32_t dll_xform_dqs10; /* 0x4a8 */ + uint32_t dll_xform_dqs11; /* 0x4ac */ + uint32_t dll_xform_dqs12; /* 0x4b0 */ + uint32_t dll_xform_dqs13; /* 0x4b4 */ + uint32_t dll_xform_dqs14; /* 0x4b8 */ + uint32_t dll_xform_dqs15; /* 0x4bc */ + uint32_t dll_xform_quse8; /* 0x4c0 */ + uint32_t dll_xform_quse9; /* 0x4c4 */ + uint32_t dll_xform_quse10; /* 0x4c8 */ + uint32_t dll_xform_quse11; /* 0x4cc */ + uint32_t dll_xform_quse12; /* 0x4d0 */ + uint32_t dll_xform_quse13; /* 0x4d4 */ + uint32_t dll_xform_quse14; /* 0x4d8 */ + uint32_t dll_xform_quse15; /* 0x4dc */ + uint32_t dll_xform_dq4; /* 0x4e0 */ + uint32_t dll_xform_dq5; /* 0x4e4 */ + uint32_t dll_xform_dq6; /* 0x4e8 */ + uint32_t dll_xform_dq7; /* 0x4ec */ + uint32_t rsvd_0x4f0[12]; /* 0x4f0 */ + + uint32_t dli_trim_txdqs8; /* 0x520 */ + uint32_t dli_trim_txdqs9; /* 0x524 */ + uint32_t dli_trim_txdqs10; /* 0x528 */ + uint32_t dli_trim_txdqs11; /* 0x52c */ + uint32_t dli_trim_txdqs12; /* 0x530 */ + uint32_t dli_trim_txdqs13; /* 0x534 */ + uint32_t dli_trim_txdqs14; /* 0x538 */ + uint32_t dli_trim_txdqs15; /* 0x53c */ + uint32_t cdb_cntl_3; /* 0x540 */ + uint32_t xm2dqspadctrl5; /* 0x544 */ + uint32_t xm2dqspadctrl6; /* 0x548 */ + uint32_t xm2dqpadctrl3; /* 0x54c */ + uint32_t dll_xform_addr3; /* 0x550 */ + uint32_t dll_xform_addr4; /* 0x554 */ + uint32_t dll_xform_addr5; /* 0x558 */ + uint32_t rsvd_0x55c[1]; /* 0x55c */ + uint32_t cfg_pipe; /* 0x560 */ + uint32_t qpop; /* 0x564 */ + uint32_t quse_width; /* 0x568 */ + uint32_t puterm_width; /* 0x56c */ + uint32_t bgbias_ctl0; /* 0x570 */ + uint32_t puterm_adj; /* 0x574 */ +} __attribute__((packed)); + +check_member(tegra_emc_regs, puterm_adj, 0x574); + +#endif /* __SOC_NVIDIA_TEGRA124_EMC_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/addressmap.h b/src/soc/nvidia/tegra124/include/soc/addressmap.h index b3c0b2961d..5e55ee57e0 100644 --- a/src/soc/nvidia/tegra124/include/soc/addressmap.h +++ b/src/soc/nvidia/tegra124/include/soc/addressmap.h @@ -66,9 +66,9 @@ enum { TEGRA_SPI6_BASE = TEGRA_APB_MISC_BASE + 0xDE00, TEGRA_DVC_BASE = TEGRA_APB_MISC_BASE + 0xD000, TEGRA_PMC_BASE = TEGRA_APB_MISC_BASE + 0xE400, - TEGRA_EMC_BASE = TEGRA_APB_MISC_BASE + 0xF400, TEGRA_FUSE_BASE = TEGRA_APB_MISC_BASE + 0xF800, TEGRA_MC_BASE = 0x70019000, + TEGRA_EMC_BASE = 0x7001B000, TEGRA_CSITE_BASE = 0x70040000, TEGRA_SYSCTR0_BASE = 0x700F0000, TEGRA_USBD_BASE = 0x7D000000, diff --git a/src/soc/nvidia/tegra124/include/soc/clock.h b/src/soc/nvidia/tegra124/include/soc/clock.h index 3ec36080c7..89be88b020 100644 --- a/src/soc/nvidia/tegra124/include/soc/clock.h +++ b/src/soc/nvidia/tegra124/include/soc/clock.h @@ -247,6 +247,9 @@ enum clock_source { /* Careful: Not true for all sources, always check TRM! */ int clock_get_osc_khz(void); void clock_early_uart(void); void clock_external_output(int clk_id); +void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, + u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source, + u32 same_freq); void clock_cpu0_config_and_reset(void * entry); void clock_halt_avp(void); void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x); diff --git a/src/soc/nvidia/tegra124/include/soc/display.h b/src/soc/nvidia/tegra124/include/soc/display.h index 27935d9cea..b764671134 100644 --- a/src/soc/nvidia/tegra124/include/soc/display.h +++ b/src/soc/nvidia/tegra124/include/soc/display.h @@ -44,6 +44,9 @@ /* ardisplay_a.h */ #define DC_WIN_A_WIN_OPTIONS_0 0x700 +#define DC_WIN_A_WIN_OPTIONS_0_A_WIN_ENABLE_SHIFT 30 +#define DC_WIN_A_WIN_OPTIONS_0_A_WIN_ENABLE_FIELD (0x1 << DC_WIN_A_WIN_OPTIONS_0_A_WIN_ENABLE_SHIFT) +#define DC_WIN_A_WIN_OPTIONS_0_A_WIN_ENABLE_ENABLE (1) #define DC_WIN_A_BYTE_SWAP_0 0x701 #define DC_WIN_A_BUFFER_CONTROL_0 0x702 #define DC_WIN_A_COLOR_DEPTH_0 0x703 @@ -59,6 +62,7 @@ #define DC_WIN_A_BLEND_MATCH_SELECT_0 0x717 #define DC_WIN_A_BLEND_NOMATCH_SELECT_0 0x718 #define DC_WIN_A_BLEND_ALPHA_1BIT_0 0x719 +#define DC_WINBUF_A_START_ADDR_LO_0 0x800 #define DC_WINBUF_A_START_ADDR_HI_0 0x80d #define DC_WINBUF_A_ADDR_H_OFFSET_0 0x806 #define DC_WINBUF_A_ADDR_V_OFFSET_0 0x808 @@ -177,9 +181,18 @@ /* ardpaux.h */ #define DPAUX_DP_AUXDATA_READ_W0 0x19 +#define DP_LVDS_SHIFT 25 +#define DP_LVDS (1 << DP_LVDS_SHIFT) + +#define SRC_BPP 16 +#define COLORDEPTH 0x6 +#define COLOR_WHITE 0xFFFFFF + void setup_display(struct soc_nvidia_tegra124_config *config); void init_dca_regs(void); -void init_dpaux_regs(void); -void init_sor_regs(void); void dp_io_powerup(void); +u32 dp_setup_timing(u32 width, u32 height); +void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr, + u32 lane_count, u32 enhanced_framing, u32 panel_edp, + u32 pclkfreq, u32 linkfreq); #endif /* __SOC_NVIDIA_TEGRA124_INCLUDE_SOC_DISPLAY_H__ */ diff --git a/src/soc/nvidia/tegra124/lp0/Makefile b/src/soc/nvidia/tegra124/lp0/Makefile new file mode 100644 index 0000000000..57680c562f --- /dev/null +++ b/src/soc/nvidia/tegra124/lp0/Makefile @@ -0,0 +1,58 @@ +################################################################################ +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +################################################################################ + +CC = $(GCC_PREFIX)gcc +NM = $(GCC_PREFIX)nm +OBJCOPY = $(GCC_PREFIX)objcopy + +OPENSSL = openssl +DD = dd +CP = cp +MV = mv +RM = rm + +SIGKEY = 00000000000000000000000000000000 + +.PHONY: all +all: tegra_lp0_resume.fw + +tegra_lp0_resume.elf: tegra_lp0_resume.ld tegra_lp0_resume.c + $(CC) -marm -march=armv4t -mno-unaligned-access -nostdlib -static \ + -Os -fpie -Wl,--build-id=none -ggdb3 -T tegra_lp0_resume.ld \ + -o $@ $(filter %.c,$+) + +tegra_lp0_resume.fw: tegra_lp0_resume.elf + @# Get rid of any files we're about to create. + $(RM) -f $@.nosig $@.sig $@.tosig + @# Convert the ELF image into a binary image. + $(OBJCOPY) -O binary $< $@.nosig + @# Extract the part of the binary which needs to be signed. + $(DD) bs=1 skip=544 if=$@.nosig of=$@.tosig + @# Calculate a signature for that part. + $(OPENSSL) dgst -mac cmac -macopt cipher:aes-128-cbc \ + -macopt hexkey:$(SIGKEY) -md5 -binary \ + $@.tosig > $@.sig + @# Inject the signature into the binary image's header. + $(DD) conv=notrunc bs=1 seek=272 count=16 if=$@.sig of=$@.nosig + @# Copy the signed binary to the target file name. + $(MV) $@.nosig $@ + +clean: + $(RM) -f tegra_lp0_resume.fw tegra_lp0_resume.fw.sig + $(RM) -f tegra_lp0_resume.fw.tosig tegra_lp0_resume.elf diff --git a/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.c b/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.c new file mode 100644 index 0000000000..72506c81f5 --- /dev/null +++ b/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.c @@ -0,0 +1,627 @@ +/* + * Copyright 2014 Google Inc. + * Copyright 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +/* Function unit addresses. */ +enum { + UP_TAG_BASE = 0X60000000, + TIMER_BASE = 0X60005000, + CLK_RST_BASE = 0X60006000, + FLOW_CTLR_BASE = 0X60007000, + TEGRA_EVP_BASE = 0x6000f000, + PMC_CTLR_BASE = 0X7000e400, + MC_CTLR_BASE = 0X70019000, + SYSCTR_CTLR_BASE = 0X700f0000 +}; + + + +/* UP tag registers. */ +static uint32_t *up_tag_ptr = (void *)(UP_TAG_BASE + 0x0); +enum { + UP_TAG_AVP = 0xaaaaaaaa +}; + + + +/* Timer registers. */ +static uint32_t *timer_us_ptr = (void *)(TIMER_BASE + 0x10); + + + +/* Clock and reset controller registers. */ +static uint32_t *clk_rst_rst_devices_l_ptr = (void *)(CLK_RST_BASE + 0x4); +enum { + SWR_TRIG_SYS_RST = 0x1 << 2 +}; + +static uint32_t *clk_rst_cclk_burst_policy_ptr = (void *)(CLK_RST_BASE + 0x20); +enum { + CCLK_PLLP_BURST_POLICY = 0x20004444 +}; + +static uint32_t *clk_rst_super_cclk_div_ptr = (void *)(CLK_RST_BASE + 0x24); +enum { + SUPER_CDIV_ENB = 0x1 << 31 +}; + +static uint32_t *clk_rst_osc_ctrl_ptr = (void *)(CLK_RST_BASE + 0x50); +enum { + OSC_XOE = 0x1 << 0, + OSC_XOFS_SHIFT = 4, + OSC_XOFS_MASK = 0x3f << OSC_XOFS_SHIFT, + OSC_FREQ_SHIFT = 28, + OSC_FREQ_MASK = 0xf << OSC_FREQ_SHIFT +}; +enum { + OSC_FREQ_13 = 0, + OSC_FREQ_16P8 = 1, + OSC_FREQ_19P2 = 4, + OSC_FREQ_38P4 = 5, + OSC_FREQ_12 = 8, + OSC_FREQ_48 = 9, + OSC_FREQ_26 = 12 +}; + +static uint32_t *clk_rst_pllu_base_ptr = (void *)(CLK_RST_BASE + 0xc0); +enum { + PLLU_DIVM_SHIFT = 0, + PLLU_DIVN_SHIFT = 8, + PLLU_OVERRIDE = 0x1 << 24, + PLLU_ENABLE = 0x1 << 30, + PLLU_BYPASS = 0x1 << 31 +}; + +static uint32_t *clk_rst_pllu_misc_ptr = (void *)(CLK_RST_BASE + 0xcc); +enum { + PLLU_LFCON_SHIFT = 4, + PLLU_CPCON_SHIFT = 8, + PLLU_LOCK_ENABLE = 22 +}; + +static uint32_t *clk_rst_pllx_base_ptr = (void *)(CLK_RST_BASE + 0xe0); +enum { + PLLX_ENABLE = 0x1 << 30 +}; + +static uint32_t *clk_rst_rst_dev_u_clr_ptr = (void *)(CLK_RST_BASE + 0x314); +enum { + SWR_CSITE_RST = 0x1 << 9 +}; + +static uint32_t *clk_rst_clk_enb_l_set_ptr = (void *)(CLK_RST_BASE + 0x320); +enum { + CLK_ENB_CPU = 0x1 << 0 +}; + +static uint32_t *clk_rst_clk_out_enb_u_set_ptr = + (void *)(CLK_RST_BASE + 0x330); +enum { + CLK_ENB_CSITE = 0x1 << 9 +}; + +static uint32_t *clk_rst_cpu_softrst_ctrl2_ptr = + (void *)(CLK_RST_BASE + 0x388); +enum { + CAR2PMC_CPU_ACK_WIDTH_SHIFT = 0, + CAR2PMC_CPU_ACK_WIDTH_MASK = 0xfff << CAR2PMC_CPU_ACK_WIDTH_SHIFT +}; + +static uint32_t *clk_rst_clk_src_mselect_ptr = + (void *)(CLK_RST_BASE + 0x3b4); +enum { + MSELECT_CLK_DIV_SHIFT = 0, + MSELECT_CLK_SRC_SHIFT = 29, + MSELECT_CLK_SRC_PLLP_OUT0 = 0x0 << MSELECT_CLK_SRC_SHIFT, + MSELECT_CLK_SRC_PLLC2_OUT0 = 0x1 << MSELECT_CLK_SRC_SHIFT, + MSELECT_CLK_SRC_PLLC_OUT0 = 0x2 << MSELECT_CLK_SRC_SHIFT, + MSELECT_CLK_SRC_PLLC3_OUT0 = 0x3 << MSELECT_CLK_SRC_SHIFT +}; + +static uint32_t *clk_rst_rst_dev_v_clr_ptr = (void *)(CLK_RST_BASE + 0x434); +enum { + SWR_MSELECT_RST = 0x1 << 3 +}; + +static uint32_t *clk_rst_clk_enb_v_set_ptr = (void *)(CLK_RST_BASE + 0x440); +enum { + CLK_ENB_CPUG = 0x1 << 0, + CLK_ENB_CPULP = 0x1 << 1, + CLK_ENB_MSELECT = 0x1 << 3 +}; + +static uint32_t *clk_rst_rst_cpulp_cmplx_clr_ptr = + (void *)(CLK_RST_BASE + 0x45c); +static uint32_t *clk_rst_rst_cpug_cmplx_clr_ptr = + (void *)(CLK_RST_BASE + 0x454); +enum { + CLR_CPURESET0 = 0x1 << 0, + CLR_CPURESET1 = 0x1 << 1, + CLR_CPURESET2 = 0x1 << 2, + CLR_CPURESET3 = 0x1 << 3, + CLR_DBGRESET0 = 0x1 << 12, + CLR_DBGRESET1 = 0x1 << 13, + CLR_DBGRESET2 = 0x1 << 14, + CLR_DBGRESET3 = 0x1 << 15, + CLR_CORERESET0 = 0x1 << 16, + CLR_CORERESET1 = 0x1 << 17, + CLR_CORERESET2 = 0x1 << 18, + CLR_CORERESET3 = 0x1 << 19, + CLR_CXRESET0 = 0x1 << 20, + CLR_CXRESET1 = 0x1 << 21, + CLR_CXRESET2 = 0x1 << 22, + CLR_CXRESET3 = 0x1 << 23, + CLR_NONCPURESET = 0x1 << 29 +}; + + + +/* Reset vector. */ + +static uint32_t *evp_cpu_reset_ptr = (void *)(TEGRA_EVP_BASE + 0x100); + + + +/* Flow controller registers. */ +static uint32_t *flow_ctlr_halt_cop_events_ptr = + (void *)(FLOW_CTLR_BASE + 0x4); +enum { + EVENT_MSEC = 0x1 << 24, + EVENT_JTAG = 0x1 << 28, + FLOW_MODE_SHIFT = 29, + FLOW_MODE_STOP = 2 << FLOW_MODE_SHIFT, +}; + +static uint32_t *flow_ctlr_cluster_control_ptr = + (void *)(FLOW_CTLR_BASE + 0x2c); +enum { + FLOW_CLUSTER_ACTIVE_LP = 0x1 << 0 +}; + + + +/* Power management controller registers. */ +enum { + PARTID_CRAIL = 0, + PARTID_CELP = 12, + PARTID_CE0 = 14, + PARTID_C0NC = 15, + PARTID_C1NC = 16 +}; + +static uint32_t *pmc_ctlr_clamp_status_ptr = (void *)(PMC_CTLR_BASE + 0x2c); + +static uint32_t *pmc_ctlr_pwrgate_toggle_ptr = (void *)(PMC_CTLR_BASE + 0x30); +enum { + PWRGATE_TOGGLE_START = 0x1 << 8 +}; + +static uint32_t *pmc_ctlr_pwrgate_status_ptr = (void *)(PMC_CTLR_BASE + 0x38); + +static uint32_t *pmc_ctlr_scratch4_ptr = (void *)(PMC_CTLR_BASE + 0x60); +enum { + PMC_SCRATCH4_LP = 0x1 << 31 +}; + +static uint32_t *pmc_ctlr_cpupwrgood_timer_ptr = + (void *)(PMC_CTLR_BASE + 0xc8); + +static uint32_t *pmc_ctlr_scratch41_ptr = (void *)(PMC_CTLR_BASE + 0x140); + +static uint32_t *pmc_ctlr_osc_edpd_over_ptr = (void *)(PMC_CTLR_BASE + 0x1a4); +enum { + PMC_XOFS_SHIFT = 1, + PMC_XOFS_MASK = 0x3f << PMC_XOFS_SHIFT +}; + + + +/* Memory controller registers. */ +static uint32_t *mc_video_protect_size_mb_ptr = (void *)(MC_CTLR_BASE + 0x64c); + +static uint32_t *mc_video_protect_reg_ctrl_ptr = + (void *)(MC_CTLR_BASE + 0x650); +enum { + VIDEO_PROTECT_WRITE_ACCESS_DISABLE = 0x1 << 0, + VIDEO_PROTECT_ALLOW_TZ_WRITE_ACCESS = 0x1 << 1 +}; + + + +/* System counter registers. */ +static uint32_t *sysctr_cntcr_ptr = (void *)(SYSCTR_CTLR_BASE + 0x0); +enum { + TSC_CNTCR_ENABLE = 0x1 << 0, + TSC_CNTCR_HDBG = 0x1 << 1 +}; + +static uint32_t *sysctr_cntfid0_ptr = (void *)(SYSCTR_CTLR_BASE + 0x20); + + + +/* Utility functions. */ + +static inline void __attribute__((always_inline)) + __attribute__((noreturn)) halt(void) +{ + for (;;); +} + +inline static uint32_t read32(const void *addr) +{ + return *(volatile uint32_t *)addr; +} + +inline static void write32(uint32_t val, void *addr) +{ + *(volatile uint32_t *)addr = val; +} + +inline static void setbits32(uint32_t bits, void *addr) +{ + write32(read32(addr) | bits, addr); +} + +inline static void clrbits32(uint32_t bits, void *addr) +{ + write32(read32(addr) & ~bits, addr); +} + +static void __attribute__((noreturn)) reset(void) +{ + write32(SWR_TRIG_SYS_RST, clk_rst_rst_devices_l_ptr); + halt(); +} + +static void udelay(unsigned usecs) +{ + uint32_t start = read32(timer_us_ptr); + while (read32(timer_us_ptr) - start < usecs) + ; +} + + + +/* Accessors. */ + +static int wakeup_on_lp(void) +{ + return !!(read32(pmc_ctlr_scratch4_ptr) & PMC_SCRATCH4_LP); +} + +static uint32_t get_wakeup_vector(void) +{ + return read32(pmc_ctlr_scratch41_ptr); +} + +static unsigned get_osc_freq(void) +{ + return (read32(clk_rst_osc_ctrl_ptr) & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; +} + + + +/* Clock configuration. */ + +static void config_oscillator(void) +{ + // Read oscillator drive strength from OSC_EDPD_OVER.XOFS and copy + // to OSC_CTRL.XOFS and set XOE. + uint32_t xofs = (read32(pmc_ctlr_osc_edpd_over_ptr) & + PMC_XOFS_MASK) >> PMC_XOFS_SHIFT; + + uint32_t osc_ctrl = read32(clk_rst_osc_ctrl_ptr); + osc_ctrl &= OSC_XOFS_MASK; + osc_ctrl |= (xofs << OSC_XOFS_SHIFT); + osc_ctrl |= OSC_XOE; + write32(osc_ctrl, clk_rst_osc_ctrl_ptr); +} + +static void config_pllu(void) +{ + // Figure out what parameters to use for PLLU. + uint32_t divm, divn, cpcon, lfcon; + switch (get_osc_freq()) { + case OSC_FREQ_12: + case OSC_FREQ_48: + divm = 0x0c; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + break; + case OSC_FREQ_16P8: + divm = 0x07; + divn = 0x190; + cpcon = 0x05; + lfcon = 0x02; + break; + case OSC_FREQ_19P2: + case OSC_FREQ_38P4: + divm = 0x04; + divn = 0xc8; + cpcon = 0x03; + lfcon = 0x02; + break; + case OSC_FREQ_26: + divm = 0x1a; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + break; + default: + // Map anything that's not recognized to 13MHz. + divm = 0x0d; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + } + + // Configure PLLU. + uint32_t base = PLLU_BYPASS | PLLU_OVERRIDE | + (divn << PLLU_DIVN_SHIFT) | (divm << PLLU_DIVM_SHIFT); + write32(base, clk_rst_pllu_base_ptr); + uint32_t misc = (cpcon << PLLU_CPCON_SHIFT) | + (lfcon << PLLU_LFCON_SHIFT); + write32(misc, clk_rst_pllu_misc_ptr); + + // Enable PLLU. + base &= ~PLLU_BYPASS; + base |= PLLU_ENABLE; + write32(base, clk_rst_pllu_base_ptr); + misc |= PLLU_LOCK_ENABLE; + write32(misc, clk_rst_pllu_misc_ptr); +} + +static void config_tsc(void) +{ + // Tell the TSC the oscillator frequency. + switch (get_osc_freq()) { + case OSC_FREQ_12: + write32(12000000, sysctr_cntfid0_ptr); + break; + case OSC_FREQ_48: + write32(48000000, sysctr_cntfid0_ptr); + break; + case OSC_FREQ_16P8: + write32(16800000, sysctr_cntfid0_ptr); + break; + case OSC_FREQ_19P2: + write32(19200000, sysctr_cntfid0_ptr); + break; + case OSC_FREQ_38P4: + write32(38400000, sysctr_cntfid0_ptr); + break; + case OSC_FREQ_26: + write32(26000000, sysctr_cntfid0_ptr); + break; + default: + // Default to 13MHz. + write32(13000000, sysctr_cntfid0_ptr); + break; + } + + // Enable the TSC. + setbits32(TSC_CNTCR_ENABLE | TSC_CNTCR_HDBG, sysctr_cntcr_ptr); +} + + + +/* Function unit configuration. */ + +static void config_core_sight(void) +{ + // Enable the CoreSight clock. + write32(CLK_ENB_CSITE, clk_rst_clk_out_enb_u_set_ptr); + + /* + * De-assert CoreSight reset. + * NOTE: We're leaving the CoreSight clock on the oscillator for + * now. It will be restored to its original clock source + * when the CPU-side restoration code runs. + */ + write32(SWR_CSITE_RST, clk_rst_rst_dev_u_clr_ptr); +} + +static void config_mselect(void) +{ + // Set MSELECT clock source to PLLP with 1:4 divider. + write32((6 << MSELECT_CLK_DIV_SHIFT) | MSELECT_CLK_SRC_PLLP_OUT0, + clk_rst_clk_src_mselect_ptr); + + // Enable clock to MSELECT. + write32(CLK_ENB_MSELECT, clk_rst_clk_enb_v_set_ptr); + + udelay(2); + + // Bring MSELECT out of reset. + write32(SWR_MSELECT_RST, clk_rst_rst_dev_v_clr_ptr); +} + + + +/* Resets. */ + +static void clear_cpu_resets(void) +{ + // Take the non-cpu of the G and LP clusters out of reset. + write32(CLR_NONCPURESET, clk_rst_rst_cpulp_cmplx_clr_ptr); + write32(CLR_NONCPURESET, clk_rst_rst_cpug_cmplx_clr_ptr); + + // Clear software controlled reset of the slow cluster. + write32(CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0, + clk_rst_rst_cpulp_cmplx_clr_ptr); + + // Clear software controlled reset of the fast cluster. + write32(CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 | + CLR_CPURESET1 | CLR_DBGRESET1 | CLR_CORERESET1 | CLR_CXRESET1 | + CLR_CPURESET2 | CLR_DBGRESET2 | CLR_CORERESET2 | CLR_CXRESET2 | + CLR_CPURESET3 | CLR_DBGRESET3 | CLR_CORERESET3 | CLR_CXRESET3, + clk_rst_rst_cpug_cmplx_clr_ptr); +} + + + +/* Power. */ + +static void power_on_partition(unsigned id) +{ + uint32_t bit = 0x1 << id; + if (!(read32(pmc_ctlr_pwrgate_status_ptr) & bit)) { + // Partition is not on. Turn it on. + write32(id | PWRGATE_TOGGLE_START, pmc_ctlr_pwrgate_toggle_ptr); + + // Wait until the partition is powerd on. + while (!(read32(pmc_ctlr_pwrgate_status_ptr) & bit)) + ; + + // Wait until clamp is off. + while (read32(pmc_ctlr_clamp_status_ptr) & bit) + ; + } +} + +static void power_on_main_cpu(void) +{ + /* + * Reprogram PMC_CPUPWRGOOD_TIMER register: + * + * XXX This is a fragile assumption. XXX + * The kernel prepares PMC_CPUPWRGOOD_TIMER based on a 32768Hz clock. + * Note that PMC_CPUPWRGOOD_TIMER is running at pclk. + * + * We need to reprogram PMC_CPUPWRGOOD_TIMER based on the current pclk + * which is at 408Mhz (pclk = sclk = pllp_out0) after reset. Multiply + * PMC_CPUPWRGOOD_TIMER by 408M / 32K. + * + * Save the original PMC_CPUPWRGOOD_TIMER register which we need to + * restore after the CPU is powered up. + */ + uint32_t orig_timer = read32(pmc_ctlr_cpupwrgood_timer_ptr); + + write32(orig_timer * (408000000 / 32768), + pmc_ctlr_cpupwrgood_timer_ptr); + + if (wakeup_on_lp()) { + power_on_partition(PARTID_C1NC); + power_on_partition(PARTID_CELP); + } else { + power_on_partition(PARTID_CRAIL); + power_on_partition(PARTID_C0NC); + power_on_partition(PARTID_CE0); + } + + // Give I/O signals time to stablize. + write32(20 | EVENT_MSEC | FLOW_MODE_STOP, + flow_ctlr_halt_cop_events_ptr); + + // Restore the original PMC_CPUPWRGOOD_TIMER. + write32(orig_timer, pmc_ctlr_cpupwrgood_timer_ptr); +} + + + +/* Entry point. */ + +void lp0_resume(void) +{ + // If not on the AVP, reset. + if (read32(up_tag_ptr) != UP_TAG_AVP) + reset(); + + config_oscillator(); + + // Tell the flow controller which cluster to wake up. The default is + // the fast cluster. + if (wakeup_on_lp()) + setbits32(FLOW_CLUSTER_ACTIVE_LP, + flow_ctlr_cluster_control_ptr); + + // Program SUPER_CCLK_DIVIDER. + write32(SUPER_CDIV_ENB, clk_rst_super_cclk_div_ptr); + + config_core_sight(); + + config_pllu(); + + // Set the CPU reset vector. + write32(get_wakeup_vector(), evp_cpu_reset_ptr); + + // Select CPU complex clock source. + write32(CCLK_PLLP_BURST_POLICY, clk_rst_cclk_burst_policy_ptr); + + config_mselect(); + + // Disable PLLX since it isn't used as CPU clock source. + clrbits32(PLLX_ENABLE, clk_rst_pllx_base_ptr); + + // Set CAR2PMC_CPU_ACK_WIDTH to 408. + uint32_t ack_width = read32(clk_rst_cpu_softrst_ctrl2_ptr); + ack_width &= ~CAR2PMC_CPU_ACK_WIDTH_MASK; + ack_width |= 408 << CAR2PMC_CPU_ACK_WIDTH_SHIFT; + write32(ack_width, clk_rst_cpu_softrst_ctrl2_ptr); + + // Enable the CPU complex clock. + write32(CLK_ENB_CPU, clk_rst_clk_enb_l_set_ptr); + write32(CLK_ENB_CPUG | CLK_ENB_CPULP, clk_rst_clk_enb_v_set_ptr); + + clear_cpu_resets(); + + config_tsc(); + + power_on_main_cpu(); + + // Disable VPR. + write32(0, mc_video_protect_size_mb_ptr); + write32(VIDEO_PROTECT_WRITE_ACCESS_DISABLE, + mc_video_protect_reg_ctrl_ptr); + + // Halt the AVP. + while (1) + write32(FLOW_MODE_STOP | EVENT_JTAG, + flow_ctlr_halt_cop_events_ptr); +} + + + +/* Header. */ + +extern uint8_t blob_data; +extern uint8_t blob_data_size; +extern uint8_t blob_total_size; + +struct lp0_header { + uint32_t length_insecure; // Insecure total length. + uint32_t reserved[3]; + uint8_t rsa_modulus[256]; // RSA key modulus. + uint8_t aes_signature[16]; // AES signature. + uint8_t rsa_signature[256]; // RSA-PSS signature. + uint8_t random_aes_block[16]; // Random data, may be zero. + uint32_t length_secure; // Secure total length. + uint32_t destination; // Where to load the blob in iRAM. + uint32_t entry_point; // Entry point for the blob. + uint32_t code_length; // Length of just the data. +} __attribute__((packed)); + +struct lp0_header header __attribute__((section(".header"))) = +{ + .length_insecure = (uintptr_t)&blob_total_size, + .length_secure = (uintptr_t)&blob_total_size, + .destination = (uintptr_t)&blob_data, + .entry_point = (uintptr_t)&lp0_resume, + .code_length = (uintptr_t)&blob_data_size +}; diff --git a/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.ld b/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.ld new file mode 100644 index 0000000000..c4c508ff4c --- /dev/null +++ b/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.ld @@ -0,0 +1,73 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* We use ELF as output format. So that we can debug the code in some form. */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +PHDRS +{ + to_load PT_LOAD; +} + +ENTRY(lp0_resume) +SECTIONS +{ + . = 0x40020000 - 0x240; + + /* + * The lp0 blob header is built as a static data structure and put + * in the .header section. + */ + .header_start = .; + .header . : { + *(.header); + } : to_load = 0xff + .header_end = .; + + . = 0x40020000; + + /* The actual lp0 blob code. */ + .data_start = .; + .data . : { + *(.text); + *(.text.*); + *(.rodata); + *(.rodata.*); + *(.data); + *(.data.*); + *(.bss); + *(.bss.*); + *(.sbss); + *(.sbss.*); + . = ALIGN(16); + } + .data_end = .; + + /* Some values we need in the header. */ + blob_data = .data_start; + blob_data_size = .data_end - .data_start; + blob_total_size = .data_end - .header_start; + + /DISCARD/ : { + *(.comment) + *(.note) + *(.comment.*) + *(.note.*) + *(.ARM.*) + } +} diff --git a/src/soc/nvidia/tegra124/mc.h b/src/soc/nvidia/tegra124/mc.h index 92a38ed95f..0fc3738746 100644 --- a/src/soc/nvidia/tegra124/mc.h +++ b/src/soc/nvidia/tegra124/mc.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2010 - 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2013 Google Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -14,34 +15,114 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _TEGRA124_MC_H_ -#define _TEGRA124_MC_H_ +#ifndef __SOC_NVIDIA_TEGRA124_MC_H__ +#define __SOC_NVIDIA_TEGRA124_MC_H__ +#include <stddef.h> #include <stdint.h> // Memory Controller registers we need/care about struct tegra_mc_regs { - u32 reserved0[4]; - u32 mc_smmu_config; - u32 mc_smmu_tlb_config; - u32 mc_smmu_ptc_config; - u32 mc_smmu_ptb_asid; - u32 mc_smmu_ptb_data; - u32 reserved1[3]; - u32 mc_smmu_tlb_flush; - u32 mc_smmu_ptc_flush; - u32 reserved2[6]; - u32 mc_emem_cfg; - u32 mc_emem_adr_cfg; - u32 mc_emem_adr_cfg_dev0; - u32 mc_emem_adr_cfg_dev1; - u32 reserved3[12]; - u32 mc_emem_arb_reserved[28]; - u32 reserved4[338]; - u32 mc_vpr_bom; - u32 mc_vpr_size; - u32 mc_vpr_ctrl; + uint32_t rsvd_0x0[4]; /* 0x00 */ + uint32_t smmu_config; /* 0x10 */ + uint32_t smmu_tlb_config; /* 0x14 */ + uint32_t smmu_ptc_config; /* 0x18 */ + uint32_t smmu_ptb_asid; /* 0x1c */ + uint32_t smmu_ptb_data; /* 0x20 */ + uint32_t rsvd_0x24[3]; /* 0x24 */ + uint32_t smmu_tlb_flush; /* 0x30 */ + uint32_t smmu_ptc_flush; /* 0x34 */ + uint32_t rsvd_0x38[6]; /* 0x38 */ + uint32_t emem_cfg; /* 0x50 */ + uint32_t emem_adr_cfg; /* 0x54 */ + uint32_t emem_adr_cfg_dev0; /* 0x58 */ + uint32_t emem_adr_cfg_dev1; /* 0x5c */ + uint32_t rsvd_0x60[1]; /* 0x60 */ + uint32_t emem_adr_cfg_bank_mask_0; /* 0x64 */ + uint32_t emem_adr_cfg_bank_mask_1; /* 0x68 */ + uint32_t emem_adr_cfg_bank_mask_2; /* 0x6c */ + uint32_t rsvd_0x70[8]; /* 0x70 */ + uint32_t emem_arb_cfg; /* 0x90 */ + uint32_t emem_arb_outstanding_req; /* 0x94 */ + uint32_t emem_arb_timing_rcd; /* 0x98 */ + uint32_t emem_arb_timing_rp; /* 0x9c */ + uint32_t emem_arb_timing_rc; /* 0xa0 */ + uint32_t emem_arb_timing_ras; /* 0xa4 */ + uint32_t emem_arb_timing_faw; /* 0xa8 */ + uint32_t emem_arb_timing_rrd; /* 0xac */ + uint32_t emem_arb_timing_rap2pre; /* 0xb0 */ + uint32_t emem_arb_timing_wap2pre; /* 0xb4 */ + uint32_t emem_arb_timing_r2r; /* 0xb8 */ + uint32_t emem_arb_timing_w2w; /* 0xbc */ + uint32_t emem_arb_timing_r2w; /* 0xc0 */ + uint32_t emem_arb_timing_w2r; /* 0xc4 */ + uint32_t rsvd_0xc8[2]; /* 0xc8 */ + uint32_t emem_arb_da_turns; /* 0xd0 */ + uint32_t emem_arb_da_covers; /* 0xd4 */ + uint32_t emem_arb_misc0; /* 0xd8 */ + uint32_t emem_arb_misc1; /* 0xdc */ + uint32_t emem_arb_ring1_throttle; /* 0xe0 */ + uint32_t emem_arb_ring3_throttle; /* 0xe4 */ + uint32_t emem_arb_override; /* 0xe8 */ + uint32_t emem_arb_rsv; /* 0xec */ + uint32_t rsvd_0xf0[1]; /* 0xf0 */ + uint32_t clken_override; /* 0xf4 */ + uint32_t timing_control_dbg; /* 0xf8 */ + uint32_t timing_control; /* 0xfc */ + uint32_t stat_control; /* 0x100 */ + uint32_t rsvd_0x104[65]; /* 0x104 */ + uint32_t emem_arb_isochronous_0; /* 0x208 */ + uint32_t emem_arb_isochronous_1; /* 0x20c */ + uint32_t emem_arb_isochronous_2; /* 0x210 */ + uint32_t rsvd_0x214[38]; /* 0x214 */ + uint32_t dis_extra_snap_levels; /* 0x2ac */ + uint32_t rsvd_0x2b0[90]; /* 0x2b0 */ + uint32_t video_protect_vpr_override; /* 0x418 */ + uint32_t rsvd_0x41c[93]; /* 0x41c */ + uint32_t video_protect_vpr_override1; /* 0x590 */ + uint32_t rsvd_0x594[29]; /* 0x594 */ + uint32_t display_snap_ring; /* 0x608 */ + uint32_t rsvd_0x60c[15]; /* 0x60c */ + uint32_t video_protect_bom; /* 0x648 */ + uint32_t video_protect_size_mb; /* 0x64c */ + uint32_t video_protect_reg_ctrl; /* 0x650 */ + uint32_t rsvd_0x654[4]; /* 0x654 */ + uint32_t emem_cfg_access_ctrl; /* 0x664 */ + uint32_t rsvd_0x668[2]; /* 0x668 */ + uint32_t sec_carveout_bom; /* 0x670 */ + uint32_t sec_carveout_size_mb; /* 0x674 */ + uint32_t sec_carveout_reg_ctrl; /* 0x678 */ + uint32_t rsvd_0x67c[187]; /* 0x67c */ + uint32_t emem_arb_override_1; /* 0x968 */ + uint32_t rsvd_0x96c[3]; /* 0x96c */ + uint32_t video_protect_bom_adr_hi; /* 0x978 */ + uint32_t rsvd_0x97c[2]; /* 0x97c */ + uint32_t video_protect_gpu_override_0; /* 0x984 */ + uint32_t video_protect_gpu_override_1; /* 0x988 */ + uint32_t rsvd_0x98c[5]; /* 0x98c */ + uint32_t mts_carveout_bom; /* 0x9a0 */ + uint32_t mts_carveout_size_mb; /* 0x9a4 */ + uint32_t mts_carveout_adr_hi; /* 0x9a8 */ + uint32_t mts_carveout_reg_ctrl; /* 0x9ac */ + uint32_t rsvd_0x9b0[4]; /* 0x9b0 */ + uint32_t emem_bank_swizzle_cfg0; /* 0x9c0 */ + uint32_t emem_bank_swizzle_cfg1; /* 0x9c4 */ + uint32_t emem_bank_swizzle_cfg2; /* 0x9c8 */ + uint32_t emem_bank_swizzle_cfg3; /* 0x9cc */ + uint32_t rsvd_0x9d0[1]; /* 0x9d0 */ + uint32_t sec_carveout_adr_hi; /* 0x9d4 */ }; -#endif /* _TEGRA124_MC_H_ */ +enum { + MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_SHIFT = 27, + MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_MASK = 1 << 27, + + MC_EMEM_CFG_ACCESS_CTRL_WRITE_ACCESS_DISABLED = 1, + + MC_TIMING_CONTROL_TIMING_UPDATE = 1, +}; + +check_member(tegra_mc_regs, sec_carveout_adr_hi, 0x9d4); + +#endif /* __SOC_NVIDIA_TEGRA124_MC_H__ */ diff --git a/src/soc/nvidia/tegra124/pmc.h b/src/soc/nvidia/tegra124/pmc.h index f88e25308c..2dfdaadb60 100644 --- a/src/soc/nvidia/tegra124/pmc.h +++ b/src/soc/nvidia/tegra124/pmc.h @@ -62,10 +62,36 @@ struct tegra_pmc_regs { u32 no_iopower; u32 pwr_det; u32 pwr_det_latch; - u32 scratch[20]; + u32 scratch0; + u32 scratch1; + u32 scratch2; + u32 scratch3; + u32 scratch4; + u32 scratch5; + u32 scratch6; + u32 scratch7; + u32 scratch8; + u32 scratch9; + u32 scratch10; + u32 scratch11; + u32 scratch12; + u32 scratch13; + u32 scratch14; + u32 scratch15; + u32 scratch16; + u32 scratch17; + u32 scratch18; + u32 scratch19; u32 odmdata; - u32 scratch21[24 - 21]; - u32 secure_scratch[6]; + u32 scratch21; + u32 scratch22; + u32 scratch23; + u32 secure_scratch0; + u32 secure_scratch1; + u32 secure_scratch2; + u32 secure_scratch3; + u32 secure_scratch4; + u32 secure_scratch5; u32 cpupwrgood_timer; u32 cpupwroff_timer; u32 pg_mask; @@ -79,7 +105,25 @@ struct tegra_pmc_regs { u32 usb_a0; u32 crypto_op; u32 pllp_wb0_override; - u32 scratch24[43 - 24]; + u32 scratch24; + u32 scratch25; + u32 scratch26; + u32 scratch27; + u32 scratch28; + u32 scratch29; + u32 scratch30; + u32 scratch31; + u32 scratch32; + u32 scratch33; + u32 scratch34; + u32 scratch35; + u32 scratch36; + u32 scratch37; + u32 scratch38; + u32 scratch39; + u32 scratch40; + u32 scratch41; + u32 scratch42; u32 bondout_mirror[3]; u32 sys_33v_en; u32 bondout_mirror_access; @@ -124,9 +168,24 @@ struct tegra_pmc_regs { u32 utmip_uhsic_status; u32 utmip_uhsic_fake; u32 bondout_mirror3[5 - 3]; - u32 secure_scratch6[8 - 6]; - u32 scratch43[56 - 43]; - u32 scratch_eco[3]; + u32 secure_scratch6; + u32 secure_scratch7; + u32 scratch43; + u32 scratch44; + u32 scratch45; + u32 scratch46; + u32 scratch47; + u32 scratch48; + u32 scratch49; + u32 scratch50; + u32 scratch51; + u32 scratch52; + u32 scratch53; + u32 scratch54; + u32 scratch55; + u32 scratch0_eco; + u32 por_dpd_ctrl; + u32 scratch2_eco; u32 utmip_uhsic_line_wakeup; u32 utmip_bias_master_cntrl; u32 utmip_master_config; @@ -153,10 +212,108 @@ struct tegra_pmc_regs { u32 reg_short; u32 pg_mask_andor; u8 _rsv1[0x2c]; - u32 secure_scratch8[24 - 8]; - u32 scratch56[120 - 56]; + u32 secure_scratch8; + u32 secure_scratch9; + u32 secure_scratch10; + u32 secure_scratch11; + u32 secure_scratch12; + u32 secure_scratch13; + u32 secure_scratch14; + u32 secure_scratch15; + u32 secure_scratch16; + u32 secure_scratch17; + u32 secure_scratch18; + u32 secure_scratch19; + u32 secure_scratch20; + u32 secure_scratch21; + u32 secure_scratch22; + u32 secure_scratch23; + u32 secure_scratch24; + u32 secure_scratch25; + u32 secure_scratch26; + u32 secure_scratch27; + u32 secure_scratch28; + u32 secure_scratch29; + u32 secure_scratch30; + u32 secure_scratch31; + u32 secure_scratch32; + u32 secure_scratch33; + u32 secure_scratch34; + u32 secure_scratch35; + u8 _rsv2[0xd0]; + u32 cntrl2; + u8 _rsv3[0x18]; + u32 io_dpd3_req; + u32 io_dqd3_status; + u32 strapping_opt_a; + u8 _rsv4[0x198]; + u32 scratch56; + u32 scratch57; + u32 scratch58; + u32 scratch59; + u32 scratch60; + u32 scratch61; + u32 scratch62; + u32 scratch63; + u32 scratch64; + u32 scratch65; + u32 scratch66; + u32 scratch67; + u32 scratch68; + u32 scratch69; + u32 scratch70; + u32 scratch71; + u32 scratch72; + u32 scratch73; + u32 scratch74; + u32 scratch75; + u32 scratch76; + u32 scratch77; + u32 scratch78; + u32 scratch79; + u32 scratch80; + u32 scratch81; + u32 scratch82; + u32 scratch83; + u32 scratch84; + u32 scratch85; + u32 scratch86; + u32 scratch87; + u32 scratch88; + u32 scratch89; + u32 scratch90; + u32 scratch91; + u32 scratch92; + u32 scratch93; + u32 scratch94; + u32 scratch95; + u32 scratch96; + u32 scratch97; + u32 scratch98; + u32 scratch99; + u32 scratch100; + u32 scratch101; + u32 scratch102; + u32 scratch103; + u32 scratch104; + u32 scratch105; + u32 scratch106; + u32 scratch107; + u32 scratch108; + u32 scratch109; + u32 scratch110; + u32 scratch111; + u32 scratch112; + u32 scratch113; + u32 scratch114; + u32 scratch115; + u32 scratch116; + u32 scratch117; + u32 scratch118; + u32 scratch119; }; -check_member(tegra_pmc_regs, scratch56, 0x340); + +check_member(tegra_pmc_regs, scratch119, 0x6fc); enum { PMC_PWRGATE_TOGGLE_PARTID_MASK = 0x1f, @@ -191,6 +348,29 @@ enum { }; enum { + PMC_DDR_PWR_EMMC_MASK = 1 << 1, + PMC_DDR_PWR_VAL_MASK = 1 << 0, +}; + +enum { + PMC_DDR_CFG_PKG_MASK = 1 << 0, + PMC_DDR_CFG_IF_MASK = 1 << 1, + PMC_DDR_CFG_XM0_RESET_TRI_MASK = 1 << 12, + PMC_DDR_CFG_XM0_RESET_DPDIO_MASK = 1 << 13, +}; + +enum { + PMC_NO_IOPOWER_MEM_MASK = 1 << 7, + PMC_NO_IOPOWER_MEM_COMP_MASK = 1 << 16, +}; + +enum { + PMC_POR_DPD_CTRL_MEM0_ADDR0_CLK_SEL_DPD_MASK = 1 << 0, + PMC_POR_DPD_CTRL_MEM0_ADDR1_CLK_SEL_DPD_MASK = 1 << 1, + PMC_POR_DPD_CTRL_MEM0_HOLD_CKE_LOW_OVR_MASK = 1 << 31, +}; + +enum { PMC_CNTRL2_HOLD_CKE_LOW_EN = 0x1 << 12 }; @@ -200,4 +380,10 @@ enum { 0x3f << PMC_OSC_EDPD_OVER_XOFS_SHIFT }; +enum { + PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT = 4, + PMC_STRAPPING_OPT_A_RAM_CODE_MASK = + 0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT, +}; + #endif /* _TEGRA124_PMC_H_ */ diff --git a/src/soc/nvidia/tegra124/sdram.c b/src/soc/nvidia/tegra124/sdram.c new file mode 100644 index 0000000000..283cbf4998 --- /dev/null +++ b/src/soc/nvidia/tegra124/sdram.c @@ -0,0 +1,611 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <arch/io.h> +#include <console/console.h> +#include <delay.h> +#include <soc/addressmap.h> +#include <soc/clock.h> + +#include "emc.h" +#include "mc.h" +#include "pmc.h" +#include "sdram.h" + +static void sdram_patch(uintptr_t addr, uint32_t value) +{ + if (addr) + writel(value, (uint32_t*)addr); +} + +static void writebits(uint32_t value, uint32_t *addr, uint32_t mask) +{ + clrsetbits_le32(addr, mask, (value & mask)); +} + +/* PMC must be configured before clock-enable and de-reset of MC/EMC. */ +static void sdram_configure_pmc(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + /* VDDP Select */ + writel(param->PmcVddpSel, ®s->vddp_sel); + udelay(param->PmcVddpSelWait); + + /* Set DDR pad voltage */ + writebits(param->PmcDdrPwr, ®s->ddr_pwr, PMC_DDR_PWR_VAL_MASK); + + /* Set package and DPD pad control */ + writebits(param->PmcDdrCfg, ®s->ddr_cfg, + (PMC_DDR_CFG_PKG_MASK | PMC_DDR_CFG_IF_MASK | + PMC_DDR_CFG_XM0_RESET_TRI_MASK | + PMC_DDR_CFG_XM0_RESET_DPDIO_MASK)); + + /* Turn on MEM IO Power */ + writebits(param->PmcNoIoPower, ®s->no_iopower, + (PMC_NO_IOPOWER_MEM_MASK | PMC_NO_IOPOWER_MEM_COMP_MASK)); + + writel(param->PmcRegShort, ®s->reg_short); +} + +static void sdram_start_clocks(const struct sdram_params *param) +{ + u32 is_same_freq = (param->McEmemArbMisc0 & + MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_MASK) ? 1 : 0; + + clock_sdram(param->PllMInputDivider, param->PllMFeedbackDivider, + param->PllMSelectDiv2, param->PllMSetupControl, + param->PllMPDLshiftPh45, param->PllMPDLshiftPh90, + param->PllMPDLshiftPh135, param->PllMKVCO, + param->PllMKCP, param->PllMStableTime, + param->EmcClockSource, is_same_freq); +} + +static void sdram_deassert_clock_enable_signal(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + clrbits_le32(®s->por_dpd_ctrl, + PMC_POR_DPD_CTRL_MEM0_HOLD_CKE_LOW_OVR_MASK); + udelay(param->PmcPorDpdCtrlWait); +} + +static void sdram_deassert_sel_dpd(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + clrbits_le32(®s->por_dpd_ctrl, + (PMC_POR_DPD_CTRL_MEM0_ADDR0_CLK_SEL_DPD_MASK | + PMC_POR_DPD_CTRL_MEM0_ADDR1_CLK_SEL_DPD_MASK)); + /* + * Note NVIDIA recommended to always do 10us delay here and ignore + * BCT.PmcPorDpdCtrlWait. + * */ + udelay(10); +} + +static void sdram_set_swizzle(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + writel(param->EmcSwizzleRank0ByteCfg, ®s->swizzle_rank0_byte_cfg); + writel(param->EmcSwizzleRank0Byte0, ®s->swizzle_rank0_byte0); + writel(param->EmcSwizzleRank0Byte1, ®s->swizzle_rank0_byte1); + writel(param->EmcSwizzleRank0Byte2, ®s->swizzle_rank0_byte2); + writel(param->EmcSwizzleRank0Byte3, ®s->swizzle_rank0_byte3); + writel(param->EmcSwizzleRank1ByteCfg, ®s->swizzle_rank1_byte_cfg); + writel(param->EmcSwizzleRank1Byte0, ®s->swizzle_rank1_byte0); + writel(param->EmcSwizzleRank1Byte1, ®s->swizzle_rank1_byte1); + writel(param->EmcSwizzleRank1Byte2, ®s->swizzle_rank1_byte2); + writel(param->EmcSwizzleRank1Byte3, ®s->swizzle_rank1_byte3); +} + +static void sdram_set_pad_controls(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program the pad controls */ + writel(param->EmcXm2CmdPadCtrl, ®s->xm2cmdpadctrl); + writel(param->EmcXm2CmdPadCtrl2, ®s->xm2cmdpadctrl2); + writel(param->EmcXm2CmdPadCtrl3, ®s->xm2cmdpadctrl3); + writel(param->EmcXm2CmdPadCtrl4, ®s->xm2cmdpadctrl4); + writel(param->EmcXm2CmdPadCtrl5, ®s->xm2cmdpadctrl5); + + writel(param->EmcXm2DqsPadCtrl, ®s->xm2dqspadctrl); + writel(param->EmcXm2DqsPadCtrl2, ®s->xm2dqspadctrl2); + writel(param->EmcXm2DqsPadCtrl3, ®s->xm2dqspadctrl3); + writel(param->EmcXm2DqsPadCtrl4, ®s->xm2dqspadctrl4); + writel(param->EmcXm2DqsPadCtrl5, ®s->xm2dqspadctrl5); + writel(param->EmcXm2DqsPadCtrl6, ®s->xm2dqspadctrl6); + + writel(param->EmcXm2DqPadCtrl, ®s->xm2dqpadctrl); + writel(param->EmcXm2DqPadCtrl2, ®s->xm2dqpadctrl2); + writel(param->EmcXm2DqPadCtrl3, ®s->xm2dqpadctrl3); + + writel(param->EmcXm2ClkPadCtrl, ®s->xm2clkpadctrl); + writel(param->EmcXm2ClkPadCtrl2, ®s->xm2clkpadctrl2); + + writel(param->EmcXm2CompPadCtrl, ®s->xm2comppadctrl); + + writel(param->EmcXm2VttGenPadCtrl, ®s->xm2vttgenpadctrl); + writel(param->EmcXm2VttGenPadCtrl2, ®s->xm2vttgenpadctrl2); + writel(param->EmcXm2VttGenPadCtrl3, ®s->xm2vttgenpadctrl3); + + writel(param->EmcCttTermCtrl, ®s->ctt_term_ctrl); +} + +static void sdram_trigger_emc_timing_update(struct tegra_emc_regs *regs) +{ + writel(EMC_TIMING_CONTROL_TIMING_UPDATE, ®s->timing_control); +} + +static void sdram_init_mc(const struct sdram_params *param, + struct tegra_mc_regs *regs) +{ + /* Initialize MC VPR settings */ + writel(param->McDisplaySnapRing, ®s->display_snap_ring); + writel(param->McVideoProtectBom, ®s->video_protect_bom); + writel(param->McVideoProtectBomAdrHi, ®s->video_protect_bom_adr_hi); + writel(param->McVideoProtectSizeMb, ®s->video_protect_size_mb); + writel(param->McVideoProtectVprOverride, + ®s->video_protect_vpr_override); + writel(param->McVideoProtectVprOverride1, + ®s->video_protect_vpr_override1); + writel(param->McVideoProtectGpuOverride0, + ®s->video_protect_gpu_override_0); + writel(param->McVideoProtectGpuOverride1, + ®s->video_protect_gpu_override_1); + + /* Program SDRAM geometry paarameters */ + writel(param->McEmemAdrCfg, ®s->emem_adr_cfg); + writel(param->McEmemAdrCfgDev0, ®s->emem_adr_cfg_dev0); + writel(param->McEmemAdrCfgDev1, ®s->emem_adr_cfg_dev1); + + /* Program bank swizzling */ + writel(param->McEmemAdrCfgBankMask0, ®s->emem_bank_swizzle_cfg0); + writel(param->McEmemAdrCfgBankMask1, ®s->emem_bank_swizzle_cfg1); + writel(param->McEmemAdrCfgBankMask2, ®s->emem_bank_swizzle_cfg2); + writel(param->McEmemAdrCfgBankSwizzle3, ®s->emem_bank_swizzle_cfg3); + + /* Program external memory aperature (base and size) */ + writel(param->McEmemCfg, ®s->emem_cfg); + + /* Program SEC carveout (base and size) */ + writel(param->McSecCarveoutBom, ®s->sec_carveout_bom); + writel(param->McSecCarveoutAdrHi, ®s->sec_carveout_adr_hi); + writel(param->McSecCarveoutSizeMb, ®s->sec_carveout_size_mb); + + /* Program MTS carveout (base and size) */ + writel(param->McMtsCarveoutBom, ®s->mts_carveout_bom); + writel(param->McMtsCarveoutAdrHi, ®s->mts_carveout_adr_hi); + writel(param->McMtsCarveoutSizeMb, ®s->mts_carveout_size_mb); + + /* Program the memory arbiter */ + writel(param->McEmemArbCfg, ®s->emem_arb_cfg); + writel(param->McEmemArbOutstandingReq, ®s->emem_arb_outstanding_req); + writel(param->McEmemArbTimingRcd, ®s->emem_arb_timing_rcd); + writel(param->McEmemArbTimingRp, ®s->emem_arb_timing_rp); + writel(param->McEmemArbTimingRc, ®s->emem_arb_timing_rc); + writel(param->McEmemArbTimingRas, ®s->emem_arb_timing_ras); + writel(param->McEmemArbTimingFaw, ®s->emem_arb_timing_faw); + writel(param->McEmemArbTimingRrd, ®s->emem_arb_timing_rrd); + writel(param->McEmemArbTimingRap2Pre, ®s->emem_arb_timing_rap2pre); + writel(param->McEmemArbTimingWap2Pre, ®s->emem_arb_timing_wap2pre); + writel(param->McEmemArbTimingR2R, ®s->emem_arb_timing_r2r); + writel(param->McEmemArbTimingW2W, ®s->emem_arb_timing_w2w); + writel(param->McEmemArbTimingR2W, ®s->emem_arb_timing_r2w); + writel(param->McEmemArbTimingW2R, ®s->emem_arb_timing_w2r); + writel(param->McEmemArbDaTurns, ®s->emem_arb_da_turns); + writel(param->McEmemArbDaCovers, ®s->emem_arb_da_covers); + writel(param->McEmemArbMisc0, ®s->emem_arb_misc0); + writel(param->McEmemArbMisc1, ®s->emem_arb_misc1); + writel(param->McEmemArbRing1Throttle, ®s->emem_arb_ring1_throttle); + writel(param->McEmemArbOverride, ®s->emem_arb_override); + writel(param->McEmemArbOverride1, ®s->emem_arb_override_1); + writel(param->McEmemArbRsv, ®s->emem_arb_rsv); + + /* Program extra snap levels for display client */ + writel(param->McDisExtraSnapLevels, ®s->dis_extra_snap_levels); + + /* Trigger MC timing update */ + writel(MC_TIMING_CONTROL_TIMING_UPDATE, ®s->timing_control); + + /* Program second-level clock enable overrides */ + writel(param->McClkenOverride, ®s->clken_override); + + /* Program statistics gathering */ + writel(param->McStatControl, ®s->stat_control); +} + +static void sdram_init_emc(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program SDRAM geometry parameters */ + writel(param->EmcAdrCfg, ®s->adr_cfg); + + /* Program second-level clock enable overrides */ + writel(param->EmcClkenOverride, ®s->clken_override); + + /* Program EMC pad auto calibration */ + writel(param->EmcAutoCalInterval, ®s->auto_cal_interval); + writel(param->EmcAutoCalConfig2, ®s->auto_cal_config2); + writel(param->EmcAutoCalConfig3, ®s->auto_cal_config3); + writel(param->EmcAutoCalConfig, ®s->auto_cal_config); + udelay(param->EmcAutoCalWait); +} + +static void sdram_set_emc_timing(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program EMC timing configuration */ + writel(param->EmcCfg2, ®s->cfg_2); + writel(param->EmcCfgPipe, ®s->cfg_pipe); + writel(param->EmcDbg, ®s->dbg); + writel(param->EmcCmdQ, ®s->cmdq); + writel(param->EmcMc2EmcQ, ®s->mc2emcq); + writel(param->EmcMrsWaitCnt, ®s->mrs_wait_cnt); + writel(param->EmcMrsWaitCnt2, ®s->mrs_wait_cnt2); + writel(param->EmcFbioCfg5, ®s->fbio_cfg5); + writel(param->EmcRc, ®s->rc); + writel(param->EmcRfc, ®s->rfc); + writel(param->EmcRfcSlr, ®s->rfc_slr); + writel(param->EmcRas, ®s->ras); + writel(param->EmcRp, ®s->rp); + writel(param->EmcR2r, ®s->r2r); + writel(param->EmcW2w, ®s->w2w); + writel(param->EmcR2w, ®s->r2w); + writel(param->EmcW2r, ®s->w2r); + writel(param->EmcR2p, ®s->r2p); + writel(param->EmcW2p, ®s->w2p); + writel(param->EmcRdRcd, ®s->rd_rcd); + writel(param->EmcWrRcd, ®s->wr_rcd); + writel(param->EmcRrd, ®s->rrd); + writel(param->EmcRext, ®s->rext); + writel(param->EmcWext, ®s->wext); + writel(param->EmcWdv, ®s->wdv); + writel(param->EmcWdvMask, ®s->wdv_mask); + writel(param->EmcQUse, ®s->quse); + writel(param->EmcQuseWidth, ®s->quse_width); + writel(param->EmcIbdly, ®s->ibdly); + writel(param->EmcEInput, ®s->einput); + writel(param->EmcEInputDuration, ®s->einput_duration); + writel(param->EmcPutermExtra, ®s->puterm_extra); + writel(param->EmcPutermWidth, ®s->puterm_width); + writel(param->EmcPutermAdj, ®s->puterm_adj); + writel(param->EmcCdbCntl1, ®s->cdb_cntl_1); + writel(param->EmcCdbCntl2, ®s->cdb_cntl_2); + writel(param->EmcCdbCntl3, ®s->cdb_cntl_3); + writel(param->EmcQRst, ®s->qrst); + writel(param->EmcQSafe, ®s->qsafe); + writel(param->EmcRdv, ®s->rdv); + writel(param->EmcRdvMask, ®s->rdv_mask); + writel(param->EmcQpop, ®s->qpop); + writel(param->EmcCtt, ®s->ctt); + writel(param->EmcCttDuration, ®s->ctt_duration); + writel(param->EmcRefresh, ®s->refresh); + writel(param->EmcBurstRefreshNum, ®s->burst_refresh_num); + writel(param->EmcPreRefreshReqCnt, ®s->pre_refresh_req_cnt); + writel(param->EmcPdEx2Wr, ®s->pdex2wr); + writel(param->EmcPdEx2Rd, ®s->pdex2rd); + writel(param->EmcPChg2Pden, ®s->pchg2pden); + writel(param->EmcAct2Pden, ®s->act2pden); + writel(param->EmcAr2Pden, ®s->ar2pden); + writel(param->EmcRw2Pden, ®s->rw2pden); + writel(param->EmcTxsr, ®s->txsr); + writel(param->EmcTxsrDll, ®s->txsrdll); + writel(param->EmcTcke, ®s->tcke); + writel(param->EmcTckesr, ®s->tckesr); + writel(param->EmcTpd, ®s->tpd); + writel(param->EmcTfaw, ®s->tfaw); + writel(param->EmcTrpab, ®s->trpab); + writel(param->EmcTClkStable, ®s->tclkstable); + writel(param->EmcTClkStop, ®s->tclkstop); + writel(param->EmcTRefBw, ®s->trefbw); + writel(param->EmcOdtWrite, ®s->odt_write); + writel(param->EmcOdtRead, ®s->odt_read); + writel(param->EmcFbioCfg6, ®s->fbio_cfg6); + writel(param->EmcCfgDigDll, ®s->cfg_dig_dll); + writel(param->EmcCfgDigDllPeriod, ®s->cfg_dig_dll_period); + + /* Don't write bit 1: addr swizzle lock bit. Written at end of sequence. */ + writel(param->EmcFbioSpare & 0xfffffffd, ®s->fbio_spare); + + writel(param->EmcCfgRsv, ®s->cfg_rsv); + writel(param->EmcDllXformDqs0, ®s->dll_xform_dqs0); + writel(param->EmcDllXformDqs1, ®s->dll_xform_dqs1); + writel(param->EmcDllXformDqs2, ®s->dll_xform_dqs2); + writel(param->EmcDllXformDqs3, ®s->dll_xform_dqs3); + writel(param->EmcDllXformDqs4, ®s->dll_xform_dqs4); + writel(param->EmcDllXformDqs5, ®s->dll_xform_dqs5); + writel(param->EmcDllXformDqs6, ®s->dll_xform_dqs6); + writel(param->EmcDllXformDqs7, ®s->dll_xform_dqs7); + writel(param->EmcDllXformDqs8, ®s->dll_xform_dqs8); + writel(param->EmcDllXformDqs9, ®s->dll_xform_dqs9); + writel(param->EmcDllXformDqs10, ®s->dll_xform_dqs10); + writel(param->EmcDllXformDqs11, ®s->dll_xform_dqs11); + writel(param->EmcDllXformDqs12, ®s->dll_xform_dqs12); + writel(param->EmcDllXformDqs13, ®s->dll_xform_dqs13); + writel(param->EmcDllXformDqs14, ®s->dll_xform_dqs14); + writel(param->EmcDllXformDqs15, ®s->dll_xform_dqs15); + writel(param->EmcDllXformQUse0, ®s->dll_xform_quse0); + writel(param->EmcDllXformQUse1, ®s->dll_xform_quse1); + writel(param->EmcDllXformQUse2, ®s->dll_xform_quse2); + writel(param->EmcDllXformQUse3, ®s->dll_xform_quse3); + writel(param->EmcDllXformQUse4, ®s->dll_xform_quse4); + writel(param->EmcDllXformQUse5, ®s->dll_xform_quse5); + writel(param->EmcDllXformQUse6, ®s->dll_xform_quse6); + writel(param->EmcDllXformQUse7, ®s->dll_xform_quse7); + writel(param->EmcDllXformQUse8, ®s->dll_xform_quse8); + writel(param->EmcDllXformQUse9, ®s->dll_xform_quse9); + writel(param->EmcDllXformQUse10, ®s->dll_xform_quse10); + writel(param->EmcDllXformQUse11, ®s->dll_xform_quse11); + writel(param->EmcDllXformQUse12, ®s->dll_xform_quse12); + writel(param->EmcDllXformQUse13, ®s->dll_xform_quse13); + writel(param->EmcDllXformQUse14, ®s->dll_xform_quse14); + writel(param->EmcDllXformQUse15, ®s->dll_xform_quse15); + writel(param->EmcDllXformDq0, ®s->dll_xform_dq0); + writel(param->EmcDllXformDq1, ®s->dll_xform_dq1); + writel(param->EmcDllXformDq2, ®s->dll_xform_dq2); + writel(param->EmcDllXformDq3, ®s->dll_xform_dq3); + writel(param->EmcDllXformDq4, ®s->dll_xform_dq4); + writel(param->EmcDllXformDq5, ®s->dll_xform_dq5); + writel(param->EmcDllXformDq6, ®s->dll_xform_dq6); + writel(param->EmcDllXformDq7, ®s->dll_xform_dq7); + writel(param->EmcDllXformAddr0, ®s->dll_xform_addr0); + writel(param->EmcDllXformAddr1, ®s->dll_xform_addr1); + writel(param->EmcDllXformAddr2, ®s->dll_xform_addr2); + writel(param->EmcDllXformAddr3, ®s->dll_xform_addr3); + writel(param->EmcDllXformAddr4, ®s->dll_xform_addr4); + writel(param->EmcDllXformAddr5, ®s->dll_xform_addr5); + writel(param->EmcAcpdControl, ®s->acpd_control); + writel(param->EmcDsrVttgenDrv, ®s->dsr_vttgen_drv); + writel(param->EmcTxdsrvttgen, ®s->txdsrvttgen); + writel(param->EmcBgbiasCtl0, ®s->bgbias_ctl0); + + /* + * Set pipe bypass enable bits before sending any DRAM commands. + * Note other bits in EMC_CFG must be set AFTER REFCTRL is configured. + */ + writebits(param->EmcCfg, ®s->cfg, + (EMC_CFG_EMC2PMACRO_CFG_BYPASS_ADDRPIPE_MASK | + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE1_MASK | + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE2_MASK)); +} + +static void sdram_patch_bootrom(const struct sdram_params *param, + struct tegra_mc_regs *regs) +{ + if (param->BootRomPatchControl & BOOT_ROM_PATCH_CONTROL_ENABLE_MASK) { + uintptr_t addr = ((param->BootRomPatchControl & + BOOT_ROM_PATCH_CONTROL_OFFSET_MASK) >> + BOOT_ROM_PATCH_CONTROL_OFFSET_SHIFT); + addr = BOOT_ROM_PATCH_CONTROL_BASE_ADDRESS + (addr << 2); + writel(param->BootRomPatchData, (uint32_t *)addr); + writel(1, ®s->timing_control); + } +} + +static void sdram_set_dpd3(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + /* Program DPD request */ + writel(param->PmcIoDpd3Req, ®s->io_dpd3_req); + udelay(param->PmcIoDpd3ReqWait); +} + +static void sdram_set_dli_trims(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program DLI trims */ + writel(param->EmcDliTrimTxDqs0, ®s->dli_trim_txdqs0); + writel(param->EmcDliTrimTxDqs1, ®s->dli_trim_txdqs1); + writel(param->EmcDliTrimTxDqs2, ®s->dli_trim_txdqs2); + writel(param->EmcDliTrimTxDqs3, ®s->dli_trim_txdqs3); + writel(param->EmcDliTrimTxDqs4, ®s->dli_trim_txdqs4); + writel(param->EmcDliTrimTxDqs5, ®s->dli_trim_txdqs5); + writel(param->EmcDliTrimTxDqs6, ®s->dli_trim_txdqs6); + writel(param->EmcDliTrimTxDqs7, ®s->dli_trim_txdqs7); + writel(param->EmcDliTrimTxDqs8, ®s->dli_trim_txdqs8); + writel(param->EmcDliTrimTxDqs9, ®s->dli_trim_txdqs9); + writel(param->EmcDliTrimTxDqs10, ®s->dli_trim_txdqs10); + writel(param->EmcDliTrimTxDqs11, ®s->dli_trim_txdqs11); + writel(param->EmcDliTrimTxDqs12, ®s->dli_trim_txdqs12); + writel(param->EmcDliTrimTxDqs13, ®s->dli_trim_txdqs13); + writel(param->EmcDliTrimTxDqs14, ®s->dli_trim_txdqs14); + writel(param->EmcDliTrimTxDqs15, ®s->dli_trim_txdqs15); + + writel(param->EmcCaTrainingTimingCntl1, + ®s->ca_training_timing_cntl1); + writel(param->EmcCaTrainingTimingCntl2, + ®s->ca_training_timing_cntl2); + + sdram_trigger_emc_timing_update(regs); + udelay(param->EmcTimingControlWait); +} + +static void sdram_set_clock_enable_signal(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + volatile uint32_t dummy = 0; + clrbits_le32(®s->pin, (EMC_PIN_RESET_MASK | EMC_PIN_DQM_MASK | + EMC_PIN_CKE_MASK)); + /* + * Assert dummy read of PIN register to ensure above write to PIN + * register went through. 200 is the recommended value by NVIDIA. + */ + dummy |= readl(®s->pin); + udelay(200 + param->EmcPinExtraWait); + + /* Deassert reset */ + setbits_le32(®s->pin, EMC_PIN_RESET_INACTIVE); + /* + * Assert dummy read of PIN register to ensure above write to PIN + * register went through. 200 is the recommended value by NVIDIA. + */ + dummy |= readl(®s->pin); + udelay(500 + param->EmcPinExtraWait); + + /* Enable clock enable signal */ + setbits_le32(®s->pin, EMC_PIN_CKE_NORMAL); + /* + * Assert dummy read of PIN register to ensure above write to PIN + * register went through. 200 is the recommended value by NVIDIA. + */ + dummy |= readl(®s->pin); + udelay(param->EmcPinProgramWait); + + if (!dummy) { + die("Failed to program EMC pin."); + } + + /* Send NOP (trigger) */ + writebits(((1 << EMC_NOP_NOP_CMD_SHIFT) | + (param->EmcDevSelect << EMC_NOP_NOP_DEV_SELECTN_SHIFT)), + ®s->nop, + EMC_NOP_NOP_CMD_MASK | EMC_NOP_NOP_DEV_SELECTN_MASK); + + /* Write mode registers */ + writel(param->EmcEmrs2, ®s->emrs2); + writel(param->EmcEmrs3, ®s->emrs3); + writel(param->EmcEmrs, ®s->emrs); + writel(param->EmcMrs, ®s->mrs); + + if (param->EmcExtraModeRegWriteEnable) { + writel(param->EmcMrwExtra, ®s->mrs); + } +} + +static void sdram_init_zq_calibration(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + if ((param->EmcZcalWarmColdBootEnables & + EMC_ZCAL_WARM_COLD_BOOT_ENABLES_COLDBOOT_MASK) == 1) { + /* Need to initialize ZCAL on coldboot. */ + writel(param->EmcZcalInitDev0, ®s->zq_cal); + udelay(param->EmcZcalInitWait); + + if ((param->EmcDevSelect & 2) == 0) { + writel(param->EmcZcalInitDev1, ®s->zq_cal); + udelay(param->EmcZcalInitWait); + } + } else { + udelay(param->EmcZcalInitWait); + } +} + +static void sdram_set_zq_calibration(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Start periodic ZQ calibration */ + writel(param->EmcZcalInterval, ®s->zcal_interval); + writel(param->EmcZcalWaitCnt, ®s->zcal_wait_cnt); + writel(param->EmcZcalMrwCmd, ®s->zcal_mrw_cmd); +} + +static void sdram_set_refresh(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Insert burst refresh */ + if (param->EmcExtraRefreshNum > 0) { + uint32_t refresh_num = (1 << param->EmcExtraRefreshNum) - 1; + writebits((EMC_REF_CMD_REFRESH | EMC_REF_NORMAL_ENABLED | + (refresh_num << EMC_REF_NUM_SHIFT) | + (param->EmcDevSelect << EMC_REF_DEV_SELECTN_SHIFT)), + ®s->ref, (EMC_REF_CMD_MASK | EMC_REF_NORMAL_MASK | + EMC_REF_NUM_MASK | + EMC_REF_DEV_SELECTN_MASK)); + } + + /* Enable refresh */ + writel((param->EmcDevSelect | EMC_REFCTRL_REF_VALID_ENABLED), + ®s->refctrl); + + writel(param->EmcDynSelfRefControl, ®s->dyn_self_ref_control); + writel(param->EmcCfg, ®s->cfg); + writel(param->EmcSelDpdCtrl, ®s->sel_dpd_ctrl); + + /* Write addr swizzle lock bit */ + writel(param->EmcFbioSpare, ®s->fbio_spare); + + /* Re-trigger timing to latch power saving functions */ + sdram_trigger_emc_timing_update(regs); +} + +static void sdram_enable_arbiter(const struct sdram_params *param) +{ + /* TODO(hungte) Move values here to standalone header file. */ + uint32_t *AHB_ARBITRATION_XBAR_CTRL = (uint32_t*)(0x6000c000 + 0xe0); + setbits_le32(AHB_ARBITRATION_XBAR_CTRL, + param->AhbArbitrationXbarCtrlMemInitDone << 16); +} + +static void sdram_lock_carveouts(const struct sdram_params *param, + struct tegra_mc_regs *regs) +{ + /* Lock carveouts, and emem_cfg registers */ + writel(param->McVideoProtectWriteAccess, ®s->video_protect_reg_ctrl); + writel(MC_EMEM_CFG_ACCESS_CTRL_WRITE_ACCESS_DISABLED, + ®s->emem_cfg_access_ctrl); + writel(param->McSecCarveoutProtectWriteAccess, + ®s->sec_carveout_reg_ctrl); + writel(param->McMtsCarveoutRegCtrl, ®s->mts_carveout_reg_ctrl); +} + +void sdram_init(const struct sdram_params *param) +{ + struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs*)TEGRA_PMC_BASE; + struct tegra_mc_regs *mc = (struct tegra_mc_regs*)TEGRA_MC_BASE; + struct tegra_emc_regs *emc = (struct tegra_emc_regs*)TEGRA_EMC_BASE; + + sdram_configure_pmc(param, pmc); + sdram_patch(param->EmcBctSpare0, param->EmcBctSpare1); + + sdram_start_clocks(param); + sdram_patch(param->EmcBctSpare2, param->EmcBctSpare3); + + sdram_deassert_sel_dpd(param, pmc); + sdram_set_swizzle(param, emc); + sdram_set_pad_controls(param, emc); + sdram_patch(param->EmcBctSpare4, param->EmcBctSpare5); + + sdram_trigger_emc_timing_update(emc); + sdram_init_mc(param, mc); + sdram_init_emc(param, emc); + sdram_patch(param->EmcBctSpare6, param->EmcBctSpare7); + + sdram_set_emc_timing(param, emc); + sdram_patch_bootrom(param, mc); + sdram_set_dpd3(param, pmc); + sdram_set_dli_trims(param, emc); + sdram_deassert_clock_enable_signal(param, pmc); + sdram_set_clock_enable_signal(param, emc); + sdram_init_zq_calibration(param, emc); + sdram_patch(param->EmcBctSpare8, param->EmcBctSpare9); + + sdram_set_zq_calibration(param, emc); + sdram_patch(param->EmcBctSpare10, param->EmcBctSpare11); + + sdram_trigger_emc_timing_update(emc); + sdram_set_refresh(param, emc); + sdram_enable_arbiter(param); + sdram_lock_carveouts(param, mc); +} + +uint32_t sdram_get_ram_code(void) +{ + struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs*)TEGRA_PMC_BASE; + return ((readl(&pmc->strapping_opt_a) & + PMC_STRAPPING_OPT_A_RAM_CODE_MASK) >> + PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT); +} diff --git a/src/soc/nvidia/tegra124/sdram.h b/src/soc/nvidia/tegra124/sdram.h new file mode 100644 index 0000000000..cf5761c236 --- /dev/null +++ b/src/soc/nvidia/tegra124/sdram.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA124_SDRAM_H__ +#define __SOC_NVIDIA_TEGRA124_SDRAM_H__ + +#include "sdram_param.h" + +uint32_t sdram_get_ram_code(void); +void sdram_init(const struct sdram_params *param); + +#endif /* __SOC_NVIDIA_TEGRA124_SDRAM_H__ */ diff --git a/src/soc/nvidia/tegra124/sdram_param.h b/src/soc/nvidia/tegra124/sdram_param.h new file mode 100644 index 0000000000..1f05566d55 --- /dev/null +++ b/src/soc/nvidia/tegra124/sdram_param.h @@ -0,0 +1,816 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * See file CREDITS for list of people who contributed to this + * project. + */ + +/** + * Defines the SDRAM parameter structure. + * + * Note that PLLM is used by EMC. The field names are in camel case to ease + * directly converting BCT config files (*.cfg) into C structure. + */ + +#ifndef __SOC_NVIDIA_TEGRA124_SDRAM_PARAM_H__ +#define __SOC_NVIDIA_TEGRA124_SDRAM_PARAM_H__ + +#include <stddef.h> +#include <stdint.h> + +enum { + /* Specifies the memory type to be undefined */ + MEMORY_TYPE_NONE = 0, + + /* Specifies the memory type to be DDR SDRAM */ + MEMORY_TYPE_DDR = 0, + + /* Specifies the memory type to be LPDDR SDRAM */ + MEMORY_TYPE_LPDDR = 0, + + /* Specifies the memory type to be DDR2 SDRAM */ + MEMORY_TYPE_DDR2 = 0, + + /* Specifies the memory type to be LPDDR2 SDRAM */ + MEMORY_TYPE_LPDDR2, + + /* Specifies the memory type to be DDR3 SDRAM */ + MEMORY_TYPE_DDR3, + + MEMORY_TYPE_NUM, + MEMORY_TYPE_FORCE32 = 0X7FFFFFF +}; + +enum { + BOOT_ROM_PATCH_CONTROL_ENABLE_MASK = 0x1 << 31, + BOOT_ROM_PATCH_CONTROL_OFFSET_SHIFT = 0, + BOOT_ROM_PATCH_CONTROL_OFFSET_MASK = 0x7FFFFFFF << 0, + BOOT_ROM_PATCH_CONTROL_BASE_ADDRESS = 0x70000000, + + EMC_ZCAL_WARM_COLD_BOOT_ENABLES_COLDBOOT_MASK = 1 << 0, +}; + +/** + * Defines the SDRAM parameter structure + */ +struct sdram_params { + + /* Specifies the type of memory device */ + uint32_t memory_type; + + /* MC/EMC clock source configuration */ + + /* Specifies the M value for PllM */ + uint32_t PllMInputDivider; + /* Specifies the N value for PllM */ + uint32_t PllMFeedbackDivider; + /* Specifies the time to wait for PLLM to lock (in microseconds) */ + uint32_t PllMStableTime; + /* Specifies misc. control bits */ + uint32_t PllMSetupControl; + /* Enables the Div by 2 */ + uint32_t PllMSelectDiv2; + /* Powers down VCO output Level shifter */ + uint32_t PllMPDLshiftPh45; + /* Powers down VCO output Level shifter */ + uint32_t PllMPDLshiftPh90; + /* Powers down VCO output Level shifter */ + uint32_t PllMPDLshiftPh135; + /* Specifies value for Charge Pump Gain Control */ + uint32_t PllMKCP; + /* Specifies VCO gain */ + uint32_t PllMKVCO; + /* Spare BCT param */ + uint32_t EmcBctSpare0; + /* Spare BCT param */ + uint32_t EmcBctSpare1; + /* Spare BCT param */ + uint32_t EmcBctSpare2; + /* Spare BCT param */ + uint32_t EmcBctSpare3; + /* Spare BCT param */ + uint32_t EmcBctSpare4; + /* Spare BCT param */ + uint32_t EmcBctSpare5; + /* Spare BCT param */ + uint32_t EmcBctSpare6; + /* Spare BCT param */ + uint32_t EmcBctSpare7; + /* Spare BCT param */ + uint32_t EmcBctSpare8; + /* Spare BCT param */ + uint32_t EmcBctSpare9; + /* Spare BCT param */ + uint32_t EmcBctSpare10; + /* Spare BCT param */ + uint32_t EmcBctSpare11; + /* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */ + uint32_t EmcClockSource; + + /* Auto-calibration of EMC pads */ + + /* Specifies the value for EMC_AUTO_CAL_INTERVAL */ + uint32_t EmcAutoCalInterval; + /* + * Specifies the value for EMC_AUTO_CAL_CONFIG + * Note: Trigger bits are set by the SDRAM code. + */ + uint32_t EmcAutoCalConfig; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG2 */ + uint32_t EmcAutoCalConfig2; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ + uint32_t EmcAutoCalConfig3; + + /* + * Specifies the time for the calibration + * to stabilize (in microseconds) + */ + uint32_t EmcAutoCalWait; + + /* + * DRAM size information + * Specifies the value for EMC_ADR_CFG + */ + uint32_t EmcAdrCfg; + + /* + * Specifies the time to wait after asserting pin + * CKE (in microseconds) + */ + uint32_t EmcPinProgramWait; + /* Specifies the extra delay before/after pin RESET/CKE command */ + uint32_t EmcPinExtraWait; + /* + * Specifies the extra delay after the first writing + * of EMC_TIMING_CONTROL + */ + uint32_t EmcTimingControlWait; + + /* Timing parameters required for the SDRAM */ + + /* Specifies the value for EMC_RC */ + uint32_t EmcRc; + /* Specifies the value for EMC_RFC */ + uint32_t EmcRfc; + /* Specifies the value for EMC_RFC_SLR */ + uint32_t EmcRfcSlr; + /* Specifies the value for EMC_RAS */ + uint32_t EmcRas; + /* Specifies the value for EMC_RP */ + uint32_t EmcRp; + /* Specifies the value for EMC_R2R */ + uint32_t EmcR2r; + /* Specifies the value for EMC_W2W */ + uint32_t EmcW2w; + /* Specifies the value for EMC_R2W */ + uint32_t EmcR2w; + /* Specifies the value for EMC_W2R */ + uint32_t EmcW2r; + /* Specifies the value for EMC_R2P */ + uint32_t EmcR2p; + /* Specifies the value for EMC_W2P */ + uint32_t EmcW2p; + /* Specifies the value for EMC_RD_RCD */ + uint32_t EmcRdRcd; + /* Specifies the value for EMC_WR_RCD */ + uint32_t EmcWrRcd; + /* Specifies the value for EMC_RRD */ + uint32_t EmcRrd; + /* Specifies the value for EMC_REXT */ + uint32_t EmcRext; + /* Specifies the value for EMC_WEXT */ + uint32_t EmcWext; + /* Specifies the value for EMC_WDV */ + uint32_t EmcWdv; + /* Specifies the value for EMC_WDV_MASK */ + uint32_t EmcWdvMask; + /* Specifies the value for EMC_QUSE */ + uint32_t EmcQUse; + /* Specifies the value for EMC_QUSE_WIDTH */ + uint32_t EmcQuseWidth; + /* Specifies the value for EMC_IBDLY */ + uint32_t EmcIbdly; + /* Specifies the value for EMC_EINPUT */ + uint32_t EmcEInput; + /* Specifies the value for EMC_EINPUT_DURATION */ + uint32_t EmcEInputDuration; + /* Specifies the value for EMC_PUTERM_EXTRA */ + uint32_t EmcPutermExtra; + /* Specifies the value for EMC_PUTERM_WIDTH */ + uint32_t EmcPutermWidth; + /* Specifies the value for EMC_PUTERM_ADJ */ + uint32_t EmcPutermAdj; + /* Specifies the value for EMC_CDB_CNTL_1 */ + uint32_t EmcCdbCntl1; + /* Specifies the value for EMC_CDB_CNTL_2 */ + uint32_t EmcCdbCntl2; + /* Specifies the value for EMC_CDB_CNTL_3 */ + uint32_t EmcCdbCntl3; + /* Specifies the value for EMC_QRST */ + uint32_t EmcQRst; + /* Specifies the value for EMC_QSAFE */ + uint32_t EmcQSafe; + /* Specifies the value for EMC_RDV */ + uint32_t EmcRdv; + /* Specifies the value for EMC_RDV_MASK */ + uint32_t EmcRdvMask; + /* Specifies the value for EMC_QPOP */ + uint32_t EmcQpop; + /* Specifies the value for EMC_CTT */ + uint32_t EmcCtt; + /* Specifies the value for EMC_CTT_DURATION */ + uint32_t EmcCttDuration; + /* Specifies the value for EMC_REFRESH */ + uint32_t EmcRefresh; + /* Specifies the value for EMC_BURST_REFRESH_NUM */ + uint32_t EmcBurstRefreshNum; + /* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */ + uint32_t EmcPreRefreshReqCnt; + /* Specifies the value for EMC_PDEX2WR */ + uint32_t EmcPdEx2Wr; + /* Specifies the value for EMC_PDEX2RD */ + uint32_t EmcPdEx2Rd; + /* Specifies the value for EMC_PCHG2PDEN */ + uint32_t EmcPChg2Pden; + /* Specifies the value for EMC_ACT2PDEN */ + uint32_t EmcAct2Pden; + /* Specifies the value for EMC_AR2PDEN */ + uint32_t EmcAr2Pden; + /* Specifies the value for EMC_RW2PDEN */ + uint32_t EmcRw2Pden; + /* Specifies the value for EMC_TXSR */ + uint32_t EmcTxsr; + /* Specifies the value for EMC_TXSRDLL */ + uint32_t EmcTxsrDll; + /* Specifies the value for EMC_TCKE */ + uint32_t EmcTcke; + /* Specifies the value for EMC_TCKESR */ + uint32_t EmcTckesr; + /* Specifies the value for EMC_TPD */ + uint32_t EmcTpd; + /* Specifies the value for EMC_TFAW */ + uint32_t EmcTfaw; + /* Specifies the value for EMC_TRPAB */ + uint32_t EmcTrpab; + /* Specifies the value for EMC_TCLKSTABLE */ + uint32_t EmcTClkStable; + /* Specifies the value for EMC_TCLKSTOP */ + uint32_t EmcTClkStop; + /* Specifies the value for EMC_TREFBW */ + uint32_t EmcTRefBw; + + /* FBIO configuration values */ + + /* Specifies the value for EMC_FBIO_CFG5 */ + uint32_t EmcFbioCfg5; + /* Specifies the value for EMC_FBIO_CFG6 */ + uint32_t EmcFbioCfg6; + /* Specifies the value for EMC_FBIO_SPARE */ + uint32_t EmcFbioSpare; + + /* Specifies the value for EMC_CFG_RSV */ + uint32_t EmcCfgRsv; + + /* MRS command values */ + + /* Specifies the value for EMC_MRS */ + uint32_t EmcMrs; + /* Specifies the MP0 command to initialize mode registers */ + uint32_t EmcEmrs; + /* Specifies the MP2 command to initialize mode registers */ + uint32_t EmcEmrs2; + /* Specifies the MP3 command to initialize mode registers */ + uint32_t EmcEmrs3; + /* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */ + uint32_t EmcMrw1; + /* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */ + uint32_t EmcMrw2; + /* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */ + uint32_t EmcMrw3; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + uint32_t EmcMrw4; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at cold boot + */ + uint32_t EmcMrwExtra; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at warm boot + */ + uint32_t EmcWarmBootMrwExtra; + /* + * Specify the enable of extra Mode Register programming at + * warm boot + */ + uint32_t EmcWarmBootExtraModeRegWriteEnable; + /* + * Specify the enable of extra Mode Register programming at + * cold boot + */ + uint32_t EmcExtraModeRegWriteEnable; + + /* Specifies the EMC_MRW reset command value */ + uint32_t EmcMrwResetCommand; + /* Specifies the EMC Reset wait time (in microseconds) */ + uint32_t EmcMrwResetNInitWait; + /* Specifies the value for EMC_MRS_WAIT_CNT */ + uint32_t EmcMrsWaitCnt; + /* Specifies the value for EMC_MRS_WAIT_CNT2 */ + uint32_t EmcMrsWaitCnt2; + + /* EMC miscellaneous configurations */ + + /* Specifies the value for EMC_CFG */ + uint32_t EmcCfg; + /* Specifies the value for EMC_CFG_2 */ + uint32_t EmcCfg2; + /* Specifies the pipe bypass controls */ + uint32_t EmcCfgPipe; + /* Specifies the value for EMC_DBG */ + uint32_t EmcDbg; + /* Specifies the value for EMC_CMDQ */ + uint32_t EmcCmdQ; + /* Specifies the value for EMC_MC2EMCQ */ + uint32_t EmcMc2EmcQ; + /* Specifies the value for EMC_DYN_SELF_REF_CONTROL */ + uint32_t EmcDynSelfRefControl; + + /* Specifies the value for MEM_INIT_DONE */ + uint32_t AhbArbitrationXbarCtrlMemInitDone; + + /* Specifies the value for EMC_CFG_DIG_DLL */ + uint32_t EmcCfgDigDll; + /* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */ + uint32_t EmcCfgDigDllPeriod; + /* Specifies the value of *DEV_SELECTN of various EMC registers */ + uint32_t EmcDevSelect; + + /* Specifies the value for EMC_SEL_DPD_CTRL */ + uint32_t EmcSelDpdCtrl; + + /* Pads trimmer delays */ + + /* Specifies the value for EMC_DLL_XFORM_DQS0 */ + uint32_t EmcDllXformDqs0; + /* Specifies the value for EMC_DLL_XFORM_DQS1 */ + uint32_t EmcDllXformDqs1; + /* Specifies the value for EMC_DLL_XFORM_DQS2 */ + uint32_t EmcDllXformDqs2; + /* Specifies the value for EMC_DLL_XFORM_DQS3 */ + uint32_t EmcDllXformDqs3; + /* Specifies the value for EMC_DLL_XFORM_DQS4 */ + uint32_t EmcDllXformDqs4; + /* Specifies the value for EMC_DLL_XFORM_DQS5 */ + uint32_t EmcDllXformDqs5; + /* Specifies the value for EMC_DLL_XFORM_DQS6 */ + uint32_t EmcDllXformDqs6; + /* Specifies the value for EMC_DLL_XFORM_DQS7 */ + uint32_t EmcDllXformDqs7; + /* Specifies the value for EMC_DLL_XFORM_DQS8 */ + uint32_t EmcDllXformDqs8; + /* Specifies the value for EMC_DLL_XFORM_DQS9 */ + uint32_t EmcDllXformDqs9; + /* Specifies the value for EMC_DLL_XFORM_DQS10 */ + uint32_t EmcDllXformDqs10; + /* Specifies the value for EMC_DLL_XFORM_DQS11 */ + uint32_t EmcDllXformDqs11; + /* Specifies the value for EMC_DLL_XFORM_DQS12 */ + uint32_t EmcDllXformDqs12; + /* Specifies the value for EMC_DLL_XFORM_DQS13 */ + uint32_t EmcDllXformDqs13; + /* Specifies the value for EMC_DLL_XFORM_DQS14 */ + uint32_t EmcDllXformDqs14; + /* Specifies the value for EMC_DLL_XFORM_DQS15 */ + uint32_t EmcDllXformDqs15; + /* Specifies the value for EMC_DLL_XFORM_QUSE0 */ + uint32_t EmcDllXformQUse0; + /* Specifies the value for EMC_DLL_XFORM_QUSE1 */ + uint32_t EmcDllXformQUse1; + /* Specifies the value for EMC_DLL_XFORM_QUSE2 */ + uint32_t EmcDllXformQUse2; + /* Specifies the value for EMC_DLL_XFORM_QUSE3 */ + uint32_t EmcDllXformQUse3; + /* Specifies the value for EMC_DLL_XFORM_QUSE4 */ + uint32_t EmcDllXformQUse4; + /* Specifies the value for EMC_DLL_XFORM_QUSE5 */ + uint32_t EmcDllXformQUse5; + /* Specifies the value for EMC_DLL_XFORM_QUSE6 */ + uint32_t EmcDllXformQUse6; + /* Specifies the value for EMC_DLL_XFORM_QUSE7 */ + uint32_t EmcDllXformQUse7; + /* Specifies the value for EMC_DLL_XFORM_ADDR0 */ + uint32_t EmcDllXformAddr0; + /* Specifies the value for EMC_DLL_XFORM_ADDR1 */ + uint32_t EmcDllXformAddr1; + /* Specifies the value for EMC_DLL_XFORM_ADDR2 */ + uint32_t EmcDllXformAddr2; + /* Specifies the value for EMC_DLL_XFORM_ADDR3 */ + uint32_t EmcDllXformAddr3; + /* Specifies the value for EMC_DLL_XFORM_ADDR4 */ + uint32_t EmcDllXformAddr4; + /* Specifies the value for EMC_DLL_XFORM_ADDR5 */ + uint32_t EmcDllXformAddr5; + /* Specifies the value for EMC_DLL_XFORM_QUSE8 */ + uint32_t EmcDllXformQUse8; + /* Specifies the value for EMC_DLL_XFORM_QUSE9 */ + uint32_t EmcDllXformQUse9; + /* Specifies the value for EMC_DLL_XFORM_QUSE10 */ + uint32_t EmcDllXformQUse10; + /* Specifies the value for EMC_DLL_XFORM_QUSE11 */ + uint32_t EmcDllXformQUse11; + /* Specifies the value for EMC_DLL_XFORM_QUSE12 */ + uint32_t EmcDllXformQUse12; + /* Specifies the value for EMC_DLL_XFORM_QUSE13 */ + uint32_t EmcDllXformQUse13; + /* Specifies the value for EMC_DLL_XFORM_QUSE14 */ + uint32_t EmcDllXformQUse14; + /* Specifies the value for EMC_DLL_XFORM_QUSE15 */ + uint32_t EmcDllXformQUse15; + /* Specifies the value for EMC_DLI_TRIM_TXDQS0 */ + uint32_t EmcDliTrimTxDqs0; + /* Specifies the value for EMC_DLI_TRIM_TXDQS1 */ + uint32_t EmcDliTrimTxDqs1; + /* Specifies the value for EMC_DLI_TRIM_TXDQS2 */ + uint32_t EmcDliTrimTxDqs2; + /* Specifies the value for EMC_DLI_TRIM_TXDQS3 */ + uint32_t EmcDliTrimTxDqs3; + /* Specifies the value for EMC_DLI_TRIM_TXDQS4 */ + uint32_t EmcDliTrimTxDqs4; + /* Specifies the value for EMC_DLI_TRIM_TXDQS5 */ + uint32_t EmcDliTrimTxDqs5; + /* Specifies the value for EMC_DLI_TRIM_TXDQS6 */ + uint32_t EmcDliTrimTxDqs6; + /* Specifies the value for EMC_DLI_TRIM_TXDQS7 */ + uint32_t EmcDliTrimTxDqs7; + /* Specifies the value for EMC_DLI_TRIM_TXDQS8 */ + uint32_t EmcDliTrimTxDqs8; + /* Specifies the value for EMC_DLI_TRIM_TXDQS9 */ + uint32_t EmcDliTrimTxDqs9; + /* Specifies the value for EMC_DLI_TRIM_TXDQS10 */ + uint32_t EmcDliTrimTxDqs10; + /* Specifies the value for EMC_DLI_TRIM_TXDQS11 */ + uint32_t EmcDliTrimTxDqs11; + /* Specifies the value for EMC_DLI_TRIM_TXDQS12 */ + uint32_t EmcDliTrimTxDqs12; + /* Specifies the value for EMC_DLI_TRIM_TXDQS13 */ + uint32_t EmcDliTrimTxDqs13; + /* Specifies the value for EMC_DLI_TRIM_TXDQS14 */ + uint32_t EmcDliTrimTxDqs14; + /* Specifies the value for EMC_DLI_TRIM_TXDQS15 */ + uint32_t EmcDliTrimTxDqs15; + /* Specifies the value for EMC_DLL_XFORM_DQ0 */ + uint32_t EmcDllXformDq0; + /* Specifies the value for EMC_DLL_XFORM_DQ1 */ + uint32_t EmcDllXformDq1; + /* Specifies the value for EMC_DLL_XFORM_DQ2 */ + uint32_t EmcDllXformDq2; + /* Specifies the value for EMC_DLL_XFORM_DQ3 */ + uint32_t EmcDllXformDq3; + /* Specifies the value for EMC_DLL_XFORM_DQ4 */ + uint32_t EmcDllXformDq4; + /* Specifies the value for EMC_DLL_XFORM_DQ5 */ + uint32_t EmcDllXformDq5; + /* Specifies the value for EMC_DLL_XFORM_DQ6 */ + uint32_t EmcDllXformDq6; + /* Specifies the value for EMC_DLL_XFORM_DQ7 */ + uint32_t EmcDllXformDq7; + + /* + * Specifies the delay after asserting CKE pin during a WarmBoot0 + * sequence (in microseconds) + */ + uint32_t WarmBootWait; + + /* Specifies the value for EMC_CTT_TERM_CTRL */ + uint32_t EmcCttTermCtrl; + + /* Specifies the value for EMC_ODT_WRITE */ + uint32_t EmcOdtWrite; + /* Specifies the value for EMC_ODT_WRITE */ + uint32_t EmcOdtRead; + + /* Periodic ZQ calibration */ + + /* + * Specifies the value for EMC_ZCAL_INTERVAL + * Value 0 disables ZQ calibration + */ + uint32_t EmcZcalInterval; + /* Specifies the value for EMC_ZCAL_WAIT_CNT */ + uint32_t EmcZcalWaitCnt; + /* Specifies the value for EMC_ZCAL_MRW_CMD */ + uint32_t EmcZcalMrwCmd; + + /* DRAM initialization sequence flow control */ + + /* Specifies the MRS command value for resetting DLL */ + uint32_t EmcMrsResetDll; + /* Specifies the command for ZQ initialization of device 0 */ + uint32_t EmcZcalInitDev0; + /* Specifies the command for ZQ initialization of device 1 */ + uint32_t EmcZcalInitDev1; + /* + * Specifies the wait time after programming a ZQ initialization + * command (in microseconds) + */ + uint32_t EmcZcalInitWait; + /* + * Specifies the enable for ZQ calibration at cold boot [bit 0] + * and warm boot [bit 1] + */ + uint32_t EmcZcalWarmColdBootEnables; + + /* + * Specifies the MRW command to LPDDR2 for ZQ calibration + * on warmboot + */ + /* Is issued to both devices separately */ + uint32_t EmcMrwLpddr2ZcalWarmBoot; + /* + * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot + * Is issued to both devices separately + */ + uint32_t EmcZqCalDdr3WarmBoot; + /* + * Specifies the wait time for ZQ calibration on warmboot + * (in microseconds) + */ + uint32_t EmcZcalWarmBootWait; + /* + * Specifies the enable for DRAM Mode Register programming + * at warm boot + */ + uint32_t EmcMrsWarmBootEnable; + /* + * Specifies the wait time after sending an MRS DLL reset command + * in microseconds) + */ + uint32_t EmcMrsResetDllWait; + /* Specifies the extra MRS command to initialize mode registers */ + uint32_t EmcMrsExtra; + /* Specifies the extra MRS command at warm boot */ + uint32_t EmcWarmBootMrsExtra; + /* Specifies the EMRS command to enable the DDR2 DLL */ + uint32_t EmcEmrsDdr2DllEnable; + /* Specifies the MRS command to reset the DDR2 DLL */ + uint32_t EmcMrsDdr2DllReset; + /* Specifies the EMRS command to set OCD calibration */ + uint32_t EmcEmrsDdr2OcdCalib; + /* + * Specifies the wait between initializing DDR and setting OCD + * calibration (in microseconds) + */ + uint32_t EmcDdr2Wait; + /* Specifies the value for EMC_CLKEN_OVERRIDE */ + uint32_t EmcClkenOverride; + /* Specifies the value for MC_DIS_EXTRA_SNAP_LEVELS */ + uint32_t McDisExtraSnapLevels; + /* + * Specifies LOG2 of the extra refresh numbers after booting + * Program 0 to disable + */ + uint32_t EmcExtraRefreshNum; + /* Specifies the master override for all EMC clocks */ + uint32_t EmcClkenOverrideAllWarmBoot; + /* Specifies the master override for all MC clocks */ + uint32_t McClkenOverrideAllWarmBoot; + /* Specifies digital dll period, choosing between 4 to 64 ms */ + uint32_t EmcCfgDigDllPeriodWarmBoot; + + /* Pad controls */ + + /* Specifies the value for PMC_VDDP_SEL */ + uint32_t PmcVddpSel; + /* Specifies the wait time after programming PMC_VDDP_SEL */ + uint32_t PmcVddpSelWait; + /* Specifies the value for PMC_DDR_PWR */ + uint32_t PmcDdrPwr; + /* Specifies the value for PMC_DDR_CFG */ + uint32_t PmcDdrCfg; + /* Specifies the value for PMC_IO_DPD3_REQ */ + uint32_t PmcIoDpd3Req; + /* Specifies the wait time after programming PMC_IO_DPD3_REQ */ + uint32_t PmcIoDpd3ReqWait; + /* Specifies the value for PMC_REG_SHORT */ + uint32_t PmcRegShort; + /* Specifies the value for PMC_NO_IOPOWER */ + uint32_t PmcNoIoPower; + /* Specifies the wait time after programming PMC_POR_DPD_CTRL */ + uint32_t PmcPorDpdCtrlWait; + /* Specifies the value for EMC_XM2CMDPADCTRL */ + uint32_t EmcXm2CmdPadCtrl; + /* Specifies the value for EMC_XM2CMDPADCTRL2 */ + uint32_t EmcXm2CmdPadCtrl2; + /* Specifies the value for EMC_XM2CMDPADCTRL3 */ + uint32_t EmcXm2CmdPadCtrl3; + /* Specifies the value for EMC_XM2CMDPADCTRL4 */ + uint32_t EmcXm2CmdPadCtrl4; + /* Specifies the value for EMC_XM2CMDPADCTRL5 */ + uint32_t EmcXm2CmdPadCtrl5; + /* Specifies the value for EMC_XM2DQSPADCTRL */ + uint32_t EmcXm2DqsPadCtrl; + /* Specifies the value for EMC_XM2DQSPADCTRL2 */ + uint32_t EmcXm2DqsPadCtrl2; + /* Specifies the value for EMC_XM2DQSPADCTRL3 */ + uint32_t EmcXm2DqsPadCtrl3; + /* Specifies the value for EMC_XM2DQSPADCTRL4 */ + uint32_t EmcXm2DqsPadCtrl4; + /* Specifies the value for EMC_XM2DQSPADCTRL5 */ + uint32_t EmcXm2DqsPadCtrl5; + /* Specifies the value for EMC_XM2DQSPADCTRL6 */ + uint32_t EmcXm2DqsPadCtrl6; + /* Specifies the value for EMC_XM2DQPADCTRL */ + uint32_t EmcXm2DqPadCtrl; + /* Specifies the value for EMC_XM2DQPADCTRL2 */ + uint32_t EmcXm2DqPadCtrl2; + /* Specifies the value for EMC_XM2DQPADCTRL3 */ + uint32_t EmcXm2DqPadCtrl3; + /* Specifies the value for EMC_XM2CLKPADCTRL */ + uint32_t EmcXm2ClkPadCtrl; + /* Specifies the value for EMC_XM2CLKPADCTRL2 */ + uint32_t EmcXm2ClkPadCtrl2; + /* Specifies the value for EMC_XM2COMPPADCTRL */ + uint32_t EmcXm2CompPadCtrl; + /* Specifies the value for EMC_XM2VTTGENPADCTRL */ + uint32_t EmcXm2VttGenPadCtrl; + /* Specifies the value for EMC_XM2VTTGENPADCTRL2 */ + uint32_t EmcXm2VttGenPadCtrl2; + /* Specifies the value for EMC_XM2VTTGENPADCTRL3 */ + uint32_t EmcXm2VttGenPadCtrl3; + /* Specifies the value for EMC_ACPD_CONTROL */ + uint32_t EmcAcpdControl; + + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE_CFG */ + uint32_t EmcSwizzleRank0ByteCfg; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */ + uint32_t EmcSwizzleRank0Byte0; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */ + uint32_t EmcSwizzleRank0Byte1; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */ + uint32_t EmcSwizzleRank0Byte2; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */ + uint32_t EmcSwizzleRank0Byte3; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE_CFG */ + uint32_t EmcSwizzleRank1ByteCfg; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */ + uint32_t EmcSwizzleRank1Byte0; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */ + uint32_t EmcSwizzleRank1Byte1; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */ + uint32_t EmcSwizzleRank1Byte2; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */ + uint32_t EmcSwizzleRank1Byte3; + + /* Specifies the value for EMC_DSR_VTTGEN_DRV */ + uint32_t EmcDsrVttgenDrv; + + /* Specifies the value for EMC_TXDSRVTTGEN */ + uint32_t EmcTxdsrvttgen; + /* Specifies the value for EMC_BGBIAS_CTL */ + uint32_t EmcBgbiasCtl0; + + /* DRAM size information */ + + /* Specifies the value for MC_EMEM_ADR_CFG */ + uint32_t McEmemAdrCfg; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */ + uint32_t McEmemAdrCfgDev0; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */ + uint32_t McEmemAdrCfgDev1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */ + uint32_t McEmemAdrCfgBankMask0; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */ + uint32_t McEmemAdrCfgBankMask1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */ + uint32_t McEmemAdrCfgBankMask2; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG3 */ + uint32_t McEmemAdrCfgBankSwizzle3; + + /* + * Specifies the value for MC_EMEM_CFG which holds the external memory + * size (in KBytes) + */ + uint32_t McEmemCfg; + + /* MC arbitration configuration */ + + /* Specifies the value for MC_EMEM_ARB_CFG */ + uint32_t McEmemArbCfg; + /* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */ + uint32_t McEmemArbOutstandingReq; + /* Specifies the value for MC_EMEM_ARB_TIMING_RCD */ + uint32_t McEmemArbTimingRcd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RP */ + uint32_t McEmemArbTimingRp; + /* Specifies the value for MC_EMEM_ARB_TIMING_RC */ + uint32_t McEmemArbTimingRc; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAS */ + uint32_t McEmemArbTimingRas; + /* Specifies the value for MC_EMEM_ARB_TIMING_FAW */ + uint32_t McEmemArbTimingFaw; + /* Specifies the value for MC_EMEM_ARB_TIMING_RRD */ + uint32_t McEmemArbTimingRrd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */ + uint32_t McEmemArbTimingRap2Pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */ + uint32_t McEmemArbTimingWap2Pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2R */ + uint32_t McEmemArbTimingR2R; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2W */ + uint32_t McEmemArbTimingW2W; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2W */ + uint32_t McEmemArbTimingR2W; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2R */ + uint32_t McEmemArbTimingW2R; + /* Specifies the value for MC_EMEM_ARB_DA_TURNS */ + uint32_t McEmemArbDaTurns; + /* Specifies the value for MC_EMEM_ARB_DA_COVERS */ + uint32_t McEmemArbDaCovers; + /* Specifies the value for MC_EMEM_ARB_MISC0 */ + uint32_t McEmemArbMisc0; + /* Specifies the value for MC_EMEM_ARB_MISC1 */ + uint32_t McEmemArbMisc1; + /* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */ + uint32_t McEmemArbRing1Throttle; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE */ + uint32_t McEmemArbOverride; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */ + uint32_t McEmemArbOverride1; + /* Specifies the value for MC_EMEM_ARB_RSV */ + uint32_t McEmemArbRsv; + + /* Specifies the value for MC_CLKEN_OVERRIDE */ + uint32_t McClkenOverride; + + /* Specifies the value for MC_STAT_CONTROL */ + uint32_t McStatControl; + /* Specifies the value for MC_DISPLAY_SNAP_RING */ + uint32_t McDisplaySnapRing; + /* Specifies the value for MC_VIDEO_PROTECT_BOM */ + uint32_t McVideoProtectBom; + /* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */ + uint32_t McVideoProtectBomAdrHi; + /* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */ + uint32_t McVideoProtectSizeMb; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */ + uint32_t McVideoProtectVprOverride; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */ + uint32_t McVideoProtectVprOverride1; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */ + uint32_t McVideoProtectGpuOverride0; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */ + uint32_t McVideoProtectGpuOverride1; + /* Specifies the value for MC_SEC_CARVEOUT_BOM */ + uint32_t McSecCarveoutBom; + /* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */ + uint32_t McSecCarveoutAdrHi; + /* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */ + uint32_t McSecCarveoutSizeMb; + /* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.VIDEO_PROTECT_WRITE_ACCESS */ + uint32_t McVideoProtectWriteAccess; + /* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.SEC_CARVEOUT_WRITE_ACCESS */ + uint32_t McSecCarveoutProtectWriteAccess; + + /* Specifies enable for CA training */ + uint32_t EmcCaTrainingEnable; + /* Specifies the value for EMC_CA_TRAINING_TIMING_CNTRL1 */ + uint32_t EmcCaTrainingTimingCntl1; + /* Specifies the value for EMC_CA_TRAINING_TIMING_CNTRL2 */ + uint32_t EmcCaTrainingTimingCntl2; + /* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */ + uint32_t SwizzleRankByteEncode; + /* Specifies enable and offset for patched boot rom write */ + uint32_t BootRomPatchControl; + /* Specifies data for patched boot rom write */ + uint32_t BootRomPatchData; + /* Specifies the value for MC_MTS_CARVEOUT_BOM */ + uint32_t McMtsCarveoutBom; + /* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */ + uint32_t McMtsCarveoutAdrHi; + /* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */ + uint32_t McMtsCarveoutSizeMb; + /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */ + uint32_t McMtsCarveoutRegCtrl; + + /* End of generated code by warmboot_code_gen */ +}; + +check_member(sdram_params, McMtsCarveoutRegCtrl, 0x4d0); + +#endif /* __SOC_NVIDIA_TEGRA124_SDRAM_PARAM_H__ */ |