> -----Original Message-----
> From: Xiaowei Bao <xiaowei....@nxp.com>
> Sent: 2020年3月22日 19:13
> To: M.h. Lian <minghuan.l...@nxp.com>; Z.q. Hou
> <zhiqiang....@nxp.com>; Mingkai Hu <mingkai...@nxp.com>;
> bmeng...@gmail.com; yamada.masah...@socionext.com;
> u-boot@lists.denx.de
> Cc: Xiaowei Bao <xiaowei....@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....@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....@nxp.com>

Reply via email to