Hopefully get the Kconfig PCI stuff right, finally.
[linux-2.6/linux-mips.git] / drivers / isdn / hisax / gazel.c
blobaf60f332763785383b4abcfc8baa1874777a3aa1
1 /* $Id: gazel.c,v 2.11.6.7 2001/09/23 22:24:47 kai Exp $
3 * low level stuff for Gazel isdn cards
5 * Author BeWan Systems
6 * based on source code from Karsten Keil
7 * Copyright by BeWan Systems
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
14 #include <linux/config.h>
15 #include <linux/init.h>
16 #include "hisax.h"
17 #include "isac.h"
18 #include "hscx.h"
19 #include "isdnl1.h"
20 #include "ipac.h"
21 #include <linux/pci.h>
23 extern const char *CardType[];
24 const char *gazel_revision = "$Revision: 2.11.6.7 $";
25 static spinlock_t gazel_lock = SPIN_LOCK_UNLOCKED;
27 #define R647 1
28 #define R685 2
29 #define R753 3
30 #define R742 4
32 #define PLX_CNTRL 0x50 /* registre de controle PLX */
33 #define RESET_GAZEL 0x4
34 #define RESET_9050 0x40000000
35 #define PLX_INCSR 0x4C /* registre d'IT du 9050 */
36 #define INT_ISAC_EN 0x8 /* 1 = enable IT isac */
37 #define INT_ISAC 0x20 /* 1 = IT isac en cours */
38 #define INT_HSCX_EN 0x1 /* 1 = enable IT hscx */
39 #define INT_HSCX 0x4 /* 1 = IT hscx en cours */
40 #define INT_PCI_EN 0x40 /* 1 = enable IT PCI */
41 #define INT_IPAC_EN 0x3 /* enable IT ipac */
44 #define byteout(addr,val) outb(val,addr)
45 #define bytein(addr) inb(addr)
47 static inline u8
48 readreg(unsigned int adr, u_short off)
50 return bytein(adr + off);
53 static inline void
54 writereg(unsigned int adr, u_short off, u8 data)
56 byteout(adr + off, data);
60 static inline void
61 read_fifo(unsigned int adr, u8 * data, int size)
63 insb(adr, data, size);
66 static void
67 write_fifo(unsigned int adr, u8 * data, int size)
69 outsb(adr, data, size);
72 static u8
73 r685_isac_read(struct IsdnCardState *cs, u8 off)
75 return readreg(cs->hw.gazel.isac, off);
78 static u8
79 r647_isac_read(struct IsdnCardState *cs, u8 off)
81 return readreg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf));
84 static void
85 r685_isac_write(struct IsdnCardState *cs, u8 off, u8 value)
87 writereg(cs->hw.gazel.isac, off, value);
90 static void
91 r647_isac_write(struct IsdnCardState *cs, u8 off, u8 value)
93 writereg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf), value);
96 static void
97 isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
99 read_fifo(cs->hw.gazel.isacfifo, data, size);
102 static void
103 isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
105 write_fifo(cs->hw.gazel.isacfifo, data, size);
108 static struct dc_hw_ops r685_isac_ops = {
109 .read_reg = r685_isac_read,
110 .write_reg = r685_isac_write,
111 .read_fifo = isac_read_fifo,
112 .write_fifo = isac_write_fifo,
115 static struct dc_hw_ops r647_isac_ops = {
116 .read_reg = r647_isac_read,
117 .write_reg = r647_isac_write,
118 .read_fifo = isac_read_fifo,
119 .write_fifo = isac_write_fifo,
122 static u8
123 r685_hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
125 return readreg(cs->hw.gazel.hscx[hscx], off);
128 static u8
129 r647_hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
131 return readreg(cs->hw.gazel.hscx[hscx],
132 (off << 8 & 0xf000) | (off & 0xf));
135 static void
136 r685_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value)
138 writereg(cs->hw.gazel.hscx[hscx], off, value);
141 static void
142 r647_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value)
144 writereg(cs->hw.gazel.hscx[hscx],
145 (off << 8 & 0xf000) | (off & 0xf), value);
148 static void
149 hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
151 read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
154 static void
155 hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
157 write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
160 static struct bc_hw_ops r685_hscx_ops = {
161 .read_reg = r685_hscx_read,
162 .write_reg = r685_hscx_write,
163 .read_fifo = hscx_read_fifo,
164 .write_fifo = hscx_write_fifo,
167 static struct bc_hw_ops r647_hscx_ops = {
168 .read_reg = r647_hscx_read,
169 .write_reg = r647_hscx_write,
170 .read_fifo = hscx_read_fifo,
171 .write_fifo = hscx_write_fifo,
174 static inline u8
175 ipac_read(struct IsdnCardState *cs, u_short off)
177 register u8 ret;
178 unsigned long flags;
180 spin_lock_irqsave(&gazel_lock, flags);
181 byteout(cs->hw.gazel.ipac, off);
182 ret = bytein(cs->hw.gazel.ipac + 4);
183 spin_unlock_irqrestore(&gazel_lock, flags);
184 return ret;
187 static inline void
188 ipac_write(struct IsdnCardState *cs, u_short off, u8 data)
190 unsigned long flags;
192 spin_lock_irqsave(&gazel_lock, flags);
193 byteout(cs->hw.gazel.ipac, off);
194 byteout(cs->hw.gazel.ipac + 4, data);
195 spin_unlock_irqrestore(&gazel_lock, flags);
199 static inline void
200 ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
202 byteout(cs->hw.gazel.ipac, off);
203 insb(cs->hw.gazel.ipac + 4, data, size);
206 static inline void
207 ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
209 byteout(cs->hw.gazel.ipac, off);
210 outsb(cs->hw.gazel.ipac + 4, data, size);
213 /* This will generate ipac_dc_ops and ipac_bc_ops using the functions
214 * above */
216 BUILD_IPAC_OPS(ipac);
218 static int
219 r647_reset(struct IsdnCardState *cs)
221 writereg(cs->hw.gazel.cfg_reg, 0, 0);
222 HZDELAY(10);
223 writereg(cs->hw.gazel.cfg_reg, 0, 1);
224 HZDELAY(2);
225 return 0;
228 static int
229 r685_reset(struct IsdnCardState *cs)
231 unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
233 plxcntrl = inl(addr + PLX_CNTRL);
234 plxcntrl |= (RESET_9050 + RESET_GAZEL);
235 outl(plxcntrl, addr + PLX_CNTRL);
236 plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
237 HZDELAY(4);
238 outl(plxcntrl, addr + PLX_CNTRL);
239 HZDELAY(10);
240 outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
241 return 0;
244 static int
245 r753_reset(struct IsdnCardState *cs)
247 unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
249 if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags))
250 /* we can't read, assume the default */
251 plxcntrl = 0x18784db6;
252 else
253 plxcntrl = inl(addr + PLX_CNTRL);
254 plxcntrl |= (RESET_9050 + RESET_GAZEL);
255 outl(plxcntrl, addr + PLX_CNTRL);
256 ipac_write(cs, IPAC_POTA2, 0x20);
257 HZDELAY(4);
258 plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
259 outl(plxcntrl, addr + PLX_CNTRL);
260 HZDELAY(10);
261 ipac_write(cs, IPAC_POTA2, 0x00);
262 ipac_write(cs, IPAC_ACFG, 0xff);
263 ipac_write(cs, IPAC_AOE, 0x0);
264 ipac_write(cs, IPAC_MASK, 0xff);
265 ipac_write(cs, IPAC_CONF, 0x1);
266 outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR);
267 ipac_write(cs, IPAC_MASK, 0xc0);
268 return 0;
271 static int
272 r742_reset(struct IsdnCardState *cs)
274 ipac_write(cs, IPAC_POTA2, 0x20);
275 HZDELAY(4);
276 ipac_write(cs, IPAC_POTA2, 0x00);
277 ipac_write(cs, IPAC_ACFG, 0xff);
278 ipac_write(cs, IPAC_AOE, 0x0);
279 ipac_write(cs, IPAC_MASK, 0xff);
280 ipac_write(cs, IPAC_CONF, 0x1);
281 ipac_write(cs, IPAC_MASK, 0xc0);
282 return 0;
285 static void
286 gazel_init(struct IsdnCardState *cs)
288 int i;
290 for (i = 0; i < 2; i++) {
291 cs->bcs[i].hw.hscx.tsaxr0 = 0x1f;
292 cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
294 inithscxisac(cs);
297 static struct card_ops r647_ops = {
298 .init = gazel_init,
299 .reset = r647_reset,
300 .release = hisax_release_resources,
301 .irq_func = hscxisac_irq,
304 static struct card_ops r685_ops = {
305 .init = gazel_init,
306 .reset = r685_reset,
307 .release = hisax_release_resources,
308 .irq_func = hscxisac_irq,
311 static struct card_ops r742_ops = {
312 .init = ipac_init,
313 .reset = r742_reset,
314 .release = hisax_release_resources,
315 .irq_func = ipac_irq,
318 static struct card_ops r753_ops = {
319 .init = ipac_init,
320 .reset = r753_reset,
321 .release = hisax_release_resources,
322 .irq_func = ipac_irq,
325 static int __init
326 gazel647_probe(struct IsdnCardState *cs, struct IsdnCard *card)
328 int i, base;
330 cs->subtyp = R647;
331 cs->irq = card->para[0];
332 cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
334 printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
335 cs->dc.isac.adf2 = 0x87;
336 printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n",
337 cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
338 printk(KERN_INFO
339 "Gazel: hscx A:0x%X hscx B:0x%X\n",
340 cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
342 cs->hw.gazel.isac = card->para[1] + 0x8000;
343 cs->hw.gazel.hscx[0] = card->para[1];
344 cs->hw.gazel.hscx[1] = card->para[1] + 0x4000;
345 cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
346 cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
347 cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
349 base = cs->hw.gazel.hscx[0];
350 for (i = 0; i < 0xc000; i += 0x1000) {
351 if (!request_io(&cs->rs, base + i, 16, "gazel"))
352 goto err;
354 if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
355 goto err;
357 cs->card_ops = &r647_ops;
358 if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops))
359 goto err;
361 cs->card_ops->reset(cs);
362 return 0;
363 err:
364 hisax_release_resources(cs);
365 return -EBUSY;
368 static int __init
369 gazel742_probe(struct IsdnCardState *cs, struct IsdnCard *card)
371 cs->subtyp = R742;
372 cs->irq = card->para[0];
373 cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
375 printk(KERN_INFO "Gazel: Card ISA R742 found\n");
376 printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X\n",
377 cs->irq, cs->hw.gazel.ipac);
379 if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
380 goto err;
382 cs->card_ops = &r742_ops;
383 if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
384 goto err;
386 cs->card_ops->reset(cs);
387 return 0;
388 err:
389 hisax_release_resources(cs);
390 return -EBUSY;
393 static int __init
394 gazel685_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
396 if (pci_enable_device(pdev))
397 goto err;
399 cs->subtyp = R685;
400 cs->irq = pdev->irq;
401 cs->irq_flags |= SA_SHIRQ;
402 cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1);
403 cs->hw.gazel.isac = pci_resource_start(pdev, 2) + 0x80;
404 cs->hw.gazel.hscx[0] = pci_resource_start(pdev, 2);
405 cs->hw.gazel.hscx[1] = pci_resource_start(pdev, 2) + 0x40;
406 cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
407 cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
408 cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
409 cs->dc.isac.adf2 = 0x87;
411 if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
412 goto err;
413 if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
414 goto err;
416 printk(KERN_INFO "Gazel: Card PCI R685 found\n");
417 printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n",
418 cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
419 printk(KERN_INFO "Gazel: hscx A:0x%X hscx B:0x%X\n",
420 cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
422 cs->card_ops = &r685_ops;
423 if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops))
424 goto err;
426 cs->card_ops->reset(cs);
427 return 0;
428 err:
429 hisax_release_resources(cs);
430 return -EBUSY;
433 static int __init
434 gazel753_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
436 u8 pci_rev;
438 if (pci_enable_device(pdev))
439 goto err;
441 cs->subtyp = R753;
442 cs->irq = pdev->irq;
443 cs->irq_flags |= SA_SHIRQ;
444 cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1);
445 cs->hw.gazel.ipac = pci_resource_start(pdev, 2);
447 if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
448 goto err;
449 if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
450 goto err;
452 printk(KERN_INFO "Gazel: Card PCI R753 found\n");
453 printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n",
454 cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
456 * Erratum for PLX9050, revision 1:
457 * If bit 7 of BAR 0/1 is set, local config registers
458 * can not be read (write is okay)
460 if (cs->hw.gazel.cfg_reg & 0x80) {
461 pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
462 if (pci_rev == 1) {
463 printk(KERN_INFO "Gazel: PLX9050 rev1 workaround "
464 "activated\n");
465 __set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
468 cs->card_ops = &r753_ops;
469 if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
470 goto err;
472 cs->card_ops->reset(cs);
473 return 0;
474 err:
475 hisax_release_resources(cs);
476 return -EBUSY;
479 static struct pci_dev *dev_tel __initdata = NULL;
480 static u16 __initdata dev_id = PCI_DEVICE_ID_PLX_R685;
482 int __init
483 setup_gazel(struct IsdnCard *card)
485 char tmp[64];
487 strcpy(tmp, gazel_revision);
488 printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
490 if (card->para[0]) {
491 printk(KERN_INFO "Gazel: ISA card automatic recognition\n");
492 // we got an irq parameter, assume it is an ISA card
493 // R742 decodes address even in not started...
494 // R647 returns FF if not present or not started
495 // eventually needs improvment
496 card->cs->hw.gazel.ipac = card->para[1];
497 if (ipac_read(card->cs, IPAC_ID) == 1) {
498 if (gazel742_probe(card->cs, card))
499 return 0;
500 } else {
501 if (gazel647_probe(card->cs, card))
502 return 0;
504 return 1;
507 for (;;) {
508 dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, dev_id, dev_tel);
509 if (dev_tel) {
510 switch (dev_id) {
511 case PCI_DEVICE_ID_PLX_R685:
512 if (gazel685_probe(card->cs, dev_tel))
513 return 0;
514 return 1;
515 case PCI_DEVICE_ID_PLX_R753:
516 case PCI_DEVICE_ID_PLX_DJINN_ITOO:
517 if (gazel753_probe(card->cs, dev_tel))
518 return 0;
519 return 1;
522 switch (dev_id) {
523 case PCI_DEVICE_ID_PLX_R685:
524 dev_id = PCI_DEVICE_ID_PLX_R753;
525 case PCI_DEVICE_ID_PLX_R753:
526 dev_id = PCI_DEVICE_ID_PLX_DJINN_ITOO;
527 default:
528 break;
531 printk(KERN_WARNING "Gazel: No PCI card found\n");
532 return 0;