[U-Boot] [PATCH 0/7 v2] support mapping PCI device ids to stream ids for MSIs

From: Stuart Yoder stuart.yoder@nxp.com
A binding for PCI nodes has been finalized specifying how PCI device IDs can be mapped to MSI specifiers. See Documentation/devicetree/bindings/pci/pci-msi.txt in the kernel.
For ls2080a and similar Layerscape SoCs, the MSI specifier is the stream id. A programmable table (LUT) in the PCI controller defines the hardware mapping of PCI requester IDs to stream IDs.
This patch series implements support for this mapping.
Patch 1 removes the obsolete available-stream-id support. Patch 2 updates stream ID partitioning info to be current Patch 3 updates pci.h so pci_get_hose_head() is available Patch 4 implements support for programming the LUT Patch 5 implements a simple stream ID allocator for PCI Patch 6 implements a function to set msi-map properties Patch 7 implements a function to iterate over all PCI buses and set up a LUT entry and msi-map for all discovered devices
This patch series enables MSIs on ls2080a on v4.5-rc5 and later kernels. The obsolete support removed was unused in any upstream kernels.
-v2 changes -in patch 7 removed skip of the host bridge when scanning the bus
Stuart Yoder (7): armv8: ls2080a: remove obsolete stream ID partitioning support armv8: ls2080a: update stream ID partitioning info pci: make pci_get_hose_head() available to external users pci/layerscape: add support for LUT pci/layerscape: add stream ID allocator pci/layerscape: fdt: function to set msi-map entries pci/layerscape: set LUT and msi-map for discovered PCI devices
arch/arm/cpu/armv8/fsl-layerscape/fdt.c | 113 ---------- .../asm/arch-fsl-layerscape/ls2080a_stream_id.h | 55 +++-- drivers/pci/pcie_layerscape.c | 222 ++++++++++++++------ include/pci.h | 1 + 4 files changed, 187 insertions(+), 204 deletions(-)

