]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/isdn/hisax/telespci.c
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
[net-next-2.6.git] / drivers / isdn / hisax / telespci.c
CommitLineData
1da177e4
LT
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>
1da177e4
LT
16#include "hisax.h"
17#include "isac.h"
18#include "hscx.h"
19#include "isdnl1.h"
20#include <linux/pci.h>
21
22extern const char *CardType[];
672c3fd9 23static const char *telespci_revision = "$Revision: 2.23.2.3 $";
1da177e4
LT
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
44static inline u_char
45readisac(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
61static inline void
62writeisac(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
77static inline u_char
78readhscx(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
93static inline void
94writehscx(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
108static inline void
109read_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
126static void
127write_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
143static inline void
144read_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
161static inline void
162write_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
181static u_char
182ReadISAC(struct IsdnCardState *cs, u_char offset)
183{
184 return (readisac(cs->hw.teles0.membase, offset));
185}
186
187static void
188WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
189{
190 writeisac(cs->hw.teles0.membase, offset, value);
191}
192
193static void
194ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
195{
196 read_fifo_isac(cs->hw.teles0.membase, data, size);
197}
198
199static void
200WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
201{
202 write_fifo_isac(cs->hw.teles0.membase, data, size);
203}
204
205static u_char
206ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
207{
208 return (readhscx(cs->hw.teles0.membase, hscx, offset));
209}
210
211static void
212WriteHSCX(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
228static irqreturn_t
7d12e780 229telespci_interrupt(int intno, void *dev_id)
1da177e4
LT
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
672c3fd9 259static void
1da177e4
LT
260release_io_telespci(struct IsdnCardState *cs)
261{
262 iounmap(cs->hw.teles0.membase);
263}
264
265static int
266TelesPCI_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
67eb5db5 287static struct pci_dev *dev_tel __devinitdata = NULL;
1da177e4 288
67eb5db5 289int __devinit
1da177e4
LT
290setup_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);
e29419ff
GKH
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);
1da177e4
LT
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;
9ba02bec 350 cs->irq_flags |= IRQF_SHARED;
1da177e4
LT
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}