summaryrefslogtreecommitdiff
path: root/arch/cris/mm/ioremap.c
diff options
context:
space:
mode:
authorMikael Starvik <mikael.starvik@axis.com>2005-07-27 11:44:39 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-27 16:26:00 -0700
commit4f18cfbf0990bfc2e8e7706eeb9e5bef898ae923 (patch)
treeb6bd033aac034e5d3cb83be8efb03506135866b2 /arch/cris/mm/ioremap.c
parent7cf32cad153d63ac4f6f2d5dd16ddd32ad72d578 (diff)
[PATCH] CRIS update: mm
Memory management patches. * SMP support. * Non-executable stack (on v32). * 4-level page tables. * Added simple Thread Local Storage support. Signed-off-by: Mikael Starvik <starvik@axis.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/cris/mm/ioremap.c')
-rw-r--r--arch/cris/mm/ioremap.c58
1 files changed, 42 insertions, 16 deletions
diff --git a/arch/cris/mm/ioremap.c b/arch/cris/mm/ioremap.c
index 6b9130bfb6c1..ebba11e270fa 100644
--- a/arch/cris/mm/ioremap.c
+++ b/arch/cris/mm/ioremap.c
@@ -14,9 +14,10 @@
#include <asm/pgalloc.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
+#include <asm/arch/memmap.h>
extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
+ unsigned long phys_addr, pgprot_t prot)
{
unsigned long end;
@@ -31,9 +32,7 @@ extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
printk("remap_area_pte: page already exists\n");
BUG();
}
- set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | __READABLE |
- __WRITEABLE | _PAGE_GLOBAL |
- _PAGE_KERNEL | flags)));
+ set_pte(pte, mk_pte_phys(phys_addr, prot));
address += PAGE_SIZE;
phys_addr += PAGE_SIZE;
pte++;
@@ -41,7 +40,7 @@ extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
}
static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
+ unsigned long phys_addr, pgprot_t prot)
{
unsigned long end;
@@ -56,7 +55,7 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
if (!pte)
return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+ remap_area_pte(pte, address, end - address, address + phys_addr, prot);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address && (address < end));
@@ -64,7 +63,7 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
}
static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
+ unsigned long size, pgprot_t prot)
{
int error;
pgd_t * dir;
@@ -77,13 +76,19 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
BUG();
spin_lock(&init_mm.page_table_lock);
do {
+ pud_t *pud;
pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
+
error = -ENOMEM;
+ pud = pud_alloc(&init_mm, dir, address);
+ if (!pud)
+ break;
+ pmd = pmd_alloc(&init_mm, pud, address);
+
if (!pmd)
break;
if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
+ phys_addr + address, prot))
break;
error = 0;
address = (address + PGDIR_SIZE) & PGDIR_MASK;
@@ -107,9 +112,9 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
* have to convert them into an offset in a page-aligned mapping, but the
* caller shouldn't need to know that small detail.
*/
-void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+void __iomem * __ioremap_prot(unsigned long phys_addr, unsigned long size, pgprot_t prot)
{
- void * addr;
+ void __iomem * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
@@ -131,15 +136,36 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
area = get_vm_area(size, VM_IOREMAP);
if (!area)
return NULL;
- addr = area->addr;
- if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
- vfree(addr);
+ addr = (void __iomem *)area->addr;
+ if (remap_area_pages((unsigned long) addr, phys_addr, size, prot)) {
+ vfree((void __force *)addr);
return NULL;
}
- return (void *) (offset + (char *)addr);
+ return (void __iomem *) (offset + (char __iomem *)addr);
+}
+
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+ return __ioremap_prot(phys_addr, size,
+ __pgprot(_PAGE_PRESENT | __READABLE |
+ __WRITEABLE | _PAGE_GLOBAL |
+ _PAGE_KERNEL | flags));
+}
+
+/**
+ * ioremap_nocache - map bus memory into CPU space
+ * @offset: bus address of the memory
+ * @size: size of the resource to map
+ *
+ * Must be freed with iounmap.
+ */
+
+void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+{
+ return __ioremap(phys_addr | MEM_NON_CACHEABLE, size, 0);
}
-void iounmap(void *addr)
+void iounmap(volatile void __iomem *addr)
{
if (addr > high_memory)
return vfree((void *) (PAGE_MASK & (unsigned long) addr));