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

Alex Marginean alexm.osslist at gmail.com
Tue Jun 11 07:30:18 UTC 2019


Hi Bin,

On 6/10/2019 6:42 AM, Bin Meng wrote:
> 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?

It is too generic, I'll rename it and move it to driver header.
I'll send a v3 for these.

> 
>>
>>   #define PCI_VENDOR_ID_PASEMI           0x1959
>>
>> --
> 
> Regards,
> Bin
> 

Thank you!
Alex


More information about the U-Boot mailing list