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