1 /* $Id: telespci.c,v 2.23.2.3 2004/01/13 14:31:26 keil Exp $
3 * low level stuff for Teles PCI isdn cards
5 * Author Ton van Rosmalen
7 * Copyright by Ton van Rosmalen
8 * by Karsten Keil <keil@isdn4linux.de>
10 * This software may be used and distributed according to the terms
11 * of the GNU General Public License, incorporated herein by reference.
15 #include <linux/init.h>
16 #include <linux/config.h>
21 #include <linux/pci.h>
23 extern const char *CardType
[];
24 static const char *telespci_revision
= "$Revision: 2.23.2.3 $";
26 #define ZORAN_PO_RQ_PEN 0x02000000
27 #define ZORAN_PO_WR 0x00800000
28 #define ZORAN_PO_GID0 0x00000000
29 #define ZORAN_PO_GID1 0x00100000
30 #define ZORAN_PO_GREG0 0x00000000
31 #define ZORAN_PO_GREG1 0x00010000
32 #define ZORAN_PO_DMASK 0xFF
34 #define WRITE_ADDR_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0)
35 #define READ_DATA_ISAC (ZORAN_PO_GID0 | ZORAN_PO_GREG1)
36 #define WRITE_DATA_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1)
37 #define WRITE_ADDR_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG0)
38 #define READ_DATA_HSCX (ZORAN_PO_GID1 | ZORAN_PO_GREG1)
39 #define WRITE_DATA_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1)
41 #define ZORAN_WAIT_NOBUSY do { \
42 portdata = readl(adr + 0x200); \
43 } while (portdata & ZORAN_PO_RQ_PEN)
46 readisac(void __iomem
*adr
, u_char off
)
48 register unsigned int portdata
;
52 /* set address for ISAC */
53 writel(WRITE_ADDR_ISAC
| off
, adr
+ 0x200);
56 /* read data from ISAC */
57 writel(READ_DATA_ISAC
, adr
+ 0x200);
59 return((u_char
)(portdata
& ZORAN_PO_DMASK
));
63 writeisac(void __iomem
*adr
, u_char off
, u_char data
)
65 register unsigned int portdata
;
69 /* set address for ISAC */
70 writel(WRITE_ADDR_ISAC
| off
, adr
+ 0x200);
73 /* write data to ISAC */
74 writel(WRITE_DATA_ISAC
| data
, adr
+ 0x200);
79 readhscx(void __iomem
*adr
, int hscx
, u_char off
)
81 register unsigned int portdata
;
84 /* set address for HSCX */
85 writel(WRITE_ADDR_HSCX
| ((hscx
? 0x40:0) + off
), adr
+ 0x200);
88 /* read data from HSCX */
89 writel(READ_DATA_HSCX
, adr
+ 0x200);
91 return ((u_char
)(portdata
& ZORAN_PO_DMASK
));
95 writehscx(void __iomem
*adr
, int hscx
, u_char off
, u_char data
)
97 register unsigned int portdata
;
100 /* set address for HSCX */
101 writel(WRITE_ADDR_HSCX
| ((hscx
? 0x40:0) + off
), adr
+ 0x200);
104 /* write data to HSCX */
105 writel(WRITE_DATA_HSCX
| data
, adr
+ 0x200);
110 read_fifo_isac(void __iomem
*adr
, u_char
* data
, int size
)
112 register unsigned int portdata
;
116 /* read data from ISAC */
117 for (i
= 0; i
< size
; i
++) {
118 /* set address for ISAC fifo */
119 writel(WRITE_ADDR_ISAC
| 0x1E, adr
+ 0x200);
121 writel(READ_DATA_ISAC
, adr
+ 0x200);
123 data
[i
] = (u_char
)(portdata
& ZORAN_PO_DMASK
);
128 write_fifo_isac(void __iomem
*adr
, u_char
* data
, int size
)
130 register unsigned int portdata
;
134 /* write data to ISAC */
135 for (i
= 0; i
< size
; i
++) {
136 /* set address for ISAC fifo */
137 writel(WRITE_ADDR_ISAC
| 0x1E, adr
+ 0x200);
139 writel(WRITE_DATA_ISAC
| data
[i
], adr
+ 0x200);
145 read_fifo_hscx(void __iomem
*adr
, int hscx
, u_char
* data
, int size
)
147 register unsigned int portdata
;
151 /* read data from HSCX */
152 for (i
= 0; i
< size
; i
++) {
153 /* set address for HSCX fifo */
154 writel(WRITE_ADDR_HSCX
|(hscx
? 0x5F:0x1F), adr
+ 0x200);
156 writel(READ_DATA_HSCX
, adr
+ 0x200);
158 data
[i
] = (u_char
) (portdata
& ZORAN_PO_DMASK
);
163 write_fifo_hscx(void __iomem
*adr
, int hscx
, u_char
* data
, int size
)
165 unsigned int portdata
;
169 /* write data to HSCX */
170 for (i
= 0; i
< size
; i
++) {
171 /* set address for HSCX fifo */
172 writel(WRITE_ADDR_HSCX
|(hscx
? 0x5F:0x1F), adr
+ 0x200);
174 writel(WRITE_DATA_HSCX
| data
[i
], adr
+ 0x200);
180 /* Interface functions */
183 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
185 return (readisac(cs
->hw
.teles0
.membase
, offset
));
189 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
191 writeisac(cs
->hw
.teles0
.membase
, offset
, value
);
195 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
197 read_fifo_isac(cs
->hw
.teles0
.membase
, data
, size
);
201 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
203 write_fifo_isac(cs
->hw
.teles0
.membase
, data
, size
);
207 ReadHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
)
209 return (readhscx(cs
->hw
.teles0
.membase
, hscx
, offset
));
213 WriteHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
, u_char value
)
215 writehscx(cs
->hw
.teles0
.membase
, hscx
, offset
, value
);
219 * fast interrupt HSCX stuff goes here
222 #define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
223 #define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
224 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
225 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
227 #include "hscx_irq.c"
230 telespci_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
232 struct IsdnCardState
*cs
= dev_id
;
236 spin_lock_irqsave(&cs
->lock
, flags
);
237 hval
= readhscx(cs
->hw
.teles0
.membase
, 1, HSCX_ISTA
);
239 hscx_int_main(cs
, hval
);
240 ival
= readisac(cs
->hw
.teles0
.membase
, ISAC_ISTA
);
241 if ((hval
| ival
) == 0) {
242 spin_unlock_irqrestore(&cs
->lock
, flags
);
246 isac_interrupt(cs
, ival
);
247 /* Clear interrupt register for Zoran PCI controller */
248 writel(0x70000000, cs
->hw
.teles0
.membase
+ 0x3C);
250 writehscx(cs
->hw
.teles0
.membase
, 0, HSCX_MASK
, 0xFF);
251 writehscx(cs
->hw
.teles0
.membase
, 1, HSCX_MASK
, 0xFF);
252 writeisac(cs
->hw
.teles0
.membase
, ISAC_MASK
, 0xFF);
253 writeisac(cs
->hw
.teles0
.membase
, ISAC_MASK
, 0x0);
254 writehscx(cs
->hw
.teles0
.membase
, 0, HSCX_MASK
, 0x0);
255 writehscx(cs
->hw
.teles0
.membase
, 1, HSCX_MASK
, 0x0);
256 spin_unlock_irqrestore(&cs
->lock
, flags
);
261 release_io_telespci(struct IsdnCardState
*cs
)
263 iounmap(cs
->hw
.teles0
.membase
);
267 TelesPCI_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
275 release_io_telespci(cs
);
278 spin_lock_irqsave(&cs
->lock
, flags
);
280 spin_unlock_irqrestore(&cs
->lock
, flags
);
288 static struct pci_dev
*dev_tel __initdata
= NULL
;
291 setup_telespci(struct IsdnCard
*card
)
293 struct IsdnCardState
*cs
= card
->cs
;
297 #error "not running on big endian machines now"
299 strcpy(tmp
, telespci_revision
);
300 printk(KERN_INFO
"HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp
));
301 if (cs
->typ
!= ISDN_CTYPE_TELESPCI
)
304 if ((dev_tel
= pci_find_device (PCI_VENDOR_ID_ZORAN
, PCI_DEVICE_ID_ZORAN_36120
, dev_tel
))) {
305 if (pci_enable_device(dev_tel
))
307 cs
->irq
= dev_tel
->irq
;
309 printk(KERN_WARNING
"Teles: No IRQ for PCI card found\n");
312 cs
->hw
.teles0
.membase
= ioremap(pci_resource_start(dev_tel
, 0),
314 printk(KERN_INFO
"Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
315 pci_resource_start(dev_tel
, 0), dev_tel
->irq
);
317 printk(KERN_WARNING
"TelesPCI: No PCI card found\n");
321 printk(KERN_WARNING
"HiSax: Teles/PCI and NO_PCI_BIOS\n");
322 printk(KERN_WARNING
"HiSax: Teles/PCI unable to config\n");
324 #endif /* CONFIG_PCI */
326 /* Initialize Zoran PCI controller */
327 writel(0x00000000, cs
->hw
.teles0
.membase
+ 0x28);
328 writel(0x01000000, cs
->hw
.teles0
.membase
+ 0x28);
329 writel(0x01000000, cs
->hw
.teles0
.membase
+ 0x28);
330 writel(0x7BFFFFFF, cs
->hw
.teles0
.membase
+ 0x2C);
331 writel(0x70000000, cs
->hw
.teles0
.membase
+ 0x3C);
332 writel(0x61000000, cs
->hw
.teles0
.membase
+ 0x40);
333 /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
336 "HiSax: %s config irq:%d mem:%p\n",
337 CardType
[cs
->typ
], cs
->irq
,
338 cs
->hw
.teles0
.membase
);
341 cs
->readisac
= &ReadISAC
;
342 cs
->writeisac
= &WriteISAC
;
343 cs
->readisacfifo
= &ReadISACfifo
;
344 cs
->writeisacfifo
= &WriteISACfifo
;
345 cs
->BC_Read_Reg
= &ReadHSCX
;
346 cs
->BC_Write_Reg
= &WriteHSCX
;
347 cs
->BC_Send_Data
= &hscx_fill_fifo
;
348 cs
->cardmsg
= &TelesPCI_card_msg
;
349 cs
->irq_func
= &telespci_interrupt
;
350 cs
->irq_flags
|= SA_SHIRQ
;
351 ISACVersion(cs
, "TelesPCI:");
352 if (HscxVersion(cs
, "TelesPCI:")) {
354 "TelesPCI: wrong HSCX versions check IO/MEM addresses\n");
355 release_io_telespci(cs
);