diff options
author | Icarus Chau <ichau@broadcom.com> | 2015-02-13 15:16:37 -0800 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2015-04-22 08:40:04 +0200 |
commit | d5f551a82a5d6f5c54798094c00ad606ca9d6807 (patch) | |
tree | 29ae658dd4c19a4bf98b4f1a0a1d3b51c968010f /src/soc/broadcom/cygnus/ddr_init.c | |
parent | 1abb6002ddc84dd6f2dc01e76475480445fa4271 (diff) | |
download | coreboot-d5f551a82a5d6f5c54798094c00ad606ca9d6807.tar.xz |
broadcom/cygnus: Initialize dram in romstage.
BUG=chrome-os-partner:36456
BRANCH=broadcom-firmware
TEST=When enable configuration CYGNUS_SDRAM_TEST_DDR,
print on console:
sdram initialization is completed.
test ddr start from 0x60000000 to 0x80000000
...
test ddr end: fail=0
Translation table is @ 02004000
Mapping address range [0x00000000:0x00000000) as uncached
Change-Id: I88dc2f0c504e2a152133edd442c3d776dd73d37e
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 376471751d6980f99bbe47faad193c79a05fa69f
Original-Signed-off-by: Icarus Chau <ichau@broadcom.com>
Original-Reviewed-on: https://chrome-internal-review.googlesource.com/199775
Original-Commit-Queue: <ichau@broadcom.com>
Original-Tested-by: <ichau@broadcom.com>
Original-Reviewed-by: Scott Branden <sbranden@broadcom.com>
Original-Change-Id: I47bc5d9ec147cc8bfbd893e8c0d7e5fc5e401771
Original-Reviewed-on: https://chromium-review.googlesource.com/256416
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Tested-by: Daisuke Nojiri <dnojiri@chromium.org>
Original-Commit-Queue: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-on: http://review.coreboot.org/9853
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/soc/broadcom/cygnus/ddr_init.c')
-rwxr-xr-x | src/soc/broadcom/cygnus/ddr_init.c | 1642 |
1 files changed, 1642 insertions, 0 deletions
diff --git a/src/soc/broadcom/cygnus/ddr_init.c b/src/soc/broadcom/cygnus/ddr_init.c new file mode 100755 index 0000000000..27a981ee66 --- /dev/null +++ b/src/soc/broadcom/cygnus/ddr_init.c @@ -0,0 +1,1642 @@ +/* +* Copyright (C) 2015 Broadcom Corporation +* +* 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. +* +* This program is distributed "as is" WITHOUT ANY WARRANTY of any +* kind, whether express or implied; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <delay.h> +#include <console/console.h> +#include <soc/config.h> +#include <soc/reg_utils.h> + +#define DDR_CTL_TYPE_1 1 +#define DDR_DRAM_TYPE_DDR3L 31 + +extern unsigned int ddr_init_tab[]; +#ifdef DDR2_SUPPORT +extern unsigned int ddr2_init_tab[]; +extern unsigned int ddr2_init_tab_400[]; +extern unsigned int ddr2_init_tab_667[]; +extern unsigned int ddr2_init_tab_800[]; +extern unsigned int ddr2_init_tab_1066[]; +extern unsigned int ddr2_mode_reg_tab[]; +#endif + +#ifdef CONFIG_DDR333 +#define CONFIG_DRAM_FREQ 333 +extern unsigned int ddr3_init_tab_667[]; +#endif +#ifdef CONFIG_DDR400 +#define CONFIG_DRAM_FREQ 400 +extern unsigned int ddr3_init_tab_800[]; +#endif +#ifdef CONFIG_DDR533 +#define CONFIG_DRAM_FREQ 533 +extern unsigned int ddr3_init_tab_1066[]; +#endif +#ifdef CONFIG_DDR667 +#define CONFIG_DRAM_FREQ 667 +extern unsigned int ddr3_init_tab_1333[]; +#endif +#ifdef CONFIG_CYGNUS_DDR800 +#define CONFIG_DRAM_FREQ 800 +extern unsigned int ddr3_init_tab_1600[]; +#endif + +#define __udelay udelay + +/* Local function prototype */ +uint32_t change_ddr_clock(uint32_t clk); +void dump_phy_regs(void); +void ddr_init_regs(unsigned int * tblptr); +void ddr_phy_ctl_regs_ovrd(unsigned int * tblptr); +void ddr_phy_wl_regs_ovrd(unsigned int * tblptr); +int is_ddr_32bit(void); +uint32_t iproc_get_ddr3_clock_mhz(uint32_t unit); +int cygnus_phy_powerup(void); +void ddr_init2(void); +void PRE_SRX(void); + +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) +void PRE_SRX(void) +{ + uint32_t readvalue = 0; + + // Disable low power receivers: bit 0 of the byte lane STATIC_PAD_CTL register + readvalue = reg32_read ((volatile uint32_t *)DDR_PHY_CONTROL_REGS_STATIC_PAD_CTL); + reg32_write ((volatile uint32_t *)DDR_PHY_CONTROL_REGS_STATIC_PAD_CTL, ( readvalue & ~(1 << DDR_PHY_CONTROL_REGS_STATIC_PAD_CTL__RX_MODE_R))); + + // Turn off ZQ_CAL drivers: bits 0,1, and 17 of the ZQ_CAL register (other bits 0 & 1 are set to 1) + readvalue = reg32_read ((volatile uint32_t *)DDR_PHY_CONTROL_REGS_ZQ_CAL); + reg32_write ((volatile uint32_t *)DDR_PHY_CONTROL_REGS_ZQ_CAL, ( readvalue & ~(1 << DDR_PHY_CONTROL_REGS_ZQ_CAL__ZQ_IDDQ))); + + // Byte lane 0 power up + readvalue = reg32_read ((volatile uint32_t *)DDR_PHY_BYTE_LANE_0_IDLE_PAD_CONTROL); + reg32_write ((volatile uint32_t *)DDR_PHY_BYTE_LANE_0_IDLE_PAD_CONTROL, ( readvalue & ~(1 << DDR_PHY_BYTE_LANE_0_IDLE_PAD_CONTROL__IDLE))); + + readvalue = reg32_read ((volatile uint32_t *)DDR_PHY_BYTE_LANE_0_IDLE_PAD_CONTROL); + reg32_write ((volatile uint32_t *)DDR_PHY_BYTE_LANE_0_IDLE_PAD_CONTROL, ( readvalue & 0xffff800f)); + + readvalue = reg32_read ((volatile uint32_t *)DDR_PHY_BYTE_LANE_0_IDLE_PAD_CONTROL); + reg32_write ((volatile uint32_t *)DDR_PHY_BYTE_LANE_0_IDLE_PAD_CONTROL, ( readvalue & ~(1 << DDR_PHY_BYTE_LANE_0_IDLE_PAD_CONTROL__IDDQ))); + + // Byte lane 1 power up + readvalue = reg32_read ((volatile uint32_t *)DDR_PHY_BYTE_LANE_1_IDLE_PAD_CONTROL); + reg32_write ((volatile uint32_t *)DDR_PHY_BYTE_LANE_1_IDLE_PAD_CONTROL, ( readvalue & ~(1 << DDR_PHY_BYTE_LANE_1_IDLE_PAD_CONTROL__IDLE))); + + readvalue = reg32_read ((volatile uint32_t *)DDR_PHY_BYTE_LANE_1_IDLE_PAD_CONTROL); + reg32_write ((volatile uint32_t *)DDR_PHY_BYTE_LANE_1_IDLE_PAD_CONTROL, ( readvalue & 0xffff800f)); + + readvalue = reg32_read ((volatile uint32_t *)DDR_PHY_BYTE_LANE_1_IDLE_PAD_CONTROL); + reg32_write ((volatile uint32_t *)DDR_PHY_BYTE_LANE_1_IDLE_PAD_CONTROL, ( readvalue & ~(1 << DDR_PHY_BYTE_LANE_1_IDLE_PAD_CONTROL__IDDQ))); + + // Turn on PHY_CONTROL AUTO_OEB ¨C not required + // Enable byte lane AUTO_DQ_RXENB_MODE: bits 18 and 19 of the byte lane IDLE_PAD_CONTROL ¨C already set 180114c8: 000f000a + + printk(BIOS_INFO, "\n....PLL power up.\n"); + reg32_write((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_CONFIG, (reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_CONFIG) & ~(1<<DDR_PHY_CONTROL_REGS_PLL_CONFIG__PWRDN))); + + // PLL out of reset + reg32_write((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_CONFIG, (reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_CONFIG) & ~(1<<DDR_PHY_CONTROL_REGS_PLL_CONFIG__RESET))); + printk(BIOS_INFO, "\n....poll lock..\n"); + // Poll lock + readvalue = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_STATUS); + while ( ( readvalue & 0x1) == 0x0 ) + { + printk(BIOS_INFO, "\n....DDR_PHY_CONTROL_REGS_PLL_STATUS = %8x..\n",readvalue); + readvalue = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_STATUS); + } + printk(BIOS_INFO, "\n....after while..\n"); + + reg32_write((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_CONFIG, (reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_CONFIG) & ~(1<<DDR_PHY_CONTROL_REGS_PLL_CONFIG__RESET_POST_DIV))); + + printk(BIOS_INFO, "\n....remove hold..\n"); + // Remove hold + reg32_write((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_CONFIG, (reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_CONFIG) & ~(1<<DDR_PHY_CONTROL_REGS_PLL_CONFIG__HOLD))); + printk(BIOS_INFO, "\n....restore dac..\n"); + + // Restore DAC + reg32_write((volatile uint32_t *)DDR_PHY_CONTROL_REGS_VREF_DAC_CONTROL, (reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_VREF_DAC_CONTROL) & 0xffff0fff)); + printk(BIOS_INFO, "\n....set iddq bit..\n"); + + // Set the iddq bit in the idle control register and select all outputs except cke and rst in the idee select registers. + // Do NOT assert any other bits in the idle control register. (This step can be done during init on power up.) + reg32_write((volatile uint32_t *)DDR_PHY_CONTROL_REGS_IDLE_PAD_CONTROL, (reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_IDLE_PAD_CONTROL) & ~(1 << DDR_PHY_CONTROL_REGS_IDLE_PAD_CONTROL__IDDQ))); + printk(BIOS_INFO, "\n....idle pad enable 0..\n"); + reg32_write((volatile uint32_t *)DDR_PHY_CONTROL_REGS_IDLE_PAD_ENABLE0, 0x0); + reg32_write((volatile uint32_t *)DDR_PHY_CONTROL_REGS_IDLE_PAD_ENABLE1, 0x0); + printk(BIOS_INFO, "\n....DDR_PHY_CONTROL_REGS_IDLE_PAD_CONTROL..\n"); + reg32_write((volatile uint32_t *)DDR_PHY_CONTROL_REGS_IDLE_PAD_CONTROL, (reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_IDLE_PAD_CONTROL) & ~(1 << DDR_PHY_CONTROL_REGS_IDLE_PAD_CONTROL__IDLE))); +} + +#endif + +#if defined(CONFIG_IPROC_DDR_ECC) && !defined(CONFIG_IPROC_P7) +void iproc_ddr_ovrd_ecc_lane(void) +{ + uint32_t val; + +#define SET_OVR_STEP(v) ( 0x30000 | ( (v) & 0x3F ) ) /* OVR_FORCE = OVR_EN = 1, OVR_STEP = v */ + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE_RD_EN); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_RD_EN, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_W); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_W, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_R_P); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_R_P, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_R_N); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_R_N, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT0_W); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT0_W, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT1_W); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT1_W, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT2_W); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT2_W, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT3_W); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT3_W, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_DM_W); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_DM_W, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT0_R_P); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT0_R_P, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT0_R_N); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT0_R_N, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT1_R_P); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT1_R_P, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT1_R_N); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT1_R_N, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT2_R_P); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT2_R_P, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT2_R_N); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT2_R_N, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT3_R_P); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT3_R_P, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT3_R_N); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT3_R_N, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE0_BIT_RD_EN); + val = SET_OVR_STEP(val & 0xff); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT_RD_EN, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_READ_DATA_DLY); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_READ_DATA_DLY, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_READ_CONTROL); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_READ_CONTROL, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_IDLE_PAD_CONTROL); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_IDLE_PAD_CONTROL, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_DRIVE_PAD_CTL); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_DRIVE_PAD_CTL, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + val = reg32_read((volatile uint32_t *)DDR_PHY_WORD_LANE_0_WR_PREAMBLE_MODE); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_WR_PREAMBLE_MODE, val); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + + __udelay(200); + reg32_write((volatile uint32_t *)DDR_PHY_ECC_LANE_READ_FIFO_CLEAR, 0x1); + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + __udelay(200); +} + +uint32_t iproc_read_ecc_syndrome(void) +{ + volatile uint32_t syndrome = 0; + /* Place uncorrectible as bits 7:0, and correctible as 15:8 */ + syndrome = ((reg32_read((volatile uint32_t *)DDR_DENALI_CTL_89) >> 3) & 0x1) | + (((reg32_read((volatile uint32_t *)DDR_DENALI_CTL_89) >> 5) & 0x1)); + return(syndrome); +} + +void iproc_clear_ecc_syndrome(void) +{ + uint32_t val; + + /* Clear the interrupts, bits 6:3 */ + reg32_write((volatile uint32_t *)DDR_DENALI_CTL_213, (1 << 5) | (1<< 3)); + __udelay(1000); +} +#endif + +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) +uint32_t iproc_get_ddr3_clock_mhz(uint32_t unit) +{ + uint32_t ndiv, mdiv, pdiv, ddrclk, data; + + data = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_PLL_DIVIDERS); + + ndiv = data >> DDR_PHY_CONTROL_REGS_PLL_DIVIDERS__NDIV_INT_R; + ndiv &= (2^DDR_PHY_CONTROL_REGS_PLL_DIVIDERS__NDIV_INT_WIDTH) - 1; + + pdiv = data >> DDR_PHY_CONTROL_REGS_PLL_DIVIDERS__PDIV_R; + pdiv &= (2^DDR_PHY_CONTROL_REGS_PLL_DIVIDERS__PDIV_WIDTH) - 1; + + mdiv = data >> DDR_PHY_CONTROL_REGS_PLL_DIVIDERS__MDIV_R; + mdiv &= (2^DDR_PHY_CONTROL_REGS_PLL_DIVIDERS__MDIV_WIDTH) - 1; + + /* read ndiv pdiv and mdiv */ + ddrclk = (25 * ndiv * 2 * pdiv) / mdiv; + printk(BIOS_INFO, "%s DDR PHY PLL divisor: ndiv(0x%x) mdiv(0x%x) ddrclk(0x%x)\n", __FUNCTION__, ndiv, mdiv, ddrclk); + + return(ddrclk); +} + +#endif + +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) + +int cygnus_phy_powerup(void) +{ + int data; + int count = 15; + + data = reg32_read((volatile uint32_t *)CRMU_DDR_PHY_AON_CTRL); + + if(reg32_read((volatile uint32_t *)CRMU_IHOST_POR_WAKEUP_FLAG)==0) + { + /* Step 1: POWRON */ + data = reg32_read((volatile uint32_t *)CRMU_DDR_PHY_AON_CTRL); + data |= 0x8;// assert power ON + reg32_write((volatile uint32_t *)CRMU_DDR_PHY_AON_CTRL, data); + + __udelay(2); + + /* Step 2: POWROK */ + data |= 0x10;// assert power OK + reg32_write((volatile uint32_t *)CRMU_DDR_PHY_AON_CTRL, data); + + while(count--) + __udelay(2); + + } + else + { + printk(BIOS_INFO, "DeepSleep wakeup: ddr phy init bypassed 1\n"); + } + + /* Step 3: DFI normal mode */ + data &= ~(0x04);// remove DFI isolation + reg32_write((volatile uint32_t *)CRMU_DDR_PHY_AON_CTRL, data); + + + /* Step 4: Enable register access */ + data &= ~(0x02);// remove PHY register isolation + reg32_write((volatile uint32_t *)CRMU_DDR_PHY_AON_CTRL, data); + + data &= ~(0x01);// remove PLL isolation + reg32_write((volatile uint32_t *)CRMU_DDR_PHY_AON_CTRL, data); + + count = 20; + while(count--) + __udelay(2); + + if(reg32_read((volatile uint32_t *)CRMU_IHOST_POR_WAKEUP_FLAG)==0) + { + /* Step 5: release reset */ + data |= 0x20;// de-assert reset + reg32_write((volatile uint32_t *)CRMU_DDR_PHY_AON_CTRL, data); + } + else + { + printk(BIOS_INFO, "DeepSleep wakeup: ddr phy init bypassed 2\n"); + } + while((reg32_read((volatile uint32_t *)DDR_S1_IDM_IO_STATUS) & 0x08) != 0x08) { + //poll DDR_S1_IDM_IO_STATUS__o_phy_pwrup_rsb + } + + return 0; +} + +#endif + +uint32_t change_ddr_clock(uint32_t clk) +{ + return(0); +} + +void dump_phy_regs(void) +{ + int i; + printk(BIOS_DEBUG, "\n PHY register dump: Control registers\n"); + for(i = 0; i <= 0x94; i+=4) + { + printk(BIOS_DEBUG, "0x%03x,\t0x%08x,\n", i, + *(volatile uint32_t *)(DDR_PHY_CONTROL_REGS_REVISION + i)); + } + + printk(BIOS_DEBUG, "\n PHY register dump: Wordlane0 registers\n"); + for(i = 0; i <= 0xc5; i+=4) + { + printk(BIOS_DEBUG, "0x%03x,\t0x%08x,\n", i, + *(volatile uint32_t *)(DDR_PHY_BYTE_LANE_0_VDL_CONTROL_WR_DQS_P + i)); + } + + return; +} + +void ddr_init_regs(unsigned int * tblptr) +{ + unsigned int offset = *tblptr; + unsigned int *addr = (unsigned int *)DDR_DENALI_CTL_00; + + while(offset != 0xffffffff) { + ++tblptr; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + addr[offset] = *tblptr; +#else + addr[offset] = swap_u32(*tblptr); +#endif + ++tblptr; + offset = *tblptr; + } +} + +void ddr_phy_ctl_regs_ovrd(unsigned int * tblptr) +{ + unsigned int offset = *tblptr; + unsigned int *addr = (unsigned int *)DDR_PHY_CONTROL_REGS_REVISION; + unsigned int val; + + while(offset != 0xffffffff) { + ++tblptr; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + addr[offset/4] = *tblptr; +#else + addr[offset/4] = swap_u32(*tblptr); +#endif + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + if (val) ; + ++tblptr; + offset = *tblptr; + } +} + +void ddr_phy_wl_regs_ovrd(unsigned int * tblptr) +{ +} + +/*DDR_SHMOO_RELATED_CHANGE*/ + +#ifdef CONFIG_RUN_DDR_SHMOO +int ReWriteModeRegisters( void ) +{ + int nRet = 0; + int j = 100; + + reg32_clear_bits( (volatile uint32_t *)DDR_DENALI_CTL_89 , 1 << 18 ); + + /* Set mode register for MR0, MR1, MR2 and MR3 write for all chip selects */ + reg32_write( (volatile uint32_t *)DDR_DENALI_CTL_43 , (1 << 17) | (1 << 24) | (1 << 25) ); + + /* Trigger Mode Register Write(MRW) sequence */ + reg32_set_bits( (volatile uint32_t *)DDR_DENALI_CTL_43 , 1 << 25 ); + + do { + if ( reg32_read( (volatile uint32_t *)DDR_DENALI_CTL_89) & (1 << 18) ) { + break; + } + --j; + } while( j ); + + if ( j == 0 && (reg32_read( (volatile uint32_t *)DDR_DENALI_CTL_89) & (1 << 18) ) == 0 ) { + printk(BIOS_ERR, "Error: DRAM mode registers write failed\n"); + nRet = 1; + }; + + return nRet; +} +#endif /* CONFIG_RUN_DDR_SHMOO */ + + +int is_ddr_32bit(void) +{ + int ddr32 = 0; + +#if (CONFIG_CYGNUS_SHMOO_REUSE_DDR_32BIT) + ddr32=1; +#endif /* (CONFIG_CYGNUS_SHMOO_REUSE_DDR_32BIT) */ + + return ddr32; +} + + +static uint32_t get_ddr_clock(uint32_t sku_id, int ddr_type) +{ +#ifdef CONFIG_DRAM_FREQ + return CONFIG_DRAM_FREQ; +#else + #error Please set DDR frequency (CONFIG_DRAM_FREQ must be set) +#endif +} + +#if defined(CONFIG_SHMOO_REUSE) || defined(CONFIG_SHMOO_AND28_REUSE) + +#define RAND_MAGIC_1 0x0000444BUL +#define RAND_MAGIC_2 0x88740000UL +#define RAND_MAGIC_3 69069UL +#define RAND_SEED 0x5301beef +#define RAND_SEED_2 ((RAND_SEED << 21) + (RAND_SEED << 14) + (RAND_SEED << 7)) +#define RAND_C_INIT (((RAND_SEED_2 + RAND_MAGIC_1) << 1) + 1) +#define RAND_T_INIT ((RAND_SEED_2 << (RAND_SEED_2 & 0xF)) + RAND_MAGIC_2) + +static int simple_memory_test(void *start, uint32_t len) +{ + register uint32_t rand_c_value, rand_t_value, rand_value; + register uint32_t i; + register volatile uint32_t *paddr; + + len /= 4; + paddr = (volatile uint32_t *)start; + rand_c_value = RAND_C_INIT; + rand_t_value = RAND_T_INIT; + for(i=0; i<len; i++, paddr++) { + rand_c_value *= RAND_MAGIC_3; + rand_t_value ^= rand_t_value >> 15; + rand_t_value ^= rand_t_value << 17; + rand_value = rand_t_value ^ rand_c_value; + *paddr = rand_value; + } + + paddr = (volatile uint32_t *)start; + rand_c_value = RAND_C_INIT; + rand_t_value = RAND_T_INIT; + for(i=0; i<len; i++, paddr++) { + rand_c_value *= RAND_MAGIC_3; + rand_t_value ^= rand_t_value >> 15; + rand_t_value ^= rand_t_value << 17; + rand_value = rand_t_value ^ rand_c_value; + if (*paddr != rand_value) { + return -1; + } + } + + return 0; +} + +#endif /* CONFIG_SHMOO_REUSE || CONFIG_SHMOO_AND28_REUSE */ + +#if defined(CONFIG_RUN_DDR_SHMOO2) && defined(CONFIG_SHMOO_REUSE) + +#define SHMOO_HEADER_MAGIC "SHMO" +#define SHMOO_MIN_BLOCK_SIZE 0x10000 + +static const uint16_t ddr_phy_ctl_regs[] = { + 0x030, + 0x034, + 0x06c +}; + +static const uint16_t ddr_phy_wl_regs[] = { + 0x000, + 0x004, + 0x008, + 0x00c, + 0x010, + 0x014, + 0x018, + 0x01c, + 0x020, + 0x024, + 0x028, + 0x02c, + 0x030, + 0x034, + 0x038, + 0x03c, + 0x040, + 0x044, + 0x048, + 0x04c, + 0x050, + 0x054, + 0x058, + 0x05c, + 0x060, + 0x064, + 0x068, + 0x06c, + 0x070, + 0x074, + 0x0a4, + 0x0a8, + 0x0ac, + 0x0b0, + 0x0b4, + 0x0b8, + 0x0bc, + 0x0c0, + 0x0c4, + 0x0c8, + 0x0cc, + 0x0d0, + 0x0d4, + 0x0d8, + 0x0dc, + 0x0e0, + 0x0e4, + 0x0e8, + 0x0ec, + 0x0f0, + 0x0f4, + 0x0f8, + 0x0fc, + 0x100, + 0x104, + 0x108, + 0x10c, + 0x110, + 0x114, + 0x118, + 0x11c, + 0x120, + 0x124, + 0x128, + 0x12c, + 0x130, + 0x134, + 0x138, + 0x13c, + 0x140, + 0x144, + 0x148, + 0x14c, + 0x150, + 0x154, + 0x158, + 0x15c, + 0x160, + 0x164, + 0x168, + 0x16c, + 0x1a0, + 0x1a4, + 0x1a8, + 0x1ac, + 0x1b0 +}; +#if defined(CONFIG_IPROC_DDR_ECC) && !defined(CONFIG_IPROC_P7) +static const uint16_t ddr_phy_eccl_regs[] = { + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_RD_EN_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_W_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_R_P_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_R_N_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT0_W_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT1_W_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT2_W_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT3_W_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_DM_W_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT0_R_P_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT0_R_N_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT1_R_P_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT1_R_N_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT2_R_P_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT2_R_N_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT3_R_P_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT3_R_N_BASE, + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT_RD_EN_BASE, + DDR_PHY_ECC_LANE_READ_DATA_DLY_BASE, + DDR_PHY_ECC_LANE_READ_CONTROL_BASE, + DDR_PHY_ECC_LANE_IDLE_PAD_CONTROL_BASE, + DDR_PHY_ECC_LANE_DRIVE_PAD_CTL_BASE, + DDR_PHY_ECC_LANE_WR_PREAMBLE_MODE_BASE, +}; +#endif +#if defined(CONFIG_IPROC_NAND) && defined(CONFIG_ENV_IS_IN_NAND) && CONFIG_ENV_IS_IN_NAND + +static int write_shmoo_to_flash(void *buf, int length) +{ + nand_info_t *nand; + int ret = 0; + uint32_t offset = CONFIG_SHMOO_REUSE_NAND_OFFSET; + uint32_t end = offset + CONFIG_SHMOO_REUSE_NAND_RANGE; + uint32_t blksize; + + /* Get flash handle */ + nand = &nand_info[0]; + if (nand->size < offset || nand->writesize == 0 || nand->erasesize == 0) { + printk(BIOS_ERR, "Failed to initialize NAND flash for saving Shmoo values!\n"); + return -1; + } + + /* For NAND with bad blocks, we always erase all blocks in the range */ + { + nand_erase_options_t opts; + memset(&opts, 0, sizeof(opts)); + opts.offset = offset / nand->erasesize * nand->erasesize; + opts.length = (CONFIG_SHMOO_REUSE_NAND_RANGE - 1) / nand->erasesize * nand->erasesize + 1; + opts.quiet = 1; + ret = nand_erase_opts(nand, &opts); + if (ret) { + printk(BIOS_ERR, "NAND flash erase failed, error=%d\n", ret); + return ret; + } + } + + /* Write data */ + blksize = nand->erasesize > SHMOO_MIN_BLOCK_SIZE? + nand->erasesize : SHMOO_MIN_BLOCK_SIZE; + while (offset < end) { + if (nand_block_isbad(nand, offset)) { + offset += blksize; + continue; + } + ret = nand_write(nand, offset, (size_t *)&length, (u_char *)buf); + if (ret) { + printk(BIOS_ERR, "NAND flash write failed, error=%d\n", ret); + } + break; + } + + return ret; +} + +#elif defined (CONFIG_SPI_FLASH) && defined(CONFIG_ENV_IS_IN_SPI_FLASH) && CONFIG_ENV_IS_IN_SPI_FLASH + +static int write_shmoo_to_flash(void *buf, int length) +{ + struct spi_flash *flash; + int erase = 0; + volatile uint32_t *flptr; + int i, j, ret = 0; + uint32_t offset = CONFIG_SHMOO_REUSE_QSPI_OFFSET; + + /* Check if erasing is required */ + flptr = (volatile uint32_t *)(IPROC_QSPI_MEM_BASE + offset / 4 * 4); + j = (length - 1) / 4 + 1; + for(i=0; i<j; i++, flptr++) { + if (*flptr != 0xFFFFFFFF) { + erase = 1; + break; + } + } + + /* Probe flash */ + flash = spi_flash_probe( + CONFIG_ENV_SPI_BUS, + CONFIG_ENV_SPI_CS, + CONFIG_ENV_SPI_MAX_HZ, + CONFIG_ENV_SPI_MODE + ); + if (!flash) { + printk(BIOS_ERR, "Failed to initialize SPI flash for saving Shmoo values!\n"); + return -1; + } + + /* Erase if necessary */ + if (erase) { + ret = spi_flash_erase( + flash, + offset / flash->sector_size * flash->sector_size, + flash->sector_size + ); + if (ret) { + printk(BIOS_ERR, "SPI flash erase failed, error=%d\n", ret); + spi_flash_free(flash); + return ret; + } + } + + /* Write data */ + ret = spi_flash_write(flash, offset, length, buf); + if (ret) { + printk(BIOS_ERR, "SPI flash write failed, error=%d\n", ret); + } + + /* Free flash instance */ + spi_flash_free(flash); + + return ret; +} + +#elif defined (CONFIG_ENV_IS_IN_FLASH) + +static int write_shmoo_to_flash(void *buf, int length) +{ + int erase = 0; + volatile uint32_t *flptr, shmoo_start; + int i, j, ret = 0; + uint32_t offset = CONFIG_SHMOO_REUSE_NOR_OFFSET; + int sect_len; + + /* Check if erasing is required */ + flptr = (volatile uint32_t *)(IPROC_NOR_MEM_BASE + offset / 4 * 4); + shmoo_start = flptr; + j = (length - 1) / 4 + 1; + for(i=0; i<j; i++, flptr++) { + if (*flptr != 0xFFFFFFFF) { + erase = 1; + break; + } + } + + sect_len = (((length / 0x20000) + 1)*0x20000 - 1); + /* Erase if necessary */ + if (erase) { + ret = flash_sect_erase((ulong)shmoo_start, (ulong)shmoo_start + sect_len); + if (ret) { + printk(BIOS_ERR, "NOR flash erase failed, error=%d, start addr: 0x%x, end addr: 0x%x\n", + ret, (ulong)shmoo_start, (ulong)shmoo_start + sect_len); + return ret; + } + } + + /* Write data */ + ret = flash_write((char *)buf, (ulong)shmoo_start, length); + + if (ret) { + printk(BIOS_ERR, "NOR flash write failed, error=%d\n", ret); + } + + + return ret; + +} +#else + #error Flash (SPI or NAND) must be enabled +#endif + +/* Return flash pointer; or NULL if validation failed */ +static volatile uint32_t *validate_flash_shmoo_values(struct shmoo_signature *psig, int *ppairs) +{ + uint32_t dev_id, sku_id, ddr_type, ddr_clk; + volatile uint32_t *ptr; + volatile uint32_t *flptr; + struct shmoo_signature sig; + uint32_t checksum, pairs, length; + uint32_t chksum; + int offset; + int i; + int numpairs = 1; + + if (is_ddr_32bit()) { + numpairs = 2; + } + + /* Calculate required length (register/value pair) */ + pairs = + sizeof(ddr_phy_ctl_regs) / sizeof(ddr_phy_ctl_regs[0]) + + sizeof(ddr_phy_wl_regs) / sizeof(ddr_phy_wl_regs[0]) * numpairs; +#ifdef CONFIG_IPROC_DDR_ECC + pairs += sizeof(ddr_phy_eccl_regs) / sizeof(ddr_phy_eccl_regs[0]); +#endif + + if (ppairs != NULL) { + *ppairs = pairs; + } + +#if defined(CONFIG_ENV_IS_IN_NAND) && CONFIG_ENV_IS_IN_NAND + /* Read SHMOO data from NAND */ + flptr = (volatile uint32_t *)(IPROC_NAND_MEM_BASE + CONFIG_SHMOO_REUSE_NAND_OFFSET); + offset = (CONFIG_SHMOO_REUSE_NAND_RANGE - 1) / SHMOO_MIN_BLOCK_SIZE * SHMOO_MIN_BLOCK_SIZE; +#elif defined (CONFIG_ENV_IS_IN_FLASH) + /* Read SHMOO data from NOR */ + flptr = (volatile uint32_t *)(IPROC_NOR_MEM_BASE + CONFIG_SHMOO_REUSE_NOR_OFFSET); + offset = 0; +#else + /* Read SHMOO data from SPI */ + flptr = (volatile uint32_t *)(IPROC_QSPI_MEM_BASE + CONFIG_SHMOO_REUSE_QSPI_OFFSET); + offset = 0; +#endif + + /* Get chip type and DDR type/clock */ + dev_id = (reg32_read((volatile uint32_t *)ChipcommonA_ChipID)) & 0x0000ffff; + sku_id = (reg32_read((volatile uint32_t *)ROM_S0_IDM_IO_STATUS) >> 2) & 0x03; + ddr_type = reg32_read((volatile uint32_t *)DDR_S1_IDM_IO_STATUS) & 0x1; + ddr_clk = get_ddr_clock(sku_id, ddr_type); + + /* Construct signature */ + memcpy(sig.magic, SHMOO_HEADER_MAGIC, 4); + sig.dev_id = dev_id; + sig.sku_id = sku_id; + sig.ddr_type = ddr_type; + sig.ddr_clock = ddr_clk; + + /* Provide signature data to caller */ + if (psig) { + memcpy(psig, &sig, sizeof(sig)); + } + + /* Check signature (in min-blocks from bottom) */ + while (offset >= 0) { + ptr = flptr + offset; + if (!shmoo_sigmemcmp(&sig,(void *)ptr)) { + break; + } + offset -= SHMOO_MIN_BLOCK_SIZE; + } + if (offset < 0) { + printk(BIOS_ERR, " Signature mismatch "); + return NULL; + } + ptr += 3; + + /* Verify checksum */ + checksum = *ptr++; + length = *ptr++; + if (pairs != length) { + /* Pair count unmatched */ + printk(BIOS_ERR, " Pair count mismatch pairs %x length %x",pairs, length); + return NULL; + } + chksum = 0; + for(i=0; i<length * 2; i++, ptr++) { + chksum += *ptr; + } + if (chksum != checksum) { + printk(BIOS_ERR, " Checksum mismatch cksum: %x checksum:%x",chksum,checksum); + return NULL; + } + + return flptr + offset; +} + +static int try_restore_shmoo(void) +{ + int invalid = 0; + struct shmoo_signature sig; + volatile uint32_t *flptr; + volatile uint32_t *reg; + uint32_t val; + int pairs, i; + + /* Validate values in flash */ + printk(BIOS_INFO, "Validate Shmoo parameters stored in flash ..... "); + flptr = validate_flash_shmoo_values(&sig, &pairs); + if (flptr == NULL) { + printk(BIOS_ERR, "failed\n"); + return 1; + } + printk(BIOS_INFO, "OK\n"); + + /* Check if user wants to skip restoring and run Shmoo */ + if (CONFIG_SHMOO_REUSE_DELAY_MSECS > 0) { + char c = 0; + unsigned long start; + printk(BIOS_INFO, "Press Ctrl-C to run Shmoo ..... "); + start = get_timer(0); + while(get_timer(start) <= CONFIG_SHMOO_REUSE_DELAY_MSECS) { + if (tstc()) { + c = getc(); + if (c == 0x03) { + printk(BIOS_INFO, "Pressed.\n"); + printk(BIOS_INFO, "Do you want to run the Shmoo? [y/N] "); + for(;;) { + c = getc(); + if (c == 'y' || c == 'Y') { + printk(BIOS_INFO, "Y\n"); + invalid = 1; + break; + } else if (c == '\r' || c == 'n' || c == 'N') { + if (c != '\r') + printk(BIOS_INFO, "N\n"); + break; + } + } + break; + } else { + c = 0; + } + } + } + if (c == 0) + printk(BIOS_INFO, "skipped\n"); + } + + if (invalid) { + return 1; + } + + /* Restore values from flash */ + printk(BIOS_INFO, "Restoring Shmoo parameters from flash ..... "); + flptr += 5; + for(i=0; i<pairs; i++) { + reg = (uint32_t *)(*flptr++); + val = (uint32_t *)(*flptr++); + if( (((uint32_t)reg >= DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE_RD_EN) && ((uint32_t)reg <= (DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE_RD_EN + 0x114))) +#if (CONFIG_CYGNUS_SHMOO_REUSE_DDR_32BIT || defined(CONFIG_NS_PLUS)) + || (((uint32_t)reg >= DDR_PHY_WORD_LANE_1_VDL_OVRIDE_BYTE_RD_EN) && ((uint32_t)reg <= (DDR_PHY_WORD_LANE_1_VDL_OVRIDE_BYTE_RD_EN + 0x114))) +#endif +#ifdef CONFIG_IPROC_DDR_ECC + || (((uint32_t)reg >= (DDR_DENALI_CTL_00 + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_RD_EN_BASE)) && ((uint32_t)reg <= (DDR_DENALI_CTL_00 + DDR_PHY_ECC_LANE_VDL_OVRIDE_BYTE_BIT_RD_EN_BASE))) +#endif + ) { + val |= (1 << 17); /* Force Override */ + } + // printk(BIOS_INFO, "Writing 0x%x to 0x%x\n",val,reg); + reg32_write(reg,val); + + reg32_read(reg); /* Dummy read back */ + } + printk(BIOS_INFO, "done\n"); + + /* Perform memory test to see if the parameters work */ + if (CONFIG_SHMOO_REUSE_MEMTEST_LENGTH > 0 ) { + printk(BIOS_INFO, "Running simple memory test ..... "); + i = simple_memory_test( + (void *)CONFIG_SHMOO_REUSE_MEMTEST_START, + CONFIG_SHMOO_REUSE_MEMTEST_LENGTH); + if (i) { + printk(BIOS_ERR, "failed!\n"); + return 1; + } + printk(BIOS_INFO, "OK\n"); + } + + return 0; +} + +#define SHMOO_REG_BUFFER_SIZE 100; +static uint32_t shmoo_reg_buffer[SHMOO_REG_BUFFER_SIZE]; + +void iproc_save_shmoo_values(void) +{ + uint32_t *buffer, *ptr; + volatile uint32_t *flptr; + uint32_t reg, val; + struct shmoo_signature sig; + int pairs, length; + uint32_t chksum; + int i; + + /* Check if flash already contains valid data */ + flptr = validate_flash_shmoo_values(&sig, &pairs); + if (flptr != NULL) { + /* Check if the flash data are the same as current DDR PHY values */ + flptr += 5; + for(i=0; i<pairs; i++) { + reg = *flptr++; + val = *flptr++; + if (val != reg32_read(reg)) { + break; + } + + } + if (i == pairs) { + /* No difference found; Saving skipped */ + return; + } + } + + /* Calculate size of buffer */ + length = 12 + + sizeof(uint32_t) * 2 + + sizeof(uint32_t) * pairs * 2; + + /* Allocate buffer */ + if (length > size(uint32_t) * SHMOO_REG_BUFFER_SIZE) { + printk(BIOS_INFO, "Error pre-allocated shmoo register buffer is not large enough!\n"); + return; + } + + buffer = shmoo_reg_buffer; + ptr = buffer; + + /* Fill signature */ + shmoo_sig2mem(&sig,ptr); + ptr += 5; + + /* Copy registers and values to buffer */ + chksum = 0; + for(i=0; i<sizeof(ddr_phy_ctl_regs) / sizeof(ddr_phy_ctl_regs[0]); i++) { + reg = (uint32_t)DDR_PHY_CONTROL_REGS_REVISION + ddr_phy_ctl_regs[i]; + *ptr++ = reg; + chksum += reg; + // val = *(volatile uint32_t *)reg; + val = reg32_read((volatile uint32_t *)reg); + *ptr++ = val; + chksum += val; + } + for(i=0; i<sizeof(ddr_phy_wl_regs) / sizeof(ddr_phy_wl_regs[0]); i++) { + reg = (uint32_t)DDR_PHY_WORD_LANE_0_VDL_OVRIDE_BYTE_RD_EN + ddr_phy_wl_regs[i]; + *ptr++ = reg; + chksum += reg; + // val = *(volatile uint32_t *)reg; + val = reg32_read((volatile uint32_t *)reg); + *ptr++ = val; + chksum += val; + } +#if (CONFIG_CYGNUS_SHMOO_REUSE_DDR_32BIT || defined(CONFIG_NS_PLUS)) + if (is_ddr_32bit()) { + for(i=0; i<sizeof(ddr_phy_wl_regs) / sizeof(ddr_phy_wl_regs[0]); i++) { + reg = (uint32_t)DDR_PHY_WORD_LANE_1_VDL_OVRIDE_BYTE_RD_EN + ddr_phy_wl_regs[i]; + *ptr++ = reg; + chksum += reg; + // val = *(volatile uint32_t *)reg; + val = reg32_read((volatile uint32_t *)reg); + *ptr++ = val; + chksum += val; + } + } +#endif /* (CONFIG_CYGNUS_SHMOO_REUSE_DDR_32BIT || defined(CONFIG_NS_PLUS)) */ +#ifdef CONFIG_IPROC_DDR_ECC + for(i=0; i<sizeof(ddr_phy_eccl_regs) / sizeof(ddr_phy_eccl_regs[0]); i++) { + reg = (uint32_t)DDR_DENALI_CTL_00 + ddr_phy_eccl_regs[i]; + *ptr++ = reg; + chksum += reg; + // val = *(volatile uint32_t *)reg; + val = reg32_read((volatile uint32_t *)reg); + *ptr++ = val; + chksum += val; + } +#endif + + /* Fill checksum and length */ + buffer[3] = chksum; + buffer[4] = pairs; + + /* Write to flash */ + printk(BIOS_INFO, "Writing Shmoo values into flash .....\n"); + i = write_shmoo_to_flash(buffer, length); + + /* Free buffer */ +// free(buffer); +} + +#endif /* CONFIG_RUN_DDR_SHMOO2 && CONFIG_SHMOO_REUSE */ + +#include "soc/ddr_bist.h" +#include "soc/shmoo_and28/shmoo_and28.h" + +#ifdef CONFIG_IPROC_DDR_ECC +static int clear_ddr(uint32_t offset, uint32_t size) +{ + unsigned long start; + unsigned int i, val; + + reg32_write((uint32_t *)DDR_BistConfig,reg32_read((uint32_t *)DDR_BistConfig) & ~0x1); + + for( i = 0; i < 1000; i++); + +#if !defined(CONFIG_IPROC_P7) + reg32_write((volatile uint32_t *)DDR_DENALI_CTL_213, 0x00FFFFFF); +#endif + + reg32_write((volatile uint32_t *)DDR_BistConfig, 0x00000002); + reg32_write((volatile uint32_t *)DDR_BistConfig, 0x00000003); + reg32_write((volatile uint32_t *)DDR_BistConfig, 0x0000C003); + reg32_write((volatile uint32_t *)DDR_BistGeneralConfigurations, 0x00000020); + + val = 255 << DDR_BistConfigurations__WriteWeight_R | + 0 << DDR_BistConfigurations__ReadWeight_R | + 1 << DDR_BistConfigurations__ConsAddr8Banks; + + reg32_write((volatile uint32_t *)DDR_BistConfigurations, val); + + + reg32_write((volatile uint32_t *)DDR_BistStartAddress, offset); + reg32_write((volatile uint32_t *)DDR_BistEndAddress, (1 << DDR_BistEndAddress__BistEndAddress_WIDTH) - 1); + reg32_write((volatile uint32_t *)DDR_BistNumberOfActions, (size + 31) / 32); + reg32_write((volatile uint32_t *)DDR_BistPatternWord0, 0); + reg32_write((volatile uint32_t *)DDR_BistPatternWord1, 0); + reg32_write((volatile uint32_t *)DDR_BistPatternWord2, 0); + reg32_write((volatile uint32_t *)DDR_BistPatternWord3, 0); + reg32_write((volatile uint32_t *)DDR_BistPatternWord4, 0); + reg32_write((volatile uint32_t *)DDR_BistPatternWord5, 0); + reg32_write((volatile uint32_t *)DDR_BistPatternWord6, 0); + reg32_write((volatile uint32_t *)DDR_BistPatternWord7, 0); + + reg32_set_bits((volatile uint32_t *)DDR_BistConfigurations, 1 << DDR_BistConfigurations__IndWrRdAddrMode); + + reg32_set_bits((volatile uint32_t *)DDR_BistConfigurations, 1 << DDR_BistConfigurations__BistEn); + + start = get_timer(0); + while(get_timer(start) <= 10000) { + if(reg32_read((volatile uint32_t *)DDR_BistStatuses) & (1 << DDR_BistStatuses__BistFinished)) + break; + } + /* Clear BIST_EN bit */ + reg32_clear_bits((volatile uint32_t *)DDR_BistConfigurations, 1 << DDR_BistConfigurations__BistEn); + + if((get_timer(start) <= 10000) && + (!reg32_read((volatile uint32_t *)DDR_BistErrorOccurred))) + { + printk(BIOS_INFO, "clear_ddr: OK\n"); + return(0); + } + printk(BIOS_INFO, "clear_ddr: Failed: 0x%lx\n", get_timer(start)); + if(reg32_read((volatile uint32_t *)DDR_BistErrorOccurred)) + printk(BIOS_ERR, "clear_ddr: Error occured\n"); + return(1); +} +#endif /* CONFIG_IPROC_DDR_ECC */ + +#if defined(CONFIG_SHMOO_AND28_REUSE) +extern void restore_shmoo_config(and28_shmoo_config_param_t *shmoo_control_para); +#endif + +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) +static int simple_ddr_crc32_check(void) +{ + return 0; + register uint32_t crc_mcu = 0; + register uint32_t crc = 0, offset = 0; + register volatile uint32_t *buf = (uint32_t *)0x60000000; + register uint32_t len = 0x00100000;//in word + + printk(BIOS_INFO, "Checking simple DDR CRC, word start 0x%p, len 0x%08x...\n", buf, len); + + for(offset=0; offset<len; offset++) + { + crc ^= *buf++; + } + + crc_mcu = reg32_read((volatile uint32_t *)0x03012A00); + + if(crc != crc_mcu) + { + printk(BIOS_ERR, "DDR CRC NOT match, old=0x%08x, new=0x%08x!\n", crc_mcu, crc); + return -1; + } + else + { + printk(BIOS_INFO, "DDR CRC 0x%08x, match!\n", crc); + return 0; + } +} +#endif + +void ddr_init2(void) +{ + int i; + volatile unsigned int val; + int ddr_type; + uint32_t status, sku_id, ddr_clk, dev_id = 0; + uint32_t unit = 0; + uint32_t skip_shmoo = 0; +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) + uint32_t pwrctli0 = reg32_read((volatile uint32_t *)IHOST_SCU_POWER_STATUS) & 0x3; + skip_shmoo = reg32_read((volatile uint32_t *)CRMU_IHOST_POR_WAKEUP_FLAG) & 0x1; + + if(pwrctli0==2) + { + goto wakeup; + } + else if(pwrctli0==3) + { + skip_shmoo = 1; + reg32_write((volatile uint32_t *)IHOST_GTIM_GLOB_CTRL, reg32_read((volatile uint32_t *)IHOST_GTIM_GLOB_CTRL)| 0x1); + } +#endif /* defined(CONFIG_SOC_BROADCOM_CYGNUS) */ + + dev_id = dev_id; +#ifdef CONFIG_SOC_BROADCOM_CYGNUS + and28_shmoo_dram_info_t sdi; + and28_shmoo_config_param_t config_param; +#endif + +#ifndef CONFIG_SOC_BROADCOM_CYGNUS + dev_id = (reg32_read((volatile uint32_t *)ChipcommonA_ChipID)) & 0x0000ffff; +#else + dev_id = 0x5800; + cygnus_phy_powerup(); +#endif + +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) + sku_id = (reg32_read((volatile uint32_t *)ROM_S0_IDM_IO_STATUS) >> 8) & 0x0f; +#else + sku_id = (reg32_read((volatile uint32_t *)ROM_S0_IDM_IO_STATUS) >> 2) & 0x03; +#endif + /* See if it is KATANA2, KATANA2 doesn't have right chip ID in ChipcommonA_ChipID */ + if(((sku_id & 0xfff0) == 0xa450) || ((sku_id & 0xfff0) == 0xb450) || sku_id == 0xb248) { + dev_id = 56450; /* KATANA2 */ + } + + printk(BIOS_INFO, "DEV ID = 0x%x\n", dev_id); + + printk(BIOS_INFO, "SKU ID = 0x%x\n", sku_id); + +#if defined(CONFIG_IPROC_P7) + val = reg32_read((volatile uint32_t *)DDR_S1_IDM_IO_STATUS) & 0x3; + if (val == 0) { + ddr_type = 1; + } else if (val == 1) { + ddr_type = 2; + } else { + printk(BIOS_ERR, "Unsupported DDR type: %d\n", val); + goto done; + } + printk(BIOS_INFO, "DDR type: DDR%d\n", (ddr_type == 1)? 3 : 4); +#elif defined(CONFIG_SOC_BROADCOM_CYGNUS) + ddr_type = 1; +#else + ddr_type = reg32_read((volatile uint32_t *)DDR_S1_IDM_IO_STATUS) & 0x1; + printk(BIOS_INFO, "DDR type: DDR%d\n", (ddr_type) ? 3 : 2); +#endif /* defined(CONFIG_IPROC_P7) */ + + ddr_clk = get_ddr_clock(sku_id, ddr_type); + printk(BIOS_INFO, "MEMC 0 DDR speed = %dMHz\n", ddr_clk); + + status = change_ddr_clock(ddr_clk); + if(status) { + printk(BIOS_INFO, "CRU LCPLL configuratioin failed\n"); + goto done; + } + +#if defined(CONFIG_IPROC_P7) + val = reg32_read((volatile uint32_t *)CRU_ddrphy_pwr_ctrl); + + /* assert power ON */ + val |= 1 << CRU_ddrphy_pwr_ctrl__i_pwronin_phy; + reg32_write((volatile uint32_t *)CRU_ddrphy_pwr_ctrl, val); + + /* assert power OK */ + __udelay(10); + val |= 1 << CRU_ddrphy_pwr_ctrl__i_pwrokin_phy; + reg32_write((volatile uint32_t *)CRU_ddrphy_pwr_ctrl, val); + + /* remove DFI isolation */ + __udelay(150); + val &= ~(1 << CRU_ddrphy_pwr_ctrl__i_iso_phy_dfi); + reg32_write((volatile uint32_t *)CRU_ddrphy_pwr_ctrl, val); + + /* remove PHY register isolation */ + val &= ~(1 << CRU_ddrphy_pwr_ctrl__i_iso_phy_regs); + reg32_write((volatile uint32_t *)CRU_ddrphy_pwr_ctrl, val); + + /* remove PLL isolation */ + val &= ~(1 << CRU_ddrphy_pwr_ctrl__i_iso_phy_pll); + reg32_write((volatile uint32_t *)CRU_ddrphy_pwr_ctrl, val); + + /* de-assert reset */ + __udelay(200); + val |= 1 << CRU_ddrphy_pwr_ctrl__i_hw_reset_n; + reg32_write((volatile uint32_t *)CRU_ddrphy_pwr_ctrl, val); + + /* Wait for PHY power up */ + for(i=0; i < 0x19000; i++) { + val = reg32_read((volatile uint32_t *)DDR_S1_IDM_IO_STATUS); + if((val & (1 << DDR_S1_IDM_IO_STATUS__o_phy_pwrup_rsb))) + break; + } + if(i == 0x19000) { + printk(BIOS_ERR, "DDR PHY not power up\n"); + goto done; + } +#endif /* defined(CONFIG_IPROC_P7) */ + +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) || defined(CONFIG_IPROC_P7) + /* Get the DDR S1 and S2 out of reset */ + reg32_write((volatile uint32_t *)DDR_S1_IDM_RESET_CONTROL, 0); + reg32_write((volatile uint32_t *)DDR_S2_IDM_RESET_CONTROL, 0); + + __udelay(1000); + reg32_write((volatile uint32_t *)DDR_S0_IDM_RESET_CONTROL, 0); + /* Set the ddr_ck to 400 MHz, 2x memc clock */ + reg32_write_masked((volatile uint32_t *)DDR_S1_IDM_IO_CONTROL_DIRECT, 0xfff << 16, /*ddr_clk*/ 0x190 << 16); + + if(pwrctli0==3) + { + printk(BIOS_INFO, "\n PRE_SRX call \n"); + PRE_SRX(); + } +#else + reg32_write((volatile uint32_t *)DDR_S1_IDM_RESET_CONTROL, 0); + reg32_write((volatile uint32_t *)DDR_S2_IDM_RESET_CONTROL, 0); + /* Set the ddr_ck to 400 MHz, 2x memc clock */ + reg32_write_masked((volatile uint32_t *)DDR_S1_IDM_IO_CONTROL_DIRECT, 0xfff << 16, /*ddr_clk*/ 0x190 << 16); +#endif /* defined(CONFIG_SOC_BROADCOM_CYGNUS) || defined(CONFIG_IPROC_P7) */ + +#if defined(CONFIG_IPROC_P7) + if (is_ddr_32bit()) { + reg32_write_masked( + (volatile uint32_t *)DDR_S2_IDM_IO_CONTROL_DIRECT, + 1 << DDR_S2_IDM_IO_CONTROL_DIRECT__mode_32b, + 1 << DDR_S2_IDM_IO_CONTROL_DIRECT__mode_32b + ); + } + + /* Wait for PHY ready */ + for(i=0; i < 0x19000; i++) { + val = reg32_read((volatile uint32_t *)DDR_S1_IDM_IO_STATUS); + if((val & (1 << DDR_S1_IDM_IO_STATUS__o_phy_ready))) + break; /* DDR PHY is up */ + } + + if(i == 0x19000) { + printk(BIOS_ERR, "DDR PLL not locked\n"); + goto done; + } + + /* Get the DDR S0 out of reset */ + reg32_write((volatile uint32_t *)DDR_S0_IDM_RESET_CONTROL, 0); +#endif /* defined(CONFIG_IPROC_P7) */ + + /* Wait for DDR PHY up */ + for(i=0; i < 0x19000; i++) { + val = reg32_read((volatile uint32_t *)DDR_PHY_CONTROL_REGS_REVISION); + if( val != 0) { + printk(BIOS_INFO, "PHY revision version: 0x%08x\n", val); + break; /* DDR PHY is up */ + } + } + + if(i == 0x19000) { + printk(BIOS_ERR, "DDR PHY is not up\n"); + return; + } + +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) + if(!skip_shmoo) + { + printk(BIOS_INFO, "ddr_init2: Calling soc_and28_shmoo_dram_info_set\n"); + /* Cygnus clock speed: + * + * clock rate + * 400 800 + * 533 1066 + * 667 1333 + * 800 1600 + */ + sdi.data_rate_mbps = (ddr_clk == 667) ? 1333 : ((ddr_clk == 333) ? 667 : (ddr_clk << 1)); + sdi.ref_clk_mhz = 50; + sdi.ctl_type = DDR_CTL_TYPE_1; + sdi.dram_type = DDR_DRAM_TYPE_DDR3L; + sdi.dram_bitmap = 0x00000001; + sdi.interface_bitwidth = SDI_INTERFACE_BITWIDTH; + sdi.num_columns = SDI_NUM_COLUMNS; + sdi.num_rows = SDI_NUM_ROWS; + sdi.num_banks = SDI_NUM_BANKS; + sdi.refi = 7800; + sdi.command_parity_latency = 0; + sdi.sim_system_mode = 0; + printk(BIOS_INFO, "ddr_init2: Calling soc_and28_shmoo_dram_info_set\n"); + soc_and28_shmoo_dram_info_set(unit, &sdi); + } + else + { + printk(BIOS_INFO, "DeepSleep wakeup: ddr init bypassed 1\n"); + } +#else +#error "DRAM config is not set" +#endif + +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) + if(!skip_shmoo) + { + printk(BIOS_INFO, "ddr_init2: Calling soc_and28_shmoo_phy_init\n"); + if(soc_and28_shmoo_phy_init(unit, 0) != SOC_E_NONE) { + + printk(BIOS_ERR, "DDR PHY initialization failed\n"); + goto done; + } + } + else + { + printk(BIOS_INFO, "DeepSleep wakeup: ddr init bypassed 2\n"); + } +#endif + +#ifdef CONFIG_RUN_DDR_SHMOO + printk(BIOS_DEBUG, "PHY register dump after DDR PHY init\n"); + dump_phy_regs(); +#endif + + printk(BIOS_INFO, "Programming controller register\n"); + ddr_init_regs(ddr_init_tab); + + ddr_type = 1; + if(ddr_type) { + /* DDR3 */ + switch(ddr_clk) { +#ifdef CONFIG_DDR333 + case 333: + ddr_init_regs(ddr3_init_tab_667); + break; +#endif +#ifdef CONFIG_DDR400 + case 400: + ddr_init_regs(ddr3_init_tab_800); + break; +#endif +#ifdef CONFIG_DDR533 + case 533: + ddr_init_regs(ddr3_init_tab_1066); + break; +#endif +#ifdef CONFIG_DDR667 + case 667: + ddr_init_regs(ddr3_init_tab_1333); + break; +#endif +#if (defined(CONFIG_DDR750) || defined(CONFIG_CYGNUS_DDR800)) + case 750: + case 800: + ddr_init_regs(ddr3_init_tab_1600); + break; +#endif + } + } + + /* Start the DDR */ + reg32_set_bits((volatile uint32_t *)DDR_DENALI_CTL_00, 0x01); + +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) + if(!skip_shmoo) + { + while(!(reg32_read((volatile uint32_t *)DDR_DENALI_CTL_175) & 0x100)); + printk(BIOS_INFO, "ddr_init2: MemC initialization complete\n"); + + reg32_set_bits((unsigned int *)DDR_DENALI_CTL_177, 0x00100); + reg32_write((unsigned int *)DDR_BistConfig, 0x00000002); + reg32_write((unsigned int *)DDR_BistConfig, 0x00000003); + reg32_write((unsigned int *)DDR_BistConfig, 0x0000C003); + reg32_write((unsigned int *)DDR_BistGeneralConfigurations, 0x00000020); + + printk(BIOS_INFO, "ddr_init2: Calling soc_and28_shmoo_ctl\n"); + #if defined(CONFIG_SHMOO_AND28_REUSE) + if (is_shmoo_data_valid()) { + restore_shmoo_config(&config_param); + soc_and28_shmoo_ctl(unit, 0, SHMOO_AND28_SHMOO_RSVP, 0, 1, SHMOO_AND28_ACTION_RESTORE, &config_param); + + #if defined(CONFIG_SHMOO_REUSE_MEMTEST_LENGTH) + /* Perform memory test to see if the stored SHMMO values work */ + if (CONFIG_SHMOO_REUSE_MEMTEST_LENGTH > 0) { + /* Release DDR to AXI for memory testing */ + reg32_clear_bits((volatile uint32_t *)DDR_BistConfig, 1 << DDR_BistConfig__axi_port_sel); + + printk(BIOS_INFO, "Running simple memory test ..... "); + i = simple_memory_test( + (void *)CONFIG_SHMOO_REUSE_MEMTEST_START, + CONFIG_SHMOO_REUSE_MEMTEST_LENGTH); + if (i) { + printk(BIOS_ERR, "failed!\n"); + + /* Connect DDR controller to BIST for SHMOO */ + reg32_set_bits((volatile uint32_t *)DDR_BistConfig, 1 << DDR_BistConfig__axi_port_sel); + + /* Perform full SHMOO since stored values don't work */ + soc_and28_shmoo_ctl(unit, 0, SHMOO_AND28_SHMOO_RSVP, 0, 1, SHMOO_AND28_ACTION_RUN, &config_param); + } else { + printk(BIOS_INFO, "OK\n"); + } + } + #endif /* defined(CONFIG_SHMOO_REUSE_MEMTEST_LENGTH) */ + + } else { + soc_and28_shmoo_ctl(unit, 0, SHMOO_AND28_SHMOO_RSVP, 0, 1, SHMOO_AND28_ACTION_RUN, &config_param); + } + #else + soc_and28_shmoo_ctl(unit, 0, SHMOO_AND28_SHMOO_RSVP, 0, 1, SHMOO_AND28_ACTION_RUN, &config_param); + #endif /* CONFIG_SHMOO_AND28_REUSE */ + } +#endif + else + { + printk(BIOS_INFO, "DeepSleep wakeup: ddr init bypassed 3\n"); + } + +#if defined(CONFIG_IPROC_P7) && defined(CONFIG_IPROC_DDR_ECC) + printk(BIOS_INFO, "Enabling DDR ECC correcting and reporting\n"); + + /* Clear DDR ECC interrupts if any */ + reg32_set_bits((volatile uint32_t *)DDR_DENALI_CTL_177, + DDR_DENALI_CTL_177_ECC_MASK); + + /* Disable auto corruption */ + reg32_set_bits((volatile uint32_t *)DDR_DENALI_CTL_148, + 1 << DDR_DENALI_CTL_148__ECC_DISABLE_W_UC_ERR); + + /* Enable ECC correction and reporting */ + reg32_set_bits((volatile uint32_t *)DDR_DENALI_CTL_146, + 1 << DDR_DENALI_CTL_146__ECC_EN); + + /* Initialize DDR so that uninitialized reads won't report ecc error */ + clear_ddr(0, CONFIG_PHYS_SDRAM_1_SIZE); +#elif defined(CONFIG_IPROC_DDR_ECC) + printk(BIOS_INFO, "Enabling DDR ECC reporting\n"); + /* Clear DDR interrupts if any */ + *(unsigned int *)(DDR_DENALI_CTL_213) = 0x00FFFFFF; + __udelay(1000); + reg32_set_bits((volatile uint32_t *)DDR_DENALI_CTL_67, 0x01); //Disable auto correction + reg32_set_bits((volatile uint32_t *)DDR_DENALI_CTL_66, 0x01); //Enable ECC + + clear_ddr(0, CONFIG_PHYS_SDRAM_1_SIZE); + printk(BIOS_INFO, "Enabling DDR ECC correction\n"); + reg32_set_bits((volatile uint32_t *)DDR_DENALI_CTL_66, 1 << 1); //Enable ECC correction +#endif /* defined(CONFIG_IPROC_P7) && defined(CONFIG_IPROC_DDR_ECC) */ + + /* Release DDR slave port to AXI */ + reg32_clear_bits((volatile uint32_t *)DDR_BistConfig, 1 << DDR_BistConfig__axi_port_sel); + printk(BIOS_INFO, "DDR Interface Ready\n"); + + //dump_phy_regs(); + +#if defined(CONFIG_SOC_BROADCOM_CYGNUS) + /* SRX */ + if(skip_shmoo) + { + // Enter Self refresh (dummy) , to keep Denali happy + reg32_write((unsigned int *)DDR_DENALI_CTL_56, 0x0a050505); + + __udelay(200); + printk(BIOS_INFO, "\nDDR self refresh exit \n"); + + // Assert DFI request from PHY to mask any interaction with MEMC + reg32_write((unsigned int *)DDR_PHY_CONTROL_REGS_DFI_CNTRL, 0xe0); + reg32_write((unsigned int *)DDR_PHY_CONTROL_REGS_DFI_CNTRL, 0); + + // Exit Self refresh + reg32_write((unsigned int *)DDR_DENALI_CTL_56, 0x09050505); + } + + /* Clear iHOST flag */ + reg32_write((unsigned int *)CRMU_IHOST_POR_WAKEUP_FLAG, 0x0); + printk(BIOS_INFO, "IHOST POR WAKEUP FLAG cleared\n"); + +// iproc_dump_ddr_regs(); + + if(pwrctli0==0) + goto done; + +wakeup: + printk(BIOS_INFO, "Wakeup from %s\n", pwrctli0==2 ? "SLEEP":"DEEPSLEEP"); + + if(pwrctli0==3) + { + __udelay(10000); + if(simple_ddr_crc32_check()<0) + { + printk(BIOS_INFO, "Die...\n"); + while(1); + } + } + + /* CRMU_IHOST_SW_PERSISTENT_REG4 = 0x03024c64 */ + asm( + "movw r3, #0x4c64\n" + "movt r3, #0x0302\n" + "ldr r5, [r3]\n" + "mov lr, #0\n" + "mov pc, r5\n"); +#endif /* defined(CONFIG_SOC_BROADCOM_CYGNUS) */ + +done: + /* Reclaim everything we have previously allocated for temporary usage. */ +// free_heap(); + return; +} + + |