[U-Boot] [PATCHv3 1/2] pci: layerscape: add LS2088A series SoC pcie support

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
The LS2088A series SoCs has different physical memory map address and CCSR registers address against LS2080A series SoCs.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- V3: - no change
arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 46 +++++++++++++++++++++++++++++++++ drivers/pci/pcie_layerscape.c | 35 +++++++++++++++++++++++++ drivers/pci/pcie_layerscape.h | 8 ++++++ 3 files changed, 89 insertions(+)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index 335f225..6afb40f 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -89,6 +89,49 @@ static inline void early_mmu_setup(void) set_sctlr(get_sctlr() | CR_M); }
+static void fix_final_mmu_map(void) +{ +#ifdef CONFIG_LS2080A + unsigned int i; + u32 svr, ver; + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + + svr = gur_in32(&gur->svr); + ver = SVR_SOC_VER(svr); + + /* Fix PCIE base and size for LS2088A */ + if ((ver == SVR_LS2088A) || (ver == SVR_LS2084A) || + (ver == SVR_LS2048A) || (ver == SVR_LS2044A)) { + for (i = 0; i < ARRAY_SIZE(final_map); i++) { + switch (final_map[i].phys) { + case CONFIG_SYS_PCIE1_PHYS_ADDR: + final_map[i].phys = 0x2000000000ULL; + final_map[i].virt = 0x2000000000ULL; + final_map[i].size = 0x800000000ULL; + break; + case CONFIG_SYS_PCIE2_PHYS_ADDR: + final_map[i].phys = 0x2800000000ULL; + final_map[i].virt = 0x2800000000ULL; + final_map[i].size = 0x800000000ULL; + break; + case CONFIG_SYS_PCIE3_PHYS_ADDR: + final_map[i].phys = 0x3000000000ULL; + final_map[i].virt = 0x3000000000ULL; + final_map[i].size = 0x800000000ULL; + break; + case CONFIG_SYS_PCIE4_PHYS_ADDR: + final_map[i].phys = 0x3800000000ULL; + final_map[i].virt = 0x3800000000ULL; + final_map[i].size = 0x800000000ULL; + break; + default: + break; + } + } + } +#endif +} + /* * The final tables look similar to early tables, but different in detail. * These tables are in DRAM. Sub tables are added to enable cache for @@ -105,6 +148,9 @@ static inline void final_mmu_setup(void) int index; #endif
+ /* fix the final_map before filling in the block entries */ + fix_final_mmu_map(); + mem_map = final_map;
#ifdef CONFIG_SYS_MEM_RESERVE_SECURE diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index 90b9fe2..9a49898 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -167,6 +167,27 @@ static void ls_pcie_setup_atu(struct ls_pcie *pcie) pci_get_regions(pcie->bus, &io, &mem, &pref); idx = PCIE_ATU_REGION_INDEX1 + 1;
+ /* Fix the pcie memory map for LS2088A series SoCs */ + svr = (svr >> SVR_VAR_PER_SHIFT) & 0xFFFFFE; + if (svr == SVR_LS2088A || svr == SVR_LS2084A || + svr == SVR_LS2048A || svr == SVR_LS2044A) { + if (io) + io->phys_start = (io->phys_start & + (PCIE_PHYS_SIZE - 1)) + + LS2088A_PCIE1_PHYS_ADDR + + LS2088A_PCIE_PHYS_SIZE * pcie->idx; + if (mem) + mem->phys_start = (mem->phys_start & + (PCIE_PHYS_SIZE - 1)) + + LS2088A_PCIE1_PHYS_ADDR + + LS2088A_PCIE_PHYS_SIZE * pcie->idx; + if (pref) + pref->phys_start = (pref->phys_start & + (PCIE_PHYS_SIZE - 1)) + + LS2088A_PCIE1_PHYS_ADDR + + LS2088A_PCIE_PHYS_SIZE * pcie->idx; + } + if (io) /* ATU : OUTBOUND : IO */ ls_pcie_atu_outbound_set(pcie, idx++, @@ -442,6 +463,7 @@ static int ls_pcie_probe(struct udevice *dev) u8 header_type; u16 link_sta; bool ep_mode; + uint svr; int ret;
pcie->bus = dev; @@ -495,6 +517,19 @@ static int ls_pcie_probe(struct udevice *dev) return ret; }
+ /* + * Fix the pcie memory map address and PF control registers address + * for LS2088A series SoCs + */ + svr = get_svr(); + svr = (svr >> SVR_VAR_PER_SHIFT) & 0xFFFFFE; + if (svr == SVR_LS2088A || svr == SVR_LS2084A || + svr == SVR_LS2048A || svr == SVR_LS2044A) { + pcie->cfg_res.start = LS2088A_PCIE1_PHYS_ADDR + + LS2088A_PCIE_PHYS_SIZE * pcie->idx; + pcie->ctrl = pcie->lut + 0x40000; + } + pcie->cfg0 = map_physmem(pcie->cfg_res.start, fdt_resource_size(&pcie->cfg_res), MAP_NOCACHE); diff --git a/drivers/pci/pcie_layerscape.h b/drivers/pci/pcie_layerscape.h index 1e635ef..029695d 100644 --- a/drivers/pci/pcie_layerscape.h +++ b/drivers/pci/pcie_layerscape.h @@ -26,6 +26,10 @@ #define CONFIG_SYS_PCI_EP_MEMORY_BASE CONFIG_SYS_LOAD_ADDR #endif
+#define PCIE_PHYS_SIZE 0x200000000 +#define LS2088A_PCIE_PHYS_SIZE 0x800000000 +#define LS2088A_PCIE1_PHYS_ADDR 0x2000000000 + /* iATU registers */ #define PCIE_ATU_VIEWPORT 0x900 #define PCIE_ATU_REGION_INBOUND (0x1 << 31) @@ -107,6 +111,10 @@ #define SVR_LS102XA 0 #define SVR_VAR_PER_SHIFT 8 #define SVR_LS102XA_MASK 0x700 +#define SVR_LS2088A 0x870900 +#define SVR_LS2084A 0x870910 +#define SVR_LS2048A 0x870920 +#define SVR_LS2044A 0x870930
/* LS1021a PCIE space */ #define LS1021_PCIE_SPACE_OFFSET 0x4000000000ULL

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
There isn't LS2088A DT file, actually it reuse LS2080A DT file under u-boot, while under kernel there are DT files for LS2080A and LS2088A respectively with different PCIe node compatible string.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- V3: - removed unused variable.
drivers/pci/pcie_layerscape_fixup.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-)
diff --git a/drivers/pci/pcie_layerscape_fixup.c b/drivers/pci/pcie_layerscape_fixup.c index 19ede2f..64e461e 100644 --- a/drivers/pci/pcie_layerscape_fixup.c +++ b/drivers/pci/pcie_layerscape_fixup.c @@ -72,19 +72,26 @@ static void fdt_pcie_set_msi_map_entry(void *blob, struct ls_pcie *pcie, u32 *prop; u32 phandle; int nodeoffset; + uint svr; + char *compat = NULL;
/* find pci controller node */ nodeoffset = fdt_node_offset_by_compat_reg(blob, "fsl,ls-pcie", pcie->dbi_res.start); if (nodeoffset < 0) { #ifdef CONFIG_FSL_PCIE_COMPAT /* Compatible with older version of dts node */ - nodeoffset = fdt_node_offset_by_compat_reg(blob, - CONFIG_FSL_PCIE_COMPAT, pcie->dbi_res.start); + svr = (get_svr() >> SVR_VAR_PER_SHIFT) & 0xFFFFFE; + if (svr == SVR_LS2088A || svr == SVR_LS2084A || + svr == SVR_LS2048A || svr == SVR_LS2044A) + compat = "fsl,ls2088a-pcie"; + else + compat = CONFIG_FSL_PCIE_COMPAT; + if (compat) + nodeoffset = fdt_node_offset_by_compat_reg(blob, + compat, pcie->dbi_res.start); +#endif if (nodeoffset < 0) return; -#else - return; -#endif }
/* get phandle to MSI controller */ @@ -146,19 +153,25 @@ static void fdt_fixup_pcie(void *blob) static void ft_pcie_ls_setup(void *blob, struct ls_pcie *pcie) { int off; + uint svr; + char *compat = NULL;
off = fdt_node_offset_by_compat_reg(blob, "fsl,ls-pcie", pcie->dbi_res.start); if (off < 0) { #ifdef CONFIG_FSL_PCIE_COMPAT /* Compatible with older version of dts node */ - off = fdt_node_offset_by_compat_reg(blob, - CONFIG_FSL_PCIE_COMPAT, - pcie->dbi_res.start); + svr = (get_svr() >> SVR_VAR_PER_SHIFT) & 0xFFFFFE; + if (svr == SVR_LS2088A || svr == SVR_LS2084A || + svr == SVR_LS2048A || svr == SVR_LS2044A) + compat = "fsl,ls2088a-pcie"; + else + compat = CONFIG_FSL_PCIE_COMPAT; + if (compat) + off = fdt_node_offset_by_compat_reg(blob, + compat, pcie->dbi_res.start); +#endif if (off < 0) return; -#else - return; -#endif }
if (pcie->enabled)

On 03/02/2017 08:49 PM, Zhiqiang Hou wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
There isn't LS2088A DT file, actually it reuse LS2080A DT file under u-boot, while under kernel there are DT files for LS2080A and LS2088A respectively with different PCIe node compatible string.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
V3:
- removed unused variable.
Reformat commit message. Applied to fsl-qoriq master, awaiting upstream. Thanks.
York

On 03/02/2017 08:49 PM, Zhiqiang Hou wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
The LS2088A series SoCs has different physical memory map address and CCSR registers address against LS2080A series SoCs.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
V3:
- no change
Applied to fsl-qoriq master, awaiting upstream. Thanks.
York
participants (2)
-
york sun
-
Zhiqiang Hou