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:
commit
f887e24e05
|
@ -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>;
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue