aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorYoshihiro Shimoda <shimoda.yoshihiro@renesas.com>2009-03-10 02:49:54 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-03-10 02:49:54 -0400
commit2f47f44790a9c8fc43e515df3c6be19a35ee5de5 (patch)
tree6a13f7abebcb04cc396a1d6de307265e36ccc89d /arch/sh
parenta29b99eccecefe5026713b226f66f117c8837ad5 (diff)
sh: Support fixed 32-bit PMB mappings from bootloader.
This provides a method for supporting fixed PMB mappings inherited from the bootloader, as an alternative to the dynamic PMB mapping currently used by the kernel. In the future these methods will be combined. P1/P2 area is handled like a regular 29-bit physical address, and local bus device are assigned P3 area addresses. Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/boot/Makefile20
-rw-r--r--arch/sh/include/asm/addrspace.h4
-rw-r--r--arch/sh/include/asm/io.h4
-rw-r--r--arch/sh/include/asm/page.h7
-rw-r--r--arch/sh/kernel/vmlinux_32.lds.S5
-rw-r--r--arch/sh/mm/Kconfig29
-rw-r--r--arch/sh/mm/Makefile_321
-rw-r--r--arch/sh/mm/ioremap_32.c6
-rw-r--r--arch/sh/mm/pmb-fixed.c45
9 files changed, 104 insertions, 17 deletions
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
index c16ccd4bfa16..95483d161258 100644
--- a/arch/sh/boot/Makefile
+++ b/arch/sh/boot/Makefile
@@ -33,20 +33,24 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
33$(obj)/compressed/vmlinux: FORCE 33$(obj)/compressed/vmlinux: FORCE
34 $(Q)$(MAKE) $(build)=$(obj)/compressed $@ 34 $(Q)$(MAKE) $(build)=$(obj)/compressed $@
35 35
36ifeq ($(CONFIG_32BIT),y) 36KERNEL_MEMORY := 0x00000000
37KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \ 37ifeq ($(CONFIG_PMB_FIXED),y)
38 $$[$(CONFIG_PAGE_OFFSET) + \ 38KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
39 $(CONFIG_ZERO_PAGE_OFFSET)]') 39 $$[$(CONFIG_MEMORY_START) & 0x1fffffff]')
40else 40endif
41ifeq ($(CONFIG_29BIT),y)
42KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
43 $$[$(CONFIG_MEMORY_START)]')
44endif
45
41KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \ 46KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \
42 $$[$(CONFIG_PAGE_OFFSET) + \ 47 $$[$(CONFIG_PAGE_OFFSET) + \
43 $(CONFIG_MEMORY_START) + \ 48 $(KERNEL_MEMORY) + \
44 $(CONFIG_ZERO_PAGE_OFFSET)]') 49 $(CONFIG_ZERO_PAGE_OFFSET)]')
45endif
46 50
47KERNEL_ENTRY := $(shell /bin/bash -c 'printf "0x%08x" \ 51KERNEL_ENTRY := $(shell /bin/bash -c 'printf "0x%08x" \
48 $$[$(CONFIG_PAGE_OFFSET) + \ 52 $$[$(CONFIG_PAGE_OFFSET) + \
49 $(CONFIG_MEMORY_START) + \ 53 $(KERNEL_MEMORY) + \
50 $(CONFIG_ZERO_PAGE_OFFSET) + $(CONFIG_ENTRY_OFFSET)]') 54 $(CONFIG_ZERO_PAGE_OFFSET) + $(CONFIG_ENTRY_OFFSET)]')
51 55
52quiet_cmd_uimage = UIMAGE $@ 56quiet_cmd_uimage = UIMAGE $@
diff --git a/arch/sh/include/asm/addrspace.h b/arch/sh/include/asm/addrspace.h
index 36736c7e93db..80d40813e057 100644
--- a/arch/sh/include/asm/addrspace.h
+++ b/arch/sh/include/asm/addrspace.h
@@ -31,7 +31,7 @@
31/* Returns the physical address of a PnSEG (n=1,2) address */ 31/* Returns the physical address of a PnSEG (n=1,2) address */
32#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) 32#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff)
33 33
34#ifdef CONFIG_29BIT 34#if defined(CONFIG_29BIT) || defined(CONFIG_PMB_FIXED)
35/* 35/*
36 * Map an address to a certain privileged segment 36 * Map an address to a certain privileged segment
37 */ 37 */
@@ -43,7 +43,7 @@
43 ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P3SEG)) 43 ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P3SEG))
44#define P4SEGADDR(a) \ 44#define P4SEGADDR(a) \
45 ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P4SEG)) 45 ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P4SEG))
46#endif /* 29BIT */ 46#endif /* 29BIT || PMB_FIXED */
47#endif /* P1SEG */ 47#endif /* P1SEG */
48 48
49/* Check if an address can be reached in 29 bits */ 49/* Check if an address can be reached in 29 bits */
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 61f6dae40534..0454f8d68059 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -238,7 +238,7 @@ extern void onchip_unmap(unsigned long vaddr);
238static inline void __iomem * 238static inline void __iomem *
239__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) 239__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
240{ 240{
241#ifdef CONFIG_SUPERH32 241#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED)
242 unsigned long last_addr = offset + size - 1; 242 unsigned long last_addr = offset + size - 1;
243#endif 243#endif
244 void __iomem *ret; 244 void __iomem *ret;
@@ -247,7 +247,7 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
247 if (ret) 247 if (ret)
248 return ret; 248 return ret;
249 249
250#ifdef CONFIG_SUPERH32 250#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED)
251 /* 251 /*
252 * For P1 and P2 space this is trivial, as everything is already 252 * For P1 and P2 space this is trivial, as everything is already
253 * mapped. Uncached access for P1 addresses are done through P2. 253 * mapped. Uncached access for P1 addresses are done through P2.
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h
index 5871d78e47e5..9c6d21ec0240 100644
--- a/arch/sh/include/asm/page.h
+++ b/arch/sh/include/asm/page.h
@@ -129,7 +129,12 @@ typedef struct page *pgtable_t;
129 * is not visible (it is part of the PMB mapping) and so needs to be 129 * is not visible (it is part of the PMB mapping) and so needs to be
130 * added or subtracted as required. 130 * added or subtracted as required.
131 */ 131 */
132#ifdef CONFIG_32BIT 132#if defined(CONFIG_PMB_FIXED)
133/* phys = virt - PAGE_OFFSET - (__MEMORY_START & 0xe0000000) */
134#define PMB_OFFSET (PAGE_OFFSET - PXSEG(__MEMORY_START))
135#define __pa(x) ((unsigned long)(x) - PMB_OFFSET)
136#define __va(x) ((void *)((unsigned long)(x) + PMB_OFFSET))
137#elif defined(CONFIG_32BIT)
133#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET+__MEMORY_START) 138#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET+__MEMORY_START)
134#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET-__MEMORY_START)) 139#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET-__MEMORY_START))
135#else 140#else
diff --git a/arch/sh/kernel/vmlinux_32.lds.S b/arch/sh/kernel/vmlinux_32.lds.S
index 7b4b82bd1156..d0b2a715cd14 100644
--- a/arch/sh/kernel/vmlinux_32.lds.S
+++ b/arch/sh/kernel/vmlinux_32.lds.S
@@ -15,7 +15,10 @@ OUTPUT_ARCH(sh)
15ENTRY(_start) 15ENTRY(_start)
16SECTIONS 16SECTIONS
17{ 17{
18#ifdef CONFIG_32BIT 18#ifdef CONFIG_PMB_FIXED
19 . = CONFIG_PAGE_OFFSET + (CONFIG_MEMORY_START & 0x1fffffff) +
20 CONFIG_ZERO_PAGE_OFFSET;
21#elif defined(CONFIG_32BIT)
19 . = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET; 22 . = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
20#else 23#else
21 . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET; 24 . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 555ec9714b9e..10c24356d2d5 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -57,7 +57,7 @@ config 32BIT
57 bool 57 bool
58 default y if CPU_SH5 58 default y if CPU_SH5
59 59
60config PMB 60config PMB_ENABLE
61 bool "Support 32-bit physical addressing through PMB" 61 bool "Support 32-bit physical addressing through PMB"
62 depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785) 62 depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
63 select 32BIT 63 select 32BIT
@@ -67,6 +67,33 @@ config PMB
67 32-bits through the SH-4A PMB. If this is not set, legacy 67 32-bits through the SH-4A PMB. If this is not set, legacy
68 29-bit physical addressing will be used. 68 29-bit physical addressing will be used.
69 69
70choice
71 prompt "PMB handling type"
72 depends on PMB_ENABLE
73 default PMB_FIXED
74
75config PMB
76 bool "PMB"
77 depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
78 select 32BIT
79 help
80 If you say Y here, physical addressing will be extended to
81 32-bits through the SH-4A PMB. If this is not set, legacy
82 29-bit physical addressing will be used.
83
84config PMB_FIXED
85 bool "fixed PMB"
86 depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || \
87 CPU_SUBTYPE_SH7785)
88 select 32BIT
89 help
90 If this option is enabled, fixed PMB mappings are inherited
91 from the boot loader, and the kernel does not attempt dynamic
92 management. This is the closest to legacy 29-bit physical mode,
93 and allows systems to support up to 512MiB of system memory.
94
95endchoice
96
70config X2TLB 97config X2TLB
71 bool "Enable extended TLB mode" 98 bool "Enable extended TLB mode"
72 depends on (CPU_SHX2 || CPU_SHX3) && MMU && EXPERIMENTAL 99 depends on (CPU_SHX2 || CPU_SHX3) && MMU && EXPERIMENTAL
diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32
index cb2f3f299591..469ff1672451 100644
--- a/arch/sh/mm/Makefile_32
+++ b/arch/sh/mm/Makefile_32
@@ -35,6 +35,7 @@ endif
35 35
36obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 36obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
37obj-$(CONFIG_PMB) += pmb.o 37obj-$(CONFIG_PMB) += pmb.o
38obj-$(CONFIG_PMB_FIXED) += pmb-fixed.o
38obj-$(CONFIG_NUMA) += numa.o 39obj-$(CONFIG_NUMA) += numa.o
39 40
40EXTRA_CFLAGS += -Werror 41EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/mm/ioremap_32.c b/arch/sh/mm/ioremap_32.c
index 8dc77026a0b5..60cc486d2c2c 100644
--- a/arch/sh/mm/ioremap_32.c
+++ b/arch/sh/mm/ioremap_32.c
@@ -59,11 +59,13 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
59 if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr)) 59 if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr))
60 return (void __iomem *)phys_addr; 60 return (void __iomem *)phys_addr;
61 61
62#if !defined(CONFIG_PMB_FIXED)
62 /* 63 /*
63 * Don't allow anybody to remap normal RAM that we're using.. 64 * Don't allow anybody to remap normal RAM that we're using..
64 */ 65 */
65 if (phys_addr < virt_to_phys(high_memory)) 66 if (phys_addr < virt_to_phys(high_memory))
66 return NULL; 67 return NULL;
68#endif
67 69
68 /* 70 /*
69 * Mappings have to be page-aligned 71 * Mappings have to be page-aligned
@@ -81,7 +83,7 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
81 area->phys_addr = phys_addr; 83 area->phys_addr = phys_addr;
82 orig_addr = addr = (unsigned long)area->addr; 84 orig_addr = addr = (unsigned long)area->addr;
83 85
84#ifdef CONFIG_32BIT 86#ifdef CONFIG_PMB
85 /* 87 /*
86 * First try to remap through the PMB once a valid VMA has been 88 * First try to remap through the PMB once a valid VMA has been
87 * established. Smaller allocations (or the rest of the size 89 * established. Smaller allocations (or the rest of the size
@@ -122,7 +124,7 @@ void __iounmap(void __iomem *addr)
122 if (seg < P3SEG || vaddr >= P3_ADDR_MAX || is_pci_memaddr(vaddr)) 124 if (seg < P3SEG || vaddr >= P3_ADDR_MAX || is_pci_memaddr(vaddr))
123 return; 125 return;
124 126
125#ifdef CONFIG_32BIT 127#ifdef CONFIG_PMB
126 /* 128 /*
127 * Purge any PMB entries that may have been established for this 129 * Purge any PMB entries that may have been established for this
128 * mapping, then proceed with conventional VMA teardown. 130 * mapping, then proceed with conventional VMA teardown.
diff --git a/arch/sh/mm/pmb-fixed.c b/arch/sh/mm/pmb-fixed.c
new file mode 100644
index 000000000000..43c8eac4d8a1
--- /dev/null
+++ b/arch/sh/mm/pmb-fixed.c
@@ -0,0 +1,45 @@
1/*
2 * arch/sh/mm/fixed_pmb.c
3 *
4 * Copyright (C) 2009 Renesas Solutions Corp.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/init.h>
11#include <linux/mm.h>
12#include <linux/io.h>
13#include <asm/mmu.h>
14#include <asm/mmu_context.h>
15
16static int __uses_jump_to_uncached fixed_pmb_init(void)
17{
18 int i;
19 unsigned long addr, data;
20
21 jump_to_uncached();
22
23 for (i = 0; i < PMB_ENTRY_MAX; i++) {
24 addr = PMB_DATA + (i << PMB_E_SHIFT);
25 data = ctrl_inl(addr);
26 if (!(data & PMB_V))
27 continue;
28
29 if (data & PMB_C) {
30#if defined(CONFIG_CACHE_WRITETHROUGH)
31 data |= PMB_WT;
32#elif defined(CONFIG_CACHE_WRITEBACK)
33 data &= ~PMB_WT;
34#else
35 data &= ~(PMB_C | PMB_WT);
36#endif
37 }
38 ctrl_outl(data, addr);
39 }
40
41 back_to_cached();
42
43 return 0;
44}
45arch_initcall(fixed_pmb_init);