1
2
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
11static 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
64err_mdiobus_reg:
65 iounmap(mdio_priv->hw->port);
66err_ioremap:
67 pci_release_mem_regions(pdev);
68err_pci_mem_reg:
69 pci_disable_device(pdev);
70
71 return err;
72}
73
74static 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
86static const struct pci_device_id enetc_pci_mdio_id_table[] = {
87 { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) },
88 { 0, }
89};
90MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table);
91
92static 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};
98module_pci_driver(enetc_pci_mdio_driver);
99
100MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME);
101MODULE_LICENSE("Dual BSD/GPL");
102