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
25static inline void delay(void)
26{
27	ctrl_inw(0xa0000000);
28}
29
30unsigned char cat68701_inb(unsigned long port)
31{
32	return *(volatile unsigned char*)PORT2ADDR(port);
33}
34
35unsigned short cat68701_inw(unsigned long port)
36{
37	return *(volatile unsigned short*)PORT2ADDR(port);
38}
39
40unsigned int cat68701_inl(unsigned long port)
41{
42	return *(volatile unsigned long*)PORT2ADDR(port);
43}
44
45unsigned 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
53unsigned 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
61unsigned 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
69void cat68701_insb(unsigned long port, void *buffer, unsigned long count)
70{
71	unsigned char *buf=buffer;
72	while(count--) *buf++=inb(port);
73}
74
75void 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
84void 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
93void cat68701_outb(unsigned char b, unsigned long port)
94{
95	*(volatile unsigned char*)PORT2ADDR(port) = b;
96}
97
98void cat68701_outw(unsigned short b, unsigned long port)
99{
100	*(volatile unsigned short*)PORT2ADDR(port) = b;
101}
102
103void cat68701_outl(unsigned int b, unsigned long port)
104{
105        *(volatile unsigned long*)PORT2ADDR(port) = b;
106}
107
108void cat68701_outb_p(unsigned char b, unsigned long port)
109{
110	*(volatile unsigned char*)PORT2ADDR(port) = b;
111	delay();
112}
113
114void cat68701_outw_p(unsigned short b, unsigned long port)
115{
116	*(volatile unsigned short*)PORT2ADDR(port) = b;
117	delay();
118}
119
120void cat68701_outl_p(unsigned int b, unsigned long port)
121{
122	*(volatile unsigned long*)PORT2ADDR(port) = b;
123	delay();
124}
125
126void 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
132void 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
141void 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
150unsigned char cat68701_readb(unsigned long addr)
151{
152	return *(volatile unsigned char*)addr;
153}
154
155unsigned short cat68701_readw(unsigned long addr)
156{
157	return *(volatile unsigned short*)addr;
158}
159
160unsigned int cat68701_readl(unsigned long addr)
161{
162	return *(volatile unsigned long*)addr;
163}
164
165void cat68701_writeb(unsigned char b, unsigned long addr)
166{
167	*(volatile unsigned char*)addr = b;
168}
169
170void cat68701_writew(unsigned short b, unsigned long addr)
171{
172	*(volatile unsigned short*)addr = b;
173}
174
175void cat68701_writel(unsigned int b, unsigned long addr)
176{
177        *(volatile unsigned long*)addr = b;
178}
179
180void * cat68701_ioremap(unsigned long offset, unsigned long size)
181{
182	return (void *) P2SEGADDR(offset);
183}
184EXPORT_SYMBOL(cat68701_ioremap);
185
186void cat68701_iounmap(void *addr)
187{
188}
189EXPORT_SYMBOL(cat68701_iounmap);
190
191unsigned 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
209int 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
220void setup_cat68701(){
221  /* dummy read erea5 (CS8900A) */
222}
223
224void init_cat68701_IRQ(){
225  make_imask_irq(10);
226  make_imask_irq(14);
227}
228
229#ifdef CONFIG_HEARTBEAT
230#include <linux/sched.h>
231void 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