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