Changeset 3a0c0f8 in rtems


Ignore:
Timestamp:
Oct 15, 2009, 4:02:12 PM (11 years ago)
Author:
Thomas Doerfler <Thomas.Doerfler@…>
Branches:
4.10, 4.11, 5, master
Children:
60c9ceb
Parents:
6504558
Message:

add PHY control support

Location:
c/src/lib/libbsp/m68k/genmcf548x
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/m68k/genmcf548x/ChangeLog

    r6504558 r3a0c0f8  
     12009-10-15      Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
     2
     3        * network/network.c: add PHY control support
     4
    152009-10-15      Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
    26
    37        * Makefile.am, include/bsp.h, network/network.c: add network support
    4         * console/console.c, clock/clock.c, startup/init548x.c:
     8        * console/console.c, clock/clock.c, startup/init548x.c,
     9        * README:
    510        various corrections
    611
  • c/src/lib/libbsp/m68k/genmcf548x/network/network.c

    r6504558 r3a0c0f8  
    5252#include <bsp.h>
    5353#include <mcf548x/mcf548x.h>
     54#include <rtems/rtems_mii_ioctl.h>
    5455#include <errno.h>
    5556
     
    6566#define NIFACES 2
    6667
     68#define FEC_WATCHDOG_TIMEOUT 5 /* check media every 5 seconds */
    6769/*
    6870 * buffer descriptor handling
     
    107109
    108110
    109 #define ETH_DEBUG
     111#undef ETH_DEBUG
    110112
    111113/*
     
    217219  rtems_id                txDaemonTid;
    218220 
     221  /*
     222   * MDIO/Phy info
     223   */
     224  struct rtems_mdio_info mdio_info;
     225  int phy_default;
     226  int phy_chan;    /* which fec channel services this phy access? */
     227  int media_state; /* (last detected) state of media */
     228
    219229  unsigned long           rxInterrupts;
    220230  unsigned long           rxNotLast;
     
    409419 *                              documentation for the register map.
    410420 *
    411  * Returns:             32-bit register value
     421 * Returns:             0 if ok
    412422 *
    413423 * Notes:
    414424 *
    415425 */
    416 int mcf548x_eth_mii_read(struct mcf548x_enet_struct *sc, unsigned char phyAddr, unsigned char regAddr, unsigned short * retVal)
    417   {
     426int mcf548x_eth_mii_read(
     427 int phyAddr,                          /* PHY number to access or -1       */
     428 void *uarg,                           /* unit argument                    */
     429 unsigned regAddr,                     /* register address                 */
     430 uint32_t *retVal)                     /* ptr to read buffer               */
     431{
     432  struct mcf548x_enet_struct *sc = uarg;
    418433  int timeout = 0xffff;
    419   int chan = sc->chan;
     434  int chan = sc->phy_chan;
    420435
    421436 /*
     
    434449  while ((timeout--) && (!(MCF548X_FEC_EIR(chan) & MCF548X_FEC_EIR_MII)));
    435450
    436   if(timeout == 0)
    437     {
     451  if(timeout == 0) {
    438452
    439453#ifdef ETH_DEBUG
    440     printf ("Read MDIO failed..." "\r\n");
     454    iprintf ("Read MDIO failed..." "\r\n");
    441455#endif
    442456
    443         return false;
    444 
    445         }
     457    return 1;
     458
     459  }
    446460
    447461 /*
     
    455469  *retVal = (unsigned short)  MCF548X_FEC_MMFR(chan);
    456470
    457   return true;
    458 
    459   }
     471  return 0;
     472
     473}
    460474
    461475/*
     
    471485 *
    472486 */
    473 static int mcf548x_eth_mii_write(struct mcf548x_enet_struct *sc, unsigned char phyAddr, unsigned char regAddr, unsigned short data)
    474   {
    475   int chan     = sc->chan;
    476   int timeout = 0xffff;
     487static int mcf548x_eth_mii_write(
     488 int phyAddr,                          /* PHY number to access or -1       */
     489 void *uarg,                           /* unit argument                    */
     490 unsigned regAddr,                     /* register address                 */
     491 uint32_t data)                        /* write data                       */
     492{
     493  struct mcf548x_enet_struct *sc = uarg;
     494  int chan     = sc->phy_chan;
     495  int timeout  = 0xffff;
    477496
    478497  MCF548X_FEC_MMFR(chan) = (MCF548X_FEC_MMFR_ST_01    |
     
    492511
    493512#ifdef ETH_DEBUG
    494     printf ("Write MDIO failed..." "\r\n");
     513    iprintf ("Write MDIO failed..." "\r\n");
    495514#endif
    496515
    497     return false;
     516    return 1;
    498517
    499518    }
     
    504523  MCF548X_FEC_EIR(chan) = MCF548X_FEC_EIR_MII;
    505524
    506   return true;
     525  return 0;
    507526
    508527  }
     
    570589
    571590#if defined(ETH_DEBUG)
    572   unsigned short phyStatus, i;
    573   unsigned char  phyAddr = 0;
     591  uint32_t phyStatus;
     592  int i;
    574593
    575594  for(i = 0; i < 9; i++)
    576595    {
    577596
    578     mcf548x_eth_mii_read(sc, phyAddr, i, &phyStatus);
    579     printf ("Mii reg %d: 0x%04x" "\r\n", i, phyStatus);
     597    mcf548x_eth_mii_read(sc->phy_default, sc, i, &phyStatus);
     598    iprintf ("Mii reg %d: 0x%04lx" "\r\n", i, phyStatus);
    580599
    581600    }
     
    584603    {
    585604
    586     mcf548x_eth_mii_read(sc, phyAddr, i, &phyStatus);
    587     printf ("Mii reg %d: 0x%04x" "\r\n", i, phyStatus);
     605    mcf548x_eth_mii_read(sc->phy_default, sc, i, &phyStatus);
     606    iprintf ("Mii reg %d: 0x%04lx" "\r\n", i, phyStatus);
     607
     608    }
     609  for(i = 0; i < 32; i++)
     610    {
     611
     612    mcf548x_eth_mii_read(i, sc, 0, &phyStatus);
     613    iprintf ("Mii Phy=%d, reg 0: 0x%04lx" "\r\n", i, phyStatus);
    588614
    589615    }
     
    747773}
    748774
    749 #if 0
    750  /*
    751   * Function:        mcf548x_fec_tx_bd_requeue
    752   *
    753   * Description:        put buffers back to interface output queue
    754   *
    755   * Returns:            void
    756   *
    757   * Notes:
    758   *
    759   */
    760 static void mcf548x_fec_tx_bd_requeue(struct mcf548x_enet_struct *sc)
    761 {
    762   /*
    763    * Clear already transmitted BDs first. Will not work calling same
    764    * from fecExceptionHandler(TFINT).
    765    */
    766  
    767   while (sc->txBdActiveCount > 0) {
    768     if (sc->txMbuf[sc->txBdHead] != NULL) {
    769       /*
    770        * NOTE: txMbuf can be NULL, if mbuf has been split into different BDs
    771        */
    772       IF_PREPEND(&(sc->arpcom.ac_if.if_snd),sc->txMbuf[sc->txBdHead]);
    773       sc->txMbuf[sc->txBdHead] = NULL;
    774     }
    775     sc->txBdActiveCount--;
    776     if(--sc->txBdHead < 0) {
    777       sc->txBdHead = sc->txBdCount-1;
    778     }   
    779   }
    780 }
    781 #endif
    782775
    783776static void mcf548x_fec_sendpacket(struct ifnet *ifp,struct mbuf *m) {
     
    11651158  }
    11661159
    1167  /*
    1168   * Initialize PHY(LXT971A):
    1169   *
    1170   *   Generally, on power up, the LXT971A reads its configuration
    1171   *   pins to check for forced operation, If not cofigured for
    1172   *   forced operation, it uses auto-negotiation/parallel detection
    1173   *   to automatically determine line operating conditions.
    1174   *   If the PHY device on the other side of the link supports
    1175   *   auto-negotiation, the LXT971A auto-negotiates with it
    1176   *   using Fast Link Pulse(FLP) Bursts. If the PHY partner does not
    1177   *   support auto-negotiation, the LXT971A automatically detects
    1178   *   the presence of either link pulses(10Mbps PHY) or Idle
    1179   *   symbols(100Mbps) and sets its operating conditions accordingly.
    1180   *
    1181   *   When auto-negotiation is controlled by software, the following
    1182   *   steps are recommended.
    1183   *
    1184   * Note:
    1185   *   The physical address is dependent on hardware configuration.
    1186   *
    1187   * Returns:            void
    1188   *
    1189   * Notes:
    1190   *
    1191   */
    1192 static void mcf548x_fec_initialize_phy(struct mcf548x_enet_struct *sc)
    1193   {
    1194   int            timeout;
    1195   unsigned short phyAddr = 0;
    1196   int chan = sc->chan;
    1197 
    1198  /*
    1199   * Reset PHY, then delay 300ns
    1200   */
    1201   mcf548x_eth_mii_write(sc, phyAddr, 0x0, 0x8000);
    1202 
    1203   rtems_task_wake_after(2);
    1204 
    1205  /* MII100 */
    1206 
    1207  /*
    1208   * Set the auto-negotiation advertisement register bits
    1209   */
    1210   mcf548x_eth_mii_write(sc, phyAddr, 0x4, 0x01e1);
    1211 
    1212  /*
    1213   * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
    1214   */
    1215   mcf548x_eth_mii_write(sc, phyAddr, 0x0, 0x1200);
    1216 
    1217  /*
    1218   * Wait for AN completion
    1219   */
    1220   timeout = 0x100;
    1221 #if 0
    1222   do
    1223     {
    1224 
    1225     rtems_task_wake_after(2);
    1226 
    1227     if((timeout--) == 0)
    1228       {
    1229 
    1230 #if defined(ETH_DEBUG)
    1231     printf ("MCF548XFEC PHY auto neg failed." "\r\n");
    1232 #endif
    1233 
    1234       }
    1235 
    1236     if(mcf548x_eth_mii_read(sc, phyAddr, 0x1, &phyStatus) != true)
    1237       {
    1238 
    1239 #if defined(ETH_DEBUG)
    1240       printf ("MCF548XFEC PHY auto neg failed: 0x%04x." "\r\n", phyStatus);
    1241 #endif
    1242 
    1243           return;
    1244 
    1245           }
    1246 
    1247     } while((phyStatus & 0x0020) != 0x0020);
    1248 
    1249 #endif
    1250 #if ETH_PROMISCOUS_MODE
    1251   MCF548X_FEC_RCR(chan) |= MCF548X_FEC_RCR_PROM;   /* set to promiscous mode */
    1252 #endif
    1253 
    1254 #if ETH_LOOP_MODE
    1255   MCF548X_FEC_RCR(chan) |= MCF548X_FEC_RCR_LOOP;   /* set to loopback mode */
    1256 #endif
    1257 
    1258 #if defined(ETH_DEBUG)
    1259   int i;
    1260   unsigned short phyStatus;
    1261  /*
    1262   * Print PHY registers after initialization.
    1263   */
    1264   for(i = 0; i < 9; i++)
    1265     {
    1266 
    1267         mcf548x_eth_mii_read(sc, phyAddr, i, &phyStatus);
    1268         printf ("Mii reg %d: 0x%04x" "\r\n", i, phyStatus);
    1269 
    1270         }
    1271 
    1272   for(i = 16; i < 21; i++)
    1273     {
    1274 
    1275     mcf548x_eth_mii_read(sc, phyAddr, i, &phyStatus);
    1276     printf ("Mii reg %d: 0x%04x" "\r\n", i, phyStatus);
    1277 
    1278     }
    1279 #endif  /* ETH_DEBUG */
    1280 
    1281   }
    1282 
    12831160
    12841161/*
     
    13131190         (void *)&MCF548X_FEC_FECRFDR(chan), /* the address to move data to */
    13141191         0,             /* the amount to increment the destination address per transfer */
    1315 #if 0
    1316          4, /* the number of bytes to transfer independent of the transfer size */
    1317 #else
    13181192         ETHER_MAX_LEN, /* the number of bytes to transfer independent of the transfer size */
    1319 #endif
    13201193         0,             /* the number bytes in of each data movement (1, 2, or 4) */
    13211194         MCF548X_FEC_RX_INITIATOR(chan), /* what device initiates the DMA */
     
    13411214         (void *)&MCF548X_FEC_FECTFDR(chan), /* the address to move data to */
    13421215         0,             /* the amount to increment the destination address per transfer */
    1343 #if 0
    1344          4, /* the number of bytes to transfer independent of the transfer size */
    1345 #else
    13461216         ETHER_MAX_LEN, /* the number of bytes to transfer independent of the transfer size */
    1347 #endif
    13481217         0,             /* the number bytes in of each data movement (1, 2, or 4) */
    13491218         MCF548X_FEC_TX_INITIATOR(chan), /* what device initiates the DMA */
     
    14341303       */
    14351304      mcf548x_fec_initialize_hardware(sc);
    1436       /*
    1437        * Set up the phy
    1438        */
    1439       mcf548x_fec_initialize_phy(sc);
    14401305
    14411306      /*
     
    14741339    MCF548X_FEC_RCR(chan) &= ~MCF548X_FEC_RCR_PROM;
    14751340
     1341  /*
     1342   * init timer so the "watchdog function gets called periodically
     1343   */
     1344  ifp->if_timer    = 1;
    14761345  /*
    14771346   * Tell the world that we're running.
     
    15441413   * FIXME: try to extract pending Tx buffers
    15451414   */
    1546 #if 0
    1547   mcf548x_fec_tx_bd_requeue(sc);
    1548 #else
    15491415  mcf548x_fec_retire_tbd(sc,true);
    1550 #endif
    15511416#endif
    15521417  /*
     
    16081473  switch(command)
    16091474    {
     1475
     1476    case SIOCGIFMEDIA:
     1477    case SIOCSIFMEDIA:
     1478      rtems_mii_ioctl (&(sc->mdio_info),sc,command,(void *)data);
     1479      break;
    16101480
    16111481    case SIOCGIFADDR:
     
    16861556
    16871557/*
     1558 * init the PHY and adapt FEC settings
     1559 */
     1560int mcf548x_fec_mode_adapt(struct ifnet *ifp)
     1561{
     1562  int result = 0;
     1563  struct mcf548x_enet_struct *sc = ifp->if_softc;
     1564  int media = IFM_MAKEWORD( 0, 0, 0, sc->phy_default);
     1565  int chan = sc->chan;
     1566
     1567  /*
     1568   * fetch media status
     1569   */
     1570  result = mcf548x_fec_ioctl(ifp,SIOCGIFMEDIA,(caddr_t)&media);
     1571  if (result != 0) {
     1572    return result;
     1573  }
     1574  /*
     1575   * status is unchanged? then do nothing
     1576   */
     1577  if (media == sc->media_state) {
     1578    return 0;
     1579  }
     1580  /*
     1581   * otherwise: for the first call, try to negotiate mode
     1582   */
     1583  if (sc->media_state == 0) {
     1584    /*
     1585     * set media status: set auto negotiation -> start auto-negotiation
     1586     */
     1587    media = IFM_MAKEWORD(0,IFM_AUTO,0,sc->phy_default);
     1588    result = mcf548x_fec_ioctl(ifp,SIOCSIFMEDIA,(caddr_t)&media);
     1589    if (result != 0) {
     1590      return result;
     1591    }
     1592    /*
     1593     * wait for auto-negotiation to terminate
     1594     */
     1595    do {
     1596      media = IFM_MAKEWORD(0,0,0,sc->phy_default);
     1597      result = mcf548x_fec_ioctl(ifp,SIOCGIFMEDIA,(caddr_t)&media);
     1598      if (result != 0) {
     1599        return result;
     1600      }
     1601    } while (IFM_NONE == IFM_SUBTYPE(media));
     1602  }
     1603
     1604  /*
     1605   * now set HW according to media results:
     1606   */
     1607
     1608  /*
     1609   * if we are half duplex then switch to half duplex
     1610   */
     1611  if (0 == (IFM_FDX & IFM_OPTIONS(media))) {
     1612    MCF548X_FEC_TCR(chan) &= ~MCF548X_FEC_TCR_FDEN;
     1613  }
     1614  else {
     1615    MCF548X_FEC_TCR(chan) |=  MCF548X_FEC_TCR_FDEN;
     1616  }   
     1617  /*
     1618   * store current media state for future compares
     1619   */
     1620  sc->media_state = media;
     1621
     1622  return 0;
     1623}
     1624
     1625/*
     1626 * periodically poll the PHY. if mode has changed,
     1627 * then adjust the FEC settings
     1628 */
     1629static void mcf548x_fec_watchdog( struct ifnet *ifp)
     1630{
     1631  mcf548x_fec_mode_adapt(ifp);
     1632  ifp->if_timer    = FEC_WATCHDOG_TIMEOUT;
     1633}
     1634
     1635/*
    16881636 * Attach the MCF548X fec driver to the system
    16891637 */
     
    18291777  sc->acceptBroadcast = !config->ignore_broadcast;
    18301778
     1779  /*
     1780   * setup info about mdio interface
     1781   */
     1782  sc->mdio_info.mdio_r   = mcf548x_eth_mii_read;
     1783  sc->mdio_info.mdio_w   = mcf548x_eth_mii_write;
     1784  sc->mdio_info.has_gmii = 0; /* we do not support gigabit IF */
     1785
     1786  /*
     1787   * XXX: Although most hardware builders will assign the PHY addresses
     1788   * like this, this should be more configurable
     1789   */
     1790  sc->phy_default = unitNumber-1;
     1791  sc->phy_chan    = 0; /* assume all MII accesses are via FEC0 */
     1792
    18311793 /*
    18321794  * Set up network interface values
     
    18401802  ifp->if_start   = mcf548x_fec_tx_start;
    18411803  ifp->if_output  = ether_output;
     1804  ifp->if_watchdog =  mcf548x_fec_watchdog; /* XXX: timer is set in "init" */
    18421805  ifp->if_flags   = IFF_BROADCAST | IFF_MULTICAST;
    18431806  /*ifp->if_flags   = IFF_BROADCAST | IFF_SIMPLEX;*/
Note: See TracChangeset for help on using the changeset viewer.