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