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 
12 static 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_c22;
43 	bus->write = enetc_mdio_write_c22;
44 	bus->read_c45 = enetc_mdio_read_c45;
45 	bus->write_c45 = enetc_mdio_write_c45;
46 	bus->parent = dev;
47 	mdio_priv = bus->priv;
48 	mdio_priv->hw = hw;
49 	mdio_priv->mdio_base = ENETC_EMDIO_BASE;
50 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
51 
52 	pcie_flr(pdev);
53 	err = pci_enable_device_mem(pdev);
54 	if (err) {
55 		dev_err(dev, "device enable failed\n");
56 		goto err_pci_enable;
57 	}
58 
59 	err = pci_request_region(pdev, 0, KBUILD_MODNAME);
60 	if (err) {
61 		dev_err(dev, "pci_request_region failed\n");
62 		goto err_pci_mem_reg;
63 	}
64 
65 	err = of_mdiobus_register(bus, dev->of_node);
66 	if (err)
67 		goto err_mdiobus_reg;
68 
69 	pci_set_drvdata(pdev, bus);
70 
71 	return 0;
72 
73 err_mdiobus_reg:
74 	pci_release_region(pdev, 0);
75 err_pci_mem_reg:
76 	pci_disable_device(pdev);
77 err_pci_enable:
78 err_mdiobus_alloc:
79 err_hw_alloc:
80 	iounmap(port_regs);
81 err_ioremap:
82 	return err;
83 }
84 
85 static void enetc_pci_mdio_remove(struct pci_dev *pdev)
86 {
87 	struct mii_bus *bus = pci_get_drvdata(pdev);
88 	struct enetc_mdio_priv *mdio_priv;
89 
90 	mdiobus_unregister(bus);
91 	mdio_priv = bus->priv;
92 	iounmap(mdio_priv->hw->port);
93 	pci_release_region(pdev, 0);
94 	pci_disable_device(pdev);
95 }
96 
97 static const struct pci_device_id enetc_pci_mdio_id_table[] = {
98 	{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) },
99 	{ 0, } /* End of table. */
100 };
101 MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table);
102 
103 static struct pci_driver enetc_pci_mdio_driver = {
104 	.name = KBUILD_MODNAME,
105 	.id_table = enetc_pci_mdio_id_table,
106 	.probe = enetc_pci_mdio_probe,
107 	.remove = enetc_pci_mdio_remove,
108 };
109 module_pci_driver(enetc_pci_mdio_driver);
110 
111 MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME);
112 MODULE_LICENSE("Dual BSD/GPL");
113