lwip 1.4 - DM9161A PHY

After reading topic http://mbed.org/forum/mbed/topic/3684/?page=1#comment-18473, i created the lpc_phy_DM9161A.c file (used lpc_phy_lan8720.c as a template).

Partially working

Auto negotiation and DHCP are OK - ethernet communication is not working.

There seems to be a communication problem between the EMAC and PHY (timing?). Any ideas on how to resolve this issue are welcome.

A debug log is available at /media/uploads/frankvnk/tcpsocket_helloworld_with_dm9161a_phy_-_debug_log.txt. The log file indicates a pbuf problem. Further investigation led me to following webpage: http://www.lpcware.com/content/forum/lwip-sample-fail#comment-1785. I tried again with the mentioned modification but then DHCP does not work. I don't know if this modification also needs to be implemented (not present in the current lwip library).

How to test

import http://mbed.org/users/mbed_official/code/TCPSocket_HelloWorld/ into the mbed compiler.

Goto folder EthernetInterface\lwip-eth\arch#

Delete lpc_phy_dp83848.c.

Copy lpc_phy_DM9161A.c into this folder.

Add following MAC address definition in main.cpp (before 'EthernetInterface eth;').

       extern "C" void mbed_mac_address(char * mac)
       {
       // define your own MAC Address
         mac[0] = 0x00;  
         mac[1] = 0x1F;  
         mac[2] = 0x33;  
         mac[3] = 0x42;  
         mac[4] = 0xFC;  
         mac[5] = 0x6F;           
       };

When used with the Mini-DK hardware

Modify EthernetInterface\lwip-eth\arch\lpc_emac_config.h:

Change #define LPC_PHYDEF_PHYADDR 1 to #define LPC_PHYDEF_PHYADDR 19

On the Mini-DK, sometimes no IP address is obtained when the 'Reset' button is pressed after programming the device. Disconnect and reconnect the device and press the 'Reset' button again to restart.

