1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2015 Broadcom Corporation |
4 | * Copyright (C) 2015 Hauke Mehrtens <hauke@hauke-m.de> |
5 | */ |
6 | |
7 | #include <linux/kernel.h> |
8 | #include <linux/pci.h> |
9 | #include <linux/module.h> |
10 | #include <linux/slab.h> |
11 | #include <linux/phy/phy.h> |
12 | #include <linux/bcma/bcma.h> |
13 | #include <linux/ioport.h> |
14 | |
15 | #include "pcie-iproc.h" |
16 | |
17 | |
18 | /* NS: CLASS field is R/O, and set to wrong 0x200 value */ |
19 | static void bcma_pcie2_fixup_class(struct pci_dev *dev) |
20 | { |
21 | dev->class = PCI_CLASS_BRIDGE_PCI_NORMAL; |
22 | } |
23 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class); |
24 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class); |
25 | |
26 | static int iproc_bcma_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
27 | { |
28 | struct iproc_pcie *pcie = dev->sysdata; |
29 | struct bcma_device *bdev = container_of(pcie->dev, struct bcma_device, dev); |
30 | |
31 | return bcma_core_irq(core: bdev, num: 5); |
32 | } |
33 | |
34 | static int iproc_bcma_pcie_probe(struct bcma_device *bdev) |
35 | { |
36 | struct device *dev = &bdev->dev; |
37 | struct iproc_pcie *pcie; |
38 | struct pci_host_bridge *bridge; |
39 | int ret; |
40 | |
41 | bridge = devm_pci_alloc_host_bridge(dev, priv: sizeof(*pcie)); |
42 | if (!bridge) |
43 | return -ENOMEM; |
44 | |
45 | pcie = pci_host_bridge_priv(bridge); |
46 | |
47 | pcie->dev = dev; |
48 | |
49 | pcie->type = IPROC_PCIE_PAXB_BCMA; |
50 | pcie->base = bdev->io_addr; |
51 | if (!pcie->base) { |
52 | dev_err(dev, "no controller registers\n" ); |
53 | return -ENOMEM; |
54 | } |
55 | |
56 | pcie->base_addr = bdev->addr; |
57 | |
58 | pcie->mem.start = bdev->addr_s[0]; |
59 | pcie->mem.end = bdev->addr_s[0] + SZ_128M - 1; |
60 | pcie->mem.name = "PCIe MEM space" ; |
61 | pcie->mem.flags = IORESOURCE_MEM; |
62 | pci_add_resource(resources: &bridge->windows, res: &pcie->mem); |
63 | ret = devm_request_pci_bus_resources(dev, resources: &bridge->windows); |
64 | if (ret) |
65 | return ret; |
66 | |
67 | pcie->map_irq = iproc_bcma_pcie_map_irq; |
68 | |
69 | bcma_set_drvdata(core: bdev, drvdata: pcie); |
70 | |
71 | return iproc_pcie_setup(pcie, res: &bridge->windows); |
72 | } |
73 | |
74 | static void iproc_bcma_pcie_remove(struct bcma_device *bdev) |
75 | { |
76 | struct iproc_pcie *pcie = bcma_get_drvdata(core: bdev); |
77 | |
78 | iproc_pcie_remove(pcie); |
79 | } |
80 | |
81 | static const struct bcma_device_id iproc_bcma_pcie_table[] = { |
82 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_PCIEG2, BCMA_ANY_REV, BCMA_ANY_CLASS), |
83 | {}, |
84 | }; |
85 | MODULE_DEVICE_TABLE(bcma, iproc_bcma_pcie_table); |
86 | |
87 | static struct bcma_driver iproc_bcma_pcie_driver = { |
88 | .name = KBUILD_MODNAME, |
89 | .id_table = iproc_bcma_pcie_table, |
90 | .probe = iproc_bcma_pcie_probe, |
91 | .remove = iproc_bcma_pcie_remove, |
92 | }; |
93 | module_bcma_driver(iproc_bcma_pcie_driver); |
94 | |
95 | MODULE_AUTHOR("Hauke Mehrtens" ); |
96 | MODULE_DESCRIPTION("Broadcom iProc PCIe BCMA driver" ); |
97 | MODULE_LICENSE("GPL v2" ); |
98 | |