1/* 2 * linux/arch/sh/boards/superh/microdev/io.c 3 * 4 * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com) 5 * Copyright (C) 2003, 2004 SuperH, Inc. 6 * Copyright (C) 2004 Paul Mundt 7 * 8 * SuperH SH4-202 MicroDev board support. 9 * 10 * May be copied or modified under the terms of the GNU General Public 11 * License. See linux/COPYING for more information. 12 */ 13 14#include <linux/init.h> 15#include <linux/pci.h> 16#include <linux/wait.h> 17#include <asm/io.h> 18#include <mach/microdev.h> 19 20 /* 21 * we need to have a 'safe' address to re-direct all I/O requests 22 * that we do not explicitly wish to handle. This safe address 23 * must have the following properies: 24 * 25 * * writes are ignored (no exception) 26 * * reads are benign (no side-effects) 27 * * accesses of width 1, 2 and 4-bytes are all valid. 28 * 29 * The Processor Version Register (PVR) has these properties. 30 */ 31#define PVR 0xff000030 /* Processor Version Register */ 32 33 34#define IO_IDE2_BASE 0x170ul /* I/O base for SMSC FDC37C93xAPM IDE #2 */ 35#define IO_IDE1_BASE 0x1f0ul /* I/O base for SMSC FDC37C93xAPM IDE #1 */ 36#define IO_ISP1161_BASE 0x290ul /* I/O port for Philips ISP1161x USB chip */ 37#define IO_SERIAL2_BASE 0x2f8ul /* I/O base for SMSC FDC37C93xAPM Serial #2 */ 38#define IO_LAN91C111_BASE 0x300ul /* I/O base for SMSC LAN91C111 Ethernet chip */ 39#define IO_IDE2_MISC 0x376ul /* I/O misc for SMSC FDC37C93xAPM IDE #2 */ 40#define IO_SUPERIO_BASE 0x3f0ul /* I/O base for SMSC FDC37C93xAPM SuperIO chip */ 41#define IO_IDE1_MISC 0x3f6ul /* I/O misc for SMSC FDC37C93xAPM IDE #1 */ 42#define IO_SERIAL1_BASE 0x3f8ul /* I/O base for SMSC FDC37C93xAPM Serial #1 */ 43 44#define IO_ISP1161_EXTENT 0x04ul /* I/O extent for Philips ISP1161x USB chip */ 45#define IO_LAN91C111_EXTENT 0x10ul /* I/O extent for SMSC LAN91C111 Ethernet chip */ 46#define IO_SUPERIO_EXTENT 0x02ul /* I/O extent for SMSC FDC37C93xAPM SuperIO chip */ 47#define IO_IDE_EXTENT 0x08ul /* I/O extent for IDE Task Register set */ 48#define IO_SERIAL_EXTENT 0x10ul 49 50#define IO_LAN91C111_PHYS 0xa7500000ul /* Physical address of SMSC LAN91C111 Ethernet chip */ 51#define IO_ISP1161_PHYS 0xa7700000ul /* Physical address of Philips ISP1161x USB chip */ 52#define IO_SUPERIO_PHYS 0xa7800000ul /* Physical address of SMSC FDC37C93xAPM SuperIO chip */ 53 54/* 55 * map I/O ports to memory-mapped addresses 56 */ 57static unsigned long microdev_isa_port2addr(unsigned long offset) 58{ 59 unsigned long result; 60 61 if ((offset >= IO_LAN91C111_BASE) && 62 (offset < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) { 63 /* 64 * SMSC LAN91C111 Ethernet chip 65 */ 66 result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE; 67 } else if ((offset >= IO_SUPERIO_BASE) && 68 (offset < IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) { 69 /* 70 * SMSC FDC37C93xAPM SuperIO chip 71 * 72 * Configuration Registers 73 */ 74 result = IO_SUPERIO_PHYS + (offset << 1); 75 } else if (((offset >= IO_IDE1_BASE) && 76 (offset < IO_IDE1_BASE + IO_IDE_EXTENT)) || 77 (offset == IO_IDE1_MISC)) { 78 /* 79 * SMSC FDC37C93xAPM SuperIO chip 80 * 81 * IDE #1 82 */ 83 result = IO_SUPERIO_PHYS + (offset << 1); 84 } else if (((offset >= IO_IDE2_BASE) && 85 (offset < IO_IDE2_BASE + IO_IDE_EXTENT)) || 86 (offset == IO_IDE2_MISC)) { 87 /* 88 * SMSC FDC37C93xAPM SuperIO chip 89 * 90 * IDE #2 91 */ 92 result = IO_SUPERIO_PHYS + (offset << 1); 93 } else if ((offset >= IO_SERIAL1_BASE) && 94 (offset < IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) { 95 /* 96 * SMSC FDC37C93xAPM SuperIO chip 97 * 98 * Serial #1 99 */ 100 result = IO_SUPERIO_PHYS + (offset << 1); 101 } else if ((offset >= IO_SERIAL2_BASE) && 102 (offset < IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) { 103 /* 104 * SMSC FDC37C93xAPM SuperIO chip 105 * 106 * Serial #2 107 */ 108 result = IO_SUPERIO_PHYS + (offset << 1); 109 } else if ((offset >= IO_ISP1161_BASE) && 110 (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) { 111 /* 112 * Philips USB ISP1161x chip 113 */ 114 result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE; 115 } else { 116 /* 117 * safe default. 118 */ 119 printk("Warning: unexpected port in %s( offset = 0x%lx )\n", 120 __func__, offset); 121 result = PVR; 122 } 123 124 return result; 125} 126 127#define PORT2ADDR(x) (microdev_isa_port2addr(x)) 128 129static inline void delay(void) 130{ 131#if defined(CONFIG_PCI) 132 /* System board present, just make a dummy SRAM access. (CS0 will be 133 mapped to PCI memory, probably good to avoid it.) */ 134 __raw_readw(0xa6800000); 135#else 136 /* CS0 will be mapped to flash, ROM etc so safe to access it. */ 137 __raw_readw(0xa0000000); 138#endif 139} 140 141unsigned char microdev_inb(unsigned long port) 142{ 143#ifdef CONFIG_PCI 144 if (port >= PCIBIOS_MIN_IO) 145 return microdev_pci_inb(port); 146#endif 147 return *(volatile unsigned char*)PORT2ADDR(port); 148} 149 150unsigned short microdev_inw(unsigned long port) 151{ 152#ifdef CONFIG_PCI 153 if (port >= PCIBIOS_MIN_IO) 154 return microdev_pci_inw(port); 155#endif 156 return *(volatile unsigned short*)PORT2ADDR(port); 157} 158 159unsigned int microdev_inl(unsigned long port) 160{ 161#ifdef CONFIG_PCI 162 if (port >= PCIBIOS_MIN_IO) 163 return microdev_pci_inl(port); 164#endif 165 return *(volatile unsigned int*)PORT2ADDR(port); 166} 167 168void microdev_outw(unsigned short b, unsigned long port) 169{ 170#ifdef CONFIG_PCI 171 if (port >= PCIBIOS_MIN_IO) { 172 microdev_pci_outw(b, port); 173 return; 174 } 175#endif 176 *(volatile unsigned short*)PORT2ADDR(port) = b; 177} 178 179void microdev_outb(unsigned char b, unsigned long port) 180{ 181#ifdef CONFIG_PCI 182 if (port >= PCIBIOS_MIN_IO) { 183 microdev_pci_outb(b, port); 184 return; 185 } 186#endif 187 188 /* 189 * There is a board feature with the current SH4-202 MicroDev in 190 * that the 2 byte enables (nBE0 and nBE1) are tied together (and 191 * to the Chip Select Line (Ethernet_CS)). Due to this connectivity, 192 * it is not possible to safely perform 8-bit writes to the 193 * Ethernet registers, as 16-bits will be consumed from the Data 194 * lines (corrupting the other byte). Hence, this function is 195 * written to implement 16-bit read/modify/write for all byte-wide 196 * accesses. 197 * 198 * Note: there is no problem with byte READS (even or odd). 199 * 200 * Sean McGoogan - 16th June 2003. 201 */ 202 if ((port >= IO_LAN91C111_BASE) && 203 (port < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) { 204 /* 205 * Then are trying to perform a byte-write to the 206 * LAN91C111. This needs special care. 207 */ 208 if (port % 2 == 1) { /* is the port odd ? */ 209 /* unset bit-0, i.e. make even */ 210 const unsigned long evenPort = port-1; 211 unsigned short word; 212 213 /* 214 * do a 16-bit read/write to write to 'port', 215 * preserving even byte. 216 * 217 * Even addresses are bits 0-7 218 * Odd addresses are bits 8-15 219 */ 220 word = microdev_inw(evenPort); 221 word = (word & 0xffu) | (b << 8); 222 microdev_outw(word, evenPort); 223 } else { 224 /* else, we are trying to do an even byte write */ 225 unsigned short word; 226 227 /* 228 * do a 16-bit read/write to write to 'port', 229 * preserving odd byte. 230 * 231 * Even addresses are bits 0-7 232 * Odd addresses are bits 8-15 233 */ 234 word = microdev_inw(port); 235 word = (word & 0xff00u) | (b); 236 microdev_outw(word, port); 237 } 238 } else { 239 *(volatile unsigned char*)PORT2ADDR(port) = b; 240 } 241} 242 243void microdev_outl(unsigned int b, unsigned long port) 244{ 245#ifdef CONFIG_PCI 246 if (port >= PCIBIOS_MIN_IO) { 247 microdev_pci_outl(b, port); 248 return; 249 } 250#endif 251 *(volatile unsigned int*)PORT2ADDR(port) = b; 252} 253 254unsigned char microdev_inb_p(unsigned long port) 255{ 256 unsigned char v = microdev_inb(port); 257 delay(); 258 return v; 259} 260 261unsigned short microdev_inw_p(unsigned long port) 262{ 263 unsigned short v = microdev_inw(port); 264 delay(); 265 return v; 266} 267 268unsigned int microdev_inl_p(unsigned long port) 269{ 270 unsigned int v = microdev_inl(port); 271 delay(); 272 return v; 273} 274 275void microdev_outb_p(unsigned char b, unsigned long port) 276{ 277 microdev_outb(b, port); 278 delay(); 279} 280 281void microdev_outw_p(unsigned short b, unsigned long port) 282{ 283 microdev_outw(b, port); 284 delay(); 285} 286 287void microdev_outl_p(unsigned int b, unsigned long port) 288{ 289 microdev_outl(b, port); 290 delay(); 291} 292 293void microdev_insb(unsigned long port, void *buffer, unsigned long count) 294{ 295 volatile unsigned char *port_addr; 296 unsigned char *buf = buffer; 297 298 port_addr = (volatile unsigned char *)PORT2ADDR(port); 299 300 while (count--) 301 *buf++ = *port_addr; 302} 303 304void microdev_insw(unsigned long port, void *buffer, unsigned long count) 305{ 306 volatile unsigned short *port_addr; 307 unsigned short *buf = buffer; 308 309 port_addr = (volatile unsigned short *)PORT2ADDR(port); 310 311 while (count--) 312 *buf++ = *port_addr; 313} 314 315void microdev_insl(unsigned long port, void *buffer, unsigned long count) 316{ 317 volatile unsigned long *port_addr; 318 unsigned int *buf = buffer; 319 320 port_addr = (volatile unsigned long *)PORT2ADDR(port); 321 322 while (count--) 323 *buf++ = *port_addr; 324} 325 326void microdev_outsb(unsigned long port, const void *buffer, unsigned long count) 327{ 328 volatile unsigned char *port_addr; 329 const unsigned char *buf = buffer; 330 331 port_addr = (volatile unsigned char *)PORT2ADDR(port); 332 333 while (count--) 334 *port_addr = *buf++; 335} 336 337void microdev_outsw(unsigned long port, const void *buffer, unsigned long count) 338{ 339 volatile unsigned short *port_addr; 340 const unsigned short *buf = buffer; 341 342 port_addr = (volatile unsigned short *)PORT2ADDR(port); 343 344 while (count--) 345 *port_addr = *buf++; 346} 347 348void microdev_outsl(unsigned long port, const void *buffer, unsigned long count) 349{ 350 volatile unsigned long *port_addr; 351 const unsigned int *buf = buffer; 352 353 port_addr = (volatile unsigned long *)PORT2ADDR(port); 354 355 while (count--) 356 *port_addr = *buf++; 357} 358