/* * 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 #include #include #include #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 #if IS_ENABLED(CONFIG_CYGNUS_DDR333) #define CYGNUS_DRAM_FREQ 333 extern unsigned int ddr3_init_tab_667[]; #endif #if IS_ENABLED(CONFIG_CYGNUS_DDR400) #define CYGNUS_DRAM_FREQ 400 extern unsigned int ddr3_init_tab_800[]; #endif #if IS_ENABLED(CONFIG_CYGNUS_DDR533) #define CYGNUS_DRAM_FREQ 533 extern unsigned int ddr3_init_tab_1066[]; #endif #if IS_ENABLED(CONFIG_CYGNUS_DDR667) #define CYGNUS_DRAM_FREQ 667 extern unsigned int ddr3_init_tab_1333[]; #endif #if IS_ENABLED(CONFIG_CYGNUS_DDR800) #define CYGNUS_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 IS_ENABLED(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<> 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 IS_ENABLED(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 IS_ENABLED(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: POWER ON */ 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: POWER OK */ 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 IS_ENABLED(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 CYGNUS_DRAM_FREQ return CYGNUS_DRAM_FREQ; #else #error Please set DDR frequency (CYGNUS_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> 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> 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; isector_size * flash->sector_size, flash->sector_size ); if (ret) { printk(BIOS_ERR, "SPI flash erase failed, error=%d\n", ret); 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); } 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> 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 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= 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 IS_ENABLED(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 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> 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 IS_ENABLED(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 IS_ENABLED(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 /* IS_ENABLED(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 IS_ENABLED(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 IS_ENABLED(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) { #if IS_ENABLED(CONFIG_CYGNUS_DDR333) case 333: ddr_init_regs(ddr3_init_tab_667); break; #endif #if IS_ENABLED(CONFIG_CYGNUS_DDR400) case 400: ddr_init_regs(ddr3_init_tab_800); break; #endif #if IS_ENABLED(CONFIG_CYGNUS_DDR533) case 533: ddr_init_regs(ddr3_init_tab_1066); break; #endif #if IS_ENABLED(CONFIG_CYGNUS_DDR667) case 667: ddr_init_regs(ddr3_init_tab_1333); break; #endif #if IS_ENABLED(CONFIG_CYGNUS_DDR800) case 800: ddr_init_regs(ddr3_init_tab_1600); break; #endif } } #if IS_ENABLED(CONFIG_CYGNUS_DDR_AUTO_SELF_REFRESH_ENABLE) #if (DDR_AUTO_SELF_REFRESH_IDLE_COUNT > 0) & (DDR_AUTO_SELF_REFRESH_IDLE_COUNT <= 0xff) /* Enable auto self-refresh */ reg32_set_bits((unsigned int *)DDR_DENALI_CTL_57, 0x2 << DDR_DENALI_CTL_57__LP_AUTO_EXIT_EN_R | 0x2 << DDR_DENALI_CTL_57__LP_AUTO_ENTRY_EN_R); reg32_set_bits((unsigned int *)DDR_DENALI_CTL_58, DDR_AUTO_SELF_REFRESH_IDLE_COUNT << DDR_DENALI_CTL_58__LP_AUTO_SR_IDLE_R); #else #error DDR_AUTO_SELF_REFRESH_IDLE_COUNT out of range #endif #else /* Disable auto-self refresh */ reg32_clear_bits((unsigned int *)DDR_DENALI_CTL_57, 0x2 << DDR_DENALI_CTL_57__LP_AUTO_EXIT_EN_R | 0x2 << DDR_DENALI_CTL_57__LP_AUTO_ENTRY_EN_R); reg32_clear_bits((unsigned int *)DDR_DENALI_CTL_58, 0xff << DDR_DENALI_CTL_58__LP_AUTO_SR_IDLE_R); #endif /* Start the DDR */ reg32_set_bits((volatile uint32_t *)DDR_DENALI_CTL_00, 0x01); #if IS_ENABLED(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 IS_ENABLED(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 /* IS_ENABLED(CONFIG_SOC_BROADCOM_CYGNUS) */ done: /* Reclaim everything we have previously allocated for temporary usage. */ // free_heap(); return; }