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