]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/ethernet_phy.c
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2822 1d2547de-c912-0410...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / ATSAM4E / ethernet_phy.c
index fc72c6ad9a87fe2649a33f9c346e3c65302ca6a2..fe9e2960ff80b754834c4c51ae7b1a3ac322b158 100644 (file)
- /**
- * \file
- *
- * \brief API driver for KSZ8051MNL PHY component.
- *
- * Copyright (c) 2013 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *
- * 2. 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.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- *    Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
- *
- * \asf_license_stop
- *
- */
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "FreeRTOSIPConfig.h"
-
-#include "ethernet_phy.h"
-#include "instance/gmac.h"
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-extern "C" {
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/**
- * \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)
- *
- * Driver for the ksz8051mnl component. This driver provides access to the main
- * features of the PHY.
- *
- * \section dependencies Dependencies
- * This driver depends on the following modules:
- * - \ref gmac_group Ethernet Media Access Controller (GMAC) module.
- *
- * @{
- */
-
-SPhyProps phyProps;
-
-/* Max PHY number */
-#define ETH_PHY_MAX_ADDR   31
-
-/* Ethernet PHY operation max retry count */
-#define ETH_PHY_RETRY_MAX 1000000
-
-/* Ethernet PHY operation timeout */
-#define ETH_PHY_TIMEOUT 10
-
-/**
- * \brief Find a valid PHY Address ( from addrStart to 31 ).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param uc_start_addr Start address of the PHY to be searched.
- *
- * \return 0xFF when no valid PHY address is found.
- */
-int ethernet_phy_addr = 0;
-static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,
-               uint8_t uc_start_addr)
-{
-       uint32_t ul_value = 0;
-       uint8_t uc_cnt;
-       uint8_t uc_phy_address = uc_phy_addr;
-
-       gmac_enable_management(p_gmac, true);
-/*
-#define GMII_OUI_MSB            0x0022
-#define GMII_OUI_LSB            0x05
-
-PHYID1 = 0x0022
-PHYID2 = 0x1550
-0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0
-*/
-       /* Check the current PHY address */
-       gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);
-
-       /* Find another one */
-       if (ul_value != GMII_OUI_MSB) {
-               ethernet_phy_addr = 0xFF;
-               for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {
-                       uc_phy_address = (uc_phy_address + 1) & 0x1F;
-                       ul_value = 0;
-                       gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);
-                       if (ul_value == GMII_OUI_MSB) {
-                               ethernet_phy_addr = uc_phy_address;
-                               break;
-                       }
-               }
-       }
-
-       gmac_enable_management(p_gmac, false);
-
-       if (ethernet_phy_addr != 0xFF) {
-               gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);
-       }
-       return ethernet_phy_addr;
-}
-
-
-/**
- * \brief Perform a HW initialization to the PHY and set up clocks.
- *
- * This should be called only once to initialize the PHY pre-settings.
- * The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).
- * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
- * The RXDV pin is used to select test mode on reset (pulled up for test mode).
- * The above pins should be predefined for corresponding settings in resetPins.
- * The GMAC peripheral pins are configured after the reset is done.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param ul_mck GMAC MCK.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)
-{
-       uint8_t uc_rc = GMAC_TIMEOUT;
-       uint8_t uc_phy;
-
-       ethernet_phy_reset(GMAC,uc_phy_addr);
-
-       /* Configure GMAC runtime clock */
-       uc_rc = gmac_set_mdc_clock(p_gmac, mck);
-       if (uc_rc != GMAC_OK) {
-               return 0;
-       }
-
-       /* Check PHY Address */
-       uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);
-       if (uc_phy == 0xFF) {
-               return 0;
-       }
-       if (uc_phy != uc_phy_addr) {
-               ethernet_phy_reset(p_gmac, uc_phy_addr);
-       }
-       phy_props.phy_chn = uc_phy;
-       return uc_phy;
-}
-
-
-/**
- * \brief Get the Link & speed settings, and automatically set up the GMAC with the
- * settings.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
-               uint8_t uc_apply_setting_flag)
-{
-       uint32_t ul_stat1;
-       uint32_t ul_stat2;
-       uint8_t uc_phy_address, uc_speed = true, uc_fd = true;
-       uint8_t uc_rc = GMAC_TIMEOUT;
-
-       gmac_enable_management(p_gmac, true);
-
-       uc_phy_address = uc_phy_addr;
-
-       uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);
-       if (uc_rc != GMAC_OK) {
-               /* Disable PHY management and start the GMAC transfer */
-               gmac_enable_management(p_gmac, false);
-
-               return uc_rc;
-       }
-       if ((ul_stat1 & GMII_LINK_STATUS) == 0) {
-               /* Disable PHY management and start the GMAC transfer */
-               gmac_enable_management(p_gmac, false);
-
-               return GMAC_INVALID;
-       }
-
-       if (uc_apply_setting_flag == 0) {
-               /* Disable PHY management and start the GMAC transfer */
-               gmac_enable_management(p_gmac, false);
-
-               return uc_rc;
-       }
-
-       /* Read advertisement */
-       uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);
-phy_props.phy_stat1 = ul_stat1;
-phy_props.phy_stat2 = ul_stat2;
-       if (uc_rc != GMAC_OK) {
-               /* Disable PHY management and start the GMAC transfer */
-               gmac_enable_management(p_gmac, false);
-
-               return uc_rc;
-       }
-
-       if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {
-               /* Set GMAC for 100BaseTX and Full Duplex */
-               uc_speed = true;
-               uc_fd = true;
-       } else
-       if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {
-               /* Set MII for 100BaseTX and Half Duplex */
-               uc_speed = true;
-               uc_fd = false;
-       } else
-       if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {
-               /* Set MII for 10BaseT and Full Duplex */
-               uc_speed = false;
-               uc_fd = true;
-       } else
-       if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {
-               /* Set MII for 10BaseT and Half Duplex */
-               uc_speed = false;
-               uc_fd = false;
-       }
-
-       gmac_set_speed(p_gmac, uc_speed);
-       gmac_enable_full_duplex(p_gmac, uc_fd);
-
-       /* Start the GMAC transfers */
-       gmac_enable_management(p_gmac, false);
-       return uc_rc;
-}
-
-PhyProps_t phy_props;
-
-/**
- * \brief Issue an auto negotiation of the PHY.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)
-{
-       uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;
-       uint32_t ul_value;
-       uint32_t ul_phy_anar;
-       uint32_t ul_retry_count = 0;
-       uint8_t uc_speed = 0;
-       uint8_t uc_fd=0;
-       uint8_t uc_rc = GMAC_TIMEOUT;
-
-       gmac_enable_management(p_gmac, true);
-
-       /* Set up control register */
-       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -1;
-               return uc_rc;
-       }
-
-       ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */
-       ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);
-       ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */
-       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -2;
-               return uc_rc;
-       }
-
-       /*
-        * Set the Auto_negotiation Advertisement Register.
-        * MII advertising for Next page.
-        * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.
-        */
-       ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |
-                       GMII_AN_IEEE_802_3;
-       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -3;
-               return uc_rc;
-       }
-
-       /* Read & modify control register */
-       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -4;
-               return uc_rc;
-       }
-
-       ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;
-       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -5;
-               return uc_rc;
-       }
-
-       /* Restart auto negotiation */
-       ul_value |= (uint32_t)GMII_RESTART_AUTONEG;
-       ul_value &= ~(uint32_t)GMII_ISOLATE;
-       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -6;
-               return uc_rc;
-       }
-
-       /* Check if auto negotiation is completed */
-       while (1) {
-               uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);
-               if (uc_rc != GMAC_OK) {
-                       gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -7;
-                       return uc_rc;
-               }
-               /* Done successfully */
-               if (ul_value & GMII_AUTONEG_COMP) {
-                       break;
-               }
-
-               /* Timeout check */
-               if (ul_retry_max) {
-                       if (++ul_retry_count >= ul_retry_max) {
-                               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -8;
-                               return GMAC_TIMEOUT;
-                       }
-               }
-       }
-
-       /* Get the auto negotiate link partner base page */
-       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -9;
-               return uc_rc;
-       }
-
-
-       /* Set up the GMAC link speed */
-       if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {
-               /* Set MII for 100BaseTX and Full Duplex */
-               uc_speed = true;
-               uc_fd = true;
-       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {
-               /* Set MII for 10BaseT and Full Duplex */
-               uc_speed = false;
-               uc_fd = true;
-       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {
-               /* Set MII for 100BaseTX and half Duplex */
-               uc_speed = true;
-               uc_fd = false;
-       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {
-               /* Set MII for 10BaseT and half Duplex */
-               uc_speed = false;
-               uc_fd = false;
-       }
-
-       gmac_set_speed(p_gmac, uc_speed);
-       gmac_enable_full_duplex(p_gmac, uc_fd);
-
-       /* Select Media Independent Interface type */
-       gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);
-
-       gmac_enable_transmit(GMAC, true);
-       gmac_enable_receive(GMAC, true);
-
-       gmac_enable_management(p_gmac, false);
-phy_props.phy_result = 1;
-       return uc_rc;
-}
-
-/**
- * \brief Issue a SW reset to reset all registers of the PHY.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- *
- * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)
-{
-       uint32_t ul_bmcr = GMII_RESET;
-       uint8_t uc_phy_address = uc_phy_addr;
-       uint32_t ul_timeout = ETH_PHY_TIMEOUT;
-       uint8_t uc_rc = GMAC_TIMEOUT;
-
-       gmac_enable_management(p_gmac, true);
-
-       ul_bmcr = GMII_RESET;
-       gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);
-
-       do {
-               gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);
-               ul_timeout--;
-       } while ((ul_bmcr & GMII_RESET) && ul_timeout);
-
-       gmac_enable_management(p_gmac, false);
-
-       if (!ul_timeout) {
-               uc_rc = GMAC_OK;
-       }
-
-       return (uc_rc);
-}
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-}
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/**
- * \}
- */
+ /**\r
+ * \file\r
+ *\r
+ * \brief API driver for KSZ8051MNL PHY component.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "FreeRTOSIPConfig.h"\r
+\r
+#include "ethernet_phy.h"\r
+#include "instance/gmac.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)\r
+ *\r
+ * Driver for the ksz8051mnl component. This driver provides access to the main\r
+ * features of the PHY.\r
+ *\r
+ * \section dependencies Dependencies\r
+ * This driver depends on the following modules:\r
+ * - \ref gmac_group Ethernet Media Access Controller (GMAC) module.\r
+ *\r
+ * @{\r
+ */\r
+\r
+SPhyProps phyProps;\r
+\r
+/* Max PHY number */\r
+#define ETH_PHY_MAX_ADDR   31\r
+\r
+/* Ethernet PHY operation max retry count */\r
+#define ETH_PHY_RETRY_MAX 1000000\r
+\r
+/* Ethernet PHY operation timeout */\r
+#define ETH_PHY_TIMEOUT 10\r
+\r
+/**\r
+ * \brief Find a valid PHY Address ( from addrStart to 31 ).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_start_addr Start address of the PHY to be searched.\r
+ *\r
+ * \return 0xFF when no valid PHY address is found.\r
+ */\r
+int ethernet_phy_addr = 0;\r
+static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+               uint8_t uc_start_addr)\r
+{\r
+       uint32_t ul_value = 0;\r
+       uint8_t uc_cnt;\r
+       uint8_t uc_phy_address = uc_phy_addr;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+/*\r
+#define GMII_OUI_MSB            0x0022\r
+#define GMII_OUI_LSB            0x05\r
+\r
+PHYID1 = 0x0022\r
+PHYID2 = 0x1550\r
+0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0\r
+*/\r
+       /* Check the current PHY address */\r
+       gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);\r
+\r
+       /* Find another one */\r
+       if (ul_value != GMII_OUI_MSB) {\r
+               ethernet_phy_addr = 0xFF;\r
+               for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {\r
+                       uc_phy_address = (uc_phy_address + 1) & 0x1F;\r
+                       ul_value = 0;\r
+                       gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);\r
+                       if (ul_value == GMII_OUI_MSB) {\r
+                               ethernet_phy_addr = uc_phy_address;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       gmac_enable_management(p_gmac, false);\r
+\r
+       if (ethernet_phy_addr != 0xFF) {\r
+               gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);\r
+       }\r
+       return ethernet_phy_addr;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Perform a HW initialization to the PHY and set up clocks.\r
+ *\r
+ * This should be called only once to initialize the PHY pre-settings.\r
+ * The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).\r
+ * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).\r
+ * The RXDV pin is used to select test mode on reset (pulled up for test mode).\r
+ * The above pins should be predefined for corresponding settings in resetPins.\r
+ * The GMAC peripheral pins are configured after the reset is done.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param ul_mck GMAC MCK.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)\r
+{\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+       uint8_t uc_phy;\r
+\r
+       ethernet_phy_reset(GMAC,uc_phy_addr);\r
+\r
+       /* Configure GMAC runtime clock */\r
+       uc_rc = gmac_set_mdc_clock(p_gmac, mck);\r
+       if (uc_rc != GMAC_OK) {\r
+               return 0;\r
+       }\r
+\r
+       /* Check PHY Address */\r
+       uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);\r
+       if (uc_phy == 0xFF) {\r
+               return 0;\r
+       }\r
+       if (uc_phy != uc_phy_addr) {\r
+               ethernet_phy_reset(p_gmac, uc_phy_addr);\r
+       }\r
+       phy_props.phy_chn = uc_phy;\r
+       return uc_phy;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Get the Link & speed settings, and automatically set up the GMAC with the\r
+ * settings.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+               uint8_t uc_apply_setting_flag)\r
+{\r
+       uint32_t ul_stat1;\r
+       uint32_t ul_stat2;\r
+       uint8_t uc_phy_address, uc_speed = true, uc_fd = true;\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+\r
+       uc_phy_address = uc_phy_addr;\r
+\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);\r
+       if (uc_rc != GMAC_OK) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return uc_rc;\r
+       }\r
+       if ((ul_stat1 & GMII_LINK_STATUS) == 0) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return GMAC_INVALID;\r
+       }\r
+\r
+       if (uc_apply_setting_flag == 0) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Read advertisement */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);\r
+phy_props.phy_stat1 = ul_stat1;\r
+phy_props.phy_stat2 = ul_stat2;\r
+       if (uc_rc != GMAC_OK) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return uc_rc;\r
+       }\r
+\r
+       if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {\r
+               /* Set GMAC for 100BaseTX and Full Duplex */\r
+               uc_speed = true;\r
+               uc_fd = true;\r
+       } else\r
+       if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {\r
+               /* Set MII for 100BaseTX and Half Duplex */\r
+               uc_speed = true;\r
+               uc_fd = false;\r
+       } else\r
+       if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {\r
+               /* Set MII for 10BaseT and Full Duplex */\r
+               uc_speed = false;\r
+               uc_fd = true;\r
+       } else\r
+       if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {\r
+               /* Set MII for 10BaseT and Half Duplex */\r
+               uc_speed = false;\r
+               uc_fd = false;\r
+       }\r
+\r
+       gmac_set_speed(p_gmac, uc_speed);\r
+       gmac_enable_full_duplex(p_gmac, uc_fd);\r
+\r
+       /* Start the GMAC transfers */\r
+       gmac_enable_management(p_gmac, false);\r
+       return uc_rc;\r
+}\r
+\r
+PhyProps_t phy_props;\r
+\r
+/**\r
+ * \brief Issue an auto negotiation of the PHY.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)\r
+{\r
+       uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;\r
+       uint32_t ul_value;\r
+       uint32_t ul_phy_anar;\r
+       uint32_t ul_retry_count = 0;\r
+       uint8_t uc_speed = 0;\r
+       uint8_t uc_fd=0;\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+\r
+       /* Set up control register */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -1;\r
+               return uc_rc;\r
+       }\r
+\r
+       ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */\r
+       ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);\r
+       ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -2;\r
+               return uc_rc;\r
+       }\r
+\r
+       /*\r
+        * Set the Auto_negotiation Advertisement Register.\r
+        * MII advertising for Next page.\r
+        * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.\r
+        */\r
+       ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |\r
+                       GMII_AN_IEEE_802_3;\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -3;\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Read & modify control register */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -4;\r
+               return uc_rc;\r
+       }\r
+\r
+       ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -5;\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Restart auto negotiation */\r
+       ul_value |= (uint32_t)GMII_RESTART_AUTONEG;\r
+       ul_value &= ~(uint32_t)GMII_ISOLATE;\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -6;\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Check if auto negotiation is completed */\r
+       while (1) {\r
+               uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);\r
+               if (uc_rc != GMAC_OK) {\r
+                       gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -7;\r
+                       return uc_rc;\r
+               }\r
+               /* Done successfully */\r
+               if (ul_value & GMII_AUTONEG_COMP) {\r
+                       break;\r
+               }\r
+\r
+               /* Timeout check */\r
+               if (ul_retry_max) {\r
+                       if (++ul_retry_count >= ul_retry_max) {\r
+                               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -8;\r
+                               return GMAC_TIMEOUT;\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* Get the auto negotiate link partner base page */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -9;\r
+               return uc_rc;\r
+       }\r
+\r
+\r
+       /* Set up the GMAC link speed */\r
+       if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {\r
+               /* Set MII for 100BaseTX and Full Duplex */\r
+               uc_speed = true;\r
+               uc_fd = true;\r
+       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {\r
+               /* Set MII for 10BaseT and Full Duplex */\r
+               uc_speed = false;\r
+               uc_fd = true;\r
+       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {\r
+               /* Set MII for 100BaseTX and half Duplex */\r
+               uc_speed = true;\r
+               uc_fd = false;\r
+       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {\r
+               /* Set MII for 10BaseT and half Duplex */\r
+               uc_speed = false;\r
+               uc_fd = false;\r
+       }\r
+\r
+       gmac_set_speed(p_gmac, uc_speed);\r
+       gmac_enable_full_duplex(p_gmac, uc_fd);\r
+\r
+       /* Select Media Independent Interface type */\r
+       gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);\r
+\r
+       gmac_enable_transmit(GMAC, true);\r
+       gmac_enable_receive(GMAC, true);\r
+\r
+       gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = 1;\r
+       return uc_rc;\r
+}\r
+\r
+/**\r
+ * \brief Issue a SW reset to reset all registers of the PHY.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)\r
+{\r
+       uint32_t ul_bmcr = GMII_RESET;\r
+       uint8_t uc_phy_address = uc_phy_addr;\r
+       uint32_t ul_timeout = ETH_PHY_TIMEOUT;\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+\r
+       ul_bmcr = GMII_RESET;\r
+       gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);\r
+\r
+       do {\r
+               gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);\r
+               ul_timeout--;\r
+       } while ((ul_bmcr & GMII_RESET) && ul_timeout);\r
+\r
+       gmac_enable_management(p_gmac, false);\r
+\r
+       if (!ul_timeout) {\r
+               uc_rc = GMAC_OK;\r
+       }\r
+\r
+       return (uc_rc);\r
+}\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \}\r
+ */\r