1
0
This repository has been archived on 2024-07-22. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2022-11-27 10:16:14 +00:00

591 lines
16 KiB
C

#include <common.h>
#include <command.h>
#include <asm/arch/rt_mmap.h>
#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<<bit_offset);
}
else {
printf("\n Set bit[%d] to '0' \n",bit_offset);
temp &= ~(1<<bit_offset);
}
if(mii_mgr_write(31, addr,temp)) {
printf("\n mdio.wb addr[0x%08X] value[0x%08X]\n",addr,temp);
}
else {
printf("\n Write[0x%08X] is Fail!!\n",addr);
}
}
else if(!memcmp(argv[0],"mdio.d",sizeof("mdio.d")))
{
#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 (argc == 2) {
addr = simple_strtoul(argv[1], NULL, 10);
dump_phy_reg(0, 0, 31, 0); //dump global register
dump_phy_reg(addr, 0, 31, 1); //dump local register
}else {
/* Global Register 0~31
* Local Register 0~31
*/
dump_phy_reg(0, 0, 31, 0); //dump global register
for(i=0;i<5;i++) {
dump_phy_reg(i, 0, 31, 1); //dump local register
}
}
#else //RT6855A, RT6855, RT6352, RT71100
/* SPEC defined Register 0~15
* Global Register 16~31 for each page
* Local Register 16~31 for each page
*/
printf("SPEC defined Register\n");
printf("===============");
for(i=0;i<=16;i++) {
if(i%8==0) {
printf("\n");
}
mii_mgr_read(0,i, &temp);
printf("%02d: %04X ",i, temp);
}
if (argc == 2) {
addr = simple_strtoul(argv[1], NULL, 10);
dump_phy_reg(addr, 16, 31, 0, i);
dump_phy_reg(addr, 16, 31, 1, 0); //dump local page 0
dump_phy_reg(addr, 16, 31, 1, 1); //dump local page 1
dump_phy_reg(addr, 16, 31, 1, 2); //dump local page 2
dump_phy_reg(addr, 16, 31, 1, 3); //dump local page 3
}else {
for(i=0;i<4;i++) { //global register page 0~4
dump_phy_reg(0, 16, 31, 0, i);
}
for(i=0;i<5;i++) { //local register port 0-port4
dump_phy_reg(i, 16, 31, 1, 0); //dump local page 0
dump_phy_reg(i, 16, 31, 1, 1); //dump local page 1
dump_phy_reg(i, 16, 31, 1, 2); //dump local page 2
dump_phy_reg(i, 16, 31, 1, 3); //dump local page 3
}
}
#endif
}
return 0;
}
U_BOOT_CMD(
mdio, 4, 1, rt2880_mdio_access,
"mdio - Ralink PHY register R/W command !!\n",
"mdio.r [phy_addr(dec)] [reg_addr(dec)] \n"
"mdio.w [phy_addr(dec)] [reg_addr(dec)] [data(HEX)] \n"
"mdio.anoff GMAC1 Force link status enable !! \n"
"mdio.anon GMAC1 Force link status disable !! \n"
"mdio.wb [phy register(dec)] [bit offset(Dec)] [Value(0/1)] \n"
"mdio.d - dump all Phy registers \n"
"mdio.d [phy register(dec)] - dump Phy registers \n"
);
#endif // RALINK_MDIO_ACCESS_FUN //