Merge Christoph's freeze cleanup patch
[linux-2.6] / drivers / isdn / hardware / eicon / s_4bri.c
1
2 /*
3  *
4   Copyright (c) Eicon Networks, 2002.
5  *
6   This source file is supplied for the use with
7   Eicon Networks range of DIVA Server Adapters.
8  *
9   Eicon File Revision :    2.1
10  *
11   This program is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 2, or (at your option)
14   any later version.
15  *
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19   See the GNU General Public License for more details.
20  *
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26 #include "platform.h"
27 #include "di_defs.h"
28 #include "pc.h"
29 #include "pr_pc.h"
30 #include "di.h"
31 #include "mi_pc.h"
32 #include "pc_maint.h"
33 #include "divasync.h"
34 #include "pc_init.h"
35 #include "io.h"
36 #include "helpers.h"
37 #include "dsrv4bri.h"
38 #include "dsp_defs.h"
39 #include "sdp_hdr.h"
40
41 /*****************************************************************************/
42 #define MAX_XLOG_SIZE   (64 * 1024)
43
44 /* --------------------------------------------------------------------------
45                 Recovery XLOG from QBRI Card
46          -------------------------------------------------------------------------- */
47 static void qBri_cpu_trapped (PISDN_ADAPTER IoAdapter) {
48         byte  __iomem *base ;
49         word *Xlog ;
50         dword   regs[4], TrapID, offset, size ;
51         Xdesc   xlogDesc ;
52         int factor = (IoAdapter->tasks == 1) ? 1 : 2;
53
54 /*
55  *      check for trapped MIPS 46xx CPU, dump exception frame
56  */
57
58         base = DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter);
59         offset = IoAdapter->ControllerNumber * (IoAdapter->MemorySize >> factor) ;
60
61         TrapID = READ_DWORD(&base[0x80]) ;
62
63         if ( (TrapID == 0x99999999) || (TrapID == 0x99999901) )
64         {
65                 dump_trap_frame (IoAdapter, &base[0x90]) ;
66                 IoAdapter->trapped = 1 ;
67         }
68
69         regs[0] = READ_DWORD((base + offset) + 0x70);
70         regs[1] = READ_DWORD((base + offset) + 0x74);
71         regs[2] = READ_DWORD((base + offset) + 0x78);
72         regs[3] = READ_DWORD((base + offset) + 0x7c);
73         regs[0] &= IoAdapter->MemorySize - 1 ;
74
75         if ( (regs[0] >= offset)
76           && (regs[0] < offset + (IoAdapter->MemorySize >> factor) - 1) )
77         {
78                 if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) {
79                         DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
80                         return ;
81                 }
82
83                 size = offset + (IoAdapter->MemorySize >> factor) - regs[0] ;
84                 if ( size > MAX_XLOG_SIZE )
85                         size = MAX_XLOG_SIZE ;
86                 memcpy_fromio (Xlog, &base[regs[0]], size) ;
87                 xlogDesc.buf = Xlog ;
88                 xlogDesc.cnt = READ_WORD(&base[regs[1] & (IoAdapter->MemorySize - 1)]) ;
89                 xlogDesc.out = READ_WORD(&base[regs[2] & (IoAdapter->MemorySize - 1)]) ;
90                 dump_xlog_buffer (IoAdapter, &xlogDesc) ;
91                 diva_os_free (0, Xlog) ;
92                 IoAdapter->trapped = 2 ;
93         }
94         DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
95 }
96
97 /* --------------------------------------------------------------------------
98                 Reset QBRI Hardware
99          -------------------------------------------------------------------------- */
100 static void reset_qBri_hardware (PISDN_ADAPTER IoAdapter) {
101         word volatile __iomem *qBriReset ;
102         byte  volatile __iomem *qBriCntrl ;
103         byte  volatile __iomem *p ;
104
105         qBriReset = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
106         WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_SOFT_RESET) ;
107         diva_os_wait (1) ;
108         WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_SOFT_RESET) ;
109         diva_os_wait (1);
110         WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_RELOAD_EEPROM) ;
111         diva_os_wait (1) ;
112         WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_RELOAD_EEPROM) ;
113         diva_os_wait (1);
114         DIVA_OS_MEM_DETACH_PROM(IoAdapter, qBriReset);
115
116         qBriCntrl = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
117         p = &qBriCntrl[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
118         WRITE_DWORD(p, 0) ;
119         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, qBriCntrl);
120
121         DBG_TRC(("resetted board @ reset addr 0x%08lx", qBriReset))
122         DBG_TRC(("resetted board @ cntrl addr 0x%08lx", p))
123 }
124
125 /* --------------------------------------------------------------------------
126                 Start Card CPU
127          -------------------------------------------------------------------------- */
128 void start_qBri_hardware (PISDN_ADAPTER IoAdapter) {
129         byte volatile __iomem *qBriReset ;
130         byte volatile __iomem *p ;
131
132         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
133         qBriReset = &p[(DIVA_4BRI_REVISION(IoAdapter)) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
134         WRITE_DWORD(qBriReset, MQ_RISC_COLD_RESET_MASK) ;
135         diva_os_wait (2) ;
136         WRITE_DWORD(qBriReset, MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK) ;
137         diva_os_wait (10) ;
138         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
139
140         DBG_TRC(("started processor @ addr 0x%08lx", qBriReset))
141 }
142
143 /* --------------------------------------------------------------------------
144                 Stop Card CPU
145          -------------------------------------------------------------------------- */
146 static void stop_qBri_hardware (PISDN_ADAPTER IoAdapter) {
147         byte volatile __iomem *p ;
148         dword volatile __iomem *qBriReset ;
149         dword volatile __iomem *qBriIrq ;
150         dword volatile __iomem *qBriIsacDspReset ;
151         int rev2 = DIVA_4BRI_REVISION(IoAdapter);
152         int reset_offset = rev2 ? (MQ2_BREG_RISC)      : (MQ_BREG_RISC);
153         int irq_offset   = rev2 ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST);
154         int hw_offset    = rev2 ? (MQ2_ISAC_DSP_RESET) : (MQ_ISAC_DSP_RESET);
155
156         if ( IoAdapter->ControllerNumber > 0 )
157                 return ;
158         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
159         qBriReset = (dword volatile __iomem *)&p[reset_offset];
160         qBriIsacDspReset = (dword volatile __iomem *)&p[hw_offset];
161 /*
162  *      clear interrupt line (reset Local Interrupt Test Register)
163  */
164         WRITE_DWORD(qBriReset, 0) ;
165         WRITE_DWORD(qBriIsacDspReset, 0) ;
166         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
167         
168         p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
169         WRITE_BYTE(&p[PLX9054_INTCSR], 0x00);   /* disable PCI interrupts */
170         DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
171         
172         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
173         qBriIrq   = (dword volatile __iomem *)&p[irq_offset];
174         WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
175         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
176
177         DBG_TRC(("stopped processor @ addr 0x%08lx", qBriReset))
178
179 }
180
181 /* --------------------------------------------------------------------------
182                 FPGA download
183          -------------------------------------------------------------------------- */
184 #define FPGA_NAME_OFFSET         0x10
185
186 static byte * qBri_check_FPGAsrc (PISDN_ADAPTER IoAdapter, char *FileName,
187                                   dword *Length, dword *code) {
188         byte *File ;
189         char  *fpgaFile, *fpgaType, *fpgaDate, *fpgaTime ;
190         dword  fpgaFlen,  fpgaTlen,  fpgaDlen, cnt, year, i ;
191
192         if (!(File = (byte *)xdiLoadFile (FileName, Length, 0))) {
193                 return (NULL) ;
194         }
195 /*
196  *       scan file until FF and put id string into buffer
197  */
198         for ( i = 0 ; File[i] != 0xff ; )
199         {
200                 if ( ++i >= *Length )
201                 {
202                         DBG_FTL(("FPGA download: start of data header not found"))
203                         xdiFreeFile (File) ;
204                         return (NULL) ;
205                 }
206         }
207         *code = i++ ;
208
209         if ( (File[i] & 0xF0) != 0x20 )
210         {
211                 DBG_FTL(("FPGA download: data header corrupted"))
212                 xdiFreeFile (File) ;
213                 return (NULL) ;
214         }
215         fpgaFlen = (dword)  File[FPGA_NAME_OFFSET - 1] ;
216         if ( fpgaFlen == 0 )
217                 fpgaFlen = 12 ;
218         fpgaFile = (char *)&File[FPGA_NAME_OFFSET] ;
219         fpgaTlen = (dword)  fpgaFile[fpgaFlen + 2] ;
220         if ( fpgaTlen == 0 )
221                 fpgaTlen = 10 ;
222         fpgaType = (char *)&fpgaFile[fpgaFlen + 3] ;
223         fpgaDlen = (dword)  fpgaType[fpgaTlen + 2] ;
224         if ( fpgaDlen == 0 )
225                 fpgaDlen = 11 ;
226         fpgaDate = (char *)&fpgaType[fpgaTlen + 3] ;
227         fpgaTime = (char *)&fpgaDate[fpgaDlen + 3] ;
228         cnt = (dword)(((File[  i  ] & 0x0F) << 20) + (File[i + 1] << 12)
229                      + (File[i + 2]         <<  4) + (File[i + 3] >>  4)) ;
230
231         if ( (dword)(i + (cnt / 8)) > *Length )
232         {
233                 DBG_FTL(("FPGA download: '%s' file too small (%ld < %ld)",
234                          FileName, *Length, code + ((cnt + 7) / 8) ))
235                 xdiFreeFile (File) ;
236                 return (NULL) ;
237         }
238         i = 0 ;
239         do
240         {
241                 while ( (fpgaDate[i] != '\0')
242                      && ((fpgaDate[i] < '0') || (fpgaDate[i] > '9')) )
243                 {
244                         i++;
245                 }
246                 year = 0 ;
247                 while ( (fpgaDate[i] >= '0') && (fpgaDate[i] <= '9') )
248                         year = year * 10 + (fpgaDate[i++] - '0') ;
249         } while ( (year < 2000) && (fpgaDate[i] != '\0') );
250
251         switch (IoAdapter->cardType) {
252                 case CARDTYPE_DIVASRV_B_2F_PCI:
253                         break;
254
255                 default:
256             if ( year >= 2001 ) {
257                                 IoAdapter->fpga_features |= PCINIT_FPGA_PLX_ACCESS_SUPPORTED ;
258                         }
259         }
260
261         DBG_LOG(("FPGA[%s] file %s (%s %s) len %d",
262                  fpgaType, fpgaFile, fpgaDate, fpgaTime, cnt))
263         return (File) ;
264 }
265
266 /******************************************************************************/
267
268 #define FPGA_PROG   0x0001              /* PROG enable low */
269 #define FPGA_BUSY   0x0002              /* BUSY high, DONE low */
270 #define FPGA_CS     0x000C              /* Enable I/O pins */
271 #define FPGA_CCLK   0x0100
272 #define FPGA_DOUT   0x0400
273 #define FPGA_DIN    FPGA_DOUT   /* bidirectional I/O */
274
275 int qBri_FPGA_download (PISDN_ADAPTER IoAdapter) {
276         int            bit ;
277         byte           *File ;
278         dword          code, FileLength ;
279         word volatile __iomem *addr = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
280         word           val, baseval = FPGA_CS | FPGA_PROG ;
281
282
283
284         if (DIVA_4BRI_REVISION(IoAdapter))
285         {
286                 char* name;
287
288                 switch (IoAdapter->cardType) {
289                         case CARDTYPE_DIVASRV_B_2F_PCI:
290                                 name = "dsbri2f.bit";
291                                 break;
292
293                         case CARDTYPE_DIVASRV_B_2M_V2_PCI:
294                         case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
295                                 name = "dsbri2m.bit";
296                                 break;
297
298                         default:
299                                 name = "ds4bri2.bit";
300                 }
301
302                 File = qBri_check_FPGAsrc (IoAdapter, name,
303                                                 &FileLength, &code);
304         }
305         else
306         {
307                 File = qBri_check_FPGAsrc (IoAdapter, "ds4bri.bit",
308                                            &FileLength, &code) ;
309         }
310         if ( !File ) {
311                 DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
312                 return (0) ;
313         }
314 /*
315  *      prepare download, pulse PROGRAM pin down.
316  */
317         WRITE_WORD(addr, baseval & ~FPGA_PROG) ; /* PROGRAM low pulse */
318         WRITE_WORD(addr, baseval) ;              /* release */
319         diva_os_wait (50) ;  /* wait until FPGA finished internal memory clear */
320 /*
321  *      check done pin, must be low
322  */
323         if ( READ_WORD(addr) & FPGA_BUSY )
324         {
325                 DBG_FTL(("FPGA download: acknowledge for FPGA memory clear missing"))
326                 xdiFreeFile (File) ;
327                 DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
328                 return (0) ;
329         }
330 /*
331  *      put data onto the FPGA
332  */
333         while ( code < FileLength )
334         {
335                 val = ((word)File[code++]) << 3 ;
336
337                 for ( bit = 8 ; bit-- > 0 ; val <<= 1 ) /* put byte onto FPGA */
338                 {
339                         baseval &= ~FPGA_DOUT ;             /* clr  data bit */
340                         baseval |= (val & FPGA_DOUT) ;      /* copy data bit */
341                         WRITE_WORD(addr, baseval) ;
342                         WRITE_WORD(addr, baseval | FPGA_CCLK) ;     /* set CCLK hi */
343                         WRITE_WORD(addr, baseval | FPGA_CCLK) ;     /* set CCLK hi */
344                         WRITE_WORD(addr, baseval) ;                 /* set CCLK lo */
345                 }
346         }
347         xdiFreeFile (File) ;
348         diva_os_wait (100) ;
349         val = READ_WORD(addr) ;
350
351         DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
352
353         if ( !(val & FPGA_BUSY) )
354         {
355                 DBG_FTL(("FPGA download: chip remains in busy state (0x%04x)", val))
356                 return (0) ;
357         }
358
359         return (1) ;
360 }
361
362 static int load_qBri_hardware (PISDN_ADAPTER IoAdapter) {
363         return (0);
364 }
365
366 /* --------------------------------------------------------------------------
367                 Card ISR
368          -------------------------------------------------------------------------- */
369 static int qBri_ISR (struct _ISDN_ADAPTER* IoAdapter) {
370         dword volatile     __iomem *qBriIrq ;
371
372         PADAPTER_LIST_ENTRY QuadroList = IoAdapter->QuadroList ;
373
374         word                    i ;
375         int                     serviced = 0 ;
376         byte __iomem *p;
377
378         p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
379
380         if ( !(READ_BYTE(&p[PLX9054_INTCSR]) & 0x80) ) {
381                 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
382                 return (0) ;
383         }
384         DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
385
386 /*
387  *      clear interrupt line (reset Local Interrupt Test Register)
388  */
389         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
390         qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST)]);
391         WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
392         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
393
394         for ( i = 0 ; i < IoAdapter->tasks; ++i )
395         {
396                 IoAdapter = QuadroList->QuadroAdapter[i] ;
397
398                 if ( IoAdapter && IoAdapter->Initialized
399                   && IoAdapter->tst_irq (&IoAdapter->a) )
400                 {
401                         IoAdapter->IrqCount++ ;
402                         serviced = 1 ;
403                         diva_os_schedule_soft_isr (&IoAdapter->isr_soft_isr);
404                 }
405         }
406
407         return (serviced) ;
408 }
409
410 /* --------------------------------------------------------------------------
411                 Does disable the interrupt on the card
412          -------------------------------------------------------------------------- */
413 static void disable_qBri_interrupt (PISDN_ADAPTER IoAdapter) {
414         dword volatile __iomem *qBriIrq ;
415         byte __iomem *p;
416
417         if ( IoAdapter->ControllerNumber > 0 )
418                 return ;
419 /*
420  *      clear interrupt line (reset Local Interrupt Test Register)
421  */
422         p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
423         WRITE_BYTE(&p[PLX9054_INTCSR], 0x00);   /* disable PCI interrupts */
424         DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
425
426         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
427         qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST)]);
428         WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
429         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
430 }
431
432 /* --------------------------------------------------------------------------
433                 Install Adapter Entry Points
434          -------------------------------------------------------------------------- */
435 static void set_common_qBri_functions (PISDN_ADAPTER IoAdapter) {
436         ADAPTER *a;
437
438         a = &IoAdapter->a ;
439
440         a->ram_in           = mem_in ;
441         a->ram_inw          = mem_inw ;
442         a->ram_in_buffer    = mem_in_buffer ;
443         a->ram_look_ahead   = mem_look_ahead ;
444         a->ram_out          = mem_out ;
445         a->ram_outw         = mem_outw ;
446         a->ram_out_buffer   = mem_out_buffer ;
447         a->ram_inc          = mem_inc ;
448
449         IoAdapter->out      = pr_out ;
450         IoAdapter->dpc      = pr_dpc ;
451         IoAdapter->tst_irq  = scom_test_int ;
452         IoAdapter->clr_irq  = scom_clear_int ;
453         IoAdapter->pcm      = (struct pc_maint *)MIPS_MAINT_OFFS ;
454
455         IoAdapter->load     = load_qBri_hardware ;
456
457         IoAdapter->disIrq   = disable_qBri_interrupt ;
458         IoAdapter->rstFnc   = reset_qBri_hardware ;
459         IoAdapter->stop     = stop_qBri_hardware ;
460         IoAdapter->trapFnc  = qBri_cpu_trapped ;
461
462         IoAdapter->diva_isr_handler = qBri_ISR;
463
464         IoAdapter->a.io       = (void*)IoAdapter ;
465 }
466
467 static void set_qBri_functions (PISDN_ADAPTER IoAdapter) {
468         if (!IoAdapter->tasks) {
469                 IoAdapter->tasks = MQ_INSTANCE_COUNT;
470         }
471         IoAdapter->MemorySize = MQ_MEMORY_SIZE ;
472         set_common_qBri_functions (IoAdapter) ;
473         diva_os_set_qBri_functions (IoAdapter) ;
474 }
475
476 static void set_qBri2_functions (PISDN_ADAPTER IoAdapter) {
477         if (!IoAdapter->tasks) {
478                 IoAdapter->tasks = MQ_INSTANCE_COUNT;
479         }
480         IoAdapter->MemorySize = (IoAdapter->tasks == 1) ? BRI2_MEMORY_SIZE : MQ2_MEMORY_SIZE;
481         set_common_qBri_functions (IoAdapter) ;
482         diva_os_set_qBri2_functions (IoAdapter) ;
483 }
484
485 /******************************************************************************/
486
487 void prepare_qBri_functions (PISDN_ADAPTER IoAdapter) {
488
489         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[0]) ;
490         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[1]) ;
491         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[2]) ;
492         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[3]) ;
493
494 }
495
496 void prepare_qBri2_functions (PISDN_ADAPTER IoAdapter) {
497         if (!IoAdapter->tasks) {
498                 IoAdapter->tasks = MQ_INSTANCE_COUNT;
499         }
500
501         set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[0]) ;
502         if (IoAdapter->tasks > 1) {
503                 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[1]) ;
504                 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[2]) ;
505                 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[3]) ;
506         }
507
508 }
509
510 /* -------------------------------------------------------------------------- */