PageRenderTime 61ms CodeModel.GetById 14ms app.highlight 41ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/mips/powertv/memory.c

http://github.com/mirrors/linux
C | 353 lines | 203 code | 47 blank | 103 comment | 38 complexity | 9a57edf75ee1e2cc6c175c9e2d7577c9 MD5 | raw file
  1/*
  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/mach-powertv/asic.h>
 33#include <asm/mach-powertv/ioremap.h>
 34
 35#include "init.h"
 36
 37/* Memory constants */
 38#define KIBIBYTE(n)		((n) * 1024)	/* Number of kibibytes */
 39#define MEBIBYTE(n)		((n) * KIBIBYTE(1024)) /* Number of mebibytes */
 40#define DEFAULT_MEMSIZE		MEBIBYTE(128)	/* If no memsize provided */
 41
 42#define BLDR_SIZE	KIBIBYTE(256)		/* Memory reserved for bldr */
 43#define RV_SIZE		MEBIBYTE(4)		/* Size of reset vector */
 44
 45#define LOW_MEM_END	0x20000000		/* Highest low memory address */
 46#define BLDR_ALIAS	0x10000000		/* Bootloader address */
 47#define RV_PHYS		0x1fc00000		/* Reset vector address */
 48#define LOW_RAM_END	RV_PHYS			/* End of real RAM in low mem */
 49
 50/*
 51 * Very low-level conversion from processor physical address to device
 52 * DMA address for the first bank of memory.
 53 */
 54#define PHYS_TO_DMA(paddr)	((paddr) + (CONFIG_LOW_RAM_DMA - LOW_RAM_ALIAS))
 55
 56unsigned long ptv_memsize;
 57
 58/*
 59 * struct low_mem_reserved - Items in low memory that are reserved
 60 * @start:	Physical address of item
 61 * @size:	Size, in bytes, of this item
 62 * @is_aliased: True if this is RAM aliased from another location. If false,
 63 *		it is something other than aliased RAM and the RAM in the
 64 *		unaliased address is still visible outside of low memory.
 65 */
 66struct low_mem_reserved {
 67	phys_addr_t	start;
 68	phys_addr_t	size;
 69	bool		is_aliased;
 70};
 71
 72/*
 73 * Must be in ascending address order
 74 */
 75struct low_mem_reserved low_mem_reserved[] = {
 76	{BLDR_ALIAS, BLDR_SIZE, true},	/* Bootloader RAM */
 77	{RV_PHYS, RV_SIZE, false},	/* Reset vector */
 78};
 79
 80/*
 81 * struct mem_layout - layout of a piece of the system RAM
 82 * @phys:	Physical address of the start of this piece of RAM. This is the
 83 *		address at which both the processor and I/O devices see the
 84 *		RAM.
 85 * @alias:	Alias of this piece of memory in order to make it appear in
 86 *		the low memory part of the processor's address space. I/O
 87 *		devices don't see anything here.
 88 * @size:	Size, in bytes, of this piece of RAM
 89 */
 90struct mem_layout {
 91	phys_addr_t	phys;
 92	phys_addr_t	alias;
 93	phys_addr_t	size;
 94};
 95
 96/*
 97 * struct mem_layout_list - list descriptor for layouts of system RAM pieces
 98 * @family:	Specifies the family being described
 99 * @n:		Number of &struct mem_layout elements
100 * @layout:	Pointer to the list of &mem_layout structures
101 */
102struct mem_layout_list {
103	enum family_type	family;
104	size_t			n;
105	struct mem_layout	*layout;
106};
107
108static struct mem_layout f1500_layout[] = {
109	{0x20000000, 0x10000000, MEBIBYTE(256)},
110};
111
112static struct mem_layout f4500_layout[] = {
113	{0x40000000, 0x10000000, MEBIBYTE(256)},
114	{0x20000000, 0x20000000, MEBIBYTE(32)},
115};
116
117static struct mem_layout f8500_layout[] = {
118	{0x40000000, 0x10000000, MEBIBYTE(256)},
119	{0x20000000, 0x20000000, MEBIBYTE(32)},
120	{0x30000000, 0x30000000, MEBIBYTE(32)},
121};
122
123static struct mem_layout fx600_layout[] = {
124	{0x20000000, 0x10000000, MEBIBYTE(256)},
125	{0x60000000, 0x60000000, MEBIBYTE(128)},
126};
127
128static struct mem_layout_list layout_list[] = {
129	{FAMILY_1500, ARRAY_SIZE(f1500_layout), f1500_layout},
130	{FAMILY_1500VZE, ARRAY_SIZE(f1500_layout), f1500_layout},
131	{FAMILY_1500VZF, ARRAY_SIZE(f1500_layout), f1500_layout},
132	{FAMILY_4500, ARRAY_SIZE(f4500_layout), f4500_layout},
133	{FAMILY_8500, ARRAY_SIZE(f8500_layout), f8500_layout},
134	{FAMILY_8500RNG, ARRAY_SIZE(f8500_layout), f8500_layout},
135	{FAMILY_4600, ARRAY_SIZE(fx600_layout), fx600_layout},
136	{FAMILY_4600VZA, ARRAY_SIZE(fx600_layout), fx600_layout},
137	{FAMILY_8600, ARRAY_SIZE(fx600_layout), fx600_layout},
138	{FAMILY_8600VZB, ARRAY_SIZE(fx600_layout), fx600_layout},
139};
140
141/* If we can't determine the layout, use this */
142static struct mem_layout default_layout[] = {
143	{0x20000000, 0x10000000, MEBIBYTE(128)},
144};
145
146/**
147 * register_non_ram - register low memory not available for RAM usage
148 */
149static __init void register_non_ram(void)
150{
151	int i;
152
153	for (i = 0; i < ARRAY_SIZE(low_mem_reserved); i++)
154		add_memory_region(low_mem_reserved[i].start,
155			low_mem_reserved[i].size, BOOT_MEM_RESERVED);
156}
157
158/**
159 * get_memsize - get the size of memory as a single bank
160 */
161static phys_addr_t get_memsize(void)
162{
163	static char cmdline[COMMAND_LINE_SIZE] __initdata;
164	phys_addr_t memsize = 0;
165	char *memsize_str;
166	char *ptr;
167
168	/* Check the command line first for a memsize directive */
169	strcpy(cmdline, arcs_cmdline);
170	ptr = strstr(cmdline, "memsize=");
171	if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
172		ptr = strstr(ptr, " memsize=");
173
174	if (ptr) {
175		memsize = memparse(ptr + 8, &ptr);
176	} else {
177		/* otherwise look in the environment */
178		memsize_str = prom_getenv("memsize");
179
180		if (memsize_str != NULL) {
181			pr_info("prom memsize = %s\n", memsize_str);
182			memsize = simple_strtol(memsize_str, NULL, 0);
183		}
184
185		if (memsize == 0) {
186			if (_prom_memsize != 0) {
187				memsize = _prom_memsize;
188				pr_info("_prom_memsize = 0x%x\n", memsize);
189				/* add in memory that the bootloader doesn't
190				 * report */
191				memsize += BLDR_SIZE;
192			} else {
193				memsize = DEFAULT_MEMSIZE;
194				pr_info("Memsize not passed by bootloader, "
195					"defaulting to 0x%x\n", memsize);
196			}
197		}
198	}
199
200	return memsize;
201}
202
203/**
204 * register_low_ram - register an aliased section of RAM
205 * @p:		Alias address of memory
206 * @n:		Number of bytes in this section of memory
207 *
208 * Returns the number of bytes registered
209 *
210 */
211static __init phys_addr_t register_low_ram(phys_addr_t p, phys_addr_t n)
212{
213	phys_addr_t s;
214	int i;
215	phys_addr_t orig_n;
216
217	orig_n = n;
218
219	BUG_ON(p + n > RV_PHYS);
220
221	for (i = 0; n != 0 && i < ARRAY_SIZE(low_mem_reserved); i++) {
222		phys_addr_t start;
223		phys_addr_t size;
224
225		start = low_mem_reserved[i].start;
226		size = low_mem_reserved[i].size;
227
228		/* Handle memory before this low memory section */
229		if (p < start) {
230			phys_addr_t s;
231			s = min(n, start - p);
232			add_memory_region(p, s, BOOT_MEM_RAM);
233			p += s;
234			n -= s;
235		}
236
237		/* Handle the low memory section itself. If it's aliased,
238		 * we reduce the number of byes left, but if not, the RAM
239		 * is available elsewhere and we don't reduce the number of
240		 * bytes remaining. */
241		if (p == start) {
242			if (low_mem_reserved[i].is_aliased) {
243				s = min(n, size);
244				n -= s;
245				p += s;
246			} else
247				p += n;
248		}
249	}
250
251	return orig_n - n;
252}
253
254/*
255 * register_ram - register real RAM
256 * @p:	Address of memory as seen by devices
257 * @alias:	If the memory is seen at an additional address by the processor,
258 *		this will be the address, otherwise it is the same as @p.
259 * @n:		Number of bytes in this section of memory
260 */
261static __init void register_ram(phys_addr_t p, phys_addr_t alias,
262	phys_addr_t n)
263{
264	/*
265	 * If some or all of this memory has an alias, break it into the
266	 * aliased and non-aliased portion.
267	 */
268	if (p != alias) {
269		phys_addr_t alias_size;
270		phys_addr_t registered;
271
272		alias_size = min(n, LOW_RAM_END - alias);
273		registered = register_low_ram(alias, alias_size);
274		ioremap_add_map(alias, p, n);
275		n -= registered;
276		p += registered;
277	}
278
279#ifdef CONFIG_HIGHMEM
280	if (n != 0) {
281		add_memory_region(p, n, BOOT_MEM_RAM);
282		ioremap_add_map(p, p, n);
283	}
284#endif
285}
286
287/**
288 * register_address_space - register things in the address space
289 * @memsize:	Number of bytes of RAM installed
290 *
291 * Takes the given number of bytes of RAM and registers as many of the regions,
292 * or partial regions, as it can. So, the default configuration might have
293 * two regions with 256 MiB each. If the memsize passed in on the command line
294 * is 384 MiB, it will register the first region with 256 MiB and the second
295 * with 128 MiB.
296 */
297static __init void register_address_space(phys_addr_t memsize)
298{
299	int i;
300	phys_addr_t size;
301	size_t n;
302	struct mem_layout *layout;
303	enum family_type family;
304
305	/*
306	 * Register all of the things that aren't available to the kernel as
307	 * memory.
308	 */
309	register_non_ram();
310
311	/* Find the appropriate memory description */
312	family = platform_get_family();
313
314	for (i = 0; i < ARRAY_SIZE(layout_list); i++) {
315		if (layout_list[i].family == family)
316			break;
317	}
318
319	if (i == ARRAY_SIZE(layout_list)) {
320		n = ARRAY_SIZE(default_layout);
321		layout = default_layout;
322	} else {
323		n = layout_list[i].n;
324		layout = layout_list[i].layout;
325	}
326
327	for (i = 0; memsize != 0 && i < n; i++) {
328		size = min(memsize, layout[i].size);
329		register_ram(layout[i].phys, layout[i].alias, size);
330		memsize -= size;
331	}
332}
333
334void __init prom_meminit(void)
335{
336	ptv_memsize = get_memsize();
337	register_address_space(ptv_memsize);
338}
339
340void __init prom_free_prom_memory(void)
341{
342	unsigned long addr;
343	int i;
344
345	for (i = 0; i < boot_mem_map.nr_map; i++) {
346		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
347			continue;
348
349		addr = boot_mem_map.map[i].addr;
350		free_init_pages("prom memory",
351				addr, addr + boot_mem_map.map[i].size);
352	}
353}