File Index
Files and directories
Sign in
FILE

mISDNinfineon.c

File preview with syntax highlighting.

linux-6.19.14/drivers/isdn/hardware/mISDN/mISDNinfineon.c C
   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_DESCRIPTION("mISDN driver for cards based on Infineon ISDN chipsets");
 249MODULE_LICENSE("GPL v2");
 250MODULE_VERSION(INFINEON_REV);
 251module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
 252MODULE_PARM_DESC(debug, "infineon debug mask");
 253module_param(irqloops, uint, S_IRUGO | S_IWUSR);
 254MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)");
 255
 256/* Interface functions */
 257
 258IOFUNC_IO(ISAC, inf_hw, isac.a.io)
 259IOFUNC_IO(IPAC, inf_hw, hscx.a.io)
 260IOFUNC_IND(ISAC, inf_hw, isac.a.io)
 261IOFUNC_IND(IPAC, inf_hw, hscx.a.io)
 262IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p)
 263IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p)
 264
 265static irqreturn_t
 266diva_irq(int intno, void *dev_id)
 267{
 268	struct inf_hw *hw = dev_id;
 269	u8 val;
 270
 271	spin_lock(&hw->lock);
 272	val = inb((u32)hw->cfg.start + DIVA_PCI_CTRL);
 273	if (!(val & DIVA_IRQ_BIT)) { /* for us or shared ? */
 274		spin_unlock(&hw->lock);
 275		return IRQ_NONE; /* shared */
 276	}
 277	hw->irqcnt++;
 278	mISDNipac_irq(&hw->ipac, irqloops);
 279	spin_unlock(&hw->lock);
 280	return IRQ_HANDLED;
 281}
 282
 283static irqreturn_t
 284diva20x_irq(int intno, void *dev_id)
 285{
 286	struct inf_hw *hw = dev_id;
 287	u8 val;
 288
 289	spin_lock(&hw->lock);
 290	val = readb(hw->cfg.p);
 291	if (!(val & PITA_INT0_STATUS)) { /* for us or shared ? */
 292		spin_unlock(&hw->lock);
 293		return IRQ_NONE; /* shared */
 294	}
 295	hw->irqcnt++;
 296	mISDNipac_irq(&hw->ipac, irqloops);
 297	writeb(PITA_INT0_STATUS, hw->cfg.p); /* ACK PITA INT0 */
 298	spin_unlock(&hw->lock);
 299	return IRQ_HANDLED;
 300}
 301
 302static irqreturn_t
 303tiger_irq(int intno, void *dev_id)
 304{
 305	struct inf_hw *hw = dev_id;
 306	u8 val;
 307
 308	spin_lock(&hw->lock);
 309	val = inb((u32)hw->cfg.start + TIGER_AUX_STATUS);
 310	if (val & TIGER_IRQ_BIT) { /* for us or shared ? */
 311		spin_unlock(&hw->lock);
 312		return IRQ_NONE; /* shared */
 313	}
 314	hw->irqcnt++;
 315	mISDNipac_irq(&hw->ipac, irqloops);
 316	spin_unlock(&hw->lock);
 317	return IRQ_HANDLED;
 318}
 319
 320static irqreturn_t
 321elsa_irq(int intno, void *dev_id)
 322{
 323	struct inf_hw *hw = dev_id;
 324	u8 val;
 325
 326	spin_lock(&hw->lock);
 327	val = inb((u32)hw->cfg.start + ELSA_IRQ_ADDR);
 328	if (!(val & ELSA_IRQ_MASK)) {
 329		spin_unlock(&hw->lock);
 330		return IRQ_NONE; /* shared */
 331	}
 332	hw->irqcnt++;
 333	mISDNipac_irq(&hw->ipac, irqloops);
 334	spin_unlock(&hw->lock);
 335	return IRQ_HANDLED;
 336}
 337
 338static irqreturn_t
 339niccy_irq(int intno, void *dev_id)
 340{
 341	struct inf_hw *hw = dev_id;
 342	u32 val;
 343
 344	spin_lock(&hw->lock);
 345	val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 346	if (!(val & NICCY_IRQ_BIT)) { /* for us or shared ? */
 347		spin_unlock(&hw->lock);
 348		return IRQ_NONE; /* shared */
 349	}
 350	outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 351	hw->irqcnt++;
 352	mISDNipac_irq(&hw->ipac, irqloops);
 353	spin_unlock(&hw->lock);
 354	return IRQ_HANDLED;
 355}
 356
 357static irqreturn_t
 358gazel_irq(int intno, void *dev_id)
 359{
 360	struct inf_hw *hw = dev_id;
 361	irqreturn_t ret;
 362
 363	spin_lock(&hw->lock);
 364	ret = mISDNipac_irq(&hw->ipac, irqloops);
 365	spin_unlock(&hw->lock);
 366	return ret;
 367}
 368
 369static irqreturn_t
 370ipac_irq(int intno, void *dev_id)
 371{
 372	struct inf_hw *hw = dev_id;
 373	u8 val;
 374
 375	spin_lock(&hw->lock);
 376	val = hw->ipac.read_reg(hw, IPAC_ISTA);
 377	if (!(val & 0x3f)) {
 378		spin_unlock(&hw->lock);
 379		return IRQ_NONE; /* shared */
 380	}
 381	hw->irqcnt++;
 382	mISDNipac_irq(&hw->ipac, irqloops);
 383	spin_unlock(&hw->lock);
 384	return IRQ_HANDLED;
 385}
 386
 387static void
 388enable_hwirq(struct inf_hw *hw)
 389{
 390	u16 w;
 391	u32 val;
 392
 393	switch (hw->ci->typ) {
 394	case INF_DIVA201:
 395	case INF_DIVA202:
 396		writel(PITA_INT0_ENABLE, hw->cfg.p);
 397		break;
 398	case INF_SPEEDWIN:
 399	case INF_SAPHIR3:
 400		outb(TIGER_IRQ_BIT, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
 401		break;
 402	case INF_QS1000:
 403		outb(QS1000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
 404		break;
 405	case INF_QS3000:
 406		outb(QS3000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
 407		break;
 408	case INF_NICCY:
 409		val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 410		val |= NICCY_IRQ_ENABLE;
 411		outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 412		break;
 413	case INF_SCT_1:
 414		w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
 415		w |= SCT_PLX_IRQ_ENABLE;
 416		outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
 417		break;
 418	case INF_GAZEL_R685:
 419		outb(GAZEL_ISAC_EN + GAZEL_HSCX_EN + GAZEL_PCI_EN,
 420		     (u32)hw->cfg.start + GAZEL_INCSR);
 421		break;
 422	case INF_GAZEL_R753:
 423		outb(GAZEL_IPAC_EN + GAZEL_PCI_EN,
 424		     (u32)hw->cfg.start + GAZEL_INCSR);
 425		break;
 426	default:
 427		break;
 428	}
 429}
 430
 431static void
 432disable_hwirq(struct inf_hw *hw)
 433{
 434	u16 w;
 435	u32 val;
 436
 437	switch (hw->ci->typ) {
 438	case INF_DIVA201:
 439	case INF_DIVA202:
 440		writel(0, hw->cfg.p);
 441		break;
 442	case INF_SPEEDWIN:
 443	case INF_SAPHIR3:
 444		outb(0, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
 445		break;
 446	case INF_QS1000:
 447		outb(QS1000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
 448		break;
 449	case INF_QS3000:
 450		outb(QS3000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
 451		break;
 452	case INF_NICCY:
 453		val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 454		val &= NICCY_IRQ_DISABLE;
 455		outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 456		break;
 457	case INF_SCT_1:
 458		w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
 459		w &= (~SCT_PLX_IRQ_ENABLE);
 460		outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
 461		break;
 462	case INF_GAZEL_R685:
 463	case INF_GAZEL_R753:
 464		outb(0, (u32)hw->cfg.start + GAZEL_INCSR);
 465		break;
 466	default:
 467		break;
 468	}
 469}
 470
 471static void
 472ipac_chip_reset(struct inf_hw *hw)
 473{
 474	hw->ipac.write_reg(hw, IPAC_POTA2, 0x20);
 475	mdelay(5);
 476	hw->ipac.write_reg(hw, IPAC_POTA2, 0x00);
 477	mdelay(5);
 478	hw->ipac.write_reg(hw, IPAC_CONF, hw->ipac.conf);
 479	hw->ipac.write_reg(hw, IPAC_MASK, 0xc0);
 480}
 481
 482static void
 483reset_inf(struct inf_hw *hw)
 484{
 485	u16 w;
 486	u32 val;
 487
 488	if (debug & DEBUG_HW)
 489		pr_notice("%s: resetting card\n", hw->name);
 490	switch (hw->ci->typ) {
 491	case INF_DIVA20:
 492	case INF_DIVA20U:
 493		outb(0, (u32)hw->cfg.start + DIVA_PCI_CTRL);
 494		mdelay(10);
 495		outb(DIVA_RESET_BIT, (u32)hw->cfg.start + DIVA_PCI_CTRL);
 496		mdelay(10);
 497		/* Workaround PCI9060 */
 498		outb(9, (u32)hw->cfg.start + 0x69);
 499		outb(DIVA_RESET_BIT | DIVA_LED_A,
 500		     (u32)hw->cfg.start + DIVA_PCI_CTRL);
 501		break;
 502	case INF_DIVA201:
 503		writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
 504		       hw->cfg.p + PITA_MISC_REG);
 505		mdelay(1);
 506		writel(PITA_PARA_MPX_MODE, hw->cfg.p + PITA_MISC_REG);
 507		mdelay(10);
 508		break;
 509	case INF_DIVA202:
 510		writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
 511		       hw->cfg.p + PITA_MISC_REG);
 512		mdelay(1);
 513		writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET,
 514		       hw->cfg.p + PITA_MISC_REG);
 515		mdelay(10);
 516		break;
 517	case INF_SPEEDWIN:
 518	case INF_SAPHIR3:
 519		ipac_chip_reset(hw);
 520		hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
 521		hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
 522		hw->ipac.write_reg(hw, IPAC_PCFG, 0x12);
 523		break;
 524	case INF_QS1000:
 525	case INF_QS3000:
 526		ipac_chip_reset(hw);
 527		hw->ipac.write_reg(hw, IPAC_ACFG, 0x00);
 528		hw->ipac.write_reg(hw, IPAC_AOE, 0x3c);
 529		hw->ipac.write_reg(hw, IPAC_ATX, 0xff);
 530		break;
 531	case INF_NICCY:
 532		break;
 533	case INF_SCT_1:
 534		w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
 535		w &= (~SCT_PLX_RESET_BIT);
 536		outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
 537		mdelay(10);
 538		w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
 539		w |= SCT_PLX_RESET_BIT;
 540		outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
 541		mdelay(10);
 542		break;
 543	case INF_GAZEL_R685:
 544		val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
 545		val |= (GAZEL_RESET_9050 + GAZEL_RESET);
 546		outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
 547		val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
 548		mdelay(4);
 549		outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
 550		mdelay(10);
 551		hw->ipac.isac.adf2 = 0x87;
 552		hw->ipac.hscx[0].slot = 0x1f;
 553		hw->ipac.hscx[1].slot = 0x23;
 554		break;
 555	case INF_GAZEL_R753:
 556		val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
 557		val |= (GAZEL_RESET_9050 + GAZEL_RESET);
 558		outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
 559		val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
 560		mdelay(4);
 561		outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
 562		mdelay(10);
 563		ipac_chip_reset(hw);
 564		hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
 565		hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
 566		hw->ipac.conf = 0x01; /* IOM off */
 567		break;
 568	default:
 569		return;
 570	}
 571	enable_hwirq(hw);
 572}
 573
 574static int
 575inf_ctrl(struct inf_hw *hw, u32 cmd, u_long arg)
 576{
 577	int ret = 0;
 578
 579	switch (cmd) {
 580	case HW_RESET_REQ:
 581		reset_inf(hw);
 582		break;
 583	default:
 584		pr_info("%s: %s unknown command %x %lx\n",
 585			hw->name, __func__, cmd, arg);
 586		ret = -EINVAL;
 587		break;
 588	}
 589	return ret;
 590}
 591
 592static int
 593init_irq(struct inf_hw *hw)
 594{
 595	int	ret, cnt = 3;
 596	u_long	flags;
 597
 598	if (!hw->ci->irqfunc)
 599		return -EINVAL;
 600	ret = request_irq(hw->irq, hw->ci->irqfunc, IRQF_SHARED, hw->name, hw);
 601	if (ret) {
 602		pr_info("%s: couldn't get interrupt %d\n", hw->name, hw->irq);
 603		return ret;
 604	}
 605	while (cnt--) {
 606		spin_lock_irqsave(&hw->lock, flags);
 607		reset_inf(hw);
 608		ret = hw->ipac.init(&hw->ipac);
 609		if (ret) {
 610			spin_unlock_irqrestore(&hw->lock, flags);
 611			pr_info("%s: ISAC init failed with %d\n",
 612				hw->name, ret);
 613			break;
 614		}
 615		spin_unlock_irqrestore(&hw->lock, flags);
 616		msleep_interruptible(10);
 617		if (debug & DEBUG_HW)
 618			pr_notice("%s: IRQ %d count %d\n", hw->name,
 619				  hw->irq, hw->irqcnt);
 620		if (!hw->irqcnt) {
 621			pr_info("%s: IRQ(%d) got no requests during init %d\n",
 622				hw->name, hw->irq, 3 - cnt);
 623		} else
 624			return 0;
 625	}
 626	free_irq(hw->irq, hw);
 627	return -EIO;
 628}
 629
 630static void
 631release_io(struct inf_hw *hw)
 632{
 633	if (hw->cfg.mode) {
 634		if (hw->cfg.mode == AM_MEMIO) {
 635			release_mem_region(hw->cfg.start, hw->cfg.size);
 636			if (hw->cfg.p)
 637				iounmap(hw->cfg.p);
 638		} else
 639			release_region(hw->cfg.start, hw->cfg.size);
 640		hw->cfg.mode = AM_NONE;
 641	}
 642	if (hw->addr.mode) {
 643		if (hw->addr.mode == AM_MEMIO) {
 644			release_mem_region(hw->addr.start, hw->addr.size);
 645			if (hw->addr.p)
 646				iounmap(hw->addr.p);
 647		} else
 648			release_region(hw->addr.start, hw->addr.size);
 649		hw->addr.mode = AM_NONE;
 650	}
 651}
 652
 653static int
 654setup_io(struct inf_hw *hw)
 655{
 656	int err = 0;
 657
 658	if (hw->ci->cfg_mode) {
 659		hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar);
 660		hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar);
 661		if (hw->ci->cfg_mode == AM_MEMIO) {
 662			if (!request_mem_region(hw->cfg.start, hw->cfg.size,
 663						hw->name))
 664				err = -EBUSY;
 665		} else {
 666			if (!request_region(hw->cfg.start, hw->cfg.size,
 667					    hw->name))
 668				err = -EBUSY;
 669		}
 670		if (err) {
 671			pr_info("mISDN: %s config port %lx (%lu bytes)"
 672				"already in use\n", hw->name,
 673				(ulong)hw->cfg.start, (ulong)hw->cfg.size);
 674			return err;
 675		}
 676		hw->cfg.mode = hw->ci->cfg_mode;
 677		if (hw->ci->cfg_mode == AM_MEMIO) {
 678			hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
 679			if (!hw->cfg.p)
 680				return -ENOMEM;
 681		}
 682		if (debug & DEBUG_HW)
 683			pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
 684				  hw->name, (ulong)hw->cfg.start,
 685				  (ulong)hw->cfg.size, hw->ci->cfg_mode);
 686
 687	}
 688	if (hw->ci->addr_mode) {
 689		hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar);
 690		hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar);
 691		if (hw->ci->addr_mode == AM_MEMIO) {
 692			if (!request_mem_region(hw->addr.start, hw->addr.size,
 693						hw->name))
 694				err = -EBUSY;
 695		} else {
 696			if (!request_region(hw->addr.start, hw->addr.size,
 697					    hw->name))
 698				err = -EBUSY;
 699		}
 700		if (err) {
 701			pr_info("mISDN: %s address port %lx (%lu bytes)"
 702				"already in use\n", hw->name,
 703				(ulong)hw->addr.start, (ulong)hw->addr.size);
 704			return err;
 705		}
 706		hw->addr.mode = hw->ci->addr_mode;
 707		if (hw->ci->addr_mode == AM_MEMIO) {
 708			hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
 709			if (!hw->addr.p)
 710				return -ENOMEM;
 711		}
 712		if (debug & DEBUG_HW)
 713			pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
 714				  hw->name, (ulong)hw->addr.start,
 715				  (ulong)hw->addr.size, hw->ci->addr_mode);
 716
 717	}
 718
 719	switch (hw->ci->typ) {
 720	case INF_DIVA20:
 721	case INF_DIVA20U:
 722		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
 723		hw->isac.mode = hw->cfg.mode;
 724		hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE;
 725		hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT;
 726		hw->hscx.mode = hw->cfg.mode;
 727		hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE;
 728		hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT;
 729		break;
 730	case INF_DIVA201:
 731		hw->ipac.type = IPAC_TYPE_IPAC;
 732		hw->ipac.isac.off = 0x80;
 733		hw->isac.mode = hw->addr.mode;
 734		hw->isac.a.p = hw->addr.p;
 735		hw->hscx.mode = hw->addr.mode;
 736		hw->hscx.a.p = hw->addr.p;
 737		break;
 738	case INF_DIVA202:
 739		hw->ipac.type = IPAC_TYPE_IPACX;
 740		hw->isac.mode = hw->addr.mode;
 741		hw->isac.a.p = hw->addr.p;
 742		hw->hscx.mode = hw->addr.mode;
 743		hw->hscx.a.p = hw->addr.p;
 744		break;
 745	case INF_SPEEDWIN:
 746	case INF_SAPHIR3:
 747		hw->ipac.type = IPAC_TYPE_IPAC;
 748		hw->ipac.isac.off = 0x80;
 749		hw->isac.mode = hw->cfg.mode;
 750		hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
 751		hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
 752		hw->hscx.mode = hw->cfg.mode;
 753		hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
 754		hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
 755		outb(0xff, (ulong)hw->cfg.start);
 756		mdelay(1);
 757		outb(0x00, (ulong)hw->cfg.start);
 758		mdelay(1);
 759		outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL);
 760		break;
 761	case INF_QS1000:
 762	case INF_QS3000:
 763		hw->ipac.type = IPAC_TYPE_IPAC;
 764		hw->ipac.isac.off = 0x80;
 765		hw->isac.a.io.ale = (u32)hw->addr.start;
 766		hw->isac.a.io.port = (u32)hw->addr.start + 1;
 767		hw->isac.mode = hw->addr.mode;
 768		hw->hscx.a.io.ale = (u32)hw->addr.start;
 769		hw->hscx.a.io.port = (u32)hw->addr.start + 1;
 770		hw->hscx.mode = hw->addr.mode;
 771		break;
 772	case INF_NICCY:
 773		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
 774		hw->isac.mode = hw->addr.mode;
 775		hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE;
 776		hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT;
 777		hw->hscx.mode = hw->addr.mode;
 778		hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE;
 779		hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT;
 780		break;
 781	case INF_SCT_1:
 782		hw->ipac.type = IPAC_TYPE_IPAC;
 783		hw->ipac.isac.off = 0x80;
 784		hw->isac.a.io.ale = (u32)hw->addr.start;
 785		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
 786		hw->isac.mode = hw->addr.mode;
 787		hw->hscx.a.io.ale = hw->isac.a.io.ale;
 788		hw->hscx.a.io.port = hw->isac.a.io.port;
 789		hw->hscx.mode = hw->addr.mode;
 790		break;
 791	case INF_SCT_2:
 792		hw->ipac.type = IPAC_TYPE_IPAC;
 793		hw->ipac.isac.off = 0x80;
 794		hw->isac.a.io.ale = (u32)hw->addr.start + 0x08;
 795		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
 796		hw->isac.mode = hw->addr.mode;
 797		hw->hscx.a.io.ale = hw->isac.a.io.ale;
 798		hw->hscx.a.io.port = hw->isac.a.io.port;
 799		hw->hscx.mode = hw->addr.mode;
 800		break;
 801	case INF_SCT_3:
 802		hw->ipac.type = IPAC_TYPE_IPAC;
 803		hw->ipac.isac.off = 0x80;
 804		hw->isac.a.io.ale = (u32)hw->addr.start + 0x10;
 805		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
 806		hw->isac.mode = hw->addr.mode;
 807		hw->hscx.a.io.ale = hw->isac.a.io.ale;
 808		hw->hscx.a.io.port = hw->isac.a.io.port;
 809		hw->hscx.mode = hw->addr.mode;
 810		break;
 811	case INF_SCT_4:
 812		hw->ipac.type = IPAC_TYPE_IPAC;
 813		hw->ipac.isac.off = 0x80;
 814		hw->isac.a.io.ale = (u32)hw->addr.start + 0x20;
 815		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
 816		hw->isac.mode = hw->addr.mode;
 817		hw->hscx.a.io.ale = hw->isac.a.io.ale;
 818		hw->hscx.a.io.port = hw->isac.a.io.port;
 819		hw->hscx.mode = hw->addr.mode;
 820		break;
 821	case INF_GAZEL_R685:
 822		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
 823		hw->ipac.isac.off = 0x80;
 824		hw->isac.mode = hw->addr.mode;
 825		hw->isac.a.io.port = (u32)hw->addr.start;
 826		hw->hscx.mode = hw->addr.mode;
 827		hw->hscx.a.io.port = hw->isac.a.io.port;
 828		break;
 829	case INF_GAZEL_R753:
 830		hw->ipac.type = IPAC_TYPE_IPAC;
 831		hw->ipac.isac.off = 0x80;
 832		hw->isac.mode = hw->addr.mode;
 833		hw->isac.a.io.ale = (u32)hw->addr.start;
 834		hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT;
 835		hw->hscx.mode = hw->addr.mode;
 836		hw->hscx.a.io.ale = hw->isac.a.io.ale;
 837		hw->hscx.a.io.port = hw->isac.a.io.port;
 838		break;
 839	default:
 840		return -EINVAL;
 841	}
 842	switch (hw->isac.mode) {
 843	case AM_MEMIO:
 844		ASSIGN_FUNC_IPAC(MIO, hw->ipac);
 845		break;
 846	case AM_IND_IO:
 847		ASSIGN_FUNC_IPAC(IND, hw->ipac);
 848		break;
 849	case AM_IO:
 850		ASSIGN_FUNC_IPAC(IO, hw->ipac);
 851		break;
 852	default:
 853		return -EINVAL;
 854	}
 855	return 0;
 856}
 857
 858static void
 859release_card(struct inf_hw *card) {
 860	ulong	flags;
 861	int	i;
 862
 863	spin_lock_irqsave(&card->lock, flags);
 864	disable_hwirq(card);
 865	spin_unlock_irqrestore(&card->lock, flags);
 866	card->ipac.isac.release(&card->ipac.isac);
 867	free_irq(card->irq, card);
 868	mISDN_unregister_device(&card->ipac.isac.dch.dev);
 869	release_io(card);
 870	write_lock_irqsave(&card_lock, flags);
 871	list_del(&card->list);
 872	write_unlock_irqrestore(&card_lock, flags);
 873	switch (card->ci->typ) {
 874	case INF_SCT_2:
 875	case INF_SCT_3:
 876	case INF_SCT_4:
 877		break;
 878	case INF_SCT_1:
 879		for (i = 0; i < 3; i++) {
 880			if (card->sc[i])
 881				release_card(card->sc[i]);
 882			card->sc[i] = NULL;
 883		}
 884		fallthrough;
 885	default:
 886		pci_disable_device(card->pdev);
 887		pci_set_drvdata(card->pdev, NULL);
 888		break;
 889	}
 890	kfree(card);
 891	inf_cnt--;
 892}
 893
 894static int
 895setup_instance(struct inf_hw *card)
 896{
 897	int err;
 898	ulong flags;
 899
 900	snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name,
 901		 inf_cnt + 1);
 902	write_lock_irqsave(&card_lock, flags);
 903	list_add_tail(&card->list, &Cards);
 904	write_unlock_irqrestore(&card_lock, flags);
 905
 906	_set_debug(card);
 907	card->ipac.isac.name = card->name;
 908	card->ipac.name = card->name;
 909	card->ipac.owner = THIS_MODULE;
 910	spin_lock_init(&card->lock);
 911	card->ipac.isac.hwlock = &card->lock;
 912	card->ipac.hwlock = &card->lock;
 913	card->ipac.ctrl = (void *)&inf_ctrl;
 914
 915	err = setup_io(card);
 916	if (err)
 917		goto error_setup;
 918
 919	card->ipac.isac.dch.dev.Bprotocols =
 920		mISDNipac_init(&card->ipac, card);
 921
 922	if (card->ipac.isac.dch.dev.Bprotocols == 0)
 923		goto error_setup;
 924
 925	err = mISDN_register_device(&card->ipac.isac.dch.dev,
 926				    &card->pdev->dev, card->name);
 927	if (err)
 928		goto error;
 929
 930	err = init_irq(card);
 931	if (!err)  {
 932		inf_cnt++;
 933		pr_notice("Infineon %d cards installed\n", inf_cnt);
 934		return 0;
 935	}
 936	mISDN_unregister_device(&card->ipac.isac.dch.dev);
 937error:
 938	card->ipac.release(&card->ipac);
 939error_setup:
 940	release_io(card);
 941	write_lock_irqsave(&card_lock, flags);
 942	list_del(&card->list);
 943	write_unlock_irqrestore(&card_lock, flags);
 944	return err;
 945}
 946
 947static const struct inf_cinfo inf_card_info[] = {
 948	{
 949		INF_DIVA20,
 950		"Dialogic Diva 2.0",
 951		"diva20",
 952		AM_IND_IO, AM_NONE, 2, 0,
 953		&diva_irq
 954	},
 955	{
 956		INF_DIVA20U,
 957		"Dialogic Diva 2.0U",
 958		"diva20U",
 959		AM_IND_IO, AM_NONE, 2, 0,
 960		&diva_irq
 961	},
 962	{
 963		INF_DIVA201,
 964		"Dialogic Diva 2.01",
 965		"diva201",
 966		AM_MEMIO, AM_MEMIO, 0, 1,
 967		&diva20x_irq
 968	},
 969	{
 970		INF_DIVA202,
 971		"Dialogic Diva 2.02",
 972		"diva202",
 973		AM_MEMIO, AM_MEMIO, 0, 1,
 974		&diva20x_irq
 975	},
 976	{
 977		INF_SPEEDWIN,
 978		"Sedlbauer SpeedWin PCI",
 979		"speedwin",
 980		AM_IND_IO, AM_NONE, 0, 0,
 981		&tiger_irq
 982	},
 983	{
 984		INF_SAPHIR3,
 985		"HST Saphir 3",
 986		"saphir",
 987		AM_IND_IO, AM_NONE, 0, 0,
 988		&tiger_irq
 989	},
 990	{
 991		INF_QS1000,
 992		"Develo Microlink PCI",
 993		"qs1000",
 994		AM_IO, AM_IND_IO, 1, 3,
 995		&elsa_irq
 996	},
 997	{
 998		INF_QS3000,
 999		"Develo QuickStep 3000",
1000		"qs3000",
1001		AM_IO, AM_IND_IO, 1, 3,
1002		&elsa_irq
1003	},
1004	{
1005		INF_NICCY,
1006		"Sagem NICCY",
1007		"niccy",
1008		AM_IO, AM_IND_IO, 0, 1,
1009		&niccy_irq
1010	},
1011	{
1012		INF_SCT_1,
1013		"SciTel Quadro",
1014		"p1_scitel",
1015		AM_IO, AM_IND_IO, 1, 5,
1016		&ipac_irq
1017	},
1018	{
1019		INF_SCT_2,
1020		"SciTel Quadro",
1021		"p2_scitel",
1022		AM_NONE, AM_IND_IO, 0, 4,
1023		&ipac_irq
1024	},
1025	{
1026		INF_SCT_3,
1027		"SciTel Quadro",
1028		"p3_scitel",
1029		AM_NONE, AM_IND_IO, 0, 3,
1030		&ipac_irq
1031	},
1032	{
1033		INF_SCT_4,
1034		"SciTel Quadro",
1035		"p4_scitel",
1036		AM_NONE, AM_IND_IO, 0, 2,
1037		&ipac_irq
1038	},
1039	{
1040		INF_GAZEL_R685,
1041		"Gazel R685",
1042		"gazel685",
1043		AM_IO, AM_IO, 1, 2,
1044		&gazel_irq
1045	},
1046	{
1047		INF_GAZEL_R753,
1048		"Gazel R753",
1049		"gazel753",
1050		AM_IO, AM_IND_IO, 1, 2,
1051		&ipac_irq
1052	},
1053	{
1054		INF_NONE,
1055	}
1056};
1057
1058static const struct inf_cinfo *
1059get_card_info(enum inf_types typ)
1060{
1061	const struct inf_cinfo *ci = inf_card_info;
1062
1063	while (ci->typ != INF_NONE) {
1064		if (ci->typ == typ)
1065			return ci;
1066		ci++;
1067	}
1068	return NULL;
1069}
1070
1071static int
1072inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1073{
1074	int err = -ENOMEM;
1075	struct inf_hw *card;
1076
1077	card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1078	if (!card) {
1079		pr_info("No memory for Infineon ISDN card\n");
1080		return err;
1081	}
1082	card->pdev = pdev;
1083	err = pci_enable_device(pdev);
1084	if (err) {
1085		kfree(card);
1086		return err;
1087	}
1088	card->ci = get_card_info(ent->driver_data);
1089	if (!card->ci) {
1090		pr_info("mISDN: do not have information about adapter at %s\n",
1091			pci_name(pdev));
1092		kfree(card);
1093		pci_disable_device(pdev);
1094		return -EINVAL;
1095	} else
1096		pr_notice("mISDN: found adapter %s at %s\n",
1097			  card->ci->full, pci_name(pdev));
1098
1099	card->irq = pdev->irq;
1100	pci_set_drvdata(pdev, card);
1101	err = setup_instance(card);
1102	if (err) {
1103		pci_disable_device(pdev);
1104		kfree(card);
1105		pci_set_drvdata(pdev, NULL);
1106	} else if (ent->driver_data == INF_SCT_1) {
1107		int i;
1108		struct inf_hw *sc;
1109
1110		for (i = 1; i < 4; i++) {
1111			sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1112			if (!sc) {
1113				release_card(card);
1114				pci_disable_device(pdev);
1115				return -ENOMEM;
1116			}
1117			sc->irq = card->irq;
1118			sc->pdev = card->pdev;
1119			sc->ci = card->ci + i;
1120			err = setup_instance(sc);
1121			if (err) {
1122				pci_disable_device(pdev);
1123				kfree(sc);
1124				release_card(card);
1125				break;
1126			} else
1127				card->sc[i - 1] = sc;
1128		}
1129	}
1130	return err;
1131}
1132
1133static void
1134inf_remove(struct pci_dev *pdev)
1135{
1136	struct inf_hw	*card = pci_get_drvdata(pdev);
1137
1138	if (card)
1139		release_card(card);
1140	else
1141		pr_debug("%s: drvdata already removed\n", __func__);
1142}
1143
1144static struct pci_driver infineon_driver = {
1145	.name = "ISDN Infineon pci",
1146	.probe = inf_probe,
1147	.remove = inf_remove,
1148	.id_table = infineon_ids,
1149};
1150
1151static int __init
1152infineon_init(void)
1153{
1154	int err;
1155
1156	pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV);
1157	err = pci_register_driver(&infineon_driver);
1158	return err;
1159}
1160
1161static void __exit
1162infineon_cleanup(void)
1163{
1164	pci_unregister_driver(&infineon_driver);
1165}
1166
1167module_init(infineon_init);
1168module_exit(infineon_cleanup);
~/ Read-only file preview.