ls1028a: Configure stream IDs for integrated PCI and fix up Linux DT
authorAlex Marginean <alexandru.marginean@nxp.com>
Wed, 27 Nov 2019 15:19:32 +0000 (17:19 +0200)
committerPriyanka Jain <priyanka.jain@nxp.com>
Thu, 26 Dec 2019 10:30:20 +0000 (16:00 +0530)
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>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Michael Walle <michael@walle.cc>
Reviewed-by: Priyanka Jain <priyanka.jain@nxp.com>
arch/arm/cpu/armv8/fsl-layerscape/cpu.c
arch/arm/cpu/armv8/fsl-layerscape/fdt.c
arch/arm/cpu/armv8/fsl-layerscape/ls1028_ids.c
arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h

index 6c87c1b11accafd6f1af101d162dc06e2de3ed1a..639f5316498feac707a94b3c03c3bcb1691f65d8 100644 (file)
@@ -1101,6 +1101,12 @@ static void config_core_prefetch(void)
        }
 }
 
+#ifdef CONFIG_PCIE_ECAM_GENERIC
+__weak void set_ecam_icids(void)
+{
+}
+#endif
+
 int arch_early_init_r(void)
 {
 #ifdef CONFIG_SYS_FSL_ERRATUM_A009635
@@ -1152,6 +1158,9 @@ int arch_early_init_r(void)
 #endif
 #ifdef CONFIG_SYS_DPAA_QBMAN
        setup_qbman_portals();
+#endif
+#ifdef CONFIG_PCIE_ECAM_GENERIC
+       set_ecam_icids();
 #endif
        return 0;
 }
index e9932095932b1d537c944c539537f1ae3e4cad46..1e7e46e88a06459ad5444c679e7d3e2ef00b8101 100644 (file)
@@ -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
 }
index 9462298fbf9169114d428ba582c162ffde5419f3..8110412da60381d5b03d086871c71135110bb24b 100644 (file)
@@ -33,3 +33,96 @@ struct icid_id_table icid_tbl[] = {
 };
 
 int icid_tbl_sz = ARRAY_SIZE(icid_tbl);
+
+/* integrated PCI is handled separately as it's not part of CCSR/SCFG */
+#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.
+ */
+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);
+       }
+}
+
+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 */
index 94ea99a349d516e4c99cd04a576724f3b7209ac0..01d362d1836517b84360bee67c99252e8349ce48 100644 (file)
  *     -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:
 #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