[U-Boot] [PATCH 2/2 v2] drivers: net: add NXP ENETC MDIO driver

Bin Meng bmeng.cn at gmail.com
Mon Jun 10 03:42:48 UTC 2019


Hi Alex,

On Sat, Jun 8, 2019 at 12:13 AM Alex Marginean <alexm.osslist at gmail.com> wrote:
>
> Adds a driver for the MDIO interface currently integrated in LS1028a SoC.
> This MDIO interface is shared by multiple ethernet interfaces and is
> presented as a stand-alone PCI function on the SoC ECAM.
>
> Signed-off-by: Alex Marginean <alexm.osslist at gmail.com>
> ---
>
> Changes in v2:
>         - fix priv structure used (was using the eth driver structure)
>         - simplified naming code in _bind
>         - ENETC_DBG -> enetc_dbg
>         - several styling and cosmetic updates to the header file
>
>  configs/ls1028aqds_tfa_defconfig |   1 +
>  configs/ls1028ardb_tfa_defconfig |   1 +
>  drivers/net/fsl_enetc.c          | 169 +++++++++++++++++++++++++++++++
>  drivers/net/fsl_enetc.h          |  18 ++++
>  include/pci_ids.h                |   1 +
>  5 files changed, 190 insertions(+)
>
> diff --git a/configs/ls1028aqds_tfa_defconfig b/configs/ls1028aqds_tfa_defconfig
> index 11fe344b04..84a1bf90bf 100644
> --- a/configs/ls1028aqds_tfa_defconfig
> +++ b/configs/ls1028aqds_tfa_defconfig
> @@ -43,6 +43,7 @@ CONFIG_SPI_FLASH_STMICRO=y
>  CONFIG_PHYLIB=y
>  CONFIG_PHY_ATHEROS=y
>  CONFIG_DM_ETH=y
> +CONFIG_DM_MDIO=y

See my comments in patch [1/2]

>  CONFIG_PHY_GIGE=y
>  CONFIG_E1000=y
>  CONFIG_FSL_ENETC=y
> diff --git a/configs/ls1028ardb_tfa_defconfig b/configs/ls1028ardb_tfa_defconfig
> index ab6f2a850c..3f5bc2e139 100644
> --- a/configs/ls1028ardb_tfa_defconfig
> +++ b/configs/ls1028ardb_tfa_defconfig
> @@ -43,6 +43,7 @@ CONFIG_SPI_FLASH_STMICRO=y
>  CONFIG_PHYLIB=y
>  CONFIG_PHY_ATHEROS=y
>  CONFIG_DM_ETH=y
> +CONFIG_DM_MDIO=y

ditto

