diff options
author | Deepak Saxena <dsaxena@plexity.net> | 2006-01-09 14:23:11 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-01-09 14:23:11 -0500 |
commit | 9d4ae7276ae26c5bfba6207cf05340af1931d8d4 (patch) | |
tree | bf6f09189541ac964365c68362e9915c48510eb5 /arch/arm/mm | |
parent | 16ed926eee5497db52fbee4d2db2dedbcd23561c (diff) |
[ARM] 3070/2: Add __ioremap_pfn() API
Patch from Deepak Saxena
In working on adding 36-bit addressed supersection support to ioremap(),
I came to the conclusion that it would be far simpler to do so by just
splitting __ioremap() into a main external interface and adding an
__ioremap_pfn() function that takes a pfn + offset into the page that
__ioremap() can call. This way existing callers of __ioremap() won't have
to change their code and 36-bit systems will just call __ioremap_pfn()
and we will not have to deal with unsigned long long variables.
Note that __ioremap_pfn() should _NOT_ be called directly by drivers
but is reserved for use by arch_ioremap() implementations that map
32-bit resource regions into the real 36-bit address and then call
this new function.
Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/ioremap.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 10901398e4a2..de3ce1eec2ec 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c | |||
@@ -86,11 +86,12 @@ remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static int | 88 | static int |
89 | remap_area_pages(unsigned long start, unsigned long phys_addr, | 89 | remap_area_pages(unsigned long start, unsigned long pfn, |
90 | unsigned long size, unsigned long flags) | 90 | unsigned long size, unsigned long flags) |
91 | { | 91 | { |
92 | unsigned long address = start; | 92 | unsigned long address = start; |
93 | unsigned long end = start + size; | 93 | unsigned long end = start + size; |
94 | unsigned long phys_addr = __pfn_to_phys(pfn); | ||
94 | int err = 0; | 95 | int err = 0; |
95 | pgd_t * dir; | 96 | pgd_t * dir; |
96 | 97 | ||
@@ -130,36 +131,44 @@ remap_area_pages(unsigned long start, unsigned long phys_addr, | |||
130 | * mapping. See include/asm-arm/proc-armv/pgtable.h for more information. | 131 | * mapping. See include/asm-arm/proc-armv/pgtable.h for more information. |
131 | */ | 132 | */ |
132 | void __iomem * | 133 | void __iomem * |
134 | __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, | ||
135 | unsigned long flags) | ||
136 | { | ||
137 | unsigned long addr; | ||
138 | struct vm_struct * area; | ||
139 | |||
140 | area = get_vm_area(size, VM_IOREMAP); | ||
141 | if (!area) | ||
142 | return NULL; | ||
143 | addr = (unsigned long)area->addr; | ||
144 | if (remap_area_pages(addr, pfn, size, flags)) { | ||
145 | vfree(addr); | ||
146 | return NULL; | ||
147 | } | ||
148 | return (void __iomem *) (offset + (char *)addr); | ||
149 | } | ||
150 | EXPORT_SYMBOL(__ioremap_pfn); | ||
151 | |||
152 | void __iomem * | ||
133 | __ioremap(unsigned long phys_addr, size_t size, unsigned long flags) | 153 | __ioremap(unsigned long phys_addr, size_t size, unsigned long flags) |
134 | { | 154 | { |
135 | void * addr; | 155 | unsigned long last_addr; |
136 | struct vm_struct * area; | 156 | unsigned long offset = phys_addr & ~PAGE_MASK; |
137 | unsigned long offset, last_addr; | 157 | unsigned long pfn = __phys_to_pfn(phys_addr); |
138 | 158 | ||
139 | /* Don't allow wraparound or zero size */ | 159 | /* |
160 | * Don't allow wraparound or zero size | ||
161 | */ | ||
140 | last_addr = phys_addr + size - 1; | 162 | last_addr = phys_addr + size - 1; |
141 | if (!size || last_addr < phys_addr) | 163 | if (!size || last_addr < phys_addr) |
142 | return NULL; | 164 | return NULL; |
143 | 165 | ||
144 | /* | 166 | /* |
145 | * Mappings have to be page-aligned | 167 | * Page align the mapping size |
146 | */ | 168 | */ |
147 | offset = phys_addr & ~PAGE_MASK; | ||
148 | phys_addr &= PAGE_MASK; | ||
149 | size = PAGE_ALIGN(last_addr + 1) - phys_addr; | 169 | size = PAGE_ALIGN(last_addr + 1) - phys_addr; |
150 | 170 | ||
151 | /* | 171 | return __ioremap_pfn(pfn, offset, size, flags); |
152 | * Ok, go for it.. | ||
153 | */ | ||
154 | area = get_vm_area(size, VM_IOREMAP); | ||
155 | if (!area) | ||
156 | return NULL; | ||
157 | addr = area->addr; | ||
158 | if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { | ||
159 | vfree(addr); | ||
160 | return NULL; | ||
161 | } | ||
162 | return (void __iomem *) (offset + (char *)addr); | ||
163 | } | 172 | } |
164 | EXPORT_SYMBOL(__ioremap); | 173 | EXPORT_SYMBOL(__ioremap); |
165 | 174 | ||