]> git.sur5r.net Git - u-boot/blob - arch/arm/mach-mvebu/dram.c
arm: mvebu: dram.c: Rework dram_init() and dram_init_banksize()
[u-boot] / arch / arm / mach-mvebu / dram.c
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 #ifdef CONFIG_SYS_MVEBU_DDR_A38X
16 #include "../../../drivers/ddr/marvell/a38x/ddr3_init.h"
17 #endif
18 #ifdef CONFIG_SYS_MVEBU_DDR_AXP
19 #include "../../../drivers/ddr/marvell/axp/ddr3_init.h"
20 #endif
21
22 DECLARE_GLOBAL_DATA_PTR;
23
24 struct sdram_bank {
25         u32     win_bar;
26         u32     win_sz;
27 };
28
29 struct sdram_addr_dec {
30         struct sdram_bank sdram_bank[4];
31 };
32
33 #define REG_CPUCS_WIN_ENABLE            (1 << 0)
34 #define REG_CPUCS_WIN_WR_PROTECT        (1 << 1)
35 #define REG_CPUCS_WIN_WIN0_CS(x)        (((x) & 0x3) << 2)
36 #define REG_CPUCS_WIN_SIZE(x)           (((x) & 0xff) << 24)
37
38 #define SDRAM_SIZE_MAX                  0xc0000000
39
40 /*
41  * mvebu_sdram_bar - reads SDRAM Base Address Register
42  */
43 u32 mvebu_sdram_bar(enum memory_bank bank)
44 {
45         struct sdram_addr_dec *base =
46                 (struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
47         u32 result = 0;
48         u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz);
49
50         if ((!enable) || (bank > BANK3))
51                 return 0;
52
53         result = readl(&base->sdram_bank[bank].win_bar);
54         return result;
55 }
56
57 /*
58  * mvebu_sdram_bs_set - writes SDRAM Bank size
59  */
60 static void mvebu_sdram_bs_set(enum memory_bank bank, u32 size)
61 {
62         struct sdram_addr_dec *base =
63                 (struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
64         /* Read current register value */
65         u32 reg = readl(&base->sdram_bank[bank].win_sz);
66
67         /* Clear window size */
68         reg &= ~REG_CPUCS_WIN_SIZE(0xFF);
69
70         /* Set new window size */
71         reg |= REG_CPUCS_WIN_SIZE((size - 1) >> 24);
72
73         writel(reg, &base->sdram_bank[bank].win_sz);
74 }
75
76 /*
77  * mvebu_sdram_bs - reads SDRAM Bank size
78  */
79 u32 mvebu_sdram_bs(enum memory_bank bank)
80 {
81         struct sdram_addr_dec *base =
82                 (struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
83         u32 result = 0;
84         u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz);
85
86         if ((!enable) || (bank > BANK3))
87                 return 0;
88         result = 0xff000000 & readl(&base->sdram_bank[bank].win_sz);
89         result += 0x01000000;
90         return result;
91 }
92
93 void mvebu_sdram_size_adjust(enum memory_bank bank)
94 {
95         u32 size;
96
97         /* probe currently equipped RAM size */
98         size = get_ram_size((void *)mvebu_sdram_bar(bank),
99                             mvebu_sdram_bs(bank));
100
101         /* adjust SDRAM window size accordingly */
102         mvebu_sdram_bs_set(bank, size);
103 }
104
105 int dram_init(void)
106 {
107         u64 size = 0;
108         int i;
109
110         for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
111                 /*
112                  * It is assumed that all memory banks are consecutive
113                  * and without gaps.
114                  * If the gap is found, ram_size will be reported for
115                  * consecutive memory only
116                  */
117                 if (mvebu_sdram_bar(i) != size)
118                         break;
119
120                 /*
121                  * Don't report more than 3GiB of SDRAM, otherwise there is no
122                  * address space left for the internal registers etc.
123                  */
124                 size += mvebu_sdram_bs(i);
125                 if (size > SDRAM_SIZE_MAX)
126                         size = SDRAM_SIZE_MAX;
127         }
128
129         for (; i < CONFIG_NR_DRAM_BANKS; i++) {
130                 /* If above loop terminated prematurely, we need to set
131                  * remaining banks' start address & size as 0. Otherwise other
132                  * u-boot functions and Linux kernel gets wrong values which
133                  * could result in crash */
134                 gd->bd->bi_dram[i].start = 0;
135                 gd->bd->bi_dram[i].size = 0;
136         }
137
138         gd->ram_size = size;
139
140         return 0;
141 }
142
143 /*
144  * If this function is not defined here,
145  * board.c alters dram bank zero configuration defined above.
146  */
147 void dram_init_banksize(void)
148 {
149         u64 size = 0;
150         int i;
151
152         for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
153                 gd->bd->bi_dram[i].start = mvebu_sdram_bar(i);
154                 gd->bd->bi_dram[i].size = mvebu_sdram_bs(i);
155
156                 /* Clip the banksize to 1GiB if it exceeds the max size */
157                 size += gd->bd->bi_dram[i].size;
158                 if (size > SDRAM_SIZE_MAX)
159                         mvebu_sdram_bs_set(i, 0x40000000);
160         }
161 }
162
163 void board_add_ram_info(int use_default)
164 {
165         u32 reg;
166
167         reg = reg_read(REG_SDRAM_CONFIG_ADDR);
168         if (reg & (1 << REG_SDRAM_CONFIG_ECC_OFFS))
169                 printf(" (ECC");
170         else
171                 printf(" (ECC not");
172         printf(" enabled)");
173 }