[U-Boot] [PATCH] ls1028a: Configure stream IDs for integrated PCI and fix up Linux DT

Hardware comes out of reset with implicit values, but these are outside the accepted range for Layerscape gen 3 chassis spec used on LS1028A. Allocate different IDs and fix up Linux DT to use them.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- arch/arm/cpu/armv8/fsl-layerscape/fdt.c | 9 ++ .../asm/arch-fsl-layerscape/stream_id_lsch3.h | 8 ++ board/freescale/ls1028a/ls1028a.c | 106 ++++++++++++++++++ 3 files changed, 123 insertions(+)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c index e993209593..1e7e46e88a 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c @@ -421,6 +421,12 @@ static void fdt_disable_multimedia(void *blob, unsigned int svr) } #endif
+#ifdef CONFIG_PCIE_ECAM_GENERIC +__weak void fdt_fixup_ecam(void *blob) +{ +} +#endif + void ft_cpu_setup(void *blob, bd_t *bd) { struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); @@ -485,4 +491,7 @@ void ft_cpu_setup(void *blob, bd_t *bd) #ifdef CONFIG_ARCH_LS1028A fdt_disable_multimedia(blob, svr); #endif +#ifdef CONFIG_PCIE_ECAM_GENERIC + fdt_fixup_ecam(blob); +#endif } diff --git a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h index 94ea99a349..01d362d183 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h @@ -42,6 +42,10 @@ * -the MC is responsible for allocating and setting up 'isolation context * IDs (ICIDs) based on the allocated stream IDs for all DPAA2 devices. * + * - ECAM (integrated PCI) + * - U-Boot applies the value here to HW and does DT fix-up for both + * 'iommu-map' and 'msi-map' + * * On Chasis-3 SoCs stream IDs are programmed in AMQ registers (32-bits) for * each of the different bus masters. The relationship between * the AMQ registers and stream IDs is defined in the table below: @@ -98,6 +102,10 @@ #define FSL_DPAA2_STREAM_ID_START 23 #define FSL_DPAA2_STREAM_ID_END 63
+/* PCI IEPs, this overlaps DPAA2 but these two are exclusive at least for now */ +#define FSL_ECAM_STREAM_ID_START 32 +#define FSL_ECAM_STREAM_ID_END 63 + #define FSL_SEC_STREAM_ID 64 #define FSL_SEC_JR1_STREAM_ID 65 #define FSL_SEC_JR2_STREAM_ID 66 diff --git a/board/freescale/ls1028a/ls1028a.c b/board/freescale/ls1028a/ls1028a.c index a9606b8865..1f5dc0d0b2 100644 --- a/board/freescale/ls1028a/ls1028a.c +++ b/board/freescale/ls1028a/ls1028a.c @@ -28,6 +28,52 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_PCIE_ECAM_GENERIC + +#define ECAM_IERB_BASE 0x1f0800000ULL +#define ECAM_IERB_OFFSET_NA -1 +#define ECAM_IERB_FUNC_CNT ARRAY_SIZE(ierb_offset) +/* cache related transaction attributes for PCIe functions */ +#define ECAM_IERB_MSICAR (ECAM_IERB_BASE + 0xa400) +#define ECAM_IERB_MSICAR_VALUE 0x30 + +/* offset of IERB config register per PCI function */ +static int ierb_offset[] = { + 0x0800, + 0x1800, + 0x2800, + 0x3800, + 0x4800, + 0x5800, + 0x6800, + ECAM_IERB_OFFSET_NA, + 0x0804, + 0x0808, + 0x1804, + 0x1808, +}; + +/* + * Use a custom function for LS1028A, for now this is the only SoC with IERB + * and we're currently considering reorganizing IERB for future SoCs. + */ +static void set_ecam_icids(void) +{ + int i; + + out_le32(ECAM_IERB_MSICAR, ECAM_IERB_MSICAR_VALUE); + + for (i = 0; i < ECAM_IERB_FUNC_CNT; i++) { + if (ierb_offset[i] == ECAM_IERB_OFFSET_NA) + continue; + + out_le32(ECAM_IERB_BASE + ierb_offset[i], + FSL_ECAM_STREAM_ID_START + i); + } +} + +#endif /* CONFIG_PCIE_ECAM_GENERIC */ + int config_board_mux(void) { #if defined(CONFIG_TARGET_LS1028AQDS) && defined(CONFIG_FSL_QIXIS) @@ -88,6 +134,16 @@ int board_init(void) #endif
#endif + + /* + * ICIDs for other hardware blocks are set really early on, before MMU + * is set up. For integrated PCI we need access to IERB which is not + * part of CCSR, so we have to wait for MMU mappings to be applied + */ +#ifdef CONFIG_PCIE_ECAM_GENERIC + set_ecam_icids(); +#endif + return 0; }
@@ -244,3 +300,53 @@ int checkboard(void) return 0; } #endif + +#ifdef CONFIG_PCIE_ECAM_GENERIC + +static int fdt_setprop_inplace_idx_u32(void *fdt, int nodeoffset, + const char *name, uint32_t idx, u32 val) +{ + val = cpu_to_be32(val); + return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, + strlen(name), + idx * sizeof(val), &val, + sizeof(val)); +} + +static int fdt_getprop_len(void *fdt, int nodeoffset, const char *name) +{ + int len; + + if (fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), &len)) + return len; + + return 0; +} + +void fdt_fixup_ecam(void *blob) +{ + int off; + + off = fdt_node_offset_by_compatible(blob, 0, "pci-host-ecam-generic"); + if (off < 0) { + debug("ECAM node not found\n"); + return; + } + + if (fdt_getprop_len(blob, off, "msi-map") != 16 || + fdt_getprop_len(blob, off, "iommu-map") != 16) { + log_err("invalid msi/iommu-map propertly size in ECAM node\n"); + return; + } + + fdt_setprop_inplace_idx_u32(blob, off, "msi-map", 2, + FSL_ECAM_STREAM_ID_START); + fdt_setprop_inplace_idx_u32(blob, off, "msi-map", 3, + ECAM_IERB_FUNC_CNT); + + fdt_setprop_inplace_idx_u32(blob, off, "iommu-map", 2, + FSL_ECAM_STREAM_ID_START); + fdt_setprop_inplace_idx_u32(blob, off, "iommu-map", 3, + ECAM_IERB_FUNC_CNT); +} +#endif /* CONFIG_PCIE_ECAM_GENERIC */

