1// SPDX-License-Identifier: GPL-2.0-only
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 *
21 * Author       Karsten Keil <keil@isdn4linux.de>
22 *
23 * Copyright 2009  by Karsten Keil <keil@isdn4linux.de>
24 */
25
26#include <linux/interrupt.h>
27#include <linux/module.h>
28#include <linux/pci.h>
29#include <linux/delay.h>
30#include <linux/mISDNhw.h>
31#include <linux/slab.h>
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
113static struct pci_device_id infineon_ids[] = {
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 },
118	{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
119	  PCI_SUBVENDOR_SEDLBAUER_PCI, PCI_SUB_ID_SEDLBAUER, 0, 0,
120	  INF_SPEEDWIN },
121	{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
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 },
126	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
127	  PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO, 0, 0,
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 },
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
232set_debug(const char *val, const struct kernel_param *kp)
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);
409		val |= NICCY_IRQ_ENABLE;
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,
419		     (u32)hw->cfg.start + GAZEL_INCSR);
420		break;
421	case INF_GAZEL_R753:
422		outb(GAZEL_IPAC_EN + GAZEL_PCI_EN,
423		     (u32)hw->cfg.start + GAZEL_INCSR);
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,
499		     (u32)hw->cfg.start + DIVA_PCI_CTRL);
500		break;
501	case INF_DIVA201:
502		writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
503		       hw->cfg.p + PITA_MISC_REG);
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,
510		       hw->cfg.p + PITA_MISC_REG);
511		mdelay(1);
512		writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET,
513		       hw->cfg.p + PITA_MISC_REG);
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;
552		hw->ipac.hscx[1].slot = 0x23;
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
591static int
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,
618				  hw->irq, hw->irqcnt);
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.mode == AM_MEMIO) {
634			release_mem_region(hw->cfg.start, hw->cfg.size);
635			if (hw->cfg.p)
636				iounmap(hw->cfg.p);
637		} else
638			release_region(hw->cfg.start, hw->cfg.size);
639		hw->cfg.mode = AM_NONE;
640	}
641	if (hw->addr.mode) {
642		if (hw->addr.mode == AM_MEMIO) {
643			release_mem_region(hw->addr.start, hw->addr.size);
644			if (hw->addr.p)
645				iounmap(hw->addr.p);
646		} else
647			release_region(hw->addr.start, hw->addr.size);
648		hw->addr.mode = AM_NONE;
649	}
650}
651
652static int
653setup_io(struct inf_hw *hw)
654{
655	int err = 0;
656
657	if (hw->ci->cfg_mode) {
658		hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar);
659		hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar);
660		if (hw->ci->cfg_mode == AM_MEMIO) {
661			if (!request_mem_region(hw->cfg.start, hw->cfg.size,
662						hw->name))
663				err = -EBUSY;
664		} else {
665			if (!request_region(hw->cfg.start, hw->cfg.size,
666					    hw->name))
667				err = -EBUSY;
668		}
669		if (err) {
670			pr_info("mISDN: %s config port %lx (%lu bytes)"
671				"already in use\n", hw->name,
672				(ulong)hw->cfg.start, (ulong)hw->cfg.size);
673			return err;
674		}
675		hw->cfg.mode = hw->ci->cfg_mode;
676		if (hw->ci->cfg_mode == AM_MEMIO) {
677			hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
678			if (!hw->cfg.p)
679				return -ENOMEM;
680		}
681		if (debug & DEBUG_HW)
682			pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
683				  hw->name, (ulong)hw->cfg.start,
684				  (ulong)hw->cfg.size, hw->ci->cfg_mode);
685
686	}
687	if (hw->ci->addr_mode) {
688		hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar);
689		hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar);
690		if (hw->ci->addr_mode == AM_MEMIO) {
691			if (!request_mem_region(hw->addr.start, hw->addr.size,
692						hw->name))
693				err = -EBUSY;
694		} else {
695			if (!request_region(hw->addr.start, hw->addr.size,
696					    hw->name))
697				err = -EBUSY;
698		}
699		if (err) {
700			pr_info("mISDN: %s address port %lx (%lu bytes)"
701				"already in use\n", hw->name,
702				(ulong)hw->addr.start, (ulong)hw->addr.size);
703			return err;
704		}
705		hw->addr.mode = hw->ci->addr_mode;
706		if (hw->ci->addr_mode == AM_MEMIO) {
707			hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
708			if (!hw->addr.p)
709				return -ENOMEM;
710		}
711		if (debug & DEBUG_HW)
712			pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
713				  hw->name, (ulong)hw->addr.start,
714				  (ulong)hw->addr.size, hw->ci->addr_mode);
715
716	}
717
718	switch (hw->ci->typ) {
719	case INF_DIVA20:
720	case INF_DIVA20U:
721		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
722		hw->isac.mode = hw->cfg.mode;
723		hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE;
724		hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT;
725		hw->hscx.mode = hw->cfg.mode;
726		hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE;
727		hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT;
728		break;
729	case INF_DIVA201:
730		hw->ipac.type = IPAC_TYPE_IPAC;
731		hw->ipac.isac.off = 0x80;
732		hw->isac.mode = hw->addr.mode;
733		hw->isac.a.p = hw->addr.p;
734		hw->hscx.mode = hw->addr.mode;
735		hw->hscx.a.p = hw->addr.p;
736		break;
737	case INF_DIVA202:
738		hw->ipac.type = IPAC_TYPE_IPACX;
739		hw->isac.mode = hw->addr.mode;
740		hw->isac.a.p = hw->addr.p;
741		hw->hscx.mode = hw->addr.mode;
742		hw->hscx.a.p = hw->addr.p;
743		break;
744	case INF_SPEEDWIN:
745	case INF_SAPHIR3:
746		hw->ipac.type = IPAC_TYPE_IPAC;
747		hw->ipac.isac.off = 0x80;
748		hw->isac.mode = hw->cfg.mode;
749		hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
750		hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
751		hw->hscx.mode = hw->cfg.mode;
752		hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
753		hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
754		outb(0xff, (ulong)hw->cfg.start);
755		mdelay(1);
756		outb(0x00, (ulong)hw->cfg.start);
757		mdelay(1);
758		outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL);
759		break;
760	case INF_QS1000:
761	case INF_QS3000:
762		hw->ipac.type = IPAC_TYPE_IPAC;
763		hw->ipac.isac.off = 0x80;
764		hw->isac.a.io.ale = (u32)hw->addr.start;
765		hw->isac.a.io.port = (u32)hw->addr.start + 1;
766		hw->isac.mode = hw->addr.mode;
767		hw->hscx.a.io.ale = (u32)hw->addr.start;
768		hw->hscx.a.io.port = (u32)hw->addr.start + 1;
769		hw->hscx.mode = hw->addr.mode;
770		break;
771	case INF_NICCY:
772		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
773		hw->isac.mode = hw->addr.mode;
774		hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE;
775		hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT;
776		hw->hscx.mode = hw->addr.mode;
777		hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE;
778		hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT;
779		break;
780	case INF_SCT_1:
781		hw->ipac.type = IPAC_TYPE_IPAC;
782		hw->ipac.isac.off = 0x80;
783		hw->isac.a.io.ale = (u32)hw->addr.start;
784		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
785		hw->isac.mode = hw->addr.mode;
786		hw->hscx.a.io.ale = hw->isac.a.io.ale;
787		hw->hscx.a.io.port = hw->isac.a.io.port;
788		hw->hscx.mode = hw->addr.mode;
789		break;
790	case INF_SCT_2:
791		hw->ipac.type = IPAC_TYPE_IPAC;
792		hw->ipac.isac.off = 0x80;
793		hw->isac.a.io.ale = (u32)hw->addr.start + 0x08;
794		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
795		hw->isac.mode = hw->addr.mode;
796		hw->hscx.a.io.ale = hw->isac.a.io.ale;
797		hw->hscx.a.io.port = hw->isac.a.io.port;
798		hw->hscx.mode = hw->addr.mode;
799		break;
800	case INF_SCT_3:
801		hw->ipac.type = IPAC_TYPE_IPAC;
802		hw->ipac.isac.off = 0x80;
803		hw->isac.a.io.ale = (u32)hw->addr.start + 0x10;
804		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
805		hw->isac.mode = hw->addr.mode;
806		hw->hscx.a.io.ale = hw->isac.a.io.ale;
807		hw->hscx.a.io.port = hw->isac.a.io.port;
808		hw->hscx.mode = hw->addr.mode;
809		break;
810	case INF_SCT_4:
811		hw->ipac.type = IPAC_TYPE_IPAC;
812		hw->ipac.isac.off = 0x80;
813		hw->isac.a.io.ale = (u32)hw->addr.start + 0x20;
814		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
815		hw->isac.mode = hw->addr.mode;
816		hw->hscx.a.io.ale = hw->isac.a.io.ale;
817		hw->hscx.a.io.port = hw->isac.a.io.port;
818		hw->hscx.mode = hw->addr.mode;
819		break;
820	case INF_GAZEL_R685:
821		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
822		hw->ipac.isac.off = 0x80;
823		hw->isac.mode = hw->addr.mode;
824		hw->isac.a.io.port = (u32)hw->addr.start;
825		hw->hscx.mode = hw->addr.mode;
826		hw->hscx.a.io.port = hw->isac.a.io.port;
827		break;
828	case INF_GAZEL_R753:
829		hw->ipac.type = IPAC_TYPE_IPAC;
830		hw->ipac.isac.off = 0x80;
831		hw->isac.mode = hw->addr.mode;
832		hw->isac.a.io.ale = (u32)hw->addr.start;
833		hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT;
834		hw->hscx.mode = hw->addr.mode;
835		hw->hscx.a.io.ale = hw->isac.a.io.ale;
836		hw->hscx.a.io.port = hw->isac.a.io.port;
837		break;
838	default:
839		return -EINVAL;
840	}
841	switch (hw->isac.mode) {
842	case AM_MEMIO:
843		ASSIGN_FUNC_IPAC(MIO, hw->ipac);
844		break;
845	case AM_IND_IO:
846		ASSIGN_FUNC_IPAC(IND, hw->ipac);
847		break;
848	case AM_IO:
849		ASSIGN_FUNC_IPAC(IO, hw->ipac);
850		break;
851	default:
852		return -EINVAL;
853	}
854	return 0;
855}
856
857static void
858release_card(struct inf_hw *card) {
859	ulong	flags;
860	int	i;
861
862	spin_lock_irqsave(&card->lock, flags);
863	disable_hwirq(card);
864	spin_unlock_irqrestore(&card->lock, flags);
865	card->ipac.isac.release(&card->ipac.isac);
866	free_irq(card->irq, card);
867	mISDN_unregister_device(&card->ipac.isac.dch.dev);
868	release_io(card);
869	write_lock_irqsave(&card_lock, flags);
870	list_del(&card->list);
871	write_unlock_irqrestore(&card_lock, flags);
872	switch (card->ci->typ) {
873	case INF_SCT_2:
874	case INF_SCT_3:
875	case INF_SCT_4:
876		break;
877	case INF_SCT_1:
878		for (i = 0; i < 3; i++) {
879			if (card->sc[i])
880				release_card(card->sc[i]);
881			card->sc[i] = NULL;
882		}
883		fallthrough;
884	default:
885		pci_disable_device(card->pdev);
886		pci_set_drvdata(card->pdev, NULL);
887		break;
888	}
889	kfree(card);
890	inf_cnt--;
891}
892
893static int
894setup_instance(struct inf_hw *card)
895{
896	int err;
897	ulong flags;
898
899	snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name,
900		 inf_cnt + 1);
901	write_lock_irqsave(&card_lock, flags);
902	list_add_tail(&card->list, &Cards);
903	write_unlock_irqrestore(&card_lock, flags);
904
905	_set_debug(card);
906	card->ipac.isac.name = card->name;
907	card->ipac.name = card->name;
908	card->ipac.owner = THIS_MODULE;
909	spin_lock_init(&card->lock);
910	card->ipac.isac.hwlock = &card->lock;
911	card->ipac.hwlock = &card->lock;
912	card->ipac.ctrl = (void *)&inf_ctrl;
913
914	err = setup_io(card);
915	if (err)
916		goto error_setup;
917
918	card->ipac.isac.dch.dev.Bprotocols =
919		mISDNipac_init(&card->ipac, card);
920
921	if (card->ipac.isac.dch.dev.Bprotocols == 0)
922		goto error_setup;
923
924	err = mISDN_register_device(&card->ipac.isac.dch.dev,
925				    &card->pdev->dev, card->name);
926	if (err)
927		goto error;
928
929	err = init_irq(card);
930	if (!err)  {
931		inf_cnt++;
932		pr_notice("Infineon %d cards installed\n", inf_cnt);
933		return 0;
934	}
935	mISDN_unregister_device(&card->ipac.isac.dch.dev);
936error:
937	card->ipac.release(&card->ipac);
938error_setup:
939	release_io(card);
940	write_lock_irqsave(&card_lock, flags);
941	list_del(&card->list);
942	write_unlock_irqrestore(&card_lock, flags);
943	return err;
944}
945
946static const struct inf_cinfo inf_card_info[] = {
947	{
948		INF_DIVA20,
949		"Dialogic Diva 2.0",
950		"diva20",
951		AM_IND_IO, AM_NONE, 2, 0,
952		&diva_irq
953	},
954	{
955		INF_DIVA20U,
956		"Dialogic Diva 2.0U",
957		"diva20U",
958		AM_IND_IO, AM_NONE, 2, 0,
959		&diva_irq
960	},
961	{
962		INF_DIVA201,
963		"Dialogic Diva 2.01",
964		"diva201",
965		AM_MEMIO, AM_MEMIO, 0, 1,
966		&diva20x_irq
967	},
968	{
969		INF_DIVA202,
970		"Dialogic Diva 2.02",
971		"diva202",
972		AM_MEMIO, AM_MEMIO, 0, 1,
973		&diva20x_irq
974	},
975	{
976		INF_SPEEDWIN,
977		"Sedlbauer SpeedWin PCI",
978		"speedwin",
979		AM_IND_IO, AM_NONE, 0, 0,
980		&tiger_irq
981	},
982	{
983		INF_SAPHIR3,
984		"HST Saphir 3",
985		"saphir",
986		AM_IND_IO, AM_NONE, 0, 0,
987		&tiger_irq
988	},
989	{
990		INF_QS1000,
991		"Develo Microlink PCI",
992		"qs1000",
993		AM_IO, AM_IND_IO, 1, 3,
994		&elsa_irq
995	},
996	{
997		INF_QS3000,
998		"Develo QuickStep 3000",
999		"qs3000",
1000		AM_IO, AM_IND_IO, 1, 3,
1001		&elsa_irq
1002	},
1003	{
1004		INF_NICCY,
1005		"Sagem NICCY",
1006		"niccy",
1007		AM_IO, AM_IND_IO, 0, 1,
1008		&niccy_irq
1009	},
1010	{
1011		INF_SCT_1,
1012		"SciTel Quadro",
1013		"p1_scitel",
1014		AM_IO, AM_IND_IO, 1, 5,
1015		&ipac_irq
1016	},
1017	{
1018		INF_SCT_2,
1019		"SciTel Quadro",
1020		"p2_scitel",
1021		AM_NONE, AM_IND_IO, 0, 4,
1022		&ipac_irq
1023	},
1024	{
1025		INF_SCT_3,
1026		"SciTel Quadro",
1027		"p3_scitel",
1028		AM_NONE, AM_IND_IO, 0, 3,
1029		&ipac_irq
1030	},
1031	{
1032		INF_SCT_4,
1033		"SciTel Quadro",
1034		"p4_scitel",
1035		AM_NONE, AM_IND_IO, 0, 2,
1036		&ipac_irq
1037	},
1038	{
1039		INF_GAZEL_R685,
1040		"Gazel R685",
1041		"gazel685",
1042		AM_IO, AM_IO, 1, 2,
1043		&gazel_irq
1044	},
1045	{
1046		INF_GAZEL_R753,
1047		"Gazel R753",
1048		"gazel753",
1049		AM_IO, AM_IND_IO, 1, 2,
1050		&ipac_irq
1051	},
1052	{
1053		INF_NONE,
1054	}
1055};
1056
1057static const struct inf_cinfo *
1058get_card_info(enum inf_types typ)
1059{
1060	const struct inf_cinfo *ci = inf_card_info;
1061
1062	while (ci->typ != INF_NONE) {
1063		if (ci->typ == typ)
1064			return ci;
1065		ci++;
1066	}
1067	return NULL;
1068}
1069
1070static int
1071inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1072{
1073	int err = -ENOMEM;
1074	struct inf_hw *card;
1075
1076	card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1077	if (!card) {
1078		pr_info("No memory for Infineon ISDN card\n");
1079		return err;
1080	}
1081	card->pdev = pdev;
1082	err = pci_enable_device(pdev);
1083	if (err) {
1084		kfree(card);
1085		return err;
1086	}
1087	card->ci = get_card_info(ent->driver_data);
1088	if (!card->ci) {
1089		pr_info("mISDN: do not have information about adapter at %s\n",
1090			pci_name(pdev));
1091		kfree(card);
1092		pci_disable_device(pdev);
1093		return -EINVAL;
1094	} else
1095		pr_notice("mISDN: found adapter %s at %s\n",
1096			  card->ci->full, pci_name(pdev));
1097
1098	card->irq = pdev->irq;
1099	pci_set_drvdata(pdev, card);
1100	err = setup_instance(card);
1101	if (err) {
1102		pci_disable_device(pdev);
1103		kfree(card);
1104		pci_set_drvdata(pdev, NULL);
1105	} else if (ent->driver_data == INF_SCT_1) {
1106		int i;
1107		struct inf_hw *sc;
1108
1109		for (i = 1; i < 4; i++) {
1110			sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1111			if (!sc) {
1112				release_card(card);
1113				pci_disable_device(pdev);
1114				return -ENOMEM;
1115			}
1116			sc->irq = card->irq;
1117			sc->pdev = card->pdev;
1118			sc->ci = card->ci + i;
1119			err = setup_instance(sc);
1120			if (err) {
1121				pci_disable_device(pdev);
1122				kfree(sc);
1123				release_card(card);
1124				break;
1125			} else
1126				card->sc[i - 1] = sc;
1127		}
1128	}
1129	return err;
1130}
1131
1132static void
1133inf_remove(struct pci_dev *pdev)
1134{
1135	struct inf_hw	*card = pci_get_drvdata(pdev);
1136
1137	if (card)
1138		release_card(card);
1139	else
1140		pr_debug("%s: drvdata already removed\n", __func__);
1141}
1142
1143static struct pci_driver infineon_driver = {
1144	.name = "ISDN Infineon pci",
1145	.probe = inf_probe,
1146	.remove = inf_remove,
1147	.id_table = infineon_ids,
1148};
1149
1150static int __init
1151infineon_init(void)
1152{
1153	int err;
1154
1155	pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV);
1156	err = pci_register_driver(&infineon_driver);
1157	return err;
1158}
1159
1160static void __exit
1161infineon_cleanup(void)
1162{
1163	pci_unregister_driver(&infineon_driver);
1164}
1165
1166module_init(infineon_init);
1167module_exit(infineon_cleanup);
1168