All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2] Add support for Microchip LAN78xx
@ 2017-03-10 18:38 Yuiko.Oshino at microchip.com
  2017-03-10 19:19 ` Marek Vasut
  2017-03-16 21:12 ` [U-Boot] [U-Boot,v2] " Tom Rini
  0 siblings, 2 replies; 12+ messages in thread
From: Yuiko.Oshino at microchip.com @ 2017-03-10 18:38 UTC (permalink / raw)
  To: u-boot

From: Yuiko Oshino <yuiko.oshino@microchip.com>

Add support for Microchip LAN7800 and 7850, USB to 10/100/1000 Ethernet Controllers

Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
Cc: Marek Vasut <marex@denx.de>
---
Changes for v2:
   - lan78xx.c header comment cleanup

 drivers/usb/eth/Makefile     |    1 +
 drivers/usb/eth/lan78xx.c    | 1319 ++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/eth/usb_ether.c  |    7 +
 include/usb_ether.h          |    6 +
 scripts/config_whitelist.txt |    1 +
 5 files changed, 1334 insertions(+)
 create mode 100644 drivers/usb/eth/lan78xx.c

diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile
index 4c44efc..aa8a6cf 100644
--- a/drivers/usb/eth/Makefile
+++ b/drivers/usb/eth/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_USB_ETHER_ASIX) += asix.o
 obj-$(CONFIG_USB_ETHER_ASIX88179) += asix88179.o
 obj-$(CONFIG_USB_ETHER_MCS7830) += mcs7830.o
 obj-$(CONFIG_USB_ETHER_SMSC95XX) += smsc95xx.o
+obj-$(CONFIG_USB_ETHER_LAN78XX) += lan78xx.o
 obj-$(CONFIG_USB_ETHER_RTL8152) += r8152.o r8152_fw.o
