[U-Boot] [PATCH] dm: pcie: designware: add correct ATU handling
Stefan Roese
sr at denx.de
Fri Mar 30 14:11:08 UTC 2018
On 14.02.2018 18:25, igall at marvell.com wrote:
> From: Igal Liberman <igall at marvell.com>
>
> Currently, ATU (address translation unit) implementation doesn't
> support translate addresses > 32 bits.
>
> This patch allows to configure ATU correctly for different
> memory accesses (memory, configuration and IO).
> The same approach is used in Linux Kernel.
>
> Signed-off-by: Igal Liberman <igall at marvell.com>
> ---
> drivers/pci/pcie_dw_mvebu.c | 91 +++++++++++++++++++++++++++++----------------
> 1 file changed, 58 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/pci/pcie_dw_mvebu.c b/drivers/pci/pcie_dw_mvebu.c
> index a198855..a0032b7 100644
> --- a/drivers/pci/pcie_dw_mvebu.c
> +++ b/drivers/pci/pcie_dw_mvebu.c
> @@ -111,6 +111,10 @@ struct pcie_dw_mvebu {
> void *cfg_base;
> fdt_size_t cfg_size;
> int first_busno;
> +
> + /* IO and MEM PCI regions */
> + struct pci_region io;
> + struct pci_region mem;
> };
>
> static int pcie_dw_get_link_speed(const void *regs_base)
> @@ -126,6 +130,34 @@ static int pcie_dw_get_link_width(const void *regs_base)
> }
>
> /**
> + * pcie_dw_prog_outbound_atu() - Configure ATU for outbound accesses
> + *
> + * @pcie: Pointer to the PCI controller state
> + * @index: ATU region index
> + * @type: ATU accsess type
> + * @cpu_addr: the physical address for the translation entry
> + * @pci_addr: the pcie bus address for the translation entry
> + * @size: the size of the translation entry
> + */
> +static void pcie_dw_prog_outbound_atu(struct pcie_dw_mvebu *pcie, int index,
> + int type, u64 cpu_addr, u64 pci_addr,
> + u32 size)
> +{
> + writel(PCIE_ATU_REGION_OUTBOUND | index,
> + pcie->ctrl_base + PCIE_ATU_VIEWPORT);
> + writel(lower_32_bits(cpu_addr), pcie->ctrl_base + PCIE_ATU_LOWER_BASE);
> + writel(upper_32_bits(cpu_addr), pcie->ctrl_base + PCIE_ATU_UPPER_BASE);
> + writel(lower_32_bits(cpu_addr + size - 1),
> + pcie->ctrl_base + PCIE_ATU_LIMIT);
> + writel(lower_32_bits(pci_addr),
> + pcie->ctrl_base + PCIE_ATU_LOWER_TARGET);
> + writel(upper_32_bits(pci_addr),
> + pcie->ctrl_base + PCIE_ATU_UPPER_TARGET);
> + writel(type, pcie->ctrl_base + PCIE_ATU_CR1);
> + writel(PCIE_ATU_ENABLE, pcie->ctrl_base + PCIE_ATU_CR2);
> +}
> +
> +/**
> * set_cfg_address() - Configure the PCIe controller config space access
> *
> * @pcie: Pointer to the PCI controller state
> @@ -143,27 +175,29 @@ static uintptr_t set_cfg_address(struct pcie_dw_mvebu *pcie,
> pci_dev_t d, uint where)
> {
> uintptr_t va_address;
> + u32 atu_type;
>
> /*
> * Region #0 is used for Outbound CFG space access.
> * Direction = Outbound
> * Region Index = 0
> */
> - writel(0, pcie->ctrl_base + PCIE_ATU_VIEWPORT);
>
> if (PCI_BUS(d) == (pcie->first_busno + 1))
> /* For local bus, change TLP Type field to 4. */
> - writel(PCIE_ATU_TYPE_CFG0, pcie->ctrl_base + PCIE_ATU_CR1);
> + atu_type = PCIE_ATU_TYPE_CFG0;
> else
> /* Otherwise, change TLP Type field to 5. */
> - writel(PCIE_ATU_TYPE_CFG1, pcie->ctrl_base + PCIE_ATU_CR1);
> + atu_type = PCIE_ATU_TYPE_CFG1;
>
> if (PCI_BUS(d) == pcie->first_busno) {
> /* Accessing root port configuration space. */
> va_address = (uintptr_t)pcie->ctrl_base;
> } else {
> d = PCI_MASK_BUS(d) | (PCI_BUS(d) - pcie->first_busno);
> - writel(d << 8, pcie->ctrl_base + PCIE_ATU_LOWER_TARGET);
> + pcie_dw_prog_outbound_atu(pcie, PCIE_ATU_REGION_INDEX0,
> + atu_type, (u64)pcie->cfg_base,
> + d << 8, pcie->cfg_size);
> va_address = (uintptr_t)pcie->cfg_base;
> }
>
> @@ -231,6 +265,10 @@ static int pcie_dw_mvebu_read_config(struct udevice *bus, pci_dev_t bdf,
> debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
> *valuep = pci_conv_32_to_size(value, offset, size);
>
> + pcie_dw_prog_outbound_atu(pcie, PCIE_ATU_REGION_INDEX0,
> + PCIE_ATU_TYPE_IO, pcie->io.phys_start,
> + pcie->io.bus_start, pcie->io.size);
> +
> return 0;
> }
>
> @@ -272,6 +310,10 @@ static int pcie_dw_mvebu_write_config(struct udevice *bus, pci_dev_t bdf,
> value = pci_conv_size_to_32(old, value, offset, size);
> writel(value, va_address);
>
> + pcie_dw_prog_outbound_atu(pcie, PCIE_ATU_REGION_INDEX0,
> + PCIE_ATU_TYPE_IO, pcie->io.phys_start,
> + pcie->io.bus_start, pcie->io.size);
> +
> return 0;
> }
>
> @@ -388,34 +430,6 @@ static int pcie_dw_mvebu_pcie_link_up(const void *regs_base, u32 cap_speed)
> }
>
> /**
> - * pcie_dw_regions_setup() - iATU region setup
> - *
> - * @pcie: Pointer to the PCI controller state
> - *
> - * Configure the iATU regions in the PCIe controller for outbound access.
> - */
> -static void pcie_dw_regions_setup(struct pcie_dw_mvebu *pcie)
> -{
> - /*
> - * Region #0 is used for Outbound CFG space access.
> - * Direction = Outbound
> - * Region Index = 0
> - */
> - writel(0, pcie->ctrl_base + PCIE_ATU_VIEWPORT);
> -
> - writel((u32)(uintptr_t)pcie->cfg_base, pcie->ctrl_base
> - + PCIE_ATU_LOWER_BASE);
> - writel(0, pcie->ctrl_base + PCIE_ATU_UPPER_BASE);
> - writel((u32)(uintptr_t)pcie->cfg_base + pcie->cfg_size,
> - pcie->ctrl_base + PCIE_ATU_LIMIT);
> -
> - writel(0, pcie->ctrl_base + PCIE_ATU_LOWER_TARGET);
> - writel(0, pcie->ctrl_base + PCIE_ATU_UPPER_TARGET);
> - writel(PCIE_ATU_TYPE_CFG0, pcie->ctrl_base + PCIE_ATU_CR1);
> - writel(PCIE_ATU_ENABLE, pcie->ctrl_base + PCIE_ATU_CR2);
> -}
> -
> -/**
> * pcie_dw_set_host_bars() - Configure the host BARs
> *
> * @regs_base: A pointer to the PCIe controller registers
> @@ -495,7 +509,18 @@ static int pcie_dw_mvebu_probe(struct udevice *dev)
> hose->first_busno);
> }
>
> - pcie_dw_regions_setup(pcie);
> + /* Store the IO and MEM windows settings for future use by the ATU */
> + pcie->io.phys_start = hose->regions[0].phys_start; /* IO base */
> + pcie->io.bus_start = hose->regions[0].bus_start; /* IO_bus_addr */
> + pcie->io.size = hose->regions[0].size; /* IO size */
> +
> + pcie->mem.phys_start = hose->regions[1].phys_start; /* MEM base */
> + pcie->mem.bus_start = hose->regions[1].bus_start; /* MEM_bus_addr */
> + pcie->mem.size = hose->regions[1].size; /* MEM size */
> +
> + pcie_dw_prog_outbound_atu(pcie, PCIE_ATU_REGION_INDEX1,
> + PCIE_ATU_TYPE_MEM, pcie->mem.phys_start,
> + pcie->mem.bus_start, pcie->mem.size);
>
> /* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */
> clrsetbits_le32(pcie->ctrl_base + PCI_CLASS_REVISION,
>
Applied to u-boot-marvell/master.
Thanks,
Stefan
More information about the U-Boot
mailing list