[PATCH 1/9] pci: layerscape: Split the EP and RC driver

Z.q. Hou zhiqiang.hou at nxp.com
Tue Apr 28 14:23:23 CEST 2020



> -----Original Message-----
> From: Xiaowei Bao <xiaowei.bao at nxp.com>
> Sent: 2020年3月22日 19:13
> To: M.h. Lian <minghuan.lian at nxp.com>; Z.q. Hou
> <zhiqiang.hou at nxp.com>; Mingkai Hu <mingkai.hu at nxp.com>;
> bmeng.cn at gmail.com; yamada.masahiro at socionext.com;
> u-boot at lists.denx.de
> Cc: Xiaowei Bao <xiaowei.bao at nxp.com>
> Subject: [PATCH 1/9] pci: layerscape: Split the EP and RC driver
> 
> Split the RC and EP driver, and reimplement the EP driver base on the EP
> framework.
> 
> Signed-off-by: Xiaowei Bao <xiaowei.bao at nxp.com>
> ---
>  drivers/pci/Makefile                |   2 +-
>  drivers/pci/pcie_layerscape.c       | 492 +++---------------------------------
>  drivers/pci/pcie_layerscape.h       |  44 +++-
>  drivers/pci/pcie_layerscape_ep.c    | 240 ++++++++++++++++++
>  drivers/pci/pcie_layerscape_fixup.c |  79 +++---
>  drivers/pci/pcie_layerscape_rc.c    | 378
> +++++++++++++++++++++++++++
>  6 files changed, 734 insertions(+), 501 deletions(-)  create mode 100644
> drivers/pci/pcie_layerscape_ep.c  create mode 100644
> drivers/pci/pcie_layerscape_rc.c
> 
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index
> c051ecc..440b5af 100644
> --- a/drivers/pci/Makefile
> +++ b/drivers/pci/Makefile
> @@ -33,7 +33,7 @@ obj-$(CONFIG_PCI_TEGRA) += pci_tegra.o
>  obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
>  obj-$(CONFIG_PCIE_DW_MVEBU) += pcie_dw_mvebu.o
>  obj-$(CONFIG_PCIE_FSL) += pcie_fsl.o pcie_fsl_fixup.o
> -obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
> +obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
> pcie_layerscape_rc.o
> +pcie_layerscape_ep.o
>  obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape_fixup.o
> pcie_layerscape_fixup_common.o
>  obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie_layerscape_gen4.o \
>  				pcie_layerscape_gen4_fixup.o \
> diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c
> index 2ab67d1..3ca75c5 100644
> --- a/drivers/pci/pcie_layerscape.c
> +++ b/drivers/pci/pcie_layerscape.c
> @@ -1,39 +1,32 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
> - * Copyright 2017-2019 NXP
> + * Copyright 2017-2020 NXP
>   * Copyright 2014-2015 Freescale Semiconductor, Inc.
>   * Layerscape PCIe driver
>   */
> 
>  #include <common.h>
> -#include <asm/arch/fsl_serdes.h>
> -#include <pci.h>
>  #include <asm/io.h>
>  #include <errno.h>
>  #include <malloc.h>
> -#include <dm.h>
> -#if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \
> -	defined(CONFIG_ARM)
> -#include <asm/arch/clock.h>
> -#endif
>  #include "pcie_layerscape.h"
> 
>  DECLARE_GLOBAL_DATA_PTR;
> 
>  LIST_HEAD(ls_pcie_list);
> 
> -static unsigned int dbi_readl(struct ls_pcie *pcie, unsigned int offset)
> +unsigned int dbi_readl(struct ls_pcie *pcie, unsigned int offset)
>  {
>  	return in_le32(pcie->dbi + offset);
>  }
> 
> -static void dbi_writel(struct ls_pcie *pcie, unsigned int value,
> -		       unsigned int offset)
> +void dbi_writel(struct ls_pcie *pcie, unsigned int value,
> +		unsigned int offset)
>  {
>  	out_le32(pcie->dbi + offset, value);
>  }
> 
> -static unsigned int ctrl_readl(struct ls_pcie *pcie, unsigned int offset)
> +unsigned int ctrl_readl(struct ls_pcie *pcie, unsigned int offset)
>  {
>  	if (pcie->big_endian)
>  		return in_be32(pcie->ctrl + offset);
> @@ -41,8 +34,8 @@ static unsigned int ctrl_readl(struct ls_pcie *pcie,
> unsigned int offset)
>  		return in_le32(pcie->ctrl + offset);
>  }
> 
> -static void ctrl_writel(struct ls_pcie *pcie, unsigned int value,
> -			unsigned int offset)
> +void ctrl_writel(struct ls_pcie *pcie, unsigned int value,
> +		 unsigned int offset)
>  {
>  	if (pcie->big_endian)
>  		out_be32(pcie->ctrl + offset, value); @@ -50,6 +43,26 @@ static
> void ctrl_writel(struct ls_pcie *pcie, unsigned int value,
>  		out_le32(pcie->ctrl + offset, value);  }
> 
> +void ls_pcie_dbi_ro_wr_en(struct ls_pcie *pcie) {
> +	u32 reg, val;
> +
> +	reg = PCIE_MISC_CONTROL_1_OFF;
> +	val = dbi_readl(pcie, reg);
> +	val |= PCIE_DBI_RO_WR_EN;
> +	dbi_writel(pcie, val, reg);
> +}
> +
> +void ls_pcie_dbi_ro_wr_dis(struct ls_pcie *pcie) {
> +	u32 reg, val;
> +
> +	reg = PCIE_MISC_CONTROL_1_OFF;
> +	val = dbi_readl(pcie, reg);
> +	val &= ~PCIE_DBI_RO_WR_EN;
> +	dbi_writel(pcie, val, reg);
> +}
> +
>  static int ls_pcie_ltssm(struct ls_pcie *pcie)  {
>  	u32 state;
> @@ -66,7 +79,7 @@ static int ls_pcie_ltssm(struct ls_pcie *pcie)
>  	return state;
>  }
> 
> -static int ls_pcie_link_up(struct ls_pcie *pcie)
> +int ls_pcie_link_up(struct ls_pcie *pcie)
>  {
>  	int ltssm;
> 
> @@ -77,22 +90,8 @@ static int ls_pcie_link_up(struct ls_pcie *pcie)
>  	return 1;
>  }
> 
> -static void ls_pcie_cfg0_set_busdev(struct ls_pcie *pcie, u32 busdev) -{
> -	dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND |
> PCIE_ATU_REGION_INDEX0,
> -		   PCIE_ATU_VIEWPORT);
> -	dbi_writel(pcie, busdev, PCIE_ATU_LOWER_TARGET);
> -}
> -
> -static void ls_pcie_cfg1_set_busdev(struct ls_pcie *pcie, u32 busdev) -{
> -	dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND |
> PCIE_ATU_REGION_INDEX1,
> -		   PCIE_ATU_VIEWPORT);
> -	dbi_writel(pcie, busdev, PCIE_ATU_LOWER_TARGET);
> -}
> -
> -static void ls_pcie_atu_outbound_set(struct ls_pcie *pcie, int idx, int type,
> -				      u64 phys, u64 bus_addr, pci_size_t size)
> +void ls_pcie_atu_outbound_set(struct ls_pcie *pcie, int idx, int type,
> +			      u64 phys, u64 bus_addr, pci_size_t size)
>  {
>  	dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND | idx,
> PCIE_ATU_VIEWPORT);
>  	dbi_writel(pcie, (u32)phys, PCIE_ATU_LOWER_BASE); @@ -105,18
> +104,18 @@ static void ls_pcie_atu_outbound_set(struct ls_pcie *pcie, int
> idx, int type,  }
> 
>  /* Use bar match mode and MEM type as default */ -static void
> ls_pcie_atu_inbound_set(struct ls_pcie *pcie, int idx,
> -				     int bar, u64 phys)
> +void ls_pcie_atu_inbound_set(struct ls_pcie *pcie, int idx, int type,
> +			     int bar, u64 phys)
>  {
>  	dbi_writel(pcie, PCIE_ATU_REGION_INBOUND | idx,
> PCIE_ATU_VIEWPORT);
>  	dbi_writel(pcie, (u32)phys, PCIE_ATU_LOWER_TARGET);
>  	dbi_writel(pcie, phys >> 32, PCIE_ATU_UPPER_TARGET);
> -	dbi_writel(pcie, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1);
> +	dbi_writel(pcie, type, PCIE_ATU_CR1);
>  	dbi_writel(pcie, PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE |
>  		   PCIE_ATU_BAR_NUM(bar), PCIE_ATU_CR2);  }
> 
> -static void ls_pcie_dump_atu(struct ls_pcie *pcie)
> +void ls_pcie_dump_atu(struct ls_pcie *pcie)
>  {
>  	int i;
> 
> @@ -133,431 +132,10 @@ static void ls_pcie_dump_atu(struct ls_pcie
> *pcie)
>  		debug("\tUPPER BUS  0x%08x\n",
>  		      dbi_readl(pcie, PCIE_ATU_UPPER_TARGET));
>  		debug("\tLIMIT      0x%08x\n",
> -		      readl(pcie->dbi + PCIE_ATU_LIMIT));
> +		      dbi_readl(pcie, PCIE_ATU_LIMIT));
>  		debug("\tCR1        0x%08x\n",
>  		      dbi_readl(pcie, PCIE_ATU_CR1));
>  		debug("\tCR2        0x%08x\n",
>  		      dbi_readl(pcie, PCIE_ATU_CR2));
>  	}
>  }
> -
> -static void ls_pcie_setup_atu(struct ls_pcie *pcie) -{
> -	struct pci_region *io, *mem, *pref;
> -	unsigned long long offset = 0;
> -	int idx = 0;
> -	uint svr;
> -
> -	svr = get_svr();
> -	if (((svr >> SVR_VAR_PER_SHIFT) & SVR_LS102XA_MASK) ==
> SVR_LS102XA) {
> -		offset = LS1021_PCIE_SPACE_OFFSET +
> -			 LS1021_PCIE_SPACE_SIZE * pcie->idx;
> -	}
> -
> -	/* ATU 0 : OUTBOUND : CFG0 */
> -	ls_pcie_atu_outbound_set(pcie, PCIE_ATU_REGION_INDEX0,
> -				 PCIE_ATU_TYPE_CFG0,
> -				 pcie->cfg_res.start + offset,
> -				 0,
> -				 fdt_resource_size(&pcie->cfg_res) / 2);
> -	/* ATU 1 : OUTBOUND : CFG1 */
> -	ls_pcie_atu_outbound_set(pcie, PCIE_ATU_REGION_INDEX1,
> -				 PCIE_ATU_TYPE_CFG1,
> -				 pcie->cfg_res.start + offset +
> -				 fdt_resource_size(&pcie->cfg_res) / 2,
> -				 0,
> -				 fdt_resource_size(&pcie->cfg_res) / 2);
> -
> -	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 ||
> -	    svr == SVR_LS2081A || svr == SVR_LS2041A) {
> -		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++,
> -					 PCIE_ATU_TYPE_IO,
> -					 io->phys_start + offset,
> -					 io->bus_start,
> -					 io->size);
> -
> -	if (mem)
> -		/* ATU : OUTBOUND : MEM */
> -		ls_pcie_atu_outbound_set(pcie, idx++,
> -					 PCIE_ATU_TYPE_MEM,
> -					 mem->phys_start + offset,
> -					 mem->bus_start,
> -					 mem->size);
> -
> -	if (pref)
> -		/* ATU : OUTBOUND : pref */
> -		ls_pcie_atu_outbound_set(pcie, idx++,
> -					 PCIE_ATU_TYPE_MEM,
> -					 pref->phys_start + offset,
> -					 pref->bus_start,
> -					 pref->size);
> -
> -	ls_pcie_dump_atu(pcie);
> -}
> -
> -/* Return 0 if the address is valid, -errno if not valid */ -static int
> ls_pcie_addr_valid(struct ls_pcie *pcie, pci_dev_t bdf) -{
> -	struct udevice *bus = pcie->bus;
> -
> -	if (pcie->mode == PCI_HEADER_TYPE_NORMAL)
> -		return -ENODEV;
> -
> -	if (!pcie->enabled)
> -		return -ENXIO;
> -
> -	if (PCI_BUS(bdf) < bus->seq)
> -		return -EINVAL;
> -
> -	if ((PCI_BUS(bdf) > bus->seq) && (!ls_pcie_link_up(pcie)))
> -		return -EINVAL;
> -
> -	if (PCI_BUS(bdf) <= (bus->seq + 1) && (PCI_DEV(bdf) > 0))
> -		return -EINVAL;
> -
> -	return 0;
> -}
> -
> -int ls_pcie_conf_address(struct udevice *bus, pci_dev_t bdf,
> -			 uint offset, void **paddress)
> -{
> -	struct ls_pcie *pcie = dev_get_priv(bus);
> -	u32 busdev;
> -
> -	if (ls_pcie_addr_valid(pcie, bdf))
> -		return -EINVAL;
> -
> -	if (PCI_BUS(bdf) == bus->seq) {
> -		*paddress = pcie->dbi + offset;
> -		return 0;
> -	}
> -
> -	busdev = PCIE_ATU_BUS(PCI_BUS(bdf) - bus->seq) |
> -		 PCIE_ATU_DEV(PCI_DEV(bdf)) |
> -		 PCIE_ATU_FUNC(PCI_FUNC(bdf));
> -
> -	if (PCI_BUS(bdf) == bus->seq + 1) {
> -		ls_pcie_cfg0_set_busdev(pcie, busdev);
> -		*paddress = pcie->cfg0 + offset;
> -	} else {
> -		ls_pcie_cfg1_set_busdev(pcie, busdev);
> -		*paddress = pcie->cfg1 + offset;
> -	}
> -	return 0;
> -}
> -
> -static int ls_pcie_read_config(struct udevice *bus, pci_dev_t bdf,
> -			       uint offset, ulong *valuep,
> -			       enum pci_size_t size)
> -{
> -	return pci_generic_mmap_read_config(bus, ls_pcie_conf_address,
> -					    bdf, offset, valuep, size);
> -}
> -
> -static int ls_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
> -				uint offset, ulong value,
> -				enum pci_size_t size)
> -{
> -	return pci_generic_mmap_write_config(bus, ls_pcie_conf_address,
> -					     bdf, offset, value, size);
> -}
> -
> -/* Clear multi-function bit */
> -static void ls_pcie_clear_multifunction(struct ls_pcie *pcie) -{
> -	writeb(PCI_HEADER_TYPE_BRIDGE, pcie->dbi + PCI_HEADER_TYPE);
> -}
> -
> -/* Fix class value */
> -static void ls_pcie_fix_class(struct ls_pcie *pcie) -{
> -	writew(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE);
> -}
> -
> -/* Drop MSG TLP except for Vendor MSG */ -static void
> ls_pcie_drop_msg_tlp(struct ls_pcie *pcie) -{
> -	u32 val;
> -
> -	val = dbi_readl(pcie, PCIE_STRFMR1);
> -	val &= 0xDFFFFFFF;
> -	dbi_writel(pcie, val, PCIE_STRFMR1);
> -}
> -
> -/* Disable all bars in RC mode */
> -static void ls_pcie_disable_bars(struct ls_pcie *pcie) -{
> -	dbi_writel(pcie, 0, PCIE_CS2_OFFSET + PCI_BASE_ADDRESS_0);
> -	dbi_writel(pcie, 0, PCIE_CS2_OFFSET + PCI_BASE_ADDRESS_1);
> -	dbi_writel(pcie, 0xfffffffe, PCIE_CS2_OFFSET + PCI_ROM_ADDRESS1);
> -}
> -
> -static void ls_pcie_setup_ctrl(struct ls_pcie *pcie) -{
> -	ls_pcie_setup_atu(pcie);
> -
> -	dbi_writel(pcie, 1, PCIE_DBI_RO_WR_EN);
> -	ls_pcie_fix_class(pcie);
> -	ls_pcie_clear_multifunction(pcie);
> -	ls_pcie_drop_msg_tlp(pcie);
> -	dbi_writel(pcie, 0, PCIE_DBI_RO_WR_EN);
> -
> -	ls_pcie_disable_bars(pcie);
> -	pcie->stream_id_cur = 0;
> -}
> -
> -static void ls_pcie_ep_setup_atu(struct ls_pcie *pcie) -{
> -	u64 phys = CONFIG_SYS_PCI_EP_MEMORY_BASE;
> -
> -	/* ATU 0 : INBOUND : map BAR0 */
> -	ls_pcie_atu_inbound_set(pcie, 0, 0, phys);
> -	/* ATU 1 : INBOUND : map BAR1 */
> -	phys += PCIE_BAR1_SIZE;
> -	ls_pcie_atu_inbound_set(pcie, 1, 1, phys);
> -	/* ATU 2 : INBOUND : map BAR2 */
> -	phys += PCIE_BAR2_SIZE;
> -	ls_pcie_atu_inbound_set(pcie, 2, 2, phys);
> -	/* ATU 3 : INBOUND : map BAR4 */
> -	phys = CONFIG_SYS_PCI_EP_MEMORY_BASE + PCIE_BAR4_SIZE;
> -	ls_pcie_atu_inbound_set(pcie, 3, 4, phys);
> -
> -	/* ATU 0 : OUTBOUND : map MEM */
> -	ls_pcie_atu_outbound_set(pcie, 0,
> -				 PCIE_ATU_TYPE_MEM,
> -				 pcie->cfg_res.start,
> -				 0,
> -				 CONFIG_SYS_PCI_MEMORY_SIZE);
> -}
> -
> -/* BAR0 and BAR1 are 32bit BAR2 and BAR4 are 64bit */ -static void
> ls_pcie_ep_setup_bar(void *bar_base, int bar, u32 size) -{
> -	/* The least inbound window is 4KiB */
> -	if (size < 4 * 1024)
> -		return;
> -
> -	switch (bar) {
> -	case 0:
> -		writel(size - 1, bar_base + PCI_BASE_ADDRESS_0);
> -		break;
> -	case 1:
> -		writel(size - 1, bar_base + PCI_BASE_ADDRESS_1);
> -		break;
> -	case 2:
> -		writel(size - 1, bar_base + PCI_BASE_ADDRESS_2);
> -		writel(0, bar_base + PCI_BASE_ADDRESS_3);
> -		break;
> -	case 4:
> -		writel(size - 1, bar_base + PCI_BASE_ADDRESS_4);
> -		writel(0, bar_base + PCI_BASE_ADDRESS_5);
> -		break;
> -	default:
> -		break;
> -	}
> -}
> -
> -static void ls_pcie_ep_setup_bars(void *bar_base) -{
> -	/* BAR0 - 32bit - 4K configuration */
> -	ls_pcie_ep_setup_bar(bar_base, 0, PCIE_BAR0_SIZE);
> -	/* BAR1 - 32bit - 8K MSIX*/
> -	ls_pcie_ep_setup_bar(bar_base, 1, PCIE_BAR1_SIZE);
> -	/* BAR2 - 64bit - 4K MEM desciptor */
> -	ls_pcie_ep_setup_bar(bar_base, 2, PCIE_BAR2_SIZE);
> -	/* BAR4 - 64bit - 1M MEM*/
> -	ls_pcie_ep_setup_bar(bar_base, 4, PCIE_BAR4_SIZE);
> -}
> -
> -static void ls_pcie_ep_enable_cfg(struct ls_pcie *pcie) -{
> -	u32 config;
> -
> -	config = ctrl_readl(pcie,  PCIE_PF_CONFIG);
> -	config |= PCIE_CONFIG_READY;
> -	ctrl_writel(pcie, config, PCIE_PF_CONFIG);
> -}
> -
> -static void ls_pcie_setup_ep(struct ls_pcie *pcie) -{
> -	u32 sriov;
> -
> -	sriov = readl(pcie->dbi + PCIE_SRIOV);
> -	if (PCI_EXT_CAP_ID(sriov) == PCI_EXT_CAP_ID_SRIOV) {
> -		int pf, vf;
> -
> -		for (pf = 0; pf < PCIE_PF_NUM; pf++) {
> -			for (vf = 0; vf <= PCIE_VF_NUM; vf++) {
> -				ctrl_writel(pcie, PCIE_LCTRL0_VAL(pf, vf),
> -					    PCIE_PF_VF_CTRL);
> -
> -				ls_pcie_ep_setup_bars(pcie->dbi);
> -				ls_pcie_ep_setup_atu(pcie);
> -			}
> -		}
> -		/* Disable CFG2 */
> -		ctrl_writel(pcie, 0, PCIE_PF_VF_CTRL);
> -	} else {
> -		ls_pcie_ep_setup_bars(pcie->dbi + PCIE_NO_SRIOV_BAR_BASE);
> -		ls_pcie_ep_setup_atu(pcie);
> -	}
> -
> -	ls_pcie_ep_enable_cfg(pcie);
> -}
> -
> -static int ls_pcie_probe(struct udevice *dev) -{
> -	struct ls_pcie *pcie = dev_get_priv(dev);
> -	const void *fdt = gd->fdt_blob;
> -	int node = dev_of_offset(dev);
> -	u16 link_sta;
> -	uint svr;
> -	int ret;
> -	fdt_size_t cfg_size;
> -
> -	pcie->bus = dev;
> -
> -	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> -				     "dbi", &pcie->dbi_res);
> -	if (ret) {
> -		printf("ls-pcie: resource \"dbi\" not found\n");
> -		return ret;
> -	}
> -
> -	pcie->idx = (pcie->dbi_res.start - PCIE_SYS_BASE_ADDR) /
> PCIE_CCSR_SIZE;
> -
> -	list_add(&pcie->list, &ls_pcie_list);
> -
> -	pcie->enabled = is_serdes_configured(PCIE_SRDS_PRTCL(pcie->idx));
> -	if (!pcie->enabled) {
> -		printf("PCIe%d: %s disabled\n", pcie->idx, dev->name);
> -		return 0;
> -	}
> -
> -	pcie->dbi = map_physmem(pcie->dbi_res.start,
> -				fdt_resource_size(&pcie->dbi_res),
> -				MAP_NOCACHE);
> -
> -	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> -				     "lut", &pcie->lut_res);
> -	if (!ret)
> -		pcie->lut = map_physmem(pcie->lut_res.start,
> -					fdt_resource_size(&pcie->lut_res),
> -					MAP_NOCACHE);
> -
> -	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> -				     "ctrl", &pcie->ctrl_res);
> -	if (!ret)
> -		pcie->ctrl = map_physmem(pcie->ctrl_res.start,
> -					 fdt_resource_size(&pcie->ctrl_res),
> -					 MAP_NOCACHE);
> -	if (!pcie->ctrl)
> -		pcie->ctrl = pcie->lut;
> -
> -	if (!pcie->ctrl) {
> -		printf("%s: NOT find CTRL\n", dev->name);
> -		return -1;
> -	}
> -
> -	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> -				     "config", &pcie->cfg_res);
> -	if (ret) {
> -		printf("%s: resource \"config\" not found\n", dev->name);
> -		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 ||
> -	    svr == SVR_LS2081A || svr == SVR_LS2041A) {
> -		cfg_size = fdt_resource_size(&pcie->cfg_res);
> -		pcie->cfg_res.start = LS2088A_PCIE1_PHYS_ADDR +
> -					LS2088A_PCIE_PHYS_SIZE * pcie->idx;
> -		pcie->cfg_res.end = pcie->cfg_res.start + cfg_size;
> -		pcie->ctrl = pcie->lut + 0x40000;
> -	}
> -
> -	pcie->cfg0 = map_physmem(pcie->cfg_res.start,
> -				 fdt_resource_size(&pcie->cfg_res),
> -				 MAP_NOCACHE);
> -	pcie->cfg1 = pcie->cfg0 + fdt_resource_size(&pcie->cfg_res) / 2;
> -
> -	pcie->big_endian = fdtdec_get_bool(fdt, node, "big-endian");
> -
> -	debug("%s dbi:%lx lut:%lx ctrl:0x%lx cfg0:0x%lx, big-endian:%d\n",
> -	      dev->name, (unsigned long)pcie->dbi, (unsigned long)pcie->lut,
> -	      (unsigned long)pcie->ctrl, (unsigned long)pcie->cfg0,
> -	      pcie->big_endian);
> -
> -	pcie->mode = readb(pcie->dbi + PCI_HEADER_TYPE) & 0x7f;
> -
> -	if (pcie->mode == PCI_HEADER_TYPE_NORMAL) {
> -		printf("PCIe%u: %s %s", pcie->idx, dev->name, "Endpoint");
> -			ls_pcie_setup_ep(pcie);
> -	} else {
> -		printf("PCIe%u: %s %s", pcie->idx, dev->name, "Root Complex");
> -			ls_pcie_setup_ctrl(pcie);
> -	}
> -
> -	if (!ls_pcie_link_up(pcie)) {
> -		/* Let the user know there's no PCIe link */
> -		printf(": no link\n");
> -		return 0;
> -	}
> -
> -	/* Print the negotiated PCIe link width */
> -	link_sta = readw(pcie->dbi + PCIE_LINK_STA);
> -	printf(": x%d gen%d\n", (link_sta & PCIE_LINK_WIDTH_MASK) >> 4,
> -	       link_sta & PCIE_LINK_SPEED_MASK);
> -
> -	return 0;
> -}
> -
> -static const struct dm_pci_ops ls_pcie_ops = {
> -	.read_config	= ls_pcie_read_config,
> -	.write_config	= ls_pcie_write_config,
> -};
> -
> -static const struct udevice_id ls_pcie_ids[] = {
> -	{ .compatible = "fsl,ls-pcie" },
> -	{ }
> -};
> -
> -U_BOOT_DRIVER(pci_layerscape) = {
> -	.name = "pci_layerscape",
> -	.id = UCLASS_PCI,
> -	.of_match = ls_pcie_ids,
> -	.ops = &ls_pcie_ops,
> -	.probe	= ls_pcie_probe,
> -	.priv_auto_alloc_size = sizeof(struct ls_pcie),
> -};
> diff --git a/drivers/pci/pcie_layerscape.h b/drivers/pci/pcie_layerscape.h
> index 95454bc..217dcda 100644
> --- a/drivers/pci/pcie_layerscape.h
> +++ b/drivers/pci/pcie_layerscape.h
> @@ -1,6 +1,6 @@
>  /* SPDX-License-Identifier: GPL-2.0+ */
>  /*
> - * Copyright 2017-2019 NXP
> + * Copyright 2017-2020 NXP
>   * Copyright 2014-2015 Freescale Semiconductor, Inc.
>   * Layerscape PCIe driver
>   */
> @@ -60,7 +60,8 @@
>  /* DBI registers */
>  #define PCIE_SRIOV		0x178
>  #define PCIE_STRFMR1		0x71c /* Symbol Timer & Filter Mask
> Register1 */
> -#define PCIE_DBI_RO_WR_EN	0x8bc
> +#define PCIE_DBI_RO_WR_EN		BIT(0)
> +#define PCIE_MISC_CONTROL_1_OFF         0x8BC
> 
>  #define PCIE_LINK_CAP		0x7c
>  #define PCIE_LINK_SPEED_MASK	0xf
> @@ -82,7 +83,7 @@
>  				 PCIE_LCTRL0_CFG2_ENABLE)
> 
>  #define PCIE_NO_SRIOV_BAR_BASE	0x1000
> -
> +#define FSL_PCIE_EP_MIN_APERTURE        4096     /* 4 Kbytes */
>  #define PCIE_PF_NUM		2
>  #define PCIE_VF_NUM		64
> 
> @@ -129,25 +130,52 @@
>  #define LS1021_LTSSM_STATE_SHIFT	20
> 
>  struct ls_pcie {
> +	void __iomem *dbi;
> +	void __iomem *lut;
> +	void __iomem *ctrl;
>  	int idx;
> +	bool big_endian;
> +	int mode;
> +};
> +
> +struct ls_pcie_rc {
> +	struct ls_pcie *pcie;
>  	struct list_head list;
>  	struct udevice *bus;
>  	struct fdt_resource dbi_res;
>  	struct fdt_resource lut_res;
>  	struct fdt_resource ctrl_res;
>  	struct fdt_resource cfg_res;
> -	void __iomem *dbi;
> -	void __iomem *lut;
> -	void __iomem *ctrl;
>  	void __iomem *cfg0;
>  	void __iomem *cfg1;
> -	bool big_endian;
>  	bool enabled;
>  	int next_lut_index;
>  	int stream_id_cur;
> -	int mode;
> +};
> +
> +struct ls_pcie_ep {
> +	struct fdt_resource addr_res;
> +	struct ls_pcie *pcie;
> +	struct udevice *bus;
> +	void __iomem *addr;
> +	u32 num_ib_wins;
> +	u32 num_ob_wins;
> +	u8 max_functions;
>  };
> 
>  extern struct list_head ls_pcie_list;
> 
> +unsigned int dbi_readl(struct ls_pcie *pcie, unsigned int offset); void
> +dbi_writel(struct ls_pcie *pcie, unsigned int value, unsigned int
> +offset); unsigned int ctrl_readl(struct ls_pcie *pcie, unsigned int
> +offset); void ctrl_writel(struct ls_pcie *pcie, unsigned int value,
> +unsigned int offset); void ls_pcie_atu_outbound_set(struct ls_pcie *pcie, int
> idx, int type,
> +			      u64 phys, u64 bus_addr, pci_size_t size); void
> +ls_pcie_atu_inbound_set(struct ls_pcie *pcie, int idx, int type,
> +			     int bar, u64 phys);
> +void ls_pcie_dump_atu(struct ls_pcie *pcie); int ls_pcie_link_up(struct
> +ls_pcie *pcie); void ls_pcie_dbi_ro_wr_en(struct ls_pcie *pcie); void
> +ls_pcie_dbi_ro_wr_dis(struct ls_pcie *pcie);
> +
>  #endif /* _PCIE_LAYERSCAPE_H_ */
> diff --git a/drivers/pci/pcie_layerscape_ep.c
> b/drivers/pci/pcie_layerscape_ep.c
> new file mode 100644
> index 0000000..8d0c99a
> --- /dev/null
> +++ b/drivers/pci/pcie_layerscape_ep.c
> @@ -0,0 +1,240 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2020 NXP
> + * Layerscape PCIe EP driver
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <pci_ep.h>
> +#include <asm/io.h>
> +#include <linux/sizes.h>
> +#include <linux/log2.h>
> +#include "pcie_layerscape.h"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static void ls_pcie_ep_enable_cfg(struct ls_pcie_ep *pcie_ep) {
> +	struct ls_pcie *pcie = pcie_ep->pcie;
> +	u32 config;
> +
> +	config = ctrl_readl(pcie,  PCIE_PF_CONFIG);
> +	config |= PCIE_CONFIG_READY;
> +	ctrl_writel(pcie, config, PCIE_PF_CONFIG); }
> +
> +static int ls_ep_set_bar(struct udevice *dev, uint fn, struct pci_bar
> +*ep_bar) {
> +	struct ls_pcie_ep *pcie_ep = dev_get_priv(dev);
> +	struct ls_pcie *pcie = pcie_ep->pcie;
> +	dma_addr_t bar_phys = ep_bar->phys_addr;
> +	enum pci_barno bar = ep_bar->barno;
> +	u32 reg = PCI_BASE_ADDRESS_0 + (4 * bar);
> +	int flags = ep_bar->flags;
> +	int type, idx;
> +	u64 size;
> +
> +	idx  = bar;
> +	/* BAR size is 2^(aperture + 11) */
> +	size = max_t(size_t, ep_bar->size, FSL_PCIE_EP_MIN_APERTURE);
> +
> +	if (!(flags & PCI_BASE_ADDRESS_SPACE))
> +		type = PCIE_ATU_TYPE_MEM;
> +	else
> +		type = PCIE_ATU_TYPE_IO;
> +
> +	ls_pcie_atu_inbound_set(pcie, idx, bar, bar_phys, type);
> +
> +	dbi_writel(pcie, lower_32_bits(size - 1), reg +
> PCIE_NO_SRIOV_BAR_BASE);
> +	dbi_writel(pcie, flags, reg);
> +
> +	if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64) {
> +		dbi_writel(pcie, upper_32_bits(size - 1),
> +			   reg + 4 + PCIE_NO_SRIOV_BAR_BASE);
> +		dbi_writel(pcie, 0, reg + 4);
> +	}
> +
> +	return 0;
> +}
> +
> +static struct pci_ep_ops ls_pcie_ep_ops = {
> +	.set_bar = ls_ep_set_bar,
> +};
> +
> +static void ls_pcie_ep_setup_atu(struct ls_pcie_ep *pcie_ep) {
> +	struct ls_pcie *pcie = pcie_ep->pcie;
> +	u64 phys = CONFIG_SYS_PCI_EP_MEMORY_BASE;
> +
> +	/* ATU 0 : INBOUND : map BAR0 */
> +	ls_pcie_atu_inbound_set(pcie, 0, PCIE_ATU_TYPE_MEM, 0, phys);
> +	/* ATU 1 : INBOUND : map BAR1 */
> +	phys += PCIE_BAR1_SIZE;
> +	ls_pcie_atu_inbound_set(pcie, 1, PCIE_ATU_TYPE_MEM, 1, phys);
> +	/* ATU 2 : INBOUND : map BAR2 */
> +	phys += PCIE_BAR2_SIZE;
> +	ls_pcie_atu_inbound_set(pcie, 2, PCIE_ATU_TYPE_MEM, 2, phys);
> +	/* ATU 3 : INBOUND : map BAR4 */
> +	phys = CONFIG_SYS_PCI_EP_MEMORY_BASE + PCIE_BAR4_SIZE;
> +	ls_pcie_atu_inbound_set(pcie, 3, PCIE_ATU_TYPE_MEM, 4, phys);
> +
> +	/* ATU 0 : OUTBOUND : map MEM */
> +	ls_pcie_atu_outbound_set(pcie, 0,
> +				 PCIE_ATU_TYPE_MEM,
> +				 pcie_ep->addr_res.start,
> +				 0,
> +				 CONFIG_SYS_PCI_MEMORY_SIZE);
> +}
> +
> +/* BAR0 and BAR1 are 32bit BAR2 and BAR4 are 64bit */ static void
> +ls_pcie_ep_setup_bar(void *bar_base, int bar, u32 size) {
> +	/* The least inbound window is 4KiB */
> +	if (size < 4 * 1024)
> +		return;
> +
> +	switch (bar) {
> +	case 0:
> +		writel(size - 1, bar_base + PCI_BASE_ADDRESS_0);
> +		break;
> +	case 1:
> +		writel(size - 1, bar_base + PCI_BASE_ADDRESS_1);
> +		break;
> +	case 2:
> +		writel(size - 1, bar_base + PCI_BASE_ADDRESS_2);
> +		writel(0, bar_base + PCI_BASE_ADDRESS_3);
> +		break;
> +	case 4:
> +		writel(size - 1, bar_base + PCI_BASE_ADDRESS_4);
> +		writel(0, bar_base + PCI_BASE_ADDRESS_5);
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +static void ls_pcie_ep_setup_bars(void *bar_base) {
> +	/* BAR0 - 32bit - 4K configuration */
> +	ls_pcie_ep_setup_bar(bar_base, 0, PCIE_BAR0_SIZE);
> +	/* BAR1 - 32bit - 8K MSIX */
> +	ls_pcie_ep_setup_bar(bar_base, 1, PCIE_BAR1_SIZE);
> +	/* BAR2 - 64bit - 4K MEM descriptor */
> +	ls_pcie_ep_setup_bar(bar_base, 2, PCIE_BAR2_SIZE);
> +	/* BAR4 - 64bit - 1M MEM */
> +	ls_pcie_ep_setup_bar(bar_base, 4, PCIE_BAR4_SIZE); }
> +
> +static void ls_pcie_setup_ep(struct ls_pcie_ep *pcie_ep) {
> +	u32 sriov;
> +	struct ls_pcie *pcie = pcie_ep->pcie;
> +
> +	sriov = readl(pcie->dbi + PCIE_SRIOV);
> +	if (PCI_EXT_CAP_ID(sriov) == PCI_EXT_CAP_ID_SRIOV) {
> +		int pf, vf;
> +
> +		for (pf = 0; pf < PCIE_PF_NUM; pf++) {
> +			for (vf = 0; vf <= PCIE_VF_NUM; vf++) {
> +				ctrl_writel(pcie, PCIE_LCTRL0_VAL(pf, vf),
> +					    PCIE_PF_VF_CTRL);
> +
> +				ls_pcie_ep_setup_bars(pcie->dbi);
> +				ls_pcie_ep_setup_atu(pcie_ep);
> +			}
> +		}
> +		/* Disable CFG2 */
> +		ctrl_writel(pcie, 0, PCIE_PF_VF_CTRL);
> +	} else {
> +		ls_pcie_ep_setup_bars(pcie->dbi + PCIE_NO_SRIOV_BAR_BASE);
> +		ls_pcie_ep_setup_atu(pcie_ep);
> +	}
> +
> +	ls_pcie_ep_enable_cfg(pcie_ep);
> +}
> +
> +static int ls_pcie_ep_probe(struct udevice *dev) {
> +	struct ls_pcie_ep *pcie_ep = dev_get_priv(dev);
> +	struct ls_pcie *pcie;
> +	u16 link_sta;
> +	int ret;
> +
> +	pcie = devm_kmalloc(dev, sizeof(*pcie), GFP_KERNEL);
> +	if (!pcie)
> +		return -ENOMEM;
> +
> +	pcie_ep->pcie = pcie;
> +
> +	pcie->dbi = (void __iomem *)devfdt_get_addr_index(dev, 0);
> +	if (!pcie->dbi)
> +		return -ENOMEM;
> +
> +	pcie->ctrl = (void __iomem *)devfdt_get_addr_index(dev, 1);
> +	if (!pcie->ctrl)
> +		return -ENOMEM;
> +
> +	ret = fdt_get_named_resource(gd->fdt_blob, dev_of_offset(dev),
> +				     "reg", "reg-names",
> +				     "addr_space", &pcie_ep->addr_res);
> +	if (ret) {
> +		printf("%s: resource \"addr_space\" not found\n", dev->name);
> +		return ret;
> +	}
> +
> +	pcie->idx = ((unsigned long)pcie->dbi - PCIE_SYS_BASE_ADDR) /
> +		    PCIE_CCSR_SIZE;
> +
> +	pcie->big_endian = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
> +					   "big-endian");
> +
> +	pcie->mode = readb(pcie->dbi + PCI_HEADER_TYPE) & 0x7f;
> +	if (pcie->mode != PCI_HEADER_TYPE_NORMAL)
> +		return 0;
> +
> +	pcie_ep->max_functions = fdtdec_get_int(gd->fdt_blob,
> +						dev_of_offset(dev),
> +						"max-functions", 1);
> +	pcie_ep->num_ib_wins = fdtdec_get_int(gd->fdt_blob,
> dev_of_offset(dev),
> +					      "num-ib-windows", 8);
> +	pcie_ep->num_ob_wins = fdtdec_get_int(gd->fdt_blob,
> dev_of_offset(dev),
> +					      "num-ob-windows", 8);
> +
> +	printf("PCIe%u: %s %s", pcie->idx, dev->name, "Endpoint");
> +	ls_pcie_setup_ep(pcie_ep);
> +
> +	if (!ls_pcie_link_up(pcie)) {
> +		/* Let the user know there's no PCIe link */
> +		printf(": no link\n");
> +		return 0;
> +	}
> +
> +	/* Print the negotiated PCIe link width */
> +	link_sta = readw(pcie->dbi + PCIE_LINK_STA);
> +	printf(": x%d gen%d\n", (link_sta & PCIE_LINK_WIDTH_MASK) >> 4,
> +	       link_sta & PCIE_LINK_SPEED_MASK);
> +
> +	return 0;
> +}
> +
> +static int ls_pcie_ep_remove(struct udevice *dev) {
> +	return 0;
> +}
> +
> +const struct udevice_id ls_pcie_ep_ids[] = {
> +	{ .compatible = "fsl,ls-pcie-ep" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pci_layerscape_ep) = {
> +	.name = "pci_layerscape_ep",
> +	.id	= UCLASS_PCI_EP,
> +	.of_match = ls_pcie_ep_ids,
> +	.ops = &ls_pcie_ep_ops,
> +	.probe = ls_pcie_ep_probe,
> +	.remove = ls_pcie_ep_remove,
> +	.priv_auto_alloc_size = sizeof(struct ls_pcie_ep), };
> diff --git a/drivers/pci/pcie_layerscape_fixup.c
> b/drivers/pci/pcie_layerscape_fixup.c
> index ec6acbb..a981f8c 100644
> --- a/drivers/pci/pcie_layerscape_fixup.c
> +++ b/drivers/pci/pcie_layerscape_fixup.c
> @@ -23,17 +23,19 @@
>  /*
>   * Return next available LUT index.
>   */
> -static int ls_pcie_next_lut_index(struct ls_pcie *pcie)
> +static int ls_pcie_next_lut_index(struct ls_pcie_rc *pcie_rc)
>  {
> -	if (pcie->next_lut_index < PCIE_LUT_ENTRY_COUNT)
> -		return pcie->next_lut_index++;
> +	if (pcie_rc->next_lut_index < PCIE_LUT_ENTRY_COUNT)
> +		return pcie_rc->next_lut_index++;
>  	else
>  		return -ENOSPC;  /* LUT is full */
>  }
> 
> -static void lut_writel(struct ls_pcie *pcie, unsigned int value,
> +static void lut_writel(struct ls_pcie_rc *pcie_rc, unsigned int value,
>  		       unsigned int offset)
>  {
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +
>  	if (pcie->big_endian)
>  		out_be32(pcie->lut + offset, value);
>  	else
> @@ -43,12 +45,12 @@ static void lut_writel(struct ls_pcie *pcie, unsigned
> int value,
>  /*
>   * Program a single LUT entry
>   */
> -static void ls_pcie_lut_set_mapping(struct ls_pcie *pcie, int index, u32
> devid,
> -				    u32 streamid)
> +static void ls_pcie_lut_set_mapping(struct ls_pcie_rc *pcie_rc, int index,
> +				    u32 devid, u32 streamid)
>  {
>  	/* leave mask as all zeroes, want to match all bits */
> -	lut_writel(pcie, devid << 16, PCIE_LUT_UDR(index));
> -	lut_writel(pcie, streamid | PCIE_LUT_ENABLE, PCIE_LUT_LDR(index));
> +	lut_writel(pcie_rc, devid << 16, PCIE_LUT_UDR(index));
> +	lut_writel(pcie_rc, streamid | PCIE_LUT_ENABLE,
> PCIE_LUT_LDR(index));
>  }
> 
>  /*
> @@ -59,7 +61,8 @@ static void ls_pcie_lut_set_mapping(struct ls_pcie
> *pcie, int index, u32 devid,
>   *      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_ls(void *blob, struct ls_pcie *pcie,
> +static void fdt_pcie_set_msi_map_entry_ls(void *blob,
> +					  struct ls_pcie_rc *pcie_rc,
>  					  u32 devid, u32 streamid)
>  {
>  	u32 *prop;
> @@ -67,10 +70,11 @@ static void fdt_pcie_set_msi_map_entry_ls(void
> *blob, struct ls_pcie *pcie,
>  	int nodeoffset;
>  	uint svr;
>  	char *compat = NULL;
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> 
>  	/* find pci controller node */
>  	nodeoffset = fdt_node_offset_by_compat_reg(blob, "fsl,ls-pcie",
> -						   pcie->dbi_res.start);
> +						   pcie_rc->dbi_res.start);
>  	if (nodeoffset < 0) {
>  #ifdef CONFIG_FSL_PCIE_COMPAT /* Compatible with older version of dts
> node */
>  		svr = (get_svr() >> SVR_VAR_PER_SHIFT) & 0xFFFFFE; @@ -82,7
> +86,7 @@ static void fdt_pcie_set_msi_map_entry_ls(void *blob, struct
> ls_pcie *pcie,
>  			compat = CONFIG_FSL_PCIE_COMPAT;
>  		if (compat)
>  			nodeoffset = fdt_node_offset_by_compat_reg(blob,
> -					compat, pcie->dbi_res.start);
> +					compat, pcie_rc->dbi_res.start);
>  #endif
>  		if (nodeoffset < 0)
>  			return;
> @@ -112,7 +116,8 @@ static void fdt_pcie_set_msi_map_entry_ls(void
> *blob, struct ls_pcie *pcie,
>   *      iommu-map = <[devid] [phandle-to-iommu-ctrl] [stream-id]
> [count]
>   *                 [devid] [phandle-to-iommu-ctrl] [stream-id]
> [count]>;
>   */
> -static void fdt_pcie_set_iommu_map_entry_ls(void *blob, struct ls_pcie
> *pcie,
> +static void fdt_pcie_set_iommu_map_entry_ls(void *blob,
> +					    struct ls_pcie_rc *pcie_rc,
>  					    u32 devid, u32 streamid)
>  {
>  	u32 *prop;
> @@ -121,10 +126,11 @@ static void
> fdt_pcie_set_iommu_map_entry_ls(void *blob, struct ls_pcie *pcie,
>  	int lenp;
>  	uint svr;
>  	char *compat = NULL;
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> 
>  	/* find pci controller node */
>  	nodeoffset = fdt_node_offset_by_compat_reg(blob, "fsl,ls-pcie",
> -						   pcie->dbi_res.start);
> +						   pcie_rc->dbi_res.start);
>  	if (nodeoffset < 0) {
>  #ifdef CONFIG_FSL_PCIE_COMPAT /* Compatible with older version of dts
> node */
>  		svr = (get_svr() >> SVR_VAR_PER_SHIFT) & 0xFFFFFE; @@ -137,7
> +143,7 @@ static void fdt_pcie_set_iommu_map_entry_ls(void *blob, struct
> ls_pcie *pcie,
> 
>  		if (compat)
>  			nodeoffset = fdt_node_offset_by_compat_reg(blob,
> -						compat, pcie->dbi_res.start);
> +						compat, pcie_rc->dbi_res.start);
>  #endif
>  		if (nodeoffset < 0)
>  			return;
> @@ -168,7 +174,7 @@ static void fdt_pcie_set_iommu_map_entry_ls(void
> *blob, struct ls_pcie *pcie,  static void fdt_fixup_pcie_ls(void *blob)  {
>  	struct udevice *dev, *bus;
> -	struct ls_pcie *pcie;
> +	struct ls_pcie_rc *pcie_rc;
>  	int streamid;
>  	int index;
>  	pci_dev_t bdf;
> @@ -179,17 +185,18 @@ static void fdt_fixup_pcie_ls(void *blob)
>  	     pci_find_next_device(&dev)) {
>  		for (bus = dev; device_is_on_pci_bus(bus);)
>  			bus = bus->parent;
> -		pcie = dev_get_priv(bus);
> +		pcie_rc = dev_get_priv(bus);
> 
> -		streamid = pcie_next_streamid(pcie->stream_id_cur, pcie->idx);
> +		streamid = pcie_next_streamid(pcie_rc->stream_id_cur,
> +					      pcie_rc->pcie->idx);
>  		if (streamid < 0) {
>  			debug("ERROR: no stream ids free\n");
>  			continue;
>  		} else {
> -			pcie->stream_id_cur++;
> +			pcie_rc->stream_id_cur++;
>  		}
> 
> -		index = ls_pcie_next_lut_index(pcie);
> +		index = ls_pcie_next_lut_index(pcie_rc);
>  		if (index < 0) {
>  			debug("ERROR: no LUT indexes free\n");
>  			continue;
> @@ -198,27 +205,28 @@ static void fdt_fixup_pcie_ls(void *blob)
>  		/* the DT fixup must be relative to the hose first_busno */
>  		bdf = dm_pci_get_bdf(dev) - PCI_BDF(bus->seq, 0, 0);
>  		/* map PCI b.d.f to streamID in LUT */
> -		ls_pcie_lut_set_mapping(pcie, index, bdf >> 8,
> +		ls_pcie_lut_set_mapping(pcie_rc, index, bdf >> 8,
>  					streamid);
>  		/* update msi-map in device tree */
> -		fdt_pcie_set_msi_map_entry_ls(blob, pcie, bdf >> 8,
> +		fdt_pcie_set_msi_map_entry_ls(blob, pcie_rc, bdf >> 8,
>  					      streamid);
>  		/* update iommu-map in device tree */
> -		fdt_pcie_set_iommu_map_entry_ls(blob, pcie, bdf >> 8,
> +		fdt_pcie_set_iommu_map_entry_ls(blob, pcie_rc, bdf >> 8,
>  						streamid);
>  	}
>  	pcie_board_fix_fdt(blob);
>  }
>  #endif
> 
> -static void ft_pcie_rc_fix(void *blob, struct ls_pcie *pcie)
> +static void ft_pcie_rc_fix(void *blob, struct ls_pcie_rc *pcie_rc)
>  {
>  	int off;
>  	uint svr;
>  	char *compat = NULL;
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> 
>  	off = fdt_node_offset_by_compat_reg(blob, "fsl,ls-pcie",
> -					    pcie->dbi_res.start);
> +					    pcie_rc->dbi_res.start);
>  	if (off < 0) {
>  #ifdef CONFIG_FSL_PCIE_COMPAT /* Compatible with older version of dts
> node */
>  		svr = (get_svr() >> SVR_VAR_PER_SHIFT) & 0xFFFFFE; @@ -230,46
> +238,47 @@ static void ft_pcie_rc_fix(void *blob, struct ls_pcie *pcie)
>  			compat = CONFIG_FSL_PCIE_COMPAT;
>  		if (compat)
>  			off = fdt_node_offset_by_compat_reg(blob,
> -					compat, pcie->dbi_res.start);
> +					compat, pcie_rc->dbi_res.start);
>  #endif
>  		if (off < 0)
>  			return;
>  	}
> 
> -	if (pcie->enabled && pcie->mode == PCI_HEADER_TYPE_BRIDGE)
> +	if (pcie_rc->enabled && pcie->mode == PCI_HEADER_TYPE_BRIDGE)
>  		fdt_set_node_status(blob, off, FDT_STATUS_OKAY, 0);
>  	else
>  		fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);  }
> 
> -static void ft_pcie_ep_fix(void *blob, struct ls_pcie *pcie)
> +static void ft_pcie_ep_fix(void *blob, struct ls_pcie_rc *pcie_rc)
>  {
>  	int off;
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> 
>  	off = fdt_node_offset_by_compat_reg(blob,
> CONFIG_FSL_PCIE_EP_COMPAT,
> -					    pcie->dbi_res.start);
> +					    pcie_rc->dbi_res.start);
>  	if (off < 0)
>  		return;
> 
> -	if (pcie->enabled && pcie->mode == PCI_HEADER_TYPE_NORMAL)
> +	if (pcie_rc->enabled && pcie->mode == PCI_HEADER_TYPE_NORMAL)
>  		fdt_set_node_status(blob, off, FDT_STATUS_OKAY, 0);
>  	else
>  		fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);  }
> 
> -static void ft_pcie_ls_setup(void *blob, struct ls_pcie *pcie)
> +static void ft_pcie_ls_setup(void *blob, struct ls_pcie_rc *pcie_rc)
>  {
> -	ft_pcie_ep_fix(blob, pcie);
> -	ft_pcie_rc_fix(blob, pcie);
> +	ft_pcie_ep_fix(blob, pcie_rc);
> +	ft_pcie_rc_fix(blob, pcie_rc);
>  }
> 
>  /* Fixup Kernel DT for PCIe */
>  void ft_pci_setup_ls(void *blob, bd_t *bd)  {
> -	struct ls_pcie *pcie;
> +	struct ls_pcie_rc *pcie_rc;
> 
> -	list_for_each_entry(pcie, &ls_pcie_list, list)
> -		ft_pcie_ls_setup(blob, pcie);
> +	list_for_each_entry(pcie_rc, &ls_pcie_list, list)
> +		ft_pcie_ls_setup(blob, pcie_rc);
> 
>  #if defined(CONFIG_FSL_LSCH3) || defined(CONFIG_FSL_LSCH2)
>  	fdt_fixup_pcie_ls(blob);
> diff --git a/drivers/pci/pcie_layerscape_rc.c
> b/drivers/pci/pcie_layerscape_rc.c
> new file mode 100644
> index 0000000..927722d
> --- /dev/null
> +++ b/drivers/pci/pcie_layerscape_rc.c
> @@ -0,0 +1,378 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2020 NXP
> + * Layerscape PCIe driver
> + */
> +
> +#include <common.h>
> +#include <asm/arch/fsl_serdes.h>
> +#include <pci.h>
> +#include <asm/io.h>
> +#include <errno.h>
> +#include <malloc.h>
> +#include <dm.h>
> +#if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \
> +	defined(CONFIG_ARM)
> +#include <asm/arch/clock.h>
> +#endif
> +#include "pcie_layerscape.h"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static void ls_pcie_cfg0_set_busdev(struct ls_pcie_rc *pcie_rc, u32
> +busdev) {
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +
> +	dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND |
> PCIE_ATU_REGION_INDEX0,
> +		   PCIE_ATU_VIEWPORT);
> +	dbi_writel(pcie, busdev, PCIE_ATU_LOWER_TARGET); }
> +
> +static void ls_pcie_cfg1_set_busdev(struct ls_pcie_rc *pcie_rc, u32
> +busdev) {
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +
> +	dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND |
> PCIE_ATU_REGION_INDEX1,
> +		   PCIE_ATU_VIEWPORT);
> +	dbi_writel(pcie, busdev, PCIE_ATU_LOWER_TARGET); }
> +
> +static void ls_pcie_setup_atu(struct ls_pcie_rc *pcie_rc) {
> +	struct pci_region *io, *mem, *pref;
> +	unsigned long long offset = 0;
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +	int idx = 0;
> +	uint svr;
> +
> +	svr = get_svr();
> +	if (((svr >> SVR_VAR_PER_SHIFT) & SVR_LS102XA_MASK) ==
> SVR_LS102XA) {
> +		offset = LS1021_PCIE_SPACE_OFFSET +
> +			 LS1021_PCIE_SPACE_SIZE * pcie->idx;
> +	}
> +
> +	/* ATU 0 : OUTBOUND : CFG0 */
> +	ls_pcie_atu_outbound_set(pcie, PCIE_ATU_REGION_INDEX0,
> +				 PCIE_ATU_TYPE_CFG0,
> +				 pcie_rc->cfg_res.start + offset,
> +				 0,
> +				 fdt_resource_size(&pcie_rc->cfg_res) / 2);
> +	/* ATU 1 : OUTBOUND : CFG1 */
> +	ls_pcie_atu_outbound_set(pcie, PCIE_ATU_REGION_INDEX1,
> +				 PCIE_ATU_TYPE_CFG1,
> +				 pcie_rc->cfg_res.start + offset +
> +				 fdt_resource_size(&pcie_rc->cfg_res) / 2,
> +				 0,
> +				 fdt_resource_size(&pcie_rc->cfg_res) / 2);
> +
> +	pci_get_regions(pcie_rc->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 ||
> +	    svr == SVR_LS2081A || svr == SVR_LS2041A) {
> +		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++,
> +					 PCIE_ATU_TYPE_IO,
> +					 io->phys_start + offset,
> +					 io->bus_start,
> +					 io->size);
> +
> +	if (mem)
> +		/* ATU : OUTBOUND : MEM */
> +		ls_pcie_atu_outbound_set(pcie, idx++,
> +					 PCIE_ATU_TYPE_MEM,
> +					 mem->phys_start + offset,
> +					 mem->bus_start,
> +					 mem->size);
> +
> +	if (pref)
> +		/* ATU : OUTBOUND : pref */
> +		ls_pcie_atu_outbound_set(pcie, idx++,
> +					 PCIE_ATU_TYPE_MEM,
> +					 pref->phys_start + offset,
> +					 pref->bus_start,
> +					 pref->size);
> +
> +	ls_pcie_dump_atu(pcie);
> +}
> +
> +/* Return 0 if the address is valid, -errno if not valid */ static int
> +ls_pcie_addr_valid(struct ls_pcie_rc *pcie_rc, pci_dev_t bdf) {
> +	struct udevice *bus = pcie_rc->bus;
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +
> +	if (pcie->mode == PCI_HEADER_TYPE_NORMAL)
> +		return -ENODEV;
> +
> +	if (!pcie_rc->enabled)
> +		return -ENXIO;
> +
> +	if (PCI_BUS(bdf) < bus->seq)
> +		return -EINVAL;
> +
> +	if ((PCI_BUS(bdf) > bus->seq) && (!ls_pcie_link_up(pcie)))
> +		return -EINVAL;
> +
> +	if (PCI_BUS(bdf) <= (bus->seq + 1) && (PCI_DEV(bdf) > 0))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +int ls_pcie_conf_address(struct udevice *bus, pci_dev_t bdf,
> +			 uint offset, void **paddress)
> +{
> +	struct ls_pcie_rc *pcie_rc = dev_get_priv(bus);
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +	u32 busdev;
> +
> +	if (ls_pcie_addr_valid(pcie_rc, bdf))
> +		return -EINVAL;
> +
> +	if (PCI_BUS(bdf) == bus->seq) {
> +		*paddress = pcie->dbi + offset;
> +		return 0;
> +	}
> +
> +	busdev = PCIE_ATU_BUS(PCI_BUS(bdf) - bus->seq) |
> +		 PCIE_ATU_DEV(PCI_DEV(bdf)) |
> +		 PCIE_ATU_FUNC(PCI_FUNC(bdf));
> +
> +	if (PCI_BUS(bdf) == bus->seq + 1) {
> +		ls_pcie_cfg0_set_busdev(pcie_rc, busdev);
> +		*paddress = pcie_rc->cfg0 + offset;
> +	} else {
> +		ls_pcie_cfg1_set_busdev(pcie_rc, busdev);
> +		*paddress = pcie_rc->cfg1 + offset;
> +	}
> +	return 0;
> +}
> +
> +static int ls_pcie_read_config(struct udevice *bus, pci_dev_t bdf,
> +			       uint offset, ulong *valuep,
> +			       enum pci_size_t size)
> +{
> +	return pci_generic_mmap_read_config(bus, ls_pcie_conf_address,
> +					    bdf, offset, valuep, size);
> +}
> +
> +static int ls_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
> +				uint offset, ulong value,
> +				enum pci_size_t size)
> +{
> +	return pci_generic_mmap_write_config(bus, ls_pcie_conf_address,
> +					     bdf, offset, value, size);
> +}
> +
> +/* Clear multi-function bit */
> +static void ls_pcie_clear_multifunction(struct ls_pcie_rc *pcie_rc) {
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +
> +	writeb(PCI_HEADER_TYPE_BRIDGE, pcie->dbi + PCI_HEADER_TYPE); }
> +
> +/* Fix class value */
> +static void ls_pcie_fix_class(struct ls_pcie_rc *pcie_rc) {
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +
> +	writew(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE); }
> +
> +/* Drop MSG TLP except for Vendor MSG */ static void
> +ls_pcie_drop_msg_tlp(struct ls_pcie_rc *pcie_rc) {
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +	u32 val;
> +
> +	val = dbi_readl(pcie, PCIE_STRFMR1);
> +	val &= 0xDFFFFFFF;
> +	dbi_writel(pcie, val, PCIE_STRFMR1);
> +}
> +
> +/* Disable all bars in RC mode */
> +static void ls_pcie_disable_bars(struct ls_pcie_rc *pcie_rc) {
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +
> +	dbi_writel(pcie, 0, PCIE_CS2_OFFSET + PCI_BASE_ADDRESS_0);
> +	dbi_writel(pcie, 0, PCIE_CS2_OFFSET + PCI_BASE_ADDRESS_1);
> +	dbi_writel(pcie, 0xfffffffe, PCIE_CS2_OFFSET + PCI_ROM_ADDRESS1); }
> +
> +static void ls_pcie_setup_ctrl(struct ls_pcie_rc *pcie_rc) {
> +	struct ls_pcie *pcie = pcie_rc->pcie;
> +
> +	ls_pcie_setup_atu(pcie_rc);
> +
> +	ls_pcie_dbi_ro_wr_en(pcie);
> +	ls_pcie_fix_class(pcie_rc);
> +	ls_pcie_clear_multifunction(pcie_rc);
> +	ls_pcie_drop_msg_tlp(pcie_rc);
> +	ls_pcie_dbi_ro_wr_dis(pcie);
> +
> +	ls_pcie_disable_bars(pcie_rc);
> +	pcie_rc->stream_id_cur = 0;
> +}
> +
> +static int ls_pcie_probe(struct udevice *dev) {
> +	struct ls_pcie_rc *pcie_rc = dev_get_priv(dev);
> +	const void *fdt = gd->fdt_blob;
> +	int node = dev_of_offset(dev);
> +	struct ls_pcie *pcie;
> +	u16 link_sta;
> +	uint svr;
> +	int ret;
> +	fdt_size_t cfg_size;
> +
> +	pcie_rc->bus = dev;
> +
> +	pcie = devm_kmalloc(dev, sizeof(*pcie), GFP_KERNEL);
> +	if (!pcie)
> +		return -ENOMEM;
> +
> +	pcie_rc->pcie = pcie;
> +
> +	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> +				     "dbi", &pcie_rc->dbi_res);
> +	if (ret) {
> +		printf("ls-pcie: resource \"dbi\" not found\n");
> +		return ret;
> +	}
> +
> +	pcie->idx = (pcie_rc->dbi_res.start - PCIE_SYS_BASE_ADDR) /
> +		    PCIE_CCSR_SIZE;
> +
> +	list_add(&pcie_rc->list, &ls_pcie_list);
> +
> +	pcie_rc->enabled = is_serdes_configured(PCIE_SRDS_PRTCL(pcie->idx));
> +	if (!pcie_rc->enabled) {
> +		printf("PCIe%d: %s disabled\n", pcie->idx, dev->name);
> +		return 0;
> +	}
> +
> +	pcie->dbi = map_physmem(pcie_rc->dbi_res.start,
> +				fdt_resource_size(&pcie_rc->dbi_res),
> +				MAP_NOCACHE);
> +
> +	pcie->mode = readb(pcie->dbi + PCI_HEADER_TYPE) & 0x7f;
> +	if (pcie->mode == PCI_HEADER_TYPE_NORMAL)
> +		return 0;
> +
> +	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> +				     "lut", &pcie_rc->lut_res);
> +	if (!ret)
> +		pcie->lut = map_physmem(pcie_rc->lut_res.start,
> +					fdt_resource_size(&pcie_rc->lut_res),
> +					MAP_NOCACHE);
> +
> +	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> +				     "ctrl", &pcie_rc->ctrl_res);
> +	if (!ret)
> +		pcie->ctrl = map_physmem(pcie_rc->ctrl_res.start,
> +					 fdt_resource_size(&pcie_rc->ctrl_res),
> +					 MAP_NOCACHE);
> +	if (!pcie->ctrl)
> +		pcie->ctrl = pcie->lut;
> +
> +	if (!pcie->ctrl) {
> +		printf("%s: NOT find CTRL\n", dev->name);
> +		return -1;
> +	}
> +
> +	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> +				     "config", &pcie_rc->cfg_res);
> +	if (ret) {
> +		printf("%s: resource \"config\" not found\n", dev->name);
> +		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 ||
> +	    svr == SVR_LS2081A || svr == SVR_LS2041A) {
> +		cfg_size = fdt_resource_size(&pcie_rc->cfg_res);
> +		pcie_rc->cfg_res.start = LS2088A_PCIE1_PHYS_ADDR +
> +					 LS2088A_PCIE_PHYS_SIZE * pcie->idx;
> +		pcie_rc->cfg_res.end = pcie_rc->cfg_res.start + cfg_size;
> +		pcie->ctrl = pcie->lut + 0x40000;
> +	}
> +
> +	pcie_rc->cfg0 = map_physmem(pcie_rc->cfg_res.start,
> +				    fdt_resource_size(&pcie_rc->cfg_res),
> +				    MAP_NOCACHE);
> +	pcie_rc->cfg1 = pcie_rc->cfg0 +
> +			fdt_resource_size(&pcie_rc->cfg_res) / 2;
> +
> +	pcie->big_endian = fdtdec_get_bool(fdt, node, "big-endian");
> +
> +	debug("%s dbi:%lx lut:%lx ctrl:0x%lx cfg0:0x%lx, big-endian:%d\n",
> +	      dev->name, (unsigned long)pcie->dbi, (unsigned long)pcie->lut,
> +	      (unsigned long)pcie->ctrl, (unsigned long)pcie_rc->cfg0,
> +	      pcie->big_endian);
> +
> +	printf("PCIe%u: %s %s", pcie->idx, dev->name, "Root Complex");
> +	ls_pcie_setup_ctrl(pcie_rc);
> +
> +	if (!ls_pcie_link_up(pcie)) {
> +		/* Let the user know there's no PCIe link */
> +		printf(": no link\n");
> +		return 0;
> +	}
> +
> +	/* Print the negotiated PCIe link width */
> +	link_sta = readw(pcie->dbi + PCIE_LINK_STA);
> +	printf(": x%d gen%d\n", (link_sta & PCIE_LINK_WIDTH_MASK) >> 4,
> +	       link_sta & PCIE_LINK_SPEED_MASK);
> +
> +	return 0;
> +}
> +
> +static const struct dm_pci_ops ls_pcie_ops = {
> +	.read_config	= ls_pcie_read_config,
> +	.write_config	= ls_pcie_write_config,
> +};
> +
> +static const struct udevice_id ls_pcie_ids[] = {
> +	{ .compatible = "fsl,ls-pcie" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pci_layerscape) = {
> +	.name = "pci_layerscape",
> +	.id = UCLASS_PCI,
> +	.of_match = ls_pcie_ids,
> +	.ops = &ls_pcie_ops,
> +	.probe	= ls_pcie_probe,
> +	.priv_auto_alloc_size = sizeof(struct ls_pcie_rc), };
> --
> 2.9.5

Reviewed-by: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>



More information about the U-Boot mailing list