/* * Copyright (C) 2019-2020 AlibabaGroup Holding Limited */ /****************************************************************************** * @file phy.h * @brief header file for generic PHY Driver * @version V1.0 * @date 21 March 2019 ******************************************************************************/ #ifndef _ETH_PHY_H_ #define _ETH_PHY_H_ #ifdef __cplusplus extern "C" { #endif #include #include "mmio.h" /** \brief Ethernet link speed */ #define CSI_ETH_SPEED_10M (0) ///< 10 Mbps link speed #define CSI_ETH_SPEED_100M (1) ///< 100 Mbps link speed #define CSI_ETH_SPEED_1G (2) ///< 1 Gpbs link speed /** \brief Ethernet duplex mode */ #define CSI_ETH_DUPLEX_HALF (0) ///< Half duplex link #define CSI_ETH_DUPLEX_FULL (1) ///< Full duplex link typedef void *eth_phy_handle_t; typedef enum eth_power_state { CSI_ETH_POWER_OFF, ///< Power off: no operation possible CSI_ETH_POWER_LOW, ///< Low Power mode: retain state, detect and signal wake-up events CSI_ETH_POWER_FULL ///< Power on: full operation at maximum performance } eth_power_state_t; typedef int32_t (*csi_eth_phy_read_t)(uint8_t phy_addr, uint8_t reg_addr, uint16_t *data); ///< Read Ethernet PHY Register. typedef int32_t (*csi_eth_phy_write_t)(uint8_t phy_addr, uint8_t reg_addr, uint16_t data); ///< Write Ethernet PHY Register. typedef volatile struct eth_link_info { uint32_t speed : 2; ///< Link speed: 0= 10 MBit, 1= 100 MBit, 2= 1 GBit uint32_t duplex : 1; ///< Duplex mode: 0= Half, 1= Full uint32_t autoneg : 1; ///< Set the interface to Auto Negotiation mode of transmission parameters uint32_t loopback : 1; ///< Set the interface into a Loop-back test mode uint32_t isolation : 1; ///< Set to indicate electrical isolation of PHY interface from MII/RMII interface uint32_t reserved : 26; } eth_link_info_t; typedef struct { csi_eth_phy_read_t phy_read; csi_eth_phy_write_t phy_write; eth_link_info_t link_info; } eth_phy_priv_t; typedef enum eth_link_state { ETH_LINK_DOWN, ///< Link is down ETH_LINK_UP ///< Link is up } eth_link_state_t; /* Basic mode control register */ #define CVI_BMCR_RESV (0x003f) #define CVI_BMCR_SPEED1000 (0x0040) #define CVI_BMCR_CTST (0x0080) #define CVI_BMCR_FULLDPLX (0x0100) #define CVI_BMCR_ANRESTART (0x0200) #define CVI_BMCR_ISOLATE (0x0400) #define CVI_BMCR_PDOWN (0x0800) #define CVI_BMCR_ANENABLE (0x1000) #define CVI_BMCR_SPEED100 (0x2000) #define CVI_BMCR_LOOPBACK (0x4000) #define CVI_BMCR_RESET (0x8000) #define BMCR_SPEED10 (0x0000) /* Generic MII registers */ #define CVI_MII_BMCR (0x00) #define CVI_MII_BMSR (0x01) #define CVI_MII_PHYSID1 (0x02) #define CVI_MII_PHYSID2 (0x03) #define CVI_MII_ADVERTISE (0x04) #define CVI_MII_LPA (0x05) #define CVI_MII_EXPANSION (0x06) #define CVI_MII_CTRL1000 (0x09) #define CVI_MII_STAT1000 (0x0a) #define MII_MMD_CTRL (0x0d) #define MII_MMD_DATA (0x0e) #define CVI_MII_ESTATUS (0x0f) #define CVI_MII_DCOUNTER (0x12) #define CVI_MII_FCSCOUNTER (0x13) #define CVI_MII_NWAYTEST (0x14) #define CVI_MII_RERRCOUNTER (0x15) #define CVI_MII_SREVISION (0x16) #define CVI_MII_RESV1 (0x17) #define CVI_MII_LBRERROR (0x18) #define CVI_MII_PHYADDR (0x19) #define CVI_MII_RESV2 (0x1a) #define CVI_MII_TPISTATUS (0x1b) #define CVI_MII_NCONFIG (0x1c) /* Advertisement control register. */ #define CVI_ADVERTISE_CSMA (0x0001) #define CVI_ADVERTISE_SLCT (0x001f) #define CVI_ADVERTISE_10HALF (0x0020) #define CVI_ADVERTISE_1000XFULL (0x0020) #define CVI_ADVERTISE_10FULL (0x0040) #define CVI_ADVERTISE_1000XHALF (0x0040) #define CVI_ADVERTISE_100HALF (0x0080) #define CVI_ADVERTISE_1000XPAUSE (0x0080) #define CVI_ADVERTISE_100FULL (0x0100) #define CVI_ADVERTISE_1000XPSE_ASYM (0x0100) #define CVI_ADVERTISE_100BASE4 (0x0200) #define CVI_ADVERTISE_PAUSE_CAP (0x0400) #define CVI_ADVERTISE_PAUSE_ASYM (0x0800) #define CVI_ADVERTISE_RESV (0x1000) #define CVI_ADVERTISE_RFAULT (0x2000) #define CVI_ADVERTISE_LPACK (0x4000) #define CVI_ADVERTISE_NPAGE (0x8000) /* Basic mode status register. */ #define CVI_BMSR_ERCAP (0x0001) #define CVI_BMSR_JCD (0x0002) #define CVI_BMSR_LSTATUS (0x0004) #define CVI_BMSR_ANEGCAPABLE (0x0008) #define CVI_BMSR_RFAULT (0x0010) #define CVI_BMSR_ANEGCOMPLETE (0x0020) #define CVI_BMSR_RESV (0x00c0) #define CVI_BMSR_ESTATEN (0x0100) #define CVI_BMSR_100HALF2 (0x0200) #define CVI_BMSR_100FULL2 (0x0400) #define CVI_BMSR_10HALF (0x0800) #define CVI_BMSR_10FULL (0x1000) #define CVI_BMSR_100HALF (0x2000) #define CVI_BMSR_100FULL (0x4000) #define CVI_BMSR_100BASE4 (0x8000) #define CVI_ADVERTISE_FULL (CVI_ADVERTISE_100FULL | CVI_ADVERTISE_10FULL | \ CVI_ADVERTISE_CSMA) #define CVI_ADVERTISE_ALL (CVI_ADVERTISE_10HALF | CVI_ADVERTISE_10FULL | \ CVI_ADVERTISE_100HALF | CVI_ADVERTISE_100FULL) /* Link partner ability register. */ #define CVI_LPA_SLCT (0x001f) /* Same as advertise selector */ #define CVI_LPA_10HALF (0x0020) /* Can do 10mbps half-duplex */ #define CVI_LPA_1000XFULL (0x0020) /* Can do 1000BASE-X full-duplex */ #define CVI_LPA_10FULL (0x0040) /* Can do 10mbps full-duplex */ #define CVI_LPA_1000XHALF (0x0040) /* Can do 1000BASE-X half-duplex */ #define CVI_LPA_100HALF (0x0080) /* Can do 100mbps half-duplex */ #define CVI_LPA_1000XPAUSE (0x0080) /* Can do 1000BASE-X pause */ #define CVI_LPA_100FULL (0x0100) /* Can do 100mbps full-duplex */ #define CVI_LPA_1000XPAUSE_ASYM (0x0100) /* Can do 1000BASE-X pause asym */ #define CVI_LPA_100BASE4 (0x0200) /* Can do 100mbps 4k packets */ #define CVI_LPA_PAUSE_CAP (0x0400) /* Can pause */ #define CVI_LPA_PAUSE_ASYM (0x0800) /* Can pause asymetrically */ #define CVI_LPA_RESV (0x1000) /* Unused */ #define CVI_LPA_RFAULT (0x2000) /* Link partner faulted */ #define CVI_LPA_LPACK (0x4000) /* Link partner acked us */ #define CVI_LPA_NPAGE (0x8000) /* Next page bit */ #define CVI_LPA_DUPLEX (CVI_LPA_10FULL | CVI_LPA_100FULL) #define CVI_LPA_100 (CVI_LPA_100FULL | CVI_LPA_100HALF | CVI_LPA_100BASE4) /* Expansion register for auto-negotiation. */ #define CVI_EXPANSION_NWAY (0x0001) /* Can do N-way auto-nego */ #define CVI_EXPANSION_LCWP (0x0002) /* Got new RX page code word */ #define CVI_EXPANSION_ENABLENPAGE (0x0004) /* This enables npage words */ #define CVI_EXPANSION_NPCAPABLE (0x0008) /* Link partner supports npage */ #define CVI_EXPANSION_MFAULTS (0x0010) /* Multiple faults detected */ #define CVI_EXPANSION_RESV (0xffe0) /* Unused */ #define CVI_ESTATUS_1000_XFULL (0x8000) /* Can do 1000BX Full */ #define CVI_ESTATUS_1000_XHALF (0x4000) /* Can do 1000BX Half */ #define CVI_ESTATUS_1000_TFULL (0x2000) /* Can do 1000BT Full */ #define CVI_ESTATUS_1000_THALF (0x1000) /* Can do 1000BT Half */ /* N-way test register. */ #define CVI_NWAYTEST_RESV1 (0x00ff) /* Unused */ #define CVI_NWAYTEST_LOOPBACK (0x0100) /* Enable loopback for N-way */ #define CVI_NWAYTEST_RESV2 (0xfe00) /* Unused */ /* 1000BASE-T Control register */ #define CVI_ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ #define CVI_ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */ #define CTL1000_AS_MASTER 0x0800 #define CTL1000_ENABLE_MASTER 0x1000 /* 1000BASE-T Status register */ #define CVI_LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */ #define CVI_LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */ #define CVI_LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */ #define CVI_LPA_1000HALF 0x0400 /* Link partner 1000BASE-T half duplex */ /* Flow control flags */ #define CVI_FLOW_CTRL_TX 0x01 #define CVI_FLOW_CTRL_RX 0x02 /* MMD Access Control register fields */ #define CVI_MII_MMD_CTRL_DEVAD_MASK 0x1f /* Mask MMD DEVAD*/ #define CVI_MII_MMD_CTRL_ADDR 0x0000 /* Address */ #define CVI_MII_MMD_CTRL_NOINCR 0x4000 /* no post increment */ #define CVI_MII_MMD_CTRL_INCR_RDWT 0x8000 /* post increment on reads & writes */ #define CVI_MII_MMD_CTRL_INCR_ON_WT 0xC000 /* post increment on writes only */ /* Indicates what features are advertised by the interface. */ #define CVI_ADVERTISED_10baseT_Half (1 << 0) #define CVI_ADVERTISED_10baseT_Full (1 << 1) #define CVI_ADVERTISED_100baseT_Half (1 << 2) #define CVI_ADVERTISED_100baseT_Full (1 << 3) #define CVI_ADVERTISED_1000baseT_Half (1 << 4) #define CVI_ADVERTISED_1000baseT_Full (1 << 5) #define CVI_ADVERTISED_Autoneg (1 << 6) #define CVI_ADVERTISED_TP (1 << 7) #define CVI_ADVERTISED_AUI (1 << 8) #define CVI_ADVERTISED_MII (1 << 9) #define CVI_ADVERTISED_FIBRE (1 << 10) #define CVI_ADVERTISED_BNC (1 << 11) #define CVI_ADVERTISED_10000baseT_Full (1 << 12) #define CVI_ADVERTISED_Pause (1 << 13) #define CVI_ADVERTISED_Asym_Pause (1 << 14) #define CVI_ADVERTISED_2500baseX_Full (1 << 15) #define CVI_ADVERTISED_Backplane (1 << 16) #define CVI_ADVERTISED_1000baseKX_Full (1 << 17) #define CVI_ADVERTISED_10000baseKX4_Full (1 << 18) #define CVI_ADVERTISED_10000baseKR_Full (1 << 19) #define CVI_ADVERTISED_10000baseR_FEC (1 << 20) #define CVI_ADVERTISED_1000baseX_Half (1 << 21) #define CVI_ADVERTISED_1000baseX_Full (1 << 22) /* Indicates what features are supported by the interface. */ #define CVI_SUPPORTED_10baseT_Half (1 << 0) #define CVI_SUPPORTED_10baseT_Full (1 << 1) #define CVI_SUPPORTED_100baseT_Half (1 << 2) #define CVI_SUPPORTED_100baseT_Full (1 << 3) #define CVI_SUPPORTED_1000baseT_Half (1 << 4) #define CVI_SUPPORTED_1000baseT_Full (1 << 5) #define CVI_SUPPORTED_Autoneg (1 << 6) #define CVI_SUPPORTED_TP (1 << 7) #define CVI_SUPPORTED_AUI (1 << 8) #define CVI_SUPPORTED_MII (1 << 9) #define CVI_SUPPORTED_FIBRE (1 << 10) #define CVI_SUPPORTED_BNC (1 << 11) #define CVI_SUPPORTED_10000baseT_Full (1 << 12) #define CVI_SUPPORTED_Pause (1 << 13) #define CVI_SUPPORTED_Asym_Pause (1 << 14) #define CVI_SUPPORTED_2500baseX_Full (1 << 15) #define CVI_SUPPORTED_Backplane (1 << 16) #define CVI_SUPPORTED_1000baseKX_Full (1 << 17) #define CVI_SUPPORTED_10000baseKX4_Full (1 << 18) #define CVI_SUPPORTED_10000baseKR_Full (1 << 19) #define CVI_SUPPORTED_10000baseR_FEC (1 << 20) #define CVI_SUPPORTED_1000baseX_Half (1 << 21) #define CVI_SUPPORTED_1000baseX_Full (1 << 22) /* PHY features */ #define CVI_PHY_DEFAULT_FEATURES (CVI_SUPPORTED_Autoneg | \ CVI_SUPPORTED_TP | \ CVI_SUPPORTED_MII) #define CVI_PHY_10BT_FEATURES (CVI_SUPPORTED_10baseT_Half | \ CVI_SUPPORTED_10baseT_Full) #define CVI_PHY_100BT_FEATURES (CVI_SUPPORTED_100baseT_Half | \ CVI_SUPPORTED_100baseT_Full) #define CVI_PHY_1000BT_FEATURES (CVI_SUPPORTED_1000baseT_Half | \ CVI_SUPPORTED_1000baseT_Full) #define CVI_PHY_BASIC_FEATURES (CVI_PHY_10BT_FEATURES | \ CVI_PHY_100BT_FEATURES | \ CVI_PHY_DEFAULT_FEATURES) #define CVI_PHY_GBIT_FEATURES (CVI_PHY_BASIC_FEATURES | \ CVI_PHY_1000BT_FEATURES) #define CVI_PHY_ANEG_TIMEOUT 5000 /* in ms */ typedef enum { LOOPBACK_XMII2MAC, LOOPBACK_PCS2MAC, LOOPBACK_PMA2MAC, LOOPBACK_RMII2PHY, } phy_loopback_mode_t; /* phy interface mode */ typedef enum { PHY_IF_MODE_MII, PHY_IF_MODE_GMII, PHY_IF_MODE_SGMII, PHY_IF_MODE_TBI, PHY_IF_MODE_RMII, PHY_IF_MODE_RGMII, PHY_IF_MODE_RGMII_ID, PHY_IF_MODE_RGMII_RXID, PHY_IF_MODE_RGMII_TXID, PHY_IF_MODE_RTBI, PHY_IF_MODE_NONE, /* Last One */ PHY_IF_MODE_COUNT, } phy_if_mode_t; typedef struct { eth_phy_priv_t *priv; eth_link_state_t link_state; uint32_t supported; uint32_t advertising; /* * platform specific */ uint32_t phy_addr; phy_if_mode_t interface; /* * driver specific */ uint32_t phy_id; uint32_t mask; uint32_t features; int8_t name[20]; /* config() should be called before calling start() */ int32_t (*config)(eth_phy_handle_t *phy_dev); int32_t (*start)(eth_phy_handle_t *phy_dev); int32_t (*stop)(eth_phy_handle_t *phy_dev); int32_t (*loopback)(eth_phy_handle_t *phy_dev); int32_t (*update_link)(eth_phy_handle_t *phy_dev); } eth_phy_dev_t; /* ethernet phy config */ #define ETH_PHY_BASE 0x03009000 #define ETH_PHY_INIT_MASK 0xFFFFFFF9 #define ETH_PHY_SHUTDOWN (1 << 1) #define ETH_PHY_POWERUP 0xFFFFFFFD #define ETH_PHY_RESET 0xFFFFFFFB #define ETH_PHY_RESET_N (1 << 2) #define ETH_PHY_LED_LOW_ACTIVE (1 << 3) int generic_phy_config_aneg(eth_phy_dev_t *dev); int generic_phy_restart_aneg(eth_phy_dev_t *dev); int generic_phy_update_link(eth_phy_dev_t *dev); int32_t eth_phy_read(eth_phy_priv_t *priv, uint8_t phy_addr, uint8_t reg_addr, uint16_t *data); int32_t eth_phy_write(eth_phy_priv_t *priv, uint8_t phy_addr, uint8_t reg_addr, uint16_t data); int32_t eth_phy_reset(eth_phy_handle_t handle); int32_t eth_phy_config(eth_phy_handle_t handle); int32_t eth_phy_start(eth_phy_handle_t handle); int32_t eth_phy_update_link(eth_phy_handle_t handle); int32_t genphy_config(eth_phy_dev_t *phy_dev); int32_t genphy_update_link(eth_phy_dev_t *phy_dev); /* * ffs: find first bit set. This is defined the same way as * the libc and compiler builtin ffs routines, therefore * differs in spirit from the above ffz (man ffs). */ // static inline int32_t ffs(int32_t x) // { // int32_t r = 1; // if (!x) // return 0; // if (!(x & 0xffff)) { // x >>= 16; // r += 16; // } // if (!(x & 0xff)) { // x >>= 8; // r += 8; // } // if (!(x & 0xf)) { // x >>= 4; // r += 4; // } // if (!(x & 3)) { // x >>= 2; // r += 2; // } // if (!(x & 1)) { // x >>= 1; // r += 1; // } // return r; // } #ifdef __cplusplus } #endif #endif /* _ETH_PHY_H_ */