Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Richard Kuo and committed by
Linus Torvalds
013bf24c 7567746e

+417
+326
arch/hexagon/include/asm/io.h
··· 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
+91
arch/hexagon/lib/io.c
··· 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 + }