1231ece36SClaudiu Manoil // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 2231ece36SClaudiu Manoil /* Copyright 2019 NXP */ 36517798dSClaudiu Manoil #include <linux/fsl/enetc_mdio.h> 4231ece36SClaudiu Manoil #include <linux/of_mdio.h> 56517798dSClaudiu Manoil #include "enetc_pf.h" 6231ece36SClaudiu Manoil 7231ece36SClaudiu Manoil #define ENETC_MDIO_DEV_ID 0xee01 8231ece36SClaudiu Manoil #define ENETC_MDIO_DEV_NAME "FSL PCIe IE Central MDIO" 9231ece36SClaudiu Manoil #define ENETC_MDIO_BUS_NAME ENETC_MDIO_DEV_NAME " Bus" 10231ece36SClaudiu Manoil #define ENETC_MDIO_DRV_NAME ENETC_MDIO_DEV_NAME " driver" 11231ece36SClaudiu Manoil 12231ece36SClaudiu Manoil static int enetc_pci_mdio_probe(struct pci_dev *pdev, 13231ece36SClaudiu Manoil const struct pci_device_id *ent) 14231ece36SClaudiu Manoil { 15231ece36SClaudiu Manoil struct enetc_mdio_priv *mdio_priv; 16231ece36SClaudiu Manoil struct device *dev = &pdev->dev; 176517798dSClaudiu Manoil void __iomem *port_regs; 18231ece36SClaudiu Manoil struct enetc_hw *hw; 19231ece36SClaudiu Manoil struct mii_bus *bus; 20231ece36SClaudiu Manoil int err; 21231ece36SClaudiu Manoil 226517798dSClaudiu Manoil port_regs = pci_iomap(pdev, 0, 0); 236517798dSClaudiu Manoil if (!port_regs) { 246517798dSClaudiu Manoil dev_err(dev, "iomap failed\n"); 256517798dSClaudiu Manoil err = -ENXIO; 266517798dSClaudiu Manoil goto err_ioremap; 276517798dSClaudiu Manoil } 286517798dSClaudiu Manoil 296517798dSClaudiu Manoil hw = enetc_hw_alloc(dev, port_regs); 304addbcb3SYueHaibing if (IS_ERR(hw)) { 316517798dSClaudiu Manoil err = PTR_ERR(hw); 326517798dSClaudiu Manoil goto err_hw_alloc; 336517798dSClaudiu Manoil } 34231ece36SClaudiu Manoil 35231ece36SClaudiu Manoil bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); 366517798dSClaudiu Manoil if (!bus) { 376517798dSClaudiu Manoil err = -ENOMEM; 386517798dSClaudiu Manoil goto err_mdiobus_alloc; 396517798dSClaudiu Manoil } 40231ece36SClaudiu Manoil 41231ece36SClaudiu Manoil bus->name = ENETC_MDIO_BUS_NAME; 42231ece36SClaudiu Manoil bus->read = enetc_mdio_read; 43231ece36SClaudiu Manoil bus->write = enetc_mdio_write; 44231ece36SClaudiu Manoil bus->parent = dev; 45231ece36SClaudiu Manoil mdio_priv = bus->priv; 46231ece36SClaudiu Manoil mdio_priv->hw = hw; 476517798dSClaudiu Manoil mdio_priv->mdio_base = ENETC_EMDIO_BASE; 48231ece36SClaudiu Manoil snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); 49231ece36SClaudiu Manoil 50231ece36SClaudiu Manoil pcie_flr(pdev); 51231ece36SClaudiu Manoil err = pci_enable_device_mem(pdev); 52231ece36SClaudiu Manoil if (err) { 53231ece36SClaudiu Manoil dev_err(dev, "device enable failed\n"); 546517798dSClaudiu Manoil goto err_pci_enable; 55231ece36SClaudiu Manoil } 56231ece36SClaudiu Manoil 57231ece36SClaudiu Manoil err = pci_request_region(pdev, 0, KBUILD_MODNAME); 58231ece36SClaudiu Manoil if (err) { 59231ece36SClaudiu Manoil dev_err(dev, "pci_request_region failed\n"); 60231ece36SClaudiu Manoil goto err_pci_mem_reg; 61231ece36SClaudiu Manoil } 62231ece36SClaudiu Manoil 63231ece36SClaudiu Manoil err = of_mdiobus_register(bus, dev->of_node); 64231ece36SClaudiu Manoil if (err) 65231ece36SClaudiu Manoil goto err_mdiobus_reg; 66231ece36SClaudiu Manoil 67231ece36SClaudiu Manoil pci_set_drvdata(pdev, bus); 68231ece36SClaudiu Manoil 69231ece36SClaudiu Manoil return 0; 70231ece36SClaudiu Manoil 71231ece36SClaudiu Manoil err_mdiobus_reg: 72*18eeb4deSChristophe JAILLET pci_release_region(pdev, 0); 73231ece36SClaudiu Manoil err_pci_mem_reg: 74231ece36SClaudiu Manoil pci_disable_device(pdev); 756517798dSClaudiu Manoil err_pci_enable: 766517798dSClaudiu Manoil err_mdiobus_alloc: 776517798dSClaudiu Manoil err_hw_alloc: 78d975cb7eSDejin Zheng iounmap(port_regs); 796517798dSClaudiu Manoil err_ioremap: 80231ece36SClaudiu Manoil return err; 81231ece36SClaudiu Manoil } 82231ece36SClaudiu Manoil 83231ece36SClaudiu Manoil static void enetc_pci_mdio_remove(struct pci_dev *pdev) 84231ece36SClaudiu Manoil { 85231ece36SClaudiu Manoil struct mii_bus *bus = pci_get_drvdata(pdev); 86231ece36SClaudiu Manoil struct enetc_mdio_priv *mdio_priv; 87231ece36SClaudiu Manoil 88231ece36SClaudiu Manoil mdiobus_unregister(bus); 89231ece36SClaudiu Manoil mdio_priv = bus->priv; 90231ece36SClaudiu Manoil iounmap(mdio_priv->hw->port); 91*18eeb4deSChristophe JAILLET pci_release_region(pdev, 0); 92231ece36SClaudiu Manoil pci_disable_device(pdev); 93231ece36SClaudiu Manoil } 94231ece36SClaudiu Manoil 95231ece36SClaudiu Manoil static const struct pci_device_id enetc_pci_mdio_id_table[] = { 96231ece36SClaudiu Manoil { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) }, 97231ece36SClaudiu Manoil { 0, } /* End of table. */ 98231ece36SClaudiu Manoil }; 99231ece36SClaudiu Manoil MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table); 100231ece36SClaudiu Manoil 101231ece36SClaudiu Manoil static struct pci_driver enetc_pci_mdio_driver = { 102231ece36SClaudiu Manoil .name = KBUILD_MODNAME, 103231ece36SClaudiu Manoil .id_table = enetc_pci_mdio_id_table, 104231ece36SClaudiu Manoil .probe = enetc_pci_mdio_probe, 105231ece36SClaudiu Manoil .remove = enetc_pci_mdio_remove, 106231ece36SClaudiu Manoil }; 107231ece36SClaudiu Manoil module_pci_driver(enetc_pci_mdio_driver); 108231ece36SClaudiu Manoil 109231ece36SClaudiu Manoil MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME); 110231ece36SClaudiu Manoil MODULE_LICENSE("Dual BSD/GPL"); 111