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 extern MAC_instance_t g_mss_mac;
\r
25 /***************************** MDIO FUNCTIONS *********************************/
\r
27 /* Defines ********************************************************************/
\r
28 #define MDIO_START 0x00004000UL
\r
29 #define MDIO_READ 0x00002000UL
\r
30 #define MDIO_WRITE 0x00001002UL
\r
31 #define MDIO_ADDR_OFFSET 7UL
\r
32 #define MDIO_ADDR_MASK 0x00000f80UL
\r
33 #define MDIO_REG_ADDR_OFFSET 2UL
\r
34 #define MDIO_REG_ADDR_MASK 0x0000007cUL
\r
35 #define PREAMBLECOUNT 32UL
\r
36 #define ONEMICROSECOND 20UL
\r
45 /***************************************************************************//**
\r
46 * Set clock high or low.
\r
49 MDIO_management_clock
\r
56 MAC_BITBAND->CSR9_MDC = (uint32_t)clock;
\r
59 for( a = 0; a < ONEMICROSECOND; a++ ){}
\r
63 /***************************************************************************//**
\r
64 * Send read or write command to PHY.
\r
74 uint16_t mask, data;
\r
76 /* enable MII output */
\r
77 MAC_BITBAND->CSR9_MDEN = 1;
\r
79 /* send 32 1's preamble */
\r
80 MAC_BITBAND->CSR9_MDO = 1;
\r
81 for (i = 0; i < PREAMBLECOUNT; i++) {
\r
82 MDIO_management_clock( 0 );
\r
83 MDIO_management_clock( 1 );
\r
86 /* calculate data bits */
\r
88 (( mdio_cmd == MDIO_CMD_READ ) ? MDIO_READ : MDIO_WRITE ) |
\r
89 ((g_mss_mac.phy_address << MDIO_ADDR_OFFSET) & MDIO_ADDR_MASK) |
\r
90 ((regad << MDIO_REG_ADDR_OFFSET) & MDIO_REG_ADDR_MASK);
\r
93 for( mask = 0x00008000L; mask>0; mask >>= 1 )
\r
95 if ((mask == 0x2) && (mdio_cmd == MDIO_CMD_READ)) {
\r
96 /* enable MII input */
\r
97 MAC_BITBAND->CSR9_MDEN = 0;
\r
100 MDIO_management_clock( 0 );
\r
103 MAC_BITBAND->CSR9_MDO = (uint32_t)((mask & data) != 0 ? 1UL : 0UL);
\r
105 MDIO_management_clock( 1 );
\r
110 /***************************************************************************//**
\r
111 * Reads a PHY register.
\r
122 MDIO_send_cmd( regad, MDIO_CMD_READ);
\r
126 for( mask = 0x00008000L; mask>0; mask >>= 1 )
\r
128 MDIO_management_clock( 0 );
\r
131 if(MAC_BITBAND-> CSR9_MDI != 0){
\r
135 MDIO_management_clock( 1 );
\r
138 MDIO_management_clock( 0 );
\r
144 /***************************************************************************//**
\r
145 * Writes to a PHY register.
\r
156 MDIO_send_cmd(regad, MDIO_CMD_WRITE);
\r
159 for( mask = 0x00008000L; mask>0; mask >>= 1 )
\r
161 MDIO_management_clock( 0 );
\r
164 MAC_BITBAND->CSR9_MDO = (uint32_t)((mask & data) != 0 ? 1UL : 0UL);
\r
166 MDIO_management_clock( 1 );
\r
169 MDIO_management_clock( 0 );
\r
173 /****************************** PHY FUNCTIONS *********************************/
\r
175 /* Defines ********************************************************************/
\r
177 /* Base registers */
\r
178 #define PHYREG_MIIMCR 0x00 /**< MII Management Control Register */
\r
179 #define MIIMCR_RESET (1<<15)
\r
180 #define MIIMCR_LOOPBACK (1<<14)
\r
181 #define MIIMCR_SPEED_SELECT (1<<13)
\r
182 #define MIIMCR_ENABLE_AUTONEGOTIATION (1<<12)
\r
183 #define MIIMCR_RESTART_AUTONEGOTIATION (1<<9)
\r
184 #define MIIMCR_DUPLEX_MODE (1<<8)
\r
185 #define MIIMCR_COLLISION_TEST (1<<7)
\r
187 #define PHYREG_MIIMSR 0x01 /**< MII Management Status Register */
\r
188 #define MIIMSR_ANC (1<<5) /**< Auto-Negotiation Completed. */
\r
189 #define MIIMSR_LINK (1<<2) /**< Link is established. */
\r
191 #define PHYREG_PHYID1R 0x02 /**< PHY Identifier 1 Register */
\r
192 #define PHYREG_PHYID2R 0x03 /**< PHY Identifier 2 Register */
\r
194 #define PHYREG_ANAR 0x04 /**< Auto-Negotiation Advertisement Register */
\r
195 #define ANAR_100FD (1<<8)
\r
196 #define ANAR_100HD (1<<7)
\r
197 #define ANAR_10FD (1<<6)
\r
198 #define ANAR_10HD (1<<5)
\r
200 #define PHYREG_ANLPAR 0x05 /**< Auto-Negotiation Link Partner Ability Register */
\r
201 #define PHYREG_ANER 0x06 /**< Auto-Negotiation Expansion Register */
\r
202 #define PHYREG_NPAR 0x07 /**< Next Page Advertisement Register */
\r
203 /* 0x08- 0x0F Reserved */
\r
204 #define PHYREG_MFR 0x10 /**< Miscellaneous Features Register */
\r
205 #define PHYREG_ICSR 0x11 /**< Interrupt Control/Status Register */
\r
207 #define PHYREG_DR 0x12 /**< Diagnostic Register */
\r
208 #define DR_DPLX (1<<11)
\r
209 #define DR_DATA_RATE (1<<10)
\r
211 #define PHYREG_PMLR 0x13 /**< Power Management & Loopback Register */
\r
212 /* 0x14 Reserved */
\r
213 #define PHYREG_MCR 0x15 /**< Mode Control Register */
\r
214 #define MCR_LED_SEL (1<<9)
\r
215 /* 0x16 Reserved */
\r
216 #define PHYREG_DCR 0x17 /**< Disconnect Counter */
\r
217 #define PHYREG_RECR 0x18 /**< Receive Error Counter */
\r
218 /* 0x19-0x1F Reserved */
\r
220 /***************************************************************************//**
\r
223 * return PHY address. If PHY don't fount, returns 255.
\r
225 uint8_t PHY_probe( void )
\r
232 for (phy = MSS_PHY_ADDRESS_MIN; phy <= MSS_PHY_ADDRESS_MAX; phy++) {
\r
233 g_mss_mac.phy_address = phy;
\r
235 reg = MDIO_read( PHYREG_PHYID1R );
\r
237 if ((reg != 0x0000ffffUL) && (reg != 0x00000000UL)) {
\r
239 phy = MSS_PHY_ADDRESS_MAX + 1;
\r
243 if( phy_found == 0 ) {
\r
244 g_mss_mac.phy_address = MSS_PHY_ADDRESS_AUTO_DETECT;
\r
246 return g_mss_mac.phy_address;
\r
250 /***************************************************************************//**
\r
253 void PHY_reset( void )
\r
255 MDIO_write( PHYREG_MIIMCR, MIIMCR_RESET );
\r
256 MDIO_write( PHYREG_MIIMCR,
\r
257 MIIMCR_ENABLE_AUTONEGOTIATION |
\r
258 MIIMCR_RESTART_AUTONEGOTIATION |
\r
259 MIIMCR_COLLISION_TEST );
\r
263 /***************************************************************************//**
\r
264 * Restarts PHY auto-negotiation and wait until it's over.
\r
266 void PHY_auto_negotiate( void )
\r
272 reg = MDIO_read( PHYREG_MIIMCR );
\r
273 MDIO_write( PHYREG_MIIMCR,
\r
274 (uint16_t)( MIIMCR_ENABLE_AUTONEGOTIATION |
\r
275 MIIMCR_RESTART_AUTONEGOTIATION |
\r
278 for(a=0; (a<1000) && (exit); a++) {
\r
279 reg = MDIO_read( PHYREG_MIIMSR );
\r
280 if( (reg & MIIMSR_ANC) != 0 ) {
\r
287 /***************************************************************************//**
\r
288 * Returns link status.
\r
290 * @return #MAC_LINK_STATUS_LINK if link is up.
\r
292 uint8_t PHY_link_status( void )
\r
294 uint8_t retval = 0;
\r
295 if(( MDIO_read( PHYREG_MIIMSR ) & MIIMSR_LINK ) != 0 ){
\r
296 retval = MSS_MAC_LINK_STATUS_LINK;
\r
302 /***************************************************************************//**
\r
303 * Returns link type.
\r
305 * @return the logical OR of the following values:
\r
306 * #MAC_LINK_STATUS_100MB - Connection is 100Mb
\r
307 * #MAC_LINK_STATUS_FDX - Connection is full duplex
\r
309 uint8_t PHY_link_type( void )
\r
311 uint16_t diagnostic;
\r
314 diagnostic = MDIO_read( PHYREG_DR );
\r
316 if( (diagnostic & DR_DPLX) != 0 ) {
\r
317 type = MSS_MAC_LINK_STATUS_FDX;
\r
320 if( (diagnostic & DR_DATA_RATE) != 0 ) {
\r
321 type |= MSS_MAC_LINK_STATUS_100MB;
\r
328 /***************************************************************************//**
\r
339 reg = MDIO_read( PHYREG_ANAR );
\r
340 reg |= ANAR_100FD | ANAR_100HD | ANAR_10FD | ANAR_10HD;
\r
342 if( (type & MSS_MAC_LINK_STATUS_100MB) == 0 ) {
\r
343 reg &= ~(ANAR_100FD | ANAR_100HD);
\r
346 if( (type & MSS_MAC_LINK_STATUS_FDX) == 0 ) {
\r
347 reg &= ~(ANAR_100FD | ANAR_10FD);
\r
350 MDIO_write( PHYREG_ANAR, reg );
\r
354 /***************************************************************************//**
\r
355 * Puts the Phy in Loopback mode
\r
367 reg = MDIO_read( PHYREG_MIIMCR );
\r
368 // If set to one we need to set the LOCAL Phy loopback
\r
370 reg |= MIIMCR_LOOPBACK;
\r
371 else // else we want to clear the bit..
\r
372 reg ^= MIIMCR_LOOPBACK;
\r
375 MDIO_write( PHYREG_MIIMCR,reg );
\r
376 reg = MDIO_read( PHYREG_MIIMCR );
\r
386 /******************************** END OF FILE *********************************/
\r