diff --git a/drivers/usb/eth/lan78xx.c b/drivers/usb/eth/lan78xx.c
new file mode 100644
index 0000000..bc25c16
--- /dev/null
+++ b/drivers/usb/eth/lan78xx.c
@@ -0,0 +1,1319 @@
+/*
+ * Copyright (c) 2017 Microchip Technology Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <usb.h>
+#include <linux/mii.h>
+#include "usb_ether.h"
+
+/* USB Vendor Requests */
+#define USB_VENDOR_REQUEST_WRITE_REGISTER	0xA0
+#define USB_VENDOR_REQUEST_READ_REGISTER	0xA1
+#define USB_VENDOR_REQUEST_GET_STATS		0xA2
+
+/* Tx Command A */
+#define TX_CMD_A_FCS_			(0x00400000)
+#define TX_CMD_A_LEN_MASK_		(0x000FFFFF)
+
+/* Rx Command A */
+#define RX_CMD_A_RX_ERRS_MASK_		(0xC03F0000)
+#define RX_CMD_A_RXE_			(0x00040000)
+#define RX_CMD_A_LEN_MASK_		(0x00003FFF)
+
+/* SCSRs */
+#define ID_REV				(0x00)
+#define ID_REV_CHIP_ID_MASK_		(0xFFFF0000)
+#define ID_REV_CHIP_REV_MASK_		(0x0000FFFF)
+#define ID_REV_CHIP_ID_7800_		(0x7800)
+#define ID_REV_CHIP_ID_7850_		(0x7850)
+
+#define INT_STS				(0x0C)
+
+#define HW_CFG				(0x010)
+#define HW_CFG_LED1_EN_			(0x00200000)
+#define HW_CFG_LED0_EN_			(0x00100000) /* Muxed with EEDO */
+#define HW_CFG_LRST_			(0x00000002) /* Mused with EECLK */
+#define HW_CFG_SRST_			(0x00000001)
+
+#define PMT_CTL				(0x014)
+#define PMT_CTL_READY_			(0x00000080)
+#define PMT_CTL_PHY_RST_		(0x00000010)
+
+#define E2P_CMD				(0x040)
+#define E2P_CMD_EPC_BUSY_		(0x80000000)
+#define E2P_CMD_EPC_CMD_MASK_		(0x70000000)
+#define E2P_CMD_EPC_CMD_READ_		(0x00000000)
+#define E2P_CMD_EPC_TIMEOUT_		(0x00000400)
+#define E2P_CMD_EPC_ADDR_MASK_		(0x000001FF)
+
+#define E2P_DATA			(0x044)
+#define E2P_DATA_EEPROM_DATA_MASK_	(0x000000FF)
+
+#define USB_CFG0			(0x080)
+#define USB_CFG_BIR_			(0x00000040)
+
+#define BURST_CAP			(0x090)
+#define BURST_CAP_SIZE_MASK_		(0x000000FF)
+
+#define BULK_IN_DLY			(0x094)
+#define BULK_IN_DLY_MASK_		(0x0000FFFF)
+
+#define RFE_CTL				(0x0B0)
+#define RFE_CTL_BCAST_EN_		(0x00000400)
+#define RFE_CTL_MCAST_EN_		(0x00000200)
+#define RFE_CTL_UCAST_EN_		(0x00000100)
+#define RFE_CTL_DA_PERFECT_		(0x00000002)
+
+#define FCT_RX_CTL			(0x0C0)
+#define FCT_RX_CTL_EN_			(0x80000000)
+
+#define FCT_TX_CTL			(0x0C4)
+#define FCT_TX_CTL_EN_			(0x80000000)
+
+#define FCT_RX_FIFO_END			(0x0C8)
+#define FCT_RX_FIFO_END_MASK_		(0x0000007F)
+
+#define FCT_TX_FIFO_END			(0x0CC)
+#define FCT_TX_FIFO_END_MASK_		(0x0000003F)
+
+#define FCT_FLOW			(0x0D0)
+
+#define MAC_CR				(0x100)
+#define MAC_CR_ADP_			(0x00002000)
+#define MAC_CR_AUTO_DUPLEX_		(0x00001000)
+#define MAC_CR_AUTO_SPEED_		(0x00000800)
+
+#define MAC_RX				(0x104)
+#define MAC_RX_MAX_SIZE_SHIFT_		(16)
+#define MAC_RX_MAX_SIZE_MASK_		(0x3FFF0000)
+#define MAC_RX_FCS_STRIP_		(0x00000010)
+#define MAC_RX_RXD_			(0x00000002)
+#define MAC_RX_RXEN_			(0x00000001)
+
+#define MAC_TX				(0x108)
+#define MAC_TX_BAD_FCS_			(0x00000004)
+#define MAC_TX_TXD_			(0x00000002)
+#define MAC_TX_TXEN_			(0x00000001)
+
+#define FLOW				(0x10C)
+#define FLOW_CR_TX_FCEN_		(0x40000000)
+#define FLOW_CR_RX_FCEN_		(0x20000000)
+
+#define RX_ADDRH			(0x118)
+#define RX_ADDRH_MASK_			(0x0000FFFF)
+
+#define RX_ADDRL			(0x11C)
+#define RX_ADDRL_MASK_			(0xFFFFFFFF)
+
+#define MII_ACC				(0x120)
+#define MII_ACC_MII_READ_		(0x00000000)
+#define MII_ACC_MII_WRITE_		(0x00000002)
+#define MII_ACC_MII_BUSY_		(0x00000001)
+
+#define MII_DATA			(0x124)
+#define MII_DATA_MASK_			(0x0000FFFF)
+
+#define MAF_BASE			(0x400)
+#define MAF_HIX				(0x00)
+#define MAF_LOX				(0x04)
+#define NUM_OF_MAF			(33)
+#define MAF_HI_BEGIN			(MAF_BASE + MAF_HIX)
+#define MAF_LO_BEGIN			(MAF_BASE + MAF_LOX)
+#define MAF_HI(index)			(MAF_BASE + (8 * (index)) + (MAF_HIX))
+#define MAF_LO(index)			(MAF_BASE + (8 * (index)) + (MAF_LOX))
+#define MAF_HI_VALID_			(0x80000000)
+#define MAF_HI_TYPE_MASK_		(0x40000000)
+#define MAF_HI_TYPE_SRC_		(0x40000000)
+#define MAF_HI_TYPE_DST_		(0x00000000)
+#define MAF_HI_ADDR_MASK		(0x0000FFFF)
+#define MAF_LO_ADDR_MASK		(0xFFFFFFFF)
+
+#define OTP_BASE_ADDR			(0x00001000)
+
+#define OTP_PWR_DN			(OTP_BASE_ADDR + 4 * 0x00)
+#define OTP_PWR_DN_PWRDN_N_		(0x01)
+
+#define OTP_ADDR1			(OTP_BASE_ADDR + 4 * 0x01)
+#define OTP_ADDR1_15_11			(0x1F)
+
+#define OTP_ADDR2			(OTP_BASE_ADDR + 4 * 0x02)
+#define OTP_ADDR2_10_3			(0xFF)
+
+#define OTP_PRGM_DATA			(OTP_BASE_ADDR + 4 * 0x04)
+
+#define OTP_RD_DATA			(OTP_BASE_ADDR + 4 * 0x06)
+
+#define OTP_FUNC_CMD			(OTP_BASE_ADDR + 4 * 0x08)
+#define OTP_FUNC_CMD_READ_		(0x01)
+
+#define OTP_CMD_GO			(OTP_BASE_ADDR + 4 * 0x0A)
+#define OTP_CMD_GO_GO_			(0x01)
+
+#define OTP_STATUS			(OTP_BASE_ADDR + 4 * 0x0C)
+#define OTP_STATUS_BUSY_		(0x01)
+
+#define SS_USB_PKT_SIZE			(1024)
+#define HS_USB_PKT_SIZE			(512)
+#define FS_USB_PKT_SIZE			(64)
+
+#define MAX_RX_FIFO_SIZE		(12 * 1024)
+#define MAX_TX_FIFO_SIZE		(12 * 1024)
+#define DEFAULT_BURST_CAP_SIZE		(MAX_TX_FIFO_SIZE)
+#define DEFAULT_BULK_IN_DELAY		(0x0800)
+#define MAX_SINGLE_PACKET_SIZE		(9000)
+#define TX_OVERHEAD			(8)
+#define RXW_PADDING			2
+
+#define LAN78XX_USB_VENDOR_ID		(0x0424)
+#define LAN7800_USB_PRODUCT_ID		(0x7800)
+#define LAN7850_USB_PRODUCT_ID		(0x7850)
+#define LAN78XX_EEPROM_MAGIC		(0x78A5)
+#define LAN78XX_OTP_MAGIC		(0x78F3)
+
+#define EEPROM_INDICATOR		(0xA5)
+#define EEPROM_MAC_OFFSET		(0x01)
+#define MAX_EEPROM_SIZE			512
+#define OTP_INDICATOR_1			(0xF3)
+#define OTP_INDICATOR_2			(0xF7)
+
+/* Vendor-specific PHY Definitions */
+#define PHY_INT_MASK			(25)
+#define PHY_INT_MASK_ANEG_COMP_		((u16)0x0400)
+#define PHY_INT_MASK_LINK_DOWN_		((u16)0x0004)
+#define PHY_INT_MASK_DEFAULT_		(PHY_INT_MASK_ANEG_COMP_ | \
+					 PHY_INT_MASK_LINK_DOWN_)
+
+#define PHY_INT_STS			(26)
+
+/* Ethernet PHY Auxiliary Control and Status Register */
+#define PHY_ACSR			(28)
+#define PHY_ACSR_DUP			(0x0020)	/* 1 is FULL */
+#define PHY_ACSR_SPD_MASK		(0x0018)
+#define PHY_ACSR_SPD_10			(0x0000)
+#define PHY_ACSR_SPD_100		(0x0008)
+#define PHY_ACSR_SPD_1000		(0x0010)
+
+/* Some extra defines */
+#define DEFAULT_HS_BURST_CAP_SIZE	(5 * HS_USB_PKT_SIZE)
+#define DEFAULT_FS_BURST_CAP_SIZE	(33 * FS_USB_PKT_SIZE)
+#define LAN78XX_INTERNAL_PHY_ID		1
+
+#define LAN78XX_MAC_RX_MAX_SIZE(mtu) \
+	((mtu) << 16)			/**< Max frame size */
+#define LAN78XX_MAC_RX_MAX_SIZE_DEFAULT \
+	LAN78XX_MAC_RX_MAX_SIZE(ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */)
+/*
+ * timeouts, in milliseconds, used for sending/receiving control messages
+ * they typically complete within a few frames (msec) after they're issued
+ * USB identifies 5 second timeouts, maybe more in a few cases, and a few
+ * slow devices (like some MGE Ellipse UPSes) actually push that limit.
+ */
+/* local defines */
+#define LAN78XX_BASE_NAME "78xx"
+#define USB_CTRL_SET_TIMEOUT 5000
+#define USB_CTRL_GET_TIMEOUT 5000
+#define USB_BULK_SEND_TIMEOUT 5000
+#define USB_BULK_RECV_TIMEOUT 5000
+
+#define RX_URB_SIZE 2048
+#define PHY_CONNECT_TIMEOUT 5000
+
+#ifndef CONFIG_DM_ETH
+/* local vars */
+static int curr_eth_dev;	/* index for name of next device detected */
+#endif
+
+/* driver private */
+struct lan78xx_private {
+#ifdef CONFIG_DM_ETH
+	struct ueth_data ueth;
+#endif
+	size_t rx_urb_size;	/* maximum USB URB size */
+	u32 mac_cr;		/* MAC control register value */
+	int have_hwaddr;	/* 1 if we have a hardware MAC address */
+};
+
+/*
+ * Lan78xx infrastructure commands
+ */
+static int lan78xx_write_reg(struct usb_device *udev, u32 index, u32 data)
+{
+	int len;
+	ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
+
+	cpu_to_le32s(&data);
+	tmpbuf[0] = data;
+
+	len = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			USB_VENDOR_REQUEST_WRITE_REGISTER,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			0, index, tmpbuf, sizeof(data),
+			USB_CTRL_SET_TIMEOUT);
+	if (len != sizeof(data)) {
+		debug("lan78xx_write_reg failed: index=%d, data=%d, len=%d",
+		      index, data, len);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int lan78xx_read_reg(struct usb_device *udev, u32 index, u32 *data)
+{
+	int len;
+	ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
+
+	len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+			USB_VENDOR_REQUEST_READ_REGISTER,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			0, index, tmpbuf, sizeof(*data),
+			USB_CTRL_GET_TIMEOUT);
+	*data = tmpbuf[0];
+	if (len != sizeof(*data)) {
+		debug("lan78xx_read_reg failed: index=%d, len=%d", index, len);
+		return -EIO;
+	}
+
+	le32_to_cpus(data);
+	return 0;
+}
+
+/* Loop until the read is completed with timeout */
+static int lan78xx_phy_wait_not_busy(struct usb_device *udev)
+{
+	unsigned long start_time = get_timer(0);
+	u32 val;
+
+	do {
+		lan78xx_read_reg(udev, MII_ACC, &val);
+		if (!(val & MII_ACC_MII_BUSY_))
+			return 0;
+	} while (get_timer(start_time) < 1000);
+
+	return -ETIMEDOUT;
+}
+
+static int lan78xx_mdio_read(struct usb_device *udev, int phy_id, int idx)
+{
+	u32 val, addr;
+
+	/* confirm MII not busy */
+	if (lan78xx_phy_wait_not_busy(udev)) {
+		debug("MII is busy in lan78xx_mdio_read\n");
+		return -ETIMEDOUT;
+	}
+
+	/* set the address, index & direction (read from PHY) */
+	addr = (phy_id << 11) | (idx << 6) |
+		MII_ACC_MII_READ_ | MII_ACC_MII_BUSY_;
+	lan78xx_write_reg(udev, MII_ACC, addr);
+
+	if (lan78xx_phy_wait_not_busy(udev)) {
+		debug("Timed out reading MII reg %02X\n", idx);
+		return -ETIMEDOUT;
+	}
+
+	lan78xx_read_reg(udev, MII_DATA, &val);
+
+	return (u16) (val & 0xFFFF);
+}
+
+static void lan78xx_mdio_write(struct usb_device *udev, int phy_id, int idx,
+				int regval)
+{
+	u32 val, addr;
+
+	/* confirm MII not busy */
+	if (lan78xx_phy_wait_not_busy(udev)) {
+		debug("MII is busy in lan78xx_mdio_write\n");
+		return;
+	}
+
+	val = regval;
+	lan78xx_write_reg(udev, MII_DATA, val);
+
+	/* set the address, index & direction (write to PHY) */
+	addr = (phy_id << 11) | (idx << 6) |
+		MII_ACC_MII_WRITE_ | MII_ACC_MII_BUSY_;
+	lan78xx_write_reg(udev, MII_ACC, addr);
+
+	if (lan78xx_phy_wait_not_busy(udev))
+		debug("Timed out writing MII reg %02X\n", idx);
+}
+
+static int lan78xx_eeprom_confirm_not_busy(struct usb_device *udev)
+{
+	unsigned long start_time = get_timer(0);
+	u32 val;
+
+	do {
+		lan78xx_read_reg(udev, E2P_CMD, &val);
+		if (!(val & E2P_CMD_EPC_BUSY_))
+			return 0;
+		udelay(40);
+	} while (get_timer(start_time) < 1000);
+
+	debug("EEPROM is busy\n");
+	return -ETIMEDOUT;
+}
+
+static int lan78xx_wait_eeprom(struct usb_device *udev)
+{
+	unsigned long start_time = get_timer(0);
+	u32 val;
+
+	do {
+		lan78xx_read_reg(udev, E2P_CMD, &val);
+		if (!(val & E2P_CMD_EPC_BUSY_) || (val & E2P_CMD_EPC_TIMEOUT_))
+			break;
+		udelay(40);
+	} while (get_timer(start_time) < 1000);
+
+	if (val & (E2P_CMD_EPC_TIMEOUT_ | E2P_CMD_EPC_BUSY_)) {
+		debug("EEPROM read operation timeout\n");
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int lan78xx_read_eeprom(struct usb_device *udev, u32
+				offset, u32 length, u8 *data)
+{
+	u32 val, chipid;
+	int i, ret;
+	int saved = 0;
+
+	/* depends on chip, some EEPROM pins are muxed with LED function.
+	 * disable & restore LED function to access EEPROM.
+	 */
+	ret = lan78xx_read_reg(udev, ID_REV, &chipid);
+	if (ret < 0)
+		return ret;
+	chipid = (chipid & ID_REV_CHIP_ID_MASK_) >> 16;
+	if ((chipid == ID_REV_CHIP_ID_7800_) ||
+	    (chipid == ID_REV_CHIP_ID_7850_)) {
+		ret = lan78xx_read_reg(udev, HW_CFG, &val);
+		saved = val;
+		val &= ~(HW_CFG_LED1_EN_ | HW_CFG_LED0_EN_);
+		ret = lan78xx_write_reg(udev, HW_CFG, val);
+		if (ret)
+			goto exit;
+	}
+
+	ret = lan78xx_eeprom_confirm_not_busy(udev);
+	if (ret)
+		goto exit;
+
+	for (i = 0; i < length; i++) {
+		val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_ |
+			(offset & E2P_CMD_EPC_ADDR_MASK_);
+		lan78xx_write_reg(udev, E2P_CMD, val);
+
+		ret = lan78xx_wait_eeprom(udev);
+		if (ret < 0)
+			goto exit;
+
+		lan78xx_read_reg(udev, E2P_DATA, &val);
+		data[i] = val & 0xFF;
+		offset++;
+	}
+	ret = 0;
+
+exit:
+	if ((chipid == ID_REV_CHIP_ID_7800_) ||
+	    (chipid == ID_REV_CHIP_ID_7850_)) {
+		ret = lan78xx_write_reg(udev, HW_CFG, saved);
+	}
+	return ret;
+}
+
+/*
+ * mii_nway_restart - restart NWay (autonegotiation) for this interface
+ *
+ * Returns 0 on success, negative on error.
+ */
+static int mii_nway_restart(struct usb_device *udev, struct ueth_data *dev)
+{
+	int bmcr;
+	int r = -1;
+
+	/* if autoneg is off, it's an error */
+	bmcr = lan78xx_mdio_read(udev, dev->phy_id, MII_BMCR);
+
+	if (bmcr & BMCR_ANENABLE) {
+		bmcr |= BMCR_ANRESTART;
+		lan78xx_mdio_write(udev, dev->phy_id, MII_BMCR, bmcr);
+		r = 0;
+	} else {
+		debug("ERROR! phy autoneg is off. BMCR = 0x%08x\n", bmcr);
+	}
+	return r;
+}
+
+static int lan78xx_phy_initialize(struct usb_device *udev,
+					struct ueth_data *dev)
+{
+	int r;
+
+	lan78xx_mdio_write(udev, dev->phy_id, MII_BMCR, BMCR_RESET);
+	lan78xx_mdio_write(udev, dev->phy_id, MII_ADVERTISE,
+			   ADVERTISE_ALL | ADVERTISE_CSMA |
+			   ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+
+	/* read to clear */
+	lan78xx_mdio_read(udev, dev->phy_id, PHY_INT_STS);
+
+	lan78xx_mdio_write(udev, dev->phy_id, PHY_INT_MASK,
+			   PHY_INT_MASK_DEFAULT_);
+	r = mii_nway_restart(udev, dev);
+
+	if (r == 0)
+		debug("phy initialised succesfully\n");
+	else
+		debug("phy initialised failed id=%d\n", dev->phy_id);
+	return 0;
+}
+
+static int lan78xx_update_flowcontrol(struct usb_device *udev,
+					struct ueth_data *dev)
+{
+	uint32_t lcladv, rmtadv, acsr;
+	uint32_t flow = 0, fct_flow = 0;
+	u8 cap = 0;
+	int ret;
+
+	lcladv = lan78xx_mdio_read(udev, dev->phy_id, MII_ADVERTISE);
+	rmtadv = lan78xx_mdio_read(udev, dev->phy_id, MII_LPA);
+	acsr = lan78xx_mdio_read(udev, dev->phy_id, PHY_ACSR);
+
+	printf("LAN78xx linked at ");
+
+	if ((acsr & PHY_ACSR_SPD_MASK) == PHY_ACSR_SPD_10)
+		printf("10 ");
+	if ((acsr & PHY_ACSR_SPD_MASK) == PHY_ACSR_SPD_100)
+		printf("100 ");
+	if ((acsr & PHY_ACSR_SPD_MASK) == PHY_ACSR_SPD_1000)
+		printf("1000 ");
+
+	if (acsr & PHY_ACSR_DUP) {
+		printf("full dup ");
+		if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) {
+			cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+		} else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) {
+			if (lcladv & ADVERTISE_PAUSE_CAP)
+				cap = FLOW_CTRL_RX;
+			else if (rmtadv & LPA_PAUSE_CAP)
+				cap = FLOW_CTRL_TX;
+		}
+		printf("TX Flow ");
+		if (cap & FLOW_CTRL_TX) {
+			flow = (FLOW_CR_TX_FCEN_ | 0xFFFF);
+			/* set fct_flow thresholds to 20% and 80% */
+			fct_flow = (((MAX_RX_FIFO_SIZE * 2) / (10 * 512))
+					& 0x7FUL);
+			fct_flow <<= 8UL;
+			fct_flow |= (((MAX_RX_FIFO_SIZE * 8) / (10 * 512))
+					& 0x7FUL);
+			printf("EN ");
+		} else {
+			printf("DIS ");
+		}
+		printf("RX Flow ");
+		if (cap & FLOW_CTRL_RX) {
+			flow |= FLOW_CR_RX_FCEN_;
+			printf("EN");
+		} else {
+			printf("DIS");
+		}
+	} else {
+		printf("half dup");
+	}
+	printf("\n");
+
+	ret = lan78xx_write_reg(udev, FLOW, flow);
+	ret = lan78xx_write_reg(udev, FCT_FLOW, fct_flow);
+	return ret;
+}
+
+static int lan78xx_read_raw_otp(struct usb_device *udev, u32 offset,
+				u32 length, u8 *data)
+{
+	int i;
+	int ret;
+	u32 buf;
+	unsigned long start_time = get_timer(0);
+
+	ret = lan78xx_read_reg(udev, OTP_PWR_DN, &buf);
+	if (ret != 0)
+		return ret;
+
+	if (buf & OTP_PWR_DN_PWRDN_N_) {
+		/* clear it and wait to be cleared */
+		ret = lan78xx_write_reg(udev, OTP_PWR_DN, 0);
+
+		do {
+			udelay(10);
+			ret = lan78xx_read_reg(udev, OTP_PWR_DN, &buf);
+			if (get_timer(start_time) > 1000) {
+				printf("timeout on OTP_PWR_DN");
+				return -EIO;
+			}
+		} while (buf & OTP_PWR_DN_PWRDN_N_);
+	}
+
+	for (i = 0; i < length; i++) {
+		ret = lan78xx_write_reg(udev, OTP_ADDR1,
+					((offset + i) >> 8) &
+					OTP_ADDR1_15_11);
+		ret = lan78xx_write_reg(udev, OTP_ADDR2,
+					((offset + i) & OTP_ADDR2_10_3));
+
+		ret = lan78xx_write_reg(udev, OTP_FUNC_CMD,
+					OTP_FUNC_CMD_READ_);
+		ret = lan78xx_write_reg(udev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+
+		if (ret != 0)
+			return ret;
+
+		start_time = get_timer(0);
+		do {
+			udelay(1);
+			ret = lan78xx_read_reg(udev, OTP_STATUS, &buf);
+			if (get_timer(start_time) > 1000) {
+				printf("LAN78xx: timeout on OTP_STATUS");
+				return -EIO;
+			}
+		} while (buf & OTP_STATUS_BUSY_);
+
+		ret = lan78xx_read_reg(udev, OTP_RD_DATA, &buf);
+
+		data[i] = (u8)(buf & 0xFF);
+	}
+
+	return 0;
+}
+
+static int lan78xx_read_otp(struct usb_device *udev, u32 offset,
+			    u32 length, u8 *data)
+{
+	u8 sig;
+	int ret;
+
+	ret = lan78xx_read_raw_otp(udev, 0, 1, &sig);
+
+	if (ret == 0) {
+		if (sig == OTP_INDICATOR_1)
+			offset = offset;
+		else if (sig == OTP_INDICATOR_2)
+			offset += 0x100;
+		else
+			ret = -EINVAL;
+		ret = lan78xx_read_raw_otp(udev, offset, length, data);
+	}
+	debug("LAN78xx: MAC address from OTP = %pM\n", data);
+
+	return ret;
+}
+
+static int lan78xx_read_mac(unsigned char *enetaddr,
+					struct usb_device *udev)
+{
+	int ret;
+
+	memset(enetaddr, 0, 6);
+	/* refer to the doc/README.enetaddr and doc/README.usb for
+	 * the U-Boot MAC address policy
+	 */
+	/* try reading mac address from EEPROM, then from OTP */
+	ret = lan78xx_read_eeprom(udev, 0, 1, enetaddr);
+	if ((ret == 0) && (enetaddr[0] == EEPROM_INDICATOR)) {
+		ret = lan78xx_read_eeprom(udev,
+					  EEPROM_MAC_OFFSET, ETH_ALEN,
+					  enetaddr);
+		if ((ret == 0) && (is_valid_ethaddr(enetaddr))) {
+			/* eeprom values are valid so use them */
+			debug("MAC address read from EEPROM %pM\n",
+			      enetaddr);
+			return 0;
+		}
+	}
+	debug("MAC address read from EEPROM invalid %pM\n", enetaddr);
+
+	memset(enetaddr, 0, 6);
+	/* try reading mac address from OTP */
+	ret = lan78xx_read_otp(udev,
+			       EEPROM_MAC_OFFSET,
+			       ETH_ALEN,
+			       enetaddr);
+	if ((ret == 0) && (is_valid_ethaddr(enetaddr))) {
+		/* eeprom values are valid so use them */
+		debug("MAC address read from OTP %pM\n", enetaddr);
+		return 0;
+	}
+	debug("MAC address read from OTP invalid %pM\n", enetaddr);
+
+	memset(enetaddr, 0, 6);
+	return 0;
+}
+
+static int lan78xx_write_hwaddr_common(struct usb_device *udev,
+					struct lan78xx_private *priv,
+					unsigned char *enetaddr)
+{
+	u32 addr_lo = get_unaligned_le32(&enetaddr[0]);
+	u32 addr_hi = get_unaligned_le16(&enetaddr[4]);
+	int ret;
+
+	/* set hardware address */
+	ret = lan78xx_write_reg(udev, RX_ADDRL, addr_lo);
+	if (ret < 0)
+		return ret;
+
+	ret = lan78xx_write_reg(udev, RX_ADDRH, addr_hi);
+	if (ret < 0)
+		return ret;
+
+	ret = lan78xx_write_reg(udev, MAF_LO(0), addr_lo);
+	if (ret < 0)
+		return ret;
+
+	ret = lan78xx_write_reg(udev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
+	if (ret < 0)
+		return ret;
+
+	debug("MAC addr %pM written\n", enetaddr);
+	priv->have_hwaddr = 1;
+
+	return 0;
+}
+
+static int lan78xx_set_multicast(struct usb_device *udev,
+				 struct lan78xx_private *priv)
+{
+	int ret;
+	u32 write_buf;
+
+	/* No multicast in u-boot */
+	write_buf = RFE_CTL_BCAST_EN_ | RFE_CTL_DA_PERFECT_;
+	ret = lan78xx_write_reg(udev, RFE_CTL, write_buf);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* starts the TX path */
+static void lan78xx_start_tx_path(struct usb_device *udev,
+					struct lan78xx_private *priv)
+{
+	u32 reg_val;
+
+	/* Enable Tx at MAC */
+	reg_val = MAC_TX_TXEN_;
+	lan78xx_write_reg(udev, MAC_TX, reg_val);
+
+	/* Enable Tx at SCSRs */
+	reg_val = FCT_TX_CTL_EN_;
+	lan78xx_write_reg(udev, FCT_TX_CTL, reg_val);
+}
+
+/* Starts the Receive path */
+static void lan78xx_start_rx_path(struct usb_device *udev,
+					struct lan78xx_private *priv)
+{
+	u32 reg_val;
+
+	/* Enable Rx at MAC */
+	reg_val = LAN78XX_MAC_RX_MAX_SIZE_DEFAULT |
+		MAC_RX_FCS_STRIP_ | MAC_RX_RXEN_;
+	lan78xx_write_reg(udev, MAC_RX, reg_val);
+
+	/* Enable Rx@SCSRs */
+	reg_val = FCT_RX_CTL_EN_;
+	lan78xx_write_reg(udev, FCT_RX_CTL, reg_val);
+}
+
+static int lan78xx_basic_reset(struct usb_device *udev,
+				struct ueth_data *dev)
+{
+	int ret;
+	u32 write_buf;
+	u32 read_buf;
+	int timeout;
+#define TIMEOUT_RESOLUTION 50	/* ms */
+
+	dev->phy_id = LAN78XX_INTERNAL_PHY_ID;	/* fixed phy id */
+
+	write_buf = HW_CFG_LRST_;
+	ret = lan78xx_write_reg(udev, HW_CFG, write_buf);
+	if (ret < 0)
+		return ret;
+
+	timeout = 0;
+	do {
+		ret = lan78xx_read_reg(udev, HW_CFG, &read_buf);
+		if (ret < 0)
+			return ret;
+		udelay(10 * 1000);
+		timeout++;
+	} while ((read_buf & HW_CFG_LRST_) && (timeout < 100));
+
+	if (timeout >= 100) {
+		debug("timeout waiting for completion of Lite Reset\n");
+		return -ETIMEDOUT;
+	}
+
+	write_buf = PMT_CTL_PHY_RST_;
+	ret = lan78xx_write_reg(udev, PMT_CTL, write_buf);
+	if (ret < 0)
+		return ret;
+
+	timeout = 0;
+	do {
+		ret = lan78xx_read_reg(udev, PMT_CTL, &read_buf);
+		if (ret < 0)
+			return ret;
+		udelay(10 * 1000);
+		timeout++;
+		if (timeout >= 100)
+			break;
+
+	/* for LAN78xx, we need to check PMT_CTL_READY_ asserted */
+	} while ((read_buf & PMT_CTL_PHY_RST_) || !(read_buf & PMT_CTL_READY_));
+	if (timeout >= 100) {
+		debug("timeout waiting for PHY Reset\n");
+		return -ETIMEDOUT;
+	}
+
+	/* Respond to the IN token with a NAK */
+	ret = lan78xx_read_reg(udev, USB_CFG0, &write_buf);
+	if (ret < 0)
+		return ret;
+	write_buf |= USB_CFG_BIR_;
+	ret = lan78xx_write_reg(udev, USB_CFG0, write_buf);
+	if (ret < 0)
+		return ret;
+
+
+	return 0;
+}
+
+static int lan78xx_init_common(struct usb_device *udev,
+				struct ueth_data *dev,
+				struct lan78xx_private *priv,
+				unsigned char *enetaddr)
+{
+	int ret;
+	u32 write_buf;
+	u32 read_buf;
+	u32 burst_cap;
+	int timeout;
+#define TIMEOUT_RESOLUTION 50	/* ms */
+	int link_detected;
+
+	/* Reset and read Mac addr were done in get_info() or in probe() */
+
+	ret = lan78xx_read_reg(udev, MAC_CR, &write_buf);
+	if (ret < 0)
+		return ret;
+	write_buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_ | MAC_CR_ADP_;
+	ret = lan78xx_write_reg(udev, MAC_CR, write_buf);
+	if (ret < 0)
+		return ret;
+
+#ifndef CONFIG_DM_ETH
+	if (!priv->have_hwaddr && (is_valid_ethaddr(enetaddr))) {
+		priv->have_hwaddr = 1;
+		debug("LAN78xx: MAC address found and set %pM\n", enetaddr);
+	}
+#endif
+	if (!priv->have_hwaddr) {
+		printf("Error: LAN78xx: No MAC address set - set usbethaddr\n");
+		return -EADDRNOTAVAIL;
+	}
+	ret = lan78xx_write_hwaddr_common(udev, priv, enetaddr);
+	if (ret < 0)
+		return ret;
+
+	burst_cap = 0;
+	priv->rx_urb_size = RX_URB_SIZE;
+
+	debug("rx_urb_size=%ld\n", (ulong) priv->rx_urb_size);
+
+	ret = lan78xx_write_reg(udev, BURST_CAP, burst_cap);
+	if (ret < 0)
+		return ret;
+
+	read_buf = DEFAULT_BULK_IN_DELAY;
+	ret = lan78xx_write_reg(udev, BULK_IN_DLY, read_buf);
+	if (ret < 0)
+		return ret;
+
+	write_buf = 0xFFFFFFFF;
+	ret = lan78xx_write_reg(udev, INT_STS, write_buf);
+	if (ret < 0)
+		return ret;
+
+	ret = lan78xx_read_reg(udev, ID_REV, &read_buf);
+	if (ret < 0)
+		return ret;
+	debug("LAN78xx ID_REV = 0x%08x\n", read_buf);
+
+	/* set FIFO sizes */
+	write_buf = (MAX_RX_FIFO_SIZE - 512) / 512;
+	ret = lan78xx_write_reg(udev, FCT_RX_FIFO_END, write_buf);
+	if (ret < 0)
+		return ret;
+
+	write_buf = (MAX_TX_FIFO_SIZE - 512) / 512;
+	ret = lan78xx_write_reg(udev, FCT_TX_FIFO_END, write_buf);
+	if (ret < 0)
+		return ret;
+
+	/* Init Tx */
+	write_buf = 0;
+	ret = lan78xx_write_reg(udev, FLOW, write_buf);
+	if (ret < 0)
+		return ret;
+
+	ret = lan78xx_read_reg(udev, MAC_CR, &priv->mac_cr);
+	if (ret < 0)
+		return ret;
+
+	/* Init Rx. Set Vlan, keep defult for VLAN on 78xx */
+	ret = lan78xx_set_multicast(udev, priv);
+	if (ret < 0)
+		return ret;
+
+	ret = lan78xx_phy_initialize(udev, dev);
+	if (ret < 0)
+		return ret;
+
+	lan78xx_start_tx_path(udev, priv);
+	lan78xx_start_rx_path(udev, priv);
+
+	timeout = 0;
+	do {
+		link_detected = lan78xx_mdio_read(udev, dev->phy_id, MII_BMSR)
+			& BMSR_LSTATUS;
+		if (!link_detected) {
+			if (timeout == 0) {
+				printf("LAN78xx: ");
+				printf("Waiting for Ethernet connection... ");
+			}
+			udelay(TIMEOUT_RESOLUTION * 1000);
+			timeout += TIMEOUT_RESOLUTION;
+		}
+	} while (!link_detected && timeout < PHY_CONNECT_TIMEOUT);
+	if (link_detected) {
+		if (timeout != 0)
+			printf("done.\n");
+		else
+			printf("LAN78xx: Ethernet connection done.\n");
+
+		link_detected = lan78xx_mdio_read(udev, dev->phy_id, MII_BMSR);
+		debug("MII_BMSR=0x%08x\n", link_detected);
+
+		ret = lan78xx_update_flowcontrol(udev, dev);
+		if (ret < 0)
+			return ret;
+
+	} else {
+		printf("unable to connect.\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int lan78xx_send_common(struct ueth_data *dev, void *packet, int length)
+{
+	int err;
+	int actual_len;
+	u32 tx_cmd_a;
+	u32 tx_cmd_b;
+	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
+				 PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b));
+
+	debug("** %s(), len %d, buf %#x\n", __func__, length,
+	      (unsigned int)(ulong) msg);
+	if (length > PKTSIZE)
+		return -ENOSPC;
+
+	/* LAN78xx disable all TX offload features for u-boot */
+	tx_cmd_a = (u32) (length & TX_CMD_A_LEN_MASK_) | TX_CMD_A_FCS_;
+	tx_cmd_b = 0;
+	cpu_to_le32s(&tx_cmd_a);
+	cpu_to_le32s(&tx_cmd_b);
+
+	/* prepend cmd_a and cmd_b */
+	memcpy(msg, &tx_cmd_a, sizeof(tx_cmd_a));
+	memcpy(msg + sizeof(tx_cmd_a), &tx_cmd_b, sizeof(tx_cmd_b));
+	memcpy(msg + sizeof(tx_cmd_a) + sizeof(tx_cmd_b), (void *)packet,
+	       length);
+	err = usb_bulk_msg(dev->pusb_dev,
+			usb_sndbulkpipe(dev->pusb_dev, dev->ep_out),
+			(void *)msg,
+			length + sizeof(tx_cmd_a) +
+			sizeof(tx_cmd_b),
+			&actual_len, USB_BULK_SEND_TIMEOUT);
+	debug("Tx: len = %u, actual = %u, err = %d\n",
+	      (unsigned int)(length + sizeof(tx_cmd_a) + sizeof(tx_cmd_b)),
+	      (unsigned int)actual_len, err);
+
+	return err;
+}
+
+static int lan78xx_recv_common(struct ueth_data *dev)
+{
+	DEFINE_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, RX_URB_SIZE);
+	unsigned char *buf_ptr;
+	int err;
+	int actual_len = 0;
+	u32 packet_len = 0;
+	u32 rx_cmd_a = 0;
+
+	err = usb_bulk_msg(dev->pusb_dev,
+			usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
+			(void *)recv_buf, RX_URB_SIZE, &actual_len,
+			USB_BULK_RECV_TIMEOUT);
+	if (actual_len == 0) {
+		debug("Rx: actual_len = 0\n");
+		return -err;
+	}
+
+	debug("Rx: RX_URB_SIZE = %u, actual = %u, err = %d\n", RX_URB_SIZE,
+	      actual_len, err);
+	if (err != 0) {
+		debug("Rx: failed to receive\n");
+		return -err;
+	}
+	if (actual_len > RX_URB_SIZE) {
+		debug("Rx: received too many bytes %d\n", actual_len);
+		return -ENOSPC;
+	}
+
+	buf_ptr = recv_buf;
+
+	/* No multiple Ethernet Frames per USB Packet (MEF) used
+	 * for the U-boot for now.
+	 */
+	if (actual_len > 0) {
+		if (actual_len < sizeof(rx_cmd_a)) {
+			debug("Rx: incomplete packet length\n");
+			return -EIO;
+		}
+		memcpy(&rx_cmd_a, buf_ptr, sizeof(rx_cmd_a));
+		le32_to_cpus(&rx_cmd_a);
+		if (rx_cmd_a & RX_CMD_A_RXE_) {
+			debug("Rx: Error header=%#x", rx_cmd_a);
+			return -EIO;
+		}
+		packet_len = (u16) (rx_cmd_a & RX_CMD_A_LEN_MASK_);
+
+		if (packet_len > actual_len - sizeof(packet_len)) {
+			debug("Rx: too large packet: %d\n", packet_len);
+			return -EIO;
+		}
+
+		/* For LAN78xx, the length in command A does not
+		 * include command A, B, and C length.
+		 * So use it as is.
+		 */
+
+		debug("Rx: cmd_a 0x%08X packet_len %d\n", rx_cmd_a, packet_len);
+
+		/* Notify net stack */
+		net_process_received_packet(buf_ptr + 10, packet_len);
+	}
+
+	return err;
+}
+
+#ifndef CONFIG_DM_ETH
+/*
+ * lan78xx callbacks
+ */
+static int lan78xx_init(struct eth_device *eth, bd_t *bd)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+	struct usb_device *udev = dev->pusb_dev;
+	struct lan78xx_private *priv = (struct lan78xx_private *)dev->dev_priv;
+
+	return lan78xx_init_common(udev, dev, priv, eth->enetaddr);
+}
+
+static int lan78xx_send(struct eth_device *eth, void *packet, int length)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+	return lan78xx_send_common(dev, packet, length);
+}
+
+static int lan78xx_recv(struct eth_device *eth)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+	return lan78xx_recv_common(dev);
+}
+
+static void lan78xx_halt(struct eth_device *eth)
+{
+	debug("** %s()\n", __func__);
+}
+
+static int lan78xx_write_hwaddr(struct eth_device *eth)
+{
+	struct ueth_data *dev = eth->priv;
+	struct usb_device *udev = dev->pusb_dev;
+	struct lan78xx_private *priv = dev->dev_priv;
+
+	return lan78xx_write_hwaddr_common(udev, priv, eth->enetaddr);
+}
+
+/*
+ * Microchip probing functions
+ */
+void lan78xx_eth_before_probe(void)
+{
+	curr_eth_dev = 0;
+}
+
+struct lan78xx_dongle {
+	unsigned short vendor;
+	unsigned short product;
+};
+
+static const struct lan78xx_dongle lan78xx_dongles[] = {
+	{0x0424, 0x7800},	/* LAN7800 USB Ethernet */
+	{0x0424, 0x7850},	/* LAN7850 USB Ethernet */
+	{0x0000, 0x0000}	/* END - Do not remove */
+};
+
+/* Probe to see if a new device is actually an Microchip device */
+int lan78xx_eth_probe(struct usb_device *dev, unsigned int ifnum,
+			struct ueth_data *ss)
+{
+	struct usb_interface *iface;
+	struct usb_interface_descriptor *iface_desc;
+	int i;
+
+	/* let's examine the device now */
+	iface = &dev->config.if_desc[ifnum];
+	iface_desc = &dev->config.if_desc[ifnum].desc;
+
+	for (i = 0; lan78xx_dongles[i].vendor != 0; i++) {
+		if (dev->descriptor.idVendor == lan78xx_dongles[i].vendor &&
+		    dev->descriptor.idProduct == lan78xx_dongles[i].product)
+			/* Found a supported dongle */
+			break;
+	}
+	if (lan78xx_dongles[i].vendor == 0)
+		return 0;
+
+	/* At this point, we know we've got a live one */
+	debug("\n\nUSB Ethernet device LAN78xx detected\n");
+	memset(ss, '\0', sizeof(struct ueth_data));
+
+	/* Initialize the ueth_data structure with some useful info */
+	ss->ifnum = ifnum;
+	ss->pusb_dev = dev;
+	ss->subclass = iface_desc->bInterfaceSubClass;
+	ss->protocol = iface_desc->bInterfaceProtocol;
+
+	/*
+	 * We are expecting a minimum of 3 endpoints
+	 * - in, out (bulk), and int.
+	 * We will ignore any others.
+	 */
+	for (i = 0; i < iface_desc->bNumEndpoints; i++) {
+		/* 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;
+		}
+
+		/* is it an interrupt endpoint? */
+		if ((iface->ep_desc[i].bmAttributes &
+			USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
+			ss->ep_int = iface->ep_desc[i].bEndpointAddress &
+				USB_ENDPOINT_NUMBER_MASK;
+			ss->irqinterval = iface->ep_desc[i].bInterval;
+		}
+	}
+	debug("Endpoints In %d Out %d Int %d\n",
+	      ss->ep_in, ss->ep_out, ss->ep_int);
+
+	/* Do some basic sanity checks, and bail if we find a problem */
+	if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) ||
+	    !ss->ep_in || !ss->ep_out || !ss->ep_int) {
+		debug("Problems with device\n");
+		return 0;
+	}
+	dev->privptr = (void *)ss;
+
+	/* alloc driver private */
+	ss->dev_priv = calloc(1, sizeof(struct lan78xx_private));
+	if (!ss->dev_priv)
+		return 0;
+
+	return 1;
+}
+
+int lan78xx_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
+			 struct eth_device *eth)
+{
+	printf("LAN78xx name: %s%d\n", LAN78XX_BASE_NAME, curr_eth_dev);
+
+	if (!eth) {
+		debug("%s: missing parameter.\n", __func__);
+		return 0;
+	}
+	sprintf(eth->name, "%s%d", LAN78XX_BASE_NAME, curr_eth_dev++);
+	eth->init = lan78xx_init;
+	eth->send = lan78xx_send;
+	eth->recv = lan78xx_recv;
+	eth->halt = lan78xx_halt;
+	eth->write_hwaddr = lan78xx_write_hwaddr;
+	eth->priv = ss;
+
+	/* Do a reset in order to get the MAC address from HW */
+	if (lan78xx_basic_reset(dev, ss))
+		return 0;
+
+	/* Get the MAC address */
+	/* We must set the eth->enetaddr from HW because the upper layer
+	 * will force to use the environmental var (usbethaddr) or random if
+	 * there is no valid MAC address in eth->enetaddr.
+	 */
+	lan78xx_read_mac(eth->enetaddr, dev);
+	/* Do not return 0 for not finding MAC addr in HW */
+
+	return 1;
+}
+#endif /* !CONFIG_DM_ETH */
+
+#ifdef CONFIG_DM_ETH
+static int lan78xx_eth_start(struct udevice *dev)
+{
+	struct usb_device *udev = dev_get_parent_priv(dev);
+	struct lan78xx_private *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	/* Driver-model Ethernet ensures we have this */
+	priv->have_hwaddr = 1;
+
+	return lan78xx_init_common(udev, &priv->ueth, priv, pdata->enetaddr);
+}
+
+void lan78xx_eth_stop(struct udevice *dev)
+{
+	debug("** %s()\n", __func__);
+}
+
+int lan78xx_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct lan78xx_private *priv = dev_get_priv(dev);
+
+	return lan78xx_send_common(&priv->ueth, packet, length);
+}
+
+int lan78xx_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct lan78xx_private *priv = dev_get_priv(dev);
+
+	return lan78xx_recv_common(&priv->ueth);
+}
+
+static int lan78xx_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
+{
+	struct lan78xx_private *priv = dev_get_priv(dev);
+
+	packet_len = ALIGN(packet_len, 4);
+	usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len);
+
+	return 0;
+}
+
+int lan78xx_write_hwaddr(struct udevice *dev)
+{
+	struct usb_device *udev = dev_get_parent_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct lan78xx_private *priv = dev_get_priv(dev);
+
+	return lan78xx_write_hwaddr_common(udev, priv, pdata->enetaddr);
+}
+
+int lan78xx_read_rom_hwaddr(struct udevice *dev)
+{
+	struct usb_device *udev = dev_get_parent_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	int ret;
+
+	ret = lan78xx_read_mac(pdata->enetaddr, udev);
+	if (ret)
+		memset(pdata->enetaddr, 0, 6);
+
+	return 0;
+}
+
+static int lan78xx_eth_probe(struct udevice *dev)
+{
+	struct usb_device *udev = dev_get_parent_priv(dev);
+	struct lan78xx_private *priv = dev_get_priv(dev);
+	struct ueth_data *ueth = &priv->ueth;
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	/* Do a reset in order to get the MAC address from HW */
+	if (lan78xx_basic_reset(udev, ueth))
+		return 0;
+
+	/* Get the MAC address */
+	/* We must set the eth->enetaddr from HW because the upper layer
+	 * will force to use the environmental var (usbethaddr) or random if
+	 * there is no valid MAC address in eth->enetaddr.
+	 */
+	lan78xx_read_mac(pdata->enetaddr, udev);
+	/* Do not return 0 for not finding MAC addr in HW */
+
+	return usb_ether_register(dev, ueth, RX_URB_SIZE);
+}
+
+static const struct eth_ops lan78xx_eth_ops = {
+	.start	= lan78xx_eth_start,
+	.send	= lan78xx_eth_send,
+	.recv	= lan78xx_eth_recv,
+	.free_pkt = lan78xx_free_pkt,
+	.stop	= lan78xx_eth_stop,
+	.write_hwaddr = lan78xx_write_hwaddr,
+	.read_rom_hwaddr = lan78xx_read_rom_hwaddr,
+};
+
+U_BOOT_DRIVER(lan78xx_eth) = {
+	.name	= "lan78xx_eth",
+	.id	= UCLASS_ETH,
+	.probe = lan78xx_eth_probe,
+	.ops	= &lan78xx_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct lan78xx_private),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+static const struct usb_device_id lan78xx_eth_id_table[] = {
+	{ USB_DEVICE(0x0424, 0x7800) },	/* LAN7800 USB Ethernet */
+	{ USB_DEVICE(0x0424, 0x7850) },	/* LAN7850 USB Ethernet */
+	{ }		/* Terminating entry */
+};
+
+U_BOOT_USB_DEVICE(lan78xx_eth, lan78xx_eth_id_table);
+#endif
diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
index 36734e2..6242b39 100644
--- a/drivers/usb/eth/usb_ether.c
+++ b/drivers/usb/eth/usb_ether.c
@@ -180,6 +180,13 @@ static const struct usb_eth_prob_dev prob_dev[] = {
 		.get_info = smsc95xx_eth_get_info,
 	},
 #endif