From: Stuart Yoder stuart.yoder@nxp.com
Remove stream ID partitioning support that has been made obsolete by upstream device tree bindings that specify how representing how PCI requester IDs are mapped to MSI specifiers and SMMU stream IDs.
Signed-off-by: Stuart Yoder stuart.yoder@nxp.com --- -v2 -no changes
arch/arm/cpu/armv8/fsl-layerscape/fdt.c | 113 ------------------------------- drivers/pci/pcie_layerscape.c | 70 ------------------- 2 files changed, 183 deletions(-)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c index 4e4861d..7a64f41 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c @@ -70,115 +70,6 @@ void ft_fixup_cpu(void *blob) } #endif
-/* - * the burden is on the the caller to not request a count - * exceeding the bounds of the stream_ids[] array - */ -void alloc_stream_ids(int start_id, int count, u32 *stream_ids, int max_cnt) -{ - int i; - - if (count > max_cnt) { - printf("\n%s: ERROR: max per-device stream ID count exceed\n", - __func__); - return; - } - - for (i = 0; i < count; i++) - stream_ids[i] = start_id++; -} - -/* - * This function updates the mmu-masters property on the SMMU - * node as per the SMMU binding-- phandle and list of stream IDs - * for each MMU master. - */ -void append_mmu_masters(void *blob, const char *smmu_path, - const char *master_name, u32 *stream_ids, int count) -{ - u32 phandle; - int smmu_nodeoffset; - int master_nodeoffset; - int i; - - /* get phandle of mmu master device */ - master_nodeoffset = fdt_path_offset(blob, master_name); - if (master_nodeoffset < 0) { - printf("\n%s: ERROR: master not found\n", __func__); - return; - } - phandle = fdt_get_phandle(blob, master_nodeoffset); - if (!phandle) { /* if master has no phandle, create one */ - phandle = fdt_create_phandle(blob, master_nodeoffset); - if (!phandle) { - printf("\n%s: ERROR: unable to create phandle\n", - __func__); - return; - } - } - - /* append it to mmu-masters */ - smmu_nodeoffset = fdt_path_offset(blob, smmu_path); - if (fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", - phandle) < 0) { - printf("\n%s: ERROR: unable to update SMMU node\n", __func__); - return; - } - - /* for each stream ID, append to mmu-masters */ - for (i = 0; i < count; i++) { - fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", - stream_ids[i]); - } - - /* fix up #stream-id-cells with stream ID count */ - if (fdt_setprop_u32(blob, master_nodeoffset, "#stream-id-cells", - count) < 0) - printf("\n%s: ERROR: unable to update #stream-id-cells\n", - __func__); -} - - -/* - * The info below summarizes how streamID partitioning works - * for ls2080a and how it is conveyed to the OS via the device tree. - * - * -non-PCI legacy, platform devices (USB, SD/MMC, SATA, DMA) - * -all legacy devices get a unique ICID assigned and programmed in - * their AMQR registers by u-boot - * -u-boot updates the hardware device tree with streamID properties - * for each platform/legacy device (smmu-masters property) - * - * -PCIe - * -for each PCI controller that is active (as per RCW settings), - * u-boot will allocate a range of ICID and convey that to Linux via - * the device tree (smmu-masters property) - * - * -DPAA2 - * -u-boot will allocate a range of ICIDs to be used by the Management - * Complex for containers and will set these values in the MC DPC image. - * -the MC is responsible for allocating and setting up ICIDs - * for all DPAA2 devices. - * - */ -#ifdef CONFIG_FSL_LSCH3 -static void fdt_fixup_smmu(void *blob) -{ - int nodeoffset; - - nodeoffset = fdt_path_offset(blob, "/iommu@5000000"); - if (nodeoffset < 0) { - printf("\n%s: WARNING: no SMMU node found\n", __func__); - return; - } - - /* fixup for all PCI controllers */ -#ifdef CONFIG_PCI - fdt_fixup_smmu_pcie(blob); -#endif -} -#endif - void ft_cpu_setup(void *blob, bd_t *bd) { #ifdef CONFIG_MP @@ -200,8 +91,4 @@ void ft_cpu_setup(void *blob, bd_t *bd) #ifdef CONFIG_FSL_ESDHC fdt_fixup_esdhc(blob, bd); #endif - -#ifdef CONFIG_FSL_LSCH3 - fdt_fixup_smmu(blob); -#endif } diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index 99f9c83..bb29222 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -664,73 +664,3 @@ void ft_pci_setup(void *blob, bd_t *bd) { } #endif - -#if defined(CONFIG_LS2080A) || defined(CONFIG_LS2085A) - -void pcie_set_available_streamids(void *blob, const char *pcie_path, - u32 *stream_ids, int count) -{ - int nodeoffset; - int i; - - nodeoffset = fdt_path_offset(blob, pcie_path); - if (nodeoffset < 0) { - printf("\n%s: ERROR: unable to update PCIe node\n", __func__); - return; - } - - /* for each stream ID, append to mmu-masters */ - for (i = 0; i < count; i++) { - fdt_appendprop_u32(blob, nodeoffset, "available-stream-ids", - stream_ids[i]); - } -} - -#define MAX_STREAM_IDS 4 -void fdt_fixup_smmu_pcie(void *blob) -{ - int count; - u32 stream_ids[MAX_STREAM_IDS]; - u32 ctlr_streamid = 0x300; - - #ifdef CONFIG_PCIE1 - /* PEX1 stream ID fixup */ - count = FSL_PEX1_STREAM_ID_END - FSL_PEX1_STREAM_ID_START + 1; - alloc_stream_ids(FSL_PEX1_STREAM_ID_START, count, stream_ids, - MAX_STREAM_IDS); - pcie_set_available_streamids(blob, "/pcie@3400000", stream_ids, count); - append_mmu_masters(blob, "/iommu@5000000", "/pcie@3400000", - &ctlr_streamid, 1); - #endif - - #ifdef CONFIG_PCIE2 - /* PEX2 stream ID fixup */ - count = FSL_PEX2_STREAM_ID_END - FSL_PEX2_STREAM_ID_START + 1; - alloc_stream_ids(FSL_PEX2_STREAM_ID_START, count, stream_ids, - MAX_STREAM_IDS); - pcie_set_available_streamids(blob, "/pcie@3500000", stream_ids, count); - append_mmu_masters(blob, "/iommu@5000000", "/pcie@3500000", - &ctlr_streamid, 1); - #endif - - #ifdef CONFIG_PCIE3 - /* PEX3 stream ID fixup */ - count = FSL_PEX3_STREAM_ID_END - FSL_PEX3_STREAM_ID_START + 1; - alloc_stream_ids(FSL_PEX3_STREAM_ID_START, count, stream_ids, - MAX_STREAM_IDS); - pcie_set_available_streamids(blob, "/pcie@3600000", stream_ids, count); - append_mmu_masters(blob, "/iommu@5000000", "/pcie@3600000", - &ctlr_streamid, 1); - #endif - - #ifdef CONFIG_PCIE4 - /* PEX4 stream ID fixup */ - count = FSL_PEX4_STREAM_ID_END - FSL_PEX4_STREAM_ID_START + 1; - alloc_stream_ids(FSL_PEX4_STREAM_ID_START, count, stream_ids, - MAX_STREAM_IDS); - pcie_set_available_streamids(blob, "/pcie@3700000", stream_ids, count); - append_mmu_masters(blob, "/iommu@5000000", "/pcie@3700000", - &ctlr_streamid, 1); - #endif -} -#endif

