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