+#ifdef CONFIG_USB_ETHER_LAN78XX
+	{
+		.before_probe = lan78xx_eth_before_probe,
+		.probe = lan78xx_eth_probe,
+		.get_info = lan78xx_eth_get_info,
+	},
+#endif
 #ifdef CONFIG_USB_ETHER_RTL8152
 	{
 		.before_probe = r8152_eth_before_probe,
diff --git a/include/usb_ether.h b/include/usb_ether.h
index 51fce4e..6cd6de9 100644
--- a/include/usb_ether.h
+++ b/include/usb_ether.h
@@ -132,6 +132,12 @@ int smsc95xx_eth_probe(struct usb_device *dev, unsigned int ifnum,
 int smsc95xx_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
 			struct eth_device *eth);
 
+void lan78xx_eth_before_probe(void);
+int lan78xx_eth_probe(struct usb_device *dev, unsigned int ifnum,
+			struct ueth_data *ss);
+int lan78xx_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
+			struct eth_device *eth);
+
 void r8152_eth_before_probe(void);
 int r8152_eth_probe(struct usb_device *dev, unsigned int ifnum,
 		    struct ueth_data *ss);
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index f6c9101..7f88449 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -6722,6 +6722,7 @@ CONFIG_USB_ETHER
 CONFIG_USB_ETHER_ASIX
 CONFIG_USB_ETHER_ASIX88179
 CONFIG_USB_ETHER_DM9601
+CONFIG_USB_ETHER_LAN78XX
 CONFIG_USB_ETHER_MCS7830
 CONFIG_USB_ETHER_RNDIS
 CONFIG_USB_ETHER_RTL8152
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v2] Add support for Microchip LAN78xx
  2017-03-10 18:38 [U-Boot] [PATCH v2] Add support for Microchip LAN78xx Yuiko.Oshino at microchip.com
@ 2017-03-10 19:19 ` Marek Vasut
  2017-03-24 18:25   ` Yuiko.Oshino at microchip.com
  2017-03-16 21:12 ` [U-Boot] [U-Boot,v2] " Tom Rini
  1 sibling, 1 reply; 12+ messages in thread
From: Marek Vasut @ 2017-03-10 19:19 UTC (permalink / raw)
  To: u-boot

On 03/10/2017 07:38 PM, Yuiko.Oshino at microchip.com wrote:
> From: Yuiko Oshino <yuiko.oshino@microchip.com>
> 
> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000 Ethernet Controllers
> 
> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
> Cc: Marek Vasut <marex@denx.de>
> ---
> Changes for v2:
>    - lan78xx.c header comment cleanup
> 
>  drivers/usb/eth/Makefile     |    1 +
>  drivers/usb/eth/lan78xx.c    | 1319 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/eth/usb_ether.c  |    7 +
>  include/usb_ether.h          |    6 +
>  scripts/config_whitelist.txt |    1 +
>  5 files changed, 1334 insertions(+)
>  create mode 100644 drivers/usb/eth/lan78xx.c
> 
> diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile
> index 4c44efc..aa8a6cf 100644
> --- a/drivers/usb/eth/Makefile
> +++ b/drivers/usb/eth/Makefile
> @@ -9,4 +9,5 @@ obj-$(CONFIG_USB_ETHER_ASIX) += asix.o
>  obj-$(CONFIG_USB_ETHER_ASIX88179) += asix88179.o
>  obj-$(CONFIG_USB_ETHER_MCS7830) += mcs7830.o
>  obj-$(CONFIG_USB_ETHER_SMSC95XX) += smsc95xx.o
> +obj-$(CONFIG_USB_ETHER_LAN78XX) += lan78xx.o
>  obj-$(CONFIG_USB_ETHER_RTL8152) += r8152.o r8152_fw.o
> diff --git a/drivers/usb/eth/lan78xx.c b/drivers/usb/eth/lan78xx.c
> new file mode 100644
> index 0000000..bc25c16
> --- /dev/null
> +++ b/drivers/usb/eth/lan78xx.c
> @@ -0,0 +1,1319 @@
> +/*
> + * Copyright (c) 2017 Microchip Technology Inc. All rights reserved.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <malloc.h>
> +#include <memalign.h>
> +#include <usb.h>
> +#include <linux/mii.h>
> +#include "usb_ether.h"
> +
> +/* USB Vendor Requests */
> +#define USB_VENDOR_REQUEST_WRITE_REGISTER	0xA0
> +#define USB_VENDOR_REQUEST_READ_REGISTER	0xA1
> +#define USB_VENDOR_REQUEST_GET_STATS		0xA2
> +
> +/* Tx Command A */
> +#define TX_CMD_A_FCS_			(0x00400000)
> +#define TX_CMD_A_LEN_MASK_		(0x000FFFFF)

Drop all those extra parenthesis around constants ...

> +/* Rx Command A */
> +#define RX_CMD_A_RX_ERRS_MASK_		(0xC03F0000)
> +#define RX_CMD_A_RXE_			(0x00040000)
> +#define RX_CMD_A_LEN_MASK_		(0x00003FFF)
> +
> +/* SCSRs */
> +#define ID_REV				(0x00)
> +#define ID_REV_CHIP_ID_MASK_		(0xFFFF0000)
> +#define ID_REV_CHIP_REV_MASK_		(0x0000FFFF)
> +#define ID_REV_CHIP_ID_7800_		(0x7800)
> +#define ID_REV_CHIP_ID_7850_		(0x7850)
> +
> +#define INT_STS				(0x0C)
> +
> +#define HW_CFG				(0x010)
> +#define HW_CFG_LED1_EN_			(0x00200000)
> +#define HW_CFG_LED0_EN_			(0x00100000) /* Muxed with EEDO */
> +#define HW_CFG_LRST_			(0x00000002) /* Mused with EECLK */
> +#define HW_CFG_SRST_			(0x00000001)
> +
> +#define PMT_CTL				(0x014)
> +#define PMT_CTL_READY_			(0x00000080)
> +#define PMT_CTL_PHY_RST_		(0x00000010)
> +
> +#define E2P_CMD				(0x040)
> +#define E2P_CMD_EPC_BUSY_		(0x80000000)
> +#define E2P_CMD_EPC_CMD_MASK_		(0x70000000)
> +#define E2P_CMD_EPC_CMD_READ_		(0x00000000)
> +#define E2P_CMD_EPC_TIMEOUT_		(0x00000400)
> +#define E2P_CMD_EPC_ADDR_MASK_		(0x000001FF)

Drop the extra trailing underscore ...

> +#define E2P_DATA			(0x044)
> +#define E2P_DATA_EEPROM_DATA_MASK_	(0x000000FF)

Why does a lot of this stuff look like the SMSC95xx driver ?
Do we even need a separate driver or can the SMSC95xx driver be updated
to support the LAN78xx ?

> +#define USB_CFG0			(0x080)
> +#define USB_CFG_BIR_			(0x00000040)

Looks like a BIT() macro can be used a lot in here ...

> +#define BURST_CAP			(0x090)
> +#define BURST_CAP_SIZE_MASK_		(0x000000FF)


[...]

> +/* local defines */
> +#define LAN78XX_BASE_NAME "78xx"
> +#define USB_CTRL_SET_TIMEOUT 5000
> +#define USB_CTRL_GET_TIMEOUT 5000
> +#define USB_BULK_SEND_TIMEOUT 5000
> +#define USB_BULK_RECV_TIMEOUT 5000

the macro should have a unit in it, like _MS or such ...

> +#define RX_URB_SIZE 2048
> +#define PHY_CONNECT_TIMEOUT 5000
> +
> +#ifndef CONFIG_DM_ETH
> +/* local vars */
> +static int curr_eth_dev;	/* index for name of next device detected */
> +#endif
> +
> +/* driver private */
> +struct lan78xx_private {
> +#ifdef CONFIG_DM_ETH
> +	struct ueth_data ueth;
> +#endif
> +	size_t rx_urb_size;	/* maximum USB URB size */
> +	u32 mac_cr;		/* MAC control register value */
> +	int have_hwaddr;	/* 1 if we have a hardware MAC address */
> +};
> +
> +/*
> + * Lan78xx infrastructure commands
> + */
> +static int lan78xx_write_reg(struct usb_device *udev, u32 index, u32 data)
> +{
> +	int len;
> +	ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
> +
> +	cpu_to_le32s(&data);
> +	tmpbuf[0] = data;
> +
> +	len = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
> +			USB_VENDOR_REQUEST_WRITE_REGISTER,
> +			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> +			0, index, tmpbuf, sizeof(data),
> +			USB_CTRL_SET_TIMEOUT);
> +	if (len != sizeof(data)) {
> +		debug("lan78xx_write_reg failed: index=%d, data=%d, len=%d",

                       ^^ just use __func__

> +		      index, data, len);
> +		return -EIO;
> +	}
> +	return 0;
> +}
> +
> +static int lan78xx_read_reg(struct usb_device *udev, u32 index, u32 *data)
> +{
> +	int len;
> +	ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
> +
> +	len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
> +			USB_VENDOR_REQUEST_READ_REGISTER,
> +			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> +			0, index, tmpbuf, sizeof(*data),
> +			USB_CTRL_GET_TIMEOUT);
> +	*data = tmpbuf[0];
> +	if (len != sizeof(*data)) {
> +		debug("lan78xx_read_reg failed: index=%d, len=%d", index, len);

DTTO

> +		return -EIO;
> +	}
> +
> +	le32_to_cpus(data);
> +	return 0;
> +}
> +
> +/* Loop until the read is completed with timeout */
> +static int lan78xx_phy_wait_not_busy(struct usb_device *udev)
> +{
> +	unsigned long start_time = get_timer(0);
> +	u32 val;
> +
> +	do {
> +		lan78xx_read_reg(udev, MII_ACC, &val);
> +		if (!(val & MII_ACC_MII_BUSY_))
> +			return 0;
> +	} while (get_timer(start_time) < 1000);
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static int lan78xx_mdio_read(struct usb_device *udev, int phy_id, int idx)
> +{
> +	u32 val, addr;
> +
> +	/* confirm MII not busy */
> +	if (lan78xx_phy_wait_not_busy(udev)) {
> +		debug("MII is busy in lan78xx_mdio_read\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	/* set the address, index & direction (read from PHY) */
> +	addr = (phy_id << 11) | (idx << 6) |
> +		MII_ACC_MII_READ_ | MII_ACC_MII_BUSY_;
> +	lan78xx_write_reg(udev, MII_ACC, addr);
> +
> +	if (lan78xx_phy_wait_not_busy(udev)) {
> +		debug("Timed out reading MII reg %02X\n", idx);
> +		return -ETIMEDOUT;
> +	}
> +
> +	lan78xx_read_reg(udev, MII_DATA, &val);
> +
> +	return (u16) (val & 0xFFFF);
> +}
> +
> +static void lan78xx_mdio_write(struct usb_device *udev, int phy_id, int idx,
> +				int regval)
> +{
> +	u32 val, addr;
> +
> +	/* confirm MII not busy */
> +	if (lan78xx_phy_wait_not_busy(udev)) {
> +		debug("MII is busy in lan78xx_mdio_write\n");
> +		return;
> +	}
> +
> +	val = regval;
> +	lan78xx_write_reg(udev, MII_DATA, val);
> +
> +	/* set the address, index & direction (write to PHY) */
> +	addr = (phy_id << 11) | (idx << 6) |
> +		MII_ACC_MII_WRITE_ | MII_ACC_MII_BUSY_;
> +	lan78xx_write_reg(udev, MII_ACC, addr);
> +
> +	if (lan78xx_phy_wait_not_busy(udev))
> +		debug("Timed out writing MII reg %02X\n", idx);
> +}
> +
> +static int lan78xx_eeprom_confirm_not_busy(struct usb_device *udev)
> +{
> +	unsigned long start_time = get_timer(0);
> +	u32 val;
> +
> +	do {
> +		lan78xx_read_reg(udev, E2P_CMD, &val);
> +		if (!(val & E2P_CMD_EPC_BUSY_))
> +			return 0;
> +		udelay(40);
> +	} while (get_timer(start_time) < 1000);

Looks like some wait_for_bit() alike function could reduce the
duplication here, this lan78xx_wait_foo functions are here@least thrice.

> +	debug("EEPROM is busy\n");
> +	return -ETIMEDOUT;
> +}
> +
> +static int lan78xx_wait_eeprom(struct usb_device *udev)
> +{
> +	unsigned long start_time = get_timer(0);
> +	u32 val;
> +
> +	do {
> +		lan78xx_read_reg(udev, E2P_CMD, &val);
> +		if (!(val & E2P_CMD_EPC_BUSY_) || (val & E2P_CMD_EPC_TIMEOUT_))
> +			break;
> +		udelay(40);
> +	} while (get_timer(start_time) < 1000);
> +
> +	if (val & (E2P_CMD_EPC_TIMEOUT_ | E2P_CMD_EPC_BUSY_)) {
> +		debug("EEPROM read operation timeout\n");
> +		return -ETIMEDOUT;
> +	}
> +	return 0;
> +}


[...]

> +static int lan78xx_read_mac(unsigned char *enetaddr,
> +					struct usb_device *udev)
> +{
> +	int ret;
> +
> +	memset(enetaddr, 0, 6);
> +	/* refer to the doc/README.enetaddr and doc/README.usb for
> +	 * the U-Boot MAC address policy
> +	 */

/*
 * multi
 * line
 * comment looks like this
 */

> +	/* try reading mac address from EEPROM, then from OTP */
> +	ret = lan78xx_read_eeprom(udev, 0, 1, enetaddr);
> +	if ((ret == 0) && (enetaddr[0] == EEPROM_INDICATOR)) {
> +		ret = lan78xx_read_eeprom(udev,
> +					  EEPROM_MAC_OFFSET, ETH_ALEN,
> +					  enetaddr);
> +		if ((ret == 0) && (is_valid_ethaddr(enetaddr))) {
> +			/* eeprom values are valid so use them */
> +			debug("MAC address read from EEPROM %pM\n",
> +			      enetaddr);
> +			return 0;
> +		}
> +	}
> +	debug("MAC address read from EEPROM invalid %pM\n", enetaddr);
> +
> +	memset(enetaddr, 0, 6);
> +	/* try reading mac address from OTP */
> +	ret = lan78xx_read_otp(udev,
> +			       EEPROM_MAC_OFFSET,
> +			       ETH_ALEN,
> +			       enetaddr);
> +	if ((ret == 0) && (is_valid_ethaddr(enetaddr))) {

No need for parenthesis around function invocation

> +		/* eeprom values are valid so use them */
> +		debug("MAC address read from OTP %pM\n", enetaddr);
> +		return 0;
> +	}
> +	debug("MAC address read from OTP invalid %pM\n", enetaddr);
> +
> +	memset(enetaddr, 0, 6);
> +	return 0;
> +}


[...]

> +static int lan78xx_basic_reset(struct usb_device *udev,
> +				struct ueth_data *dev)
> +{
> +	int ret;
> +	u32 write_buf;
> +	u32 read_buf;
> +	int timeout;
> +#define TIMEOUT_RESOLUTION 50	/* ms */

Yet another ad-hoc macro ?

> +	dev->phy_id = LAN78XX_INTERNAL_PHY_ID;	/* fixed phy id */
> +
> +	write_buf = HW_CFG_LRST_;
> +	ret = lan78xx_write_reg(udev, HW_CFG, write_buf);
> +	if (ret < 0)
> +		return ret;
> +
> +	timeout = 0;
> +	do {
> +		ret = lan78xx_read_reg(udev, HW_CFG, &read_buf);
> +		if (ret < 0)
> +			return ret;
> +		udelay(10 * 1000);
> +		timeout++;
> +	} while ((read_buf & HW_CFG_LRST_) && (timeout < 100));

aka wait_for_bit() , again ?

> +	if (timeout >= 100) {
> +		debug("timeout waiting for completion of Lite Reset\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	write_buf = PMT_CTL_PHY_RST_;
> +	ret = lan78xx_write_reg(udev, PMT_CTL, write_buf);
> +	if (ret < 0)
> +		return ret;
> +
> +	timeout = 0;
> +	do {
> +		ret = lan78xx_read_reg(udev, PMT_CTL, &read_buf);
> +		if (ret < 0)
> +			return ret;
> +		udelay(10 * 1000);
> +		timeout++;
> +		if (timeout >= 100)
> +			break;

And again ?

> +	/* for LAN78xx, we need to check PMT_CTL_READY_ asserted */
> +	} while ((read_buf & PMT_CTL_PHY_RST_) || !(read_buf & PMT_CTL_READY_));
> +	if (timeout >= 100) {
> +		debug("timeout waiting for PHY Reset\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	/* Respond to the IN token with a NAK */
> +	ret = lan78xx_read_reg(udev, USB_CFG0, &write_buf);
> +	if (ret < 0)
> +		return ret;
> +	write_buf |= USB_CFG_BIR_;
> +	ret = lan78xx_write_reg(udev, USB_CFG0, write_buf);
> +	if (ret < 0)
> +		return ret;
> +
> +
> +	return 0;
> +}
> +
> +static int lan78xx_init_common(struct usb_device *udev,
> +				struct ueth_data *dev,
> +				struct lan78xx_private *priv,
> +				unsigned char *enetaddr)
> +{
> +	int ret;
> +	u32 write_buf;
> +	u32 read_buf;
> +	u32 burst_cap;
> +	int timeout;
> +#define TIMEOUT_RESOLUTION 50	/* ms */

This is redefined ...

> +	int link_detected;
> +
> +	/* Reset and read Mac addr were done in get_info() or in probe() */
> +
> +	ret = lan78xx_read_reg(udev, MAC_CR, &write_buf);
> +	if (ret < 0)
> +		return ret;
> +	write_buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_ | MAC_CR_ADP_;
> +	ret = lan78xx_write_reg(udev, MAC_CR, write_buf);
> +	if (ret < 0)
> +		return ret;
> +
> +#ifndef CONFIG_DM_ETH
> +	if (!priv->have_hwaddr && (is_valid_ethaddr(enetaddr))) {
> +		priv->have_hwaddr = 1;
> +		debug("LAN78xx: MAC address found and set %pM\n", enetaddr);
> +	}
> +#endif
> +	if (!priv->have_hwaddr) {
> +		printf("Error: LAN78xx: No MAC address set - set usbethaddr\n");
> +		return -EADDRNOTAVAIL;
> +	}
> +	ret = lan78xx_write_hwaddr_common(udev, priv, enetaddr);
> +	if (ret < 0)
> +		return ret;
> +
> +	burst_cap = 0;
> +	priv->rx_urb_size = RX_URB_SIZE;
> +
> +	debug("rx_urb_size=%ld\n", (ulong) priv->rx_urb_size);
> +
> +	ret = lan78xx_write_reg(udev, BURST_CAP, burst_cap);
> +	if (ret < 0)
> +		return ret;
> +
> +	read_buf = DEFAULT_BULK_IN_DELAY;
> +	ret = lan78xx_write_reg(udev, BULK_IN_DLY, read_buf);
> +	if (ret < 0)
> +		return ret;
> +
> +	write_buf = 0xFFFFFFFF;
> +	ret = lan78xx_write_reg(udev, INT_STS, write_buf);

Just use the value directly ?

> +	if (ret < 0)
> +		return ret;
> +
> +	ret = lan78xx_read_reg(udev, ID_REV, &read_buf);
> +	if (ret < 0)
> +		return ret;
> +	debug("LAN78xx ID_REV = 0x%08x\n", read_buf);
> +
> +	/* set FIFO sizes */
> +	write_buf = (MAX_RX_FIFO_SIZE - 512) / 512;
> +	ret = lan78xx_write_reg(udev, FCT_RX_FIFO_END, write_buf);
> +	if (ret < 0)
> +		return ret;
> +
> +	write_buf = (MAX_TX_FIFO_SIZE - 512) / 512;
> +	ret = lan78xx_write_reg(udev, FCT_TX_FIFO_END, write_buf);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Init Tx */
> +	write_buf = 0;
> +	ret = lan78xx_write_reg(udev, FLOW, write_buf);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = lan78xx_read_reg(udev, MAC_CR, &priv->mac_cr);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Init Rx. Set Vlan, keep defult for VLAN on 78xx */
> +	ret = lan78xx_set_multicast(udev, priv);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = lan78xx_phy_initialize(udev, dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	lan78xx_start_tx_path(udev, priv);
> +	lan78xx_start_rx_path(udev, priv);
> +
> +	timeout = 0;
> +	do {
> +		link_detected = lan78xx_mdio_read(udev, dev->phy_id, MII_BMSR)
> +			& BMSR_LSTATUS;
> +		if (!link_detected) {
> +			if (timeout == 0) {
> +				printf("LAN78xx: ");
> +				printf("Waiting for Ethernet connection... ");
> +			}
> +			udelay(TIMEOUT_RESOLUTION * 1000);
> +			timeout += TIMEOUT_RESOLUTION;
> +		}
> +	} while (!link_detected && timeout < PHY_CONNECT_TIMEOUT);

We had this wait_for_bit() before ...

> +	if (link_detected) {
> +		if (timeout != 0)
> +			printf("done.\n");
> +		else
> +			printf("LAN78xx: Ethernet connection done.\n");
> +
> +		link_detected = lan78xx_mdio_read(udev, dev->phy_id, MII_BMSR);
> +		debug("MII_BMSR=0x%08x\n", link_detected);
> +
> +		ret = lan78xx_update_flowcontrol(udev, dev);
> +		if (ret < 0)
> +			return ret;
> +
> +	} else {
> +		printf("unable to connect.\n");
> +		return -EIO;
> +	}
> +	return 0;
> +}
> +
> +static int lan78xx_send_common(struct ueth_data *dev, void *packet, int length)
> +{
> +	int err;
> +	int actual_len;
> +	u32 tx_cmd_a;
> +	u32 tx_cmd_b;
> +	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
> +				 PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b));
> +
> +	debug("** %s(), len %d, buf %#x\n", __func__, length,
> +	      (unsigned int)(ulong) msg);
> +	if (length > PKTSIZE)
> +		return -ENOSPC;
> +
> +	/* LAN78xx disable all TX offload features for u-boot */
> +	tx_cmd_a = (u32) (length & TX_CMD_A_LEN_MASK_) | TX_CMD_A_FCS_;
> +	tx_cmd_b = 0;
> +	cpu_to_le32s(&tx_cmd_a);
> +	cpu_to_le32s(&tx_cmd_b);
> +
> +	/* prepend cmd_a and cmd_b */
> +	memcpy(msg, &tx_cmd_a, sizeof(tx_cmd_a));
> +	memcpy(msg + sizeof(tx_cmd_a), &tx_cmd_b, sizeof(tx_cmd_b));
> +	memcpy(msg + sizeof(tx_cmd_a) + sizeof(tx_cmd_b), (void *)packet,
> +	       length);
> +	err = usb_bulk_msg(dev->pusb_dev,
> +			usb_sndbulkpipe(dev->pusb_dev, dev->ep_out),
> +			(void *)msg,
> +			length + sizeof(tx_cmd_a) +
> +			sizeof(tx_cmd_b),
> +			&actual_len, USB_BULK_SEND_TIMEOUT);
> +	debug("Tx: len = %u, actual = %u, err = %d\n",
> +	      (unsigned int)(length + sizeof(tx_cmd_a) + sizeof(tx_cmd_b)),
> +	      (unsigned int)actual_len, err);
> +
> +	return err;
> +}

[...]

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [U-Boot,v2] Add support for Microchip LAN78xx
  2017-03-10 18:38 [U-Boot] [PATCH v2] Add support for Microchip LAN78xx Yuiko.Oshino at microchip.com
  2017-03-10 19:19 ` Marek Vasut
