1 /* $Id: telespci.c,v 2.23.2.3 2004/01/13 14:31:26 keil Exp $
2  *
3  * low level stuff for Teles PCI isdn cards
4  *
5  * Author       Ton van Rosmalen
6  *              Karsten Keil
7  * Copyright    by Ton van Rosmalen
8  *              by Karsten Keil      <keil@isdn4linux.de>
9  *
10  * This software may be used and distributed according to the terms
11  * of the GNU General Public License, incorporated herein by reference.
12  *
13  */
14 
15 #include <linux/init.h>
16 #include "hisax.h"
17 #include "isac.h"
18 #include "hscx.h"
19 #include "isdnl1.h"
20 #include <linux/pci.h>
21 
22 static const char *telespci_revision = "$Revision: 2.23.2.3 $";
23 
24 #define ZORAN_PO_RQ_PEN	0x02000000
25 #define ZORAN_PO_WR	0x00800000
26 #define ZORAN_PO_GID0	0x00000000
27 #define ZORAN_PO_GID1	0x00100000
28 #define ZORAN_PO_GREG0	0x00000000
29 #define ZORAN_PO_GREG1	0x00010000
30 #define ZORAN_PO_DMASK	0xFF
31 
32 #define WRITE_ADDR_ISAC	(ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0)
33 #define READ_DATA_ISAC	(ZORAN_PO_GID0 | ZORAN_PO_GREG1)
34 #define WRITE_DATA_ISAC	(ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1)
35 #define WRITE_ADDR_HSCX	(ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG0)
36 #define READ_DATA_HSCX	(ZORAN_PO_GID1 | ZORAN_PO_GREG1)
37 #define WRITE_DATA_HSCX	(ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1)
38 
39 #define ZORAN_WAIT_NOBUSY	do {		\
40 		portdata = readl(adr + 0x200);	\
41 	} while (portdata & ZORAN_PO_RQ_PEN)
42 
43 static inline u_char
readisac(void __iomem * adr,u_char off)44 readisac(void __iomem *adr, u_char off)
45 {
46 	register unsigned int portdata;
47 
48 	ZORAN_WAIT_NOBUSY;
49 
50 	/* set address for ISAC */
51 	writel(WRITE_ADDR_ISAC | off, adr + 0x200);
52 	ZORAN_WAIT_NOBUSY;
53 
54 	/* read data from ISAC */
55 	writel(READ_DATA_ISAC, adr + 0x200);
56 	ZORAN_WAIT_NOBUSY;
57 	return ((u_char)(portdata & ZORAN_PO_DMASK));
58 }
59 
60 static inline void
writeisac(void __iomem * adr,u_char off,u_char data)61 writeisac(void __iomem *adr, u_char off, u_char data)
62 {
63 	register unsigned int portdata;
64 
65 	ZORAN_WAIT_NOBUSY;
66 
67 	/* set address for ISAC */
68 	writel(WRITE_ADDR_ISAC | off, adr + 0x200);
69 	ZORAN_WAIT_NOBUSY;
70 
71 	/* write data to ISAC */
72 	writel(WRITE_DATA_ISAC | data, adr + 0x200);
73 	ZORAN_WAIT_NOBUSY;
74 }
75 
76 static inline u_char
readhscx(void __iomem * adr,int hscx,u_char off)77 readhscx(void __iomem *adr, int hscx, u_char off)
78 {
79 	register unsigned int portdata;
80 
81 	ZORAN_WAIT_NOBUSY;
82 	/* set address for HSCX */
83 	writel(WRITE_ADDR_HSCX | ((hscx ? 0x40 : 0) + off), adr + 0x200);
84 	ZORAN_WAIT_NOBUSY;
85 
86 	/* read data from HSCX */
87 	writel(READ_DATA_HSCX, adr + 0x200);
88 	ZORAN_WAIT_NOBUSY;
89 	return ((u_char)(portdata & ZORAN_PO_DMASK));
90 }
91 
92 static inline void
writehscx(void __iomem * adr,int hscx,u_char off,u_char data)93 writehscx(void __iomem *adr, int hscx, u_char off, u_char data)
94 {
95 	register unsigned int portdata;
96 
97 	ZORAN_WAIT_NOBUSY;
98 	/* set address for HSCX */
99 	writel(WRITE_ADDR_HSCX | ((hscx ? 0x40 : 0) + off), adr + 0x200);
100 	ZORAN_WAIT_NOBUSY;
101 
102 	/* write data to HSCX */
103 	writel(WRITE_DATA_HSCX | data, adr + 0x200);
104 	ZORAN_WAIT_NOBUSY;
105 }
106 
107 static inline void
read_fifo_isac(void __iomem * adr,u_char * data,int size)108 read_fifo_isac(void __iomem *adr, u_char *data, int size)
109 {
110 	register unsigned int portdata;
111 	register int i;
112 
113 	ZORAN_WAIT_NOBUSY;
114 	/* read data from ISAC */
115 	for (i = 0; i < size; i++) {
116 		/* set address for ISAC fifo */
117 		writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
118 		ZORAN_WAIT_NOBUSY;
119 		writel(READ_DATA_ISAC, adr + 0x200);
120 		ZORAN_WAIT_NOBUSY;
121 		data[i] = (u_char)(portdata & ZORAN_PO_DMASK);
122 	}
123 }
124 
125 static void
write_fifo_isac(void __iomem * adr,u_char * data,int size)126 write_fifo_isac(void __iomem *adr, u_char *data, int size)
127 {
128 	register unsigned int portdata;
129 	register int i;
130 
131 	ZORAN_WAIT_NOBUSY;
132 	/* write data to ISAC */
133 	for (i = 0; i < size; i++) {
134 		/* set address for ISAC fifo */
135 		writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
136 		ZORAN_WAIT_NOBUSY;
137 		writel(WRITE_DATA_ISAC | data[i], adr + 0x200);
138 		ZORAN_WAIT_NOBUSY;
139 	}
140 }
141 
142 static inline void
read_fifo_hscx(void __iomem * adr,int hscx,u_char * data,int size)143 read_fifo_hscx(void __iomem *adr, int hscx, u_char *data, int size)
144 {
145 	register unsigned int portdata;
146 	register int i;
147 
148 	ZORAN_WAIT_NOBUSY;
149 	/* read data from HSCX */
150 	for (i = 0; i < size; i++) {
151 		/* set address for HSCX fifo */
152 		writel(WRITE_ADDR_HSCX | (hscx ? 0x5F : 0x1F), adr + 0x200);
153 		ZORAN_WAIT_NOBUSY;
154 		writel(READ_DATA_HSCX, adr + 0x200);
155 		ZORAN_WAIT_NOBUSY;
156 		data[i] = (u_char) (portdata & ZORAN_PO_DMASK);
157 	}
158 }
159 
160 static inline void
write_fifo_hscx(void __iomem * adr,int hscx,u_char * data,int size)161 write_fifo_hscx(void __iomem *adr, int hscx, u_char *data, int size)
162 {
163 	unsigned int portdata;
164 	register int i;
165 
166 	ZORAN_WAIT_NOBUSY;
167 	/* write data to HSCX */
168 	for (i = 0; i < size; i++) {
169 		/* set address for HSCX fifo */
170 		writel(WRITE_ADDR_HSCX | (hscx ? 0x5F : 0x1F), adr + 0x200);
171 		ZORAN_WAIT_NOBUSY;
172 		writel(WRITE_DATA_HSCX | data[i], adr + 0x200);
173 		ZORAN_WAIT_NOBUSY;
174 		udelay(10);
175 	}
176 }
177 
178 /* Interface functions */
179 
180 static u_char
ReadISAC(struct IsdnCardState * cs,u_char offset)181 ReadISAC(struct IsdnCardState *cs, u_char offset)
182 {
183 	return (readisac(cs->hw.teles0.membase, offset));
184 }
185 
186 static void
WriteISAC(struct IsdnCardState * cs,u_char offset,u_char value)187 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
188 {
189 	writeisac(cs->hw.teles0.membase, offset, value);
190 }
191 
192 static void
ReadISACfifo(struct IsdnCardState * cs,u_char * data,int size)193 ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
194 {
195 	read_fifo_isac(cs->hw.teles0.membase, data, size);
196 }
197 
198 static void
WriteISACfifo(struct IsdnCardState * cs,u_char * data,int size)199 WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
200 {
201 	write_fifo_isac(cs->hw.teles0.membase, data, size);
202 }
203 
204 static u_char
ReadHSCX(struct IsdnCardState * cs,int hscx,u_char offset)205 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
206 {
207 	return (readhscx(cs->hw.teles0.membase, hscx, offset));
208 }
209 
210 static void
WriteHSCX(struct IsdnCardState * cs,int hscx,u_char offset,u_char value)211 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
212 {
213 	writehscx(cs->hw.teles0.membase, hscx, offset, value);
214 }
215 
216 /*
217  * fast interrupt HSCX stuff goes here
218  */
219 
220 #define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
221 #define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
222 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
223 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
224 
225 #include "hscx_irq.c"
226 
227 static irqreturn_t
telespci_interrupt(int intno,void * dev_id)228 telespci_interrupt(int intno, void *dev_id)
229 {
230 	struct IsdnCardState *cs = dev_id;
231 	u_char hval, ival;
232 	u_long flags;
233 
234 	spin_lock_irqsave(&cs->lock, flags);
235 	hval = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
236 	if (hval)
237 		hscx_int_main(cs, hval);
238 	ival = readisac(cs->hw.teles0.membase, ISAC_ISTA);
239 	if ((hval | ival) == 0) {
240 		spin_unlock_irqrestore(&cs->lock, flags);
241 		return IRQ_NONE;
242 	}
243 	if (ival)
244 		isac_interrupt(cs, ival);
245 	/* Clear interrupt register for Zoran PCI controller */
246 	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
247 
248 	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
249 	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
250 	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
251 	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
252 	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
253 	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
254 	spin_unlock_irqrestore(&cs->lock, flags);
255 	return IRQ_HANDLED;
256 }
257 
258 static void
release_io_telespci(struct IsdnCardState * cs)259 release_io_telespci(struct IsdnCardState *cs)
260 {
261 	iounmap(cs->hw.teles0.membase);
262 }
263 
264 static int
TelesPCI_card_msg(struct IsdnCardState * cs,int mt,void * arg)265 TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
266 {
267 	u_long flags;
268 
269 	switch (mt) {
270 	case CARD_RESET:
271 		return (0);
272 	case CARD_RELEASE:
273 		release_io_telespci(cs);
274 		return (0);
275 	case CARD_INIT:
276 		spin_lock_irqsave(&cs->lock, flags);
277 		inithscxisac(cs, 3);
278 		spin_unlock_irqrestore(&cs->lock, flags);
279 		return (0);
280 	case CARD_TEST:
281 		return (0);
282 	}
283 	return (0);
284 }
285 
286 static struct pci_dev *dev_tel __devinitdata = NULL;
287 
288 int __devinit
setup_telespci(struct IsdnCard * card)289 setup_telespci(struct IsdnCard *card)
290 {
291 	struct IsdnCardState *cs = card->cs;
292 	char tmp[64];
293 
294 #ifdef __BIG_ENDIAN
295 #error "not running on big endian machines now"
296 #endif
297 
298 	strcpy(tmp, telespci_revision);
299 	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
300 	if (cs->typ != ISDN_CTYPE_TELESPCI)
301 		return (0);
302 
303 	if ((dev_tel = hisax_find_pci_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
304 		if (pci_enable_device(dev_tel))
305 			return (0);
306 		cs->irq = dev_tel->irq;
307 		if (!cs->irq) {
308 			printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
309 			return (0);
310 		}
311 		cs->hw.teles0.membase = ioremap(pci_resource_start(dev_tel, 0),
312 						PAGE_SIZE);
313 		printk(KERN_INFO "Found: Zoran, base-address: 0x%llx, irq: 0x%x\n",
314 		       (unsigned long long)pci_resource_start(dev_tel, 0),
315 		       dev_tel->irq);
316 	} else {
317 		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
318 		return (0);
319 	}
320 
321 	/* Initialize Zoran PCI controller */
322 	writel(0x00000000, cs->hw.teles0.membase + 0x28);
323 	writel(0x01000000, cs->hw.teles0.membase + 0x28);
324 	writel(0x01000000, cs->hw.teles0.membase + 0x28);
325 	writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C);
326 	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
327 	writel(0x61000000, cs->hw.teles0.membase + 0x40);
328 	/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
329 
330 	printk(KERN_INFO
331 	       "HiSax: Teles PCI config irq:%d mem:%p\n",
332 	       cs->irq,
333 	       cs->hw.teles0.membase);
334 
335 	setup_isac(cs);
336 	cs->readisac = &ReadISAC;
337 	cs->writeisac = &WriteISAC;
338 	cs->readisacfifo = &ReadISACfifo;
339 	cs->writeisacfifo = &WriteISACfifo;
340 	cs->BC_Read_Reg = &ReadHSCX;
341 	cs->BC_Write_Reg = &WriteHSCX;
342 	cs->BC_Send_Data = &hscx_fill_fifo;
343 	cs->cardmsg = &TelesPCI_card_msg;
344 	cs->irq_func = &telespci_interrupt;
345 	cs->irq_flags |= IRQF_SHARED;
346 	ISACVersion(cs, "TelesPCI:");
347 	if (HscxVersion(cs, "TelesPCI:")) {
348 		printk(KERN_WARNING
349 		       "TelesPCI: wrong HSCX versions check IO/MEM addresses\n");
350 		release_io_telespci(cs);
351 		return (0);
352 	}
353 	return (1);
354 }
355