1 /***************************************************************************//**
\r
2 * PHY access methods for DP83848C.
\r
3 * The implementation in this file is specific to the DP83848C,
\r
4 * If a different PHY support is required the PHY specific registers must
\r
6 * (c) Copyright 2007 Actel Corporation
\r
8 * SVN $Revision: 2324 $
\r
9 * SVN $Date: 2010-02-26 10:47:36 +0000 (Fri, 26 Feb 2010) $
\r
11 ******************************************************************************/
\r
18 #include "mss_ethernet_mac.h"
\r
19 #include "mss_ethernet_mac_regs.h"
\r
23 #include "FreeRTOS.h"
\r
26 extern MAC_instance_t g_mss_mac;
\r
28 /***************************** MDIO FUNCTIONS *********************************/
\r
30 /* Defines ********************************************************************/
\r
31 #define MDIO_START 0x00004000UL
\r
32 #define MDIO_READ 0x00002000UL
\r
33 #define MDIO_WRITE 0x00001002UL
\r
34 #define MDIO_ADDR_OFFSET 7UL
\r
35 #define MDIO_ADDR_MASK 0x00000f80UL
\r
36 #define MDIO_REG_ADDR_OFFSET 2UL
\r
37 #define MDIO_REG_ADDR_MASK 0x0000007cUL
\r
38 #define PREAMBLECOUNT 32UL
\r
39 #define ONEMICROSECOND 20UL
\r
48 /***************************************************************************//**
\r
49 * Set clock high or low.
\r
52 MDIO_management_clock
\r
59 MAC_BITBAND->CSR9_MDC = (uint32_t)clock;
\r
62 for( a = 0; a < ONEMICROSECOND; a++ ){}
\r
66 /***************************************************************************//**
\r
67 * Send read or write command to PHY.
\r
77 uint16_t mask, data;
\r
79 /* enable MII output */
\r
80 MAC_BITBAND->CSR9_MDEN = 1;
\r
82 /* send 32 1's preamble */
\r
83 MAC_BITBAND->CSR9_MDO = 1;
\r
84 for (i = 0; i < PREAMBLECOUNT; i++) {
\r
85 MDIO_management_clock( 0 );
\r
86 MDIO_management_clock( 1 );
\r
89 /* calculate data bits */
\r
91 (( mdio_cmd == MDIO_CMD_READ ) ? MDIO_READ : MDIO_WRITE ) |
\r
92 ((g_mss_mac.phy_address << MDIO_ADDR_OFFSET) & MDIO_ADDR_MASK) |
\r
93 ((regad << MDIO_REG_ADDR_OFFSET) & MDIO_REG_ADDR_MASK);
\r
96 for( mask = 0x00008000L; mask>0; mask >>= 1 )
\r
98 if ((mask == 0x2) && (mdio_cmd == MDIO_CMD_READ)) {
\r
99 /* enable MII input */
\r
100 MAC_BITBAND->CSR9_MDEN = 0;
\r
103 MDIO_management_clock( 0 );
\r
106 MAC_BITBAND->CSR9_MDO = (uint32_t)((mask & data) != 0 ? 1UL : 0UL);
\r
108 MDIO_management_clock( 1 );
\r
113 /***************************************************************************//**
\r
114 * Reads a PHY register.
\r
125 MDIO_send_cmd( regad, MDIO_CMD_READ);
\r
129 for( mask = 0x00008000L; mask>0; mask >>= 1 )
\r
131 MDIO_management_clock( 0 );
\r
134 if(MAC_BITBAND-> CSR9_MDI != 0){
\r
138 MDIO_management_clock( 1 );
\r
141 MDIO_management_clock( 0 );
\r
147 /***************************************************************************//**
\r
148 * Writes to a PHY register.
\r
159 MDIO_send_cmd(regad, MDIO_CMD_WRITE);
\r
162 for( mask = 0x00008000L; mask>0; mask >>= 1 )
\r
164 MDIO_management_clock( 0 );
\r
167 MAC_BITBAND->CSR9_MDO = (uint32_t)((mask & data) != 0 ? 1UL : 0UL);
\r
169 MDIO_management_clock( 1 );
\r
172 MDIO_management_clock( 0 );
\r
176 /****************************** PHY FUNCTIONS *********************************/
\r
178 /* Defines ********************************************************************/
\r
180 /* Base registers */
\r
181 #define PHYREG_MIIMCR 0x00 /**< MII Management Control Register */
\r
182 #define MIIMCR_RESET (1<<15)
\r
183 #define MIIMCR_LOOPBACK (1<<14)
\r
184 #define MIIMCR_SPEED_SELECT (1<<13)
\r
185 #define MIIMCR_ENABLE_AUTONEGOTIATION (1<<12)
\r
186 #define MIIMCR_RESTART_AUTONEGOTIATION (1<<9)
\r
187 #define MIIMCR_DUPLEX_MODE (1<<8)
\r
188 #define MIIMCR_COLLISION_TEST (1<<7)
\r
190 #define PHYREG_MIIMSR 0x01 /**< MII Management Status Register */
\r
191 #define MIIMSR_ANC (1<<5) /**< Auto-Negotiation Completed. */
\r
192 #define MIIMSR_LINK (1<<2) /**< Link is established. */
\r
194 #define PHYREG_PHYID1R 0x02 /**< PHY Identifier 1 Register */
\r
195 #define PHYREG_PHYID2R 0x03 /**< PHY Identifier 2 Register */
\r
197 #define PHYREG_ANAR 0x04 /**< Auto-Negotiation Advertisement Register */
\r
198 #define ANAR_100FD (1<<8)
\r
199 #define ANAR_100HD (1<<7)
\r
200 #define ANAR_10FD (1<<6)
\r
201 #define ANAR_10HD (1<<5)
\r
203 #define PHYREG_ANLPAR 0x05 /**< Auto-Negotiation Link Partner Ability Register */
\r
204 #define PHYREG_ANER 0x06 /**< Auto-Negotiation Expansion Register */
\r
205 #define PHYREG_NPAR 0x07 /**< Next Page Advertisement Register */
\r
206 /* 0x08- 0x0F Reserved */
\r
207 #define PHYREG_MFR 0x10 /**< Miscellaneous Features Register */
\r
208 #define PHYREG_ICSR 0x11 /**< Interrupt Control/Status Register */
\r
210 #define PHYREG_DR 0x12 /**< Diagnostic Register */
\r
211 #define DR_DPLX (1<<11)
\r
212 #define DR_DATA_RATE (1<<10)
\r
214 #define PHYREG_PMLR 0x13 /**< Power Management & Loopback Register */
\r
215 /* 0x14 Reserved */
\r
216 #define PHYREG_MCR 0x15 /**< Mode Control Register */
\r
217 #define MCR_LED_SEL (1<<9)
\r
218 /* 0x16 Reserved */
\r
219 #define PHYREG_DCR 0x17 /**< Disconnect Counter */
\r
220 #define PHYREG_RECR 0x18 /**< Receive Error Counter */
\r
221 /* 0x19-0x1F Reserved */
\r
223 /***************************************************************************//**
\r
226 * return PHY address. If PHY don't fount, returns 255.
\r
228 uint8_t PHY_probe( void )
\r
235 for (phy = MSS_PHY_ADDRESS_MIN; phy <= MSS_PHY_ADDRESS_MAX; phy++) {
\r
236 g_mss_mac.phy_address = phy;
\r
238 reg = MDIO_read( PHYREG_PHYID1R );
\r
240 if ((reg != 0x0000ffffUL) && (reg != 0x00000000UL)) {
\r
242 phy = MSS_PHY_ADDRESS_MAX + 1;
\r
246 if( phy_found == 0 ) {
\r
247 g_mss_mac.phy_address = MSS_PHY_ADDRESS_AUTO_DETECT;
\r
249 return g_mss_mac.phy_address;
\r
253 /***************************************************************************//**
\r
256 void PHY_reset( void )
\r
258 MDIO_write( PHYREG_MIIMCR, MIIMCR_RESET );
\r
259 MDIO_write( PHYREG_MIIMCR,
\r
260 MIIMCR_ENABLE_AUTONEGOTIATION |
\r
261 MIIMCR_RESTART_AUTONEGOTIATION |
\r
262 MIIMCR_COLLISION_TEST );
\r
266 /***************************************************************************//**
\r
267 * Restarts PHY auto-negotiation and wait until it's over.
\r
269 void PHY_auto_negotiate( void )
\r
273 reg = MDIO_read( PHYREG_MIIMCR );
\r
274 MDIO_write( PHYREG_MIIMCR,
\r
275 (uint16_t)( MIIMCR_ENABLE_AUTONEGOTIATION |
\r
276 MIIMCR_RESTART_AUTONEGOTIATION |
\r
280 reg = MDIO_read( PHYREG_MIIMSR );
\r
281 if( (reg & MIIMSR_ANC) != 0 ) {
\r
290 /***************************************************************************//**
\r
291 * Returns link status.
\r
293 * @return #MAC_LINK_STATUS_LINK if link is up.
\r
295 uint8_t PHY_link_status( void )
\r
297 uint8_t retval = 0;
\r
298 if(( MDIO_read( PHYREG_MIIMSR ) & MIIMSR_LINK ) != 0 ){
\r
299 retval = MSS_MAC_LINK_STATUS_LINK;
\r
305 /***************************************************************************//**
\r
306 * Returns link type.
\r
308 * @return the logical OR of the following values:
\r
309 * #MAC_LINK_STATUS_100MB - Connection is 100Mb
\r
310 * #MAC_LINK_STATUS_FDX - Connection is full duplex
\r
312 uint8_t PHY_link_type( void )
\r
314 uint16_t diagnostic;
\r
317 diagnostic = MDIO_read( PHYREG_DR );
\r
319 if( (diagnostic & DR_DPLX) != 0 ) {
\r
320 type = MSS_MAC_LINK_STATUS_FDX;
\r
323 if( (diagnostic & DR_DATA_RATE) != 0 ) {
\r
324 type |= MSS_MAC_LINK_STATUS_100MB;
\r
331 /***************************************************************************//**
\r
342 reg = MDIO_read( PHYREG_ANAR );
\r
343 reg |= ANAR_100FD | ANAR_100HD | ANAR_10FD | ANAR_10HD;
\r
345 if( (type & MSS_MAC_LINK_STATUS_100MB) == 0 ) {
\r
346 reg &= ~(ANAR_100FD | ANAR_100HD);
\r
349 if( (type & MSS_MAC_LINK_STATUS_FDX) == 0 ) {
\r
350 reg &= ~(ANAR_100FD | ANAR_10FD);
\r
353 MDIO_write( PHYREG_ANAR, reg );
\r
357 /***************************************************************************//**
\r
358 * Puts the Phy in Loopback mode
\r
370 reg = MDIO_read( PHYREG_MIIMCR );
\r
371 // If set to one we need to set the LOCAL Phy loopback
\r
373 reg |= MIIMCR_LOOPBACK;
\r
374 else // else we want to clear the bit..
\r
375 reg ^= MIIMCR_LOOPBACK;
\r
378 MDIO_write( PHYREG_MIIMCR,reg );
\r
379 reg = MDIO_read( PHYREG_MIIMCR );
\r
389 /******************************** END OF FILE *********************************/
\r