diff options
Diffstat (limited to 'arch/cris/mm/ioremap.c')
-rw-r--r-- | arch/cris/mm/ioremap.c | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/arch/cris/mm/ioremap.c b/arch/cris/mm/ioremap.c index 6b9130b..ebba11e 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)); |