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/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>
56 unsigned int ifx_sw_conf
[ADM_SW_MAX_PORT_NUM
+1] = \
57 {ADM_SW_PORT0_CONF
, ADM_SW_PORT1_CONF
, ADM_SW_PORT2_CONF
, \
58 ADM_SW_PORT3_CONF
, ADM_SW_PORT4_CONF
, ADM_SW_PORT5_CONF
};
59 unsigned int ifx_sw_bits
[8] = \
60 {0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
61 unsigned int ifx_sw_vlan_port
[6] = {0, 2, 4, 6, 7, 8};
63 /* 507281:linmars start */
64 #ifdef CONFIG_SWITCH_ADM6996_MDIO
65 #define ADM6996_MDC_MDIO_MODE 1 //000001.joelin
67 #undef ADM6996_MDC_MDIO_MODE
69 /* 507281:linmars end */
73 unsigned int adm6996_mode
=adm6996i
;
78 void ifx_gpio_init(void)
80 //GPIO16,17,18 direction:output
81 //GPIO16,17,18 output 0
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
);
88 /* read one bit from mdio port */
89 int ifx_sw_mdio_readbit(void)
93 //val = (AMAZON_SW_REG(GPIO_conf0_REG) & GPIO0_INPUT_MASK) >> 8;
96 return AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)&1;
104 switch input/output mode of GPIO 0
106 void ifx_mdio_mode(int mode
)
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;*/
117 void ifx_mdc_hi(void)
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);
123 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
125 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)|GPIO_MDC
;
128 void ifx_mdio_hi(void)
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);
134 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
136 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)|GPIO_MDIO
;
139 void ifx_mdcs_hi(void)
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);
145 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
147 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)|GPIO_MDCS
;
150 void ifx_mdc_lo(void)
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);
156 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
158 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)&(~GPIO_MDC
);
161 void ifx_mdio_lo(void)
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);
167 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
169 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)&(~GPIO_MDIO
);
172 void ifx_mdcs_lo(void)
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);
178 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
180 AMAZON_SW_REG(AMAZON_GPIO_P1_OUT
)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN
)&(~GPIO_MDCS
);
187 static void ifx_sw_mdc_pulse(void)
190 udelay(ADM_SW_MDC_DOWN_DELAY
);
192 udelay(ADM_SW_MDC_UP_DELAY
);
200 static void ifx_sw_mdc_toggle(void)
203 udelay(ADM_SW_MDC_UP_DELAY
);
205 udelay(ADM_SW_MDC_DOWN_DELAY
);
210 For ATC 93C66 type EEPROM; accessing ADM6996 internal EEPROM type registers
212 static void ifx_sw_eeprom_write_enable(void)
219 udelay(ADM_SW_CS_DELAY
);
220 /* enable chip select */
222 udelay(ADM_SW_CS_DELAY
);
227 /* eeprom write enable */
228 op
= ADM_SW_BIT_MASK_4
;
231 if (op
& ADM_SW_EEPROM_WRITE_ENABLE
)
240 op
= ADM_SW_BIT_MASK_1
<< (EEPROM_TYPE
- 3);
247 /* disable chip select */
249 udelay(ADM_SW_CS_DELAY
);
256 static void ifx_sw_eeprom_write_disable(void)
263 udelay(ADM_SW_CS_DELAY
);
264 /* enable chip select */
266 udelay(ADM_SW_CS_DELAY
);
271 /* eeprom write disable */
272 op
= ADM_SW_BIT_MASK_4
;
275 if (op
& ADM_SW_EEPROM_WRITE_DISABLE
)
284 op
= ADM_SW_BIT_MASK_1
<< (EEPROM_TYPE
- 3);
292 /* disable chip select */
294 udelay(ADM_SW_CS_DELAY
);
299 read registers from ADM6996
300 serial registers start at 0x200 (addr bit 9 = 1b)
301 EEPROM registers -> 16bits; Serial registers -> 32bits
303 #ifdef ADM6996_MDC_MDIO_MODE //smi mode//000001.joelin
304 static int ifx_sw_read_adm6996i_smi(unsigned int addr
, unsigned int *dat
)
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);
314 static int ifx_sw_read_adm6996i(unsigned int addr
, unsigned int *dat
)
321 udelay(ADM_SW_CS_DELAY
);
327 udelay(ADM_SW_CS_DELAY
);
329 /* preamble, 32 bit 1 */
331 op
= ADM_SW_BIT_MASK_32
;
338 /* command start (01b) */
339 op
= ADM_SW_BIT_MASK_2
;
342 if (op
& ADM_SW_SMI_START
)
351 /* read command (10b) */
352 op
= ADM_SW_BIT_MASK_2
;
355 if (op
& ADM_SW_SMI_READ
)
364 /* send address A9 ~ A0 */
365 op
= ADM_SW_BIT_MASK_10
;
377 /* turnaround bits */
378 op
= ADM_SW_BIT_MASK_2
;
386 udelay(ADM_SW_MDC_DOWN_DELAY
);
388 /* set MDIO pin to input mode */
389 ifx_mdio_mode(ADM_SW_MDIO_INPUT
);
391 /* start read data */
393 //adm6996i op = ADM_SW_BIT_MASK_32;
394 op
= ADM_SW_BIT_MASK_16
;//adm6996i
398 if (ifx_sw_mdio_readbit()) *dat
|= 1;
404 /* set MDIO to output mode */
405 ifx_mdio_mode(ADM_SW_MDIO_OUTPUT
);
408 op
= ADM_SW_BIT_MASK_4
;
420 /* EEPROM registers */
421 //adm6996i if (!(addr & 0x200))
423 //adm6996i if (addr % 2)
424 //adm6996i *dat >>= 16;
426 //adm6996i *dat &= 0xffff;
432 static int ifx_sw_read_adm6996l(unsigned int addr
, unsigned int *dat
)
439 udelay(ADM_SW_CS_DELAY
);
445 udelay(ADM_SW_CS_DELAY
);
447 /* preamble, 32 bit 1 */
449 op
= ADM_SW_BIT_MASK_32
;
456 /* command start (01b) */
457 op
= ADM_SW_BIT_MASK_2
;
460 if (op
& ADM_SW_SMI_START
)
469 /* read command (10b) */
470 op
= ADM_SW_BIT_MASK_2
;
473 if (op
& ADM_SW_SMI_READ
)
482 /* send address A9 ~ A0 */
483 op
= ADM_SW_BIT_MASK_10
;
495 /* turnaround bits */
496 op
= ADM_SW_BIT_MASK_2
;
504 udelay(ADM_SW_MDC_DOWN_DELAY
);
506 /* set MDIO pin to input mode */
507 ifx_mdio_mode(ADM_SW_MDIO_INPUT
);
509 /* start read data */
511 op
= ADM_SW_BIT_MASK_32
;
515 if (ifx_sw_mdio_readbit()) *dat
|= 1;
521 /* set MDIO to output mode */
522 ifx_mdio_mode(ADM_SW_MDIO_OUTPUT
);
525 op
= ADM_SW_BIT_MASK_4
;
537 /* EEPROM registers */
549 static int ifx_sw_read(unsigned int addr
, unsigned int *dat
)
551 #ifdef ADM6996_MDC_MDIO_MODE //smi mode ////000001.joelin
552 ifx_sw_read_adm6996i_smi(addr
,dat
);
554 if (adm6996_mode
==adm6996i
) ifx_sw_read_adm6996i(addr
,dat
);
555 else ifx_sw_read_adm6996l(addr
,dat
);
562 write register to ADM6996 eeprom registers
564 //for adm6996i -start
565 #ifdef ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
566 static int ifx_sw_write_adm6996i_smi(unsigned int addr
, unsigned int dat
)
569 AMAZON_SW_REG(AMAZON_SW_MDIO_ACC
) = ((addr
<<16)&0x3ff0000)|dat
|0x80000000;
570 while ((AMAZON_SW_REG(AMAZON_SW_MDIO_ACC
))&0x80000000){};
575 #endif //ADM6996_MDC_MDIO_MODE //000001.joelin
577 static int ifx_sw_write_adm6996i(unsigned int addr
, unsigned int dat
)
584 udelay(ADM_SW_CS_DELAY
);
590 udelay(ADM_SW_CS_DELAY
);
592 /* preamble, 32 bit 1 */
594 op
= ADM_SW_BIT_MASK_32
;
601 /* command start (01b) */
602 op
= ADM_SW_BIT_MASK_2
;
605 if (op
& ADM_SW_SMI_START
)
614 /* write command (01b) */
615 op
= ADM_SW_BIT_MASK_2
;
618 if (op
& ADM_SW_SMI_WRITE
)
627 /* send address A9 ~ A0 */
628 op
= ADM_SW_BIT_MASK_10
;
640 /* turnaround bits */
641 op
= ADM_SW_BIT_MASK_2
;
649 udelay(ADM_SW_MDC_DOWN_DELAY
);
651 /* set MDIO pin to output mode */
652 ifx_mdio_mode(ADM_SW_MDIO_OUTPUT
);
655 /* start write data */
656 op
= ADM_SW_BIT_MASK_16
;
668 // /* set MDIO to output mode */
669 // ifx_mdio_mode(ADM_SW_MDIO_OUTPUT);
672 op
= ADM_SW_BIT_MASK_4
;
684 /* EEPROM registers */
685 //adm6996i if (!(addr & 0x200))
687 //adm6996i if (addr % 2)
688 //adm6996i *dat >>= 16;
690 //adm6996i *dat &= 0xffff;
696 static int ifx_sw_write_adm6996l(unsigned int addr
, unsigned int dat
)
703 ifx_sw_eeprom_write_enable();
707 udelay(ADM_SW_CS_DELAY
);
709 /* issue write command */
714 /* EEPROM write command */
715 op
= ADM_SW_BIT_MASK_2
;
718 if (op
& ADM_SW_EEPROM_WRITE
)
727 /* send address A7 ~ A0 */
728 op
= ADM_SW_BIT_MASK_1
<< (EEPROM_TYPE
- 1);
741 /* start write data */
742 op
= ADM_SW_BIT_MASK_16
;
754 /* disable cs & wait 1 clock */
756 udelay(ADM_SW_CS_DELAY
);
759 ifx_sw_eeprom_write_disable();
764 static int ifx_sw_write(unsigned int addr
, unsigned int dat
)
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
778 int ifx_sw_reset(void)
781 ifx_sw_write(ADM_SW_PHY_RESET
, 0);
786 /* 509201:linmars start */
791 int ifx_check_port_status(int port
)
795 if ((port
< 0) || (port
> ADM_SW_MAX_PORT_NUM
))
797 ifx_printf(("error on port number (%d)!!\n", port
));
801 ifx_sw_read(ifx_sw_conf
[port
], &val
);
802 if (ifx_sw_conf
[port
]%2) val
>>= 16;
803 /* only 16bits are effective */
806 ifx_printf(("Port %d status (%.8x): \n", port
, val
));
808 if (val
& ADM_SW_PORT_FLOWCTL
)
809 ifx_printf(("\t802.3x flow control supported!\n"));
811 ifx_printf(("\t802.3x flow control not supported!\n"));
813 if (val
& ADM_SW_PORT_AN
)
814 ifx_printf(("\tAuto negotiation ON!\n"));
816 ifx_printf(("\tAuto negotiation OFF!\n"));
818 if (val
& ADM_SW_PORT_100M
)
819 ifx_printf(("\tLink at 100M!\n"));
821 ifx_printf(("\tLink at 10M!\n"));
823 if (val
& ADM_SW_PORT_FULL
)
824 ifx_printf(("\tFull duplex!\n"));
826 ifx_printf(("\tHalf duplex!\n"));
828 if (val
& ADM_SW_PORT_DISABLE
)
829 ifx_printf(("\tPort disabled!\n"));
831 ifx_printf(("\tPort enabled!\n"));
833 if (val
& ADM_SW_PORT_TOS
)
834 ifx_printf(("\tTOS enabled!\n"));
836 ifx_printf(("\tTOS disabled!\n"));
838 if (val
& ADM_SW_PORT_PPRI
)
839 ifx_printf(("\tPort priority first!\n"));
841 ifx_printf(("\tVLAN or TOS priority first!\n"));
843 if (val
& ADM_SW_PORT_MDIX
)
844 ifx_printf(("\tAuto MDIX!\n"));
846 ifx_printf(("\tNo auto MDIX\n"));
848 ifx_printf(("\tPVID: %d\n", \
849 ((val
>> ADM_SW_PORT_PVID_SHIFT
)&ifx_sw_bits
[ADM_SW_PORT_PVID_BITS
])));
857 int ifx_sw_vlan_init(int vlanid
)
859 ifx_sw_write(ADM_SW_VLAN0_CONF
+ vlanid
, 0);
865 add a port to certain vlan
867 int ifx_sw_vlan_add(int port
, int vlanid
)
871 if ((port
< 0) || (port
> ADM_SW_MAX_PORT_NUM
) || (vlanid
< 0) ||
872 (vlanid
> ADM_SW_MAX_VLAN_NUM
))
874 ifx_printf(("Port number or VLAN number ERROR!!\n"));
877 ifx_sw_read(ADM_SW_VLAN0_CONF
+ vlanid
, ®
);
878 reg
|= (1 << ifx_sw_vlan_port
[port
]);
879 ifx_sw_write(ADM_SW_VLAN0_CONF
+ vlanid
, reg
);
885 delete a given port from certain vlan
887 int ifx_sw_vlan_del(int port
, int vlanid
)
889 unsigned int reg
= 0;
891 if ((port
< 0) || (port
> ADM_SW_MAX_PORT_NUM
) || (vlanid
< 0) || (vlanid
> ADM_SW_MAX_VLAN_NUM
))
893 ifx_printf(("Port number or VLAN number ERROR!!\n"));
896 ifx_sw_read(ADM_SW_VLAN0_CONF
+ vlanid
, ®
);
897 reg
&= ~(1 << ifx_sw_vlan_port
[port
]);
898 ifx_sw_write(ADM_SW_VLAN0_CONF
+ vlanid
, reg
);
906 port 0~3 as untag port and PVID = 1
907 VLAN1: port 0~3 and port 5 (MII)
909 static int ifx_sw_init(void)
911 ifx_printf(("Setting default ADM6996 registers... \n"));
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);
928 /* 509201:linmars end */
930 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 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
954 static long adm_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long args
)
956 static int adm_ioctl(struct inode
*inode
, struct file
*filp
, unsigned int cmd
, unsigned long args
)
961 unsigned int val
; //6996i
962 unsigned int control
[6] ; //6996i
963 unsigned int status
[6] ; //6996i
965 PMACENTRY mMACENTRY
;//adm6996i
966 PPROTOCOLFILTER uPROTOCOLFILTER
;///adm6996i
968 if (_IOC_TYPE(cmd
) != ADM_MAGIC
)
970 printk("adm_ioctl: IOC_TYPE(%x) != ADM_MAGIC(%x)! \n", _IOC_TYPE(cmd
), ADM_MAGIC
);
974 if(_IOC_NR(cmd
) >= KEY_IOCTL_MAX_KEY
)
976 printk(KERN_WARNING
"adm_ioctl: IOC_NR(%x) invalid! \n", _IOC_NR(cmd
));
982 case ADM_IOCTL_REGRW
:
984 uREGRW
= (PREGRW
)kmalloc(sizeof(REGRW
), GFP_KERNEL
);
985 rtval
= copy_from_user(uREGRW
, (PREGRW
)args
, sizeof(REGRW
));
988 printk("ADM_IOCTL_REGRW: copy from user FAILED!! \n");
995 uREGRW
->value
= 0x12345678;//inl(uREGRW->addr);
996 copy_to_user((PREGRW
)args
, uREGRW
, sizeof(REGRW
));
999 //outl(uREGRW->value, uREGRW->addr);
1003 printk("No such Register Read/Write function!! \n");
1010 case ADM_SW_IOCTL_REGRW
:
1012 unsigned int val
= 0xff;
1014 uREGRW
= (PREGRW
)kmalloc(sizeof(REGRW
), GFP_KERNEL
);
1015 rtval
= copy_from_user(uREGRW
, (PREGRW
)args
, sizeof(REGRW
));
1018 printk("ADM_IOCTL_REGRW: copy from user FAILED!! \n");
1022 switch(uREGRW
->mode
)
1025 ifx_sw_read(uREGRW
->addr
, &val
);
1026 uREGRW
->value
= val
;
1027 copy_to_user((PREGRW
)args
, uREGRW
, sizeof(REGRW
));
1031 ifx_sw_write(uREGRW
->addr
, uREGRW
->value
);
1034 printk("No such Register Read/Write function!! \n");
1040 /* 509201:linmars start */
1042 case ADM_SW_IOCTL_PORTSTS
:
1043 for (rtval
= 0; rtval
< ADM_SW_MAX_PORT_NUM
+1; rtval
++)
1044 ifx_check_port_status(rtval
);
1046 case ADM_SW_IOCTL_INIT
:
1050 /* 509201:linmars end */
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
:
1058 mMACENTRY
= (PMACENTRY
)kmalloc(sizeof(MACENTRY
), GFP_KERNEL
);
1059 rtval
= copy_from_user(mMACENTRY
, (PMACENTRY
)args
, sizeof(MACENTRY
));
1062 printk("ADM_SW_IOCTL_MACENTRY: copy from user FAILED!! \n");
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
);
1077 control
[5]=0x030;//initial the first address
1078 ifx_sw_write(0x11f,control
[5]);
1081 val
=0x8000;//busy ,status5[15]
1082 while(val
&0x8000){ //check busy ?
1083 ifx_sw_read(0x125, &val
);
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
1092 val
=0x8000;//busy ,status5[15]
1093 while(val
&0x8000){ //check busy ?
1094 ifx_sw_read(0x125, &val
);
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
);
1106 val
=((val
&0x7000)>>12);//result ,status5[14:12]
1107 mMACENTRY
->result
=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]));
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;
1132 else {//not static age_timer
1133 mMACENTRY
->ctrl
.age_timer
=(status
[4]&0x00ff);
1134 mMACENTRY
->info_type
=0;
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))
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");
1151 printk(" UnKnown Error!! \n");
1153 copy_to_user((PMACENTRY
)args
, mMACENTRY
,sizeof(MACENTRY
));
1157 case ADM_SW_IOCTL_FILTER_ADD
:
1158 case ADM_SW_IOCTL_FILTER_DEL
:
1159 case ADM_SW_IOCTL_FILTER_GET
:
1161 uPROTOCOLFILTER
= (PPROTOCOLFILTER
)kmalloc(sizeof(PROTOCOLFILTER
), GFP_KERNEL
);
1162 rtval
= copy_from_user(uPROTOCOLFILTER
, (PPROTOCOLFILTER
)args
, sizeof(PROTOCOLFILTER
));
1165 printk("ADM_SW_IOCTL_FILTER_ADD: copy from user FAILED!! \n");
1169 if(cmd
==ADM_SW_IOCTL_FILTER_DEL
) { //delete filter
1170 uPROTOCOLFILTER
->ip_p
=00; //delet filter
1171 uPROTOCOLFILTER
->action
=00; //delete filter
1174 ifx_sw_read(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), &val
);//rx68~rx6b,protocol filter0~7
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
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
1184 if(cmd
!=ADM_SW_IOCTL_FILTER_GET
) ifx_sw_write(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), val
);//write rx68~rx6b,protocol filter0~7
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
));
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
1209 /* Santosh: handle IGMP protocol filter ADD/DEL/GET */
1210 int adm_process_protocol_filter_request (unsigned int cmd
, PPROTOCOLFILTER uPROTOCOLFILTER
)
1212 unsigned int val
; //6996i
1214 if(cmd
==ADM_SW_IOCTL_FILTER_DEL
) { //delete filter
1215 uPROTOCOLFILTER
->ip_p
=00; //delet filter
1216 uPROTOCOLFILTER
->action
=00; //delete filter
1219 ifx_sw_read(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), &val
);//rx68~rx6b,protocol filter0~7
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
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
1229 if(cmd
!=ADM_SW_IOCTL_FILTER_GET
) ifx_sw_write(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), val
);//write rx68~rx6b,protocol filter0~7
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
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
1244 /* Santosh: function for MAC ENTRY ADD/DEL/GET */
1246 int adm_process_mac_table_request (unsigned int cmd
, PMACENTRY mMACENTRY
)
1249 unsigned int val
; //6996i
1250 unsigned int control
[6] ; //6996i
1251 unsigned int status
[6] ; //6996i
1253 // printk ("adm_process_mac_table_request: enter\n");
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);
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
);
1268 control
[5]=0x030;//initial the first address
1269 ifx_sw_write(0x11f,control
[5]);
1272 val
=0x8000;//busy ,status5[15]
1273 while(val
&0x8000){ //check busy ?
1274 ifx_sw_read(0x125, &val
);
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
1283 val
=0x8000;//busy ,status5[15]
1284 while(val
&0x8000){ //check busy ?
1285 ifx_sw_read(0x125, &val
);
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
);
1297 val
=((val
&0x7000)>>12);//result ,status5[14:12]
1298 mMACENTRY
->result
=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]));
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;
1323 else {//not static age_timer
1324 mMACENTRY
->ctrl
.age_timer
=(status
[4]&0x00ff);
1325 mMACENTRY
->info_type
=0;
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))
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");
1342 printk(" UnKnown Error!! \n");
1344 // printk ("adm_process_mac_table_request: Exit\n");
1348 /* Santosh: End of function for MAC ENTRY ADD/DEL*/
1349 struct file_operations adm_ops
=
1354 release
: adm_release
,
1355 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
1356 unlocked_ioctl
: adm_ioctl
1362 int adm_proc(char *buf
, char **start
, off_t offset
, int count
, int *eof
, void *data
)
1366 len
+= sprintf(buf
+len
, " ************ Registers ************ \n");
1371 int __init
init_adm6996_module(void)
1373 unsigned int val
= 000;
1374 unsigned int val1
= 000;
1376 printk("Loading ADM6996 driver... \n");
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
1398 AMAZON_SW_REG(AMAZON_SW_MDIO_CFG
) = 0x2c50;
1399 AMAZON_SW_REG(AMAZON_SW_EPHY
) = 0xff;
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
);
1406 register_chrdev(69, "adm6996", &adm_ops
);
1409 /* create proc entries */
1410 // create_proc_read_entry("admide", 0, NULL, admide_proc, NULL);
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
;
1422 else if ((val1
&0xffffff00)==0x71000) {//71010 or 71020
1423 printk ("\n ADM6996LC .. \n");
1424 adm6996_mode
=adm6996lc
;
1427 printk ("\n ADM6996L .. \n");
1428 adm6996_mode
=adm6996l
;
1430 #endif //ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
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);
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);
1443 //joelin adm6996i support end
1447 void __exit
cleanup_adm6996_module(void)
1449 printk("Free ADM device driver... \n");
1451 unregister_chrdev(69, "adm6996");
1453 /* remove proc entries */
1454 // remove_proc_entry("admide", NULL);
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)
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);
1469 SET_BIT((*AMAZON_GPIO_P0_OUT
), 0x2000);
1470 cleanup_adm6996_module();
1471 return init_adm6996_module();
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
);
1481 /* MarsLin, add end */
1483 /* Santosh: for IGMP proxy/snooping, Begin */
1484 EXPORT_SYMBOL (adm_process_mac_table_request
);
1485 EXPORT_SYMBOL (adm_process_protocol_filter_request
);
1486 /* Santosh: for IGMP proxy/snooping, End */
1488 MODULE_DESCRIPTION("ADMtek 6996 Driver");
1489 MODULE_AUTHOR("Joe Lin <joe.lin@infineon.com>");
1490 MODULE_LICENSE("GPL");
1492 module_init(init_adm6996_module
);
1493 module_exit(cleanup_adm6996_module
);