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