Commit b66c1a3919abb40f9bd8fb92a0d9fd77eb899c54
Committed by
Linus Torvalds
1 parent
bf3a00f88c
Exists in
master
and in
39 other branches
[PATCH] sh: I/O routine cleanups and ioremap() overhaul
This introduces a few changes in the way that the I/O routines are defined on SH, specifically so that things like the iomap API properly wrap through the machvec for board-specific quirks. In addition to this, the old p3_ioremap() work is converted to a more generic __ioremap() that will map through the PMB if it's available, or fall back on page tables for everything else. An alpha-like IO_CONCAT is also added so we can start to clean up the board-specific io.h mess, which will be handled in board update patches.. Signed-off-by: Paul Mundt <lethal@linux-sh.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 6 changed files with 440 additions and 337 deletions Side-by-side Diff
arch/sh/kernel/io.c
... | ... | @@ -2,58 +2,74 @@ |
2 | 2 | * linux/arch/sh/kernel/io.c |
3 | 3 | * |
4 | 4 | * Copyright (C) 2000 Stuart Menefy |
5 | + * Copyright (C) 2005 Paul Mundt | |
5 | 6 | * |
6 | 7 | * Provide real functions which expand to whatever the header file defined. |
7 | 8 | * Also definitions of machine independent IO functions. |
9 | + * | |
10 | + * This file is subject to the terms and conditions of the GNU General Public | |
11 | + * License. See the file "COPYING" in the main directory of this archive | |
12 | + * for more details. | |
8 | 13 | */ |
9 | - | |
10 | -#include <asm/io.h> | |
11 | 14 | #include <linux/module.h> |
15 | +#include <asm/machvec.h> | |
16 | +#include <asm/io.h> | |
12 | 17 | |
13 | 18 | /* |
14 | 19 | * Copy data from IO memory space to "real" memory space. |
15 | 20 | * This needs to be optimized. |
16 | 21 | */ |
17 | -void memcpy_fromio(void * to, unsigned long from, unsigned long count) | |
22 | +void memcpy_fromio(void *to, volatile void __iomem *from, unsigned long count) | |
18 | 23 | { |
19 | 24 | char *p = to; |
20 | 25 | while (count) { |
21 | 26 | count--; |
22 | - *p = readb(from); | |
27 | + *p = readb((void __iomem *)from); | |
23 | 28 | p++; |
24 | 29 | from++; |
25 | 30 | } |
26 | 31 | } |
27 | - | |
32 | +EXPORT_SYMBOL(memcpy_fromio); | |
33 | + | |
28 | 34 | /* |
29 | 35 | * Copy data from "real" memory space to IO memory space. |
30 | 36 | * This needs to be optimized. |
31 | 37 | */ |
32 | -void memcpy_toio(unsigned long to, const void * from, unsigned long count) | |
38 | +void memcpy_toio(volatile void __iomem *to, const void *from, unsigned long count) | |
33 | 39 | { |
34 | 40 | const char *p = from; |
35 | 41 | while (count) { |
36 | 42 | count--; |
37 | - writeb(*p, to); | |
43 | + writeb(*p, (void __iomem *)to); | |
38 | 44 | p++; |
39 | 45 | to++; |
40 | 46 | } |
41 | 47 | } |
42 | - | |
48 | +EXPORT_SYMBOL(memcpy_toio); | |
49 | + | |
43 | 50 | /* |
44 | 51 | * "memset" on IO memory space. |
45 | 52 | * This needs to be optimized. |
46 | 53 | */ |
47 | -void memset_io(unsigned long dst, int c, unsigned long count) | |
54 | +void memset_io(volatile void __iomem *dst, int c, unsigned long count) | |
48 | 55 | { |
49 | 56 | while (count) { |
50 | 57 | count--; |
51 | - writeb(c, dst); | |
58 | + writeb(c, (void __iomem *)dst); | |
52 | 59 | dst++; |
53 | 60 | } |
54 | 61 | } |
55 | - | |
56 | -EXPORT_SYMBOL(memcpy_fromio); | |
57 | -EXPORT_SYMBOL(memcpy_toio); | |
58 | 62 | EXPORT_SYMBOL(memset_io); |
63 | + | |
64 | +void __iomem *ioport_map(unsigned long port, unsigned int nr) | |
65 | +{ | |
66 | + return sh_mv.mv_ioport_map(port, nr); | |
67 | +} | |
68 | +EXPORT_SYMBOL(ioport_map); | |
69 | + | |
70 | +void ioport_unmap(void __iomem *addr) | |
71 | +{ | |
72 | + sh_mv.mv_ioport_unmap(addr); | |
73 | +} | |
74 | +EXPORT_SYMBOL(ioport_unmap); |
arch/sh/kernel/io_generic.c
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | * linux/arch/sh/kernel/io_generic.c |
4 | 4 | * |
5 | 5 | * Copyright (C) 2000 Niibe Yutaka |
6 | + * Copyright (C) 2005 Paul Mundt | |
6 | 7 | * |
7 | 8 | * Generic I/O routine. These can be used where a machine specific version |
8 | 9 | * is not required. |
9 | 10 | |
10 | 11 | |
11 | 12 | |
12 | 13 | |
13 | 14 | |
... | ... | @@ -10,21 +11,20 @@ |
10 | 11 | * This file is subject to the terms and conditions of the GNU General Public |
11 | 12 | * License. See the file "COPYING" in the main directory of this archive |
12 | 13 | * for more details. |
13 | - * | |
14 | 14 | */ |
15 | - | |
15 | +#include <linux/module.h> | |
16 | 16 | #include <asm/io.h> |
17 | 17 | #include <asm/machvec.h> |
18 | -#include <linux/module.h> | |
19 | 18 | |
20 | -#if defined(CONFIG_CPU_SH3) | |
19 | +#ifdef CONFIG_CPU_SH3 | |
20 | +/* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a | |
21 | + * workaround. */ | |
21 | 22 | /* I'm not sure SH7709 has this kind of bug */ |
22 | -#define SH3_PCMCIA_BUG_WORKAROUND 1 | |
23 | -#define DUMMY_READ_AREA6 0xba000000 | |
23 | +#define dummy_read() ctrl_inb(0xba000000) | |
24 | +#else | |
25 | +#define dummy_read() | |
24 | 26 | #endif |
25 | 27 | |
26 | -#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) | |
27 | - | |
28 | 28 | unsigned long generic_io_base; |
29 | 29 | |
30 | 30 | static inline void delay(void) |
31 | 31 | |
32 | 32 | |
33 | 33 | |
34 | 34 | |
35 | 35 | |
36 | 36 | |
37 | 37 | |
38 | 38 | |
39 | 39 | |
40 | 40 | |
41 | 41 | |
... | ... | @@ -32,40 +32,40 @@ |
32 | 32 | ctrl_inw(0xa0000000); |
33 | 33 | } |
34 | 34 | |
35 | -unsigned char generic_inb(unsigned long port) | |
35 | +u8 generic_inb(unsigned long port) | |
36 | 36 | { |
37 | - return *(volatile unsigned char*)PORT2ADDR(port); | |
37 | + return ctrl_inb((unsigned long __force)ioport_map(port, 1)); | |
38 | 38 | } |
39 | 39 | |
40 | -unsigned short generic_inw(unsigned long port) | |
40 | +u16 generic_inw(unsigned long port) | |
41 | 41 | { |
42 | - return *(volatile unsigned short*)PORT2ADDR(port); | |
42 | + return ctrl_inw((unsigned long __force)ioport_map(port, 2)); | |
43 | 43 | } |
44 | 44 | |
45 | -unsigned int generic_inl(unsigned long port) | |
45 | +u32 generic_inl(unsigned long port) | |
46 | 46 | { |
47 | - return *(volatile unsigned long*)PORT2ADDR(port); | |
47 | + return ctrl_inl((unsigned long __force)ioport_map(port, 4)); | |
48 | 48 | } |
49 | 49 | |
50 | -unsigned char generic_inb_p(unsigned long port) | |
50 | +u8 generic_inb_p(unsigned long port) | |
51 | 51 | { |
52 | - unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); | |
52 | + unsigned long v = generic_inb(port); | |
53 | 53 | |
54 | 54 | delay(); |
55 | 55 | return v; |
56 | 56 | } |
57 | 57 | |
58 | -unsigned short generic_inw_p(unsigned long port) | |
58 | +u16 generic_inw_p(unsigned long port) | |
59 | 59 | { |
60 | - unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); | |
60 | + unsigned long v = generic_inw(port); | |
61 | 61 | |
62 | 62 | delay(); |
63 | 63 | return v; |
64 | 64 | } |
65 | 65 | |
66 | -unsigned int generic_inl_p(unsigned long port) | |
66 | +u32 generic_inl_p(unsigned long port) | |
67 | 67 | { |
68 | - unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); | |
68 | + unsigned long v = generic_inl(port); | |
69 | 69 | |
70 | 70 | delay(); |
71 | 71 | return v; |
72 | 72 | |
73 | 73 | |
74 | 74 | |
75 | 75 | |
76 | 76 | |
77 | 77 | |
78 | 78 | |
79 | 79 | |
80 | 80 | |
81 | 81 | |
82 | 82 | |
83 | 83 | |
84 | 84 | |
85 | 85 | |
86 | 86 | |
87 | 87 | |
88 | 88 | |
89 | 89 | |
90 | 90 | |
91 | 91 | |
92 | 92 | |
93 | 93 | |
... | ... | @@ -77,75 +77,70 @@ |
77 | 77 | * convert the port address to real address once. |
78 | 78 | */ |
79 | 79 | |
80 | -void generic_insb(unsigned long port, void *buffer, unsigned long count) | |
80 | +void generic_insb(unsigned long port, void *dst, unsigned long count) | |
81 | 81 | { |
82 | - volatile unsigned char *port_addr; | |
83 | - unsigned char *buf=buffer; | |
82 | + volatile u8 *port_addr; | |
83 | + u8 *buf = dst; | |
84 | 84 | |
85 | - port_addr = (volatile unsigned char *)PORT2ADDR(port); | |
86 | - | |
87 | - while(count--) | |
88 | - *buf++ = *port_addr; | |
85 | + port_addr = (volatile u8 *)ioport_map(port, 1); | |
86 | + while (count--) | |
87 | + *buf++ = *port_addr; | |
89 | 88 | } |
90 | 89 | |
91 | -void generic_insw(unsigned long port, void *buffer, unsigned long count) | |
90 | +void generic_insw(unsigned long port, void *dst, unsigned long count) | |
92 | 91 | { |
93 | - volatile unsigned short *port_addr; | |
94 | - unsigned short *buf=buffer; | |
92 | + volatile u16 *port_addr; | |
93 | + u16 *buf = dst; | |
95 | 94 | |
96 | - port_addr = (volatile unsigned short *)PORT2ADDR(port); | |
95 | + port_addr = (volatile u16 *)ioport_map(port, 2); | |
96 | + while (count--) | |
97 | + *buf++ = *port_addr; | |
97 | 98 | |
98 | - while(count--) | |
99 | - *buf++ = *port_addr; | |
100 | -#ifdef SH3_PCMCIA_BUG_WORKAROUND | |
101 | - ctrl_inb (DUMMY_READ_AREA6); | |
102 | -#endif | |
99 | + dummy_read(); | |
103 | 100 | } |
104 | 101 | |
105 | -void generic_insl(unsigned long port, void *buffer, unsigned long count) | |
102 | +void generic_insl(unsigned long port, void *dst, unsigned long count) | |
106 | 103 | { |
107 | - volatile unsigned long *port_addr; | |
108 | - unsigned long *buf=buffer; | |
104 | + volatile u32 *port_addr; | |
105 | + u32 *buf = dst; | |
109 | 106 | |
110 | - port_addr = (volatile unsigned long *)PORT2ADDR(port); | |
107 | + port_addr = (volatile u32 *)ioport_map(port, 4); | |
108 | + while (count--) | |
109 | + *buf++ = *port_addr; | |
111 | 110 | |
112 | - while(count--) | |
113 | - *buf++ = *port_addr; | |
114 | -#ifdef SH3_PCMCIA_BUG_WORKAROUND | |
115 | - ctrl_inb (DUMMY_READ_AREA6); | |
116 | -#endif | |
111 | + dummy_read(); | |
117 | 112 | } |
118 | 113 | |
119 | -void generic_outb(unsigned char b, unsigned long port) | |
114 | +void generic_outb(u8 b, unsigned long port) | |
120 | 115 | { |
121 | - *(volatile unsigned char*)PORT2ADDR(port) = b; | |
116 | + ctrl_outb(b, (unsigned long __force)ioport_map(port, 1)); | |
122 | 117 | } |
123 | 118 | |
124 | -void generic_outw(unsigned short b, unsigned long port) | |
119 | +void generic_outw(u16 b, unsigned long port) | |
125 | 120 | { |
126 | - *(volatile unsigned short*)PORT2ADDR(port) = b; | |
121 | + ctrl_outw(b, (unsigned long __force)ioport_map(port, 2)); | |
127 | 122 | } |
128 | 123 | |
129 | -void generic_outl(unsigned int b, unsigned long port) | |
124 | +void generic_outl(u32 b, unsigned long port) | |
130 | 125 | { |
131 | - *(volatile unsigned long*)PORT2ADDR(port) = b; | |
126 | + ctrl_outl(b, (unsigned long __force)ioport_map(port, 4)); | |
132 | 127 | } |
133 | 128 | |
134 | -void generic_outb_p(unsigned char b, unsigned long port) | |
129 | +void generic_outb_p(u8 b, unsigned long port) | |
135 | 130 | { |
136 | - *(volatile unsigned char*)PORT2ADDR(port) = b; | |
131 | + generic_outb(b, port); | |
137 | 132 | delay(); |
138 | 133 | } |
139 | 134 | |
140 | -void generic_outw_p(unsigned short b, unsigned long port) | |
135 | +void generic_outw_p(u16 b, unsigned long port) | |
141 | 136 | { |
142 | - *(volatile unsigned short*)PORT2ADDR(port) = b; | |
137 | + generic_outw(b, port); | |
143 | 138 | delay(); |
144 | 139 | } |
145 | 140 | |
146 | -void generic_outl_p(unsigned int b, unsigned long port) | |
141 | +void generic_outl_p(u32 b, unsigned long port) | |
147 | 142 | { |
148 | - *(volatile unsigned long*)PORT2ADDR(port) = b; | |
143 | + generic_outl(b, port); | |
149 | 144 | delay(); |
150 | 145 | } |
151 | 146 | |
152 | 147 | |
153 | 148 | |
154 | 149 | |
155 | 150 | |
156 | 151 | |
157 | 152 | |
158 | 153 | |
159 | 154 | |
160 | 155 | |
161 | 156 | |
162 | 157 | |
163 | 158 | |
164 | 159 | |
165 | 160 | |
166 | 161 | |
167 | 162 | |
168 | 163 | |
169 | 164 | |
170 | 165 | |
171 | 166 | |
172 | 167 | |
173 | 168 | |
174 | 169 | |
175 | 170 | |
176 | 171 | |
177 | 172 | |
178 | 173 | |
179 | 174 | |
180 | 175 | |
... | ... | @@ -154,91 +149,78 @@ |
154 | 149 | * address. However as the port address doesn't change we only need to |
155 | 150 | * convert the port address to real address once. |
156 | 151 | */ |
157 | - | |
158 | -void generic_outsb(unsigned long port, const void *buffer, unsigned long count) | |
152 | +void generic_outsb(unsigned long port, const void *src, unsigned long count) | |
159 | 153 | { |
160 | - volatile unsigned char *port_addr; | |
161 | - const unsigned char *buf=buffer; | |
154 | + volatile u8 *port_addr; | |
155 | + const u8 *buf = src; | |
162 | 156 | |
163 | - port_addr = (volatile unsigned char *)PORT2ADDR(port); | |
157 | + port_addr = (volatile u8 __force *)ioport_map(port, 1); | |
164 | 158 | |
165 | - while(count--) | |
166 | - *port_addr = *buf++; | |
159 | + while (count--) | |
160 | + *port_addr = *buf++; | |
167 | 161 | } |
168 | 162 | |
169 | -void generic_outsw(unsigned long port, const void *buffer, unsigned long count) | |
163 | +void generic_outsw(unsigned long port, const void *src, unsigned long count) | |
170 | 164 | { |
171 | - volatile unsigned short *port_addr; | |
172 | - const unsigned short *buf=buffer; | |
165 | + volatile u16 *port_addr; | |
166 | + const u16 *buf = src; | |
173 | 167 | |
174 | - port_addr = (volatile unsigned short *)PORT2ADDR(port); | |
168 | + port_addr = (volatile u16 __force *)ioport_map(port, 2); | |
175 | 169 | |
176 | - while(count--) | |
177 | - *port_addr = *buf++; | |
170 | + while (count--) | |
171 | + *port_addr = *buf++; | |
178 | 172 | |
179 | -#ifdef SH3_PCMCIA_BUG_WORKAROUND | |
180 | - ctrl_inb (DUMMY_READ_AREA6); | |
181 | -#endif | |
173 | + dummy_read(); | |
182 | 174 | } |
183 | 175 | |
184 | -void generic_outsl(unsigned long port, const void *buffer, unsigned long count) | |
176 | +void generic_outsl(unsigned long port, const void *src, unsigned long count) | |
185 | 177 | { |
186 | - volatile unsigned long *port_addr; | |
187 | - const unsigned long *buf=buffer; | |
178 | + volatile u32 *port_addr; | |
179 | + const u32 *buf = src; | |
188 | 180 | |
189 | - port_addr = (volatile unsigned long *)PORT2ADDR(port); | |
181 | + port_addr = (volatile u32 __force *)ioport_map(port, 4); | |
182 | + while (count--) | |
183 | + *port_addr = *buf++; | |
190 | 184 | |
191 | - while(count--) | |
192 | - *port_addr = *buf++; | |
193 | - | |
194 | -#ifdef SH3_PCMCIA_BUG_WORKAROUND | |
195 | - ctrl_inb (DUMMY_READ_AREA6); | |
196 | -#endif | |
185 | + dummy_read(); | |
197 | 186 | } |
198 | 187 | |
199 | -unsigned char generic_readb(unsigned long addr) | |
188 | +u8 generic_readb(void __iomem *addr) | |
200 | 189 | { |
201 | - return *(volatile unsigned char*)addr; | |
190 | + return ctrl_inb((unsigned long __force)addr); | |
202 | 191 | } |
203 | 192 | |
204 | -unsigned short generic_readw(unsigned long addr) | |
193 | +u16 generic_readw(void __iomem *addr) | |
205 | 194 | { |
206 | - return *(volatile unsigned short*)addr; | |
195 | + return ctrl_inw((unsigned long __force)addr); | |
207 | 196 | } |
208 | 197 | |
209 | -unsigned int generic_readl(unsigned long addr) | |
198 | +u32 generic_readl(void __iomem *addr) | |
210 | 199 | { |
211 | - return *(volatile unsigned long*)addr; | |
200 | + return ctrl_inl((unsigned long __force)addr); | |
212 | 201 | } |
213 | 202 | |
214 | -void generic_writeb(unsigned char b, unsigned long addr) | |
203 | +void generic_writeb(u8 b, void __iomem *addr) | |
215 | 204 | { |
216 | - *(volatile unsigned char*)addr = b; | |
205 | + ctrl_outb(b, (unsigned long __force)addr); | |
217 | 206 | } |
218 | 207 | |
219 | -void generic_writew(unsigned short b, unsigned long addr) | |
208 | +void generic_writew(u16 b, void __iomem *addr) | |
220 | 209 | { |
221 | - *(volatile unsigned short*)addr = b; | |
210 | + ctrl_outw(b, (unsigned long __force)addr); | |
222 | 211 | } |
223 | 212 | |
224 | -void generic_writel(unsigned int b, unsigned long addr) | |
213 | +void generic_writel(u32 b, void __iomem *addr) | |
225 | 214 | { |
226 | - *(volatile unsigned long*)addr = b; | |
215 | + ctrl_outl(b, (unsigned long __force)addr); | |
227 | 216 | } |
228 | 217 | |
229 | -void * generic_ioremap(unsigned long offset, unsigned long size) | |
218 | +void __iomem *generic_ioport_map(unsigned long addr, unsigned int size) | |
230 | 219 | { |
231 | - return (void *) P2SEGADDR(offset); | |
220 | + return (void __iomem *)(addr + generic_io_base); | |
232 | 221 | } |
233 | -EXPORT_SYMBOL(generic_ioremap); | |
234 | 222 | |
235 | -void generic_iounmap(void *addr) | |
223 | +void generic_ioport_unmap(void __iomem *addr) | |
236 | 224 | { |
237 | -} | |
238 | -EXPORT_SYMBOL(generic_iounmap); | |
239 | - | |
240 | -unsigned long generic_isa_port2addr(unsigned long offset) | |
241 | -{ | |
242 | - return offset + generic_io_base; | |
243 | 225 | } |
arch/sh/mm/ioremap.c
... | ... | @@ -6,13 +6,19 @@ |
6 | 6 | * 640k-1MB IO memory area on PC's |
7 | 7 | * |
8 | 8 | * (C) Copyright 1995 1996 Linus Torvalds |
9 | + * (C) Copyright 2005, 2006 Paul Mundt | |
10 | + * | |
11 | + * This file is subject to the terms and conditions of the GNU General | |
12 | + * Public License. See the file "COPYING" in the main directory of this | |
13 | + * archive for more details. | |
9 | 14 | */ |
10 | - | |
11 | 15 | #include <linux/vmalloc.h> |
16 | +#include <linux/module.h> | |
12 | 17 | #include <linux/mm.h> |
13 | 18 | #include <asm/io.h> |
14 | 19 | #include <asm/page.h> |
15 | 20 | #include <asm/pgalloc.h> |
21 | +#include <asm/addrspace.h> | |
16 | 22 | #include <asm/cacheflush.h> |
17 | 23 | #include <asm/tlbflush.h> |
18 | 24 | |
19 | 25 | |
20 | 26 | |
... | ... | @@ -80,9 +86,15 @@ |
80 | 86 | if (address >= end) |
81 | 87 | BUG(); |
82 | 88 | do { |
89 | + pud_t *pud; | |
83 | 90 | pmd_t *pmd; |
84 | - pmd = pmd_alloc(&init_mm, dir, address); | |
91 | + | |
85 | 92 | error = -ENOMEM; |
93 | + | |
94 | + pud = pud_alloc(&init_mm, dir, address); | |
95 | + if (!pud) | |
96 | + break; | |
97 | + pmd = pmd_alloc(&init_mm, pud, address); | |
86 | 98 | if (!pmd) |
87 | 99 | break; |
88 | 100 | if (remap_area_pmd(pmd, address, end - address, |
... | ... | @@ -97,10 +109,6 @@ |
97 | 109 | } |
98 | 110 | |
99 | 111 | /* |
100 | - * Generic mapping function (not visible outside): | |
101 | - */ | |
102 | - | |
103 | -/* | |
104 | 112 | * Remap an arbitrary physical address space into the kernel virtual |
105 | 113 | * address space. Needed when the kernel wants to access high addresses |
106 | 114 | * directly. |
107 | 115 | |
108 | 116 | |
... | ... | @@ -109,11 +117,11 @@ |
109 | 117 | * have to convert them into an offset in a page-aligned mapping, but the |
110 | 118 | * caller shouldn't need to know that small detail. |
111 | 119 | */ |
112 | -void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) | |
120 | +void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, | |
121 | + unsigned long flags) | |
113 | 122 | { |
114 | - void * addr; | |
115 | 123 | struct vm_struct * area; |
116 | - unsigned long offset, last_addr; | |
124 | + unsigned long offset, last_addr, addr, orig_addr; | |
117 | 125 | |
118 | 126 | /* Don't allow wraparound or zero size */ |
119 | 127 | last_addr = phys_addr + size - 1; |
... | ... | @@ -124,7 +132,7 @@ |
124 | 132 | * Don't remap the low PCI/ISA area, it's always mapped.. |
125 | 133 | */ |
126 | 134 | if (phys_addr >= 0xA0000 && last_addr < 0x100000) |
127 | - return phys_to_virt(phys_addr); | |
135 | + return (void __iomem *)phys_to_virt(phys_addr); | |
128 | 136 | |
129 | 137 | /* |
130 | 138 | * Don't allow anybody to remap normal RAM that we're using.. |
131 | 139 | |
132 | 140 | |
133 | 141 | |
134 | 142 | |
135 | 143 | |
... | ... | @@ -146,17 +154,72 @@ |
146 | 154 | if (!area) |
147 | 155 | return NULL; |
148 | 156 | area->phys_addr = phys_addr; |
149 | - addr = area->addr; | |
150 | - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { | |
151 | - vunmap(addr); | |
152 | - return NULL; | |
157 | + orig_addr = addr = (unsigned long)area->addr; | |
158 | + | |
159 | +#ifdef CONFIG_32BIT | |
160 | + /* | |
161 | + * First try to remap through the PMB once a valid VMA has been | |
162 | + * established. Smaller allocations (or the rest of the size | |
163 | + * remaining after a PMB mapping due to the size not being | |
164 | + * perfectly aligned on a PMB size boundary) are then mapped | |
165 | + * through the UTLB using conventional page tables. | |
166 | + * | |
167 | + * PMB entries are all pre-faulted. | |
168 | + */ | |
169 | + if (unlikely(size >= 0x1000000)) { | |
170 | + unsigned long mapped = pmb_remap(addr, phys_addr, size, flags); | |
171 | + | |
172 | + if (likely(mapped)) { | |
173 | + addr += mapped; | |
174 | + phys_addr += mapped; | |
175 | + size -= mapped; | |
176 | + } | |
153 | 177 | } |
154 | - return (void *) (offset + (char *)addr); | |
178 | +#endif | |
179 | + | |
180 | + if (likely(size)) | |
181 | + if (remap_area_pages(addr, phys_addr, size, flags)) { | |
182 | + vunmap((void *)orig_addr); | |
183 | + return NULL; | |
184 | + } | |
185 | + | |
186 | + return (void __iomem *)(offset + (char *)orig_addr); | |
155 | 187 | } |
188 | +EXPORT_SYMBOL(__ioremap); | |
156 | 189 | |
157 | -void p3_iounmap(void *addr) | |
190 | +void __iounmap(void __iomem *addr) | |
158 | 191 | { |
159 | - if (addr > high_memory) | |
160 | - vfree((void *)(PAGE_MASK & (unsigned long)addr)); | |
192 | + unsigned long vaddr = (unsigned long __force)addr; | |
193 | + struct vm_struct *p; | |
194 | + | |
195 | + if (PXSEG(vaddr) < P3SEG) | |
196 | + return; | |
197 | + | |
198 | +#ifdef CONFIG_32BIT | |
199 | + /* | |
200 | + * Purge any PMB entries that may have been established for this | |
201 | + * mapping, then proceed with conventional VMA teardown. | |
202 | + * | |
203 | + * XXX: Note that due to the way that remove_vm_area() does | |
204 | + * matching of the resultant VMA, we aren't able to fast-forward | |
205 | + * the address past the PMB space until the end of the VMA where | |
206 | + * the page tables reside. As such, unmap_vm_area() will be | |
207 | + * forced to linearly scan over the area until it finds the page | |
208 | + * tables where PTEs that need to be unmapped actually reside, | |
209 | + * which is far from optimal. Perhaps we need to use a separate | |
210 | + * VMA for the PMB mappings? | |
211 | + * -- PFM. | |
212 | + */ | |
213 | + pmb_unmap(vaddr); | |
214 | +#endif | |
215 | + | |
216 | + p = remove_vm_area((void *)(vaddr & PAGE_MASK)); | |
217 | + if (!p) { | |
218 | + printk(KERN_ERR "%s: bad address %p\n", __FUNCTION__, addr); | |
219 | + return; | |
220 | + } | |
221 | + | |
222 | + kfree(p); | |
161 | 223 | } |
224 | +EXPORT_SYMBOL(__iounmap); |
include/asm-sh/io.h
... | ... | @@ -11,7 +11,7 @@ |
11 | 11 | * For read{b,w,l} and write{b,w,l} there are also __raw versions, which |
12 | 12 | * do not have a memory barrier after them. |
13 | 13 | * |
14 | - * In addition, we have | |
14 | + * In addition, we have | |
15 | 15 | * ctrl_in{b,w,l}/ctrl_out{b,w,l} for SuperH specific I/O. |
16 | 16 | * which are processor specific. |
17 | 17 | */ |
18 | 18 | |
19 | 19 | |
20 | 20 | |
21 | 21 | |
... | ... | @@ -23,19 +23,27 @@ |
23 | 23 | * inb by default expands to _inb, but the machine specific code may |
24 | 24 | * define it to __inb if it chooses. |
25 | 25 | */ |
26 | - | |
26 | +#include <linux/config.h> | |
27 | 27 | #include <asm/cache.h> |
28 | 28 | #include <asm/system.h> |
29 | 29 | #include <asm/addrspace.h> |
30 | 30 | #include <asm/machvec.h> |
31 | -#include <linux/config.h> | |
31 | +#include <asm/pgtable.h> | |
32 | +#include <asm-generic/iomap.h> | |
32 | 33 | |
34 | +#ifdef __KERNEL__ | |
35 | + | |
33 | 36 | /* |
34 | 37 | * Depending on which platform we are running on, we need different |
35 | 38 | * I/O functions. |
36 | 39 | */ |
40 | +#define __IO_PREFIX generic | |
41 | +#include <asm/io_generic.h> | |
37 | 42 | |
38 | -#ifdef __KERNEL__ | |
43 | +#define maybebadio(port) \ | |
44 | + printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \ | |
45 | + __FUNCTION__, __LINE__, (port), (u32)__builtin_return_address(0)) | |
46 | + | |
39 | 47 | /* |
40 | 48 | * Since boards are able to define their own set of I/O routines through |
41 | 49 | * their respective machine vector, we always wrap through the mv. |
42 | 50 | |
43 | 51 | |
44 | 52 | |
45 | 53 | |
46 | 54 | |
47 | 55 | |
48 | 56 | |
49 | 57 | |
50 | 58 | |
51 | 59 | |
52 | 60 | |
53 | 61 | |
54 | 62 | |
55 | 63 | |
56 | 64 | |
57 | 65 | |
58 | 66 | |
59 | 67 | |
60 | 68 | |
... | ... | @@ -44,113 +52,120 @@ |
44 | 52 | * a given routine, it will be wrapped to generic code at run-time. |
45 | 53 | */ |
46 | 54 | |
47 | -# define __inb(p) sh_mv.mv_inb((p)) | |
48 | -# define __inw(p) sh_mv.mv_inw((p)) | |
49 | -# define __inl(p) sh_mv.mv_inl((p)) | |
50 | -# define __outb(x,p) sh_mv.mv_outb((x),(p)) | |
51 | -# define __outw(x,p) sh_mv.mv_outw((x),(p)) | |
52 | -# define __outl(x,p) sh_mv.mv_outl((x),(p)) | |
55 | +#define __inb(p) sh_mv.mv_inb((p)) | |
56 | +#define __inw(p) sh_mv.mv_inw((p)) | |
57 | +#define __inl(p) sh_mv.mv_inl((p)) | |
58 | +#define __outb(x,p) sh_mv.mv_outb((x),(p)) | |
59 | +#define __outw(x,p) sh_mv.mv_outw((x),(p)) | |
60 | +#define __outl(x,p) sh_mv.mv_outl((x),(p)) | |
53 | 61 | |
54 | -# define __inb_p(p) sh_mv.mv_inb_p((p)) | |
55 | -# define __inw_p(p) sh_mv.mv_inw_p((p)) | |
56 | -# define __inl_p(p) sh_mv.mv_inl_p((p)) | |
57 | -# define __outb_p(x,p) sh_mv.mv_outb_p((x),(p)) | |
58 | -# define __outw_p(x,p) sh_mv.mv_outw_p((x),(p)) | |
59 | -# define __outl_p(x,p) sh_mv.mv_outl_p((x),(p)) | |
62 | +#define __inb_p(p) sh_mv.mv_inb_p((p)) | |
63 | +#define __inw_p(p) sh_mv.mv_inw_p((p)) | |
64 | +#define __inl_p(p) sh_mv.mv_inl_p((p)) | |
65 | +#define __outb_p(x,p) sh_mv.mv_outb_p((x),(p)) | |
66 | +#define __outw_p(x,p) sh_mv.mv_outw_p((x),(p)) | |
67 | +#define __outl_p(x,p) sh_mv.mv_outl_p((x),(p)) | |
60 | 68 | |
61 | -# define __insb(p,b,c) sh_mv.mv_insb((p), (b), (c)) | |
62 | -# define __insw(p,b,c) sh_mv.mv_insw((p), (b), (c)) | |
63 | -# define __insl(p,b,c) sh_mv.mv_insl((p), (b), (c)) | |
64 | -# define __outsb(p,b,c) sh_mv.mv_outsb((p), (b), (c)) | |
65 | -# define __outsw(p,b,c) sh_mv.mv_outsw((p), (b), (c)) | |
66 | -# define __outsl(p,b,c) sh_mv.mv_outsl((p), (b), (c)) | |
69 | +#define __insb(p,b,c) sh_mv.mv_insb((p), (b), (c)) | |
70 | +#define __insw(p,b,c) sh_mv.mv_insw((p), (b), (c)) | |
71 | +#define __insl(p,b,c) sh_mv.mv_insl((p), (b), (c)) | |
72 | +#define __outsb(p,b,c) sh_mv.mv_outsb((p), (b), (c)) | |
73 | +#define __outsw(p,b,c) sh_mv.mv_outsw((p), (b), (c)) | |
74 | +#define __outsl(p,b,c) sh_mv.mv_outsl((p), (b), (c)) | |
67 | 75 | |
68 | -# define __readb(a) sh_mv.mv_readb((a)) | |
69 | -# define __readw(a) sh_mv.mv_readw((a)) | |
70 | -# define __readl(a) sh_mv.mv_readl((a)) | |
71 | -# define __writeb(v,a) sh_mv.mv_writeb((v),(a)) | |
72 | -# define __writew(v,a) sh_mv.mv_writew((v),(a)) | |
73 | -# define __writel(v,a) sh_mv.mv_writel((v),(a)) | |
76 | +#define __readb(a) sh_mv.mv_readb((a)) | |
77 | +#define __readw(a) sh_mv.mv_readw((a)) | |
78 | +#define __readl(a) sh_mv.mv_readl((a)) | |
79 | +#define __writeb(v,a) sh_mv.mv_writeb((v),(a)) | |
80 | +#define __writew(v,a) sh_mv.mv_writew((v),(a)) | |
81 | +#define __writel(v,a) sh_mv.mv_writel((v),(a)) | |
74 | 82 | |
75 | -# define __ioremap(a,s) sh_mv.mv_ioremap((a), (s)) | |
76 | -# define __iounmap(a) sh_mv.mv_iounmap((a)) | |
83 | +#define inb __inb | |
84 | +#define inw __inw | |
85 | +#define inl __inl | |
86 | +#define outb __outb | |
87 | +#define outw __outw | |
88 | +#define outl __outl | |
77 | 89 | |
78 | -# define __isa_port2addr(a) sh_mv.mv_isa_port2addr(a) | |
90 | +#define inb_p __inb_p | |
91 | +#define inw_p __inw_p | |
92 | +#define inl_p __inl_p | |
93 | +#define outb_p __outb_p | |
94 | +#define outw_p __outw_p | |
95 | +#define outl_p __outl_p | |
79 | 96 | |
80 | -# define inb __inb | |
81 | -# define inw __inw | |
82 | -# define inl __inl | |
83 | -# define outb __outb | |
84 | -# define outw __outw | |
85 | -# define outl __outl | |
97 | +#define insb __insb | |
98 | +#define insw __insw | |
99 | +#define insl __insl | |
100 | +#define outsb __outsb | |
101 | +#define outsw __outsw | |
102 | +#define outsl __outsl | |
86 | 103 | |
87 | -# define inb_p __inb_p | |
88 | -# define inw_p __inw_p | |
89 | -# define inl_p __inl_p | |
90 | -# define outb_p __outb_p | |
91 | -# define outw_p __outw_p | |
92 | -# define outl_p __outl_p | |
104 | +#define __raw_readb(a) __readb((void __iomem *)(a)) | |
105 | +#define __raw_readw(a) __readw((void __iomem *)(a)) | |
106 | +#define __raw_readl(a) __readl((void __iomem *)(a)) | |
107 | +#define __raw_writeb(v, a) __writeb(v, (void __iomem *)(a)) | |
108 | +#define __raw_writew(v, a) __writew(v, (void __iomem *)(a)) | |
109 | +#define __raw_writel(v, a) __writel(v, (void __iomem *)(a)) | |
93 | 110 | |
94 | -# define insb __insb | |
95 | -# define insw __insw | |
96 | -# define insl __insl | |
97 | -# define outsb __outsb | |
98 | -# define outsw __outsw | |
99 | -# define outsl __outsl | |
100 | - | |
101 | -# define __raw_readb __readb | |
102 | -# define __raw_readw __readw | |
103 | -# define __raw_readl __readl | |
104 | -# define __raw_writeb __writeb | |
105 | -# define __raw_writew __writew | |
106 | -# define __raw_writel __writel | |
107 | - | |
108 | 111 | /* |
109 | 112 | * The platform header files may define some of these macros to use |
110 | 113 | * the inlined versions where appropriate. These macros may also be |
111 | 114 | * redefined by userlevel programs. |
112 | 115 | */ |
113 | -#ifdef __raw_readb | |
114 | -# define readb(a) ({ unsigned long r_ = __raw_readb((unsigned long)a); mb(); r_; }) | |
116 | +#ifdef __readb | |
117 | +# define readb(a) ({ unsigned long r_ = __raw_readb(a); mb(); r_; }) | |
115 | 118 | #endif |
116 | 119 | #ifdef __raw_readw |
117 | -# define readw(a) ({ unsigned long r_ = __raw_readw((unsigned long)a); mb(); r_; }) | |
120 | +# define readw(a) ({ unsigned long r_ = __raw_readw(a); mb(); r_; }) | |
118 | 121 | #endif |
119 | 122 | #ifdef __raw_readl |
120 | -# define readl(a) ({ unsigned long r_ = __raw_readl((unsigned long)a); mb(); r_; }) | |
123 | +# define readl(a) ({ unsigned long r_ = __raw_readl(a); mb(); r_; }) | |
121 | 124 | #endif |
122 | 125 | |
123 | 126 | #ifdef __raw_writeb |
124 | -# define writeb(v,a) ({ __raw_writeb((v),(unsigned long)(a)); mb(); }) | |
127 | +# define writeb(v,a) ({ __raw_writeb((v),(a)); mb(); }) | |
125 | 128 | #endif |
126 | 129 | #ifdef __raw_writew |
127 | -# define writew(v,a) ({ __raw_writew((v),(unsigned long)(a)); mb(); }) | |
130 | +# define writew(v,a) ({ __raw_writew((v),(a)); mb(); }) | |
128 | 131 | #endif |
129 | 132 | #ifdef __raw_writel |
130 | -# define writel(v,a) ({ __raw_writel((v),(unsigned long)(a)); mb(); }) | |
133 | +# define writel(v,a) ({ __raw_writel((v),(a)); mb(); }) | |
131 | 134 | #endif |
132 | 135 | |
133 | 136 | #define readb_relaxed(a) readb(a) |
134 | 137 | #define readw_relaxed(a) readw(a) |
135 | 138 | #define readl_relaxed(a) readl(a) |
136 | 139 | |
137 | -#define mmiowb() | |
140 | +/* Simple MMIO */ | |
141 | +#define ioread8(a) readb(a) | |
142 | +#define ioread16(a) readw(a) | |
143 | +#define ioread16be(a) be16_to_cpu(__raw_readw((a))) | |
144 | +#define ioread32(a) readl(a) | |
145 | +#define ioread32be(a) be32_to_cpu(__raw_readl((a))) | |
138 | 146 | |
139 | -/* | |
140 | - * If the platform has PC-like I/O, this function converts the offset into | |
141 | - * an address. | |
142 | - */ | |
143 | -static __inline__ unsigned long isa_port2addr(unsigned long offset) | |
144 | -{ | |
145 | - return __isa_port2addr(offset); | |
146 | -} | |
147 | +#define iowrite8(v,a) writeb((v),(a)) | |
148 | +#define iowrite16(v,a) writew((v),(a)) | |
149 | +#define iowrite16be(v,a) __raw_writew(cpu_to_be16((v)),(a)) | |
150 | +#define iowrite32(v,a) writel((v),(a)) | |
151 | +#define iowrite32be(v,a) __raw_writel(cpu_to_be32((v)),(a)) | |
147 | 152 | |
153 | +#define ioread8_rep(a,d,c) insb((a),(d),(c)) | |
154 | +#define ioread16_rep(a,d,c) insw((a),(d),(c)) | |
155 | +#define ioread32_rep(a,d,c) insl((a),(d),(c)) | |
156 | + | |
157 | +#define iowrite8_rep(a,s,c) outsb((a),(s),(c)) | |
158 | +#define iowrite16_rep(a,s,c) outsw((a),(s),(c)) | |
159 | +#define iowrite32_rep(a,s,c) outsl((a),(s),(c)) | |
160 | + | |
161 | +#define mmiowb() wmb() /* synco on SH-4A, otherwise a nop */ | |
162 | + | |
148 | 163 | /* |
149 | 164 | * This function provides a method for the generic case where a board-specific |
150 | - * isa_port2addr simply needs to return the port + some arbitrary port base. | |
165 | + * ioport_map simply needs to return the port + some arbitrary port base. | |
151 | 166 | * |
152 | 167 | * We use this at board setup time to implicitly set the port base, and |
153 | - * as a result, we can use the generic isa_port2addr. | |
168 | + * as a result, we can use the generic ioport_map. | |
154 | 169 | */ |
155 | 170 | static inline void __set_io_port_base(unsigned long pbase) |
156 | 171 | { |
157 | 172 | |
158 | 173 | |
159 | 174 | |
160 | 175 | |
161 | 176 | |
162 | 177 | |
163 | 178 | |
164 | 179 | |
165 | 180 | |
166 | 181 | |
... | ... | @@ -159,51 +174,52 @@ |
159 | 174 | generic_io_base = pbase; |
160 | 175 | } |
161 | 176 | |
162 | -#define isa_readb(a) readb(isa_port2addr(a)) | |
163 | -#define isa_readw(a) readw(isa_port2addr(a)) | |
164 | -#define isa_readl(a) readl(isa_port2addr(a)) | |
165 | -#define isa_writeb(b,a) writeb(b,isa_port2addr(a)) | |
166 | -#define isa_writew(w,a) writew(w,isa_port2addr(a)) | |
167 | -#define isa_writel(l,a) writel(l,isa_port2addr(a)) | |
177 | +#define isa_readb(a) readb(ioport_map(a, 1)) | |
178 | +#define isa_readw(a) readw(ioport_map(a, 2)) | |
179 | +#define isa_readl(a) readl(ioport_map(a, 4)) | |
180 | +#define isa_writeb(b,a) writeb(b,ioport_map(a, 1)) | |
181 | +#define isa_writew(w,a) writew(w,ioport_map(a, 2)) | |
182 | +#define isa_writel(l,a) writel(l,ioport_map(a, 4)) | |
183 | + | |
168 | 184 | #define isa_memset_io(a,b,c) \ |
169 | - memset((void *)(isa_port2addr((unsigned long)a)),(b),(c)) | |
185 | + memset((void *)(ioport_map((unsigned long)(a), 1)),(b),(c)) | |
170 | 186 | #define isa_memcpy_fromio(a,b,c) \ |
171 | - memcpy((a),(void *)(isa_port2addr((unsigned long)(b))),(c)) | |
187 | + memcpy((a),(void *)(ioport_map((unsigned long)(b), 1)),(c)) | |
172 | 188 | #define isa_memcpy_toio(a,b,c) \ |
173 | - memcpy((void *)(isa_port2addr((unsigned long)(a))),(b),(c)) | |
189 | + memcpy((void *)(ioport_map((unsigned long)(a), 1)),(b),(c)) | |
174 | 190 | |
175 | 191 | /* We really want to try and get these to memcpy etc */ |
176 | -extern void memcpy_fromio(void *, unsigned long, unsigned long); | |
177 | -extern void memcpy_toio(unsigned long, const void *, unsigned long); | |
178 | -extern void memset_io(unsigned long, int, unsigned long); | |
192 | +extern void memcpy_fromio(void *, volatile void __iomem *, unsigned long); | |
193 | +extern void memcpy_toio(volatile void __iomem *, const void *, unsigned long); | |
194 | +extern void memset_io(volatile void __iomem *, int, unsigned long); | |
179 | 195 | |
180 | 196 | /* SuperH on-chip I/O functions */ |
181 | -static __inline__ unsigned char ctrl_inb(unsigned long addr) | |
197 | +static inline unsigned char ctrl_inb(unsigned long addr) | |
182 | 198 | { |
183 | 199 | return *(volatile unsigned char*)addr; |
184 | 200 | } |
185 | 201 | |
186 | -static __inline__ unsigned short ctrl_inw(unsigned long addr) | |
202 | +static inline unsigned short ctrl_inw(unsigned long addr) | |
187 | 203 | { |
188 | 204 | return *(volatile unsigned short*)addr; |
189 | 205 | } |
190 | 206 | |
191 | -static __inline__ unsigned int ctrl_inl(unsigned long addr) | |
207 | +static inline unsigned int ctrl_inl(unsigned long addr) | |
192 | 208 | { |
193 | 209 | return *(volatile unsigned long*)addr; |
194 | 210 | } |
195 | 211 | |
196 | -static __inline__ void ctrl_outb(unsigned char b, unsigned long addr) | |
212 | +static inline void ctrl_outb(unsigned char b, unsigned long addr) | |
197 | 213 | { |
198 | 214 | *(volatile unsigned char*)addr = b; |
199 | 215 | } |
200 | 216 | |
201 | -static __inline__ void ctrl_outw(unsigned short b, unsigned long addr) | |
217 | +static inline void ctrl_outw(unsigned short b, unsigned long addr) | |
202 | 218 | { |
203 | 219 | *(volatile unsigned short*)addr = b; |
204 | 220 | } |
205 | 221 | |
206 | -static __inline__ void ctrl_outl(unsigned int b, unsigned long addr) | |
222 | +static inline void ctrl_outl(unsigned int b, unsigned long addr) | |
207 | 223 | { |
208 | 224 | *(volatile unsigned long*)addr = b; |
209 | 225 | } |
210 | 226 | |
... | ... | @@ -214,12 +230,12 @@ |
214 | 230 | * Change virtual addresses to physical addresses and vv. |
215 | 231 | * These are trivial on the 1:1 Linux/SuperH mapping |
216 | 232 | */ |
217 | -static __inline__ unsigned long virt_to_phys(volatile void * address) | |
233 | +static inline unsigned long virt_to_phys(volatile void *address) | |
218 | 234 | { |
219 | 235 | return PHYSADDR(address); |
220 | 236 | } |
221 | 237 | |
222 | -static __inline__ void * phys_to_virt(unsigned long address) | |
238 | +static inline void *phys_to_virt(unsigned long address) | |
223 | 239 | { |
224 | 240 | return (void *)P1SEGADDR(address); |
225 | 241 | } |
226 | 242 | |
227 | 243 | |
228 | 244 | |
229 | 245 | |
230 | 246 | |
231 | 247 | |
... | ... | @@ -234,27 +250,60 @@ |
234 | 250 | * differently. On the x86 architecture, we just read/write the |
235 | 251 | * memory location directly. |
236 | 252 | * |
237 | - * On SH, we have the whole physical address space mapped at all times | |
238 | - * (as MIPS does), so "ioremap()" and "iounmap()" do not need to do | |
239 | - * anything. (This isn't true for all machines but we still handle | |
240 | - * these cases with wired TLB entries anyway ...) | |
253 | + * On SH, we traditionally have the whole physical address space mapped | |
254 | + * at all times (as MIPS does), so "ioremap()" and "iounmap()" do not | |
255 | + * need to do anything but place the address in the proper segment. This | |
256 | + * is true for P1 and P2 addresses, as well as some P3 ones. However, | |
257 | + * most of the P3 addresses and newer cores using extended addressing | |
258 | + * need to map through page tables, so the ioremap() implementation | |
259 | + * becomes a bit more complicated. See arch/sh/mm/ioremap.c for | |
260 | + * additional notes on this. | |
241 | 261 | * |
242 | 262 | * We cheat a bit and always return uncachable areas until we've fixed |
243 | - * the drivers to handle caching properly. | |
263 | + * the drivers to handle caching properly. | |
244 | 264 | */ |
245 | -static __inline__ void * ioremap(unsigned long offset, unsigned long size) | |
246 | -{ | |
247 | - return __ioremap(offset, size); | |
248 | -} | |
265 | +#ifdef CONFIG_MMU | |
266 | +void __iomem *__ioremap(unsigned long offset, unsigned long size, | |
267 | + unsigned long flags); | |
268 | +void __iounmap(void __iomem *addr); | |
269 | +#else | |
270 | +#define __ioremap(offset, size, flags) ((void __iomem *)(offset)) | |
271 | +#define __iounmap(addr) do { } while (0) | |
272 | +#endif /* CONFIG_MMU */ | |
249 | 273 | |
250 | -static __inline__ void iounmap(void *addr) | |
274 | +static inline void __iomem * | |
275 | +__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) | |
251 | 276 | { |
252 | - return __iounmap(addr); | |
277 | + unsigned long last_addr = offset + size - 1; | |
278 | + | |
279 | + /* | |
280 | + * For P1 and P2 space this is trivial, as everything is already | |
281 | + * mapped. Uncached access for P1 addresses are done through P2. | |
282 | + * In the P3 case or for addresses outside of the 29-bit space, | |
283 | + * mapping must be done by the PMB or by using page tables. | |
284 | + */ | |
285 | + if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) { | |
286 | + if (unlikely(flags & _PAGE_CACHABLE)) | |
287 | + return (void __iomem *)P1SEGADDR(offset); | |
288 | + | |
289 | + return (void __iomem *)P2SEGADDR(offset); | |
290 | + } | |
291 | + | |
292 | + return __ioremap(offset, size, flags); | |
253 | 293 | } |
254 | 294 | |
255 | -#define ioremap_nocache(off,size) ioremap(off,size) | |
295 | +#define ioremap(offset, size) \ | |
296 | + __ioremap_mode((offset), (size), 0) | |
297 | +#define ioremap_nocache(offset, size) \ | |
298 | + __ioremap_mode((offset), (size), 0) | |
299 | +#define ioremap_cache(offset, size) \ | |
300 | + __ioremap_mode((offset), (size), _PAGE_CACHABLE) | |
301 | +#define p3_ioremap(offset, size, flags) \ | |
302 | + __ioremap((offset), (size), (flags)) | |
303 | +#define iounmap(addr) \ | |
304 | + __iounmap((addr)) | |
256 | 305 | |
257 | -static __inline__ int check_signature(unsigned long io_addr, | |
306 | +static inline int check_signature(char __iomem *io_addr, | |
258 | 307 | const unsigned char *signature, int length) |
259 | 308 | { |
260 | 309 | int retval = 0; |
include/asm-sh/io_generic.h
1 | 1 | /* |
2 | - * include/asm-sh/io_generic.h | |
3 | - * | |
4 | - * Copyright 2000 Stuart Menefy (stuart.menefy@st.com) | |
5 | - * | |
6 | - * May be copied or modified under the terms of the GNU General Public | |
7 | - * License. See linux/COPYING for more information. | |
8 | - * | |
9 | - * Generic IO functions | |
2 | + * Trivial I/O routine definitions, intentionally meant to be included | |
3 | + * multiple times. Ugly I/O routine concatenation helpers taken from | |
4 | + * alpha. Must be included _before_ io.h to avoid preprocessor-induced | |
5 | + * routine mismatch. | |
10 | 6 | */ |
7 | +#define IO_CONCAT(a,b) _IO_CONCAT(a,b) | |
8 | +#define _IO_CONCAT(a,b) a ## _ ## b | |
11 | 9 | |
12 | -#ifndef _ASM_SH_IO_GENERIC_H | |
13 | -#define _ASM_SH_IO_GENERIC_H | |
10 | +#ifndef __IO_PREFIX | |
11 | +#error "Don't include this header without a valid system prefix" | |
12 | +#endif | |
14 | 13 | |
15 | -extern unsigned long generic_io_base; | |
14 | +u8 IO_CONCAT(__IO_PREFIX,inb)(unsigned long); | |
15 | +u16 IO_CONCAT(__IO_PREFIX,inw)(unsigned long); | |
16 | +u32 IO_CONCAT(__IO_PREFIX,inl)(unsigned long); | |
16 | 17 | |
17 | -extern unsigned char generic_inb(unsigned long port); | |
18 | -extern unsigned short generic_inw(unsigned long port); | |
19 | -extern unsigned int generic_inl(unsigned long port); | |
18 | +void IO_CONCAT(__IO_PREFIX,outb)(u8, unsigned long); | |
19 | +void IO_CONCAT(__IO_PREFIX,outw)(u16, unsigned long); | |
20 | +void IO_CONCAT(__IO_PREFIX,outl)(u32, unsigned long); | |
20 | 21 | |
21 | -extern void generic_outb(unsigned char value, unsigned long port); | |
22 | -extern void generic_outw(unsigned short value, unsigned long port); | |
23 | -extern void generic_outl(unsigned int value, unsigned long port); | |
22 | +u8 IO_CONCAT(__IO_PREFIX,inb_p)(unsigned long); | |
23 | +u16 IO_CONCAT(__IO_PREFIX,inw_p)(unsigned long); | |
24 | +u32 IO_CONCAT(__IO_PREFIX,inl_p)(unsigned long); | |
25 | +void IO_CONCAT(__IO_PREFIX,outb_p)(u8, unsigned long); | |
26 | +void IO_CONCAT(__IO_PREFIX,outw_p)(u16, unsigned long); | |
27 | +void IO_CONCAT(__IO_PREFIX,outl_p)(u32, unsigned long); | |
24 | 28 | |
25 | -extern unsigned char generic_inb_p(unsigned long port); | |
26 | -extern unsigned short generic_inw_p(unsigned long port); | |
27 | -extern unsigned int generic_inl_p(unsigned long port); | |
28 | -extern void generic_outb_p(unsigned char value, unsigned long port); | |
29 | -extern void generic_outw_p(unsigned short value, unsigned long port); | |
30 | -extern void generic_outl_p(unsigned int value, unsigned long port); | |
29 | +void IO_CONCAT(__IO_PREFIX,insb)(unsigned long, void *dst, unsigned long count); | |
30 | +void IO_CONCAT(__IO_PREFIX,insw)(unsigned long, void *dst, unsigned long count); | |
31 | +void IO_CONCAT(__IO_PREFIX,insl)(unsigned long, void *dst, unsigned long count); | |
32 | +void IO_CONCAT(__IO_PREFIX,outsb)(unsigned long, const void *src, unsigned long count); | |
33 | +void IO_CONCAT(__IO_PREFIX,outsw)(unsigned long, const void *src, unsigned long count); | |
34 | +void IO_CONCAT(__IO_PREFIX,outsl)(unsigned long, const void *src, unsigned long count); | |
31 | 35 | |
32 | -extern void generic_insb(unsigned long port, void *addr, unsigned long count); | |
33 | -extern void generic_insw(unsigned long port, void *addr, unsigned long count); | |
34 | -extern void generic_insl(unsigned long port, void *addr, unsigned long count); | |
35 | -extern void generic_outsb(unsigned long port, const void *addr, unsigned long count); | |
36 | -extern void generic_outsw(unsigned long port, const void *addr, unsigned long count); | |
37 | -extern void generic_outsl(unsigned long port, const void *addr, unsigned long count); | |
36 | +u8 IO_CONCAT(__IO_PREFIX,readb)(void __iomem *); | |
37 | +u16 IO_CONCAT(__IO_PREFIX,readw)(void __iomem *); | |
38 | +u32 IO_CONCAT(__IO_PREFIX,readl)(void __iomem *); | |
39 | +void IO_CONCAT(__IO_PREFIX,writeb)(u8, void __iomem *); | |
40 | +void IO_CONCAT(__IO_PREFIX,writew)(u16, void __iomem *); | |
41 | +void IO_CONCAT(__IO_PREFIX,writel)(u32, void __iomem *); | |
38 | 42 | |
39 | -extern unsigned char generic_readb(unsigned long addr); | |
40 | -extern unsigned short generic_readw(unsigned long addr); | |
41 | -extern unsigned int generic_readl(unsigned long addr); | |
42 | -extern void generic_writeb(unsigned char b, unsigned long addr); | |
43 | -extern void generic_writew(unsigned short b, unsigned long addr); | |
44 | -extern void generic_writel(unsigned int b, unsigned long addr); | |
43 | +void *IO_CONCAT(__IO_PREFIX,ioremap)(unsigned long offset, unsigned long size); | |
44 | +void IO_CONCAT(__IO_PREFIX,iounmap)(void *addr); | |
45 | 45 | |
46 | -extern void *generic_ioremap(unsigned long offset, unsigned long size); | |
47 | -extern void generic_iounmap(void *addr); | |
46 | +void __iomem *IO_CONCAT(__IO_PREFIX,ioport_map)(unsigned long addr, unsigned int size); | |
47 | +void IO_CONCAT(__IO_PREFIX,ioport_unmap)(void __iomem *addr); | |
48 | 48 | |
49 | -extern unsigned long generic_isa_port2addr(unsigned long offset); | |
50 | - | |
51 | -#endif /* _ASM_SH_IO_GENERIC_H */ | |
49 | +#undef __IO_PREFIX |
include/asm-sh/machvec.h
... | ... | @@ -18,45 +18,38 @@ |
18 | 18 | #include <asm/machvec_init.h> |
19 | 19 | |
20 | 20 | struct device; |
21 | -struct timeval; | |
22 | 21 | |
23 | -struct sh_machine_vector | |
24 | -{ | |
22 | +struct sh_machine_vector { | |
25 | 23 | int mv_nr_irqs; |
26 | 24 | |
27 | - unsigned char (*mv_inb)(unsigned long); | |
28 | - unsigned short (*mv_inw)(unsigned long); | |
29 | - unsigned int (*mv_inl)(unsigned long); | |
30 | - void (*mv_outb)(unsigned char, unsigned long); | |
31 | - void (*mv_outw)(unsigned short, unsigned long); | |
32 | - void (*mv_outl)(unsigned int, unsigned long); | |
25 | + u8 (*mv_inb)(unsigned long); | |
26 | + u16 (*mv_inw)(unsigned long); | |
27 | + u32 (*mv_inl)(unsigned long); | |
28 | + void (*mv_outb)(u8, unsigned long); | |
29 | + void (*mv_outw)(u16, unsigned long); | |
30 | + void (*mv_outl)(u32, unsigned long); | |
33 | 31 | |
34 | - unsigned char (*mv_inb_p)(unsigned long); | |
35 | - unsigned short (*mv_inw_p)(unsigned long); | |
36 | - unsigned int (*mv_inl_p)(unsigned long); | |
37 | - void (*mv_outb_p)(unsigned char, unsigned long); | |
38 | - void (*mv_outw_p)(unsigned short, unsigned long); | |
39 | - void (*mv_outl_p)(unsigned int, unsigned long); | |
32 | + u8 (*mv_inb_p)(unsigned long); | |
33 | + u16 (*mv_inw_p)(unsigned long); | |
34 | + u32 (*mv_inl_p)(unsigned long); | |
35 | + void (*mv_outb_p)(u8, unsigned long); | |
36 | + void (*mv_outw_p)(u16, unsigned long); | |
37 | + void (*mv_outl_p)(u32, unsigned long); | |
40 | 38 | |
41 | - void (*mv_insb)(unsigned long port, void *addr, unsigned long count); | |
42 | - void (*mv_insw)(unsigned long port, void *addr, unsigned long count); | |
43 | - void (*mv_insl)(unsigned long port, void *addr, unsigned long count); | |
44 | - void (*mv_outsb)(unsigned long port, const void *addr, unsigned long count); | |
45 | - void (*mv_outsw)(unsigned long port, const void *addr, unsigned long count); | |
46 | - void (*mv_outsl)(unsigned long port, const void *addr, unsigned long count); | |
39 | + void (*mv_insb)(unsigned long, void *dst, unsigned long count); | |
40 | + void (*mv_insw)(unsigned long, void *dst, unsigned long count); | |
41 | + void (*mv_insl)(unsigned long, void *dst, unsigned long count); | |
42 | + void (*mv_outsb)(unsigned long, const void *src, unsigned long count); | |
43 | + void (*mv_outsw)(unsigned long, const void *src, unsigned long count); | |
44 | + void (*mv_outsl)(unsigned long, const void *src, unsigned long count); | |
47 | 45 | |
48 | - unsigned char (*mv_readb)(unsigned long); | |
49 | - unsigned short (*mv_readw)(unsigned long); | |
50 | - unsigned int (*mv_readl)(unsigned long); | |
51 | - void (*mv_writeb)(unsigned char, unsigned long); | |
52 | - void (*mv_writew)(unsigned short, unsigned long); | |
53 | - void (*mv_writel)(unsigned int, unsigned long); | |
46 | + u8 (*mv_readb)(void __iomem *); | |
47 | + u16 (*mv_readw)(void __iomem *); | |
48 | + u32 (*mv_readl)(void __iomem *); | |
49 | + void (*mv_writeb)(u8, void __iomem *); | |
50 | + void (*mv_writew)(u16, void __iomem *); | |
51 | + void (*mv_writel)(u32, void __iomem *); | |
54 | 52 | |
55 | - void* (*mv_ioremap)(unsigned long offset, unsigned long size); | |
56 | - void (*mv_iounmap)(void *addr); | |
57 | - | |
58 | - unsigned long (*mv_isa_port2addr)(unsigned long offset); | |
59 | - | |
60 | 53 | int (*mv_irq_demux)(int irq); |
61 | 54 | |
62 | 55 | void (*mv_init_irq)(void); |
... | ... | @@ -66,6 +59,9 @@ |
66 | 59 | |
67 | 60 | void *(*mv_consistent_alloc)(struct device *, size_t, dma_addr_t *, gfp_t); |
68 | 61 | int (*mv_consistent_free)(struct device *, size_t, void *, dma_addr_t); |
62 | + | |
63 | + void __iomem *(*mv_ioport_map)(unsigned long port, unsigned int size); | |
64 | + void (*mv_ioport_unmap)(void __iomem *); | |
69 | 65 | }; |
70 | 66 | |
71 | 67 | extern struct sh_machine_vector sh_mv; |