1 /* 2 * (C) Copyright 2009 3 * Marvell Semiconductor <www.marvell.com> 4 * Written-by: Prafulla Wadaskar <prafulla@marvell.com> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <config.h> 10 #include <common.h> 11 #include <asm/io.h> 12 #include <asm/arch/cpu.h> 13 #include <asm/arch/soc.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 struct sdram_bank { 18 u32 win_bar; 19 u32 win_sz; 20 }; 21 22 struct sdram_addr_dec { 23 struct sdram_bank sdram_bank[4]; 24 }; 25 26 #define REG_CPUCS_WIN_ENABLE (1 << 0) 27 #define REG_CPUCS_WIN_WR_PROTECT (1 << 1) 28 #define REG_CPUCS_WIN_WIN0_CS(x) (((x) & 0x3) << 2) 29 #define REG_CPUCS_WIN_SIZE(x) (((x) & 0xff) << 24) 30 31 /* 32 * mvebu_sdram_bar - reads SDRAM Base Address Register 33 */ 34 u32 mvebu_sdram_bar(enum memory_bank bank) 35 { 36 struct sdram_addr_dec *base = 37 (struct sdram_addr_dec *)MVEBU_SDRAM_BASE; 38 u32 result = 0; 39 u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz); 40 41 if ((!enable) || (bank > BANK3)) 42 return 0; 43 44 result = readl(&base->sdram_bank[bank].win_bar); 45 return result; 46 } 47 48 /* 49 * mvebu_sdram_bs_set - writes SDRAM Bank size 50 */ 51 static void mvebu_sdram_bs_set(enum memory_bank bank, u32 size) 52 { 53 struct sdram_addr_dec *base = 54 (struct sdram_addr_dec *)MVEBU_SDRAM_BASE; 55 /* Read current register value */ 56 u32 reg = readl(&base->sdram_bank[bank].win_sz); 57 58 /* Clear window size */ 59 reg &= ~REG_CPUCS_WIN_SIZE(0xFF); 60 61 /* Set new window size */ 62 reg |= REG_CPUCS_WIN_SIZE((size - 1) >> 24); 63 64 writel(reg, &base->sdram_bank[bank].win_sz); 65 } 66 67 /* 68 * mvebu_sdram_bs - reads SDRAM Bank size 69 */ 70 u32 mvebu_sdram_bs(enum memory_bank bank) 71 { 72 struct sdram_addr_dec *base = 73 (struct sdram_addr_dec *)MVEBU_SDRAM_BASE; 74 u32 result = 0; 75 u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz); 76 77 if ((!enable) || (bank > BANK3)) 78 return 0; 79 result = 0xff000000 & readl(&base->sdram_bank[bank].win_sz); 80 result += 0x01000000; 81 return result; 82 } 83 84 void mvebu_sdram_size_adjust(enum memory_bank bank) 85 { 86 u32 size; 87 88 /* probe currently equipped RAM size */ 89 size = get_ram_size((void *)mvebu_sdram_bar(bank), 90 mvebu_sdram_bs(bank)); 91 92 /* adjust SDRAM window size accordingly */ 93 mvebu_sdram_bs_set(bank, size); 94 } 95 96 #ifndef CONFIG_SYS_BOARD_DRAM_INIT 97 int dram_init(void) 98 { 99 int i; 100 101 gd->ram_size = 0; 102 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 103 gd->bd->bi_dram[i].start = mvebu_sdram_bar(i); 104 gd->bd->bi_dram[i].size = mvebu_sdram_bs(i); 105 /* 106 * It is assumed that all memory banks are consecutive 107 * and without gaps. 108 * If the gap is found, ram_size will be reported for 109 * consecutive memory only 110 */ 111 if (gd->bd->bi_dram[i].start != gd->ram_size) 112 break; 113 114 /* 115 * Don't report more than 3GiB of SDRAM, otherwise there is no 116 * address space left for the internal registers etc. 117 */ 118 if ((gd->ram_size + gd->bd->bi_dram[i].size != 0) && 119 (gd->ram_size + gd->bd->bi_dram[i].size <= (3 << 30))) 120 gd->ram_size += gd->bd->bi_dram[i].size; 121 122 } 123 124 for (; i < CONFIG_NR_DRAM_BANKS; i++) { 125 /* If above loop terminated prematurely, we need to set 126 * remaining banks' start address & size as 0. Otherwise other 127 * u-boot functions and Linux kernel gets wrong values which 128 * could result in crash */ 129 gd->bd->bi_dram[i].start = 0; 130 gd->bd->bi_dram[i].size = 0; 131 } 132 133 return 0; 134 } 135 136 /* 137 * If this function is not defined here, 138 * board.c alters dram bank zero configuration defined above. 139 */ 140 void dram_init_banksize(void) 141 { 142 dram_init(); 143 } 144 #endif /* CONFIG_SYS_BOARD_DRAM_INIT */ 145