~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/isdn/hisax/telespci.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
181
ReadISAC(struct IsdnCardState *cs, u_char offset)
 
182
{
 
183
        return (readisac(cs->hw.teles0.membase, offset));
 
184
}
 
185
 
 
186
static void
 
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
 
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
 
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
 
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
 
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
 
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
 
259
release_io_telespci(struct IsdnCardState *cs)
 
260
{
 
261
        iounmap(cs->hw.teles0.membase);
 
262
}
 
263
 
 
264
static int
 
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
 
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
}