blob: fb3d29660c42d601eff8b2b9cdba37f7a2fad68d [file] [log] [blame]
David VomLehna3a0f8c2009-08-30 17:15:11 -07001/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 * Portions copyright (C) 2009 Cisco Systems, Inc.
5 *
6 * This program is free software; you can distribute it and/or modify it
7 * under the terms of the GNU General Public License (Version 2) as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
18 *
19 * Apparently originally from arch/mips/malta-memory.c. Modified to work
20 * with the PowerTV bootloader.
21 */
22#include <linux/init.h>
23#include <linux/mm.h>
24#include <linux/bootmem.h>
25#include <linux/pfn.h>
26#include <linux/string.h>
27
28#include <asm/bootinfo.h>
29#include <asm/page.h>
30#include <asm/sections.h>
31
32#include <asm/mips-boards/prom.h>
David VomLehnca36c362010-05-21 11:25:36 -070033#include <asm/mach-powertv/asic.h>
34#include <asm/mach-powertv/ioremap.h>
David VomLehna3a0f8c2009-08-30 17:15:11 -070035
36#include "init.h"
37
38/* Memory constants */
39#define KIBIBYTE(n) ((n) * 1024) /* Number of kibibytes */
40#define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
David VomLehnca36c362010-05-21 11:25:36 -070041#define DEFAULT_MEMSIZE MEBIBYTE(128) /* If no memsize provided */
David VomLehna3a0f8c2009-08-30 17:15:11 -070042
David VomLehnca36c362010-05-21 11:25:36 -070043#define BLDR_SIZE KIBIBYTE(256) /* Memory reserved for bldr */
44#define RV_SIZE MEBIBYTE(4) /* Size of reset vector */
David VomLehna3a0f8c2009-08-30 17:15:11 -070045
David VomLehnca36c362010-05-21 11:25:36 -070046#define LOW_MEM_END 0x20000000 /* Highest low memory address */
47#define BLDR_ALIAS 0x10000000 /* Bootloader address */
48#define RV_PHYS 0x1fc00000 /* Reset vector address */
49#define LOW_RAM_END RV_PHYS /* End of real RAM in low mem */
50
51/*
52 * Very low-level conversion from processor physical address to device
53 * DMA address for the first bank of memory.
54 */
55#define PHYS_TO_DMA(paddr) ((paddr) + (CONFIG_LOW_RAM_DMA - LOW_RAM_ALIAS))
56
57unsigned long ptv_memsize;
58
59/*
Uwe Kleine-Königb5950762010-11-01 15:38:34 -040060 * struct low_mem_reserved - Items in low memory that are reserved
David VomLehnca36c362010-05-21 11:25:36 -070061 * @start: Physical address of item
62 * @size: Size, in bytes, of this item
63 * @is_aliased: True if this is RAM aliased from another location. If false,
64 * it is something other than aliased RAM and the RAM in the
65 * unaliased address is still visible outside of low memory.
66 */
67struct low_mem_reserved {
68 phys_addr_t start;
69 phys_addr_t size;
70 bool is_aliased;
71};
72
73/*
74 * Must be in ascending address order
75 */
76struct low_mem_reserved low_mem_reserved[] = {
77 {BLDR_ALIAS, BLDR_SIZE, true}, /* Bootloader RAM */
78 {RV_PHYS, RV_SIZE, false}, /* Reset vector */
79};
80
81/*
82 * struct mem_layout - layout of a piece of the system RAM
83 * @phys: Physical address of the start of this piece of RAM. This is the
84 * address at which both the processor and I/O devices see the
85 * RAM.
86 * @alias: Alias of this piece of memory in order to make it appear in
87 * the low memory part of the processor's address space. I/O
88 * devices don't see anything here.
89 * @size: Size, in bytes, of this piece of RAM
90 */
91struct mem_layout {
92 phys_addr_t phys;
93 phys_addr_t alias;
94 phys_addr_t size;
95};
96
97/*
98 * struct mem_layout_list - list descriptor for layouts of system RAM pieces
99 * @family: Specifies the family being described
100 * @n: Number of &struct mem_layout elements
101 * @layout: Pointer to the list of &mem_layout structures
102 */
103struct mem_layout_list {
104 enum family_type family;
105 size_t n;
106 struct mem_layout *layout;
107};
108
109static struct mem_layout f1500_layout[] = {
110 {0x20000000, 0x10000000, MEBIBYTE(256)},
111};
112
113static struct mem_layout f4500_layout[] = {
114 {0x40000000, 0x10000000, MEBIBYTE(256)},
115 {0x20000000, 0x20000000, MEBIBYTE(32)},
116};
117
118static struct mem_layout f8500_layout[] = {
119 {0x40000000, 0x10000000, MEBIBYTE(256)},
120 {0x20000000, 0x20000000, MEBIBYTE(32)},
121 {0x30000000, 0x30000000, MEBIBYTE(32)},
122};
123
124static struct mem_layout fx600_layout[] = {
125 {0x20000000, 0x10000000, MEBIBYTE(256)},
126 {0x60000000, 0x60000000, MEBIBYTE(128)},
127};
128
129static struct mem_layout_list layout_list[] = {
130 {FAMILY_1500, ARRAY_SIZE(f1500_layout), f1500_layout},
131 {FAMILY_1500VZE, ARRAY_SIZE(f1500_layout), f1500_layout},
132 {FAMILY_1500VZF, ARRAY_SIZE(f1500_layout), f1500_layout},
133 {FAMILY_4500, ARRAY_SIZE(f4500_layout), f4500_layout},
134 {FAMILY_8500, ARRAY_SIZE(f8500_layout), f8500_layout},
135 {FAMILY_8500RNG, ARRAY_SIZE(f8500_layout), f8500_layout},
136 {FAMILY_4600, ARRAY_SIZE(fx600_layout), fx600_layout},
137 {FAMILY_4600VZA, ARRAY_SIZE(fx600_layout), fx600_layout},
138 {FAMILY_8600, ARRAY_SIZE(fx600_layout), fx600_layout},
139 {FAMILY_8600VZB, ARRAY_SIZE(fx600_layout), fx600_layout},
140};
141
142/* If we can't determine the layout, use this */
143static struct mem_layout default_layout[] = {
144 {0x20000000, 0x10000000, MEBIBYTE(128)},
145};
146
147/**
148 * register_non_ram - register low memory not available for RAM usage
149 */
150static __init void register_non_ram(void)
David VomLehna3a0f8c2009-08-30 17:15:11 -0700151{
David VomLehnca36c362010-05-21 11:25:36 -0700152 int i;
153
154 for (i = 0; i < ARRAY_SIZE(low_mem_reserved); i++)
155 add_memory_region(low_mem_reserved[i].start,
156 low_mem_reserved[i].size, BOOT_MEM_RESERVED);
157}
158
159/**
160 * get_memsize - get the size of memory as a single bank
161 */
162static phys_addr_t get_memsize(void)
163{
164 static char cmdline[COMMAND_LINE_SIZE] __initdata;
165 phys_addr_t memsize = 0;
David VomLehna3a0f8c2009-08-30 17:15:11 -0700166 char *memsize_str;
David VomLehna3a0f8c2009-08-30 17:15:11 -0700167 char *ptr;
David VomLehna3a0f8c2009-08-30 17:15:11 -0700168
169 /* Check the command line first for a memsize directive */
170 strcpy(cmdline, arcs_cmdline);
171 ptr = strstr(cmdline, "memsize=");
172 if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
173 ptr = strstr(ptr, " memsize=");
174
175 if (ptr) {
176 memsize = memparse(ptr + 8, &ptr);
177 } else {
178 /* otherwise look in the environment */
179 memsize_str = prom_getenv("memsize");
180
181 if (memsize_str != NULL) {
182 pr_info("prom memsize = %s\n", memsize_str);
183 memsize = simple_strtol(memsize_str, NULL, 0);
184 }
185
186 if (memsize == 0) {
187 if (_prom_memsize != 0) {
188 memsize = _prom_memsize;
David VomLehnca36c362010-05-21 11:25:36 -0700189 pr_info("_prom_memsize = 0x%x\n", memsize);
David VomLehna3a0f8c2009-08-30 17:15:11 -0700190 /* add in memory that the bootloader doesn't
191 * report */
David VomLehnca36c362010-05-21 11:25:36 -0700192 memsize += BLDR_SIZE;
David VomLehna3a0f8c2009-08-30 17:15:11 -0700193 } else {
194 memsize = DEFAULT_MEMSIZE;
195 pr_info("Memsize not passed by bootloader, "
David VomLehnca36c362010-05-21 11:25:36 -0700196 "defaulting to 0x%x\n", memsize);
David VomLehna3a0f8c2009-08-30 17:15:11 -0700197 }
198 }
199 }
200
David VomLehnca36c362010-05-21 11:25:36 -0700201 return memsize;
202}
203
204/**
205 * register_low_ram - register an aliased section of RAM
206 * @p: Alias address of memory
207 * @n: Number of bytes in this section of memory
208 *
209 * Returns the number of bytes registered
210 *
211 */
212static __init phys_addr_t register_low_ram(phys_addr_t p, phys_addr_t n)
213{
214 phys_addr_t s;
215 int i;
216 phys_addr_t orig_n;
217
218 orig_n = n;
219
220 BUG_ON(p + n > RV_PHYS);
221
222 for (i = 0; n != 0 && i < ARRAY_SIZE(low_mem_reserved); i++) {
223 phys_addr_t start;
224 phys_addr_t size;
225
226 start = low_mem_reserved[i].start;
227 size = low_mem_reserved[i].size;
228
229 /* Handle memory before this low memory section */
230 if (p < start) {
231 phys_addr_t s;
232 s = min(n, start - p);
233 add_memory_region(p, s, BOOT_MEM_RAM);
234 p += s;
235 n -= s;
236 }
237
238 /* Handle the low memory section itself. If it's aliased,
239 * we reduce the number of byes left, but if not, the RAM
240 * is available elsewhere and we don't reduce the number of
241 * bytes remaining. */
242 if (p == start) {
243 if (low_mem_reserved[i].is_aliased) {
244 s = min(n, size);
245 n -= s;
246 p += s;
247 } else
248 p += n;
249 }
David VomLehna3a0f8c2009-08-30 17:15:11 -0700250 }
251
David VomLehnca36c362010-05-21 11:25:36 -0700252 return orig_n - n;
253}
254
David VomLehna3a0f8c2009-08-30 17:15:11 -0700255/*
David VomLehnca36c362010-05-21 11:25:36 -0700256 * register_ram - register real RAM
257 * @p: Address of memory as seen by devices
258 * @alias: If the memory is seen at an additional address by the processor,
259 * this will be the address, otherwise it is the same as @p.
260 * @n: Number of bytes in this section of memory
David VomLehna3a0f8c2009-08-30 17:15:11 -0700261 */
David VomLehnca36c362010-05-21 11:25:36 -0700262static __init void register_ram(phys_addr_t p, phys_addr_t alias,
263 phys_addr_t n)
264{
David VomLehna3a0f8c2009-08-30 17:15:11 -0700265 /*
David VomLehnca36c362010-05-21 11:25:36 -0700266 * If some or all of this memory has an alias, break it into the
267 * aliased and non-aliased portion.
David VomLehna3a0f8c2009-08-30 17:15:11 -0700268 */
David VomLehnca36c362010-05-21 11:25:36 -0700269 if (p != alias) {
270 phys_addr_t alias_size;
271 phys_addr_t registered;
272
273 alias_size = min(n, LOW_RAM_END - alias);
274 registered = register_low_ram(alias, alias_size);
275 ioremap_add_map(alias, p, n);
276 n -= registered;
277 p += registered;
278 }
279
280#ifdef CONFIG_HIGHMEM
281 if (n != 0) {
282 add_memory_region(p, n, BOOT_MEM_RAM);
283 ioremap_add_map(p, p, n);
284 }
David VomLehna3a0f8c2009-08-30 17:15:11 -0700285#endif
286}
287
David VomLehnca36c362010-05-21 11:25:36 -0700288/**
289 * register_address_space - register things in the address space
290 * @memsize: Number of bytes of RAM installed
291 *
292 * Takes the given number of bytes of RAM and registers as many of the regions,
293 * or partial regions, as it can. So, the default configuration might have
294 * two regions with 256 MiB each. If the memsize passed in on the command line
295 * is 384 MiB, it will register the first region with 256 MiB and the second
296 * with 128 MiB.
297 */
298static __init void register_address_space(phys_addr_t memsize)
299{
300 int i;
301 phys_addr_t size;
302 size_t n;
303 struct mem_layout *layout;
304 enum family_type family;
305
306 /*
307 * Register all of the things that aren't available to the kernel as
308 * memory.
309 */
310 register_non_ram();
311
312 /* Find the appropriate memory description */
313 family = platform_get_family();
314
315 for (i = 0; i < ARRAY_SIZE(layout_list); i++) {
316 if (layout_list[i].family == family)
317 break;
318 }
319
320 if (i == ARRAY_SIZE(layout_list)) {
321 n = ARRAY_SIZE(default_layout);
322 layout = default_layout;
323 } else {
324 n = layout_list[i].n;
325 layout = layout_list[i].layout;
326 }
327
328 for (i = 0; memsize != 0 && i < n; i++) {
329 size = min(memsize, layout[i].size);
330 register_ram(layout[i].phys, layout[i].alias, size);
331 memsize -= size;
332 }
333}
334
335void __init prom_meminit(void)
336{
337 ptv_memsize = get_memsize();
338 register_address_space(ptv_memsize);
339}
340
David VomLehna3a0f8c2009-08-30 17:15:11 -0700341void __init prom_free_prom_memory(void)
342{
343 unsigned long addr;
344 int i;
345
346 for (i = 0; i < boot_mem_map.nr_map; i++) {
347 if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
348 continue;
349
350 addr = boot_mem_map.map[i].addr;
351 free_init_pages("prom memory",
352 addr, addr + boot_mem_map.map[i].size);
353 }
354}