Merge branch 'pci/host-iproc' into next

* pci/host-iproc:
  PCI: iproc: Skip check for legacy IRQ on PAXC buses
  PCI: iproc: Fix incorrect MSI address alignment
  PCI: iproc: Add support for the next-gen PAXB controller
  PCI: iproc: Add PAXBv2 binding info
  PCI: iproc: Add inbound DMA mapping support
  PCI: iproc: Add optional dma-ranges
  PCI: iproc: Make outbound mapping code more generic
  PCI: iproc: Remove redundant outbound properties
  PCI: iproc: Add PAXC v2 support
  PCI: iproc: Add PAXCv2 related binding
  PCI: iproc: Fix exception with multi-function devices
  PCI: iproc: Add BCMA type
  PCI: iproc: Do not reset PAXC when initializing the driver
  PCI: iproc: Improve core register population
This commit is contained in:
Bjorn Helgaas 2016-12-12 11:25:08 -06:00
commit f887e24e05
6 changed files with 929 additions and 136 deletions

View File

@ -1,10 +1,17 @@
* Broadcom iProc PCIe controller with the platform bus interface * Broadcom iProc PCIe controller with the platform bus interface
Required properties: Required properties:
- compatible: Must be "brcm,iproc-pcie" for PAXB, or "brcm,iproc-pcie-paxc" - compatible:
for PAXC. PAXB-based root complex is used for external endpoint devices. "brcm,iproc-pcie" for the first generation of PAXB based controller,
PAXC-based root complex is connected to emulated endpoint devices used in SoCs including NSP, Cygnus, NS2, and Pegasus
internal to the ASIC "brcm,iproc-pcie-paxb-v2" for the second generation of PAXB-based
controllers, used in Stingray
"brcm,iproc-pcie-paxc" for the first generation of PAXC based
controller, used in NS2
"brcm,iproc-pcie-paxc-v2" for the second generation of PAXC based
controller, used in Stingray
PAXB-based root complex is used for external endpoint devices. PAXC-based
root complex is connected to emulated endpoint devices internal to the ASIC
- reg: base address and length of the PCIe controller I/O register space - reg: base address and length of the PCIe controller I/O register space
- #interrupt-cells: set to <1> - #interrupt-cells: set to <1>
- interrupt-map-mask and interrupt-map, standard PCI properties to define the - interrupt-map-mask and interrupt-map, standard PCI properties to define the
@ -19,6 +26,10 @@ Required properties:
Optional properties: Optional properties:
- phys: phandle of the PCIe PHY device - phys: phandle of the PCIe PHY device
- phy-names: must be "pcie-phy" - phy-names: must be "pcie-phy"
- dma-coherent: present if DMA operations are coherent
- dma-ranges: Some PAXB-based root complexes do not have inbound mapping done
by the ASIC after power on reset. In this case, SW is required to configure
the mapping, based on inbound memory regions specified by this property.
- brcm,pcie-ob: Some iProc SoCs do not have the outbound address mapping done - brcm,pcie-ob: Some iProc SoCs do not have the outbound address mapping done
by the ASIC after power on reset. In this case, SW needs to configure it by the ASIC after power on reset. In this case, SW needs to configure it
@ -29,11 +40,6 @@ effective:
Required: Required:
- brcm,pcie-ob-axi-offset: The offset from the AXI address to the internal - brcm,pcie-ob-axi-offset: The offset from the AXI address to the internal
address used by the iProc PCIe core (not the PCIe address) address used by the iProc PCIe core (not the PCIe address)
- brcm,pcie-ob-window-size: The outbound address mapping window size (in MB)
Optional:
- brcm,pcie-ob-oarr-size: Some iProc SoCs need the OARR size bit to be set to
increase the outbound window size
MSI support (optional): MSI support (optional):
@ -41,10 +47,19 @@ For older platforms without MSI integrated in the GIC, iProc PCIe core provides
an event queue based MSI support. The iProc MSI uses host memories to store an event queue based MSI support. The iProc MSI uses host memories to store
MSI posted writes in the event queues MSI posted writes in the event queues
- msi-parent: Link to the device node of the MSI controller. On newer iProc On newer iProc platforms, gicv2m or gicv3-its based MSI support should be used
platforms, the MSI controller may be gicv2m or gicv3-its. On older iProc
platforms without MSI support in its interrupt controller, one may use the - msi-map: Maps a Requester ID to an MSI controller and associated MSI
event queue based MSI support integrated within the iProc PCIe core. sideband data
- msi-parent: Link to the device node of the MSI controller, used when no MSI
sideband data is passed between the iProc PCIe controller and the MSI
controller
Refer to the following binding documents for more detailed description on
the use of 'msi-map' and 'msi-parent':
Documentation/devicetree/bindings/pci/pci-msi.txt
Documentation/devicetree/bindings/interrupt-controller/msi.txt
When the iProc event queue based MSI is used, one needs to define the When the iProc event queue based MSI is used, one needs to define the
following properties in the MSI device node: following properties in the MSI device node:
@ -80,9 +95,7 @@ Example:
phy-names = "pcie-phy"; phy-names = "pcie-phy";
brcm,pcie-ob; brcm,pcie-ob;
brcm,pcie-ob-oarr-size;
brcm,pcie-ob-axi-offset = <0x00000000>; brcm,pcie-ob-axi-offset = <0x00000000>;
brcm,pcie-ob-window-size = <256>;
msi-parent = <&msi0>; msi-parent = <&msi0>;

View File

@ -54,6 +54,7 @@ static int iproc_pcie_bcma_probe(struct bcma_device *bdev)
pcie->dev = dev; pcie->dev = dev;
pcie->type = IPROC_PCIE_PAXB_BCMA;
pcie->base = bdev->io_addr; pcie->base = bdev->io_addr;
if (!pcie->base) { if (!pcie->base) {
dev_err(dev, "no controller registers\n"); dev_err(dev, "no controller registers\n");

View File

@ -563,6 +563,7 @@ int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node)
} }
switch (pcie->type) { switch (pcie->type) {
case IPROC_PCIE_PAXB_BCMA:
case IPROC_PCIE_PAXB: case IPROC_PCIE_PAXB:
msi->reg_offsets = iproc_msi_reg_paxb; msi->reg_offsets = iproc_msi_reg_paxb;
msi->nr_eq_region = 1; msi->nr_eq_region = 1;

View File

@ -30,9 +30,15 @@ static const struct of_device_id iproc_pcie_of_match_table[] = {
{ {
.compatible = "brcm,iproc-pcie", .compatible = "brcm,iproc-pcie",
.data = (int *)IPROC_PCIE_PAXB, .data = (int *)IPROC_PCIE_PAXB,
}, {
.compatible = "brcm,iproc-pcie-paxb-v2",
.data = (int *)IPROC_PCIE_PAXB_V2,
}, { }, {
.compatible = "brcm,iproc-pcie-paxc", .compatible = "brcm,iproc-pcie-paxc",
.data = (int *)IPROC_PCIE_PAXC, .data = (int *)IPROC_PCIE_PAXC,
}, {
.compatible = "brcm,iproc-pcie-paxc-v2",
.data = (int *)IPROC_PCIE_PAXC_V2,
}, },
{ /* sentinel */ } { /* sentinel */ }
}; };
@ -84,19 +90,6 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
return ret; return ret;
} }
pcie->ob.axi_offset = val; pcie->ob.axi_offset = val;
ret = of_property_read_u32(np, "brcm,pcie-ob-window-size",
&val);
if (ret) {
dev_err(dev,
"missing brcm,pcie-ob-window-size property\n");
return ret;
}
pcie->ob.window_size = (resource_size_t)val * SZ_1M;
if (of_property_read_bool(np, "brcm,pcie-ob-oarr-size"))
pcie->ob.set_oarr_size = true;
pcie->need_ob_cfg = true; pcie->need_ob_cfg = true;
} }
@ -115,7 +108,14 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
return ret; return ret;
} }
/* PAXC doesn't support legacy IRQs, skip mapping */
switch (pcie->type) {
case IPROC_PCIE_PAXC:
case IPROC_PCIE_PAXC_V2:
break;
default:
pcie->map_irq = of_irq_parse_and_map_pci; pcie->map_irq = of_irq_parse_and_map_pci;
}
ret = iproc_pcie_setup(pcie, &res); ret = iproc_pcie_setup(pcie, &res);
if (ret) if (ret)

File diff suppressed because it is too large Load Diff

View File

@ -24,23 +24,34 @@
* endpoint devices. * endpoint devices.
*/ */
enum iproc_pcie_type { enum iproc_pcie_type {
IPROC_PCIE_PAXB = 0, IPROC_PCIE_PAXB_BCMA = 0,
IPROC_PCIE_PAXB,
IPROC_PCIE_PAXB_V2,
IPROC_PCIE_PAXC, IPROC_PCIE_PAXC,
IPROC_PCIE_PAXC_V2,
}; };
/** /**
* iProc PCIe outbound mapping * iProc PCIe outbound mapping
* @set_oarr_size: indicates the OARR size bit needs to be set
* @axi_offset: offset from the AXI address to the internal address used by * @axi_offset: offset from the AXI address to the internal address used by
* the iProc PCIe core * the iProc PCIe core
* @window_size: outbound window size * @nr_windows: total number of supported outbound mapping windows
*/ */
struct iproc_pcie_ob { struct iproc_pcie_ob {
bool set_oarr_size;
resource_size_t axi_offset; resource_size_t axi_offset;
resource_size_t window_size; unsigned int nr_windows;
}; };
/**
* iProc PCIe inbound mapping
* @nr_regions: total number of supported inbound mapping regions
*/
struct iproc_pcie_ib {
unsigned int nr_regions;
};
struct iproc_pcie_ob_map;
struct iproc_pcie_ib_map;
struct iproc_msi; struct iproc_msi;
/** /**
@ -55,14 +66,25 @@ struct iproc_msi;
* @root_bus: pointer to root bus * @root_bus: pointer to root bus
* @phy: optional PHY device that controls the Serdes * @phy: optional PHY device that controls the Serdes
* @map_irq: function callback to map interrupts * @map_irq: function callback to map interrupts
* @ep_is_internal: indicates an internal emulated endpoint device is connected
* @has_apb_err_disable: indicates the controller can be configured to prevent
* unsupported request from being forwarded as an APB bus error
*
* @need_ob_cfg: indicates SW needs to configure the outbound mapping window * @need_ob_cfg: indicates SW needs to configure the outbound mapping window
* @ob: outbound mapping parameters * @ob: outbound mapping related parameters
* @ob_map: outbound mapping related parameters specific to the controller
*
* @ib: inbound mapping related parameters
* @ib_map: outbound mapping region related parameters
*
* @need_msi_steer: indicates additional configuration of the iProc PCIe
* controller is required to steer MSI writes to external interrupt controller
* @msi: MSI data * @msi: MSI data
*/ */
struct iproc_pcie { struct iproc_pcie {
struct device *dev; struct device *dev;
enum iproc_pcie_type type; enum iproc_pcie_type type;
const u16 *reg_offsets; u16 *reg_offsets;
void __iomem *base; void __iomem *base;
phys_addr_t base_addr; phys_addr_t base_addr;
#ifdef CONFIG_ARM #ifdef CONFIG_ARM
@ -71,8 +93,17 @@ struct iproc_pcie {
struct pci_bus *root_bus; struct pci_bus *root_bus;
struct phy *phy; struct phy *phy;
int (*map_irq)(const struct pci_dev *, u8, u8); int (*map_irq)(const struct pci_dev *, u8, u8);
bool ep_is_internal;
bool has_apb_err_disable;
bool need_ob_cfg; bool need_ob_cfg;
struct iproc_pcie_ob ob; struct iproc_pcie_ob ob;
const struct iproc_pcie_ob_map *ob_map;
struct iproc_pcie_ib ib;
const struct iproc_pcie_ib_map *ib_map;
bool need_msi_steer;
struct iproc_msi *msi; struct iproc_msi *msi;
}; };