@ 2017-03-16 21:12 ` Tom Rini
  2017-03-24 18:30   ` Yuiko.Oshino at microchip.com
  1 sibling, 1 reply; 12+ messages in thread
From: Tom Rini @ 2017-03-16 21:12 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 10, 2017 at 06:38:10PM +0000, Yuiko.Oshino at microchip.com wrote:

> From: Yuiko Oshino <yuiko.oshino@microchip.com>
> 
> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000 Ethernet Controllers
> 
> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
> Cc: Marek Vasut <marex@denx.de>
> ---
> Changes for v2:
>    - lan78xx.c header comment cleanup
> 
>  drivers/usb/eth/Makefile     |    1 +
>  drivers/usb/eth/lan78xx.c    | 1319 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/eth/usb_ether.c  |    7 +
>  include/usb_ether.h          |    6 +
>  scripts/config_whitelist.txt |    1 +

NAK.  You don't add to the whitelist, you start adding to Kconfig.
Thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170316/f9bbe8c7/attachment.sig>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v2] Add support for Microchip LAN78xx
  2017-03-10 19:19 ` Marek Vasut
@ 2017-03-24 18:25   ` Yuiko.Oshino at microchip.com
  2017-03-24 18:28     ` Marek Vasut
  0 siblings, 1 reply; 12+ messages in thread
From: Yuiko.Oshino at microchip.com @ 2017-03-24 18:25 UTC (permalink / raw)
  To: u-boot

From: Yuiko Oshino <yuiko.oshino@microchip.com>
>-----Original Message-----
>From: Marek Vasut [mailto:marex at denx.de]
>Sent: Friday, March 10, 2017 2:19 PM
>To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>
>On 03/10/2017 07:38 PM, Yuiko.Oshino at microchip.com wrote:
>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>
>> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000
>> Ethernet Controllers
>>
>> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
>> Cc: Marek Vasut <marex@denx.de>
>> ---
>> Changes for v2:
>>    - lan78xx.c header comment cleanup
>>

[...]

>
>Why does a lot of this stuff look like the SMSC95xx driver ?
>Do we even need a separate driver or can the SMSC95xx driver be updated to
>support the LAN78xx ?
>

Marek,
Thank you so much for your review.
The LAN78xx's register addresses and bit definitions are not compatible to our old part LAN95xx (==SMSC95xx).
The new devices LAN78xx and LAN75xx device have similarities. I plan to support these two devices in this driver.
I will take care of all your comments and will submit a new PATCH with a file name change to lan7x.c.

Best Regards,
Yuiko

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v2] Add support for Microchip LAN78xx
  2017-03-24 18:25   ` Yuiko.Oshino at microchip.com
