blob: 92498b4947d542725c557e2450075acf69359542 [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 */
kogiidena94c0fa52006-09-27 14:53:35 +090017#include <linux/kernel.h>
18#include <linux/types.h>
Paul Mundt959f85f2006-09-27 16:43:28 +090019#include <linux/pci.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
kogiidena94c0fa52006-09-27 14:53:35 +090024extern void *area5_io_base; /* Area 5 I/O Base address */
25extern void *area6_io_base; /* Area 6 I/O Base address */
26
kogiidena94c0fa52006-09-27 14:53:35 +090027static inline unsigned long port2adr(unsigned int port)
28{
29 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
30 if (port == 0x3f6)
31 return ((unsigned long)area5_io_base + 0x2c);
32 else
33 return ((unsigned long)area5_io_base + PA_PIDE_OFFSET +
34 ((port - 0x1f0) << 1));
35 else if ((0x170 <= port && port < 0x178) || port == 0x376)
36 if (port == 0x376)
37 return ((unsigned long)area6_io_base + 0x2c);
38 else
39 return ((unsigned long)area6_io_base + PA_SIDE_OFFSET +
40 ((port - 0x170) << 1));
41 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090042 maybebadio((unsigned long)port);
kogiidena94c0fa52006-09-27 14:53:35 +090043
44 return port;
45}
46
kogiidena94c0fa52006-09-27 14:53:35 +090047/*
48 * General outline: remap really low stuff [eventually] to SuperIO,
49 * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
50 * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
51 * should be way beyond the window, and is used w/o translation for
52 * compatibility.
53 */
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090054u8 landisk_inb(unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +090055{
56 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090057 return ctrl_inb(port);
Paul Mundt959f85f2006-09-27 16:43:28 +090058 else if (is_pci_ioaddr(port))
59 return ctrl_inb(pci_ioaddr(port));
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090060
61 return ctrl_inw(port2adr(port)) & 0xff;
kogiidena94c0fa52006-09-27 14:53:35 +090062}
63
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090064u8 landisk_inb_p(unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +090065{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090066 u8 v;
kogiidena94c0fa52006-09-27 14:53:35 +090067
68 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090069 v = ctrl_inb(port);
Paul Mundt959f85f2006-09-27 16:43:28 +090070 else if (is_pci_ioaddr(port))
71 v = ctrl_inb(pci_ioaddr(port));
kogiidena94c0fa52006-09-27 14:53:35 +090072 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090073 v = ctrl_inw(port2adr(port)) & 0xff;
74
Paul Mundt959f85f2006-09-27 16:43:28 +090075 ctrl_delay();
kogiidena94c0fa52006-09-27 14:53:35 +090076
77 return v;
78}
79
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090080u16 landisk_inw(unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +090081{
82 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090083 return ctrl_inw(port);
Paul Mundt959f85f2006-09-27 16:43:28 +090084 else if (is_pci_ioaddr(port))
85 return ctrl_inw(pci_ioaddr(port));
kogiidena94c0fa52006-09-27 14:53:35 +090086 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090087 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +090088
89 return 0;
90}
91
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090092u32 landisk_inl(unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +090093{
94 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090095 return ctrl_inl(port);
Paul Mundt959f85f2006-09-27 16:43:28 +090096 else if (is_pci_ioaddr(port))
97 return ctrl_inl(pci_ioaddr(port));
kogiidena94c0fa52006-09-27 14:53:35 +090098 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +090099 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900100
101 return 0;
102}
103
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900104void landisk_outb(u8 value, unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +0900105{
kogiidena94c0fa52006-09-27 14:53:35 +0900106 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900107 ctrl_outb(value, port);
Paul Mundt959f85f2006-09-27 16:43:28 +0900108 else if (is_pci_ioaddr(port))
109 ctrl_outb(value, pci_ioaddr(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900110 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900111 ctrl_outw(value, port2adr(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900112}
113
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900114void landisk_outb_p(u8 value, unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +0900115{
116 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900117 ctrl_outb(value, port);
Paul Mundt959f85f2006-09-27 16:43:28 +0900118 else if (is_pci_ioaddr(port))
119 ctrl_outb(value, pci_ioaddr(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900120 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900121 ctrl_outw(value, port2adr(port));
Paul Mundt959f85f2006-09-27 16:43:28 +0900122 ctrl_delay();
kogiidena94c0fa52006-09-27 14:53:35 +0900123}
124
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900125void landisk_outw(u16 value, unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +0900126{
127 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900128 ctrl_outw(value, port);
Paul Mundt959f85f2006-09-27 16:43:28 +0900129 else if (is_pci_ioaddr(port))
130 ctrl_outw(value, pci_ioaddr(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900131 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900132 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900133}
134
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900135void landisk_outl(u32 value, unsigned long port)
kogiidena94c0fa52006-09-27 14:53:35 +0900136{
137 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900138 ctrl_outl(value, port);
Paul Mundt959f85f2006-09-27 16:43:28 +0900139 else if (is_pci_ioaddr(port))
140 ctrl_outl(value, pci_ioaddr(port));
kogiidena94c0fa52006-09-27 14:53:35 +0900141 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900142 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900143}
144
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900145void landisk_insb(unsigned long port, void *dst, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900146{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900147 volatile u16 *p;
148 u8 *buf = dst;
kogiidena94c0fa52006-09-27 14:53:35 +0900149
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900150 if (PXSEG(port)) {
151 while (count--)
152 *buf++ = *(volatile u8 *)port;
Paul Mundt959f85f2006-09-27 16:43:28 +0900153 } else if (is_pci_ioaddr(port)) {
154 volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900155
156 while (count--)
157 *buf++ = *bp;
kogiidena94c0fa52006-09-27 14:53:35 +0900158 } else {
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900159 p = (volatile u16 *)port2adr(port);
160 while (count--)
161 *buf++ = *p & 0xff;
kogiidena94c0fa52006-09-27 14:53:35 +0900162 }
163}
164
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900165void landisk_insw(unsigned long port, void *dst, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900166{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900167 volatile u16 *p;
168 u16 *buf = dst;
kogiidena94c0fa52006-09-27 14:53:35 +0900169
170 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900171 p = (volatile u16 *)port;
Paul Mundt959f85f2006-09-27 16:43:28 +0900172 else if (is_pci_ioaddr(port))
173 p = (volatile u16 *)pci_ioaddr(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900174 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900175 p = (volatile u16 *)port2adr(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900176 while (count--)
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900177 *buf++ = *p;
kogiidena94c0fa52006-09-27 14:53:35 +0900178}
179
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900180void landisk_insl(unsigned long port, void *dst, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900181{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900182 u32 *buf = dst;
183
Paul Mundt959f85f2006-09-27 16:43:28 +0900184 if (is_pci_ioaddr(port)) {
185 volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900186
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900187 while (count--)
188 *buf++ = *p;
kogiidena94c0fa52006-09-27 14:53:35 +0900189 } else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900190 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900191}
192
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900193void landisk_outsb(unsigned long port, const void *src, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900194{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900195 volatile u16 *p;
196 const u8 *buf = src;
197
kogiidena94c0fa52006-09-27 14:53:35 +0900198 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900199 while (count--)
200 ctrl_outb(*buf++, port);
Paul Mundt959f85f2006-09-27 16:43:28 +0900201 else if (is_pci_ioaddr(port)) {
202 volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900203
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900204 while (count--)
205 *bp = *buf++;
kogiidena94c0fa52006-09-27 14:53:35 +0900206 } else {
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900207 p = (volatile u16 *)port2adr(port);
208 while (count--)
209 *p = *buf++;
kogiidena94c0fa52006-09-27 14:53:35 +0900210 }
211}
212
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900213void landisk_outsw(unsigned long port, const void *src, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900214{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900215 volatile u16 *p;
216 const u16 *buf = src;
kogiidena94c0fa52006-09-27 14:53:35 +0900217
218 if (PXSEG(port))
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900219 p = (volatile u16 *)port;
Paul Mundt959f85f2006-09-27 16:43:28 +0900220 else if (is_pci_ioaddr(port))
221 p = (volatile u16 *)pci_ioaddr(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900222 else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900223 p = (volatile u16 *)port2adr(port);
224
225 while (count--)
226 *p = *buf++;
kogiidena94c0fa52006-09-27 14:53:35 +0900227}
228
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900229void landisk_outsl(unsigned long port, const void *src, unsigned long count)
kogiidena94c0fa52006-09-27 14:53:35 +0900230{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900231 const u32 *buf = src;
232
Paul Mundt959f85f2006-09-27 16:43:28 +0900233 if (is_pci_ioaddr(port)) {
234 volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900235
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900236 while (count--)
237 *p = *buf++;
kogiidena94c0fa52006-09-27 14:53:35 +0900238 } else
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900239 maybebadio(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900240}
241
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900242void __iomem *landisk_ioport_map(unsigned long port, unsigned int size)
kogiidena94c0fa52006-09-27 14:53:35 +0900243{
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900244 if (PXSEG(port))
245 return (void __iomem *)port;
Paul Mundt959f85f2006-09-27 16:43:28 +0900246 else if (is_pci_ioaddr(port))
247 return (void __iomem *)pci_ioaddr(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900248
Paul Mundtd7cdc9e2006-09-27 15:16:42 +0900249 return (void __iomem *)port2adr(port);
kogiidena94c0fa52006-09-27 14:53:35 +0900250}