Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
[linux-2.6] / arch / sh / boards / mach-systemh / io.c
1 /*
2  * linux/arch/sh/boards/renesas/systemh/io.c
3  *
4  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
5  * Based largely on io_se.c.
6  *
7  * I/O routine for Hitachi 7751 Systemh.
8  */
9 #include <linux/kernel.h>
10 #include <linux/types.h>
11 #include <linux/pci.h>
12 #include <asm/systemh7751.h>
13 #include <asm/addrspace.h>
14 #include <asm/io.h>
15
16 #define ETHER_IOMAP(adr) (0xB3000000 + (adr)) /*map to 16bits access area
17                                                 of smc lan chip*/
18 static inline volatile __u16 *
19 port2adr(unsigned int port)
20 {
21         if (port >= 0x2000)
22                 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
23         maybebadio((unsigned long)port);
24         return (volatile __u16*)port;
25 }
26
27 /*
28  * General outline: remap really low stuff [eventually] to SuperIO,
29  * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
30  * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
31  * should be way beyond the window, and is used  w/o translation for
32  * compatibility.
33  */
34 unsigned char sh7751systemh_inb(unsigned long port)
35 {
36         if (PXSEG(port))
37                 return *(volatile unsigned char *)port;
38         else if (is_pci_ioaddr(port))
39                 return *(volatile unsigned char *)pci_ioaddr(port);
40         else if (port <= 0x3F1)
41                 return *(volatile unsigned char *)ETHER_IOMAP(port);
42         else
43                 return (*port2adr(port))&0xff;
44 }
45
46 unsigned char sh7751systemh_inb_p(unsigned long port)
47 {
48         unsigned char v;
49
50         if (PXSEG(port))
51                 v = *(volatile unsigned char *)port;
52         else if (is_pci_ioaddr(port))
53                 v = *(volatile unsigned char *)pci_ioaddr(port);
54         else if (port <= 0x3F1)
55                 v = *(volatile unsigned char *)ETHER_IOMAP(port);
56         else
57                 v = (*port2adr(port))&0xff;
58         ctrl_delay();
59         return v;
60 }
61
62 unsigned short sh7751systemh_inw(unsigned long port)
63 {
64         if (PXSEG(port))
65                 return *(volatile unsigned short *)port;
66         else if (is_pci_ioaddr(port))
67                 return *(volatile unsigned short *)pci_ioaddr(port);
68         else if (port >= 0x2000)
69                 return *port2adr(port);
70         else if (port <= 0x3F1)
71                 return *(volatile unsigned int *)ETHER_IOMAP(port);
72         else
73                 maybebadio(port);
74         return 0;
75 }
76
77 unsigned int sh7751systemh_inl(unsigned long port)
78 {
79         if (PXSEG(port))
80                 return *(volatile unsigned long *)port;
81         else if (is_pci_ioaddr(port))
82                 return *(volatile unsigned int *)pci_ioaddr(port);
83         else if (port >= 0x2000)
84                 return *port2adr(port);
85         else if (port <= 0x3F1)
86                 return *(volatile unsigned int *)ETHER_IOMAP(port);
87         else
88                 maybebadio(port);
89         return 0;
90 }
91
92 void sh7751systemh_outb(unsigned char value, unsigned long port)
93 {
94
95         if (PXSEG(port))
96                 *(volatile unsigned char *)port = value;
97         else if (is_pci_ioaddr(port))
98                 *((unsigned char*)pci_ioaddr(port)) = value;
99         else if (port <= 0x3F1)
100                 *(volatile unsigned char *)ETHER_IOMAP(port) = value;
101         else
102                 *(port2adr(port)) = value;
103 }
104
105 void sh7751systemh_outb_p(unsigned char value, unsigned long port)
106 {
107         if (PXSEG(port))
108                 *(volatile unsigned char *)port = value;
109         else if (is_pci_ioaddr(port))
110                 *((unsigned char*)pci_ioaddr(port)) = value;
111         else if (port <= 0x3F1)
112                 *(volatile unsigned char *)ETHER_IOMAP(port) = value;
113         else
114                 *(port2adr(port)) = value;
115         ctrl_delay();
116 }
117
118 void sh7751systemh_outw(unsigned short value, unsigned long port)
119 {
120         if (PXSEG(port))
121                 *(volatile unsigned short *)port = value;
122         else if (is_pci_ioaddr(port))
123                 *((unsigned short *)pci_ioaddr(port)) = value;
124         else if (port >= 0x2000)
125                 *port2adr(port) = value;
126         else if (port <= 0x3F1)
127                 *(volatile unsigned short *)ETHER_IOMAP(port) = value;
128         else
129                 maybebadio(port);
130 }
131
132 void sh7751systemh_outl(unsigned int value, unsigned long port)
133 {
134         if (PXSEG(port))
135                 *(volatile unsigned long *)port = value;
136         else if (is_pci_ioaddr(port))
137                 *((unsigned long*)pci_ioaddr(port)) = value;
138         else
139                 maybebadio(port);
140 }
141
142 void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count)
143 {
144         unsigned char *p = addr;
145         while (count--) *p++ = sh7751systemh_inb(port);
146 }
147
148 void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count)
149 {
150         unsigned short *p = addr;
151         while (count--) *p++ = sh7751systemh_inw(port);
152 }
153
154 void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count)
155 {
156         maybebadio(port);
157 }
158
159 void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count)
160 {
161         unsigned char *p = (unsigned char*)addr;
162         while (count--) sh7751systemh_outb(*p++, port);
163 }
164
165 void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long count)
166 {
167         unsigned short *p = (unsigned short*)addr;
168         while (count--) sh7751systemh_outw(*p++, port);
169 }
170
171 void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count)
172 {
173         maybebadio(port);
174 }