From cec6fd5d85511bd7364d8472c28f7136a3196edb Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Mon, 13 Jan 2014 12:39:59 +0400 Subject: [PATCH 1/6] net/phy: add driver for National Semiconductor DP83865 PHY Based on Linux kernel 3.12 driver. Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- drivers/net/phy/Kconfig | 5 ++ drivers/net/phy/Makefile | 1 + drivers/net/phy/national.c | 95 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 drivers/net/phy/national.c diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 7ebdaa0c0..260774e26 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -23,6 +23,11 @@ config MICREL_PHY ---help--- Supports the KSZ9021, VSC8201, KS8001 PHYs. +config NATIONAL_PHY + bool "Driver for National Semiconductor PHYs" + ---help--- + Currently supports the DP83865 PHY. + config SMSC_PHY bool "Drivers for SMSC PHYs" ---help--- diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 451573ed8..a00cc76ef 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -2,4 +2,5 @@ obj-y += phy.o mdio_bus.o obj-$(CONFIG_AT803X_PHY) += at803x.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_MICREL_PHY) += micrel.o +obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_SMSC_PHY) += smsc.o diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c new file mode 100644 index 000000000..e46d587cd --- /dev/null +++ b/drivers/net/phy/national.c @@ -0,0 +1,95 @@ +/* + * drivers/net/phy/national.c + * + * Driver for National Semiconductor PHYs + * + * based on Stuart Menefy's linux national.c driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include + +/* Advanced proprietary configuration */ +#define NS_EXP_MEM_CTL 0x16 +#define NS_EXP_MEM_DATA 0x1d +#define NS_EXP_MEM_ADD 0x1e + +#define LED_CTRL_REG 0x13 +#define AN_FALLBACK_AN 0x0001 +#define AN_FALLBACK_CRC 0x0002 +#define AN_FALLBACK_IE 0x0004 +#define ALL_FALLBACK_ON (AN_FALLBACK_AN | AN_FALLBACK_CRC | AN_FALLBACK_IE) + +enum hdx_loopback { + hdx_loopback_on = 0, + hdx_loopback_off = 1, +}; + +static u8 ns_exp_read(struct phy_device *phydev, u16 reg) +{ + phy_write(phydev, NS_EXP_MEM_ADD, reg); + return phy_read(phydev, NS_EXP_MEM_DATA); +} + +static void ns_exp_write(struct phy_device *phydev, u16 reg, u8 data) +{ + phy_write(phydev, NS_EXP_MEM_ADD, reg); + phy_write(phydev, NS_EXP_MEM_DATA, data); +} + +static void ns_giga_speed_fallback(struct phy_device *phydev, int mode) +{ + int bmcr = phy_read(phydev, MII_BMCR); + + phy_write(phydev, MII_BMCR, (bmcr | BMCR_PDOWN)); + + /* Enable 8 bit expended memory read/write (no auto increment) */ + phy_write(phydev, NS_EXP_MEM_CTL, 0); + phy_write(phydev, NS_EXP_MEM_ADD, 0x1C0); + phy_write(phydev, NS_EXP_MEM_DATA, 0x0008); + phy_write(phydev, MII_BMCR, (bmcr & ~BMCR_PDOWN)); + phy_write(phydev, LED_CTRL_REG, mode); +} + +static void ns_10_base_t_hdx_loopack(struct phy_device *phydev, int disable) +{ + if (disable) + ns_exp_write(phydev, 0x1c0, ns_exp_read(phydev, 0x1c0) | 1); + else + ns_exp_write(phydev, 0x1c0, + ns_exp_read(phydev, 0x1c0) & 0xfffe); + + pr_debug("10BASE-T HDX loopback %s\n", + (ns_exp_read(phydev, 0x1c0) & 0x0001) ? "off" : "on"); +} + +static int ns_config_init(struct phy_device *phydev) +{ + ns_giga_speed_fallback(phydev, ALL_FALLBACK_ON); + /* In the latest MAC or switches design, the 10 Mbps loopback + is desired to be turned off. */ + ns_10_base_t_hdx_loopack(phydev, hdx_loopback_off); + + return 0; +} + +static struct phy_driver dp83865_driver = { + .phy_id = 0x20005c70, + .phy_id_mask = 0xfffffff0, + .drv.name = "NatSemi DP83865", + .features = PHY_GBIT_FEATURES | + SUPPORTED_Pause | SUPPORTED_Asym_Pause, + .config_init = ns_config_init, +}; + +static int ns_phy_init(void) +{ + return phy_driver_register(&dp83865_driver); +} +fs_initcall(ns_phy_init); From 27d4fe7a08ed83360824eba37b533ca30c5b7303 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 11 Nov 2013 12:35:21 +0100 Subject: [PATCH 2/6] net: Fix error return value for string_to_ethaddr Return a proper error code instead of -1 which would be -EPERM. Signed-off-by: Sascha Hauer --- net/net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/net.c b/net/net.c index 9ef0784da..20051bc12 100644 --- a/net/net.c +++ b/net/net.c @@ -143,12 +143,12 @@ int string_to_ethaddr(const char *str, u8 enetaddr[6]) if (!str || strlen(str) != 17) { memset(enetaddr, 0, 6); - return -1; + return -EINVAL; } if (str[2] != ':' || str[5] != ':' || str[8] != ':' || str[11] != ':' || str[14] != ':') - return -1; + return -EINVAL; for (reg = 0; reg < 6; ++reg) { enetaddr[reg] = simple_strtoul (str, &e, 16); From c827eb8ff343f6d9d5a70a5c82bcf0263f405f64 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 22 Jan 2014 23:50:46 +0100 Subject: [PATCH 3/6] net usb asix: Simplify condition in rx_fixup() Signed-off-by: Marek Vasut Signed-off-by: Philipp Zabel Signed-off-by: Sascha Hauer --- drivers/net/usb/asix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 5975e2a34..8b73bf975 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -408,7 +408,7 @@ static int asix_rx_fixup(struct usbnet *dev, void *buf, int len) len -= 4; while (len > 0) { - if ((short)(header & 0x0000ffff) != ~((short)((header & 0xffff0000) >> 16))) + if ((header & 0xffff) != ((~header >> 16) & 0xffff)) dev_err(&dev->edev.dev, "asix_rx_fixup() Bad Header Length\n"); /* get the packet length */ From f5fa816cff580047d1e52d26c77aa38ccabf17a3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 22 Jan 2014 23:50:47 +0100 Subject: [PATCH 4/6] net usb asix: Use only 11 bits of header for data size The AX88772B uses only 11 bits of the header for the actual size. The other bits are used for something else. This causes dmesg full of messages: asix_rx_fixup() Bad Header Length This patch trims the check to only 11 bits. I believe on older chips, the remaining 5 top bits are unused. Signed-off-by: Marek Vasut Signed-off-by: Philipp Zabel Signed-off-by: Sascha Hauer --- drivers/net/usb/asix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 8b73bf975..003ebbaae 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -408,11 +408,11 @@ static int asix_rx_fixup(struct usbnet *dev, void *buf, int len) len -= 4; while (len > 0) { - if ((header & 0xffff) != ((~header >> 16) & 0xffff)) + if ((header & 0x07ff) != ((~header >> 16) & 0x07ff)) dev_err(&dev->edev.dev, "asix_rx_fixup() Bad Header Length\n"); /* get the packet length */ - size = (unsigned short) (header & 0x0000ffff); + size = (unsigned short) (header & 0x07ff); if (size > 1514) { dev_err(&dev->edev.dev, "asix_rx_fixup() Bad RX Length %d\n", size); From 4eabf125fb6bbd8f138b4293c77c9bdb01887478 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 28 Jan 2014 22:46:46 +0100 Subject: [PATCH 5/6] net usb asix: read MAC from EEPROM on AX88772B Signed-off-by: Philipp Zabel Signed-off-by: Sascha Hauer --- drivers/net/usb/asix.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 003ebbaae..085d728a7 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -132,6 +132,8 @@ #define MARVELL_CTRL_TXDELAY 0x0002 #define MARVELL_CTRL_RXDELAY 0x0080 +#define FLAG_EEPROM_MAC (1UL << 0) /* init device MAC from eeprom */ + /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ struct asix_data { u8 multi_filter[AX_MCAST_FILTER_SIZE]; @@ -364,11 +366,21 @@ static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep) static int asix_get_ethaddr(struct eth_device *edev, unsigned char *adr) { struct usbnet *udev = container_of(edev, struct usbnet, edev); - int ret; + int i, ret; /* Get the MAC address */ - if ((ret = asix_read_cmd(udev, AX_CMD_READ_NODE_ID, - 0, 0, 6, adr)) < 0) { + if (udev->driver_info->data & FLAG_EEPROM_MAC) { + for (i = 0; i < (6 >> 1); i++) { + ret = asix_read_cmd(udev, AX_CMD_READ_EEPROM, 0x04 + i, + 0, 2, adr + i * 2); + if (ret < 0) + break; + } + } else { + ret = asix_read_cmd(udev, AX_CMD_READ_NODE_ID, 0, 0, 6, adr); + } + + if (ret < 0) { debug("Failed to read MAC address: %d\n", ret); return -1; } From 7a150c5fb1007fef1ffb7b57aa5c3869b3275803 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 22 Jan 2014 23:52:36 +0100 Subject: [PATCH 6/6] net usb asix: add AX88772B USB ID Signed-off-by: Philipp Zabel Signed-off-by: Sascha Hauer --- drivers/net/usb/asix.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 085d728a7..b58db5d7b 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -692,6 +692,16 @@ static struct driver_info ax88772_info = { .tx_fixup = asix_tx_fixup, }; +static struct driver_info ax88772b_info = { + .description = "ASIX AX88772B USB 2.0 Ethernet", + .bind = ax88772_bind, + .unbind = asix_unbind, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = asix_rx_fixup, + .tx_fixup = asix_tx_fixup, + .data = FLAG_EEPROM_MAC, +}; + static const struct usb_device_id products [] = { { // Linksys USB200M @@ -773,6 +783,10 @@ static const struct usb_device_id products [] = { // Cables-to-Go USB Ethernet Adapter USB_DEVICE(0x0b95, 0x772a), .driver_info = &ax88772_info, +}, { + // LevelOne USB Fast Ethernet Adapter + USB_DEVICE(0x0b95, 0x772b), + .driver_info = &ax88772b_info, }, { }, // END };