source: trunk/target/linux/amazon/files/drivers/net/ethernet/admmod.c @ 31706

Last change on this file since 31706 was 31706, checked in by hauke, 4 years ago

amazon: update amazon target to kernel 3.3

This is just compile tested, my device is currently not working.

File size: 40.5 KB
Line 
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 val;           //6996i
1249    unsigned int control[6] ;   //6996i
1250    unsigned int status[6] ;    //6996i
1251
1252        // printk ("adm_process_mac_table_request: enter\n");   
1253
1254    control[0]=(mMACENTRY->mac_addr[1]<<8)+mMACENTRY->mac_addr[0]     ; 
1255    control[1]=(mMACENTRY->mac_addr[3]<<8)+mMACENTRY->mac_addr[2]      ;         
1256    control[2]=(mMACENTRY->mac_addr[5]<<8)+mMACENTRY->mac_addr[4]     ;
1257    control[3]=(mMACENTRY->fid&0xf)+((mMACENTRY->portmap&0x3f)<<4);
1258
1259    if (((mMACENTRY->info_type)&0x01)) control[4]=(mMACENTRY->ctrl.info_ctrl)+0x1000; //static ,info control
1260                else    control[4]=((mMACENTRY->ctrl.age_timer)&0xff);//not static ,agetimer
1261                if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT) {     
1262                  //initial  the pointer to the first address   
1263                   val=0x8000;//busy ,status5[15]
1264                   while(val&0x8000){           //check busy ?
1265                   ifx_sw_read(0x125, &val);
1266                }   
1267                control[5]=0x030;//initial the first address   
1268                ifx_sw_write(0x11f,control[5]);
1269                                               
1270                                       
1271                                   val=0x8000;//busy ,status5[15]
1272                                   while(val&0x8000){           //check busy ?
1273                                          ifx_sw_read(0x125, &val);
1274                                        }               
1275                       
1276                   }    //if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)                                                             
1277           if (cmd==ADM_SW_IOCTL_MACENTRY_ADD) control[5]=0x07;//create a new address
1278                else if (cmd==ADM_SW_IOCTL_MACENTRY_DEL) control[5]=0x01f;//erased an existed address
1279                else if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE)) 
1280                        control[5]=0x02c;//search by the mac address field
1281           
1282           val=0x8000;//busy ,status5[15]
1283           while(val&0x8000){           //check busy ?
1284                  ifx_sw_read(0x125, &val);
1285                }
1286                ifx_sw_write(0x11a,control[0]); 
1287                ifx_sw_write(0x11b,control[1]); 
1288                ifx_sw_write(0x11c,control[2]); 
1289                ifx_sw_write(0x11d,control[3]); 
1290                ifx_sw_write(0x11e,control[4]); 
1291                ifx_sw_write(0x11f,control[5]); 
1292           val=0x8000;//busy ,status5[15]
1293           while(val&0x8000){           //check busy ?
1294                  ifx_sw_read(0x125, &val);
1295                }       
1296           val=((val&0x7000)>>12);//result ,status5[14:12]
1297           mMACENTRY->result=val;
1298   
1299           if (!val) {
1300                        printk(" Command OK!! \n");
1301                        if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE)) {
1302                                        ifx_sw_read(0x120,&(status[0]));       
1303                                        ifx_sw_read(0x121,&(status[1]));       
1304                                        ifx_sw_read(0x122,&(status[2]));       
1305                                        ifx_sw_read(0x123,&(status[3]));       
1306                                        ifx_sw_read(0x124,&(status[4]));       
1307                                        ifx_sw_read(0x125,&(status[5]));       
1308               
1309                                       
1310                                        mMACENTRY->mac_addr[0]=(status[0]&0x00ff)       ;
1311                                        mMACENTRY->mac_addr[1]=(status[0]&0xff00)>>8    ;
1312                                        mMACENTRY->mac_addr[2]=(status[1]&0x00ff)    ;
1313                                        mMACENTRY->mac_addr[3]=(status[1]&0xff00)>>8 ;
1314                                        mMACENTRY->mac_addr[4]=(status[2]&0x00ff)    ;
1315                                        mMACENTRY->mac_addr[5]=(status[2]&0xff00)>>8 ;
1316                                        mMACENTRY->fid=(status[3]&0xf);
1317                                        mMACENTRY->portmap=((status[3]>>4)&0x3f);
1318                                        if (status[5]&0x2) {//static info_ctrl //status5[1]????
1319                                                mMACENTRY->ctrl.info_ctrl=(status[4]&0x00ff);
1320                                                mMACENTRY->info_type=1;
1321                                                        }
1322                                        else {//not static age_timer
1323                                                mMACENTRY->ctrl.age_timer=(status[4]&0x00ff);
1324                                                mMACENTRY->info_type=0;
1325                                                        }
1326//status5[13]????                                       mMACENTRY->occupy=(status[5]&0x02)>>1;//status5[1]
1327                                        mMACENTRY->occupy=(status[5]&0x02000)>>13;//status5[13] ???
1328                                        mMACENTRY->bad=(status[5]&0x04)>>2;//status5[2]
1329                                }//if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
1330                       
1331                }
1332           else if (val==0x001) 
1333                printk(" All Entry Used!! \n");
1334            else if (val==0x002) 
1335                printk("  Entry Not Found!! \n");
1336            else if (val==0x003) 
1337                printk(" Try Next Entry!! \n");
1338            else if (val==0x005) 
1339                printk(" Command Error!! \n");   
1340            else   
1341                printk(" UnKnown Error!! \n");
1342
1343        // printk ("adm_process_mac_table_request: Exit\n");   
1344        return 0;
1345}
1346
1347/* Santosh: End of function for MAC ENTRY ADD/DEL*/
1348struct file_operations adm_ops =
1349{
1350    read: adm_read,
1351    write: adm_write,
1352    open: adm_open,
1353    release: adm_release,
1354#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
1355    unlocked_ioctl: adm_ioctl
1356#else
1357    ioctl: adm_ioctl
1358#endif
1359};
1360
1361int adm_proc(char *buf, char **start, off_t offset, int count, int *eof, void *data)
1362{
1363    int len = 0;
1364
1365    len += sprintf(buf+len, " ************ Registers ************ \n");
1366    *eof = 1;
1367    return len;
1368}
1369
1370int __init init_adm6996_module(void)
1371{
1372    unsigned int val = 000;
1373    unsigned int val1 = 000;
1374
1375    printk("Loading ADM6996 driver... \n");
1376
1377    /* if running on adm5120 */
1378    /* set GPIO 0~2 as adm6996 control pins */
1379    //outl(0x003f3f00, 0x12000028);
1380    /* enable switch port 5 (MII) as RMII mode (5120MAC <-> 6996MAC) */
1381    //outl(0x18a, 0x12000030);
1382    /* group adm5120 port 1 ~ 5 as VLAN0, port 5 & 6(CPU) as VLAN1 */
1383    //outl(0x417e, 0x12000040);
1384    /* end adm5120 fixup */
1385#ifdef ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
1386    register_chrdev(69, "adm6996", &adm_ops);
1387    AMAZON_SW_REG(AMAZON_SW_MDIO_CFG) = 0x27be;
1388    AMAZON_SW_REG(AMAZON_SW_EPHY) = 0xfc;
1389    adm6996_mode=adm6996i;
1390    ifx_sw_read(0xa0, &val);
1391    ifx_sw_read(0xa1, &val1);
1392    val=((val1&0x0f)<<16)|val;
1393    printk ("\nADM6996 SMI Mode-");
1394    printk ("Chip ID:%5x \n ", val);
1395#else    //000001.joelin
1396 
1397    AMAZON_SW_REG(AMAZON_SW_MDIO_CFG) = 0x2c50;
1398    AMAZON_SW_REG(AMAZON_SW_EPHY) = 0xff;
1399
1400    AMAZON_SW_REG(AMAZON_GPIO_P1_ALTSEL0) &= ~(GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
1401    AMAZON_SW_REG(AMAZON_GPIO_P1_ALTSEL1) &= ~(GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
1402    AMAZON_SW_REG(AMAZON_GPIO_P1_OD) |= (GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
1403 
1404    ifx_gpio_init();
1405    register_chrdev(69, "adm6996", &adm_ops);
1406    mdelay(100);
1407
1408    /* create proc entries */
1409    //  create_proc_read_entry("admide", 0, NULL, admide_proc, NULL);
1410
1411//joelin adm6996i support start
1412    adm6996_mode=adm6996i;
1413    ifx_sw_read(0xa0, &val);
1414    adm6996_mode=adm6996l;
1415    ifx_sw_read(0x200, &val1);
1416//  printk ("\n %0x \n",val1);
1417    if ((val&0xfff0)==0x1020) {
1418        printk ("\n ADM6996I .. \n");
1419        adm6996_mode=adm6996i; 
1420    }
1421    else if ((val1&0xffffff00)==0x71000) {//71010 or 71020
1422        printk ("\n ADM6996LC .. \n");
1423        adm6996_mode=adm6996lc; 
1424    }
1425    else  {
1426        printk ("\n ADM6996L .. \n");
1427        adm6996_mode=adm6996l; 
1428    }
1429#endif //ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin       
1430
1431    if ((adm6996_mode==adm6996lc)||(adm6996_mode==adm6996i)){
1432#if 0   /* removed by MarsLin */
1433        ifx_sw_write(0x29,0xc000);
1434        ifx_sw_write(0x30,0x0985);
1435#else
1436        ifx_sw_read(0xa0, &val);
1437        if (val == 0x1021) // for both 6996LC and 6996I, only AB version need the patch
1438            ifx_sw_write(0x29, 0x9000);
1439        ifx_sw_write(0x30,0x0985);
1440#endif
1441    }
1442//joelin adm6996i support end
1443    return 0;
1444}
1445
1446void __exit cleanup_adm6996_module(void)
1447{
1448    printk("Free ADM device driver... \n");
1449
1450    unregister_chrdev(69, "adm6996");
1451
1452    /* remove proc entries */
1453    //  remove_proc_entry("admide", NULL);
1454}
1455
1456/* MarsLin, add start */
1457#if defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT) || defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT_MODULE)
1458    #define SET_BIT(reg, mask)          reg |= (mask)
1459    #define CLEAR_BIT(reg, mask)        reg &= (~mask)
1460    static int ifx_hw_reset(void)
1461    {
1462        CLEAR_BIT((*AMAZON_GPIO_P0_ALTSEL0),0x2000);
1463        CLEAR_BIT((*AMAZON_GPIO_P0_ALTSEL1),0x2000);
1464        SET_BIT((*AMAZON_GPIO_P0_OD),0x2000);
1465        SET_BIT((*AMAZON_GPIO_P0_DIR), 0x2000);
1466        CLEAR_BIT((*AMAZON_GPIO_P0_OUT), 0x2000);
1467        mdelay(500);
1468        SET_BIT((*AMAZON_GPIO_P0_OUT), 0x2000);
1469        cleanup_adm6996_module();
1470        return init_adm6996_module();
1471    }
1472    int (*adm6996_hw_reset)(void) = ifx_hw_reset;
1473    EXPORT_SYMBOL(adm6996_hw_reset);
1474    EXPORT_SYMBOL(adm6996_mode);
1475    int (*adm6996_sw_read)(unsigned int addr, unsigned int *data) = ifx_sw_read;
1476    EXPORT_SYMBOL(adm6996_sw_read);
1477    int (*adm6996_sw_write)(unsigned int addr, unsigned int data) = ifx_sw_write;
1478    EXPORT_SYMBOL(adm6996_sw_write);
1479#endif
1480/* MarsLin, add end */
1481
1482/* Santosh: for IGMP proxy/snooping, Begin */
1483EXPORT_SYMBOL (adm_process_mac_table_request);
1484EXPORT_SYMBOL (adm_process_protocol_filter_request);
1485/* Santosh: for IGMP proxy/snooping, End */
1486       
1487MODULE_DESCRIPTION("ADMtek 6996 Driver");
1488MODULE_AUTHOR("Joe Lin <joe.lin@infineon.com>");
1489MODULE_LICENSE("GPL");
1490
1491module_init(init_adm6996_module);
1492module_exit(cleanup_adm6996_module);
1493
Note: See TracBrowser for help on using the repository browser.