summaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/consistent.c29
-rw-r--r--arch/arm/mm/fault-common.c2
-rw-r--r--arch/arm/mm/init.c295
-rw-r--r--arch/arm/mm/map.h6
-rw-r--r--arch/arm/mm/mm-armo.c4
-rw-r--r--arch/arm/mm/mm-armv.c22
-rw-r--r--arch/arm/mm/mm-ebsa110.c3
-rw-r--r--arch/arm/mm/mm-rpc.c2
-rw-r--r--arch/arm/mm/mm-sa1100.c162
-rw-r--r--arch/arm/mm/proc-sa110.S59
10 files changed, 421 insertions, 163 deletions
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 76d1a5c74..310107678 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -29,20 +29,29 @@ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
if (in_interrupt())
BUG();
+ size = PAGE_ALIGN(size);
order = get_order(size);
page = __get_free_pages(gfp, order);
if (!page)
goto no_page;
- memset((void *)page, 0, PAGE_SIZE << order);
- clean_cache_area(page, PAGE_SIZE << order);
+ memset((void *)page, 0, size);
+ clean_cache_area(page, size);
*dma_handle = virt_to_bus((void *)page);
- ret = __ioremap(virt_to_phys((void *)page), PAGE_SIZE << order, 0);
- if (ret)
+ ret = __ioremap(virt_to_phys((void *)page), size, 0);
+ if (ret) {
+ /* free wasted pages */
+ unsigned long end = page + (PAGE_SIZE << order);
+ page += size;
+ while (page < end) {
+ free_page(page);
+ page += PAGE_SIZE;
+ }
return ret;
+ }
free_pages(page, order);
no_page:
@@ -81,18 +90,18 @@ void consistent_free(void *vaddr)
/*
* make an area consistent.
*/
-void consistent_sync(void *vaddr, size_t size, int rw)
+void consistent_sync(void *vaddr, size_t size, int direction)
{
- switch (rw) {
- case 0:
+ switch (direction) {
+ case PCI_DMA_NONE:
BUG();
- case 1: /* invalidate only */
+ case PCI_DMA_FROMDEVICE: /* invalidate only */
dma_cache_inv(vaddr, size);
break;
- case 2: /* writeback only */
+ case PCI_DMA_TODEVICE: /* writeback only */
dma_cache_wback(vaddr, size);
break;
- case 3: /* writeback and invalidate */
+ case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */
dma_cache_wback_inv(vaddr, size);
break;
}
diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
index c34c37203..14cf5a925 100644
--- a/arch/arm/mm/fault-common.c
+++ b/arch/arm/mm/fault-common.c
@@ -123,7 +123,7 @@ good_area:
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
- if (!handle_mm_fault(tsk, vma, addr & PAGE_MASK, DO_COW(mode)))
+ if (!handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(mode)))
goto do_sigbus;
up(&mm->mmap_sem);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index e7b8c8bb9..61feb6a55 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -1,9 +1,8 @@
/*
* linux/arch/arm/mm/init.c
*
- * Copyright (C) 1995-1999 Russell King
+ * Copyright (C) 1995-2000 Russell King
*/
-
#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
@@ -32,9 +31,22 @@
#include "map.h"
+#ifdef CONFIG_CPU_32
+#define TABLE_OFFSET (PTRS_PER_PTE)
+#else
+#define TABLE_OFFSET 0
+#endif
+#define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *))
+
static unsigned long totalram_pages;
-struct meminfo meminfo;
pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern int _stext, _text, _etext, _edata, _end;
+
+/*
+ * The sole use of this is to pass memory configuration
+ * data from paging_init to mem_init.
+ */
+static struct meminfo __initdata meminfo;
/*
* empty_bad_page is the page that is used for page faults when
@@ -119,33 +131,36 @@ int do_check_pgt_cache(int low, int high)
void show_mem(void)
{
int free = 0, total = 0, reserved = 0;
- int shared = 0, cached = 0;
- struct page *page, *end;
+ int shared = 0, cached = 0, node;
printk("Mem-info:\n");
show_free_areas();
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
- page = mem_map;
- end = mem_map + max_mapnr;
+ for (node = 0; node < numnodes; node++) {
+ struct page *page, *end;
- do {
- if (PageSkip(page)) {
- page = page->next_hash;
- if (page == NULL)
- break;
- }
- total++;
- if (PageReserved(page))
- reserved++;
- else if (PageSwapCache(page))
- cached++;
- else if (!page_count(page))
- free++;
- else
- shared += atomic_read(&page->count) - 1;
- page++;
- } while (page < end);
+ page = NODE_MEM_MAP(node);
+ end = page + NODE_DATA(node)->node_size;
+
+ do {
+ if (PageSkip(page)) {
+ page = page->next_hash;
+ if (page == NULL)
+ break;
+ }
+ total++;
+ if (PageReserved(page))
+ reserved++;
+ else if (PageSwapCache(page))
+ cached++;
+ else if (!page_count(page))
+ free++;
+ else
+ shared += atomic_read(&page->count) - 1;
+ page++;
+ } while (page < end);
+ }
printk("%d pages of RAM\n", total);
printk("%d free pages\n", free);
@@ -158,24 +173,173 @@ void show_mem(void)
show_buffers();
}
+#define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x))
+
+#define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT)
+#define V_PFN_UP(x) O_PFN_UP(__pa(x))
+
+#define PFN_SIZE(x) ((x) >> PAGE_SHIFT)
+#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
+ (((unsigned long)(s)) & PAGE_MASK))
+
+static unsigned int __init
+find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages)
+{
+ unsigned int start_pfn, bank, bootmap_pfn;
+
+ start_pfn = V_PFN_UP(&_end);
+ bootmap_pfn = 0;
+
+ /*
+ * FIXME: We really want to avoid allocating the bootmap
+ * over the top of the initrd.
+ */
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start) {
+ if (__pa(initrd_end) > mi->end) {
+ printk ("initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx) - disabling initrd\n",
+ __pa(initrd_end), mi->end);
+ initrd_start = 0;
+ initrd_end = 0;
+ }
+ }
+#endif
+
+ for (bank = 0; bank < mi->nr_banks; bank ++) {
+ unsigned int start, end;
+
+ if (mi->bank[bank].size == 0)
+ continue;
+
+ start = O_PFN_UP(mi->bank[bank].start);
+ end = O_PFN_DOWN(mi->bank[bank].size +
+ mi->bank[bank].start);
+
+ if (end < start_pfn)
+ continue;
+
+ if (start < start_pfn)
+ start = start_pfn;
+
+ if (end <= start)
+ continue;
+
+ if (end - start >= bootmap_pages) {
+ bootmap_pfn = start;
+ break;
+ }
+ }
+
+ if (bootmap_pfn == 0)
+ BUG();
+
+ return bootmap_pfn;
+}
+
+/*
+ * Initialise one node of the bootmem allocator. For now, we
+ * only initialise node 0. Notice that we have a bootmem
+ * bitmap per node.
+ */
+static void __init setup_bootmem_node(int node, struct meminfo *mi)
+{
+ unsigned int end_pfn, start_pfn, bootmap_pages, bootmap_pfn;
+ unsigned int i;
+
+ if (node != 0) /* only initialise node 0 for now */
+ return;
+
+ start_pfn = O_PFN_UP(PHYS_OFFSET);
+ end_pfn = O_PFN_DOWN(mi->end);
+ bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
+ bootmap_pfn = find_bootmap_pfn(mi, bootmap_pages);
+
+ /*
+ * Initialise the boot-time allocator
+ */
+ init_bootmem_node(node, bootmap_pfn, start_pfn, end_pfn);
+
+ /*
+ * Register all available RAM with the bootmem allocator.
+ */
+ for (i = 0; i < mi->nr_banks; i++)
+ if (mi->bank[i].size)
+ free_bootmem_node(node, mi->bank[i].start,
+ PFN_SIZE(mi->bank[i].size) << PAGE_SHIFT);
+
+ reserve_bootmem_node(node, bootmap_pfn << PAGE_SHIFT,
+ bootmap_pages << PAGE_SHIFT);
+}
+
+/*
+ * Initialise the bootmem allocator.
+ */
+void __init bootmem_init(struct meminfo *mi)
+{
+ unsigned int i, node;
+
+ /*
+ * Calculate the physical address of the top of memory.
+ * Note that there are no guarantees assumed about the
+ * ordering of the bank information.
+ */
+ mi->end = 0;
+ for (i = 0; i < mi->nr_banks; i++) {
+ unsigned long end;
+
+ if (mi->bank[i].size != 0) {
+ end = mi->bank[i].start + mi->bank[i].size;
+ if (mi->end < end)
+ mi->end = end;
+ }
+ }
+
+ max_low_pfn = O_PFN_DOWN(mi->end - PHYS_OFFSET);
+
+ /*
+ * Setup each node
+ */
+ for (node = 0; node < numnodes; node++)
+ setup_bootmem_node(node, mi);
+
+ /*
+ * Register the kernel text and data with bootmem.
+ * Note that this can only be in node 0.
+ */
+ reserve_bootmem_node(0, V_PFN_DOWN(&_stext) << PAGE_SHIFT,
+ PFN_RANGE(&_stext, &_end) << PAGE_SHIFT);
+
+#ifdef CONFIG_CPU_32
+ /*
+ * Reserve the page tables. These are already in use,
+ * and can only be in node 0.
+ */
+ reserve_bootmem_node(0, V_PFN_DOWN(swapper_pg_dir) << PAGE_SHIFT,
+ PFN_SIZE(PTRS_PER_PGD * sizeof(void *)) << PAGE_SHIFT);
+#endif
+#ifdef CONFIG_BLK_DEV_INITRD
+ /*
+ * This may be in any bank. Currently, we assume that
+ * it is in bank 0.
+ */
+ if (initrd_start)
+ reserve_bootmem_node(0, V_PFN_DOWN(initrd_start) << PAGE_SHIFT,
+ PFN_RANGE(initrd_start, initrd_end) << PAGE_SHIFT);
+#endif
+}
+
/*
* paging_init() sets up the page tables...
*/
void __init paging_init(struct meminfo *mi)
{
void *zero_page, *bad_page, *bad_table;
- unsigned long zone_size[MAX_NR_ZONES];
- int i;
+ int node;
memcpy(&meminfo, mi, sizeof(meminfo));
-#ifdef CONFIG_CPU_32
-#define TABLE_OFFSET (PTRS_PER_PTE)
-#else
-#define TABLE_OFFSET 0
-#endif
-#define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *))
-
/*
* allocate what we need for the bad pages
*/
@@ -186,31 +350,42 @@ void __init paging_init(struct meminfo *mi)
/*
* initialise the page tables
*/
- pagetable_init();
+ pagetable_init(mi);
flush_tlb_all();
/*
- * Initialise the zones and mem_map
+ * initialise the zones within each node
*/
- for (i = 0; i < MAX_NR_ZONES; i++)
- zone_size[i] = 0;
+ for (node = 0; node < numnodes; node++) {
+ unsigned long zone_size[MAX_NR_ZONES];
+ unsigned long zhole_size[MAX_NR_ZONES];
+ struct bootmem_data *bdata;
+ pg_data_t *pgdat;
+ int i;
- /*
- * Calculate the size of the zones. On ARM, we don't have
- * any problems with DMA or highmem, so all memory is
- * allocated to the DMA zone.
- */
- for (i = 0; i < mi->nr_banks; i++) {
- if (mi->bank[i].size) {
- unsigned int end;
-
- end = (mi->bank[i].start - PHYS_OFFSET +
- mi->bank[i].size) >> PAGE_SHIFT;
- if (zone_size[0] < end)
- zone_size[0] = end;
+ /*
+ * Initialise the zone size information.
+ */
+ for (i = 0; i < MAX_NR_ZONES; i++) {
+ zone_size[i] = 0;
+ zhole_size[i] = 0;
}
+
+ pgdat = NODE_DATA(node);
+ bdata = pgdat->bdata;
+
+ /*
+ * The size of this node has already been determined.
+ * If we need to do anything fancy with the allocation
+ * of this memory to the zones, now is the time to do
+ * it. For now, we don't touch zhole_size.
+ */
+ zone_size[0] = bdata->node_low_pfn -
+ (bdata->node_boot_start >> PAGE_SHIFT);
+
+ free_area_init_node(node, pgdat, zone_size,
+ bdata->node_boot_start, zhole_size);
}
- free_area_init(zone_size);
/*
* finish off the bad pages once
@@ -256,32 +431,33 @@ static inline void free_unused_mem_map(void)
*/
void __init mem_init(void)
{
- extern char __init_begin, __init_end, _text, _etext, _end;
+ extern char __init_begin, __init_end;
unsigned int codepages, datapages, initpages;
- int i;
+ int i, node;
codepages = &_etext - &_text;
datapages = &_end - &_etext;
initpages = &__init_end - &__init_begin;
- max_mapnr = max_low_pfn;
- high_memory = (void *)__va(PHYS_OFFSET + max_low_pfn * PAGE_SIZE);
+ high_memory = (void *)__va(meminfo.end);
+ max_mapnr = MAP_NR(high_memory);
/*
* We may have non-contiguous memory. Setup the PageSkip stuff,
* and mark the areas of mem_map which can be freed
*/
if (meminfo.nr_banks != 1)
- create_memmap_holes();
+ create_memmap_holes(&meminfo);
/* this will put all unused low memory onto the freelists */
- totalram_pages += free_all_bootmem();
+ for (node = 0; node < numnodes; node++)
+ totalram_pages += free_all_bootmem_node(node);
/*
* Since our memory may not be contiguous, calculate the
* real number of pages we have in this system
*/
- printk("Memory:");
+ printk(KERN_INFO "Memory:");
num_physpages = 0;
for (i = 0; i < meminfo.nr_banks; i++) {
@@ -290,7 +466,8 @@ void __init mem_init(void)
}
printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
- printk("Memory: %luKB available (%dK code, %dK data, %dK init)\n",
+ printk(KERN_NOTICE "Memory: %luKB available (%dK code, "
+ "%dK data, %dK init)\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
codepages >> 10, datapages >> 10, initpages >> 10);
diff --git a/arch/arm/mm/map.h b/arch/arm/mm/map.h
index b596c6479..1d071748d 100644
--- a/arch/arm/mm/map.h
+++ b/arch/arm/mm/map.h
@@ -19,7 +19,7 @@ struct map_desc {
extern struct map_desc io_desc[];
extern unsigned int io_desc_size;
-extern void zonesize_init(unsigned int *);
-extern void create_memmap_holes(void);
-extern void pagetable_init(void);
+struct meminfo;
+extern void create_memmap_holes(struct meminfo *);
+extern void pagetable_init(struct meminfo *);
diff --git a/arch/arm/mm/mm-armo.c b/arch/arm/mm/mm-armo.c
index f4bf7cad5..dc1647a2d 100644
--- a/arch/arm/mm/mm-armo.c
+++ b/arch/arm/mm/mm-armo.c
@@ -147,7 +147,7 @@ void setup_mm_for_reboot(char mode)
* some more work to get it to fit into our separate processor and
* architecture structure.
*/
-void __init pagetable_init(void)
+void __init pagetable_init(struct meminfo *mi)
{
pte_t *pte;
int i;
@@ -165,6 +165,6 @@ void __init pagetable_init(void)
/*
* We never have holes in the memmap
*/
-void __init create_memmap_holes(void)
+void __init create_memmap_holes(struct meminfo *mi)
{
}
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 5d46369eb..f58bc66f5 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -310,7 +310,7 @@ void setup_mm_for_reboot(char mode)
}
}
-void __init pagetable_init(void)
+void __init pagetable_init(struct meminfo *mi)
{
struct map_desc *init_maps, *p, *q;
unsigned long address = 0;
@@ -335,13 +335,13 @@ void __init pagetable_init(void)
p ++;
- for (i = 0; i < meminfo.nr_banks; i++) {
- if (meminfo.bank[i].size == 0)
+ for (i = 0; i < mi->nr_banks; i++) {
+ if (mi->bank[i].size == 0)
continue;
- p->physical = meminfo.bank[i].start;
+ p->physical = mi->bank[i].start;
p->virtual = __phys_to_virt(p->physical);
- p->length = meminfo.bank[i].size;
+ p->length = mi->bank[i].size;
p->domain = DOMAIN_KERNEL;
p->prot_read = 0;
p->prot_write = 1;
@@ -414,7 +414,7 @@ void __init pagetable_init(void)
* The mem_map array can get very big. Mark the end of the valid mem_map
* banks with PG_skip, and setup the address validity bitmap.
*/
-void __init create_memmap_holes(void)
+void __init create_memmap_holes(struct meminfo *mi)
{
unsigned int start_pfn, end_pfn = -1;
struct page *pg = NULL;
@@ -423,11 +423,11 @@ void __init create_memmap_holes(void)
#define PFN(x) (((x) - PHYS_OFFSET) >> PAGE_SHIFT)
#define free_bootmem(s,sz) free_bootmem(((s)<<PAGE_SHIFT)+PHYS_OFFSET, (sz)<<PAGE_SHIFT)
- for (i = 0; i < meminfo.nr_banks; i++) {
- if (meminfo.bank[i].size == 0)
+ for (i = 0; i < mi->nr_banks; i++) {
+ if (mi->bank[i].size == 0)
continue;
- start_pfn = PFN(meminfo.bank[i].start);
+ start_pfn = PFN(mi->bank[i].start);
/*
* subtle here - if we have a full bank, then
@@ -447,9 +447,9 @@ void __init create_memmap_holes(void)
pg = NULL;
}
- end_pfn = PFN(meminfo.bank[i].start + meminfo.bank[i].size);
+ end_pfn = PFN(mi->bank[i].start + mi->bank[i].size);
- if (end_pfn != PFN(meminfo.end))
+ if (end_pfn != PFN(mi->end))
pg = mem_map + end_pfn;
}
diff --git a/arch/arm/mm/mm-ebsa110.c b/arch/arm/mm/mm-ebsa110.c
index a1172b1f1..f16c93793 100644
--- a/arch/arm/mm/mm-ebsa110.c
+++ b/arch/arm/mm/mm-ebsa110.c
@@ -8,6 +8,7 @@
#include <linux/mm.h>
#include <linux/init.h>
+#include <asm/hardware.h>
#include <asm/pgtable.h>
#include <asm/page.h>
@@ -15,7 +16,7 @@
#define SIZE(x) (sizeof(x) / sizeof(x[0]))
-const struct map_desc io_desc[] __initdata = {
+struct map_desc io_desc[] __initdata = {
{ IO_BASE - PGDIR_SIZE, 0xc0000000, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
{ IO_BASE , IO_START , IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 }
};
diff --git a/arch/arm/mm/mm-rpc.c b/arch/arm/mm/mm-rpc.c
index 0490cbdd0..494a61988 100644
--- a/arch/arm/mm/mm-rpc.c
+++ b/arch/arm/mm/mm-rpc.c
@@ -18,7 +18,7 @@
struct map_desc io_desc[] __initdata = {
/* VRAM */
- { SCREEN2_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1, 0, 0 },
+ { SCREEN_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1, 0, 0 },
/* IO space */
{ IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
/* EASI space */
diff --git a/arch/arm/mm/mm-sa1100.c b/arch/arm/mm/mm-sa1100.c
index 1cb1a3b58..5674dbe37 100644
--- a/arch/arm/mm/mm-sa1100.c
+++ b/arch/arm/mm/mm-sa1100.c
@@ -9,6 +9,10 @@
* 1999/12/04 Nicolas Pitre <nico@cam.org>
* Converted memory definition for struct meminfo initialisations.
* Memory is listed physically now.
+ *
+ * 2000/04/07 Nicolas Pitre <nico@cam.org>
+ * Reworked for real-time selection of memory definitions
+ *
*/
#include <linux/config.h>
@@ -23,79 +27,109 @@
#define SIZE(x) (sizeof(x) / sizeof(x[0]))
-/*
- * These are the RAM memory mappings for SA1100 implementations.
- * Note that LART is a special case - it doesn't use physical
- * address line A23 on the DRAM, so we effectively have 4 * 8MB
- * in two banks.
- */
-struct mem_desc {
- unsigned long phys_start;
- unsigned long length;
-} mem_desc[] __initdata = {
-#if defined(CONFIG_SA1100_BRUTUS)
- { 0xc0000000, 0x00400000 }, /* 4MB */
- { 0xc8000000, 0x00400000 }, /* 4MB */
- { 0xd0000000, 0x00400000 }, /* 4MB */
- { 0xd8000000, 0x00400000 } /* 4MB */
-#elif defined(CONFIG_SA1100_EMPEG)
- { 0xc0000000, 0x00400000 }, /* 4MB */
- { 0xc8000000, 0x00400000 } /* 4MB */
-#elif defined(CONFIG_SA1100_LART)
- { 0xc0000000, 0x00800000 }, /* 8MB */
- { 0xc1000000, 0x00800000 }, /* 8MB */
- { 0xc8000000, 0x00800000 }, /* 8MB */
- { 0xc9000000, 0x00800000 } /* 8MB */
-#elif defined(CONFIG_SA1100_VICTOR)
- { 0xc0000000, 0x00400000 } /* 4MB */
-#elif defined(CONFIG_SA1100_THINCLIENT)
- { 0xc0000000, 0x01000000 } /* 16MB */
-#elif defined(CONFIG_SA1100_TIFON)
- { 0xc0000000, 0x01000000 }, /* 16MB */
- { 0xc8000000, 0x01000000 } /* 16MB */
-#else
-#error missing memory configuration
+#define SA1100_STD_IO_MAPPING \
+ /* virtual physical length domain r w c b */ \
+ { 0xe0000000, 0x20000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */ \
+ { 0xe4000000, 0x30000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */ \
+ { 0xe8000000, 0x28000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 attr */ \
+ { 0xec000000, 0x38000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 attr */ \
+ { 0xf0000000, 0x2c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 mem */ \
+ { 0xf4000000, 0x3c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 mem */ \
+ { 0xf8000000, 0x80000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */ \
+ { 0xfa000000, 0x90000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */ \
+ { 0xfc000000, 0xa0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */ \
+ { 0xfe000000, 0xb0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 } /* LCD + DMA */
+
+
+static struct map_desc assabet_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_ASSABET
+ { 0xd0000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xdc000000, 0x12000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
+ SA1100_STD_IO_MAPPING
#endif
};
-unsigned int __initdata mem_desc_size = SIZE(mem_desc);
+static struct map_desc bitsy_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_BITSY
+ { 0xd0000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
+ SA1100_STD_IO_MAPPING
+#endif
+};
+static struct map_desc empeg_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_EMPEG
+ { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
+ SA1100_STD_IO_MAPPING
+#endif
+};
-struct map_desc io_desc[] __initdata = {
- /* virtual physical length domain r w c b */
-#if defined(CONFIG_SA1100_VICTOR)
- { 0xd0000000, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
-#elif defined(CONFIG_SA1100_EMPEG)
- { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
-#elif defined(CONFIG_SA1100_THINCLIENT)
+static struct map_desc thinclient_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_THINCLIENT
#if 1
- /* ThinClient: only one of those... */
-// { 0xd0000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 when JP1 2-4 */
- { 0xd0000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 when JP1 3-4 */
+ /* ThinClient: only one of those... */
+// { 0xd0000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 when JP1 2-4 */
+ { 0xd0000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 when JP1 3-4 */
#else
- /* GraphicsClient: */
- { 0xd0000000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
- { 0xd0800000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 3 */
+ /* GraphicsClient: */
+ { 0xd0000000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
+ { 0xd0800000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 3 */
+#endif
+ { 0xdc000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
+ SA1100_STD_IO_MAPPING
#endif
-#elif defined(CONFIG_SA1100_TIFON)
- { 0xd0000000, 0x00000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
- { 0xd0800000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 2 */
+};
+
+static struct map_desc tifon_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_TIFON
+ { 0xd0000000, 0x00000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
+ { 0xd0800000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 2 */
+ SA1100_STD_IO_MAPPING
#endif
-#if defined( CONFIG_SA1101 )
- { 0xdc000000, SA1101_BASE, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA1101 */
-#elif defined( CONFIG_SA1100_THINCLIENT )
- { 0xdc000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
+};
+
+static struct map_desc victor_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_VICTOR
+ { 0xd0000000, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
+ SA1100_STD_IO_MAPPING
#endif
- { 0xe0000000, 0x20000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */
- { 0xe4000000, 0x30000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */
- { 0xe8000000, 0x28000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 attr */
- { 0xec000000, 0x38000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 attr */
- { 0xf0000000, 0x2c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 mem */
- { 0xf4000000, 0x3c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 mem */
- { 0xf8000000, 0x80000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */
- { 0xfa000000, 0x90000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */
- { 0xfc000000, 0xa0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */
- { 0xfe000000, 0xb0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 } /* LCD + DMA */
};
-unsigned int __initdata io_desc_size = SIZE(io_desc);
+
+static struct map_desc default_io_desc[] __initdata = {
+ SA1100_STD_IO_MAPPING
+};
+
+
+/*
+ * Here it would be wiser to simply assign a pointer to the appropriate
+ * list, but io_desc is already declared as an array in "map.h".
+ */
+struct map_desc io_desc[20] __initdata = { { 0, }, };
+unsigned int io_desc_size;
+
+void __init select_sa1100_io_desc(void)
+{
+ if( machine_is_assabet() ) {
+ memcpy( io_desc, assabet_io_desc, sizeof(assabet_io_desc) );
+ io_desc_size = SIZE(assabet_io_desc);
+ } else if( machine_is_bitsy() ) {
+ memcpy( io_desc, bitsy_io_desc, sizeof(bitsy_io_desc) );
+ io_desc_size = SIZE(bitsy_io_desc);
+ } else if( machine_is_empeg() ) {
+ memcpy( io_desc, empeg_io_desc, sizeof(empeg_io_desc) );
+ io_desc_size = SIZE(empeg_io_desc);
+ } else if( machine_is_thinclient() ) {
+ memcpy( io_desc, thinclient_io_desc, sizeof(thinclient_io_desc) );
+ io_desc_size = SIZE(thinclient_io_desc);
+ } else if( machine_is_tifon() ) {
+ memcpy( io_desc, tifon_io_desc, sizeof(tifon_io_desc) );
+ io_desc_size = SIZE(tifon_io_desc);
+ } else if( machine_is_victor() ) {
+ memcpy( io_desc, victor_io_desc, sizeof(victor_io_desc) );
+ io_desc_size = SIZE(victor_io_desc);
+ } else {
+ memcpy( io_desc, default_io_desc, sizeof(default_io_desc) );
+ io_desc_size = SIZE(default_io_desc);
+ }
+}
+
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 13c1f2773..9ae5fb9d6 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -4,7 +4,9 @@
* (C) 1997-2000 Russell King
*
* These are the low level assembler for performing cache and TLB
- * functions on the StrongARM-110 and StrongARM-1100
+ * functions on the StrongARM-110, StrongARM-1100 and StrongARM-1110.
+ *
+ * Note that SA1100 and SA1110 share everything but their name and CPU ID.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
@@ -420,13 +422,12 @@ ENTRY(cpu_sa1100_proc_init)
mov pc, lr
ENTRY(cpu_sa110_proc_fin)
-ENTRY(cpu_sa1100_proc_fin)
stmfd sp!, {r1, lr}
mrs r0, cpsr
orr r0, r0, #F_BIT | I_BIT
msr cpsr, r0
bl cpu_sa110_flush_cache_all @ clean caches
- mov r0, #0
+1: mov r0, #0
mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x1000 @ ...i............
@@ -434,8 +435,17 @@ ENTRY(cpu_sa1100_proc_fin)
mcr p15, 0, r0, c1, c0, 0 @ disable caches
ldmfd sp!, {r1, pc}
+ENTRY(cpu_sa1100_proc_fin)
+ stmfd sp!, {r1, lr}
+ mrs r0, cpsr
+ orr r0, r0, #F_BIT | I_BIT
+ msr cpsr, r0
+ bl cpu_sa1100_flush_cache_all @ clean caches
+ b 1b
+
+
.align 5
-idle: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt
+idle: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt, cache aligned
mov r0, r0 @ safety
mov pc, lr
/*
@@ -483,16 +493,14 @@ ENTRY(cpu_sa1100_reset)
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
mov pc, r0
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
+
cpu_manu_name: .asciz "Intel"
-ENTRY(cpu_sa110_name)
- .asciz "StrongARM-110"
-ENTRY(cpu_sa1100_name)
+cpu_sa110_name: .asciz "StrongARM-110"
+cpu_sa1100_name:
.asciz "StrongARM-1100"
+cpu_sa1110_name:
+ .asciz "StrongARM-1110"
.align
.section ".text.init", #alloc, #execinstr
@@ -511,6 +519,13 @@ __sa110_setup: mov r0, #0
orr r0, r0, #0x1100 @ ...I...S........
mov pc, lr
+ .text
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ * come through these
+ */
+
.type sa110_processor_functions, #object
ENTRY(sa110_processor_functions)
.word cpu_sa110_data_abort
@@ -543,6 +558,9 @@ cpu_sa110_info:
.size cpu_sa110_info, . - cpu_sa110_info
+/*
+ * SA1100 and SA1110 share the same function calls
+ */
.type sa1100_processor_functions, #object
ENTRY(sa1100_processor_functions)
.word cpu_sa1100_data_abort
@@ -573,6 +591,12 @@ cpu_sa1100_info:
.long cpu_sa1100_name
.size cpu_sa1100_info, . - cpu_sa1100_info
+cpu_sa1110_info:
+ .long cpu_manu_name
+ .long cpu_sa1110_name
+ .size cpu_sa1110_info, . - cpu_sa1110_info
+
+
.type cpu_arch_name, #object
cpu_arch_name: .asciz "armv4"
.size cpu_arch_name, . - cpu_arch_name
@@ -610,4 +634,17 @@ __sa1100_proc_info:
.long sa1100_processor_functions
.size __sa1100_proc_info, . - __sa1100_proc_info
+ .type __sa1110_proc_info,#object
+__sa1110_proc_info:
+ .long 0x6901b110
+ .long 0xfffffff0
+ .long 0x00000c02
+ b __sa110_setup
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+ .long cpu_sa1110_info
+ .long sa1100_processor_functions
+ .size __sa1110_proc_info, . - __sa1110_proc_info
+