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