>  CONFIG_PHY_GIGE=y
>  CONFIG_E1000=y
>  CONFIG_FSL_ENETC=y
> diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c
> index 325e032746..8fe84949b8 100644
> --- a/drivers/net/fsl_enetc.c
> +++ b/drivers/net/fsl_enetc.c
> @@ -12,6 +12,7 @@
>  #include <asm/io.h>
>  #include <asm/processor.h>
>  #include <pci.h>
> +#include <miiphy.h>
>
>  static int enetc_bind(struct udevice *dev)
>  {
> @@ -23,6 +24,61 @@ static int enetc_bind(struct udevice *dev)
>         return 0;
>  }
>
> +static void enetc_start_phy(struct udevice *dev)
> +{
> +#ifdef CONFIG_DM_MDIO
> +       int supported, if_type = PHY_INTERFACE_MODE_NONE;
> +       struct udevice *miidev;
> +       struct phy_device *phy;
> +       u32 phandle, phy_id;
> +       const char *if_str;
> +       ofnode phy_node;
> +
> +       if (!ofnode_valid(dev->node)) {
> +               enetc_dbg(dev, "no enetc ofnode found, skipping PHY set-up\n");
> +               return;
> +       }
> +
> +       if (ofnode_read_u32(dev->node, "phy-handle", &phandle)) {
> +               enetc_dbg(dev, "phy-handle not found, skipping PHY set-up\n");
> +               return;
> +       }
> +
> +       phy_node = ofnode_get_by_phandle(phandle);
> +       if (!ofnode_valid(phy_node)) {
> +               enetc_dbg(dev, "invalid phy node, skipping PHY set-up\n");
> +               return;
> +       }
> +       enetc_dbg(dev, "phy node: %s\n", ofnode_get_name(phy_node));
> +
> +       if (ofnode_read_u32(phy_node, "reg", &phy_id)) {
> +               enetc_dbg(dev,
> +                         "missing reg in PHY node, skipping PHY set-up\n");
> +               return;
> +       }
> +
> +       if_str = ofnode_read_string(phy_node, "phy-mode");
> +       if (if_str)
> +               if_type = phy_get_interface_by_name(if_str);
> +       if (if_type < 0)
> +               if_type = PHY_INTERFACE_MODE_NONE;
> +
> +       if (uclass_get_device_by_ofnode(UCLASS_MDIO,
> +                                       ofnode_get_parent(phy_node),
> +                                       &miidev))
> +               return;
> +
> +       phy = dm_mdio_phy_connect(miidev, phy_id, dev, if_type);
> +       if (!phy)
> +               return;
> +
> +       supported = GENMASK(6, 0); /* speeds up to 1G & AN */
> +       phy->advertising = phy->supported & supported;
> +       phy_config(phy);
> +       phy_startup(phy);
> +#endif
> +}
> +
>  /*
>   * Probe ENETC driver:
>   * - initialize port and station interface BARs
> @@ -223,6 +279,8 @@ static int enetc_start(struct udevice *dev)
>         enetc_setup_tx_bdr(hw);
>         enetc_setup_rx_bdr(dev, hw);
>
> +       enetc_start_phy(dev);
> +
>         return 0;
>  }
>
> @@ -342,3 +400,114 @@ static struct pci_device_id enetc_ids[] = {
>  };
>
>  U_BOOT_PCI_DEVICE(eth_enetc, enetc_ids);
> +
> +#ifdef CONFIG_DM_MDIO
> +
> +static void enetc_mdio_wait_bsy(struct enetc_mdio_devfn *hw)
> +{
> +       while (enetc_read(hw, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_BSY)
> +               cpu_relax();
> +}
> +
> +static int enetc_mdio_read(struct udevice *dev, int addr, int devad, int reg)
> +{
> +       struct enetc_mdio_devfn *hw = dev_get_priv(dev);
> +
> +       if (devad == MDIO_DEVAD_NONE)
> +               enetc_write(hw, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C22);
> +       else
> +               enetc_write(hw, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C45);
> +       enetc_mdio_wait_bsy(hw);
> +
> +       if (devad == MDIO_DEVAD_NONE) {
> +               enetc_write(hw, ENETC_MDIO_CTL, ENETC_MDIO_CTL_READ |
> +                           (addr << 5) | reg);
> +       } else {
> +               enetc_write(hw, ENETC_MDIO_CTL, (addr << 5) + devad);
> +               enetc_mdio_wait_bsy(hw);
> +
> +               enetc_write(hw, ENETC_MDIO_STAT, reg);
> +               enetc_mdio_wait_bsy(hw);
> +
> +               enetc_write(hw, ENETC_MDIO_CTL, ENETC_MDIO_CTL_READ |
> +                           (addr << 5) | devad);
> +       }
> +
> +       enetc_mdio_wait_bsy(hw);
> +       if (enetc_read(hw, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_RD_ER)
> +               return ENETC_MDIO_READ_ERR;
> +
> +       return enetc_read(hw, ENETC_MDIO_DATA);
> +}
> +
> +static int enetc_mdio_write(struct udevice *dev, int addr, int devad, int reg,
> +                           u16 val)
> +{
> +       struct enetc_mdio_devfn *hw = dev_get_priv(dev);
> +
> +       if (devad == MDIO_DEVAD_NONE)
> +               enetc_write(hw, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C22);
> +       else
> +               enetc_write(hw, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C45);
> +       enetc_mdio_wait_bsy(hw);
> +
> +       if (devad != MDIO_DEVAD_NONE) {
> +               enetc_write(hw, ENETC_MDIO_CTL, (addr << 5) + devad);
> +               enetc_write(hw, ENETC_MDIO_STAT, reg);
> +       } else {
> +               enetc_write(hw, ENETC_MDIO_CTL, (addr << 5) + reg);
> +       }
> +       enetc_mdio_wait_bsy(hw);
> +
> +       enetc_write(hw, ENETC_MDIO_DATA, val);
> +       enetc_mdio_wait_bsy(hw);
> +
> +       return 0;
> +}
> +
> +static const struct mdio_ops enetc_mdio_ops = {
> +       .read = enetc_mdio_read,
> +       .write = enetc_mdio_write,
> +};
> +
> +static int enetc_mdio_bind(struct udevice *dev)
> +{
> +       char name[16];
> +
> +       sprintf(name, "emdio#%u", PCI_FUNC(dm_pci_get_bdf(dev)));
> +       device_set_name(dev, name);
> +
> +       return 0;
> +}
> +
> +static int enetc_mdio_probe(struct udevice *dev)
> +{
> +       struct enetc_devfn *hw = dev_get_priv(dev);
> +
> +       hw->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0);
> +       if (!hw->regs_base) {
> +               enetc_dbg(dev, "failed to map BAR0\n");
> +               return -EINVAL;
> +       }
> +
> +       dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY);
> +
> +       return 0;
> +}
> +
> +U_BOOT_DRIVER(enetc_mdio) = {
> +       .name   = "enetc_mdio",
> +       .id     = UCLASS_MDIO,
> +       .bind   = enetc_mdio_bind,
> +       .probe  = enetc_mdio_probe,
> +       .ops    = &enetc_mdio_ops,
> +       .priv_auto_alloc_size = sizeof(struct enetc_mdio_devfn),
> +};
> +
> +static struct pci_device_id enetc_mdio_ids[] = {
> +       { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_MDIO) },
> +};
> +
> +U_BOOT_PCI_DEVICE(enetc_mdio, enetc_mdio_ids);

We should create a separate file fsl_enetc_mdio.c for the ENETC MDIO
driver, and create a Kconfig option that depends on DM_MDIO for that
driver, and select the new MDIO driver in the board defconfig file,
instead of select DM_MDIO.

> +
> +#endif /* CONFIG_DM_MDIO */
> diff --git a/drivers/net/fsl_enetc.h b/drivers/net/fsl_enetc.h
> index 94f836760a..fb9d31bf79 100644
> --- a/drivers/net/fsl_enetc.h
> +++ b/drivers/net/fsl_enetc.h
> @@ -169,4 +169,22 @@ struct enetc_devfn {
>  #define enetc_bdr_write(hw, t, n, off, val) \
>                                 enetc_write(hw, ENETC_BDR(t, n, off), val)
>
> +/* ENETC external MDIO registers */
> +
> +#define ENETC_MDIO_CFG         0x1c00
> +#define  ENETC_EMDIO_CFG_C22   0x00809508
> +#define  ENETC_EMDIO_CFG_C45   0x00809548
> +#define  ENETC_EMDIO_CFG_RD_ER BIT(1)
> +#define  ENETC_EMDIO_CFG_BSY   BIT(0)
> +#define ENETC_MDIO_CTL         0x1c04
> +#define  ENETC_MDIO_CTL_READ   BIT(15)
> +#define ENETC_MDIO_DATA                0x1c08
> +#define ENETC_MDIO_STAT                0x1c0c
> +
> +#define ENETC_MDIO_READ_ERR    0xffff
> +
> +struct enetc_mdio_devfn {
> +       void *regs_base;
> +};
> +
>  #endif /* _ENETC_H */
> diff --git a/include/pci_ids.h b/include/pci_ids.h
> index 16cf0641c7..855136e89a 100644
> --- a/include/pci_ids.h
> +++ b/include/pci_ids.h
> @@ -2484,6 +2484,7 @@
>  #define PCI_DEVICE_ID_MPC8641D         0x7011
>  #define PCI_DEVICE_ID_MPC8610          0x7018
>  #define PCI_DEVICE_ID_ENETC_PF         0xE100
> +#define PCI_DEVICE_ID_MDIO             0xEE01

Suggest we put this macro in the fsl_enetc.h, and the name _MDIO is
too generic. Maybe _ENETC_MDIO?

>
>  #define PCI_VENDOR_ID_PASEMI           0x1959
>
> --

Regards,
Bin


More information about the U-Boot mailing list