linux/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
   2/* Copyright 2019 NXP */
   3#include <linux/fsl/enetc_mdio.h>
   4#include <linux/of_mdio.h>
   5#include "enetc_pf.h"
   6
   7#define ENETC_MDIO_DEV_ID       0xee01
   8#define ENETC_MDIO_DEV_NAME     "FSL PCIe IE Central MDIO"
   9#define ENETC_MDIO_BUS_NAME     ENETC_MDIO_DEV_NAME " Bus"
  10#define ENETC_MDIO_DRV_NAME     ENETC_MDIO_DEV_NAME " driver"
  11
  12static int enetc_pci_mdio_probe(struct pci_dev *pdev,
  13                                const struct pci_device_id *ent)
  14{
  15        struct enetc_mdio_priv *mdio_priv;
  16        struct device *dev = &pdev->dev;
  17        void __iomem *port_regs;
  18        struct enetc_hw *hw;
  19        struct mii_bus *bus;
  20        int err;
  21
  22        port_regs = pci_iomap(pdev, 0, 0);
  23        if (!port_regs) {
  24                dev_err(dev, "iomap failed\n");
  25                err = -ENXIO;
  26                goto err_ioremap;
  27        }
  28
  29        hw = enetc_hw_alloc(dev, port_regs);
  30        if (IS_ERR(hw)) {
  31                err = PTR_ERR(hw);
  32                goto err_hw_alloc;
  33        }
  34
  35        bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
  36        if (!bus) {
  37                err = -ENOMEM;
  38                goto err_mdiobus_alloc;
  39        }
  40
  41        bus->name = ENETC_MDIO_BUS_NAME;
  42        bus->read = enetc_mdio_read;
  43        bus->write = enetc_mdio_write;
  44        bus->parent = dev;
  45        mdio_priv = bus->priv;
  46        mdio_priv->hw = hw;
  47        mdio_priv->mdio_base = ENETC_EMDIO_BASE;
  48        snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
  49
  50        pcie_flr(pdev);
  51        err = pci_enable_device_mem(pdev);
  52        if (err) {
  53                dev_err(dev, "device enable failed\n");
  54                goto err_pci_enable;
  55        }
  56
  57        err = pci_request_region(pdev, 0, KBUILD_MODNAME);
  58        if (err) {
  59                dev_err(dev, "pci_request_region failed\n");
  60                goto err_pci_mem_reg;
  61        }
  62
  63        err = of_mdiobus_register(bus, dev->of_node);
  64        if (err)
  65                goto err_mdiobus_reg;
  66
  67        pci_set_drvdata(pdev, bus);
  68
  69        return 0;
  70
  71err_mdiobus_reg:
  72        pci_release_mem_regions(pdev);
  73err_pci_mem_reg:
  74        pci_disable_device(pdev);
  75err_pci_enable:
  76err_mdiobus_alloc:
  77err_hw_alloc:
  78        iounmap(port_regs);
  79err_ioremap:
  80        return err;
  81}
  82
  83static void enetc_pci_mdio_remove(struct pci_dev *pdev)
  84{
  85        struct mii_bus *bus = pci_get_drvdata(pdev);
  86        struct enetc_mdio_priv *mdio_priv;
  87
  88        mdiobus_unregister(bus);
  89        mdio_priv = bus->priv;
  90        iounmap(mdio_priv->hw->port);
  91        pci_release_mem_regions(pdev);
  92        pci_disable_device(pdev);
  93}
  94
  95static const struct pci_device_id enetc_pci_mdio_id_table[] = {
  96        { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) },
  97        { 0, } /* End of table. */
  98};
  99MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table);
 100
 101static struct pci_driver enetc_pci_mdio_driver = {
 102        .name = KBUILD_MODNAME,
 103        .id_table = enetc_pci_mdio_id_table,
 104        .probe = enetc_pci_mdio_probe,
 105        .remove = enetc_pci_mdio_remove,
 106};
 107module_pci_driver(enetc_pci_mdio_driver);
 108
 109MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME);
 110MODULE_LICENSE("Dual BSD/GPL");
 111