0229f53f5586764cf285809dd87a52ec25560fdd
[openwrt/staging/dedeckeh.git] / target / linux / amazon-2.6 / files / drivers / char / admmod.c
1 /******************************************************************************
2 Copyright (c) 2004, Infineon Technologies. All rights reserved.
3
4 No Warranty
5 Because the program is licensed free of charge, there is no warranty for
6 the program, to the extent permitted by applicable law. Except when
7 otherwise stated in writing the copyright holders and/or other parties
8 provide the program "as is" without warranty of any kind, either
9 expressed or implied, including, but not limited to, the implied
10 warranties of merchantability and fitness for a particular purpose. The
11 entire risk as to the quality and performance of the program is with
12 you. should the program prove defective, you assume the cost of all
13 necessary servicing, repair or correction.
14
15 In no event unless required by applicable law or agreed to in writing
16 will any copyright holder, or any other party who may modify and/or
17 redistribute the program as permitted above, be liable to you for
18 damages, including any general, special, incidental or consequential
19 damages arising out of the use or inability to use the program
20 (including but not limited to loss of data or data being rendered
21 inaccurate or losses sustained by you or third parties or a failure of
22 the program to operate with any other programs), even if such holder or
23 other party has been advised of the possibility of such damages.
24 ******************************************************************************
25 Module : admmod.c
26 Date : 2004-09-01
27 Description : JoeLin
28 Remarks:
29
30 Revision:
31 MarsLin, add to support VLAN
32
33 *****************************************************************************/
34 //000001.joelin 2005/06/02 add"ADM6996_MDC_MDIO_MODE" define,
35 // if define ADM6996_MDC_MDIO_MODE==> ADM6996LC and ADM6996I will be in MDIO/MDC(SMI)(16 bit) mode,
36 // amazon should contrl ADM6996 by MDC/MDIO pin
37 // if undef ADM6996_MDC_MDIO_MODE==> ADM6996 will be in EEProm(32 bit) mode,
38 // amazon should contrl ADM6996 by GPIO15,16,17,18 pin
39 /* 507281:linmars 2005/07/28 support MDIO/EEPROM config mode */
40 /* 509201:linmars remove driver testing codes */
41
42 #include <linux/module.h>
43 #include <linux/string.h>
44 #include <linux/proc_fs.h>
45 #include <linux/delay.h>
46 #include <asm/uaccess.h>
47 #include <linux/init.h>
48 #include <linux/ioctl.h>
49 #include <asm/atomic.h>
50 #include <asm-mips/amazon/amazon.h>
51 #include <asm-mips/amazon/adm6996.h>
52 //#include <linux/amazon/adm6996.h>
53
54
55 unsigned int ifx_sw_conf[ADM_SW_MAX_PORT_NUM+1] = \
56 {ADM_SW_PORT0_CONF, ADM_SW_PORT1_CONF, ADM_SW_PORT2_CONF, \
57 ADM_SW_PORT3_CONF, ADM_SW_PORT4_CONF, ADM_SW_PORT5_CONF};
58 unsigned int ifx_sw_bits[8] = \
59 {0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
60 unsigned int ifx_sw_vlan_port[6] = {0, 2, 4, 6, 7, 8};
61 //050613:fchang
62 /* 507281:linmars start */
63 #ifdef CONFIG_SWITCH_ADM6996_MDIO
64 #define ADM6996_MDC_MDIO_MODE 1 //000001.joelin
65 #else
66 #undef ADM6996_MDC_MDIO_MODE
67 #endif
68 /* 507281:linmars end */
69 #define adm6996i 0
70 #define adm6996lc 1
71 #define adm6996l 2
72 unsigned int adm6996_mode=adm6996i;
73 /*
74 initialize GPIO pins.
75 output mode, low
76 */
77 void ifx_gpio_init(void)
78 {
79 //GPIO16,17,18 direction:output
80 //GPIO16,17,18 output 0
81
82 AMAZON_SW_REG(AMAZON_GPIO_P1_DIR) |= (GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
83 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT) =AMAZON_SW_REG(AMAZON_GPIO_P1_IN)& ~(GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
84
85 }
86
87 /* read one bit from mdio port */
88 int ifx_sw_mdio_readbit(void)
89 {
90 //int val;
91
92 //val = (AMAZON_SW_REG(GPIO_conf0_REG) & GPIO0_INPUT_MASK) >> 8;
93 //return val;
94 //GPIO16
95 return AMAZON_SW_REG(AMAZON_GPIO_P1_IN)&1;
96 }
97
98 /*
99 MDIO mode selection
100 1 -> output
101 0 -> input
102
103 switch input/output mode of GPIO 0
104 */
105 void ifx_mdio_mode(int mode)
106 {
107 // AMAZON_SW_REG(GPIO_conf0_REG) = mode ? GPIO_ENABLEBITS :
108 // ((GPIO_ENABLEBITS | MDIO_INPUT) & ~MDIO_OUTPUT_EN);
109 mode?(AMAZON_SW_REG(AMAZON_GPIO_P1_DIR)|=GPIO_MDIO):
110 (AMAZON_SW_REG(AMAZON_GPIO_P1_DIR)&=~GPIO_MDIO);
111 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_DIR);
112 mode?(r|=GPIO_MDIO):(r&=~GPIO_MDIO);
113 AMAZON_SW_REG(AMAZON_GPIO_P1_DIR)=r;*/
114 }
115
116 void ifx_mdc_hi(void)
117 {
118 //GPIO_SET_HI(GPIO_MDC);
119 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)|=GPIO_MDC;
120 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
121 r|=GPIO_MDC;
122 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
123
124 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)|GPIO_MDC;
125 }
126
127 void ifx_mdio_hi(void)
128 {
129 //GPIO_SET_HI(GPIO_MDIO);
130 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)|=GPIO_MDIO;
131 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
132 r|=GPIO_MDIO;
133 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
134
135 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)|GPIO_MDIO;
136 }
137
138 void ifx_mdcs_hi(void)
139 {
140 //GPIO_SET_HI(GPIO_MDCS);
141 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)|=GPIO_MDCS;
142 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
143 r|=GPIO_MDCS;
144 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
145
146 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)|GPIO_MDCS;
147 }
148
149 void ifx_mdc_lo(void)
150 {
151 //GPIO_SET_LOW(GPIO_MDC);
152 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)&=~GPIO_MDC;
153 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
154 r&=~GPIO_MDC;
155 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
156
157 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)&(~GPIO_MDC);
158 }
159
160 void ifx_mdio_lo(void)
161 {
162 //GPIO_SET_LOW(GPIO_MDIO);
163 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)&=~GPIO_MDIO;
164 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
165 r&=~GPIO_MDIO;
166 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
167
168 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)&(~GPIO_MDIO);
169 }
170
171 void ifx_mdcs_lo(void)
172 {
173 //GPIO_SET_LOW(GPIO_MDCS);
174 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)&=~GPIO_MDCS;
175 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
176 r&=~GPIO_MDCS;
177 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
178
179 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)&(~GPIO_MDCS);
180 }
181
182 /*
183 mdc pulse
184 0 -> 1 -> 0
185 */
186 static void ifx_sw_mdc_pulse(void)
187 {
188 ifx_mdc_lo();
189 udelay(ADM_SW_MDC_DOWN_DELAY);
190 ifx_mdc_hi();
191 udelay(ADM_SW_MDC_UP_DELAY);
192 ifx_mdc_lo();
193 }
194
195 /*
196 mdc toggle
197 1 -> 0
198 */
199 static void ifx_sw_mdc_toggle(void)
200 {
201 ifx_mdc_hi();
202 udelay(ADM_SW_MDC_UP_DELAY);
203 ifx_mdc_lo();
204 udelay(ADM_SW_MDC_DOWN_DELAY);
205 }
206
207 /*
208 enable eeprom write
209 For ATC 93C66 type EEPROM; accessing ADM6996 internal EEPROM type registers
210 */
211 static void ifx_sw_eeprom_write_enable(void)
212 {
213 unsigned int op;
214
215 ifx_mdcs_lo();
216 ifx_mdc_lo();
217 ifx_mdio_hi();
218 udelay(ADM_SW_CS_DELAY);
219 /* enable chip select */
220 ifx_mdcs_hi();
221 udelay(ADM_SW_CS_DELAY);
222 /* start bit */
223 ifx_mdio_hi();
224 ifx_sw_mdc_pulse();
225
226 /* eeprom write enable */
227 op = ADM_SW_BIT_MASK_4;
228 while (op)
229 {
230 if (op & ADM_SW_EEPROM_WRITE_ENABLE)
231 ifx_mdio_hi();
232 else
233 ifx_mdio_lo();
234
235 ifx_sw_mdc_pulse();
236 op >>= 1;
237 }
238
239 op = ADM_SW_BIT_MASK_1 << (EEPROM_TYPE - 3);
240 while (op)
241 {
242 ifx_mdio_lo();
243 ifx_sw_mdc_pulse();
244 op >>= 1;
245 }
246 /* disable chip select */
247 ifx_mdcs_lo();
248 udelay(ADM_SW_CS_DELAY);
249 ifx_sw_mdc_pulse();
250 }
251
252 /*
253 disable eeprom write
254 */
255 static void ifx_sw_eeprom_write_disable(void)
256 {
257 unsigned int op;
258
259 ifx_mdcs_lo();
260 ifx_mdc_lo();
261 ifx_mdio_hi();
262 udelay(ADM_SW_CS_DELAY);
263 /* enable chip select */
264 ifx_mdcs_hi();
265 udelay(ADM_SW_CS_DELAY);
266
267 /* start bit */
268 ifx_mdio_hi();
269 ifx_sw_mdc_pulse();
270 /* eeprom write disable */
271 op = ADM_SW_BIT_MASK_4;
272 while (op)
273 {
274 if (op & ADM_SW_EEPROM_WRITE_DISABLE)
275 ifx_mdio_hi();
276 else
277 ifx_mdio_lo();
278
279 ifx_sw_mdc_pulse();
280 op >>= 1;
281 }
282
283 op = ADM_SW_BIT_MASK_1 << (EEPROM_TYPE - 3);
284 while (op)
285 {
286 ifx_mdio_lo();
287
288 ifx_sw_mdc_pulse();
289 op >>= 1;
290 }
291 /* disable chip select */
292 ifx_mdcs_lo();
293 udelay(ADM_SW_CS_DELAY);
294 ifx_sw_mdc_pulse();
295 }
296
297 /*
298 read registers from ADM6996
299 serial registers start at 0x200 (addr bit 9 = 1b)
300 EEPROM registers -> 16bits; Serial registers -> 32bits
301 */
302 #ifdef ADM6996_MDC_MDIO_MODE //smi mode//000001.joelin
303 static int ifx_sw_read_adm6996i_smi(unsigned int addr, unsigned int *dat)
304 {
305 addr=(addr<<16)&0x3ff0000;
306 AMAZON_SW_REG(AMAZON_SW_MDIO_ACC) =(0xC0000000|addr);
307 while ((AMAZON_SW_REG(AMAZON_SW_MDIO_ACC))&0x80000000){};
308 *dat=((AMAZON_SW_REG(AMAZON_SW_MDIO_ACC))&0x0FFFF);
309 return 0;
310 }
311 #endif
312
313 static int ifx_sw_read_adm6996i(unsigned int addr, unsigned int *dat)
314 {
315 unsigned int op;
316
317 ifx_gpio_init();
318
319 ifx_mdcs_hi();
320 udelay(ADM_SW_CS_DELAY);
321
322 ifx_mdcs_lo();
323 ifx_mdc_lo();
324 ifx_mdio_lo();
325
326 udelay(ADM_SW_CS_DELAY);
327
328 /* preamble, 32 bit 1 */
329 ifx_mdio_hi();
330 op = ADM_SW_BIT_MASK_32;
331 while (op)
332 {
333 ifx_sw_mdc_pulse();
334 op >>= 1;
335 }
336
337 /* command start (01b) */
338 op = ADM_SW_BIT_MASK_2;
339 while (op)
340 {
341 if (op & ADM_SW_SMI_START)
342 ifx_mdio_hi();
343 else
344 ifx_mdio_lo();
345
346 ifx_sw_mdc_pulse();
347 op >>= 1;
348 }
349
350 /* read command (10b) */
351 op = ADM_SW_BIT_MASK_2;
352 while (op)
353 {
354 if (op & ADM_SW_SMI_READ)
355 ifx_mdio_hi();
356 else
357 ifx_mdio_lo();
358
359 ifx_sw_mdc_pulse();
360 op >>= 1;
361 }
362
363 /* send address A9 ~ A0 */
364 op = ADM_SW_BIT_MASK_10;
365 while (op)
366 {
367 if (op & addr)
368 ifx_mdio_hi();
369 else
370 ifx_mdio_lo();
371
372 ifx_sw_mdc_pulse();
373 op >>= 1;
374 }
375
376 /* turnaround bits */
377 op = ADM_SW_BIT_MASK_2;
378 ifx_mdio_hi();
379 while (op)
380 {
381 ifx_sw_mdc_pulse();
382 op >>= 1;
383 }
384
385 udelay(ADM_SW_MDC_DOWN_DELAY);
386
387 /* set MDIO pin to input mode */
388 ifx_mdio_mode(ADM_SW_MDIO_INPUT);
389
390 /* start read data */
391 *dat = 0;
392 //adm6996i op = ADM_SW_BIT_MASK_32;
393 op = ADM_SW_BIT_MASK_16;//adm6996i
394 while (op)
395 {
396 *dat <<= 1;
397 if (ifx_sw_mdio_readbit()) *dat |= 1;
398 ifx_sw_mdc_toggle();
399
400 op >>= 1;
401 }
402
403 /* set MDIO to output mode */
404 ifx_mdio_mode(ADM_SW_MDIO_OUTPUT);
405
406 /* dummy clock */
407 op = ADM_SW_BIT_MASK_4;
408 ifx_mdio_lo();
409 while(op)
410 {
411 ifx_sw_mdc_pulse();
412 op >>= 1;
413 }
414
415 ifx_mdc_lo();
416 ifx_mdio_lo();
417 ifx_mdcs_hi();
418
419 /* EEPROM registers */
420 //adm6996i if (!(addr & 0x200))
421 //adm6996i {
422 //adm6996i if (addr % 2)
423 //adm6996i *dat >>= 16;
424 //adm6996i else
425 //adm6996i *dat &= 0xffff;
426 //adm6996i }
427
428 return 0;
429 }
430 //adm6996
431 static int ifx_sw_read_adm6996l(unsigned int addr, unsigned int *dat)
432 {
433 unsigned int op;
434
435 ifx_gpio_init();
436
437 ifx_mdcs_hi();
438 udelay(ADM_SW_CS_DELAY);
439
440 ifx_mdcs_lo();
441 ifx_mdc_lo();
442 ifx_mdio_lo();
443
444 udelay(ADM_SW_CS_DELAY);
445
446 /* preamble, 32 bit 1 */
447 ifx_mdio_hi();
448 op = ADM_SW_BIT_MASK_32;
449 while (op)
450 {
451 ifx_sw_mdc_pulse();
452 op >>= 1;
453 }
454
455 /* command start (01b) */
456 op = ADM_SW_BIT_MASK_2;
457 while (op)
458 {
459 if (op & ADM_SW_SMI_START)
460 ifx_mdio_hi();
461 else
462 ifx_mdio_lo();
463
464 ifx_sw_mdc_pulse();
465 op >>= 1;
466 }
467
468 /* read command (10b) */
469 op = ADM_SW_BIT_MASK_2;
470 while (op)
471 {
472 if (op & ADM_SW_SMI_READ)
473 ifx_mdio_hi();
474 else
475 ifx_mdio_lo();
476
477 ifx_sw_mdc_pulse();
478 op >>= 1;
479 }
480
481 /* send address A9 ~ A0 */
482 op = ADM_SW_BIT_MASK_10;
483 while (op)
484 {
485 if (op & addr)
486 ifx_mdio_hi();
487 else
488 ifx_mdio_lo();
489
490 ifx_sw_mdc_pulse();
491 op >>= 1;
492 }
493
494 /* turnaround bits */
495 op = ADM_SW_BIT_MASK_2;
496 ifx_mdio_hi();
497 while (op)
498 {
499 ifx_sw_mdc_pulse();
500 op >>= 1;
501 }
502
503 udelay(ADM_SW_MDC_DOWN_DELAY);
504
505 /* set MDIO pin to input mode */
506 ifx_mdio_mode(ADM_SW_MDIO_INPUT);
507
508 /* start read data */
509 *dat = 0;
510 op = ADM_SW_BIT_MASK_32;
511 while (op)
512 {
513 *dat <<= 1;
514 if (ifx_sw_mdio_readbit()) *dat |= 1;
515 ifx_sw_mdc_toggle();
516
517 op >>= 1;
518 }
519
520 /* set MDIO to output mode */
521 ifx_mdio_mode(ADM_SW_MDIO_OUTPUT);
522
523 /* dummy clock */
524 op = ADM_SW_BIT_MASK_4;
525 ifx_mdio_lo();
526 while(op)
527 {
528 ifx_sw_mdc_pulse();
529 op >>= 1;
530 }
531
532 ifx_mdc_lo();
533 ifx_mdio_lo();
534 ifx_mdcs_hi();
535
536 /* EEPROM registers */
537 if (!(addr & 0x200))
538 {
539 if (addr % 2)
540 *dat >>= 16;
541 else
542 *dat &= 0xffff;
543 }
544
545 return 0;
546 }
547
548 static int ifx_sw_read(unsigned int addr, unsigned int *dat)
549 {
550 #ifdef ADM6996_MDC_MDIO_MODE //smi mode ////000001.joelin
551 ifx_sw_read_adm6996i_smi(addr,dat);
552 #else
553 if (adm6996_mode==adm6996i) ifx_sw_read_adm6996i(addr,dat);
554 else ifx_sw_read_adm6996l(addr,dat);
555 #endif
556 return 0;
557
558 }
559
560 /*
561 write register to ADM6996 eeprom registers
562 */
563 //for adm6996i -start
564 #ifdef ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
565 static int ifx_sw_write_adm6996i_smi(unsigned int addr, unsigned int dat)
566 {
567
568 AMAZON_SW_REG(AMAZON_SW_MDIO_ACC) = ((addr<<16)&0x3ff0000)|dat|0x80000000;
569 while ((AMAZON_SW_REG(AMAZON_SW_MDIO_ACC))&0x80000000){};
570
571 return 0;
572
573 }
574 #endif //ADM6996_MDC_MDIO_MODE //000001.joelin
575
576 static int ifx_sw_write_adm6996i(unsigned int addr, unsigned int dat)
577 {
578 unsigned int op;
579
580 ifx_gpio_init();
581
582 ifx_mdcs_hi();
583 udelay(ADM_SW_CS_DELAY);
584
585 ifx_mdcs_lo();
586 ifx_mdc_lo();
587 ifx_mdio_lo();
588
589 udelay(ADM_SW_CS_DELAY);
590
591 /* preamble, 32 bit 1 */
592 ifx_mdio_hi();
593 op = ADM_SW_BIT_MASK_32;
594 while (op)
595 {
596 ifx_sw_mdc_pulse();
597 op >>= 1;
598 }
599
600 /* command start (01b) */
601 op = ADM_SW_BIT_MASK_2;
602 while (op)
603 {
604 if (op & ADM_SW_SMI_START)
605 ifx_mdio_hi();
606 else
607 ifx_mdio_lo();
608
609 ifx_sw_mdc_pulse();
610 op >>= 1;
611 }
612
613 /* write command (01b) */
614 op = ADM_SW_BIT_MASK_2;
615 while (op)
616 {
617 if (op & ADM_SW_SMI_WRITE)
618 ifx_mdio_hi();
619 else
620 ifx_mdio_lo();
621
622 ifx_sw_mdc_pulse();
623 op >>= 1;
624 }
625
626 /* send address A9 ~ A0 */
627 op = ADM_SW_BIT_MASK_10;
628 while (op)
629 {
630 if (op & addr)
631 ifx_mdio_hi();
632 else
633 ifx_mdio_lo();
634
635 ifx_sw_mdc_pulse();
636 op >>= 1;
637 }
638
639 /* turnaround bits */
640 op = ADM_SW_BIT_MASK_2;
641 ifx_mdio_hi();
642 while (op)
643 {
644 ifx_sw_mdc_pulse();
645 op >>= 1;
646 }
647
648 udelay(ADM_SW_MDC_DOWN_DELAY);
649
650 /* set MDIO pin to output mode */
651 ifx_mdio_mode(ADM_SW_MDIO_OUTPUT);
652
653
654 /* start write data */
655 op = ADM_SW_BIT_MASK_16;
656 while (op)
657 {
658 if (op & dat)
659 ifx_mdio_hi();
660 else
661 ifx_mdio_lo();
662
663 ifx_sw_mdc_toggle();
664 op >>= 1;
665 }
666
667 // /* set MDIO to output mode */
668 // ifx_mdio_mode(ADM_SW_MDIO_OUTPUT);
669
670 /* dummy clock */
671 op = ADM_SW_BIT_MASK_4;
672 ifx_mdio_lo();
673 while(op)
674 {
675 ifx_sw_mdc_pulse();
676 op >>= 1;
677 }
678
679 ifx_mdc_lo();
680 ifx_mdio_lo();
681 ifx_mdcs_hi();
682
683 /* EEPROM registers */
684 //adm6996i if (!(addr & 0x200))
685 //adm6996i {
686 //adm6996i if (addr % 2)
687 //adm6996i *dat >>= 16;
688 //adm6996i else
689 //adm6996i *dat &= 0xffff;
690 //adm6996i }
691
692 return 0;
693 }
694 //for adm6996i-end
695 static int ifx_sw_write_adm6996l(unsigned int addr, unsigned int dat)
696 {
697 unsigned int op;
698
699 ifx_gpio_init();
700
701 /* enable write */
702 ifx_sw_eeprom_write_enable();
703
704 /* chip select */
705 ifx_mdcs_hi();
706 udelay(ADM_SW_CS_DELAY);
707
708 /* issue write command */
709 /* start bit */
710 ifx_mdio_hi();
711 ifx_sw_mdc_pulse();
712
713 /* EEPROM write command */
714 op = ADM_SW_BIT_MASK_2;
715 while (op)
716 {
717 if (op & ADM_SW_EEPROM_WRITE)
718 ifx_mdio_hi();
719 else
720 ifx_mdio_lo();
721
722 ifx_sw_mdc_pulse();
723 op >>= 1;
724 }
725
726 /* send address A7 ~ A0 */
727 op = ADM_SW_BIT_MASK_1 << (EEPROM_TYPE - 1);
728
729 while (op)
730 {
731 if (op & addr)
732 ifx_mdio_hi();
733 else
734 ifx_mdio_lo();
735
736 ifx_sw_mdc_toggle();
737 op >>= 1;
738 }
739
740 /* start write data */
741 op = ADM_SW_BIT_MASK_16;
742 while (op)
743 {
744 if (op & dat)
745 ifx_mdio_hi();
746 else
747 ifx_mdio_lo();
748
749 ifx_sw_mdc_toggle();
750 op >>= 1;
751 }
752
753 /* disable cs & wait 1 clock */
754 ifx_mdcs_lo();
755 udelay(ADM_SW_CS_DELAY);
756 ifx_sw_mdc_toggle();
757
758 ifx_sw_eeprom_write_disable();
759
760 return 0;
761 }
762
763 static int ifx_sw_write(unsigned int addr, unsigned int dat)
764 {
765 #ifdef ADM6996_MDC_MDIO_MODE //smi mode ////000001.joelin
766 ifx_sw_write_adm6996i_smi(addr,dat);
767 #else //000001.joelin
768 if (adm6996_mode==adm6996i) ifx_sw_write_adm6996i(addr,dat);
769 else ifx_sw_write_adm6996l(addr,dat);
770 #endif //000001.joelin
771 return 0;
772 }
773
774 /*
775 do switch PHY reset
776 */
777 int ifx_sw_reset(void)
778 {
779 /* reset PHY */
780 ifx_sw_write(ADM_SW_PHY_RESET, 0);
781
782 return 0;
783 }
784
785 /* 509201:linmars start */
786 #if 0
787 /*
788 check port status
789 */
790 int ifx_check_port_status(int port)
791 {
792 unsigned int val;
793
794 if ((port < 0) || (port > ADM_SW_MAX_PORT_NUM))
795 {
796 ifx_printf(("error on port number (%d)!!\n", port));
797 return -1;
798 }
799
800 ifx_sw_read(ifx_sw_conf[port], &val);
801 if (ifx_sw_conf[port]%2) val >>= 16;
802 /* only 16bits are effective */
803 val &= 0xFFFF;
804
805 ifx_printf(("Port %d status (%.8x): \n", port, val));
806
807 if (val & ADM_SW_PORT_FLOWCTL)
808 ifx_printf(("\t802.3x flow control supported!\n"));
809 else
810 ifx_printf(("\t802.3x flow control not supported!\n"));
811
812 if (val & ADM_SW_PORT_AN)
813 ifx_printf(("\tAuto negotiation ON!\n"));
814 else
815 ifx_printf(("\tAuto negotiation OFF!\n"));
816
817 if (val & ADM_SW_PORT_100M)
818 ifx_printf(("\tLink at 100M!\n"));
819 else
820 ifx_printf(("\tLink at 10M!\n"));
821
822 if (val & ADM_SW_PORT_FULL)
823 ifx_printf(("\tFull duplex!\n"));
824 else
825 ifx_printf(("\tHalf duplex!\n"));
826
827 if (val & ADM_SW_PORT_DISABLE)
828 ifx_printf(("\tPort disabled!\n"));
829 else
830 ifx_printf(("\tPort enabled!\n"));
831
832 if (val & ADM_SW_PORT_TOS)
833 ifx_printf(("\tTOS enabled!\n"));
834 else
835 ifx_printf(("\tTOS disabled!\n"));
836
837 if (val & ADM_SW_PORT_PPRI)
838 ifx_printf(("\tPort priority first!\n"));
839 else
840 ifx_printf(("\tVLAN or TOS priority first!\n"));
841
842 if (val & ADM_SW_PORT_MDIX)
843 ifx_printf(("\tAuto MDIX!\n"));
844 else
845 ifx_printf(("\tNo auto MDIX\n"));
846
847 ifx_printf(("\tPVID: %d\n", \
848 ((val >> ADM_SW_PORT_PVID_SHIFT)&ifx_sw_bits[ADM_SW_PORT_PVID_BITS])));
849
850 return 0;
851 }
852 /*
853 initialize a VLAN
854 clear all VLAN bits
855 */
856 int ifx_sw_vlan_init(int vlanid)
857 {
858 ifx_sw_write(ADM_SW_VLAN0_CONF + vlanid, 0);
859
860 return 0;
861 }
862
863 /*
864 add a port to certain vlan
865 */
866 int ifx_sw_vlan_add(int port, int vlanid)
867 {
868 int reg = 0;
869
870 if ((port < 0) || (port > ADM_SW_MAX_PORT_NUM) || (vlanid < 0) ||
871 (vlanid > ADM_SW_MAX_VLAN_NUM))
872 {
873 ifx_printf(("Port number or VLAN number ERROR!!\n"));
874 return -1;
875 }
876 ifx_sw_read(ADM_SW_VLAN0_CONF + vlanid, &reg);
877 reg |= (1 << ifx_sw_vlan_port[port]);
878 ifx_sw_write(ADM_SW_VLAN0_CONF + vlanid, reg);
879
880 return 0;
881 }
882
883 /*
884 delete a given port from certain vlan
885 */
886 int ifx_sw_vlan_del(int port, int vlanid)
887 {
888 unsigned int reg = 0;
889
890 if ((port < 0) || (port > ADM_SW_MAX_PORT_NUM) || (vlanid < 0) || (vlanid > ADM_SW_MAX_VLAN_NUM))
891 {
892 ifx_printf(("Port number or VLAN number ERROR!!\n"));
893 return -1;
894 }
895 ifx_sw_read(ADM_SW_VLAN0_CONF + vlanid, &reg);
896 reg &= ~(1 << ifx_sw_vlan_port[port]);
897 ifx_sw_write(ADM_SW_VLAN0_CONF + vlanid, reg);
898
899 return 0;
900 }
901
902 /*
903 default VLAN setting
904
905 port 0~3 as untag port and PVID = 1
906 VLAN1: port 0~3 and port 5 (MII)
907 */
908 static int ifx_sw_init(void)
909 {
910 ifx_printf(("Setting default ADM6996 registers... \n"));
911
912 /* MAC clone, 802.1q based VLAN */
913 ifx_sw_write(ADM_SW_VLAN_MODE, 0xff30);
914 /* auto MDIX, PVID=1, untag */
915 ifx_sw_write(ADM_SW_PORT0_CONF, 0x840f);
916 ifx_sw_write(ADM_SW_PORT1_CONF, 0x840f);
917 ifx_sw_write(ADM_SW_PORT2_CONF, 0x840f);
918 ifx_sw_write(ADM_SW_PORT3_CONF, 0x840f);
919 /* auto MDIX, PVID=2, untag */
920 ifx_sw_write(ADM_SW_PORT5_CONF, 0x880f);
921 /* port 0~3 & 5 as VLAN1 */
922 ifx_sw_write(ADM_SW_VLAN0_CONF+1, 0x0155);
923
924 return 0;
925 }
926 #endif
927 /* 509201:linmars end */
928
929 int adm_open(struct inode *node, struct file *filp)
930 {
931 MOD_INC_USE_COUNT;
932 return 0;
933 }
934
935 ssize_t adm_read(struct file *filep, char *buf, size_t count, loff_t *ppos)
936 {
937 return count;
938 }
939
940 ssize_t adm_write(struct file *filep, const char *buf, size_t count, loff_t *ppos)
941 {
942 return count;
943 }
944
945 /* close */
946 int adm_release(struct inode *inode, struct file *filp)
947 {
948 MOD_DEC_USE_COUNT;
949 return 0;
950 }
951
952 /* IOCTL function */
953 int adm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long args)
954 {
955 PREGRW uREGRW;
956 unsigned int rtval;
957 unsigned int val; //6996i
958 unsigned int control[6] ; //6996i
959 unsigned int status[6] ; //6996i
960
961 PMACENTRY mMACENTRY;//adm6996i
962 PPROTOCOLFILTER uPROTOCOLFILTER ;///adm6996i
963
964 if (_IOC_TYPE(cmd) != ADM_MAGIC)
965 {
966 printk("adm_ioctl: IOC_TYPE(%x) != ADM_MAGIC(%x)! \n", _IOC_TYPE(cmd), ADM_MAGIC);
967 return (-EINVAL);
968 }
969
970 if(_IOC_NR(cmd) >= KEY_IOCTL_MAX_KEY)
971 {
972 printk(KERN_WARNING "adm_ioctl: IOC_NR(%x) invalid! \n", _IOC_NR(cmd));
973 return (-EINVAL);
974 }
975
976 switch (cmd)
977 {
978 case ADM_IOCTL_REGRW:
979 {
980 uREGRW = (PREGRW)kmalloc(sizeof(REGRW), GFP_KERNEL);
981 rtval = copy_from_user(uREGRW, (PREGRW)args, sizeof(REGRW));
982 if (rtval != 0)
983 {
984 printk("ADM_IOCTL_REGRW: copy from user FAILED!! \n");
985 return (-EFAULT);
986 }
987
988 switch(uREGRW->mode)
989 {
990 case REG_READ:
991 uREGRW->value = 0x12345678;//inl(uREGRW->addr);
992 copy_to_user((PREGRW)args, uREGRW, sizeof(REGRW));
993 break;
994 case REG_WRITE:
995 //outl(uREGRW->value, uREGRW->addr);
996 break;
997
998 default:
999 printk("No such Register Read/Write function!! \n");
1000 return (-EFAULT);
1001 }
1002 kfree(uREGRW);
1003 break;
1004 }
1005
1006 case ADM_SW_IOCTL_REGRW:
1007 {
1008 unsigned int val = 0xff;
1009
1010 uREGRW = (PREGRW)kmalloc(sizeof(REGRW), GFP_KERNEL);
1011 rtval = copy_from_user(uREGRW, (PREGRW)args, sizeof(REGRW));
1012 if (rtval != 0)
1013 {
1014 printk("ADM_IOCTL_REGRW: copy from user FAILED!! \n");
1015 return (-EFAULT);
1016 }
1017
1018 switch(uREGRW->mode)
1019 {
1020 case REG_READ:
1021 ifx_sw_read(uREGRW->addr, &val);
1022 uREGRW->value = val;
1023 copy_to_user((PREGRW)args, uREGRW, sizeof(REGRW));
1024 break;
1025
1026 case REG_WRITE:
1027 ifx_sw_write(uREGRW->addr, uREGRW->value);
1028 break;
1029 default:
1030 printk("No such Register Read/Write function!! \n");
1031 return (-EFAULT);
1032 }
1033 kfree(uREGRW);
1034 break;
1035 }
1036 /* 509201:linmars start */
1037 #if 0
1038 case ADM_SW_IOCTL_PORTSTS:
1039 for (rtval = 0; rtval < ADM_SW_MAX_PORT_NUM+1; rtval++)
1040 ifx_check_port_status(rtval);
1041 break;
1042 case ADM_SW_IOCTL_INIT:
1043 ifx_sw_init();
1044 break;
1045 #endif
1046 /* 509201:linmars end */
1047 //adm6996i
1048 case ADM_SW_IOCTL_MACENTRY_ADD:
1049 case ADM_SW_IOCTL_MACENTRY_DEL:
1050 case ADM_SW_IOCTL_MACENTRY_GET_INIT:
1051 case ADM_SW_IOCTL_MACENTRY_GET_MORE:
1052
1053
1054 mMACENTRY = (PMACENTRY)kmalloc(sizeof(MACENTRY), GFP_KERNEL);
1055 rtval = copy_from_user(mMACENTRY, (PMACENTRY)args, sizeof(MACENTRY));
1056 if (rtval != 0)
1057 {
1058 printk("ADM_SW_IOCTL_MACENTRY: copy from user FAILED!! \n");
1059 return (-EFAULT);
1060 }
1061 control[0]=(mMACENTRY->mac_addr[1]<<8)+mMACENTRY->mac_addr[0] ;
1062 control[1]=(mMACENTRY->mac_addr[3]<<8)+mMACENTRY->mac_addr[2] ;
1063 control[2]=(mMACENTRY->mac_addr[5]<<8)+mMACENTRY->mac_addr[4] ;
1064 control[3]=(mMACENTRY->fid&0xf)+((mMACENTRY->portmap&0x3f)<<4);
1065 if (((mMACENTRY->info_type)&0x01)) control[4]=(mMACENTRY->ctrl.info_ctrl)+0x1000; //static ,info control
1066 else control[4]=((mMACENTRY->ctrl.age_timer)&0xff);//not static ,agetimer
1067 if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT) {
1068 //initial the pointer to the first address
1069 val=0x8000;//busy ,status5[15]
1070 while(val&0x8000){ //check busy ?
1071 ifx_sw_read(0x125, &val);
1072 }
1073 control[5]=0x030;//initial the first address
1074 ifx_sw_write(0x11f,control[5]);
1075
1076
1077 val=0x8000;//busy ,status5[15]
1078 while(val&0x8000){ //check busy ?
1079 ifx_sw_read(0x125, &val);
1080 }
1081
1082 } //if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)
1083 if (cmd==ADM_SW_IOCTL_MACENTRY_ADD) control[5]=0x07;//create a new address
1084 else if (cmd==ADM_SW_IOCTL_MACENTRY_DEL) control[5]=0x01f;//erased an existed address
1085 else if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
1086 control[5]=0x02c;//search by the mac address field
1087
1088 val=0x8000;//busy ,status5[15]
1089 while(val&0x8000){ //check busy ?
1090 ifx_sw_read(0x125, &val);
1091 }
1092 ifx_sw_write(0x11a,control[0]);
1093 ifx_sw_write(0x11b,control[1]);
1094 ifx_sw_write(0x11c,control[2]);
1095 ifx_sw_write(0x11d,control[3]);
1096 ifx_sw_write(0x11e,control[4]);
1097 ifx_sw_write(0x11f,control[5]);
1098 val=0x8000;//busy ,status5[15]
1099 while(val&0x8000){ //check busy ?
1100 ifx_sw_read(0x125, &val);
1101 }
1102 val=((val&0x7000)>>12);//result ,status5[14:12]
1103 mMACENTRY->result=val;
1104
1105 if (!val) {
1106 printk(" Command OK!! \n");
1107 if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE)) {
1108 ifx_sw_read(0x120,&(status[0]));
1109 ifx_sw_read(0x121,&(status[1]));
1110 ifx_sw_read(0x122,&(status[2]));
1111 ifx_sw_read(0x123,&(status[3]));
1112 ifx_sw_read(0x124,&(status[4]));
1113 ifx_sw_read(0x125,&(status[5]));
1114
1115
1116 mMACENTRY->mac_addr[0]=(status[0]&0x00ff) ;
1117 mMACENTRY->mac_addr[1]=(status[0]&0xff00)>>8 ;
1118 mMACENTRY->mac_addr[2]=(status[1]&0x00ff) ;
1119 mMACENTRY->mac_addr[3]=(status[1]&0xff00)>>8 ;
1120 mMACENTRY->mac_addr[4]=(status[2]&0x00ff) ;
1121 mMACENTRY->mac_addr[5]=(status[2]&0xff00)>>8 ;
1122 mMACENTRY->fid=(status[3]&0xf);
1123 mMACENTRY->portmap=((status[3]>>4)&0x3f);
1124 if (status[5]&0x2) {//static info_ctrl //status5[1]????
1125 mMACENTRY->ctrl.info_ctrl=(status[4]&0x00ff);
1126 mMACENTRY->info_type=1;
1127 }
1128 else {//not static age_timer
1129 mMACENTRY->ctrl.age_timer=(status[4]&0x00ff);
1130 mMACENTRY->info_type=0;
1131 }
1132 //status5[13]???? mMACENTRY->occupy=(status[5]&0x02)>>1;//status5[1]
1133 mMACENTRY->occupy=(status[5]&0x02000)>>13;//status5[13] ???
1134 mMACENTRY->bad=(status[5]&0x04)>>2;//status5[2]
1135 }//if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
1136
1137 }
1138 else if (val==0x001)
1139 printk(" All Entry Used!! \n");
1140 else if (val==0x002)
1141 printk(" Entry Not Found!! \n");
1142 else if (val==0x003)
1143 printk(" Try Next Entry!! \n");
1144 else if (val==0x005)
1145 printk(" Command Error!! \n");
1146 else
1147 printk(" UnKnown Error!! \n");
1148
1149 copy_to_user((PMACENTRY)args, mMACENTRY,sizeof(MACENTRY));
1150
1151 break;
1152
1153 case ADM_SW_IOCTL_FILTER_ADD:
1154 case ADM_SW_IOCTL_FILTER_DEL:
1155 case ADM_SW_IOCTL_FILTER_GET:
1156
1157 uPROTOCOLFILTER = (PPROTOCOLFILTER)kmalloc(sizeof(PROTOCOLFILTER), GFP_KERNEL);
1158 rtval = copy_from_user(uPROTOCOLFILTER, (PPROTOCOLFILTER)args, sizeof(PROTOCOLFILTER));
1159 if (rtval != 0)
1160 {
1161 printk("ADM_SW_IOCTL_FILTER_ADD: copy from user FAILED!! \n");
1162 return (-EFAULT);
1163 }
1164
1165 if(cmd==ADM_SW_IOCTL_FILTER_DEL) { //delete filter
1166 uPROTOCOLFILTER->ip_p=00; //delet filter
1167 uPROTOCOLFILTER->action=00; //delete filter
1168 } //delete filter
1169
1170 ifx_sw_read(((uPROTOCOLFILTER->protocol_filter_num/2)+0x68), &val);//rx68~rx6b,protocol filter0~7
1171
1172 if (((uPROTOCOLFILTER->protocol_filter_num)%2)==00){
1173 if(cmd==ADM_SW_IOCTL_FILTER_GET) uPROTOCOLFILTER->ip_p= val&0x00ff;//get filter ip_p
1174 else val=(val&0xff00)|(uPROTOCOLFILTER->ip_p);//set filter ip_p
1175 }
1176 else {
1177 if(cmd==ADM_SW_IOCTL_FILTER_GET) uPROTOCOLFILTER->ip_p= (val>>8);//get filter ip_p
1178 else val=(val&0x00ff)|((uPROTOCOLFILTER->ip_p)<<8);//set filter ip_p
1179 }
1180 if(cmd!=ADM_SW_IOCTL_FILTER_GET) ifx_sw_write(((uPROTOCOLFILTER->protocol_filter_num/2)+0x68), val);//write rx68~rx6b,protocol filter0~7
1181
1182 ifx_sw_read(0x95, &val); //protocol filter action
1183 if(cmd==ADM_SW_IOCTL_FILTER_GET) {
1184 uPROTOCOLFILTER->action= ((val>>(uPROTOCOLFILTER->protocol_filter_num*2))&0x3);//get filter action
1185 copy_to_user((PPROTOCOLFILTER)args, uPROTOCOLFILTER, sizeof(PROTOCOLFILTER));
1186
1187 }
1188 else {
1189 val=(val&(~(0x03<<(uPROTOCOLFILTER->protocol_filter_num*2))))|(((uPROTOCOLFILTER->action)&0x03)<<(uPROTOCOLFILTER->protocol_filter_num*2));
1190 // printk("%d----\n",val);
1191 ifx_sw_write(0x95, val); //write protocol filter action
1192 }
1193
1194 break;
1195 //adm6996i
1196
1197 /* others */
1198 default:
1199 return -EFAULT;
1200 }
1201 /* end of switch */
1202 return 0;
1203 }
1204
1205 /* Santosh: handle IGMP protocol filter ADD/DEL/GET */
1206 int adm_process_protocol_filter_request (unsigned int cmd, PPROTOCOLFILTER uPROTOCOLFILTER)
1207 {
1208 unsigned int val; //6996i
1209
1210 if(cmd==ADM_SW_IOCTL_FILTER_DEL) { //delete filter
1211 uPROTOCOLFILTER->ip_p=00; //delet filter
1212 uPROTOCOLFILTER->action=00; //delete filter
1213 } //delete filter
1214
1215 ifx_sw_read(((uPROTOCOLFILTER->protocol_filter_num/2)+0x68), &val);//rx68~rx6b,protocol filter0~7
1216
1217 if (((uPROTOCOLFILTER->protocol_filter_num)%2)==00){
1218 if(cmd==ADM_SW_IOCTL_FILTER_GET) uPROTOCOLFILTER->ip_p= val&0x00ff;//get filter ip_p
1219 else val=(val&0xff00)|(uPROTOCOLFILTER->ip_p);//set filter ip_p
1220 }
1221 else {
1222 if(cmd==ADM_SW_IOCTL_FILTER_GET) uPROTOCOLFILTER->ip_p= (val>>8);//get filter ip_p
1223 else val=(val&0x00ff)|((uPROTOCOLFILTER->ip_p)<<8);//set filter ip_p
1224 }
1225 if(cmd!=ADM_SW_IOCTL_FILTER_GET) ifx_sw_write(((uPROTOCOLFILTER->protocol_filter_num/2)+0x68), val);//write rx68~rx6b,protocol filter0~7
1226
1227 ifx_sw_read(0x95, &val); //protocol filter action
1228 if(cmd==ADM_SW_IOCTL_FILTER_GET) {
1229 uPROTOCOLFILTER->action= ((val>>(uPROTOCOLFILTER->protocol_filter_num*2))&0x3);//get filter action
1230 }
1231 else {
1232 val=(val&(~(0x03<<(uPROTOCOLFILTER->protocol_filter_num*2))))|(((uPROTOCOLFILTER->action)&0x03)<<(uPROTOCOLFILTER->protocol_filter_num*2));
1233 ifx_sw_write(0x95, val); //write protocol filter action
1234 }
1235
1236 return 0;
1237 }
1238
1239
1240 /* Santosh: function for MAC ENTRY ADD/DEL/GET */
1241
1242 int adm_process_mac_table_request (unsigned int cmd, PMACENTRY mMACENTRY)
1243 {
1244 unsigned int rtval;
1245 unsigned int val; //6996i
1246 unsigned int control[6] ; //6996i
1247 unsigned int status[6] ; //6996i
1248
1249 // printk ("adm_process_mac_table_request: enter\n");
1250
1251 control[0]=(mMACENTRY->mac_addr[1]<<8)+mMACENTRY->mac_addr[0] ;
1252 control[1]=(mMACENTRY->mac_addr[3]<<8)+mMACENTRY->mac_addr[2] ;
1253 control[2]=(mMACENTRY->mac_addr[5]<<8)+mMACENTRY->mac_addr[4] ;
1254 control[3]=(mMACENTRY->fid&0xf)+((mMACENTRY->portmap&0x3f)<<4);
1255
1256 if (((mMACENTRY->info_type)&0x01)) control[4]=(mMACENTRY->ctrl.info_ctrl)+0x1000; //static ,info control
1257 else control[4]=((mMACENTRY->ctrl.age_timer)&0xff);//not static ,agetimer
1258 if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT) {
1259 //initial the pointer to the first address
1260 val=0x8000;//busy ,status5[15]
1261 while(val&0x8000){ //check busy ?
1262 ifx_sw_read(0x125, &val);
1263 }
1264 control[5]=0x030;//initial the first address
1265 ifx_sw_write(0x11f,control[5]);
1266
1267
1268 val=0x8000;//busy ,status5[15]
1269 while(val&0x8000){ //check busy ?
1270 ifx_sw_read(0x125, &val);
1271 }
1272
1273 } //if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)
1274 if (cmd==ADM_SW_IOCTL_MACENTRY_ADD) control[5]=0x07;//create a new address
1275 else if (cmd==ADM_SW_IOCTL_MACENTRY_DEL) control[5]=0x01f;//erased an existed address
1276 else if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
1277 control[5]=0x02c;//search by the mac address field
1278
1279 val=0x8000;//busy ,status5[15]
1280 while(val&0x8000){ //check busy ?
1281 ifx_sw_read(0x125, &val);
1282 }
1283 ifx_sw_write(0x11a,control[0]);
1284 ifx_sw_write(0x11b,control[1]);
1285 ifx_sw_write(0x11c,control[2]);
1286 ifx_sw_write(0x11d,control[3]);
1287 ifx_sw_write(0x11e,control[4]);
1288 ifx_sw_write(0x11f,control[5]);
1289 val=0x8000;//busy ,status5[15]
1290 while(val&0x8000){ //check busy ?
1291 ifx_sw_read(0x125, &val);
1292 }
1293 val=((val&0x7000)>>12);//result ,status5[14:12]
1294 mMACENTRY->result=val;
1295
1296 if (!val) {
1297 printk(" Command OK!! \n");
1298 if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE)) {
1299 ifx_sw_read(0x120,&(status[0]));
1300 ifx_sw_read(0x121,&(status[1]));
1301 ifx_sw_read(0x122,&(status[2]));
1302 ifx_sw_read(0x123,&(status[3]));
1303 ifx_sw_read(0x124,&(status[4]));
1304 ifx_sw_read(0x125,&(status[5]));
1305
1306
1307 mMACENTRY->mac_addr[0]=(status[0]&0x00ff) ;
1308 mMACENTRY->mac_addr[1]=(status[0]&0xff00)>>8 ;
1309 mMACENTRY->mac_addr[2]=(status[1]&0x00ff) ;
1310 mMACENTRY->mac_addr[3]=(status[1]&0xff00)>>8 ;
1311 mMACENTRY->mac_addr[4]=(status[2]&0x00ff) ;
1312 mMACENTRY->mac_addr[5]=(status[2]&0xff00)>>8 ;
1313 mMACENTRY->fid=(status[3]&0xf);
1314 mMACENTRY->portmap=((status[3]>>4)&0x3f);
1315 if (status[5]&0x2) {//static info_ctrl //status5[1]????
1316 mMACENTRY->ctrl.info_ctrl=(status[4]&0x00ff);
1317 mMACENTRY->info_type=1;
1318 }
1319 else {//not static age_timer
1320 mMACENTRY->ctrl.age_timer=(status[4]&0x00ff);
1321 mMACENTRY->info_type=0;
1322 }
1323 //status5[13]???? mMACENTRY->occupy=(status[5]&0x02)>>1;//status5[1]
1324 mMACENTRY->occupy=(status[5]&0x02000)>>13;//status5[13] ???
1325 mMACENTRY->bad=(status[5]&0x04)>>2;//status5[2]
1326 }//if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
1327
1328 }
1329 else if (val==0x001)
1330 printk(" All Entry Used!! \n");
1331 else if (val==0x002)
1332 printk(" Entry Not Found!! \n");
1333 else if (val==0x003)
1334 printk(" Try Next Entry!! \n");
1335 else if (val==0x005)
1336 printk(" Command Error!! \n");
1337 else
1338 printk(" UnKnown Error!! \n");
1339
1340 // printk ("adm_process_mac_table_request: Exit\n");
1341 return 0;
1342 }
1343
1344 /* Santosh: End of function for MAC ENTRY ADD/DEL*/
1345 struct file_operations adm_ops =
1346 {
1347 read: adm_read,
1348 write: adm_write,
1349 open: adm_open,
1350 release: adm_release,
1351 ioctl: adm_ioctl
1352 };
1353
1354 int adm_proc(char *buf, char **start, off_t offset, int count, int *eof, void *data)
1355 {
1356 int len = 0;
1357
1358 len += sprintf(buf+len, " ************ Registers ************ \n");
1359 *eof = 1;
1360 return len;
1361 }
1362
1363 int __init init_adm6996_module(void)
1364 {
1365 unsigned int val = 000;
1366 unsigned int val1 = 000;
1367
1368 printk("Loading ADM6996 driver... \n");
1369
1370 /* if running on adm5120 */
1371 /* set GPIO 0~2 as adm6996 control pins */
1372 //outl(0x003f3f00, 0x12000028);
1373 /* enable switch port 5 (MII) as RMII mode (5120MAC <-> 6996MAC) */
1374 //outl(0x18a, 0x12000030);
1375 /* group adm5120 port 1 ~ 5 as VLAN0, port 5 & 6(CPU) as VLAN1 */
1376 //outl(0x417e, 0x12000040);
1377 /* end adm5120 fixup */
1378 #ifdef ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
1379 register_chrdev(69, "adm6996", &adm_ops);
1380 AMAZON_SW_REG(AMAZON_SW_MDIO_CFG) = 0x27be;
1381 AMAZON_SW_REG(AMAZON_SW_EPHY) = 0xfc;
1382 adm6996_mode=adm6996i;
1383 ifx_sw_read(0xa0, &val);
1384 ifx_sw_read(0xa1, &val1);
1385 val=((val1&0x0f)<<16)|val;
1386 printk ("\nADM6996 SMI Mode-");
1387 printk ("Chip ID:%5x \n ", val);
1388 #else //000001.joelin
1389
1390 AMAZON_SW_REG(AMAZON_SW_MDIO_CFG) = 0x2c50;
1391 AMAZON_SW_REG(AMAZON_SW_EPHY) = 0xff;
1392
1393 AMAZON_SW_REG(AMAZON_GPIO_P1_ALTSEL0) &= ~(GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
1394 AMAZON_SW_REG(AMAZON_GPIO_P1_ALTSEL1) &= ~(GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
1395 AMAZON_SW_REG(AMAZON_GPIO_P1_OD) |= (GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
1396
1397 ifx_gpio_init();
1398 register_chrdev(69, "adm6996", &adm_ops);
1399 mdelay(100);
1400
1401 /* create proc entries */
1402 // create_proc_read_entry("admide", 0, NULL, admide_proc, NULL);
1403
1404 //joelin adm6996i support start
1405 adm6996_mode=adm6996i;
1406 ifx_sw_read(0xa0, &val);
1407 adm6996_mode=adm6996l;
1408 ifx_sw_read(0x200, &val1);
1409 // printk ("\n %0x \n",val1);
1410 if ((val&0xfff0)==0x1020) {
1411 printk ("\n ADM6996I .. \n");
1412 adm6996_mode=adm6996i;
1413 }
1414 else if ((val1&0xffffff00)==0x71000) {//71010 or 71020
1415 printk ("\n ADM6996LC .. \n");
1416 adm6996_mode=adm6996lc;
1417 }
1418 else {
1419 printk ("\n ADM6996L .. \n");
1420 adm6996_mode=adm6996l;
1421 }
1422 #endif //ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
1423
1424 if ((adm6996_mode==adm6996lc)||(adm6996_mode==adm6996i)){
1425 #if 0 /* removed by MarsLin */
1426 ifx_sw_write(0x29,0xc000);
1427 ifx_sw_write(0x30,0x0985);
1428 #else
1429 ifx_sw_read(0xa0, &val);
1430 if (val == 0x1021) // for both 6996LC and 6996I, only AB version need the patch
1431 ifx_sw_write(0x29, 0x9000);
1432 ifx_sw_write(0x30,0x0985);
1433 #endif
1434 }
1435 //joelin adm6996i support end
1436 return 0;
1437 }
1438
1439 void __exit cleanup_adm6996_module(void)
1440 {
1441 printk("Free ADM device driver... \n");
1442
1443 unregister_chrdev(69, "adm6996");
1444
1445 /* remove proc entries */
1446 // remove_proc_entry("admide", NULL);
1447 }
1448
1449 /* MarsLin, add start */
1450 #if defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT) || defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT_MODULE)
1451 #define SET_BIT(reg, mask) reg |= (mask)
1452 #define CLEAR_BIT(reg, mask) reg &= (~mask)
1453 static int ifx_hw_reset(void)
1454 {
1455 CLEAR_BIT((*AMAZON_GPIO_P0_ALTSEL0),0x2000);
1456 CLEAR_BIT((*AMAZON_GPIO_P0_ALTSEL1),0x2000);
1457 SET_BIT((*AMAZON_GPIO_P0_OD),0x2000);
1458 SET_BIT((*AMAZON_GPIO_P0_DIR), 0x2000);
1459 CLEAR_BIT((*AMAZON_GPIO_P0_OUT), 0x2000);
1460 mdelay(500);
1461 SET_BIT((*AMAZON_GPIO_P0_OUT), 0x2000);
1462 cleanup_adm6996_module();
1463 return init_adm6996_module();
1464 }
1465 int (*adm6996_hw_reset)(void) = ifx_hw_reset;
1466 EXPORT_SYMBOL(adm6996_hw_reset);
1467 EXPORT_SYMBOL(adm6996_mode);
1468 int (*adm6996_sw_read)(unsigned int addr, unsigned int *data) = ifx_sw_read;
1469 EXPORT_SYMBOL(adm6996_sw_read);
1470 int (*adm6996_sw_write)(unsigned int addr, unsigned int data) = ifx_sw_write;
1471 EXPORT_SYMBOL(adm6996_sw_write);
1472 #endif
1473 /* MarsLin, add end */
1474
1475 /* Santosh: for IGMP proxy/snooping, Begin */
1476 EXPORT_SYMBOL (adm_process_mac_table_request);
1477 EXPORT_SYMBOL (adm_process_protocol_filter_request);
1478 /* Santosh: for IGMP proxy/snooping, End */
1479
1480 MODULE_DESCRIPTION("ADMtek 6996 Driver");
1481 MODULE_AUTHOR("Joe Lin <joe.lin@infineon.com>");
1482 MODULE_LICENSE("GPL");
1483
1484 module_init(init_adm6996_module);
1485 module_exit(cleanup_adm6996_module);
1486