1/* 2 * linux/arch/arm/mach-ebsa110/isamem.c 3 * 4 * Copyright (C) 2001 Russell King 5 * 6 * Perform "ISA" memory and IO accesses. The EBSA110 has some "peculiarities" 7 * in the way it handles accesses to odd IO ports on 16-bit devices. These 8 * devices have their D0-D15 lines connected to the processors D0-D15 lines. 9 * Since they expect all byte IO operations to be performed on D0-D7, and the 10 * StrongARM expects to transfer the byte to these odd addresses on D8-D15, 11 * we must use a trick to get the required behaviour. 12 * 13 * The trick employed here is to use long word stores to odd address -1. The 14 * glue logic picks this up as a "trick" access, and asserts the LSB of the 15 * peripherals address bus, thereby accessing the odd IO port. Meanwhile, the 16 * StrongARM transfers its data on D0-D7 as expected. 17 * 18 * Things get more interesting on the pass-1 EBSA110 - the PCMCIA controller 19 * wiring was screwed in such a way that it had limited memory space access. 20 * Luckily, the work-around for this is not too horrible. See 21 * __isamem_convert_addr for the details. 22 */ 23#include <linux/module.h> 24#include <linux/kernel.h> 25#include <linux/types.h> 26#include <linux/io.h> 27 28#include <mach/hardware.h> 29#include <asm/page.h> 30 31static void __iomem *__isamem_convert_addr(const volatile void __iomem *addr) 32{ 33 u32 ret, a = (u32 __force) addr; 34 35 /* 36 * The PCMCIA controller is wired up as follows: 37 * +---------+---------+---------+---------+---------+---------+ 38 * PCMCIA | 2 2 2 2 | 1 1 1 1 | 1 1 1 1 | 1 1 | | | 39 * | 3 2 1 0 | 9 8 7 6 | 5 4 3 2 | 1 0 9 8 | 7 6 5 4 | 3 2 1 0 | 40 * +---------+---------+---------+---------+---------+---------+ 41 * CPU | 2 2 2 2 | 2 1 1 1 | 1 1 1 1 | 1 1 1 | | | 42 * | 4 3 2 1 | 0 9 9 8 | 7 6 5 4 | 3 2 0 9 | 8 7 6 5 | 4 3 2 x | 43 * +---------+---------+---------+---------+---------+---------+ 44 * 45 * This means that we can access PCMCIA regions as follows: 46 * 0x*10000 -> 0x*1ffff 47 * 0x*70000 -> 0x*7ffff 48 * 0x*90000 -> 0x*9ffff 49 * 0x*f0000 -> 0x*fffff 50 */ 51 ret = (a & 0xf803fe) << 1; 52 ret |= (a & 0x03fc00) << 2; 53 54 ret += 0xe8000000; 55 56 if ((a & 0x20000) == (a & 0x40000) >> 1) 57 return (void __iomem *)ret; 58 59 BUG(); 60 return NULL; 61} 62 63/* 64 * read[bwl] and write[bwl] 65 */ 66u8 __readb(const volatile void __iomem *addr) 67{ 68 void __iomem *a = __isamem_convert_addr(addr); 69 u32 ret; 70 71 if ((unsigned long)addr & 1) 72 ret = __raw_readl(a); 73 else 74 ret = __raw_readb(a); 75 return ret; 76} 77 78u16 __readw(const volatile void __iomem *addr) 79{ 80 void __iomem *a = __isamem_convert_addr(addr); 81 82 if ((unsigned long)addr & 1) 83 BUG(); 84 85 return __raw_readw(a); 86} 87 88u32 __readl(const volatile void __iomem *addr) 89{ 90 void __iomem *a = __isamem_convert_addr(addr); 91 u32 ret; 92 93 if ((unsigned long)addr & 3) 94 BUG(); 95 96 ret = __raw_readw(a); 97 ret |= __raw_readw(a + 4) << 16; 98 return ret; 99} 100 101EXPORT_SYMBOL(__readb); 102EXPORT_SYMBOL(__readw); 103EXPORT_SYMBOL(__readl); 104 105void readsw(const volatile void __iomem *addr, void *data, int len) 106{ 107 void __iomem *a = __isamem_convert_addr(addr); 108 109 BUG_ON((unsigned long)addr & 1); 110 111 __raw_readsw(a, data, len); 112} 113EXPORT_SYMBOL(readsw); 114 115void readsl(const volatile void __iomem *addr, void *data, int len) 116{ 117 void __iomem *a = __isamem_convert_addr(addr); 118 119 BUG_ON((unsigned long)addr & 3); 120 121 __raw_readsl(a, data, len); 122} 123EXPORT_SYMBOL(readsl); 124 125void __writeb(u8 val, volatile void __iomem *addr) 126{ 127 void __iomem *a = __isamem_convert_addr(addr); 128 129 if ((unsigned long)addr & 1) 130 __raw_writel(val, a); 131 else 132 __raw_writeb(val, a); 133} 134 135void __writew(u16 val, volatile void __iomem *addr) 136{ 137 void __iomem *a = __isamem_convert_addr(addr); 138 139 if ((unsigned long)addr & 1) 140 BUG(); 141 142 __raw_writew(val, a); 143} 144 145void __writel(u32 val, volatile void __iomem *addr) 146{ 147 void __iomem *a = __isamem_convert_addr(addr); 148 149 if ((unsigned long)addr & 3) 150 BUG(); 151 152 __raw_writew(val, a); 153 __raw_writew(val >> 16, a + 4); 154} 155 156EXPORT_SYMBOL(__writeb); 157EXPORT_SYMBOL(__writew); 158EXPORT_SYMBOL(__writel); 159 160void writesw(volatile void __iomem *addr, const void *data, int len) 161{ 162 void __iomem *a = __isamem_convert_addr(addr); 163 164 BUG_ON((unsigned long)addr & 1); 165 166 __raw_writesw(a, data, len); 167} 168EXPORT_SYMBOL(writesw); 169 170void writesl(volatile void __iomem *addr, const void *data, int len) 171{ 172 void __iomem *a = __isamem_convert_addr(addr); 173 174 BUG_ON((unsigned long)addr & 3); 175 176 __raw_writesl(a, data, len); 177} 178EXPORT_SYMBOL(writesl); 179 180/* 181 * The EBSA110 has a weird "ISA IO" region: 182 * 183 * Region 0 (addr = 0xf0000000 + io << 2) 184 * -------------------------------------------------------- 185 * Physical region IO region 186 * f0000fe0 - f0000ffc 3f8 - 3ff ttyS0 187 * f0000e60 - f0000e64 398 - 399 188 * f0000de0 - f0000dfc 378 - 37f lp0 189 * f0000be0 - f0000bfc 2f8 - 2ff ttyS1 190 * 191 * Region 1 (addr = 0xf0000000 + (io & ~1) << 1 + (io & 1)) 192 * -------------------------------------------------------- 193 * Physical region IO region 194 * f00014f1 a79 pnp write data 195 * f00007c0 - f00007c1 3e0 - 3e1 pcmcia 196 * f00004f1 279 pnp address 197 * f0000440 - f000046c 220 - 236 eth0 198 * f0000405 203 pnp read data 199 */ 200#define SUPERIO_PORT(p) \ 201 (((p) >> 3) == (0x3f8 >> 3) || \ 202 ((p) >> 3) == (0x2f8 >> 3) || \ 203 ((p) >> 3) == (0x378 >> 3)) 204 205/* 206 * We're addressing an 8 or 16-bit peripheral which tranfers 207 * odd addresses on the low ISA byte lane. 208 */ 209u8 __inb8(unsigned int port) 210{ 211 u32 ret; 212 213 /* 214 * The SuperIO registers use sane addressing techniques... 215 */ 216 if (SUPERIO_PORT(port)) 217 ret = __raw_readb((void __iomem *)ISAIO_BASE + (port << 2)); 218 else { 219 void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1); 220 221 /* 222 * Shame nothing else does 223 */ 224 if (port & 1) 225 ret = __raw_readl(a); 226 else 227 ret = __raw_readb(a); 228 } 229 return ret; 230} 231 232/* 233 * We're addressing a 16-bit peripheral which transfers odd 234 * addresses on the high ISA byte lane. 235 */ 236u8 __inb16(unsigned int port) 237{ 238 unsigned int offset; 239 240 /* 241 * The SuperIO registers use sane addressing techniques... 242 */ 243 if (SUPERIO_PORT(port)) 244 offset = port << 2; 245 else 246 offset = (port & ~1) << 1 | (port & 1); 247 248 return __raw_readb((void __iomem *)ISAIO_BASE + offset); 249} 250 251u16 __inw(unsigned int port) 252{ 253 unsigned int offset; 254 255 /* 256 * The SuperIO registers use sane addressing techniques... 257 */ 258 if (SUPERIO_PORT(port)) 259 offset = port << 2; 260 else { 261 offset = port << 1; 262 BUG_ON(port & 1); 263 } 264 return __raw_readw((void __iomem *)ISAIO_BASE + offset); 265} 266 267/* 268 * Fake a 32-bit read with two 16-bit reads. Needed for 3c589. 269 */ 270u32 __inl(unsigned int port) 271{ 272 void __iomem *a; 273 274 if (SUPERIO_PORT(port) || port & 3) 275 BUG(); 276 277 a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1); 278 279 return __raw_readw(a) | __raw_readw(a + 4) << 16; 280} 281 282EXPORT_SYMBOL(__inb8); 283EXPORT_SYMBOL(__inb16); 284EXPORT_SYMBOL(__inw); 285EXPORT_SYMBOL(__inl); 286 287void __outb8(u8 val, unsigned int port) 288{ 289 /* 290 * The SuperIO registers use sane addressing techniques... 291 */ 292 if (SUPERIO_PORT(port)) 293 __raw_writeb(val, (void __iomem *)ISAIO_BASE + (port << 2)); 294 else { 295 void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1); 296 297 /* 298 * Shame nothing else does 299 */ 300 if (port & 1) 301 __raw_writel(val, a); 302 else 303 __raw_writeb(val, a); 304 } 305} 306 307void __outb16(u8 val, unsigned int port) 308{ 309 unsigned int offset; 310 311 /* 312 * The SuperIO registers use sane addressing techniques... 313 */ 314 if (SUPERIO_PORT(port)) 315 offset = port << 2; 316 else 317 offset = (port & ~1) << 1 | (port & 1); 318 319 __raw_writeb(val, (void __iomem *)ISAIO_BASE + offset); 320} 321 322void __outw(u16 val, unsigned int port) 323{ 324 unsigned int offset; 325 326 /* 327 * The SuperIO registers use sane addressing techniques... 328 */ 329 if (SUPERIO_PORT(port)) 330 offset = port << 2; 331 else { 332 offset = port << 1; 333 BUG_ON(port & 1); 334 } 335 __raw_writew(val, (void __iomem *)ISAIO_BASE + offset); 336} 337 338void __outl(u32 val, unsigned int port) 339{ 340 BUG(); 341} 342 343EXPORT_SYMBOL(__outb8); 344EXPORT_SYMBOL(__outb16); 345EXPORT_SYMBOL(__outw); 346EXPORT_SYMBOL(__outl); 347 348void outsb(unsigned int port, const void *from, int len) 349{ 350 u32 off; 351 352 if (SUPERIO_PORT(port)) 353 off = port << 2; 354 else { 355 off = (port & ~1) << 1; 356 if (port & 1) 357 BUG(); 358 } 359 360 __raw_writesb((void __iomem *)ISAIO_BASE + off, from, len); 361} 362 363void insb(unsigned int port, void *from, int len) 364{ 365 u32 off; 366 367 if (SUPERIO_PORT(port)) 368 off = port << 2; 369 else { 370 off = (port & ~1) << 1; 371 if (port & 1) 372 BUG(); 373 } 374 375 __raw_readsb((void __iomem *)ISAIO_BASE + off, from, len); 376} 377 378EXPORT_SYMBOL(outsb); 379EXPORT_SYMBOL(insb); 380 381void outsw(unsigned int port, const void *from, int len) 382{ 383 u32 off; 384 385 if (SUPERIO_PORT(port)) 386 off = port << 2; 387 else { 388 off = (port & ~1) << 1; 389 if (port & 1) 390 BUG(); 391 } 392 393 __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len); 394} 395 396void insw(unsigned int port, void *from, int len) 397{ 398 u32 off; 399 400 if (SUPERIO_PORT(port)) 401 off = port << 2; 402 else { 403 off = (port & ~1) << 1; 404 if (port & 1) 405 BUG(); 406 } 407 408 __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len); 409} 410 411EXPORT_SYMBOL(outsw); 412EXPORT_SYMBOL(insw); 413 414/* 415 * We implement these as 16-bit insw/outsw, mainly for 416 * 3c589 cards. 417 */ 418void outsl(unsigned int port, const void *from, int len) 419{ 420 u32 off = port << 1; 421 422 if (SUPERIO_PORT(port) || port & 3) 423 BUG(); 424 425 __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len << 1); 426} 427 428void insl(unsigned int port, void *from, int len) 429{ 430 u32 off = port << 1; 431 432 if (SUPERIO_PORT(port) || port & 3) 433 BUG(); 434 435 __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len << 1); 436} 437 438EXPORT_SYMBOL(outsl); 439EXPORT_SYMBOL(insl); 440