Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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