blob: 0befd4f9894c0e55f52b23126230bc421191a121 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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>
Paul Mundt373e68b2006-09-27 15:41:24 +090013#include <linux/pci.h>
14#include <asm/systemh7751.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <asm/addrspace.h>
16#include <asm/io.h>
Paul Mundt35305702006-09-27 13:28:23 +090017#include "../../../drivers/pci/pci-sh7751.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
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*/
Linus Torvalds1da177e2005-04-16 15:20:36 -070033static inline void delay(void)
34{
35 ctrl_inw(0xa0000000);
36}
37
38static inline volatile __u16 *
39port2adr(unsigned int port)
40{
41 if (port >= 0x2000)
42 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
Paul Mundt373e68b2006-09-27 15:41:24 +090043 maybebadio((unsigned long)port);
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 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 */
65unsigned 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
77unsigned 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
93unsigned 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
Paul Mundt373e68b2006-09-27 15:41:24 +0900104 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 return 0;
106}
107
108unsigned 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
Paul Mundt373e68b2006-09-27 15:41:24 +0900119 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 return 0;
121}
122
123void 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
136void 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
149void 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
Paul Mundt373e68b2006-09-27 15:41:24 +0900160 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161}
162
163void 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
Paul Mundt373e68b2006-09-27 15:41:24 +0900170 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171}
172
173void 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
179void 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
185void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count)
186{
Paul Mundt373e68b2006-09-27 15:41:24 +0900187 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188}
189
190void 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
196void 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
202void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count)
203{
Paul Mundt373e68b2006-09-27 15:41:24 +0900204 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205}