sh: Board updates for I/O routine rework.
[linux-2.6.git] / arch / sh / boards / se / 7751 / io.c
1 /*
2  * linux/arch/sh/kernel/io_7751se.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 SolutionEngine.
8  *
9  * Initial version only to support LAN access; some
10  * placeholder code from io_se.c left in with the
11  * expectation of later SuperIO and PCMCIA access.
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <asm/io.h>
17 #include <asm/se7751.h>
18 #include <asm/addrspace.h>
19
20 #include <linux/pci.h>
21 #include "../../../drivers/pci/pci-sh7751.h"
22
23 #if 0
24 /******************************************************************
25  * Variables from io_se.c, related to PCMCIA (not PCI); we're not
26  * compiling them in, and have removed references from functions
27  * which follow.  [Many checked for IO ports in the range bounded
28  * by sh_pcic_io_start/stop, and used sh_pcic_io_wbase as offset.
29  * As start/stop are uninitialized, only port 0x0 would match?]
30  * When used, remember to adjust names to avoid clash with io_se?
31  *****************************************************************/
32 /* SH pcmcia io window base, start and end.  */
33 int sh_pcic_io_wbase = 0xb8400000;
34 int sh_pcic_io_start;
35 int sh_pcic_io_stop;
36 int sh_pcic_io_type;
37 int sh_pcic_io_dummy;
38 /*************************************************************/
39 #endif
40
41 /*
42  * The 7751 Solution Engine uses the built-in PCI controller (PCIC)
43  * of the 7751 processor, and has a SuperIO accessible via the PCI.
44  * The board also includes a PCMCIA controller on its memory bus,
45  * like the other Solution Engine boards.
46  */ 
47
48 #define PCIIOBR         (volatile long *)PCI_REG(SH7751_PCIIOBR)
49 #define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
50 #define PCI_IO_AREA     SH7751_PCI_IO_BASE
51 #define PCI_MEM_AREA    SH7751_PCI_CONFIG_BASE
52
53 #define PCI_IOMAP(adr)  (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
54
55 static inline void delay(void)
56 {
57         ctrl_inw(0xa0000000);
58 }
59
60 static inline volatile __u16 *
61 port2adr(unsigned int port)
62 {
63         if (port >= 0x2000)
64                 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
65         maybebadio((unsigned long)port);
66         return (volatile __u16*)port;
67 }
68
69 #if 0
70 /* The 7751 Solution Engine seems to have everything hooked */
71 /* up pretty normally (nothing on high-bytes only...) so this */
72 /* shouldn't be needed */
73 static inline int
74 shifted_port(unsigned long port)
75 {
76         /* For IDE registers, value is not shifted */
77         if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
78                 return 0;
79         else
80                 return 1;
81 }
82 #endif
83
84 /* In case someone configures the kernel w/o PCI support: in that */
85 /* scenario, don't ever bother to check for PCI-window addresses */
86
87 /* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
88 #if defined(CONFIG_PCI)
89 #define CHECK_SH7751_PCIIO(port) \
90   ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
91 #else
92 #define CHECK_SH7751_PCIIO(port) (0)
93 #endif
94
95 /*
96  * General outline: remap really low stuff [eventually] to SuperIO,
97  * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
98  * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
99  * should be way beyond the window, and is used  w/o translation for
100  * compatibility.
101  */
102 unsigned char sh7751se_inb(unsigned long port)
103 {
104         if (PXSEG(port))
105                 return *(volatile unsigned char *)port;
106         else if (CHECK_SH7751_PCIIO(port))
107                 return *(volatile unsigned char *)PCI_IOMAP(port);
108         else
109                 return (*port2adr(port))&0xff; 
110 }
111
112 unsigned char sh7751se_inb_p(unsigned long port)
113 {
114         unsigned char v;
115
116         if (PXSEG(port))
117                 v = *(volatile unsigned char *)port;
118         else if (CHECK_SH7751_PCIIO(port))
119                 v = *(volatile unsigned char *)PCI_IOMAP(port);
120         else
121                 v = (*port2adr(port))&0xff; 
122         delay();
123         return v;
124 }
125
126 unsigned short sh7751se_inw(unsigned long port)
127 {
128         if (PXSEG(port))
129                 return *(volatile unsigned short *)port;
130         else if (CHECK_SH7751_PCIIO(port))
131                 return *(volatile unsigned short *)PCI_IOMAP(port);
132         else if (port >= 0x2000)
133                 return *port2adr(port);
134         else
135                 maybebadio(port);
136         return 0;
137 }
138
139 unsigned int sh7751se_inl(unsigned long port)
140 {
141         if (PXSEG(port))
142                 return *(volatile unsigned long *)port;
143         else if (CHECK_SH7751_PCIIO(port))
144                 return *(volatile unsigned int *)PCI_IOMAP(port);
145         else if (port >= 0x2000)
146                 return *port2adr(port);
147         else
148                 maybebadio(port);
149         return 0;
150 }
151
152 void sh7751se_outb(unsigned char value, unsigned long port)
153 {
154
155         if (PXSEG(port))
156                 *(volatile unsigned char *)port = value;
157         else if (CHECK_SH7751_PCIIO(port))
158                 *((unsigned char*)PCI_IOMAP(port)) = value;
159         else
160                 *(port2adr(port)) = value;
161 }
162
163 void sh7751se_outb_p(unsigned char value, unsigned long port)
164 {
165         if (PXSEG(port))
166                 *(volatile unsigned char *)port = value;
167         else if (CHECK_SH7751_PCIIO(port))
168                 *((unsigned char*)PCI_IOMAP(port)) = value;
169         else
170                 *(port2adr(port)) = value;
171         delay();
172 }
173
174 void sh7751se_outw(unsigned short value, unsigned long port)
175 {
176         if (PXSEG(port))
177                 *(volatile unsigned short *)port = value;
178         else if (CHECK_SH7751_PCIIO(port))
179                 *((unsigned short *)PCI_IOMAP(port)) = value;
180         else if (port >= 0x2000)
181                 *port2adr(port) = value;
182         else
183                 maybebadio(port);
184 }
185
186 void sh7751se_outl(unsigned int value, unsigned long port)
187 {
188         if (PXSEG(port))
189                 *(volatile unsigned long *)port = value;
190         else if (CHECK_SH7751_PCIIO(port))
191                 *((unsigned long*)PCI_IOMAP(port)) = value;
192         else
193                 maybebadio(port);
194 }
195
196 void sh7751se_insl(unsigned long port, void *addr, unsigned long count)
197 {
198         maybebadio(port);
199 }
200
201 void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count)
202 {
203         maybebadio(port);
204 }
205
206 /* Map ISA bus address to the real address. Only for PCMCIA.  */
207
208 /* ISA page descriptor.  */
209 static __u32 sh_isa_memmap[256];
210
211 #if 0
212 static int
213 sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
214 {
215         int idx;
216
217         if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
218                 return -1;
219
220         idx = start >> 12;
221         sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
222         printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
223                start, length, offset, idx, sh_isa_memmap[idx]);
224         return 0;
225 }
226 #endif
227
228 unsigned long
229 sh7751se_isa_port2addr(unsigned long offset)
230 {
231         int idx;
232
233         idx = (offset >> 12) & 0xff;
234         offset &= 0xfff;
235         return sh_isa_memmap[idx] + offset;
236 }