On Wed, Nov 27, 2019 at 9:58 PM Alex Marginean alexandru.marginean@nxp.com wrote:
Hardware comes out of reset with implicit values, but these are outside the accepted range for Layerscape gen 3 chassis spec used on LS1028A. Allocate different IDs and fix up Linux DT to use them.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
arch/arm/cpu/armv8/fsl-layerscape/fdt.c | 9 ++ .../asm/arch-fsl-layerscape/stream_id_lsch3.h | 8 ++ board/freescale/ls1028a/ls1028a.c | 106 ++++++++++++++++++ 3 files changed, 123 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Hi Alex,
Am 2019-11-27 14:57, schrieb Alex Marginean:
Hardware comes out of reset with implicit values, but these are outside the accepted range for Layerscape gen 3 chassis spec used on LS1028A. Allocate different IDs and fix up Linux DT to use them.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
arch/arm/cpu/armv8/fsl-layerscape/fdt.c | 9 ++ .../asm/arch-fsl-layerscape/stream_id_lsch3.h | 8 ++ board/freescale/ls1028a/ls1028a.c | 106 ++++++++++++++++++
Doh :( is there no other place where to put this fixup? That would mean I have to replicate this code for our custom board and so does every board which uses the LS1028A. Shouldn't this be in the SoC LS1028A architecture specific code?
3 files changed, 123 insertions(+)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c index e993209593..1e7e46e88a 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c @@ -421,6 +421,12 @@ static void fdt_disable_multimedia(void *blob, unsigned int svr) } #endif
+#ifdef CONFIG_PCIE_ECAM_GENERIC +__weak void fdt_fixup_ecam(void *blob) +{ +} +#endif
void ft_cpu_setup(void *blob, bd_t *bd) { struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); @@ -485,4 +491,7 @@ void ft_cpu_setup(void *blob, bd_t *bd) #ifdef CONFIG_ARCH_LS1028A fdt_disable_multimedia(blob, svr); #endif +#ifdef CONFIG_PCIE_ECAM_GENERIC
- fdt_fixup_ecam(blob);
+#endif } diff --git a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h index 94ea99a349..01d362d183 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h @@ -42,6 +42,10 @@
-the MC is responsible for allocating and setting up 'isolation
context
IDs (ICIDs) based on the allocated stream IDs for all DPAA2
devices.
- ECAM (integrated PCI)
- U-Boot applies the value here to HW and does DT fix-up for
both
'iommu-map' and 'msi-map'
mhh this is not entirely true, because it is the board code which does the fixup, which may lead to some confusion.
- On Chasis-3 SoCs stream IDs are programmed in AMQ registers
(32-bits) for
- each of the different bus masters. The relationship between
- the AMQ registers and stream IDs is defined in the table below:
@@ -98,6 +102,10 @@ #define FSL_DPAA2_STREAM_ID_START 23 #define FSL_DPAA2_STREAM_ID_END 63
+/* PCI IEPs, this overlaps DPAA2 but these two are exclusive at least for now */ +#define FSL_ECAM_STREAM_ID_START 32 +#define FSL_ECAM_STREAM_ID_END 63
#define FSL_SEC_STREAM_ID 64 #define FSL_SEC_JR1_STREAM_ID 65 #define FSL_SEC_JR2_STREAM_ID 66 diff --git a/board/freescale/ls1028a/ls1028a.c b/board/freescale/ls1028a/ls1028a.c index a9606b8865..1f5dc0d0b2 100644 --- a/board/freescale/ls1028a/ls1028a.c +++ b/board/freescale/ls1028a/ls1028a.c @@ -28,6 +28,52 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_PCIE_ECAM_GENERIC
+#define ECAM_IERB_BASE 0x1f0800000ULL +#define ECAM_IERB_OFFSET_NA -1 +#define ECAM_IERB_FUNC_CNT ARRAY_SIZE(ierb_offset) +/* cache related transaction attributes for PCIe functions */ +#define ECAM_IERB_MSICAR (ECAM_IERB_BASE + 0xa400) +#define ECAM_IERB_MSICAR_VALUE 0x30
+/* offset of IERB config register per PCI function */ +static int ierb_offset[] = {
- 0x0800,
- 0x1800,
- 0x2800,
- 0x3800,
- 0x4800,
- 0x5800,
- 0x6800,
- ECAM_IERB_OFFSET_NA,
- 0x0804,
- 0x0808,
- 0x1804,
- 0x1808,
+};
+/*
- Use a custom function for LS1028A, for now this is the only SoC
with IERB
- and we're currently considering reorganizing IERB for future SoCs.
- */
+static void set_ecam_icids(void) +{
- int i;
- out_le32(ECAM_IERB_MSICAR, ECAM_IERB_MSICAR_VALUE);
- for (i = 0; i < ECAM_IERB_FUNC_CNT; i++) {
if (ierb_offset[i] == ECAM_IERB_OFFSET_NA)
continue;
out_le32(ECAM_IERB_BASE + ierb_offset[i],
FSL_ECAM_STREAM_ID_START + i);
- }
+}
+#endif /* CONFIG_PCIE_ECAM_GENERIC */
int config_board_mux(void) { #if defined(CONFIG_TARGET_LS1028AQDS) && defined(CONFIG_FSL_QIXIS) @@ -88,6 +134,16 @@ int board_init(void) #endif
#endif
- /*
* ICIDs for other hardware blocks are set really early on, before
MMU
* is set up. For integrated PCI we need access to IERB which is not
* part of CCSR, so we have to wait for MMU mappings to be applied
*/
+#ifdef CONFIG_PCIE_ECAM_GENERIC
- set_ecam_icids();
+#endif
- return 0;
}
@@ -244,3 +300,53 @@ int checkboard(void) return 0; } #endif
+#ifdef CONFIG_PCIE_ECAM_GENERIC
+static int fdt_setprop_inplace_idx_u32(void *fdt, int nodeoffset,
const char *name, uint32_t idx, u32 val)
+{
- val = cpu_to_be32(val);
- return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
strlen(name),
idx * sizeof(val), &val,
sizeof(val));
+}
+static int fdt_getprop_len(void *fdt, int nodeoffset, const char *name) +{
- int len;
- if (fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), &len))
return len;
- return 0;
+}
+void fdt_fixup_ecam(void *blob) +{
- int off;
- off = fdt_node_offset_by_compatible(blob, 0,
"pci-host-ecam-generic");
- if (off < 0) {
debug("ECAM node not found\n");
return;
- }
- if (fdt_getprop_len(blob, off, "msi-map") != 16 ||
fdt_getprop_len(blob, off, "iommu-map") != 16) {
log_err("invalid msi/iommu-map propertly size in ECAM node\n");
return;
- }
- fdt_setprop_inplace_idx_u32(blob, off, "msi-map", 2,
FSL_ECAM_STREAM_ID_START);
- fdt_setprop_inplace_idx_u32(blob, off, "msi-map", 3,
ECAM_IERB_FUNC_CNT);
- fdt_setprop_inplace_idx_u32(blob, off, "iommu-map", 2,
FSL_ECAM_STREAM_ID_START);
- fdt_setprop_inplace_idx_u32(blob, off, "iommu-map", 3,
ECAM_IERB_FUNC_CNT);
+} +#endif /* CONFIG_PCIE_ECAM_GENERIC */
-michael

