01 > ȸҰ

 
작성일 : 16-03-03 16:34
ZYNQ 7 lwip Echo Server 모두시 Micrel PHY KSZ9031 추가 함수 ( 호출 관계 분석)
 글쓴이 : 이로직…
조회 : 6,500  
// 파일명: xemacpsif.c
static err_t low_level_init(struct netif *netif){
init_emacps(xemacpsif, netif);

}

// 여기 호출
// 파일명: xemacpsif_hw.c
void init_emacps(xemacpsif_s *xemacps, struct netif *netif)
{
u32_t mac_address = (u32_t)(netif->state);
XEmacPs *xemacpsp;
XEmacPs_Config *mac_config;
s32_t status = XST_SUCCESS;
u32_t i;
u32_t phyfoundforemac0 = FALSE;
u32_t phyfoundforemac1 = FALSE;

mac_config = (XEmacPs_Config *)xemacps_lookup_config(mac_address);

xemacpsp = &xemacps->emacps;

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);

#ifdef PCM_PMA_CORE_PRESENT
#ifdef XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT
link_speed = phy_setup(xemacpsp, XPAR_PCSPMA_1000BASEX_PHYADDR);
#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT
link_speed = phy_setup(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(xemacpsp, i); /// initialize maker phy vendor
phyfoundforemac0 = TRUE;
}
} else {
if (phymapemac1[i] == TRUE) {
link_speed = phy_setup(xemacpsp, i);
phyfoundforemac1 = TRUE;
}
}
}
if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
if (phyfoundforemac0 == FALSE)
link_speed = phy_setup(xemacpsp, 0);
} else {
if (phyfoundforemac1 == FALSE)
link_speed = phy_setup(xemacpsp, 0);
}
#endif

XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
{
volatile s32_t wait;
for (wait=0; wait < 20000; wait++);
}
}

void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif)
{
u32_t mac_address = (u32_t)(netif->state);
XEmacPs *xemacpsp;
XEmacPs_Config *mac_config;
s32_t status = XST_SUCCESS;

mac_config = (XEmacPs_Config *)xemacps_lookup_config(mac_address);

xemacpsp = &xemacps->emacps;

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_SetOperatingSpeed(xemacpsp, link_speed);

{
volatile s32_t wait;
for (wait=0; wait < 20000; wait++);
}
}

void setup_isr (struct xemac_s *xemac)
{
xemacpsif_s *xemacpsif;

xemacpsif = (xemacpsif_s *)(xemac->state);
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
(void *) emacps_send_handler,
(void *) xemac);

XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
(void *) emacps_recv_handler,
(void *) xemac);

XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
(void *) emacps_error_handler,
(void *) xemac);
}

// 여기호출
// 파일명: xemacpsif_speed.c
void detect_phy(XEmacPs *xemacpsp)
{
u16_t phy_reg;
u32_t phy_addr;
u32_t emacnum;

if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR)
emacnum = 0;
else
emacnum = 1;
//while(1){
for (phy_addr = 31; phy_addr > 0; phy_addr--) {
XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
&phy_reg);

if ((phy_reg != 0xFFFF) &&
((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
phy_addr));
if (emacnum == 0)
phymapemac0[phy_addr] = TRUE;
else
phymapemac1[phy_addr] = TRUE;

XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
&phy_reg);
if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
(phy_reg != PHY_TI_IDENTIFIER)) {
xil_printf("WARNING: Not a Marvell or TI Ethernet PHY. Please verify the initialization sequence\r\n");
}
}
}

//}
}

u32_t phy_setup (XEmacPs *xemacpsp, u32_t phy_addr)
{
u32_t link_speed;
u16_t regval;
u32_t conv_present = 0;
u32_t convspeeddupsetting = 0;
u32_t convphyaddr = 0;

link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr); // micron phy set
if (link_speed == 1000) {
SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
} else if (link_speed == 100) {
SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
} else {
SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
}

if (conv_present) {
XEmacPs_PhyWrite(xemacpsp, convphyaddr,
XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
}

xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
return link_speed;
}


static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
{
u16_t phy_identity;
u32_t RetStatus;

XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
&phy_identity);
if (phy_identity == PHY_TI_IDENTIFIER) {
RetStatus = get_TI_phy_speed(xemacpsp, phy_addr);
}
else if(phy_identity == PHY_MIC_IDENTIFIER){
RetStatus = get_Micrel_phy_speed(xemacpsp, phy_addr);
} else {
RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
}
if (RetStatus != XST_SUCCESS) {
return RetStatus;
}

return XST_SUCCESS;
}

static u32_t get_Micrel_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
{
u16_t temp;
u16_t control;
u16_t status;
u16_t status_speed;
u32_t timeout_counter = 0;
u32_t temp_speed;
u32_t phyregtemp;

xil_printf("Start Micrel PHY autonegotiation \r\n");

XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); //reg 0x04
control |= IEEE_ASYMMETRIC_PAUSE_MASK; //0x0800
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_COPPER_SPECIFIC_CONTROL_REG, &control); //reg 0x0f
control |= (7 << 12);
control |= (1 << 11);
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, control);

XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); //reg 0x00
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);
XEmacPs_PhyRead(xemacpsp, phy_addr,
IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
timeout_counter++;

if (timeout_counter == 30) {
xil_printf("Auto negotiation error \r\n");
return;
}
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
}
xil_printf("autonegotiation complete \r\n");

#define IEEE_1000BASE_STATUS_REG 0x0a

//XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG, &status_speed);
XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_1000BASE_STATUS_REG, &status_speed);
if (status_speed & 0x0800) {

xil_printf("micrel phy ksz9031 speed %x \r\n",status_speed);
return 1000;
}

return XST_SUCCESS;
}