summaryrefslogtreecommitdiff
path: root/arch/arm/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/cpu.c9
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/fdt.c9
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/ls1028_ids.c93
3 files changed, 111 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 6c87c1b11a..639f531649 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -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
@@ -1153,6 +1159,9 @@ int arch_early_init_r(void)
#ifdef CONFIG_SYS_DPAA_QBMAN
setup_qbman_portals();
#endif
+#ifdef CONFIG_PCIE_ECAM_GENERIC
+ set_ecam_icids();
+#endif
return 0;
}
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/cpu/armv8/fsl-layerscape/ls1028_ids.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1028_ids.c
index 9462298fbf..8110412da6 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/ls1028_ids.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1028_ids.c
@@ -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 */