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
)
934 ssize_t
adm_read(struct file
*filep
, char *buf
, size_t count
, loff_t
*ppos
)
939 ssize_t
adm_write(struct file
*filep
, const char *buf
, size_t count
, loff_t
*ppos
)
945 int adm_release(struct inode
*inode
, struct file
*filp
)
951 int adm_ioctl(struct inode
*inode
, struct file
*filp
, unsigned int cmd
, unsigned long args
)
955 unsigned int val
; //6996i
956 unsigned int control
[6] ; //6996i
957 unsigned int status
[6] ; //6996i
959 PMACENTRY mMACENTRY
;//adm6996i
960 PPROTOCOLFILTER uPROTOCOLFILTER
;///adm6996i
962 if (_IOC_TYPE(cmd
) != ADM_MAGIC
)
964 printk("adm_ioctl: IOC_TYPE(%x) != ADM_MAGIC(%x)! \n", _IOC_TYPE(cmd
), ADM_MAGIC
);
968 if(_IOC_NR(cmd
) >= KEY_IOCTL_MAX_KEY
)
970 printk(KERN_WARNING
"adm_ioctl: IOC_NR(%x) invalid! \n", _IOC_NR(cmd
));
976 case ADM_IOCTL_REGRW
:
978 uREGRW
= (PREGRW
)kmalloc(sizeof(REGRW
), GFP_KERNEL
);
979 rtval
= copy_from_user(uREGRW
, (PREGRW
)args
, sizeof(REGRW
));
982 printk("ADM_IOCTL_REGRW: copy from user FAILED!! \n");
989 uREGRW
->value
= 0x12345678;//inl(uREGRW->addr);
990 copy_to_user((PREGRW
)args
, uREGRW
, sizeof(REGRW
));
993 //outl(uREGRW->value, uREGRW->addr);
997 printk("No such Register Read/Write function!! \n");
1004 case ADM_SW_IOCTL_REGRW
:
1006 unsigned int val
= 0xff;
1008 uREGRW
= (PREGRW
)kmalloc(sizeof(REGRW
), GFP_KERNEL
);
1009 rtval
= copy_from_user(uREGRW
, (PREGRW
)args
, sizeof(REGRW
));
1012 printk("ADM_IOCTL_REGRW: copy from user FAILED!! \n");
1016 switch(uREGRW
->mode
)
1019 ifx_sw_read(uREGRW
->addr
, &val
);
1020 uREGRW
->value
= val
;
1021 copy_to_user((PREGRW
)args
, uREGRW
, sizeof(REGRW
));
1025 ifx_sw_write(uREGRW
->addr
, uREGRW
->value
);
1028 printk("No such Register Read/Write function!! \n");
1034 /* 509201:linmars start */
1036 case ADM_SW_IOCTL_PORTSTS
:
1037 for (rtval
= 0; rtval
< ADM_SW_MAX_PORT_NUM
+1; rtval
++)
1038 ifx_check_port_status(rtval
);
1040 case ADM_SW_IOCTL_INIT
:
1044 /* 509201:linmars end */
1046 case ADM_SW_IOCTL_MACENTRY_ADD
:
1047 case ADM_SW_IOCTL_MACENTRY_DEL
:
1048 case ADM_SW_IOCTL_MACENTRY_GET_INIT
:
1049 case ADM_SW_IOCTL_MACENTRY_GET_MORE
:
1052 mMACENTRY
= (PMACENTRY
)kmalloc(sizeof(MACENTRY
), GFP_KERNEL
);
1053 rtval
= copy_from_user(mMACENTRY
, (PMACENTRY
)args
, sizeof(MACENTRY
));
1056 printk("ADM_SW_IOCTL_MACENTRY: copy from user FAILED!! \n");
1059 control
[0]=(mMACENTRY
->mac_addr
[1]<<8)+mMACENTRY
->mac_addr
[0] ;
1060 control
[1]=(mMACENTRY
->mac_addr
[3]<<8)+mMACENTRY
->mac_addr
[2] ;
1061 control
[2]=(mMACENTRY
->mac_addr
[5]<<8)+mMACENTRY
->mac_addr
[4] ;
1062 control
[3]=(mMACENTRY
->fid
&0xf)+((mMACENTRY
->portmap
&0x3f)<<4);
1063 if (((mMACENTRY
->info_type
)&0x01)) control
[4]=(mMACENTRY
->ctrl
.info_ctrl
)+0x1000; //static ,info control
1064 else control
[4]=((mMACENTRY
->ctrl
.age_timer
)&0xff);//not static ,agetimer
1065 if (cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
) {
1066 //initial the pointer to the first address
1067 val
=0x8000;//busy ,status5[15]
1068 while(val
&0x8000){ //check busy ?
1069 ifx_sw_read(0x125, &val
);
1071 control
[5]=0x030;//initial the first address
1072 ifx_sw_write(0x11f,control
[5]);
1075 val
=0x8000;//busy ,status5[15]
1076 while(val
&0x8000){ //check busy ?
1077 ifx_sw_read(0x125, &val
);
1080 } //if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)
1081 if (cmd
==ADM_SW_IOCTL_MACENTRY_ADD
) control
[5]=0x07;//create a new address
1082 else if (cmd
==ADM_SW_IOCTL_MACENTRY_DEL
) control
[5]=0x01f;//erased an existed address
1083 else if ((cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
)||(cmd
==ADM_SW_IOCTL_MACENTRY_GET_MORE
))
1084 control
[5]=0x02c;//search by the mac address field
1086 val
=0x8000;//busy ,status5[15]
1087 while(val
&0x8000){ //check busy ?
1088 ifx_sw_read(0x125, &val
);
1090 ifx_sw_write(0x11a,control
[0]);
1091 ifx_sw_write(0x11b,control
[1]);
1092 ifx_sw_write(0x11c,control
[2]);
1093 ifx_sw_write(0x11d,control
[3]);
1094 ifx_sw_write(0x11e,control
[4]);
1095 ifx_sw_write(0x11f,control
[5]);
1096 val
=0x8000;//busy ,status5[15]
1097 while(val
&0x8000){ //check busy ?
1098 ifx_sw_read(0x125, &val
);
1100 val
=((val
&0x7000)>>12);//result ,status5[14:12]
1101 mMACENTRY
->result
=val
;
1104 printk(" Command OK!! \n");
1105 if ((cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
)||(cmd
==ADM_SW_IOCTL_MACENTRY_GET_MORE
)) {
1106 ifx_sw_read(0x120,&(status
[0]));
1107 ifx_sw_read(0x121,&(status
[1]));
1108 ifx_sw_read(0x122,&(status
[2]));
1109 ifx_sw_read(0x123,&(status
[3]));
1110 ifx_sw_read(0x124,&(status
[4]));
1111 ifx_sw_read(0x125,&(status
[5]));
1114 mMACENTRY
->mac_addr
[0]=(status
[0]&0x00ff) ;
1115 mMACENTRY
->mac_addr
[1]=(status
[0]&0xff00)>>8 ;
1116 mMACENTRY
->mac_addr
[2]=(status
[1]&0x00ff) ;
1117 mMACENTRY
->mac_addr
[3]=(status
[1]&0xff00)>>8 ;
1118 mMACENTRY
->mac_addr
[4]=(status
[2]&0x00ff) ;
1119 mMACENTRY
->mac_addr
[5]=(status
[2]&0xff00)>>8 ;
1120 mMACENTRY
->fid
=(status
[3]&0xf);
1121 mMACENTRY
->portmap
=((status
[3]>>4)&0x3f);
1122 if (status
[5]&0x2) {//static info_ctrl //status5[1]????
1123 mMACENTRY
->ctrl
.info_ctrl
=(status
[4]&0x00ff);
1124 mMACENTRY
->info_type
=1;
1126 else {//not static age_timer
1127 mMACENTRY
->ctrl
.age_timer
=(status
[4]&0x00ff);
1128 mMACENTRY
->info_type
=0;
1130 //status5[13]???? mMACENTRY->occupy=(status[5]&0x02)>>1;//status5[1]
1131 mMACENTRY
->occupy
=(status
[5]&0x02000)>>13;//status5[13] ???
1132 mMACENTRY
->bad
=(status
[5]&0x04)>>2;//status5[2]
1133 }//if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
1136 else if (val
==0x001)
1137 printk(" All Entry Used!! \n");
1138 else if (val
==0x002)
1139 printk(" Entry Not Found!! \n");
1140 else if (val
==0x003)
1141 printk(" Try Next Entry!! \n");
1142 else if (val
==0x005)
1143 printk(" Command Error!! \n");
1145 printk(" UnKnown Error!! \n");
1147 copy_to_user((PMACENTRY
)args
, mMACENTRY
,sizeof(MACENTRY
));
1151 case ADM_SW_IOCTL_FILTER_ADD
:
1152 case ADM_SW_IOCTL_FILTER_DEL
:
1153 case ADM_SW_IOCTL_FILTER_GET
:
1155 uPROTOCOLFILTER
= (PPROTOCOLFILTER
)kmalloc(sizeof(PROTOCOLFILTER
), GFP_KERNEL
);
1156 rtval
= copy_from_user(uPROTOCOLFILTER
, (PPROTOCOLFILTER
)args
, sizeof(PROTOCOLFILTER
));
1159 printk("ADM_SW_IOCTL_FILTER_ADD: copy from user FAILED!! \n");
1163 if(cmd
==ADM_SW_IOCTL_FILTER_DEL
) { //delete filter
1164 uPROTOCOLFILTER
->ip_p
=00; //delet filter
1165 uPROTOCOLFILTER
->action
=00; //delete filter
1168 ifx_sw_read(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), &val
);//rx68~rx6b,protocol filter0~7
1170 if (((uPROTOCOLFILTER
->protocol_filter_num
)%2)==00){
1171 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) uPROTOCOLFILTER
->ip_p
= val
&0x00ff;//get filter ip_p
1172 else val
=(val
&0xff00)|(uPROTOCOLFILTER
->ip_p
);//set filter ip_p
1175 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) uPROTOCOLFILTER
->ip_p
= (val
>>8);//get filter ip_p
1176 else val
=(val
&0x00ff)|((uPROTOCOLFILTER
->ip_p
)<<8);//set filter ip_p
1178 if(cmd
!=ADM_SW_IOCTL_FILTER_GET
) ifx_sw_write(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), val
);//write rx68~rx6b,protocol filter0~7
1180 ifx_sw_read(0x95, &val
); //protocol filter action
1181 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) {
1182 uPROTOCOLFILTER
->action
= ((val
>>(uPROTOCOLFILTER
->protocol_filter_num
*2))&0x3);//get filter action
1183 copy_to_user((PPROTOCOLFILTER
)args
, uPROTOCOLFILTER
, sizeof(PROTOCOLFILTER
));
1187 val
=(val
&(~(0x03<<(uPROTOCOLFILTER
->protocol_filter_num
*2))))|(((uPROTOCOLFILTER
->action
)&0x03)<<(uPROTOCOLFILTER
->protocol_filter_num
*2));
1188 // printk("%d----\n",val);
1189 ifx_sw_write(0x95, val
); //write protocol filter action
1203 /* Santosh: handle IGMP protocol filter ADD/DEL/GET */
1204 int adm_process_protocol_filter_request (unsigned int cmd
, PPROTOCOLFILTER uPROTOCOLFILTER
)
1206 unsigned int val
; //6996i
1208 if(cmd
==ADM_SW_IOCTL_FILTER_DEL
) { //delete filter
1209 uPROTOCOLFILTER
->ip_p
=00; //delet filter
1210 uPROTOCOLFILTER
->action
=00; //delete filter
1213 ifx_sw_read(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), &val
);//rx68~rx6b,protocol filter0~7
1215 if (((uPROTOCOLFILTER
->protocol_filter_num
)%2)==00){
1216 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) uPROTOCOLFILTER
->ip_p
= val
&0x00ff;//get filter ip_p
1217 else val
=(val
&0xff00)|(uPROTOCOLFILTER
->ip_p
);//set filter ip_p
1220 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) uPROTOCOLFILTER
->ip_p
= (val
>>8);//get filter ip_p
1221 else val
=(val
&0x00ff)|((uPROTOCOLFILTER
->ip_p
)<<8);//set filter ip_p
1223 if(cmd
!=ADM_SW_IOCTL_FILTER_GET
) ifx_sw_write(((uPROTOCOLFILTER
->protocol_filter_num
/2)+0x68), val
);//write rx68~rx6b,protocol filter0~7
1225 ifx_sw_read(0x95, &val
); //protocol filter action
1226 if(cmd
==ADM_SW_IOCTL_FILTER_GET
) {
1227 uPROTOCOLFILTER
->action
= ((val
>>(uPROTOCOLFILTER
->protocol_filter_num
*2))&0x3);//get filter action
1230 val
=(val
&(~(0x03<<(uPROTOCOLFILTER
->protocol_filter_num
*2))))|(((uPROTOCOLFILTER
->action
)&0x03)<<(uPROTOCOLFILTER
->protocol_filter_num
*2));
1231 ifx_sw_write(0x95, val
); //write protocol filter action
1238 /* Santosh: function for MAC ENTRY ADD/DEL/GET */
1240 int adm_process_mac_table_request (unsigned int cmd
, PMACENTRY mMACENTRY
)
1243 unsigned int val
; //6996i
1244 unsigned int control
[6] ; //6996i
1245 unsigned int status
[6] ; //6996i
1247 // printk ("adm_process_mac_table_request: enter\n");
1249 control
[0]=(mMACENTRY
->mac_addr
[1]<<8)+mMACENTRY
->mac_addr
[0] ;
1250 control
[1]=(mMACENTRY
->mac_addr
[3]<<8)+mMACENTRY
->mac_addr
[2] ;
1251 control
[2]=(mMACENTRY
->mac_addr
[5]<<8)+mMACENTRY
->mac_addr
[4] ;
1252 control
[3]=(mMACENTRY
->fid
&0xf)+((mMACENTRY
->portmap
&0x3f)<<4);
1254 if (((mMACENTRY
->info_type
)&0x01)) control
[4]=(mMACENTRY
->ctrl
.info_ctrl
)+0x1000; //static ,info control
1255 else control
[4]=((mMACENTRY
->ctrl
.age_timer
)&0xff);//not static ,agetimer
1256 if (cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
) {
1257 //initial the pointer to the first address
1258 val
=0x8000;//busy ,status5[15]
1259 while(val
&0x8000){ //check busy ?
1260 ifx_sw_read(0x125, &val
);
1262 control
[5]=0x030;//initial the first address
1263 ifx_sw_write(0x11f,control
[5]);
1266 val
=0x8000;//busy ,status5[15]
1267 while(val
&0x8000){ //check busy ?
1268 ifx_sw_read(0x125, &val
);
1271 } //if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)
1272 if (cmd
==ADM_SW_IOCTL_MACENTRY_ADD
) control
[5]=0x07;//create a new address
1273 else if (cmd
==ADM_SW_IOCTL_MACENTRY_DEL
) control
[5]=0x01f;//erased an existed address
1274 else if ((cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
)||(cmd
==ADM_SW_IOCTL_MACENTRY_GET_MORE
))
1275 control
[5]=0x02c;//search by the mac address field
1277 val
=0x8000;//busy ,status5[15]
1278 while(val
&0x8000){ //check busy ?
1279 ifx_sw_read(0x125, &val
);
1281 ifx_sw_write(0x11a,control
[0]);
1282 ifx_sw_write(0x11b,control
[1]);
1283 ifx_sw_write(0x11c,control
[2]);
1284 ifx_sw_write(0x11d,control
[3]);
1285 ifx_sw_write(0x11e,control
[4]);
1286 ifx_sw_write(0x11f,control
[5]);
1287 val
=0x8000;//busy ,status5[15]
1288 while(val
&0x8000){ //check busy ?
1289 ifx_sw_read(0x125, &val
);
1291 val
=((val
&0x7000)>>12);//result ,status5[14:12]
1292 mMACENTRY
->result
=val
;
1295 printk(" Command OK!! \n");
1296 if ((cmd
==ADM_SW_IOCTL_MACENTRY_GET_INIT
)||(cmd
==ADM_SW_IOCTL_MACENTRY_GET_MORE
)) {
1297 ifx_sw_read(0x120,&(status
[0]));
1298 ifx_sw_read(0x121,&(status
[1]));
1299 ifx_sw_read(0x122,&(status
[2]));
1300 ifx_sw_read(0x123,&(status
[3]));
1301 ifx_sw_read(0x124,&(status
[4]));
1302 ifx_sw_read(0x125,&(status
[5]));
1305 mMACENTRY
->mac_addr
[0]=(status
[0]&0x00ff) ;
1306 mMACENTRY
->mac_addr
[1]=(status
[0]&0xff00)>>8 ;
1307 mMACENTRY
->mac_addr
[2]=(status
[1]&0x00ff) ;
1308 mMACENTRY
->mac_addr
[3]=(status
[1]&0xff00)>>8 ;
1309 mMACENTRY
->mac_addr
[4]=(status
[2]&0x00ff) ;
1310 mMACENTRY
->mac_addr
[5]=(status
[2]&0xff00)>>8 ;
1311 mMACENTRY
->fid
=(status
[3]&0xf);
1312 mMACENTRY
->portmap
=((status
[3]>>4)&0x3f);
1313 if (status
[5]&0x2) {//static info_ctrl //status5[1]????
1314 mMACENTRY
->ctrl
.info_ctrl
=(status
[4]&0x00ff);
1315 mMACENTRY
->info_type
=1;
1317 else {//not static age_timer
1318 mMACENTRY
->ctrl
.age_timer
=(status
[4]&0x00ff);
1319 mMACENTRY
->info_type
=0;
1321 //status5[13]???? mMACENTRY->occupy=(status[5]&0x02)>>1;//status5[1]
1322 mMACENTRY
->occupy
=(status
[5]&0x02000)>>13;//status5[13] ???
1323 mMACENTRY
->bad
=(status
[5]&0x04)>>2;//status5[2]
1324 }//if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
1327 else if (val
==0x001)
1328 printk(" All Entry Used!! \n");
1329 else if (val
==0x002)
1330 printk(" Entry Not Found!! \n");
1331 else if (val
==0x003)
1332 printk(" Try Next Entry!! \n");
1333 else if (val
==0x005)
1334 printk(" Command Error!! \n");
1336 printk(" UnKnown Error!! \n");
1338 // printk ("adm_process_mac_table_request: Exit\n");
1342 /* Santosh: End of function for MAC ENTRY ADD/DEL*/
1343 struct file_operations adm_ops
=
1348 release
: adm_release
,
1352 int adm_proc(char *buf
, char **start
, off_t offset
, int count
, int *eof
, void *data
)
1356 len
+= sprintf(buf
+len
, " ************ Registers ************ \n");
1361 int __init
init_adm6996_module(void)
1363 unsigned int val
= 000;
1364 unsigned int val1
= 000;
1366 printk("Loading ADM6996 driver... \n");
1368 /* if running on adm5120 */
1369 /* set GPIO 0~2 as adm6996 control pins */
1370 //outl(0x003f3f00, 0x12000028);
1371 /* enable switch port 5 (MII) as RMII mode (5120MAC <-> 6996MAC) */
1372 //outl(0x18a, 0x12000030);
1373 /* group adm5120 port 1 ~ 5 as VLAN0, port 5 & 6(CPU) as VLAN1 */
1374 //outl(0x417e, 0x12000040);
1375 /* end adm5120 fixup */
1376 #ifdef ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
1377 register_chrdev(69, "adm6996", &adm_ops
);
1378 AMAZON_SW_REG(AMAZON_SW_MDIO_CFG
) = 0x27be;
1379 AMAZON_SW_REG(AMAZON_SW_EPHY
) = 0xfc;
1380 adm6996_mode
=adm6996i
;
1381 ifx_sw_read(0xa0, &val
);
1382 ifx_sw_read(0xa1, &val1
);
1383 val
=((val1
&0x0f)<<16)|val
;
1384 printk ("\nADM6996 SMI Mode-");
1385 printk ("Chip ID:%5x \n ", val
);
1386 #else //000001.joelin
1388 AMAZON_SW_REG(AMAZON_SW_MDIO_CFG
) = 0x2c50;
1389 AMAZON_SW_REG(AMAZON_SW_EPHY
) = 0xff;
1391 AMAZON_SW_REG(AMAZON_GPIO_P1_ALTSEL0
) &= ~(GPIO_MDIO
|GPIO_MDCS
|GPIO_MDC
);
1392 AMAZON_SW_REG(AMAZON_GPIO_P1_ALTSEL1
) &= ~(GPIO_MDIO
|GPIO_MDCS
|GPIO_MDC
);
1393 AMAZON_SW_REG(AMAZON_GPIO_P1_OD
) |= (GPIO_MDIO
|GPIO_MDCS
|GPIO_MDC
);
1396 register_chrdev(69, "adm6996", &adm_ops
);
1399 /* create proc entries */
1400 // create_proc_read_entry("admide", 0, NULL, admide_proc, NULL);
1402 //joelin adm6996i support start
1403 adm6996_mode
=adm6996i
;
1404 ifx_sw_read(0xa0, &val
);
1405 adm6996_mode
=adm6996l
;
1406 ifx_sw_read(0x200, &val1
);
1407 // printk ("\n %0x \n",val1);
1408 if ((val
&0xfff0)==0x1020) {
1409 printk ("\n ADM6996I .. \n");
1410 adm6996_mode
=adm6996i
;
1412 else if ((val1
&0xffffff00)==0x71000) {//71010 or 71020
1413 printk ("\n ADM6996LC .. \n");
1414 adm6996_mode
=adm6996lc
;
1417 printk ("\n ADM6996L .. \n");
1418 adm6996_mode
=adm6996l
;
1420 #endif //ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
1422 if ((adm6996_mode
==adm6996lc
)||(adm6996_mode
==adm6996i
)){
1423 #if 0 /* removed by MarsLin */
1424 ifx_sw_write(0x29,0xc000);
1425 ifx_sw_write(0x30,0x0985);
1427 ifx_sw_read(0xa0, &val
);
1428 if (val
== 0x1021) // for both 6996LC and 6996I, only AB version need the patch
1429 ifx_sw_write(0x29, 0x9000);
1430 ifx_sw_write(0x30,0x0985);
1433 //joelin adm6996i support end
1437 void __exit
cleanup_adm6996_module(void)
1439 printk("Free ADM device driver... \n");
1441 unregister_chrdev(69, "adm6996");
1443 /* remove proc entries */
1444 // remove_proc_entry("admide", NULL);
1447 /* MarsLin, add start */
1448 #if defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT) || defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT_MODULE)
1449 #define SET_BIT(reg, mask) reg |= (mask)
1450 #define CLEAR_BIT(reg, mask) reg &= (~mask)
1451 static int ifx_hw_reset(void)
1453 CLEAR_BIT((*AMAZON_GPIO_P0_ALTSEL0
),0x2000);
1454 CLEAR_BIT((*AMAZON_GPIO_P0_ALTSEL1
),0x2000);
1455 SET_BIT((*AMAZON_GPIO_P0_OD
),0x2000);
1456 SET_BIT((*AMAZON_GPIO_P0_DIR
), 0x2000);
1457 CLEAR_BIT((*AMAZON_GPIO_P0_OUT
), 0x2000);
1459 SET_BIT((*AMAZON_GPIO_P0_OUT
), 0x2000);
1460 cleanup_adm6996_module();
1461 return init_adm6996_module();
1463 int (*adm6996_hw_reset
)(void) = ifx_hw_reset
;
1464 EXPORT_SYMBOL(adm6996_hw_reset
);
1465 EXPORT_SYMBOL(adm6996_mode
);
1466 int (*adm6996_sw_read
)(unsigned int addr
, unsigned int *data
) = ifx_sw_read
;
1467 EXPORT_SYMBOL(adm6996_sw_read
);
1468 int (*adm6996_sw_write
)(unsigned int addr
, unsigned int data
) = ifx_sw_write
;
1469 EXPORT_SYMBOL(adm6996_sw_write
);
1471 /* MarsLin, add end */
1473 /* Santosh: for IGMP proxy/snooping, Begin */
1474 EXPORT_SYMBOL (adm_process_mac_table_request
);
1475 EXPORT_SYMBOL (adm_process_protocol_filter_request
);
1476 /* Santosh: for IGMP proxy/snooping, End */
1478 MODULE_DESCRIPTION("ADMtek 6996 Driver");
1479 MODULE_AUTHOR("Joe Lin <joe.lin@infineon.com>");
1480 MODULE_LICENSE("GPL");
1482 module_init(init_adm6996_module
);
1483 module_exit(cleanup_adm6996_module
);