1/* $Id: io.c,v 1.1.1.1 2007/08/03 18:52:15 Exp $
2 *
3 * linux/arch/sh/kernel/io_se.c
4 *
5 * Copyright (C) 2000  Kazumoto Kojima
6 *
7 * I/O routine for Hitachi SolutionEngine.
8 *
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <asm/io.h>
14#include <asm/se.h>
15
16/* SH pcmcia io window base, start and end.  */
17int sh_pcic_io_wbase = 0xb8400000;
18int sh_pcic_io_start;
19int sh_pcic_io_stop;
20int sh_pcic_io_type;
21int sh_pcic_io_dummy;
22
23/* MS7750 requires special versions of in*, out* routines, since
24   PC-like io ports are located at upper half byte of 16-bit word which
25   can be accessed only with 16-bit wide.  */
26
27static inline volatile __u16 *
28port2adr(unsigned int port)
29{
30	if (port & 0xff000000)
31		return ( volatile __u16 *) port;
32	if (port >= 0x2000)
33		return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
34	else if (port >= 0x1000)
35		return (volatile __u16 *) (PA_83902 + (port << 1));
36	else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
37		return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
38	else
39		return (volatile __u16 *) (PA_SUPERIO + (port << 1));
40}
41
42static inline int
43shifted_port(unsigned long port)
44{
45	/* For IDE registers, value is not shifted */
46	if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
47		return 0;
48	else
49		return 1;
50}
51
52unsigned char se_inb(unsigned long port)
53{
54	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
55		return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
56	else if (shifted_port(port))
57		return (*port2adr(port) >> 8);
58	else
59		return (*port2adr(port))&0xff;
60}
61
62unsigned char se_inb_p(unsigned long port)
63{
64	unsigned long v;
65
66	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
67		v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
68	else if (shifted_port(port))
69		v = (*port2adr(port) >> 8);
70	else
71		v = (*port2adr(port))&0xff;
72	ctrl_delay();
73	return v;
74}
75
76unsigned short se_inw(unsigned long port)
77{
78	if (port >= 0x2000 ||
79	    (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
80		return *port2adr(port);
81	else
82		maybebadio(port);
83	return 0;
84}
85
86unsigned int se_inl(unsigned long port)
87{
88	maybebadio(port);
89	return 0;
90}
91
92void se_outb(unsigned char value, unsigned long port)
93{
94	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
95		*(__u8 *)(sh_pcic_io_wbase + port) = value;
96	else if (shifted_port(port))
97		*(port2adr(port)) = value << 8;
98	else
99		*(port2adr(port)) = value;
100}
101
102void se_outb_p(unsigned char value, unsigned long port)
103{
104	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
105		*(__u8 *)(sh_pcic_io_wbase + port) = value;
106	else if (shifted_port(port))
107		*(port2adr(port)) = value << 8;
108	else
109		*(port2adr(port)) = value;
110	ctrl_delay();
111}
112
113void se_outw(unsigned short value, unsigned long port)
114{
115	if (port >= 0x2000 ||
116	    (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
117		*port2adr(port) = value;
118	else
119		maybebadio(port);
120}
121
122void se_outl(unsigned int value, unsigned long port)
123{
124	maybebadio(port);
125}
126
127void se_insb(unsigned long port, void *addr, unsigned long count)
128{
129	volatile __u16 *p = port2adr(port);
130	__u8 *ap = addr;
131
132	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
133		volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
134		while (count--)
135			*ap++ = *bp;
136	} else if (shifted_port(port)) {
137		while (count--)
138			*ap++ = *p >> 8;
139	} else {
140		while (count--)
141			*ap++ = *p;
142	}
143}
144
145void se_insw(unsigned long port, void *addr, unsigned long count)
146{
147	volatile __u16 *p = port2adr(port);
148	__u16 *ap = addr;
149	while (count--)
150		*ap++ = *p;
151}
152
153void se_insl(unsigned long port, void *addr, unsigned long count)
154{
155	maybebadio(port);
156}
157
158void se_outsb(unsigned long port, const void *addr, unsigned long count)
159{
160	volatile __u16 *p = port2adr(port);
161	const __u8 *ap = addr;
162
163	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
164		volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port);
165		while (count--)
166			*bp = *ap++;
167	} else if (shifted_port(port)) {
168		while (count--)
169			*p = *ap++ << 8;
170	} else {
171		while (count--)
172			*p = *ap++;
173	}
174}
175
176void se_outsw(unsigned long port, const void *addr, unsigned long count)
177{
178	volatile __u16 *p = port2adr(port);
179	const __u16 *ap = addr;
180	while (count--)
181		*p = *ap++;
182}
183
184void se_outsl(unsigned long port, const void *addr, unsigned long count)
185{
186	maybebadio(port);
187}
188