Committer:
frankvnk
Date:
Mon Mar 18 17:42:16 2013 +0000
Revision:
2:e8cdfd3c70f5
Parent:
0:6901daab33f0
Added wait for autonegotiation completion in init routine

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frankvnk 0:6901daab33f0 1 /**********************************************************************
frankvnk 0:6901daab33f0 2 * $Id$ lpc_phy_DM9161A.c 2013-01-28
frankvnk 0:6901daab33f0 3 *//**
frankvnk 0:6901daab33f0 4 * @file lpc_phy_DM9161A.c
frankvnk 0:6901daab33f0 5 * @brief DM9161A PHY status and control.
frankvnk 0:6901daab33f0 6 * @version 1.0
frankvnk 0:6901daab33f0 7 * @date 14 Jan. 2013
frankvnk 0:6901daab33f0 8 * @author Frank Vannieuwkerke
frankvnk 0:6901daab33f0 9 * based on NXP MCU SW Application Team lpc_phy_dp83848.c
frankvnk 0:6901daab33f0 10 * Copyright(C) 2011, NXP Semiconductor
frankvnk 0:6901daab33f0 11 * All rights reserved.
frankvnk 0:6901daab33f0 12 *
frankvnk 0:6901daab33f0 13 *
frankvnk 0:6901daab33f0 14 *
frankvnk 0:6901daab33f0 15 * @NOTES:
frankvnk 0:6901daab33f0 16 * 1. How to test : import http://mbed.org/users/mbed_official/code/TCPSocket_HelloWorld/ into the mbed compiler.
frankvnk 0:6901daab33f0 17 *
frankvnk 0:6901daab33f0 18 * 2. Open EthernetInterface\lwip-eth\arch folder
frankvnk 0:6901daab33f0 19 * Delete 'lpc_phy_dp83848.c'.
frankvnk 0:6901daab33f0 20 * Copy 'lpc_phy_DM9161A.c' (this file) into this folder.
frankvnk 0:6901daab33f0 21 *
frankvnk 0:6901daab33f0 22 * 3. When used with the Mini-DK hardware:
frankvnk 0:6901daab33f0 23 * Modify EthernetInterface\lwip-eth\arch\lpc_emac_config.h:
frankvnk 0:6901daab33f0 24 * Change #define LPC_PHYDEF_PHYADDR 1 to #define LPC_PHYDEF_PHYADDR 19
frankvnk 0:6901daab33f0 25 *
frankvnk 0:6901daab33f0 26 * Add following MAC address definition in main.cpp (before 'EthernetInterface eth;').
frankvnk 0:6901daab33f0 27 * extern "C" void mbed_mac_address(char * mac)
frankvnk 0:6901daab33f0 28 * {
frankvnk 0:6901daab33f0 29 * // define your own MAC Address
frankvnk 0:6901daab33f0 30 * mac[0] = 0x00;
frankvnk 0:6901daab33f0 31 * mac[1] = 0x1F;
frankvnk 0:6901daab33f0 32 * mac[2] = 0x33;
frankvnk 0:6901daab33f0 33 * mac[3] = 0x42;
frankvnk 0:6901daab33f0 34 * mac[4] = 0xFC;
frankvnk 0:6901daab33f0 35 * mac[5] = 0x6F;
frankvnk 0:6901daab33f0 36 * };
frankvnk 0:6901daab33f0 37 *
frankvnk 0:6901daab33f0 38 *
frankvnk 0:6901daab33f0 39 *
frankvnk 0:6901daab33f0 40 *
frankvnk 0:6901daab33f0 41 ***********************************************************************
frankvnk 0:6901daab33f0 42 * Software that is described herein is for illustrative purposes only
frankvnk 0:6901daab33f0 43 * which provides customers with programming information regarding the
frankvnk 0:6901daab33f0 44 * products. This software is supplied "AS IS" without any warranties.
frankvnk 0:6901daab33f0 45 * NXP Semiconductors assumes no responsibility or liability for the
frankvnk 0:6901daab33f0 46 * use of the software, conveys no license or title under any patent,
frankvnk 0:6901daab33f0 47 * copyright, or mask work right to the product. NXP Semiconductors
frankvnk 0:6901daab33f0 48 * reserves the right to make changes in the software without
frankvnk 0:6901daab33f0 49 * notification. NXP Semiconductors also make no representation or
frankvnk 0:6901daab33f0 50 * warranty that such application will be suitable for the specified
frankvnk 0:6901daab33f0 51 * use without further testing or modification.
frankvnk 0:6901daab33f0 52 **********************************************************************/
frankvnk 0:6901daab33f0 53
frankvnk 0:6901daab33f0 54 #include "lwip/opt.h"
frankvnk 0:6901daab33f0 55 #include "lwip/err.h"
frankvnk 0:6901daab33f0 56 #include "lwip/tcpip.h"
frankvnk 0:6901daab33f0 57 #include "lwip/snmp.h"
frankvnk 0:6901daab33f0 58 #include "lpc_emac_config.h"
frankvnk 0:6901daab33f0 59 #include "lpc_phy.h"
frankvnk 0:6901daab33f0 60
frankvnk 0:6901daab33f0 61 /** @defgroup DM9161A_phy PHY status and control for the DM9161A.
frankvnk 0:6901daab33f0 62 * @ingroup lwip_phy
frankvnk 0:6901daab33f0 63 *
frankvnk 0:6901daab33f0 64 * Various functions for controlling and monitoring the status of the
frankvnk 0:6901daab33f0 65 * DM9161A PHY. In polled (standalone) systems, the PHY state must be
frankvnk 0:6901daab33f0 66 * monitored as part of the application. In a threaded (RTOS) system,
frankvnk 0:6901daab33f0 67 * the PHY state is monitored by the PHY handler thread. The MAC
frankvnk 0:6901daab33f0 68 * driver will not transmit unless the PHY link is active.
frankvnk 0:6901daab33f0 69 * @{
frankvnk 0:6901daab33f0 70 */
frankvnk 0:6901daab33f0 71
frankvnk 0:6901daab33f0 72 /** \brief DM9161A PHY register offsets */
frankvnk 0:6901daab33f0 73 #define DM9161A_BMCR_REG 0x00 /**< Basic Mode Control Register */
frankvnk 0:6901daab33f0 74 #define DM9161A_BMSR_REG 0x01 /**< Basic Mode Status Reg */
frankvnk 0:6901daab33f0 75 #define DM9161A_IDR1_REG 0x02 /**< PHY ID 1 Reg */
frankvnk 0:6901daab33f0 76 #define DM9161A_IDR2_REG 0x03 /**< PHY ID 2 Reg */
frankvnk 0:6901daab33f0 77 #define DM9161A_ANAR_REG 0x04 /**< Auto_Neg Advt Reg */
frankvnk 0:6901daab33f0 78 #define DM9161A_ANLPAR_REG 0x05 /**< Auto_neg Link Partner Ability Reg */
frankvnk 0:6901daab33f0 79 #define DM9161A_ANER_REG 0x06 /**< Auto-neg Expansion Reg */
frankvnk 0:6901daab33f0 80 #define DM9161A_DSCR_REG 0x10 /**< Specified Configuration Reg */
frankvnk 0:6901daab33f0 81 #define DM9161A_DSCSR_REG 0x11 /**< Specified Configuration and Status Reg */
frankvnk 0:6901daab33f0 82 #define DM9161A_10BTCSR_REG 0x12 /**< 10BASE-T Configuration and Satus Reg */
frankvnk 0:6901daab33f0 83 #define DM9161A_MDINTR_REG 0x15 /**< Specified Interrupt Reg */
frankvnk 0:6901daab33f0 84 #define DM9161A_RECR_REG 0x16 /**< Specified Receive Error Counter Reg */
frankvnk 0:6901daab33f0 85 #define DM9161A_DISCR_REG 0x17 /**< Specified Disconnect Counter Reg */
frankvnk 0:6901daab33f0 86 #define DM9161A_RLSR_REG 0x18 /**< Hardware Reset Latch State Reg */
frankvnk 0:6901daab33f0 87
frankvnk 0:6901daab33f0 88 /** \brief DM9161A BMCR register definitions */
frankvnk 0:6901daab33f0 89 #define DM9161A_RESET (1 << 15) /**< 1= S/W Reset */
frankvnk 0:6901daab33f0 90 #define DM9161A_LOOPBACK (1 << 14) /**< 1=loopback Enabled */
frankvnk 0:6901daab33f0 91 #define DM9161A_SPEED_SELECT (1 << 13) /**< 1=Select 100MBps */
frankvnk 0:6901daab33f0 92 #define DM9161A_AUTONEG (1 << 12) /**< 1=Enable auto-negotiation */
frankvnk 0:6901daab33f0 93 #define DM9161A_POWER_DOWN (1 << 11) /**< 1=Power down PHY */
frankvnk 0:6901daab33f0 94 #define DM9161A_ISOLATE (1 << 10) /**< 1=Isolate PHY */
frankvnk 0:6901daab33f0 95 #define DM9161A_RESTART_AUTONEG (1 << 9 ) /**< 1=Restart auto-negoatiation */
frankvnk 0:6901daab33f0 96 #define DM9161A_DUPLEX_MODE (1 << 8 ) /**< 1=Full duplex mode */
frankvnk 0:6901daab33f0 97 #define DM9161A_COLLISION_TEST (1 << 7 ) /**< 1=Perform collsion test */
frankvnk 0:6901daab33f0 98
frankvnk 0:6901daab33f0 99 /** \brief DM9161A BMSR register definitions */
frankvnk 0:6901daab33f0 100 #define DM9161A_100BASE_T4 (1 << 15) /**< T4 mode */
frankvnk 0:6901daab33f0 101 #define DM9161A_100BASE_TX_FD (1 << 14) /**< 100MBps full duplex */
frankvnk 0:6901daab33f0 102 #define DM9161A_100BASE_TX_HD (1 << 13) /**< 100MBps half duplex */
frankvnk 0:6901daab33f0 103 #define DM9161A_10BASE_T_FD (1 << 12) /**< 10MBps full duplex */
frankvnk 0:6901daab33f0 104 #define DM9161A_10BASE_T_HD (1 << 11) /**< 10MBps half duplex */
frankvnk 0:6901daab33f0 105 #define DM9161A_MF_PREAMB_SUPPR (1 << 6 ) /**< Preamble suppress */
frankvnk 0:6901daab33f0 106 #define DM9161A_AUTONEG_COMP (1 << 5 ) /**< Auto-negotation complete */
frankvnk 0:6901daab33f0 107 #define DM9161A_RMT_FAULT (1 << 4 ) /**< Fault */
frankvnk 0:6901daab33f0 108 #define DM9161A_AUTONEG_ABILITY (1 << 3 ) /**< Auto-negotation supported */
frankvnk 0:6901daab33f0 109 #define DM9161A_LINK_STATUS (1 << 2 ) /**< 1=Link active */
frankvnk 0:6901daab33f0 110 #define DM9161A_JABBER_DETECT (1 << 1 ) /**< Jabber detect */
frankvnk 0:6901daab33f0 111 #define DM9161A_EXTEND_CAPAB (1 << 0 ) /**< Supports extended capabilities */
frankvnk 0:6901daab33f0 112
frankvnk 0:6901daab33f0 113 /** \brief DM9161A ANAR and ANLPAR register definitions */
frankvnk 0:6901daab33f0 114 #define DM9161A_NP (1 << 15) /**< No next page - always = 0 */
frankvnk 0:6901daab33f0 115 #define DM9161A_ACK (1 << 14) /**< 1 = Link partner ability data reception acknowledged */
frankvnk 0:6901daab33f0 116 #define DM9161A_RF (1 << 13) /**< 1 = Local device senses a fault condition */
frankvnk 0:6901daab33f0 117 #define DM9161A_FCS (1 << 10) /**< 1 = Controller chip supports flow control ability */
frankvnk 0:6901daab33f0 118 #define DM9161A_T4 (1 << 9 ) /**< No 100BASE-T4 is supported - always = 0 */
frankvnk 0:6901daab33f0 119 #define DM9161A_TX_FDX (1 << 8 ) /**< 1 = 100BASE-TX full duplex is supported by the local device */
frankvnk 0:6901daab33f0 120 #define DM9161A_TX_HDX (1 << 7 ) /**< 1 = 100BASE-TX half duplex is supported by the local device */
frankvnk 0:6901daab33f0 121 #define DM9161A_10_FDX (1 << 6 ) /**< 1 = 10BASE-T full duplex is supported by the local device */
frankvnk 0:6901daab33f0 122 #define DM9161A_10_HDX (1 << 5 ) /**< 1 = 10BASE-T half duplex is supported by the local device */
frankvnk 0:6901daab33f0 123 #define DM9161A_AN_IEEE_802_3 0x0001 /**< this device supports IEEE 802.3 CSMA/CD */
frankvnk 0:6901daab33f0 124
frankvnk 0:6901daab33f0 125 /** \brief DM9161A ANER register definitions */
frankvnk 0:6901daab33f0 126 #define DM9161A_PDF (1 << 4 ) /**< 1 = A fault detected via parallel detection function */
frankvnk 0:6901daab33f0 127 #define DM9161A_LP_NP_ABLE (1 << 3 ) /**< 1 = Link partner, next page available */
frankvnk 0:6901daab33f0 128 #define DM9161A_NP_ABLE (1 << 2 ) /**< No next page - always = 0 */
frankvnk 0:6901daab33f0 129 #define DM9161A_PAGE_RX (1 << 1 ) /**< New page received - cleared when reg 6 is read */
frankvnk 0:6901daab33f0 130 #define DM9161A_LP_AN_ABLE (1 << 0 ) /**< 1 = Link partner supports auto-negotiation */
frankvnk 0:6901daab33f0 131
frankvnk 0:6901daab33f0 132 /** \brief DM9161A DSCR register definitions */
frankvnk 0:6901daab33f0 133 #define DM9161A_BP4B5B (1 << 15) /**< 1 = 4B5B encoder and 5B4B decoder function bypassed */
frankvnk 0:6901daab33f0 134 #define DM9161A_BP_SCR (1 << 14) /**< 1 = Scrambler and descrambler function bypassed */
frankvnk 0:6901daab33f0 135 #define DM9161A_BP_ALIGN (1 << 13) /**< 1 = Receive and Transmit functions disabled */
frankvnk 0:6901daab33f0 136 #define DM9161A_BP_ADPOK (1 << 12) /**< 1 = Force signal detector (SD) active - ONLY FOR DEBUG */
frankvnk 0:6901daab33f0 137 #define DM9161A_REPEATER (1 << 11) /**< 1 = Repeater mode - latched at power up reset */
frankvnk 0:6901daab33f0 138 #define DM9161A_TX (1 << 10) /**< 1 = 100BASE-TX operation */
frankvnk 0:6901daab33f0 139 #define DM9161A_RMII_ENABLE (1 << 8 ) /**< 1 = Enable Reduced MII */
frankvnk 0:6901daab33f0 140 #define DM9161A_F_LINK_100 (1 << 7 ) /**< 1 = Force 100Mbps good link status */
frankvnk 0:6901daab33f0 141 #define DM9161A_SPLED_CTL (1 << 6 ) /**< 1 = Disable SPEEDLED output and enable SD signal monitor - ONLY FOR DEBUG */
frankvnk 0:6901daab33f0 142 #define DM9161A_COLLED_CTL (1 << 5 ) /**< 1 = FDX/COLLED output is configured to indicate Fullduplex Collision status */
frankvnk 0:6901daab33f0 143 #define DM9161A_RPDCTR_EN (1 << 4 ) /**< 1 = Enable automatic reduced power down */
frankvnk 0:6901daab33f0 144 #define DM9161A_SM_RST (1 << 3 ) /**< 1 = Reset state machine - auto cleared after reset */
frankvnk 0:6901daab33f0 145 #define DM9161A_MFP_SC (1 << 2 ) /**< 1 = MF preamble suppression bit on */
frankvnk 0:6901daab33f0 146 #define DM9161A_SLEEP (1 << 1 ) /**< 1 = sleep mode */
frankvnk 0:6901daab33f0 147 #define DM9161A_RLOUT (1 << 0 ) /**< 1 = 1, loop out the received data to the transmit channel */
frankvnk 0:6901daab33f0 148
frankvnk 0:6901daab33f0 149 /** \brief DM9161A DSCSR register definitions */
frankvnk 0:6901daab33f0 150 #define DM9161A_SPEEDMASK (15 << 12) /**< Speed and duplex mask */
frankvnk 0:6901daab33f0 151 #define DM9161A_100FDX (1 << 15) /**< 1 = 100MB full duplex */
frankvnk 0:6901daab33f0 152 #define DM9161A_100HDX (1 << 14) /**< 1 = 100MB half duplex */
frankvnk 0:6901daab33f0 153 #define DM9161A_10FDX (1 << 13) /**< 1 = 10MB full duplex */
frankvnk 0:6901daab33f0 154 #define DM9161A_10HDX (1 << 12) /**< 1 = 10MB half duplex */
frankvnk 0:6901daab33f0 155
frankvnk 0:6901daab33f0 156 /** \brief DM9161A 10BTCSR register definitions */
frankvnk 0:6901daab33f0 157 #define DM9161A_LP_EN (1 << 14) /**< 1 = Transmission of link pulses enabled */
frankvnk 0:6901daab33f0 158 #define DM9161A_HBE (1 << 13) /**< 1 = Heartbeat function enabled */
frankvnk 0:6901daab33f0 159 #define DM9161A_SQUELCH (1 << 12) /**< 1 = normal squelch */
frankvnk 0:6901daab33f0 160 #define DM9161A_JABEN (1 << 11) /**< 1 = Jabber function enabled */
frankvnk 0:6901daab33f0 161 #define DM9161A_10BT_SER (1 << 10) /**< 1 = 10BASE-T GPSI mode selected */
frankvnk 0:6901daab33f0 162 #define DM9161A_POLR (1 << 0 ) /**< 1 = 10Mbps cable polarity is reversed */
frankvnk 0:6901daab33f0 163
frankvnk 0:6901daab33f0 164 /** \brief DM9161A MDINTR register definitions */
frankvnk 0:6901daab33f0 165 #define DM9161A_INTR_PEND (1 << 15) /**< Interrupt pending */
frankvnk 0:6901daab33f0 166 #define DM9161A_FDX_MASK (1 << 11) /**< Full-duplex interrupt mask */
frankvnk 0:6901daab33f0 167 #define DM9161A_SPD_MASK (1 << 10) /**< Speed interrupt mask */
frankvnk 0:6901daab33f0 168 #define DM9161A_LINK_MASK (1 << 9 ) /**< Link interrupt mask */
frankvnk 0:6901daab33f0 169 #define DM9161A_INTR_MASK (1 << 8 ) /**< Master interrupt mask */
frankvnk 0:6901daab33f0 170 #define DM9161A_FDX_CHANGE (1 << 4 ) /**< 1 = indicates a change of duplex since last register read */
frankvnk 0:6901daab33f0 171 #define DM9161A_SPD_CHANGE (1 << 3 ) /**< 1 = indicates a change of speed since last register read */
frankvnk 0:6901daab33f0 172 #define DM9161A_LINK_CHANGE (1 << 2 ) /**< 1 = indicates a change of link since last register read */
frankvnk 0:6901daab33f0 173 #define DM9161A_INTR_STATUS (1 << 0 ) /**< 1 = indicates that the interrupt mask is off */
frankvnk 0:6901daab33f0 174
frankvnk 0:6901daab33f0 175 /** \brief DM9161A RLSR register definitions */
frankvnk 0:6901daab33f0 176 #define DM9161A_LH_LEDMODE (1 << 15) /**< LEDMODE pin reset latch value */
frankvnk 0:6901daab33f0 177 #define DM9161A_LH_MDINTR (1 << 14) /**< MDINTR pin reset latch value */
frankvnk 0:6901daab33f0 178 #define DM9161A_LH_CSTS (1 << 13) /**< CABLESTS pin reset latch value */
frankvnk 0:6901daab33f0 179 #define DM9161A_LH_ISO (1 << 12) /**< TXCLK pin reset latch value */
frankvnk 0:6901daab33f0 180 #define DM9161A_LH_RMII (1 << 11) /**< COL pin reset latch value */
frankvnk 0:6901daab33f0 181 #define DM9161A_LH_TP10SER (1 << 10) /**< RXCLK pin reset latch value */
frankvnk 0:6901daab33f0 182 #define DM9161A_LH_REPTR (1 << 9) /**< RXER pin reset latch value */
frankvnk 0:6901daab33f0 183 #define DM9161A_LH_TSTMOD (1 << 8 ) /**< RXDV pin reset latch value */
frankvnk 0:6901daab33f0 184 #define DM9161A_LH_OP2 (1 << 7 ) /**< LINKLED pin reset latch value */
frankvnk 0:6901daab33f0 185 #define DM9161A_LH_OP1 (1 << 6 ) /**< SPOLED pin reset latch value */
frankvnk 0:6901daab33f0 186 #define DM9161A_LH_OP0 (1 << 5 ) /**< FDXLED pin reset latch value */
frankvnk 0:6901daab33f0 187 #define DM9161A_LH_PH4 (1 << 4 ) /**< CRS pin reset latch value */
frankvnk 0:6901daab33f0 188 #define DM9161A_LH_PH3 (1 << 3 ) /**< RXD3 pin reset latch value */
frankvnk 0:6901daab33f0 189 #define DM9161A_LH_PH2 (1 << 2 ) /**< RXD2 pin reset latch value */
frankvnk 0:6901daab33f0 190 #define DM9161A_LH_PH1 (1 << 1 ) /**< RXD1 pin reset latch value */
frankvnk 0:6901daab33f0 191 #define DM9161A_LH_PH0 (1 << 0 ) /**< RXD0 pin reset latch value */
frankvnk 0:6901daab33f0 192
frankvnk 0:6901daab33f0 193 #define DM9161A_FULLD_100M 0x2100 /**< Full Duplex 100Mbit */
frankvnk 0:6901daab33f0 194 #define DM9161A_HALFD_100M 0x2000 /**< Half Duplex 100Mbit */
frankvnk 0:6901daab33f0 195 #define DM9161A_FULLD_10M 0x0100 /**< Full Duplex 10Mbit */
frankvnk 0:6901daab33f0 196 #define DM9161A_HALFD_10M 0x0000 /**< Half Duplex 10MBit */
frankvnk 0:6901daab33f0 197 #define DM9161A_AUTO_NEG 0x3000 /**< Select Auto Negotiation */
frankvnk 0:6901daab33f0 198 #define DM9161A_AUTO_NEG_MASK 0xEFFF /**< Auto Negotiation mask bit */
frankvnk 0:6901daab33f0 199
frankvnk 0:6901daab33f0 200 /** \brief DM9161A PHY ID register definitions */
frankvnk 0:6901daab33f0 201 #define DM9161A_PHYID1_OUI 0x0181 /**< Expected PHY ID1 */
frankvnk 0:6901daab33f0 202 #define DM9161A_PHYID2_OUI 0xB8A0 /**< Expected PHY ID2 */
frankvnk 0:6901daab33f0 203
frankvnk 0:6901daab33f0 204 #define DM9161A_DEF_ADR 0x1300 /**< Default PHY device address DM9161A */
frankvnk 0:6901daab33f0 205
frankvnk 0:6901daab33f0 206 /** \brief PHY status structure used to indicate current status of PHY.
frankvnk 0:6901daab33f0 207 */
frankvnk 0:6901daab33f0 208 typedef struct {
frankvnk 0:6901daab33f0 209 u32_t phy_speed_100mbs:2; /**< 10/100 MBS connection speed flag. */
frankvnk 0:6901daab33f0 210 u32_t phy_full_duplex:2; /**< Half/full duplex connection speed flag. */
frankvnk 0:6901daab33f0 211 u32_t phy_link_active:2; /**< Phy link active flag. */
frankvnk 0:6901daab33f0 212 } PHY_STATUS_TYPE;
frankvnk 0:6901daab33f0 213
frankvnk 0:6901daab33f0 214 /** \brief PHY update flags */
frankvnk 0:6901daab33f0 215 static PHY_STATUS_TYPE physts;
frankvnk 0:6901daab33f0 216
frankvnk 0:6901daab33f0 217 /** \brief Last PHY update flags, used for determing if something has changed */
frankvnk 0:6901daab33f0 218 static PHY_STATUS_TYPE olddphysts;
frankvnk 0:6901daab33f0 219
frankvnk 0:6901daab33f0 220 /** \brief PHY update counter for state machine */
frankvnk 0:6901daab33f0 221 static s32_t phyustate;
frankvnk 0:6901daab33f0 222
frankvnk 0:6901daab33f0 223 /** \brief Update PHY status from passed value
frankvnk 0:6901daab33f0 224 *
frankvnk 0:6901daab33f0 225 * This function updates the current PHY status based on the
frankvnk 0:6901daab33f0 226 * passed PHY status word. The PHY status indicate if the link
frankvnk 0:6901daab33f0 227 * is active, the connection speed, and duplex.
frankvnk 0:6901daab33f0 228 *
frankvnk 0:6901daab33f0 229 * \param[in] netif NETIF structure
frankvnk 0:6901daab33f0 230 * \param[in] linksts Status word with link state
frankvnk 0:6901daab33f0 231 * \param[in] sdsts Status word with speed and duplex states
frankvnk 0:6901daab33f0 232 * \return 1 if the status has changed, otherwise 0
frankvnk 0:6901daab33f0 233 */
frankvnk 0:6901daab33f0 234 static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts, u32_t sdsts)
frankvnk 0:6901daab33f0 235 {
frankvnk 0:6901daab33f0 236 s32_t changed = 0;
frankvnk 0:6901daab33f0 237
frankvnk 0:6901daab33f0 238 // sdsts &= DM9161A_AUTO_NEG_MASK; // mask DM9161A_AUTO_NEG
frankvnk 0:6901daab33f0 239
frankvnk 0:6901daab33f0 240 /* Update link active status */
frankvnk 0:6901daab33f0 241 if (linksts & DM9161A_LINK_STATUS)
frankvnk 0:6901daab33f0 242 physts.phy_link_active = 1;
frankvnk 0:6901daab33f0 243 else
frankvnk 0:6901daab33f0 244 physts.phy_link_active = 0;
frankvnk 0:6901daab33f0 245
frankvnk 0:6901daab33f0 246 /* Full or half duplex */
frankvnk 0:6901daab33f0 247 if (sdsts & DM9161A_DUPLEX_MODE)
frankvnk 0:6901daab33f0 248 physts.phy_full_duplex = 1;
frankvnk 0:6901daab33f0 249 else
frankvnk 0:6901daab33f0 250 physts.phy_full_duplex = 0;
frankvnk 0:6901daab33f0 251
frankvnk 0:6901daab33f0 252 /* Configure 100MBit/10MBit mode. */
frankvnk 0:6901daab33f0 253 if (sdsts & DM9161A_SPEED_SELECT)
frankvnk 0:6901daab33f0 254 physts.phy_speed_100mbs = 1;
frankvnk 0:6901daab33f0 255 else
frankvnk 0:6901daab33f0 256 physts.phy_speed_100mbs = 0;
frankvnk 0:6901daab33f0 257
frankvnk 0:6901daab33f0 258 if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) {
frankvnk 0:6901daab33f0 259 changed = 1;
frankvnk 0:6901daab33f0 260 if (physts.phy_speed_100mbs) {
frankvnk 0:6901daab33f0 261 /* 100MBit mode. */
frankvnk 0:6901daab33f0 262 lpc_emac_set_speed(1);
frankvnk 0:6901daab33f0 263
frankvnk 0:6901daab33f0 264 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
frankvnk 0:6901daab33f0 265 }
frankvnk 0:6901daab33f0 266 else {
frankvnk 0:6901daab33f0 267 /* 10MBit mode. */
frankvnk 0:6901daab33f0 268 lpc_emac_set_speed(0);
frankvnk 0:6901daab33f0 269
frankvnk 0:6901daab33f0 270 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
frankvnk 0:6901daab33f0 271 }
frankvnk 0:6901daab33f0 272
frankvnk 0:6901daab33f0 273 olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs;
frankvnk 0:6901daab33f0 274 }
frankvnk 0:6901daab33f0 275
frankvnk 0:6901daab33f0 276 if (physts.phy_full_duplex != olddphysts.phy_full_duplex) {
frankvnk 0:6901daab33f0 277 changed = 1;
frankvnk 0:6901daab33f0 278 if (physts.phy_full_duplex)
frankvnk 0:6901daab33f0 279 lpc_emac_set_duplex(1);
frankvnk 0:6901daab33f0 280 else
frankvnk 0:6901daab33f0 281 lpc_emac_set_duplex(0);
frankvnk 0:6901daab33f0 282
frankvnk 0:6901daab33f0 283 olddphysts.phy_full_duplex = physts.phy_full_duplex;
frankvnk 0:6901daab33f0 284 }
frankvnk 0:6901daab33f0 285
frankvnk 0:6901daab33f0 286 if (physts.phy_link_active != olddphysts.phy_link_active) {
frankvnk 0:6901daab33f0 287 changed = 1;
frankvnk 0:6901daab33f0 288 #if NO_SYS == 1
frankvnk 0:6901daab33f0 289 if (physts.phy_link_active)
frankvnk 0:6901daab33f0 290 netif_set_link_up(netif);
frankvnk 0:6901daab33f0 291 else
frankvnk 0:6901daab33f0 292 netif_set_link_down(netif);
frankvnk 0:6901daab33f0 293 #else
frankvnk 0:6901daab33f0 294 if (physts.phy_link_active)
frankvnk 0:6901daab33f0 295 tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
frankvnk 0:6901daab33f0 296 (void*) netif, 1);
frankvnk 0:6901daab33f0 297 else
frankvnk 0:6901daab33f0 298 tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
frankvnk 0:6901daab33f0 299 (void*) netif, 1);
frankvnk 0:6901daab33f0 300 #endif
frankvnk 0:6901daab33f0 301
frankvnk 0:6901daab33f0 302 olddphysts.phy_link_active = physts.phy_link_active;
frankvnk 0:6901daab33f0 303 }
frankvnk 0:6901daab33f0 304
frankvnk 0:6901daab33f0 305 return changed;
frankvnk 0:6901daab33f0 306 }
frankvnk 0:6901daab33f0 307
frankvnk 0:6901daab33f0 308 /** \brief Initialize the DM9161A PHY.
frankvnk 0:6901daab33f0 309 *
frankvnk 0:6901daab33f0 310 * This function initializes the DM9161A PHY. It will block until
frankvnk 0:6901daab33f0 311 * complete. This function is called as part of the EMAC driver
frankvnk 0:6901daab33f0 312 * initialization. Configuration of the PHY at startup is
frankvnk 0:6901daab33f0 313 * controlled by setting up configuration defines in lpc_phy.h.
frankvnk 0:6901daab33f0 314 *
frankvnk 0:6901daab33f0 315 * \param[in] netif NETIF structure
frankvnk 0:6901daab33f0 316 * \param[in] rmii If set, configures the PHY for RMII mode
frankvnk 0:6901daab33f0 317 * \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
frankvnk 0:6901daab33f0 318 */
frankvnk 0:6901daab33f0 319 err_t lpc_phy_init(struct netif *netif, int rmii)
frankvnk 0:6901daab33f0 320 {
frankvnk 0:6901daab33f0 321 u32_t tmp;
frankvnk 0:6901daab33f0 322 s32_t i;
frankvnk 0:6901daab33f0 323
frankvnk 0:6901daab33f0 324 physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 2;
frankvnk 0:6901daab33f0 325 physts.phy_full_duplex = olddphysts.phy_full_duplex = 2;
frankvnk 0:6901daab33f0 326 physts.phy_link_active = olddphysts.phy_link_active = 2;
frankvnk 0:6901daab33f0 327 phyustate = 0;
frankvnk 0:6901daab33f0 328
frankvnk 0:6901daab33f0 329 /* Only first read and write are checked for failure */
frankvnk 0:6901daab33f0 330 /* Put the DM9161A in reset mode and wait for completion */
frankvnk 0:6901daab33f0 331 if (lpc_mii_write(DM9161A_BMCR_REG, DM9161A_RESET) != 0)
frankvnk 0:6901daab33f0 332 return ERR_TIMEOUT;
frankvnk 0:6901daab33f0 333 i = 400;
frankvnk 0:6901daab33f0 334 while (i > 0) {
frankvnk 0:6901daab33f0 335 osDelay(1); // 1 ms
frankvnk 0:6901daab33f0 336 if (lpc_mii_read(DM9161A_BMCR_REG, &tmp) != 0)
frankvnk 0:6901daab33f0 337 return ERR_TIMEOUT;
frankvnk 0:6901daab33f0 338
frankvnk 0:6901daab33f0 339 if (!(tmp & (DM9161A_RESET | DM9161A_POWER_DOWN)))
frankvnk 0:6901daab33f0 340 i = -1;
frankvnk 0:6901daab33f0 341 else
frankvnk 0:6901daab33f0 342 i--;
frankvnk 0:6901daab33f0 343 }
frankvnk 0:6901daab33f0 344 // Timeout?
frankvnk 0:6901daab33f0 345 if (i == 0)
frankvnk 0:6901daab33f0 346 return ERR_TIMEOUT;
frankvnk 0:6901daab33f0 347
frankvnk 0:6901daab33f0 348 /* Setup link based on configuration options */
frankvnk 0:6901daab33f0 349 #if PHY_USE_AUTONEG==1
frankvnk 0:6901daab33f0 350 tmp = DM9161A_AUTONEG | DM9161A_RESTART_AUTONEG;
frankvnk 0:6901daab33f0 351 #else
frankvnk 0:6901daab33f0 352 tmp = 0;
frankvnk 0:6901daab33f0 353 #endif
frankvnk 0:6901daab33f0 354 #if PHY_USE_100MBS==1
frankvnk 0:6901daab33f0 355 tmp |= DM9161A_SPEED_SELECT;
frankvnk 0:6901daab33f0 356 #endif
frankvnk 0:6901daab33f0 357 #if PHY_USE_FULL_DUPLEX==1
frankvnk 0:6901daab33f0 358 tmp |= DM9161A_DUPLEX_MODE;
frankvnk 0:6901daab33f0 359 #endif
frankvnk 0:6901daab33f0 360
frankvnk 0:6901daab33f0 361 lpc_mii_write(DM9161A_BMCR_REG, tmp);
frankvnk 0:6901daab33f0 362
frankvnk 2:e8cdfd3c70f5 363 /* Wait for autonegotiation completion */
frankvnk 2:e8cdfd3c70f5 364 i = 400;
frankvnk 2:e8cdfd3c70f5 365 while (i > 0)
frankvnk 2:e8cdfd3c70f5 366 {
frankvnk 2:e8cdfd3c70f5 367 osDelay(1); // 1 ms
frankvnk 2:e8cdfd3c70f5 368 if (lpc_mii_read(DM9161A_BMSR_REG, &tmp) != 0)
frankvnk 2:e8cdfd3c70f5 369 {
frankvnk 2:e8cdfd3c70f5 370 printf("Timeout\n");
frankvnk 2:e8cdfd3c70f5 371 return ERR_TIMEOUT;
frankvnk 2:e8cdfd3c70f5 372 }
frankvnk 2:e8cdfd3c70f5 373 if (tmp & (DM9161A_AUTONEG_COMP))
frankvnk 2:e8cdfd3c70f5 374 i = -1;
frankvnk 2:e8cdfd3c70f5 375 else
frankvnk 2:e8cdfd3c70f5 376 i--;
frankvnk 2:e8cdfd3c70f5 377 }
frankvnk 2:e8cdfd3c70f5 378 // Timeout?
frankvnk 2:e8cdfd3c70f5 379 if (i == 0)
frankvnk 2:e8cdfd3c70f5 380 {
frankvnk 2:e8cdfd3c70f5 381 printf("Timeout\n");
frankvnk 2:e8cdfd3c70f5 382 return ERR_TIMEOUT;
frankvnk 2:e8cdfd3c70f5 383 }
frankvnk 2:e8cdfd3c70f5 384
frankvnk 0:6901daab33f0 385 /* Enable RMII mode for PHY - NOT NEEDED FOR MIDI-DK - RMII pin is lathed on reset*/
frankvnk 0:6901daab33f0 386 /* if (rmii)
frankvnk 0:6901daab33f0 387 lpc_mii_write(DM9161A_DSCR_REG, DM9161A_RMII_ENABLE);
frankvnk 0:6901daab33f0 388 */
frankvnk 0:6901daab33f0 389 /* The link is not set active at this point, but will be detected
frankvnk 0:6901daab33f0 390 later */
frankvnk 0:6901daab33f0 391
frankvnk 0:6901daab33f0 392 return ERR_OK;
frankvnk 0:6901daab33f0 393 }
frankvnk 0:6901daab33f0 394
frankvnk 0:6901daab33f0 395 /* Phy status update state machine */
frankvnk 0:6901daab33f0 396 s32_t lpc_phy_sts_sm(struct netif *netif)
frankvnk 0:6901daab33f0 397 {
frankvnk 0:6901daab33f0 398 static u32_t sts;
frankvnk 0:6901daab33f0 399 s32_t changed = 0;
frankvnk 0:6901daab33f0 400 switch (phyustate)
frankvnk 0:6901daab33f0 401 {
frankvnk 0:6901daab33f0 402 default:
frankvnk 0:6901daab33f0 403 case 0:
frankvnk 0:6901daab33f0 404 // Read BMSR to clear faults
frankvnk 0:6901daab33f0 405 lpc_mii_read_noblock(DM9161A_BMSR_REG);
frankvnk 0:6901daab33f0 406 phyustate = 1;
frankvnk 0:6901daab33f0 407 break;
frankvnk 0:6901daab33f0 408
frankvnk 0:6901daab33f0 409 case 1:
frankvnk 0:6901daab33f0 410 // Wait for read status state
frankvnk 0:6901daab33f0 411 if (!lpc_mii_is_busy())
frankvnk 0:6901daab33f0 412 {
frankvnk 0:6901daab33f0 413 // Get autonegotiation complete bit
frankvnk 0:6901daab33f0 414 sts = lpc_mii_read_data();
frankvnk 0:6901daab33f0 415 lpc_mii_read_noblock(DM9161A_BMCR_REG);
frankvnk 0:6901daab33f0 416 phyustate = 2;
frankvnk 0:6901daab33f0 417 }
frankvnk 0:6901daab33f0 418 break;
frankvnk 0:6901daab33f0 419
frankvnk 0:6901daab33f0 420 case 2:
frankvnk 0:6901daab33f0 421 // Wait for read status state
frankvnk 0:6901daab33f0 422 if (!lpc_mii_is_busy())
frankvnk 0:6901daab33f0 423 {
frankvnk 0:6901daab33f0 424 // Update PHY status (BMCR contains speed and duplex state)
frankvnk 0:6901daab33f0 425 changed = lpc_update_phy_sts(netif, sts, lpc_mii_read_data());
frankvnk 0:6901daab33f0 426 phyustate = 0;
frankvnk 0:6901daab33f0 427 }
frankvnk 0:6901daab33f0 428 break;
frankvnk 0:6901daab33f0 429 }
frankvnk 0:6901daab33f0 430 return changed;
frankvnk 0:6901daab33f0 431 }
frankvnk 0:6901daab33f0 432
frankvnk 0:6901daab33f0 433 /* //Original state machine code
frankvnk 0:6901daab33f0 434 */
frankvnk 0:6901daab33f0 435
frankvnk 0:6901daab33f0 436
frankvnk 0:6901daab33f0 437
frankvnk 0:6901daab33f0 438 /**
frankvnk 0:6901daab33f0 439 * @}
frankvnk 0:6901daab33f0 440 */
frankvnk 0:6901daab33f0 441
frankvnk 0:6901daab33f0 442 /* --------------------------------- End Of File ------------------------------ */