diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2023-06-22 09:59:24 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2023-06-22 09:59:24 +0200 |
commit | 2c4523beb1aaa54d5ff2af2ad89b0c900d31cf39 (patch) | |
tree | 26a5845e79fe9e807ae63e7bb1cf8d8563588d54 /drivers/net | |
parent | 47f6d253d678f97108b50d0c99a599f082de6a87 (diff) | |
parent | b1185e4a6a935b14dfe24654a4cb058dce5b93aa (diff) | |
download | barebox-2c4523beb1aaa54d5ff2af2ad89b0c900d31cf39.tar.gz barebox-2c4523beb1aaa54d5ff2af2ad89b0c900d31cf39.tar.xz |
Merge branch 'for-next/misc'
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/phy/Kconfig | 5 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/phy/dp83867.c | 37 | ||||
-rw-r--r-- | drivers/net/phy/motorcomm.c | 129 | ||||
-rw-r--r-- | drivers/net/phy/mv88e6xxx/chip.c | 8 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 23 | ||||
-rw-r--r-- | drivers/net/r8169_main.c | 1 |
7 files changed, 197 insertions, 7 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index cd20e1de27..e95e2a3228 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -50,6 +50,11 @@ config MICREL_PHY help Supports the KSZ9021, VSC8201, KS8001 PHYs. +config MOTORCOMM_PHY + bool "Driver for Motorcomm PHYs" + help + Currently supports the YT8511 PHY. + config NATIONAL_PHY bool "Driver for National Semiconductor PHYs" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 83f46f11d3..26e4ad884d 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_DAVICOM_PHY) += davicom.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_MARVELL_PHY) += marvell.o obj-$(CONFIG_MICREL_PHY) += micrel.o +obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_REALTEK_PHY) += realtek.o obj-$(CONFIG_SMSC_PHY) += smsc.o diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 375dcd0753..d8109172df 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -96,6 +96,9 @@ #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f +#define DP83867_IO_MUX_CFG_CLK_O_DISABLE BIT(6) +#define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK (0x1f << 8) +#define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8 /* CFG4 bits */ #define DP83867_CFG4_PORT_MIRROR_EN BIT(0) @@ -113,6 +116,8 @@ struct dp83867_private { int io_impedance; int port_mirroring; bool rxctrl_strap_quirk; + bool set_clk_output; + u32 clk_output_sel; }; static int dp83867_read_status(struct phy_device *phydev) @@ -174,6 +179,22 @@ static int dp83867_of_init(struct phy_device *phydev) dp83867->io_impedance = -EINVAL; /* Optional configuration */ + ret = of_property_read_u32(of_node, "ti,clk-output-sel", + &dp83867->clk_output_sel); + /* If not set, keep default */ + if (!ret) { + dp83867->set_clk_output = true; + /* Valid values are 0 to DP83867_CLK_O_SEL_REF_CLK or + * DP83867_CLK_O_SEL_OFF. + */ + if (dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK && + dp83867->clk_output_sel != DP83867_CLK_O_SEL_OFF) { + dev_err(&phydev->dev, "ti,clk-output-sel value %u out of range\n", + dp83867->clk_output_sel); + return -EINVAL; + } + } + if (of_property_read_bool(of_node, "ti,max-output-impedance")) dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX; else if (of_property_read_bool(of_node, "ti,min-output-impedance")) @@ -308,6 +329,22 @@ static int dp83867_config_init(struct phy_device *phydev) if (dp83867->port_mirroring != DP83867_PORT_MIRROING_KEEP) dp83867_config_port_mirroring(phydev); + /* Clock output selection if muxing property is set */ + if (dp83867->set_clk_output) { + u16 mask = DP83867_IO_MUX_CFG_CLK_O_DISABLE; + + if (dp83867->clk_output_sel == DP83867_CLK_O_SEL_OFF) { + val = DP83867_IO_MUX_CFG_CLK_O_DISABLE; + } else { + mask |= DP83867_IO_MUX_CFG_CLK_O_SEL_MASK; + val = dp83867->clk_output_sel << + DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT; + } + + phy_modify_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, mask, val); + } + return 0; } diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c new file mode 100644 index 0000000000..d4cd05a1f6 --- /dev/null +++ b/drivers/net/phy/motorcomm.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * drivers/net/phy/motorcomm.c + * + * Driver for Motorcomm PHYs + * + * Author: Peter Geis <pgwipeout@gmail.com> + */ + +#include <common.h> +#include <init.h> +#include <linux/phy.h> +#include <linux/mdio.h> + +#define PHY_ID_YT8511 0x0000010a + +#define YT8511_PAGE_SELECT 0x1e +#define YT8511_PAGE 0x1f +#define YT8511_EXT_CLK_GATE 0x0c +#define YT8511_EXT_DELAY_DRIVE 0x0d +#define YT8511_EXT_SLEEP_CTRL 0x27 + +/* 2b00 25m from pll + * 2b01 25m from xtl *default* + * 2b10 62.m from pll + * 2b11 125m from pll + */ +#define YT8511_CLK_125M (BIT(2) | BIT(1)) +#define YT8511_PLLON_SLP BIT(14) + +/* RX Delay enabled = 1.8ns 1000T, 8ns 10/100T */ +#define YT8511_DELAY_RX BIT(0) + +/* TX Gig-E Delay is bits 7:4, default 0x5 + * TX Fast-E Delay is bits 15:12, default 0xf + * Delay = 150ps * N - 250ps + * On = 2000ps, off = 50ps + */ +#define YT8511_DELAY_GE_TX_EN (0xf << 4) +#define YT8511_DELAY_GE_TX_DIS (0x2 << 4) +#define YT8511_DELAY_FE_TX_EN (0xf << 12) +#define YT8511_DELAY_FE_TX_DIS (0x2 << 12) + +static int yt8511_read_page(struct phy_device *phydev) +{ + return phy_read(phydev, YT8511_PAGE_SELECT); +}; + +static int yt8511_write_page(struct phy_device *phydev, int page) +{ + return phy_write(phydev, YT8511_PAGE_SELECT, page); +}; + +static int yt8511_config_init(struct phy_device *phydev) +{ + int oldpage, ret = 0; + unsigned int ge, fe; + + oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE); + if (oldpage < 0) + goto err_restore_page; + + /* set rgmii delay mode */ + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII: + ge = YT8511_DELAY_GE_TX_DIS; + fe = YT8511_DELAY_FE_TX_DIS; + break; + case PHY_INTERFACE_MODE_RGMII_RXID: + ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_DIS; + fe = YT8511_DELAY_FE_TX_DIS; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + ge = YT8511_DELAY_GE_TX_EN; + fe = YT8511_DELAY_FE_TX_EN; + break; + case PHY_INTERFACE_MODE_RGMII_ID: + ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN; + fe = YT8511_DELAY_FE_TX_EN; + break; + default: /* do not support other modes */ + ret = -EOPNOTSUPP; + goto err_restore_page; + } + + ret = phy_modify(phydev, YT8511_PAGE, (YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN), ge); + if (ret < 0) + goto err_restore_page; + + /* set clock mode to 125mhz */ + ret = phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M); + if (ret < 0) + goto err_restore_page; + + /* fast ethernet delay is in a separate page */ + ret = phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_DELAY_DRIVE); + if (ret < 0) + goto err_restore_page; + + ret = phy_modify(phydev, YT8511_PAGE, YT8511_DELAY_FE_TX_EN, fe); + if (ret < 0) + goto err_restore_page; + + /* leave pll enabled in sleep */ + ret = phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_SLEEP_CTRL); + if (ret < 0) + goto err_restore_page; + + ret = phy_modify(phydev, YT8511_PAGE, 0, YT8511_PLLON_SLP); + if (ret < 0) + goto err_restore_page; + +err_restore_page: + return phy_restore_page(phydev, oldpage, ret); +} + +static struct phy_driver motorcomm_phy_drvs[] = { + { + .phy_id = PHY_ID_YT8511, + .phy_id_mask = 0xffffffff, + .drv.name = "YT8511 Gigabit Ethernet", + .config_init = yt8511_config_init, + .features = PHY_GBIT_FEATURES, + .read_page = yt8511_read_page, + .write_page = yt8511_write_page, + }, +}; + +device_phy_drivers(motorcomm_phy_drvs); diff --git a/drivers/net/phy/mv88e6xxx/chip.c b/drivers/net/phy/mv88e6xxx/chip.c index 0c37ba9594..b9b02c52f2 100644 --- a/drivers/net/phy/mv88e6xxx/chip.c +++ b/drivers/net/phy/mv88e6xxx/chip.c @@ -832,11 +832,6 @@ static int mv88e6xxx_eeprom_write(void *ctx, unsigned offset, const void *val, s return chip->info->ops->set_eeprom(chip, &eeprom, (void *)val); } -static const struct nvmem_bus mv88e6xxx_eeprom_nvmem_bus = { - .write = mv88e6xxx_eeprom_write, - .read = mv88e6xxx_eeprom_read, -}; - static int mv88e6xxx_probe(struct device *dev) { struct device_node *np = dev->of_node; @@ -911,7 +906,8 @@ static int mv88e6xxx_probe(struct device *dev) .stride = 1, .size = eeprom_len, .read_only = false, - .bus = &mv88e6xxx_eeprom_nvmem_bus, + .reg_write = mv88e6xxx_eeprom_write, + .reg_read = mv88e6xxx_eeprom_read, }; if (IS_ERR(nvmem_register(&config))) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index dbc30b66b8..74381949b4 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -882,6 +882,29 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, int devad, phy_write(phydev, MII_MMD_DATA, data); } +/** + * phy_modify_mmd_indirect - Convenience function for modifying a MMD register + * @phydev: phy device + * @prtad: MMD Address + * @devad: MMD DEVAD + * @mask: bit mask of bits to clear + * @set: new value of bits set in @mask + * + */ +int phy_modify_mmd_indirect(struct phy_device *phydev, int prtad, int devad, + u16 mask, u16 set) +{ + int ret; + + ret = phy_read_mmd_indirect(phydev, prtad, devad); + if (ret < 0) + return ret; + + phy_write_mmd_indirect(phydev, prtad, devad, (ret & ~mask) | set); + + return 0; +} + int genphy_config_init(struct phy_device *phydev) { int val; diff --git a/drivers/net/r8169_main.c b/drivers/net/r8169_main.c index 9c28c92ded..fd53ec1bc3 100644 --- a/drivers/net/r8169_main.c +++ b/drivers/net/r8169_main.c @@ -17,7 +17,6 @@ #include <linux/pci.h> #include <linux/sizes.h> #include <asm/unaligned.h> -#include <asm/system.h> #include "r8169.h" #include "r8169_firmware.h" |