1 /* $Id: io_generic.c,v 1.12 2000/11/14 16:45:11 sugioka Exp $
2  *
3  * linux/arch/sh/kernel/io_generic.c
4  *
5  * Copyright (C) 2000  Niibe Yutaka
6  *
7  * Generic I/O routine. These can be used where a machine specific version
8  * is not required.
9  *
10  * This file is subject to the terms and conditions of the GNU General Public
11  * License.  See the file "COPYING" in the main directory of this archive
12  * for more details.
13  *
14  */
15 
16 #include <asm/io.h>
17 #include <asm/machvec.h>
18 #include <linux/module.h>
19 
20 #if defined(__sh3__)
21 /* I'm not sure SH7709 has this kind of bug */
22 #define SH3_PCMCIA_BUG_WORKAROUND 1
23 #define DUMMY_READ_AREA6	  0xba000000
24 #endif
25 
26 #define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
27 
28 unsigned long generic_io_base;
29 
delay(void)30 static inline void delay(void)
31 {
32 	ctrl_inw(0xa0000000);
33 }
34 
generic_inb(unsigned long port)35 unsigned char generic_inb(unsigned long port)
36 {
37 	return *(volatile unsigned char*)PORT2ADDR(port);
38 }
39 
generic_inw(unsigned long port)40 unsigned short generic_inw(unsigned long port)
41 {
42 	return *(volatile unsigned short*)PORT2ADDR(port);
43 }
44 
generic_inl(unsigned long port)45 unsigned int generic_inl(unsigned long port)
46 {
47 	return *(volatile unsigned long*)PORT2ADDR(port);
48 }
49 
generic_inb_p(unsigned long port)50 unsigned char generic_inb_p(unsigned long port)
51 {
52 	unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
53 
54 	delay();
55 	return v;
56 }
57 
generic_inw_p(unsigned long port)58 unsigned short generic_inw_p(unsigned long port)
59 {
60 	unsigned long v = *(volatile unsigned short*)PORT2ADDR(port);
61 
62 	delay();
63 	return v;
64 }
65 
generic_inl_p(unsigned long port)66 unsigned int generic_inl_p(unsigned long port)
67 {
68 	unsigned long v = *(volatile unsigned long*)PORT2ADDR(port);
69 
70 	delay();
71 	return v;
72 }
73 
generic_insb(unsigned long port,void * buffer,unsigned long count)74 void generic_insb(unsigned long port, void *buffer, unsigned long count)
75 {
76 	unsigned char *buf=buffer;
77 	while(count--) *buf++=inb(port);
78 }
79 
generic_insw(unsigned long port,void * buffer,unsigned long count)80 void generic_insw(unsigned long port, void *buffer, unsigned long count)
81 {
82 	unsigned short *buf=buffer;
83 	while(count--) *buf++=inw(port);
84 #ifdef SH3_PCMCIA_BUG_WORKAROUND
85 	ctrl_inb (DUMMY_READ_AREA6);
86 #endif
87 }
88 
generic_insl(unsigned long port,void * buffer,unsigned long count)89 void generic_insl(unsigned long port, void *buffer, unsigned long count)
90 {
91 	unsigned long *buf=buffer;
92 	while(count--) *buf++=inl(port);
93 #ifdef SH3_PCMCIA_BUG_WORKAROUND
94 	ctrl_inb (DUMMY_READ_AREA6);
95 #endif
96 }
97 
generic_outb(unsigned char b,unsigned long port)98 void generic_outb(unsigned char b, unsigned long port)
99 {
100 	*(volatile unsigned char*)PORT2ADDR(port) = b;
101 }
102 
generic_outw(unsigned short b,unsigned long port)103 void generic_outw(unsigned short b, unsigned long port)
104 {
105 	*(volatile unsigned short*)PORT2ADDR(port) = b;
106 }
107 
generic_outl(unsigned int b,unsigned long port)108 void generic_outl(unsigned int b, unsigned long port)
109 {
110         *(volatile unsigned long*)PORT2ADDR(port) = b;
111 }
112 
generic_outb_p(unsigned char b,unsigned long port)113 void generic_outb_p(unsigned char b, unsigned long port)
114 {
115 	*(volatile unsigned char*)PORT2ADDR(port) = b;
116 	delay();
117 }
118 
generic_outw_p(unsigned short b,unsigned long port)119 void generic_outw_p(unsigned short b, unsigned long port)
120 {
121 	*(volatile unsigned short*)PORT2ADDR(port) = b;
122 	delay();
123 }
124 
generic_outl_p(unsigned int b,unsigned long port)125 void generic_outl_p(unsigned int b, unsigned long port)
126 {
127 	*(volatile unsigned long*)PORT2ADDR(port) = b;
128 	delay();
129 }
130 
generic_outsb(unsigned long port,const void * buffer,unsigned long count)131 void generic_outsb(unsigned long port, const void *buffer, unsigned long count)
132 {
133 	const unsigned char *buf=buffer;
134 	while(count--) outb(*buf++, port);
135 }
136 
generic_outsw(unsigned long port,const void * buffer,unsigned long count)137 void generic_outsw(unsigned long port, const void *buffer, unsigned long count)
138 {
139 	const unsigned short *buf=buffer;
140 	while(count--) outw(*buf++, port);
141 #ifdef SH3_PCMCIA_BUG_WORKAROUND
142 	ctrl_inb (DUMMY_READ_AREA6);
143 #endif
144 }
145 
generic_outsl(unsigned long port,const void * buffer,unsigned long count)146 void generic_outsl(unsigned long port, const void *buffer, unsigned long count)
147 {
148 	const unsigned long *buf=buffer;
149 	while(count--) outl(*buf++, port);
150 #ifdef SH3_PCMCIA_BUG_WORKAROUND
151 	ctrl_inb (DUMMY_READ_AREA6);
152 #endif
153 }
154 
generic_readb(unsigned long addr)155 unsigned char generic_readb(unsigned long addr)
156 {
157 	return *(volatile unsigned char*)addr;
158 }
159 
generic_readw(unsigned long addr)160 unsigned short generic_readw(unsigned long addr)
161 {
162 	return *(volatile unsigned short*)addr;
163 }
164 
generic_readl(unsigned long addr)165 unsigned int generic_readl(unsigned long addr)
166 {
167 	return *(volatile unsigned long*)addr;
168 }
169 
generic_writeb(unsigned char b,unsigned long addr)170 void generic_writeb(unsigned char b, unsigned long addr)
171 {
172 	*(volatile unsigned char*)addr = b;
173 }
174 
generic_writew(unsigned short b,unsigned long addr)175 void generic_writew(unsigned short b, unsigned long addr)
176 {
177 	*(volatile unsigned short*)addr = b;
178 }
179 
generic_writel(unsigned int b,unsigned long addr)180 void generic_writel(unsigned int b, unsigned long addr)
181 {
182         *(volatile unsigned long*)addr = b;
183 }
184 
generic_ioremap(unsigned long offset,unsigned long size)185 void * generic_ioremap(unsigned long offset, unsigned long size)
186 {
187 	return (void *) P2SEGADDR(offset);
188 }
189 EXPORT_SYMBOL(generic_ioremap);
190 
generic_iounmap(void * addr)191 void generic_iounmap(void *addr)
192 {
193 }
194 EXPORT_SYMBOL(generic_iounmap);
195 
generic_isa_port2addr(unsigned long offset)196 unsigned long generic_isa_port2addr(unsigned long offset)
197 {
198 	return offset + generic_io_base;
199 }
200