赞
踩
//工业级
static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
{
u16_t control;
u16_t status;
u16_t status_speed;
u32_t timeout_counter = 0;
u32_t temp_speed;
xil_printf("Start Realtek PHY autonegotiation \r\n");
/***********************************************************************/
XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, &control);
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, 0xD08);
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x10, 0x5E);
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x11, 0x109);
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, 0xA42);
usleep(10);
/***********************************************************************/
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
control |= IEEE_ASYMMETRIC_PAUSE_MASK;
control |= IEEE_PAUSE_MASK;
control |= ADVERTISE_100;
control |= ADVERTISE_10;
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &control);
control |= ADVERTISE_1000;
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, control);
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
control |= IEEE_CTRL_RESET_MASK;
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
while (1)
{
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
if (control & IEEE_CTRL_RESET_MASK)
continue;
else
break;
}
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
while (!(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE))
{
sleep(1);
timeout_counter++;
if (timeout_counter == 30)
{
xil_printf("Auto negotiation error \r\n");
return XST_FAILURE;
}
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
}
xil_printf("autonegotiation complete \r\n");
XEmacPs_PhyRead(xemacpsp, phy_addr, 0X1A, &status_speed); /* Industrial RTL8211 */
if (status_speed & 0x04)
{
temp_speed = status_speed & 0x30;
if (temp_speed == 0x20)
return 1000;
else if (temp_speed == 0x10)
return 100;
else
return 10;
}
return XST_SUCCESS;
}
//商业级,商业级这个没测,也是网上找到的,我也粘贴出来
static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
{
u16_t control;
u16_t status;
u16_t status_speed;
u32_t timeout_counter = 0;
u32_t temp_speed;
xil_printf("Start PHY autonegotiation \r\n");
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
control |= IEEE_ASYMMETRIC_PAUSE_MASK;
control |= IEEE_PAUSE_MASK;
control |= ADVERTISE_100;
control |= ADVERTISE_10;
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &control);
control |= ADVERTISE_1000;
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, control);
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
control |= IEEE_CTRL_RESET_MASK;
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
while (1)
{
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
if (control & IEEE_CTRL_RESET_MASK)
continue;
else
break;
}
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
while (!(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE))
{
sleep(1);
timeout_counter++;
if (timeout_counter == 30)
{
xil_printf("Auto negotiation error \r\n");
return XST_FAILURE;
}
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
}
xil_printf("autonegotiation complete \r\n");
XEmacPs_PhyRead(xemacpsp, phy_addr, 0x11, &status_speed); /* Commercial RTL8211*/
if (status_speed & 0x400)
{
temp_speed = status_speed & 0xc000;
if (temp_speed == 0x8000)
return 1000;
else if (temp_speed == 0x4000)
return 100;
else
return 10;
}
return XST_SUCCESS;
}
这个函数里面要注意下面这段,从Linux驱动里面薅出来的
/***********************************************************************/
XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, &control);
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, 0xD08);
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x10, 0x5E);
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x11, 0x109);
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, 0xA42);
usleep(10);
/***********************************************************************/
void init_emacps(xemacpsif_s *xemacps, struct netif *netif)
{
XEmacPs *xemacpsp;
s32_t status = XST_SUCCESS;
u32_t i;
u32_t phyfoundforemac0 = FALSE;
u32_t phyfoundforemac1 = FALSE;
xemacpsp = &xemacps->emacps;
#ifdef ZYNQMP_USE_JUMBO
XEmacPs_SetOptions(xemacpsp, XEMACPS_JUMBO_ENABLE_OPTION);
#endif
#ifdef LWIP_IGMP
XEmacPs_SetOptions(xemacpsp, XEMACPS_MULTICAST_OPTION);
#endif
/* set mac address */
status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
if (status != XST_SUCCESS) {
xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
}
XEmacPs_SetMdioDivisor(xemacpsp, MDC_DIV_224);
/* Please refer to file header comments for the file xemacpsif_physpeed.c
* to know more about the PHY programming sequence.
* For PCS PMA core, phy_setup_emacps is called with the predefined PHY address
* exposed through xaparemeters.h
* For RGMII case, assuming multiple PHYs can be present on the MDIO bus,
* detect_phy is called to get the addresses of the PHY present on
* a particular MDIO bus (emac0 or emac1). This address map is populated
* in phymapemac0 or phymapemac1.
* phy_setup_emacps is then called for each PHY present on the MDIO bus.
*/
#ifdef PCM_PMA_CORE_PRESENT
#ifdef XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT
link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_1000BASEX_PHYADDR);
#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT
link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_SGMII_PHYADDR);
#endif
#else
detect_phy(xemacpsp);
for (i = 31; i > 0; i--) {
if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
if (phymapemac0[i] == TRUE) {
link_speed = phy_setup_emacps(xemacpsp, i);
phyfoundforemac0 = TRUE;
phyaddrforemac = i;
}
} else {
if (phymapemac1[i] == TRUE) {
link_speed = phy_setup_emacps(xemacpsp, i);
phyfoundforemac1 = TRUE;
phyaddrforemac = i;
}
}
}
/* If no PHY was detected, use broadcast PHY address of 0 */
if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
if (phyfoundforemac0 == FALSE)
link_speed = phy_setup_emacps(xemacpsp, 1);
} else {
if (phyfoundforemac1 == FALSE)
link_speed = phy_setup_emacps(xemacpsp, 1);
}
#endif
if (link_speed == XST_FAILURE) {
eth_link_status = ETH_LINK_DOWN;
xil_printf("Assert due to phy setup failure \n\r",__func__);
} else {
eth_link_status = ETH_LINK_UP;
}
XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
/* Setting the operating speed of the MAC needs a delay. */
{
volatile s32_t wait;
for (wait=0; wait < 20000; wait++);
}
}
这个函数里面的link_speed = phy_setup_emacps(xemacpsp, 1);这一句是默认0,改成phy地址
在开头添加
do
{
XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG, &phy_identity);
}while(phy_identity != PHY_REALTEK_IDENTIFIER);
添加他避免有时候读取不到,硬件上面不太稳定吧估计
ps:有问题可以加448551544,加的时候注明来意否则不会通过
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。