import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / isdn / hisax / telespci.c
1 /* $Id: telespci.c,v 1.1.1.1 2005/04/11 02:50:24 jack Exp $
2  *
3  * low level stuff for Teles PCI isdn cards
4  *
5  * Author       Ton van Rosmalen
6  *              Karsten Keil
7  * Copyright    by Ton van Rosmalen
8  *              by Karsten Keil      <keil@isdn4linux.de>
9  * 
10  * This software may be used and distributed according to the terms
11  * of the GNU General Public License, incorporated herein by reference.
12  *
13  */
14
15 #define __NO_VERSION__
16 #include <linux/init.h>
17 #include <linux/config.h>
18 #include "hisax.h"
19 #include "isac.h"
20 #include "hscx.h"
21 #include "isdnl1.h"
22 #include <linux/pci.h>
23
24 extern const char *CardType[];
25 const char *telespci_revision = "$Revision: 1.1.1.1 $";
26
27 #define ZORAN_PO_RQ_PEN 0x02000000
28 #define ZORAN_PO_WR     0x00800000
29 #define ZORAN_PO_GID0   0x00000000
30 #define ZORAN_PO_GID1   0x00100000
31 #define ZORAN_PO_GREG0  0x00000000
32 #define ZORAN_PO_GREG1  0x00010000
33 #define ZORAN_PO_DMASK  0xFF
34
35 #define WRITE_ADDR_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0)
36 #define READ_DATA_ISAC  (ZORAN_PO_GID0 | ZORAN_PO_GREG1)
37 #define WRITE_DATA_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1)
38 #define WRITE_ADDR_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG0)
39 #define READ_DATA_HSCX  (ZORAN_PO_GID1 | ZORAN_PO_GREG1)
40 #define WRITE_DATA_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1)
41
42 #define ZORAN_WAIT_NOBUSY       do { \
43                                         portdata = readl(adr + 0x200); \
44                                 } while (portdata & ZORAN_PO_RQ_PEN)
45
46 static inline u_char
47 readisac(unsigned long adr, u_char off)
48 {
49         register unsigned int portdata;
50
51         ZORAN_WAIT_NOBUSY;
52         
53         /* set address for ISAC */
54         writel(WRITE_ADDR_ISAC | off, adr + 0x200);
55         ZORAN_WAIT_NOBUSY;
56         
57         /* read data from ISAC */
58         writel(READ_DATA_ISAC, adr + 0x200);
59         ZORAN_WAIT_NOBUSY;
60         return((u_char)(portdata & ZORAN_PO_DMASK));
61 }
62
63 static inline void
64 writeisac(unsigned long adr, u_char off, u_char data)
65 {
66         register unsigned int portdata;
67
68         ZORAN_WAIT_NOBUSY;
69         
70         /* set address for ISAC */
71         writel(WRITE_ADDR_ISAC | off, adr + 0x200);
72         ZORAN_WAIT_NOBUSY;
73
74         /* write data to ISAC */
75         writel(WRITE_DATA_ISAC | data, adr + 0x200);
76         ZORAN_WAIT_NOBUSY;
77 }
78
79 static inline u_char
80 readhscx(unsigned long adr, int hscx, u_char off)
81 {
82         register unsigned int portdata;
83
84         ZORAN_WAIT_NOBUSY;
85         /* set address for HSCX */
86         writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
87         ZORAN_WAIT_NOBUSY;
88         
89         /* read data from HSCX */
90         writel(READ_DATA_HSCX, adr + 0x200);
91         ZORAN_WAIT_NOBUSY;
92         return ((u_char)(portdata & ZORAN_PO_DMASK));
93 }
94
95 static inline void
96 writehscx(unsigned long adr, int hscx, u_char off, u_char data)
97 {
98         register unsigned int portdata;
99
100         ZORAN_WAIT_NOBUSY;
101         /* set address for HSCX */
102         writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
103         ZORAN_WAIT_NOBUSY;
104
105         /* write data to HSCX */
106         writel(WRITE_DATA_HSCX | data, adr + 0x200);
107         ZORAN_WAIT_NOBUSY;
108 }
109
110 static inline void
111 read_fifo_isac(unsigned long adr, u_char * data, int size)
112 {
113         register unsigned int portdata;
114         register int i;
115
116         ZORAN_WAIT_NOBUSY;
117         /* read data from ISAC */
118         for (i = 0; i < size; i++) {
119                 /* set address for ISAC fifo */
120                 writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
121                 ZORAN_WAIT_NOBUSY;
122                 writel(READ_DATA_ISAC, adr + 0x200);
123                 ZORAN_WAIT_NOBUSY;
124                 data[i] = (u_char)(portdata & ZORAN_PO_DMASK);
125         }
126 }
127
128 static void
129 write_fifo_isac(unsigned long adr, u_char * data, int size)
130 {
131         register unsigned int portdata;
132         register int i;
133
134         ZORAN_WAIT_NOBUSY;
135         /* write data to ISAC */
136         for (i = 0; i < size; i++) {
137                 /* set address for ISAC fifo */
138                 writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
139                 ZORAN_WAIT_NOBUSY;
140                 writel(WRITE_DATA_ISAC | data[i], adr + 0x200);
141                 ZORAN_WAIT_NOBUSY;
142         }
143 }
144
145 static inline void
146 read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size)
147 {
148         register unsigned int portdata;
149         register int i;
150
151         ZORAN_WAIT_NOBUSY;
152         /* read data from HSCX */
153         for (i = 0; i < size; i++) {
154                 /* set address for HSCX fifo */
155                 writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
156                 ZORAN_WAIT_NOBUSY;
157                 writel(READ_DATA_HSCX, adr + 0x200);
158                 ZORAN_WAIT_NOBUSY;
159                 data[i] = (u_char) (portdata & ZORAN_PO_DMASK);
160         }
161 }
162
163 static inline void
164 write_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size)
165 {
166         unsigned int portdata;
167         register int i;
168
169         ZORAN_WAIT_NOBUSY;
170         /* write data to HSCX */
171         for (i = 0; i < size; i++) {
172                 /* set address for HSCX fifo */
173                 writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
174                 ZORAN_WAIT_NOBUSY;
175                 writel(WRITE_DATA_HSCX | data[i], adr + 0x200);
176                 ZORAN_WAIT_NOBUSY;
177                 udelay(10);
178         }
179 }
180
181 /* Interface functions */
182
183 static u_char
184 ReadISAC(struct IsdnCardState *cs, u_char offset)
185 {
186         return (readisac(cs->hw.teles0.membase, offset));
187 }
188
189 static void
190 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
191 {
192         writeisac(cs->hw.teles0.membase, offset, value);
193 }
194
195 static void
196 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
197 {
198         read_fifo_isac(cs->hw.teles0.membase, data, size);
199 }
200
201 static void
202 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
203 {
204         write_fifo_isac(cs->hw.teles0.membase, data, size);
205 }
206
207 static u_char
208 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
209 {
210         return (readhscx(cs->hw.teles0.membase, hscx, offset));
211 }
212
213 static void
214 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
215 {
216         writehscx(cs->hw.teles0.membase, hscx, offset, value);
217 }
218
219 /*
220  * fast interrupt HSCX stuff goes here
221  */
222
223 #define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
224 #define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
225 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
226 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
227
228 #include "hscx_irq.c"
229
230 static void
231 telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
232 {
233 #define MAXCOUNT 20
234         struct IsdnCardState *cs = dev_id;
235         u_char val;
236
237         if (!cs) {
238                 printk(KERN_WARNING "TelesPCI: Spurious interrupt!\n");
239                 return;
240         }
241         val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
242         if (val)
243                 hscx_int_main(cs, val);
244         val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
245         if (val)
246                 isac_interrupt(cs, val);
247         /* Clear interrupt register for Zoran PCI controller */
248         writel(0x70000000, cs->hw.teles0.membase + 0x3C);
249
250         writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
251         writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
252         writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
253         writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
254         writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
255         writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
256 }
257
258 void
259 release_io_telespci(struct IsdnCardState *cs)
260 {
261         iounmap((void *)cs->hw.teles0.membase);
262 }
263
264 static int
265 TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
266 {
267         switch (mt) {
268                 case CARD_RESET:
269                         return(0);
270                 case CARD_RELEASE:
271                         release_io_telespci(cs);
272                         return(0);
273                 case CARD_INIT:
274                         inithscxisac(cs, 3);
275                         return(0);
276                 case CARD_TEST:
277                         return(0);
278         }
279         return(0);
280 }
281
282 static struct pci_dev *dev_tel __initdata = NULL;
283
284 int __init
285 setup_telespci(struct IsdnCard *card)
286 {
287         struct IsdnCardState *cs = card->cs;
288         char tmp[64];
289
290 #ifdef __BIG_ENDIAN
291 #error "not running on big endian machines now"
292 #endif
293         strcpy(tmp, telespci_revision);
294         printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
295         if (cs->typ != ISDN_CTYPE_TELESPCI)
296                 return (0);
297 #if CONFIG_PCI
298         if (!pci_present()) {
299                 printk(KERN_ERR "TelesPCI: no PCI bus present\n");
300                 return(0);
301         }
302         if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
303                 if (pci_enable_device(dev_tel))
304                         return(0);
305                 cs->irq = dev_tel->irq;
306                 if (!cs->irq) {
307                         printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
308                         return(0);
309                 }
310                 cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start(dev_tel, 0),
311                         PAGE_SIZE);
312                 printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
313                         pci_resource_start(dev_tel, 0), dev_tel->irq);
314         } else {
315                 printk(KERN_WARNING "TelesPCI: No PCI card found\n");
316                 return(0);
317         }
318 #else
319         printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n");
320         printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n");
321         return (0);
322 #endif /* CONFIG_PCI */
323
324         /* Initialize Zoran PCI controller */
325         writel(0x00000000, cs->hw.teles0.membase + 0x28);
326         writel(0x01000000, cs->hw.teles0.membase + 0x28);
327         writel(0x01000000, cs->hw.teles0.membase + 0x28);
328         writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C);
329         writel(0x70000000, cs->hw.teles0.membase + 0x3C);
330         writel(0x61000000, cs->hw.teles0.membase + 0x40);
331         /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
332
333         printk(KERN_INFO
334                "HiSax: %s config irq:%d mem:%lx\n",
335                CardType[cs->typ], cs->irq,
336                cs->hw.teles0.membase);
337
338         cs->readisac = &ReadISAC;
339         cs->writeisac = &WriteISAC;
340         cs->readisacfifo = &ReadISACfifo;
341         cs->writeisacfifo = &WriteISACfifo;
342         cs->BC_Read_Reg = &ReadHSCX;
343         cs->BC_Write_Reg = &WriteHSCX;
344         cs->BC_Send_Data = &hscx_fill_fifo;
345         cs->cardmsg = &TelesPCI_card_msg;
346         cs->irq_func = &telespci_interrupt;
347         cs->irq_flags |= SA_SHIRQ;
348         ISACVersion(cs, "TelesPCI:");
349         if (HscxVersion(cs, "TelesPCI:")) {
350                 printk(KERN_WARNING
351                  "TelesPCI: wrong HSCX versions check IO/MEM addresses\n");
352                 release_io_telespci(cs);
353                 return (0);
354         }
355         return (1);
356 }