@ 2017-03-24 18:28     ` Marek Vasut
  2017-03-27 11:59       ` Yuiko.Oshino at microchip.com
  0 siblings, 1 reply; 12+ messages in thread
From: Marek Vasut @ 2017-03-24 18:28 UTC (permalink / raw)
  To: u-boot

On 03/24/2017 07:25 PM, Yuiko.Oshino at microchip.com wrote:
> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>> -----Original Message-----
>> From: Marek Vasut [mailto:marex at denx.de]
>> Sent: Friday, March 10, 2017 2:19 PM
>> To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>> Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>>
>> On 03/10/2017 07:38 PM, Yuiko.Oshino at microchip.com wrote:
>>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>
>>> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000
>>> Ethernet Controllers
>>>
>>> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
>>> Cc: Marek Vasut <marex@denx.de>
>>> ---
>>> Changes for v2:
>>>    - lan78xx.c header comment cleanup
>>>
> 
> [...]
> 
>>
>> Why does a lot of this stuff look like the SMSC95xx driver ?
>> Do we even need a separate driver or can the SMSC95xx driver be updated to
>> support the LAN78xx ?
>>
> 
> Marek,
> Thank you so much for your review.
> The LAN78xx's register addresses and bit definitions are not compatible to our old part LAN95xx (==SMSC95xx).
> The new devices LAN78xx and LAN75xx device have similarities. I plan to support these two devices in this driver.
> I will take care of all your comments and will submit a new PATCH with a file name change to lan7x.c.
> 

