1 /******************************************************************************
2 Copyright (c) 2004, Infineon Technologies. All rights reserved.
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.
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 ******************************************************************************
31 MarsLin, add to support VLAN
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 */
42 #include <linux/module.h>
43 #include <linux/string.h>
44 #include <linux/proc_fs.h>
45 #include <linux/delay.h>
46 #include <asm/uaccess.h>
47 #include <linux/init.h>
48 #include <linux/ioctl.h>
49 #include <asm/atomic.h>
50 #include <asm-mips/amazon/amazon.h>
51 #include <asm-mips/amazon/adm6996.h>
52 //#include <linux/amazon/adm6996.h>
55 unsigned int ifx_sw_conf
[ADM_SW_MAX_PORT_NUM
+1] = \
56 {ADM_SW_PORT0_CONF
, ADM_SW_PORT1_CONF
, ADM_SW_PORT2_CONF
, \
57 ADM_SW_PORT3_CONF
, ADM_SW_PORT4_CONF
, ADM_SW_PORT5_CONF
};
58 unsigned int ifx_sw_bits
[8] = \
59 {0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
60 unsigned int ifx_sw_vlan_port
[6] = {0, 2, 4, 6, 7, 8};
62 /* 507281:linmars start */
63 #ifdef CONFIG_SWITCH_ADM6996_MDIO
64 #define ADM6996_MDC_MDIO_MODE 1 //000001.joelin
66 #undef ADM6996_MDC_MDIO_MODE
68 /* 507281:linmars end */
72 unsigned int adm6996_mode
=adm6996i
;
77 void ifx_gpio_init(void)
79 //GPIO16,17,18 direction:output
80 //GPIO16,17,18 output 0
82 AMAZON_SW_REG(AMAZON_GPIO_P1_DIR
) |= (GPIO_MDIO
|GPIO_MDCS
|GPIO_MDC
);
83 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
) =AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)& ~(GPIO_MDIO
|GPIO_MDCS
|GPIO_MDC
);
87 /* read one bit from mdio port */
88 int ifx_sw_mdio_readbit(void)
92 //val = (AMAZON_SW_REG(GPIO_conf0_REG) & GPIO0_INPUT_MASK) >> 8;
95 return AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)&1;
103 switch input/output mode of GPIO 0
105 void ifx_mdio_mode(int mode
)
107 // AMAZON_SW_REG(GPIO_conf0_REG) = mode ? GPIO_ENABLEBITS :
108 // ((GPIO_ENABLEBITS | MDIO_INPUT) & ~MDIO_OUTPUT_EN);
109 mode
?(AMAZON_SW_REG(AMAZON_GPIO_P1_DIR
)|=GPIO_MDIO
):
110 (AMAZON_SW_REG(AMAZON_GPIO_P1_DIR
)&=~GPIO_MDIO
);
111 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_DIR);
112 mode?(r|=GPIO_MDIO):(r&=~GPIO_MDIO);
113 AMAZON_SW_REG(AMAZON_GPIO_P1_DIR)=r;*/
116 void ifx_mdc_hi(void)
118 //GPIO_SET_HI(GPIO_MDC);
119 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)|=GPIO_MDC;
120 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
122 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
124 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)|GPIO_MDC
;
127 void ifx_mdio_hi(void)
129 //GPIO_SET_HI(GPIO_MDIO);
130 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)|=GPIO_MDIO;
131 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
133 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
135 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)|GPIO_MDIO
;
138 void ifx_mdcs_hi(void)
140 //GPIO_SET_HI(GPIO_MDCS);
141 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)|=GPIO_MDCS;
142 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
144 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
146 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)|GPIO_MDCS
;
149 void ifx_mdc_lo(void)
151 //GPIO_SET_LOW(GPIO_MDC);
152 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)&=~GPIO_MDC;
153 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
155 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
157 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)&(~GPIO_MDC
);
160 void ifx_mdio_lo(void)
162 //GPIO_SET_LOW(GPIO_MDIO);
163 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)&=~GPIO_MDIO;
164 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
166 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
168 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)&(~GPIO_MDIO
);
171 void ifx_mdcs_lo(void)
173 //GPIO_SET_LOW(GPIO_MDCS);
174 //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)&=~GPIO_MDCS;
175 /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
177 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
179 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)&(~GPIO_MDCS
);
186 static void ifx_sw_mdc_pulse(void)
189 udelay(ADM_SW_MDC_DOWN_DELAY
);
191 udelay(ADM_SW_MDC_UP_DELAY
);
199 static void ifx_sw_mdc_toggle(void)
202 udelay(ADM_SW_MDC_UP_DELAY
);
204 udelay(ADM_SW_MDC_DOWN_DELAY
);
209 For ATC 93C66 type EEPROM; accessing ADM6996 internal EEPROM type registers
211 static void ifx_sw_eeprom_write_enable(void)
218 udelay(ADM_SW_CS_DELAY
);
219 /* enable chip select */
221 udelay(ADM_SW_CS_DELAY
);
226 /* eeprom write enable */
227 op
= ADM_SW_BIT_MASK_4
;
230 if (op
& ADM_SW_EEPROM_WRITE_ENABLE
)
239 op
= ADM_SW_BIT_MASK_1
<< (EEPROM_TYPE
- 3);
246 /* disable chip select */
248 udelay(ADM_SW_CS_DELAY
);
255 static void ifx_sw_eeprom_write_disable(void)
262 udelay(ADM_SW_CS_DELAY
);
263 /* enable chip select */
265 udelay(ADM_SW_CS_DELAY
);
270 /* eeprom write disable */
271 op
= ADM_SW_BIT_MASK_4
;
274 if (op
& ADM_SW_EEPROM_WRITE_DISABLE
)
283 op
= ADM_SW_BIT_MASK_1
<< (EEPROM_TYPE
- 3);
291 /* disable chip select */
293 udelay(ADM_SW_CS_DELAY
);
298 read registers from ADM6996
299 serial registers start at 0x200 (addr bit 9 = 1b)
300 EEPROM registers -> 16bits; Serial registers -> 32bits
302 #ifdef ADM6996_MDC_MDIO_MODE //smi mode//000001.joelin
303 static int ifx_sw_read_adm6996i_smi(unsigned int addr
, unsigned int *dat
)
305 addr
=(addr
<<16)&0x3ff0000;
306 AMAZON_SW_REG(AMAZON_SW_MDIO_ACC
) =(0xC0000000|addr
);
307 while ((AMAZON_SW_REG(AMAZON_SW_MDIO_ACC
))&0x80000000){};
308 *dat
=((AMAZON_SW_REG(AMAZON_SW_MDIO_ACC
))&0x0FFFF);
313 static int ifx_sw_read_adm6996i(unsigned int addr
, unsigned int *dat
)
320 udelay(ADM_SW_CS_DELAY
);
326 udelay(ADM_SW_CS_DELAY
);
328 /* preamble, 32 bit 1 */
330 op
= ADM_SW_BIT_MASK_32
;
337 /* command start (01b) */
338 op
= ADM_SW_BIT_MASK_2
;
341 if (op
& ADM_SW_SMI_START
)
350 /* read command (10b) */
351 op
= ADM_SW_BIT_MASK_2
;
354 if (op
& ADM_SW_SMI_READ
)
363 /* send address A9 ~ A0 */
364 op
= ADM_SW_BIT_MASK_10
;
376 /* turnaround bits */
377 op
= ADM_SW_BIT_MASK_2
;
385 udelay(ADM_SW_MDC_DOWN_DELAY
);
387 /* set MDIO pin to input mode */
388 ifx_mdio_mode(ADM_SW_MDIO_INPUT
);
390 /* start read data */
392 //adm6996i op = ADM_SW_BIT_MASK_32;
393 op
= ADM_SW_BIT_MASK_16
;//adm6996i
397 if (ifx_sw_mdio_readbit()) *dat
|= 1;
403 /* set MDIO to output mode */
404 ifx_mdio_mode(ADM_SW_MDIO_OUTPUT
);
407 op
= ADM_SW_BIT_MASK_4
;
419 /* EEPROM registers */
420 //adm6996i if (!(addr & 0x200))
422 //adm6996i if (addr % 2)
423 //adm6996i *dat >>= 16;
425 //adm6996i *dat &= 0xffff;
431 static int ifx_sw_read_adm6996l(unsigned int addr
, unsigned int *dat
)
438 udelay(ADM_SW_CS_DELAY
);
444 udelay(ADM_SW_CS_DELAY
);
446 /* preamble, 32 bit 1 */
448 op
= ADM_SW_BIT_MASK_32
;
455 /* command start (01b) */
456 op
= ADM_SW_BIT_MASK_2
;
459 if (op
& ADM_SW_SMI_START
)
468 /* read command (10b) */
469 op
= ADM_SW_BIT_MASK_2
;
472 if (op
& ADM_SW_SMI_READ
)
481 /* send address A9 ~ A0 */
482 op
= ADM_SW_BIT_MASK_10
;
494 /* turnaround bits */
495 op
= ADM_SW_BIT_MASK_2
;
503 udelay(ADM_SW_MDC_DOWN_DELAY
);
505 /* set MDIO pin to input mode */
506 ifx_mdio_mode(ADM_SW_MDIO_INPUT
);
508 /* start read data */
510 op
= ADM_SW_BIT_MASK_32
;
514 if (ifx_sw_mdio_readbit()) *dat
|= 1;
520 /* set MDIO to output mode */
521 ifx_mdio_mode(ADM_SW_MDIO_OUTPUT
);
524 op
= ADM_SW_BIT_MASK_4
;
536 /* EEPROM registers */
548 static int ifx_sw_read(unsigned int addr
, unsigned int *dat
)
550 #ifdef ADM6996_MDC_MDIO_MODE //smi mode ////000001.joelin
551 ifx_sw_read_adm6996i_smi(addr
,dat
);
553 if (adm6996_mode
==adm6996i
) ifx_sw_read_adm6996i(addr
,dat
);
554 else ifx_sw_read_adm6996l(addr
,dat
);
561 write register to ADM6996 eeprom registers
563 //for adm6996i -start
564 #ifdef ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
565 static int ifx_sw_write_adm6996i_smi(unsigned int addr
, unsigned int dat
)
568 AMAZON_SW_REG(AMAZON_SW_MDIO_ACC
) = ((addr
<<16)&0x3ff0000)|dat
|0x80000000;
569 while ((AMAZON_SW_REG(AMAZON_SW_MDIO_ACC
))&0x80000000){};
574 #endif //ADM6996_MDC_MDIO_MODE //000001.joelin
576 static int ifx_sw_write_adm6996i(unsigned int addr
, unsigned int dat
)
583 udelay(ADM_SW_CS_DELAY
);
589 udelay(ADM_SW_CS_DELAY
);
591 /* preamble, 32 bit 1 */
593 op
= ADM_SW_BIT_MASK_32
;
600 /* command start (01b) */
601 op
= ADM_SW_BIT_MASK_2
;
604 if (op
& ADM_SW_SMI_START
)
613 /* write command (01b) */
614 op
= ADM_SW_BIT_MASK_2
;
617 if (op
& ADM_SW_SMI_WRITE
)
626 /* send address A9 ~ A0 */
627 op
= ADM_SW_BIT_MASK_10
;
639 /* turnaround bits */
640 op
= ADM_SW_BIT_MASK_2
;
648 udelay(ADM_SW_MDC_DOWN_DELAY
);
650 /* set MDIO pin to output mode */
651 ifx_mdio_mode(ADM_SW_MDIO_OUTPUT
);
654 /* start write data */
655 op
= ADM_SW_BIT_MASK_16
;
667 // /* set MDIO to output mode */
668 // ifx_mdio_mode(ADM_SW_MDIO_OUTPUT);
671 op
= ADM_SW_BIT_MASK_4
;
683 /* EEPROM registers */
684 //adm6996i if (!(addr & 0x200))
686 //adm6996i if (addr % 2)
687 //adm6996i *dat >>= 16;
689 //adm6996i *dat &= 0xffff;
695 static int ifx_sw_write_adm6996l(unsigned int addr
, unsigned int dat
)
702 ifx_sw_eeprom_write_enable();
706 udelay(ADM_SW_CS_DELAY
);
708 /* issue write command */
713 /* EEPROM write command */
714 op
= ADM_SW_BIT_MASK_2
;
717 if (op
& ADM_SW_EEPROM_WRITE
)
726 /* send address A7 ~ A0 */
727 op
= ADM_SW_BIT_MASK_1
<< (EEPROM_TYPE
- 1);
740 /* start write data */
741 op
= ADM_SW_BIT_MASK_16
;
753 /* disable cs & wait 1 clock */
755 udelay(ADM_SW_CS_DELAY
);
758 ifx_sw_eeprom_write_disable();
763 static int ifx_sw_write(unsigned int addr
, unsigned int dat
)
765 #ifdef ADM6996_MDC_MDIO_MODE //smi mode ////000001.joelin
766 ifx_sw_write_adm6996i_smi(addr
,dat
);
767 #else //000001.joelin
768 if (adm6996_mode
==adm6996i
) ifx_sw_write_adm6996i(addr
,dat
);
769 else ifx_sw_write_adm6996l(addr
,dat
);
770 #endif //000001.joelin
777 int ifx_sw_reset(void)
780 ifx_sw_write(ADM_SW_PHY_RESET
, 0);
785 /* 509201:linmars start */
790 int ifx_check_port_status(int port
)
794 if ((port
< 0) || (port
> ADM_SW_MAX_PORT_NUM
))
796 ifx_printf(("error on port number (%d)!!\n", port
));
800 ifx_sw_read(ifx_sw_conf
[port
], &val
);
801 if (ifx_sw_conf
[port
]%2) val
>>= 16;
802 /* only 16bits are effective */
805 ifx_printf(("Port %d status (%.8x): \n", port
, val
));
807 if (val
& ADM_SW_PORT_FLOWCTL
)
808 ifx_printf(("\t802.3x flow control supported!\n"));
810 ifx_printf(("\t802.3x flow control not supported!\n"));
812 if (val
& ADM_SW_PORT_AN
)
813 ifx_printf(("\tAuto negotiation ON!\n"));
815 ifx_printf(("\tAuto negotiation OFF!\n"));
817 if (val
& ADM_SW_PORT_100M
)
818 ifx_printf(("\tLink at 100M!\n"));
820 ifx_printf(("\tLink at 10M!\n"));
822 if (val
& ADM_SW_PORT_FULL
)
823 ifx_printf(("\tFull duplex!\n"));
825 ifx_printf(("\tHalf duplex!\n"));
827 if (val
& ADM_SW_PORT_DISABLE
)
828 ifx_printf(("\tPort disabled!\n"));
830 ifx_printf(("\tPort enabled!\n"));
832 if (val
& ADM_SW_PORT_TOS
)
833 ifx_printf(("\tTOS enabled!\n"));
835 ifx_printf(("\tTOS disabled!\n"));
837 if (val
& ADM_SW_PORT_PPRI
)
838 ifx_printf(("\tPort priority first!\n"));
840 ifx_printf(("\tVLAN or TOS priority first!\n"));
842 if (val
& ADM_SW_PORT_MDIX
)
843 ifx_printf(("\tAuto MDIX!\n"));
845 ifx_printf(("\tNo auto MDIX\n"));
847 ifx_printf(("\tPVID: %d\n", \
848 ((val
>> ADM_SW_PORT_PVID_SHIFT
)&ifx_sw_bits
[ADM_SW_PORT_PVID_BITS
])));
856 int ifx_sw_vlan_init(int vlanid
)
858 ifx_sw_write(ADM_SW_VLAN0_CONF
+ vlanid
, 0);
864 add a port to certain vlan
866 int ifx_sw_vlan_add(int port
, int vlanid
)
870 if ((port
< 0) || (port
> ADM_SW_MAX_PORT_NUM
) || (vlanid
< 0) ||
871 (vlanid
> ADM_SW_MAX_VLAN_NUM
))
873 ifx_printf(("Port number or VLAN number ERROR!!\n"));
876 ifx_sw_read(ADM_SW_VLAN0_CONF
+ vlanid
, ®
);
877 reg
|= (1 << ifx_sw_vlan_port
[port
]);
878 ifx_sw_write(ADM_SW_VLAN0_CONF
+ vlanid
, reg
);
884 delete a given port from certain vlan
886 int ifx_sw_vlan_del(int port
, int vlanid
)
888 unsigned int reg
= 0;
890 if ((port
< 0) || (port
> ADM_SW_MAX_PORT_NUM
) || (vlanid
< 0) || (vlanid
> ADM_SW_MAX_VLAN_NUM
))
892 ifx_printf(("Port number or VLAN number ERROR!!\n"));
895 ifx_sw_read(ADM_SW_VLAN0_CONF
+ vlanid
, ®
);
896 reg
&= ~(1 << ifx_sw_vlan_port
[port
]);
897 ifx_sw_write(ADM_SW_VLAN0_CONF
+ vlanid
, reg
);
905 port 0~3 as untag port and PVID = 1
906 VLAN1: port 0~3 and port 5 (MII)
908 static int ifx_sw_init(void)
910 ifx_printf(("Setting default ADM6996 registers... \n"));
912 /* MAC clone, 802.1q based VLAN */
913 ifx_sw_write(ADM_SW_VLAN_MODE
, 0xff30);
914 /* auto MDIX, PVID=1, untag */
915 ifx_sw_write(ADM_SW_PORT0_CONF
, 0x840f);
916 ifx_sw_write(ADM_SW_PORT1_CONF
, 0x840f);
917 ifx_sw_write(ADM_SW_PORT2_CONF
, 0x840f);
918 ifx_sw_write(ADM_SW_PORT3_CONF
, 0x840f);
919 /* auto MDIX, PVID=2, untag */
920 ifx_sw_write(ADM_SW_PORT5_CONF
, 0x880f);
921 /* port 0~3 & 5 as VLAN1 */
922 ifx_sw_write(ADM_SW_VLAN0_CONF
+1, 0x0155);
927 /* 509201:linmars end */
929 int adm_open(struct inode
*node
, struct file
*filp
)
935 ssize_t
adm_read(struct file
*filep
, char *buf
, size_t count
, loff_t
*ppos
)
940 ssize_t
adm_write(struct file
*filep
, const char *buf
, size_t count
, loff_t
*ppos
)
946 int adm_release(struct inode
*inode
, struct file
*filp
)
953 int adm_ioctl(struct inode
*inode
, struct file
*filp
, unsigned int cmd
, unsigned long args
)
957 unsigned int val
; //6996i
958 unsigned int control
[6] ; //6996i
959 unsigned int status
[6] ; //6996i
961 PMACENTRY mMACENTRY
;//adm6996i
962 PPROTOCOLFILTER uPROTOCOLFILTER
;///adm6996i
964 if (_IOC_TYPE(cmd
) != ADM_MAGIC
)
966 printk("adm_ioctl: IOC_TYPE(%x) != ADM_MAGIC(%x)! \n", _IOC_TYPE(cmd
), ADM_MAGIC
);
970 if(_IOC_NR(cmd
) >= KEY_IOCTL_MAX_KEY
)
972 printk(KERN_WARNING
"adm_ioctl: IOC_NR(%x) invalid! \n", _IOC_NR(cmd
));
978 case ADM_IOCTL_REGRW
:
980 uREGRW
= (PREGRW
)kmalloc(sizeof(REGRW
), GFP_KERNEL
);
981 rtval
= copy_from_user(uREGRW
, (PREGRW
)args
, sizeof(REGRW
));
984 printk("ADM_IOCTL_REGRW: copy from user FAILED!! \n");
991 uREGRW
->value
= 0x12345678;//inl(uREGRW->addr);
992 copy_to_user((PREGRW
)args
, uREGRW
, sizeof(REGRW
));
995 //outl(uREGRW->value, uREGRW->addr);
999 printk("No such Register Read/Write function!! \n");
1006 case ADM_SW_IOCTL_REGRW
:
1008 unsigned int val
= 0xff;
1010 uREGRW
= (PREGRW
)kmalloc(sizeof(REGRW
), GFP_KERNEL
);
1011 rtval
= copy_from_user(uREGRW
, (PREGRW
)args
, sizeof(REGRW
));
1014 printk("ADM_IOCTL_REGRW: copy from user FAILED!! \n");
1018 switch(uREGRW
->mode
)
1021 ifx_sw_read(uREGRW
->addr
, &val
);
1022 uREGRW
->value
= val
;
1023 copy_to_user((PREGRW
)args
, uREGRW
, sizeof(REGRW
));
1027 ifx_sw_write(uREGRW
->addr
, uREGRW
->value
);
1030 printk("No such Register Read/Write function!! \n");
1036 /* 509201:linmars start */
1038 case ADM_SW_IOCTL_PORTSTS
:
1039 for (rtval
= 0; rtval
< ADM_SW_MAX_PORT_NUM
+1; rtval
++)
1040 ifx_check_port_status(rtval
);
1042 case ADM_SW_IOCTL_INIT
:
1046 /* 509201:linmars end */
1048 case ADM_SW_IOCTL_MACENTRY_ADD
:
1049 case ADM_SW_IOCTL_MACENTRY_DEL
:
1050 case ADM_SW_IOCTL_MACENTRY_GET_INIT
:
1051 case ADM_SW_IOCTL_MACENTRY_GET_MORE
:
1054 mMACENTRY
= (PMACENTRY
)kmalloc(sizeof(MACENTRY
), GFP_KERNEL
);
1055 rtval
= copy_from_user(mMACENTRY
, (PMACENTRY
)args
, sizeof(MACENTRY
));
1058 printk("ADM_SW_IOCTL_MACENTRY: copy from user FAILED!! \n");
1061 control
[0]=(mMACENTRY
->mac_addr
[1]<<8)+mMACENTRY
->mac_addr
[0] ;
1062 control
[1]=(mMACENTRY
->mac_addr
[3]<<8)+mMACENTRY
->mac_addr
[2] ;
1063 control
[2]=(mMACENTRY
->mac_addr
[5]<<8)+mMACENTRY
->mac_addr
[4] ;
1064 control
[3]=(mMACENTRY
->fid
&0xf)+((mMACENTRY
->portmap
&0x3f)<<4);
1065 if (((mMACENTRY
->info_type
)&0x01)) control
[4]=(mMACENTRY
->ctrl
.info_ctrl
)+0x1000; //static ,info control
1066 else control
[4]=((mMACENTRY
->ctrl
.age_timer
)&0xff);//not static ,agetimer
1067 if (cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
) {
1068 //initial the pointer to the first address
1069 val
=0x8000;//busy ,status5[15]
1070 while(val
&0x8000){ //check busy ?
1071 ifx_sw_read(0x125, &val
);
1073 control
[5]=0x030;//initial the first address
1074 ifx_sw_write(0x11f,control
[5]);
1077 val
=0x8000;//busy ,status5[15]
1078 while(val
&0x8000){ //check busy ?
1079 ifx_sw_read(0x125, &val
);
1082 } //if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)
1083 if (cmd
==ADM_SW_IOCTL_MACENTRY_ADD
) control
[5]=0x07;//create a new address
1084 else if (cmd
==ADM_SW_IOCTL_MACENTRY_DEL
) control
[5]=0x01f;//erased an existed address
1085 else if ((cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
)||(cmd
==ADM_SW_IOCTL_MACENTRY_GET_MORE
))
1086 control
[5]=0x02c;//search by the mac address field
1088 val
=0x8000;//busy ,status5[15]
1089 while(val
&0x8000){ //check busy ?
1090 ifx_sw_read(0x125, &val
);
1092 ifx_sw_write(0x11a,control
[0]);
1093 ifx_sw_write(0x11b,control
[1]);
1094 ifx_sw_write(0x11c,control
[2]);
1095 ifx_sw_write(0x11d,control
[3]);
1096 ifx_sw_write(0x11e,control
[4]);
1097 ifx_sw_write(0x11f,control
[5]);
1098 val
=0x8000;//busy ,status5[15]
1099 while(val
&0x8000){ //check busy ?
1100 ifx_sw_read(0x125, &val
);
1102 val
=((val
&0x7000)>>12);//result ,status5[14:12]
1103 mMACENTRY
->result
=val
;
1106 printk(" Command OK!! \n");
1107 if ((cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
)||(cmd
==ADM_SW_IOCTL_MACENTRY_GET_MORE
)) {
1108 ifx_sw_read(0x120,&(status
[0]));
1109 ifx_sw_read(0x121,&(status
[1]));
1110 ifx_sw_read(0x122,&(status
[2]));
1111 ifx_sw_read(0x123,&(status
[3]));
1112 ifx_sw_read(0x124,&(status
[4]));
1113 ifx_sw_read(0x125,&(status
[5]));
1116 mMACENTRY
->mac_addr
[0]=(status
[0]&0x00ff) ;
1117 mMACENTRY
->mac_addr
[1]=(status
[0]&0xff00)>>8 ;
1118 mMACENTRY
->mac_addr
[2]=(status
[1]&0x00ff) ;
1119 mMACENTRY
->mac_addr
[3]=(status
[1]&0xff00)>>8 ;
1120 mMACENTRY
->mac_addr
[4]=(status
[2]&0x00ff) ;
1121 mMACENTRY
->mac_addr
[5]=(status
[2]&0xff00)>>8 ;
1122 mMACENTRY
->fid
=(status
[3]&0xf);
1123 mMACENTRY
->portmap
=((status
[3]>>4)&0x3f);
1124 if (status
[5]&0x2) {//static info_ctrl //status5[1]????
1125 mMACENTRY
->ctrl
.info_ctrl
=(status
[4]&0x00ff);
1126 mMACENTRY
->info_type
=1;
1128 else {//not static age_timer
1129 mMACENTRY
->ctrl
.age_timer
=(status
[4]&0x00ff);
1130 mMACENTRY
->info_type
=0;
1132 //status5[13]???? mMACENTRY->occupy=(status[5]&0x02)>>1;//status5[1]
1133 mMACENTRY
->occupy
=(status
[5]&0x02000)>>13;//status5[13] ???
1134 mMACENTRY
->bad
=(status
[5]&0x04)>>2;//status5[2]
1135 }//if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
1138 else if (val
==0x001)
1139 printk(" All Entry Used!! \n");
1140 else if (val
==0x002)
1141 printk(" Entry Not Found!! \n");
1142 else if (val
==0x003)
1143 printk(" Try Next Entry!! \n");
1144 else if (val
==0x005)
1145 printk(" Command Error!! \n");
1147 printk(" UnKnown Error!! \n");
1149 copy_to_user((PMACENTRY
)args
, mMACENTRY
,sizeof(MACENTRY
));
1153 case ADM_SW_IOCTL_FILTER_ADD
:
1154 case ADM_SW_IOCTL_FILTER_DEL
:
1155 case ADM_SW_IOCTL_FILTER_GET
:
1157 uPROTOCOLFILTER
= (PPROTOCOLFILTER
)kmalloc(sizeof(PROTOCOLFILTER
), GFP_KERNEL
);
1158 rtval
= copy_from_user(uPROTOCOLFILTER
, (PPROTOCOLFILTER
)args
, sizeof(PROTOCOLFILTER
));
1161 printk("ADM_SW_IOCTL_FILTER_ADD: copy from user FAILED!! \n");
1165 if(cmd
==ADM_SW_IOCTL_FILTER_DEL
) { //delete filter
1166 uPROTOCOLFILTER
->ip_p
=00; //delet filter
1167 uPROTOCOLFILTER
->action
=00; //delete filter
1170 ifx_sw_read(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), &val
);//rx68~rx6b,protocol filter0~7
1172 if (((uPROTOCOLFILTER
->protocol_filter_num
)%2)==00){
1173 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) uPROTOCOLFILTER
->ip_p
= val
&0x00ff;//get filter ip_p
1174 else val
=(val
&0xff00)|(uPROTOCOLFILTER
->ip_p
);//set filter ip_p
1177 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) uPROTOCOLFILTER
->ip_p
= (val
>>8);//get filter ip_p
1178 else val
=(val
&0x00ff)|((uPROTOCOLFILTER
->ip_p
)<<8);//set filter ip_p
1180 if(cmd
!=ADM_SW_IOCTL_FILTER_GET
) ifx_sw_write(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), val
);//write rx68~rx6b,protocol filter0~7
1182 ifx_sw_read(0x95, &val
); //protocol filter action
1183 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) {
1184 uPROTOCOLFILTER
->action
= ((val
>>(uPROTOCOLFILTER
->protocol_filter_num
*2))&0x3);//get filter action
1185 copy_to_user((PPROTOCOLFILTER
)args
, uPROTOCOLFILTER
, sizeof(PROTOCOLFILTER
));
1189 val
=(val
&(~(0x03<<(uPROTOCOLFILTER
->protocol_filter_num
*2))))|(((uPROTOCOLFILTER
->action
)&0x03)<<(uPROTOCOLFILTER
->protocol_filter_num
*2));
1190 // printk("%d----\n",val);
1191 ifx_sw_write(0x95, val
); //write protocol filter action
1205 /* Santosh: handle IGMP protocol filter ADD/DEL/GET */
1206 int adm_process_protocol_filter_request (unsigned int cmd
, PPROTOCOLFILTER uPROTOCOLFILTER
)
1208 unsigned int val
; //6996i
1210 if(cmd
==ADM_SW_IOCTL_FILTER_DEL
) { //delete filter
1211 uPROTOCOLFILTER
->ip_p
=00; //delet filter
1212 uPROTOCOLFILTER
->action
=00; //delete filter
1215 ifx_sw_read(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), &val
);//rx68~rx6b,protocol filter0~7
1217 if (((uPROTOCOLFILTER
->protocol_filter_num
)%2)==00){
1218 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) uPROTOCOLFILTER
->ip_p
= val
&0x00ff;//get filter ip_p
1219 else val
=(val
&0xff00)|(uPROTOCOLFILTER
->ip_p
);//set filter ip_p
1222 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) uPROTOCOLFILTER
->ip_p
= (val
>>8);//get filter ip_p
1223 else val
=(val
&0x00ff)|((uPROTOCOLFILTER
->ip_p
)<<8);//set filter ip_p
1225 if(cmd
!=ADM_SW_IOCTL_FILTER_GET
) ifx_sw_write(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), val
);//write rx68~rx6b,protocol filter0~7
1227 ifx_sw_read(0x95, &val
); //protocol filter action
1228 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) {
1229 uPROTOCOLFILTER
->action
= ((val
>>(uPROTOCOLFILTER
->protocol_filter_num
*2))&0x3);//get filter action
1232 val
=(val
&(~(0x03<<(uPROTOCOLFILTER
->protocol_filter_num
*2))))|(((uPROTOCOLFILTER
->action
)&0x03)<<(uPROTOCOLFILTER
->protocol_filter_num
*2));
1233 ifx_sw_write(0x95, val
); //write protocol filter action
1240 /* Santosh: function for MAC ENTRY ADD/DEL/GET */
1242 int adm_process_mac_table_request (unsigned int cmd
, PMACENTRY mMACENTRY
)
1245 unsigned int val
; //6996i
1246 unsigned int control
[6] ; //6996i
1247 unsigned int status
[6] ; //6996i
1249 // printk ("adm_process_mac_table_request: enter\n");
1251 control
[0]=(mMACENTRY
->mac_addr
[1]<<8)+mMACENTRY
->mac_addr
[0] ;
1252 control
[1]=(mMACENTRY
->mac_addr
[3]<<8)+mMACENTRY
->mac_addr
[2] ;
1253 control
[2]=(mMACENTRY
->mac_addr
[5]<<8)+mMACENTRY
->mac_addr
[4] ;
1254 control
[3]=(mMACENTRY
->fid
&0xf)+((mMACENTRY
->portmap
&0x3f)<<4);
1256 if (((mMACENTRY
->info_type
)&0x01)) control
[4]=(mMACENTRY
->ctrl
.info_ctrl
)+0x1000; //static ,info control
1257 else control
[4]=((mMACENTRY
->ctrl
.age_timer
)&0xff);//not static ,agetimer
1258 if (cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
) {
1259 //initial the pointer to the first address
1260 val
=0x8000;//busy ,status5[15]
1261 while(val
&0x8000){ //check busy ?
1262 ifx_sw_read(0x125, &val
);
1264 control
[5]=0x030;//initial the first address
1265 ifx_sw_write(0x11f,control
[5]);
1268 val
=0x8000;//busy ,status5[15]
1269 while(val
&0x8000){ //check busy ?
1270 ifx_sw_read(0x125, &val
);
1273 } //if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)
1274 if (cmd
==ADM_SW_IOCTL_MACENTRY_ADD
) control
[5]=0x07;//create a new address
1275 else if (cmd
==ADM_SW_IOCTL_MACENTRY_DEL
) control
[5]=0x01f;//erased an existed address
1276 else if ((cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
)||(cmd
==ADM_SW_IOCTL_MACENTRY_GET_MORE
))
1277 control
[5]=0x02c;//search by the mac address field
1279 val
=0x8000;//busy ,status5[15]
1280 while(val
&0x8000){ //check busy ?
1281 ifx_sw_read(0x125, &val
);
1283 ifx_sw_write(0x11a,control
[0]);
1284 ifx_sw_write(0x11b,control
[1]);
1285 ifx_sw_write(0x11c,control
[2]);
1286 ifx_sw_write(0x11d,control
[3]);
1287 ifx_sw_write(0x11e,control
[4]);
1288 ifx_sw_write(0x11f,control
[5]);
1289 val
=0x8000;//busy ,status5[15]
1290 while(val
&0x8000){ //check busy ?
1291 ifx_sw_read(0x125, &val
);
1293 val
=((val
&0x7000)>>12);//result ,status5[14:12]
1294 mMACENTRY
->result
=val
;
1297 printk(" Command OK!! \n");
1298 if ((cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
)||(cmd
==ADM_SW_IOCTL_MACENTRY_GET_MORE
)) {
1299 ifx_sw_read(0x120,&(status
[0]));
1300 ifx_sw_read(0x121,&(status
[1]));
1301 ifx_sw_read(0x122,&(status
[2]));
1302 ifx_sw_read(0x123,&(status
[3]));
1303 ifx_sw_read(0x124,&(status
[4]));
1304 ifx_sw_read(0x125,&(status
[5]));
1307 mMACENTRY
->mac_addr
[0]=(status
[0]&0x00ff) ;
1308 mMACENTRY
->mac_addr
[1]=(status
[0]&0xff00)>>8 ;
1309 mMACENTRY
->mac_addr
[2]=(status
[1]&0x00ff) ;
1310 mMACENTRY
->mac_addr
[3]=(status
[1]&0xff00)>>8 ;
1311 mMACENTRY
->mac_addr
[4]=(status
[2]&0x00ff) ;
1312 mMACENTRY
->mac_addr
[5]=(status
[2]&0xff00)>>8 ;
1313 mMACENTRY
->fid
=(status
[3]&0xf);
1314 mMACENTRY
->portmap
=((status
[3]>>4)&0x3f);
1315 if (status
[5]&0x2) {//static info_ctrl //status5[1]????
1316 mMACENTRY
->ctrl
.info_ctrl
=(status
[4]&0x00ff);
1317 mMACENTRY
->info_type
=1;
1319 else {//not static age_timer
1320 mMACENTRY
->ctrl
.age_timer
=(status
[4]&0x00ff);
1321 mMACENTRY
->info_type
=0;
1323 //status5[13]???? mMACENTRY->occupy=(status[5]&0x02)>>1;//status5[1]
1324 mMACENTRY
->occupy
=(status
[5]&0x02000)>>13;//status5[13] ???
1325 mMACENTRY
->bad
=(status
[5]&0x04)>>2;//status5[2]
1326 }//if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
1329 else if (val
==0x001)
1330 printk(" All Entry Used!! \n");
1331 else if (val
==0x002)
1332 printk(" Entry Not Found!! \n");
1333 else if (val
==0x003)
1334 printk(" Try Next Entry!! \n");
1335 else if (val
==0x005)
1336 printk(" Command Error!! \n");
1338 printk(" UnKnown Error!! \n");
1340 // printk ("adm_process_mac_table_request: Exit\n");
1344 /* Santosh: End of function for MAC ENTRY ADD/DEL*/
1345 struct file_operations adm_ops
=
1350 release
: adm_release
,
1354 int adm_proc(char *buf
, char **start
, off_t offset
, int count
, int *eof
, void *data
)
1358 len
+= sprintf(buf
+len
, " ************ Registers ************ \n");
1363 int __init
init_adm6996_module(void)
1365 unsigned int val
= 000;
1366 unsigned int val1
= 000;
1368 printk("Loading ADM6996 driver... \n");
1370 /* if running on adm5120 */
1371 /* set GPIO 0~2 as adm6996 control pins */
1372 //outl(0x003f3f00, 0x12000028);
1373 /* enable switch port 5 (MII) as RMII mode (5120MAC <-> 6996MAC) */
1374 //outl(0x18a, 0x12000030);
1375 /* group adm5120 port 1 ~ 5 as VLAN0, port 5 & 6(CPU) as VLAN1 */
1376 //outl(0x417e, 0x12000040);
1377 /* end adm5120 fixup */
1378 #ifdef ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
1379 register_chrdev(69, "adm6996", &adm_ops
);
1380 AMAZON_SW_REG(AMAZON_SW_MDIO_CFG
) = 0x27be;
1381 AMAZON_SW_REG(AMAZON_SW_EPHY
) = 0xfc;
1382 adm6996_mode
=adm6996i
;
1383 ifx_sw_read(0xa0, &val
);
1384 ifx_sw_read(0xa1, &val1
);
1385 val
=((val1
&0x0f)<<16)|val
;
1386 printk ("\nADM6996 SMI Mode-");
1387 printk ("Chip ID:%5x \n ", val
);
1388 #else //000001.joelin
1390 AMAZON_SW_REG(AMAZON_SW_MDIO_CFG
) = 0x2c50;
1391 AMAZON_SW_REG(AMAZON_SW_EPHY
) = 0xff;
1393 AMAZON_SW_REG(AMAZON_GPIO_P1_ALTSEL0
) &= ~(GPIO_MDIO
|GPIO_MDCS
|GPIO_MDC
);
1394 AMAZON_SW_REG(AMAZON_GPIO_P1_ALTSEL1
) &= ~(GPIO_MDIO
|GPIO_MDCS
|GPIO_MDC
);
1395 AMAZON_SW_REG(AMAZON_GPIO_P1_OD
) |= (GPIO_MDIO
|GPIO_MDCS
|GPIO_MDC
);
1398 register_chrdev(69, "adm6996", &adm_ops
);
1401 /* create proc entries */
1402 // create_proc_read_entry("admide", 0, NULL, admide_proc, NULL);
1404 //joelin adm6996i support start
1405 adm6996_mode
=adm6996i
;
1406 ifx_sw_read(0xa0, &val
);
1407 adm6996_mode
=adm6996l
;
1408 ifx_sw_read(0x200, &val1
);
1409 // printk ("\n %0x \n",val1);
1410 if ((val
&0xfff0)==0x1020) {
1411 printk ("\n ADM6996I .. \n");
1412 adm6996_mode
=adm6996i
;
1414 else if ((val1
&0xffffff00)==0x71000) {//71010 or 71020
1415 printk ("\n ADM6996LC .. \n");
1416 adm6996_mode
=adm6996lc
;
1419 printk ("\n ADM6996L .. \n");
1420 adm6996_mode
=adm6996l
;
1422 #endif //ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
1424 if ((adm6996_mode
==adm6996lc
)||(adm6996_mode
==adm6996i
)){
1425 #if 0 /* removed by MarsLin */
1426 ifx_sw_write(0x29,0xc000);
1427 ifx_sw_write(0x30,0x0985);
1429 ifx_sw_read(0xa0, &val
);
1430 if (val
== 0x1021) // for both 6996LC and 6996I, only AB version need the patch
1431 ifx_sw_write(0x29, 0x9000);
1432 ifx_sw_write(0x30,0x0985);
1435 //joelin adm6996i support end
1439 void __exit
cleanup_adm6996_module(void)
1441 printk("Free ADM device driver... \n");
1443 unregister_chrdev(69, "adm6996");
1445 /* remove proc entries */
1446 // remove_proc_entry("admide", NULL);
1449 /* MarsLin, add start */
1450 #if defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT) || defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT_MODULE)
1451 #define SET_BIT(reg, mask) reg |= (mask)
1452 #define CLEAR_BIT(reg, mask) reg &= (~mask)
1453 static int ifx_hw_reset(void)
1455 CLEAR_BIT((*AMAZON_GPIO_P0_ALTSEL0
),0x2000);
1456 CLEAR_BIT((*AMAZON_GPIO_P0_ALTSEL1
),0x2000);
1457 SET_BIT((*AMAZON_GPIO_P0_OD
),0x2000);
1458 SET_BIT((*AMAZON_GPIO_P0_DIR
), 0x2000);
1459 CLEAR_BIT((*AMAZON_GPIO_P0_OUT
), 0x2000);
1461 SET_BIT((*AMAZON_GPIO_P0_OUT
), 0x2000);
1462 cleanup_adm6996_module();
1463 return init_adm6996_module();
1465 int (*adm6996_hw_reset
)(void) = ifx_hw_reset
;
1466 EXPORT_SYMBOL(adm6996_hw_reset
);
1467 EXPORT_SYMBOL(adm6996_mode
);
1468 int (*adm6996_sw_read
)(unsigned int addr
, unsigned int *data
) = ifx_sw_read
;
1469 EXPORT_SYMBOL(adm6996_sw_read
);
1470 int (*adm6996_sw_write
)(unsigned int addr
, unsigned int data
) = ifx_sw_write
;
1471 EXPORT_SYMBOL(adm6996_sw_write
);
1473 /* MarsLin, add end */
1475 /* Santosh: for IGMP proxy/snooping, Begin */
1476 EXPORT_SYMBOL (adm_process_mac_table_request
);
1477 EXPORT_SYMBOL (adm_process_protocol_filter_request
);
1478 /* Santosh: for IGMP proxy/snooping, End */
1480 MODULE_DESCRIPTION("ADMtek 6996 Driver");
1481 MODULE_AUTHOR("Joe Lin <joe.lin@infineon.com>");
1482 MODULE_LICENSE("GPL");
1484 module_init(init_adm6996_module
);
1485 module_exit(cleanup_adm6996_module
);