xref: /linux/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
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 NETC_EMDIO_VEN_ID	0x1131
8 #define NETC_EMDIO_DEV_ID	0xee00
9 #define ENETC_MDIO_DEV_ID	0xee01
10 #define ENETC_MDIO_DEV_NAME	"FSL PCIe IE Central MDIO"
11 #define ENETC_MDIO_BUS_NAME	ENETC_MDIO_DEV_NAME " Bus"
12 #define ENETC_MDIO_DRV_NAME	ENETC_MDIO_DEV_NAME " driver"
13 
14 DEFINE_STATIC_KEY_FALSE(enetc_has_err050089);
15 EXPORT_SYMBOL_GPL(enetc_has_err050089);
16 
17 static void enetc_emdio_enable_err050089(struct pci_dev *pdev)
18 {
19 	if (pdev->vendor == PCI_VENDOR_ID_FREESCALE &&
20 	    pdev->device == ENETC_MDIO_DEV_ID) {
21 		static_branch_inc(&enetc_has_err050089);
22 		dev_info(&pdev->dev, "Enabled ERR050089 workaround\n");
23 	}
24 }
25 
26 static void enetc_emdio_disable_err050089(struct pci_dev *pdev)
27 {
28 	if (pdev->vendor == PCI_VENDOR_ID_FREESCALE &&
29 	    pdev->device == ENETC_MDIO_DEV_ID) {
30 		static_branch_dec(&enetc_has_err050089);
31 		if (!static_key_enabled(&enetc_has_err050089.key))
32 			dev_info(&pdev->dev, "Disabled ERR050089 workaround\n");
33 	}
34 }
35 
36 static int enetc_pci_mdio_probe(struct pci_dev *pdev,
37 				const struct pci_device_id *ent)
38 {
39 	struct enetc_mdio_priv *mdio_priv;
40 	struct device *dev = &pdev->dev;
41 	void __iomem *port_regs;
42 	struct enetc_hw *hw;
43 	struct mii_bus *bus;
44 	int err;
45 
46 	port_regs = pci_iomap(pdev, 0, 0);
47 	if (!port_regs) {
48 		dev_err(dev, "iomap failed\n");
49 		err = -ENXIO;
50 		goto err_ioremap;
51 	}
52 
53 	hw = enetc_hw_alloc(dev, port_regs);
54 	if (IS_ERR(hw)) {
55 		err = PTR_ERR(hw);
56 		goto err_hw_alloc;
57 	}
58 
59 	bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
60 	if (!bus) {
61 		err = -ENOMEM;
62 		goto err_mdiobus_alloc;
63 	}
64 
65 	bus->name = ENETC_MDIO_BUS_NAME;
66 	bus->read = enetc_mdio_read_c22;
67 	bus->write = enetc_mdio_write_c22;
68 	bus->read_c45 = enetc_mdio_read_c45;
69 	bus->write_c45 = enetc_mdio_write_c45;
70 	bus->parent = dev;
71 	mdio_priv = bus->priv;
72 	mdio_priv->hw = hw;
73 	mdio_priv->mdio_base = ENETC_EMDIO_BASE;
74 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
75 
76 	pcie_flr(pdev);
77 	err = pci_enable_device_mem(pdev);
78 	if (err) {
79 		dev_err(dev, "device enable failed\n");
80 		goto err_pci_enable;
81 	}
82 
83 	err = pci_request_region(pdev, 0, KBUILD_MODNAME);
84 	if (err) {
85 		dev_err(dev, "pci_request_region failed\n");
86 		goto err_pci_mem_reg;
87 	}
88 
89 	enetc_emdio_enable_err050089(pdev);
90 
91 	err = of_mdiobus_register(bus, dev->of_node);
92 	if (err)
93 		goto err_mdiobus_reg;
94 
95 	pci_set_drvdata(pdev, bus);
96 
97 	return 0;
98 
99 err_mdiobus_reg:
100 	enetc_emdio_disable_err050089(pdev);
101 	pci_release_region(pdev, 0);
102 err_pci_mem_reg:
103 	pci_disable_device(pdev);
104 err_pci_enable:
105 err_mdiobus_alloc:
106 err_hw_alloc:
107 	iounmap(port_regs);
108 err_ioremap:
109 	return err;
110 }
111 
112 static void enetc_pci_mdio_remove(struct pci_dev *pdev)
113 {
114 	struct mii_bus *bus = pci_get_drvdata(pdev);
115 	struct enetc_mdio_priv *mdio_priv;
116 
117 	mdiobus_unregister(bus);
118 
119 	enetc_emdio_disable_err050089(pdev);
120 
121 	mdio_priv = bus->priv;
122 	iounmap(mdio_priv->hw->port);
123 	pci_release_region(pdev, 0);
124 	pci_disable_device(pdev);
125 }
126 
127 static const struct pci_device_id enetc_pci_mdio_id_table[] = {
128 	{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) },
129 	{ PCI_DEVICE(NETC_EMDIO_VEN_ID, NETC_EMDIO_DEV_ID) },
130 	{ 0, } /* End of table. */
131 };
132 MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table);
133 
134 static struct pci_driver enetc_pci_mdio_driver = {
135 	.name = KBUILD_MODNAME,
136 	.id_table = enetc_pci_mdio_id_table,
137 	.probe = enetc_pci_mdio_probe,
138 	.remove = enetc_pci_mdio_remove,
139 };
140 module_pci_driver(enetc_pci_mdio_driver);
141 
142 MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME);
143 MODULE_LICENSE("Dual BSD/GPL");
144