From d88ecb373bd1877acc43e13311a8e0e6daffc3d2 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Sat, 17 Oct 2015 06:04:36 +0200 Subject: net: phy: smsc: disable energy detect mode On some boards the energy enable detect mode leads in trouble with some switches, so make the enabling of this mode configurable through DT. Signed-off-by: Heiko Schocher Signed-off-by: David S. Miller --- drivers/net/phy/smsc.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers/net/phy') diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 70b08958763a..dc2da8770918 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -43,16 +43,25 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev) static int smsc_phy_config_init(struct phy_device *phydev) { + int __maybe_unused len; + struct device *dev __maybe_unused = &phydev->dev; + struct device_node *of_node __maybe_unused = dev->of_node; int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); + int enable_energy = 1; if (rc < 0) return rc; - /* Enable energy detect mode for this SMSC Transceivers */ - rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, - rc | MII_LAN83C185_EDPWRDOWN); - if (rc < 0) - return rc; + if (of_find_property(of_node, "smsc,disable-energy-detect", &len)) + enable_energy = 0; + + if (enable_energy) { + /* Enable energy detect mode for this SMSC Transceivers */ + rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, + rc | MII_LAN83C185_EDPWRDOWN); + if (rc < 0) + return rc; + } return smsc_phy_ack_interrupt(phydev); } -- cgit v1.2.3 From 34e45ad9378c31ef2b59e8bd63d62f0ca8e719a3 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 20 Oct 2015 16:28:57 -0500 Subject: net: phy: dp83848: Add TI DP83848 Ethernet PHY Add support for the TI DP83848 Ethernet PHY device. The DP83848 is a highly reliable, feature rich, IEEE 802.3 compliant single port 10/100 Mb/s Ethernet Physical Layer Transceiver supporting the MII and RMII interfaces. Signed-off-by: Andrew F. Davis Signed-off-by: Dan Murphy Reviewed-by: Florian Fainelli Acked-by: Dan Murphy Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 5 +++ drivers/net/phy/Makefile | 1 + drivers/net/phy/dp83848.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 drivers/net/phy/dp83848.c (limited to 'drivers/net/phy') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 11e3975485c1..436972b2a746 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -122,6 +122,11 @@ config MICREL_PHY ---help--- Supports the KSZ9021, VSC8201, KS8001 PHYs. +config DP83848_PHY + tristate "Driver for Texas Instruments DP83848 PHY" + ---help--- + Supports the DP83848 PHY. + config DP83867_PHY tristate "Drivers for Texas Instruments DP83867 Gigabit PHY" ---help--- diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 87f079c4b2c7..b74822463930 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_DP83640_PHY) += dp83640.o +obj-$(CONFIG_DP83848_PHY) += dp83848.o obj-$(CONFIG_DP83867_PHY) += dp83867.o obj-$(CONFIG_STE10XP) += ste10Xp.o obj-$(CONFIG_MICREL_PHY) += micrel.o diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c new file mode 100644 index 000000000000..5ce9bef54468 --- /dev/null +++ b/drivers/net/phy/dp83848.c @@ -0,0 +1,99 @@ +/* + * Driver for the Texas Instruments DP83848 PHY + * + * Copyright (C) 2015 Texas Instruments Inc. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#define DP83848_PHY_ID 0x20005c90 + +/* Registers */ +#define DP83848_MICR 0x11 +#define DP83848_MISR 0x12 + +/* MICR Register Fields */ +#define DP83848_MICR_INT_OE BIT(0) /* Interrupt Output Enable */ +#define DP83848_MICR_INTEN BIT(1) /* Interrupt Enable */ + +/* MISR Register Fields */ +#define DP83848_MISR_RHF_INT_EN BIT(0) /* Receive Error Counter */ +#define DP83848_MISR_FHF_INT_EN BIT(1) /* False Carrier Counter */ +#define DP83848_MISR_ANC_INT_EN BIT(2) /* Auto-negotiation complete */ +#define DP83848_MISR_DUP_INT_EN BIT(3) /* Duplex Status */ +#define DP83848_MISR_SPD_INT_EN BIT(4) /* Speed status */ +#define DP83848_MISR_LINK_INT_EN BIT(5) /* Link status */ +#define DP83848_MISR_ED_INT_EN BIT(6) /* Energy detect */ +#define DP83848_MISR_LQM_INT_EN BIT(7) /* Link Quality Monitor */ + +static int dp83848_ack_interrupt(struct phy_device *phydev) +{ + int err = phy_read(phydev, DP83848_MISR); + + return err < 0 ? err : 0; +} + +static int dp83848_config_intr(struct phy_device *phydev) +{ + int err; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { + err = phy_write(phydev, DP83848_MICR, + DP83848_MICR_INT_OE | + DP83848_MICR_INTEN); + if (err < 0) + return err; + + return phy_write(phydev, DP83848_MISR, + DP83848_MISR_ANC_INT_EN | + DP83848_MISR_DUP_INT_EN | + DP83848_MISR_SPD_INT_EN | + DP83848_MISR_LINK_INT_EN); + } + + return phy_write(phydev, DP83848_MICR, 0x0); +} + +static struct mdio_device_id __maybe_unused dp83848_tbl[] = { + { DP83848_PHY_ID, 0xfffffff0 }, + { } +}; +MODULE_DEVICE_TABLE(mdio, dp83848_tbl); + +static struct phy_driver dp83848_driver[] = { + { + .phy_id = DP83848_PHY_ID, + .phy_id_mask = 0xfffffff0, + .name = "TI DP83848", + .features = PHY_BASIC_FEATURES, + .flags = PHY_HAS_INTERRUPT, + + .soft_reset = genphy_soft_reset, + .config_init = genphy_config_init, + .suspend = genphy_suspend, + .resume = genphy_resume, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + + /* IRQ related */ + .ack_interrupt = dp83848_ack_interrupt, + .config_intr = dp83848_config_intr, + + .driver = { .owner = THIS_MODULE, }, + }, +}; +module_phy_driver(dp83848_driver); + +MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver"); +MODULE_AUTHOR("Andrew F. Davis Date: Wed, 21 Oct 2015 14:17:04 -0500 Subject: net/phy: micrel: Add workaround for bad autoneg Very rarely, the KSZ9031 will appear to complete autonegotiation, but will drop all traffic afterwards. When this happens, the idle error count will read 0xFF after autonegotiation completes. Reset the PHY when in that state. Signed-off-by: Nathan Sullivan Signed-off-by: David S. Miller --- drivers/net/phy/micrel.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers/net/phy') diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 499185eaf413..cf6312fafea5 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -514,6 +514,27 @@ static int ksz8873mll_read_status(struct phy_device *phydev) return 0; } +static int ksz9031_read_status(struct phy_device *phydev) +{ + int err; + int regval; + + err = genphy_read_status(phydev); + if (err) + return err; + + /* Make sure the PHY is not broken. Read idle error count, + * and reset the PHY if it is maxed out. + */ + regval = phy_read(phydev, MII_STAT1000); + if ((regval & 0xFF) == 0xFF) { + phy_init_hw(phydev); + phydev->link = 0; + } + + return 0; +} + static int ksz8873mll_config_aneg(struct phy_device *phydev) { return 0; @@ -772,7 +793,7 @@ static struct phy_driver ksphy_driver[] = { .driver_data = &ksz9021_type, .config_init = ksz9031_config_init, .config_aneg = genphy_config_aneg, - .read_status = genphy_read_status, + .read_status = ksz9031_read_status, .ack_interrupt = kszphy_ack_interrupt, .config_intr = kszphy_config_intr, .suspend = genphy_suspend, -- cgit v1.2.3