Root/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
56unsigned 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};
59unsigned int ifx_sw_bits[8] = \
60    {0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
61unsigned 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
73unsigned int adm6996_mode=adm6996i;
74/*
75  initialize GPIO pins.
76  output mode, low
77*/
78void 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 */
89int 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*/
106void 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
117void 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
128void 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
139void 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
150void 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
161void 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
172void 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*/
187static 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*/
200static 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*/
212static 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*/
256static 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
304static 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
314static 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
432static 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
549static 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
566static 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
577static 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
696static 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
764static 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*/
778int 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*/
791int 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*/
857int 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*/
867int 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*/
887int 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*/
909static 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
930int adm_open(struct inode *node, struct file *filp)
931{
932    return 0;
933}
934
935ssize_t adm_read(struct file *filep, char *buf, size_t count, loff_t *ppos)
936{
937    return count;
938}
939
940ssize_t adm_write(struct file *filep, const char *buf, size_t count, loff_t *ppos)
941{
942    return count;
943}
944
945/* close */
946int 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))
954static long adm_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
955#else
956static 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 */
1210int 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
1246int 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*/
1349struct 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
1362int 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
1371int __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
1447void __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 */
1484EXPORT_SYMBOL (adm_process_mac_table_request);
1485EXPORT_SYMBOL (adm_process_protocol_filter_request);
1486/* Santosh: for IGMP proxy/snooping, End */
1487    
1488MODULE_DESCRIPTION("ADMtek 6996 Driver");
1489MODULE_AUTHOR("Joe Lin <joe.lin@infineon.com>");
1490MODULE_LICENSE("GPL");
1491
1492module_init(init_adm6996_module);
1493module_exit(cleanup_adm6996_module);
1494
1495

Archive Download this file



interactive