Commit 1d4e3016 authored by Marc Singer's avatar Marc Singer Committed by Russell King

[ARM PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM

Patch from Marc Singer

[if's replaced by ifdef's.]

While the BLOB boot loader doesn't support it, there are two others,
UBOOT and Logic's LOLO, that will initialize the SDRAM controller such
that the memory appears as a contiguous region.  This layout to be
required for WinCE and, thus, is the default for these loaders.  The
memory organization had been optimized for discontiguous blocks.  Now,
it supports a default mode that is compatible with all of the
bootloaders as well as options to optimize for either contiguous or
discontiguous models.

Withing, there is also a slight change to the way that the DEBUG_LL
macros select the UART address.  Now it uses immediate constants
exclusively.
parent a2ecd1a8
README on the SDRAM Controller for the LH7a40X
==============================================
The standard configuration for the SDRAM controller generates a sparse
memory array. The precise layout is determined by the SDRAM chips. A
default kernel configuration assembles the discontiguous memory
regions into separate memory nodes via the NUMA (Non-Uniform Memory
Architecture) facilities. In this default configuration, the kernel
is forgiving about the precise layout. As long as it is given an
accurate picture of available memory by the bootloader the kernel will
execute correctly.
The SDRC supports a mode where some of the chip select lines are
swapped in order to make SDRAM look like a synchronous ROM. Setting
this bit means that the RAM will present as a contiguous array. Some
programmers prefer this to the discontiguous layout. Be aware that
may be a penalty for this feature where some some configurations of
memory are significantly reduced; i.e. 64MiB of RAM appears as only 32
MiB.
There are a couple of configuration options to override the default
behavior. When the SROMLL bit is set and memory appears as a
contiguous array, there is no reason to support NUMA.
CONFIG_LH7A40X_CONTIGMEM disables NUMA support. When physical memory
is discontiguous, the memory tables are organized such that there are
two banks per nodes with a small gap between them. This layout wastes
some kernel memory for page tables representing non-existent memory.
CONFIG_LH7A40X_ONE_BANK_PER_NODE optimizes the node tables such that
there are no gaps. These options control the low level organization
of the memory management tables in ways that may prevent the kernel
from booting or may cause the kernel to allocated excessively large
page tables. Be warned. Only change these options if you know what
you are doing. The default behavior is a reasonable compromise that
will suit all users.
--
A typical 32MiB system with the default configuration options will
find physical memory managed as follows.
node 0: 0xc0000000 4MiB
0xc1000000 4MiB
node 1: 0xc4000000 4MiB
0xc5000000 4MiB
node 2: 0xc8000000 4MiB
0xc9000000 4MiB
node 3: 0xcc000000 4MiB
0xcd000000 4MiB
Setting CONFIG_LH7A40X_ONE_BANK_PER_NODE will put each bank into a
separate node.
...@@ -246,10 +246,10 @@ menu "General setup" ...@@ -246,10 +246,10 @@ menu "General setup"
# Select various configuration options depending on the machine type # Select various configuration options depending on the machine type
config DISCONTIGMEM config DISCONTIGMEM
bool bool
depends on ARCH_EDB7211 || ARCH_SA1100 || ARCH_LH7A40X depends on ARCH_EDB7211 || ARCH_SA1100 || (ARCH_LH7A40X && !LH7A40X_SROMLL)
default y default y
help help
Say Y to upport efficient handling of discontiguous physical memory, Say Y to support efficient handling of discontiguous physical memory,
for architectures which are either NUMA (Non-Uniform Memory Access) for architectures which are either NUMA (Non-Uniform Memory Access)
or have huge holes in the physical address space for other reasons. or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more. See <file:Documentation/vm/numa> for more.
......
...@@ -591,7 +591,8 @@ ...@@ -591,7 +591,8 @@
.macro addruart,rx .macro addruart,rx
mrc p15, 0, \rx, c1, c0 mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled? tst \rx, #1 @ MMU enabled?
ldr \rx, =0x80000700 @ physical base address mov \rx, #0x00000700 @ offset from base
orreq \rx, \rx, #0x80000000 @ physical base
orrne \rx, \rx, #0xf8000000 @ virtual base orrne \rx, \rx, #0xf8000000 @ virtual base
.endm .endm
......
...@@ -34,6 +34,37 @@ config ARCH_LH7A400 ...@@ -34,6 +34,37 @@ config ARCH_LH7A400
config ARCH_LH7A404 config ARCH_LH7A404
bool bool
config LH7A40X_CONTIGMEM
bool "Disable NUMA Support"
depends on ARCH_LH7A40X
help
Say Y here if your bootloader sets the SROMLL bit(s) in
the SDRAM controller, organizing memory as a contiguous
array. This option will disable CONFIG_DISCONTIGMEM and
force the kernel to manage all memory in one node.
Setting this option incorrectly may prevent the kernel from
booting. It is OK to leave it N.
For more information, consult
<file:Documentation/arm/Sharp-LH/SDRAM>.
config LH7A40X_ONE_BANK_PER_NODE
bool "Optimize NUMA Node Tables for Size"
depends on ARCH_LH7A40X && !LH7A40X_CONTIGMEM
help
Say Y here to produce compact memory node tables. By
default pairs of adjacent physical RAM banks are managed
together in a single node, incurring some wasted overhead
in the node tables, however also maintaining compatibility
with systems where physical memory is truly contiguous.
Setting this option incorrectly may prevent the kernel from
booting. It is OK to leave it N.
For more information, consult
<file:Documentation/arm/Sharp-LH/SDRAM>.
endmenu endmenu
endif endif
...@@ -6,14 +6,14 @@ ...@@ -6,14 +6,14 @@
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation. * version 2 as published by the Free Software Foundation.
* *
*
* Refer to <file:Documentation/arm/Sharp-LH/SDRAM> for more information.
*
*/ */
#ifndef __ASM_ARCH_MEMORY_H #ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H
#define BANKS_PER_NODE 1 /* Define as either 1 or 2 */
/* /*
* Physical DRAM offset. * Physical DRAM offset.
*/ */
...@@ -30,57 +30,30 @@ ...@@ -30,57 +30,30 @@
#define __bus_to_virt(x) __phys_to_virt(x) #define __bus_to_virt(x) __phys_to_virt(x)
#ifdef CONFIG_DISCONTIGMEM #ifdef CONFIG_DISCONTIGMEM
/*
* Because of the wide memory address space between physical RAM
* banks, it's convenient to use Linux's NUMA support to represent our
* memory map. Assuming all memory nodes have equal access
* characteristics, we then have a generic discontiguous memory setup.
*
* Of course, all this isn't mandatory for implementations with only
* one used memory bank. For those, simply undefine
* CONFIG_DISCONTIGMEM. However, keep in mind that a featurefull
* system will need more than 4MiB of RAM.
*
* The contiguous memory blocks are small enough that it pays to
* aggregate two banks into one node. Setting BANKS_PER_NODE to 2
* puts pairs of banks into a node.
*
* A typical layout would start like this:
*
* node 0: 0xc0000000
* 0xc1000000
* node 1: 0xc4000000
* 0xc5000000
* node 2: 0xc8000000
* 0xc9000000
*
* The proximity of the pairs of blocks makes it feasible to combine them.
*
*/
/* /*
* Given a kernel address, find the home node of the underlying memory. * Given a kernel address, find the home node of the underlying memory.
*/ */
#if BANKS_PER_NODE==1 # ifdef CONFIG_LH7A40X_ONE_BANK_PER_NODE
#define KVADDR_TO_NID(addr) \ # define KVADDR_TO_NID(addr) \
( ((((unsigned long) (addr) - PAGE_OFFSET) >> 24) & 1)\ ( ((((unsigned long) (addr) - PAGE_OFFSET) >> 24) & 1)\
| ((((unsigned long) (addr) - PAGE_OFFSET) >> 25) & ~1)) | ((((unsigned long) (addr) - PAGE_OFFSET) >> 25) & ~1))
#else /* 2 banks per node */ # else /* 2 banks per node */
#define KVADDR_TO_NID(addr) \ # define KVADDR_TO_NID(addr) \
((unsigned long) (addr) - PAGE_OFFSET) >> 26) (((unsigned long) (addr) - PAGE_OFFSET) >> 26)
#endif # endif
/* /*
* Given a page frame number, convert it to a node id. * Given a page frame number, convert it to a node id.
*/ */
#if BANKS_PER_NODE==1 # ifdef CONFIG_LH7A40X_ONE_BANK_PER_NODE
#define PFN_TO_NID(pfn) \ # define PFN_TO_NID(pfn) \
(((((pfn) - PHYS_PFN_OFFSET) >> (24 - PAGE_SHIFT)) & 1)\ (((((pfn) - PHYS_PFN_OFFSET) >> (24 - PAGE_SHIFT)) & 1)\
| ((((pfn) - PHYS_PFN_OFFSET) >> (25 - PAGE_SHIFT)) & ~1)) | ((((pfn) - PHYS_PFN_OFFSET) >> (25 - PAGE_SHIFT)) & ~1))
#else /* 2 banks per node */ # else /* 2 banks per node */
#define PFN_TO_NID(addr) \ # define PFN_TO_NID(pfn) \
(((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT)) (((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT))
#endif #endif
...@@ -88,13 +61,13 @@ ...@@ -88,13 +61,13 @@
* Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
* and return the mem_map of that node. * and return the mem_map of that node.
*/ */
#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr)) # define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
/* /*
* Given a page frame number, find the owning node of the memory * Given a page frame number, find the owning node of the memory
* and return the mem_map of that node. * and return the mem_map of that node.
*/ */
#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn)) # define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn))
/* /*
* Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
...@@ -102,17 +75,17 @@ ...@@ -102,17 +75,17 @@
* node's mem_map. * node's mem_map.
*/ */
#if BANKS_PER_NODE==1 # ifdef CONFIG_LH7A40X_ONE_BANK_PER_NODE
#define LOCAL_MAP_NR(addr) \ # define LOCAL_MAP_NR(addr) \
(((unsigned long)(addr) & 0x003fffff) >> PAGE_SHIFT) (((unsigned long)(addr) & 0x003fffff) >> PAGE_SHIFT)
#else /* 2 banks per node */ # else /* 2 banks per node */
#define LOCAL_MAP_NR(addr) \ # define LOCAL_MAP_NR(addr) \
(((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT) (((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT)
#endif # endif
#else #else
#define PFN_TO_NID(addr) (0) # define PFN_TO_NID(addr) (0)
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment