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