2 * linux/arch/sh/kernel/io_microdev.c
4 * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
5 * Copyright (C) 2003, 2004 SuperH, Inc.
6 * Copyright (C) 2004 Paul Mundt
8 * SuperH SH4-202 MicroDev board support.
10 * May be copied or modified under the terms of the GNU General Public
11 * License. See linux/COPYING for more information.
14 #include <linux/config.h>
15 #include <linux/init.h>
16 #include <linux/pci.h>
17 #include <linux/wait.h>
19 #include <asm/microdev.h>
22 * we need to have a 'safe' address to re-direct all I/O requests
23 * that we do not explicitly wish to handle. This safe address
24 * must have the following properies:
26 * * writes are ignored (no exception)
27 * * reads are benign (no side-effects)
28 * * accesses of width 1, 2 and 4-bytes are all valid.
30 * The Processor Version Register (PVR) has these properties.
32 #define PVR 0xff000030 /* Processor Version Register */
35 #define IO_IDE2_BASE 0x170ul /* I/O base for SMSC FDC37C93xAPM IDE #2 */
36 #define IO_IDE1_BASE 0x1f0ul /* I/O base for SMSC FDC37C93xAPM IDE #1 */
37 #define IO_ISP1161_BASE 0x290ul /* I/O port for Philips ISP1161x USB chip */
38 #define IO_SERIAL2_BASE 0x2f8ul /* I/O base for SMSC FDC37C93xAPM Serial #2 */
39 #define IO_LAN91C111_BASE 0x300ul /* I/O base for SMSC LAN91C111 Ethernet chip */
40 #define IO_IDE2_MISC 0x376ul /* I/O misc for SMSC FDC37C93xAPM IDE #2 */
41 #define IO_SUPERIO_BASE 0x3f0ul /* I/O base for SMSC FDC37C93xAPM SuperIO chip */
42 #define IO_IDE1_MISC 0x3f6ul /* I/O misc for SMSC FDC37C93xAPM IDE #1 */
43 #define IO_SERIAL1_BASE 0x3f8ul /* I/O base for SMSC FDC37C93xAPM Serial #1 */
45 #define IO_ISP1161_EXTENT 0x04ul /* I/O extent for Philips ISP1161x USB chip */
46 #define IO_LAN91C111_EXTENT 0x10ul /* I/O extent for SMSC LAN91C111 Ethernet chip */
47 #define IO_SUPERIO_EXTENT 0x02ul /* I/O extent for SMSC FDC37C93xAPM SuperIO chip */
48 #define IO_IDE_EXTENT 0x08ul /* I/O extent for IDE Task Register set */
49 #define IO_SERIAL_EXTENT 0x10ul
51 #define IO_LAN91C111_PHYS 0xa7500000ul /* Physical address of SMSC LAN91C111 Ethernet chip */
52 #define IO_ISP1161_PHYS 0xa7700000ul /* Physical address of Philips ISP1161x USB chip */
53 #define IO_SUPERIO_PHYS 0xa7800000ul /* Physical address of SMSC FDC37C93xAPM SuperIO chip */
56 * map I/O ports to memory-mapped addresses
58 static unsigned long microdev_isa_port2addr(unsigned long offset)
62 if ((offset >= IO_LAN91C111_BASE) &&
63 (offset < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
65 * SMSC LAN91C111 Ethernet chip
67 result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE;
68 } else if ((offset >= IO_SUPERIO_BASE) &&
69 (offset < IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) {
71 * SMSC FDC37C93xAPM SuperIO chip
73 * Configuration Registers
75 result = IO_SUPERIO_PHYS + (offset << 1);
77 } else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG ||
78 offset == KBD_STATUS_REG) {
80 * SMSC FDC37C93xAPM SuperIO chip
82 * PS/2 Keyboard + Mouse (ports 0x60 and 0x64).
84 result = IO_SUPERIO_PHYS + (offset << 1);
86 } else if (((offset >= IO_IDE1_BASE) &&
87 (offset < IO_IDE1_BASE + IO_IDE_EXTENT)) ||
88 (offset == IO_IDE1_MISC)) {
90 * SMSC FDC37C93xAPM SuperIO chip
94 result = IO_SUPERIO_PHYS + (offset << 1);
95 } else if (((offset >= IO_IDE2_BASE) &&
96 (offset < IO_IDE2_BASE + IO_IDE_EXTENT)) ||
97 (offset == IO_IDE2_MISC)) {
99 * SMSC FDC37C93xAPM SuperIO chip
103 result = IO_SUPERIO_PHYS + (offset << 1);
104 } else if ((offset >= IO_SERIAL1_BASE) &&
105 (offset < IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) {
107 * SMSC FDC37C93xAPM SuperIO chip
111 result = IO_SUPERIO_PHYS + (offset << 1);
112 } else if ((offset >= IO_SERIAL2_BASE) &&
113 (offset < IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) {
115 * SMSC FDC37C93xAPM SuperIO chip
119 result = IO_SUPERIO_PHYS + (offset << 1);
120 } else if ((offset >= IO_ISP1161_BASE) &&
121 (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) {
123 * Philips USB ISP1161x chip
125 result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE;
130 printk("Warning: unexpected port in %s( offset = 0x%lx )\n",
131 __FUNCTION__, offset);
138 #define PORT2ADDR(x) (microdev_isa_port2addr(x))
140 static inline void delay(void)
142 #if defined(CONFIG_PCI)
143 /* System board present, just make a dummy SRAM access. (CS0 will be
144 mapped to PCI memory, probably good to avoid it.) */
145 ctrl_inw(0xa6800000);
147 /* CS0 will be mapped to flash, ROM etc so safe to access it. */
148 ctrl_inw(0xa0000000);
152 unsigned char microdev_inb(unsigned long port)
155 if (port >= PCIBIOS_MIN_IO)
156 return microdev_pci_inb(port);
158 return *(volatile unsigned char*)PORT2ADDR(port);
161 unsigned short microdev_inw(unsigned long port)
164 if (port >= PCIBIOS_MIN_IO)
165 return microdev_pci_inw(port);
167 return *(volatile unsigned short*)PORT2ADDR(port);
170 unsigned int microdev_inl(unsigned long port)
173 if (port >= PCIBIOS_MIN_IO)
174 return microdev_pci_inl(port);
176 return *(volatile unsigned int*)PORT2ADDR(port);
179 void microdev_outw(unsigned short b, unsigned long port)
182 if (port >= PCIBIOS_MIN_IO) {
183 microdev_pci_outw(b, port);
187 *(volatile unsigned short*)PORT2ADDR(port) = b;
190 void microdev_outb(unsigned char b, unsigned long port)
193 if (port >= PCIBIOS_MIN_IO) {
194 microdev_pci_outb(b, port);
200 * There is a board feature with the current SH4-202 MicroDev in
201 * that the 2 byte enables (nBE0 and nBE1) are tied together (and
202 * to the Chip Select Line (Ethernet_CS)). Due to this conectivity,
203 * it is not possible to safely perform 8-bit writes to the
204 * Ethernet registers, as 16-bits will be consumed from the Data
205 * lines (corrupting the other byte). Hence, this function is
206 * written to impliment 16-bit read/modify/write for all byte-wide
209 * Note: there is no problem with byte READS (even or odd).
211 * Sean McGoogan - 16th June 2003.
213 if ((port >= IO_LAN91C111_BASE) &&
214 (port < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
216 * Then are trying to perform a byte-write to the
217 * LAN91C111. This needs special care.
219 if (port % 2 == 1) { /* is the port odd ? */
220 /* unset bit-0, i.e. make even */
221 const unsigned long evenPort = port-1;
225 * do a 16-bit read/write to write to 'port',
226 * preserving even byte.
228 * Even addresses are bits 0-7
229 * Odd addresses are bits 8-15
231 word = microdev_inw(evenPort);
232 word = (word & 0xffu) | (b << 8);
233 microdev_outw(word, evenPort);
235 /* else, we are trying to do an even byte write */
239 * do a 16-bit read/write to write to 'port',
240 * preserving odd byte.
242 * Even addresses are bits 0-7
243 * Odd addresses are bits 8-15
245 word = microdev_inw(port);
246 word = (word & 0xff00u) | (b);
247 microdev_outw(word, port);
250 *(volatile unsigned char*)PORT2ADDR(port) = b;
254 void microdev_outl(unsigned int b, unsigned long port)
257 if (port >= PCIBIOS_MIN_IO) {
258 microdev_pci_outl(b, port);
262 *(volatile unsigned int*)PORT2ADDR(port) = b;
265 unsigned char microdev_inb_p(unsigned long port)
267 unsigned char v = microdev_inb(port);
272 unsigned short microdev_inw_p(unsigned long port)
274 unsigned short v = microdev_inw(port);
279 unsigned int microdev_inl_p(unsigned long port)
281 unsigned int v = microdev_inl(port);
286 void microdev_outb_p(unsigned char b, unsigned long port)
288 microdev_outb(b, port);
292 void microdev_outw_p(unsigned short b, unsigned long port)
294 microdev_outw(b, port);
298 void microdev_outl_p(unsigned int b, unsigned long port)
300 microdev_outl(b, port);
304 void microdev_insb(unsigned long port, void *buffer, unsigned long count)
306 volatile unsigned char *port_addr;
307 unsigned char *buf = buffer;
309 port_addr = (volatile unsigned char *)PORT2ADDR(port);
315 void microdev_insw(unsigned long port, void *buffer, unsigned long count)
317 volatile unsigned short *port_addr;
318 unsigned short *buf = buffer;
320 port_addr = (volatile unsigned short *)PORT2ADDR(port);
326 void microdev_insl(unsigned long port, void *buffer, unsigned long count)
328 volatile unsigned long *port_addr;
329 unsigned int *buf = buffer;
331 port_addr = (volatile unsigned long *)PORT2ADDR(port);
337 void microdev_outsb(unsigned long port, const void *buffer, unsigned long count)
339 volatile unsigned char *port_addr;
340 const unsigned char *buf = buffer;
342 port_addr = (volatile unsigned char *)PORT2ADDR(port);
348 void microdev_outsw(unsigned long port, const void *buffer, unsigned long count)
350 volatile unsigned short *port_addr;
351 const unsigned short *buf = buffer;
353 port_addr = (volatile unsigned short *)PORT2ADDR(port);
359 void microdev_outsl(unsigned long port, const void *buffer, unsigned long count)
361 volatile unsigned long *port_addr;
362 const unsigned int *buf = buffer;
364 port_addr = (volatile unsigned long *)PORT2ADDR(port);