1 /* -*- linux-c -*- */
2 /*
3 * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 **/
11
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/pci.h>
15 #include <linux/stddef.h>
16 #include <linux/string.h>
17 #include <linux/sockios.h>
18 #include <asm/io.h>
19 #include <asm/byteorder.h>
20 #include <asm/pgtable.h>
21 #include <linux/skbuff.h>
22 #include <linux/if_arp.h>
23 #include <linux/fs.h>
24 #include <linux/sched.h>
25 #include <asm/uaccess.h>
26 #include <linux/version.h>
27 #include <linux/etherdevice.h>
28 #include "Reg9050.h"
29 #include "8253xctl.h"
30 #include "ring.h"
31 #include "8253x.h"
32 #include "crc32dcl.h"
33 #include "8253xmcs.h"
34 #include "sp502.h"
35
36 /* Just to guarantee that strings are null terminated */
37 #define MEMCPY(dest, src, cnt) \
38 { \
39 memcpy((dest), (src), (cnt)); \
40 (dest)[cnt] = 0; \
41 }
42
43 static unsigned char sp502progbyte[] =
44 {
45 SP502_OFF,
46 SP502_RS232,
47 SP502_RS422,
48 SP502_RS485,
49 SP502_RS449,
50 SP502_EIA530,
51 SP502_V35
52 };
53
54 /*
55 * The following routines are the multichannel server I2C serial EPROM routines.
56 */
57
58 /*
59 * Set the clock and the data lines of the SEP.
60 */
61 static void
mcs_sep_set(mcs_sep_t * msp,unsigned sdavalid,unsigned sda,unsigned sclvalid,unsigned scl)62 mcs_sep_set(mcs_sep_t *msp, unsigned sdavalid, unsigned sda,
63 unsigned sclvalid, unsigned scl)
64 {
65 #ifdef MAX
66 #undef MAX
67 #endif /* MAX */
68
69 #define MAX(x, y) ((x) > (y) ? (x) : (y))
70
71 unsigned char csr;
72 unsigned int sleeptime;
73
74 /*
75 * Ensure sufficient clock
76 */
77
78 sleeptime = 0;
79
80 if (sclvalid)
81 {
82 if (msp->s_scl && !scl)
83 { /* do we have a downgoing transition? */
84 sleeptime = MAX(1, sleeptime);
85 }
86 else if (!msp->s_scl && scl)
87 { /* upgoing */
88 sleeptime = MAX(2, sleeptime);
89 }
90 msp->s_scl = scl;
91 }
92
93 if (sdavalid)
94 {
95 if ((msp->s_sda && !sda) || (!msp->s_sda && sda))
96 {
97 sleeptime = MAX(1, sleeptime);
98 }
99
100 msp->s_sda = sda;
101 }
102
103 if (sleeptime > 0)
104 {
105 udelay(sleeptime);
106 }
107
108 /*
109 * Construct the CSR byte.
110 */
111 csr = 0;
112 if (msp->s_sda)
113 {
114 csr |= CIMCMD_CIMCSR_SDA;
115 }
116
117 if (msp->s_scl)
118 {
119 csr |= CIMCMD_CIMCSR_SCL;
120 }
121
122 writeb((unsigned char) csr, msp->s_wrptr);
123 }
124
125 static void
mcs_sep_start(mcs_sep_t * msp)126 mcs_sep_start(mcs_sep_t *msp)
127 {
128 /*
129 * Generate a START condition
130 */
131 mcs_sep_set(msp, TRUE, TRUE, TRUE, TRUE);
132 mcs_sep_set(msp, TRUE, FALSE, TRUE, TRUE);
133 }
134
135 static void
mcs_sep_stop(mcs_sep_t * msp)136 mcs_sep_stop(mcs_sep_t *msp)
137 {
138 /*
139 * Generate a STOP condition
140 */
141 mcs_sep_set(msp, TRUE, FALSE, TRUE, TRUE);
142 mcs_sep_set(msp, TRUE, TRUE, TRUE, TRUE);
143 }
144
145 /*
146 * Send out a single byte.
147 */
148 static void
mcs_sep_byte(mcs_sep_t * msp,unsigned char val)149 mcs_sep_byte(mcs_sep_t *msp, unsigned char val)
150 {
151 register int bitcount;
152
153 /* Clock may be high ... lower the clock */
154 mcs_sep_set(msp, TRUE, FALSE, TRUE, FALSE);
155
156 bitcount = 8;
157
158 while (TRUE)
159 {
160 mcs_sep_set(msp, TRUE, (val & 0x80) != 0, TRUE, FALSE);
161 mcs_sep_set(msp, TRUE, (val & 0x80) != 0, TRUE, TRUE);
162
163 bitcount--;
164 if (bitcount == 0)
165 {
166 break;
167 }
168 val <<= 1;
169 }
170
171 /* Clock is high ... lower the clock */
172 mcs_sep_set(msp, FALSE, FALSE, TRUE, FALSE);
173 }
174
175 /*
176 * Wait for an acknowledge cycle. Expects the clock to be low.
177 */
178 static unsigned
mcs_sep_waitsep(mcs_sep_t * msp)179 mcs_sep_waitsep(mcs_sep_t *msp)
180 {
181 int loopcount;
182 unsigned char cimcsr;
183
184 /* Stop driving SDA */
185 mcs_sep_set(msp, TRUE, TRUE, FALSE, FALSE);
186 /* Raise the clock */
187 mcs_sep_set(msp, FALSE, FALSE, TRUE, TRUE);
188
189 loopcount = 1000;
190 while (loopcount != 0)
191 {
192 cimcsr = readb(msp->s_rdptr);
193
194 if ((cimcsr & CIMCMD_CIMCSR_SDA) == 0)
195 {
196 break;
197 }
198 loopcount--;
199 }
200
201 /* Lower the clock */
202 mcs_sep_set(msp, FALSE, FALSE, TRUE, FALSE);
203
204 if (loopcount == 0)
205 {
206 return FALSE;
207 }
208 else
209 {
210 return TRUE;
211 }
212 }
213
214 /*
215 * Read the given CIM's SEP, starting at the given address, into
216 * the given buffer, for the given length.
217 *
218 * Returns -1 if there was a failure, otherwise the byte count.
219 */
220
221 static int
mcs_sep_read(mcs_sep_t * msp,unsigned short addr,unsigned char * buf,unsigned int nbytes)222 mcs_sep_read(mcs_sep_t *msp, unsigned short addr,
223 unsigned char *buf, unsigned int nbytes)
224 {
225 unsigned char cmdaddr, val, cimcsr;
226 unsigned int bytecount, bitcount;
227
228 mcs_sep_start(msp);
229
230 /*
231 * First, send out a dummy WRITE command with no data.
232 */
233
234 cmdaddr = 0xa0 | (((addr >> 8) & 0x7) << 1) | 0x0;
235
236 mcs_sep_byte(msp, cmdaddr);
237
238 if (!mcs_sep_waitsep(msp))
239 {
240 return -1;
241 }
242
243 /*
244 * Now, send the reset of the address.
245 */
246
247 mcs_sep_byte(msp, (unsigned char) addr);
248
249 if (!mcs_sep_waitsep(msp))
250 {
251 return -1;
252 }
253
254 /*
255 * Now, restart with a read command.
256 */
257
258 mcs_sep_start(msp);
259
260 cmdaddr = 0xa0 | (((addr >> 8) & 0x7) << 1) | 0x1;
261
262 mcs_sep_byte(msp, cmdaddr);
263
264 if (!mcs_sep_waitsep(msp))
265 {
266 return -1;
267 }
268
269 /*
270 * Now, start reading the bytes.
271 */
272 bytecount = 0;
273 while (TRUE)
274 {
275 bitcount = 8;
276 val = 0;
277 while (TRUE)
278 {
279 mcs_sep_set(msp, TRUE, TRUE, TRUE, TRUE);
280
281 cimcsr = readb(msp->s_rdptr);
282
283 if ((cimcsr & CIMCMD_CIMCSR_SDA) != 0)
284 {
285 val |= 0x01;
286 }
287
288 mcs_sep_set(msp, FALSE, FALSE, TRUE, FALSE);
289 bitcount--;
290
291 if (bitcount == 0)
292 {
293 break;
294 }
295 val <<= 1;
296 }
297
298 *buf++ = val;
299 bytecount++;
300 nbytes--;
301
302 if (nbytes == 0)
303 {
304 break;
305 }
306
307 /*
308 * Send the acknowledge.
309 */
310
311 mcs_sep_set(msp, FALSE, FALSE, TRUE, FALSE);
312 mcs_sep_set(msp, TRUE, FALSE, TRUE, TRUE);
313 mcs_sep_set(msp, FALSE, FALSE, TRUE, FALSE);
314 }
315
316 mcs_sep_stop(msp);
317
318 return (int) bytecount;
319 }
320
321
mcs_ciminit(SAB_BOARD * bptr,AURA_CIM * cim)322 unsigned int mcs_ciminit(SAB_BOARD *bptr, AURA_CIM *cim)
323 {
324 mcs_sep_t ms;
325
326 ms.s_rdptr = (unsigned char *)
327 (bptr->CIMCMD_REG + (CIMCMD_RDCIMCSR | (cim->ci_num << CIMCMD_CIMSHIFT)));
328 ms.s_wrptr = (unsigned char *)
329 (bptr->CIMCMD_REG + (CIMCMD_WRCIMCSR | (cim->ci_num << CIMCMD_CIMSHIFT)));
330 ms.s_scl = ms.s_sda = FALSE;
331
332 if (mcs_sep_read(&ms, (unsigned short) 0, &(cim->ci_sep[0]),
333 sizeof(cim->ci_sep)) != sizeof(cim->ci_sep)
334 || cim->ci_sep[MCS_SEP_MAGIC] != MCS_SEP_MAGICVAL)
335 {
336
337 if (cim->ci_sep[MCS_SEP_MAGIC] != MCS_SEP_MAGICVAL)
338 {
339 DEBUGPRINT((KERN_ALERT
340 "auraXX20: invalid CIM %d serial EPROM on board %d",
341 cim->ci_num, bptr->board_number));
342 }
343 else
344 {
345 DEBUGPRINT((KERN_ALERT
346 "auraXX20: error reading CIM %d serial EPROM on board %d",
347 cim->ci_num, bptr->board_number));
348 }
349
350 cim->ci_clkspeed = WANMCS_CLKSPEED;
351 cim->ci_clkspdsrc = -1;
352 cim->ci_spdgrd = 10;
353 cim->ci_spdgrdsrc = -1;
354 cim->ci_flags = 0;
355 cim->ci_rev[0] = '\0';
356 cim->ci_sn[0] = '\0';
357 cim->ci_mfgdate[0] = '\0';
358 cim->ci_mfgloc[0] = '\0';
359
360 /*
361 * Diddle the port setup registers to determine if this
362 * CIM was built up for RS232 or SP502.
363 */
364
365 writew((unsigned short) 0xffff, (unsigned short *)
366 (bptr->CIMCMD_REG +
367 (CIMCMD_WRSETUP | (cim->ci_num << CIMCMD_CIMSHIFT))));
368
369 #ifdef RICHARD_DELAY
370 udelay(1);
371 #endif /* RICHARD_DELAY */
372
373 if (readw((unsigned short *)
374 (bptr->CIMCMD_REG +
375 (CIMCMD_RDSETUP | (cim->ci_num << CIMCMD_CIMSHIFT)))) == 0xffff)
376 {
377
378 writew(0, (unsigned short *)
379 (bptr->CIMCMD_REG +
380 (CIMCMD_WRSETUP | (cim->ci_num << CIMCMD_CIMSHIFT))));
381
382 #ifdef RICHARD_DELAY
383 udelay(1);
384 #endif /* RICHARD_DELAY */
385
386 if (readw((unsigned short *)
387 (bptr->CIMCMD_REG +
388 (CIMCMD_RDSETUP | (cim->ci_num << CIMCMD_CIMSHIFT)))) == 0)
389 {
390
391 cim->ci_type = CIM_SP502;
392 }
393 else
394 {
395 cim->ci_type = CIM_RS232;
396 }
397 }
398 else
399 {
400 cim->ci_type = CIM_RS232;
401 }
402
403 if (cim->ci_type == CIM_SP502)
404 {
405 cim->ci_flags |= CIM_SYNC;
406 }
407 }
408 else
409 {
410 /*
411 * Pick through the serial EPROM contents and derive
412 * the values we need.
413 */
414 MEMCPY(&(cim->ci_rev[0]), &(cim->ci_sep[MCS_SEP_REV]),
415 MCS_SEP_REVLEN);
416 MEMCPY(&(cim->ci_sn[0]), &(cim->ci_sep[MCS_SEP_SN]),
417 MCS_SEP_SNLEN);
418 MEMCPY(&(cim->ci_mfgdate[0]), &(cim->ci_sep[MCS_SEP_MFGDATE]),
419 MCS_SEP_MFGDATELEN);
420 MEMCPY(&(cim->ci_mfgloc[0]), &(cim->ci_sep[MCS_SEP_MFGLOC]),
421 MCS_SEP_MFGLOCLEN);
422
423 cim->ci_clkspeed = (unsigned long) cim->ci_sep[MCS_SEP_CLKSPD]
424 | ((unsigned long) cim->ci_sep[MCS_SEP_CLKSPD + 1] << 8)
425 | ((unsigned long) cim->ci_sep[MCS_SEP_CLKSPD + 2] << 16)
426 | ((unsigned long) cim->ci_sep[MCS_SEP_CLKSPD + 3] << 24);
427
428 cim->ci_clkspdsrc = SEPROM;
429
430 cim->ci_spdgrd = (int) cim->ci_sep[MCS_SEP_SPDGRD];
431 cim->ci_spdgrdsrc = SEPROM;
432
433 cim->ci_flags = (unsigned long) cim->ci_sep[MCS_SEP_FLAGS];
434
435 cim->ci_type = (int) cim->ci_sep[MCS_SEP_TYPE];
436 }
437
438 /*
439 * Possibly initialize the port setup registers.
440 */
441
442 if (cim->ci_type == CIM_SP502)
443 {
444 unsigned short alloff;
445 #ifdef DEBUG_VERBOSE
446 unsigned short readback;
447 #endif
448 int offset;
449
450 /*
451 * Turn off all of the electrical interfaces. The
452 * hardware *should* initialize to this state, but the
453 * prototype, at least, does not. Note that this setting
454 * is reflected in the SIF_OFF setting of l_interface in
455 * mustard_lineinit, above.
456 */
457
458 alloff = (unsigned short) SP502_OFF
459 | ((unsigned short) SP502_OFF << 4)
460 | ((unsigned short) SP502_OFF << 8)
461 | ((unsigned short) SP502_OFF << 12);
462 for (offset = 0; offset < 8; offset++)
463 {
464 #ifdef DEBUG_VERBOSE
465 DEBUGPRINT((KERN_ALERT "cim %d setup reg #%d: writing 0x%x to 0x%x",
466 cim->ci_num, offset, (unsigned) alloff,
467 (CIMCMD_WRSETUP | (offset << 1) |
468 (cim->ci_num << CIMCMD_CIMSHIFT))));
469 #endif /* DEBUG_VERBOSE */
470
471 writew((unsigned short) alloff, (unsigned short *)
472 (bptr->CIMCMD_REG +
473 (CIMCMD_WRSETUP | (offset << 1) |
474 (cim->ci_num << CIMCMD_CIMSHIFT))));
475 #ifdef RICHARD_DELAY
476 udelay(1);
477 #endif /* RICHARD_DELAY */
478 #ifdef DEBUG_VERBOSE
479 readback = readw((unsigned short *)
480 (bptr->CIMCMD_REG +
481 (CIMCMD_RDSETUP | (offset << 1) |
482 (cim->ci_num << CIMCMD_CIMSHIFT))));
483 if (readback != alloff)
484 {
485 DEBUGPRINT((KERN_ALERT "cim %d setup reg #%d: readback (0x%x) should be 0x%x",
486 cim->ci_num, offset, readback, alloff));
487 }
488 #endif /* DEBUG_VERBOSE */
489 }
490 }
491
492 /*
493 * Clear out the CIM CSR with the exception of the LED.
494 */
495
496 writeb((unsigned char) 0,
497 (unsigned char *) (bptr->CIMCMD_REG +
498 (CIMCMD_WRCIMCSR | (cim->ci_num << CIMCMD_CIMSHIFT))));
499
500 return TRUE;
501 }
502
503
wanmcs_reset(SAB_BOARD * bptr)504 int wanmcs_reset(SAB_BOARD* bptr) /* note the board is the host card not the
505 * individual extension boards
506 */
507 {
508 int counter;
509
510 #if 0 /* from the ASE driver */
511 /*
512 * Program the AMCC to deactivate the write FIFO.
513 */
514
515 ASE_PUT32(cboard->b_bridgehandle,
516 (aseuint32_t *) (cboard->b_bridge + AMCC_PTCR),
517 ((aseuint32_t) (AMCC_PTMODE | AMCC_WRFIFODIS) << 24) |
518 ((aseuint32_t) (AMCC_PTMODE | AMCC_WRFIFODIS) << 16) |
519 ((aseuint32_t) (AMCC_PTMODE | AMCC_WRFIFODIS) << 8) |
520 (aseuint32_t) (AMCC_PTMODE | AMCC_WRFIFODIS));
521 #endif /* 0 */
522
523 /*
524 * First thing: do a reset of the local bus on the MIC
525 * by diddling the Add-On Reset bit in the RCR.
526 */
527
528 writel((unsigned int) AMCC_AORESET,
529 (unsigned int *)(bptr->AMCC_REG + AMCC_RCR));
530
531 udelay(10); /* wait for 10 us. */
532
533 writel((unsigned int) 0,
534 (unsigned int *)(bptr->AMCC_REG + AMCC_RCR));
535
536 udelay(10); /* wait for 10 us. */
537
538 /*
539 * Now the PCI bridge is reset. Try to establish
540 * a link through the Glink chipset.
541 */
542
543 for (counter = 1000; counter != 0; counter--)
544 {
545 writeb(0, (unsigned char*) (bptr->MICCMD_REG + MICCMD_MICCSR));
546
547 udelay(5);
548
549 if((readb((unsigned char*)
550 (bptr->MICCMD_REG + MICCMD_MICCSR)) & MICCMD_MICCSR_GLE) == 0)
551 {
552 break;
553 }
554 }
555
556 /*
557 * Did we run out of time?
558 */
559
560 if (counter == 0)
561 {
562 printk(KERN_ALERT
563 "AMCC5920: board %p: GLink did not reset -- is the MEB on?",
564 bptr);
565
566 return FALSE;
567 }
568
569 /*
570 * Now, hit the reset in the MEB.
571 */
572
573 writeb(0, (unsigned int *) (bptr->CIMCMD_REG + CIMCMD_RESETENA));
574
575 udelay(5);
576
577 writeb(0, (unsigned int *) (bptr->CIMCMD_REG + CIMCMD_RESETDIS));
578
579 /*
580 * And we're done!
581 */
582
583 return TRUE;
584 }
585
aura_sp502_program(SAB_PORT * port,register unsigned int sigindex)586 void aura_sp502_program(SAB_PORT *port, register unsigned int sigindex)
587 {
588 register unsigned char prognibble;
589 SAB_BOARD *bptr;
590 unsigned int cimnum;
591 unsigned int chipno;
592 unsigned int portno;
593 unsigned int rdaddressreceiver;
594 unsigned int rdaddresstransmitter;
595 unsigned int wraddressreceiver;
596 unsigned int wraddresstransmitter;
597 unsigned short datareceiver;
598 unsigned short datatransmitter;
599
600 bptr = port->board;
601 cimnum = port->chip->c_cim->ci_num;
602 chipno = (port->chip->c_chipno & 1); /* chip number relative to EB not MCS */
603 portno = (port->portno + (8 * chipno)); /* portno on a per EB basis */
604
605 prognibble = (sp502progbyte[sigindex] & 0x0F);
606
607 /* first 4 shorts contain receiver control bits */
608 rdaddressreceiver =
609 (((unsigned int)bptr->CIMCMD_REG) +
610 ((cimnum << CIMCMD_CIMSHIFT) | CIMCMD_RDSETUP | ((portno/4) << CIMCMD_CTRLSHIFT)));
611 /* second 4 shorts contain transmitter control bits */
612 rdaddresstransmitter =
613 (((unsigned int)bptr->CIMCMD_REG) +
614 ((cimnum << CIMCMD_CIMSHIFT) | CIMCMD_RDSETUP | ((4+(portno/4)) << CIMCMD_CTRLSHIFT)));
615
616 wraddressreceiver =
617 (((unsigned int)bptr->CIMCMD_REG) +
618 ((cimnum << CIMCMD_CIMSHIFT) | CIMCMD_WRSETUP | ((portno/4) << CIMCMD_CTRLSHIFT)));
619 wraddresstransmitter =
620 (((unsigned int)bptr->CIMCMD_REG) +
621 ((cimnum << CIMCMD_CIMSHIFT) | CIMCMD_WRSETUP | ((4+(portno/4)) << CIMCMD_CTRLSHIFT)));
622
623 /* read out the current receiver status */
624 datareceiver = readw((unsigned short*) rdaddressreceiver);
625 /* clear out nibble that corresponds to current port */
626 datareceiver &= (unsigned short) ~(0x0F << ((3 - (portno % 4)) * 4));
627 /* or in new receiver control field */
628 datareceiver |= (prognibble << ((3 - (portno % 4)) * 4));
629 /* write back the short that corresponds to 4 ports */
630 writew(datareceiver, (unsigned short*) wraddressreceiver);
631
632 /* just as above except that next 4 shorts correspond to transmitters */
633 datatransmitter = readw((unsigned short*) rdaddresstransmitter);
634 datatransmitter &= (unsigned short) ~(0x0F << ((3 - (portno % 4)) * 4));
635 datatransmitter |= (prognibble << ((3 - (portno % 4)) * 4));
636 writew(datatransmitter, (unsigned short*) wraddresstransmitter);
637 }
638