diff options
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/consistent.c | 29 | ||||
-rw-r--r-- | arch/arm/mm/fault-common.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/init.c | 295 | ||||
-rw-r--r-- | arch/arm/mm/map.h | 6 | ||||
-rw-r--r-- | arch/arm/mm/mm-armo.c | 4 | ||||
-rw-r--r-- | arch/arm/mm/mm-armv.c | 22 | ||||
-rw-r--r-- | arch/arm/mm/mm-ebsa110.c | 3 | ||||
-rw-r--r-- | arch/arm/mm/mm-rpc.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/mm-sa1100.c | 162 | ||||
-rw-r--r-- | arch/arm/mm/proc-sa110.S | 59 |
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 + |