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
enetc_pci_mdio_probe(struct pci_dev * pdev,const struct pci_device_id * ent)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;
42*80e87442SAndrew Lunn bus->read = enetc_mdio_read_c22;
43*80e87442SAndrew Lunn bus->write = enetc_mdio_write_c22;
44*80e87442SAndrew Lunn bus->read_c45 = enetc_mdio_read_c45;
45*80e87442SAndrew Lunn bus->write_c45 = enetc_mdio_write_c45;
46231ece36SClaudiu Manoil bus->parent = dev;
47231ece36SClaudiu Manoil mdio_priv = bus->priv;
48231ece36SClaudiu Manoil mdio_priv->hw = hw;
496517798dSClaudiu Manoil mdio_priv->mdio_base = ENETC_EMDIO_BASE;
50231ece36SClaudiu Manoil snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
51231ece36SClaudiu Manoil
52231ece36SClaudiu Manoil pcie_flr(pdev);
53231ece36SClaudiu Manoil err = pci_enable_device_mem(pdev);
54231ece36SClaudiu Manoil if (err) {
55231ece36SClaudiu Manoil dev_err(dev, "device enable failed\n");
566517798dSClaudiu Manoil goto err_pci_enable;
57231ece36SClaudiu Manoil }
58231ece36SClaudiu Manoil
59231ece36SClaudiu Manoil err = pci_request_region(pdev, 0, KBUILD_MODNAME);
60231ece36SClaudiu Manoil if (err) {
61231ece36SClaudiu Manoil dev_err(dev, "pci_request_region failed\n");
62231ece36SClaudiu Manoil goto err_pci_mem_reg;
63231ece36SClaudiu Manoil }
64231ece36SClaudiu Manoil
65231ece36SClaudiu Manoil err = of_mdiobus_register(bus, dev->of_node);
66231ece36SClaudiu Manoil if (err)
67231ece36SClaudiu Manoil goto err_mdiobus_reg;
68231ece36SClaudiu Manoil
69231ece36SClaudiu Manoil pci_set_drvdata(pdev, bus);
70231ece36SClaudiu Manoil
71231ece36SClaudiu Manoil return 0;
72231ece36SClaudiu Manoil
73231ece36SClaudiu Manoil err_mdiobus_reg:
7418eeb4deSChristophe JAILLET pci_release_region(pdev, 0);
75231ece36SClaudiu Manoil err_pci_mem_reg:
76231ece36SClaudiu Manoil pci_disable_device(pdev);
776517798dSClaudiu Manoil err_pci_enable:
786517798dSClaudiu Manoil err_mdiobus_alloc:
796517798dSClaudiu Manoil err_hw_alloc:
80d975cb7eSDejin Zheng iounmap(port_regs);
816517798dSClaudiu Manoil err_ioremap:
82231ece36SClaudiu Manoil return err;
83231ece36SClaudiu Manoil }
84231ece36SClaudiu Manoil
enetc_pci_mdio_remove(struct pci_dev * pdev)85231ece36SClaudiu Manoil static void enetc_pci_mdio_remove(struct pci_dev *pdev)
86231ece36SClaudiu Manoil {
87231ece36SClaudiu Manoil struct mii_bus *bus = pci_get_drvdata(pdev);
88231ece36SClaudiu Manoil struct enetc_mdio_priv *mdio_priv;
89231ece36SClaudiu Manoil
90231ece36SClaudiu Manoil mdiobus_unregister(bus);
91231ece36SClaudiu Manoil mdio_priv = bus->priv;
92231ece36SClaudiu Manoil iounmap(mdio_priv->hw->port);
9318eeb4deSChristophe JAILLET pci_release_region(pdev, 0);
94231ece36SClaudiu Manoil pci_disable_device(pdev);
95231ece36SClaudiu Manoil }
96231ece36SClaudiu Manoil
97231ece36SClaudiu Manoil static const struct pci_device_id enetc_pci_mdio_id_table[] = {
98231ece36SClaudiu Manoil { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) },
99231ece36SClaudiu Manoil { 0, } /* End of table. */
100231ece36SClaudiu Manoil };
101231ece36SClaudiu Manoil MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table);
102231ece36SClaudiu Manoil
103231ece36SClaudiu Manoil static struct pci_driver enetc_pci_mdio_driver = {
104231ece36SClaudiu Manoil .name = KBUILD_MODNAME,
105231ece36SClaudiu Manoil .id_table = enetc_pci_mdio_id_table,
106231ece36SClaudiu Manoil .probe = enetc_pci_mdio_probe,
107231ece36SClaudiu Manoil .remove = enetc_pci_mdio_remove,
108231ece36SClaudiu Manoil };
109231ece36SClaudiu Manoil module_pci_driver(enetc_pci_mdio_driver);
110231ece36SClaudiu Manoil
111231ece36SClaudiu Manoil MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME);
112231ece36SClaudiu Manoil MODULE_LICENSE("Dual BSD/GPL");
113