diff options
author | Richard Kuo <rkuo@codeaurora.org> | 2011-10-31 19:48:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-01 10:34:20 -0400 |
commit | 013bf24c38293ca1142823d3c67a4aa4d90c6e66 (patch) | |
tree | fbae4d8bb2900a5dbcdec456eec85b31d169eb66 | |
parent | 7567746e1c0d66ac0ef8a9d8816ca694462c7370 (diff) |
Hexagon: Provide basic implementation and/or stubs for I/O routines.
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/hexagon/include/asm/io.h | 326 | ||||
-rw-r--r-- | arch/hexagon/lib/io.c | 91 |
2 files changed, 417 insertions, 0 deletions
diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h new file mode 100644 index 000000000000..b3acc2cc71bf --- /dev/null +++ b/arch/hexagon/include/asm/io.h | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | * IO definitions for the Hexagon architecture | ||
3 | * | ||
4 | * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 and | ||
8 | * only version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
18 | * 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef _ASM_IO_H | ||
22 | #define _ASM_IO_H | ||
23 | |||
24 | #ifdef __KERNEL__ | ||
25 | |||
26 | #include <linux/types.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/vmalloc.h> | ||
29 | #include <asm/string.h> | ||
30 | #include <asm/mem-layout.h> | ||
31 | #include <asm/iomap.h> | ||
32 | #include <asm/page.h> | ||
33 | #include <asm/cacheflush.h> | ||
34 | #include <asm/tlbflush.h> | ||
35 | |||
36 | /* | ||
37 | * We don't have PCI yet. | ||
38 | * _IO_BASE is pointing at what should be unused virtual space. | ||
39 | */ | ||
40 | #define IO_SPACE_LIMIT 0xffff | ||
41 | #define _IO_BASE ((void __iomem *)0xfe000000) | ||
42 | |||
43 | extern int remap_area_pages(unsigned long start, unsigned long phys_addr, | ||
44 | unsigned long end, unsigned long flags); | ||
45 | |||
46 | extern void __iounmap(const volatile void __iomem *addr); | ||
47 | |||
48 | /* Defined in lib/io.c, needed for smc91x driver. */ | ||
49 | extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen); | ||
50 | extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen); | ||
51 | |||
52 | extern void __raw_readsl(const void __iomem *addr, void *data, int wordlen); | ||
53 | extern void __raw_writesl(void __iomem *addr, const void *data, int wordlen); | ||
54 | |||
55 | #define readsw(p, d, l) __raw_readsw(p, d, l) | ||
56 | #define writesw(p, d, l) __raw_writesw(p, d, l) | ||
57 | |||
58 | #define readsl(p, d, l) __raw_readsl(p, d, l) | ||
59 | #define writesl(p, d, l) __raw_writesl(p, d, l) | ||
60 | |||
61 | /* | ||
62 | * virt_to_phys - map virtual address to physical | ||
63 | * @address: address to map | ||
64 | */ | ||
65 | static inline unsigned long virt_to_phys(volatile void *address) | ||
66 | { | ||
67 | return __pa(address); | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * phys_to_virt - map physical address to virtual | ||
72 | * @address: address to map | ||
73 | */ | ||
74 | static inline void *phys_to_virt(unsigned long address) | ||
75 | { | ||
76 | return __va(address); | ||
77 | } | ||
78 | |||
79 | /* | ||
80 | * convert a physical pointer to a virtual kernel pointer for | ||
81 | * /dev/mem access. | ||
82 | */ | ||
83 | #define xlate_dev_kmem_ptr(p) __va(p) | ||
84 | #define xlate_dev_mem_ptr(p) __va(p) | ||
85 | |||
86 | /* | ||
87 | * IO port access primitives. Hexagon doesn't have special IO access | ||
88 | * instructions; all I/O is memory mapped. | ||
89 | * | ||
90 | * in/out are used for "ports", but we don't have "port instructions", | ||
91 | * so these are really just memory mapped too. | ||
92 | */ | ||
93 | |||
94 | /* | ||
95 | * readb - read byte from memory mapped device | ||
96 | * @addr: pointer to memory | ||
97 | * | ||
98 | * Operates on "I/O bus memory space" | ||
99 | */ | ||
100 | static inline u8 readb(const volatile void __iomem *addr) | ||
101 | { | ||
102 | u8 val; | ||
103 | asm volatile( | ||
104 | "%0 = memb(%1);" | ||
105 | : "=&r" (val) | ||
106 | : "r" (addr) | ||
107 | ); | ||
108 | return val; | ||
109 | } | ||
110 | |||
111 | static inline u16 readw(const volatile void __iomem *addr) | ||
112 | { | ||
113 | u16 val; | ||
114 | asm volatile( | ||
115 | "%0 = memh(%1);" | ||
116 | : "=&r" (val) | ||
117 | : "r" (addr) | ||
118 | ); | ||
119 | return val; | ||
120 | } | ||
121 | |||
122 | static inline u32 readl(const volatile void __iomem *addr) | ||
123 | { | ||
124 | u32 val; | ||
125 | asm volatile( | ||
126 | "%0 = memw(%1);" | ||
127 | : "=&r" (val) | ||
128 | : "r" (addr) | ||
129 | ); | ||
130 | return val; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * writeb - write a byte to a memory location | ||
135 | * @data: data to write to | ||
136 | * @addr: pointer to memory | ||
137 | * | ||
138 | */ | ||
139 | static inline void writeb(u8 data, volatile void __iomem *addr) | ||
140 | { | ||
141 | asm volatile( | ||
142 | "memb(%0) = %1;" | ||
143 | : | ||
144 | : "r" (addr), "r" (data) | ||
145 | : "memory" | ||
146 | ); | ||
147 | } | ||
148 | |||
149 | static inline void writew(u16 data, volatile void __iomem *addr) | ||
150 | { | ||
151 | asm volatile( | ||
152 | "memh(%0) = %1;" | ||
153 | : | ||
154 | : "r" (addr), "r" (data) | ||
155 | : "memory" | ||
156 | ); | ||
157 | |||
158 | } | ||
159 | |||
160 | static inline void writel(u32 data, volatile void __iomem *addr) | ||
161 | { | ||
162 | asm volatile( | ||
163 | "memw(%0) = %1;" | ||
164 | : | ||
165 | : "r" (addr), "r" (data) | ||
166 | : "memory" | ||
167 | ); | ||
168 | } | ||
169 | |||
170 | #define __raw_writeb writeb | ||
171 | #define __raw_writew writew | ||
172 | #define __raw_writel writel | ||
173 | |||
174 | #define __raw_readb readb | ||
175 | #define __raw_readw readw | ||
176 | #define __raw_readl readl | ||
177 | |||
178 | /* | ||
179 | * Need an mtype somewhere in here, for cache type deals? | ||
180 | * This is probably too long for an inline. | ||
181 | */ | ||
182 | void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size); | ||
183 | |||
184 | static inline void __iomem *ioremap(unsigned long phys_addr, unsigned long size) | ||
185 | { | ||
186 | return ioremap_nocache(phys_addr, size); | ||
187 | } | ||
188 | |||
189 | static inline void iounmap(volatile void __iomem *addr) | ||
190 | { | ||
191 | __iounmap(addr); | ||
192 | } | ||
193 | |||
194 | #define __raw_writel writel | ||
195 | |||
196 | static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, | ||
197 | int count) | ||
198 | { | ||
199 | memcpy(dst, (void *) src, count); | ||
200 | } | ||
201 | |||
202 | static inline void memcpy_toio(volatile void __iomem *dst, const void *src, | ||
203 | int count) | ||
204 | { | ||
205 | memcpy((void *) dst, src, count); | ||
206 | } | ||
207 | |||
208 | #define PCI_IO_ADDR (volatile void __iomem *) | ||
209 | |||
210 | /* | ||
211 | * inb - read byte from I/O port or something | ||
212 | * @port: address in I/O space | ||
213 | * | ||
214 | * Operates on "I/O bus I/O space" | ||
215 | */ | ||
216 | static inline u8 inb(unsigned long port) | ||
217 | { | ||
218 | return readb(_IO_BASE + (port & IO_SPACE_LIMIT)); | ||
219 | } | ||
220 | |||
221 | static inline u16 inw(unsigned long port) | ||
222 | { | ||
223 | return readw(_IO_BASE + (port & IO_SPACE_LIMIT)); | ||
224 | } | ||
225 | |||
226 | static inline u32 inl(unsigned long port) | ||
227 | { | ||
228 | return readl(_IO_BASE + (port & IO_SPACE_LIMIT)); | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | * outb - write a byte to a memory location | ||
233 | * @data: data to write to | ||
234 | * @addr: address in I/O space | ||
235 | */ | ||
236 | static inline void outb(u8 data, unsigned long port) | ||
237 | { | ||
238 | writeb(data, _IO_BASE + (port & IO_SPACE_LIMIT)); | ||
239 | } | ||
240 | |||
241 | static inline void outw(u16 data, unsigned long port) | ||
242 | { | ||
243 | writew(data, _IO_BASE + (port & IO_SPACE_LIMIT)); | ||
244 | } | ||
245 | |||
246 | static inline void outl(u32 data, unsigned long port) | ||
247 | { | ||
248 | writel(data, _IO_BASE + (port & IO_SPACE_LIMIT)); | ||
249 | } | ||
250 | |||
251 | #define outb_p outb | ||
252 | #define outw_p outw | ||
253 | #define outl_p outl | ||
254 | |||
255 | #define inb_p inb | ||
256 | #define inw_p inw | ||
257 | #define inl_p inl | ||
258 | |||
259 | static inline void insb(unsigned long port, void *buffer, int count) | ||
260 | { | ||
261 | if (count) { | ||
262 | u8 *buf = buffer; | ||
263 | do { | ||
264 | u8 x = inb(port); | ||
265 | *buf++ = x; | ||
266 | } while (--count); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | static inline void insw(unsigned long port, void *buffer, int count) | ||
271 | { | ||
272 | if (count) { | ||
273 | u16 *buf = buffer; | ||
274 | do { | ||
275 | u16 x = inw(port); | ||
276 | *buf++ = x; | ||
277 | } while (--count); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | static inline void insl(unsigned long port, void *buffer, int count) | ||
282 | { | ||
283 | if (count) { | ||
284 | u32 *buf = buffer; | ||
285 | do { | ||
286 | u32 x = inw(port); | ||
287 | *buf++ = x; | ||
288 | } while (--count); | ||
289 | } | ||
290 | } | ||
291 | |||
292 | static inline void outsb(unsigned long port, const void *buffer, int count) | ||
293 | { | ||
294 | if (count) { | ||
295 | const u8 *buf = buffer; | ||
296 | do { | ||
297 | outb(*buf++, port); | ||
298 | } while (--count); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | static inline void outsw(unsigned long port, const void *buffer, int count) | ||
303 | { | ||
304 | if (count) { | ||
305 | const u16 *buf = buffer; | ||
306 | do { | ||
307 | outw(*buf++, port); | ||
308 | } while (--count); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | static inline void outsl(unsigned long port, const void *buffer, int count) | ||
313 | { | ||
314 | if (count) { | ||
315 | const u32 *buf = buffer; | ||
316 | do { | ||
317 | outl(*buf++, port); | ||
318 | } while (--count); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | #define flush_write_buffers() do { } while (0) | ||
323 | |||
324 | #endif /* __KERNEL__ */ | ||
325 | |||
326 | #endif | ||
diff --git a/arch/hexagon/lib/io.c b/arch/hexagon/lib/io.c new file mode 100644 index 000000000000..8ae47ba0e705 --- /dev/null +++ b/arch/hexagon/lib/io.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * I/O access functions for Hexagon | ||
3 | * | ||
4 | * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 and | ||
8 | * only version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
18 | * 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #include <asm/io.h> | ||
22 | |||
23 | /* These are all FIFO routines! */ | ||
24 | |||
25 | /* | ||
26 | * __raw_readsw - read words a short at a time | ||
27 | * @addr: source address | ||
28 | * @data: data address | ||
29 | * @len: number of shorts to read | ||
30 | */ | ||
31 | void __raw_readsw(const void __iomem *addr, void *data, int len) | ||
32 | { | ||
33 | const volatile short int *src = (short int *) addr; | ||
34 | short int *dst = (short int *) data; | ||
35 | |||
36 | if ((u32)data & 0x1) | ||
37 | panic("unaligned pointer to readsw"); | ||
38 | |||
39 | while (len-- > 0) | ||
40 | *dst++ = *src; | ||
41 | |||
42 | } | ||
43 | |||
44 | /* | ||
45 | * __raw_writesw - read words a short at a time | ||
46 | * @addr: source address | ||
47 | * @data: data address | ||
48 | * @len: number of shorts to read | ||
49 | */ | ||
50 | void __raw_writesw(void __iomem *addr, const void *data, int len) | ||
51 | { | ||
52 | const short int *src = (short int *)data; | ||
53 | volatile short int *dst = (short int *)addr; | ||
54 | |||
55 | if ((u32)data & 0x1) | ||
56 | panic("unaligned pointer to writesw"); | ||
57 | |||
58 | while (len-- > 0) | ||
59 | *dst = *src++; | ||
60 | |||
61 | |||
62 | } | ||
63 | |||
64 | /* Pretty sure len is pre-adjusted for the length of the access already */ | ||
65 | void __raw_readsl(const void __iomem *addr, void *data, int len) | ||
66 | { | ||
67 | const volatile long *src = (long *) addr; | ||
68 | long *dst = (long *) data; | ||
69 | |||
70 | if ((u32)data & 0x3) | ||
71 | panic("unaligned pointer to readsl"); | ||
72 | |||
73 | while (len-- > 0) | ||
74 | *dst++ = *src; | ||
75 | |||
76 | |||
77 | } | ||
78 | |||
79 | void __raw_writesl(void __iomem *addr, const void *data, int len) | ||
80 | { | ||
81 | const long *src = (long *)data; | ||
82 | volatile long *dst = (long *)addr; | ||
83 | |||
84 | if ((u32)data & 0x3) | ||
85 | panic("unaligned pointer to writesl"); | ||
86 | |||
87 | while (len-- > 0) | ||
88 | *dst = *src++; | ||
89 | |||
90 | |||
91 | } | ||