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 NETC_EMDIO_VEN_ID 0x1131 8 #define NETC_EMDIO_DEV_ID 0xee00 9 #define ENETC_MDIO_DEV_ID 0xee01 10 #define ENETC_MDIO_DEV_NAME "FSL PCIe IE Central MDIO" 11 #define ENETC_MDIO_BUS_NAME ENETC_MDIO_DEV_NAME " Bus" 12 #define ENETC_MDIO_DRV_NAME ENETC_MDIO_DEV_NAME " driver" 13 14 DEFINE_STATIC_KEY_FALSE(enetc_has_err050089); 15 EXPORT_SYMBOL_GPL(enetc_has_err050089); 16 17 static void enetc_emdio_enable_err050089(struct pci_dev *pdev) 18 { 19 if (pdev->vendor == PCI_VENDOR_ID_FREESCALE && 20 pdev->device == ENETC_MDIO_DEV_ID) { 21 static_branch_inc(&enetc_has_err050089); 22 dev_info(&pdev->dev, "Enabled ERR050089 workaround\n"); 23 } 24 } 25 26 static void enetc_emdio_disable_err050089(struct pci_dev *pdev) 27 { 28 if (pdev->vendor == PCI_VENDOR_ID_FREESCALE && 29 pdev->device == ENETC_MDIO_DEV_ID) { 30 static_branch_dec(&enetc_has_err050089); 31 if (!static_key_enabled(&enetc_has_err050089.key)) 32 dev_info(&pdev->dev, "Disabled ERR050089 workaround\n"); 33 } 34 } 35 36 static int enetc_pci_mdio_probe(struct pci_dev *pdev, 37 const struct pci_device_id *ent) 38 { 39 struct enetc_mdio_priv *mdio_priv; 40 struct device *dev = &pdev->dev; 41 void __iomem *port_regs; 42 struct enetc_hw *hw; 43 struct mii_bus *bus; 44 int err; 45 46 port_regs = pci_iomap(pdev, 0, 0); 47 if (!port_regs) { 48 dev_err(dev, "iomap failed\n"); 49 err = -ENXIO; 50 goto err_ioremap; 51 } 52 53 hw = enetc_hw_alloc(dev, port_regs); 54 if (IS_ERR(hw)) { 55 err = PTR_ERR(hw); 56 goto err_hw_alloc; 57 } 58 59 bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); 60 if (!bus) { 61 err = -ENOMEM; 62 goto err_mdiobus_alloc; 63 } 64 65 bus->name = ENETC_MDIO_BUS_NAME; 66 bus->read = enetc_mdio_read_c22; 67 bus->write = enetc_mdio_write_c22; 68 bus->read_c45 = enetc_mdio_read_c45; 69 bus->write_c45 = enetc_mdio_write_c45; 70 bus->parent = dev; 71 mdio_priv = bus->priv; 72 mdio_priv->hw = hw; 73 mdio_priv->mdio_base = ENETC_EMDIO_BASE; 74 snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); 75 76 pcie_flr(pdev); 77 err = pci_enable_device_mem(pdev); 78 if (err) { 79 dev_err(dev, "device enable failed\n"); 80 goto err_pci_enable; 81 } 82 83 err = pci_request_region(pdev, 0, KBUILD_MODNAME); 84 if (err) { 85 dev_err(dev, "pci_request_region failed\n"); 86 goto err_pci_mem_reg; 87 } 88 89 enetc_emdio_enable_err050089(pdev); 90 91 err = of_mdiobus_register(bus, dev->of_node); 92 if (err) 93 goto err_mdiobus_reg; 94 95 pci_set_drvdata(pdev, bus); 96 97 return 0; 98 99 err_mdiobus_reg: 100 enetc_emdio_disable_err050089(pdev); 101 pci_release_region(pdev, 0); 102 err_pci_mem_reg: 103 pci_disable_device(pdev); 104 err_pci_enable: 105 err_mdiobus_alloc: 106 err_hw_alloc: 107 iounmap(port_regs); 108 err_ioremap: 109 return err; 110 } 111 112 static void enetc_pci_mdio_remove(struct pci_dev *pdev) 113 { 114 struct mii_bus *bus = pci_get_drvdata(pdev); 115 struct enetc_mdio_priv *mdio_priv; 116 117 mdiobus_unregister(bus); 118 119 enetc_emdio_disable_err050089(pdev); 120 121 mdio_priv = bus->priv; 122 iounmap(mdio_priv->hw->port); 123 pci_release_region(pdev, 0); 124 pci_disable_device(pdev); 125 } 126 127 static const struct pci_device_id enetc_pci_mdio_id_table[] = { 128 { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) }, 129 { PCI_DEVICE(NETC_EMDIO_VEN_ID, NETC_EMDIO_DEV_ID) }, 130 { 0, } /* End of table. */ 131 }; 132 MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table); 133 134 static struct pci_driver enetc_pci_mdio_driver = { 135 .name = KBUILD_MODNAME, 136 .id_table = enetc_pci_mdio_id_table, 137 .probe = enetc_pci_mdio_probe, 138 .remove = enetc_pci_mdio_remove, 139 }; 140 module_pci_driver(enetc_pci_mdio_driver); 141 142 MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME); 143 MODULE_LICENSE("Dual BSD/GPL"); 144