amazon: Upgrade amazon target to kernel 2.6.37
[openwrt.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