cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mdio-thunder.c (3483B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2009-2016 Cavium, Inc.
      4 */
      5
      6#include <linux/acpi.h>
      7#include <linux/gfp.h>
      8#include <linux/io.h>
      9#include <linux/module.h>
     10#include <linux/of_address.h>
     11#include <linux/of_mdio.h>
     12#include <linux/pci.h>
     13#include <linux/phy.h>
     14
     15#include "mdio-cavium.h"
     16
     17struct thunder_mdiobus_nexus {
     18	void __iomem *bar0;
     19	struct cavium_mdiobus *buses[4];
     20};
     21
     22static int thunder_mdiobus_pci_probe(struct pci_dev *pdev,
     23				     const struct pci_device_id *ent)
     24{
     25	struct device_node *node;
     26	struct fwnode_handle *fwn;
     27	struct thunder_mdiobus_nexus *nexus;
     28	int err;
     29	int i;
     30
     31	nexus = devm_kzalloc(&pdev->dev, sizeof(*nexus), GFP_KERNEL);
     32	if (!nexus)
     33		return -ENOMEM;
     34
     35	pci_set_drvdata(pdev, nexus);
     36
     37	err = pcim_enable_device(pdev);
     38	if (err) {
     39		dev_err(&pdev->dev, "Failed to enable PCI device\n");
     40		pci_set_drvdata(pdev, NULL);
     41		return err;
     42	}
     43
     44	err = pci_request_regions(pdev, KBUILD_MODNAME);
     45	if (err) {
     46		dev_err(&pdev->dev, "pci_request_regions failed\n");
     47		goto err_disable_device;
     48	}
     49
     50	nexus->bar0 = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0));
     51	if (!nexus->bar0) {
     52		err = -ENOMEM;
     53		goto err_release_regions;
     54	}
     55
     56	i = 0;
     57	device_for_each_child_node(&pdev->dev, fwn) {
     58		struct resource r;
     59		struct mii_bus *mii_bus;
     60		struct cavium_mdiobus *bus;
     61		union cvmx_smix_en smi_en;
     62
     63		/* If it is not an OF node we cannot handle it yet, so
     64		 * exit the loop.
     65		 */
     66		node = to_of_node(fwn);
     67		if (!node)
     68			break;
     69
     70		err = of_address_to_resource(node, 0, &r);
     71		if (err) {
     72			dev_err(&pdev->dev,
     73				"Couldn't translate address for \"%pOFn\"\n",
     74				node);
     75			break;
     76		}
     77
     78		mii_bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*bus));
     79		if (!mii_bus)
     80			break;
     81		bus = mii_bus->priv;
     82		bus->mii_bus = mii_bus;
     83
     84		nexus->buses[i] = bus;
     85		i++;
     86
     87		bus->register_base = nexus->bar0 +
     88			r.start - pci_resource_start(pdev, 0);
     89
     90		smi_en.u64 = 0;
     91		smi_en.s.en = 1;
     92		oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
     93		bus->mii_bus->name = KBUILD_MODNAME;
     94		snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", r.start);
     95		bus->mii_bus->parent = &pdev->dev;
     96		bus->mii_bus->read = cavium_mdiobus_read;
     97		bus->mii_bus->write = cavium_mdiobus_write;
     98
     99		err = of_mdiobus_register(bus->mii_bus, node);
    100		if (err)
    101			dev_err(&pdev->dev, "of_mdiobus_register failed\n");
    102
    103		dev_info(&pdev->dev, "Added bus at %llx\n", r.start);
    104		if (i >= ARRAY_SIZE(nexus->buses))
    105			break;
    106	}
    107	return 0;
    108
    109err_release_regions:
    110	pci_release_regions(pdev);
    111
    112err_disable_device:
    113	pci_set_drvdata(pdev, NULL);
    114	return err;
    115}
    116
    117static void thunder_mdiobus_pci_remove(struct pci_dev *pdev)
    118{
    119	int i;
    120	struct thunder_mdiobus_nexus *nexus = pci_get_drvdata(pdev);
    121
    122	for (i = 0; i < ARRAY_SIZE(nexus->buses); i++) {
    123		struct cavium_mdiobus *bus = nexus->buses[i];
    124
    125		if (!bus)
    126			continue;
    127
    128		mdiobus_unregister(bus->mii_bus);
    129		oct_mdio_writeq(0, bus->register_base + SMI_EN);
    130	}
    131	pci_release_regions(pdev);
    132	pci_set_drvdata(pdev, NULL);
    133}
    134
    135static const struct pci_device_id thunder_mdiobus_id_table[] = {
    136	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa02b) },
    137	{ 0, } /* End of table. */
    138};
    139MODULE_DEVICE_TABLE(pci, thunder_mdiobus_id_table);
    140
    141static struct pci_driver thunder_mdiobus_driver = {
    142	.name = KBUILD_MODNAME,
    143	.id_table = thunder_mdiobus_id_table,
    144	.probe = thunder_mdiobus_pci_probe,
    145	.remove = thunder_mdiobus_pci_remove,
    146};
    147
    148module_pci_driver(thunder_mdiobus_driver);
    149
    150MODULE_DESCRIPTION("Cavium ThunderX MDIO bus driver");
    151MODULE_LICENSE("GPL v2");