> -----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 4/9] PCI_EP: layerscape: Add the multiple function supprot > > Add the multiple function support for Layerscape platform, some PEXs of > Layerscaple platform have more than one PF. > > Signed-off-by: Xiaowei Bao <xiaowei....@nxp.com> > --- > drivers/pci/pcie_layerscape.c | 6 +- > drivers/pci/pcie_layerscape.h | 21 +++++-- > drivers/pci/pcie_layerscape_ep.c | 119 > ++++++++++++++++++++++++++------------- > 3 files changed, 98 insertions(+), 48 deletions(-) > > diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c > index 3ca75c5..88a0e8a 100644 > --- a/drivers/pci/pcie_layerscape.c > +++ b/drivers/pci/pcie_layerscape.c > @@ -104,13 +104,13 @@ void ls_pcie_atu_outbound_set(struct ls_pcie > *pcie, int idx, int type, } > > /* Use bar match mode and MEM type as default */ -void > ls_pcie_atu_inbound_set(struct ls_pcie *pcie, int idx, int type, > - int bar, u64 phys) > +void ls_pcie_atu_inbound_set(struct ls_pcie *pcie, u32 pf, int type, > + int idx, 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, type, PCIE_ATU_CR1); > + dbi_writel(pcie, type | PCIE_ATU_FUNC_NUM(pf), PCIE_ATU_CR1); > dbi_writel(pcie, PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE | > PCIE_ATU_BAR_NUM(bar), PCIE_ATU_CR2); } diff --git > a/drivers/pci/pcie_layerscape.h b/drivers/pci/pcie_layerscape.h index > 217dcda..dabfff3 100644 > --- a/drivers/pci/pcie_layerscape.h > +++ b/drivers/pci/pcie_layerscape.h > @@ -9,6 +9,7 @@ > #define _PCIE_LAYERSCAPE_H_ > #include <pci.h> > #include <dm.h> > +#include <linux/sizes.h> > > #ifndef CONFIG_SYS_PCI_MEMORY_BUS > #define CONFIG_SYS_PCI_MEMORY_BUS CONFIG_SYS_SDRAM_BASE @@ > -44,6 +45,7 @@ > #define PCIE_ATU_TYPE_IO (0x2 << 0) > #define PCIE_ATU_TYPE_CFG0 (0x4 << 0) > #define PCIE_ATU_TYPE_CFG1 (0x5 << 0) > +#define PCIE_ATU_FUNC_NUM(pf) ((pf) << 20) > #define PCIE_ATU_CR2 0x908 > #define PCIE_ATU_ENABLE (0x1 << 31) > #define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30) > @@ -86,11 +88,16 @@ > #define FSL_PCIE_EP_MIN_APERTURE 4096 /* 4 Kbytes */ > #define PCIE_PF_NUM 2 > #define PCIE_VF_NUM 64 > +#define BAR_NUM 4 > > -#define PCIE_BAR0_SIZE (4 * 1024) /* 4K */ > -#define PCIE_BAR1_SIZE (8 * 1024) /* 8K for MSIX */ > -#define PCIE_BAR2_SIZE (4 * 1024) /* 4K */ > -#define PCIE_BAR4_SIZE (1 * 1024 * 1024) /* 1M */ > +#define PCIE_BAR0_SIZE SZ_4K > +#define PCIE_BAR1_SIZE SZ_8K > +#define PCIE_BAR2_SIZE SZ_4K > +#define PCIE_BAR4_SIZE SZ_1M > + > +#define PCIE_SRIOV_VFBAR0 0x19C > + > +#define PCIE_MASK_OFFSET(flag, pf) ((flag) ? 0 : (0x1000 + 0x20000 * > +(pf))) > > /* LUT registers */ > #define PCIE_LUT_UDR(n) (0x800 + (n) * 8) > @@ -158,6 +165,8 @@ struct ls_pcie_ep { > struct ls_pcie *pcie; > struct udevice *bus; > void __iomem *addr; > + u32 cfg2_flag; > + u32 sriov_flag; > u32 num_ib_wins; > u32 num_ob_wins; > u8 max_functions; > @@ -171,8 +180,8 @@ 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_atu_inbound_set(struct ls_pcie *pcie, u32 pf, int type, > + int idx, 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); diff --git > a/drivers/pci/pcie_layerscape_ep.c b/drivers/pci/pcie_layerscape_ep.c > index 8d0c99a..bec374b 100644 > --- a/drivers/pci/pcie_layerscape_ep.c > +++ b/drivers/pci/pcie_layerscape_ep.c > @@ -45,7 +45,7 @@ static int ls_ep_set_bar(struct udevice *dev, uint fn, > struct pci_bar *ep_bar) > else > type = PCIE_ATU_TYPE_IO; > > - ls_pcie_atu_inbound_set(pcie, idx, bar, bar_phys, type); > + ls_pcie_atu_inbound_set(pcie, fn, type, idx, bar, bar_phys); > > dbi_writel(pcie, lower_32_bits(size - 1), reg + > PCIE_NO_SRIOV_BAR_BASE); > dbi_writel(pcie, flags, reg); > @@ -63,51 +63,61 @@ 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) > +static void ls_pcie_ep_setup_atu(struct ls_pcie_ep *pcie_ep, u32 pf) > { > struct ls_pcie *pcie = pcie_ep->pcie; > - u64 phys = CONFIG_SYS_PCI_EP_MEMORY_BASE; > + u64 phys = 0; > > + phys = CONFIG_SYS_PCI_EP_MEMORY_BASE + pf * SZ_64M; > + > + phys = ALIGN(phys, PCIE_BAR0_SIZE); > /* ATU 0 : INBOUND : map BAR0 */ > - ls_pcie_atu_inbound_set(pcie, 0, PCIE_ATU_TYPE_MEM, 0, phys); > + ls_pcie_atu_inbound_set(pcie, pf, PCIE_ATU_TYPE_MEM, > + 0 + pf * BAR_NUM, 0, phys); > /* ATU 1 : INBOUND : map BAR1 */ > - phys += PCIE_BAR1_SIZE; > - ls_pcie_atu_inbound_set(pcie, 1, PCIE_ATU_TYPE_MEM, 1, phys); > + phys = ALIGN(phys + PCIE_BAR0_SIZE, PCIE_BAR1_SIZE); > + ls_pcie_atu_inbound_set(pcie, pf, PCIE_ATU_TYPE_MEM, > + 1 + pf * BAR_NUM, 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); > + phys = ALIGN(phys + PCIE_BAR1_SIZE, PCIE_BAR2_SIZE); > + ls_pcie_atu_inbound_set(pcie, pf, PCIE_ATU_TYPE_MEM, > + 2 + pf * BAR_NUM, 2, phys); > + /* ATU 3 : INBOUND : map BAR2 */ > + phys = ALIGN(phys + PCIE_BAR2_SIZE, PCIE_BAR4_SIZE); > + ls_pcie_atu_inbound_set(pcie, pf, PCIE_ATU_TYPE_MEM, > + 3 + pf * BAR_NUM, 4, phys); > + > + /* ATU: OUTBOUND : map MEM */ > + ls_pcie_atu_outbound_set(pcie, pf, PCIE_ATU_TYPE_MEM, > + (u64)pcie_ep->addr_res.start + > + pf * CONFIG_SYS_PCI_MEMORY_SIZE, > + 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) { > + u32 mask; > + > /* The least inbound window is 4KiB */ > - if (size < 4 * 1024) > - return; > + if (size < SZ_4K) > + mask = 0; > + else > + mask = size - 1; > > switch (bar) { > case 0: > - writel(size - 1, bar_base + PCI_BASE_ADDRESS_0); > + writel(mask, bar_base + PCI_BASE_ADDRESS_0); > break; > case 1: > - writel(size - 1, bar_base + PCI_BASE_ADDRESS_1); > + writel(mask, bar_base + PCI_BASE_ADDRESS_1); > break; > case 2: > - writel(size - 1, bar_base + PCI_BASE_ADDRESS_2); > + writel(mask, 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(mask, bar_base + PCI_BASE_ADDRESS_4); > writel(0, bar_base + PCI_BASE_ADDRESS_5); > break; > default: > @@ -117,39 +127,62 @@ static void ls_pcie_ep_setup_bar(void *bar_base, > int bar, u32 size) > > static void ls_pcie_ep_setup_bars(void *bar_base) { > - /* BAR0 - 32bit - 4K configuration */ > + /* BAR0 - 32bit - MEM */ > + ls_pcie_ep_setup_bar(bar_base, 0, PCIE_BAR0_SIZE); > + /* BAR1 - 32bit - MEM*/ > + ls_pcie_ep_setup_bar(bar_base, 1, PCIE_BAR1_SIZE); > + /* BAR2 - 64bit - MEM */ > + ls_pcie_ep_setup_bar(bar_base, 2, PCIE_BAR2_SIZE); > + /* BAR4 - 64bit - MEM */ > + ls_pcie_ep_setup_bar(bar_base, 4, PCIE_BAR4_SIZE); } > + > +static void ls_pcie_ep_setup_vf_bars(void *bar_base) { > + /* VF BAR0 MASK register at offset 0x19c*/ > + bar_base += PCIE_SRIOV_VFBAR0 - PCI_BASE_ADDRESS_0; > + > + /* VF-BAR0 - 32bit - MEM */ > ls_pcie_ep_setup_bar(bar_base, 0, PCIE_BAR0_SIZE); > - /* BAR1 - 32bit - 8K MSIX */ > + /* VF-BAR1 - 32bit - MEM*/ > ls_pcie_ep_setup_bar(bar_base, 1, PCIE_BAR1_SIZE); > - /* BAR2 - 64bit - 4K MEM descriptor */ > + /* VF-BAR2 - 64bit - MEM */ > ls_pcie_ep_setup_bar(bar_base, 2, PCIE_BAR2_SIZE); > - /* BAR4 - 64bit - 1M MEM */ > + /* VF-BAR4 - 64bit - 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; > + u32 pf, vf; > + void *bar_base = NULL; > 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; > - > + pcie_ep->sriov_flag = 1; > 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); > + if (pcie_ep->cfg2_flag) { > + for (vf = 0; vf <= PCIE_VF_NUM; vf++) { > + ctrl_writel(pcie, > + PCIE_LCTRL0_VAL(pf, vf), > + PCIE_PF_VF_CTRL); > + } > } > + bar_base = pcie->dbi + > + PCIE_MASK_OFFSET(pcie_ep->cfg2_flag, pf); > + ls_pcie_ep_setup_bars(bar_base); > + ls_pcie_ep_setup_vf_bars(bar_base); > + > + ls_pcie_ep_setup_atu(pcie_ep, pf); > } > - /* Disable CFG2 */ > - ctrl_writel(pcie, 0, PCIE_PF_VF_CTRL); > + > + if (pcie_ep->cfg2_flag) /* 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_setup_atu(pcie_ep, 0); > } > > ls_pcie_ep_enable_cfg(pcie_ep); > @@ -161,6 +194,7 @@ static int ls_pcie_ep_probe(struct udevice *dev) > struct ls_pcie *pcie; > u16 link_sta; > int ret; > + u32 svr; > > pcie = devm_kmalloc(dev, sizeof(*pcie), GFP_KERNEL); > if (!pcie) > @@ -190,6 +224,13 @@ static int ls_pcie_ep_probe(struct udevice *dev) > pcie->big_endian = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), > "big-endian"); > > + svr = SVR_SOC_VER(get_svr()); > + > + if (svr == SVR_LS2080A || svr == SVR_LS2085A) > + pcie_ep->cfg2_flag = 1; > + else > + pcie_ep->cfg2_flag = 0; > + > pcie->mode = readb(pcie->dbi + PCI_HEADER_TYPE) & 0x7f; > if (pcie->mode != PCI_HEADER_TYPE_NORMAL) > return 0; > -- > 2.9.5 Reviewed-by: Hou Zhiqiang <zhiqiang....@nxp.com>