Merge branch 'bkl/procfs' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[linux-2.6-block.git] / drivers / isdn / hardware / mISDN / mISDNinfineon.c
CommitLineData
cae86d4a
KK
1/*
2 * mISDNinfineon.c
3 * Support for cards based on following Infineon ISDN chipsets
4 * - ISAC + HSCX
5 * - IPAC and IPAC-X
6 * - ISAC-SX + HSCX
7 *
8 * Supported cards:
9 * - Dialogic Diva 2.0
10 * - Dialogic Diva 2.0U
11 * - Dialogic Diva 2.01
12 * - Dialogic Diva 2.02
13 * - Sedlbauer Speedwin
14 * - HST Saphir3
15 * - Develo (former ELSA) Microlink PCI (Quickstep 1000)
16 * - Develo (former ELSA) Quickstep 3000
17 * - Berkom Scitel BRIX Quadro
18 * - Dr.Neuhaus (Sagem) Niccy
19 *
20 *
21 *
22 * Author Karsten Keil <keil@isdn4linux.de>
23 *
24 * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
25 *
26 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License version 2 as
28 * published by the Free Software Foundation.
29 *
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
34 *
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38 *
39 */
40
41#include <linux/module.h>
42#include <linux/pci.h>
43#include <linux/delay.h>
44#include <linux/mISDNhw.h>
5a0e3ad6 45#include <linux/slab.h>
cae86d4a
KK
46#include "ipac.h"
47
48#define INFINEON_REV "1.0"
49
50static int inf_cnt;
51static u32 debug;
52static u32 irqloops = 4;
53
54enum inf_types {
55 INF_NONE,
56 INF_DIVA20,
57 INF_DIVA20U,
58 INF_DIVA201,
59 INF_DIVA202,
60 INF_SPEEDWIN,
61 INF_SAPHIR3,
62 INF_QS1000,
63 INF_QS3000,
64 INF_NICCY,
65 INF_SCT_1,
66 INF_SCT_2,
67 INF_SCT_3,
68 INF_SCT_4,
69 INF_GAZEL_R685,
70 INF_GAZEL_R753
71};
72
73enum addr_mode {
74 AM_NONE = 0,
75 AM_IO,
76 AM_MEMIO,
77 AM_IND_IO,
78};
79
80struct inf_cinfo {
81 enum inf_types typ;
82 const char *full;
83 const char *name;
84 enum addr_mode cfg_mode;
85 enum addr_mode addr_mode;
86 u8 cfg_bar;
87 u8 addr_bar;
88 void *irqfunc;
89};
90
91struct _ioaddr {
92 enum addr_mode mode;
93 union {
94 void __iomem *p;
95 struct _ioport io;
96 } a;
97};
98
99struct _iohandle {
100 enum addr_mode mode;
101 resource_size_t size;
102 resource_size_t start;
103 void __iomem *p;
104};
105
106struct inf_hw {
107 struct list_head list;
108 struct pci_dev *pdev;
109 const struct inf_cinfo *ci;
110 char name[MISDN_MAX_IDLEN];
111 u32 irq;
112 u32 irqcnt;
113 struct _iohandle cfg;
114 struct _iohandle addr;
115 struct _ioaddr isac;
116 struct _ioaddr hscx;
117 spinlock_t lock; /* HW access lock */
118 struct ipac_hw ipac;
119 struct inf_hw *sc[3]; /* slave cards */
120};
121
122
123#define PCI_SUBVENDOR_HST_SAPHIR3 0x52
124#define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53
125#define PCI_SUB_ID_SEDLBAUER 0x01
126
127static struct pci_device_id infineon_ids[] __devinitdata = {
128 { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20,
129 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA20},
130 { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U,
131 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA20U},
132 { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201,
133 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA201},
134 { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA202,
135 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA202},
136 { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
137 PCI_SUBVENDOR_SEDLBAUER_PCI, PCI_SUB_ID_SEDLBAUER, 0, 0,
138 INF_SPEEDWIN},
139 { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
140 PCI_SUBVENDOR_HST_SAPHIR3, PCI_SUB_ID_SEDLBAUER, 0, 0, INF_SAPHIR3},
141 { PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK,
142 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_QS1000},
143 { PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000,
144 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_QS3000},
145 { PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY,
146 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_NICCY},
147 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
148 PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO, 0, 0,
149 INF_SCT_1},
150 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R685,
151 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R685},
152 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R753,
153 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R753},
154 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO,
155 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R753},
156 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_OLITEC,
157 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R753},
158 { }
159};
160MODULE_DEVICE_TABLE(pci, infineon_ids);
161
162/* PCI interface specific defines */
163/* Diva 2.0/2.0U */
164#define DIVA_HSCX_PORT 0x00
165#define DIVA_HSCX_ALE 0x04
166#define DIVA_ISAC_PORT 0x08
167#define DIVA_ISAC_ALE 0x0C
168#define DIVA_PCI_CTRL 0x10
169
170/* DIVA_PCI_CTRL bits */
171#define DIVA_IRQ_BIT 0x01
172#define DIVA_RESET_BIT 0x08
173#define DIVA_EEPROM_CLK 0x40
174#define DIVA_LED_A 0x10
175#define DIVA_LED_B 0x20
176#define DIVA_IRQ_CLR 0x80
177
178/* Diva 2.01/2.02 */
179/* Siemens PITA */
180#define PITA_ICR_REG 0x00
181#define PITA_INT0_STATUS 0x02
182
183#define PITA_MISC_REG 0x1c
184#define PITA_PARA_SOFTRESET 0x01000000
185#define PITA_SER_SOFTRESET 0x02000000
186#define PITA_PARA_MPX_MODE 0x04000000
187#define PITA_INT0_ENABLE 0x00020000
188
189/* TIGER 100 Registers */
190#define TIGER_RESET_ADDR 0x00
191#define TIGER_EXTERN_RESET 0x01
192#define TIGER_AUX_CTRL 0x02
193#define TIGER_AUX_DATA 0x03
194#define TIGER_AUX_IRQMASK 0x05
195#define TIGER_AUX_STATUS 0x07
196
197/* Tiger AUX BITs */
198#define TIGER_IOMASK 0xdd /* 1 and 5 are inputs */
199#define TIGER_IRQ_BIT 0x02
200
201#define TIGER_IPAC_ALE 0xC0
202#define TIGER_IPAC_PORT 0xC8
203
204/* ELSA (now Develo) PCI cards */
205#define ELSA_IRQ_ADDR 0x4c
206#define ELSA_IRQ_MASK 0x04
207#define QS1000_IRQ_OFF 0x01
208#define QS3000_IRQ_OFF 0x03
209#define QS1000_IRQ_ON 0x41
210#define QS3000_IRQ_ON 0x43
211
212/* Dr Neuhaus/Sagem Niccy */
213#define NICCY_ISAC_PORT 0x00
214#define NICCY_HSCX_PORT 0x01
215#define NICCY_ISAC_ALE 0x02
216#define NICCY_HSCX_ALE 0x03
217
218#define NICCY_IRQ_CTRL_REG 0x38
219#define NICCY_IRQ_ENABLE 0x001f00
220#define NICCY_IRQ_DISABLE 0xff0000
221#define NICCY_IRQ_BIT 0x800000
222
223
224/* Scitel PLX */
225#define SCT_PLX_IRQ_ADDR 0x4c
226#define SCT_PLX_RESET_ADDR 0x50
227#define SCT_PLX_IRQ_ENABLE 0x41
228#define SCT_PLX_RESET_BIT 0x04
229
230/* Gazel */
231#define GAZEL_IPAC_DATA_PORT 0x04
232/* Gazel PLX */
233#define GAZEL_CNTRL 0x50
234#define GAZEL_RESET 0x04
235#define GAZEL_RESET_9050 0x40000000
236#define GAZEL_INCSR 0x4C
237#define GAZEL_ISAC_EN 0x08
238#define GAZEL_INT_ISAC 0x20
239#define GAZEL_HSCX_EN 0x01
240#define GAZEL_INT_HSCX 0x04
241#define GAZEL_PCI_EN 0x40
242#define GAZEL_IPAC_EN 0x03
243
244
245static LIST_HEAD(Cards);
246static DEFINE_RWLOCK(card_lock); /* protect Cards */
247
248static void
249_set_debug(struct inf_hw *card)
250{
251 card->ipac.isac.dch.debug = debug;
252 card->ipac.hscx[0].bch.debug = debug;
253 card->ipac.hscx[1].bch.debug = debug;
254}
255
256static int
257set_debug(const char *val, struct kernel_param *kp)
258{
259 int ret;
260 struct inf_hw *card;
261
262 ret = param_set_uint(val, kp);
263 if (!ret) {
264 read_lock(&card_lock);
265 list_for_each_entry(card, &Cards, list)
266 _set_debug(card);
267 read_unlock(&card_lock);
268 }
269 return ret;
270}
271
272MODULE_AUTHOR("Karsten Keil");
273MODULE_LICENSE("GPL v2");
274MODULE_VERSION(INFINEON_REV);
275module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
276MODULE_PARM_DESC(debug, "infineon debug mask");
277module_param(irqloops, uint, S_IRUGO | S_IWUSR);
278MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)");
279
280/* Interface functions */
281
282IOFUNC_IO(ISAC, inf_hw, isac.a.io)
283IOFUNC_IO(IPAC, inf_hw, hscx.a.io)
284IOFUNC_IND(ISAC, inf_hw, isac.a.io)
285IOFUNC_IND(IPAC, inf_hw, hscx.a.io)
286IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p)
287IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p)
288
289static irqreturn_t
290diva_irq(int intno, void *dev_id)
291{
292 struct inf_hw *hw = dev_id;
293 u8 val;
294
295 spin_lock(&hw->lock);
296 val = inb((u32)hw->cfg.start + DIVA_PCI_CTRL);
297 if (!(val & DIVA_IRQ_BIT)) { /* for us or shared ? */
298 spin_unlock(&hw->lock);
299 return IRQ_NONE; /* shared */
300 }
301 hw->irqcnt++;
302 mISDNipac_irq(&hw->ipac, irqloops);
303 spin_unlock(&hw->lock);
304 return IRQ_HANDLED;
305}
306
307static irqreturn_t
308diva20x_irq(int intno, void *dev_id)
309{
310 struct inf_hw *hw = dev_id;
311 u8 val;
312
313 spin_lock(&hw->lock);
314 val = readb(hw->cfg.p);
315 if (!(val & PITA_INT0_STATUS)) { /* for us or shared ? */
316 spin_unlock(&hw->lock);
317 return IRQ_NONE; /* shared */
318 }
319 hw->irqcnt++;
320 mISDNipac_irq(&hw->ipac, irqloops);
321 writeb(PITA_INT0_STATUS, hw->cfg.p); /* ACK PITA INT0 */
322 spin_unlock(&hw->lock);
323 return IRQ_HANDLED;
324}
325
326static irqreturn_t
327tiger_irq(int intno, void *dev_id)
328{
329 struct inf_hw *hw = dev_id;
330 u8 val;
331
332 spin_lock(&hw->lock);
333 val = inb((u32)hw->cfg.start + TIGER_AUX_STATUS);
334 if (val & TIGER_IRQ_BIT) { /* for us or shared ? */
335 spin_unlock(&hw->lock);
336 return IRQ_NONE; /* shared */
337 }
338 hw->irqcnt++;
339 mISDNipac_irq(&hw->ipac, irqloops);
340 spin_unlock(&hw->lock);
341 return IRQ_HANDLED;
342}
343
344static irqreturn_t
345elsa_irq(int intno, void *dev_id)
346{
347 struct inf_hw *hw = dev_id;
348 u8 val;
349
350 spin_lock(&hw->lock);
351 val = inb((u32)hw->cfg.start + ELSA_IRQ_ADDR);
352 if (!(val & ELSA_IRQ_MASK)) {
353 spin_unlock(&hw->lock);
354 return IRQ_NONE; /* shared */
355 }
356 hw->irqcnt++;
357 mISDNipac_irq(&hw->ipac, irqloops);
358 spin_unlock(&hw->lock);
359 return IRQ_HANDLED;
360}
361
362static irqreturn_t
363niccy_irq(int intno, void *dev_id)
364{
365 struct inf_hw *hw = dev_id;
366 u32 val;
367
368 spin_lock(&hw->lock);
369 val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
370 if (!(val & NICCY_IRQ_BIT)) { /* for us or shared ? */
371 spin_unlock(&hw->lock);
372 return IRQ_NONE; /* shared */
373 }
374 outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
375 hw->irqcnt++;
376 mISDNipac_irq(&hw->ipac, irqloops);
377 spin_unlock(&hw->lock);
378 return IRQ_HANDLED;
379}
380
381static irqreturn_t
382gazel_irq(int intno, void *dev_id)
383{
384 struct inf_hw *hw = dev_id;
385 irqreturn_t ret;
386
387 spin_lock(&hw->lock);
388 ret = mISDNipac_irq(&hw->ipac, irqloops);
389 spin_unlock(&hw->lock);
390 return ret;
391}
392
393static irqreturn_t
394ipac_irq(int intno, void *dev_id)
395{
396 struct inf_hw *hw = dev_id;
397 u8 val;
398
399 spin_lock(&hw->lock);
400 val = hw->ipac.read_reg(hw, IPAC_ISTA);
401 if (!(val & 0x3f)) {
402 spin_unlock(&hw->lock);
403 return IRQ_NONE; /* shared */
404 }
405 hw->irqcnt++;
406 mISDNipac_irq(&hw->ipac, irqloops);
407 spin_unlock(&hw->lock);
408 return IRQ_HANDLED;
409}
410
411static void
412enable_hwirq(struct inf_hw *hw)
413{
414 u16 w;
415 u32 val;
416
417 switch (hw->ci->typ) {
418 case INF_DIVA201:
419 case INF_DIVA202:
420 writel(PITA_INT0_ENABLE, hw->cfg.p);
421 break;
422 case INF_SPEEDWIN:
423 case INF_SAPHIR3:
424 outb(TIGER_IRQ_BIT, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
425 break;
426 case INF_QS1000:
427 outb(QS1000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
428 break;
429 case INF_QS3000:
430 outb(QS3000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
431 break;
432 case INF_NICCY:
433 val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
434 val |= NICCY_IRQ_ENABLE;;
435 outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
436 break;
437 case INF_SCT_1:
438 w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
439 w |= SCT_PLX_IRQ_ENABLE;
440 outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
441 break;
442 case INF_GAZEL_R685:
443 outb(GAZEL_ISAC_EN + GAZEL_HSCX_EN + GAZEL_PCI_EN,
444 (u32)hw->cfg.start + GAZEL_INCSR);
445 break;
446 case INF_GAZEL_R753:
447 outb(GAZEL_IPAC_EN + GAZEL_PCI_EN,
448 (u32)hw->cfg.start + GAZEL_INCSR);
449 break;
450 default:
451 break;
452 }
453}
454
455static void
456disable_hwirq(struct inf_hw *hw)
457{
458 u16 w;
459 u32 val;
460
461 switch (hw->ci->typ) {
462 case INF_DIVA201:
463 case INF_DIVA202:
464 writel(0, hw->cfg.p);
465 break;
466 case INF_SPEEDWIN:
467 case INF_SAPHIR3:
468 outb(0, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
469 break;
470 case INF_QS1000:
471 outb(QS1000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
472 break;
473 case INF_QS3000:
474 outb(QS3000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
475 break;
476 case INF_NICCY:
477 val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
478 val &= NICCY_IRQ_DISABLE;
479 outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
480 break;
481 case INF_SCT_1:
482 w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
483 w &= (~SCT_PLX_IRQ_ENABLE);
484 outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
485 break;
486 case INF_GAZEL_R685:
487 case INF_GAZEL_R753:
488 outb(0, (u32)hw->cfg.start + GAZEL_INCSR);
489 break;
490 default:
491 break;
492 }
493}
494
495static void
496ipac_chip_reset(struct inf_hw *hw)
497{
498 hw->ipac.write_reg(hw, IPAC_POTA2, 0x20);
499 mdelay(5);
500 hw->ipac.write_reg(hw, IPAC_POTA2, 0x00);
501 mdelay(5);
502 hw->ipac.write_reg(hw, IPAC_CONF, hw->ipac.conf);
503 hw->ipac.write_reg(hw, IPAC_MASK, 0xc0);
504}
505
506static void
507reset_inf(struct inf_hw *hw)
508{
509 u16 w;
510 u32 val;
511
512 if (debug & DEBUG_HW)
513 pr_notice("%s: resetting card\n", hw->name);
514 switch (hw->ci->typ) {
515 case INF_DIVA20:
516 case INF_DIVA20U:
517 outb(0, (u32)hw->cfg.start + DIVA_PCI_CTRL);
518 mdelay(10);
519 outb(DIVA_RESET_BIT, (u32)hw->cfg.start + DIVA_PCI_CTRL);
520 mdelay(10);
521 /* Workaround PCI9060 */
522 outb(9, (u32)hw->cfg.start + 0x69);
523 outb(DIVA_RESET_BIT | DIVA_LED_A,
524 (u32)hw->cfg.start + DIVA_PCI_CTRL);
525 break;
526 case INF_DIVA201:
527 writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
528 hw->cfg.p + PITA_MISC_REG);
529 mdelay(1);
530 writel(PITA_PARA_MPX_MODE, hw->cfg.p + PITA_MISC_REG);
531 mdelay(10);
532 break;
533 case INF_DIVA202:
534 writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
535 hw->cfg.p + PITA_MISC_REG);
536 mdelay(1);
537 writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET,
538 hw->cfg.p + PITA_MISC_REG);
539 mdelay(10);
540 break;
541 case INF_SPEEDWIN:
542 case INF_SAPHIR3:
543 ipac_chip_reset(hw);
544 hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
545 hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
546 hw->ipac.write_reg(hw, IPAC_PCFG, 0x12);
547 break;
548 case INF_QS1000:
549 case INF_QS3000:
550 ipac_chip_reset(hw);
551 hw->ipac.write_reg(hw, IPAC_ACFG, 0x00);
552 hw->ipac.write_reg(hw, IPAC_AOE, 0x3c);
553 hw->ipac.write_reg(hw, IPAC_ATX, 0xff);
554 break;
555 case INF_NICCY:
556 break;
557 case INF_SCT_1:
558 w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
559 w &= (~SCT_PLX_RESET_BIT);
560 outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
561 mdelay(10);
562 w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
563 w |= SCT_PLX_RESET_BIT;
564 outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
565 mdelay(10);
566 break;
567 case INF_GAZEL_R685:
568 val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
569 val |= (GAZEL_RESET_9050 + GAZEL_RESET);
570 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
571 val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
572 mdelay(4);
573 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
574 mdelay(10);
575 hw->ipac.isac.adf2 = 0x87;
576 hw->ipac.hscx[0].slot = 0x1f;
577 hw->ipac.hscx[0].slot = 0x23;
578 break;
579 case INF_GAZEL_R753:
580 val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
581 val |= (GAZEL_RESET_9050 + GAZEL_RESET);
582 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
583 val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
584 mdelay(4);
585 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
586 mdelay(10);
587 ipac_chip_reset(hw);
588 hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
589 hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
590 hw->ipac.conf = 0x01; /* IOM off */
591 break;
592 default:
593 return;
594 }
595 enable_hwirq(hw);
596}
597
598static int
599inf_ctrl(struct inf_hw *hw, u32 cmd, u_long arg)
600{
601 int ret = 0;
602
603 switch (cmd) {
604 case HW_RESET_REQ:
605 reset_inf(hw);
606 break;
607 default:
608 pr_info("%s: %s unknown command %x %lx\n",
609 hw->name, __func__, cmd, arg);
610 ret = -EINVAL;
611 break;
612 }
613 return ret;
614}
615
616static int __devinit
617init_irq(struct inf_hw *hw)
618{
619 int ret, cnt = 3;
620 u_long flags;
621
622 if (!hw->ci->irqfunc)
623 return -EINVAL;
624 ret = request_irq(hw->irq, hw->ci->irqfunc, IRQF_SHARED, hw->name, hw);
625 if (ret) {
626 pr_info("%s: couldn't get interrupt %d\n", hw->name, hw->irq);
627 return ret;
628 }
629 while (cnt--) {
630 spin_lock_irqsave(&hw->lock, flags);
631 reset_inf(hw);
632 ret = hw->ipac.init(&hw->ipac);
633 if (ret) {
634 spin_unlock_irqrestore(&hw->lock, flags);
635 pr_info("%s: ISAC init failed with %d\n",
636 hw->name, ret);
637 break;
638 }
639 spin_unlock_irqrestore(&hw->lock, flags);
640 msleep_interruptible(10);
641 if (debug & DEBUG_HW)
642 pr_notice("%s: IRQ %d count %d\n", hw->name,
643 hw->irq, hw->irqcnt);
644 if (!hw->irqcnt) {
645 pr_info("%s: IRQ(%d) got no requests during init %d\n",
646 hw->name, hw->irq, 3 - cnt);
647 } else
648 return 0;
649 }
650 free_irq(hw->irq, hw);
651 return -EIO;
652}
653
654static void
655release_io(struct inf_hw *hw)
656{
657 if (hw->cfg.mode) {
658 if (hw->cfg.p) {
659 release_mem_region(hw->cfg.start, hw->cfg.size);
660 iounmap(hw->cfg.p);
661 } else
662 release_region(hw->cfg.start, hw->cfg.size);
663 hw->cfg.mode = AM_NONE;
664 }
665 if (hw->addr.mode) {
666 if (hw->addr.p) {
667 release_mem_region(hw->addr.start, hw->addr.size);
668 iounmap(hw->addr.p);
669 } else
670 release_region(hw->addr.start, hw->addr.size);
671 hw->addr.mode = AM_NONE;
672 }
673}
674
675static int __devinit
676setup_io(struct inf_hw *hw)
677{
678 int err = 0;
679
680 if (hw->ci->cfg_mode) {
681 hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar);
682 hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar);
683 if (hw->ci->cfg_mode == AM_MEMIO) {
684 if (!request_mem_region(hw->cfg.start, hw->cfg.size,
685 hw->name))
686 err = -EBUSY;
687 } else {
688 if (!request_region(hw->cfg.start, hw->cfg.size,
689 hw->name))
690 err = -EBUSY;
691 }
692 if (err) {
693 pr_info("mISDN: %s config port %lx (%lu bytes)"
694 "already in use\n", hw->name,
695 (ulong)hw->cfg.start, (ulong)hw->cfg.size);
696 return err;
697 }
698 if (hw->ci->cfg_mode == AM_MEMIO)
699 hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
700 hw->cfg.mode = hw->ci->cfg_mode;
701 if (debug & DEBUG_HW)
702 pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
703 hw->name, (ulong)hw->cfg.start,
704 (ulong)hw->cfg.size, hw->ci->cfg_mode);
705
706 }
707 if (hw->ci->addr_mode) {
708 hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar);
709 hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar);
710 if (hw->ci->addr_mode == AM_MEMIO) {
711 if (!request_mem_region(hw->addr.start, hw->addr.size,
712 hw->name))
713 err = -EBUSY;
714 } else {
715 if (!request_region(hw->addr.start, hw->addr.size,
716 hw->name))
717 err = -EBUSY;
718 }
719 if (err) {
720 pr_info("mISDN: %s address port %lx (%lu bytes)"
721 "already in use\n", hw->name,
722 (ulong)hw->addr.start, (ulong)hw->addr.size);
723 return err;
724 }
725 if (hw->ci->addr_mode == AM_MEMIO)
726 hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
727 hw->addr.mode = hw->ci->addr_mode;
728 if (debug & DEBUG_HW)
729 pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
730 hw->name, (ulong)hw->addr.start,
731 (ulong)hw->addr.size, hw->ci->addr_mode);
732
733 }
734
735 switch (hw->ci->typ) {
736 case INF_DIVA20:
737 case INF_DIVA20U:
738 hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
739 hw->isac.mode = hw->cfg.mode;
740 hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE;
741 hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT;
742 hw->hscx.mode = hw->cfg.mode;
743 hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE;
744 hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT;
745 break;
746 case INF_DIVA201:
747 hw->ipac.type = IPAC_TYPE_IPAC;
748 hw->ipac.isac.off = 0x80;
749 hw->isac.mode = hw->addr.mode;
750 hw->isac.a.p = hw->addr.p;
751 hw->hscx.mode = hw->addr.mode;
752 hw->hscx.a.p = hw->addr.p;
753 break;
754 case INF_DIVA202:
755 hw->ipac.type = IPAC_TYPE_IPACX;
756 hw->isac.mode = hw->addr.mode;
757 hw->isac.a.p = hw->addr.p;
758 hw->hscx.mode = hw->addr.mode;
759 hw->hscx.a.p = hw->addr.p;
760 break;
761 case INF_SPEEDWIN:
762 case INF_SAPHIR3:
763 hw->ipac.type = IPAC_TYPE_IPAC;
764 hw->ipac.isac.off = 0x80;
765 hw->isac.mode = hw->cfg.mode;
766 hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
767 hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
768 hw->hscx.mode = hw->cfg.mode;
769 hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
770 hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
771 outb(0xff, (ulong)hw->cfg.start);
772 mdelay(1);
773 outb(0x00, (ulong)hw->cfg.start);
774 mdelay(1);
775 outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL);
776 break;
777 case INF_QS1000:
778 case INF_QS3000:
779 hw->ipac.type = IPAC_TYPE_IPAC;
780 hw->ipac.isac.off = 0x80;
781 hw->isac.a.io.ale = (u32)hw->addr.start;
782 hw->isac.a.io.port = (u32)hw->addr.start + 1;
783 hw->isac.mode = hw->addr.mode;
784 hw->hscx.a.io.ale = (u32)hw->addr.start;
785 hw->hscx.a.io.port = (u32)hw->addr.start + 1;
786 hw->hscx.mode = hw->addr.mode;
787 break;
788 case INF_NICCY:
789 hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
790 hw->isac.mode = hw->addr.mode;
791 hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE;
792 hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT;
793 hw->hscx.mode = hw->addr.mode;
794 hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE;
795 hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT;
796 break;
797 case INF_SCT_1:
798 hw->ipac.type = IPAC_TYPE_IPAC;
799 hw->ipac.isac.off = 0x80;
800 hw->isac.a.io.ale = (u32)hw->addr.start;
801 hw->isac.a.io.port = hw->isac.a.io.ale + 4;
802 hw->isac.mode = hw->addr.mode;
803 hw->hscx.a.io.ale = hw->isac.a.io.ale;
804 hw->hscx.a.io.port = hw->isac.a.io.port;
805 hw->hscx.mode = hw->addr.mode;
806 break;
807 case INF_SCT_2:
808 hw->ipac.type = IPAC_TYPE_IPAC;
809 hw->ipac.isac.off = 0x80;
810 hw->isac.a.io.ale = (u32)hw->addr.start + 0x08;
811 hw->isac.a.io.port = hw->isac.a.io.ale + 4;
812 hw->isac.mode = hw->addr.mode;
813 hw->hscx.a.io.ale = hw->isac.a.io.ale;
814 hw->hscx.a.io.port = hw->isac.a.io.port;
815 hw->hscx.mode = hw->addr.mode;
816 break;
817 case INF_SCT_3:
818 hw->ipac.type = IPAC_TYPE_IPAC;
819 hw->ipac.isac.off = 0x80;
820 hw->isac.a.io.ale = (u32)hw->addr.start + 0x10;
821 hw->isac.a.io.port = hw->isac.a.io.ale + 4;
822 hw->isac.mode = hw->addr.mode;
823 hw->hscx.a.io.ale = hw->isac.a.io.ale;
824 hw->hscx.a.io.port = hw->isac.a.io.port;
825 hw->hscx.mode = hw->addr.mode;
826 break;
827 case INF_SCT_4:
828 hw->ipac.type = IPAC_TYPE_IPAC;
829 hw->ipac.isac.off = 0x80;
830 hw->isac.a.io.ale = (u32)hw->addr.start + 0x20;
831 hw->isac.a.io.port = hw->isac.a.io.ale + 4;
832 hw->isac.mode = hw->addr.mode;
833 hw->hscx.a.io.ale = hw->isac.a.io.ale;
834 hw->hscx.a.io.port = hw->isac.a.io.port;
835 hw->hscx.mode = hw->addr.mode;
836 break;
837 case INF_GAZEL_R685:
838 hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
839 hw->ipac.isac.off = 0x80;
840 hw->isac.mode = hw->addr.mode;
841 hw->isac.a.io.port = (u32)hw->addr.start;
842 hw->hscx.mode = hw->addr.mode;
843 hw->hscx.a.io.port = hw->isac.a.io.port;
844 break;
845 case INF_GAZEL_R753:
846 hw->ipac.type = IPAC_TYPE_IPAC;
847 hw->ipac.isac.off = 0x80;
848 hw->isac.mode = hw->addr.mode;
849 hw->isac.a.io.ale = (u32)hw->addr.start;
850 hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT;
851 hw->hscx.mode = hw->addr.mode;
852 hw->hscx.a.io.ale = hw->isac.a.io.ale;
853 hw->hscx.a.io.port = hw->isac.a.io.port;
854 break;
855 default:
856 return -EINVAL;
857 }
858 switch (hw->isac.mode) {
859 case AM_MEMIO:
860 ASSIGN_FUNC_IPAC(MIO, hw->ipac);
861 break;
862 case AM_IND_IO:
863 ASSIGN_FUNC_IPAC(IND, hw->ipac);
864 break;
865 case AM_IO:
866 ASSIGN_FUNC_IPAC(IO, hw->ipac);
867 break;
868 default:
869 return -EINVAL;
870 }
871 return 0;
872}
873
874static void
875release_card(struct inf_hw *card) {
876 ulong flags;
877 int i;
878
879 spin_lock_irqsave(&card->lock, flags);
880 disable_hwirq(card);
881 spin_unlock_irqrestore(&card->lock, flags);
882 card->ipac.isac.release(&card->ipac.isac);
883 free_irq(card->irq, card);
884 mISDN_unregister_device(&card->ipac.isac.dch.dev);
885 release_io(card);
886 write_lock_irqsave(&card_lock, flags);
887 list_del(&card->list);
888 write_unlock_irqrestore(&card_lock, flags);
889 switch (card->ci->typ) {
890 case INF_SCT_2:
891 case INF_SCT_3:
892 case INF_SCT_4:
893 break;
894 case INF_SCT_1:
895 for (i = 0; i < 3; i++) {
896 if (card->sc[i])
897 release_card(card->sc[i]);
898 card->sc[i] = NULL;
899 }
900 default:
901 pci_disable_device(card->pdev);
902 pci_set_drvdata(card->pdev, NULL);
903 break;
904 }
905 kfree(card);
906 inf_cnt--;
907}
908
909static int __devinit
910setup_instance(struct inf_hw *card)
911{
912 int err;
913 ulong flags;
914
915 snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name,
916 inf_cnt + 1);
917 write_lock_irqsave(&card_lock, flags);
918 list_add_tail(&card->list, &Cards);
919 write_unlock_irqrestore(&card_lock, flags);
920
921 _set_debug(card);
922 card->ipac.isac.name = card->name;
923 card->ipac.name = card->name;
924 card->ipac.owner = THIS_MODULE;
925 spin_lock_init(&card->lock);
926 card->ipac.isac.hwlock = &card->lock;
927 card->ipac.hwlock = &card->lock;
928 card->ipac.ctrl = (void *)&inf_ctrl;
929
930 err = setup_io(card);
931 if (err)
932 goto error_setup;
933
934 card->ipac.isac.dch.dev.Bprotocols =
935 mISDNipac_init(&card->ipac, card);
936
937 if (card->ipac.isac.dch.dev.Bprotocols == 0)
938 goto error_setup;;
939
940 err = mISDN_register_device(&card->ipac.isac.dch.dev,
941 &card->pdev->dev, card->name);
942 if (err)
943 goto error;
944
945 err = init_irq(card);
946 if (!err) {
947 inf_cnt++;
948 pr_notice("Infineon %d cards installed\n", inf_cnt);
949 return 0;
950 }
951 mISDN_unregister_device(&card->ipac.isac.dch.dev);
952error:
953 card->ipac.release(&card->ipac);
954error_setup:
955 release_io(card);
956 write_lock_irqsave(&card_lock, flags);
957 list_del(&card->list);
958 write_unlock_irqrestore(&card_lock, flags);
959 return err;
960}
961
962static const struct inf_cinfo inf_card_info[] = {
963 {
964 INF_DIVA20,
965 "Dialogic Diva 2.0",
966 "diva20",
967 AM_IND_IO, AM_NONE, 2, 0,
968 &diva_irq
969 },
970 {
971 INF_DIVA20U,
972 "Dialogic Diva 2.0U",
973 "diva20U",
974 AM_IND_IO, AM_NONE, 2, 0,
975 &diva_irq
976 },
977 {
978 INF_DIVA201,
979 "Dialogic Diva 2.01",
980 "diva201",
981 AM_MEMIO, AM_MEMIO, 0, 1,
982 &diva20x_irq
983 },
984 {
985 INF_DIVA202,
986 "Dialogic Diva 2.02",
987 "diva202",
988 AM_MEMIO, AM_MEMIO, 0, 1,
989 &diva20x_irq
990 },
991 {
992 INF_SPEEDWIN,
993 "Sedlbauer SpeedWin PCI",
994 "speedwin",
995 AM_IND_IO, AM_NONE, 0, 0,
996 &tiger_irq
997 },
998 {
999 INF_SAPHIR3,
1000 "HST Saphir 3",
1001 "saphir",
1002 AM_IND_IO, AM_NONE, 0, 0,
1003 &tiger_irq
1004 },
1005 {
1006 INF_QS1000,
1007 "Develo Microlink PCI",
1008 "qs1000",
1009 AM_IO, AM_IND_IO, 1, 3,
1010 &elsa_irq
1011 },
1012 {
1013 INF_QS3000,
1014 "Develo QuickStep 3000",
1015 "qs3000",
1016 AM_IO, AM_IND_IO, 1, 3,
1017 &elsa_irq
1018 },
1019 {
1020 INF_NICCY,
1021 "Sagem NICCY",
1022 "niccy",
1023 AM_IO, AM_IND_IO, 0, 1,
1024 &niccy_irq
1025 },
1026 {
1027 INF_SCT_1,
1028 "SciTel Quadro",
1029 "p1_scitel",
1030 AM_IO, AM_IND_IO, 1, 5,
1031 &ipac_irq
1032 },
1033 {
1034 INF_SCT_2,
1035 "SciTel Quadro",
1036 "p2_scitel",
1037 AM_NONE, AM_IND_IO, 0, 4,
1038 &ipac_irq
1039 },
1040 {
1041 INF_SCT_3,
1042 "SciTel Quadro",
1043 "p3_scitel",
1044 AM_NONE, AM_IND_IO, 0, 3,
1045 &ipac_irq
1046 },
1047 {
1048 INF_SCT_4,
1049 "SciTel Quadro",
1050 "p4_scitel",
1051 AM_NONE, AM_IND_IO, 0, 2,
1052 &ipac_irq
1053 },
1054 {
1055 INF_GAZEL_R685,
1056 "Gazel R685",
1057 "gazel685",
1058 AM_IO, AM_IO, 1, 2,
1059 &gazel_irq
1060 },
1061 {
1062 INF_GAZEL_R753,
1063 "Gazel R753",
1064 "gazel753",
1065 AM_IO, AM_IND_IO, 1, 2,
1066 &ipac_irq
1067 },
1068 {
1069 INF_NONE,
1070 }
1071};
1072
1073static const struct inf_cinfo * __devinit
1074get_card_info(enum inf_types typ)
1075{
1076 const struct inf_cinfo *ci = inf_card_info;
1077
1078 while (ci->typ != INF_NONE) {
1079 if (ci->typ == typ)
1080 return ci;
1081 ci++;
1082 }
1083 return NULL;
1084}
1085
1086static int __devinit
1087inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1088{
1089 int err = -ENOMEM;
1090 struct inf_hw *card;
1091
1092 card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1093 if (!card) {
1094 pr_info("No memory for Infineon ISDN card\n");
1095 return err;
1096 }
1097 card->pdev = pdev;
1098 err = pci_enable_device(pdev);
1099 if (err) {
1100 kfree(card);
1101 return err;
1102 }
1103 card->ci = get_card_info(ent->driver_data);
1104 if (!card->ci) {
1105 pr_info("mISDN: do not have informations about adapter at %s\n",
1106 pci_name(pdev));
1107 kfree(card);
1108 return -EINVAL;
1109 } else
1110 pr_notice("mISDN: found adapter %s at %s\n",
1111 card->ci->full, pci_name(pdev));
1112
1113 card->irq = pdev->irq;
1114 pci_set_drvdata(pdev, card);
1115 err = setup_instance(card);
1116 if (err) {
1117 pci_disable_device(card->pdev);
1118 kfree(card);
1119 pci_set_drvdata(pdev, NULL);
1120 } else if (ent->driver_data == INF_SCT_1) {
1121 int i;
1122 struct inf_hw *sc;
1123
1124 for (i = 1; i < 4; i++) {
1125 sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1126 if (!sc) {
1127 release_card(card);
1128 return -ENOMEM;
1129 }
1130 sc->irq = card->irq;
1131 sc->pdev = card->pdev;
1132 sc->ci = card->ci + i;
1133 err = setup_instance(sc);
1134 if (err) {
1135 kfree(sc);
1136 release_card(card);
f0f4d641 1137 break;
cae86d4a
KK
1138 } else
1139 card->sc[i - 1] = sc;
1140 }
1141 }
1142 return err;
1143}
1144
1145static void __devexit
1146inf_remove(struct pci_dev *pdev)
1147{
1148 struct inf_hw *card = pci_get_drvdata(pdev);
1149
1150 if (card)
1151 release_card(card);
1152 else
1153 pr_debug("%s: drvdata allready removed\n", __func__);
1154}
1155
1156static struct pci_driver infineon_driver = {
1157 .name = "ISDN Infineon pci",
1158 .probe = inf_probe,
1159 .remove = __devexit_p(inf_remove),
1160 .id_table = infineon_ids,
1161};
1162
1163static int __init
1164infineon_init(void)
1165{
1166 int err;
1167
1168 pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV);
1169 err = pci_register_driver(&infineon_driver);
1170 return err;
1171}
1172
1173static void __exit
1174infineon_cleanup(void)
1175{
1176 pci_unregister_driver(&infineon_driver);
1177}
1178
1179module_init(infineon_init);
1180module_exit(infineon_cleanup);