linux/drivers/pci/host/pcie-iproc-bcma.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 Broadcom Corporation
   3 * Copyright (C) 2015 Hauke Mehrtens <hauke@hauke-m.de>
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public License as
   7 * published by the Free Software Foundation version 2.
   8 *
   9 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  10 * kind, whether express or implied; without even the implied warranty
  11 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 */
  14
  15#include <linux/kernel.h>
  16#include <linux/pci.h>
  17#include <linux/module.h>
  18#include <linux/slab.h>
  19#include <linux/phy/phy.h>
  20#include <linux/bcma/bcma.h>
  21#include <linux/ioport.h>
  22
  23#include "pcie-iproc.h"
  24
  25
  26/* NS: CLASS field is R/O, and set to wrong 0x200 value */
  27static void bcma_pcie2_fixup_class(struct pci_dev *dev)
  28{
  29        dev->class = PCI_CLASS_BRIDGE_PCI << 8;
  30}
  31DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class);
  32DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class);
  33
  34static int iproc_pcie_bcma_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
  35{
  36        struct pci_sys_data *sys = dev->sysdata;
  37        struct iproc_pcie *pcie = sys->private_data;
  38        struct bcma_device *bdev = container_of(pcie->dev, struct bcma_device, dev);
  39
  40        return bcma_core_irq(bdev, 5);
  41}
  42
  43static int iproc_pcie_bcma_probe(struct bcma_device *bdev)
  44{
  45        struct device *dev = &bdev->dev;
  46        struct iproc_pcie *pcie;
  47        LIST_HEAD(resources);
  48        int ret;
  49
  50        pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
  51        if (!pcie)
  52                return -ENOMEM;
  53
  54        pcie->dev = dev;
  55
  56        pcie->type = IPROC_PCIE_PAXB_BCMA;
  57        pcie->base = bdev->io_addr;
  58        if (!pcie->base) {
  59                dev_err(dev, "no controller registers\n");
  60                return -ENOMEM;
  61        }
  62
  63        pcie->base_addr = bdev->addr;
  64
  65        pcie->mem.start = bdev->addr_s[0];
  66        pcie->mem.end = bdev->addr_s[0] + SZ_128M - 1;
  67        pcie->mem.name = "PCIe MEM space";
  68        pcie->mem.flags = IORESOURCE_MEM;
  69        pci_add_resource(&resources, &pcie->mem);
  70
  71        pcie->map_irq = iproc_pcie_bcma_map_irq;
  72
  73        ret = iproc_pcie_setup(pcie, &resources);
  74        if (ret) {
  75                dev_err(dev, "PCIe controller setup failed\n");
  76                pci_free_resource_list(&resources);
  77                return ret;
  78        }
  79
  80        bcma_set_drvdata(bdev, pcie);
  81        return 0;
  82}
  83
  84static void iproc_pcie_bcma_remove(struct bcma_device *bdev)
  85{
  86        struct iproc_pcie *pcie = bcma_get_drvdata(bdev);
  87
  88        iproc_pcie_remove(pcie);
  89}
  90
  91static const struct bcma_device_id iproc_pcie_bcma_table[] = {
  92        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_PCIEG2, BCMA_ANY_REV, BCMA_ANY_CLASS),
  93        {},
  94};
  95MODULE_DEVICE_TABLE(bcma, iproc_pcie_bcma_table);
  96
  97static struct bcma_driver iproc_pcie_bcma_driver = {
  98        .name           = KBUILD_MODNAME,
  99        .id_table       = iproc_pcie_bcma_table,
 100        .probe          = iproc_pcie_bcma_probe,
 101        .remove         = iproc_pcie_bcma_remove,
 102};
 103
 104static int __init iproc_pcie_bcma_init(void)
 105{
 106        return bcma_driver_register(&iproc_pcie_bcma_driver);
 107}
 108module_init(iproc_pcie_bcma_init);
 109
 110static void __exit iproc_pcie_bcma_exit(void)
 111{
 112        bcma_driver_unregister(&iproc_pcie_bcma_driver);
 113}
 114module_exit(iproc_pcie_bcma_exit);
 115
 116MODULE_AUTHOR("Hauke Mehrtens");
 117MODULE_DESCRIPTION("Broadcom iProc PCIe BCMA driver");
 118MODULE_LICENSE("GPL v2");
 119