[U-Boot] [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx

From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3 - All #ifdef CONFIG_DM_ETH and #endif are removed. - The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en. - Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2 - The wait_for_bit functions copy the real one. - Uses phylib - Unnecessary variables are removed - All return values are checked - Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com --- Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
drivers/usb/Kconfig | 2 + drivers/usb/eth/Kconfig | 17 ++ drivers/usb/eth/Makefile | 2 + drivers/usb/eth/lan75xx.c | 318 +++++++++++++++++++++++++++++ drivers/usb/eth/lan78xx.c | 477 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/lan7x.c | 495 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/lan7x.h | 230 +++++++++++++++++++++ 7 files changed, 1541 insertions(+) create mode 100644 drivers/usb/eth/Kconfig create mode 100644 drivers/usb/eth/lan75xx.c create mode 100644 drivers/usb/eth/lan78xx.c create mode 100644 drivers/usb/eth/lan7x.c create mode 100644 drivers/usb/eth/lan7x.h
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index da3ec2f..62126aa 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -94,4 +94,6 @@ endif
source "drivers/usb/gadget/Kconfig"
+source "drivers/usb/eth/Kconfig" + endif diff --git a/drivers/usb/eth/Kconfig b/drivers/usb/eth/Kconfig new file mode 100644 index 0000000..14cfa26 --- /dev/null +++ b/drivers/usb/eth/Kconfig @@ -0,0 +1,17 @@ +comment "USB to Ethernet Controller Drivers" + +config USB_ETHER_LAN75XX + bool "Microchip LAN75XX support" + ---help--- + Say Y here if you would like to support Microchip LAN75XX Hi-Speed + USB 2.0 to 10/100/1000 Gigabit Ethernet controller. + Supports 10Base-T/ 100Base-TX/1000Base-T. + This driver supports the internal PHY. + +config USB_ETHER_LAN78XX + bool "Microchip LAN78XX support" + ---help--- + Say Y here if you would like to support Microchip LAN78XX USB 3.1 + Gen 1 to 10/100/1000 Gigabit Ethernet controller. + Supports 10Base-T/ 100Base-TX/1000Base-T. + This driver supports the internal PHY. diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile index 4c44efc..4b935a3 100644 --- a/drivers/usb/eth/Makefile +++ b/drivers/usb/eth/Makefile @@ -9,4 +9,6 @@ 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_LAN75XX) += lan7x.o lan75xx.o +obj-$(CONFIG_USB_ETHER_LAN78XX) += lan7x.o lan78xx.o obj-$(CONFIG_USB_ETHER_RTL8152) += r8152.o r8152_fw.o diff --git a/drivers/usb/eth/lan75xx.c b/drivers/usb/eth/lan75xx.c new file mode 100644 index 0000000..a3c1411 --- /dev/null +++ b/drivers/usb/eth/lan75xx.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2017 Microchip Technology Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <dm.h> +#include <usb.h> +#include <linux/mii.h> +#include "usb_ether.h" +#include "lan7x.h" + +/* LAN75xx specific register/bit defines */ +#define LAN75XX_HW_CFG_BIR BIT(7) + +#define LAN75XX_BURST_CAP 0x034 + +#define LAN75XX_BULK_IN_DLY 0x03C + +#define LAN75XX_RFE_CTL 0x060 + +#define LAN75XX_FCT_RX_CTL 0x090 + +#define LAN75XX_FCT_TX_CTL 0x094 + +#define LAN75XX_FCT_RX_FIFO_END 0x098 + +#define LAN75XX_FCT_TX_FIFO_END 0x09C + +#define LAN75XX_FCT_FLOW 0x0A0 + +/* MAC ADDRESS PERFECT FILTER For LAN75xx */ +#define LAN75XX_ADDR_FILTX 0x300 +#define LAN75XX_ADDR_FILTX_FB_VALID BIT(31) + +/* + * Lan75xx infrastructure commands + */ +static int lan75xx_phy_gig_workaround(struct usb_device *udev, + struct ueth_data *dev) +{ + int ret = 0; + + /* Only internal phy */ + /* Set the phy in Gig loopback */ + lan7x_mdio_write(udev, dev->phy_id, MII_BMCR, + (BMCR_LOOPBACK | BMCR_SPEED1000)); + + /* Wait for the link up */ + ret = lan7x_mdio_wait_for_bit(udev, "BMSR_LSTATUS", + dev->phy_id, MII_BMSR, BMSR_LSTATUS, + true, PHY_CONNECT_TIMEOUT_MS, 1); + if (ret) + return ret; + + /* phy reset */ + return lan7x_pmt_phy_reset(udev, dev); +} + +static int lan75xx_update_flowcontrol(struct usb_device *udev, + struct ueth_data *dev) +{ + uint32_t flow = 0, fct_flow = 0; + int ret; + + ret = lan7x_update_flowcontrol(udev, dev, &flow, &fct_flow); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN75XX_FCT_FLOW, fct_flow); + if (ret) + return ret; + return lan7x_write_reg(udev, FLOW, flow); +} + +static int lan75xx_read_mac(unsigned char *enetaddr, + struct usb_device *udev) +{ + /* + * Refer to the doc/README.enetaddr and doc/README.usb for + * the U-Boot MAC address policy + */ + return lan7x_read_eeprom_mac(enetaddr, udev); +} + +static int lan75xx_set_receive_filter(struct usb_device *udev) +{ + /* No multicast in u-boot */ + return lan7x_write_reg(udev, LAN75XX_RFE_CTL, + RFE_CTL_BCAST_EN | RFE_CTL_DA_PERFECT); +} + +/* starts the TX path */ +static void lan75xx_start_tx_path(struct usb_device *udev) +{ + /* Enable Tx at MAC */ + lan7x_write_reg(udev, MAC_TX, MAC_TX_TXEN); + + /* Enable Tx at SCSRs */ + lan7x_write_reg(udev, LAN75XX_FCT_TX_CTL, FCT_TX_CTL_EN); +} + +/* Starts the Receive path */ +static void lan75xx_start_rx_path(struct usb_device *udev) +{ + /* Enable Rx at MAC */ + lan7x_write_reg(udev, MAC_RX, + LAN7X_MAC_RX_MAX_SIZE_DEFAULT | + MAC_RX_FCS_STRIP | MAC_RX_RXEN); + + /* Enable Rx at SCSRs */ + lan7x_write_reg(udev, LAN75XX_FCT_RX_CTL, FCT_RX_CTL_EN); +} + +static int lan75xx_basic_reset(struct usb_device *udev, + struct ueth_data *dev, + struct lan7x_private *priv) +{ + int ret; + u32 val; + + ret = lan7x_basic_reset(udev, dev); + if (ret) + return ret; + + /* Keep the chip ID */ + ret = lan7x_read_reg(udev, ID_REV, &val); + if (ret) + return ret; + debug("LAN75xx ID_REV = 0x%08x\n", val); + + priv->chipid = (val & ID_REV_CHIP_ID_MASK) >> 16; + + /* Respond to the IN token with a NAK */ + ret = lan7x_read_reg(udev, HW_CFG, &val); + if (ret) + return ret; + val |= LAN75XX_HW_CFG_BIR; + return lan7x_write_reg(udev, HW_CFG, val); +} + +int lan75xx_write_hwaddr(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parent_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + unsigned char *enetaddr = pdata->enetaddr; + u32 addr_lo = get_unaligned_le32(&enetaddr[0]); + u32 addr_hi = (u32)get_unaligned_le16(&enetaddr[4]); + int ret; + + /* set hardware address */ + ret = lan7x_write_reg(udev, RX_ADDRL, addr_lo); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, RX_ADDRH, addr_hi); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN75XX_ADDR_FILTX + 4, addr_lo); + if (ret) + return ret; + + addr_hi |= LAN75XX_ADDR_FILTX_FB_VALID; + ret = lan7x_write_reg(udev, LAN75XX_ADDR_FILTX, addr_hi); + if (ret) + return ret; + + debug("MAC addr %pM written\n", enetaddr); + + return 0; +} + +static int lan75xx_eth_start(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parent_priv(dev); + struct lan7x_private *priv = dev_get_priv(dev); + struct ueth_data *ueth = &priv->ueth; + int ret; + u32 write_buf; + + /* Reset and read Mac addr were done in probe() */ + ret = lan75xx_write_hwaddr(dev); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, INT_STS, 0xFFFFFFFF); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN75XX_BURST_CAP, 0); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN75XX_BULK_IN_DLY, DEFAULT_BULK_IN_DELAY); + if (ret) + return ret; + + /* set FIFO sizes */ + write_buf = (MAX_RX_FIFO_SIZE - 512) / 512; + ret = lan7x_write_reg(udev, LAN75XX_FCT_RX_FIFO_END, write_buf); + if (ret) + return ret; + + write_buf = (MAX_TX_FIFO_SIZE - 512) / 512; + ret = lan7x_write_reg(udev, LAN75XX_FCT_TX_FIFO_END, write_buf); + if (ret) + return ret; + + /* Init Tx */ + ret = lan7x_write_reg(udev, FLOW, 0); + if (ret) + return ret; + + /* Init Rx. Set Vlan, keep defult for VLAN on 75xx */ + ret = lan75xx_set_receive_filter(udev); + if (ret) + return ret; + + /* phy workaround for gig link */ + ret = lan75xx_phy_gig_workaround(udev, ueth); + if (ret) + return ret; + + /* Init PHY, autonego, and link */ + ret = lan7x_eth_phylib_connect(dev, &priv->ueth); + if (ret) + return ret; + ret = lan7x_eth_phylib_config_start(dev); + if (ret) + return ret; + + /* + * MAC_CR has to be set after PHY init. + * MAC will auto detect the PHY speed. + */ + ret = lan7x_read_reg(udev, MAC_CR, &write_buf); + if (ret) + return ret; + write_buf |= MAC_CR_AUTO_DUPLEX | MAC_CR_AUTO_SPEED | MAC_CR_ADP; + ret = lan7x_write_reg(udev, MAC_CR, write_buf); + if (ret) + return ret; + + lan75xx_start_tx_path(udev); + lan75xx_start_rx_path(udev); + + return lan75xx_update_flowcontrol(udev, ueth); +} + +int lan75xx_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 = lan75xx_read_mac(pdata->enetaddr, udev); + if (ret) + memset(pdata->enetaddr, 0, 6); + + return 0; +} + +static int lan75xx_eth_probe(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parent_priv(dev); + struct lan7x_private *priv = dev_get_priv(dev); + struct ueth_data *ueth = &priv->ueth; + struct eth_pdata *pdata = dev_get_platdata(dev); + int ret; + + /* Do a reset in order to get the MAC address from HW */ + if (lan75xx_basic_reset(udev, ueth, priv)) + 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. + */ + lan75xx_read_mac(pdata->enetaddr, udev); + /* Do not return 0 for not finding MAC addr in HW */ + + ret = usb_ether_register(dev, ueth, RX_URB_SIZE); + if (ret) + return ret; + + /* Register phylib */ + return lan7x_phylib_register(dev); +} + +static const struct eth_ops lan75xx_eth_ops = { + .start = lan75xx_eth_start, + .send = lan7x_eth_send, + .recv = lan7x_eth_recv, + .free_pkt = lan7x_free_pkt, + .stop = lan7x_eth_stop, + .write_hwaddr = lan75xx_write_hwaddr, + .read_rom_hwaddr = lan75xx_read_rom_hwaddr, +}; + +U_BOOT_DRIVER(lan75xx_eth) = { + .name = "lan75xx_eth", + .id = UCLASS_ETH, + .probe = lan75xx_eth_probe, + .remove = lan7x_eth_remove, + .ops = &lan75xx_eth_ops, + .priv_auto_alloc_size = sizeof(struct lan7x_private), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; + +static const struct usb_device_id lan75xx_eth_id_table[] = { + { USB_DEVICE(0x0424, 0x7500) }, /* LAN7500 USB Ethernet */ + { } /* Terminating entry */ +}; + +U_BOOT_USB_DEVICE(lan75xx_eth, lan75xx_eth_id_table); diff --git a/drivers/usb/eth/lan78xx.c b/drivers/usb/eth/lan78xx.c new file mode 100644 index 0000000..b998f4f --- /dev/null +++ b/drivers/usb/eth/lan78xx.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2017 Microchip Technology Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <dm.h> +#include <usb.h> +#include "usb_ether.h" +#include "lan7x.h" + +/* LAN78xx specific register/bit defines */ +#define LAN78XX_HW_CFG_LED1_EN BIT(21) /* Muxed with EEDO */ +#define LAN78XX_HW_CFG_LED0_EN BIT(20) /* Muxed with EECLK */ + +#define LAN78XX_USB_CFG0 0x080 +#define LAN78XX_USB_CFG0_BIR BIT(6) + +#define LAN78XX_BURST_CAP 0x090 + +#define LAN78XX_BULK_IN_DLY 0x094 + +#define LAN78XX_RFE_CTL 0x0B0 + +#define LAN78XX_FCT_RX_CTL 0x0C0 + +#define LAN78XX_FCT_TX_CTL 0x0C4 + +#define LAN78XX_FCT_RX_FIFO_END 0x0C8 + +#define LAN78XX_FCT_TX_FIFO_END 0x0CC + +#define LAN78XX_FCT_FLOW 0x0D0 + +#define LAN78XX_MAF_BASE 0x400 +#define LAN78XX_MAF_HIX 0x00 +#define LAN78XX_MAF_LOX 0x04 +#define LAN78XX_MAF_HI_BEGIN (LAN78XX_MAF_BASE + LAN78XX_MAF_HIX) +#define LAN78XX_MAF_LO_BEGIN (LAN78XX_MAF_BASE + LAN78XX_MAF_LOX) +#define LAN78XX_MAF_HI(index) (LAN78XX_MAF_BASE + (8 * (index)) + \ + LAN78XX_MAF_HIX) +#define LAN78XX_MAF_LO(index) (LAN78XX_MAF_BASE + (8 * (index)) + \ + LAN78XX_MAF_LOX) +#define LAN78XX_MAF_HI_VALID BIT(31) + +/* OTP registers */ +#define LAN78XX_OTP_BASE_ADDR 0x00001000 + +#define LAN78XX_OTP_PWR_DN (LAN78XX_OTP_BASE_ADDR + 4 * 0x00) +#define LAN78XX_OTP_PWR_DN_PWRDN_N BIT(0) + +#define LAN78XX_OTP_ADDR1 (LAN78XX_OTP_BASE_ADDR + 4 * 0x01) +#define LAN78XX_OTP_ADDR1_15_11 0x1F + +#define LAN78XX_OTP_ADDR2 (LAN78XX_OTP_BASE_ADDR + 4 * 0x02) +#define LAN78XX_OTP_ADDR2_10_3 0xFF + +#define LAN78XX_OTP_RD_DATA (LAN78XX_OTP_BASE_ADDR + 4 * 0x06) + +#define LAN78XX_OTP_FUNC_CMD (LAN78XX_OTP_BASE_ADDR + 4 * 0x08) +#define LAN78XX_OTP_FUNC_CMD_READ BIT(0) + +#define LAN78XX_OTP_CMD_GO (LAN78XX_OTP_BASE_ADDR + 4 * 0x0A) +#define LAN78XX_OTP_CMD_GO_GO BIT(0) + +#define LAN78XX_OTP_STATUS (LAN78XX_OTP_BASE_ADDR + 4 * 0x0C) +#define LAN78XX_OTP_STATUS_BUSY BIT(0) + +#define LAN78XX_OTP_INDICATOR_1 0xF3 +#define LAN78XX_OTP_INDICATOR_2 0xF7 + +/* + * Lan78xx infrastructure commands + */ +static int lan78xx_read_raw_otp(struct usb_device *udev, u32 offset, + u32 length, u8 *data) +{ + int i; + int ret; + u32 buf; + + ret = lan7x_read_reg(udev, LAN78XX_OTP_PWR_DN, &buf); + if (ret) + return ret; + + if (buf & LAN78XX_OTP_PWR_DN_PWRDN_N) { + /* clear it and wait to be cleared */ + ret = lan7x_write_reg(udev, LAN78XX_OTP_PWR_DN, 0); + if (ret) + return ret; + + ret = lan7x_wait_for_bit(udev, "LAN78XX_OTP_PWR_DN_PWRDN_N", + LAN78XX_OTP_PWR_DN, + LAN78XX_OTP_PWR_DN_PWRDN_N, + false, 1000, 0); + if (ret) + return ret; + } + + for (i = 0; i < length; i++) { + ret = lan7x_write_reg(udev, LAN78XX_OTP_ADDR1, + ((offset + i) >> 8) & + LAN78XX_OTP_ADDR1_15_11); + if (ret) + return ret; + ret = lan7x_write_reg(udev, LAN78XX_OTP_ADDR2, + ((offset + i) & LAN78XX_OTP_ADDR2_10_3)); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN78XX_OTP_FUNC_CMD, + LAN78XX_OTP_FUNC_CMD_READ); + if (ret) + return ret; + ret = lan7x_write_reg(udev, LAN78XX_OTP_CMD_GO, + LAN78XX_OTP_CMD_GO_GO); + + if (ret) + return ret; + + ret = lan7x_wait_for_bit(udev, "LAN78XX_OTP_STATUS_BUSY", + LAN78XX_OTP_STATUS, + LAN78XX_OTP_STATUS_BUSY, + false, 1000, 0); + if (ret) + return ret; + + ret = lan7x_read_reg(udev, LAN78XX_OTP_RD_DATA, &buf); + if (ret) + return ret; + + 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) { + if (sig == LAN78XX_OTP_INDICATOR_1) + offset = offset; + else if (sig == LAN78XX_OTP_INDICATOR_2) + offset += 0x100; + else + return -EINVAL; + ret = lan78xx_read_raw_otp(udev, offset, length, data); + if (ret) + return ret; + } + debug("LAN78x: MAC address from OTP = %pM\n", data); + + return ret; +} + +static int lan78xx_read_otp_mac(unsigned char *enetaddr, + struct usb_device *udev) +{ + int ret; + + memset(enetaddr, 0, 6); + + ret = lan78xx_read_otp(udev, + EEPROM_MAC_OFFSET, + ETH_ALEN, + enetaddr); + if (!ret && 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 -EINVAL; +} + +static int lan78xx_update_flowcontrol(struct usb_device *udev, + struct ueth_data *dev) +{ + uint32_t flow = 0, fct_flow = 0; + int ret; + + ret = lan7x_update_flowcontrol(udev, dev, &flow, &fct_flow); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN78XX_FCT_FLOW, fct_flow); + if (ret) + return ret; + return lan7x_write_reg(udev, FLOW, flow); +} + +static int lan78xx_read_mac(unsigned char *enetaddr, + struct usb_device *udev, + struct lan7x_private *priv) +{ + u32 val; + int ret; + int saved = 0, done = 0; + + /* + * Depends on chip, some EEPROM pins are muxed with LED function. + * disable & restore LED function to access EEPROM. + */ + if ((priv->chipid == ID_REV_CHIP_ID_7800) || + (priv->chipid == ID_REV_CHIP_ID_7850)) { + ret = lan7x_read_reg(udev, HW_CFG, &val); + if (ret) + return ret; + saved = val; + val &= ~(LAN78XX_HW_CFG_LED1_EN | LAN78XX_HW_CFG_LED0_EN); + ret = lan7x_write_reg(udev, HW_CFG, val); + if (ret) + goto restore; + } + + /* + * 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 = lan7x_read_eeprom_mac(enetaddr, udev); + if (!ret) + done = 1; + +restore: + if ((priv->chipid == ID_REV_CHIP_ID_7800) || + (priv->chipid == ID_REV_CHIP_ID_7850)) { + ret = lan7x_write_reg(udev, HW_CFG, saved); + if (ret) + return ret; + } + /* if the EEPROM mac address is good, then exit */ + if (done) + return 0; + + /* try reading mac address from OTP if the device is LAN78xx */ + return lan78xx_read_otp_mac(enetaddr, udev); +} + +static int lan78xx_set_receive_filter(struct usb_device *udev) +{ + /* No multicast in u-boot for now */ + return lan7x_write_reg(udev, LAN78XX_RFE_CTL, + RFE_CTL_BCAST_EN | RFE_CTL_DA_PERFECT); +} + +/* starts the TX path */ +static void lan78xx_start_tx_path(struct usb_device *udev) +{ + /* Enable Tx at MAC */ + lan7x_write_reg(udev, MAC_TX, MAC_TX_TXEN); + + /* Enable Tx at SCSRs */ + lan7x_write_reg(udev, LAN78XX_FCT_TX_CTL, FCT_TX_CTL_EN); +} + +/* Starts the Receive path */ +static void lan78xx_start_rx_path(struct usb_device *udev) +{ + /* Enable Rx at MAC */ + lan7x_write_reg(udev, MAC_RX, + LAN7X_MAC_RX_MAX_SIZE_DEFAULT | + MAC_RX_FCS_STRIP | MAC_RX_RXEN); + + /* Enable Rx at SCSRs */ + lan7x_write_reg(udev, LAN78XX_FCT_RX_CTL, FCT_RX_CTL_EN); +} + +static int lan78xx_basic_reset(struct usb_device *udev, + struct ueth_data *dev, + struct lan7x_private *priv) +{ + int ret; + u32 val; + + ret = lan7x_basic_reset(udev, dev); + if (ret) + return ret; + + /* Keep the chip ID */ + ret = lan7x_read_reg(udev, ID_REV, &val); + if (ret) + return ret; + debug("LAN78xx ID_REV = 0x%08x\n", val); + + priv->chipid = (val & ID_REV_CHIP_ID_MASK) >> 16; + + /* Respond to the IN token with a NAK */ + ret = lan7x_read_reg(udev, LAN78XX_USB_CFG0, &val); + if (ret) + return ret; + val |= LAN78XX_USB_CFG0_BIR; + return lan7x_write_reg(udev, LAN78XX_USB_CFG0, val); +} + +int lan78xx_write_hwaddr(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parent_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + unsigned char *enetaddr = pdata->enetaddr; + u32 addr_lo = get_unaligned_le32(&enetaddr[0]); + u32 addr_hi = (u32)get_unaligned_le16(&enetaddr[4]); + int ret; + + /* set hardware address */ + ret = lan7x_write_reg(udev, RX_ADDRL, addr_lo); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, RX_ADDRH, addr_hi); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN78XX_MAF_LO(0), addr_lo); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN78XX_MAF_HI(0), + addr_hi | LAN78XX_MAF_HI_VALID); + if (ret) + return ret; + + debug("MAC addr %pM written\n", enetaddr); + + return 0; +} + +static int lan78xx_eth_start(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parent_priv(dev); + struct lan7x_private *priv = dev_get_priv(dev); + + int ret; + u32 write_buf; + + /* Reset and read Mac addr were done in probe() */ + ret = lan78xx_write_hwaddr(dev); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN78XX_BURST_CAP, 0); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN78XX_BULK_IN_DLY, DEFAULT_BULK_IN_DELAY); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, INT_STS, 0xFFFFFFFF); + if (ret) + return ret; + + /* set FIFO sizes */ + ret = lan7x_write_reg(udev, LAN78XX_FCT_RX_FIFO_END, + (MAX_RX_FIFO_SIZE - 512) / 512); + if (ret) + return ret; + + ret = lan7x_write_reg(udev, LAN78XX_FCT_TX_FIFO_END, + (MAX_TX_FIFO_SIZE - 512) / 512); + if (ret) + return ret; + + /* Init Tx */ + ret = lan7x_write_reg(udev, FLOW, 0); + if (ret) + return ret; + + /* Init Rx. Set Vlan, keep defult for VLAN on 78xx */ + ret = lan78xx_set_receive_filter(udev); + if (ret) + return ret; + + /* Init PHY, autonego, and link */ + ret = lan7x_eth_phylib_connect(dev, &priv->ueth); + if (ret) + return ret; + ret = lan7x_eth_phylib_config_start(dev); + if (ret) + return ret; + + /* + * MAC_CR has to be set after PHY init. + * MAC will auto detect the PHY speed. + */ + ret = lan7x_read_reg(udev, MAC_CR, &write_buf); + if (ret) + return ret; + write_buf |= MAC_CR_AUTO_DUPLEX | MAC_CR_AUTO_SPEED | MAC_CR_ADP; + ret = lan7x_write_reg(udev, MAC_CR, write_buf); + if (ret) + return ret; + + lan78xx_start_tx_path(udev); + lan78xx_start_rx_path(udev); + + return lan78xx_update_flowcontrol(udev, &priv->ueth); +} + +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); + struct lan7x_private *priv = dev_get_priv(dev); + int ret; + + ret = lan78xx_read_mac(pdata->enetaddr, udev, priv); + 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 lan7x_private *priv = dev_get_priv(dev); + struct ueth_data *ueth = &priv->ueth; + struct eth_pdata *pdata = dev_get_platdata(dev); + int ret; + + /* Do a reset in order to get the MAC address from HW */ + if (lan78xx_basic_reset(udev, ueth, priv)) + 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, priv); + /* Do not return 0 for not finding MAC addr in HW */ + + ret = usb_ether_register(dev, ueth, RX_URB_SIZE); + if (ret) + return ret; + + /* Register phylib */ + return lan7x_phylib_register(dev); +} + +static const struct eth_ops lan78xx_eth_ops = { + .start = lan78xx_eth_start, + .send = lan7x_eth_send, + .recv = lan7x_eth_recv, + .free_pkt = lan7x_free_pkt, + .stop = lan7x_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, + .remove = lan7x_eth_remove, + .ops = &lan78xx_eth_ops, + .priv_auto_alloc_size = sizeof(struct lan7x_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); diff --git a/drivers/usb/eth/lan7x.c b/drivers/usb/eth/lan7x.c new file mode 100644 index 0000000..fe2bfe1 --- /dev/null +++ b/drivers/usb/eth/lan7x.c @@ -0,0 +1,495 @@ +/* + * Copyright (c) 2017 Microchip Technology Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <dm.h> +#include <malloc.h> +#include <miiphy.h> +#include <memalign.h> +#include <usb.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#include "usb_ether.h" +#include "lan7x.h" + +/* + * Lan7x infrastructure commands + */ +int lan7x_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_MS); + if (len != sizeof(data)) { + debug("%s failed: index=%d, data=%d, len=%d", + __func__, index, data, len); + return -EIO; + } + return 0; +} + +int lan7x_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_MS); + *data = tmpbuf[0]; + if (len != sizeof(*data)) { + debug("%s failed: index=%d, len=%d", __func__, index, len); + return -EIO; + } + + le32_to_cpus(data); + return 0; +} + +static int lan7x_phy_wait_not_busy(struct usb_device *udev) +{ + return lan7x_wait_for_bit(udev, __func__, + MII_ACC, MII_ACC_MII_BUSY, + false, 100, 0); +} + +int lan7x_mdio_read(struct usb_device *udev, int phy_id, int idx) +{ + u32 val, addr; + + /* confirm MII not busy */ + if (lan7x_phy_wait_not_busy(udev)) { + debug("MII is busy in %s\n", __func__); + return -ETIMEDOUT; + } + + /* set the address, index & direction (read from PHY) */ + addr = (phy_id << 11) | (idx << 6) | + MII_ACC_MII_READ | MII_ACC_MII_BUSY; + lan7x_write_reg(udev, MII_ACC, addr); + + if (lan7x_phy_wait_not_busy(udev)) { + debug("Timed out reading MII reg %02X\n", idx); + return -ETIMEDOUT; + } + + lan7x_read_reg(udev, MII_DATA, &val); + + return val & 0xFFFF; +} + +void lan7x_mdio_write(struct usb_device *udev, int phy_id, int idx, int regval) +{ + u32 addr; + + /* confirm MII not busy */ + if (lan7x_phy_wait_not_busy(udev)) { + debug("MII is busy in %s\n", __func__); + return; + } + + lan7x_write_reg(udev, MII_DATA, regval); + + /* set the address, index & direction (write to PHY) */ + addr = (phy_id << 11) | (idx << 6) | + MII_ACC_MII_WRITE | MII_ACC_MII_BUSY; + lan7x_write_reg(udev, MII_ACC, addr); + + if (lan7x_phy_wait_not_busy(udev)) + debug("Timed out writing MII reg %02X\n", idx); +} + +/* + * Lan7x phylib wrappers + */ +static int lan7x_phylib_mdio_read(struct mii_dev *bus, + int addr, int devad, int reg) +{ + struct usb_device *udev = dev_get_parent_priv(bus->priv); + + return lan7x_mdio_read(udev, addr, reg); +} + +static int lan7x_phylib_mdio_write(struct mii_dev *bus, + int addr, int devad, int reg, u16 val) +{ + struct usb_device *udev = dev_get_parent_priv(bus->priv); + + lan7x_mdio_write(udev, addr, reg, (int)val); + + return 0; +} + +/* + * Lan7x eeprom functions + */ +static int lan7x_eeprom_confirm_not_busy(struct usb_device *udev) +{ + return lan7x_wait_for_bit(udev, __func__, + E2P_CMD, E2P_CMD_EPC_BUSY, + false, 100, 0); +} + +static int lan7x_wait_eeprom(struct usb_device *udev) +{ + return lan7x_wait_for_bit(udev, __func__, + E2P_CMD, + (E2P_CMD_EPC_BUSY | E2P_CMD_EPC_TIMEOUT), + false, 100, 0); +} + +static int lan7x_read_eeprom(struct usb_device *udev, + u32 offset, u32 length, u8 *data) +{ + u32 val; + int i, ret; + + ret = lan7x_eeprom_confirm_not_busy(udev); + if (ret) + return ret; + + for (i = 0; i < length; i++) { + val = E2P_CMD_EPC_BUSY | E2P_CMD_EPC_CMD_READ | + (offset & E2P_CMD_EPC_ADDR_MASK); + lan7x_write_reg(udev, E2P_CMD, val); + + ret = lan7x_wait_eeprom(udev); + if (ret) + return ret; + + lan7x_read_reg(udev, E2P_DATA, &val); + data[i] = val & 0xFF; + offset++; + } + return ret; +} + +/* + * Lan7x phylib functions + */ +int lan7x_phylib_register(struct udevice *udev) +{ + struct lan7x_private *priv = dev_get_priv(udev); + int ret; + + priv->mdiobus = mdio_alloc(); + if (!priv->mdiobus) { + printf("mdio_alloc failed\n"); + return -ENOMEM; + } + priv->mdiobus->read = lan7x_phylib_mdio_read; + priv->mdiobus->write = lan7x_phylib_mdio_write; + strcpy(priv->mdiobus->name, "lan78x_mdiobus"); + priv->mdiobus->priv = (void *)udev; + + ret = mdio_register(priv->mdiobus); + if (ret) { + printf("mdio_register failed\n"); + free(priv->mdiobus); + return -ENOMEM; + } + + return 0; +} + +int lan7x_eth_phylib_connect(struct udevice *udev, struct ueth_data *dev) +{ + struct lan7x_private *priv = dev_get_priv(udev); + + priv->phydev = phy_connect(priv->mdiobus, dev->phy_id, + udev, PHY_INTERFACE_MODE_MII); + + if (!priv->phydev) { + printf("phy_connect failed\n"); + return -ENODEV; + } + return 0; +} + +int lan7x_eth_phylib_config_start(struct udevice *udev) +{ + struct lan7x_private *priv = dev_get_priv(udev); + int ret; + + /* configure supported modes */ + priv->phydev->supported = PHY_BASIC_FEATURES | + SUPPORTED_1000baseT_Full | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause; + + priv->phydev->advertising = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full | + ADVERTISED_Pause | + ADVERTISED_Asym_Pause | + ADVERTISED_Autoneg; + + priv->phydev->autoneg = AUTONEG_ENABLE; + + ret = genphy_config_aneg(priv->phydev); + if (ret) { + printf("genphy_config_aneg failed\n"); + return ret; + } + ret = phy_startup(priv->phydev); + if (ret) { + printf("phy_startup failed\n"); + return ret; + } + + debug("** %s() speed %i duplex %i adv %X supp %X\n", __func__, + priv->phydev->speed, priv->phydev->duplex, + priv->phydev->advertising, priv->phydev->supported); + + return 0; +} + +int lan7x_update_flowcontrol(struct usb_device *udev, + struct ueth_data *dev, + uint32_t *flow, uint32_t *fct_flow) +{ + uint32_t lcladv, rmtadv; + u8 cap = 0; + struct lan7x_private *priv = dev_get_priv(udev->dev); + + debug("** %s()\n", __func__); + debug("** %s() priv->phydev->speed %i duplex %i\n", __func__, + priv->phydev->speed, priv->phydev->duplex); + + if (priv->phydev->duplex == DUPLEX_FULL) { + lcladv = lan7x_mdio_read(udev, dev->phy_id, MII_ADVERTISE); + rmtadv = lan7x_mdio_read(udev, dev->phy_id, MII_LPA); + cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv); + + debug("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; + debug("EN "); + } else { + debug("DIS "); + } + debug("RX Flow "); + if (cap & FLOW_CTRL_RX) { + *flow |= FLOW_CR_RX_FCEN; + debug("EN"); + } else { + debug("DIS"); + } + } + debug("\n"); + return 0; +} + +int lan7x_read_eeprom_mac(unsigned char *enetaddr, struct usb_device *udev) +{ + int ret; + + memset(enetaddr, 0, 6); + + ret = lan7x_read_eeprom(udev, 0, 1, enetaddr); + + if ((ret == 0) && (enetaddr[0] == EEPROM_INDICATOR)) { + ret = lan7x_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); + return -EINVAL; +} + +int lan7x_pmt_phy_reset(struct usb_device *udev, + struct ueth_data *dev) +{ + int ret; + u32 data; + + ret = lan7x_read_reg(udev, PMT_CTL, &data); + if (ret) + return ret; + ret = lan7x_write_reg(udev, PMT_CTL, data | PMT_CTL_PHY_RST); + if (ret) + return ret; + + /* for LAN7x, we need to check PMT_CTL_READY asserted */ + ret = lan7x_wait_for_bit(udev, "PMT_CTL_PHY_RST", + PMT_CTL, PMT_CTL_PHY_RST, + false, 1000, 0); /* could take over 125mS */ + if (ret) + return ret; + + return lan7x_wait_for_bit(udev, "PMT_CTL_READY", + PMT_CTL, PMT_CTL_READY, + true, 1000, 0); +} + +int lan7x_basic_reset(struct usb_device *udev, + struct ueth_data *dev) +{ + int ret; + + dev->phy_id = LAN7X_INTERNAL_PHY_ID; /* fixed phy id */ + + ret = lan7x_write_reg(udev, HW_CFG, HW_CFG_LRST); + if (ret) + return ret; + + ret = lan7x_wait_for_bit(udev, "HW_CFG_LRST", + HW_CFG, HW_CFG_LRST, + false, 1000, 0); + if (ret) + return ret; + + return lan7x_pmt_phy_reset(udev, dev); +} + +void lan7x_eth_stop(struct udevice *dev) +{ + debug("** %s()\n", __func__); +} + +int lan7x_eth_send(struct udevice *dev, void *packet, int length) +{ + struct lan7x_private *priv = dev_get_priv(dev); + struct ueth_data *ueth = &priv->ueth; + 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; + + /* LAN7x 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(ueth->pusb_dev, + usb_sndbulkpipe(ueth->pusb_dev, ueth->ep_out), + (void *)msg, + length + sizeof(tx_cmd_a) + + sizeof(tx_cmd_b), + &actual_len, USB_BULK_SEND_TIMEOUT_MS); + 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; +} + +int lan7x_eth_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct lan7x_private *priv = dev_get_priv(dev); + struct ueth_data *ueth = &priv->ueth; + uint8_t *ptr; + int ret, len; + u32 packet_len = 0; + u32 rx_cmd_a = 0; + + len = usb_ether_get_rx_bytes(ueth, &ptr); + debug("%s: first try, len=%d\n", __func__, len); + if (!len) { + if (!(flags & ETH_RECV_CHECK_DEVICE)) + return -EAGAIN; + ret = usb_ether_receive(ueth, RX_URB_SIZE); + if (ret == -EAGAIN) + return ret; + + len = usb_ether_get_rx_bytes(ueth, &ptr); + debug("%s: second try, len=%d\n", __func__, len); + } + + /* + * 1st 4 bytes contain the length of the actual data plus error info. + * Extract data length. + */ + if (len < sizeof(packet_len)) { + debug("Rx: incomplete packet length\n"); + goto err; + } + memcpy(&rx_cmd_a, 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); + goto err; + } + packet_len = (u16) (rx_cmd_a & RX_CMD_A_LEN_MASK); + + if (packet_len > len - sizeof(packet_len)) { + debug("Rx: too large packet: %d\n", packet_len); + goto err; + } + + /* + * For LAN7x, the length in command A does not + * include command A, B, and C length. + * So use it as is. + */ + + *packetp = ptr + 10; + return packet_len; + +err: + usb_ether_advance_rxbuf(ueth, -1); + return -EINVAL; +} + +int lan7x_free_pkt(struct udevice *dev, uchar *packet, int packet_len) +{ + struct lan7x_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 lan7x_eth_remove(struct udevice *dev) +{ + struct lan7x_private *priv = dev_get_priv(dev); + + debug("** %s()\n", __func__); + free(priv->phydev); + mdio_unregister(priv->mdiobus); + mdio_free(priv->mdiobus); + + return 0; +} diff --git a/drivers/usb/eth/lan7x.h b/drivers/usb/eth/lan7x.h new file mode 100644 index 0000000..4f4b3f8 --- /dev/null +++ b/drivers/usb/eth/lan7x.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2017 Microchip Technology Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <console.h> +#include <watchdog.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 BIT(22) +#define TX_CMD_A_LEN_MASK 0x000FFFFF + +/* Rx Command A */ +#define RX_CMD_A_RXE BIT(18) +#define RX_CMD_A_LEN_MASK 0x00003FFF + +/* SCSRs */ +#define ID_REV 0x00 +#define ID_REV_CHIP_ID_MASK 0xFFFF0000 +#define ID_REV_CHIP_ID_7500 0x7500 +#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_LRST BIT(1) + +#define PMT_CTL 0x014 +#define PMT_CTL_PHY_PWRUP BIT(10) +#define PMT_CTL_READY BIT(7) +#define PMT_CTL_PHY_RST BIT(4) + +#define E2P_CMD 0x040 +#define E2P_CMD_EPC_BUSY BIT(31) +#define E2P_CMD_EPC_CMD_READ 0x00000000 +#define E2P_CMD_EPC_TIMEOUT BIT(10) +#define E2P_CMD_EPC_ADDR_MASK 0x000001FF + +#define E2P_DATA 0x044 + +#define RFE_CTL_BCAST_EN BIT(10) +#define RFE_CTL_DA_PERFECT BIT(1) + +#define FCT_RX_CTL_EN BIT(31) + +#define FCT_TX_CTL_EN BIT(31) + +#define MAC_CR 0x100 +#define MAC_CR_ADP BIT(13) +#define MAC_CR_AUTO_DUPLEX BIT(12) +#define MAC_CR_AUTO_SPEED BIT(11) + +#define MAC_RX 0x104 +#define MAC_RX_FCS_STRIP BIT(4) +#define MAC_RX_RXEN BIT(0) + +#define MAC_TX 0x108 +#define MAC_TX_TXEN BIT(0) + +#define FLOW 0x10C +#define FLOW_CR_TX_FCEN BIT(30) +#define FLOW_CR_RX_FCEN BIT(29) + +#define RX_ADDRH 0x118 +#define RX_ADDRL 0x11C + +#define MII_ACC 0x120 +#define MII_ACC_MII_READ 0x00000000 +#define MII_ACC_MII_WRITE 0x00000002 +#define MII_ACC_MII_BUSY BIT(0) + +#define MII_DATA 0x124 + +#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_BULK_IN_DELAY 0x0800 + +#define EEPROM_INDICATOR 0xA5 +#define EEPROM_MAC_OFFSET 0x01 + +/* Some extra defines */ +#define LAN7X_INTERNAL_PHY_ID 1 + +#define LAN7X_MAC_RX_MAX_SIZE(mtu) \ + ((mtu) << 16) /* Max frame size */ +#define LAN7X_MAC_RX_MAX_SIZE_DEFAULT \ + LAN7X_MAC_RX_MAX_SIZE(ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */) + +/* Timeouts */ +#define USB_CTRL_SET_TIMEOUT_MS 5000 +#define USB_CTRL_GET_TIMEOUT_MS 5000 +#define USB_BULK_SEND_TIMEOUT_MS 5000 +#define USB_BULK_RECV_TIMEOUT_MS 5000 +#define TIMEOUT_RESOLUTION_MS 50 +#define PHY_CONNECT_TIMEOUT_MS 5000 + +#define RX_URB_SIZE 2048 + +/* driver private */ +struct lan7x_private { + struct ueth_data ueth; + u32 chipid; /* Chip or device ID */ + struct mii_dev *mdiobus; + struct phy_device *phydev; +}; + +/* + * Lan7x infrastructure commands + */ + +int lan7x_write_reg(struct usb_device *udev, u32 index, u32 data); + +int lan7x_read_reg(struct usb_device *udev, u32 index, u32 *data); + +static inline int lan7x_wait_for_bit(struct usb_device *udev, + const char *prefix, const u32 reg, + const u32 mask, const bool set, + const unsigned int timeout_ms, + const bool breakable) +{ + u32 val; + unsigned long start = get_timer(0); + + while (1) { + lan7x_read_reg(udev, reg, &val); + + if (!set) + val = ~val; + + if ((val & mask) == mask) + return 0; + + if (get_timer(start) > timeout_ms) + break; + + if (breakable && ctrlc()) { + puts("Abort\n"); + return -EINTR; + } + + udelay(1); + WATCHDOG_RESET(); + } + + debug("%s: Timeout (reg=0x%x mask=%08x wait_set=%i)\n", prefix, reg, + mask, set); + + return -ETIMEDOUT; +} + +int lan7x_mdio_read(struct usb_device *udev, int phy_id, int idx); + +void lan7x_mdio_write(struct usb_device *udev, int phy_id, int idx, + int regval); + +static inline int lan7x_mdio_wait_for_bit(struct usb_device *udev, + const char *prefix, + int phy_id, const u32 reg, + const u32 mask, const bool set, + const unsigned int timeout_ms, + const bool breakable) +{ + u32 val; + unsigned long start = get_timer(0); + + while (1) { + val = lan7x_mdio_read(udev, phy_id, reg); + + if (!set) + val = ~val; + + if ((val & mask) == mask) + return 0; + + if (get_timer(start) > timeout_ms) + break; + + if (breakable && ctrlc()) { + puts("Abort\n"); + return -EINTR; + } + + udelay(1); + WATCHDOG_RESET(); + } + + debug("%s: Timeout (reg=0x%x mask=%08x wait_set=%i)\n", prefix, reg, + mask, set); + + return -ETIMEDOUT; +} + +int lan7x_phylib_register(struct udevice *udev); + +int lan7x_eth_phylib_connect(struct udevice *udev, struct ueth_data *dev); + +int lan7x_eth_phylib_config_start(struct udevice *udev); + +int lan7x_pmt_phy_reset(struct usb_device *udev, + struct ueth_data *dev); + +int lan7x_update_flowcontrol(struct usb_device *udev, + struct ueth_data *dev, + uint32_t *flow, uint32_t *fct_flow); + +int lan7x_read_eeprom_mac(unsigned char *enetaddr, struct usb_device *udev); + +int lan7x_basic_reset(struct usb_device *udev, + struct ueth_data *dev); + +void lan7x_eth_stop(struct udevice *dev); + +int lan7x_eth_send(struct udevice *dev, void *packet, int length); + +int lan7x_eth_recv(struct udevice *dev, int flags, uchar **packetp); + +int lan7x_free_pkt(struct udevice *dev, uchar *packet, int packet_len); + +int lan7x_eth_remove(struct udevice *dev);

