Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / isdn / hisax / saphir.c
1 /* $Id: saphir.c,v 1.10.2.4 2004/01/13 23:48:39 keil Exp $
2  *
3  * low level stuff for HST Saphir 1
4  *
5  * Author       Karsten Keil
6  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
7  *
8  * This software may be used and distributed according to the terms
9  * of the GNU General Public License, incorporated herein by reference.
10  *
11  * Thanks to    HST High Soft Tech GmbH
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
21 static char *saphir_rev = "$Revision: 1.10.2.4 $";
22
23 #define byteout(addr, val) outb(val, addr)
24 #define bytein(addr) inb(addr)
25
26 #define ISAC_DATA       0
27 #define HSCX_DATA       1
28 #define ADDRESS_REG     2
29 #define IRQ_REG         3
30 #define SPARE_REG       4
31 #define RESET_REG       5
32
33 static inline u_char
34 readreg(unsigned int ale, unsigned int adr, u_char off)
35 {
36         register u_char ret;
37
38         byteout(ale, off);
39         ret = bytein(adr);
40         return (ret);
41 }
42
43 static inline void
44 readfifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size)
45 {
46         byteout(ale, off);
47         insb(adr, data, size);
48 }
49
50
51 static inline void
52 writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
53 {
54         byteout(ale, off);
55         byteout(adr, data);
56 }
57
58 static inline void
59 writefifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size)
60 {
61         byteout(ale, off);
62         outsb(adr, data, size);
63 }
64
65 /* Interface functions */
66
67 static u_char
68 ReadISAC(struct IsdnCardState *cs, u_char offset)
69 {
70         return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset));
71 }
72
73 static void
74 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
75 {
76         writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value);
77 }
78
79 static void
80 ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
81 {
82         readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
83 }
84
85 static void
86 WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
87 {
88         writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
89 }
90
91 static u_char
92 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
93 {
94         return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
95                         offset + (hscx ? 0x40 : 0)));
96 }
97
98 static void
99 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
100 {
101         writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
102                  offset + (hscx ? 0x40 : 0), value);
103 }
104
105 #define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale,                \
106                                       cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0))
107 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale,        \
108                                               cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data)
109
110 #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale,      \
111                                                 cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
112
113 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale,    \
114                                                   cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
115
116 #include "hscx_irq.c"
117
118 static irqreturn_t
119 saphir_interrupt(int intno, void *dev_id)
120 {
121         struct IsdnCardState *cs = dev_id;
122         u_char val;
123         u_long flags;
124
125         spin_lock_irqsave(&cs->lock, flags);
126         val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
127 Start_HSCX:
128         if (val)
129                 hscx_int_main(cs, val);
130         val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
131 Start_ISAC:
132         if (val)
133                 isac_interrupt(cs, val);
134         val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
135         if (val) {
136                 if (cs->debug & L1_DEB_HSCX)
137                         debugl1(cs, "HSCX IntStat after IntRoutine");
138                 goto Start_HSCX;
139         }
140         val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
141         if (val) {
142                 if (cs->debug & L1_DEB_ISAC)
143                         debugl1(cs, "ISAC IntStat after IntRoutine");
144                 goto Start_ISAC;
145         }
146         /* Watchdog */
147         if (cs->hw.saphir.timer.function)
148                 mod_timer(&cs->hw.saphir.timer, jiffies + 1 * HZ);
149         else
150                 printk(KERN_WARNING "saphir: Spurious timer!\n");
151         writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF);
152         writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF);
153         writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF);
154         writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0);
155         writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0);
156         writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0);
157         spin_unlock_irqrestore(&cs->lock, flags);
158         return IRQ_HANDLED;
159 }
160
161 static void
162 SaphirWatchDog(struct IsdnCardState *cs)
163 {
164         u_long flags;
165
166         spin_lock_irqsave(&cs->lock, flags);
167         /* 5 sec WatchDog, so read at least every 4 sec */
168         cs->readisac(cs, ISAC_RBCH);
169         spin_unlock_irqrestore(&cs->lock, flags);
170         mod_timer(&cs->hw.saphir.timer, jiffies + 1 * HZ);
171 }
172
173 static void
174 release_io_saphir(struct IsdnCardState *cs)
175 {
176         byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
177         del_timer(&cs->hw.saphir.timer);
178         cs->hw.saphir.timer.function = NULL;
179         if (cs->hw.saphir.cfg_reg)
180                 release_region(cs->hw.saphir.cfg_reg, 6);
181 }
182
183 static int
184 saphir_reset(struct IsdnCardState *cs)
185 {
186         u_char irq_val;
187
188         switch (cs->irq) {
189         case 5: irq_val = 0;
190                 break;
191         case 3: irq_val = 1;
192                 break;
193         case 11:
194                 irq_val = 2;
195                 break;
196         case 12:
197                 irq_val = 3;
198                 break;
199         case 15:
200                 irq_val = 4;
201                 break;
202         default:
203                 printk(KERN_WARNING "HiSax: saphir wrong IRQ %d\n",
204                        cs->irq);
205                 return (1);
206         }
207         byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
208         byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1);
209         mdelay(10);
210         byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0);
211         mdelay(10);
212         byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
213         byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02);
214         return (0);
215 }
216
217 static int
218 saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
219 {
220         u_long flags;
221
222         switch (mt) {
223         case CARD_RESET:
224                 spin_lock_irqsave(&cs->lock, flags);
225                 saphir_reset(cs);
226                 spin_unlock_irqrestore(&cs->lock, flags);
227                 return (0);
228         case CARD_RELEASE:
229                 release_io_saphir(cs);
230                 return (0);
231         case CARD_INIT:
232                 spin_lock_irqsave(&cs->lock, flags);
233                 inithscxisac(cs, 3);
234                 spin_unlock_irqrestore(&cs->lock, flags);
235                 return (0);
236         case CARD_TEST:
237                 return (0);
238         }
239         return (0);
240 }
241
242
243 int setup_saphir(struct IsdnCard *card)
244 {
245         struct IsdnCardState *cs = card->cs;
246         char tmp[64];
247
248         strcpy(tmp, saphir_rev);
249         printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
250         if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
251                 return (0);
252
253         /* IO-Ports */
254         cs->hw.saphir.cfg_reg = card->para[1];
255         cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
256         cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
257         cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
258         cs->irq = card->para[0];
259         if (!request_region(cs->hw.saphir.cfg_reg, 6, "saphir")) {
260                 printk(KERN_WARNING
261                        "HiSax: HST Saphir config port %x-%x already in use\n",
262                        cs->hw.saphir.cfg_reg,
263                        cs->hw.saphir.cfg_reg + 5);
264                 return (0);
265         }
266
267         printk(KERN_INFO "HiSax: HST Saphir config irq:%d io:0x%X\n",
268                cs->irq, cs->hw.saphir.cfg_reg);
269
270         setup_isac(cs);
271         cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
272         cs->hw.saphir.timer.data = (long) cs;
273         init_timer(&cs->hw.saphir.timer);
274         cs->hw.saphir.timer.expires = jiffies + 4 * HZ;
275         add_timer(&cs->hw.saphir.timer);
276         if (saphir_reset(cs)) {
277                 release_io_saphir(cs);
278                 return (0);
279         }
280         cs->readisac = &ReadISAC;
281         cs->writeisac = &WriteISAC;
282         cs->readisacfifo = &ReadISACfifo;
283         cs->writeisacfifo = &WriteISACfifo;
284         cs->BC_Read_Reg = &ReadHSCX;
285         cs->BC_Write_Reg = &WriteHSCX;
286         cs->BC_Send_Data = &hscx_fill_fifo;
287         cs->cardmsg = &saphir_card_msg;
288         cs->irq_func = &saphir_interrupt;
289         ISACVersion(cs, "saphir:");
290         if (HscxVersion(cs, "saphir:")) {
291                 printk(KERN_WARNING
292                        "saphir: wrong HSCX versions check IO address\n");
293                 release_io_saphir(cs);
294                 return (0);
295         }
296         return (1);
297 }