xref: /openbmc/u-boot/arch/arm/mach-mvebu/dram.c (revision 95de1e2f)
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