Is the rename really mandatory ?

Then again, I looked into Linux and that one has two separate drivers .
So I wonder if it's really a good idea. Maybe we can share some common
code and have the rest separate ?

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [U-Boot,v2] Add support for Microchip LAN78xx
  2017-03-16 21:12 ` [U-Boot] [U-Boot,v2] " Tom Rini
@ 2017-03-24 18:30   ` Yuiko.Oshino at microchip.com
  2017-04-04 14:45     ` Tom Rini
  0 siblings, 1 reply; 12+ messages in thread
From: Yuiko.Oshino at microchip.com @ 2017-03-24 18:30 UTC (permalink / raw)
  To: u-boot

From: Yuiko Oshino <yuiko.oshino@microchip.com>
>-----Original Message-----
>From: Tom Rini [mailto:trini at konsulko.com]
>Sent: Thursday, March 16, 2017 5:12 PM
>To: Yuiko Oshino - C18177
>Cc: u-boot at lists.denx.de; marex at denx.de
>Subject: Re: [U-Boot,v2] Add support for Microchip LAN78xx
>
>On Fri, Mar 10, 2017 at 06:38:10PM +0000, Yuiko.Oshino at microchip.com
>wrote:
>
>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>
>> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000 Ethernet
>Controllers
>>
>> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
>> Cc: Marek Vasut <marex@denx.de>
>> ---
>> Changes for v2:
>>    - lan78xx.c header comment cleanup
>>
>>  drivers/usb/eth/Makefile     |    1 +
>>  drivers/usb/eth/lan78xx.c    | 1319
>++++++++++++++++++++++++++++++++++++++++++
>>  drivers/usb/eth/usb_ether.c  |    7 +
>>  include/usb_ether.h          |    6 +
>>  scripts/config_whitelist.txt |    1 +
>
>NAK.  You don't add to the whitelist, you start adding to Kconfig.
>Thanks!
>
>--
>Tom

Hi Tom,
There is no Kconfig in the drivers/usb/eth. Should I add a new Kconfig file in there?
Please advise.
Thank you in advance.

Best regards,
Yuiko

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v2] Add support for Microchip LAN78xx
  2017-03-24 18:28     ` Marek Vasut
@ 2017-03-27 11:59       ` Yuiko.Oshino at microchip.com
  2017-03-27 13:30         ` Marek Vasut
  0 siblings, 1 reply; 12+ messages in thread
From: Yuiko.Oshino at microchip.com @ 2017-03-27 11:59 UTC (permalink / raw)
  To: u-boot

From: Yuiko Oshino <yuiko.oshino@microchip.com>
>-----Original Message-----
>From: Marek Vasut [mailto:marex at denx.de]
>Sent: Friday, March 24, 2017 2:29 PM
>To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>
>On 03/24/2017 07:25 PM, Yuiko.Oshino at microchip.com wrote:
>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>> -----Original Message-----
>>> From: Marek Vasut [mailto:marex at denx.de]
>>> Sent: Friday, March 10, 2017 2:19 PM
>>> To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>>> Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>>>
>>> On 03/10/2017 07:38 PM, Yuiko.Oshino at microchip.com wrote:
>>>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>>
>>>> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000
>>>> Ethernet Controllers
>>>>
>>>> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>> Cc: Marek Vasut <marex@denx.de>
>>>> ---
>>>> Changes for v2:
>>>>    - lan78xx.c header comment cleanup
>>>>
>>
>> [...]
>>
>>>
>>> Why does a lot of this stuff look like the SMSC95xx driver ?
>>> Do we even need a separate driver or can the SMSC95xx driver be
>>> updated to support the LAN78xx ?
>>>
>>
>> Marek,
>> Thank you so much for your review.
>> The LAN78xx's register addresses and bit definitions are not compatible to
>our old part LAN95xx (==SMSC95xx).
>> The new devices LAN78xx and LAN75xx device have similarities. I plan to
>support these two devices in this driver.
>> I will take care of all your comments and will submit a new PATCH with a file
>name change to lan7x.c.
>>
>
>Is the rename really mandatory ?
>
Yes, if we are going to make one file that supports both LAN78xx and LAN75xx, it's very important for us to make the driver file name to support both devices.

>Then again, I looked into Linux and that one has two separate drivers .
>So I wonder if it's really a good idea. Maybe we can share some common code
>and have the rest separate ?

Marek,
1. we can submit LAN78xx and LA75xx drivers separately like in Linux. We do prefer this option.
2. we can submit one LAN7x.c that supports both LAN78xx and LAN75xx in one file.
Could you pick one?
Thank you.
Yuiko

>
>--
>Best regards,
>Marek Vasut

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v2] Add support for Microchip LAN78xx
  2017-03-27 11:59       ` Yuiko.Oshino at microchip.com
@ 2017-03-27 13:30         ` Marek Vasut
  2017-04-07 15:43           ` Yuiko.Oshino at microchip.com
  0 siblings, 1 reply; 12+ messages in thread
From: Marek Vasut @ 2017-03-27 13:30 UTC (permalink / raw)
  To: u-boot

On 03/27/2017 01:59 PM, Yuiko.Oshino at microchip.com wrote:
> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>> -----Original Message-----
>> From: Marek Vasut [mailto:marex at denx.de]
>> Sent: Friday, March 24, 2017 2:29 PM
>> To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>> Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>>
>> On 03/24/2017 07:25 PM, Yuiko.Oshino at microchip.com wrote:
>>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>> -----Original Message-----
>>>> From: Marek Vasut [mailto:marex at denx.de]
>>>> Sent: Friday, March 10, 2017 2:19 PM
>>>> To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>>>> Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>>>>
>>>> On 03/10/2017 07:38 PM, Yuiko.Oshino at microchip.com wrote:
>>>>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>>>
>>>>> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000
>>>>> Ethernet Controllers
>>>>>
>>>>> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>>> Cc: Marek Vasut <marex@denx.de>
>>>>> ---
>>>>> Changes for v2:
>>>>>    - lan78xx.c header comment cleanup
>>>>>
>>>
>>> [...]
>>>
>>>>
>>>> Why does a lot of this stuff look like the SMSC95xx driver ?
>>>> Do we even need a separate driver or can the SMSC95xx driver be
>>>> updated to support the LAN78xx ?
>>>>
>>>
>>> Marek,
>>> Thank you so much for your review.
>>> The LAN78xx's register addresses and bit definitions are not compatible to
>> our old part LAN95xx (==SMSC95xx).
>>> The new devices LAN78xx and LAN75xx device have similarities. I plan to
>> support these two devices in this driver.
>>> I will take care of all your comments and will submit a new PATCH with a file
>> name change to lan7x.c.
>>>
>>
>> Is the rename really mandatory ?
>>
> Yes, if we are going to make one file that supports both LAN78xx and LAN75xx, it's very important for us to make the driver file name to support both devices.

The filename has nothing to do with which chips are supported though ?

>> Then again, I looked into Linux and that one has two separate drivers .
>> So I wonder if it's really a good idea. Maybe we can share some common code
>> and have the rest separate ?
> 
> Marek,
> 1. we can submit LAN78xx and LA75xx drivers separately like in Linux. We do prefer this option.
> 2. we can submit one LAN7x.c that supports both LAN78xx and LAN75xx in one file.
> Could you pick one?

Can we have option 3 -- pull common code into some file and make both
drivers use the common code ?

> Thank you.
> Yuiko
> 
>>
>> --
>> Best regards,
>> Marek Vasut


-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [U-Boot,v2] Add support for Microchip LAN78xx
  2017-03-24 18:30   ` Yuiko.Oshino at microchip.com
@ 2017-04-04 14:45     ` Tom Rini
  2017-04-07 15:44       ` Yuiko.Oshino at microchip.com
  0 siblings, 1 reply; 12+ messages in thread
