File: /usr/src/linux/arch/sh/kernel/io_cat68701.c

1     /* 
2      * linux/arch/sh/kernel/io_cat68701.c
3      *
4      * Copyright (C) 2000  Niibe Yutaka
5      *               2001  Yutaro Ebihara
6      *
7      * I/O routine and setup routines for A-ONE Corp CAT-68701 SH7708 Board
8      *
9      * This file is subject to the terms and conditions of the GNU General Public
10      * License.  See the file "COPYING" in the main directory of this archive
11      * for more details.
12      *
13      */
14     
15     #include <asm/io.h>
16     #include <asm/machvec.h>
17     #include <linux/config.h>
18     #include <linux/module.h>
19     
20     #define SH3_PCMCIA_BUG_WORKAROUND 1
21     #define DUMMY_READ_AREA6	  0xba000000
22     
23     #define PORT2ADDR(x) (cat68701_isa_port2addr(x))
24     
25     static inline void delay(void)
26     {
27     	ctrl_inw(0xa0000000);
28     }
29     
30     unsigned char cat68701_inb(unsigned long port)
31     {
32     	return *(volatile unsigned char*)PORT2ADDR(port);
33     }
34     
35     unsigned short cat68701_inw(unsigned long port)
36     {
37     	return *(volatile unsigned short*)PORT2ADDR(port);
38     }
39     
40     unsigned int cat68701_inl(unsigned long port)
41     {
42     	return *(volatile unsigned long*)PORT2ADDR(port);
43     }
44     
45     unsigned char cat68701_inb_p(unsigned long port)
46     {
47     	unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
48     
49     	delay();
50     	return v;
51     }
52     
53     unsigned short cat68701_inw_p(unsigned long port)
54     {
55     	unsigned long v = *(volatile unsigned short*)PORT2ADDR(port);
56     
57     	delay();
58     	return v;
59     }
60     
61     unsigned int cat68701_inl_p(unsigned long port)
62     {
63     	unsigned long v = *(volatile unsigned long*)PORT2ADDR(port);
64     
65     	delay();
66     	return v;
67     }
68     
69     void cat68701_insb(unsigned long port, void *buffer, unsigned long count)
70     {
71     	unsigned char *buf=buffer;
72     	while(count--) *buf++=inb(port);
73     }
74     
75     void cat68701_insw(unsigned long port, void *buffer, unsigned long count)
76     {
77     	unsigned short *buf=buffer;
78     	while(count--) *buf++=inw(port);
79     #ifdef SH3_PCMCIA_BUG_WORKAROUND
80     	ctrl_inb (DUMMY_READ_AREA6);
81     #endif
82     }
83     
84     void cat68701_insl(unsigned long port, void *buffer, unsigned long count)
85     {
86     	unsigned long *buf=buffer;
87     	while(count--) *buf++=inl(port);
88     #ifdef SH3_PCMCIA_BUG_WORKAROUND
89     	ctrl_inb (DUMMY_READ_AREA6);
90     #endif
91     }
92     
93     void cat68701_outb(unsigned char b, unsigned long port)
94     {
95     	*(volatile unsigned char*)PORT2ADDR(port) = b;
96     }
97     
98     void cat68701_outw(unsigned short b, unsigned long port)
99     {
100     	*(volatile unsigned short*)PORT2ADDR(port) = b;
101     }
102     
103     void cat68701_outl(unsigned int b, unsigned long port)
104     {
105             *(volatile unsigned long*)PORT2ADDR(port) = b;
106     }
107     
108     void cat68701_outb_p(unsigned char b, unsigned long port)
109     {
110     	*(volatile unsigned char*)PORT2ADDR(port) = b;
111     	delay();
112     }
113     
114     void cat68701_outw_p(unsigned short b, unsigned long port)
115     {
116     	*(volatile unsigned short*)PORT2ADDR(port) = b;
117     	delay();
118     }
119     
120     void cat68701_outl_p(unsigned int b, unsigned long port)
121     {
122     	*(volatile unsigned long*)PORT2ADDR(port) = b;
123     	delay();
124     }
125     
126     void cat68701_outsb(unsigned long port, const void *buffer, unsigned long count)
127     {
128     	const unsigned char *buf=buffer;
129     	while(count--) outb(*buf++, port);
130     }
131     
132     void cat68701_outsw(unsigned long port, const void *buffer, unsigned long count)
133     {
134     	const unsigned short *buf=buffer;
135     	while(count--) outw(*buf++, port);
136     #ifdef SH3_PCMCIA_BUG_WORKAROUND
137     	ctrl_inb (DUMMY_READ_AREA6);
138     #endif
139     }
140     
141     void cat68701_outsl(unsigned long port, const void *buffer, unsigned long count)
142     {
143     	const unsigned long *buf=buffer;
144     	while(count--) outl(*buf++, port);
145     #ifdef SH3_PCMCIA_BUG_WORKAROUND
146     	ctrl_inb (DUMMY_READ_AREA6);
147     #endif
148     }
149     
150     unsigned char cat68701_readb(unsigned long addr)
151     {
152     	return *(volatile unsigned char*)addr;
153     }
154     
155     unsigned short cat68701_readw(unsigned long addr)
156     {
157     	return *(volatile unsigned short*)addr;
158     }
159     
160     unsigned int cat68701_readl(unsigned long addr)
161     {
162     	return *(volatile unsigned long*)addr;
163     }
164     
165     void cat68701_writeb(unsigned char b, unsigned long addr)
166     {
167     	*(volatile unsigned char*)addr = b;
168     }
169     
170     void cat68701_writew(unsigned short b, unsigned long addr)
171     {
172     	*(volatile unsigned short*)addr = b;
173     }
174     
175     void cat68701_writel(unsigned int b, unsigned long addr)
176     {
177             *(volatile unsigned long*)addr = b;
178     }
179     
180     void * cat68701_ioremap(unsigned long offset, unsigned long size)
181     {
182     	return (void *) P2SEGADDR(offset);
183     }
184     EXPORT_SYMBOL(cat68701_ioremap);
185     
186     void cat68701_iounmap(void *addr)
187     {
188     }
189     EXPORT_SYMBOL(cat68701_iounmap);
190     
191     unsigned long cat68701_isa_port2addr(unsigned long offset)
192     {
193       /* CompactFlash (IDE) */
194       if(((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6))
195         return 0xba000000 + offset;
196     
197       /* INPUT PORT */
198       if((offset >= 0x3fc) && (offset <= 0x3fd))
199         return 0xb4007000 + offset;
200     
201       /* OUTPUT PORT */
202       if((offset >= 0x3fe) && (offset <= 0x3ff))
203         return 0xb4007400 + offset;
204     
205       return offset + 0xb4000000; /* other I/O (EREA 5)*/
206     }
207     
208     
209     int cat68701_irq_demux(int irq)
210     {
211       if(irq==13) return 14;
212       if(irq==7)  return 10;
213       return irq;
214     }
215     
216     
217     
218     /*-------------------------------------------------------*/
219     
220     void setup_cat68701(){
221       /* dummy read erea5 (CS8900A) */
222     }
223     
224     void init_cat68701_IRQ(){
225       make_imask_irq(10);
226       make_imask_irq(14);
227     }
228     
229     #ifdef CONFIG_HEARTBEAT
230     #include <linux/sched.h>
231     void heartbeat_cat68701()
232     {
233             static unsigned int cnt = 0, period = 0 , bit = 0;
234             cnt += 1;
235             if (cnt < period) {
236                     return;
237             }
238             cnt = 0;
239     
240             /* Go through the points (roughly!):
241              * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
242              */
243             period = 110 - ( (300<<FSHIFT)/
244                              ((avenrun[0]/5) + (3<<FSHIFT)) );
245     
246     	if(bit){ bit=0; }else{ bit=1; }
247     	outw(bit<<15,0x3fe);
248     }
249     #endif /* CONFIG_HEARTBEAT */
250