123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- #include <stdio.h>
- #include "app_phy.h"
- #define PHY_BASE_ADDR 0x7
- #define PHY_REG_CONTROL 0x0
- #define PHY_REG_STATUS 0x1
- #define PHY_REG_ANE 0x6
- #define PHY_REG_SPEC_STATUS 0x11
- #define PHY_REG_EXTEND_STATUS 0x1B
- #define PHY_BIT_CONTROL_RESET 0x8000 /*!< Control reg : reset */
- #define PHY_BIT_CONTROL_ANEN 0x1000 /*!< Control reg : auto-negotiation enable */
- #define PHY_BIT_CONTROL_RSAN 0x0200 /*!< Control reg : auto-negotiation restart */
- #define PHY_BIT_STATUS_ANC 0x0020 /*!< Status reg : auto-negotiation complete */
- #define PHY_BIT_STATUS_LINK 0x0004 /*!< Status reg : link is up */
- #define PHY_BIT_ANE_LPAN 0x0001 /*!< ANE reg : link partner can auto-neg */
- #define PHY_BIT_SPEED 0xC000 /*!< specific status reg : speed */
- #define PHY_BIT_DUPLEX 0x2000 /*!< specific status reg : duplex */
- #define PHY_BIT_AUTO_MEDIA_DISABLE 0x8000 /*!< extended status reg : auto media select disable */
- #define PHY_BIT_AUTO_MEDIA_REG_DISABLE 0x0200 /*!< extended status reg : auto media register select disable */
- void phy_Reset() {
- ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_CONTROL, PHY_BIT_CONTROL_RESET);
- while (1) {
- uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_CONTROL);
- if ((ret & PHY_BIT_CONTROL_RESET) == 0) {
- break;
- }
- }
- }
- void phy_AutoMediaSelect() {
- uint32_t data;
- // auto media and auto media register selection
- data = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_EXTEND_STATUS);
- data &= ~PHY_BIT_AUTO_MEDIA_DISABLE;
- data &= ~PHY_BIT_AUTO_MEDIA_REG_DISABLE;
- ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_EXTEND_STATUS, data);
- }
- void phy_AutoNeg()
- {
- uint32_t data;
- data = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_CONTROL);
- data |= (PHY_BIT_CONTROL_ANEN | PHY_BIT_CONTROL_RSAN);
- ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_CONTROL, data);
- while (1)
- {
- uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_STATUS);
- if ((ret & PHY_BIT_STATUS_ANC) == PHY_BIT_STATUS_ANC)
- {
- break;
- }
- rt_thread_delay(1);
- }
- }
- BOOL phy_IsLink() {
- uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_STATUS);
- return (ret & PHY_BIT_STATUS_LINK) ? TRUE : FALSE;
- }
- BOOL phy_PartnerCanAutoNeg() {
- uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_ANE);
- return (ret & PHY_BIT_ANE_LPAN) ? TRUE : FALSE;
- }
- uint32_t phy_GetSpeed() {
- uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_SPEC_STATUS);
- return ((ret & PHY_BIT_SPEED) >> 14);
- }
- uint32_t phy_GetDuplex() {
- uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_SPEC_STATUS);
- return ((ret & PHY_BIT_DUPLEX) >> 13);
- }
- BOOL phy_Init() {
- phy_AutoMediaSelect();
- phy_AutoNeg();
- if (!phy_PartnerCanAutoNeg()) {
- printf("Warning:: PHY's partner can't do auto-negotiation\n");
- }
- if (!phy_IsLink()) {
- printf("link is down\n");
- return FALSE;
- }
- {
- uint32_t speed = phy_GetSpeed();
- if (speed == PHY_SPEED_10) {
- speed = 10;
- } else if (speed == PHY_SPEED_100) {
- speed = 100;
- } else if (speed == PHY_SPEED_1000) {
- speed = 1000;
- }
- printf("PHY runs in %dM speed %s duplex\n",
- speed, (phy_GetDuplex() == PHY_DUPLEX_HALF) ? "half" : "full");
- }
- // After auto-negcioation, Mawell PHY need some
- // time to initial itself.
- // So we have to delay some time since different
- // connection way, such as direct wire, hub, switch.
- // If not to delay, the first several sent frame
- // may be lost.
- // Please according to actual environment to tune
- // this delay.
- udelay(200000);
- return TRUE;
- }
|