From 1f69b6af9171f50135cce8023c84d82fbf42a8f5 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 6 Oct 2009 21:22:25 +0000 Subject: sh: Prepare for dynamic PMB support To allow the MMU to be switched between 29bit and 32bit mode at runtime some constants need to swapped for functions that return a runtime value. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/include/asm/mmu.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/sh/include/asm/mmu.h') diff --git a/arch/sh/include/asm/mmu.h b/arch/sh/include/asm/mmu.h index f5963037c9d6..5025e12b7864 100644 --- a/arch/sh/include/asm/mmu.h +++ b/arch/sh/include/asm/mmu.h @@ -7,6 +7,8 @@ #define PMB_PASCR 0xff000070 #define PMB_IRMCR 0xff000078 +#define PASCR_SE 0x80000000 + #define PMB_ADDR 0xf6100000 #define PMB_DATA 0xf7100000 #define PMB_ENTRY_MAX 16 @@ -75,4 +77,3 @@ void pmb_unmap(unsigned long addr); #endif /* __ASSEMBLY__ */ #endif /* __MMU_H */ - -- cgit v1.2.3 From 8386aebb9e15a94137693ea4f4df84207f71cc75 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 6 Oct 2009 21:22:28 +0000 Subject: sh: Make most PMB functions static There's no need to export the internal PMB functions for allocating, freeing and modifying PMB entries, etc. This way we can restrict the interface for PMB. Also remove the static from pmb_init() so that we have more freedom in setting up the initial PMB entries and turning on MMU 32bit mode. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/include/asm/mmu.h | 8 +------- arch/sh/kernel/setup.c | 4 ++++ arch/sh/mm/pmb.c | 17 ++++++++--------- 3 files changed, 13 insertions(+), 16 deletions(-) (limited to 'arch/sh/include/asm/mmu.h') diff --git a/arch/sh/include/asm/mmu.h b/arch/sh/include/asm/mmu.h index 5025e12b7864..9c84b4546c8d 100644 --- a/arch/sh/include/asm/mmu.h +++ b/arch/sh/include/asm/mmu.h @@ -64,16 +64,10 @@ struct pmb_entry { }; /* arch/sh/mm/pmb.c */ -int __set_pmb_entry(unsigned long vpn, unsigned long ppn, - unsigned long flags, int *entry); -int set_pmb_entry(struct pmb_entry *pmbe); -void clear_pmb_entry(struct pmb_entry *pmbe); -struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn, - unsigned long flags); -void pmb_free(struct pmb_entry *pmbe); long pmb_remap(unsigned long virt, unsigned long phys, unsigned long size, unsigned long flags); void pmb_unmap(unsigned long addr); +int pmb_init(void); #endif /* __ASSEMBLY__ */ #endif /* __MMU_H */ diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index f9d44f8e0df6..8fdd03a67680 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -453,6 +453,10 @@ void __init setup_arch(char **cmdline_p) paging_init(); +#ifdef CONFIG_PMB + pmb_init(); +#endif + #ifdef CONFIG_SMP plat_smp_setup(); #endif diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c index b8a33949296a..f01c8191144c 100644 --- a/arch/sh/mm/pmb.c +++ b/arch/sh/mm/pmb.c @@ -115,8 +115,8 @@ repeat: return pos; } -struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn, - unsigned long flags) +static struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn, + unsigned long flags) { struct pmb_entry *pmbe; int pos; @@ -141,7 +141,7 @@ struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn, return pmbe; } -void pmb_free(struct pmb_entry *pmbe) +static void pmb_free(struct pmb_entry *pmbe) { spin_lock_irq(&pmb_list_lock); pmb_list_del(pmbe); @@ -153,8 +153,8 @@ void pmb_free(struct pmb_entry *pmbe) /* * Must be in P2 for __set_pmb_entry() */ -void __set_pmb_entry(unsigned long vpn, unsigned long ppn, - unsigned long flags, int pos) +static void __set_pmb_entry(unsigned long vpn, unsigned long ppn, + unsigned long flags, int pos) { ctrl_outl(vpn | PMB_V, mk_pmb_addr(pos)); @@ -171,14 +171,14 @@ void __set_pmb_entry(unsigned long vpn, unsigned long ppn, ctrl_outl(ppn | flags | PMB_V, mk_pmb_data(pos)); } -void __uses_jump_to_uncached set_pmb_entry(struct pmb_entry *pmbe) +static void __uses_jump_to_uncached set_pmb_entry(struct pmb_entry *pmbe) { jump_to_uncached(); __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, pmbe->entry); back_to_cached(); } -void __uses_jump_to_uncached clear_pmb_entry(struct pmb_entry *pmbe) +static void __uses_jump_to_uncached clear_pmb_entry(struct pmb_entry *pmbe) { unsigned int entry = pmbe->entry; unsigned long addr; @@ -327,7 +327,7 @@ static void pmb_cache_ctor(void *pmb) memset(pmb, 0, sizeof(struct pmb_entry)); } -static int __uses_jump_to_uncached pmb_init(void) +int __uses_jump_to_uncached pmb_init(void) { unsigned int nr_entries = ARRAY_SIZE(pmb_init_map); unsigned int entry, i; @@ -364,7 +364,6 @@ static int __uses_jump_to_uncached pmb_init(void) return 0; } -arch_initcall(pmb_init); static int pmb_seq_show(struct seq_file *file, void *iter) { -- cgit v1.2.3 From 20b5014b3e5fe7b874a3f6a1dc03b0c21cb222cd Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 6 Oct 2009 21:22:33 +0000 Subject: sh: Fold fixed-PMB support into dynamic PMB support The initialisation process differs for CONFIG_PMB and for CONFIG_PMB_FIXED. For CONFIG_PMB_FIXED we need to register the PMB entries that were allocated by the bootloader. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/include/asm/mmu.h | 2 ++ arch/sh/kernel/setup.c | 2 +- arch/sh/mm/Makefile | 3 +-- arch/sh/mm/pmb-fixed.c | 45 -------------------------------- arch/sh/mm/pmb.c | 65 +++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 64 insertions(+), 53 deletions(-) delete mode 100644 arch/sh/mm/pmb-fixed.c (limited to 'arch/sh/include/asm/mmu.h') diff --git a/arch/sh/include/asm/mmu.h b/arch/sh/include/asm/mmu.h index 9c84b4546c8d..c7426ad9926e 100644 --- a/arch/sh/include/asm/mmu.h +++ b/arch/sh/include/asm/mmu.h @@ -15,6 +15,8 @@ #define PMB_E_MASK 0x0000000f #define PMB_E_SHIFT 8 +#define PMB_PFN_MASK 0xff000000 + #define PMB_SZ_16M 0x00000000 #define PMB_SZ_64M 0x00000010 #define PMB_SZ_128M 0x00000080 diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 8fdd03a67680..df65fe2d43b8 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -453,7 +453,7 @@ void __init setup_arch(char **cmdline_p) paging_init(); -#ifdef CONFIG_PMB +#ifdef CONFIG_PMB_ENABLE pmb_init(); #endif diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index 3759bf853293..8a70535fa7ce 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile @@ -33,8 +33,7 @@ obj-y += $(tlb-y) endif obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o -obj-$(CONFIG_PMB) += pmb.o -obj-$(CONFIG_PMB_FIXED) += pmb-fixed.o +obj-$(CONFIG_PMB_ENABLE) += pmb.o obj-$(CONFIG_NUMA) += numa.o # Special flags for fault_64.o. This puts restrictions on the number of diff --git a/arch/sh/mm/pmb-fixed.c b/arch/sh/mm/pmb-fixed.c deleted file mode 100644 index 43c8eac4d8a1..000000000000 --- a/arch/sh/mm/pmb-fixed.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * arch/sh/mm/fixed_pmb.c - * - * Copyright (C) 2009 Renesas Solutions Corp. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include - -static int __uses_jump_to_uncached fixed_pmb_init(void) -{ - int i; - unsigned long addr, data; - - jump_to_uncached(); - - for (i = 0; i < PMB_ENTRY_MAX; i++) { - addr = PMB_DATA + (i << PMB_E_SHIFT); - data = ctrl_inl(addr); - if (!(data & PMB_V)) - continue; - - if (data & PMB_C) { -#if defined(CONFIG_CACHE_WRITETHROUGH) - data |= PMB_WT; -#elif defined(CONFIG_CACHE_WRITEBACK) - data &= ~PMB_WT; -#else - data &= ~(PMB_C | PMB_WT); -#endif - } - ctrl_outl(data, addr); - } - - back_to_cached(); - - return 0; -} -arch_initcall(fixed_pmb_init); diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c index 7e64f6d960c5..280f6a166035 100644 --- a/arch/sh/mm/pmb.c +++ b/arch/sh/mm/pmb.c @@ -70,14 +70,20 @@ repeat: } static struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn, - unsigned long flags) + unsigned long flags, int entry) { struct pmb_entry *pmbe; int pos; - pos = pmb_alloc_entry(); - if (pos < 0) - return ERR_PTR(pos); + if (entry == PMB_NO_ENTRY) { + pos = pmb_alloc_entry(); + if (pos < 0) + return ERR_PTR(pos); + } else { + if (test_bit(entry, &pmb_map)) + return ERR_PTR(-ENOSPC); + pos = entry; + } pmbe = &pmb_entry_list[pos]; if (!pmbe) @@ -187,7 +193,8 @@ again: if (size < pmb_sizes[i].size) continue; - pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag); + pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag, + PMB_NO_ENTRY); if (IS_ERR(pmbe)) { err = PTR_ERR(pmbe); goto out; @@ -272,6 +279,7 @@ static void __pmb_unmap(struct pmb_entry *pmbe) } while (pmbe); } +#ifdef CONFIG_PMB int __uses_jump_to_uncached pmb_init(void) { unsigned int i; @@ -309,6 +317,53 @@ int __uses_jump_to_uncached pmb_init(void) return 0; } +#else +int __uses_jump_to_uncached pmb_init(void) +{ + int i; + unsigned long addr, data; + + jump_to_uncached(); + + for (i = 0; i < PMB_ENTRY_MAX; i++) { + struct pmb_entry *pmbe; + unsigned long vpn, ppn, flags; + + addr = PMB_DATA + (i << PMB_E_SHIFT); + data = ctrl_inl(addr); + if (!(data & PMB_V)) + continue; + + if (data & PMB_C) { +#if defined(CONFIG_CACHE_WRITETHROUGH) + data |= PMB_WT; +#elif defined(CONFIG_CACHE_WRITEBACK) + data &= ~PMB_WT; +#else + data &= ~(PMB_C | PMB_WT); +#endif + } + ctrl_outl(data, addr); + + ppn = data & PMB_PFN_MASK; + + flags = data & (PMB_C | PMB_WT | PMB_UB); + flags |= data & PMB_SZ_MASK; + + addr = PMB_ADDR + (i << PMB_E_SHIFT); + data = ctrl_inl(addr); + + vpn = data & PMB_PFN_MASK; + + pmbe = pmb_alloc(vpn, ppn, flags, i); + WARN_ON(IS_ERR(pmbe)); + } + + back_to_cached(); + + return 0; +} +#endif /* CONFIG_PMB */ static int pmb_seq_show(struct seq_file *file, void *iter) { -- cgit v1.2.3