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        = dev_get_tstats64,
 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                ret = -EIO;
 191                goto free;
 192        }
 193        memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 194
 195        dev->net->netdev_ops = &ax88172a_netdev_ops;
 196        dev->net->ethtool_ops = &ax88172a_ethtool_ops;
 197
 198        /* are we using the internal or the external phy? */
 199        ret = asix_read_cmd(dev, AX_CMD_SW_PHY_STATUS, 0, 0, 1, buf, 0);
 200        if (ret < 0) {
 201                netdev_err(dev->net, "Failed to read software interface selection register: %d\n",
 202                           ret);
 203                goto free;
 204        }
 205
 206        netdev_dbg(dev->net, "AX_CMD_SW_PHY_STATUS = 0x%02x\n", buf[0]);
 207        switch (buf[0] & AX_PHY_SELECT_MASK) {
 208        case AX_PHY_SELECT_INTERNAL:
 209                netdev_dbg(dev->net, "use internal phy\n");
 210                priv->use_embdphy = 1;
 211                break;
 212        case AX_PHY_SELECT_EXTERNAL:
 213                netdev_dbg(dev->net, "use external phy\n");
 214                priv->use_embdphy = 0;
 215                break;
 216        default:
 217                netdev_err(dev->net, "Interface mode not supported by driver\n");
 218                ret = -ENOTSUPP;
 219                goto free;
 220        }
 221
 222        priv->phy_addr = asix_read_phy_addr(dev, priv->use_embdphy);
 223        ax88172a_reset_phy(dev, priv->use_embdphy);
 224
 225        /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
 226        if (dev->driver_info->flags & FLAG_FRAMING_AX) {
 227                /* hard_mtu  is still the default - the device does not support
 228                   jumbo eth frames */
 229                dev->rx_urb_size = 2048;
 230        }
 231
 232        /* init MDIO bus */
 233        ret = ax88172a_init_mdio(dev);
 234        if (ret)
 235                goto free;
 236
 237        return 0;
 238
 239free:
 240        kfree(priv);
 241        return ret;
 242}
 243
 244static int ax88172a_stop(struct usbnet *dev)
 245{
 246        struct ax88172a_private *priv = dev->driver_priv;
 247
 248        netdev_dbg(dev->net, "Stopping interface\n");
 249
 250        if (priv->phydev) {
 251                netdev_info(dev->net, "Disconnecting from phy %s\n",
 252                            priv->phy_name);
 253                phy_stop(priv->phydev);
 254                phy_disconnect(priv->phydev);
 255        }
 256
 257        return 0;
 258}
 259
 260static void ax88172a_unbind(struct usbnet *dev, struct usb_interface *intf)
 261{
 262        struct ax88172a_private *priv = dev->driver_priv;
 263
 264        ax88172a_remove_mdio(dev);
 265        kfree(priv);
 266}
 267
 268static int ax88172a_reset(struct usbnet *dev)
 269{
 270        struct asix_data *data = (struct asix_data *)&dev->data;
 271        struct ax88172a_private *priv = dev->driver_priv;
 272        int ret;
 273        u16 rx_ctl;
 274
 275        ax88172a_reset_phy(dev, priv->use_embdphy);
 276
 277        msleep(150);
 278        rx_ctl = asix_read_rx_ctl(dev, 0);
 279        netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
 280        ret = asix_write_rx_ctl(dev, 0x0000, 0);
 281        if (ret < 0)
 282                goto out;
 283
 284        rx_ctl = asix_read_rx_ctl(dev, 0);
 285        netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
 286
 287        msleep(150);
 288
 289        ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
 290                             AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
 291                             AX88772_IPG2_DEFAULT, 0, NULL, 0);
 292        if (ret < 0) {
 293                netdev_err(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret);
 294                goto out;
 295        }
 296
 297        /* Rewrite MAC address */
 298        memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
 299        ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
 300                             data->mac_addr, 0);
 301        if (ret < 0)
 302                goto out;
 303
 304        /* Set RX_CTL to default values with 2k buffer, and enable cactus */
 305        ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL, 0);
 306        if (ret < 0)
 307                goto out;
 308
 309        rx_ctl = asix_read_rx_ctl(dev, 0);
 310        netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n",
 311                   rx_ctl);
 312
 313        rx_ctl = asix_read_medium_status(dev, 0);
 314        netdev_dbg(dev->net, "Medium Status is 0x%04x after all initializations\n",
 315                   rx_ctl);
 316
 317        /* Connect to PHY */
 318        snprintf(priv->phy_name, 20, PHY_ID_FMT,
 319                 priv->mdio->id, priv->phy_addr);
 320
 321        priv->phydev = phy_connect(dev->net, priv->phy_name,
 322                                   &ax88172a_adjust_link,
 323                                   PHY_INTERFACE_MODE_MII);
 324        if (IS_ERR(priv->phydev)) {
 325                netdev_err(dev->net, "Could not connect to PHY device %s\n",
 326                           priv->phy_name);
 327                ret = PTR_ERR(priv->phydev);
 328                goto out;
 329        }
 330
 331        netdev_info(dev->net, "Connected to phy %s\n", priv->phy_name);
 332
 333        /* During power-up, the AX88172A set the power down (BMCR_PDOWN)
 334         * bit of the PHY. Bring the PHY up again.
 335         */
 336        genphy_resume(priv->phydev);
 337        phy_start(priv->phydev);
 338
 339        return 0;
 340
 341out:
 342        return ret;
 343
 344}
 345
 346static int ax88172a_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 347{
 348        struct ax88172a_private *dp = dev->driver_priv;
 349        struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;
 350
 351        return asix_rx_fixup_internal(dev, skb, rx);
 352}
 353
 354const struct driver_info ax88172a_info = {
 355        .description = "ASIX AX88172A USB 2.0 Ethernet",
 356        .bind = ax88172a_bind,
 357        .reset = ax88172a_reset,
 358        .stop = ax88172a_stop,
 359        .unbind = ax88172a_unbind,
 360        .status = ax88172a_status,
 361        .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
 362                 FLAG_MULTI_PACKET,
 363        .rx_fixup = ax88172a_rx_fixup,
 364        .tx_fixup = asix_tx_fixup,
 365};
 366