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? > > #define PCI_VENDOR_ID_PASEMI 0x1959 > > -- Regards, Bin _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot