diff options
Diffstat (limited to 'arch/sh64/lib/io.c')
-rw-r--r-- | arch/sh64/lib/io.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/arch/sh64/lib/io.c b/arch/sh64/lib/io.c new file mode 100644 index 000000000000..277e11b10c2b --- /dev/null +++ b/arch/sh64/lib/io.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) | ||
3 | * | ||
4 | * May be copied or modified under the terms of the GNU General Public | ||
5 | * License. See linux/COPYING for more information. | ||
6 | * | ||
7 | * This file contains the I/O routines for use on the overdrive board | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <asm/system.h> | ||
16 | #include <asm/processor.h> | ||
17 | #include <asm/io.h> | ||
18 | |||
19 | /* | ||
20 | * readX/writeX() are used to access memory mapped devices. On some | ||
21 | * architectures the memory mapped IO stuff needs to be accessed | ||
22 | * differently. On the SuperH architecture, we just read/write the | ||
23 | * memory location directly. | ||
24 | */ | ||
25 | |||
26 | /* This is horrible at the moment - needs more work to do something sensible */ | ||
27 | #define IO_DELAY() | ||
28 | |||
29 | #define OUT_DELAY(x,type) \ | ||
30 | void out##x##_p(unsigned type value,unsigned long port){out##x(value,port);IO_DELAY();} | ||
31 | |||
32 | #define IN_DELAY(x,type) \ | ||
33 | unsigned type in##x##_p(unsigned long port) {unsigned type tmp=in##x(port);IO_DELAY();return tmp;} | ||
34 | |||
35 | #if 1 | ||
36 | OUT_DELAY(b, long) OUT_DELAY(w, long) OUT_DELAY(l, long) | ||
37 | IN_DELAY(b, long) IN_DELAY(w, long) IN_DELAY(l, long) | ||
38 | #endif | ||
39 | /* Now for the string version of these functions */ | ||
40 | void outsb(unsigned long port, const void *addr, unsigned long count) | ||
41 | { | ||
42 | int i; | ||
43 | unsigned char *p = (unsigned char *) addr; | ||
44 | |||
45 | for (i = 0; i < count; i++, p++) { | ||
46 | outb(*p, port); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | void insb(unsigned long port, void *addr, unsigned long count) | ||
51 | { | ||
52 | int i; | ||
53 | unsigned char *p = (unsigned char *) addr; | ||
54 | |||
55 | for (i = 0; i < count; i++, p++) { | ||
56 | *p = inb(port); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | /* For the 16 and 32 bit string functions, we have to worry about alignment. | ||
61 | * The SH does not do unaligned accesses, so we have to read as bytes and | ||
62 | * then write as a word or dword. | ||
63 | * This can be optimised a lot more, especially in the case where the data | ||
64 | * is aligned | ||
65 | */ | ||
66 | |||
67 | void outsw(unsigned long port, const void *addr, unsigned long count) | ||
68 | { | ||
69 | int i; | ||
70 | unsigned short tmp; | ||
71 | unsigned char *p = (unsigned char *) addr; | ||
72 | |||
73 | for (i = 0; i < count; i++, p += 2) { | ||
74 | tmp = (*p) | ((*(p + 1)) << 8); | ||
75 | outw(tmp, port); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | void insw(unsigned long port, void *addr, unsigned long count) | ||
80 | { | ||
81 | int i; | ||
82 | unsigned short tmp; | ||
83 | unsigned char *p = (unsigned char *) addr; | ||
84 | |||
85 | for (i = 0; i < count; i++, p += 2) { | ||
86 | tmp = inw(port); | ||
87 | p[0] = tmp & 0xff; | ||
88 | p[1] = (tmp >> 8) & 0xff; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | void outsl(unsigned long port, const void *addr, unsigned long count) | ||
93 | { | ||
94 | int i; | ||
95 | unsigned tmp; | ||
96 | unsigned char *p = (unsigned char *) addr; | ||
97 | |||
98 | for (i = 0; i < count; i++, p += 4) { | ||
99 | tmp = (*p) | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) | | ||
100 | ((*(p + 3)) << 24); | ||
101 | outl(tmp, port); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | void insl(unsigned long port, void *addr, unsigned long count) | ||
106 | { | ||
107 | int i; | ||
108 | unsigned tmp; | ||
109 | unsigned char *p = (unsigned char *) addr; | ||
110 | |||
111 | for (i = 0; i < count; i++, p += 4) { | ||
112 | tmp = inl(port); | ||
113 | p[0] = tmp & 0xff; | ||
114 | p[1] = (tmp >> 8) & 0xff; | ||
115 | p[2] = (tmp >> 16) & 0xff; | ||
116 | p[3] = (tmp >> 24) & 0xff; | ||
117 | |||
118 | } | ||
119 | } | ||
120 | |||
121 | void memcpy_toio(void __iomem *to, const void *from, long count) | ||
122 | { | ||
123 | unsigned char *p = (unsigned char *) from; | ||
124 | |||
125 | while (count) { | ||
126 | count--; | ||
127 | writeb(*p++, to++); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | void memcpy_fromio(void *to, void __iomem *from, long count) | ||
132 | { | ||
133 | int i; | ||
134 | unsigned char *p = (unsigned char *) to; | ||
135 | |||
136 | for (i = 0; i < count; i++) { | ||
137 | p[i] = readb(from); | ||
138 | from++; | ||
139 | } | ||
140 | } | ||