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)
}
/**
+ * 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
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;
}
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;
}
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;
}
}
/**
- * 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
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,