/*
* Copyright (c) 2011 The Chromium OS Authors.
- * See file CREDITS for list of people who contributed to this
- * project.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#define AX_CMD_READ_MII_REG 0x07
#define AX_CMD_WRITE_MII_REG 0x08
#define AX_CMD_SET_HW_MII 0x0a
+#define AX_CMD_READ_EEPROM 0x0b
#define AX_CMD_READ_RX_CTL 0x0f
#define AX_CMD_WRITE_RX_CTL 0x10
#define AX_CMD_WRITE_IPG0 0x12
#define FLAG_NONE 0
#define FLAG_TYPE_AX88172 (1U << 0)
#define FLAG_TYPE_AX88772 (1U << 1)
+#define FLAG_TYPE_AX88772B (1U << 2)
+#define FLAG_EEPROM_MAC (1U << 3) /* initial mac address in eeprom */
/* local vars */
static int curr_eth_dev; /* index for name of next device detected */
return r;
}
+static int asix_read_mac(struct eth_device *eth)
+{
+ struct ueth_data *dev = (struct ueth_data *)eth->priv;
+ struct asix_private *priv = (struct asix_private *)dev->dev_priv;
+ int i;
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN);
+
+ if (priv->flags & FLAG_EEPROM_MAC) {
+ for (i = 0; i < (ETH_ALEN >> 1); i++) {
+ if (asix_read_cmd(dev, AX_CMD_READ_EEPROM,
+ 0x04 + i, 0, 2, buf) < 0) {
+ debug("Failed to read SROM address 04h.\n");
+ return -1;
+ }
+ memcpy((eth->enetaddr + i * 2), buf, 2);
+ }
+ } else {
+ if (asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)
+ < 0) {
+ debug("Failed to read MAC address.\n");
+ return -1;
+ }
+ memcpy(eth->enetaddr, buf, ETH_ALEN);
+ }
+
+ return 0;
+}
+
static int asix_basic_reset(struct ueth_data *dev)
{
int embd_phy;
rx_ctl = asix_read_rx_ctl(dev);
debug("RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
- return 0;
-}
-
-/*
- * Asix callbacks
- */
-static int asix_init(struct eth_device *eth, bd_t *bd)
-{
- struct ueth_data *dev = (struct ueth_data *)eth->priv;
- int timeout = 0;
-#define TIMEOUT_RESOLUTION 50 /* ms */
- int link_detected;
-
- debug("** %s()\n", __func__);
-
- /* Get the MAC address */
- if (asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
- 0, 0, ETH_ALEN, buf) < 0) {
- debug("Failed to read MAC address.\n");
- goto out_err;
- }
- memcpy(eth->enetaddr, buf, ETH_ALEN);
- debug("MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
- eth->enetaddr[0], eth->enetaddr[1],
- eth->enetaddr[2], eth->enetaddr[3],
- eth->enetaddr[4], eth->enetaddr[5]);
-
dev->phy_id = asix_get_phy_addr(dev);
if (dev->phy_id < 0)
debug("Failed to read phy id\n");
- if (asix_sw_reset(dev, AX_SWRESET_PRL) < 0)
- goto out_err;
-
- if (asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL) < 0)
- goto out_err;
-
asix_mdio_write(dev, dev->phy_id, MII_BMCR, BMCR_RESET);
asix_mdio_write(dev, dev->phy_id, MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_CSMA);
mii_nway_restart(dev);
if (asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT) < 0)
- goto out_err;
+ return -1;
if (asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
AX88772_IPG2_DEFAULT, 0, NULL) < 0) {
debug("Write IPG,IPG1,IPG2 failed\n");
- goto out_err;
+ return -1;
}
+ return 0;
+}
+
+/*
+ * Asix callbacks
+ */
+static int asix_init(struct eth_device *eth, bd_t *bd)
+{
+ struct ueth_data *dev = (struct ueth_data *)eth->priv;
+ int timeout = 0;
+#define TIMEOUT_RESOLUTION 50 /* ms */
+ int link_detected;
+
+ debug("** %s()\n", __func__);
+
if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0)
goto out_err;
memcpy(msg, &packet_len, sizeof(packet_len));
memcpy(msg + sizeof(packet_len), (void *)packet, length);
- if (length & 1)
- length++;
err = usb_bulk_msg(dev->pusb_dev,
usb_sndbulkpipe(dev->pusb_dev, dev->ep_out),
}
memcpy(&packet_len, buf_ptr, sizeof(packet_len));
le32_to_cpus(&packet_len);
- if (((packet_len >> 16) ^ 0xffff) != (packet_len & 0xffff)) {
+ if (((~packet_len >> 16) & 0x7ff) != (packet_len & 0x7ff)) {
debug("Rx: malformed packet length: %#x (%#x:%#x)\n",
- packet_len, (packet_len >> 16) ^ 0xffff,
- packet_len & 0xffff);
+ packet_len, (~packet_len >> 16) & 0x7ff,
+ packet_len & 0x7ff);
return -1;
}
- packet_len = packet_len & 0xffff;
+ packet_len = packet_len & 0x7ff;
if (packet_len > actual_len - sizeof(packet_len)) {
debug("Rx: too large packet: %d\n", packet_len);
return -1;
int flags;
};
-static const struct asix_dongle const asix_dongles[] = {
+static const struct asix_dongle asix_dongles[] = {
{ 0x05ac, 0x1402, FLAG_TYPE_AX88772 }, /* Apple USB Ethernet Adapter */
{ 0x07d1, 0x3c05, FLAG_TYPE_AX88772 }, /* D-Link DUB-E100 H/W Ver B1 */
+ { 0x2001, 0x1a02, FLAG_TYPE_AX88772 }, /* D-Link DUB-E100 H/W Ver C1 */
/* Cables-to-Go USB Ethernet Adapter */
{ 0x0b95, 0x772a, FLAG_TYPE_AX88772 },
{ 0x0b95, 0x7720, FLAG_TYPE_AX88772 }, /* Trendnet TU2-ET100 V3.0R */
{ 0x1557, 0x7720, FLAG_TYPE_AX88772 }, /* 0Q0 cable ethernet */
/* DLink DUB-E100 H/W Ver B1 Alternate */
{ 0x2001, 0x3c05, FLAG_TYPE_AX88772 },
+ /* ASIX 88772B */
+ { 0x0b95, 0x772b, FLAG_TYPE_AX88772B | FLAG_EEPROM_MAC },
+ { 0x0b95, 0x7e2b, FLAG_TYPE_AX88772B },
{ 0x0000, 0x0000, FLAG_NONE } /* END - Do not remove */
};
{
struct usb_interface *iface;
struct usb_interface_descriptor *iface_desc;
+ int ep_in_found = 0, ep_out_found = 0;
int i;
/* let's examine the device now */
/* is it an BULK endpoint? */
if ((iface->ep_desc[i].bmAttributes &
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
- if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
- ss->ep_in = iface->ep_desc[i].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- else
- ss->ep_out =
- iface->ep_desc[i].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
+ u8 ep_addr = iface->ep_desc[i].bEndpointAddress;
+ if (ep_addr & USB_DIR_IN) {
+ if (!ep_in_found) {
+ ss->ep_in = ep_addr &
+ USB_ENDPOINT_NUMBER_MASK;
+ ep_in_found = 1;
+ }
+ } else {
+ if (!ep_out_found) {
+ ss->ep_out = ep_addr &
+ USB_ENDPOINT_NUMBER_MASK;
+ ep_out_found = 1;
+ }
+ }
}
/* is it an interrupt endpoint? */
if (asix_basic_reset(ss))
return 0;
+ /* Get the MAC address */
+ if (asix_read_mac(eth))
+ return 0;
+ debug("MAC %pM\n", eth->enetaddr);
+
return 1;
}