Hi Michael,
On 11/27/2019 3:33 PM, Michael Walle wrote:
Hi Alex,
Am 2019-11-27 14:57, schrieb Alex Marginean:
Hardware comes out of reset with implicit values, but these are outside the accepted range for Layerscape gen 3 chassis spec used on LS1028A. Allocate different IDs and fix up Linux DT to use them.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
arch/arm/cpu/armv8/fsl-layerscape/fdt.c | 9 ++ .../asm/arch-fsl-layerscape/stream_id_lsch3.h | 8 ++ board/freescale/ls1028a/ls1028a.c | 106 ++++++++++++++++++
Doh :( is there no other place where to put this fixup? That would mean I have to replicate this code for our custom board and so does every board which uses the LS1028A. Shouldn't this be in the SoC LS1028A architecture specific code?
Yeah, you're right about that. It should probably go into armv8/fsl-layerscape/icid.c or somewhere around there. I'll send a v2.
Thanks! Alex
3 files changed, 123 insertions(+)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c index e993209593..1e7e46e88a 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c @@ -421,6 +421,12 @@ static void fdt_disable_multimedia(void *blob, unsigned int svr) } #endif
+#ifdef CONFIG_PCIE_ECAM_GENERIC +__weak void fdt_fixup_ecam(void *blob) +{ +} +#endif
void ft_cpu_setup(void *blob, bd_t *bd) { struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); @@ -485,4 +491,7 @@ void ft_cpu_setup(void *blob, bd_t *bd) #ifdef CONFIG_ARCH_LS1028A fdt_disable_multimedia(blob, svr); #endif +#ifdef CONFIG_PCIE_ECAM_GENERIC + fdt_fixup_ecam(blob); +#endif } diff --git a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h index 94ea99a349..01d362d183 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h @@ -42,6 +42,10 @@ * -the MC is responsible for allocating and setting up 'isolation context * IDs (ICIDs) based on the allocated stream IDs for all DPAA2 devices. *
- * - ECAM (integrated PCI)
- * - U-Boot applies the value here to HW and does DT fix-up for both
- * 'iommu-map' and 'msi-map'
mhh this is not entirely true, because it is the board code which does the fixup, which may lead to some confusion. >
* On Chasis-3 SoCs stream IDs are programmed in AMQ registers (32-bits) for * each of the different bus masters. The relationship between * the AMQ registers and stream IDs is defined in the table below: @@ -98,6 +102,10 @@ #define FSL_DPAA2_STREAM_ID_START 23 #define FSL_DPAA2_STREAM_ID_END 63
+/* PCI IEPs, this overlaps DPAA2 but these two are exclusive at least for now */ +#define FSL_ECAM_STREAM_ID_START 32 +#define FSL_ECAM_STREAM_ID_END 63
#define FSL_SEC_STREAM_ID 64 #define FSL_SEC_JR1_STREAM_ID 65 #define FSL_SEC_JR2_STREAM_ID 66 diff --git a/board/freescale/ls1028a/ls1028a.c b/board/freescale/ls1028a/ls1028a.c index a9606b8865..1f5dc0d0b2 100644 --- a/board/freescale/ls1028a/ls1028a.c +++ b/board/freescale/ls1028a/ls1028a.c @@ -28,6 +28,52 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_PCIE_ECAM_GENERIC
+#define ECAM_IERB_BASE 0x1f0800000ULL +#define ECAM_IERB_OFFSET_NA -1 +#define ECAM_IERB_FUNC_CNT ARRAY_SIZE(ierb_offset) +/* cache related transaction attributes for PCIe functions */ +#define ECAM_IERB_MSICAR (ECAM_IERB_BASE + 0xa400) +#define ECAM_IERB_MSICAR_VALUE 0x30
+/* offset of IERB config register per PCI function */ +static int ierb_offset[] = { + 0x0800, + 0x1800, + 0x2800, + 0x3800, + 0x4800, + 0x5800, + 0x6800, + ECAM_IERB_OFFSET_NA, + 0x0804, + 0x0808, + 0x1804, + 0x1808, +};
+/*
- Use a custom function for LS1028A, for now this is the only SoC
with IERB
- and we're currently considering reorganizing IERB for future SoCs.
- */
+static void set_ecam_icids(void) +{ + int i;
+ out_le32(ECAM_IERB_MSICAR, ECAM_IERB_MSICAR_VALUE);
+ for (i = 0; i < ECAM_IERB_FUNC_CNT; i++) { + if (ierb_offset[i] == ECAM_IERB_OFFSET_NA) + continue;
+ out_le32(ECAM_IERB_BASE + ierb_offset[i], + FSL_ECAM_STREAM_ID_START + i); + } +}
+#endif /* CONFIG_PCIE_ECAM_GENERIC */
int config_board_mux(void) { #if defined(CONFIG_TARGET_LS1028AQDS) && defined(CONFIG_FSL_QIXIS) @@ -88,6 +134,16 @@ int board_init(void) #endif
#endif
+ /* + * ICIDs for other hardware blocks are set really early on, before MMU + * is set up. For integrated PCI we need access to IERB which is not + * part of CCSR, so we have to wait for MMU mappings to be applied + */ +#ifdef CONFIG_PCIE_ECAM_GENERIC + set_ecam_icids(); +#endif
return 0; }
@@ -244,3 +300,53 @@ int checkboard(void) return 0; } #endif
+#ifdef CONFIG_PCIE_ECAM_GENERIC
+static int fdt_setprop_inplace_idx_u32(void *fdt, int nodeoffset, + const char *name, uint32_t idx, u32 val) +{ + val = cpu_to_be32(val); + return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, + strlen(name), + idx * sizeof(val), &val, + sizeof(val)); +}
+static int fdt_getprop_len(void *fdt, int nodeoffset, const char *name) +{ + int len;
+ if (fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), &len)) + return len;
+ return 0; +}
+void fdt_fixup_ecam(void *blob) +{ + int off;
+ off = fdt_node_offset_by_compatible(blob, 0, "pci-host-ecam-generic"); + if (off < 0) { + debug("ECAM node not found\n"); + return; + }
+ if (fdt_getprop_len(blob, off, "msi-map") != 16 || + fdt_getprop_len(blob, off, "iommu-map") != 16) { + log_err("invalid msi/iommu-map propertly size in ECAM node\n"); + return; + }
+ fdt_setprop_inplace_idx_u32(blob, off, "msi-map", 2, + FSL_ECAM_STREAM_ID_START); + fdt_setprop_inplace_idx_u32(blob, off, "msi-map", 3, + ECAM_IERB_FUNC_CNT);
+ fdt_setprop_inplace_idx_u32(blob, off, "iommu-map", 2, + FSL_ECAM_STREAM_ID_START); + fdt_setprop_inplace_idx_u32(blob, off, "iommu-map", 3, + ECAM_IERB_FUNC_CNT); +} +#endif /* CONFIG_PCIE_ECAM_GENERIC */
-michael _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
participants (4)
-
Alex Marginean
-
Alexandru Marginean
-
Bin Meng
-
Michael Walle