Linux Audio

Check our new training course

Linux BSP development engineering services

Need help to port Linux and bootloaders to your hardware?
Loading...
Note: File does not exist in v4.17.
  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
 14DEFINE_STATIC_KEY_FALSE(enetc_has_err050089);
 15EXPORT_SYMBOL_GPL(enetc_has_err050089);
 16
 17static 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
 26static 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
 36static 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
 99err_mdiobus_reg:
100	enetc_emdio_disable_err050089(pdev);
101	pci_release_region(pdev, 0);
102err_pci_mem_reg:
103	pci_disable_device(pdev);
104err_pci_enable:
105err_mdiobus_alloc:
106err_hw_alloc:
107	iounmap(port_regs);
108err_ioremap:
109	return err;
110}
111
112static 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
127static 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};
132MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table);
133
134static 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};
140module_pci_driver(enetc_pci_mdio_driver);
141
142MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME);
143MODULE_LICENSE("Dual BSD/GPL");