Changeset d101ed8 in rtems-libbsd


Ignore:
Timestamp:
Sep 14, 2018, 7:43:12 AM (9 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
eeb3fd5d9b07ac9a2e280cff60a1b762bd273a8d, 1e989998de954bef51e6c19cc3d64d39f32100aa
Children:
1b70957
Parents:
457b4fc
git-author:
Sebastian Huber <sebastian.huber@…> (09/14/18 07:43:12)
git-committer:
Sebastian Huber <sebastian.huber@…> (09/21/18 08:29:43)
Message:

if_ffec_mpc8xx: New MDIO driver support

Update #3523.

Location:
rtemsbsd
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • rtemsbsd/include/bsp/nexus-devices.h

    r457b4fc rd101ed8  
    179179
    180180RTEMS_BSD_DEFINE_NEXUS_DEVICE(fec, 0, 0, NULL);
     181SYSINIT_DRIVER_REFERENCE(ukphy, miibus);
    181182
    182183#endif
  • rtemsbsd/sys/dev/ffec/if_ffec_mpc8xx.c

    r457b4fc rd101ed8  
    7777#include <net/if_var.h>
    7878
     79#include <machine/bus.h>
     80
     81#include <dev/mii/mii.h>
     82#include <dev/mii/miivar.h>
     83
     84#include <rtems/bsd/local/miibus_if.h>
     85
    7986#include <bsp/irq.h>
    80 #include <rtems/rtems_mii_ioctl.h>
    8187#include <rtems/bsd/bsd.h>
    82 #include <errno.h>
    8388
    8489/* FIXME */
     
    143148  int                     txBdActiveCount;
    144149  struct callout          watchdogCallout;
     150  device_t                miibus;
     151  struct mii_data         *mii_softc;
    145152  m8xxBufferDescriptor_t  *rxBdBase;
    146153  m8xxBufferDescriptor_t  *txBdBase;
     
    152159   * MDIO/Phy info
    153160   */
    154   struct rtems_mdio_info mdio_info;
    155161  int phy_default;
    156   int media_state; /* (last detected) state of media */
    157162  /*
    158163   * Statistics
     
    178183};
    179184
    180 int fec_mode_adapt (struct ifnet *ifp);
    181 
    182185#define FEC_LOCK(sc) mtx_lock(&(sc)->mtx)
    183186
     
    202205}
    203206
    204 /* declare ioctl function for internal use */
    205 static int fec_ioctl (struct ifnet *ifp,
    206                       ioctl_command_t command, caddr_t data);
    207207/***************************************************************************\
    208208|  MII Management access functions                                          |
     
    232232   * set clock divider
    233233   */
    234   m8xx.fec.mii_speed = BSP_bus_frequency / 25000000 / 2 + 1;
    235 }
    236 
    237 /*=========================================================================*\
    238 | Function:                                                                 |
    239 \*-------------------------------------------------------------------------*/
    240 int fec_mdio_read
    241 (
    242 /*-------------------------------------------------------------------------*\
    243 | Purpose:                                                                  |
    244 |   read register of a phy                                                  |
    245 +---------------------------------------------------------------------------+
    246 | Input Parameters:                                                         |
    247 \*-------------------------------------------------------------------------*/
    248  int phy,                              /* PHY number to access or -1       */
    249  void *uarg,                           /* unit argument                    */
    250  unsigned reg,                         /* register address                 */
    251  uint32_t *pval                        /* ptr to read buffer               */
    252  )
    253 /*-------------------------------------------------------------------------*\
    254 | Return Value:                                                             |
    255 |    0, if ok, else error                                                   |
    256 \*=========================================================================*/
    257 {
    258   struct m8xx_fec_enet_struct *sc = uarg;/* control structure            */
     234  m8xx.fec.mii_speed = BSP_bus_frequency / 1250000 / 2 + 1;
     235}
     236
     237static int
     238fec_miibus_read_reg(device_t dev, int phy, int reg)
     239{
     240  struct m8xx_fec_enet_struct *sc;
     241
     242  sc = device_get_softc(dev);
    259243
    260244  /*
     
    271255     * invalid phy number
    272256     */
    273     return EINVAL;
     257    return 0;
    274258  }
    275259  /*
     
    284268                       M8xx_FEC_MII_DATA_PHYAD(phy) |
    285269                       M8xx_FEC_MII_DATA_PHYRA(reg) |
     270                       M8xx_FEC_MII_DATA_TA |
    286271                       M8xx_FEC_MII_DATA_WDATA(0));
    287272
     
    296281   * fetch read data, if available
    297282   */
    298   if (pval != NULL) {
    299     *pval = M8xx_FEC_MII_DATA_RDATA(m8xx.fec.mii_data);
    300   }
    301   return 0;
    302 }
    303 
    304 /*=========================================================================*\
    305 | Function:                                                                 |
    306 \*-------------------------------------------------------------------------*/
    307 int fec_mdio_write
    308 (
    309 /*-------------------------------------------------------------------------*\
    310 | Purpose:                                                                  |
    311 |   write register of a phy                                                 |
    312 +---------------------------------------------------------------------------+
    313 | Input Parameters:                                                         |
    314 \*-------------------------------------------------------------------------*/
    315  int phy,                              /* PHY number to access or -1       */
    316  void *uarg,                           /* unit argument                    */
    317  unsigned reg,                         /* register address                 */
    318  uint32_t val                          /* write value                      */
    319  )
    320 /*-------------------------------------------------------------------------*\
    321 | Return Value:                                                             |
    322 |    0, if ok, else error                                                   |
    323 \*=========================================================================*/
    324 {
    325   struct m8xx_fec_enet_struct *sc = uarg;/* control structure            */
     283  return M8xx_FEC_MII_DATA_RDATA(m8xx.fec.mii_data);
     284}
     285
     286static int
     287fec_miibus_write_reg(device_t dev, int phy, int reg, int val)
     288{
     289  struct m8xx_fec_enet_struct *sc;
     290
     291  sc = device_get_softc(dev);
    326292
    327293  /*
     
    351317                       M8xx_FEC_MII_DATA_PHYAD(phy) |
    352318                       M8xx_FEC_MII_DATA_PHYRA(reg) |
     319                       M8xx_FEC_MII_DATA_TA |
    353320                       M8xx_FEC_MII_DATA_WDATA(val));
    354321
     
    516483  sc->txBdHead = sc->txBdTail = 0;
    517484  sc->txBdActiveCount = 0;
     485
     486  /* Set pin multiplexing */
     487  m8xx.fec.ecntrl = M8xx_FEC_ECNTRL_FEC_PINMUX;
    518488
    519489  /*
     
    880850  struct m8xx_fec_enet_struct *sc = arg;
    881851
    882   fec_mode_adapt(sc->ifp);
     852  mii_tick(sc->mii_softc);
    883853  callout_reset(&sc->watchdogCallout, FEC_WATCHDOG_TIMEOUT * hz,
    884854                fec_watchdog, sc);
    885855}
    886856
     857static int
     858fec_media_change(struct ifnet * ifp)
     859{
     860        struct m8xx_fec_enet_struct *sc;
     861        struct mii_data *mii;
     862        int error;
     863
     864        sc = ifp->if_softc;
     865        mii = sc->mii_softc;
     866
     867        if (mii != NULL) {
     868                FEC_LOCK(sc);
     869                error = mii_mediachg(sc->mii_softc);
     870                FEC_UNLOCK(sc);
     871        } else {
     872                error = ENXIO;
     873        }
     874
     875        return (error);
     876}
     877
     878static void
     879fec_media_status(struct ifnet * ifp, struct ifmediareq *ifmr)
     880{
     881        struct m8xx_fec_enet_struct *sc;
     882        struct mii_data *mii;
     883
     884        sc = ifp->if_softc;
     885        mii = sc->mii_softc;
     886
     887        if (mii != NULL) {
     888                FEC_LOCK(sc);
     889                mii_pollstat(mii);
     890                ifmr->ifm_active = mii->mii_media_active;
     891                ifmr->ifm_status = mii->mii_media_status;
     892                FEC_UNLOCK(sc);
     893        }
     894}
     895
    887896static void fec_init (void *arg)
    888897{
     
    891900
    892901  if (sc->txDaemonTid == 0) {
     902    int error;
    893903
    894904    /*
     
    908918    sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, fec_rxDaemon, sc);
    909919
     920    /* Attach the mii driver. */
     921    error = mii_attach(sc->dev, &sc->miibus, ifp, fec_media_change,
     922                       fec_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY,
     923                       MII_OFFSET_ANY, 0);
     924    if (error == 0) {
     925      sc->mii_softc = device_get_softc(sc->miibus);
     926    }
    910927  }
    911928
     
    918935    m8xx.fec.r_cntrl &= ~M8xx_FEC_R_CNTRL_PROM;
    919936
    920   /*
    921    * init timer so the "watchdog function gets called periodically
    922    */
    923   callout_reset(&sc->watchdogCallout, hz, fec_watchdog, sc);
     937  if (sc->mii_softc != NULL ) {
     938    /*
     939     * init timer so the "watchdog function gets called periodically
     940     */
     941    mii_mediachg(sc->mii_softc);
     942    callout_reset(&sc->watchdogCallout, hz, fec_watchdog, sc);
     943  }
    924944
    925945  /*
     
    931951   * Enable receiver and transmitter
    932952   */
    933   m8xx.fec.ecntrl = M8xx_FEC_ECNTRL_ETHER_EN | M8xx_FEC_ECNTRL_FEC_PINMUX;
     953  m8xx.fec.ecntrl |= M8xx_FEC_ECNTRL_ETHER_EN;
    934954}
    935955
     
    955975   * Shut down receiver and transmitter
    956976   */
    957   m8xx.fec.ecntrl = 0x0;
     977  m8xx.fec.ecntrl &= ~M8xx_FEC_ECNTRL_ETHER_EN;
    958978}
    959979
     
    9831003}
    9841004
    985 static int fec_ioctl (struct ifnet *ifp,
    986                       ioctl_command_t command, caddr_t data)
    987 {
    988   struct m8xx_fec_enet_struct *sc = ifp->if_softc;
    989   int error = 0;
    990 
    991   switch (command) {
    992     /*
    993      * access PHY via MII
    994      */
    995   case SIOCGIFMEDIA:
    996   case SIOCSIFMEDIA:
    997     rtems_mii_ioctl (&(sc->mdio_info),sc,command,(void *)data);
    998     break;
    999 
     1005static int fec_ioctl (struct ifnet *ifp, ioctl_command_t cmd, caddr_t data)
     1006{
     1007  struct m8xx_fec_enet_struct *sc;
     1008  struct ifreq *ifr;
     1009  int error;
     1010  struct mii_data *mii;
     1011
     1012  sc = ifp->if_softc;
     1013  ifr = (struct ifreq *)data;
     1014
     1015  error = 0;
     1016  switch (cmd) {
    10001017  case SIOCSIFFLAGS:
    10011018    FEC_LOCK(sc);
     
    10121029    break;
    10131030
     1031  case SIOCSIFMEDIA:
     1032  case SIOCGIFMEDIA:
     1033    mii = sc->mii_softc;
     1034
     1035    if (mii != NULL) {
     1036      error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
     1037    } else {
     1038      error = ether_ioctl(ifp, cmd, data);
     1039    }
     1040
     1041    break;
     1042
    10141043  case SIO_RTEMS_SHOW_STATS:
    10151044    fec_enet_stats (sc);
     
    10201049     */
    10211050  default:
    1022     error = ether_ioctl(ifp, command, data);
     1051    error = ether_ioctl(ifp, cmd, data);
    10231052    break;
    10241053  }
     
    10261055}
    10271056
    1028 /*=========================================================================*\
    1029 | Function:                                                                 |
    1030 \*-------------------------------------------------------------------------*/
    1031 int fec_mode_adapt
    1032 (
    1033 /*-------------------------------------------------------------------------*\
    1034 | Purpose:                                                                  |
    1035 |   init the PHY and adapt FEC settings                                     |
    1036 +---------------------------------------------------------------------------+
    1037 | Input Parameters:                                                         |
    1038 \*-------------------------------------------------------------------------*/
    1039  struct ifnet *ifp
    1040 )
    1041 /*-------------------------------------------------------------------------*\
    1042 | Return Value:                                                             |
    1043 |    0, if success                                                          |
    1044 \*=========================================================================*/
    1045 {
    1046   int result = 0;
    1047   struct m8xx_fec_enet_struct *sc = ifp->if_softc;
    1048   int media = IFM_MAKEWORD( 0, 0, 0, sc->phy_default);
    1049 
    1050 #ifdef DEBUG
    1051   printf("c");
    1052 #endif
    1053   /*
    1054    * fetch media status
    1055    */
    1056   result = fec_ioctl(ifp,SIOCGIFMEDIA,(caddr_t)&media);
    1057   if (result != 0) {
    1058     return result;
    1059   }
    1060 #ifdef DEBUG
    1061   printf("C");
    1062 #endif
    1063   /*
    1064    * status is unchanged? then do nothing
    1065    */
    1066   if (media == sc->media_state) {
    1067     return 0;
    1068   }
    1069   /*
    1070    * otherwise: for the first call, try to negotiate mode
    1071    */
    1072   if (sc->media_state == 0) {
    1073     /*
    1074      * set media status: set auto negotiation -> start auto-negotiation
    1075      */
    1076     media = IFM_MAKEWORD(0,IFM_AUTO,0,sc->phy_default);
    1077     result = fec_ioctl(ifp,SIOCSIFMEDIA,(caddr_t)&media);
    1078     if (result != 0) {
    1079       return result;
    1080     }
    1081     /*
    1082      * wait for auto-negotiation to terminate
    1083      */
    1084     do {
    1085       media = IFM_MAKEWORD(0,0,0,sc->phy_default);
    1086       result = fec_ioctl(ifp,SIOCGIFMEDIA,(caddr_t)&media);
    1087       if (result != 0) {
    1088         return result;
    1089       }
    1090     } while (IFM_NONE == IFM_SUBTYPE(media));
    1091   }
    1092 
    1093   /*
    1094    * now set HW according to media results:
    1095    */
    1096   /*
    1097    * if we are half duplex then switch to half duplex
    1098    */
    1099   if (0 == (IFM_FDX & IFM_OPTIONS(media))) {
    1100     m8xx.fec.x_cntrl &= ~M8xx_FEC_X_CNTRL_FDEN;
    1101     m8xx.fec.r_cntrl |=  M8xx_FEC_R_CNTRL_DRT;
    1102   }
    1103   else {
    1104     m8xx.fec.x_cntrl |=  M8xx_FEC_X_CNTRL_FDEN;
    1105     m8xx.fec.r_cntrl &= ~M8xx_FEC_R_CNTRL_DRT;
    1106   }
    1107   /*
    1108    * store current media state for future compares
    1109    */
    1110   sc->media_state = media;
    1111 
    1112   return 0;
     1057static void
     1058fec_miibus_statchg(device_t dev)
     1059{
     1060        struct m8xx_fec_enet_struct *sc;
     1061        struct mii_data *mii;
     1062
     1063        sc = device_get_softc(dev);
     1064        mii = sc->mii_softc;
     1065
     1066        if (mii == NULL ||
     1067            (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
     1068                m8xx.fec.x_cntrl |=  M8xx_FEC_X_CNTRL_FDEN;
     1069                m8xx.fec.r_cntrl &= ~M8xx_FEC_R_CNTRL_DRT;
     1070        } else {
     1071                m8xx.fec.x_cntrl &= ~M8xx_FEC_X_CNTRL_FDEN;
     1072                m8xx.fec.r_cntrl |=  M8xx_FEC_R_CNTRL_DRT;
     1073        }
    11131074}
    11141075
     
    11201081  uint8_t hwaddr[ETHER_ADDR_LEN];
    11211082
    1122   /*
    1123    * enable FEC functionality at hardware pins*
    1124    * PD[3-15] are FEC pins
    1125    */
    1126   m8xx.pdpar |= 0x1fff;
    1127   m8xx.pddir |= 0x1fff;
    1128 
    11291083  rtems_bsd_get_mac_address(device_get_name(dev), device_get_unit(dev),
    11301084                            hwaddr);
     
    11401094  sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
    11411095
    1142   /*
    1143    * setup info about mdio interface
    1144    */
    1145   sc->mdio_info.mdio_r   = fec_mdio_read;
    1146   sc->mdio_info.mdio_w   = fec_mdio_write;
    1147   sc->mdio_info.has_gmii = 0; /* we do not support gigabit IF */
    11481096  /*
    11491097   * assume: IF 1 -> PHY 0
     
    11911139        DEVMETHOD(device_attach,        fec_attach),
    11921140
     1141        /* MII Interface */
     1142        DEVMETHOD(miibus_readreg,       fec_miibus_read_reg),
     1143        DEVMETHOD(miibus_writereg,      fec_miibus_write_reg),
     1144        DEVMETHOD(miibus_statchg,       fec_miibus_statchg),
     1145
    11931146        DEVMETHOD_END
    11941147};
     
    12011154
    12021155static devclass_t fec_devclass;
     1156
    12031157DRIVER_MODULE(fec, nexus, fec_nexus_driver, fec_devclass, 0, 0);
     1158DRIVER_MODULE(miibus, fec, miibus_driver, miibus_devclass, 0, 0);
     1159
    12041160MODULE_DEPEND(fec, nexus, 1, 1, 1);
    12051161MODULE_DEPEND(fec, ether, 1, 1, 1);
Note: See TracChangeset for help on using the changeset viewer.