1*c9b37458SLiu Junliang /* 2*c9b37458SLiu Junliang * CoreChip-sz SR9700 one chip USB 1.1 Ethernet Devices 3*c9b37458SLiu Junliang * 4*c9b37458SLiu Junliang * Author : Liu Junliang <liujunliang_ljl@163.com> 5*c9b37458SLiu Junliang * 6*c9b37458SLiu Junliang * Based on dm9601.c 7*c9b37458SLiu Junliang * 8*c9b37458SLiu Junliang * This file is licensed under the terms of the GNU General Public License 9*c9b37458SLiu Junliang * version 2. This program is licensed "as is" without any warranty of any 10*c9b37458SLiu Junliang * kind, whether express or implied. 11*c9b37458SLiu Junliang */ 12*c9b37458SLiu Junliang 13*c9b37458SLiu Junliang #include <linux/module.h> 14*c9b37458SLiu Junliang #include <linux/sched.h> 15*c9b37458SLiu Junliang #include <linux/stddef.h> 16*c9b37458SLiu Junliang #include <linux/init.h> 17*c9b37458SLiu Junliang #include <linux/netdevice.h> 18*c9b37458SLiu Junliang #include <linux/etherdevice.h> 19*c9b37458SLiu Junliang #include <linux/ethtool.h> 20*c9b37458SLiu Junliang #include <linux/mii.h> 21*c9b37458SLiu Junliang #include <linux/usb.h> 22*c9b37458SLiu Junliang #include <linux/crc32.h> 23*c9b37458SLiu Junliang #include <linux/usb/usbnet.h> 24*c9b37458SLiu Junliang 25*c9b37458SLiu Junliang #include "sr9700.h" 26*c9b37458SLiu Junliang 27*c9b37458SLiu Junliang static int sr_read(struct usbnet *dev, u8 reg, u16 length, void *data) 28*c9b37458SLiu Junliang { 29*c9b37458SLiu Junliang int err; 30*c9b37458SLiu Junliang 31*c9b37458SLiu Junliang err = usbnet_read_cmd(dev, SR_RD_REGS, SR_REQ_RD_REG, 0, reg, data, 32*c9b37458SLiu Junliang length); 33*c9b37458SLiu Junliang if ((err != length) && (err >= 0)) 34*c9b37458SLiu Junliang err = -EINVAL; 35*c9b37458SLiu Junliang return err; 36*c9b37458SLiu Junliang } 37*c9b37458SLiu Junliang 38*c9b37458SLiu Junliang static int sr_write(struct usbnet *dev, u8 reg, u16 length, void *data) 39*c9b37458SLiu Junliang { 40*c9b37458SLiu Junliang int err; 41*c9b37458SLiu Junliang 42*c9b37458SLiu Junliang err = usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG, 0, reg, data, 43*c9b37458SLiu Junliang length); 44*c9b37458SLiu Junliang if ((err >= 0) && (err < length)) 45*c9b37458SLiu Junliang err = -EINVAL; 46*c9b37458SLiu Junliang return err; 47*c9b37458SLiu Junliang } 48*c9b37458SLiu Junliang 49*c9b37458SLiu Junliang static int sr_read_reg(struct usbnet *dev, u8 reg, u8 *value) 50*c9b37458SLiu Junliang { 51*c9b37458SLiu Junliang return sr_read(dev, reg, 1, value); 52*c9b37458SLiu Junliang } 53*c9b37458SLiu Junliang 54*c9b37458SLiu Junliang static int sr_write_reg(struct usbnet *dev, u8 reg, u8 value) 55*c9b37458SLiu Junliang { 56*c9b37458SLiu Junliang return usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG, 57*c9b37458SLiu Junliang value, reg, NULL, 0); 58*c9b37458SLiu Junliang } 59*c9b37458SLiu Junliang 60*c9b37458SLiu Junliang static void sr_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) 61*c9b37458SLiu Junliang { 62*c9b37458SLiu Junliang usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG, 63*c9b37458SLiu Junliang 0, reg, data, length); 64*c9b37458SLiu Junliang } 65*c9b37458SLiu Junliang 66*c9b37458SLiu Junliang static void sr_write_reg_async(struct usbnet *dev, u8 reg, u8 value) 67*c9b37458SLiu Junliang { 68*c9b37458SLiu Junliang usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG, 69*c9b37458SLiu Junliang value, reg, NULL, 0); 70*c9b37458SLiu Junliang } 71*c9b37458SLiu Junliang 72*c9b37458SLiu Junliang static int wait_phy_eeprom_ready(struct usbnet *dev, int phy) 73*c9b37458SLiu Junliang { 74*c9b37458SLiu Junliang int i; 75*c9b37458SLiu Junliang 76*c9b37458SLiu Junliang for (i = 0; i < SR_SHARE_TIMEOUT; i++) { 77*c9b37458SLiu Junliang u8 tmp = 0; 78*c9b37458SLiu Junliang int ret; 79*c9b37458SLiu Junliang 80*c9b37458SLiu Junliang udelay(1); 81*c9b37458SLiu Junliang ret = sr_read_reg(dev, EPCR, &tmp); 82*c9b37458SLiu Junliang if (ret < 0) 83*c9b37458SLiu Junliang return ret; 84*c9b37458SLiu Junliang 85*c9b37458SLiu Junliang /* ready */ 86*c9b37458SLiu Junliang if (!(tmp & EPCR_ERRE)) 87*c9b37458SLiu Junliang return 0; 88*c9b37458SLiu Junliang } 89*c9b37458SLiu Junliang 90*c9b37458SLiu Junliang netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom"); 91*c9b37458SLiu Junliang 92*c9b37458SLiu Junliang return -EIO; 93*c9b37458SLiu Junliang } 94*c9b37458SLiu Junliang 95*c9b37458SLiu Junliang static int sr_share_read_word(struct usbnet *dev, int phy, u8 reg, 96*c9b37458SLiu Junliang __le16 *value) 97*c9b37458SLiu Junliang { 98*c9b37458SLiu Junliang int ret; 99*c9b37458SLiu Junliang 100*c9b37458SLiu Junliang mutex_lock(&dev->phy_mutex); 101*c9b37458SLiu Junliang 102*c9b37458SLiu Junliang sr_write_reg(dev, EPAR, phy ? (reg | EPAR_PHY_ADR) : reg); 103*c9b37458SLiu Junliang sr_write_reg(dev, EPCR, phy ? (EPCR_EPOS | EPCR_ERPRR) : EPCR_ERPRR); 104*c9b37458SLiu Junliang 105*c9b37458SLiu Junliang ret = wait_phy_eeprom_ready(dev, phy); 106*c9b37458SLiu Junliang if (ret < 0) 107*c9b37458SLiu Junliang goto out_unlock; 108*c9b37458SLiu Junliang 109*c9b37458SLiu Junliang sr_write_reg(dev, EPCR, 0x0); 110*c9b37458SLiu Junliang ret = sr_read(dev, EPDR, 2, value); 111*c9b37458SLiu Junliang 112*c9b37458SLiu Junliang netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n", 113*c9b37458SLiu Junliang phy, reg, *value, ret); 114*c9b37458SLiu Junliang 115*c9b37458SLiu Junliang out_unlock: 116*c9b37458SLiu Junliang mutex_unlock(&dev->phy_mutex); 117*c9b37458SLiu Junliang return ret; 118*c9b37458SLiu Junliang } 119*c9b37458SLiu Junliang 120*c9b37458SLiu Junliang static int sr_share_write_word(struct usbnet *dev, int phy, u8 reg, 121*c9b37458SLiu Junliang __le16 value) 122*c9b37458SLiu Junliang { 123*c9b37458SLiu Junliang int ret; 124*c9b37458SLiu Junliang 125*c9b37458SLiu Junliang mutex_lock(&dev->phy_mutex); 126*c9b37458SLiu Junliang 127*c9b37458SLiu Junliang ret = sr_write(dev, EPDR, 2, &value); 128*c9b37458SLiu Junliang if (ret < 0) 129*c9b37458SLiu Junliang goto out_unlock; 130*c9b37458SLiu Junliang 131*c9b37458SLiu Junliang sr_write_reg(dev, EPAR, phy ? (reg | EPAR_PHY_ADR) : reg); 132*c9b37458SLiu Junliang sr_write_reg(dev, EPCR, phy ? (EPCR_WEP | EPCR_EPOS | EPCR_ERPRW) : 133*c9b37458SLiu Junliang (EPCR_WEP | EPCR_ERPRW)); 134*c9b37458SLiu Junliang 135*c9b37458SLiu Junliang ret = wait_phy_eeprom_ready(dev, phy); 136*c9b37458SLiu Junliang if (ret < 0) 137*c9b37458SLiu Junliang goto out_unlock; 138*c9b37458SLiu Junliang 139*c9b37458SLiu Junliang sr_write_reg(dev, EPCR, 0x0); 140*c9b37458SLiu Junliang 141*c9b37458SLiu Junliang out_unlock: 142*c9b37458SLiu Junliang mutex_unlock(&dev->phy_mutex); 143*c9b37458SLiu Junliang return ret; 144*c9b37458SLiu Junliang } 145*c9b37458SLiu Junliang 146*c9b37458SLiu Junliang static int sr_read_eeprom_word(struct usbnet *dev, u8 offset, void *value) 147*c9b37458SLiu Junliang { 148*c9b37458SLiu Junliang return sr_share_read_word(dev, 0, offset, value); 149*c9b37458SLiu Junliang } 150*c9b37458SLiu Junliang 151*c9b37458SLiu Junliang static int sr9700_get_eeprom_len(struct net_device *netdev) 152*c9b37458SLiu Junliang { 153*c9b37458SLiu Junliang return SR_EEPROM_LEN; 154*c9b37458SLiu Junliang } 155*c9b37458SLiu Junliang 156*c9b37458SLiu Junliang static int sr9700_get_eeprom(struct net_device *netdev, 157*c9b37458SLiu Junliang struct ethtool_eeprom *eeprom, u8 *data) 158*c9b37458SLiu Junliang { 159*c9b37458SLiu Junliang struct usbnet *dev = netdev_priv(netdev); 160*c9b37458SLiu Junliang __le16 *buf = (__le16 *)data; 161*c9b37458SLiu Junliang int ret = 0; 162*c9b37458SLiu Junliang int i; 163*c9b37458SLiu Junliang 164*c9b37458SLiu Junliang /* access is 16bit */ 165*c9b37458SLiu Junliang if ((eeprom->offset & 0x01) || (eeprom->len & 0x01)) 166*c9b37458SLiu Junliang return -EINVAL; 167*c9b37458SLiu Junliang 168*c9b37458SLiu Junliang for (i = 0; i < eeprom->len / 2; i++) { 169*c9b37458SLiu Junliang ret = sr_read_eeprom_word(dev, eeprom->offset / 2 + i, buf + i); 170*c9b37458SLiu Junliang if (ret < 0) 171*c9b37458SLiu Junliang break; 172*c9b37458SLiu Junliang } 173*c9b37458SLiu Junliang 174*c9b37458SLiu Junliang return ret; 175*c9b37458SLiu Junliang } 176*c9b37458SLiu Junliang 177*c9b37458SLiu Junliang static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc) 178*c9b37458SLiu Junliang { 179*c9b37458SLiu Junliang struct usbnet *dev = netdev_priv(netdev); 180*c9b37458SLiu Junliang __le16 res; 181*c9b37458SLiu Junliang int rc = 0; 182*c9b37458SLiu Junliang 183*c9b37458SLiu Junliang if (phy_id) { 184*c9b37458SLiu Junliang netdev_dbg(netdev, "Only internal phy supported\n"); 185*c9b37458SLiu Junliang return 0; 186*c9b37458SLiu Junliang } 187*c9b37458SLiu Junliang 188*c9b37458SLiu Junliang /* Access NSR_LINKST bit for link status instead of MII_BMSR */ 189*c9b37458SLiu Junliang if (loc == MII_BMSR) { 190*c9b37458SLiu Junliang u8 value; 191*c9b37458SLiu Junliang 192*c9b37458SLiu Junliang sr_read_reg(dev, NSR, &value); 193*c9b37458SLiu Junliang if (value & NSR_LINKST) 194*c9b37458SLiu Junliang rc = 1; 195*c9b37458SLiu Junliang } 196*c9b37458SLiu Junliang sr_share_read_word(dev, 1, loc, &res); 197*c9b37458SLiu Junliang if (rc == 1) 198*c9b37458SLiu Junliang res = le16_to_cpu(res) | BMSR_LSTATUS; 199*c9b37458SLiu Junliang else 200*c9b37458SLiu Junliang res = le16_to_cpu(res) & ~BMSR_LSTATUS; 201*c9b37458SLiu Junliang 202*c9b37458SLiu Junliang netdev_dbg(netdev, "sr_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", 203*c9b37458SLiu Junliang phy_id, loc, res); 204*c9b37458SLiu Junliang 205*c9b37458SLiu Junliang return res; 206*c9b37458SLiu Junliang } 207*c9b37458SLiu Junliang 208*c9b37458SLiu Junliang static void sr_mdio_write(struct net_device *netdev, int phy_id, int loc, 209*c9b37458SLiu Junliang int val) 210*c9b37458SLiu Junliang { 211*c9b37458SLiu Junliang struct usbnet *dev = netdev_priv(netdev); 212*c9b37458SLiu Junliang __le16 res = cpu_to_le16(val); 213*c9b37458SLiu Junliang 214*c9b37458SLiu Junliang if (phy_id) { 215*c9b37458SLiu Junliang netdev_dbg(netdev, "Only internal phy supported\n"); 216*c9b37458SLiu Junliang return; 217*c9b37458SLiu Junliang } 218*c9b37458SLiu Junliang 219*c9b37458SLiu Junliang netdev_dbg(netdev, "sr_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", 220*c9b37458SLiu Junliang phy_id, loc, val); 221*c9b37458SLiu Junliang 222*c9b37458SLiu Junliang sr_share_write_word(dev, 1, loc, res); 223*c9b37458SLiu Junliang } 224*c9b37458SLiu Junliang 225*c9b37458SLiu Junliang static u32 sr9700_get_link(struct net_device *netdev) 226*c9b37458SLiu Junliang { 227*c9b37458SLiu Junliang struct usbnet *dev = netdev_priv(netdev); 228*c9b37458SLiu Junliang u8 value = 0; 229*c9b37458SLiu Junliang int rc = 0; 230*c9b37458SLiu Junliang 231*c9b37458SLiu Junliang /* Get the Link Status directly */ 232*c9b37458SLiu Junliang sr_read_reg(dev, NSR, &value); 233*c9b37458SLiu Junliang if (value & NSR_LINKST) 234*c9b37458SLiu Junliang rc = 1; 235*c9b37458SLiu Junliang 236*c9b37458SLiu Junliang return rc; 237*c9b37458SLiu Junliang } 238*c9b37458SLiu Junliang 239*c9b37458SLiu Junliang static int sr9700_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) 240*c9b37458SLiu Junliang { 241*c9b37458SLiu Junliang struct usbnet *dev = netdev_priv(netdev); 242*c9b37458SLiu Junliang 243*c9b37458SLiu Junliang return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); 244*c9b37458SLiu Junliang } 245*c9b37458SLiu Junliang 246*c9b37458SLiu Junliang static const struct ethtool_ops sr9700_ethtool_ops = { 247*c9b37458SLiu Junliang .get_drvinfo = usbnet_get_drvinfo, 248*c9b37458SLiu Junliang .get_link = sr9700_get_link, 249*c9b37458SLiu Junliang .get_msglevel = usbnet_get_msglevel, 250*c9b37458SLiu Junliang .set_msglevel = usbnet_set_msglevel, 251*c9b37458SLiu Junliang .get_eeprom_len = sr9700_get_eeprom_len, 252*c9b37458SLiu Junliang .get_eeprom = sr9700_get_eeprom, 253*c9b37458SLiu Junliang .get_settings = usbnet_get_settings, 254*c9b37458SLiu Junliang .set_settings = usbnet_set_settings, 255*c9b37458SLiu Junliang .nway_reset = usbnet_nway_reset, 256*c9b37458SLiu Junliang }; 257*c9b37458SLiu Junliang 258*c9b37458SLiu Junliang static void sr9700_set_multicast(struct net_device *netdev) 259*c9b37458SLiu Junliang { 260*c9b37458SLiu Junliang struct usbnet *dev = netdev_priv(netdev); 261*c9b37458SLiu Junliang /* We use the 20 byte dev->data for our 8 byte filter buffer 262*c9b37458SLiu Junliang * to avoid allocating memory that is tricky to free later 263*c9b37458SLiu Junliang */ 264*c9b37458SLiu Junliang u8 *hashes = (u8 *)&dev->data; 265*c9b37458SLiu Junliang /* rx_ctl setting : enable, disable_long, disable_crc */ 266*c9b37458SLiu Junliang u8 rx_ctl = RCR_RXEN | RCR_DIS_CRC | RCR_DIS_LONG; 267*c9b37458SLiu Junliang 268*c9b37458SLiu Junliang memset(hashes, 0x00, SR_MCAST_SIZE); 269*c9b37458SLiu Junliang /* broadcast address */ 270*c9b37458SLiu Junliang hashes[SR_MCAST_SIZE - 1] |= SR_MCAST_ADDR_FLAG; 271*c9b37458SLiu Junliang if (netdev->flags & IFF_PROMISC) { 272*c9b37458SLiu Junliang rx_ctl |= RCR_PRMSC; 273*c9b37458SLiu Junliang } else if (netdev->flags & IFF_ALLMULTI || 274*c9b37458SLiu Junliang netdev_mc_count(netdev) > SR_MCAST_MAX) { 275*c9b37458SLiu Junliang rx_ctl |= RCR_RUNT; 276*c9b37458SLiu Junliang } else if (!netdev_mc_empty(netdev)) { 277*c9b37458SLiu Junliang struct netdev_hw_addr *ha; 278*c9b37458SLiu Junliang 279*c9b37458SLiu Junliang netdev_for_each_mc_addr(ha, netdev) { 280*c9b37458SLiu Junliang u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26; 281*c9b37458SLiu Junliang hashes[crc >> 3] |= 1 << (crc & 0x7); 282*c9b37458SLiu Junliang } 283*c9b37458SLiu Junliang } 284*c9b37458SLiu Junliang 285*c9b37458SLiu Junliang sr_write_async(dev, MAR, SR_MCAST_SIZE, hashes); 286*c9b37458SLiu Junliang sr_write_reg_async(dev, RCR, rx_ctl); 287*c9b37458SLiu Junliang } 288*c9b37458SLiu Junliang 289*c9b37458SLiu Junliang static int sr9700_set_mac_address(struct net_device *netdev, void *p) 290*c9b37458SLiu Junliang { 291*c9b37458SLiu Junliang struct usbnet *dev = netdev_priv(netdev); 292*c9b37458SLiu Junliang struct sockaddr *addr = p; 293*c9b37458SLiu Junliang 294*c9b37458SLiu Junliang if (!is_valid_ether_addr(addr->sa_data)) { 295*c9b37458SLiu Junliang netdev_err(netdev, "not setting invalid mac address %pM\n", 296*c9b37458SLiu Junliang addr->sa_data); 297*c9b37458SLiu Junliang return -EINVAL; 298*c9b37458SLiu Junliang } 299*c9b37458SLiu Junliang 300*c9b37458SLiu Junliang memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); 301*c9b37458SLiu Junliang sr_write_async(dev, PAR, 6, netdev->dev_addr); 302*c9b37458SLiu Junliang 303*c9b37458SLiu Junliang return 0; 304*c9b37458SLiu Junliang } 305*c9b37458SLiu Junliang 306*c9b37458SLiu Junliang static const struct net_device_ops sr9700_netdev_ops = { 307*c9b37458SLiu Junliang .ndo_open = usbnet_open, 308*c9b37458SLiu Junliang .ndo_stop = usbnet_stop, 309*c9b37458SLiu Junliang .ndo_start_xmit = usbnet_start_xmit, 310*c9b37458SLiu Junliang .ndo_tx_timeout = usbnet_tx_timeout, 311*c9b37458SLiu Junliang .ndo_change_mtu = usbnet_change_mtu, 312*c9b37458SLiu Junliang .ndo_validate_addr = eth_validate_addr, 313*c9b37458SLiu Junliang .ndo_do_ioctl = sr9700_ioctl, 314*c9b37458SLiu Junliang .ndo_set_rx_mode = sr9700_set_multicast, 315*c9b37458SLiu Junliang .ndo_set_mac_address = sr9700_set_mac_address, 316*c9b37458SLiu Junliang }; 317*c9b37458SLiu Junliang 318*c9b37458SLiu Junliang static int sr9700_bind(struct usbnet *dev, struct usb_interface *intf) 319*c9b37458SLiu Junliang { 320*c9b37458SLiu Junliang struct net_device *netdev; 321*c9b37458SLiu Junliang struct mii_if_info *mii; 322*c9b37458SLiu Junliang int ret; 323*c9b37458SLiu Junliang 324*c9b37458SLiu Junliang ret = usbnet_get_endpoints(dev, intf); 325*c9b37458SLiu Junliang if (ret) 326*c9b37458SLiu Junliang goto out; 327*c9b37458SLiu Junliang 328*c9b37458SLiu Junliang netdev = dev->net; 329*c9b37458SLiu Junliang 330*c9b37458SLiu Junliang netdev->netdev_ops = &sr9700_netdev_ops; 331*c9b37458SLiu Junliang netdev->ethtool_ops = &sr9700_ethtool_ops; 332*c9b37458SLiu Junliang netdev->hard_header_len += SR_TX_OVERHEAD; 333*c9b37458SLiu Junliang dev->hard_mtu = netdev->mtu + netdev->hard_header_len; 334*c9b37458SLiu Junliang /* bulkin buffer is preferably not less than 3K */ 335*c9b37458SLiu Junliang dev->rx_urb_size = 3072; 336*c9b37458SLiu Junliang 337*c9b37458SLiu Junliang mii = &dev->mii; 338*c9b37458SLiu Junliang mii->dev = netdev; 339*c9b37458SLiu Junliang mii->mdio_read = sr_mdio_read; 340*c9b37458SLiu Junliang mii->mdio_write = sr_mdio_write; 341*c9b37458SLiu Junliang mii->phy_id_mask = 0x1f; 342*c9b37458SLiu Junliang mii->reg_num_mask = 0x1f; 343*c9b37458SLiu Junliang 344*c9b37458SLiu Junliang sr_write_reg(dev, NCR, NCR_RST); 345*c9b37458SLiu Junliang udelay(20); 346*c9b37458SLiu Junliang 347*c9b37458SLiu Junliang /* read MAC 348*c9b37458SLiu Junliang * After Chip Power on, the Chip will reload the MAC from 349*c9b37458SLiu Junliang * EEPROM automatically to PAR. In case there is no EEPROM externally, 350*c9b37458SLiu Junliang * a default MAC address is stored in PAR for making chip work properly. 351*c9b37458SLiu Junliang */ 352*c9b37458SLiu Junliang if (sr_read(dev, PAR, ETH_ALEN, netdev->dev_addr) < 0) { 353*c9b37458SLiu Junliang netdev_err(netdev, "Error reading MAC address\n"); 354*c9b37458SLiu Junliang ret = -ENODEV; 355*c9b37458SLiu Junliang goto out; 356*c9b37458SLiu Junliang } 357*c9b37458SLiu Junliang 358*c9b37458SLiu Junliang /* power up and reset phy */ 359*c9b37458SLiu Junliang sr_write_reg(dev, PRR, PRR_PHY_RST); 360*c9b37458SLiu Junliang /* at least 10ms, here 20ms for safe */ 361*c9b37458SLiu Junliang mdelay(20); 362*c9b37458SLiu Junliang sr_write_reg(dev, PRR, 0); 363*c9b37458SLiu Junliang /* at least 1ms, here 2ms for reading right register */ 364*c9b37458SLiu Junliang udelay(2 * 1000); 365*c9b37458SLiu Junliang 366*c9b37458SLiu Junliang /* receive broadcast packets */ 367*c9b37458SLiu Junliang sr9700_set_multicast(netdev); 368*c9b37458SLiu Junliang 369*c9b37458SLiu Junliang sr_mdio_write(netdev, mii->phy_id, MII_BMCR, BMCR_RESET); 370*c9b37458SLiu Junliang sr_mdio_write(netdev, mii->phy_id, MII_ADVERTISE, ADVERTISE_ALL | 371*c9b37458SLiu Junliang ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); 372*c9b37458SLiu Junliang mii_nway_restart(mii); 373*c9b37458SLiu Junliang 374*c9b37458SLiu Junliang out: 375*c9b37458SLiu Junliang return ret; 376*c9b37458SLiu Junliang } 377*c9b37458SLiu Junliang 378*c9b37458SLiu Junliang static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 379*c9b37458SLiu Junliang { 380*c9b37458SLiu Junliang struct sk_buff *sr_skb; 381*c9b37458SLiu Junliang int len; 382*c9b37458SLiu Junliang 383*c9b37458SLiu Junliang /* skb content (packets) format : 384*c9b37458SLiu Junliang * p0 p1 p2 ...... pm 385*c9b37458SLiu Junliang * / \ 386*c9b37458SLiu Junliang * / \ 387*c9b37458SLiu Junliang * / \ 388*c9b37458SLiu Junliang * / \ 389*c9b37458SLiu Junliang * p0b0 p0b1 p0b2 p0b3 ...... p0b(n-4) p0b(n-3)...p0bn 390*c9b37458SLiu Junliang * 391*c9b37458SLiu Junliang * p0 : packet 0 392*c9b37458SLiu Junliang * p0b0 : packet 0 byte 0 393*c9b37458SLiu Junliang * 394*c9b37458SLiu Junliang * b0: rx status 395*c9b37458SLiu Junliang * b1: packet length (incl crc) low 396*c9b37458SLiu Junliang * b2: packet length (incl crc) high 397*c9b37458SLiu Junliang * b3..n-4: packet data 398*c9b37458SLiu Junliang * bn-3..bn: ethernet packet crc 399*c9b37458SLiu Junliang */ 400*c9b37458SLiu Junliang if (unlikely(skb->len < SR_RX_OVERHEAD)) { 401*c9b37458SLiu Junliang netdev_err(dev->net, "unexpected tiny rx frame\n"); 402*c9b37458SLiu Junliang return 0; 403*c9b37458SLiu Junliang } 404*c9b37458SLiu Junliang 405*c9b37458SLiu Junliang /* one skb may contains multiple packets */ 406*c9b37458SLiu Junliang while (skb->len > SR_RX_OVERHEAD) { 407*c9b37458SLiu Junliang if (skb->data[0] != 0x40) 408*c9b37458SLiu Junliang return 0; 409*c9b37458SLiu Junliang 410*c9b37458SLiu Junliang /* ignore the CRC length */ 411*c9b37458SLiu Junliang len = (skb->data[1] | (skb->data[2] << 8)) - 4; 412*c9b37458SLiu Junliang 413*c9b37458SLiu Junliang if (len > ETH_FRAME_LEN) 414*c9b37458SLiu Junliang return 0; 415*c9b37458SLiu Junliang 416*c9b37458SLiu Junliang /* the last packet of current skb */ 417*c9b37458SLiu Junliang if (skb->len == (len + SR_RX_OVERHEAD)) { 418*c9b37458SLiu Junliang skb_pull(skb, 3); 419*c9b37458SLiu Junliang skb->len = len; 420*c9b37458SLiu Junliang skb_set_tail_pointer(skb, len); 421*c9b37458SLiu Junliang skb->truesize = len + sizeof(struct sk_buff); 422*c9b37458SLiu Junliang return 2; 423*c9b37458SLiu Junliang } 424*c9b37458SLiu Junliang 425*c9b37458SLiu Junliang /* skb_clone is used for address align */ 426*c9b37458SLiu Junliang sr_skb = skb_clone(skb, GFP_ATOMIC); 427*c9b37458SLiu Junliang if (!sr_skb) 428*c9b37458SLiu Junliang return 0; 429*c9b37458SLiu Junliang 430*c9b37458SLiu Junliang sr_skb->len = len; 431*c9b37458SLiu Junliang sr_skb->data = skb->data + 3; 432*c9b37458SLiu Junliang skb_set_tail_pointer(sr_skb, len); 433*c9b37458SLiu Junliang sr_skb->truesize = len + sizeof(struct sk_buff); 434*c9b37458SLiu Junliang usbnet_skb_return(dev, sr_skb); 435*c9b37458SLiu Junliang 436*c9b37458SLiu Junliang skb_pull(skb, len + SR_RX_OVERHEAD); 437*c9b37458SLiu Junliang }; 438*c9b37458SLiu Junliang 439*c9b37458SLiu Junliang return 0; 440*c9b37458SLiu Junliang } 441*c9b37458SLiu Junliang 442*c9b37458SLiu Junliang static struct sk_buff *sr9700_tx_fixup(struct usbnet *dev, struct sk_buff *skb, 443*c9b37458SLiu Junliang gfp_t flags) 444*c9b37458SLiu Junliang { 445*c9b37458SLiu Junliang int len; 446*c9b37458SLiu Junliang 447*c9b37458SLiu Junliang /* SR9700 can only send out one ethernet packet at once. 448*c9b37458SLiu Junliang * 449*c9b37458SLiu Junliang * b0 b1 b2 b3 ...... b(n-4) b(n-3)...bn 450*c9b37458SLiu Junliang * 451*c9b37458SLiu Junliang * b0: rx status 452*c9b37458SLiu Junliang * b1: packet length (incl crc) low 453*c9b37458SLiu Junliang * b2: packet length (incl crc) high 454*c9b37458SLiu Junliang * b3..n-4: packet data 455*c9b37458SLiu Junliang * bn-3..bn: ethernet packet crc 456*c9b37458SLiu Junliang */ 457*c9b37458SLiu Junliang 458*c9b37458SLiu Junliang len = skb->len; 459*c9b37458SLiu Junliang 460*c9b37458SLiu Junliang if (skb_headroom(skb) < SR_TX_OVERHEAD) { 461*c9b37458SLiu Junliang struct sk_buff *skb2; 462*c9b37458SLiu Junliang 463*c9b37458SLiu Junliang skb2 = skb_copy_expand(skb, SR_TX_OVERHEAD, 0, flags); 464*c9b37458SLiu Junliang dev_kfree_skb_any(skb); 465*c9b37458SLiu Junliang skb = skb2; 466*c9b37458SLiu Junliang if (!skb) 467*c9b37458SLiu Junliang return NULL; 468*c9b37458SLiu Junliang } 469*c9b37458SLiu Junliang 470*c9b37458SLiu Junliang __skb_push(skb, SR_TX_OVERHEAD); 471*c9b37458SLiu Junliang 472*c9b37458SLiu Junliang /* usbnet adds padding if length is a multiple of packet size 473*c9b37458SLiu Junliang * if so, adjust length value in header 474*c9b37458SLiu Junliang */ 475*c9b37458SLiu Junliang if ((skb->len % dev->maxpacket) == 0) 476*c9b37458SLiu Junliang len++; 477*c9b37458SLiu Junliang 478*c9b37458SLiu Junliang skb->data[0] = len; 479*c9b37458SLiu Junliang skb->data[1] = len >> 8; 480*c9b37458SLiu Junliang 481*c9b37458SLiu Junliang return skb; 482*c9b37458SLiu Junliang } 483*c9b37458SLiu Junliang 484*c9b37458SLiu Junliang static void sr9700_status(struct usbnet *dev, struct urb *urb) 485*c9b37458SLiu Junliang { 486*c9b37458SLiu Junliang int link; 487*c9b37458SLiu Junliang u8 *buf; 488*c9b37458SLiu Junliang 489*c9b37458SLiu Junliang /* format: 490*c9b37458SLiu Junliang b0: net status 491*c9b37458SLiu Junliang b1: tx status 1 492*c9b37458SLiu Junliang b2: tx status 2 493*c9b37458SLiu Junliang b3: rx status 494*c9b37458SLiu Junliang b4: rx overflow 495*c9b37458SLiu Junliang b5: rx count 496*c9b37458SLiu Junliang b6: tx count 497*c9b37458SLiu Junliang b7: gpr 498*c9b37458SLiu Junliang */ 499*c9b37458SLiu Junliang 500*c9b37458SLiu Junliang if (urb->actual_length < 8) 501*c9b37458SLiu Junliang return; 502*c9b37458SLiu Junliang 503*c9b37458SLiu Junliang buf = urb->transfer_buffer; 504*c9b37458SLiu Junliang 505*c9b37458SLiu Junliang link = !!(buf[0] & 0x40); 506*c9b37458SLiu Junliang if (netif_carrier_ok(dev->net) != link) { 507*c9b37458SLiu Junliang usbnet_link_change(dev, link, 1); 508*c9b37458SLiu Junliang netdev_dbg(dev->net, "Link Status is: %d\n", link); 509*c9b37458SLiu Junliang } 510*c9b37458SLiu Junliang } 511*c9b37458SLiu Junliang 512*c9b37458SLiu Junliang static int sr9700_link_reset(struct usbnet *dev) 513*c9b37458SLiu Junliang { 514*c9b37458SLiu Junliang struct ethtool_cmd ecmd; 515*c9b37458SLiu Junliang 516*c9b37458SLiu Junliang mii_check_media(&dev->mii, 1, 1); 517*c9b37458SLiu Junliang mii_ethtool_gset(&dev->mii, &ecmd); 518*c9b37458SLiu Junliang 519*c9b37458SLiu Junliang netdev_dbg(dev->net, "link_reset() speed: %d duplex: %d\n", 520*c9b37458SLiu Junliang ecmd.speed, ecmd.duplex); 521*c9b37458SLiu Junliang 522*c9b37458SLiu Junliang return 0; 523*c9b37458SLiu Junliang } 524*c9b37458SLiu Junliang 525*c9b37458SLiu Junliang static const struct driver_info sr9700_driver_info = { 526*c9b37458SLiu Junliang .description = "CoreChip SR9700 USB Ethernet", 527*c9b37458SLiu Junliang .flags = FLAG_ETHER, 528*c9b37458SLiu Junliang .bind = sr9700_bind, 529*c9b37458SLiu Junliang .rx_fixup = sr9700_rx_fixup, 530*c9b37458SLiu Junliang .tx_fixup = sr9700_tx_fixup, 531*c9b37458SLiu Junliang .status = sr9700_status, 532*c9b37458SLiu Junliang .link_reset = sr9700_link_reset, 533*c9b37458SLiu Junliang .reset = sr9700_link_reset, 534*c9b37458SLiu Junliang }; 535*c9b37458SLiu Junliang 536*c9b37458SLiu Junliang static const struct usb_device_id products[] = { 537*c9b37458SLiu Junliang { 538*c9b37458SLiu Junliang USB_DEVICE(0x0fe6, 0x9700), /* SR9700 device */ 539*c9b37458SLiu Junliang .driver_info = (unsigned long)&sr9700_driver_info, 540*c9b37458SLiu Junliang }, 541*c9b37458SLiu Junliang {}, /* END */ 542*c9b37458SLiu Junliang }; 543*c9b37458SLiu Junliang 544*c9b37458SLiu Junliang MODULE_DEVICE_TABLE(usb, products); 545*c9b37458SLiu Junliang 546*c9b37458SLiu Junliang static struct usb_driver sr9700_usb_driver = { 547*c9b37458SLiu Junliang .name = "sr9700", 548*c9b37458SLiu Junliang .id_table = products, 549*c9b37458SLiu Junliang .probe = usbnet_probe, 550*c9b37458SLiu Junliang .disconnect = usbnet_disconnect, 551*c9b37458SLiu Junliang .suspend = usbnet_suspend, 552*c9b37458SLiu Junliang .resume = usbnet_resume, 553*c9b37458SLiu Junliang .disable_hub_initiated_lpm = 1, 554*c9b37458SLiu Junliang }; 555*c9b37458SLiu Junliang 556*c9b37458SLiu Junliang module_usb_driver(sr9700_usb_driver); 557*c9b37458SLiu Junliang 558*c9b37458SLiu Junliang MODULE_AUTHOR("liujl <liujunliang_ljl@163.com>"); 559*c9b37458SLiu Junliang MODULE_DESCRIPTION("SR9700 one chip USB 1.1 USB to Ethernet device from http://www.corechip-sz.com/"); 560*c9b37458SLiu Junliang MODULE_LICENSE("GPL"); 561