blob: aa6b145c9e8f400bbbe784bd57e66395be998f97 [file] [log] [blame]
kogiidena94c0fa52006-09-27 14:53:35 +09001/*
2 * arch/sh/boards/landisk/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 I-O Data Device, Inc. LANDISK.
8 *
9 * Initial version only to support LAN access; some
10 * placeholder code from io_landisk.c left in with the
11 * expectation of later SuperIO and PCMCIA access.
12 */
13/*
14 * modifed by kogiidena
15 * 2005.03.03
16 */
17
18#include <linux/kernel.h>
19#include <linux/types.h>
kogiidena94c0fa52006-09-27 14:53:35 +090020#include <asm/landisk/iodata_landisk.h>
21#include <asm/addrspace.h>
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090022#include <asm/io.h>
kogiidena94c0fa52006-09-27 14:53:35 +090023
24#include <linux/module.h>
25#include <linux/pci.h>
26#include "../../drivers/pci/pci-sh7751.h"
27
28extern void *area5_io_base; /* Area 5 I/O Base address */
29extern void *area6_io_base; /* Area 6 I/O Base address */
30
31/*
32 * The 7751R LANDISK uses the built-in PCI controller (PCIC)
33 * of the 7751R processor, and has a SuperIO accessible via the PCI.
34 * The board also includes a PCMCIA controller on its memory bus,
35 * like the other Solution Engine boards.
36 */
37
38#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
39#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
40#define PCI_IO_AREA SH7751_PCI_IO_BASE
41#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
42
43#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
44
kogiidena94c0fa52006-09-27 14:53:35 +090045static inline void delay(void)
46{
47 ctrl_inw(0xa0000000);
48}
49
50static inline unsigned long port2adr(unsigned int port)
51{
52 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
53 if (port == 0x3f6)
54 return ((unsigned long)area5_io_base + 0x2c);
55 else
56 return ((unsigned long)area5_io_base + PA_PIDE_OFFSET +
57 ((port - 0x1f0) << 1));
58 else if ((0x170 <= port && port < 0x178) || port == 0x376)
59 if (port == 0x376)
60 return ((unsigned long)area6_io_base + 0x2c);
61 else
62 return ((unsigned long)area6_io_base + PA_SIDE_OFFSET +
63 ((port - 0x170) << 1));
64 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090065 maybebadio((unsigned long)port);
kogiidena94c0fa52006-09-27 14:53:35 +090066
67 return port;
68}
69
70/* In case someone configures the kernel w/o PCI support: in that */
71/* scenario, don't ever bother to check for PCI-window addresses */
72
73/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
74#if defined(CONFIG_PCI)
75#define CHECK_SH7751_PCIIO(port) \
76 ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
77#else
78#define CHECK_SH_7751_PCIIO(port) (0)
79#endif
80
81/*
82 * General outline: remap really low stuff [eventually] to SuperIO,
83 * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
84 * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
85 * should be way beyond the window, and is used w/o translation for
86 * compatibility.
87 */
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090088u8 landisk_inb(unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +090089{
90 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090091 return ctrl_inb(port);
kogiidena94c0fa52006-09-27 14:53:35 +090092 else if (CHECK_SH7751_PCIIO(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090093 return ctrl_inb(PCI_IOMAP(port));
94
95 return ctrl_inw(port2adr(port)) & 0xff;
kogiidena94c0fa52006-09-27 14:53:35 +090096}
97
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090098u8 landisk_inb_p(unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +090099{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900100 u8 v;
kogiidena94c0fa52006-09-27 14:53:35 +0900101
102 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900103 v = ctrl_inb(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900104 else if (CHECK_SH7751_PCIIO(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900105 v = ctrl_inb(PCI_IOMAP(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900106 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900107 v = ctrl_inw(port2adr(port)) & 0xff;
108
kogiidena94c0fa52006-09-27 14:53:35 +0900109 delay();
110
111 return v;
112}
113
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900114u16 landisk_inw(unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +0900115{
116 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900117 return ctrl_inw(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900118 else if (CHECK_SH7751_PCIIO(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900119 return ctrl_inw(PCI_IOMAP(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900120 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900121 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900122
123 return 0;
124}
125
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900126u32 landisk_inl(unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +0900127{
128 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900129 return ctrl_inl(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900130 else if (CHECK_SH7751_PCIIO(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900131 return ctrl_inl(PCI_IOMAP(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900132 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900133 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900134
135 return 0;
136}
137
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900138void landisk_outb(u8 value, unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +0900139{
kogiidena94c0fa52006-09-27 14:53:35 +0900140 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900141 ctrl_outb(value, port);
kogiidena94c0fa52006-09-27 14:53:35 +0900142 else if (CHECK_SH7751_PCIIO(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900143 ctrl_outb(value, PCI_IOMAP(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900144 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900145 ctrl_outw(value, port2adr(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900146}
147
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900148void landisk_outb_p(u8 value, unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +0900149{
150 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900151 ctrl_outb(value, port);
kogiidena94c0fa52006-09-27 14:53:35 +0900152 else if (CHECK_SH7751_PCIIO(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900153 ctrl_outb(value, PCI_IOMAP(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900154 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900155 ctrl_outw(value, port2adr(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900156 delay();
157}
158
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900159void landisk_outw(u16 value, unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +0900160{
161 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900162 ctrl_outw(value, port);
kogiidena94c0fa52006-09-27 14:53:35 +0900163 else if (CHECK_SH7751_PCIIO(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900164 ctrl_outw(value, PCI_IOMAP(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900165 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900166 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900167}
168
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900169void landisk_outl(u32 value, unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +0900170{
171 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900172 ctrl_outl(value, port);
kogiidena94c0fa52006-09-27 14:53:35 +0900173 else if (CHECK_SH7751_PCIIO(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900174 ctrl_outl(value, PCI_IOMAP(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900175 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900176 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900177}
178
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900179void landisk_insb(unsigned long port, void *dst, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900180{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900181 volatile u16 *p;
182 u8 *buf = dst;
kogiidena94c0fa52006-09-27 14:53:35 +0900183
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900184 if (PXSEG(port)) {
185 while (count--)
186 *buf++ = *(volatile u8 *)port;
187 } else if (CHECK_SH7751_PCIIO(port)) {
188 volatile u8 *bp = (volatile u8 *)PCI_IOMAP(port);
189
190 while (count--)
191 *buf++ = *bp;
kogiidena94c0fa52006-09-27 14:53:35 +0900192 } else {
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900193 p = (volatile u16 *)port2adr(port);
194 while (count--)
195 *buf++ = *p & 0xff;
kogiidena94c0fa52006-09-27 14:53:35 +0900196 }
197}
198
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900199void landisk_insw(unsigned long port, void *dst, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900200{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900201 volatile u16 *p;
202 u16 *buf = dst;
kogiidena94c0fa52006-09-27 14:53:35 +0900203
204 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900205 p = (volatile u16 *)port;
kogiidena94c0fa52006-09-27 14:53:35 +0900206 else if (CHECK_SH7751_PCIIO(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900207 p = (volatile u16 *)PCI_IOMAP(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900208 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900209 p = (volatile u16 *)port2adr(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900210 while (count--)
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900211 *buf++ = *p;
kogiidena94c0fa52006-09-27 14:53:35 +0900212}
213
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900214void landisk_insl(unsigned long port, void *dst, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900215{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900216 u32 *buf = dst;
217
kogiidena94c0fa52006-09-27 14:53:35 +0900218 if (CHECK_SH7751_PCIIO(port)) {
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900219 volatile u32 *p = (volatile u32 *)PCI_IOMAP(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900220
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900221 while (count--)
222 *buf++ = *p;
kogiidena94c0fa52006-09-27 14:53:35 +0900223 } else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900224 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900225}
226
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900227void landisk_outsb(unsigned long port, const void *src, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900228{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900229 volatile u16 *p;
230 const u8 *buf = src;
231
kogiidena94c0fa52006-09-27 14:53:35 +0900232 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900233 while (count--)
234 ctrl_outb(*buf++, port);
kogiidena94c0fa52006-09-27 14:53:35 +0900235 else if (CHECK_SH7751_PCIIO(port)) {
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900236 volatile u8 *bp = (volatile u8 *)PCI_IOMAP(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900237
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900238 while (count--)
239 *bp = *buf++;
kogiidena94c0fa52006-09-27 14:53:35 +0900240 } else {
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900241 p = (volatile u16 *)port2adr(port);
242 while (count--)
243 *p = *buf++;
kogiidena94c0fa52006-09-27 14:53:35 +0900244 }
245}
246
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900247void landisk_outsw(unsigned long port, const void *src, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900248{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900249 volatile u16 *p;
250 const u16 *buf = src;
kogiidena94c0fa52006-09-27 14:53:35 +0900251
252 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900253 p = (volatile u16 *)port;
kogiidena94c0fa52006-09-27 14:53:35 +0900254 else if (CHECK_SH7751_PCIIO(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900255 p = (volatile u16 *)PCI_IOMAP(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900256 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900257 p = (volatile u16 *)port2adr(port);
258
259 while (count--)
260 *p = *buf++;
kogiidena94c0fa52006-09-27 14:53:35 +0900261}
262
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900263void landisk_outsl(unsigned long port, const void *src, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900264{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900265 const u32 *buf = src;
266
kogiidena94c0fa52006-09-27 14:53:35 +0900267 if (CHECK_SH7751_PCIIO(port)) {
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900268 volatile u32 *p = (volatile u32 *)PCI_IOMAP(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900269
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900270 while (count--)
271 *p = *buf++;
kogiidena94c0fa52006-09-27 14:53:35 +0900272 } else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900273 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900274}
275
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900276void __iomem *landisk_ioport_map(unsigned long port, unsigned int size)
kogiidena94c0fa52006-09-27 14:53:35 +0900277{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900278 if (PXSEG(port))
279 return (void __iomem *)port;
280 else if (CHECK_SH7751_PCIIO(port))
281 return (void __iomem *)PCI_IOMAP(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900282
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900283 return (void __iomem *)port2adr(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900284}