From: Tom Rini @ 2017-04-04 14:45 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 24, 2017 at 06:30:46PM +0000, Yuiko.Oshino at microchip.com wrote:
> From: Yuiko Oshino <yuiko.oshino@microchip.com>
> >-----Original Message-----
> >From: Tom Rini [mailto:trini at konsulko.com]
> >Sent: Thursday, March 16, 2017 5:12 PM
> >To: Yuiko Oshino - C18177
> >Cc: u-boot at lists.denx.de; marex at denx.de
> >Subject: Re: [U-Boot,v2] Add support for Microchip LAN78xx
> >
> >On Fri, Mar 10, 2017 at 06:38:10PM +0000, Yuiko.Oshino at microchip.com
> >wrote:
> >
> >> From: Yuiko Oshino <yuiko.oshino@microchip.com>
> >>
> >> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000 Ethernet
> >Controllers
> >>
> >> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
> >> Cc: Marek Vasut <marex@denx.de>
> >> ---
> >> Changes for v2:
> >>    - lan78xx.c header comment cleanup
> >>
> >>  drivers/usb/eth/Makefile     |    1 +
> >>  drivers/usb/eth/lan78xx.c    | 1319
> >++++++++++++++++++++++++++++++++++++++++++
> >>  drivers/usb/eth/usb_ether.c  |    7 +
> >>  include/usb_ether.h          |    6 +
> >>  scripts/config_whitelist.txt |    1 +
> >
> >NAK.  You don't add to the whitelist, you start adding to Kconfig.
> >Thanks!
> >
> >--
> >Tom
> 
> Hi Tom,
> There is no Kconfig in the drivers/usb/eth. Should I add a new Kconfig file in there?
> Please advise.
> Thank you in advance.

Sorry for the late reply, yes, please add a new Kconfig entry (and
include it from somewhere reasonable).

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170404/2a046d35/attachment.sig>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v2] Add support for Microchip LAN78xx
  2017-03-27 13:30         ` Marek Vasut
@ 2017-04-07 15:43           ` Yuiko.Oshino at microchip.com
  2017-04-07 16:42             ` Marek Vasut
  0 siblings, 1 reply; 12+ messages in thread
From: Yuiko.Oshino at microchip.com @ 2017-04-07 15:43 UTC (permalink / raw)
  To: u-boot

From: Yuiko Oshino <yuiko.oshino@microchip.com>
>-----Original Message-----
>From: Marek Vasut [mailto:marex at denx.de]
>Sent: Monday, March 27, 2017 9:30 AM
>To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>
>On 03/27/2017 01:59 PM, Yuiko.Oshino at microchip.com wrote:
>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>> -----Original Message-----
>>> From: Marek Vasut [mailto:marex at denx.de]
>>> Sent: Friday, March 24, 2017 2:29 PM
>>> To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>>> Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>>>
>>> On 03/24/2017 07:25 PM, Yuiko.Oshino at microchip.com wrote:
>>>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>>> -----Original Message-----
>>>>> From: Marek Vasut [mailto:marex at denx.de]
>>>>> Sent: Friday, March 10, 2017 2:19 PM
>>>>> To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>>>>> Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>>>>>
>>>>> On 03/10/2017 07:38 PM, Yuiko.Oshino at microchip.com wrote:
>>>>>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>>>>
>>>>>> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000
>>>>>> Ethernet Controllers
>>>>>>
>>>>>> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>>>> Cc: Marek Vasut <marex@denx.de>
>>>>>> ---
>>>>>> Changes for v2:
>>>>>>    - lan78xx.c header comment cleanup
>>>>>>
>>>>
>>>> [...]
>>>>
>>>>>
>>>>> Why does a lot of this stuff look like the SMSC95xx driver ?
>>>>> Do we even need a separate driver or can the SMSC95xx driver be
>>>>> updated to support the LAN78xx ?
>>>>>
>>>>
>>>> Marek,
>>>> Thank you so much for your review.
>>>> The LAN78xx's register addresses and bit definitions are not
>>>> compatible to
>>> our old part LAN95xx (==SMSC95xx).
>>>> The new devices LAN78xx and LAN75xx device have similarities. I plan
>>>> to
>>> support these two devices in this driver.
>>>> I will take care of all your comments and will submit a new PATCH
>>>> with a file
>>> name change to lan7x.c.
>>>>
>>>
>>> Is the rename really mandatory ?
>>>
>> Yes, if we are going to make one file that supports both LAN78xx and
>LAN75xx, it's very important for us to make the driver file name to support
>both devices.
>
>The filename has nothing to do with which chips are supported though ?
>
>>> Then again, I looked into Linux and that one has two separate drivers .
>>> So I wonder if it's really a good idea. Maybe we can share some
>>> common code and have the rest separate ?
>>
>> Marek,
>> 1. we can submit LAN78xx and LA75xx drivers separately like in Linux. We do
>prefer this option.
>> 2. we can submit one LAN7x.c that supports both LAN78xx and LAN75xx in
>one file.
>> Could you pick one?
>
>Can we have option 3 -- pull common code into some file and make both
>drivers use the common code ?

Hi Marek,
Sure, we will do the option 3 with lan75xx.c, lan78xx.c, lan7xc, and lan7x.h as you like.

Should I keep this thread and make [PATCH v3] Add support for Microchip LAN78xx to submit?
Even though the new patch will also include LAN75xx as well?
Or new thread and include the LAN75xx in the title?
Please let me know.

Thank you again!
>
>> Thank you.
>> Yuiko
>>
>>>
>>> --
>>> Best regards,
>>> Marek Vasut
>
>
>--
>Best regards,
>Marek Vasut

Best regards,
Yuiko Oshino

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [U-Boot,v2] Add support for Microchip LAN78xx
  2017-04-04 14:45     ` Tom Rini
@ 2017-04-07 15:44       ` Yuiko.Oshino at microchip.com
  0 siblings, 0 replies; 12+ messages in thread
From: Yuiko.Oshino at microchip.com @ 2017-04-07 15:44 UTC (permalink / raw)
  To: u-boot

From: Yuiko Oshino <yuiko.oshino@microchip.com>
>-----Original Message-----
>From: Tom Rini [mailto:trini at konsulko.com]
>Sent: Tuesday, April 04, 2017 10:46 AM
>To: Yuiko Oshino - C18177
>Cc: u-boot at lists.denx.de; marex at denx.de
>Subject: Re: [U-Boot,v2] Add support for Microchip LAN78xx
>
>On Fri, Mar 24, 2017 at 06:30:46PM +0000, Yuiko.Oshino at microchip.com
>wrote:
>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>> >-----Original Message-----
>> >From: Tom Rini [mailto:trini at konsulko.com]
>> >Sent: Thursday, March 16, 2017 5:12 PM
>> >To: Yuiko Oshino - C18177
>> >Cc: u-boot at lists.denx.de; marex at denx.de
>> >Subject: Re: [U-Boot,v2] Add support for Microchip LAN78xx
>> >
>> >On Fri, Mar 10, 2017 at 06:38:10PM +0000, Yuiko.Oshino at microchip.com
>> >wrote:
>> >
>> >> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>> >>
>> >> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000
>> >> Ethernet
>> >Controllers
>> >>
>> >> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
>> >> Cc: Marek Vasut <marex@denx.de>
>> >> ---
>> >> Changes for v2:
>> >>    - lan78xx.c header comment cleanup
>> >>
>> >>  drivers/usb/eth/Makefile     |    1 +
>> >>  drivers/usb/eth/lan78xx.c    | 1319
>> >++++++++++++++++++++++++++++++++++++++++++
>> >>  drivers/usb/eth/usb_ether.c  |    7 +
>> >>  include/usb_ether.h          |    6 +
>> >>  scripts/config_whitelist.txt |    1 +
>> >
>> >NAK.  You don't add to the whitelist, you start adding to Kconfig.
>> >Thanks!
>> >
>> >--
>> >Tom
>>
>> Hi Tom,
>> There is no Kconfig in the drivers/usb/eth. Should I add a new Kconfig file in
>there?
>> Please advise.
>> Thank you in advance.
>
>Sorry for the late reply, yes, please add a new Kconfig entry (and include it
>from somewhere reasonable).
>
>--
>Tom

Thank you for your reply, Tom.
Will do that.

Yuiko

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v2] Add support for Microchip LAN78xx
  2017-04-07 15:43           ` Yuiko.Oshino at microchip.com
@ 2017-04-07 16:42             ` Marek Vasut
  0 siblings, 0 replies; 12+ messages in thread
From: Marek Vasut @ 2017-04-07 16:42 UTC (permalink / raw)
  To: u-boot

On 04/07/2017 05:43 PM, Yuiko.Oshino at microchip.com wrote:
> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>> -----Original Message-----
>> From: Marek Vasut [mailto:marex at denx.de]
>> Sent: Monday, March 27, 2017 9:30 AM
>> To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>> Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>>
>> On 03/27/2017 01:59 PM, Yuiko.Oshino at microchip.com wrote:
>>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>> -----Original Message-----
>>>> From: Marek Vasut [mailto:marex at denx.de]
>>>> Sent: Friday, March 24, 2017 2:29 PM
>>>> To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>>>> Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>>>>
>>>> On 03/24/2017 07:25 PM, Yuiko.Oshino at microchip.com wrote:
>>>>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>>>> -----Original Message-----
>>>>>> From: Marek Vasut [mailto:marex at denx.de]
>>>>>> Sent: Friday, March 10, 2017 2:19 PM
>>>>>> To: Yuiko Oshino - C18177; u-boot at lists.denx.de
>>>>>> Subject: Re: [PATCH v2] Add support for Microchip LAN78xx
>>>>>>
>>>>>> On 03/10/2017 07:38 PM, Yuiko.Oshino at microchip.com wrote:
>>>>>>> From: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>>>>>
>>>>>>> Add support for Microchip LAN7800 and 7850, USB to 10/100/1000
>>>>>>> Ethernet Controllers
>>>>>>>
>>>>>>> Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
>>>>>>> Cc: Marek Vasut <marex@denx.de>
>>>>>>> ---
>>>>>>> Changes for v2:
>>>>>>>    - lan78xx.c header comment cleanup
>>>>>>>
>>>>>
>>>>> [...]
>>>>>
>>>>>>
>>>>>> Why does a lot of this stuff look like the SMSC95xx driver ?
>>>>>> Do we even need a separate driver or can the SMSC95xx driver be
>>>>>> updated to support the LAN78xx ?
>>>>>>
>>>>>
>>>>> Marek,
>>>>> Thank you so much for your review.
>>>>> The LAN78xx's register addresses and bit definitions are not
>>>>> compatible to
>>>> our old part LAN95xx (==SMSC95xx).
>>>>> The new devices LAN78xx and LAN75xx device have similarities. I plan
>>>>> to
>>>> support these two devices in this driver.
>>>>> I will take care of all your comments and will submit a new PATCH
>>>>> with a file
>>>> name change to lan7x.c.
>>>>>
>>>>
>>>> Is the rename really mandatory ?
>>>>
>>> Yes, if we are going to make one file that supports both LAN78xx and
>> LAN75xx, it's very important for us to make the driver file name to support
>> both devices.
>>
>> The filename has nothing to do with which chips are supported though ?
>>
>>>> Then again, I looked into Linux and that one has two separate drivers .
>>>> So I wonder if it's really a good idea. Maybe we can share some
>>>> common code and have the rest separate ?
>>>
>>> Marek,
>>> 1. we can submit LAN78xx and LA75xx drivers separately like in Linux. We do
>> prefer this option.
>>> 2. we can submit one LAN7x.c that supports both LAN78xx and LAN75xx in
>> one file.
>>> Could you pick one?
>>
>> Can we have option 3 -- pull common code into some file and make both
>> drivers use the common code ?
> 
> Hi Marek,

Hi Yuiko,

> Sure, we will do the option 3 with lan75xx.c, lan78xx.c, lan7xc, and lan7x.h as you like.

Well don't you think this makes sense from the code reuse perspective ?

> Should I keep this thread and make [PATCH v3] Add support for Microchip LAN78xx to submit?
> Even though the new patch will also include LAN75xx as well?

That's fine

> Or new thread and include the LAN75xx in the title?

New thread please. I think it'll be more patches and there'll be some
refactoring first anyway.

> Please let me know.
> 
> Thank you again!

Thanks for keeping up the good work !

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-04-07 16:42 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-10 18:38 [U-Boot] [PATCH v2] Add support for Microchip LAN78xx Yuiko.Oshino at microchip.com
2017-03-10 19:19 ` Marek Vasut
2017-03-24 18:25   ` Yuiko.Oshino at microchip.com
2017-03-24 18:28     ` Marek Vasut
2017-03-27 11:59       ` Yuiko.Oshino at microchip.com
2017-03-27 13:30         ` Marek Vasut
2017-04-07 15:43           ` Yuiko.Oshino at microchip.com
2017-04-07 16:42             ` Marek Vasut
2017-03-16 21:12 ` [U-Boot] [U-Boot,v2] " Tom Rini
2017-03-24 18:30   ` Yuiko.Oshino at microchip.com
2017-04-04 14:45     ` Tom Rini
2017-04-07 15:44       ` Yuiko.Oshino at microchip.com

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.