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