[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