root/drivers/net/usb/ax88172a.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. asix_mdio_bus_read
  2. asix_mdio_bus_write
  3. ax88172a_ioctl
  4. ax88172a_adjust_link
  5. ax88172a_status
  6. ax88172a_init_mdio
  7. ax88172a_remove_mdio
  8. ax88172a_reset_phy
  9. ax88172a_bind
  10. ax88172a_stop
  11. ax88172a_unbind
  12. ax88172a_reset
  13. ax88172a_rx_fixup

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * ASIX AX88172A based USB 2.0 Ethernet Devices
   4  * Copyright (C) 2012 OMICRON electronics GmbH
   5  *
   6  * Supports external PHYs via phylib. Based on the driver for the
   7  * AX88772. Original copyrights follow:
   8  *
   9  * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
  10  * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
  11  * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
  12  * Copyright (c) 2002-2003 TiVo Inc.
  13  */
  14 
  15 #include "asix.h"
  16 #include <linux/phy.h>
  17 
  18 struct ax88172a_private {
  19         struct mii_bus *mdio;
  20         struct phy_device *phydev;
  21         char phy_name[20];
  22         u16 phy_addr;
  23         u16 oldmode;
  24         int use_embdphy;
  25         struct asix_rx_fixup_info rx_fixup_info;
  26 };
  27 
  28 /* MDIO read and write wrappers for phylib */
  29 static int asix_mdio_bus_read(struct mii_bus *bus, int phy_id, int regnum)
  30 {
  31         return asix_mdio_read(((struct usbnet *)bus->priv)->net, phy_id,
  32                               regnum);
  33 }
  34 
  35 static int asix_mdio_bus_write(struct mii_bus *bus, int phy_id, int regnum,
  36                                u16 val)
  37 {
  38         asix_mdio_write(((struct usbnet *)bus->priv)->net, phy_id, regnum, val);
  39         return 0;
  40 }
  41 
  42 static int ax88172a_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
  43 {
  44         if (!netif_running(net))
  45                 return -EINVAL;
  46 
  47         if (!net->phydev)
  48                 return -ENODEV;
  49 
  50         return phy_mii_ioctl(net->phydev, rq, cmd);
  51 }
  52 
  53 /* set MAC link settings according to information from phylib */
  54 static void ax88172a_adjust_link(struct net_device *netdev)
  55 {
  56         struct phy_device *phydev = netdev->phydev;
  57         struct usbnet *dev = netdev_priv(netdev);
  58         struct ax88172a_private *priv = dev->driver_priv;
  59         u16 mode = 0;
  60 
  61         if (phydev->link) {
  62                 mode = AX88772_MEDIUM_DEFAULT;
  63 
  64                 if (phydev->duplex == DUPLEX_HALF)
  65                         mode &= ~AX_MEDIUM_FD;
  66 
  67                 if (phydev->speed != SPEED_100)
  68                         mode &= ~AX_MEDIUM_PS;
  69         }
  70 
  71         if (mode != priv->oldmode) {
  72                 asix_write_medium_mode(dev, mode, 0);
  73                 priv->oldmode = mode;
  74                 netdev_dbg(netdev, "speed %u duplex %d, setting mode to 0x%04x\n",
  75                            phydev->speed, phydev->duplex, mode);
  76                 phy_print_status(phydev);
  77         }
  78 }
  79 
  80 static void ax88172a_status(struct usbnet *dev, struct urb *urb)
  81 {
  82         /* link changes are detected by polling the phy */
  83 }
  84 
  85 /* use phylib infrastructure */
  86 static int ax88172a_init_mdio(struct usbnet *dev)
  87 {
  88         struct ax88172a_private *priv = dev->driver_priv;
  89         int ret;
  90 
  91         priv->mdio = mdiobus_alloc();
  92         if (!priv->mdio) {
  93                 netdev_err(dev->net, "Could not allocate MDIO bus\n");
  94                 return -ENOMEM;
  95         }
  96 
  97         priv->mdio->priv = (void *)dev;
  98         priv->mdio->read = &asix_mdio_bus_read;
  99         priv->mdio->write = &asix_mdio_bus_write;
 100         priv->mdio->name = "Asix MDIO Bus";
 101         /* mii bus name is usb-<usb bus number>-<usb device number> */
 102         snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
 103                  dev->udev->bus->busnum, dev->udev->devnum);
 104 
 105         ret = mdiobus_register(priv->mdio);
 106         if (ret) {
 107                 netdev_err(dev->net, "Could not register MDIO bus\n");
 108                 goto mfree;
 109         }
 110 
 111         netdev_info(dev->net, "registered mdio bus %s\n", priv->mdio->id);
 112         return 0;
 113 
 114 mfree:
 115         mdiobus_free(priv->mdio);
 116         return ret;
 117 }
 118 
 119 static void ax88172a_remove_mdio(struct usbnet *dev)
 120 {
 121         struct ax88172a_private *priv = dev->driver_priv;
 122 
 123         netdev_info(dev->net, "deregistering mdio bus %s\n", priv->mdio->id);
 124         mdiobus_unregister(priv->mdio);
 125         mdiobus_free(priv->mdio);
 126 }
 127 
 128 static const struct net_device_ops ax88172a_netdev_ops = {
 129         .ndo_open               = usbnet_open,
 130         .ndo_stop               = usbnet_stop,
 131         .ndo_start_xmit         = usbnet_start_xmit,
 132         .ndo_tx_timeout         = usbnet_tx_timeout,
 133         .ndo_change_mtu         = usbnet_change_mtu,
 134         .ndo_get_stats64        = usbnet_get_stats64,
 135         .ndo_set_mac_address    = asix_set_mac_address,
 136         .ndo_validate_addr      = eth_validate_addr,
 137         .ndo_do_ioctl           = ax88172a_ioctl,
 138         .ndo_set_rx_mode        = asix_set_multicast,
 139 };
 140 
 141 static const struct ethtool_ops ax88172a_ethtool_ops = {
 142         .get_drvinfo            = asix_get_drvinfo,
 143         .get_link               = usbnet_get_link,
 144         .get_msglevel           = usbnet_get_msglevel,
 145         .set_msglevel           = usbnet_set_msglevel,
 146         .get_wol                = asix_get_wol,
 147         .set_wol                = asix_set_wol,
 148         .get_eeprom_len         = asix_get_eeprom_len,
 149         .get_eeprom             = asix_get_eeprom,
 150         .set_eeprom             = asix_set_eeprom,
 151         .nway_reset             = phy_ethtool_nway_reset,
 152         .get_link_ksettings     = phy_ethtool_get_link_ksettings,
 153         .set_link_ksettings     = phy_ethtool_set_link_ksettings,
 154 };
 155 
 156 static int ax88172a_reset_phy(struct usbnet *dev, int embd_phy)
 157 {
 158         int ret;
 159 
 160         ret = asix_sw_reset(dev, AX_SWRESET_IPPD, 0);
 161         if (ret < 0)
 162                 goto err;
 163 
 164         msleep(150);
 165         ret = asix_sw_reset(dev, AX_SWRESET_CLEAR, 0);
 166         if (ret < 0)
 167                 goto err;
 168 
 169         msleep(150);
 170 
 171         ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_IPPD,
 172                             0);
 173         if (ret < 0)
 174                 goto err;
 175 
 176         return 0;
 177 
 178 err:
 179         return ret;
 180 }
 181 
 182 
 183 static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
 184 {
 185         int ret;
 186         u8 buf[ETH_ALEN];
 187         struct ax88172a_private *priv;
 188 
 189         usbnet_get_endpoints(dev, intf);
 190 
 191         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 192         if (!priv)
 193                 return -ENOMEM;
 194 
 195         dev->driver_priv = priv;
 196 
 197         /* Get the MAC address */
 198         ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf, 0);
 199         if (ret < ETH_ALEN) {
 200                 netdev_err(dev->net, "Failed to read MAC address: %d\n", ret);
 201                 goto free;
 202         }
 203         memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 204 
 205         dev->net->netdev_ops = &ax88172a_netdev_ops;
 206         dev->net->ethtool_ops = &ax88172a_ethtool_ops;
 207 
 208         /* are we using the internal or the external phy? */
 209         ret = asix_read_cmd(dev, AX_CMD_SW_PHY_STATUS, 0, 0, 1, buf, 0);
 210         if (ret < 0) {
 211                 netdev_err(dev->net, "Failed to read software interface selection register: %d\n",
 212                            ret);
 213                 goto free;
 214         }
 215 
 216         netdev_dbg(dev->net, "AX_CMD_SW_PHY_STATUS = 0x%02x\n", buf[0]);
 217         switch (buf[0] & AX_PHY_SELECT_MASK) {
 218         case AX_PHY_SELECT_INTERNAL:
 219                 netdev_dbg(dev->net, "use internal phy\n");
 220                 priv->use_embdphy = 1;
 221                 break;
 222         case AX_PHY_SELECT_EXTERNAL:
 223                 netdev_dbg(dev->net, "use external phy\n");
 224                 priv->use_embdphy = 0;
 225                 break;
 226         default:
 227                 netdev_err(dev->net, "Interface mode not supported by driver\n");
 228                 ret = -ENOTSUPP;
 229                 goto free;
 230         }
 231 
 232         priv->phy_addr = asix_read_phy_addr(dev, priv->use_embdphy);
 233         ax88172a_reset_phy(dev, priv->use_embdphy);
 234 
 235         /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
 236         if (dev->driver_info->flags & FLAG_FRAMING_AX) {
 237                 /* hard_mtu  is still the default - the device does not support
 238                    jumbo eth frames */
 239                 dev->rx_urb_size = 2048;
 240         }
 241 
 242         /* init MDIO bus */
 243         ret = ax88172a_init_mdio(dev);
 244         if (ret)
 245                 goto free;
 246 
 247         return 0;
 248 
 249 free:
 250         kfree(priv);
 251         return ret;
 252 }
 253 
 254 static int ax88172a_stop(struct usbnet *dev)
 255 {
 256         struct ax88172a_private *priv = dev->driver_priv;
 257 
 258         netdev_dbg(dev->net, "Stopping interface\n");
 259 
 260         if (priv->phydev) {
 261                 netdev_info(dev->net, "Disconnecting from phy %s\n",
 262                             priv->phy_name);
 263                 phy_stop(priv->phydev);
 264                 phy_disconnect(priv->phydev);
 265         }
 266 
 267         return 0;
 268 }
 269 
 270 static void ax88172a_unbind(struct usbnet *dev, struct usb_interface *intf)
 271 {
 272         struct ax88172a_private *priv = dev->driver_priv;
 273 
 274         ax88172a_remove_mdio(dev);
 275         kfree(priv);
 276 }
 277 
 278 static int ax88172a_reset(struct usbnet *dev)
 279 {
 280         struct asix_data *data = (struct asix_data *)&dev->data;
 281         struct ax88172a_private *priv = dev->driver_priv;
 282         int ret;
 283         u16 rx_ctl;
 284 
 285         ax88172a_reset_phy(dev, priv->use_embdphy);
 286 
 287         msleep(150);
 288         rx_ctl = asix_read_rx_ctl(dev, 0);
 289         netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
 290         ret = asix_write_rx_ctl(dev, 0x0000, 0);
 291         if (ret < 0)
 292                 goto out;
 293 
 294         rx_ctl = asix_read_rx_ctl(dev, 0);
 295         netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
 296 
 297         msleep(150);
 298 
 299         ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
 300                              AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
 301                              AX88772_IPG2_DEFAULT, 0, NULL, 0);
 302         if (ret < 0) {
 303                 netdev_err(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret);
 304                 goto out;
 305         }
 306 
 307         /* Rewrite MAC address */
 308         memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
 309         ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
 310                              data->mac_addr, 0);
 311         if (ret < 0)
 312                 goto out;
 313 
 314         /* Set RX_CTL to default values with 2k buffer, and enable cactus */
 315         ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL, 0);
 316         if (ret < 0)
 317                 goto out;
 318 
 319         rx_ctl = asix_read_rx_ctl(dev, 0);
 320         netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n",
 321                    rx_ctl);
 322 
 323         rx_ctl = asix_read_medium_status(dev, 0);
 324         netdev_dbg(dev->net, "Medium Status is 0x%04x after all initializations\n",
 325                    rx_ctl);
 326 
 327         /* Connect to PHY */
 328         snprintf(priv->phy_name, 20, PHY_ID_FMT,
 329                  priv->mdio->id, priv->phy_addr);
 330 
 331         priv->phydev = phy_connect(dev->net, priv->phy_name,
 332                                    &ax88172a_adjust_link,
 333                                    PHY_INTERFACE_MODE_MII);
 334         if (IS_ERR(priv->phydev)) {
 335                 netdev_err(dev->net, "Could not connect to PHY device %s\n",
 336                            priv->phy_name);
 337                 ret = PTR_ERR(priv->phydev);
 338                 goto out;
 339         }
 340 
 341         netdev_info(dev->net, "Connected to phy %s\n", priv->phy_name);
 342 
 343         /* During power-up, the AX88172A set the power down (BMCR_PDOWN)
 344          * bit of the PHY. Bring the PHY up again.
 345          */
 346         genphy_resume(priv->phydev);
 347         phy_start(priv->phydev);
 348 
 349         return 0;
 350 
 351 out:
 352         return ret;
 353 
 354 }
 355 
 356 static int ax88172a_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 357 {
 358         struct ax88172a_private *dp = dev->driver_priv;
 359         struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;
 360 
 361         return asix_rx_fixup_internal(dev, skb, rx);
 362 }
 363 
 364 const struct driver_info ax88172a_info = {
 365         .description = "ASIX AX88172A USB 2.0 Ethernet",
 366         .bind = ax88172a_bind,
 367         .reset = ax88172a_reset,
 368         .stop = ax88172a_stop,
 369         .unbind = ax88172a_unbind,
 370         .status = ax88172a_status,
 371         .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
 372                  FLAG_MULTI_PACKET,
 373         .rx_fixup = ax88172a_rx_fixup,
 374         .tx_fixup = asix_tx_fixup,
 375 };

/* [<][>][^][v][top][bottom][index][help] */