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