diff options
Diffstat (limited to 'target/linux/coldfire/patches/007-mcfv4e_arch_mm_mods_1.patch')
-rw-r--r-- | target/linux/coldfire/patches/007-mcfv4e_arch_mm_mods_1.patch | 513 |
1 files changed, 0 insertions, 513 deletions
diff --git a/target/linux/coldfire/patches/007-mcfv4e_arch_mm_mods_1.patch b/target/linux/coldfire/patches/007-mcfv4e_arch_mm_mods_1.patch deleted file mode 100644 index 2abd477465..0000000000 --- a/target/linux/coldfire/patches/007-mcfv4e_arch_mm_mods_1.patch +++ /dev/null @@ -1,513 +0,0 @@ -From 2bef1f8ce148cce9e782f75f9537767c1d8c0eea Mon Sep 17 00:00:00 2001 -From: Kurt Mahan <kmahan@freescale.com> -Date: Wed, 31 Oct 2007 16:58:27 -0600 -Subject: [PATCH] Core Coldfire/MCF5445x arch/mm changes. - -LTIBName: mcfv4e-arch-mm-mods-1 -Signed-off-by: Kurt Mahan <kmahan@freescale.com> ---- - arch/m68k/mm/Makefile | 1 + - arch/m68k/mm/cache.c | 41 ++++++++ - arch/m68k/mm/cf-mmu.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++++ - arch/m68k/mm/hwtest.c | 2 + - arch/m68k/mm/init.c | 3 +- - arch/m68k/mm/kmap.c | 13 +++ - arch/m68k/mm/memory.c | 66 +++++++++++++- - 7 files changed, 373 insertions(+), 4 deletions(-) - create mode 100644 arch/m68k/mm/cf-mmu.c - ---- a/arch/m68k/mm/Makefile -+++ b/arch/m68k/mm/Makefile -@@ -6,3 +6,4 @@ obj-y := cache.o init.o fault.o hwtest. - - obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o - obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o -+obj-$(CONFIG_MMU_CFV4E) += cf-mmu.o kmap.o memory.o ---- a/arch/m68k/mm/cache.c -+++ b/arch/m68k/mm/cache.c -@@ -10,7 +10,11 @@ - #include <asm/pgalloc.h> - #include <asm/traps.h> - -+#ifdef CONFIG_COLDFIRE -+#include <asm/cfcache.h> -+#endif /* CONFIG_COLDFIRE */ - -+#ifndef CONFIG_COLDFIRE - static unsigned long virt_to_phys_slow(unsigned long vaddr) - { - if (CPU_IS_060) { -@@ -69,11 +73,45 @@ static unsigned long virt_to_phys_slow(u - } - return 0; - } -+#endif /* CONFIG_COLDFIRE */ -+ - - /* Push n pages at kernel virtual address and clear the icache */ - /* RZ: use cpush %bc instead of cpush %dc, cinv %ic */ - void flush_icache_range(unsigned long address, unsigned long endaddr) - { -+#ifdef CONFIG_COLDFIRE -+ unsigned long set; -+ unsigned long start_set; -+ unsigned long end_set; -+ -+ start_set = address & _ICACHE_SET_MASK; -+ end_set = endaddr & _ICACHE_SET_MASK; -+ -+ if (start_set > end_set) { -+ /* from the begining to the lowest address */ -+ for (set = 0; set <= end_set; set += (0x10 - 3)) -+ asm volatile ("cpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)" : : "a" (set)); -+ -+ /* next loop will finish the cache ie pass the hole */ -+ end_set = LAST_ICACHE_ADDR; -+ } -+ for (set = start_set; set <= end_set; set += (0x10 - 3)) -+ asm volatile ("cpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)" : : "a" (set)); -+ -+#else /* !CONFIG_COLDFIRE */ - - if (CPU_IS_040_OR_060) { - address &= PAGE_MASK; -@@ -94,9 +132,11 @@ void flush_icache_range(unsigned long ad - : "=&d" (tmp) - : "di" (FLUSH_I)); - } -+#endif /* CONFIG_COLDFIRE */ - } - EXPORT_SYMBOL(flush_icache_range); - -+#ifndef CONFIG_COLDFIRE - void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, - unsigned long addr, int len) - { -@@ -115,4 +155,5 @@ void flush_icache_user_range(struct vm_a - : "di" (FLUSH_I)); - } - } -+#endif /* CONFIG_COLDFIRE */ - ---- /dev/null -+++ b/arch/m68k/mm/cf-mmu.c -@@ -0,0 +1,251 @@ -+/* -+ * linux/arch/m68k/mm/cf-mmu.c -+ * -+ * Based upon linux/arch/m68k/mm/sun3mmu.c -+ * Based upon linux/arch/ppc/mm/mmu_context.c -+ * -+ * Implementations of mm routines specific to the Coldfire MMU. -+ * -+ * Copyright (c) 2008 Freescale Semiconductor, Inc. -+ */ -+ -+#include <linux/signal.h> -+#include <linux/sched.h> -+#include <linux/mm.h> -+#include <linux/swap.h> -+#include <linux/kernel.h> -+#include <linux/string.h> -+#include <linux/types.h> -+#include <linux/init.h> -+#ifdef CONFIG_BLK_DEV_RAM -+#include <linux/blkdev.h> -+#endif -+#include <linux/bootmem.h> -+ -+#include <asm/setup.h> -+#include <asm/uaccess.h> -+#include <asm/page.h> -+#include <asm/pgtable.h> -+#include <asm/system.h> -+#include <asm/machdep.h> -+#include <asm/io.h> -+#include <asm/mmu_context.h> -+#include <asm/cf_pgalloc.h> -+ -+#include <asm/coldfire.h> -+#include <asm/tlbflush.h> -+ -+mm_context_t next_mmu_context; -+unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1]; -+ -+atomic_t nr_free_contexts; -+struct mm_struct *context_mm[LAST_CONTEXT+1]; -+void steal_context(void); -+ -+ -+const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n"; -+ -+extern unsigned long empty_bad_page_table; -+extern unsigned long empty_bad_page; -+extern unsigned long num_pages; -+ -+extern char __init_begin, __init_end; -+ -+void free_initmem(void) -+{ -+ unsigned long addr; -+ unsigned long start = (unsigned long)&__init_begin; -+ unsigned long end = (unsigned long)&__init_end; -+ -+ printk(KERN_INFO "free_initmem: __init_begin = 0x%lx __init_end = 0x%lx\n", start, end); -+ -+ addr = (unsigned long)&__init_begin; -+ for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) { -+ /* not currently used */ -+ virt_to_page(addr)->flags &= ~(1 << PG_reserved); -+ init_page_count(virt_to_page(addr)); -+ free_page(addr); -+ totalram_pages++; -+ } -+} -+ -+/* Coldfire paging_init derived from sun3 */ -+void __init paging_init(void) -+{ -+ pgd_t * pg_dir; -+ pte_t * pg_table; -+ int i; -+ unsigned long address; -+ unsigned long next_pgtable; -+ unsigned long bootmem_end; -+ unsigned long zones_size[MAX_NR_ZONES]; -+ unsigned long size; -+ enum zone_type zone; -+ -+ empty_zero_page = (void *)alloc_bootmem_pages(PAGE_SIZE); -+ memset((void *)empty_zero_page, 0, PAGE_SIZE); -+ -+ pg_dir = swapper_pg_dir; -+ memset(swapper_pg_dir, 0, sizeof (swapper_pg_dir)); -+ -+ size = num_pages * sizeof(pte_t); -+ size = (size + PAGE_SIZE) & ~(PAGE_SIZE-1); -+ next_pgtable = (unsigned long)alloc_bootmem_pages(size); -+ -+ bootmem_end = (next_pgtable + size + PAGE_SIZE) & PAGE_MASK; -+ pg_dir += PAGE_OFFSET >> PGDIR_SHIFT; -+ -+ address = PAGE_OFFSET; -+ while (address < (unsigned long)high_memory) -+ { -+ pg_table = (pte_t *)next_pgtable; -+ next_pgtable += PTRS_PER_PTE * sizeof (pte_t); -+ pgd_val(*pg_dir) = (unsigned long) pg_table; -+ pg_dir++; -+ -+ /* now change pg_table to kernel virtual addresses */ -+ for (i=0; i<PTRS_PER_PTE; ++i, ++pg_table) -+ { -+ pte_t pte = pfn_pte(virt_to_pfn(address), PAGE_INIT); -+ if (address >= (unsigned long)high_memory) -+ pte_val (pte) = 0; -+ -+ set_pte (pg_table, pte); -+ address += PAGE_SIZE; -+ } -+ } -+ -+ current->mm = NULL; -+ -+ /* clear zones */ -+ for (zone = 0; zone < MAX_NR_ZONES; zone++) -+ zones_size[zone] = 0x0; -+ -+ /* allocate the bottom 32M (0x40x 0x41x) to DMA - head.S marks them NO CACHE */ -+ /* JKM - this should be changed to allocate from the TOP (0x4f,0x4e) but the -+ * allocator is being a bit challenging */ -+ zones_size[ZONE_DMA] = (32*1024*1024) >> PAGE_SHIFT; -+ -+ /* allocate the rest to NORMAL - head.S marks them CACHE */ -+ zones_size[ZONE_NORMAL] = (((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT) - zones_size[0]; -+ -+ free_area_init(zones_size); -+} -+ -+ -+int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word) -+{ -+ struct mm_struct *mm; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long mmuar; -+ int asid; -+ int flags; -+ -+ local_save_flags(flags); -+ local_irq_disable(); -+ -+ mmuar = ( dtlb ) ? regs->mmuar -+ : regs->pc + (extension_word * sizeof(long)); -+ -+ mm = (!user_mode(regs) && (mmuar >= PAGE_OFFSET)) ? &init_mm -+ : current->mm; -+ if (!mm) { -+ local_irq_restore(flags); -+ return (-1); -+ } -+ -+ pgd = pgd_offset(mm, mmuar); -+ if (pgd_none(*pgd)) { -+ local_irq_restore(flags); -+ return (-1); -+ } -+ -+ pmd = pmd_offset(pgd, mmuar); -+ if (pmd_none(*pmd)) { -+ local_irq_restore(flags); -+ return (-1); -+ } -+ -+ pte = (mmuar >= PAGE_OFFSET) ? pte_offset_kernel(pmd, mmuar) -+ : pte_offset_map(pmd, mmuar); -+ if (pte_none(*pte) || !pte_present(*pte)) { -+ local_irq_restore(flags); -+ return (-1); -+ } -+ -+ if (write) { -+ if (!pte_write(*pte)) { -+ local_irq_restore(flags); -+ return (-1); -+ } -+ set_pte(pte, pte_mkdirty(*pte)); -+ } -+ -+ set_pte(pte, pte_mkyoung(*pte)); -+ asid = mm->context & 0xff; -+ if (!pte_dirty(*pte) && mmuar<=PAGE_OFFSET) -+ set_pte(pte, pte_wrprotect(*pte)); -+ -+ *MMUTR = (mmuar & PAGE_MASK) | (asid << CF_ASID_MMU_SHIFT) -+ | (((int)(pte->pte) & (int)CF_PAGE_MMUTR_MASK ) >> CF_PAGE_MMUTR_SHIFT) -+ | MMUTR_V; -+ -+ *MMUDR = (pte_val(*pte) & PAGE_MASK) -+ | ((pte->pte) & CF_PAGE_MMUDR_MASK) -+ | MMUDR_SZ8K | MMUDR_X; -+ -+ if ( dtlb ) -+ *MMUOR = MMUOR_ACC | MMUOR_UAA; -+ else -+ *MMUOR = MMUOR_ITLB | MMUOR_ACC | MMUOR_UAA; -+ -+ asm ("nop"); -+ /*printk("cf_tlb_miss: va=%lx, pa=%lx\n", (mmuar & PAGE_MASK), -+ (pte_val(*pte) & PAGE_MASK));*/ -+ local_irq_restore(flags); -+ return (0); -+} -+ -+ -+/* The following was taken from arch/ppc/mmu_context.c -+ * -+ * Initialize the context management stuff. -+ */ -+void __init mmu_context_init(void) -+{ -+ /* -+ * Some processors have too few contexts to reserve one for -+ * init_mm, and require using context 0 for a normal task. -+ * Other processors reserve the use of context zero for the kernel. -+ * This code assumes FIRST_CONTEXT < 32. -+ */ -+ context_map[0] = (1 << FIRST_CONTEXT) - 1; -+ next_mmu_context = FIRST_CONTEXT; -+ atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1); -+} -+ -+/* -+ * Steal a context from a task that has one at the moment. -+ * This is only used on 8xx and 4xx and we presently assume that -+ * they don't do SMP. If they do then thicfpgalloc.hs will have to check -+ * whether the MM we steal is in use. -+ * We also assume that this is only used on systems that don't -+ * use an MMU hash table - this is true for 8xx and 4xx. -+ * This isn't an LRU system, it just frees up each context in -+ * turn (sort-of pseudo-random replacement :). This would be the -+ * place to implement an LRU scheme if anyone was motivated to do it. -+ * -- paulus -+ */ -+void steal_context(void) -+{ -+ struct mm_struct *mm; -+ /* free up context `next_mmu_context' */ -+ /* if we shouldn't free context 0, don't... */ -+ if (next_mmu_context < FIRST_CONTEXT) -+ next_mmu_context = FIRST_CONTEXT; -+ mm = context_mm[next_mmu_context]; -+ flush_tlb_mm(mm); -+ destroy_context(mm); -+} ---- a/arch/m68k/mm/hwtest.c -+++ b/arch/m68k/mm/hwtest.c -@@ -25,6 +25,7 @@ - - #include <linux/module.h> - -+#ifndef CONFIG_COLDFIRE - int hwreg_present( volatile void *regp ) - { - int ret = 0; -@@ -82,4 +83,5 @@ int hwreg_write( volatile void *regp, un - return( ret ); - } - EXPORT_SYMBOL(hwreg_write); -+#endif - ---- a/arch/m68k/mm/init.c -+++ b/arch/m68k/mm/init.c -@@ -122,7 +122,6 @@ void __init mem_init(void) - if (MACH_IS_ATARI) - atari_stram_mem_init_hook(); - #endif -- - /* this will put all memory onto the freelists */ - totalram_pages = num_physpages = 0; - for_each_online_pgdat(pgdat) { -@@ -146,7 +145,7 @@ void __init mem_init(void) - } - } - --#ifndef CONFIG_SUN3 -+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE) - /* insert pointer tables allocated so far into the tablelist */ - init_pointer_table((unsigned long)kernel_pg_dir); - for (i = 0; i < PTRS_PER_PGD; i++) { ---- a/arch/m68k/mm/kmap.c -+++ b/arch/m68k/mm/kmap.c -@@ -24,7 +24,11 @@ - - #undef DEBUG - -+#ifndef CONFIG_COLDFIRE - #define PTRTREESIZE (256*1024) -+#else -+#define PTRTREESIZE PAGE_SIZE -+#endif - - /* - * For 040/060 we can use the virtual memory area like other architectures, -@@ -50,7 +54,11 @@ static inline void free_io_area(void *ad - - #else - -+#ifdef CONFIG_COLDFIRE -+#define IO_SIZE PAGE_SIZE -+#else - #define IO_SIZE (256*1024) -+#endif - - static struct vm_struct *iolist; - -@@ -170,7 +178,12 @@ void __iomem *__ioremap(unsigned long ph - break; - } - } else { -+#ifndef CONFIG_COLDFIRE - physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); -+#else -+ physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY | \ -+ _PAGE_READWRITE); -+#endif - switch (cacheflag) { - case IOMAP_NOCACHE_SER: - case IOMAP_NOCACHE_NONSER: ---- a/arch/m68k/mm/memory.c -+++ b/arch/m68k/mm/memory.c -@@ -203,7 +203,38 @@ static inline void pushcl040(unsigned lo - - void cache_clear (unsigned long paddr, int len) - { -- if (CPU_IS_040_OR_060) { -+ if (CPU_IS_CFV4E) { -+ unsigned long set; -+ unsigned long start_set; -+ unsigned long end_set; -+ -+ start_set = paddr & _ICACHE_SET_MASK; -+ end_set = (paddr+len-1) & _ICACHE_SET_MASK; -+ -+ if (start_set > end_set) { -+ /* from the begining to the lowest address */ -+ for (set = 0; set <= end_set; set += (0x10 - 3)) -+ asm volatile("cpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)" : : "a" (set)); -+ -+ /* next loop will finish the cache ie pass the hole */ -+ end_set = LAST_ICACHE_ADDR; -+ } -+ for (set = start_set; set <= end_set; set += (0x10 - 3)) -+ asm volatile("cpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)" : : "a" (set)); -+ -+ } else if (CPU_IS_040_OR_060) { - int tmp; - - /* -@@ -250,7 +281,38 @@ EXPORT_SYMBOL(cache_clear); - - void cache_push (unsigned long paddr, int len) - { -- if (CPU_IS_040_OR_060) { -+ if (CPU_IS_CFV4E) { -+ unsigned long set; -+ unsigned long start_set; -+ unsigned long end_set; -+ -+ start_set = paddr & _ICACHE_SET_MASK; -+ end_set = (paddr+len-1) & _ICACHE_SET_MASK; -+ -+ if (start_set > end_set) { -+ /* from the begining to the lowest address */ -+ for (set = 0; set <= end_set; set += (0x10 - 3)) -+ asm volatile("cpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)" : : "a" (set)); -+ -+ /* next loop will finish the cache ie pass the hole */ -+ end_set = LAST_ICACHE_ADDR; -+ } -+ for (set = start_set; set <= end_set; set += (0x10 - 3)) -+ asm volatile("cpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%bc,(%0)" : : "a" (set)); -+ -+ } else if (CPU_IS_040_OR_060) { - int tmp = PAGE_SIZE; - - /* |