From: Yuiko Oshino yuiko.oshino@microchip.com
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
---
Changes in v3: - This patch is added to a series.
Changes in v2: - The patch's tag is changed to net:.
include/linux/mii.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/include/linux/mii.h b/include/linux/mii.h index 66b83d8..19afb74 100644 --- a/include/linux/mii.h +++ b/include/linux/mii.h @@ -190,4 +190,27 @@ static inline unsigned int mii_duplex (unsigned int duplex_lock, return 0; }
+/** + * mii_resolve_flowctrl_fdx + * @lcladv: value of MII ADVERTISE register + * @rmtadv: value of MII LPA register + * + * Resolve full duplex flow control as per IEEE 802.3-2005 table 28B-3 + */ +static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv) +{ + u8 cap = 0; + + 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 & ADVERTISE_PAUSE_CAP) + cap = FLOW_CTRL_TX; + } + + return cap; +} + #endif /* __LINUX_MII_H__ */

On Wed, Aug 9, 2017 at 11:25 AM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

On 08/09/2017 06:25 PM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
FYI, this will end in the commit message when applied, remove it or move it below the --- . Also commit message is missing.
- All #ifdef CONFIG_DM_ETH and #endif are removed.
- The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en.
- Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2
- The wait_for_bit functions copy the real one.
- Uses phylib
- Unnecessary variables are removed
- All return values are checked
- Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
drivers/usb/Kconfig | 2 + drivers/usb/eth/Kconfig | 17 ++ drivers/usb/eth/Makefile | 2 + drivers/usb/eth/lan75xx.c | 318 +++++++++++++++++++++++++++++ drivers/usb/eth/lan78xx.c | 477 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/lan7x.c | 495 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/lan7x.h | 230 +++++++++++++++++++++ 7 files changed, 1541 insertions(+) create mode 100644 drivers/usb/eth/Kconfig create mode 100644 drivers/usb/eth/lan75xx.c create mode 100644 drivers/usb/eth/lan78xx.c create mode 100644 drivers/usb/eth/lan7x.c create mode 100644 drivers/usb/eth/lan7x.h
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index da3ec2f..62126aa 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -94,4 +94,6 @@ endif
source "drivers/usb/gadget/Kconfig"
+source "drivers/usb/eth/Kconfig"
endif diff --git a/drivers/usb/eth/Kconfig b/drivers/usb/eth/Kconfig new file mode 100644 index 0000000..14cfa26 --- /dev/null +++ b/drivers/usb/eth/Kconfig @@ -0,0 +1,17 @@ +comment "USB to Ethernet Controller Drivers"
+config USB_ETHER_LAN75XX
- bool "Microchip LAN75XX support"
- ---help---
Say Y here if you would like to support Microchip LAN75XX Hi-Speed
USB 2.0 to 10/100/1000 Gigabit Ethernet controller.
Supports 10Base-T/ 100Base-TX/1000Base-T.
This driver supports the internal PHY.
+config USB_ETHER_LAN78XX
- bool "Microchip LAN78XX support"
- ---help---
Say Y here if you would like to support Microchip LAN78XX USB 3.1
Gen 1 to 10/100/1000 Gigabit Ethernet controller.
Supports 10Base-T/ 100Base-TX/1000Base-T.
This driver supports the internal PHY.
diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile index 4c44efc..4b935a3 100644 --- a/drivers/usb/eth/Makefile +++ b/drivers/usb/eth/Makefile @@ -9,4 +9,6 @@ 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_LAN75XX) += lan7x.o lan75xx.o +obj-$(CONFIG_USB_ETHER_LAN78XX) += lan7x.o lan78xx.o obj-$(CONFIG_USB_ETHER_RTL8152) += r8152.o r8152_fw.o diff --git a/drivers/usb/eth/lan75xx.c b/drivers/usb/eth/lan75xx.c new file mode 100644 index 0000000..a3c1411 --- /dev/null +++ b/drivers/usb/eth/lan75xx.c @@ -0,0 +1,318 @@ +/*
- Copyright (c) 2017 Microchip Technology Inc. All rights reserved.
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <dm.h> +#include <usb.h> +#include <linux/mii.h> +#include "usb_ether.h" +#include "lan7x.h"
+/* LAN75xx specific register/bit defines */ +#define LAN75XX_HW_CFG_BIR BIT(7)
+#define LAN75XX_BURST_CAP 0x034
+#define LAN75XX_BULK_IN_DLY 0x03C
+#define LAN75XX_RFE_CTL 0x060
+#define LAN75XX_FCT_RX_CTL 0x090
+#define LAN75XX_FCT_TX_CTL 0x094
+#define LAN75XX_FCT_RX_FIFO_END 0x098
+#define LAN75XX_FCT_TX_FIFO_END 0x09C
+#define LAN75XX_FCT_FLOW 0x0A0
+/* MAC ADDRESS PERFECT FILTER For LAN75xx */ +#define LAN75XX_ADDR_FILTX 0x300 +#define LAN75XX_ADDR_FILTX_FB_VALID BIT(31)
+/*
- Lan75xx infrastructure commands
- */
+static int lan75xx_phy_gig_workaround(struct usb_device *udev,
struct ueth_data *dev)
+{
- int ret = 0;
- /* Only internal phy */
- /* Set the phy in Gig loopback */
- lan7x_mdio_write(udev, dev->phy_id, MII_BMCR,
(BMCR_LOOPBACK | BMCR_SPEED1000));
- /* Wait for the link up */
- ret = lan7x_mdio_wait_for_bit(udev, "BMSR_LSTATUS",
dev->phy_id, MII_BMSR, BMSR_LSTATUS,
true, PHY_CONNECT_TIMEOUT_MS, 1);
- if (ret)
return ret;
- /* phy reset */
- return lan7x_pmt_phy_reset(udev, dev);
+}
+static int lan75xx_update_flowcontrol(struct usb_device *udev,
struct ueth_data *dev)
+{
- uint32_t flow = 0, fct_flow = 0;
- int ret;
- ret = lan7x_update_flowcontrol(udev, dev, &flow, &fct_flow);
- if (ret)
return ret;
- ret = lan7x_write_reg(udev, LAN75XX_FCT_FLOW, fct_flow);
- if (ret)
return ret;
- return lan7x_write_reg(udev, FLOW, flow);
+}
+static int lan75xx_read_mac(unsigned char *enetaddr,
struct usb_device *udev)
+{
- /*
* Refer to the doc/README.enetaddr and doc/README.usb for
* the U-Boot MAC address policy
*/
- return lan7x_read_eeprom_mac(enetaddr, udev);
Is this function needed ?
+}
+static int lan75xx_set_receive_filter(struct usb_device *udev) +{
- /* No multicast in u-boot */
- return lan7x_write_reg(udev, LAN75XX_RFE_CTL,
RFE_CTL_BCAST_EN | RFE_CTL_DA_PERFECT);
+}
+/* starts the TX path */ +static void lan75xx_start_tx_path(struct usb_device *udev) +{
- /* Enable Tx at MAC */
- lan7x_write_reg(udev, MAC_TX, MAC_TX_TXEN);
- /* Enable Tx at SCSRs */
- lan7x_write_reg(udev, LAN75XX_FCT_TX_CTL, FCT_TX_CTL_EN);
+}
+/* Starts the Receive path */ +static void lan75xx_start_rx_path(struct usb_device *udev) +{
- /* Enable Rx at MAC */
- lan7x_write_reg(udev, MAC_RX,
LAN7X_MAC_RX_MAX_SIZE_DEFAULT |
MAC_RX_FCS_STRIP | MAC_RX_RXEN);
- /* Enable Rx at SCSRs */
- lan7x_write_reg(udev, LAN75XX_FCT_RX_CTL, FCT_RX_CTL_EN);
+}
+static int lan75xx_basic_reset(struct usb_device *udev,
struct ueth_data *dev,
struct lan7x_private *priv)
+{
- int ret;
- u32 val;
- ret = lan7x_basic_reset(udev, dev);
- if (ret)
return ret;
- /* Keep the chip ID */
- ret = lan7x_read_reg(udev, ID_REV, &val);
- if (ret)
return ret;
- debug("LAN75xx ID_REV = 0x%08x\n", val);
Some sort of USB bus ID would be useful in the debug message to identify the chip in case multiple are present.
- priv->chipid = (val & ID_REV_CHIP_ID_MASK) >> 16;
- /* Respond to the IN token with a NAK */
- ret = lan7x_read_reg(udev, HW_CFG, &val);
- if (ret)
return ret;
- val |= LAN75XX_HW_CFG_BIR;
- return lan7x_write_reg(udev, HW_CFG, val);
+}
[...]

On Wed, Aug 9, 2017 at 12:12 PM, Marek Vasut marex@denx.de wrote:
On 08/09/2017 06:25 PM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
FYI, this will end in the commit message when applied, remove it or move it below the --- . Also commit message is missing.
This is what I was talking about when I said I would fix the commit log as I apply it.
- All #ifdef CONFIG_DM_ETH and #endif are removed.
- The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en.
- Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2
- The wait_for_bit functions copy the real one.
- Uses phylib
- Unnecessary variables are removed
- All return values are checked
- Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.

On 08/09/2017 07:47 PM, Joe Hershberger wrote:
On Wed, Aug 9, 2017 at 12:12 PM, Marek Vasut marex@denx.de wrote:
On 08/09/2017 06:25 PM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
FYI, this will end in the commit message when applied, remove it or move it below the --- . Also commit message is missing.
This is what I was talking about when I said I would fix the commit log as I apply it.
I have a few more comments though, but feel free to fix them up too.
- All #ifdef CONFIG_DM_ETH and #endif are removed.
- The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en.
- Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2
- The wait_for_bit functions copy the real one.
- Uses phylib
- Unnecessary variables are removed
- All return values are checked
- Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.

On Thu, Aug 10, 2017 at 2:15 AM, Marek Vasut marex@denx.de wrote:
On 08/09/2017 07:47 PM, Joe Hershberger wrote:
On Wed, Aug 9, 2017 at 12:12 PM, Marek Vasut marex@denx.de wrote:
On 08/09/2017 06:25 PM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
FYI, this will end in the commit message when applied, remove it or move it below the --- . Also commit message is missing.
This is what I was talking about when I said I would fix the commit log as I apply it.
I have a few more comments though, but feel free to fix them up too.
I'll let you guys work through the rest of your comments and apply them when you're done.
Cheers, -Joe

Hi Marek,
-----Original Message----- From: Marek Vasut [mailto:marex@denx.de] Sent: Wednesday, August 9, 2017 1:12 PM To: Yuiko Oshino - C18177; u-boot@lists.denx.de Cc: Joe Hershberger Subject: Re: [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx
On 08/09/2017 06:25 PM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
FYI, this will end in the commit message when applied, remove it or move it below the --- . Also commit message is missing.
I did my best to follow the patman instructions and I added "commit-notes:" tag, but I guess it wasn't good enough. Should I always manually edit the patch before sending email in the patman? Also, when I am ready to update this patch again, should I do a series or just this patch? How can I update the [PATCH v] number? If just his patch, then will it be [PATCH v4]?
- All #ifdef CONFIG_DM_ETH and #endif are removed.
- The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en.
- Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2
- The wait_for_bit functions copy the real one.
- Uses phylib
- Unnecessary variables are removed
- All return values are checked
- Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
drivers/usb/Kconfig | 2 + drivers/usb/eth/Kconfig | 17 ++ drivers/usb/eth/Makefile | 2 + drivers/usb/eth/lan75xx.c | 318 +++++++++++++++++++++++++++++ drivers/usb/eth/lan78xx.c | 477
++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.c | 495
++++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.h | 230 +++++++++++++++++++++ 7 files changed, 1541 insertions(+) create mode 100644 drivers/usb/eth/Kconfig create mode 100644 drivers/usb/eth/lan75xx.c create mode 100644 drivers/usb/eth/lan78xx.c create mode 100644 drivers/usb/eth/lan7x.c create mode 100644 drivers/usb/eth/lan7x.h
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index da3ec2f..62126aa 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -94,4 +94,6 @@ endif
source "drivers/usb/gadget/Kconfig"
+source "drivers/usb/eth/Kconfig"
endif diff --git a/drivers/usb/eth/Kconfig b/drivers/usb/eth/Kconfig new file mode 100644 index 0000000..14cfa26 --- /dev/null +++ b/drivers/usb/eth/Kconfig @@ -0,0 +1,17 @@ +comment "USB to Ethernet Controller Drivers"
+config USB_ETHER_LAN75XX
- bool "Microchip LAN75XX support"
- ---help---
Say Y here if you would like to support Microchip LAN75XX Hi-Speed
USB 2.0 to 10/100/1000 Gigabit Ethernet controller.
Supports 10Base-T/ 100Base-TX/1000Base-T.
This driver supports the internal PHY.
+config USB_ETHER_LAN78XX
- bool "Microchip LAN78XX support"
- ---help---
Say Y here if you would like to support Microchip LAN78XX USB 3.1
Gen 1 to 10/100/1000 Gigabit Ethernet controller.
Supports 10Base-T/ 100Base-TX/1000Base-T.
This driver supports the internal PHY.
diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile index 4c44efc..4b935a3 100644 --- a/drivers/usb/eth/Makefile +++ b/drivers/usb/eth/Makefile @@ -9,4 +9,6 @@ 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_LAN75XX) += lan7x.o lan75xx.o +obj-$(CONFIG_USB_ETHER_LAN78XX) += lan7x.o lan78xx.o obj-$(CONFIG_USB_ETHER_RTL8152) += r8152.o r8152_fw.o diff --git a/drivers/usb/eth/lan75xx.c b/drivers/usb/eth/lan75xx.c new file mode 100644 index 0000000..a3c1411 --- /dev/null +++ b/drivers/usb/eth/lan75xx.c @@ -0,0 +1,318 @@ +/*
- Copyright (c) 2017 Microchip Technology Inc. All rights reserved.
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <dm.h> +#include <usb.h> +#include <linux/mii.h> +#include "usb_ether.h" +#include "lan7x.h"
+/* LAN75xx specific register/bit defines */ +#define LAN75XX_HW_CFG_BIR BIT(7)
+#define LAN75XX_BURST_CAP 0x034
+#define LAN75XX_BULK_IN_DLY 0x03C
+#define LAN75XX_RFE_CTL 0x060
+#define LAN75XX_FCT_RX_CTL 0x090
+#define LAN75XX_FCT_TX_CTL 0x094
+#define LAN75XX_FCT_RX_FIFO_END 0x098
+#define LAN75XX_FCT_TX_FIFO_END 0x09C
+#define LAN75XX_FCT_FLOW 0x0A0
+/* MAC ADDRESS PERFECT FILTER For LAN75xx */ +#define LAN75XX_ADDR_FILTX 0x300 +#define LAN75XX_ADDR_FILTX_FB_VALID BIT(31)
+/*
- Lan75xx infrastructure commands
- */
+static int lan75xx_phy_gig_workaround(struct usb_device *udev,
struct ueth_data *dev)
+{
- int ret = 0;
- /* Only internal phy */
- /* Set the phy in Gig loopback */
- lan7x_mdio_write(udev, dev->phy_id, MII_BMCR,
(BMCR_LOOPBACK | BMCR_SPEED1000));
- /* Wait for the link up */
- ret = lan7x_mdio_wait_for_bit(udev, "BMSR_LSTATUS",
dev->phy_id, MII_BMSR, BMSR_LSTATUS,
true, PHY_CONNECT_TIMEOUT_MS, 1);
- if (ret)
return ret;
- /* phy reset */
- return lan7x_pmt_phy_reset(udev, dev); }
+static int lan75xx_update_flowcontrol(struct usb_device *udev,
struct ueth_data *dev)
+{
- uint32_t flow = 0, fct_flow = 0;
- int ret;
- ret = lan7x_update_flowcontrol(udev, dev, &flow, &fct_flow);
- if (ret)
return ret;
- ret = lan7x_write_reg(udev, LAN75XX_FCT_FLOW, fct_flow);
- if (ret)
return ret;
- return lan7x_write_reg(udev, FLOW, flow); }
+static int lan75xx_read_mac(unsigned char *enetaddr,
struct usb_device *udev)
+{
- /*
* Refer to the doc/README.enetaddr and doc/README.usb for
* the U-Boot MAC address policy
*/
- return lan7x_read_eeprom_mac(enetaddr, udev);
Is this function needed ?
I wanted to maintain the same function name convention among our drivers. Therefore the wrapper for this device. But I can remove it.
+}
+static int lan75xx_set_receive_filter(struct usb_device *udev) {
- /* No multicast in u-boot */
- return lan7x_write_reg(udev, LAN75XX_RFE_CTL,
RFE_CTL_BCAST_EN | RFE_CTL_DA_PERFECT); }
+/* starts the TX path */ +static void lan75xx_start_tx_path(struct usb_device *udev) {
- /* Enable Tx at MAC */
- lan7x_write_reg(udev, MAC_TX, MAC_TX_TXEN);
- /* Enable Tx at SCSRs */
- lan7x_write_reg(udev, LAN75XX_FCT_TX_CTL, FCT_TX_CTL_EN); }
+/* Starts the Receive path */ +static void lan75xx_start_rx_path(struct usb_device *udev) {
- /* Enable Rx at MAC */
- lan7x_write_reg(udev, MAC_RX,
LAN7X_MAC_RX_MAX_SIZE_DEFAULT |
MAC_RX_FCS_STRIP | MAC_RX_RXEN);
- /* Enable Rx at SCSRs */
- lan7x_write_reg(udev, LAN75XX_FCT_RX_CTL, FCT_RX_CTL_EN); }
+static int lan75xx_basic_reset(struct usb_device *udev,
struct ueth_data *dev,
struct lan7x_private *priv) {
- int ret;
- u32 val;
- ret = lan7x_basic_reset(udev, dev);
- if (ret)
return ret;
- /* Keep the chip ID */
- ret = lan7x_read_reg(udev, ID_REV, &val);
- if (ret)
return ret;
- debug("LAN75xx ID_REV = 0x%08x\n", val);
Some sort of USB bus ID would be useful in the debug message to identify the chip in case multiple are present.
I can add this to the lan7x_basic_reset() debug("USB devnum %d portnr %d\n", udev->devnum, udev->portnr); This shows device number and port number. Is this ok?
- priv->chipid = (val & ID_REV_CHIP_ID_MASK) >> 16;
- /* Respond to the IN token with a NAK */
- ret = lan7x_read_reg(udev, HW_CFG, &val);
- if (ret)
return ret;
- val |= LAN75XX_HW_CFG_BIR;
- return lan7x_write_reg(udev, HW_CFG, val); }
[...]
Best regards, Marek Vasut
Thank you! Yuiko

On 08/10/2017 08:13 PM, Yuiko.Oshino@microchip.com wrote:
Hi Marek,
Hi,
-----Original Message----- From: Marek Vasut [mailto:marex@denx.de] Sent: Wednesday, August 9, 2017 1:12 PM To: Yuiko Oshino - C18177; u-boot@lists.denx.de Cc: Joe Hershberger Subject: Re: [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx
On 08/09/2017 06:25 PM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
FYI, this will end in the commit message when applied, remove it or move it below the --- . Also commit message is missing.
I did my best to follow the patman instructions and I added "commit-notes:" tag, but I guess it wasn't good enough. Should I always manually edit the patch before sending email in the patman? Also, when I am ready to update this patch again, should I do a series or just this patch? How can I update the [PATCH v] number? If just his patch, then will it be [PATCH v4]?
TBH, I dunno, I don't use patman :)
- All #ifdef CONFIG_DM_ETH and #endif are removed.
- The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en.
- Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2
- The wait_for_bit functions copy the real one.
- Uses phylib
- Unnecessary variables are removed
- All return values are checked
- Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
drivers/usb/Kconfig | 2 + drivers/usb/eth/Kconfig | 17 ++ drivers/usb/eth/Makefile | 2 + drivers/usb/eth/lan75xx.c | 318 +++++++++++++++++++++++++++++ drivers/usb/eth/lan78xx.c | 477
++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.c | 495
++++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.h | 230 +++++++++++++++++++++ 7 files changed, 1541 insertions(+) create mode 100644 drivers/usb/eth/Kconfig create mode 100644 drivers/usb/eth/lan75xx.c create mode 100644 drivers/usb/eth/lan78xx.c create mode 100644 drivers/usb/eth/lan7x.c create mode 100644 drivers/usb/eth/lan7x.h
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index da3ec2f..62126aa 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -94,4 +94,6 @@ endif
source "drivers/usb/gadget/Kconfig"
+source "drivers/usb/eth/Kconfig"
endif diff --git a/drivers/usb/eth/Kconfig b/drivers/usb/eth/Kconfig new file mode 100644 index 0000000..14cfa26 --- /dev/null +++ b/drivers/usb/eth/Kconfig @@ -0,0 +1,17 @@ +comment "USB to Ethernet Controller Drivers"
+config USB_ETHER_LAN75XX
- bool "Microchip LAN75XX support"
- ---help---
Say Y here if you would like to support Microchip LAN75XX Hi-Speed
USB 2.0 to 10/100/1000 Gigabit Ethernet controller.
Supports 10Base-T/ 100Base-TX/1000Base-T.
This driver supports the internal PHY.
+config USB_ETHER_LAN78XX
- bool "Microchip LAN78XX support"
- ---help---
Say Y here if you would like to support Microchip LAN78XX USB 3.1
Gen 1 to 10/100/1000 Gigabit Ethernet controller.
Supports 10Base-T/ 100Base-TX/1000Base-T.
This driver supports the internal PHY.
diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile index 4c44efc..4b935a3 100644 --- a/drivers/usb/eth/Makefile +++ b/drivers/usb/eth/Makefile @@ -9,4 +9,6 @@ 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_LAN75XX) += lan7x.o lan75xx.o +obj-$(CONFIG_USB_ETHER_LAN78XX) += lan7x.o lan78xx.o obj-$(CONFIG_USB_ETHER_RTL8152) += r8152.o r8152_fw.o diff --git a/drivers/usb/eth/lan75xx.c b/drivers/usb/eth/lan75xx.c new file mode 100644 index 0000000..a3c1411 --- /dev/null +++ b/drivers/usb/eth/lan75xx.c @@ -0,0 +1,318 @@ +/*
- Copyright (c) 2017 Microchip Technology Inc. All rights reserved.
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <dm.h> +#include <usb.h> +#include <linux/mii.h> +#include "usb_ether.h" +#include "lan7x.h"
+/* LAN75xx specific register/bit defines */ +#define LAN75XX_HW_CFG_BIR BIT(7)
+#define LAN75XX_BURST_CAP 0x034
+#define LAN75XX_BULK_IN_DLY 0x03C
+#define LAN75XX_RFE_CTL 0x060
+#define LAN75XX_FCT_RX_CTL 0x090
+#define LAN75XX_FCT_TX_CTL 0x094
+#define LAN75XX_FCT_RX_FIFO_END 0x098
+#define LAN75XX_FCT_TX_FIFO_END 0x09C
+#define LAN75XX_FCT_FLOW 0x0A0
+/* MAC ADDRESS PERFECT FILTER For LAN75xx */ +#define LAN75XX_ADDR_FILTX 0x300 +#define LAN75XX_ADDR_FILTX_FB_VALID BIT(31)
+/*
- Lan75xx infrastructure commands
- */
+static int lan75xx_phy_gig_workaround(struct usb_device *udev,
struct ueth_data *dev)
+{
- int ret = 0;
- /* Only internal phy */
- /* Set the phy in Gig loopback */
- lan7x_mdio_write(udev, dev->phy_id, MII_BMCR,
(BMCR_LOOPBACK | BMCR_SPEED1000));
- /* Wait for the link up */
- ret = lan7x_mdio_wait_for_bit(udev, "BMSR_LSTATUS",
dev->phy_id, MII_BMSR, BMSR_LSTATUS,
true, PHY_CONNECT_TIMEOUT_MS, 1);
- if (ret)
return ret;
- /* phy reset */
- return lan7x_pmt_phy_reset(udev, dev); }
+static int lan75xx_update_flowcontrol(struct usb_device *udev,
struct ueth_data *dev)
+{
- uint32_t flow = 0, fct_flow = 0;
- int ret;
- ret = lan7x_update_flowcontrol(udev, dev, &flow, &fct_flow);
- if (ret)
return ret;
- ret = lan7x_write_reg(udev, LAN75XX_FCT_FLOW, fct_flow);
- if (ret)
return ret;
- return lan7x_write_reg(udev, FLOW, flow); }
+static int lan75xx_read_mac(unsigned char *enetaddr,
struct usb_device *udev)
+{
- /*
* Refer to the doc/README.enetaddr and doc/README.usb for
* the U-Boot MAC address policy
*/
- return lan7x_read_eeprom_mac(enetaddr, udev);
Is this function needed ?
I wanted to maintain the same function name convention among our drivers. Therefore the wrapper for this device. But I can remove it.
Please do.
+}
+static int lan75xx_set_receive_filter(struct usb_device *udev) {
- /* No multicast in u-boot */
- return lan7x_write_reg(udev, LAN75XX_RFE_CTL,
RFE_CTL_BCAST_EN | RFE_CTL_DA_PERFECT); }
+/* starts the TX path */ +static void lan75xx_start_tx_path(struct usb_device *udev) {
- /* Enable Tx at MAC */
- lan7x_write_reg(udev, MAC_TX, MAC_TX_TXEN);
- /* Enable Tx at SCSRs */
- lan7x_write_reg(udev, LAN75XX_FCT_TX_CTL, FCT_TX_CTL_EN); }
+/* Starts the Receive path */ +static void lan75xx_start_rx_path(struct usb_device *udev) {
- /* Enable Rx at MAC */
- lan7x_write_reg(udev, MAC_RX,
LAN7X_MAC_RX_MAX_SIZE_DEFAULT |
MAC_RX_FCS_STRIP | MAC_RX_RXEN);
- /* Enable Rx at SCSRs */
- lan7x_write_reg(udev, LAN75XX_FCT_RX_CTL, FCT_RX_CTL_EN); }
+static int lan75xx_basic_reset(struct usb_device *udev,
struct ueth_data *dev,
struct lan7x_private *priv) {
- int ret;
- u32 val;
- ret = lan7x_basic_reset(udev, dev);
- if (ret)
return ret;
- /* Keep the chip ID */
- ret = lan7x_read_reg(udev, ID_REV, &val);
- if (ret)
return ret;
- debug("LAN75xx ID_REV = 0x%08x\n", val);
Some sort of USB bus ID would be useful in the debug message to identify the chip in case multiple are present.
I can add this to the lan7x_basic_reset() debug("USB devnum %d portnr %d\n", udev->devnum, udev->portnr); This shows device number and port number. Is this ok?
Yes, thanks.

On Thu, Aug 10, 2017 at 1:13 PM, Yuiko.Oshino@microchip.com wrote:
Hi Marek,
-----Original Message----- From: Marek Vasut [mailto:marex@denx.de] Sent: Wednesday, August 9, 2017 1:12 PM To: Yuiko Oshino - C18177; u-boot@lists.denx.de Cc: Joe Hershberger Subject: Re: [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx
On 08/09/2017 06:25 PM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
FYI, this will end in the commit message when applied, remove it or move it below the --- . Also commit message is missing.
I did my best to follow the patman instructions and I added "commit-notes:" tag, but I guess it wasn't good enough.
You need to not use commit notes here. That's for things that you want to be a note in the email, but not end up in the commit log.
Should I always manually edit the patch before sending email in the patman?
No, you shouldn't have to. The reason this failed to be removed is that you capitalized the 'C' in changes, and it didn't see it.
Also, these tags are parsed and included as notes. You don't want to put these in a commit notes tag. That's only needed for other random commit notes.
Also, when I am ready to update this patch again, should I do a series or just this patch?
Do the series. Also, you should have the dependency patch first, and the dependent patch second (swap them around).
How can I update the [PATCH v] number? If just his patch, then will it be [PATCH v4]?
Go ahead and use v4. So use:
Series-version: 4
- All #ifdef CONFIG_DM_ETH and #endif are removed.
- The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en.
- Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2
- The wait_for_bit functions copy the real one.
- Uses phylib
- Unnecessary variables are removed
- All return values are checked
- Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
The fact that this is in the notes means that you put it under "Commit-notes:" ... "END"
drivers/usb/Kconfig | 2 + drivers/usb/eth/Kconfig | 17 ++ drivers/usb/eth/Makefile | 2 + drivers/usb/eth/lan75xx.c | 318 +++++++++++++++++++++++++++++ drivers/usb/eth/lan78xx.c | 477
++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.c | 495
++++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.h | 230 +++++++++++++++++++++ 7 files changed, 1541 insertions(+)
-Joe

-----Original Message----- From: Joe Hershberger [mailto:joe.hershberger@ni.com] Sent: Thursday, August 10, 2017 2:45 PM To: Yuiko Oshino - C18177 Cc: Marek Vasut; u-boot; Joe Hershberger Subject: Re: [U-Boot] [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx
On Thu, Aug 10, 2017 at 1:13 PM, Yuiko.Oshino@microchip.com wrote:
Hi Marek,
-----Original Message----- From: Marek Vasut [mailto:marex@denx.de] Sent: Wednesday, August 9, 2017 1:12 PM To: Yuiko Oshino - C18177; u-boot@lists.denx.de Cc: Joe Hershberger Subject: Re: [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx
On 08/09/2017 06:25 PM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
FYI, this will end in the commit message when applied, remove it or move it below the --- . Also commit message is missing.
I did my best to follow the patman instructions and I added "commit-notes:" tag,
but I guess it wasn't good enough.
You need to not use commit notes here. That's for things that you want to be a note in the email, but not end up in the commit log.
Understood. So what is the "commit message" that Marek meant that I missed?
Should I always manually edit the patch before sending email in the patman?
No, you shouldn't have to. The reason this failed to be removed is that you capitalized the 'C' in changes, and it didn't see it.
I see...
Also, these tags are parsed and included as notes. You don't want to put these in a commit notes tag. That's only needed for other random commit notes.
What are "threse"?
Also, when I am ready to update this patch again, should I do a series or just this
patch?
Do the series. Also, you should have the dependency patch first, and the dependent patch second (swap them around).
How can I update the [PATCH v] number? If just his patch, then will it be [PATCH
v4]?
Go ahead and use v4. So use:
Series-version: 4
Got it.
- All #ifdef CONFIG_DM_ETH and #endif are removed.
- The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en.
- Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2
- The wait_for_bit functions copy the real one.
- Uses phylib
- Unnecessary variables are removed
- All return values are checked
- Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
The fact that this is in the notes means that you put it under "Commit-notes:" ... "END"
Yes, I did. Is the Commit-notes: == Commit message? Do I still need this tag?
Following tags are all I need? Series-to: u-boot Series-version: 4 Series-changes: 4 Series-changes: 3 Series-changes: 2 Series-changes: 1 Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Should I add Acked-by:?
drivers/usb/Kconfig | 2 + drivers/usb/eth/Kconfig | 17 ++ drivers/usb/eth/Makefile | 2 + drivers/usb/eth/lan75xx.c | 318 +++++++++++++++++++++++++++++ drivers/usb/eth/lan78xx.c | 477
++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.c | 495
++++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.h | 230 +++++++++++++++++++++ 7 files changed, 1541 insertions(+)
-Joe
Thank you, Joe. Yuiko

On Thu, Aug 10, 2017 at 2:32 PM, Yuiko.Oshino@microchip.com wrote:
-----Original Message----- From: Joe Hershberger [mailto:joe.hershberger@ni.com] Sent: Thursday, August 10, 2017 2:45 PM To: Yuiko Oshino - C18177 Cc: Marek Vasut; u-boot; Joe Hershberger Subject: Re: [U-Boot] [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx
On Thu, Aug 10, 2017 at 1:13 PM, Yuiko.Oshino@microchip.com wrote:
Hi Marek,
-----Original Message----- From: Marek Vasut [mailto:marex@denx.de] Sent: Wednesday, August 9, 2017 1:12 PM To: Yuiko Oshino - C18177; u-boot@lists.denx.de Cc: Joe Hershberger Subject: Re: [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx
On 08/09/2017 06:25 PM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
FYI, this will end in the commit message when applied, remove it or move it below the --- . Also commit message is missing.
I did my best to follow the patman instructions and I added "commit-notes:" tag,
but I guess it wasn't good enough.
You need to not use commit notes here. That's for things that you want to be a note in the email, but not end up in the commit log.
Understood. So what is the "commit message" that Marek meant that I missed?
This: Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
Should I always manually edit the patch before sending email in the patman?
No, you shouldn't have to. The reason this failed to be removed is that you capitalized the 'C' in changes, and it didn't see it.
I see...
Also, these tags are parsed and included as notes. You don't want to put these in a commit notes tag. That's only needed for other random commit notes.
What are "threse"?
The tags I was referring to the Series-*: tags. It seemed like you were putting those tags into the Commit-notes: since that's there they should ultimately end up, but I'm saying that it happens for you. There should not be any nested tags.
Also, when I am ready to update this patch again, should I do a series or just this
patch?
Do the series. Also, you should have the dependency patch first, and the dependent patch second (swap them around).
How can I update the [PATCH v] number? If just his patch, then will it be [PATCH
v4]?
Go ahead and use v4. So use:
Series-version: 4
Got it.
- All #ifdef CONFIG_DM_ETH and #endif are removed.
- The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en.
- Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2
- The wait_for_bit functions copy the real one.
- Uses phylib
- Unnecessary variables are removed
- All return values are checked
- Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
The fact that this is in the notes means that you put it under "Commit-notes:" ... "END"
Yes, I did. Is the Commit-notes: == Commit message?
That's not correct. Commit-notes: is for the random other notes that you want not to be in git.
Just like not using patman, the standard un-tagged text is the Commit message.
Do I still need this tag?
No, unless you have something to say in the notes beyond the change comments.
Following tags are all I need? Series-to: u-boot Series-version: 4 Series-changes: 4 Series-changes: 3 Series-changes: 2 Series-changes: 1
Presumably there is no change for the initial version.
Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
Should I add Acked-by:?
Yes, you should add any Acked-by that you got on a previous version to the commit so it is already included in all following versions.
drivers/usb/Kconfig | 2 + drivers/usb/eth/Kconfig | 17 ++ drivers/usb/eth/Makefile | 2 + drivers/usb/eth/lan75xx.c | 318 +++++++++++++++++++++++++++++ drivers/usb/eth/lan78xx.c | 477
++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.c | 495
++++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.h | 230 +++++++++++++++++++++ 7 files changed, 1541 insertions(+)
-Joe
Thank you, Joe. Yuiko

-----Original Message----- From: Joe Hershberger [mailto:joe.hershberger@gmail.com] Sent: Thursday, August 10, 2017 5:12 PM To: Yuiko Oshino - C18177 Cc: Marek Vasut; u-boot Subject: Re: [U-Boot] [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx
On Thu, Aug 10, 2017 at 2:32 PM, Yuiko.Oshino@microchip.com wrote:
-----Original Message----- From: Joe Hershberger [mailto:joe.hershberger@ni.com] Sent: Thursday, August 10, 2017 2:45 PM To: Yuiko Oshino - C18177 Cc: Marek Vasut; u-boot; Joe Hershberger Subject: Re: [U-Boot] [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx
On Thu, Aug 10, 2017 at 1:13 PM, Yuiko.Oshino@microchip.com wrote:
Hi Marek,
-----Original Message----- From: Marek Vasut [mailto:marex@denx.de] Sent: Wednesday, August 9, 2017 1:12 PM To: Yuiko Oshino - C18177; u-boot@lists.denx.de Cc: Joe Hershberger Subject: Re: [PATCH v3 1/2] usb: net: Add support for Microchip LAN75xx and LAN78xx
On 08/09/2017 06:25 PM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
FYI, this will end in the commit message when applied, remove it or move it below the --- . Also commit message is missing.
I did my best to follow the patman instructions and I added "commit-notes:" tag,
but I guess it wasn't good enough.
You need to not use commit notes here. That's for things that you want to be a note in the email, but not end up in the commit log.
Understood. So what is the "commit message" that Marek meant that I missed?
This: Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
Should I always manually edit the patch before sending email in the patman?
No, you shouldn't have to. The reason this failed to be removed is that you capitalized the 'C' in changes, and it didn't see it.
I see...
Also, these tags are parsed and included as notes. You don't want to put these in a commit notes tag. That's only needed for other random commit
notes.
What are "threse"?
The tags I was referring to the Series-*: tags. It seemed like you were putting those tags into the Commit-notes: since that's there they should ultimately end up, but I'm saying that it happens for you. There should not be any nested tags.
Series-*: tags were placed after Commit-notes: and END, so I did not think it was nested. In any case, I can delete the Commit-notes: and just add the non-tagged commit message. And I fixed the C to c and they look much better. Thank you so much.
Also, when I am ready to update this patch again, should I do a series or just this
patch?
Do the series. Also, you should have the dependency patch first, and the dependent patch second (swap them around).
How can I update the [PATCH v] number? If just his patch, then will it be [PATCH
v4]?
Go ahead and use v4. So use:
Series-version: 4
Got it.
- All #ifdef CONFIG_DM_ETH and #endif are removed.
- The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en.
- Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2
- The wait_for_bit functions copy the real one.
- Uses phylib
- Unnecessary variables are removed
- All return values are checked
- Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
The fact that this is in the notes means that you put it under "Commit-notes:" ... "END"
Yes, I did. Is the Commit-notes: == Commit message?
That's not correct. Commit-notes: is for the random other notes that you want not to be in git.
Just like not using patman, the standard un-tagged text is the Commit message.
Do I still need this tag?
No, unless you have something to say in the notes beyond the change comments.
Following tags are all I need? Series-to: u-boot Series-version: 4 Series-changes: 4 Series-changes: 3 Series-changes: 2 Series-changes: 1
Presumably there is no change for the initial version.
That's right...!
Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
Should I add Acked-by:?
Yes, you should add any Acked-by that you got on a previous version to the commit so it is already included in all following versions.
drivers/usb/Kconfig | 2 + drivers/usb/eth/Kconfig | 17 ++ drivers/usb/eth/Makefile | 2 + drivers/usb/eth/lan75xx.c | 318 +++++++++++++++++++++++++++++ drivers/usb/eth/lan78xx.c | 477
++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.c | 495
++++++++++++++++++++++++++++++++++++++++++++++
drivers/usb/eth/lan7x.h | 230 +++++++++++++++++++++ 7 files changed, 1541 insertions(+)
-Joe
Thank you, Joe. Yuiko

On Wed, Aug 9, 2017 at 11:25 AM, yuiko.oshino@microchip.com wrote:
From: Yuiko Oshino yuiko.oshino@microchip.com
Series-Changes: 3
- All #ifdef CONFIG_DM_ETH and #endif are removed.
- The lan7x_eth_recv() is modifed to correctly support the Driver Model and returns packet_en.
- Add mii_resolve_flowctrl_fdx() patch in the series.
Series-Changes: 2
- The wait_for_bit functions copy the real one.
- Uses phylib
- Unnecessary variables are removed
- All return values are checked
- Uses mii_resolve_flowctrl_fdx() from linux/mii.h
Signed-off-by: Yuiko Oshino yuiko.oshino@microchip.com
Add support for Microchip LAN7500, LAN7800 and LAN7850, USB to 10/100/1000 Ethernet Controllers.
I'll fix up this commit log as I pull it.
Acked-by: Joe Hershberger joe.hershberger@ni.com
participants (5)
-
Joe Hershberger
-
Joe Hershberger
-
Marek Vasut
-
Yuiko.Oshino@microchip.com
-
yuiko.oshino@microchip.com