#include #include #include #define outw(address, value) *((volatile uint32_t *)(address)) = cpu_to_le32(value) #define inw(address) le32_to_cpu(*(volatile u32 *)(address)) #if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \ defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \ defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) #define PHY_CONTROL_0 0xC0 #define PHY_CONTROL_1 0xC4 #define MDIO_PHY_CONTROL_0 (RALINK_ETH_SW_BASE + PHY_CONTROL_0) #define MDIO_PHY_CONTROL_1 (RALINK_ETH_SW_BASE + PHY_CONTROL_1) #define GPIO_MDIO_BIT (1<<7) #define GPIO_PURPOSE_SELECT 0x60 #define GPIO_PRUPOSE (RALINK_SYSCTL_BASE + GPIO_PURPOSE_SELECT) #elif defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \ defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) || \ defined (RT6352_FPGA_BOARD) || defined (RT6352_ASIC_BOARD) || \ defined (RT71100_FPGA_BOARD) || defined (RT71100_ASIC_BOARD) #define PHY_CONTROL_0 0x7004 #define PHY_CONTROL_1 0x7000 #define MDIO_PHY_CONTROL_0 (RALINK_ETH_SW_BASE + PHY_CONTROL_0) #define MDIO_PHY_CONTROL_1 (RALINK_ETH_SW_BASE + PHY_CONTROL_1) #define GPIO_MDIO_BIT (1<<7) #define GPIO_PURPOSE_SELECT 0x60 #define GPIO_PRUPOSE (RALINK_SYSCTL_BASE + GPIO_PURPOSE_SELECT) #else #define PHY_CONTROL_0 0x00 #define PHY_CONTROL_1 0x04 #define MDIO_PHY_CONTROL_0 (RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_0) #define MDIO_PHY_CONTROL_1 (RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_1) #define enable_mdio(x) #endif #if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \ defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \ defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \ defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \ defined (RT6352_FPGA_BOARD) || defined (RT6352_ASIC_BOARD) || \ defined (RT71100_FPGA_BOARD) || defined (RT71100_ASIC_BOARD) void enable_mdio(int enable) { #if !defined (P5_MAC_TO_PHY_MODE) u32 data = inw(GPIO_PRUPOSE); if(enable) data &= ~GPIO_MDIO_BIT; else data |= GPIO_MDIO_BIT; outw(GPIO_PRUPOSE, data); #endif } #endif #if defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) #define enable_mdio(x) #endif #if defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \ defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) || \ defined (RT6352_FPGA_BOARD) || defined (RT6352_ASIC_BOARD) || \ defined (RT71100_FPGA_BOARD) || defined (RT71100_ASIC_BOARD) int mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data) { u32 volatile status = 0; u32 volatile data = 0; u32 rc = 0; unsigned long volatile t_start = get_timer(0); /* We enable mdio gpio purpose register, and disable it when exit. */ enable_mdio(1); //printf("\n MDIO Read operation!!\n"); // make sure previous read operation is complete while(1) { // 0 : Read/write operation complet if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) { break; }else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)){ enable_mdio(0); printf("\n MDIO Read operation is ongoing !!\n"); return rc; } } data = (0x01 << 16) | (0x02 << 18) | (phy_addr << 20) | (phy_register << 25); outw(MDIO_PHY_CONTROL_0, data); data |= (1<<31); outw(MDIO_PHY_CONTROL_0, data); //printf("\n Set Command [0x%08X] to PHY 0x%8x!!\n", data, MDIO_PHY_CONTROL_0); // make sure read operation is complete t_start = get_timer(0); while(1) { if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) { udelay(100000); status = inw(MDIO_PHY_CONTROL_0); *read_data = (u32)(status & 0x0000FFFF); //printf("\n MDIO_PHY_CONTROL_0: 0x%8x!!\n", status); enable_mdio(0); return 1; } else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)) { enable_mdio(0); printf("\n MDIO Read operation is ongoing and Time Out!!\n"); return 0; } } } int mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data) { unsigned long volatile t_start=get_timer(0); u32 volatile data; enable_mdio(1); // make sure previous write operation is complete while(1) { if (!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) { break; } else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)) { enable_mdio(0); printf("\n MDIO Write operation is ongoing !!\n"); return 0; } } data = (0x01 << 16) | (1<<18) | (phy_addr << 20) | (phy_register << 25) | write_data; outw(MDIO_PHY_CONTROL_0, data); data |= (1<<31); outw(MDIO_PHY_CONTROL_0, data); //start operation //printf("\n Set Command [0x%08X] to PHY 0x%8x!!\n", data, MDIO_PHY_CONTROL_0); t_start = get_timer(0); // make sure write operation is complete while(1) { if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) // 0 : Read/write operation complete { enable_mdio(0); return 1; } else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)) { enable_mdio(0); printf("\n MDIO Write operation is ongoing and Time Out!!\n"); return 0; } } } #else int mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data) { u32 volatile status = 0; u32 volatile data = 0; u32 rc = 0; unsigned long volatile t_start = get_timer(0); /* We enable mdio gpio purpose register, and disable it when exit. */ enable_mdio(1); // make sure previous read operation is complete while(1) { #if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \ defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \ defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) // rd_rdy: read operation is complete if(!( inw(MDIO_PHY_CONTROL_1) & (0x1 << 1))) #else // 0 : Read/write operation complet if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) #endif { break; }else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)){ enable_mdio(0); printf("\n MDIO Read operation is ongoing !!\n"); return rc; } } #if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \ defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \ defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) outw(MDIO_PHY_CONTROL_0 , (1<<14) | (phy_register << 8) | (phy_addr)); #else data = (phy_addr << 24) | (phy_register << 16); outw(MDIO_PHY_CONTROL_0, data); data |= (1<<31); outw(MDIO_PHY_CONTROL_0, data); #endif //printf("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0); // make sure read operation is complete t_start = get_timer(0); while(1) { #if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \ defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \ defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) if( inw(MDIO_PHY_CONTROL_1) & (0x1 << 1)) { status = inw(MDIO_PHY_CONTROL_1); *read_data = (u32)(status >>16); enable_mdio(0); return 1; } #else if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) { status = inw(MDIO_PHY_CONTROL_0); *read_data = (u32)(status & 0x0000FFFF); enable_mdio(0); return 1; } #endif else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)) { enable_mdio(0); printf("\n MDIO Read operation is ongoing and Time Out!!\n"); return 0; } } } int mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data) { unsigned long volatile t_start=get_timer(0); u32 volatile data; enable_mdio(1); // make sure previous write operation is complete while(1) { #if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \ defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \ defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \ defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \ defined (RT6352_FPGA_BOARD) || defined (RT6352_ASIC_BOARD) || \ defined (RT71100_FPGA_BOARD) || defined (RT71100_ASIC_BOARD) if(!( inw(MDIO_PHY_CONTROL_1) & (0x1 << 0))) #else if (!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) #endif { break; } else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)) { enable_mdio(0); printf("\n MDIO Write operation is ongoing !!\n"); return 0; } } #if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \ defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \ defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) data = ((write_data & 0xFFFF)<<16); data |= (phy_register << 8) | (phy_addr); data |= (1<<13); outw(MDIO_PHY_CONTROL_0, data); #else data = (1<<30) | (phy_addr << 24) | (phy_register << 16) | write_data; outw(MDIO_PHY_CONTROL_0, data); data |= (1<<31); outw(MDIO_PHY_CONTROL_0, data); //start operation #endif //printf("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0); t_start = get_timer(0); // make sure write operation is complete while(1) { #if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \ defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \ defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) if( inw(MDIO_PHY_CONTROL_1) & (0x1 << 0)) //wt_done ?= 1 #else if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) // 0 : Read/write operation complete #endif { enable_mdio(0); return 1; } else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)) { enable_mdio(0); printf("\n MDIO Write operation is ongoing and Time Out!!\n"); return 0; } } } #endif #ifdef RALINK_MDIO_ACCESS_FUN #if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \ defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \ defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) void dump_phy_reg(int port_no, int from, int to, int is_local) { u32 i=0; u32 temp=0; if(is_local==0) { printf("Global Register\n"); printf("==============="); mii_mgr_write(0, 31, 0); //select global register for(i=from;i<=to;i++) { if(i%8==0) { printf("\n"); } mii_mgr_read(port_no,i, &temp); printf("%02d: %04X ",i, temp); } } else { mii_mgr_write(0, 31, 0x8000); //select local register printf("\n\nLocal Register Port %d\n",port_no); printf("==============="); for(i=from;i<=to;i++) { if(i%8==0) { printf("\n"); } mii_mgr_read(port_no,i, &temp); printf("%02d: %04X ",i, temp); } } printf("\n"); } #else void dump_phy_reg(int port_no, int from, int to, int is_local, int page_no) { u32 i=0; u32 temp=0; u32 r31=0; if(is_local==0) { printf("\n\nGlobal Register Page %d\n",page_no); printf("==============="); r31 = 0 << 15; //global r31 = page_no&0x7 << 12; //page no mii_mgr_write(0, 31, r31); //select global page x for(i=16;i<32;i++) { if(i%8==0) { printf("\n"); } mii_mgr_read(port_no,i, &temp); printf("%02d: %04X ",i, temp); } }else { printf("\n\nLocal Register Port %d Page %d\n",port_no, page_no); printf("==============="); r31 = 1 << 15; //local r31 = page_no&0x7 << 12; //page no mii_mgr_write(0, 31, r31); //select local page x for(i=16;i<32;i++) { if(i%8==0) { printf("\n"); } mii_mgr_read(port_no,i, &temp); printf("%02d: %04X ",i, temp); } } printf("\n"); } #endif int rt2880_mdio_access(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { u32 addr; u32 phy_addr; u32 value = 0,bit_offset,temp; u32 i=0; if(!memcmp(argv[0],"mdio.anoff",sizeof("mdio.anoff"))) { #if defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \ defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) || \ defined (RT6352_FPGA_BOARD) || defined (RT6352_ASIC_BOARD) || \ defined (RT71100_FPGA_BOARD) || defined (RT71100_ASIC_BOARD) value = inw(MDIO_PHY_CONTROL_1); value &= ~(1 << 31); outw(MDIO_PHY_CONTROL_1,value); puts("\n GMAC1 Force link status enable !! \n"); #else value = inw(MDIO_PHY_CONTROL_1); value |= (1<<15); outw(MDIO_PHY_CONTROL_1,value); puts("\n GMAC1 Force link status enable !! \n"); #endif } else if(!memcmp(argv[0],"mdio.anon",sizeof("mdio.anon"))) { #if defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \ defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) || \ defined (RT6352_FPGA_BOARD) || defined (RT6352_ASIC_BOARD) || \ defined (RT71100_FPGA_BOARD) || defined (RT71100_ASIC_BOARD) value = inw(MDIO_PHY_CONTROL_1); value |= (1<<31); outw(MDIO_PHY_CONTROL_1,value); puts("\n GMAC1 Force link status disable !! \n"); #else value = inw(MDIO_PHY_CONTROL_1); value &= ~(1 << 15); outw(MDIO_PHY_CONTROL_1,value); puts("\n GMAC1 Force link status disable !! \n"); #endif } else if(!memcmp(argv[0],"mdio.r",sizeof("mdio.r"))) { if (argc != 3) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } phy_addr = simple_strtoul(argv[1], NULL, 10); addr = simple_strtoul(argv[2], NULL, 10); phy_addr &=0x1f; if(mii_mgr_read(phy_addr, addr, &value)) printf("\n mdio.r addr[0x%08X]=0x%04X\n",addr,value); else { printf("\n Read addr[0x%08X] is Fail!!\n",addr); } } else if(!memcmp(argv[0],"mdio.w",sizeof("mdio.w"))) { if (argc != 4) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } phy_addr = simple_strtoul(argv[1], NULL, 10); addr = simple_strtoul(argv[2], NULL, 10); value = simple_strtoul(argv[3], NULL, 16); phy_addr &=0x1f; if(mii_mgr_write(phy_addr, addr,value)) { printf("\n mdio.w addr[0x%08X] value[0x%08X]\n",addr,value); } else { printf("\n Write[0x%08X] is Fail!!\n",addr); } } else if(!memcmp(argv[0],"mdio.wb",sizeof("mdio.wb"))) { if (argc != 4) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } addr = simple_strtoul(argv[1], NULL, 10); bit_offset = simple_strtoul(argv[2], NULL, 10); value = simple_strtoul(argv[3], NULL, 10); if(mii_mgr_read(31, addr,&temp)) { } else { printf("\n Rasd PHY fail while mdio.wb was called\n"); return 1; } if(value) { printf("\n Set bit[%d] to '1' \n",bit_offset); temp |= (1<