strip the kernel version suffix from target directories, except for brcm-2.4 (the...
[openwrt.git] / target / linux / amazon / 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