/* * (C) Copyright 2007 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * 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; either version 2 of * the License, or (at your option) any later version. * * 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., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #define CRAM_BANK0_BASE 0x0 #define CRAM_DIDR 0x00100000 #define MICRON_MT45W8MW16BGX_CRAM_ID 0x1b431b43 #define MICRON_MT45W8MW16BGX_CRAM_ID2 0x13431343 #define MICRON_DIDR_VENDOR_ID 0x00030003 /* 00011b */ #define CRAM_DIDR_VENDOR_ID_MASK 0x001f001f /* DIDR[4:0] */ #define CRAM_DEVID_NOT_SUPPORTED 0x00000000 #define PSRAM_PASS 0x50415353 /* "PASS" */ #define PSRAM_FAIL 0x4641494C /* "FAIL" */ static u32 is_cram_inited(void); static u32 is_cram(void); static long int cram_init(u32); static void cram_bcr_write(u32); void udelay (unsigned long); void sdram_init(void) { volatile unsigned long spr_reg; /* * If CRAM not initialized or CRAM looks initialized because this * is after a warm reboot then set SPRG7 to indicate CRAM needs * initialization. Note that CRAM is initialized by the SPI and * NAND preloader. */ spr_reg = (volatile unsigned long) mfspr(SPRG6); if ((is_cram_inited() != 1) || (spr_reg != LOAK_SPL)) { mtspr(SPRG7, LOAK_NONE); /* "NONE" */ } #if 1 /* * When running the NAND SPL, the normal EBC configuration is not * done, so We need to enable EPLD access on EBC_CS_2 and the memory * on EBC_CS_3 */ /* Enable CPLD - Needed for PSRAM Access */ /* Init SDRAM by setting EBC Bank 3 for PSRAM */ mtebc(pb1ap, CFG_EBC_PB1AP); mtebc(pb1cr, CFG_EBC_PB1CR); mtebc(pb2ap, CFG_EBC_PB2AP); mtebc(pb2cr, CFG_EBC_PB2CR); /* pre-boot loader code: we are in OCM */ mtspr(SPRG6, LOAK_SPL); /* "SPL " */ mtspr(SPRG7, LOAK_OCM); /* "OCM " */ #endif return; } static void cram_bcr_write(u32 wr_val) { u32 tmp_reg; u32 val; volatile u32 gpio_reg; /* # Program CRAM write */ /* * set CRAM_CRE = 0x1 * set wr_val = wr_val << 2 */ gpio_reg = in32(GPIO1_OR); out32(GPIO1_OR, gpio_reg | 0x00000400); wr_val = wr_val << 2; /* wr_val = 0x1c048; */ /* * # stop PLL clock before programming CRAM * set EPLD0_MUX_CTL.OESPR3 = 1 * delay 2 */ /* * # CS1 * read 0x00200000 * #shift 2 bit left before write * set val = wr_val + 0x00200000 * write dmem val 0 * read 0x00200000 val * print val/8x */ tmp_reg = in32(0x00200000); val = wr_val + 0x00200000; /* val = 0x0021c048; */ out32(val, 0x0000); udelay(100000); val = in32(0x00200000); debug("CRAM VAL: %x for CS1 ", val); /* * # CS2 * read 0x02200000 * #shift 2 bit left before write * set val = wr_val + 0x02200000 * write dmem val 0 * read 0x02200000 val * print val/8x */ tmp_reg = in32(0x02200000); val = wr_val + 0x02200000; /* val = 0x0221c048; */ out32(val, 0x0000); udelay(100000); val = in32(0x02200000); debug("CRAM VAL: %x for CS2 ", val); /* * # Start PLL clock before programming CRAM * set EPLD0_MUX_CTL.OESPR3 = 0 */ /* * set CRAMCR = 0x1 */ gpio_reg = in32(GPIO1_OR); out32(GPIO1_OR, gpio_reg | 0x00000400); /* * # read CRAM config BCR ( bit19:18 = 10b ) * #read 0x00200000 * # 1001_1001_0001_1111 ( 991f ) => * #10_0110_0100_0111_1100 => 2647c => 0022647c * #0011_0010_0011_1110 (323e) * # */ /* * set EPLD0_MUX_CTL.CRAMCR = 0x0 */ gpio_reg = in32(GPIO1_OR); out32(GPIO1_OR, gpio_reg & 0xFFFFFBFF); return; } static u32 is_cram_inited() { volatile unsigned long spr_reg; /* * If CRAM is initialized already, then don't reinitialize it again. * In the case of NAND boot and SPI boot, CRAM will already be * initialized by the pre-loader */ spr_reg = (volatile unsigned long) mfspr(SPRG7); if (spr_reg == LOAK_CRAM) { return 1; } else { return 0; } } /****** * return 0 if not CRAM * return 1 if CRAM and it's already inited by preloader * else return cram_id (CRAM Device Identification Register) ******/ static u32 is_cram(void) { u32 gpio_TCR, gpio_OSRL, gpio_OR, gpio_ISR1L; volatile u32 gpio_reg; volatile u32 cram_id = 0; if (is_cram_inited() == 1) { /* this is CRAM and it is already inited (by preloader) */ cram_id = 1; } else { /* * # CRAM CLOCK * set GPIO0_TCR.G8 = 1 * set GPIO0_OSRL.G8 = 0 * set GPIO0_OR.G8 = 0 */ gpio_reg = in32(GPIO0_TCR); gpio_TCR = gpio_reg; out32(GPIO0_TCR, gpio_reg | 0x00800000); gpio_reg = in32(GPIO0_OSRL); gpio_OSRL = gpio_reg; out32(GPIO0_OSRL, gpio_reg & 0xffffbfff); gpio_reg = in32(GPIO0_OR); gpio_OR = gpio_reg; out32(GPIO0_OR, gpio_reg & 0xff7fffff); /* * # CRAM Addreaa Valid * set GPIO0_TCR.G10 = 1 * set GPIO0_OSRL.G10 = 0 * set GPIO0_OR.G10 = 0 */ gpio_reg = in32(GPIO0_TCR); out32(GPIO0_TCR, gpio_reg | 0x00200000); gpio_reg = in32(GPIO0_OSRL); out32(GPIO0_OSRL, gpio_reg & 0xfffffbff); gpio_reg = in32(GPIO0_OR); out32(GPIO0_OR, gpio_reg & 0xffdfffff); /* * # config input (EBC_WAIT) * set GPIO0_ISR1L.G9 = 1 * set GPIO0_TCR.G9 = 0 */ gpio_reg = in32(GPIO0_ISR1L); gpio_ISR1L = gpio_reg; out32(GPIO0_ISR1L, gpio_reg | 0x00001000); gpio_reg = in32(GPIO0_TCR); out32(GPIO0_TCR, gpio_reg & 0xffbfffff); /* * Enable CRE to read Registers * set GPIO0_TCR.21 = 1 * set GPIO1_OR.21 = 1 */ gpio_reg = in32(GPIO1_TCR); out32(GPIO1_TCR, gpio_reg | 0x00000400); gpio_reg = in32(GPIO1_OR); out32(GPIO1_OR, gpio_reg | 0x00000400); /* Read Version ID */ cram_id = (volatile u32) in32(CRAM_BANK0_BASE+CRAM_DIDR); udelay(100000); asm volatile(" sync"); asm volatile(" eieio"); debug("Cram ID: %X ", cram_id); switch (cram_id) { case MICRON_MT45W8MW16BGX_CRAM_ID: case MICRON_MT45W8MW16BGX_CRAM_ID2: /* supported CRAM vendor/part */ break; case CRAM_DEVID_NOT_SUPPORTED: default: /* check for DIDR Vendor ID of Micron */ if ((cram_id & CRAM_DIDR_VENDOR_ID_MASK) == MICRON_DIDR_VENDOR_ID) { /* supported CRAM vendor */ break; } /* this is not CRAM or not supported CRAM vendor/part */ cram_id = 0; /* * reset the GPIO registers to the values that were * there before this routine */ out32(GPIO0_TCR, gpio_TCR); out32(GPIO0_OSRL, gpio_OSRL); out32(GPIO0_OR, gpio_OR); out32(GPIO0_ISR1L, gpio_ISR1L); break; } } return cram_id; } static long int cram_init(u32 already_inited) { volatile u32 tmp_reg; u32 cram_wr_val; if (already_inited == 0) return 0; /* * If CRAM is initialized already, then don't reinitialize it again. * In the case of NAND boot and SPI boot, CRAM will already be * initialized by the pre-loader */ if (already_inited != 1) { /* * #o CRAM Card * # - CRAMCRE @reg16 = 1; for CRAM to use * # - CRAMCRE @reg16 = 0; for CRAM to program * * # enable CRAM SEL, move from setEPLD.cmd * set EPLD0_MUX_CTL.OECRAM = 0 * set EPLD0_MUX_CTL.CRAMCR = 1 * set EPLD0_ETHRSTBOOT.SLCRAM = 0 * #end */ /* * #1. EBC need to program READY, CLK, ADV for ASync mode * # config output */ /* * # CRAM CLOCK * set GPIO0_TCR.G8 = 1 * set GPIO0_OSRL.G8 = 0 * set GPIO0_OR.G8 = 0 */ tmp_reg = in32(GPIO0_TCR); out32(GPIO0_TCR, tmp_reg | 0x00800000); tmp_reg = in32(GPIO0_OSRL); out32(GPIO0_OSRL, tmp_reg & 0xffffbfff); tmp_reg = in32(GPIO0_OR); out32(GPIO0_OR, tmp_reg & 0xff7fffff); /* * # CRAM Addreaa Valid * set GPIO0_TCR.G10 = 1 * set GPIO0_OSRL.G10 = 0 * set GPIO0_OR.G10 = 0 */ tmp_reg = in32(GPIO0_TCR); out32(GPIO0_TCR, tmp_reg | 0x00200000); tmp_reg = in32(GPIO0_OSRL); out32(GPIO0_OSRL, tmp_reg & 0xfffffbff); tmp_reg = in32(GPIO0_OR); out32(GPIO0_OR, tmp_reg & 0xffdfffff); /* * # config input (EBC_WAIT) * set GPIO0_ISR1L.G9 = 1 * set GPIO0_TCR.G9 = 0 */ tmp_reg = in32(GPIO0_ISR1L); out32(GPIO0_ISR1L, tmp_reg | 0x00001000); tmp_reg = in32(GPIO0_TCR); out32(GPIO0_TCR, tmp_reg & 0xffbfffff); /* * # config CS4 from GPIO * set GPIO0_TCR.G0 = 1 * set GPIO0_OSRL.G0 = 1 */ tmp_reg = in32(GPIO0_TCR); out32(GPIO0_TCR, tmp_reg | 0x80000000); tmp_reg = in32(GPIO0_OSRL); out32(GPIO0_OSRL, tmp_reg | 0x40000000); /* * #2. EBC in Async mode * # set EBC0_PB1AP = 0x078f0ec0 * set EBC0_PB1AP = 0x078f1ec0 * set EBC0_PB2AP = 0x078f1ec0 */ mtebc(pb1ap, 0x078F1EC0); mtebc(pb2ap, 0x078F1EC0); /* * #set EBC0_PB1CR = 0x000bc000 * #enable CS2 for CRAM * set EBC0_PB2CR = 0x020bc000 */ mtebc(pb1cr, 0x000BC000); mtebc(pb2cr, 0x020BC000); /* * #3. set CRAM in Sync mode * #exec cm_bcr_write.cmd { 0x701f } * #3. set CRAM in Sync mode (full drv strength) * exec cm_bcr_write.cmd { 0x701F } */ cram_wr_val = 0x7012; /* CRAM burst setting */ cram_bcr_write(cram_wr_val); /* * #4. EBC in Sync mode * #set EBC0_PB1AP = 0x9f800fc0 * #set EBC0_PB1AP = 0x900001c0 * set EBC0_PB2AP = 0x9C0201c0 * set EBC0_PB2AP = 0x9C0201c0 */ mtebc(pb1ap, 0x9C0201C0); mtebc(pb2ap, 0x9C0201C0); /* * #5. EBC need to program READY, CLK, ADV for Sync mode * # config output * set GPIO0_TCR.G8 = 1 * set GPIO0_OSRL.G8 = 1 * set GPIO0_TCR.G10 = 1 * set GPIO0_OSRL.G10 = 1 */ tmp_reg = in32(GPIO0_TCR); out32(GPIO0_TCR, tmp_reg | 0x00800000); tmp_reg = in32(GPIO0_OSRL); out32(GPIO0_OSRL, tmp_reg | 0x00004000); tmp_reg = in32(GPIO0_TCR); out32(GPIO0_TCR, tmp_reg | 0x00200000); tmp_reg = in32(GPIO0_OSRL); out32(GPIO0_OSRL, tmp_reg | 0x00000400); /* * # config input * set GPIO0_ISR1L.G9 = 1 * set GPIO0_TCR.G9 = 0 */ tmp_reg = in32(GPIO0_ISR1L); out32(GPIO0_ISR1L, tmp_reg | 0x00001000); tmp_reg = in32(GPIO0_TCR); out32(GPIO0_TCR, tmp_reg & 0xffbfffff); /* * # config EBC to use RDY * set SDR0_ULTRA0.EBCREN = 1 */ mfsdr(sdrultra0, tmp_reg); mtsdr(sdrultra0, tmp_reg | 0x04000000); /* * set EPLD0_MUX_CTL.OESPR3 = 0 */ mtspr(SPRG7, LOAK_CRAM); /* "CRAM" */ } /* if (already_inited != 1) */ return (64 * 1024 * 1024); } /****** * return 0 if not PSRAM * return 1 if is PSRAM ******/ static int is_psram(u32 addr) { u32 test_pattern = 0xdeadbeef; volatile u32 readback; if (addr == CFG_SDRAM_BASE) { /* This is to temp enable OE for PSRAM */ out16(EPLD_BASE+EPLD_MUXOE, 0x7f0f); udelay(10000); } out32(addr, test_pattern); asm volatile(" sync"); asm volatile(" eieio"); readback = (volatile u32) in32(addr); asm volatile(" sync"); asm volatile(" eieio"); if (readback == test_pattern) { return 1; } else { return 0; } } static long int psram_init(void) { u32 readback; long psramsize = 0; int i; /* This is to temp enable OE for PSRAM */ out16(EPLD_BASE+EPLD_MUXOE, 0x7f0f); udelay(10000); /* * PSRAM bank 1: read then write to address 0x00000000 */ for (i = 0; i < 100; i++) { if (is_psram(CFG_SDRAM_BASE + (i*256)) == 1) { readback = PSRAM_PASS; } else { readback = PSRAM_FAIL; break; } } if (readback == PSRAM_PASS) { debug("psram_init(bank0): pass\n"); psramsize = (16 * 1024 * 1024); } else { debug("psram_init(bank0): fail\n"); return 0; } #if 0 /* * PSRAM bank 1: read then write to address 0x01000000 */ for (i = 0; i < 100; i++) { if (is_psram((1 << 24) + (i*256)) == 1) { readback = PSRAM_PASS; } else { readback = PSRAM_FAIL; break; } } if (readback == PSRAM_PASS) { debug("psram_init(bank1): pass\n"); psramsize = psramsize + (16 * 1024 * 1024); } #endif mtspr(SPRG7, LOAK_PSRAM); /* "PSRA" - PSRAM */ return psramsize; } long int initdram(int board_type) { long int sram_size; u32 cram_inited; /* Determine Attached Memory Expansion Card*/ cram_inited = is_cram(); if (cram_inited != 0) { /* CRAM */ debug("CRAM Expansion Card attached\n"); sram_size = cram_init(cram_inited); } else if (is_psram(CFG_SDRAM_BASE+4) == 1) { /* PSRAM */ debug("PSRAM Expansion Card attached\n"); sram_size = psram_init(); } else { /* no SRAM */ debug("No Memory Card Attached!!\n"); sram_size = 0; } return sram_size; } int testdram(void) { return (0); }