📄 lepus_gmac_phy.c
字号:
/***************************************************************************** Copyright Storlink Corp 2005. All rights reserved. *--------------------------------------------------------------------------* Name : emac_phy.c* Description : * Handle Ethernet PHY and MII interface** History** Date Writer Description* ----------- ----------- -------------------------------------------------* 08/16/2005 Gary Chen Create and implement from Amos Linux Code*****************************************************************************/#include <define.h>#include <board_config.h>#include <sl2312.h>#if defined(MIDWAY) && (defined(LEPUS_FPGA) || defined(LEPUS_ASIC))#include "sl_lepus_gmac.h"//extern unsigned int FLAG_SWITCH;unsigned int mii_read(unsigned char phyad,unsigned char regad);void mii_write(unsigned char phyad,unsigned char regad,unsigned int value);extern void gmac_write_reg(unsigned int base, unsigned int offset,unsigned int data,unsigned int bit_mask);extern void toe_gmac_disable_tx_rx(void);//(GMAC_INFO_T *tp);extern void toe_gmac_enable_tx_rx(void);//(GMAC_INFO_T *tp);void gmac_get_phy_status(GMAC_INFO_T *tp);extern unsigned int gmac_read_reg(unsigned int base, unsigned int offset);extern void gmac_write_reg(unsigned int base, unsigned int offset,unsigned int data,unsigned int bit_mask);extern gmac_num;int switch_pre_speed[5]={0,0,0,0,0};int switch_pre_link[5]={0,0,0,0,0};unsigned int switch_status;void gmac_set_phy_status(GMAC_INFO_T *tp){ GMAC_STATUS_T status; unsigned int reg_val, ability ,rcv_mask; unsigned int i = 0; if(gmac_num) {#if 0 switch_status = LINK_DOWN; rcv_mask = SPI_read(2,0,0x10); // Receive mask rcv_mask |= 0x4F; for(i=0;i<4;i++){ reg_val = BIT(26)|(i<<21)|(10<<16); SPI_write(3,0,1,reg_val); hal_delay_us(10*1000); reg_val = SPI_read(3,0,2); if(reg_val & 0x0c00){ //printf("Port%d:Giga mode\n",i); SPI_write(1,i,0x00,0x300701b1); SPI_write(1,i,0x00,0x10070181); switch_pre_link[i]=LINK_UP; switch_pre_speed[i]=GMAC_SPEED_1000; } else{ reg_val = BIT(26)|(i<<21)|(5<<16); SPI_write(3,0,1,reg_val); hal_delay_us(10*1000); ability = (reg_val = SPI_read(3,0,2)&0x5e0) >>5; if ((ability & 0x0C)) /* 100M full duplex */ { SPI_write(1,i,0x00,0x30050472); SPI_write(1,i,0x00,0x10050442); //printf("Port%d:100M\n",i); switch_pre_link[i]=LINK_UP; switch_pre_speed[i]=GMAC_SPEED_100; } else if((ability & 0x03)) /* 10M full duplex */ { SPI_write(1,i,0x00,0x30050473); SPI_write(1,i,0x00,0x10050443); //printf("Port%d:10M\n",i); switch_pre_link[i]=LINK_UP; switch_pre_speed[i]=GMAC_SPEED_10; } else{ SPI_write(1,i,0x00,0x20000030); // PORT_RST switch_pre_link[i]=LINK_DOWN; switch_pre_speed[i]=GMAC_SPEED_10; rcv_mask &= ~BIT(i); SPI_write(2,0,0x10,rcv_mask); // Disable Receive } } } SPI_write(2,0,0x10,rcv_mask); // Enable Receive#endif gmac_get_phy_status(tp); gmac_write_reg(tp->base_addr, GMAC_STATUS, 0x7d, 0x0000007f); } else { // if (FLAG_SWITCH==1) // { // return; /* GMAC connects to a switch chip, not PHY */ // } reg_val=(mii_read(tp->phy_addr,0x02) << 16) + mii_read(tp->phy_addr,0x03); printf("PHY %d Addr %d Vendor ID: 0x%08x\n", tp->phy_id, tp->phy_addr, reg_val); #if defined(GEMINI_ASIC) || defined(LEPUS_ASIC) mii_write(tp->phy_addr,0x04,0x05e1); mii_write(tp->phy_addr,0x09,0x0300); #else mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */ mii_write(tp->phy_addr,0x09,0x0000); /* advertisement no 1000M */ #endif mii_write(tp->phy_addr,0x00,0x1200); reg_val = 0x1200 | (1 << 15); mii_write(tp->phy_addr,0x00,reg_val); /* Enable and Restart Auto-Negotiation */ reg_val &= ~(1 << 15); mii_write(tp->phy_addr, 0x00, reg_val); hal_delay_us(100000);#if 1 // SJC if (1) { unsigned int reg_val; reg_val = mii_read(tp->phy_addr, 0x18); reg_val |= 1; mii_write(tp->phy_addr, 0x18, reg_val); }#endif } gmac_get_phy_status(tp);}void gmac_get_phy_status(GMAC_INFO_T *tp){ GMAC_CONFIG0_T config0,config0_mask; GMAC_STATUS_T status, old_status; unsigned int reg_val,ability; unsigned int dev_index,rcv_mask,mac_config,speed_fdx_mode,link_mode=0; int i; if(gmac_num) { rcv_mask = SPI_read(2,0,0x10); // Receive mask old_status.bits32 = status.bits32 = gmac_read_reg(tp->base_addr, GMAC_STATUS); for(i=0;i<4;i++){ //if(((phy_read(i, 1) & 0x0004) != 0)) //{ // printf("Port %x link up\n",i); // // /* Get info about speed and duplex mode from PHY reg. 28 */ // reg_val = phy_read(i, 28);
// // /* set speed field (bit 1:0) = bit 4:3 of PHY reg. */ // speed_fdx_mode = ((unsigned char) reg_val >> 3) & 0x03;
// // /* update full duplex bit */ // if (reg_val & 0x20) { // speed_fdx_mode |= 0x10; // } // // // /* check if link partner supports pause frames */ // if (phy_read(i, 5) & 0x0400) { // link_mode |= 0x20; // } // printf("reg_val %x speed_fdx_mode %x link_mode %x\n",reg_val,speed_fdx_mode,link_mode); //} reg_val = BIT(26)|(i<<21)|(1<<16); SPI_write(3,0,1,reg_val); hal_delay_us(5*1000); reg_val = SPI_read(3,0,2); if ((reg_val & 0x0024) == 0x0024) /* link is established and auto_negotiate process completed */ { if(switch_pre_link[i]==LINK_DOWN){ // Link Down ==> Link up rcv_mask |= BIT(i); // Enable receive //reg_val = phy_read(i,28) ; reg_val = BIT(26)|(i<<21)|(10<<16); SPI_write(3,0,1,reg_val); hal_delay_us(5*1000); reg_val = SPI_read(3,0,2); if(reg_val & 0x0c00){#if 0 printk("Port%d:Giga mode\n",i); phy_optimize_receiver_reconfig(i); SPI_write(1,i,0x00,0x300701B1); SPI_write(1,i,0x00,0x10070181); switch_pre_link[i]=LINK_UP; switch_pre_speed[i]=GMAC_SPEED_1000;#else //printk("Port%d:Giga mode\n",i); //mac_config = 0x00060004; mac_config = 0x00060184; SPI_write(1,i,0x00,((mac_config & 0xfffffff8) | 1) | 0x20000030); // reset port mac_config |= (( BIT(i) << 19) | 0x08000000); SPI_write(1,i,0x00,mac_config); SPI_write(1,i,0x04,0x000300ff); // flow control reg_val = SPI_read(5,0,0x12); reg_val &= ~BIT(i); SPI_write(5,0,0x12,reg_val); reg_val = SPI_read(1,i,0x00); reg_val |= 0x18010000; SPI_write(1,i,0x00,reg_val); //phy_receiver_reconfig(i); switch_pre_link[i]=LINK_UP; switch_pre_speed[i]=GMAC_SPEED_1000; #endif } else{ reg_val = BIT(26)|(i<<21)|(5<<16); SPI_write(3,0,1,reg_val); hal_delay_us(5 * 1000); ability = (reg_val = SPI_read(3,0,2)&0x5e0) >>5; if ((ability & 0x0C)) /* 100M full duplex */ {#if 0 SPI_write(1,i,0x00,0x30050472); SPI_write(1,i,0x00,0x10050442); printk("Port%d:100M\n",i); switch_pre_link[i]=LINK_UP; switch_pre_speed[i]=GMAC_SPEED_100;#else //mac_config = 0x00040004; mac_config = 0x00040444; SPI_write(1,i,0x00,((mac_config & 0xfffffff8) | 1) | 0x20000030); // reset port mac_config |= (( BIT(i) << 19) | 0x08000000); SPI_write(1,i,0x00,mac_config); SPI_write(1,i,0x04,0x000300ff); // flow control reg_val = SPI_read(5,0,0x12); reg_val &= ~BIT(i); SPI_write(5,0,0x12,reg_val); reg_val = SPI_read(1,i,0x00); reg_val |= 0x18010000; SPI_write(1,i,0x00,reg_val); //printk("Port%d:100M\n",i); switch_pre_link[i]=LINK_UP; switch_pre_speed[i]=GMAC_SPEED_100;#endif } else if((ability & 0x03)) /* 10M full duplex */ {#if 0 SPI_write(1,i,0x00,0x30050473); SPI_write(1,i,0x00,0x10050443); printk("Port%d:10M\n",i); switch_pre_link[i]=LINK_UP; switch_pre_speed[i]=GMAC_SPEED_10;#else mac_config = 0x00040004; SPI_write(1,i,0x00,((mac_config & 0xfffffff8) | 1) | 0x20000030); // reset port mac_config |= (( BIT(i) << 19) | 0x08000000); SPI_write(1,i,0x00,mac_config); SPI_write(1,i,0x04,0x000300ff); // flow control reg_val = SPI_read(5,0,0x12); reg_val &= ~BIT(i); SPI_write(5,0,0x12,reg_val); reg_val = SPI_read(1,i,0x00); reg_val |= 0x18010000; SPI_write(1,i,0x00,reg_val); //printk("Port%d:10M\n",i); switch_pre_link[i]=LINK_UP; switch_pre_speed[i]=GMAC_SPEED_10;#endif } else{ SPI_write(1,i,0x00,0x20000030); //printk("Port%d:Unknown mode\n",i); switch_pre_link[i]=LINK_DOWN; switch_pre_speed[i]=GMAC_SPEED_10; } } arp_flush_cache();#if 0 reg_val = SPI_read(2,0,0x80+i); reg_val &= ~BIT(i); SPI_write(2,0,0x80+i,reg_val);#endif } else{ // Link up ==> Link UP tp->pre_phy_status = LINK_UP; } if((tp->pre_phy_status == LINK_UP)&&(switch_status == LINK_DOWN)) { //printf(" toe_gmac_enable_tx_rx 1: \n"); toe_gmac_enable_tx_rx(); switch_status = LINK_UP; } } else{ // Link up ==> Link Down if(switch_pre_link[i]==LINK_UP){#if 0 printk("Port%d:Link Down\n",i); phy_optimize_receiver_init(i); reg_val = SPI_read(1,i,0x00); reg_val &= ~BIT(16); SPI_write(1,i,0x00,reg_val); // disable RX SPI_write(5,0,0x0E,BIT(i)); // dicard packet while((SPI_read(5,0,0x0C)&BIT(i))==0) // wait to be empty hal_delay_us(1*1000); SPI_write(1,i,0x00,0x20000030); // PORT_RST#else //printk("Port%d:Link Down\n",i); phy_receiver_init(i); reg_val = SPI_read(1,i,0); reg_val &= ~BIT(16); SPI_write(1,i,0x00,reg_val); // disable RX SPI_write(5,0,0x0E,BIT(i)); // dicard packet while((SPI_read(5,0,0x0C)&BIT(i))==0) // wait to be empty hal_delay_us(1*1000); SPI_write(1,i,0x00,0x20000030); // PORT_RST SPI_write(5,0,0x0E,SPI_read(5,0,0x0E)&~BIT(i)); // dicard packet reg_val = SPI_read(5,0,0x12); reg_val |= BIT(i); SPI_write(5,0,0x12,reg_val);#endif }#if 0 switch_pre_link[i]=LINK_DOWN; rcv_mask &= ~BIT(i); // disable receive SPI_write(5,0,0x12,BIT(i)); #else switch_pre_link[i]=LINK_DOWN; rcv_mask &= ~BIT(i); // disable receive#endif } } if((switch_pre_link[0]==LINK_DOWN)&&(switch_pre_link[1]==LINK_DOWN)&&(switch_pre_link[2]==LINK_DOWN)&&(switch_pre_link[3]==LINK_DOWN)) tp->pre_phy_status = LINK_DOWN; SPI_write(2,0,0x10,rcv_mask); // Receive mask if((tp->pre_phy_status == LINK_UP)&&(switch_status == LINK_DOWN)) { //printf(" toe_gmac_enable_tx_rx: \n"); toe_gmac_enable_tx_rx(); switch_status = LINK_UP; } else if((tp->pre_phy_status == LINK_DOWN)&&(switch_status == LINK_UP)){ //printf("toe_gmac_disable_tx_rx\n"); toe_gmac_disable_tx_rx(); //arp_flush_cache(); switch_status = LINK_DOWN; } } else //if(!gmac_num) { status.bits32 = old_status.bits32 = gmac_read_reg(tp->base_addr, GMAC_STATUS); /* read PHY status register */ reg_val = mii_read(tp->phy_addr,0x01); if ((reg_val & 0x0024) == 0x0024) /* link is established and auto_negotiate process completed */ { /* read PHY Auto-Negotiation Link Partner Ability Register */ reg_val = mii_read(tp->phy_addr,10); if ((reg_val & 0x0800) == 0x0800)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -