Message ID | 20240415104352.4685-6-fujita.tomonori@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | add ethernet driver for Tehuti Networks TN40xx chips | expand |
On Mon, Apr 15, 2024 at 07:43:52PM +0900, FUJITA Tomonori wrote: > This patch adds supports for multiple PHY hardware with PHYLIB. The > adapters with TN40xx chips use multiple PHY hardware; AMCC QT2025, TI > TLK10232, Aqrate AQR105, and Marvell 88X3120, 88X3310, and MV88E2010. > > For now, the PCI ID table of this driver enables adapters using only > QT2025 PHY. I've tested this driver and the QT2025 PHY driver with > Edimax EN-9320 10G adapter. Please split this up. Add the MDIO bus master in one patch. Then add support for phylib in a second patch. They are logically different things. Are there variants of this device using SFP? It might be you actually want to use phylink, not phylib. That is a bit messy for a PCI device, look at drivers/net/ethernet/wangxun. > diff --git a/drivers/net/ethernet/tehuti/Kconfig b/drivers/net/ethernet/tehuti/Kconfig > index 4198fd59e42e..71f22471f9a0 100644 > --- a/drivers/net/ethernet/tehuti/Kconfig > +++ b/drivers/net/ethernet/tehuti/Kconfig > @@ -27,6 +27,7 @@ config TEHUTI_TN40 > tristate "Tehuti Networks TN40xx 10G Ethernet adapters" > depends on PCI > select FW_LOADER > + select AMCC_QT2025_PHY That is pretty unusual, especially when you say there are a few different choices. > +static u32 bdx_mdio_get(struct bdx_priv *priv) > +{ > + void __iomem *regs = priv->regs; > + > +#define BDX_MAX_MDIO_BUSY_LOOPS 1024 > + int tries = 0; > + > + while (++tries < BDX_MAX_MDIO_BUSY_LOOPS) { > + u32 mdio_cmd_stat = readl(regs + REG_MDIO_CMD_STAT); > + > + if (GET_MDIO_BUSY(mdio_cmd_stat) == 0) > + return mdio_cmd_stat; > + } > + dev_err(&priv->pdev->dev, "MDIO busy!\n"); include/linux/iopoll.h > + return 0xFFFFFFFF; It is always better to use standard error codes. In this case, -ETIMEDOUT. > +static u16 bdx_mdio_read(struct bdx_priv *priv, int device, int port, u16 addr) > +{ > + void __iomem *regs = priv->regs; > + u32 tmp_reg, i; > + /* wait until MDIO is not busy */ > + if (bdx_mdio_get(priv) == 0xFFFFFFFF) > + return -1; > + > + i = ((device & 0x1F) | ((port & 0x1F) << 5)); > + writel(i, regs + REG_MDIO_CMD); > + writel((u32)addr, regs + REG_MDIO_ADDR); > + tmp_reg = bdx_mdio_get(priv); > + if (tmp_reg == 0xFFFFFFFF) > + return -1; This function has a return type of u16. So returning -1 makes no sense. > +static int mdio_read_reg(struct mii_bus *mii_bus, int addr, int devnum, int regnum) > +{ > + return bdx_mdio_read(mii_bus->priv, devnum, addr, regnum); I would probably change bdx_mdio_read() so that it takes the parameters in the same order as mdio_read_reg(). There is also a reasonably common convention that the functions performing C45 bus protocol operations have c45 in their name. It appears this hardware does not support C22 at all. That makes it unusual, and little hits like this are useful. Andrew
Hi, On Mon, 15 Apr 2024 16:44:31 +0200 Andrew Lunn <andrew@lunn.ch> wrote: > On Mon, Apr 15, 2024 at 07:43:52PM +0900, FUJITA Tomonori wrote: >> This patch adds supports for multiple PHY hardware with PHYLIB. The >> adapters with TN40xx chips use multiple PHY hardware; AMCC QT2025, TI >> TLK10232, Aqrate AQR105, and Marvell 88X3120, 88X3310, and MV88E2010. >> >> For now, the PCI ID table of this driver enables adapters using only >> QT2025 PHY. I've tested this driver and the QT2025 PHY driver with >> Edimax EN-9320 10G adapter. > > Please split this up. Add the MDIO bus master in one patch. Then add > support for phylib in a second patch. They are logically different > things. Understood, I'll split this in v2. > Are there variants of this device using SFP? It might be you actually > want to use phylink, not phylib. That is a bit messy for a PCI device, > look at drivers/net/ethernet/wangxun. phylink is necessary if PHY is hot-pluggable, right? if so, the driver doesn't need it. The PHYs that adapters with TN40XX use are AMCC QT2025 PHY (SFP+) - Tehuti TN9310 - DLink DXE-810S - Asus XG-C100F - Edimax EN-9320 Marvell MV88x3120 (10GBase-T) - Tehuti TN9210 Marvell MV88X3310 (10GBase-T) - Tehuti TN9710 - Edimax EN-9320TX-E - Buffalo LGY-PCIE-MG - IOI GE10 - LR-Link LREC6860BT - QNAP PCIe Expansion Card Marvell MV88E2010 (5GBase-T) - Tehuti TN9710Q TI TLK10232 (SFP+) - Tehuti TN9610 - LR-Link LREC6860AF Aquantia AQR105 (10GBase-T) - Tehuti TN9510 - DLink DXE-810T - Edimax EN-9320TX-E >> diff --git a/drivers/net/ethernet/tehuti/Kconfig b/drivers/net/ethernet/tehuti/Kconfig >> index 4198fd59e42e..71f22471f9a0 100644 >> --- a/drivers/net/ethernet/tehuti/Kconfig >> +++ b/drivers/net/ethernet/tehuti/Kconfig >> @@ -27,6 +27,7 @@ config TEHUTI_TN40 >> tristate "Tehuti Networks TN40xx 10G Ethernet adapters" >> depends on PCI >> select FW_LOADER >> + select AMCC_QT2025_PHY > > That is pretty unusual, especially when you say there are a few > different choices. I should not put any 'select *_PHY' here? >> +static u32 bdx_mdio_get(struct bdx_priv *priv) >> +{ >> + void __iomem *regs = priv->regs; >> + >> +#define BDX_MAX_MDIO_BUSY_LOOPS 1024 >> + int tries = 0; >> + >> + while (++tries < BDX_MAX_MDIO_BUSY_LOOPS) { >> + u32 mdio_cmd_stat = readl(regs + REG_MDIO_CMD_STAT); >> + >> + if (GET_MDIO_BUSY(mdio_cmd_stat) == 0) >> + return mdio_cmd_stat; >> + } >> + dev_err(&priv->pdev->dev, "MDIO busy!\n"); > > include/linux/iopoll.h > >> + return 0xFFFFFFFF; > > It is always better to use standard error codes. In this case, > -ETIMEDOUT. I'll >> +static u16 bdx_mdio_read(struct bdx_priv *priv, int device, int port, u16 addr) >> +{ >> + void __iomem *regs = priv->regs; >> + u32 tmp_reg, i; >> + /* wait until MDIO is not busy */ >> + if (bdx_mdio_get(priv) == 0xFFFFFFFF) >> + return -1; >> + >> + i = ((device & 0x1F) | ((port & 0x1F) << 5)); >> + writel(i, regs + REG_MDIO_CMD); >> + writel((u32)addr, regs + REG_MDIO_ADDR); >> + tmp_reg = bdx_mdio_get(priv); >> + if (tmp_reg == 0xFFFFFFFF) >> + return -1; > > This function has a return type of u16. So returning -1 makes no sense. Yeah, I thought the same but left it alone. I'll change in v2. >> +static int mdio_read_reg(struct mii_bus *mii_bus, int addr, int devnum, int regnum) >> +{ >> + return bdx_mdio_read(mii_bus->priv, devnum, addr, regnum); > > I would probably change bdx_mdio_read() so that it takes the > parameters in the same order as mdio_read_reg(). Sure, I'll. > There is also a reasonably common convention that the functions > performing C45 bus protocol operations have c45 in their name. It > appears this hardware does not support C22 at all. That makes it > unusual, and little hits like this are useful. I'm not sure the adapters supports C22 or not (probably do, I guess). But the original driver uses C45 bus protocol operations.
> > Are there variants of this device using SFP? It might be you actually > > want to use phylink, not phylib. That is a bit messy for a PCI device, > > look at drivers/net/ethernet/wangxun. > > phylink is necessary if PHY is hot-pluggable, right? if so, the driver > doesn't need it. The PHYs that adapters with TN40XX use are There is more to it than that. phylib has problems when the bandwidth is > 1G and the MAC/PHY link becomes more problematic. Often the PHY will change this link depending on what the media side is doing. If you have a 1G SFP inserted, the QT2025 will change the MAC/PHY link to 1000BaseX. If it has a 10G SFP it will use XAUI. phylink knows how to decode the SFP EEPROM to determine what sort of module it is, and how the PHY should be configured. To fully support this hardware you are going to need to use phylink. > >> diff --git a/drivers/net/ethernet/tehuti/Kconfig b/drivers/net/ethernet/tehuti/Kconfig > >> index 4198fd59e42e..71f22471f9a0 100644 > >> --- a/drivers/net/ethernet/tehuti/Kconfig > >> +++ b/drivers/net/ethernet/tehuti/Kconfig > >> @@ -27,6 +27,7 @@ config TEHUTI_TN40 > >> tristate "Tehuti Networks TN40xx 10G Ethernet adapters" > >> depends on PCI > >> select FW_LOADER > >> + select AMCC_QT2025_PHY > > > > That is pretty unusual, especially when you say there are a few > > different choices. > > I should not put any 'select *_PHY' here? Correct. Most distributions just package everything. We are going to get into an odd corner case that since Rust is still experimental, i doubt distributions are building Rust modules. So they will end up with a MAC driver but no PHY driver, at least not for the QT2025. The Marvell and Aquantia PHY should just work. Anybody who does want to use the QT2025 will either need to build there own kernel, or black list the in kernel MAC driver and use the out of tree driver. But eventually, Rust will start to be packaged, and then it should work out O.K. Andrew
Hi, On Tue, 16 Apr 2024 14:57:58 +0200 Andrew Lunn <andrew@lunn.ch> wrote: >> > Are there variants of this device using SFP? It might be you actually >> > want to use phylink, not phylib. That is a bit messy for a PCI device, >> > look at drivers/net/ethernet/wangxun. >> >> phylink is necessary if PHY is hot-pluggable, right? if so, the driver >> doesn't need it. The PHYs that adapters with TN40XX use are > > There is more to it than that. phylib has problems when the bandwidth > is > 1G and the MAC/PHY link becomes more problematic. Often the PHY > will change this link depending on what the media side is doing. If > you have a 1G SFP inserted, the QT2025 will change the MAC/PHY link to > 1000BaseX. If it has a 10G SFP it will use XAUI. phylink knows how to > decode the SFP EEPROM to determine what sort of module it is, and how > the PHY should be configured. > > To fully support this hardware you are going to need to use phylink. I updated the code to use phylink and posted v2. At least seems that it works with 10G SFP+ as before. I suppose that more changes are necessary for full support. For example, with 1G SFP inserted, the MAC driver has to configure the hardware for 1G. I'll investigate once I get 1G SFP. Note that the original driver supports only 10G SFP+. >> >> diff --git a/drivers/net/ethernet/tehuti/Kconfig b/drivers/net/ethernet/tehuti/Kconfig >> >> index 4198fd59e42e..71f22471f9a0 100644 >> >> --- a/drivers/net/ethernet/tehuti/Kconfig >> >> +++ b/drivers/net/ethernet/tehuti/Kconfig >> >> @@ -27,6 +27,7 @@ config TEHUTI_TN40 >> >> tristate "Tehuti Networks TN40xx 10G Ethernet adapters" >> >> depends on PCI >> >> select FW_LOADER >> >> + select AMCC_QT2025_PHY >> > >> > That is pretty unusual, especially when you say there are a few >> > different choices. >> >> I should not put any 'select *_PHY' here? > > Correct. Most distributions just package everything. > > We are going to get into an odd corner case that since Rust is still > experimental, i doubt distributions are building Rust modules. So they > will end up with a MAC driver but no PHY driver, at least not for the > QT2025. The Marvell and Aquantia PHY should just work. > > Anybody who does want to use the QT2025 will either need to > build there own kernel, or black list the in kernel MAC driver and use > the out of tree driver. But eventually, Rust will start to be > packaged, and then it should work out O.K. Sure, I dropped the above in v2.
> I updated the code to use phylink and posted v2. At least seems that > it works with 10G SFP+ as before. > > I suppose that more changes are necessary for full support. For > example, with 1G SFP inserted, the MAC driver has to configure the > hardware for 1G. I'll investigate once I get 1G SFP. > > Note that the original driver supports only 10G SFP+. This is where the Rust PHY driver gets more interesting. A PHY which is being used as a media converter needs to support a few additional things. The marvel10g driver is a good example to follow for some things. Look at mv3310_sfp_ops. But there is more to it than that. phylink assumes it has access to the i2c bus the module is on. The datasheet for the QT2025, shows a couple of diagrams how an SFP is connected to it. The QT2025 has an I2C bus which should be connected to the SFP cage. So you need to export this I2C bus master in the PHY driver. So a Rust I2C bus driver. Has anybody done that yet? However, it is not clear from my reading of the datasheet if you get true access to the I2C bus. It says: XFP/SFP+ Module Access through MDIO The MDIO interface can be used to access an XFP or SFP+ module. The XFP/SFP+ module 2-wire interface must be connected to the UC_SCL and UC_SDA clock and data lines. The XFP module address is 1010000, while the SFP+ module uses memory at addresses 1010000 and 1010001. The entire module address space will be automatically read upon powerup, reset or module hotplug by detection of the MOD_ABS signal. A 400ms delay is observed before upload to allow the module to initialize. The memory at module address 1010000 is mapped to MDIO register range 3.D000 - 3.D0FFh. Read/write access to the module memory is controlled by MDIO register 3.D100h. This applies to both module types. The memory at module address 1010001 is mapped to MDIO register range 1.8007 - 1.8106h. No read/write access to the module memory is provided. DOM Memory Access The SFP+ DOM memory (A2) is mapped to MDIO registers 1.8007-1.8106h (the NVR address space) or alternatively to 1.A000-1.A0FF (this is firmware load dependent; it may be configurable). If mapped to 1.A000-1.A0FF, DOM-related alarms in the SFP+ module will feed into the LASI alarm tree (see “Link Alarm Status Interrupt Pin (LASI)” on page 74 for details). Later firmware versions implement a DOM periodic polling feature, where the DOM memory is read at every 1s. Optical alarms will then automatically alert the host system through the LASI interrupt pins. Only a subset of registers containing dynamically changing values are polled on each update. Consult AMCC for details on this feature. So i guess you are going to need to fake the I2C bus, mapping I2C transfer requests into MDIO reads of the mapped memory. Additionally, phylink expects a few GPIO for Los of Signal, TX Enable, TX Fault, etc. The PHY has these, so the PHY driver needs to export a GPIO driver. And then you need some glue, to bring all the parts together. The wangxun Ethernet driver has mostly solved this, so you can take inspiration from there. You picked an interesting device to add Rust support for. Andrew
diff --git a/drivers/net/ethernet/tehuti/Kconfig b/drivers/net/ethernet/tehuti/Kconfig index 4198fd59e42e..71f22471f9a0 100644 --- a/drivers/net/ethernet/tehuti/Kconfig +++ b/drivers/net/ethernet/tehuti/Kconfig @@ -27,6 +27,7 @@ config TEHUTI_TN40 tristate "Tehuti Networks TN40xx 10G Ethernet adapters" depends on PCI select FW_LOADER + select AMCC_QT2025_PHY help This driver supports 10G Ethernet adapters using Tehuti Networks TN40xx chips. Currently, adapters with Applied Micro Circuits diff --git a/drivers/net/ethernet/tehuti/Makefile b/drivers/net/ethernet/tehuti/Makefile index 1c468d99e476..7a0fe586a243 100644 --- a/drivers/net/ethernet/tehuti/Makefile +++ b/drivers/net/ethernet/tehuti/Makefile @@ -5,5 +5,5 @@ obj-$(CONFIG_TEHUTI) += tehuti.o -tn40xx-y := tn40.o +tn40xx-y := tn40.o tn40_mdio.o obj-$(CONFIG_TEHUTI_TN40) += tn40xx.o diff --git a/drivers/net/ethernet/tehuti/tn40.c b/drivers/net/ethernet/tehuti/tn40.c index c8ed9b743753..2c50295f4e68 100644 --- a/drivers/net/ethernet/tehuti/tn40.c +++ b/drivers/net/ethernet/tehuti/tn40.c @@ -1285,18 +1285,26 @@ static void bdx_link_changed(struct bdx_priv *priv) if (priv->link_loop_cnt++ > LINK_LOOP_MAX) { /* MAC reset */ bdx_set_link_speed(priv, 0); + bdx_set_link_speed(priv, priv->phydev->speed); priv->link_loop_cnt = 0; } write_reg(priv, 0x5150, 1000000); return; } + + if (!netif_carrier_ok(priv->ndev)) { + netif_wake_queue(priv->ndev); + phy_print_status(priv->phydev); + } priv->link = link; + netif_carrier_on(priv->ndev); } static inline void bdx_isr_extra(struct bdx_priv *priv, u32 isr) { if (isr & (IR_LNKCHG0 | IR_LNKCHG1 | IR_TMR0)) { netdev_dbg(priv->ndev, "isr = 0x%x\n", isr); + phy_mac_interrupt(priv->phydev); bdx_link_changed(priv); } } @@ -1580,23 +1588,42 @@ static int bdx_close(struct net_device *ndev) bdx_disable_interrupts(priv); free_irq(priv->pdev->irq, priv->ndev); + phy_stop(priv->phydev); + phy_disconnect(priv->phydev); bdx_sw_reset(priv); destroy_rx_ring(priv); destroy_tx_ring(priv); return 0; } +static void phy_handler(struct net_device *_dev) +{ +} + static int bdx_open(struct net_device *dev) { struct bdx_priv *priv = netdev_priv(dev); int ret; bdx_sw_reset(priv); + + ret = phy_connect_direct(priv->ndev, priv->phydev, phy_handler, PHY_INTERFACE_MODE_XAUI); + if (ret) { + netdev_err(dev, "failed to connect to phy %d\n", ret); + return ret; + } + phy_attached_info(priv->phydev); + phy_start(priv->phydev); + ret = bdx_start(priv); if (ret) { netdev_err(dev, "failed to start %d\n", ret); + phy_stop(priv->phydev); + phy_disconnect(priv->phydev); return ret; } + napi_enable(&priv->napi); + netif_start_queue(priv->ndev); return 0; } @@ -1872,6 +1899,11 @@ static int bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->stats_flag = ((read_reg(priv, FPGA_VER) & 0xFFF) != 308); + ret = bdx_mdiobus_init(priv); + if (ret) { + dev_err(&pdev->dev, "failed to find PHY.\n"); + goto err_free_irq; + } priv->isr_mask = IR_RX_FREE_0 | IR_LNKCHG0 | IR_PSE | IR_TMR0 | IR_RX_DESC_0 | IR_TX_FREE_0 | IR_TMR1; diff --git a/drivers/net/ethernet/tehuti/tn40.h b/drivers/net/ethernet/tehuti/tn40.h index fb43ebb5911f..06ab9a2cb42d 100644 --- a/drivers/net/ethernet/tehuti/tn40.h +++ b/drivers/net/ethernet/tehuti/tn40.h @@ -197,6 +197,9 @@ struct bdx_priv { char *b0_va; /* Virtual address of buffer */ struct bdx_rx_page_table rx_page_table; + + struct mii_bus *mdio; + struct phy_device *phydev; }; /* RX FREE descriptor - 64bit */ @@ -283,4 +286,6 @@ static inline void write_reg(struct bdx_priv *priv, u32 reg, u32 val) writel(val, priv->regs + reg); } +int bdx_mdiobus_init(struct bdx_priv *priv); + #endif /* _TN40XX_H */ diff --git a/drivers/net/ethernet/tehuti/tn40_mdio.c b/drivers/net/ethernet/tehuti/tn40_mdio.c new file mode 100644 index 000000000000..f7f83c77e8b2 --- /dev/null +++ b/drivers/net/ethernet/tehuti/tn40_mdio.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) Tehuti Networks Ltd. */ + +#include "tn40.h" + +static u32 bdx_mdio_get(struct bdx_priv *priv) +{ + void __iomem *regs = priv->regs; + +#define BDX_MAX_MDIO_BUSY_LOOPS 1024 + int tries = 0; + + while (++tries < BDX_MAX_MDIO_BUSY_LOOPS) { + u32 mdio_cmd_stat = readl(regs + REG_MDIO_CMD_STAT); + + if (GET_MDIO_BUSY(mdio_cmd_stat) == 0) + return mdio_cmd_stat; + } + dev_err(&priv->pdev->dev, "MDIO busy!\n"); + return 0xFFFFFFFF; +} + +static u16 bdx_mdio_read(struct bdx_priv *priv, int device, int port, u16 addr) +{ + void __iomem *regs = priv->regs; + u32 tmp_reg, i; + /* wait until MDIO is not busy */ + if (bdx_mdio_get(priv) == 0xFFFFFFFF) + return -1; + + i = ((device & 0x1F) | ((port & 0x1F) << 5)); + writel(i, regs + REG_MDIO_CMD); + writel((u32)addr, regs + REG_MDIO_ADDR); + tmp_reg = bdx_mdio_get(priv); + if (tmp_reg == 0xFFFFFFFF) + return -1; + + writel(((1 << 15) | i), regs + REG_MDIO_CMD); + /* read CMD_STAT until not busy */ + tmp_reg = bdx_mdio_get(priv); + if (tmp_reg == 0xFFFFFFFF) + return -1; + + if (GET_MDIO_RD_ERR(tmp_reg)) { + dev_dbg(&priv->pdev->dev, "MDIO error after read command\n"); + return -1; + } + tmp_reg = readl(regs + REG_MDIO_DATA); + + return (tmp_reg & 0xFFFF); +} + +static int bdx_mdio_write(struct bdx_priv *priv, int device, int port, u16 addr, + u16 data) +{ + void __iomem *regs = priv->regs; + u32 tmp_reg; + + /* wait until MDIO is not busy */ + if (bdx_mdio_get(priv) == 0xFFFFFFFF) + return -1; + writel(((device & 0x1F) | ((port & 0x1F) << 5)), regs + REG_MDIO_CMD); + writel((u32)addr, regs + REG_MDIO_ADDR); + if (bdx_mdio_get(priv) == 0xFFFFFFFF) + return -1; + writel((u32)data, regs + REG_MDIO_DATA); + /* read CMD_STAT until not busy */ + tmp_reg = bdx_mdio_get(priv); + if (tmp_reg == 0xFFFFFFFF) + return -1; + + if (GET_MDIO_RD_ERR(tmp_reg)) { + dev_err(&priv->pdev->dev, "MDIO error after write command\n"); + return -1; + } + return 0; +} + +static void bdx_mdio_set_speed(struct bdx_priv *priv, u32 speed) +{ + void __iomem *regs = priv->regs; + int mdio_cfg; + + mdio_cfg = readl(regs + REG_MDIO_CMD_STAT); + if (speed == 1) + mdio_cfg = (0x7d << 7) | 0x08; /* 1MHz */ + else + mdio_cfg = 0xA08; /* 6MHz */ + mdio_cfg |= (1 << 6); + writel(mdio_cfg, regs + REG_MDIO_CMD_STAT); + msleep(100); +} + +static int mdio_read_reg(struct mii_bus *mii_bus, int addr, int devnum, int regnum) +{ + return bdx_mdio_read(mii_bus->priv, devnum, addr, regnum); +} + +static int mdio_write_reg(struct mii_bus *mii_bus, int addr, int devnum, int regnum, u16 val) +{ + return bdx_mdio_write(mii_bus->priv, devnum, addr, regnum, val); +} + +int bdx_mdiobus_init(struct bdx_priv *priv) +{ + struct pci_dev *pdev = priv->pdev; + struct mii_bus *bus; + struct phy_device *phydev; + int ret; + + bus = devm_mdiobus_alloc(&pdev->dev); + if (!bus) + return -ENOMEM; + + bus->name = BDX_DRV_NAME; + bus->parent = &pdev->dev; + snprintf(bus->id, MII_BUS_ID_SIZE, "tn40xx-%x-%x", + pci_domain_nr(pdev->bus), pci_dev_id(pdev)); + bus->priv = priv; + + bus->read_c45 = mdio_read_reg; + bus->write_c45 = mdio_write_reg; + + ret = devm_mdiobus_register(&pdev->dev, bus); + if (ret) { + dev_err(&pdev->dev, "failed to register mdiobus %d %u %u\n", + ret, bus->state, MDIOBUS_UNREGISTERED); + return ret; + } + + phydev = phy_find_first(bus); + if (!phydev) { + dev_err(&pdev->dev, "failed to find phy\n"); + return -1; + } + phydev->irq = PHY_MAC_INTERRUPT; + priv->mdio = bus; + priv->phydev = phydev; + bdx_mdio_set_speed(priv, MDIO_SPEED_6MHZ); + return 0; +}
This patch adds supports for multiple PHY hardware with PHYLIB. The adapters with TN40xx chips use multiple PHY hardware; AMCC QT2025, TI TLK10232, Aqrate AQR105, and Marvell 88X3120, 88X3310, and MV88E2010. For now, the PCI ID table of this driver enables adapters using only QT2025 PHY. I've tested this driver and the QT2025 PHY driver with Edimax EN-9320 10G adapter. Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com> --- drivers/net/ethernet/tehuti/Kconfig | 1 + drivers/net/ethernet/tehuti/Makefile | 2 +- drivers/net/ethernet/tehuti/tn40.c | 32 ++++++ drivers/net/ethernet/tehuti/tn40.h | 5 + drivers/net/ethernet/tehuti/tn40_mdio.c | 141 ++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/tehuti/tn40_mdio.c