From: Stuart Yoder stuart.yoder@nxp.com
put pci_get_hose_head() prototype in header so it is available to external users-- allowing them to find and iterate over all pci controllers
Signed-off-by: Stuart Yoder stuart.yoder@nxp.com --- -v2 -no changes
include/pci.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/pci.h b/include/pci.h index 68548b0..8698056 100644 --- a/include/pci.h +++ b/include/pci.h @@ -700,6 +700,7 @@ extern void *pci_map_bar(pci_dev_t pdev, int bar, int flags); extern void pci_register_hose(struct pci_controller* hose); extern struct pci_controller* pci_bus_to_hose(int bus); extern struct pci_controller *find_hose_by_cfg_addr(void *cfg_addr); +extern struct pci_controller *pci_get_hose_head(void);
extern int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev); extern int pci_hose_scan(struct pci_controller *hose);

From: Stuart Yoder stuart.yoder@nxp.com
The per-PCI controller LUT (Look-Up-Table) is a 32-entry table that maps PCI requester IDs (bus/dev/fun) to a stream ID.
This patch implements infrastructure to enable LUT initialization: -define registers offsets -add an index to 'struct ls_pcie' to track next available slot in LUT -add function to allocate the next available entry index -add function to program a LUT entry
Signed-off-by: Stuart Yoder stuart.yoder@nxp.com --- -v2 -no changes
drivers/pci/pcie_layerscape.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index bb29222..6886488 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -58,6 +58,13 @@ #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) #define PCIE_ATU_UPPER_TARGET 0x91C
+/* LUT registers */ +#define PCIE_LUT_BASE 0x80000 +#define PCIE_LUT_UDR(n) (0x800 + (n) * 8) +#define PCIE_LUT_LDR(n) (0x804 + (n) * 8) +#define PCIE_LUT_ENABLE (1 << 31) +#define PCIE_LUT_ENTRY_COUNT 32 + #define PCIE_DBI_RO_WR_EN 0x8bc
#define PCIE_LINK_CAP 0x7c @@ -93,6 +100,7 @@ struct ls_pcie { void __iomem *dbi; void __iomem *va_cfg0; void __iomem *va_cfg1; + int next_lut_index; struct pci_controller hose; };
@@ -482,6 +490,33 @@ static void ls_pcie_setup_ep(struct ls_pcie *pcie, struct ls_pcie_info *info) } }
+ +/* + * Return next available LUT index. + */ +static u32 ls_pcie_next_lut_index(struct ls_pcie *pcie) +{ + if (pcie->next_lut_index < PCIE_LUT_ENTRY_COUNT) + return pcie->next_lut_index++; + else + return -1; /* LUT is full */ +} + +/* + * Program a single LUT entry + */ +static void ls_pcie_lut_set_mapping(struct ls_pcie *pcie, int index, u32 devid, + u32 streamid) +{ + void __iomem *lut; + + lut = pcie->dbi + PCIE_LUT_BASE; + + /* leave mask as all zeroes, want to match all bits */ + writel((devid << 16), lut + PCIE_LUT_UDR(index)); + writel(streamid | PCIE_LUT_ENABLE, lut + PCIE_LUT_LDR(index)); +} + int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) { struct ls_pcie *pcie; @@ -513,6 +548,7 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) pcie->va_cfg1 = map_physmem(info->cfg1_phys, info->cfg1_size, MAP_NOCACHE); + pcie->next_lut_index = 0;
/* outbound memory */ pci_set_region(&hose->regions[0],

Hi Stuart,
Please see my comments inline.
Thanks, Minghuan
-----Original Message----- From: Stuart Yoder [mailto:stuart.yoder@nxp.com] Sent: Friday, February 26, 2016 7:06 AM To: u-boot@lists.denx.de Cc: york sun york.sun@nxp.com; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com; Mingkai Hu mingkai.hu@nxp.com; Minghuan Lian minghuan.lian@nxp.com; Yang-Leo Li leoyang.li@nxp.com; marc.zyngier@arm.com; Stuart Yoder stuart.yoder@nxp.com Subject: [PATCH 4/7 v2] pci/layerscape: add support for LUT
From: Stuart Yoder stuart.yoder@nxp.com
The per-PCI controller LUT (Look-Up-Table) is a 32-entry table that maps PCI requester IDs (bus/dev/fun) to a stream ID.
This patch implements infrastructure to enable LUT initialization: -define registers offsets -add an index to 'struct ls_pcie' to track next available slot in LUT -add function to allocate the next available entry index -add function to program a LUT entry
Signed-off-by: Stuart Yoder stuart.yoder@nxp.com
-v2 -no changes
drivers/pci/pcie_layerscape.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index bb29222..6886488 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -58,6 +58,13 @@ #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) #define PCIE_ATU_UPPER_TARGET 0x91C
+/* LUT registers */ +#define PCIE_LUT_BASE 0x80000
[Minghuan Lian] PCIE_LUT_BASE has been defined in immap_lsch2.h and immap_lsch3.h. LS1043a has the different base address.
+#define PCIE_LUT_UDR(n) (0x800 + (n) * 8) +#define PCIE_LUT_LDR(n) (0x804 + (n) * 8) +#define PCIE_LUT_ENABLE (1 << 31) +#define PCIE_LUT_ENTRY_COUNT 32
#define PCIE_DBI_RO_WR_EN 0x8bc
#define PCIE_LINK_CAP 0x7c @@ -93,6 +100,7 @@ struct ls_pcie { void __iomem *dbi; void __iomem *va_cfg0; void __iomem *va_cfg1;
- int next_lut_index; struct pci_controller hose;
};
@@ -482,6 +490,33 @@ static void ls_pcie_setup_ep(struct ls_pcie *pcie, struct ls_pcie_info *info) } }
+/*
- Return next available LUT index.
- */
+static u32 ls_pcie_next_lut_index(struct ls_pcie *pcie) +{
- if (pcie->next_lut_index < PCIE_LUT_ENTRY_COUNT)
return pcie->next_lut_index++;
- else
return -1; /* LUT is full */
+}
+/*
- Program a single LUT entry
- */
+static void ls_pcie_lut_set_mapping(struct ls_pcie *pcie, int index, u32 devid,
u32 streamid)
+{
- void __iomem *lut;
- lut = pcie->dbi + PCIE_LUT_BASE;
- /* leave mask as all zeroes, want to match all bits */
- writel((devid << 16), lut + PCIE_LUT_UDR(index));
- writel(streamid | PCIE_LUT_ENABLE, lut + PCIE_LUT_LDR(index));
+}
int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) { struct ls_pcie *pcie; @@ -513,6 +548,7 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) pcie->va_cfg1 = map_physmem(info->cfg1_phys, info->cfg1_size, MAP_NOCACHE);
pcie->next_lut_index = 0;
/* outbound memory */ pci_set_region(&hose->regions[0],
-- 1.7.9.5

-----Original Message----- From: Minghuan Lian Sent: Thursday, February 25, 2016 11:56 PM To: Stuart Yoder stuart.yoder@nxp.com; u-boot@lists.denx.de Cc: york sun york.sun@nxp.com; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com; Mingkai Hu mingkai.hu@nxp.com; Yang-Leo Li leoyang.li@nxp.com; marc.zyngier@arm.com; Stuart Yoder stuart.yoder@nxp.com Subject: RE: [PATCH 4/7 v2] pci/layerscape: add support for LUT
Hi Stuart,
Please see my comments inline.
Thanks, Minghuan
-----Original Message----- From: Stuart Yoder [mailto:stuart.yoder@nxp.com] Sent: Friday, February 26, 2016 7:06 AM To: u-boot@lists.denx.de Cc: york sun york.sun@nxp.com; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com; Mingkai Hu mingkai.hu@nxp.com; Minghuan Lian minghuan.lian@nxp.com; Yang-Leo Li leoyang.li@nxp.com; marc.zyngier@arm.com; Stuart Yoder stuart.yoder@nxp.com Subject: [PATCH 4/7 v2] pci/layerscape: add support for LUT
From: Stuart Yoder stuart.yoder@nxp.com
The per-PCI controller LUT (Look-Up-Table) is a 32-entry table that maps PCI requester IDs (bus/dev/fun) to a stream ID.
This patch implements infrastructure to enable LUT initialization: -define registers offsets -add an index to 'struct ls_pcie' to track next available slot in LUT -add function to allocate the next available entry index -add function to program a LUT entry
Signed-off-by: Stuart Yoder stuart.yoder@nxp.com
-v2 -no changes
drivers/pci/pcie_layerscape.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index bb29222..6886488 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -58,6 +58,13 @@ #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) #define PCIE_ATU_UPPER_TARGET 0x91C
+/* LUT registers */ +#define PCIE_LUT_BASE 0x80000
[Minghuan Lian] PCIE_LUT_BASE has been defined in immap_lsch2.h and immap_lsch3.h. LS1043a has the different base address.
+#define PCIE_LUT_UDR(n) (0x800 + (n) * 8) +#define PCIE_LUT_LDR(n) (0x804 + (n) * 8) +#define PCIE_LUT_ENABLE (1 << 31) +#define PCIE_LUT_ENTRY_COUNT 32
I'll move the new defines into immap_lsch3.h.
Stuart

From: Stuart Yoder stuart.yoder@nxp.com
add a function to return the next available stream ID for PCI
Signed-off-by: Stuart Yoder stuart.yoder@nxp.com --- -v2 -no changes
drivers/pci/pcie_layerscape.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index 6886488..f96a08c 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -517,6 +517,17 @@ static void ls_pcie_lut_set_mapping(struct ls_pcie *pcie, int index, u32 devid, writel(streamid | PCIE_LUT_ENABLE, lut + PCIE_LUT_LDR(index)); }
+/* returns the next available streamid */ +static u32 ls_pcie_next_streamid(void) +{ + static int next_stream_id = FSL_PEX_STREAM_ID_START; + + if (next_stream_id > FSL_PEX_STREAM_ID_END) + return -1; + + return next_stream_id++; +} + int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) { struct ls_pcie *pcie;

From: Stuart Yoder stuart.yoder@nxp.com
msi-map properties are used to tell an OS how PCI requester IDs are mapped to ARM SMMU stream IDs. This patch defines a function to append a single msi-map entry to a given PCI controller device tree node.
Signed-off-by: Stuart Yoder stuart.yoder@nxp.com --- -v2 -no changes
drivers/pci/pcie_layerscape.c | 43 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index f96a08c..dfafaf2 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -490,7 +490,6 @@ static void ls_pcie_setup_ep(struct ls_pcie *pcie, struct ls_pcie_info *info) } }
- /* * Return next available LUT index. */ @@ -528,6 +527,48 @@ static u32 ls_pcie_next_streamid(void) return next_stream_id++; }
+/* + * An msi-map is a property to be added to the pci controller + * node. It is a table, where each entry consists of 4 fields + * e.g.: + * + * msi-map = <[devid] [phandle-to-msi-ctrl] [stream-id] [count] + * [devid] [phandle-to-msi-ctrl] [stream-id] [count]>; + */ +static void fdt_pcie_set_msi_map_entry(void *blob, struct ls_pcie *pcie, + u32 devid, u32 streamid) +{ + char pcie_path[19]; + u32 *prop; + u32 phandle; + int nodeoffset; + + /* find pci controller node */ + snprintf(pcie_path, sizeof(pcie_path), "/soc/pcie@%llx", + (u64)pcie->dbi); + nodeoffset = fdt_path_offset(blob, pcie_path); + if (nodeoffset < 0) { + printf("\n%s: ERROR: unable to update PCIe node: %s\n", + __func__, pcie_path); + return; + } + + /* get phandle to MSI controller */ + prop = (u32 *)fdt_getprop(blob, nodeoffset, "msi-parent", 0); + if (prop == NULL) { + printf("\n%s: ERROR: missing msi-parent: %s\n", __func__, + pcie_path); + return; + } + phandle = be32_to_cpu(*prop); + + /* set one msi-map row */ + fdt_appendprop_u32(blob, nodeoffset, "msi-map", devid); + fdt_appendprop_u32(blob, nodeoffset, "msi-map", phandle); + fdt_appendprop_u32(blob, nodeoffset, "msi-map", streamid); + fdt_appendprop_u32(blob, nodeoffset, "msi-map", 1); +} + int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) { struct ls_pcie *pcie;

From: Stuart Yoder stuart.yoder@nxp.com
for all PCI devices discovered in a system: -allocate a LUT (look-up-table) entry in that PCI controller -allocate a stream ID for the device -program and enable a LUT entry (maps PCI requester id to stream ID) -set the msi-map property on the controller reflecting the LUT mapping
basic bus scanning loop/logic was taken from drivers/pci/pci.c pci_hose_scan_bus().
Signed-off-by: Stuart Yoder stuart.yoder@nxp.com --- -v2 -removed skip of host bridge when scanning the bus
drivers/pci/pcie_layerscape.c | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index dfafaf2..3470210 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -569,6 +569,66 @@ static void fdt_pcie_set_msi_map_entry(void *blob, struct ls_pcie *pcie, fdt_appendprop_u32(blob, nodeoffset, "msi-map", 1); }
+static void fdt_fixup_pcie(void *blob) +{ + unsigned int found_multi = 0; + unsigned char header_type; + int index; + u32 streamid; + pci_dev_t dev; + int bus; + unsigned short id; + struct pci_controller *hose; + struct ls_pcie *pcie; + int i; + + for (i = 0, hose = pci_get_hose_head(); hose; hose = hose->next, i++) { + pcie = hose->priv_data; + for (bus = hose->first_busno; bus <= hose->last_busno; bus++) { + + for (dev = PCI_BDF(bus, 0, 0); + dev < PCI_BDF(bus, PCI_MAX_PCI_DEVICES - 1, + PCI_MAX_PCI_FUNCTIONS - 1); + dev += PCI_BDF(0, 0, 1)) { + + if (PCI_FUNC(dev) && !found_multi) + continue; + + pci_read_config_word(dev, PCI_VENDOR_ID, &id); + + pci_read_config_byte(dev, PCI_HEADER_TYPE, + &header_type); + + if ((id == 0xFFFF) || (id == 0x0000)) + continue; + + if (!PCI_FUNC(dev)) + found_multi = header_type & 0x80; + + streamid = ls_pcie_next_streamid(); + if (streamid < 0) { + printf("ERROR: no stream ids free\n"); + continue; + } + + index = ls_pcie_next_lut_index(pcie); + if (index < 0) { + printf("ERROR: no LUT indexes free\n"); + continue; + } + + /* map PCI b.d.f to streamID in LUT */ + ls_pcie_lut_set_mapping(pcie, index, dev >> 8, + streamid); + + /* update msi-map in device tree */ + fdt_pcie_set_msi_map_entry(blob, pcie, dev >> 8, + streamid); + } + } + } +} + int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) { struct ls_pcie *pcie; @@ -745,6 +805,10 @@ void ft_pci_setup(void *blob, bd_t *bd) #ifdef CONFIG_PCIE4 ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE4_ADDR, PCIE4); #endif + + #if defined(CONFIG_LS2080A) || defined(CONFIG_LS2085A) + fdt_fixup_pcie(blob); + #endif }
#else

Hi Stuart,
Please see my comments inline.
Thanks, Minghuan
-----Original Message----- From: Stuart Yoder [mailto:stuart.yoder@nxp.com] Sent: Friday, February 26, 2016 7:06 AM To: u-boot@lists.denx.de Cc: york sun york.sun@nxp.com; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com; Mingkai Hu mingkai.hu@nxp.com; Minghuan Lian minghuan.lian@nxp.com; Yang-Leo Li leoyang.li@nxp.com; marc.zyngier@arm.com; Stuart Yoder stuart.yoder@nxp.com Subject: [PATCH 7/7 v2] pci/layerscape: set LUT and msi-map for discovered PCI devices
From: Stuart Yoder stuart.yoder@nxp.com
for all PCI devices discovered in a system: -allocate a LUT (look-up-table) entry in that PCI controller -allocate a stream ID for the device -program and enable a LUT entry (maps PCI requester id to stream ID) -set the msi-map property on the controller reflecting the LUT mapping
basic bus scanning loop/logic was taken from drivers/pci/pci.c pci_hose_scan_bus().
Signed-off-by: Stuart Yoder stuart.yoder@nxp.com
-v2 -removed skip of host bridge when scanning the bus
drivers/pci/pcie_layerscape.c | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index dfafaf2..3470210 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -569,6 +569,66 @@ static void fdt_pcie_set_msi_map_entry(void *blob, struct ls_pcie *pcie, fdt_appendprop_u32(blob, nodeoffset, "msi-map", 1); }
+static void fdt_fixup_pcie(void *blob) +{
- unsigned int found_multi = 0;
- unsigned char header_type;
- int index;
- u32 streamid;
- pci_dev_t dev;
- int bus;
- unsigned short id;
- struct pci_controller *hose;
- struct ls_pcie *pcie;
- int i;
- for (i = 0, hose = pci_get_hose_head(); hose; hose = hose->next, i++) {
pcie = hose->priv_data;
for (bus = hose->first_busno; bus <= hose->last_busno; bus++) {
for (dev = PCI_BDF(bus, 0, 0);
dev < PCI_BDF(bus, PCI_MAX_PCI_DEVICES - 1,
PCI_MAX_PCI_FUNCTIONS - 1);
dev += PCI_BDF(0, 0, 1)) {
if (PCI_FUNC(dev) && !found_multi)
continue;
pci_read_config_word(dev, PCI_VENDOR_ID, &id);
pci_read_config_byte(dev, PCI_HEADER_TYPE,
&header_type);
if ((id == 0xFFFF) || (id == 0x0000))
continue;
if (!PCI_FUNC(dev))
found_multi = header_type & 0x80;
streamid = ls_pcie_next_streamid();
if (streamid < 0) {
[Minghuan Lian] streamed is u32 type not int, it should be always >= 0.
printf("ERROR: no stream ids free\n");
continue;
}
index = ls_pcie_next_lut_index(pcie);
[Minghuan Lian] ls_pcie_next_lut_index() returns an u32 value not int. we may change all index and streamid to int type.
if (index < 0) {
printf("ERROR: no LUT indexes free\n");
continue;
}
/* map PCI b.d.f to streamID in LUT */
ls_pcie_lut_set_mapping(pcie, index, dev >> 8,
streamid);
/* update msi-map in device tree */
fdt_pcie_set_msi_map_entry(blob, pcie, dev >> 8,
streamid);
}
}
- }
+}
int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) { struct ls_pcie *pcie; @@ -745,6 +805,10 @@ void ft_pci_setup(void *blob, bd_t *bd) #ifdef CONFIG_PCIE4 ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE4_ADDR, PCIE4); #endif
- #if defined(CONFIG_LS2080A) || defined(CONFIG_LS2085A)
- fdt_fixup_pcie(blob);
- #endif
}
#else
1.7.9.5

