Updated PHY KSZ8031

Dependents:   EthernetInterface

Committer:
brdarji
Date:
Wed Feb 28 07:22:25 2018 +0000
Revision:
34:aadfa95d41d2
Parent:
arch/TARGET_NXP/lpc_phy_ksz8031.c@33:44b00841690b
STM32f4 ethernet add ; LPC1768 ethernet kSZ8081 added

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dwijaybane 30:7a9b2350a72a 1 /**********************************************************************
dwijaybane 30:7a9b2350a72a 2 * $Id$ lpc_phy_ksz8031.c 2016-1-22
dwijaybane 30:7a9b2350a72a 3 *//**
dwijaybane 30:7a9b2350a72a 4 * @file lpc_phy_ksz8031.c
dwijaybane 30:7a9b2350a72a 5 * @brief KSZ8031 PHY status and control.
dwijaybane 30:7a9b2350a72a 6 * @version 1.0
dwijaybane 30:7a9b2350a72a 7 * @date 22 Jan. 2016
dwijaybane 30:7a9b2350a72a 8 * @author Edutech IoT Team
dwijaybane 30:7a9b2350a72a 9 *
dwijaybane 30:7a9b2350a72a 10 **********************************************************************/
dwijaybane 30:7a9b2350a72a 11
dwijaybane 30:7a9b2350a72a 12 #include "lwip/opt.h"
dwijaybane 30:7a9b2350a72a 13 #include "lwip/err.h"
dwijaybane 30:7a9b2350a72a 14 #include "lwip/tcpip.h"
dwijaybane 30:7a9b2350a72a 15 #include "lwip/snmp.h"
dwijaybane 30:7a9b2350a72a 16 #include "lpc_emac_config.h"
dwijaybane 30:7a9b2350a72a 17 #include "lpc_phy.h"
dwijaybane 30:7a9b2350a72a 18 #include "lpc17xx_emac.h"
dwijaybane 30:7a9b2350a72a 19
dwijaybane 30:7a9b2350a72a 20 /** @defgroup ksz8031_phy PHY status and control for the KSZ8031.
dwijaybane 30:7a9b2350a72a 21 * @ingroup lwip_phy
dwijaybane 30:7a9b2350a72a 22 *
dwijaybane 30:7a9b2350a72a 23 * Various functions for controlling and monitoring the status of the
dwijaybane 30:7a9b2350a72a 24 * KSZ8031 PHY. In polled (standalone) systems, the PHY state must be
dwijaybane 30:7a9b2350a72a 25 * monitored as part of the application. In a threaded (RTOS) system,
dwijaybane 30:7a9b2350a72a 26 * the PHY state is monitored by the PHY handler thread. The MAC
dwijaybane 30:7a9b2350a72a 27 * driver will not transmit unless the PHY link is active.
dwijaybane 30:7a9b2350a72a 28 * @{
dwijaybane 30:7a9b2350a72a 29 */
dwijaybane 30:7a9b2350a72a 30
dwijaybane 30:7a9b2350a72a 31 /** \brief KSZ8031 PHY register offsets */
dwijaybane 30:7a9b2350a72a 32 #define KSZ_BMCR_REG 0x0 /**< Basic Mode Control Register */
dwijaybane 30:7a9b2350a72a 33 #define KSZ_BMSR_REG 0x1 /**< Basic Mode Status Reg */
dwijaybane 30:7a9b2350a72a 34 #define KSZ_IDR1_REG 0x2 /**< Basic Mode Status Reg */
dwijaybane 30:7a9b2350a72a 35 #define KSZ_IDR2_REG 0x3 /**< Basic Mode Status Reg */
dwijaybane 30:7a9b2350a72a 36 #define KSZ_ANADV_REG 0x4 /**< Auto_Neg Advt Reg */
dwijaybane 30:7a9b2350a72a 37 #define KSZ_ANLPA_REG 0x5 /**< Auto_neg Link Partner Ability Reg */
dwijaybane 30:7a9b2350a72a 38 #define KSZ_ANEEXP_REG 0x6 /**< Auto-neg Expansion Reg */
dwijaybane 30:7a9b2350a72a 39 #define KSZ_PHY_STAT_REG 0x10 /**< PHY Status Register */
dwijaybane 30:7a9b2350a72a 40 #define KSZ_PHY_INT_CTL_REG 0x11 /**< PHY Interrupt Control Register */
dwijaybane 30:7a9b2350a72a 41 #define KSZ_PHY_RBR_REG 0x17 /**< PHY RMII and Bypass Register */
dwijaybane 30:7a9b2350a72a 42 #define KSZ_PHY_STS_REG 0x19 /**< PHY Status Register */
dwijaybane 30:7a9b2350a72a 43
dwijaybane 30:7a9b2350a72a 44 #define KSZ_PHY_SCSR_REG 0x1f /**< PHY Special Control/Status Register (LAN8720) */
dwijaybane 30:7a9b2350a72a 45
dwijaybane 30:7a9b2350a72a 46 /** \brief KSZ8031 Control register definitions */
dwijaybane 30:7a9b2350a72a 47 #define KSZ_RESET (1 << 15) /**< 1= S/W Reset */
dwijaybane 30:7a9b2350a72a 48 #define KSZ_LOOPBACK (1 << 14) /**< 1=loopback Enabled */
dwijaybane 30:7a9b2350a72a 49 #define KSZ_SPEED_SELECT (1 << 13) /**< 1=Select 100MBps */
dwijaybane 30:7a9b2350a72a 50 #define KSZ_AUTONEG (3 << 12) /**< 1=Enable auto-negotiation */
dwijaybane 30:7a9b2350a72a 51 #define KSZ_POWER_DOWN (1 << 11) /**< 1=Power down PHY */
dwijaybane 30:7a9b2350a72a 52 #define KSZ_ISOLATE (1 << 10) /**< 1=Isolate PHY */
dwijaybane 30:7a9b2350a72a 53 #define KSZ_RESTART_AUTONEG (1 << 9) /**< 1=Restart auto-negoatiation */
dwijaybane 30:7a9b2350a72a 54 #define KSZ_DUPLEX_MODE (1 << 8) /**< 1=Full duplex mode */
dwijaybane 30:7a9b2350a72a 55 #define KSZ_COLLISION_TEST (1 << 7) /**< 1=Perform collsion test */
dwijaybane 30:7a9b2350a72a 56
dwijaybane 30:7a9b2350a72a 57 /** \brief KSZ3848 Status register definitions */
dwijaybane 30:7a9b2350a72a 58 #define KSZ_100BASE_T4 (1 << 15) /**< T4 mode */
dwijaybane 30:7a9b2350a72a 59 #define KSZ_100BASE_TX_FD (1 << 14) /**< 100MBps full duplex */
dwijaybane 30:7a9b2350a72a 60 #define KSZ_100BASE_TX_HD (1 << 13) /**< 100MBps half duplex */
dwijaybane 30:7a9b2350a72a 61 #define KSZ_10BASE_T_FD (1 << 12) /**< 100Bps full duplex */
dwijaybane 30:7a9b2350a72a 62 #define KSZ_10BASE_T_HD (1 << 11) /**< 10MBps half duplex */
dwijaybane 30:7a9b2350a72a 63 #define KSZ_MF_PREAMB_SUPPR (1 << 6) /**< Preamble suppress */
dwijaybane 30:7a9b2350a72a 64 #define KSZ_AUTONEG_COMP (1 << 5) /**< Auto-negotation complete */
dwijaybane 30:7a9b2350a72a 65 #define KSZ_RMT_FAULT (1 << 4) /**< Fault */
dwijaybane 30:7a9b2350a72a 66 #define KSZ_AUTONEG_ABILITY (1 << 3) /**< Auto-negotation supported */
dwijaybane 30:7a9b2350a72a 67 #define KSZ_LINK_STATUS (1 << 2) /**< 1=Link active */
dwijaybane 30:7a9b2350a72a 68 #define KSZ_JABBER_DETECT (1 << 1) /**< Jabber detect */
dwijaybane 30:7a9b2350a72a 69 #define KSZ_EXTEND_CAPAB (1 << 0) /**< Supports extended capabilities */
dwijaybane 30:7a9b2350a72a 70
dwijaybane 30:7a9b2350a72a 71 /** \brief KSZ8031 PHY RBR MII dode definitions */
dwijaybane 30:7a9b2350a72a 72 #define KSZ_RBR_RMII_MODE (1 << 5) /**< Use RMII mode */
dwijaybane 30:7a9b2350a72a 73
dwijaybane 30:7a9b2350a72a 74 /** \brief KSZ8031 PHY status definitions */
dwijaybane 30:7a9b2350a72a 75 #define KSZ_REMOTEFAULT (1 << 6) /**< Remote fault */
dwijaybane 30:7a9b2350a72a 76 #define KSZ_FULLDUPLEX (1 << 2) /**< 1=full duplex */
dwijaybane 30:7a9b2350a72a 77 #define KSZ_SPEED10MBPS (1 << 1) /**< 1=10MBps speed */
dwijaybane 30:7a9b2350a72a 78 #define KSZ_VALID_LINK (1 << 0) /**< 1=Link active */
dwijaybane 30:7a9b2350a72a 79
brdarji 34:aadfa95d41d2 80 //KSZ8081
dwijaybane 30:7a9b2350a72a 81 #define KSZ_PHYID1_OUI 0x0022 /**< Expected PHY ID1 */
dwijaybane 33:44b00841690b 82 #define KSZ_PHYID2_OUI 0x1560 /**< Expected PHY ID2 */
dwijaybane 30:7a9b2350a72a 83
brdarji 34:aadfa95d41d2 84
brdarji 34:aadfa95d41d2 85 //KSZ8031
brdarji 34:aadfa95d41d2 86 //#define KSZ_PHYID1_OUI 0x0022 /**< Expected PHY ID1 */
brdarji 34:aadfa95d41d2 87 //#define KSZ_PHYID2_OUI 0x1550 /**< Expected PHY ID2 */
brdarji 34:aadfa95d41d2 88
brdarji 34:aadfa95d41d2 89
dwijaybane 30:7a9b2350a72a 90 /** \brief LAN8720 PHY Special Control/Status Register */
dwijaybane 30:7a9b2350a72a 91 #define PHY_SCSR_100MBIT 0x0008 /**< Speed: 1=100 MBit, 0=10Mbit */
dwijaybane 30:7a9b2350a72a 92 #define PHY_SCSR_DUPLEX 0x0010 /**< PHY Duplex Mask */
dwijaybane 30:7a9b2350a72a 93
dwijaybane 30:7a9b2350a72a 94 /** \brief Link status bits */
dwijaybane 30:7a9b2350a72a 95 #define LNK_STAT_VALID 0x01
dwijaybane 30:7a9b2350a72a 96 #define LNK_STAT_FULLDUPLEX 0x02
dwijaybane 30:7a9b2350a72a 97 #define LNK_STAT_SPEED10MPS 0x04
dwijaybane 30:7a9b2350a72a 98
dwijaybane 30:7a9b2350a72a 99 /** \brief PHY ID definitions */
brdarji 34:aadfa95d41d2 100 //#define KSZ8031_ID 0x00221550 /**< PHY Identifier - KSZ8031 */
brdarji 34:aadfa95d41d2 101 #define KSZ8081_ID 0x00221560 /**< PHY Identifier - KSZ8081 */
dwijaybane 30:7a9b2350a72a 102 #define LAN8720_ID 0x0007C0F0 /**< PHY Identifier - LAN8720 */
dwijaybane 30:7a9b2350a72a 103
dwijaybane 30:7a9b2350a72a 104 /** \brief PHY status structure used to indicate current status of PHY.
dwijaybane 30:7a9b2350a72a 105 */
dwijaybane 30:7a9b2350a72a 106 typedef struct {
dwijaybane 30:7a9b2350a72a 107 u32_t phy_speed_100mbs:1; /**< 10/100 MBS connection speed flag. */
dwijaybane 30:7a9b2350a72a 108 u32_t phy_full_duplex:1; /**< Half/full duplex connection speed flag. */
dwijaybane 30:7a9b2350a72a 109 u32_t phy_link_active:1; /**< Phy link active flag. */
dwijaybane 30:7a9b2350a72a 110 } PHY_STATUS_TYPE;
dwijaybane 30:7a9b2350a72a 111
dwijaybane 30:7a9b2350a72a 112 /** \brief PHY update flags */
dwijaybane 30:7a9b2350a72a 113 static PHY_STATUS_TYPE physts;
dwijaybane 30:7a9b2350a72a 114
dwijaybane 30:7a9b2350a72a 115 /** \brief Last PHY update flags, used for determing if something has changed */
dwijaybane 30:7a9b2350a72a 116 static PHY_STATUS_TYPE olddphysts;
dwijaybane 30:7a9b2350a72a 117
dwijaybane 30:7a9b2350a72a 118 /** \brief PHY update counter for state machine */
dwijaybane 30:7a9b2350a72a 119 static s32_t phyustate;
dwijaybane 30:7a9b2350a72a 120
dwijaybane 30:7a9b2350a72a 121 /** \brief Holds the PHY ID */
dwijaybane 30:7a9b2350a72a 122 static u32_t phy_id;
dwijaybane 30:7a9b2350a72a 123
dwijaybane 30:7a9b2350a72a 124 /** \brief Temporary holder of link status for LAN7420 */
dwijaybane 30:7a9b2350a72a 125 static u32_t phy_lan7420_sts_tmp;
dwijaybane 30:7a9b2350a72a 126
dwijaybane 30:7a9b2350a72a 127 /* Write a value via the MII link (non-blocking) */
dwijaybane 30:7a9b2350a72a 128 void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value)
dwijaybane 30:7a9b2350a72a 129 {
dwijaybane 30:7a9b2350a72a 130 /* Write value at PHY address and register */
dwijaybane 30:7a9b2350a72a 131 LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
dwijaybane 30:7a9b2350a72a 132 LPC_EMAC->MWTD = Value;
dwijaybane 30:7a9b2350a72a 133 }
dwijaybane 30:7a9b2350a72a 134
dwijaybane 30:7a9b2350a72a 135 /* Write a value via the MII link (blocking) */
dwijaybane 30:7a9b2350a72a 136 err_t lpc_mii_write(u32_t PhyReg, u32_t Value)
dwijaybane 30:7a9b2350a72a 137 {
dwijaybane 30:7a9b2350a72a 138 u32_t mst = 250;
dwijaybane 30:7a9b2350a72a 139 err_t sts = ERR_OK;
dwijaybane 30:7a9b2350a72a 140
dwijaybane 30:7a9b2350a72a 141 /* Write value at PHY address and register */
dwijaybane 30:7a9b2350a72a 142 lpc_mii_write_noblock(PhyReg, Value);
dwijaybane 30:7a9b2350a72a 143
dwijaybane 30:7a9b2350a72a 144 /* Wait for unbusy status */
dwijaybane 30:7a9b2350a72a 145 while (mst > 0) {
dwijaybane 30:7a9b2350a72a 146 sts = LPC_EMAC->MIND;
dwijaybane 30:7a9b2350a72a 147 if ((sts & EMAC_MIND_BUSY) == 0)
dwijaybane 30:7a9b2350a72a 148 mst = 0;
dwijaybane 30:7a9b2350a72a 149 else {
dwijaybane 30:7a9b2350a72a 150 mst--;
dwijaybane 30:7a9b2350a72a 151 osDelay(1);
dwijaybane 30:7a9b2350a72a 152 }
dwijaybane 30:7a9b2350a72a 153 }
dwijaybane 30:7a9b2350a72a 154
dwijaybane 30:7a9b2350a72a 155 if (sts != 0)
dwijaybane 30:7a9b2350a72a 156 sts = ERR_TIMEOUT;
dwijaybane 30:7a9b2350a72a 157
dwijaybane 30:7a9b2350a72a 158 return sts;
dwijaybane 30:7a9b2350a72a 159 }
dwijaybane 30:7a9b2350a72a 160
dwijaybane 30:7a9b2350a72a 161 /* Reads current MII link busy status */
dwijaybane 30:7a9b2350a72a 162 u32_t lpc_mii_is_busy(void)
dwijaybane 30:7a9b2350a72a 163 {
dwijaybane 30:7a9b2350a72a 164 return (u32_t) (LPC_EMAC->MIND & EMAC_MIND_BUSY);
dwijaybane 30:7a9b2350a72a 165 }
dwijaybane 30:7a9b2350a72a 166
dwijaybane 30:7a9b2350a72a 167 /* Starts a read operation via the MII link (non-blocking) */
dwijaybane 30:7a9b2350a72a 168 u32_t lpc_mii_read_data(void)
dwijaybane 30:7a9b2350a72a 169 {
dwijaybane 30:7a9b2350a72a 170 u32_t data = LPC_EMAC->MRDD;
dwijaybane 30:7a9b2350a72a 171 LPC_EMAC->MCMD = 0;
dwijaybane 30:7a9b2350a72a 172
dwijaybane 30:7a9b2350a72a 173 return data;
dwijaybane 30:7a9b2350a72a 174 }
dwijaybane 30:7a9b2350a72a 175
dwijaybane 30:7a9b2350a72a 176 /* Starts a read operation via the MII link (non-blocking) */
dwijaybane 30:7a9b2350a72a 177 void lpc_mii_read_noblock(u32_t PhyReg)
dwijaybane 30:7a9b2350a72a 178 {
dwijaybane 30:7a9b2350a72a 179 /* Read value at PHY address and register */
dwijaybane 30:7a9b2350a72a 180 LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
dwijaybane 30:7a9b2350a72a 181 LPC_EMAC->MCMD = EMAC_MCMD_READ;
dwijaybane 30:7a9b2350a72a 182 }
dwijaybane 30:7a9b2350a72a 183
dwijaybane 30:7a9b2350a72a 184 /* Read a value via the MII link (blocking) */
dwijaybane 30:7a9b2350a72a 185 err_t lpc_mii_read(u32_t PhyReg, u32_t *data)
dwijaybane 30:7a9b2350a72a 186 {
dwijaybane 30:7a9b2350a72a 187 u32_t mst = 250;
dwijaybane 30:7a9b2350a72a 188 err_t sts = ERR_OK;
dwijaybane 30:7a9b2350a72a 189
dwijaybane 30:7a9b2350a72a 190 /* Read value at PHY address and register */
dwijaybane 30:7a9b2350a72a 191 lpc_mii_read_noblock(PhyReg);
dwijaybane 30:7a9b2350a72a 192
dwijaybane 30:7a9b2350a72a 193 /* Wait for unbusy status */
dwijaybane 30:7a9b2350a72a 194 while (mst > 0) {
dwijaybane 30:7a9b2350a72a 195 sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL;
dwijaybane 30:7a9b2350a72a 196 if ((sts & EMAC_MIND_BUSY) == 0) {
dwijaybane 30:7a9b2350a72a 197 mst = 0;
dwijaybane 30:7a9b2350a72a 198 *data = LPC_EMAC->MRDD;
dwijaybane 30:7a9b2350a72a 199 } else {
dwijaybane 30:7a9b2350a72a 200 mst--;
dwijaybane 30:7a9b2350a72a 201 osDelay(1);
dwijaybane 30:7a9b2350a72a 202 }
dwijaybane 30:7a9b2350a72a 203 }
dwijaybane 30:7a9b2350a72a 204
dwijaybane 30:7a9b2350a72a 205 LPC_EMAC->MCMD = 0;
dwijaybane 30:7a9b2350a72a 206
dwijaybane 30:7a9b2350a72a 207 if (sts != 0)
dwijaybane 30:7a9b2350a72a 208 sts = ERR_TIMEOUT;
dwijaybane 30:7a9b2350a72a 209
dwijaybane 30:7a9b2350a72a 210 return sts;
dwijaybane 30:7a9b2350a72a 211 }
dwijaybane 30:7a9b2350a72a 212
dwijaybane 30:7a9b2350a72a 213
dwijaybane 30:7a9b2350a72a 214 /** \brief Update PHY status from passed value
dwijaybane 30:7a9b2350a72a 215 *
dwijaybane 30:7a9b2350a72a 216 * This function updates the current PHY status based on the
dwijaybane 30:7a9b2350a72a 217 * passed PHY status word. The PHY status indicate if the link
dwijaybane 30:7a9b2350a72a 218 * is active, the connection speed, and duplex.
dwijaybane 30:7a9b2350a72a 219 *
dwijaybane 30:7a9b2350a72a 220 * \param[in] netif NETIF structure
dwijaybane 30:7a9b2350a72a 221 * \param[in] linksts Status word from PHY
dwijaybane 30:7a9b2350a72a 222 * \return 1 if the status has changed, otherwise 0
dwijaybane 30:7a9b2350a72a 223 */
dwijaybane 30:7a9b2350a72a 224 static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts)
dwijaybane 30:7a9b2350a72a 225 {
dwijaybane 30:7a9b2350a72a 226 s32_t changed = 0;
dwijaybane 30:7a9b2350a72a 227
dwijaybane 30:7a9b2350a72a 228 /* Update link active status */
dwijaybane 30:7a9b2350a72a 229 if (linksts & LNK_STAT_VALID)
dwijaybane 30:7a9b2350a72a 230 physts.phy_link_active = 1;
dwijaybane 30:7a9b2350a72a 231 else
dwijaybane 30:7a9b2350a72a 232 physts.phy_link_active = 0;
dwijaybane 30:7a9b2350a72a 233
dwijaybane 30:7a9b2350a72a 234 /* Full or half duplex */
dwijaybane 30:7a9b2350a72a 235 if (linksts & LNK_STAT_FULLDUPLEX)
dwijaybane 30:7a9b2350a72a 236 physts.phy_full_duplex = 1;
dwijaybane 30:7a9b2350a72a 237 else
dwijaybane 30:7a9b2350a72a 238 physts.phy_full_duplex = 0;
dwijaybane 30:7a9b2350a72a 239
dwijaybane 30:7a9b2350a72a 240 /* Configure 100MBit/10MBit mode. */
dwijaybane 30:7a9b2350a72a 241 if (linksts & LNK_STAT_SPEED10MPS)
dwijaybane 30:7a9b2350a72a 242 physts.phy_speed_100mbs = 0;
dwijaybane 30:7a9b2350a72a 243 else
dwijaybane 30:7a9b2350a72a 244 physts.phy_speed_100mbs = 1;
dwijaybane 30:7a9b2350a72a 245
dwijaybane 30:7a9b2350a72a 246 if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) {
dwijaybane 30:7a9b2350a72a 247 changed = 1;
dwijaybane 30:7a9b2350a72a 248 if (physts.phy_speed_100mbs) {
dwijaybane 30:7a9b2350a72a 249 /* 100MBit mode. */
dwijaybane 30:7a9b2350a72a 250 lpc_emac_set_speed(1);
dwijaybane 30:7a9b2350a72a 251
dwijaybane 30:7a9b2350a72a 252 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
dwijaybane 30:7a9b2350a72a 253 }
dwijaybane 30:7a9b2350a72a 254 else {
dwijaybane 30:7a9b2350a72a 255 /* 10MBit mode. */
dwijaybane 30:7a9b2350a72a 256 lpc_emac_set_speed(0);
dwijaybane 30:7a9b2350a72a 257
dwijaybane 30:7a9b2350a72a 258 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
dwijaybane 30:7a9b2350a72a 259 }
dwijaybane 30:7a9b2350a72a 260
dwijaybane 30:7a9b2350a72a 261 olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs;
dwijaybane 30:7a9b2350a72a 262 }
dwijaybane 30:7a9b2350a72a 263
dwijaybane 30:7a9b2350a72a 264 if (physts.phy_full_duplex != olddphysts.phy_full_duplex) {
dwijaybane 30:7a9b2350a72a 265 changed = 1;
dwijaybane 30:7a9b2350a72a 266 if (physts.phy_full_duplex)
dwijaybane 30:7a9b2350a72a 267 lpc_emac_set_duplex(1);
dwijaybane 30:7a9b2350a72a 268 else
dwijaybane 30:7a9b2350a72a 269 lpc_emac_set_duplex(0);
dwijaybane 30:7a9b2350a72a 270
dwijaybane 30:7a9b2350a72a 271 olddphysts.phy_full_duplex = physts.phy_full_duplex;
dwijaybane 30:7a9b2350a72a 272 }
dwijaybane 30:7a9b2350a72a 273
dwijaybane 30:7a9b2350a72a 274 if (physts.phy_link_active != olddphysts.phy_link_active) {
dwijaybane 30:7a9b2350a72a 275 changed = 1;
dwijaybane 30:7a9b2350a72a 276 #if NO_SYS == 1
dwijaybane 30:7a9b2350a72a 277 if (physts.phy_link_active)
dwijaybane 30:7a9b2350a72a 278 netif_set_link_up(netif);
dwijaybane 30:7a9b2350a72a 279 else
dwijaybane 30:7a9b2350a72a 280 netif_set_link_down(netif);
dwijaybane 30:7a9b2350a72a 281 #else
dwijaybane 30:7a9b2350a72a 282 if (physts.phy_link_active)
dwijaybane 30:7a9b2350a72a 283 tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
dwijaybane 30:7a9b2350a72a 284 (void*) netif, 1);
dwijaybane 30:7a9b2350a72a 285 else
dwijaybane 30:7a9b2350a72a 286 tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
dwijaybane 30:7a9b2350a72a 287 (void*) netif, 1);
dwijaybane 30:7a9b2350a72a 288 #endif
dwijaybane 30:7a9b2350a72a 289
dwijaybane 30:7a9b2350a72a 290 olddphysts.phy_link_active = physts.phy_link_active;
dwijaybane 30:7a9b2350a72a 291 }
dwijaybane 30:7a9b2350a72a 292
dwijaybane 30:7a9b2350a72a 293 return changed;
dwijaybane 30:7a9b2350a72a 294 }
dwijaybane 30:7a9b2350a72a 295
dwijaybane 30:7a9b2350a72a 296 /** \brief Initialize the KSZ8031 PHY.
dwijaybane 30:7a9b2350a72a 297 *
dwijaybane 30:7a9b2350a72a 298 * This function initializes the KSZ8031 PHY. It will block until
dwijaybane 30:7a9b2350a72a 299 * complete. This function is called as part of the EMAC driver
dwijaybane 30:7a9b2350a72a 300 * initialization. Configuration of the PHY at startup is
dwijaybane 30:7a9b2350a72a 301 * controlled by setting up configuration defines in lpc_phy.h.
dwijaybane 30:7a9b2350a72a 302 *
dwijaybane 30:7a9b2350a72a 303 * \param[in] netif NETIF structure
dwijaybane 30:7a9b2350a72a 304 * \param[in] rmii If set, configures the PHY for RMII mode
dwijaybane 30:7a9b2350a72a 305 * \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
dwijaybane 30:7a9b2350a72a 306 */
dwijaybane 30:7a9b2350a72a 307 err_t lpc_phy_init(struct netif *netif, int rmii)
dwijaybane 30:7a9b2350a72a 308 {
dwijaybane 30:7a9b2350a72a 309 u32_t tmp;
dwijaybane 30:7a9b2350a72a 310 s32_t i;
dwijaybane 30:7a9b2350a72a 311
dwijaybane 30:7a9b2350a72a 312 physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 0;
dwijaybane 30:7a9b2350a72a 313 physts.phy_full_duplex = olddphysts.phy_full_duplex = 0;
dwijaybane 30:7a9b2350a72a 314 physts.phy_link_active = olddphysts.phy_link_active = 0;
dwijaybane 30:7a9b2350a72a 315 phyustate = 0;
dwijaybane 30:7a9b2350a72a 316
dwijaybane 30:7a9b2350a72a 317 /* Only first read and write are checked for failure */
dwijaybane 30:7a9b2350a72a 318 /* Put the KSZ8031 in reset mode and wait for completion */
dwijaybane 30:7a9b2350a72a 319 if (lpc_mii_write(KSZ_BMCR_REG, KSZ_RESET) != 0)
dwijaybane 30:7a9b2350a72a 320 return ERR_TIMEOUT;
dwijaybane 30:7a9b2350a72a 321 i = 400;
dwijaybane 30:7a9b2350a72a 322 while (i > 0) {
dwijaybane 30:7a9b2350a72a 323 osDelay(1); /* 1 ms */
dwijaybane 30:7a9b2350a72a 324 if (lpc_mii_read(KSZ_BMCR_REG, &tmp) != 0)
dwijaybane 30:7a9b2350a72a 325 return ERR_TIMEOUT;
dwijaybane 30:7a9b2350a72a 326
dwijaybane 30:7a9b2350a72a 327 if (!(tmp & (KSZ_RESET | KSZ_POWER_DOWN)))
dwijaybane 30:7a9b2350a72a 328 i = -1;
dwijaybane 30:7a9b2350a72a 329 else
dwijaybane 30:7a9b2350a72a 330 i--;
dwijaybane 30:7a9b2350a72a 331 }
dwijaybane 30:7a9b2350a72a 332 /* Timeout? */
dwijaybane 30:7a9b2350a72a 333 if (i == 0)
dwijaybane 30:7a9b2350a72a 334 return ERR_TIMEOUT;
dwijaybane 30:7a9b2350a72a 335
dwijaybane 30:7a9b2350a72a 336 // read PHY ID
dwijaybane 30:7a9b2350a72a 337 lpc_mii_read(KSZ_IDR1_REG, &tmp);
dwijaybane 30:7a9b2350a72a 338 phy_id = (tmp << 16);
dwijaybane 30:7a9b2350a72a 339 lpc_mii_read(KSZ_IDR2_REG, &tmp);
dwijaybane 30:7a9b2350a72a 340 phy_id |= (tmp & 0XFFF0);
dwijaybane 30:7a9b2350a72a 341
dwijaybane 30:7a9b2350a72a 342 /* Setup link based on configuration options */
dwijaybane 30:7a9b2350a72a 343 #if PHY_USE_AUTONEG==1
dwijaybane 30:7a9b2350a72a 344 tmp = KSZ_AUTONEG;
dwijaybane 30:7a9b2350a72a 345 #else
dwijaybane 30:7a9b2350a72a 346 tmp = 0;
dwijaybane 30:7a9b2350a72a 347 #endif
dwijaybane 30:7a9b2350a72a 348 #if PHY_USE_100MBS==1
dwijaybane 30:7a9b2350a72a 349 tmp |= KSZ_SPEED_SELECT;
dwijaybane 30:7a9b2350a72a 350 #endif
dwijaybane 30:7a9b2350a72a 351 #if PHY_USE_FULL_DUPLEX==1
dwijaybane 30:7a9b2350a72a 352 tmp |= KSZ_DUPLEX_MODE;
dwijaybane 30:7a9b2350a72a 353 #endif
dwijaybane 30:7a9b2350a72a 354 lpc_mii_write(KSZ_BMCR_REG, tmp);
dwijaybane 30:7a9b2350a72a 355
dwijaybane 30:7a9b2350a72a 356 /* Wait for autonegotiation completion */
dwijaybane 30:7a9b2350a72a 357 int j = 1000;
dwijaybane 30:7a9b2350a72a 358 while (j > 0)
dwijaybane 30:7a9b2350a72a 359 {
dwijaybane 30:7a9b2350a72a 360 osDelay(1); // 1 ms
dwijaybane 30:7a9b2350a72a 361 if (lpc_mii_read(KSZ_BMSR_REG, &tmp) != 0)
dwijaybane 30:7a9b2350a72a 362 {
dwijaybane 30:7a9b2350a72a 363 return ERR_TIMEOUT;
dwijaybane 30:7a9b2350a72a 364 }
dwijaybane 30:7a9b2350a72a 365 if (tmp & (KSZ_AUTONEG_COMP))
dwijaybane 30:7a9b2350a72a 366 j = -1;
dwijaybane 30:7a9b2350a72a 367 else
dwijaybane 30:7a9b2350a72a 368 j--;
dwijaybane 30:7a9b2350a72a 369 }
dwijaybane 30:7a9b2350a72a 370 // Timeout?
dwijaybane 30:7a9b2350a72a 371 if (j == 0)
dwijaybane 30:7a9b2350a72a 372 {
dwijaybane 30:7a9b2350a72a 373 printf("Timeout\n");
dwijaybane 30:7a9b2350a72a 374 return ERR_TIMEOUT;
dwijaybane 30:7a9b2350a72a 375 }
dwijaybane 30:7a9b2350a72a 376
dwijaybane 30:7a9b2350a72a 377 /* The link is not set active at this point, but will be detected
dwijaybane 30:7a9b2350a72a 378 later */
dwijaybane 30:7a9b2350a72a 379
dwijaybane 30:7a9b2350a72a 380 return ERR_OK;
dwijaybane 30:7a9b2350a72a 381 }
dwijaybane 30:7a9b2350a72a 382
dwijaybane 30:7a9b2350a72a 383 /* Phy status update state machine */
dwijaybane 30:7a9b2350a72a 384 s32_t lpc_phy_sts_sm(struct netif *netif)
dwijaybane 30:7a9b2350a72a 385 {
dwijaybane 30:7a9b2350a72a 386 s32_t changed = 0;
dwijaybane 30:7a9b2350a72a 387 u32_t data = 0;
dwijaybane 30:7a9b2350a72a 388 u32_t tmp,tmp1;
dwijaybane 30:7a9b2350a72a 389
dwijaybane 30:7a9b2350a72a 390 switch (phyustate) {
dwijaybane 30:7a9b2350a72a 391 default:
dwijaybane 30:7a9b2350a72a 392 case 0:
brdarji 34:aadfa95d41d2 393 if (phy_id == KSZ8081_ID) {
dwijaybane 30:7a9b2350a72a 394 lpc_mii_read(KSZ_BMSR_REG, &tmp);
dwijaybane 30:7a9b2350a72a 395 /* To Debug Link Status */
dwijaybane 30:7a9b2350a72a 396 // if (tmp & LNK_STAT_VALID)
dwijaybane 30:7a9b2350a72a 397 // {
dwijaybane 30:7a9b2350a72a 398 // /* Link is on. */
dwijaybane 30:7a9b2350a72a 399 // printf("Link is UP\n\r");
dwijaybane 30:7a9b2350a72a 400 // }
dwijaybane 30:7a9b2350a72a 401 phyustate = 2;
dwijaybane 30:7a9b2350a72a 402 }
dwijaybane 30:7a9b2350a72a 403 else if (phy_id == LAN8720_ID) {
dwijaybane 30:7a9b2350a72a 404 lpc_mii_read_noblock(KSZ_PHY_SCSR_REG);
dwijaybane 30:7a9b2350a72a 405 phyustate = 1;
dwijaybane 30:7a9b2350a72a 406 }
dwijaybane 30:7a9b2350a72a 407 break;
dwijaybane 30:7a9b2350a72a 408
dwijaybane 30:7a9b2350a72a 409 case 1:
dwijaybane 30:7a9b2350a72a 410 if (phy_id == LAN8720_ID) {
dwijaybane 30:7a9b2350a72a 411 tmp = lpc_mii_read_data();
dwijaybane 31:2abbad89a5b8 412 // we get speed and duplex here
dwijaybane 30:7a9b2350a72a 413 phy_lan7420_sts_tmp = (tmp & PHY_SCSR_DUPLEX) ? LNK_STAT_FULLDUPLEX : 0;
dwijaybane 30:7a9b2350a72a 414 phy_lan7420_sts_tmp |= (tmp & PHY_SCSR_100MBIT) ? 0 : LNK_STAT_SPEED10MPS;
dwijaybane 30:7a9b2350a72a 415
dwijaybane 30:7a9b2350a72a 416 //read the status register to get link status
dwijaybane 30:7a9b2350a72a 417 lpc_mii_read_noblock(KSZ_BMSR_REG);
dwijaybane 30:7a9b2350a72a 418 phyustate = 2;
dwijaybane 30:7a9b2350a72a 419 }
dwijaybane 30:7a9b2350a72a 420 break;
dwijaybane 30:7a9b2350a72a 421
dwijaybane 30:7a9b2350a72a 422 case 2:
dwijaybane 30:7a9b2350a72a 423 /* Wait for read status state */
dwijaybane 30:7a9b2350a72a 424 if (!lpc_mii_is_busy()) {
dwijaybane 30:7a9b2350a72a 425 /* Update PHY status */
dwijaybane 30:7a9b2350a72a 426 tmp = lpc_mii_read_data();
dwijaybane 30:7a9b2350a72a 427
brdarji 34:aadfa95d41d2 428 if (phy_id == KSZ8081_ID) {
dwijaybane 30:7a9b2350a72a 429 // Get autonegotiation complete bit
dwijaybane 30:7a9b2350a72a 430 lpc_mii_read(KSZ_BMSR_REG,&tmp1);
dwijaybane 30:7a9b2350a72a 431 /* To Debug Auto-negotiation */
dwijaybane 30:7a9b2350a72a 432 // if (tmp1 & KSZ_AUTONEG_COMP)
dwijaybane 30:7a9b2350a72a 433 // {
dwijaybane 30:7a9b2350a72a 434 // /* Auto-negotiation Complete. */
dwijaybane 30:7a9b2350a72a 435 // printf("Auto-negotiation has completed\n\r");
dwijaybane 30:7a9b2350a72a 436 // }
dwijaybane 30:7a9b2350a72a 437 // STS register contains all needed status bits
dwijaybane 30:7a9b2350a72a 438 data = (tmp & KSZ_VALID_LINK) ? LNK_STAT_VALID : 0;
dwijaybane 30:7a9b2350a72a 439 data |= (tmp & KSZ_FULLDUPLEX) ? LNK_STAT_FULLDUPLEX : 0;
dwijaybane 30:7a9b2350a72a 440 data |= (tmp & KSZ_SPEED10MBPS) ? LNK_STAT_SPEED10MPS : 0;
dwijaybane 30:7a9b2350a72a 441 }
dwijaybane 30:7a9b2350a72a 442 else if (phy_id == LAN8720_ID) {
dwijaybane 30:7a9b2350a72a 443 // we only get the link status here.
dwijaybane 30:7a9b2350a72a 444 phy_lan7420_sts_tmp |= (tmp & KSZ_LINK_STATUS) ? LNK_STAT_VALID : 0;
dwijaybane 30:7a9b2350a72a 445 data = phy_lan7420_sts_tmp;
dwijaybane 30:7a9b2350a72a 446 }
dwijaybane 30:7a9b2350a72a 447
dwijaybane 30:7a9b2350a72a 448 changed = lpc_update_phy_sts(netif, data);
dwijaybane 30:7a9b2350a72a 449 phyustate = 0;
dwijaybane 30:7a9b2350a72a 450 }
dwijaybane 30:7a9b2350a72a 451 break;
dwijaybane 30:7a9b2350a72a 452 }
dwijaybane 30:7a9b2350a72a 453
dwijaybane 30:7a9b2350a72a 454 return changed;
dwijaybane 30:7a9b2350a72a 455 }
dwijaybane 30:7a9b2350a72a 456
dwijaybane 30:7a9b2350a72a 457 /**
dwijaybane 30:7a9b2350a72a 458 * @}
dwijaybane 30:7a9b2350a72a 459 */
dwijaybane 30:7a9b2350a72a 460
dwijaybane 30:7a9b2350a72a 461 /* --------------------------------- End Of File ------------------------------ */