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