diff options
author | Magnus Damm <magnus.damm@gmail.com> | 2008-02-07 06:18:21 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-02-14 00:22:09 -0500 |
commit | e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51 (patch) | |
tree | a797888f8d3f95734288978351c33af3c965494c /include/asm-sh | |
parent | 2ade1a9b425c24037327197ea97db054395b536b (diff) |
sh: trapped io support V2
The idea is that we want to get rid of the in/out/readb/writeb callbacks from
the machvec and replace that with simple inline read and write operations to
memory. Fast and simple for most hardware devices (think pci).
Some devices require special treatment though - like 16-bit only CF devices -
so we need to have some method to hook in callbacks.
This patch makes it possible to add a per-device trap generating filter. This
way we can get maximum performance of sane hardware - which doesn't need this
filter - and crappy hardware works but gets punished by a performance hit.
V2 changes things around a bit and replaces io access callbacks with a
simple minimum_bus_width value. In the future we can add stride as well.
Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'include/asm-sh')
-rw-r--r-- | include/asm-sh/io.h | 10 | ||||
-rw-r--r-- | include/asm-sh/io_trapped.h | 58 | ||||
-rw-r--r-- | include/asm-sh/system.h | 5 | ||||
-rw-r--r-- | include/asm-sh/system_32.h | 3 |
4 files changed, 76 insertions, 0 deletions
diff --git a/include/asm-sh/io.h b/include/asm-sh/io.h index 94900c089519..3d2b114f9d57 100644 --- a/include/asm-sh/io.h +++ b/include/asm-sh/io.h | |||
@@ -38,6 +38,7 @@ | |||
38 | */ | 38 | */ |
39 | #define __IO_PREFIX generic | 39 | #define __IO_PREFIX generic |
40 | #include <asm/io_generic.h> | 40 | #include <asm/io_generic.h> |
41 | #include <asm/io_trapped.h> | ||
41 | 42 | ||
42 | #define maybebadio(port) \ | 43 | #define maybebadio(port) \ |
43 | printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \ | 44 | printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \ |
@@ -207,6 +208,8 @@ static inline void __set_io_port_base(unsigned long pbase) | |||
207 | generic_io_base = pbase; | 208 | generic_io_base = pbase; |
208 | } | 209 | } |
209 | 210 | ||
211 | #define __ioport_map(p, n) sh_mv.mv_ioport_map((p), (n)) | ||
212 | |||
210 | /* We really want to try and get these to memcpy etc */ | 213 | /* We really want to try and get these to memcpy etc */ |
211 | extern void memcpy_fromio(void *, volatile void __iomem *, unsigned long); | 214 | extern void memcpy_fromio(void *, volatile void __iomem *, unsigned long); |
212 | extern void memcpy_toio(volatile void __iomem *, const void *, unsigned long); | 215 | extern void memcpy_toio(volatile void __iomem *, const void *, unsigned long); |
@@ -309,7 +312,14 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) | |||
309 | { | 312 | { |
310 | #ifdef CONFIG_SUPERH32 | 313 | #ifdef CONFIG_SUPERH32 |
311 | unsigned long last_addr = offset + size - 1; | 314 | unsigned long last_addr = offset + size - 1; |
315 | #endif | ||
316 | void __iomem *ret; | ||
312 | 317 | ||
318 | ret = __ioremap_trapped(offset, size); | ||
319 | if (ret) | ||
320 | return ret; | ||
321 | |||
322 | #ifdef CONFIG_SUPERH32 | ||
313 | /* | 323 | /* |
314 | * For P1 and P2 space this is trivial, as everything is already | 324 | * For P1 and P2 space this is trivial, as everything is already |
315 | * mapped. Uncached access for P1 addresses are done through P2. | 325 | * mapped. Uncached access for P1 addresses are done through P2. |
diff --git a/include/asm-sh/io_trapped.h b/include/asm-sh/io_trapped.h new file mode 100644 index 000000000000..f1251d4f0ba9 --- /dev/null +++ b/include/asm-sh/io_trapped.h | |||
@@ -0,0 +1,58 @@ | |||
1 | #ifndef __ASM_SH_IO_TRAPPED_H | ||
2 | #define __ASM_SH_IO_TRAPPED_H | ||
3 | |||
4 | #include <linux/list.h> | ||
5 | #include <linux/ioport.h> | ||
6 | #include <asm/page.h> | ||
7 | |||
8 | #define IO_TRAPPED_MAGIC 0xfeedbeef | ||
9 | |||
10 | struct trapped_io { | ||
11 | unsigned int magic; | ||
12 | struct resource *resource; | ||
13 | unsigned int num_resources; | ||
14 | unsigned int minimum_bus_width; | ||
15 | struct list_head list; | ||
16 | void __iomem *virt_base; | ||
17 | } __aligned(PAGE_SIZE); | ||
18 | |||
19 | #ifdef CONFIG_IO_TRAPPED | ||
20 | int register_trapped_io(struct trapped_io *tiop); | ||
21 | int handle_trapped_io(struct pt_regs *regs, unsigned long address); | ||
22 | |||
23 | void __iomem *match_trapped_io_handler(struct list_head *list, | ||
24 | unsigned long offset, | ||
25 | unsigned long size); | ||
26 | |||
27 | #ifdef CONFIG_HAS_IOMEM | ||
28 | extern struct list_head trapped_mem; | ||
29 | |||
30 | static inline void __iomem * | ||
31 | __ioremap_trapped(unsigned long offset, unsigned long size) | ||
32 | { | ||
33 | return match_trapped_io_handler(&trapped_mem, offset, size); | ||
34 | } | ||
35 | #else | ||
36 | #define __ioremap_trapped(offset, size) NULL | ||
37 | #endif | ||
38 | |||
39 | #ifdef CONFIG_HAS_IOPORT | ||
40 | extern struct list_head trapped_io; | ||
41 | |||
42 | static inline void __iomem * | ||
43 | __ioport_map_trapped(unsigned long offset, unsigned long size) | ||
44 | { | ||
45 | return match_trapped_io_handler(&trapped_io, offset, size); | ||
46 | } | ||
47 | #else | ||
48 | #define __ioport_map_trapped(offset, size) NULL | ||
49 | #endif | ||
50 | |||
51 | #else | ||
52 | #define register_trapped_io(tiop) (-1) | ||
53 | #define handle_trapped_io(tiop, address) 0 | ||
54 | #define __ioremap_trapped(offset, size) NULL | ||
55 | #define __ioport_map_trapped(offset, size) NULL | ||
56 | #endif | ||
57 | |||
58 | #endif /* __ASM_SH_IO_TRAPPED_H */ | ||
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h index 772cd1a0a674..5145aa2a0ce9 100644 --- a/include/asm-sh/system.h +++ b/include/asm-sh/system.h | |||
@@ -182,6 +182,11 @@ BUILD_TRAP_HANDLER(fpu_state_restore); | |||
182 | 182 | ||
183 | #define arch_align_stack(x) (x) | 183 | #define arch_align_stack(x) (x) |
184 | 184 | ||
185 | struct mem_access { | ||
186 | unsigned long (*from)(void *dst, const void *src, unsigned long cnt); | ||
187 | unsigned long (*to)(void *dst, const void *src, unsigned long cnt); | ||
188 | }; | ||
189 | |||
185 | #ifdef CONFIG_SUPERH32 | 190 | #ifdef CONFIG_SUPERH32 |
186 | # include "system_32.h" | 191 | # include "system_32.h" |
187 | #else | 192 | #else |
diff --git a/include/asm-sh/system_32.h b/include/asm-sh/system_32.h index 7ff08d956ba8..f11bcf0855ed 100644 --- a/include/asm-sh/system_32.h +++ b/include/asm-sh/system_32.h | |||
@@ -96,4 +96,7 @@ do { \ | |||
96 | : "=&r" (__dummy)); \ | 96 | : "=&r" (__dummy)); \ |
97 | } while (0) | 97 | } while (0) |
98 | 98 | ||
99 | int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs, | ||
100 | struct mem_access *ma); | ||
101 | |||
99 | #endif /* __ASM_SH_SYSTEM_32_H */ | 102 | #endif /* __ASM_SH_SYSTEM_32_H */ |