0befd4f9894c0e55f52b23126230bc421191a121
[linux-2.6.git] / arch / sh / boards / renesas / systemh / io.c
1 /*
2  * linux/arch/sh/boards/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  */
10
11 #include <linux/kernel.h>
12 #include <linux/types.h>
13 #include <linux/pci.h>
14 #include <asm/systemh7751.h>
15 #include <asm/addrspace.h>
16 #include <asm/io.h>
17 #include "../../../drivers/pci/pci-sh7751.h"
18
19 /*
20  * The 7751 SystemH Engine uses the built-in PCI controller (PCIC)
21  * of the 7751 processor, and has a SuperIO accessible on its memory
22  * bus.
23  */
24
25 #define PCIIOBR         (volatile long *)PCI_REG(SH7751_PCIIOBR)
26 #define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
27 #define PCI_IO_AREA     SH7751_PCI_IO_BASE
28 #define PCI_MEM_AREA    SH7751_PCI_CONFIG_BASE
29
30 #define PCI_IOMAP(adr)  (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
31 #define ETHER_IOMAP(adr) (0xB3000000 + (adr)) /*map to 16bits access area
32                                                 of smc lan chip*/
33 static inline void delay(void)
34 {
35         ctrl_inw(0xa0000000);
36 }
37
38 static inline volatile __u16 *
39 port2adr(unsigned int port)
40 {
41         if (port >= 0x2000)
42                 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
43         maybebadio((unsigned long)port);
44         return (volatile __u16*)port;
45 }
46
47 /* In case someone configures the kernel w/o PCI support: in that */
48 /* scenario, don't ever bother to check for PCI-window addresses */
49
50 /* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
51 #if defined(CONFIG_PCI)
52 #define CHECK_SH7751_PCIIO(port) \
53   ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
54 #else
55 #define CHECK_SH7751_PCIIO(port) (0)
56 #endif
57
58 /*
59  * General outline: remap really low stuff [eventually] to SuperIO,
60  * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
61  * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
62  * should be way beyond the window, and is used  w/o translation for
63  * compatibility.
64  */
65 unsigned char sh7751systemh_inb(unsigned long port)
66 {
67         if (PXSEG(port))
68                 return *(volatile unsigned char *)port;
69         else if (CHECK_SH7751_PCIIO(port))
70                 return *(volatile unsigned char *)PCI_IOMAP(port);
71         else if (port <= 0x3F1)
72                 return *(volatile unsigned char *)ETHER_IOMAP(port);
73         else
74                 return (*port2adr(port))&0xff;
75 }
76
77 unsigned char sh7751systemh_inb_p(unsigned long port)
78 {
79         unsigned char v;
80
81         if (PXSEG(port))
82                 v = *(volatile unsigned char *)port;
83         else if (CHECK_SH7751_PCIIO(port))
84                 v = *(volatile unsigned char *)PCI_IOMAP(port);
85         else if (port <= 0x3F1)
86                 v = *(volatile unsigned char *)ETHER_IOMAP(port);
87         else
88                 v = (*port2adr(port))&0xff;
89         delay();
90         return v;
91 }
92
93 unsigned short sh7751systemh_inw(unsigned long port)
94 {
95         if (PXSEG(port))
96                 return *(volatile unsigned short *)port;
97         else if (CHECK_SH7751_PCIIO(port))
98                 return *(volatile unsigned short *)PCI_IOMAP(port);
99         else if (port >= 0x2000)
100                 return *port2adr(port);
101         else if (port <= 0x3F1)
102                 return *(volatile unsigned int *)ETHER_IOMAP(port);
103         else
104                 maybebadio(port);
105         return 0;
106 }
107
108 unsigned int sh7751systemh_inl(unsigned long port)
109 {
110         if (PXSEG(port))
111                 return *(volatile unsigned long *)port;
112         else if (CHECK_SH7751_PCIIO(port))
113                 return *(volatile unsigned int *)PCI_IOMAP(port);
114         else if (port >= 0x2000)
115                 return *port2adr(port);
116         else if (port <= 0x3F1)
117                 return *(volatile unsigned int *)ETHER_IOMAP(port);
118         else
119                 maybebadio(port);
120         return 0;
121 }
122
123 void sh7751systemh_outb(unsigned char value, unsigned long port)
124 {
125
126         if (PXSEG(port))
127                 *(volatile unsigned char *)port = value;
128         else if (CHECK_SH7751_PCIIO(port))
129                 *((unsigned char*)PCI_IOMAP(port)) = value;
130         else if (port <= 0x3F1)
131                 *(volatile unsigned char *)ETHER_IOMAP(port) = value;
132         else
133                 *(port2adr(port)) = value;
134 }
135
136 void sh7751systemh_outb_p(unsigned char value, unsigned long port)
137 {
138         if (PXSEG(port))
139                 *(volatile unsigned char *)port = value;
140         else if (CHECK_SH7751_PCIIO(port))
141                 *((unsigned char*)PCI_IOMAP(port)) = value;
142         else if (port <= 0x3F1)
143                 *(volatile unsigned char *)ETHER_IOMAP(port) = value;
144         else
145                 *(port2adr(port)) = value;
146         delay();
147 }
148
149 void sh7751systemh_outw(unsigned short value, unsigned long port)
150 {
151         if (PXSEG(port))
152                 *(volatile unsigned short *)port = value;
153         else if (CHECK_SH7751_PCIIO(port))
154                 *((unsigned short *)PCI_IOMAP(port)) = value;
155         else if (port >= 0x2000)
156                 *port2adr(port) = value;
157         else if (port <= 0x3F1)
158                 *(volatile unsigned short *)ETHER_IOMAP(port) = value;
159         else
160                 maybebadio(port);
161 }
162
163 void sh7751systemh_outl(unsigned int value, unsigned long port)
164 {
165         if (PXSEG(port))
166                 *(volatile unsigned long *)port = value;
167         else if (CHECK_SH7751_PCIIO(port))
168                 *((unsigned long*)PCI_IOMAP(port)) = value;
169         else
170                 maybebadio(port);
171 }
172
173 void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count)
174 {
175         unsigned char *p = addr;
176         while (count--) *p++ = sh7751systemh_inb(port);
177 }
178
179 void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count)
180 {
181         unsigned short *p = addr;
182         while (count--) *p++ = sh7751systemh_inw(port);
183 }
184
185 void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count)
186 {
187         maybebadio(port);
188 }
189
190 void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count)
191 {
192         unsigned char *p = (unsigned char*)addr;
193         while (count--) sh7751systemh_outb(*p++, port);
194 }
195
196 void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long count)
197 {
198         unsigned short *p = (unsigned short*)addr;
199         while (count--) sh7751systemh_outw(*p++, port);
200 }
201
202 void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count)
203 {
204         maybebadio(port);
205 }