aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/mm/ioremap.c
diff options
context:
space:
mode:
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 6b9130bfb6c..ebba11e270f 100644
--- a/arch/cris/mm/ioremap.c
+++ b/arch/cris/mm/ioremap.c
@@ -14,9 +14,10 @@
14#include <asm/pgalloc.h> 14#include <asm/pgalloc.h>
15#include <asm/cacheflush.h> 15#include <asm/cacheflush.h>
16#include <asm/tlbflush.h> 16#include <asm/tlbflush.h>
17#include <asm/arch/memmap.h>
17 18
18extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, 19extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
19 unsigned long phys_addr, unsigned long flags) 20 unsigned long phys_addr, pgprot_t prot)
20{ 21{
21 unsigned long end; 22 unsigned long end;
22 23
@@ -31,9 +32,7 @@ extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
31 printk("remap_area_pte: page already exists\n"); 32 printk("remap_area_pte: page already exists\n");
32 BUG(); 33 BUG();
33 } 34 }
34 set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | __READABLE | 35 set_pte(pte, mk_pte_phys(phys_addr, prot));
35 __WRITEABLE | _PAGE_GLOBAL |
36 _PAGE_KERNEL | flags)));
37 address += PAGE_SIZE; 36 address += PAGE_SIZE;
38 phys_addr += PAGE_SIZE; 37 phys_addr += PAGE_SIZE;
39 pte++; 38 pte++;
@@ -41,7 +40,7 @@ extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
41} 40}
42 41
43static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, 42static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
44 unsigned long phys_addr, unsigned long flags) 43 unsigned long phys_addr, pgprot_t prot)
45{ 44{
46 unsigned long end; 45 unsigned long end;
47 46
@@ -56,7 +55,7 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
56 pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address); 55 pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
57 if (!pte) 56 if (!pte)
58 return -ENOMEM; 57 return -ENOMEM;
59 remap_area_pte(pte, address, end - address, address + phys_addr, flags); 58 remap_area_pte(pte, address, end - address, address + phys_addr, prot);
60 address = (address + PMD_SIZE) & PMD_MASK; 59 address = (address + PMD_SIZE) & PMD_MASK;
61 pmd++; 60 pmd++;
62 } while (address && (address < end)); 61 } while (address && (address < end));
@@ -64,7 +63,7 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
64} 63}
65 64
66static int remap_area_pages(unsigned long address, unsigned long phys_addr, 65static int remap_area_pages(unsigned long address, unsigned long phys_addr,
67 unsigned long size, unsigned long flags) 66 unsigned long size, pgprot_t prot)
68{ 67{
69 int error; 68 int error;
70 pgd_t * dir; 69 pgd_t * dir;
@@ -77,13 +76,19 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
77 BUG(); 76 BUG();
78 spin_lock(&init_mm.page_table_lock); 77 spin_lock(&init_mm.page_table_lock);
79 do { 78 do {
79 pud_t *pud;
80 pmd_t *pmd; 80 pmd_t *pmd;
81 pmd = pmd_alloc(&init_mm, dir, address); 81
82 error = -ENOMEM; 82 error = -ENOMEM;
83 pud = pud_alloc(&init_mm, dir, address);
84 if (!pud)
85 break;
86 pmd = pmd_alloc(&init_mm, pud, address);
87
83 if (!pmd) 88 if (!pmd)
84 break; 89 break;
85 if (remap_area_pmd(pmd, address, end - address, 90 if (remap_area_pmd(pmd, address, end - address,
86 phys_addr + address, flags)) 91 phys_addr + address, prot))
87 break; 92 break;
88 error = 0; 93 error = 0;
89 address = (address + PGDIR_SIZE) & PGDIR_MASK; 94 address = (address + PGDIR_SIZE) & PGDIR_MASK;
@@ -107,9 +112,9 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
107 * have to convert them into an offset in a page-aligned mapping, but the 112 * have to convert them into an offset in a page-aligned mapping, but the
108 * caller shouldn't need to know that small detail. 113 * caller shouldn't need to know that small detail.
109 */ 114 */
110void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) 115void __iomem * __ioremap_prot(unsigned long phys_addr, unsigned long size, pgprot_t prot)
111{ 116{
112 void * addr; 117 void __iomem * addr;
113 struct vm_struct * area; 118 struct vm_struct * area;
114 unsigned long offset, last_addr; 119 unsigned long offset, last_addr;
115 120
@@ -131,15 +136,36 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
131 area = get_vm_area(size, VM_IOREMAP); 136 area = get_vm_area(size, VM_IOREMAP);
132 if (!area) 137 if (!area)
133 return NULL; 138 return NULL;
134 addr = area->addr; 139 addr = (void __iomem *)area->addr;
135 if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { 140 if (remap_area_pages((unsigned long) addr, phys_addr, size, prot)) {
136 vfree(addr); 141 vfree((void __force *)addr);
137 return NULL; 142 return NULL;
138 } 143 }
139 return (void *) (offset + (char *)addr); 144 return (void __iomem *) (offset + (char __iomem *)addr);
145}
146
147void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
148{
149 return __ioremap_prot(phys_addr, size,
150 __pgprot(_PAGE_PRESENT | __READABLE |
151 __WRITEABLE | _PAGE_GLOBAL |
152 _PAGE_KERNEL | flags));
153}
154
155/**
156 * ioremap_nocache - map bus memory into CPU space
157 * @offset: bus address of the memory
158 * @size: size of the resource to map
159 *
160 * Must be freed with iounmap.
161 */
162
163void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
164{
165 return __ioremap(phys_addr | MEM_NON_CACHEABLE, size, 0);
140} 166}
141 167
142void iounmap(void *addr) 168void iounmap(volatile void __iomem *addr)
143{ 169{
144 if (addr > high_memory) 170 if (addr > high_memory)
145 return vfree((void *) (PAGE_MASK & (unsigned long) addr)); 171 return vfree((void *) (PAGE_MASK & (unsigned long) addr));