linux/drivers/net/usb/ax88172a.c
<<
>>
Prefs
   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
  18struct 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 */
  29static 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
  35static 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
  42static 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 */
  54static 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
  80static 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 */
  86static 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
 114mfree:
 115        mdiobus_free(priv->mdio);
 116        return ret;
 117}
 118
 119static 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
 128static 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
 141static 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
 156static 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
 178err:
 179        return ret;
 180}
 181
 182
 183static 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
 249free:
 250        kfree(priv);
 251        return ret;
 252}
 253
 254static 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
 270static 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
 278static 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
 351out:
 352        return ret;
 353
 354}
 355
 356static 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
 364const 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};
 376