diff options
Diffstat (limited to 'drivers/net/usb/dm9601.c')
-rw-r--r-- | drivers/net/usb/dm9601.c | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 3f554c1149f3..d7e99445518e 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c | |||
@@ -45,6 +45,12 @@ | |||
45 | #define DM_MCAST_ADDR 0x16 /* 8 bytes */ | 45 | #define DM_MCAST_ADDR 0x16 /* 8 bytes */ |
46 | #define DM_GPR_CTRL 0x1e | 46 | #define DM_GPR_CTRL 0x1e |
47 | #define DM_GPR_DATA 0x1f | 47 | #define DM_GPR_DATA 0x1f |
48 | #define DM_CHIP_ID 0x2c | ||
49 | #define DM_MODE_CTRL 0x91 /* only on dm9620 */ | ||
50 | |||
51 | /* chip id values */ | ||
52 | #define ID_DM9601 0 | ||
53 | #define ID_DM9620 1 | ||
48 | 54 | ||
49 | #define DM_MAX_MCAST 64 | 55 | #define DM_MAX_MCAST 64 |
50 | #define DM_MCAST_SIZE 8 | 56 | #define DM_MCAST_SIZE 8 |
@@ -53,7 +59,6 @@ | |||
53 | #define DM_RX_OVERHEAD 7 /* 3 byte header + 4 byte crc tail */ | 59 | #define DM_RX_OVERHEAD 7 /* 3 byte header + 4 byte crc tail */ |
54 | #define DM_TIMEOUT 1000 | 60 | #define DM_TIMEOUT 1000 |
55 | 61 | ||
56 | |||
57 | static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data) | 62 | static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data) |
58 | { | 63 | { |
59 | int err; | 64 | int err; |
@@ -84,32 +89,23 @@ static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data) | |||
84 | 89 | ||
85 | static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) | 90 | static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) |
86 | { | 91 | { |
87 | return usbnet_write_cmd(dev, DM_WRITE_REGS, | 92 | return usbnet_write_cmd(dev, DM_WRITE_REG, |
88 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 93 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
89 | value, reg, NULL, 0); | 94 | value, reg, NULL, 0); |
90 | } | 95 | } |
91 | 96 | ||
92 | static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value, | 97 | static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) |
93 | u16 length, void *data) | ||
94 | { | 98 | { |
95 | usbnet_write_cmd_async(dev, DM_WRITE_REGS, | 99 | usbnet_write_cmd_async(dev, DM_WRITE_REGS, |
96 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 100 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
97 | value, reg, data, length); | 101 | 0, reg, data, length); |
98 | } | ||
99 | |||
100 | static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) | ||
101 | { | ||
102 | netdev_dbg(dev->net, "dm_write_async() reg=0x%02x length=%d\n", reg, length); | ||
103 | |||
104 | dm_write_async_helper(dev, reg, 0, length, data); | ||
105 | } | 102 | } |
106 | 103 | ||
107 | static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value) | 104 | static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value) |
108 | { | 105 | { |
109 | netdev_dbg(dev->net, "dm_write_reg_async() reg=0x%02x value=0x%02x\n", | 106 | usbnet_write_cmd_async(dev, DM_WRITE_REG, |
110 | reg, value); | 107 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
111 | 108 | value, reg, NULL, 0); | |
112 | dm_write_async_helper(dev, reg, value, 0, NULL); | ||
113 | } | 109 | } |
114 | 110 | ||
115 | static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value) | 111 | static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value) |
@@ -358,7 +354,7 @@ static const struct net_device_ops dm9601_netdev_ops = { | |||
358 | static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) | 354 | static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) |
359 | { | 355 | { |
360 | int ret; | 356 | int ret; |
361 | u8 mac[ETH_ALEN]; | 357 | u8 mac[ETH_ALEN], id; |
362 | 358 | ||
363 | ret = usbnet_get_endpoints(dev, intf); | 359 | ret = usbnet_get_endpoints(dev, intf); |
364 | if (ret) | 360 | if (ret) |
@@ -399,6 +395,24 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) | |||
399 | __dm9601_set_mac_address(dev); | 395 | __dm9601_set_mac_address(dev); |
400 | } | 396 | } |
401 | 397 | ||
398 | if (dm_read_reg(dev, DM_CHIP_ID, &id) < 0) { | ||
399 | netdev_err(dev->net, "Error reading chip ID\n"); | ||
400 | ret = -ENODEV; | ||
401 | goto out; | ||
402 | } | ||
403 | |||
404 | /* put dm9620 devices in dm9601 mode */ | ||
405 | if (id == ID_DM9620) { | ||
406 | u8 mode; | ||
407 | |||
408 | if (dm_read_reg(dev, DM_MODE_CTRL, &mode) < 0) { | ||
409 | netdev_err(dev->net, "Error reading MODE_CTRL\n"); | ||
410 | ret = -ENODEV; | ||
411 | goto out; | ||
412 | } | ||
413 | dm_write_reg(dev, DM_MODE_CTRL, mode & 0x7f); | ||
414 | } | ||
415 | |||
402 | /* power up phy */ | 416 | /* power up phy */ |
403 | dm_write_reg(dev, DM_GPR_CTRL, 1); | 417 | dm_write_reg(dev, DM_GPR_CTRL, 1); |
404 | dm_write_reg(dev, DM_GPR_DATA, 0); | 418 | dm_write_reg(dev, DM_GPR_DATA, 0); |
@@ -581,6 +595,10 @@ static const struct usb_device_id products[] = { | |||
581 | USB_DEVICE(0x0a46, 0x9000), /* DM9000E */ | 595 | USB_DEVICE(0x0a46, 0x9000), /* DM9000E */ |
582 | .driver_info = (unsigned long)&dm9601_info, | 596 | .driver_info = (unsigned long)&dm9601_info, |
583 | }, | 597 | }, |
598 | { | ||
599 | USB_DEVICE(0x0a46, 0x9620), /* DM9620 USB to Fast Ethernet Adapter */ | ||
600 | .driver_info = (unsigned long)&dm9601_info, | ||
601 | }, | ||
584 | {}, // END | 602 | {}, // END |
585 | }; | 603 | }; |
586 | 604 | ||