1 /* 2 * (C) Copyright 2010 3 * Marvell Semiconductor <www.marvell.com> 4 * Written-by: Prafulla Wadaskar <prafulla@marvell.com>, 5 * Contributor: Mahavir Jain <mjain@marvell.com> 6 * 7 * See file CREDITS for list of people who contributed to this 8 * project. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation; either version 2 of 13 * the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 23 * MA 02110-1301 USA 24 */ 25 26 #include <common.h> 27 #include <asm/io.h> 28 #include <asm/arch/armada100.h> 29 30 DECLARE_GLOBAL_DATA_PTR; 31 32 /* 33 * ARMADA100 DRAM controller supports upto 8 banks 34 * for chip select 0 and 1 35 */ 36 37 /* 38 * DDR Memory Control Registers 39 * Refer Datasheet Appendix A.17 40 */ 41 struct armd1ddr_map_registers { 42 u32 cs; /* Memory Address Map Register -CS */ 43 u32 pad[3]; 44 }; 45 46 struct armd1ddr_registers { 47 u8 pad[0x100 - 0x000]; 48 struct armd1ddr_map_registers mmap[2]; 49 }; 50 51 /* 52 * armd1_sdram_base - reads SDRAM Base Address Register 53 */ 54 u32 armd1_sdram_base(int chip_sel) 55 { 56 struct armd1ddr_registers *ddr_regs = 57 (struct armd1ddr_registers *)ARMD1_DRAM_BASE; 58 u32 result = 0; 59 u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); 60 61 if (!CS_valid) 62 return 0; 63 64 result = readl(&ddr_regs->mmap[chip_sel].cs) & 0xFF800000; 65 return result; 66 } 67 68 /* 69 * armd1_sdram_size - reads SDRAM size 70 */ 71 u32 armd1_sdram_size(int chip_sel) 72 { 73 struct armd1ddr_registers *ddr_regs = 74 (struct armd1ddr_registers *)ARMD1_DRAM_BASE; 75 u32 result = 0; 76 u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); 77 78 if (!CS_valid) 79 return 0; 80 81 result = readl(&ddr_regs->mmap[chip_sel].cs); 82 result = (result >> 16) & 0xF; 83 if (result < 0x7) { 84 printf("Unknown DRAM Size\n"); 85 return -1; 86 } else { 87 return ((0x8 << (result - 0x7)) * 1024 * 1024); 88 } 89 } 90 91 #ifndef CONFIG_SYS_BOARD_DRAM_INIT 92 int dram_init(void) 93 { 94 int i; 95 96 gd->ram_size = 0; 97 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 98 gd->bd->bi_dram[i].start = armd1_sdram_base(i); 99 gd->bd->bi_dram[i].size = armd1_sdram_size(i); 100 /* 101 * It is assumed that all memory banks are consecutive 102 * and without gaps. 103 * If the gap is found, ram_size will be reported for 104 * consecutive memory only 105 */ 106 if (gd->bd->bi_dram[i].start != gd->ram_size) 107 break; 108 109 gd->ram_size += gd->bd->bi_dram[i].size; 110 111 } 112 113 for (; i < CONFIG_NR_DRAM_BANKS; i++) { 114 /* If above loop terminated prematurely, we need to set 115 * remaining banks' start address & size as 0. Otherwise other 116 * u-boot functions and Linux kernel gets wrong values which 117 * could result in crash */ 118 gd->bd->bi_dram[i].start = 0; 119 gd->bd->bi_dram[i].size = 0; 120 } 121 return 0; 122 } 123 124 /* 125 * If this function is not defined here, 126 * board.c alters dram bank zero configuration defined above. 127 */ 128 void dram_init_banksize(void) 129 { 130 dram_init(); 131 } 132 #endif /* CONFIG_SYS_BOARD_DRAM_INIT */ 133