PCIe layerscape ATU

Fabian Cenedese Cenedese at indel.ch
Fri Nov 10 10:58:36 CET 2023


Hello

I have a question to this code (drivers/pci/pcie_layerscape.c):

void ls_pcie_atu_outbound_set(struct ls_pcie *pcie, int idx, int type,
			      u64 phys, u64 bus_addr, u64 size)
{
	dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND | idx, PCIE_ATU_VIEWPORT);
	dbi_writel(pcie, (u32)phys, PCIE_ATU_LOWER_BASE);
	dbi_writel(pcie, phys >> 32, PCIE_ATU_UPPER_BASE);
	dbi_writel(pcie, (u32)phys + size - 1, PCIE_ATU_LIMIT);
	dbi_writel(pcie, (u32)bus_addr, PCIE_ATU_LOWER_TARGET);
	dbi_writel(pcie, bus_addr >> 32, PCIE_ATU_UPPER_TARGET);
	dbi_writel(pcie, type, PCIE_ATU_CR1);
	dbi_writel(pcie, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
}

/* Use bar match mode and MEM type as default */
void ls_pcie_atu_inbound_set(struct ls_pcie *pcie, u32 pf, u32 vf_flag,
			     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_FUNC_NUM(pf), PCIE_ATU_CR1);
	dbi_writel(pcie, PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE |
		   (vf_flag ? PCIE_ATU_FUNC_NUM_MATCH_EN : 0) |
		   (vf_flag ? PCIE_ATU_VFBAR_MATCH_MODE_EN : 0) |
		   PCIE_ATU_BAR_NUM(bar), PCIE_ATU_CR2);
}

void ls_pcie_dump_atu(struct ls_pcie *pcie, u32 win_num, u32 type)
{
	int win_idx;

	for (win_idx = 0; win_idx < win_num; win_idx++) {
		dbi_writel(pcie, type | win_idx, PCIE_ATU_VIEWPORT);
		debug("iATU%d:\n", win_idx);
		debug("\tLOWER PHYS 0x%08x\n",
		      dbi_readl(pcie, PCIE_ATU_LOWER_BASE));
		debug("\tUPPER PHYS 0x%08x\n",
		      dbi_readl(pcie, PCIE_ATU_UPPER_BASE));
		if (type == PCIE_ATU_REGION_OUTBOUND) {
			debug("\tLOWER BUS  0x%08x\n",
			      dbi_readl(pcie, PCIE_ATU_LOWER_TARGET));
			debug("\tUPPER BUS  0x%08x\n",
			      dbi_readl(pcie, PCIE_ATU_UPPER_TARGET));
			debug("\tLIMIT      0x%08x\n",
			      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));
	}
}

For outbound *_BASE and *_TARGET values are set. For inbound
only *_TARGET values are set. However in dump it always prints
the *_BASE values while the *_TARGET are only printed for outbound.

Shouldn't that be the other way around? Either I didn't understand
ATUs or there's a mixup here.

Second question: We want to make an endpoint with 4 BARs. Is it
possible to configure the internal addresses in the ATUs? The function
ls_pcie_ep_setup_atu uses a configurable base address but then all
ATUs are placed one after each other. How can I give them arbitrary
addresses?

Thanks

bye  Fabi



More information about the U-Boot mailing list