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