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.ossl...@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.ossl...@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
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to