Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/powertv/memory.c
10817 views
1
/*
2
* Carsten Langgaard, [email protected]
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>
33
#include <asm/mach-powertv/asic.h>
34
#include <asm/mach-powertv/ioremap.h>
35
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 */
41
#define DEFAULT_MEMSIZE MEBIBYTE(128) /* If no memsize provided */
42
43
#define BLDR_SIZE KIBIBYTE(256) /* Memory reserved for bldr */
44
#define RV_SIZE MEBIBYTE(4) /* Size of reset vector */
45
46
#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
57
unsigned long ptv_memsize;
58
59
/*
60
* struct low_mem_reserved - Items in low memory that are reserved
61
* @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
*/
67
struct 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
*/
76
struct 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
*/
91
struct 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
*/
103
struct mem_layout_list {
104
enum family_type family;
105
size_t n;
106
struct mem_layout *layout;
107
};
108
109
static struct mem_layout f1500_layout[] = {
110
{0x20000000, 0x10000000, MEBIBYTE(256)},
111
};
112
113
static struct mem_layout f4500_layout[] = {
114
{0x40000000, 0x10000000, MEBIBYTE(256)},
115
{0x20000000, 0x20000000, MEBIBYTE(32)},
116
};
117
118
static struct mem_layout f8500_layout[] = {
119
{0x40000000, 0x10000000, MEBIBYTE(256)},
120
{0x20000000, 0x20000000, MEBIBYTE(32)},
121
{0x30000000, 0x30000000, MEBIBYTE(32)},
122
};
123
124
static struct mem_layout fx600_layout[] = {
125
{0x20000000, 0x10000000, MEBIBYTE(256)},
126
{0x60000000, 0x60000000, MEBIBYTE(128)},
127
};
128
129
static 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 */
143
static 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
*/
150
static __init void register_non_ram(void)
151
{
152
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
*/
162
static phys_addr_t get_memsize(void)
163
{
164
static char cmdline[COMMAND_LINE_SIZE] __initdata;
165
phys_addr_t memsize = 0;
166
char *memsize_str;
167
char *ptr;
168
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;
189
pr_info("_prom_memsize = 0x%x\n", memsize);
190
/* add in memory that the bootloader doesn't
191
* report */
192
memsize += BLDR_SIZE;
193
} else {
194
memsize = DEFAULT_MEMSIZE;
195
pr_info("Memsize not passed by bootloader, "
196
"defaulting to 0x%x\n", memsize);
197
}
198
}
199
}
200
201
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
*/
212
static __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
}
250
}
251
252
return orig_n - n;
253
}
254
255
/*
256
* 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
261
*/
262
static __init void register_ram(phys_addr_t p, phys_addr_t alias,
263
phys_addr_t n)
264
{
265
/*
266
* If some or all of this memory has an alias, break it into the
267
* aliased and non-aliased portion.
268
*/
269
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
}
285
#endif
286
}
287
288
/**
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
*/
298
static __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
335
void __init prom_meminit(void)
336
{
337
ptv_memsize = get_memsize();
338
register_address_space(ptv_memsize);
339
}
340
341
void __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
}
355
356