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