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