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/arch/armada100.h> 28 29 DECLARE_GLOBAL_DATA_PTR; 30 31 /* 32 * ARMADA100 DRAM controller supports upto 8 banks 33 * for chip select 0 and 1 34 */ 35 36 /* 37 * DDR Memory Control Registers 38 * Refer Datasheet Appendix A.17 39 */ 40 struct armd1ddr_map_registers { 41 u32 cs; /* Memory Address Map Register -CS */ 42 u32 pad[3]; 43 }; 44 45 struct armd1ddr_registers { 46 u8 pad[0x100 - 0x000]; 47 struct armd1ddr_map_registers mmap[2]; 48 }; 49 50 /* 51 * armd1_sdram_base - reads SDRAM Base Address Register 52 */ 53 u32 armd1_sdram_base(int chip_sel) 54 { 55 struct armd1ddr_registers *ddr_regs = 56 (struct armd1ddr_registers *)ARMD1_DRAM_BASE; 57 u32 result = 0; 58 u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); 59 60 if (!CS_valid) 61 return 0; 62 63 result = readl(&ddr_regs->mmap[chip_sel].cs) & 0xFF800000; 64 return result; 65 } 66 67 /* 68 * armd1_sdram_size - reads SDRAM size 69 */ 70 u32 armd1_sdram_size(int chip_sel) 71 { 72 struct armd1ddr_registers *ddr_regs = 73 (struct armd1ddr_registers *)ARMD1_DRAM_BASE; 74 u32 result = 0; 75 u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); 76 77 if (!CS_valid) 78 return 0; 79 80 result = readl(&ddr_regs->mmap[chip_sel].cs); 81 result = (result >> 16) & 0xF; 82 if (result < 0x7) { 83 printf("Unknown DRAM Size\n"); 84 return -1; 85 } else { 86 return ((0x8 << (result - 0x7)) * 1024 * 1024); 87 } 88 } 89 90 #ifndef CONFIG_SYS_BOARD_DRAM_INIT 91 int dram_init(void) 92 { 93 int i; 94 95 gd->ram_size = 0; 96 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 97 gd->bd->bi_dram[i].start = armd1_sdram_base(i); 98 gd->bd->bi_dram[i].size = armd1_sdram_size(i); 99 /* 100 * It is assumed that all memory banks are consecutive 101 * and without gaps. 102 * If the gap is found, ram_size will be reported for 103 * consecutive memory only 104 */ 105 if (gd->bd->bi_dram[i].start != gd->ram_size) 106 break; 107 108 gd->ram_size += gd->bd->bi_dram[i].size; 109 110 } 111 112 for (; i < CONFIG_NR_DRAM_BANKS; i++) { 113 /* If above loop terminated prematurely, we need to set 114 * remaining banks' start address & size as 0. Otherwise other 115 * u-boot functions and Linux kernel gets wrong values which 116 * could result in crash */ 117 gd->bd->bi_dram[i].start = 0; 118 gd->bd->bi_dram[i].size = 0; 119 } 120 return 0; 121 } 122 123 /* 124 * If this function is not defined here, 125 * board.c alters dram bank zero configuration defined above. 126 */ 127 void dram_init_banksize(void) 128 { 129 dram_init(); 130 } 131 #endif /* CONFIG_SYS_BOARD_DRAM_INIT */ 132