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