-/*\r
- * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- *\r
- * * Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * * Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in\r
- * the documentation and/or other materials provided with the\r
- * distribution.\r
- * * Neither the name of Advanced Micro Devices, Inc. nor the names\r
- * of its contributors may be used to endorse or promote products\r
- * derived from this software without specific prior written\r
- * permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-/*\r
- * Some portions copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.\r
- *\r
- * Xilinx, Inc.\r
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE.\r
- *\r
- */\r
-\r
-/* Standard includes. */\r
-#include <stdint.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-\r
-#include "Zynq/x_emacpsif.h"\r
-//#include "lwipopts.h"\r
-#include "xparameters_ps.h"\r
-#include "xparameters.h"\r
-\r
-/* FreeRTOS includes. */\r
-#include "FreeRTOS.h"\r
-#include "task.h"\r
-#include "queue.h"\r
-#include "semphr.h"\r
-\r
-///* FreeRTOS+TCP includes. */\r
-/* FreeRTOS+TCP includes. */\r
-#include "FreeRTOS_IP.h"\r
-#include "FreeRTOS_Sockets.h"\r
-#include "FreeRTOS_IP_Private.h"\r
-#include "NetworkBufferManagement.h"\r
-\r
-int phy_detected = 0;\r
-\r
-/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c\r
- *** to run it on a PEEP board\r
- ***/\r
-\r
-/* Advertisement control register. */\r
-#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */\r
-#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */\r
-#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */\r
-#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */\r
-\r
-#define ADVERTISE_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | \\r
- ADVERTISE_10HALF | ADVERTISE_100HALF)\r
-#define ADVERTISE_100 (ADVERTISE_100FULL | ADVERTISE_100HALF)\r
-#define ADVERTISE_10 (ADVERTISE_10FULL | ADVERTISE_10HALF)\r
-\r
-#define ADVERTISE_1000 0x0300\r
-\r
-\r
-//#define PHY_REG_00_BMCR 0x00 // Basic mode control register\r
-//#define PHY_REG_01_BMSR 0x01 // Basic mode status register\r
-//#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1\r
-//#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2\r
-//#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg\r
-\r
-#define IEEE_CONTROL_REG_OFFSET 0\r
-#define IEEE_STATUS_REG_OFFSET 1\r
-#define IEEE_AUTONEGO_ADVERTISE_REG 4\r
-#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5\r
-#define IEEE_1000_ADVERTISE_REG_OFFSET 9\r
-#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10\r
-#define IEEE_COPPER_SPECIFIC_CONTROL_REG 16\r
-#define IEEE_SPECIFIC_STATUS_REG 17\r
-#define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19\r
-#define IEEE_CONTROL_REG_MAC 21\r
-#define IEEE_PAGE_ADDRESS_REGISTER 22\r
-\r
-\r
-#define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040\r
-#define IEEE_CTRL_LINKSPEED_MASK 0x0040\r
-#define IEEE_CTRL_LINKSPEED_1000M 0x0040\r
-#define IEEE_CTRL_LINKSPEED_100M 0x2000\r
-#define IEEE_CTRL_LINKSPEED_10M 0x0000\r
-#define IEEE_CTRL_RESET_MASK 0x8000\r
-#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000\r
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
-#define IEEE_CTRL_RESET 0x9140\r
-#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF\r
-#endif\r
-#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008\r
-#define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020\r
-#define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200\r
-#define IEEE_STAT_1GBPS_EXTENSIONS 0x0100\r
-#define IEEE_AN1_ABILITY_MASK 0x1FE0\r
-#define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00\r
-#define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380\r
-#define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060\r
-#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030\r
-\r
-#define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800\r
-#define IEEE_PAUSE_MASK 0x0400\r
-#define IEEE_AUTONEG_ERROR_MASK 0x8000\r
-\r
-#define PHY_DETECT_REG 1\r
-#define PHY_DETECT_MASK 0x1808\r
-\r
-#define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140\r
-#define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100\r
-#define XEMACPS_GMII2RGMII_SPEED10_FD 0x100\r
-#define XEMACPS_GMII2RGMII_REG_NUM 0x10\r
-\r
-/* Frequency setting */\r
-#define SLCR_LOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x4)\r
-#define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8)\r
-#define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140)\r
-#define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144)\r
-#ifdef PEEP\r
-#define SLCR_GEM_10M_CLK_CTRL_VALUE 0x00103031\r
-#define SLCR_GEM_100M_CLK_CTRL_VALUE 0x00103001\r
-#define SLCR_GEM_1G_CLK_CTRL_VALUE 0x00103011\r
-#endif\r
-#define SLCR_LOCK_KEY_VALUE 0x767B\r
-#define SLCR_UNLOCK_KEY_VALUE 0xDF0D\r
-#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214)\r
-#define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF\r
-\r
-#define EMAC0_BASE_ADDRESS 0xE000B000\r
-#define EMAC1_BASE_ADDRESS 0xE000C000\r
-\r
-static int detect_phy(XEmacPs *xemacpsp)\r
-{\r
- u16 phy_reg;\r
- u32 phy_addr;\r
-\r
- for (phy_addr = 31; phy_addr > 0; phy_addr--) {\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,\r
- &phy_reg);\r
-\r
- if ((phy_reg != 0xFFFF) &&\r
- ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {\r
- /* Found a valid PHY address */\r
- FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n",\r
- phy_addr));\r
- FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) );\r
- phy_detected = phy_addr;\r
- return phy_addr;\r
- }\r
- }\r
-\r
- FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected. Assuming a PHY at address 0\n" ) );\r
-\r
- /* default to zero */\r
- return 0;\r
-}\r
-\r
-#ifdef PEEP\r
-unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
-{\r
-\r
- u16 control;\r
- u16 status;\r
- u16 partner_capabilities;\r
- u16 partner_capabilities_1000;\r
- u16 phylinkspeed;\r
- u32 phy_addr = detect_phy(xemacpsp);\r
-\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
- ADVERTISE_1000);\r
- /* Advertise PHY speed of 100 and 10 Mbps */\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
- ADVERTISE_100_AND_10);\r
-\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
- &control);\r
- control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |\r
- IEEE_STAT_AUTONEGOTIATE_RESTART);\r
-\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
-\r
- /* Read PHY control and status registers is successful. */\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
-\r
- if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &\r
- IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {\r
-\r
- while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
- &status);\r
- }\r
-\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,\r
- &partner_capabilities);\r
-\r
- if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,\r
- &partner_capabilities_1000);\r
- if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)\r
- return 1000;\r
- }\r
-\r
- if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)\r
- return 100;\r
- if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)\r
- return 10;\r
-\r
- xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",\r
- __FUNCTION__);\r
- return 10;\r
-\r
- } else {\r
-\r
- /* Update TEMAC speed accordingly */\r
- if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
- /* Get commanded link speed */\r
- phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;\r
-\r
- switch (phylinkspeed) {\r
- case (IEEE_CTRL_LINKSPEED_1000M):\r
- return 1000;\r
- case (IEEE_CTRL_LINKSPEED_100M):\r
- return 100;\r
- case (IEEE_CTRL_LINKSPEED_10M):\r
- return 10;\r
- default:\r
- xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",\r
- __FUNCTION__, phylinkspeed);\r
- return 10;\r
- }\r
-\r
- } else {\r
-\r
- return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;\r
-\r
- }\r
- }\r
-}\r
-\r
-#else /* Zynq */\r
-unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
-{\r
- u16 temp;\r
- u16 control;\r
- u16 status;\r
- u16 partner_capabilities;\r
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
- u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;\r
-#else\r
- u32 phy_addr = detect_phy(xemacpsp);\r
-#endif\r
- xil_printf("Start PHY autonegotiation \r\n");\r
-\r
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
-#else\r
- XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
- control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
-\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
-\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
- control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
- control |= IEEE_PAUSE_MASK;\r
- control |= ADVERTISE_100;\r
- control |= ADVERTISE_10;\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
-\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
- &control);\r
- control |= ADVERTISE_1000;\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
- control);\r
-\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
- &control);\r
- control |= (7 << 12); /* max number of gigabit attempts */\r
- control |= (1 << 11); /* enable downshift */\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
- control);\r
-#endif\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
- control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;\r
- control |= IEEE_STAT_AUTONEGOTIATE_RESTART;\r
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
- control &= IEEE_CTRL_ISOLATE_DISABLE;\r
-#endif\r
-\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
-\r
-\r
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
-#else\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
- control |= IEEE_CTRL_RESET_MASK;\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
-\r
- while (1) {\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
- if (control & IEEE_CTRL_RESET_MASK)\r
- continue;\r
- else\r
- break;\r
- }\r
-#endif\r
- xil_printf("Waiting for PHY to complete autonegotiation.\r\n");\r
-\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
- while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
- sleep(1);\r
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
-#else\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,\r
- &temp);\r
- if (temp & IEEE_AUTONEG_ERROR_MASK) {\r
- xil_printf("Auto negotiation error \r\n");\r
- }\r
-#endif\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
- &status);\r
- }\r
-\r
- xil_printf("autonegotiation complete \r\n");\r
-\r
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
-#else\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);\r
-#endif\r
-\r
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
- xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
- while(!(temp & 0x8000)) {\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
- }\r
- if((temp & 0x0C00) == 0x0800) {\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
- return 1000;\r
- }\r
- else if((temp & 0x0C00) == 0x0400) {\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
- return 100;\r
- }\r
- else if((temp & 0x0C00) == 0x0000) {\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
- return 10;\r
- } else {\r
- xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);\r
- return 10;\r
- }\r
-#else\r
- if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */\r
- return 1000;\r
- else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */\r
- return 100;\r
- else /* 10Mbps */\r
- return 10;\r
-#endif\r
-}\r
-#endif\r
-\r
-unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)\r
-{\r
- u16 control;\r
- u32 phy_addr = detect_phy(xemacpsp);\r
-\r
- XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
- control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
-\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
-\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
- control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
- control |= IEEE_PAUSE_MASK;\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
-\r
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
- control &= ~IEEE_CTRL_LINKSPEED_1000M;\r
- control &= ~IEEE_CTRL_LINKSPEED_100M;\r
- control &= ~IEEE_CTRL_LINKSPEED_10M;\r
-\r
- if (speed == 1000) {\r
- control |= IEEE_CTRL_LINKSPEED_1000M;\r
- }\r
-\r
- else if (speed == 100) {\r
- control |= IEEE_CTRL_LINKSPEED_100M;\r
- /* Dont advertise PHY speed of 1000 Mbps */\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);\r
- /* Dont advertise PHY speed of 10 Mbps */\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
- ADVERTISE_100);\r
- }\r
-\r
- else if (speed == 10) {\r
- control |= IEEE_CTRL_LINKSPEED_10M;\r
- /* Dont advertise PHY speed of 1000 Mbps */\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
- 0);\r
- /* Dont advertise PHY speed of 100 Mbps */\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
- ADVERTISE_10);\r
- }\r
-\r
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
- control | IEEE_CTRL_RESET_MASK);\r
- {\r
- volatile int wait;\r
- for (wait=0; wait < 100000; wait++);\r
- }\r
- return 0;\r
-}\r
-\r
-static void SetUpSLCRDivisors(int mac_baseaddr, int speed)\r
-{\r
- volatile u32 slcrBaseAddress;\r
-#ifndef PEEP\r
- u32 SlcrDiv0;\r
- u32 SlcrDiv1=0;\r
- u32 SlcrTxClkCntrl;\r
-#endif\r
-\r
- *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;\r
-\r
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
- slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;\r
- } else {\r
- slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;\r
- }\r
-#ifdef PEEP\r
- if (speed == 1000) {\r
- *(volatile unsigned int *)(slcrBaseAddress) =\r
- SLCR_GEM_1G_CLK_CTRL_VALUE;\r
- } else if (speed == 100) {\r
- *(volatile unsigned int *)(slcrBaseAddress) =\r
- SLCR_GEM_100M_CLK_CTRL_VALUE;\r
- } else {\r
- *(volatile unsigned int *)(slcrBaseAddress) =\r
- SLCR_GEM_10M_CLK_CTRL_VALUE;\r
- }\r
-#else\r
- if (speed == 1000) {\r
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0\r
- SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;\r
- SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;\r
-#endif\r
- } else {\r
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0\r
- SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;\r
- SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;\r
-#endif\r
- }\r
- } else if (speed == 100) {\r
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0\r
- SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;\r
- SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;\r
-#endif\r
- } else {\r
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0\r
- SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;\r
- SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;\r
-#endif\r
- }\r
- } else {\r
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0\r
- SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;\r
- SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;\r
-#endif\r
- } else {\r
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0\r
- SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;\r
- SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;\r
-#endif\r
- }\r
- }\r
- SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);\r
- SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;\r
- SlcrTxClkCntrl |= (SlcrDiv1 << 20);\r
- SlcrTxClkCntrl |= (SlcrDiv0 << 8);\r
- *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;\r
-#endif\r
- *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;\r
- return;\r
-}\r
-\r
-\r
-unsigned link_speed;\r
-unsigned Phy_Setup (XEmacPs *xemacpsp)\r
-{\r
- unsigned long conv_present = 0;\r
- unsigned long convspeeddupsetting = 0;\r
- unsigned long convphyaddr = 0;\r
-\r
-#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR\r
- convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;\r
- conv_present = 1;\r
-#else\r
-#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR\r
- convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;\r
- conv_present = 1;\r
-#endif\r
-#endif\r
-\r
-#ifdef ipconfigNIC_LINKSPEED_AUTODETECT\r
- link_speed = get_IEEE_phy_speed(xemacpsp);\r
- if (link_speed == 1000) {\r
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
- } else if (link_speed == 100) {\r
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
- } else {\r
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
- }\r
-#elif defined(ipconfigNIC_LINKSPEED1000)\r
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
- link_speed = 1000;\r
- configure_IEEE_phy_speed(xemacpsp, link_speed);\r
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
- sleep(1);\r
-#elif defined(ipconfigNIC_LINKSPEED100)\r
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
- link_speed = 100;\r
- configure_IEEE_phy_speed(xemacpsp, link_speed);\r
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
- sleep(1);\r
-#elif defined(ipconfigNIC_LINKSPEED10)\r
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
- link_speed = 10;\r
- configure_IEEE_phy_speed(xemacpsp, link_speed);\r
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
- sleep(1);\r
-#endif\r
- if (conv_present) {\r
- XEmacPs_PhyWrite(xemacpsp, convphyaddr,\r
- XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);\r
- }\r
-\r
- xil_printf("link speed: %d\r\n", link_speed);\r
- return link_speed;\r
-}\r
-\r
+/*
+ * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names
+ * of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Some portions copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
+ *
+ * Xilinx, Inc.
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+/* Standard includes. */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "Zynq/x_emacpsif.h"
+//#include "lwipopts.h"
+#include "xparameters_ps.h"
+#include "xparameters.h"
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+///* FreeRTOS+TCP includes. */
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+#include "FreeRTOS_IP_Private.h"
+#include "NetworkBufferManagement.h"
+
+int phy_detected = 0;
+
+/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
+ *** to run it on a PEEP board
+ ***/
+
+/* Advertisement control register. */
+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
+
+#define ADVERTISE_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | \
+ ADVERTISE_10HALF | ADVERTISE_100HALF)
+#define ADVERTISE_100 (ADVERTISE_100FULL | ADVERTISE_100HALF)
+#define ADVERTISE_10 (ADVERTISE_10FULL | ADVERTISE_10HALF)
+
+#define ADVERTISE_1000 0x0300
+
+
+//#define PHY_REG_00_BMCR 0x00 // Basic mode control register
+//#define PHY_REG_01_BMSR 0x01 // Basic mode status register
+//#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1
+//#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2
+//#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg
+
+#define IEEE_CONTROL_REG_OFFSET 0
+#define IEEE_STATUS_REG_OFFSET 1
+#define IEEE_AUTONEGO_ADVERTISE_REG 4
+#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5
+#define IEEE_1000_ADVERTISE_REG_OFFSET 9
+#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10
+#define IEEE_COPPER_SPECIFIC_CONTROL_REG 16
+#define IEEE_SPECIFIC_STATUS_REG 17
+#define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19
+#define IEEE_CONTROL_REG_MAC 21
+#define IEEE_PAGE_ADDRESS_REGISTER 22
+
+
+#define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040
+#define IEEE_CTRL_LINKSPEED_MASK 0x0040
+#define IEEE_CTRL_LINKSPEED_1000M 0x0040
+#define IEEE_CTRL_LINKSPEED_100M 0x2000
+#define IEEE_CTRL_LINKSPEED_10M 0x0000
+#define IEEE_CTRL_RESET_MASK 0x8000
+#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
+#define IEEE_CTRL_RESET 0x9140
+#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF
+#endif
+#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008
+#define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020
+#define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200
+#define IEEE_STAT_1GBPS_EXTENSIONS 0x0100
+#define IEEE_AN1_ABILITY_MASK 0x1FE0
+#define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00
+#define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380
+#define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060
+#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030
+
+#define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800
+#define IEEE_PAUSE_MASK 0x0400
+#define IEEE_AUTONEG_ERROR_MASK 0x8000
+
+#define PHY_DETECT_REG 1
+#define PHY_DETECT_MASK 0x1808
+
+#define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140
+#define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100
+#define XEMACPS_GMII2RGMII_SPEED10_FD 0x100
+#define XEMACPS_GMII2RGMII_REG_NUM 0x10
+
+/* Frequency setting */
+#define SLCR_LOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x4)
+#define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8)
+#define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140)
+#define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144)
+#ifdef PEEP
+#define SLCR_GEM_10M_CLK_CTRL_VALUE 0x00103031
+#define SLCR_GEM_100M_CLK_CTRL_VALUE 0x00103001
+#define SLCR_GEM_1G_CLK_CTRL_VALUE 0x00103011
+#endif
+#define SLCR_LOCK_KEY_VALUE 0x767B
+#define SLCR_UNLOCK_KEY_VALUE 0xDF0D
+#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214)
+#define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF
+
+#define EMAC0_BASE_ADDRESS 0xE000B000
+#define EMAC1_BASE_ADDRESS 0xE000C000
+
+static int detect_phy(XEmacPs *xemacpsp)
+{
+ u16 phy_reg;
+ u32 phy_addr;
+
+ 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)) {
+ /* Found a valid PHY address */
+ FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
+ phy_addr));
+ FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) );
+ phy_detected = phy_addr;
+ return phy_addr;
+ }
+ }
+
+ FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected. Assuming a PHY at address 0\n" ) );
+
+ /* default to zero */
+ return 0;
+}
+
+#ifdef PEEP
+unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
+{
+
+ u16 control;
+ u16 status;
+ u16 partner_capabilities;
+ u16 partner_capabilities_1000;
+ u16 phylinkspeed;
+ u32 phy_addr = detect_phy(xemacpsp);
+
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+ ADVERTISE_1000);
+ /* Advertise PHY speed of 100 and 10 Mbps */
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
+ ADVERTISE_100_AND_10);
+
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
+ &control);
+ control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |
+ IEEE_STAT_AUTONEGOTIATE_RESTART);
+
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+ /* Read PHY control and status registers is successful. */
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+ if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &
+ IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {
+
+ while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
+ &status);
+ }
+
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
+ &partner_capabilities);
+
+ if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,
+ &partner_capabilities_1000);
+ if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)
+ return 1000;
+ }
+
+ if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)
+ return 100;
+ if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)
+ return 10;
+
+ xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",
+ __FUNCTION__);
+ return 10;
+
+ } else {
+
+ /* Update TEMAC speed accordingly */
+ if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
+ /* Get commanded link speed */
+ phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;
+
+ switch (phylinkspeed) {
+ case (IEEE_CTRL_LINKSPEED_1000M):
+ return 1000;
+ case (IEEE_CTRL_LINKSPEED_100M):
+ return 100;
+ case (IEEE_CTRL_LINKSPEED_10M):
+ return 10;
+ default:
+ xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",
+ __FUNCTION__, phylinkspeed);
+ return 10;
+ }
+
+ } else {
+
+ return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;
+
+ }
+ }
+}
+
+#else /* Zynq */
+unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
+{
+ u16 temp;
+ u16 control;
+ u16 status;
+ u16 partner_capabilities;
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
+ u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
+#else
+ u32 phy_addr = detect_phy(xemacpsp);
+#endif
+ xil_printf("Start PHY autonegotiation \r\n");
+
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
+#else
+ XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
+ control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
+
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+
+ 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_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
+ &control);
+ control |= (7 << 12); /* max number of gigabit attempts */
+ control |= (1 << 11); /* enable downshift */
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
+ control);
+#endif
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+ control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+ control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
+ control &= IEEE_CTRL_ISOLATE_DISABLE;
+#endif
+
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
+#else
+ 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;
+ }
+#endif
+ xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+ while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+ sleep(1);
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
+#else
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,
+ &temp);
+ if (temp & IEEE_AUTONEG_ERROR_MASK) {
+ xil_printf("Auto negotiation error \r\n");
+ }
+#endif
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
+ &status);
+ }
+
+ xil_printf("autonegotiation complete \r\n");
+
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
+#else
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);
+#endif
+
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
+ xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
+ while(!(temp & 0x8000)) {
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
+ }
+ if((temp & 0x0C00) == 0x0800) {
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
+ return 1000;
+ }
+ else if((temp & 0x0C00) == 0x0400) {
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
+ return 100;
+ }
+ else if((temp & 0x0C00) == 0x0000) {
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
+ return 10;
+ } else {
+ xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);
+ return 10;
+ }
+#else
+ if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */
+ return 1000;
+ else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */
+ return 100;
+ else /* 10Mbps */
+ return 10;
+#endif
+}
+#endif
+
+unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)
+{
+ u16 control;
+ u32 phy_addr = detect_phy(xemacpsp);
+
+ XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
+ control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
+
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+ control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+ control |= IEEE_PAUSE_MASK;
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+ control &= ~IEEE_CTRL_LINKSPEED_1000M;
+ control &= ~IEEE_CTRL_LINKSPEED_100M;
+ control &= ~IEEE_CTRL_LINKSPEED_10M;
+
+ if (speed == 1000) {
+ control |= IEEE_CTRL_LINKSPEED_1000M;
+ }
+
+ else if (speed == 100) {
+ control |= IEEE_CTRL_LINKSPEED_100M;
+ /* Dont advertise PHY speed of 1000 Mbps */
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);
+ /* Dont advertise PHY speed of 10 Mbps */
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
+ ADVERTISE_100);
+ }
+
+ else if (speed == 10) {
+ control |= IEEE_CTRL_LINKSPEED_10M;
+ /* Dont advertise PHY speed of 1000 Mbps */
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+ 0);
+ /* Dont advertise PHY speed of 100 Mbps */
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
+ ADVERTISE_10);
+ }
+
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
+ control | IEEE_CTRL_RESET_MASK);
+ {
+ volatile int wait;
+ for (wait=0; wait < 100000; wait++);
+ }
+ return 0;
+}
+
+static void SetUpSLCRDivisors(int mac_baseaddr, int speed)
+{
+ volatile u32 slcrBaseAddress;
+#ifndef PEEP
+ u32 SlcrDiv0;
+ u32 SlcrDiv1=0;
+ u32 SlcrTxClkCntrl;
+#endif
+
+ *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
+
+ if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
+ slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
+ } else {
+ slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
+ }
+#ifdef PEEP
+ if (speed == 1000) {
+ *(volatile unsigned int *)(slcrBaseAddress) =
+ SLCR_GEM_1G_CLK_CTRL_VALUE;
+ } else if (speed == 100) {
+ *(volatile unsigned int *)(slcrBaseAddress) =
+ SLCR_GEM_100M_CLK_CTRL_VALUE;
+ } else {
+ *(volatile unsigned int *)(slcrBaseAddress) =
+ SLCR_GEM_10M_CLK_CTRL_VALUE;
+ }
+#else
+ if (speed == 1000) {
+ if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
+ SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+ SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
+#endif
+ } else {
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
+ SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+ SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
+#endif
+ }
+ } else if (speed == 100) {
+ if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
+ SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+ SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
+#endif
+ } else {
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
+ SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+ SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
+#endif
+ }
+ } else {
+ if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
+ SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+ SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
+#endif
+ } else {
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
+ SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+ SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
+#endif
+ }
+ }
+ SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);
+ SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
+ SlcrTxClkCntrl |= (SlcrDiv1 << 20);
+ SlcrTxClkCntrl |= (SlcrDiv0 << 8);
+ *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;
+#endif
+ *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
+ return;
+}
+
+
+unsigned link_speed;
+unsigned Phy_Setup (XEmacPs *xemacpsp)
+{
+ unsigned long conv_present = 0;
+ unsigned long convspeeddupsetting = 0;
+ unsigned long convphyaddr = 0;
+
+#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
+ convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
+ conv_present = 1;
+#else
+#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
+ convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
+ conv_present = 1;
+#endif
+#endif
+
+#ifdef ipconfigNIC_LINKSPEED_AUTODETECT
+ link_speed = get_IEEE_phy_speed(xemacpsp);
+ 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;
+ }
+#elif defined(ipconfigNIC_LINKSPEED1000)
+ SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
+ link_speed = 1000;
+ configure_IEEE_phy_speed(xemacpsp, link_speed);
+ convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
+ sleep(1);
+#elif defined(ipconfigNIC_LINKSPEED100)
+ SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
+ link_speed = 100;
+ configure_IEEE_phy_speed(xemacpsp, link_speed);
+ convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
+ sleep(1);
+#elif defined(ipconfigNIC_LINKSPEED10)
+ SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
+ link_speed = 10;
+ configure_IEEE_phy_speed(xemacpsp, link_speed);
+ convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
+ sleep(1);
+#endif
+ if (conv_present) {
+ XEmacPs_PhyWrite(xemacpsp, convphyaddr,
+ XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
+ }
+
+ xil_printf("link speed: %d\r\n", link_speed);
+ return link_speed;
+}
+