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)
1248 unsigned int val; //6996i
1249 unsigned int control[6] ; //6996i
1250 unsigned int status[6] ; //6996i
1252 // printk ("adm_process_mac_table_request: enter\n");
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);
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);
1267 control[5]=0x030;//initial the first address
1268 ifx_sw_write(0x11f,control[5]);
1271 val=0x8000;//busy ,status5[15]
1272 while(val&0x8000){ //check busy ?
1273 ifx_sw_read(0x125, &val);
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
1282 val=0x8000;//busy ,status5[15]
1283 while(val&0x8000){ //check busy ?
1284 ifx_sw_read(0x125, &val);
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);
1296 val=((val&0x7000)>>12);//result ,status5[14:12]
1297 mMACENTRY->result=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]));
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;
1322 else {//not static age_timer
1323 mMACENTRY->ctrl.age_timer=(status[4]&0x00ff);
1324 mMACENTRY->info_type=0;
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))
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");
1341 printk(" UnKnown Error!! \n");
1343 // printk ("adm_process_mac_table_request: Exit\n");
1347 /* Santosh: End of function for MAC ENTRY ADD/DEL*/
1348 struct file_operations adm_ops =
1353 release: adm_release,
1354 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
1355 unlocked_ioctl: adm_ioctl
1361 int adm_proc(char *buf, char **start, off_t offset, int count, int *eof, void *data)
1365 len += sprintf(buf+len, " ************ Registers ************ \n");
1370 int __init init_adm6996_module(void)
1372 unsigned int val = 000;
1373 unsigned int val1 = 000;
1375 printk("Loading ADM6996 driver... \n");
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
1397 AMAZON_SW_REG(AMAZON_SW_MDIO_CFG) = 0x2c50;
1398 AMAZON_SW_REG(AMAZON_SW_EPHY) = 0xff;
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);
1405 register_chrdev(69, "adm6996", &adm_ops);
1408 /* create proc entries */
1409 // create_proc_read_entry("admide", 0, NULL, admide_proc, NULL);
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;
1421 else if ((val1&0xffffff00)==0x71000) {//71010 or 71020
1422 printk ("\n ADM6996LC .. \n");
1423 adm6996_mode=adm6996lc;
1426 printk ("\n ADM6996L .. \n");
1427 adm6996_mode=adm6996l;
1429 #endif //ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
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);
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);
1442 //joelin adm6996i support end
1446 void __exit cleanup_adm6996_module(void)
1448 printk("Free ADM device driver... \n");
1450 unregister_chrdev(69, "adm6996");
1452 /* remove proc entries */
1453 // remove_proc_entry("admide", NULL);
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)
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);
1468 SET_BIT((*AMAZON_GPIO_P0_OUT), 0x2000);
1469 cleanup_adm6996_module();
1470 return init_adm6996_module();
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);
1480 /* MarsLin, add end */
1482 /* Santosh: for IGMP proxy/snooping, Begin */
1483 EXPORT_SYMBOL (adm_process_mac_table_request);
1484 EXPORT_SYMBOL (adm_process_protocol_filter_request);
1485 /* Santosh: for IGMP proxy/snooping, End */
1487 MODULE_DESCRIPTION("ADMtek 6996 Driver");
1488 MODULE_AUTHOR("Joe Lin <joe.lin@infineon.com>");
1489 MODULE_LICENSE("GPL");
1491 module_init(init_adm6996_module);
1492 module_exit(cleanup_adm6996_module);