-----Original Message----- From: Minghuan Lian Sent: Thursday, February 25, 2016 11:55 PM To: Stuart Yoder stuart.yoder@nxp.com; u-boot@lists.denx.de Cc: york sun york.sun@nxp.com; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com; Mingkai Hu mingkai.hu@nxp.com; Yang-Leo Li leoyang.li@nxp.com; marc.zyngier@arm.com; Stuart Yoder stuart.yoder@nxp.com Subject: RE: [PATCH 7/7 v2] pci/layerscape: set LUT and msi-map for discovered PCI devices
Hi Stuart,
Please see my comments inline.
Thanks, Minghuan
-----Original Message----- From: Stuart Yoder [mailto:stuart.yoder@nxp.com] Sent: Friday, February 26, 2016 7:06 AM To: u-boot@lists.denx.de Cc: york sun york.sun@nxp.com; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com; Mingkai Hu mingkai.hu@nxp.com; Minghuan Lian minghuan.lian@nxp.com; Yang-Leo Li leoyang.li@nxp.com; marc.zyngier@arm.com; Stuart Yoder stuart.yoder@nxp.com Subject: [PATCH 7/7 v2] pci/layerscape: set LUT and msi-map for discovered PCI devices
From: Stuart Yoder stuart.yoder@nxp.com
for all PCI devices discovered in a system: -allocate a LUT (look-up-table) entry in that PCI controller -allocate a stream ID for the device -program and enable a LUT entry (maps PCI requester id to stream ID) -set the msi-map property on the controller reflecting the LUT mapping
basic bus scanning loop/logic was taken from drivers/pci/pci.c pci_hose_scan_bus().
Signed-off-by: Stuart Yoder stuart.yoder@nxp.com
-v2 -removed skip of host bridge when scanning the bus
drivers/pci/pcie_layerscape.c | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index dfafaf2..3470210 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -569,6 +569,66 @@ static void fdt_pcie_set_msi_map_entry(void *blob, struct ls_pcie *pcie, fdt_appendprop_u32(blob, nodeoffset, "msi-map", 1); }
+static void fdt_fixup_pcie(void *blob) +{
- unsigned int found_multi = 0;
- unsigned char header_type;
- int index;
- u32 streamid;
- pci_dev_t dev;
- int bus;
- unsigned short id;
- struct pci_controller *hose;
- struct ls_pcie *pcie;
- int i;
- for (i = 0, hose = pci_get_hose_head(); hose; hose = hose->next, i++) {
pcie = hose->priv_data;
for (bus = hose->first_busno; bus <= hose->last_busno; bus++) {
for (dev = PCI_BDF(bus, 0, 0);
dev < PCI_BDF(bus, PCI_MAX_PCI_DEVICES - 1,
PCI_MAX_PCI_FUNCTIONS - 1);
dev += PCI_BDF(0, 0, 1)) {
if (PCI_FUNC(dev) && !found_multi)
continue;
pci_read_config_word(dev, PCI_VENDOR_ID, &id);
pci_read_config_byte(dev, PCI_HEADER_TYPE,
&header_type);
if ((id == 0xFFFF) || (id == 0x0000))
continue;
if (!PCI_FUNC(dev))
found_multi = header_type & 0x80;
streamid = ls_pcie_next_streamid();
if (streamid < 0) {
[Minghuan Lian] streamed is u32 type not int, it should be always >= 0.
printf("ERROR: no stream ids free\n");
continue;
}
index = ls_pcie_next_lut_index(pcie);
[Minghuan Lian] ls_pcie_next_lut_index() returns an u32 value not int. we may change all index and streamid to int type.
Thanks. Stream IDs are not signed numbers, I'll update the patch series to be consistent and use a value of 0xffffffff to indicate an error. The LUT index I think should be an int.
Stuart
participants (2)
-
Minghuan Lian
-
Stuart Yoder