Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * ASIX AX88172A based USB 2.0 Ethernet Devices
0004  * Copyright (C) 2012 OMICRON electronics GmbH
0005  *
0006  * Supports external PHYs via phylib. Based on the driver for the
0007  * AX88772. Original copyrights follow:
0008  *
0009  * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
0010  * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
0011  * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
0012  * Copyright (c) 2002-2003 TiVo Inc.
0013  */
0014 
0015 #include "asix.h"
0016 #include <linux/phy.h>
0017 
0018 struct ax88172a_private {
0019     struct mii_bus *mdio;
0020     struct phy_device *phydev;
0021     char phy_name[20];
0022     u16 phy_addr;
0023     u16 oldmode;
0024     int use_embdphy;
0025     struct asix_rx_fixup_info rx_fixup_info;
0026 };
0027 
0028 /* set MAC link settings according to information from phylib */
0029 static void ax88172a_adjust_link(struct net_device *netdev)
0030 {
0031     struct phy_device *phydev = netdev->phydev;
0032     struct usbnet *dev = netdev_priv(netdev);
0033     struct ax88172a_private *priv = dev->driver_priv;
0034     u16 mode = 0;
0035 
0036     if (phydev->link) {
0037         mode = AX88772_MEDIUM_DEFAULT;
0038 
0039         if (phydev->duplex == DUPLEX_HALF)
0040             mode &= ~AX_MEDIUM_FD;
0041 
0042         if (phydev->speed != SPEED_100)
0043             mode &= ~AX_MEDIUM_PS;
0044     }
0045 
0046     if (mode != priv->oldmode) {
0047         asix_write_medium_mode(dev, mode, 0);
0048         priv->oldmode = mode;
0049         netdev_dbg(netdev, "speed %u duplex %d, setting mode to 0x%04x\n",
0050                phydev->speed, phydev->duplex, mode);
0051         phy_print_status(phydev);
0052     }
0053 }
0054 
0055 static void ax88172a_status(struct usbnet *dev, struct urb *urb)
0056 {
0057     /* link changes are detected by polling the phy */
0058 }
0059 
0060 /* use phylib infrastructure */
0061 static int ax88172a_init_mdio(struct usbnet *dev)
0062 {
0063     struct ax88172a_private *priv = dev->driver_priv;
0064     int ret;
0065 
0066     priv->mdio = mdiobus_alloc();
0067     if (!priv->mdio) {
0068         netdev_err(dev->net, "Could not allocate MDIO bus\n");
0069         return -ENOMEM;
0070     }
0071 
0072     priv->mdio->priv = (void *)dev;
0073     priv->mdio->read = &asix_mdio_bus_read;
0074     priv->mdio->write = &asix_mdio_bus_write;
0075     priv->mdio->name = "Asix MDIO Bus";
0076     /* mii bus name is usb-<usb bus number>-<usb device number> */
0077     snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
0078          dev->udev->bus->busnum, dev->udev->devnum);
0079 
0080     ret = mdiobus_register(priv->mdio);
0081     if (ret) {
0082         netdev_err(dev->net, "Could not register MDIO bus\n");
0083         goto mfree;
0084     }
0085 
0086     netdev_info(dev->net, "registered mdio bus %s\n", priv->mdio->id);
0087     return 0;
0088 
0089 mfree:
0090     mdiobus_free(priv->mdio);
0091     return ret;
0092 }
0093 
0094 static void ax88172a_remove_mdio(struct usbnet *dev)
0095 {
0096     struct ax88172a_private *priv = dev->driver_priv;
0097 
0098     netdev_info(dev->net, "deregistering mdio bus %s\n", priv->mdio->id);
0099     mdiobus_unregister(priv->mdio);
0100     mdiobus_free(priv->mdio);
0101 }
0102 
0103 static const struct net_device_ops ax88172a_netdev_ops = {
0104     .ndo_open       = usbnet_open,
0105     .ndo_stop       = usbnet_stop,
0106     .ndo_start_xmit     = usbnet_start_xmit,
0107     .ndo_tx_timeout     = usbnet_tx_timeout,
0108     .ndo_change_mtu     = usbnet_change_mtu,
0109     .ndo_get_stats64    = dev_get_tstats64,
0110     .ndo_set_mac_address    = asix_set_mac_address,
0111     .ndo_validate_addr  = eth_validate_addr,
0112     .ndo_eth_ioctl      = phy_do_ioctl_running,
0113     .ndo_set_rx_mode        = asix_set_multicast,
0114 };
0115 
0116 static const struct ethtool_ops ax88172a_ethtool_ops = {
0117     .get_drvinfo        = asix_get_drvinfo,
0118     .get_link       = usbnet_get_link,
0119     .get_msglevel       = usbnet_get_msglevel,
0120     .set_msglevel       = usbnet_set_msglevel,
0121     .get_wol        = asix_get_wol,
0122     .set_wol        = asix_set_wol,
0123     .get_eeprom_len     = asix_get_eeprom_len,
0124     .get_eeprom     = asix_get_eeprom,
0125     .set_eeprom     = asix_set_eeprom,
0126     .nway_reset     = phy_ethtool_nway_reset,
0127     .get_link_ksettings = phy_ethtool_get_link_ksettings,
0128     .set_link_ksettings = phy_ethtool_set_link_ksettings,
0129 };
0130 
0131 static int ax88172a_reset_phy(struct usbnet *dev, int embd_phy)
0132 {
0133     int ret;
0134 
0135     ret = asix_sw_reset(dev, AX_SWRESET_IPPD, 0);
0136     if (ret < 0)
0137         goto err;
0138 
0139     msleep(150);
0140     ret = asix_sw_reset(dev, AX_SWRESET_CLEAR, 0);
0141     if (ret < 0)
0142         goto err;
0143 
0144     msleep(150);
0145 
0146     ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_IPPD,
0147                 0);
0148     if (ret < 0)
0149         goto err;
0150 
0151     return 0;
0152 
0153 err:
0154     return ret;
0155 }
0156 
0157 
0158 static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
0159 {
0160     int ret;
0161     u8 buf[ETH_ALEN];
0162     struct ax88172a_private *priv;
0163 
0164     usbnet_get_endpoints(dev, intf);
0165 
0166     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0167     if (!priv)
0168         return -ENOMEM;
0169 
0170     dev->driver_priv = priv;
0171 
0172     /* Get the MAC address */
0173     ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf, 0);
0174     if (ret < ETH_ALEN) {
0175         netdev_err(dev->net, "Failed to read MAC address: %d\n", ret);
0176         ret = -EIO;
0177         goto free;
0178     }
0179     eth_hw_addr_set(dev->net, buf);
0180 
0181     dev->net->netdev_ops = &ax88172a_netdev_ops;
0182     dev->net->ethtool_ops = &ax88172a_ethtool_ops;
0183 
0184     /* are we using the internal or the external phy? */
0185     ret = asix_read_cmd(dev, AX_CMD_SW_PHY_STATUS, 0, 0, 1, buf, 0);
0186     if (ret < 0) {
0187         netdev_err(dev->net, "Failed to read software interface selection register: %d\n",
0188                ret);
0189         goto free;
0190     }
0191 
0192     netdev_dbg(dev->net, "AX_CMD_SW_PHY_STATUS = 0x%02x\n", buf[0]);
0193     switch (buf[0] & AX_PHY_SELECT_MASK) {
0194     case AX_PHY_SELECT_INTERNAL:
0195         netdev_dbg(dev->net, "use internal phy\n");
0196         priv->use_embdphy = 1;
0197         break;
0198     case AX_PHY_SELECT_EXTERNAL:
0199         netdev_dbg(dev->net, "use external phy\n");
0200         priv->use_embdphy = 0;
0201         break;
0202     default:
0203         netdev_err(dev->net, "Interface mode not supported by driver\n");
0204         ret = -ENOTSUPP;
0205         goto free;
0206     }
0207 
0208     ret = asix_read_phy_addr(dev, priv->use_embdphy);
0209     if (ret < 0)
0210         goto free;
0211 
0212     priv->phy_addr = ret;
0213 
0214     ax88172a_reset_phy(dev, priv->use_embdphy);
0215 
0216     /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
0217     if (dev->driver_info->flags & FLAG_FRAMING_AX) {
0218         /* hard_mtu  is still the default - the device does not support
0219            jumbo eth frames */
0220         dev->rx_urb_size = 2048;
0221     }
0222 
0223     /* init MDIO bus */
0224     ret = ax88172a_init_mdio(dev);
0225     if (ret)
0226         goto free;
0227 
0228     return 0;
0229 
0230 free:
0231     kfree(priv);
0232     return ret;
0233 }
0234 
0235 static int ax88172a_stop(struct usbnet *dev)
0236 {
0237     struct ax88172a_private *priv = dev->driver_priv;
0238 
0239     netdev_dbg(dev->net, "Stopping interface\n");
0240 
0241     if (priv->phydev) {
0242         netdev_info(dev->net, "Disconnecting from phy %s\n",
0243                 priv->phy_name);
0244         phy_stop(priv->phydev);
0245         phy_disconnect(priv->phydev);
0246     }
0247 
0248     return 0;
0249 }
0250 
0251 static void ax88172a_unbind(struct usbnet *dev, struct usb_interface *intf)
0252 {
0253     struct ax88172a_private *priv = dev->driver_priv;
0254 
0255     ax88172a_remove_mdio(dev);
0256     kfree(priv);
0257 }
0258 
0259 static int ax88172a_reset(struct usbnet *dev)
0260 {
0261     struct asix_data *data = (struct asix_data *)&dev->data;
0262     struct ax88172a_private *priv = dev->driver_priv;
0263     int ret;
0264     u16 rx_ctl;
0265 
0266     ax88172a_reset_phy(dev, priv->use_embdphy);
0267 
0268     msleep(150);
0269     rx_ctl = asix_read_rx_ctl(dev, 0);
0270     netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
0271     ret = asix_write_rx_ctl(dev, 0x0000, 0);
0272     if (ret < 0)
0273         goto out;
0274 
0275     rx_ctl = asix_read_rx_ctl(dev, 0);
0276     netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
0277 
0278     msleep(150);
0279 
0280     ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
0281                  AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
0282                  AX88772_IPG2_DEFAULT, 0, NULL, 0);
0283     if (ret < 0) {
0284         netdev_err(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret);
0285         goto out;
0286     }
0287 
0288     /* Rewrite MAC address */
0289     memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
0290     ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
0291                  data->mac_addr, 0);
0292     if (ret < 0)
0293         goto out;
0294 
0295     /* Set RX_CTL to default values with 2k buffer, and enable cactus */
0296     ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL, 0);
0297     if (ret < 0)
0298         goto out;
0299 
0300     rx_ctl = asix_read_rx_ctl(dev, 0);
0301     netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n",
0302            rx_ctl);
0303 
0304     rx_ctl = asix_read_medium_status(dev, 0);
0305     netdev_dbg(dev->net, "Medium Status is 0x%04x after all initializations\n",
0306            rx_ctl);
0307 
0308     /* Connect to PHY */
0309     snprintf(priv->phy_name, 20, PHY_ID_FMT,
0310          priv->mdio->id, priv->phy_addr);
0311 
0312     priv->phydev = phy_connect(dev->net, priv->phy_name,
0313                    &ax88172a_adjust_link,
0314                    PHY_INTERFACE_MODE_MII);
0315     if (IS_ERR(priv->phydev)) {
0316         netdev_err(dev->net, "Could not connect to PHY device %s\n",
0317                priv->phy_name);
0318         ret = PTR_ERR(priv->phydev);
0319         goto out;
0320     }
0321 
0322     netdev_info(dev->net, "Connected to phy %s\n", priv->phy_name);
0323 
0324     /* During power-up, the AX88172A set the power down (BMCR_PDOWN)
0325      * bit of the PHY. Bring the PHY up again.
0326      */
0327     genphy_resume(priv->phydev);
0328     phy_start(priv->phydev);
0329 
0330     return 0;
0331 
0332 out:
0333     return ret;
0334 
0335 }
0336 
0337 static int ax88172a_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
0338 {
0339     struct ax88172a_private *dp = dev->driver_priv;
0340     struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;
0341 
0342     return asix_rx_fixup_internal(dev, skb, rx);
0343 }
0344 
0345 const struct driver_info ax88172a_info = {
0346     .description = "ASIX AX88172A USB 2.0 Ethernet",
0347     .bind = ax88172a_bind,
0348     .reset = ax88172a_reset,
0349     .stop = ax88172a_stop,
0350     .unbind = ax88172a_unbind,
0351     .status = ax88172a_status,
0352     .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
0353          FLAG_MULTI_PACKET,
0354     .rx_fixup = ax88172a_rx_fixup,
0355     .tx_fixup = asix_tx_fixup,
0356 };