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.
lpc_phy_DM9161A.c@0:6901daab33f0, 2013-01-29 (annotated)
- Committer:
- frankvnk
- Date:
- Tue Jan 29 12:45:31 2013 +0000
- Revision:
- 0:6901daab33f0
- Child:
- 2:e8cdfd3c70f5
DM9161 PHY for lwip 1.4 library
Who changed what in which revision?
User | Revision | Line number | New 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 | 0:6901daab33f0 | 363 | /* Enable RMII mode for PHY - NOT NEEDED FOR MIDI-DK - RMII pin is lathed on reset*/ |
frankvnk | 0:6901daab33f0 | 364 | /* if (rmii) |
frankvnk | 0:6901daab33f0 | 365 | lpc_mii_write(DM9161A_DSCR_REG, DM9161A_RMII_ENABLE); |
frankvnk | 0:6901daab33f0 | 366 | */ |
frankvnk | 0:6901daab33f0 | 367 | /* The link is not set active at this point, but will be detected |
frankvnk | 0:6901daab33f0 | 368 | later */ |
frankvnk | 0:6901daab33f0 | 369 | |
frankvnk | 0:6901daab33f0 | 370 | return ERR_OK; |
frankvnk | 0:6901daab33f0 | 371 | } |
frankvnk | 0:6901daab33f0 | 372 | |
frankvnk | 0:6901daab33f0 | 373 | /* Phy status update state machine */ |
frankvnk | 0:6901daab33f0 | 374 | s32_t lpc_phy_sts_sm(struct netif *netif) |
frankvnk | 0:6901daab33f0 | 375 | { |
frankvnk | 0:6901daab33f0 | 376 | static u32_t sts; |
frankvnk | 0:6901daab33f0 | 377 | s32_t changed = 0; |
frankvnk | 0:6901daab33f0 | 378 | switch (phyustate) |
frankvnk | 0:6901daab33f0 | 379 | { |
frankvnk | 0:6901daab33f0 | 380 | default: |
frankvnk | 0:6901daab33f0 | 381 | case 0: |
frankvnk | 0:6901daab33f0 | 382 | // Read BMSR to clear faults |
frankvnk | 0:6901daab33f0 | 383 | lpc_mii_read_noblock(DM9161A_BMSR_REG); |
frankvnk | 0:6901daab33f0 | 384 | phyustate = 1; |
frankvnk | 0:6901daab33f0 | 385 | break; |
frankvnk | 0:6901daab33f0 | 386 | |
frankvnk | 0:6901daab33f0 | 387 | case 1: |
frankvnk | 0:6901daab33f0 | 388 | // Wait for read status state |
frankvnk | 0:6901daab33f0 | 389 | if (!lpc_mii_is_busy()) |
frankvnk | 0:6901daab33f0 | 390 | { |
frankvnk | 0:6901daab33f0 | 391 | // Get autonegotiation complete bit |
frankvnk | 0:6901daab33f0 | 392 | sts = lpc_mii_read_data(); |
frankvnk | 0:6901daab33f0 | 393 | lpc_mii_read_noblock(DM9161A_BMCR_REG); |
frankvnk | 0:6901daab33f0 | 394 | phyustate = 2; |
frankvnk | 0:6901daab33f0 | 395 | } |
frankvnk | 0:6901daab33f0 | 396 | break; |
frankvnk | 0:6901daab33f0 | 397 | |
frankvnk | 0:6901daab33f0 | 398 | case 2: |
frankvnk | 0:6901daab33f0 | 399 | // Wait for read status state |
frankvnk | 0:6901daab33f0 | 400 | if (!lpc_mii_is_busy()) |
frankvnk | 0:6901daab33f0 | 401 | { |
frankvnk | 0:6901daab33f0 | 402 | // Update PHY status (BMCR contains speed and duplex state) |
frankvnk | 0:6901daab33f0 | 403 | changed = lpc_update_phy_sts(netif, sts, lpc_mii_read_data()); |
frankvnk | 0:6901daab33f0 | 404 | phyustate = 0; |
frankvnk | 0:6901daab33f0 | 405 | } |
frankvnk | 0:6901daab33f0 | 406 | break; |
frankvnk | 0:6901daab33f0 | 407 | } |
frankvnk | 0:6901daab33f0 | 408 | return changed; |
frankvnk | 0:6901daab33f0 | 409 | } |
frankvnk | 0:6901daab33f0 | 410 | |
frankvnk | 0:6901daab33f0 | 411 | /* //Original state machine code |
frankvnk | 0:6901daab33f0 | 412 | */ |
frankvnk | 0:6901daab33f0 | 413 | |
frankvnk | 0:6901daab33f0 | 414 | |
frankvnk | 0:6901daab33f0 | 415 | |
frankvnk | 0:6901daab33f0 | 416 | /** |
frankvnk | 0:6901daab33f0 | 417 | * @} |
frankvnk | 0:6901daab33f0 | 418 | */ |
frankvnk | 0:6901daab33f0 | 419 | |
frankvnk | 0:6901daab33f0 | 420 | /* --------------------------------- End Of File ------------------------------ */ |