mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
Merge branch 'enetc-PCIe-MDIO'
Claudiu Manoil says: ==================== enetc: Add mdio bus driver for the PCIe MDIO endpoint First patch fixes a sparse issue and cleans up accessors to avoid casting to __iomem. The second one cleans up the Makefile, to make it easier to add new entries. Third patch just registers the PCIe endpoint device containing the MDIO registers as a standalone MDIO bus driver, to provide an alternative way to control the MDIO bus. The same code used by the ENETC ports (eth controllers) to manage MDIO via local registers applies and is reused. Bindings are provided for the new MDIO node, similarly to ENETC port nodes bindings. Last patch enables the ENETC port 1 and its RGMII PHY on the LS1028A QDS board, where the MDIO muxing configuration relies on the MDIO support provided in the first patch. Changes since v0: v1 - fixed mdio bus allocation v2 - cleaned up accessors to avoid casting v3 - fixed spelling (mostly commit message) v4 - fixed err path check blunder v5 - fixed loadble module build, provided separate kbuild module for the driver ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4de97b0c86
9 changed files with 264 additions and 67 deletions
|
@ -11,7 +11,9 @@ Required properties:
|
|||
to parent node bindings.
|
||||
- compatible : Should be "fsl,enetc".
|
||||
|
||||
1) The ENETC external port is connected to a MDIO configurable phy:
|
||||
1. The ENETC external port is connected to a MDIO configurable phy
|
||||
|
||||
1.1. Using the local ENETC Port MDIO interface
|
||||
|
||||
In this case, the ENETC node should include a "mdio" sub-node
|
||||
that in turn should contain the "ethernet-phy" node describing the
|
||||
|
@ -47,8 +49,42 @@ Example:
|
|||
};
|
||||
};
|
||||
|
||||
2) The ENETC port is an internal port or has a fixed-link external
|
||||
connection:
|
||||
1.2. Using the central MDIO PCIe endpoint device
|
||||
|
||||
In this case, the mdio node should be defined as another PCIe
|
||||
endpoint node, at the same level with the ENETC port nodes.
|
||||
|
||||
Required properties:
|
||||
|
||||
- reg : Specifies PCIe Device Number and Function
|
||||
Number of the ENETC endpoint device, according
|
||||
to parent node bindings.
|
||||
- compatible : Should be "fsl,enetc-mdio".
|
||||
|
||||
The remaining required mdio bus properties are standard, their bindings
|
||||
already defined in Documentation/devicetree/bindings/net/mdio.txt.
|
||||
|
||||
Example:
|
||||
|
||||
ethernet@0,0 {
|
||||
compatible = "fsl,enetc";
|
||||
reg = <0x000000 0 0 0 0>;
|
||||
phy-handle = <&sgmii_phy0>;
|
||||
phy-connection-type = "sgmii";
|
||||
};
|
||||
|
||||
mdio@0,3 {
|
||||
compatible = "fsl,enetc-mdio";
|
||||
reg = <0x000300 0 0 0 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
sgmii_phy0: ethernet-phy@2 {
|
||||
reg = <0x2>;
|
||||
};
|
||||
};
|
||||
|
||||
2. The ENETC port is an internal port or has a fixed-link external
|
||||
connection
|
||||
|
||||
In this case, the ENETC port node defines a fixed link connection,
|
||||
as specified by Documentation/devicetree/bindings/net/fixed-link.txt.
|
||||
|
|
|
@ -85,6 +85,26 @@ simple-audio-card,codec {
|
|||
system-clock-frequency = <25000000>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio-mux {
|
||||
compatible = "mdio-mux-multiplexer";
|
||||
mux-controls = <&mux 0>;
|
||||
mdio-parent-bus = <&enetc_mdio_pf3>;
|
||||
#address-cells=<1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* on-board RGMII PHY */
|
||||
mdio@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
|
||||
qds_phy1: ethernet-phy@5 {
|
||||
/* Atheros 8035 */
|
||||
reg = <5>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&duart0 {
|
||||
|
@ -164,6 +184,26 @@ sgtl5000: audio-codec@a {
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
fpga@66 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,ls1028aqds-fpga", "fsl,fpga-qixis-i2c",
|
||||
"simple-mfd";
|
||||
reg = <0x66>;
|
||||
|
||||
mux: mux-controller {
|
||||
compatible = "reg-mux";
|
||||
#mux-control-cells = <1>;
|
||||
mux-reg-masks = <0x54 0xf0>; /* 0: reg 0x54, bits 7:4 */
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&enetc_port1 {
|
||||
phy-handle = <&qds_phy1>;
|
||||
phy-connection-type = "rgmii-id";
|
||||
};
|
||||
|
||||
&sai1 {
|
||||
|
|
|
@ -536,6 +536,12 @@ enetc_port1: ethernet@0,1 {
|
|||
compatible = "fsl,enetc";
|
||||
reg = <0x000100 0 0 0 0>;
|
||||
};
|
||||
enetc_mdio_pf3: mdio@0,3 {
|
||||
compatible = "fsl,enetc-mdio";
|
||||
reg = <0x000300 0 0 0 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
ethernet@0,4 {
|
||||
compatible = "fsl,enetc-ptp";
|
||||
reg = <0x000400 0 0 0 0>;
|
||||
|
|
|
@ -18,6 +18,15 @@ config FSL_ENETC_VF
|
|||
|
||||
If compiled as module (M), the module name is fsl-enetc-vf.
|
||||
|
||||
config FSL_ENETC_MDIO
|
||||
tristate "ENETC MDIO driver"
|
||||
depends on PCI && (ARCH_LAYERSCAPE || COMPILE_TEST)
|
||||
help
|
||||
This driver supports NXP ENETC Central MDIO controller as a PCIe
|
||||
physical function (PF) device.
|
||||
|
||||
If compiled as module (M), the module name is fsl-enetc-mdio.
|
||||
|
||||
config FSL_ENETC_PTP_CLOCK
|
||||
tristate "ENETC PTP clock driver"
|
||||
depends on PTP_1588_CLOCK_QORIQ && (FSL_ENETC || FSL_ENETC_VF)
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
common-objs := enetc.o enetc_cbdr.o enetc_ethtool.o
|
||||
|
||||
obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
|
||||
fsl-enetc-$(CONFIG_FSL_ENETC) += enetc.o enetc_cbdr.o enetc_ethtool.o \
|
||||
enetc_mdio.o
|
||||
fsl-enetc-y := enetc_pf.o enetc_mdio.o $(common-objs)
|
||||
fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
|
||||
fsl-enetc-objs := enetc_pf.o $(fsl-enetc-y)
|
||||
|
||||
obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
|
||||
fsl-enetc-vf-y := enetc_vf.o $(common-objs)
|
||||
|
||||
ifeq ($(CONFIG_FSL_ENETC)$(CONFIG_FSL_ENETC_VF), yy)
|
||||
fsl-enetc-vf-objs := enetc_vf.o
|
||||
else
|
||||
fsl-enetc-vf-$(CONFIG_FSL_ENETC_VF) += enetc.o enetc_cbdr.o \
|
||||
enetc_ethtool.o
|
||||
fsl-enetc-vf-objs := enetc_vf.o $(fsl-enetc-vf-y)
|
||||
endif
|
||||
obj-$(CONFIG_FSL_ENETC_MDIO) += fsl-enetc-mdio.o
|
||||
fsl-enetc-mdio-y := enetc_pci_mdio.o enetc_mdio.o
|
||||
|
||||
obj-$(CONFIG_FSL_ENETC_PTP_CLOCK) += fsl-enetc-ptp.o
|
||||
fsl-enetc-ptp-$(CONFIG_FSL_ENETC_PTP_CLOCK) += enetc_ptp.o
|
||||
fsl-enetc-ptp-y := enetc_ptp.o
|
||||
|
|
|
@ -6,18 +6,20 @@
|
|||
#include <linux/iopoll.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "enetc_pf.h"
|
||||
#include "enetc_mdio.h"
|
||||
|
||||
struct enetc_mdio_regs {
|
||||
u32 mdio_cfg; /* MDIO configuration and status */
|
||||
u32 mdio_ctl; /* MDIO control */
|
||||
u32 mdio_data; /* MDIO data */
|
||||
u32 mdio_addr; /* MDIO address */
|
||||
};
|
||||
#define ENETC_MDIO_REG_OFFSET 0x1c00
|
||||
#define ENETC_MDIO_CFG 0x0 /* MDIO configuration and status */
|
||||
#define ENETC_MDIO_CTL 0x4 /* MDIO control */
|
||||
#define ENETC_MDIO_DATA 0x8 /* MDIO data */
|
||||
#define ENETC_MDIO_ADDR 0xc /* MDIO address */
|
||||
|
||||
#define bus_to_enetc_regs(bus) (struct enetc_mdio_regs __iomem *)((bus)->priv)
|
||||
#define enetc_mdio_rd(hw, off) \
|
||||
enetc_port_rd(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET)
|
||||
#define enetc_mdio_wr(hw, off, val) \
|
||||
enetc_port_wr(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET, val)
|
||||
#define enetc_mdio_rd_reg(off) enetc_mdio_rd(hw, off)
|
||||
|
||||
#define ENETC_MDIO_REG_OFFSET 0x1c00
|
||||
#define ENETC_MDC_DIV 258
|
||||
|
||||
#define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8)
|
||||
|
@ -33,18 +35,18 @@ struct enetc_mdio_regs {
|
|||
#define MDIO_DATA(x) ((x) & 0xffff)
|
||||
|
||||
#define TIMEOUT 1000
|
||||
static int enetc_mdio_wait_complete(struct enetc_mdio_regs __iomem *regs)
|
||||
static int enetc_mdio_wait_complete(struct enetc_hw *hw)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
return readx_poll_timeout(enetc_rd_reg, ®s->mdio_cfg, val,
|
||||
return readx_poll_timeout(enetc_mdio_rd_reg, MDIO_CFG, val,
|
||||
!(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT);
|
||||
}
|
||||
|
||||
static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
|
||||
u16 value)
|
||||
int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
|
||||
{
|
||||
struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus);
|
||||
struct enetc_mdio_priv *mdio_priv = bus->priv;
|
||||
struct enetc_hw *hw = mdio_priv->hw;
|
||||
u32 mdio_ctl, mdio_cfg;
|
||||
u16 dev_addr;
|
||||
int ret;
|
||||
|
@ -59,38 +61,39 @@ static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
|
|||
mdio_cfg &= ~MDIO_CFG_ENC45;
|
||||
}
|
||||
|
||||
enetc_wr_reg(®s->mdio_cfg, mdio_cfg);
|
||||
enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
|
||||
|
||||
ret = enetc_mdio_wait_complete(regs);
|
||||
ret = enetc_mdio_wait_complete(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* set port and dev addr */
|
||||
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
|
||||
enetc_wr_reg(®s->mdio_ctl, mdio_ctl);
|
||||
enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
|
||||
|
||||
/* set the register address */
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
enetc_wr_reg(®s->mdio_addr, regnum & 0xffff);
|
||||
enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
|
||||
|
||||
ret = enetc_mdio_wait_complete(regs);
|
||||
ret = enetc_mdio_wait_complete(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* write the value */
|
||||
enetc_wr_reg(®s->mdio_data, MDIO_DATA(value));
|
||||
enetc_mdio_wr(hw, MDIO_DATA, MDIO_DATA(value));
|
||||
|
||||
ret = enetc_mdio_wait_complete(regs);
|
||||
ret = enetc_mdio_wait_complete(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
||||
int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
||||
{
|
||||
struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus);
|
||||
struct enetc_mdio_priv *mdio_priv = bus->priv;
|
||||
struct enetc_hw *hw = mdio_priv->hw;
|
||||
u32 mdio_ctl, mdio_cfg;
|
||||
u16 dev_addr, value;
|
||||
int ret;
|
||||
|
@ -104,41 +107,41 @@ static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
|||
mdio_cfg &= ~MDIO_CFG_ENC45;
|
||||
}
|
||||
|
||||
enetc_wr_reg(®s->mdio_cfg, mdio_cfg);
|
||||
enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
|
||||
|
||||
ret = enetc_mdio_wait_complete(regs);
|
||||
ret = enetc_mdio_wait_complete(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* set port and device addr */
|
||||
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
|
||||
enetc_wr_reg(®s->mdio_ctl, mdio_ctl);
|
||||
enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
|
||||
|
||||
/* set the register address */
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
enetc_wr_reg(®s->mdio_addr, regnum & 0xffff);
|
||||
enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
|
||||
|
||||
ret = enetc_mdio_wait_complete(regs);
|
||||
ret = enetc_mdio_wait_complete(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initiate the read */
|
||||
enetc_wr_reg(®s->mdio_ctl, mdio_ctl | MDIO_CTL_READ);
|
||||
enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
|
||||
|
||||
ret = enetc_mdio_wait_complete(regs);
|
||||
ret = enetc_mdio_wait_complete(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* return all Fs if nothing was there */
|
||||
if (enetc_rd_reg(®s->mdio_cfg) & MDIO_CFG_RD_ER) {
|
||||
if (enetc_mdio_rd(hw, MDIO_CFG) & MDIO_CFG_RD_ER) {
|
||||
dev_dbg(&bus->dev,
|
||||
"Error while reading PHY%d reg at %d.%hhu\n",
|
||||
phy_id, dev_addr, regnum);
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
value = enetc_rd_reg(®s->mdio_data) & 0xffff;
|
||||
value = enetc_mdio_rd(hw, MDIO_DATA) & 0xffff;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -146,12 +149,12 @@ static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
|||
int enetc_mdio_probe(struct enetc_pf *pf)
|
||||
{
|
||||
struct device *dev = &pf->si->pdev->dev;
|
||||
struct enetc_mdio_regs __iomem *regs;
|
||||
struct enetc_mdio_priv *mdio_priv;
|
||||
struct device_node *np;
|
||||
struct mii_bus *bus;
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
bus = mdiobus_alloc_size(sizeof(regs));
|
||||
bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -159,41 +162,31 @@ int enetc_mdio_probe(struct enetc_pf *pf)
|
|||
bus->read = enetc_mdio_read;
|
||||
bus->write = enetc_mdio_write;
|
||||
bus->parent = dev;
|
||||
mdio_priv = bus->priv;
|
||||
mdio_priv->hw = &pf->si->hw;
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
|
||||
|
||||
/* store the enetc mdio base address for this bus */
|
||||
regs = pf->si->hw.port + ENETC_MDIO_REG_OFFSET;
|
||||
bus->priv = regs;
|
||||
|
||||
np = of_get_child_by_name(dev->of_node, "mdio");
|
||||
if (!np) {
|
||||
dev_err(dev, "MDIO node missing\n");
|
||||
ret = -EINVAL;
|
||||
goto err_registration;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_mdiobus_register(bus, np);
|
||||
if (ret) {
|
||||
err = of_mdiobus_register(bus, np);
|
||||
if (err) {
|
||||
of_node_put(np);
|
||||
dev_err(dev, "cannot register MDIO bus\n");
|
||||
goto err_registration;
|
||||
return err;
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
pf->mdio = bus;
|
||||
|
||||
return 0;
|
||||
|
||||
err_registration:
|
||||
mdiobus_free(bus);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void enetc_mdio_remove(struct enetc_pf *pf)
|
||||
{
|
||||
if (pf->mdio) {
|
||||
if (pf->mdio)
|
||||
mdiobus_unregister(pf->mdio);
|
||||
mdiobus_free(pf->mdio);
|
||||
}
|
||||
}
|
||||
|
|
12
drivers/net/ethernet/freescale/enetc/enetc_mdio.h
Normal file
12
drivers/net/ethernet/freescale/enetc/enetc_mdio.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
|
||||
/* Copyright 2019 NXP */
|
||||
|
||||
#include <linux/phy.h>
|
||||
#include "enetc_pf.h"
|
||||
|
||||
struct enetc_mdio_priv {
|
||||
struct enetc_hw *hw;
|
||||
};
|
||||
|
||||
int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value);
|
||||
int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum);
|
101
drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
Normal file
101
drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
|
||||
/* Copyright 2019 NXP */
|
||||
#include <linux/of_mdio.h>
|
||||
#include "enetc_mdio.h"
|
||||
|
||||
#define ENETC_MDIO_DEV_ID 0xee01
|
||||
#define ENETC_MDIO_DEV_NAME "FSL PCIe IE Central MDIO"
|
||||
#define ENETC_MDIO_BUS_NAME ENETC_MDIO_DEV_NAME " Bus"
|
||||
#define ENETC_MDIO_DRV_NAME ENETC_MDIO_DEV_NAME " driver"
|
||||
|
||||
static int enetc_pci_mdio_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct enetc_mdio_priv *mdio_priv;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct enetc_hw *hw;
|
||||
struct mii_bus *bus;
|
||||
int err;
|
||||
|
||||
hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
|
||||
if (!hw)
|
||||
return -ENOMEM;
|
||||
|
||||
bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
|
||||
bus->name = ENETC_MDIO_BUS_NAME;
|
||||
bus->read = enetc_mdio_read;
|
||||
bus->write = enetc_mdio_write;
|
||||
bus->parent = dev;
|
||||
mdio_priv = bus->priv;
|
||||
mdio_priv->hw = hw;
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
|
||||
|
||||
pcie_flr(pdev);
|
||||
err = pci_enable_device_mem(pdev);
|
||||
if (err) {
|
||||
dev_err(dev, "device enable failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = pci_request_region(pdev, 0, KBUILD_MODNAME);
|
||||
if (err) {
|
||||
dev_err(dev, "pci_request_region failed\n");
|
||||
goto err_pci_mem_reg;
|
||||
}
|
||||
|
||||
hw->port = pci_iomap(pdev, 0, 0);
|
||||
if (!hw->port) {
|
||||
err = -ENXIO;
|
||||
dev_err(dev, "iomap failed\n");
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
err = of_mdiobus_register(bus, dev->of_node);
|
||||
if (err)
|
||||
goto err_mdiobus_reg;
|
||||
|
||||
pci_set_drvdata(pdev, bus);
|
||||
|
||||
return 0;
|
||||
|
||||
err_mdiobus_reg:
|
||||
iounmap(mdio_priv->hw->port);
|
||||
err_ioremap:
|
||||
pci_release_mem_regions(pdev);
|
||||
err_pci_mem_reg:
|
||||
pci_disable_device(pdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void enetc_pci_mdio_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct mii_bus *bus = pci_get_drvdata(pdev);
|
||||
struct enetc_mdio_priv *mdio_priv;
|
||||
|
||||
mdiobus_unregister(bus);
|
||||
mdio_priv = bus->priv;
|
||||
iounmap(mdio_priv->hw->port);
|
||||
pci_release_mem_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id enetc_pci_mdio_id_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) },
|
||||
{ 0, } /* End of table. */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table);
|
||||
|
||||
static struct pci_driver enetc_pci_mdio_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = enetc_pci_mdio_id_table,
|
||||
.probe = enetc_pci_mdio_probe,
|
||||
.remove = enetc_pci_mdio_remove,
|
||||
};
|
||||
module_pci_driver(enetc_pci_mdio_driver);
|
||||
|
||||
MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME);
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -750,6 +750,7 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv)
|
|||
{
|
||||
struct enetc_pf *pf = enetc_si_priv(priv->si);
|
||||
struct device_node *np = priv->dev->of_node;
|
||||
struct device_node *mdio_np;
|
||||
int err;
|
||||
|
||||
if (!np) {
|
||||
|
@ -773,7 +774,9 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv)
|
|||
priv->phy_node = of_node_get(np);
|
||||
}
|
||||
|
||||
if (!of_phy_is_fixed_link(np)) {
|
||||
mdio_np = of_get_child_by_name(np, "mdio");
|
||||
if (mdio_np) {
|
||||
of_node_put(mdio_np);
|
||||
err = enetc_mdio_probe(pf);
|
||||
if (err) {
|
||||
of_node_put(priv->phy_node);
|
||||
|
|
Loading…
Reference in a new issue