123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * ENETC ethernet controller driver
- * Copyright 2019 NXP
- */
- #include <common.h>
- #include <dm.h>
- #include <errno.h>
- #include <pci.h>
- #include <miiphy.h>
- #include <asm/io.h>
- #include <asm/processor.h>
- #include <miiphy.h>
- #include "fsl_enetc.h"
- static void enetc_mdio_wait_bsy(struct enetc_mdio_priv *priv)
- {
- int to = 10000;
- while ((enetc_read(priv, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_BSY) &&
- --to)
- cpu_relax();
- if (!to)
- printf("T");
- }
- int enetc_mdio_read_priv(struct enetc_mdio_priv *priv, int addr, int devad,
- int reg)
- {
- if (devad == MDIO_DEVAD_NONE)
- enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C22);
- else
- enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C45);
- enetc_mdio_wait_bsy(priv);
- if (devad == MDIO_DEVAD_NONE) {
- enetc_write(priv, ENETC_MDIO_CTL, ENETC_MDIO_CTL_READ |
- (addr << 5) | reg);
- } else {
- enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + devad);
- enetc_mdio_wait_bsy(priv);
- enetc_write(priv, ENETC_MDIO_STAT, reg);
- enetc_mdio_wait_bsy(priv);
- enetc_write(priv, ENETC_MDIO_CTL, ENETC_MDIO_CTL_READ |
- (addr << 5) | devad);
- }
- enetc_mdio_wait_bsy(priv);
- if (enetc_read(priv, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_RD_ER)
- return ENETC_MDIO_READ_ERR;
- return enetc_read(priv, ENETC_MDIO_DATA);
- }
- int enetc_mdio_write_priv(struct enetc_mdio_priv *priv, int addr, int devad,
- int reg, u16 val)
- {
- if (devad == MDIO_DEVAD_NONE)
- enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C22);
- else
- enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C45);
- enetc_mdio_wait_bsy(priv);
- if (devad != MDIO_DEVAD_NONE) {
- enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + devad);
- enetc_write(priv, ENETC_MDIO_STAT, reg);
- } else {
- enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + reg);
- }
- enetc_mdio_wait_bsy(priv);
- enetc_write(priv, ENETC_MDIO_DATA, val);
- enetc_mdio_wait_bsy(priv);
- return 0;
- }
- /* DM wrappers */
- static int dm_enetc_mdio_read(struct udevice *dev, int addr, int devad, int reg)
- {
- struct enetc_mdio_priv *priv = dev_get_priv(dev);
- return enetc_mdio_read_priv(priv, addr, devad, reg);
- }
- static int dm_enetc_mdio_write(struct udevice *dev, int addr, int devad,
- int reg, u16 val)
- {
- struct enetc_mdio_priv *priv = dev_get_priv(dev);
- return enetc_mdio_write_priv(priv, addr, devad, reg, val);
- }
- static const struct mdio_ops enetc_mdio_ops = {
- .read = dm_enetc_mdio_read,
- .write = dm_enetc_mdio_write,
- };
- static int enetc_mdio_bind(struct udevice *dev)
- {
- char name[16];
- static int eth_num_devices;
- /*
- * prefer using PCI function numbers to number interfaces, but these
- * are only available if dts nodes are present. For PCI they are
- * optional, handle that case too. Just in case some nodes are present
- * and some are not, use different naming scheme - enetc-N based on
- * PCI function # and enetc#N based on interface count
- */
- if (ofnode_valid(dev_ofnode(dev)))
- sprintf(name, "emdio-%u", PCI_FUNC(pci_get_devfn(dev)));
- else
- sprintf(name, "emdio#%u", eth_num_devices++);
- device_set_name(dev, name);
- return 0;
- }
- static int enetc_mdio_probe(struct udevice *dev)
- {
- struct enetc_mdio_priv *priv = dev_get_priv(dev);
- priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0);
- if (!priv->regs_base) {
- enetc_dbg(dev, "failed to map BAR0\n");
- return -EINVAL;
- }
- priv->regs_base += ENETC_MDIO_BASE;
- 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 = sizeof(struct enetc_mdio_priv),
- };
- static struct pci_device_id enetc_mdio_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_ENETC_MDIO) },
- { }
- };
- U_BOOT_PCI_DEVICE(enetc_mdio, enetc_mdio_ids);
|