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
12static 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(dev: pdev, bar: 0, max: 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(ptr: hw)) {
31 err = PTR_ERR(ptr: hw);
32 goto err_hw_alloc;
33 }
34
35 bus = devm_mdiobus_alloc_size(dev, sizeof_priv: 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(buf: bus->id, MII_BUS_ID_SIZE, fmt: "%s", dev_name(dev));
51
52 pcie_flr(dev: pdev);
53 err = pci_enable_device_mem(dev: 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(mdio: bus, np: dev->of_node);
66 if (err)
67 goto err_mdiobus_reg;
68
69 pci_set_drvdata(pdev, data: bus);
70
71 return 0;
72
73err_mdiobus_reg:
74 pci_release_region(pdev, 0);
75err_pci_mem_reg:
76 pci_disable_device(dev: pdev);
77err_pci_enable:
78err_mdiobus_alloc:
79err_hw_alloc:
80 iounmap(addr: port_regs);
81err_ioremap:
82 return err;
83}
84
85static 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(addr: mdio_priv->hw->port);
93 pci_release_region(pdev, 0);
94 pci_disable_device(dev: pdev);
95}
96
97static 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};
101MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table);
102
103static 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};
109module_pci_driver(enetc_pci_mdio_driver);
110
111MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME);
112MODULE_LICENSE("Dual BSD/GPL");
113

source code of linux/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c