mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
Merge branch 'pci/controller/dwc-cpu-addr-fixup'
- Ioremap() msg_res region using res->start (the CPU address), not the ATU 'cpu_addr', which will be replaced with the ATU input address (which may not be the CPU address) (Frank Li) - Rename struct dw_pcie_ob_atu_cfg.cpu_addr to 'parent_bus_addr' (Frank Li) - Call devm_pci_alloc_host_bridge() early in dw_pcie_host_init() to keep devicetree-related code together (Frank Li) - Consolidate devicetree handling in dw_pcie_host_get_resources() (Bjorn Helgaas) - Add dw_pcie_parent_bus_offset() to look up the parent bus address of a specified 'reg' property and return the offset from the CPU physical address (Frank Li) - Add cross-checking with .cpu_addr_fixup() and debug logging to dw_pcie_parent_bus_offset() (Frank Li) - Use devicetree 'reg[config]' via dw_pcie_parent_bus_offset() to derive CPU -> ATU addr offset for host controller (Frank Li) - Call epc_create() early in dw_pcie_ep_init() to keep devicetree-related code together (Bjorn Helgaas) - Consolidate devicetree handling in dw_pcie_ep_get_resources() (Bjorn Helgaas) - Use devicetree 'reg[addr_space]' via dw_pcie_parent_bus_offset() to derive CPU -> ATU addr offset for endpoint controller (Frank Li) - Update dw_pcie_find_index() to remove assumption that ATU input address is non-zero (Frank Li) - Apply struct dw_pcie.parent_bus_offset in ATU users to remove use of .cpu_addr_fixup() when programming ATU (Frank Li) - Remove imx_pcie_cpu_addr_fixup() since dwc core can now derive the ATU input address (using parent_bus_offset) from devicetree (Frank Li) - Remove intel_pcie_cpu_addr() since dwc core can now derive the ATU input address (using parent_bus_offset) from devicetree (Frank Li) * pci/controller/dwc-cpu-addr-fixup: PCI: intel-gw: Remove intel_pcie_cpu_addr() PCI: imx6: Remove imx_pcie_cpu_addr_fixup() PCI: dwc: Use parent_bus_offset to remove need for .cpu_addr_fixup() PCI: dwc: ep: Ensure proper iteration over outbound map windows PCI: dwc: ep: Use devicetree 'reg[addr_space]' to derive CPU -> ATU addr offset PCI: dwc: ep: Consolidate devicetree handling in dw_pcie_ep_get_resources() PCI: dwc: ep: Call epc_create() early in dw_pcie_ep_init() PCI: dwc: Use devicetree 'reg[config]' to derive CPU -> ATU addr offset PCI: dwc: Add dw_pcie_parent_bus_offset() checking and debug PCI: dwc: Add dw_pcie_parent_bus_offset() PCI: dwc: Consolidate devicetree handling in dw_pcie_host_get_resources() PCI: dwc: Call devm_pci_alloc_host_bridge() early in dw_pcie_host_init() PCI: dwc: Rename cpu_addr to parent_bus_addr for ATU configuration PCI: dwc: Use resource start as ioremap() input in dw_pcie_pme_turn_off() # Conflicts: # drivers/pci/controller/dwc/pcie-designware.c # drivers/pci/controller/dwc/pcie-designware.h
This commit is contained in:
commit
63c83f1fff
|
|
@ -1214,22 +1214,6 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp)
|
|||
regulator_disable(imx_pcie->vpcie);
|
||||
}
|
||||
|
||||
static u64 imx_pcie_cpu_addr_fixup(struct dw_pcie *pcie, u64 cpu_addr)
|
||||
{
|
||||
struct imx_pcie *imx_pcie = to_imx_pcie(pcie);
|
||||
struct dw_pcie_rp *pp = &pcie->pp;
|
||||
struct resource_entry *entry;
|
||||
|
||||
if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_CPU_ADDR_FIXUP))
|
||||
return cpu_addr;
|
||||
|
||||
entry = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM);
|
||||
if (!entry)
|
||||
return cpu_addr;
|
||||
|
||||
return cpu_addr - entry->offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* In old DWC implementations, PCIE_ATU_INHIBIT_PAYLOAD in iATU Ctrl2
|
||||
* register is reserved, so the generic DWC implementation of sending the
|
||||
|
|
@ -1260,7 +1244,6 @@ static const struct dw_pcie_host_ops imx_pcie_host_dw_pme_ops = {
|
|||
static const struct dw_pcie_ops dw_pcie_ops = {
|
||||
.start_link = imx_pcie_start_link,
|
||||
.stop_link = imx_pcie_stop_link,
|
||||
.cpu_addr_fixup = imx_pcie_cpu_addr_fixup,
|
||||
};
|
||||
|
||||
static void imx_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
|
|
@ -1631,6 +1614,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pci->use_parent_dt_ranges = true;
|
||||
if (imx_pcie->drvdata->mode == DW_PCIE_EP_TYPE) {
|
||||
ret = imx_add_pcie_ep(imx_pcie, pdev);
|
||||
if (ret < 0)
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
|||
}
|
||||
|
||||
static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
|
||||
dma_addr_t cpu_addr, enum pci_barno bar,
|
||||
dma_addr_t parent_bus_addr, enum pci_barno bar,
|
||||
size_t size)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -185,7 +185,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
|
|||
}
|
||||
|
||||
ret = dw_pcie_prog_ep_inbound_atu(pci, func_no, free_win, type,
|
||||
cpu_addr, bar, size);
|
||||
parent_bus_addr, bar, size);
|
||||
if (ret < 0) {
|
||||
dev_err(pci->dev, "Failed to program IB window\n");
|
||||
return ret;
|
||||
|
|
@ -220,7 +220,7 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep,
|
|||
return ret;
|
||||
|
||||
set_bit(free_win, ep->ob_window_map);
|
||||
ep->outbound_addr[free_win] = atu->cpu_addr;
|
||||
ep->outbound_addr[free_win] = atu->parent_bus_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -451,7 +451,7 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
|
|||
u32 index;
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
|
||||
for (index = 0; index < pci->num_ob_windows; index++) {
|
||||
for_each_set_bit(index, ep->ob_window_map, pci->num_ob_windows) {
|
||||
if (ep->outbound_addr[index] != addr)
|
||||
continue;
|
||||
*atu_index = index;
|
||||
|
|
@ -483,7 +483,8 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
|||
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
|
||||
ret = dw_pcie_find_index(ep, addr, &atu_index);
|
||||
ret = dw_pcie_find_index(ep, addr - pci->parent_bus_offset,
|
||||
&atu_index);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
|
|
@ -502,7 +503,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
|
|||
|
||||
atu.func_no = func_no;
|
||||
atu.type = PCIE_ATU_TYPE_MEM;
|
||||
atu.cpu_addr = addr;
|
||||
atu.parent_bus_addr = addr - pci->parent_bus_offset;
|
||||
atu.pci_addr = pci_addr;
|
||||
atu.size = size;
|
||||
ret = dw_pcie_ep_outbound_atu(ep, &atu);
|
||||
|
|
@ -1060,26 +1061,15 @@ void dw_pcie_ep_linkdown(struct dw_pcie_ep *ep)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(dw_pcie_ep_linkdown);
|
||||
|
||||
/**
|
||||
* dw_pcie_ep_init - Initialize the endpoint device
|
||||
* @ep: DWC EP device
|
||||
*
|
||||
* Initialize the endpoint device. Allocate resources and create the EPC
|
||||
* device with the endpoint framework.
|
||||
*
|
||||
* Return: 0 if success, errno otherwise.
|
||||
*/
|
||||
int dw_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
static int dw_pcie_ep_get_resources(struct dw_pcie_ep *ep)
|
||||
{
|
||||
int ret;
|
||||
struct resource *res;
|
||||
struct pci_epc *epc;
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
struct device *dev = pci->dev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
INIT_LIST_HEAD(&ep->func_list);
|
||||
struct pci_epc *epc = ep->epc;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
ret = dw_pcie_get_resources(pci);
|
||||
if (ret)
|
||||
|
|
@ -1092,8 +1082,37 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
|
|||
ep->phys_base = res->start;
|
||||
ep->addr_size = resource_size(res);
|
||||
|
||||
if (ep->ops->pre_init)
|
||||
ep->ops->pre_init(ep);
|
||||
/*
|
||||
* artpec6_pcie_cpu_addr_fixup() uses ep->phys_base, so call
|
||||
* dw_pcie_parent_bus_offset() after setting ep->phys_base.
|
||||
*/
|
||||
pci->parent_bus_offset = dw_pcie_parent_bus_offset(pci, "addr_space",
|
||||
ep->phys_base);
|
||||
|
||||
ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
|
||||
if (ret < 0)
|
||||
epc->max_functions = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dw_pcie_ep_init - Initialize the endpoint device
|
||||
* @ep: DWC EP device
|
||||
*
|
||||
* Initialize the endpoint device. Allocate resources and create the EPC
|
||||
* device with the endpoint framework.
|
||||
*
|
||||
* Return: 0 if success, errno otherwise.
|
||||
*/
|
||||
int dw_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
{
|
||||
int ret;
|
||||
struct pci_epc *epc;
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
struct device *dev = pci->dev;
|
||||
|
||||
INIT_LIST_HEAD(&ep->func_list);
|
||||
|
||||
epc = devm_pci_epc_create(dev, &epc_ops);
|
||||
if (IS_ERR(epc)) {
|
||||
|
|
@ -1104,9 +1123,12 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
|
|||
ep->epc = epc;
|
||||
epc_set_drvdata(epc, ep);
|
||||
|
||||
ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
|
||||
if (ret < 0)
|
||||
epc->max_functions = 1;
|
||||
ret = dw_pcie_ep_get_resources(ep);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ep->ops->pre_init)
|
||||
ep->ops->pre_init(ep);
|
||||
|
||||
ret = pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
|
||||
ep->page_size);
|
||||
|
|
|
|||
|
|
@ -418,19 +418,15 @@ static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
|
|||
}
|
||||
}
|
||||
|
||||
int dw_pcie_host_init(struct dw_pcie_rp *pp)
|
||||
static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||||
struct device *dev = pci->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct resource_entry *win;
|
||||
struct pci_host_bridge *bridge;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
raw_spin_lock_init(&pp->lock);
|
||||
|
||||
ret = dw_pcie_get_resources(pci);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -448,19 +444,42 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
|
|||
if (IS_ERR(pp->va_cfg0_base))
|
||||
return PTR_ERR(pp->va_cfg0_base);
|
||||
|
||||
/* Get the I/O range from DT */
|
||||
win = resource_list_first_type(&pp->bridge->windows, IORESOURCE_IO);
|
||||
if (win) {
|
||||
pp->io_size = resource_size(win->res);
|
||||
pp->io_bus_addr = win->res->start - win->offset;
|
||||
pp->io_base = pci_pio_to_address(win->res->start);
|
||||
}
|
||||
|
||||
/*
|
||||
* visconti_pcie_cpu_addr_fixup() uses pp->io_base, so we have to
|
||||
* call dw_pcie_parent_bus_offset() after setting pp->io_base.
|
||||
*/
|
||||
pci->parent_bus_offset = dw_pcie_parent_bus_offset(pci, "config",
|
||||
pp->cfg0_base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dw_pcie_host_init(struct dw_pcie_rp *pp)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||||
struct device *dev = pci->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct pci_host_bridge *bridge;
|
||||
int ret;
|
||||
|
||||
raw_spin_lock_init(&pp->lock);
|
||||
|
||||
bridge = devm_pci_alloc_host_bridge(dev, 0);
|
||||
if (!bridge)
|
||||
return -ENOMEM;
|
||||
|
||||
pp->bridge = bridge;
|
||||
|
||||
/* Get the I/O range from DT */
|
||||
win = resource_list_first_type(&bridge->windows, IORESOURCE_IO);
|
||||
if (win) {
|
||||
pp->io_size = resource_size(win->res);
|
||||
pp->io_bus_addr = win->res->start - win->offset;
|
||||
pp->io_base = pci_pio_to_address(win->res->start);
|
||||
}
|
||||
ret = dw_pcie_host_get_resources(pp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set default bus ops */
|
||||
bridge->ops = &dw_pcie_ops;
|
||||
|
|
@ -620,7 +639,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
|
|||
type = PCIE_ATU_TYPE_CFG1;
|
||||
|
||||
atu.type = type;
|
||||
atu.cpu_addr = pp->cfg0_base;
|
||||
atu.parent_bus_addr = pp->cfg0_base - pci->parent_bus_offset;
|
||||
atu.pci_addr = busdev;
|
||||
atu.size = pp->cfg0_size;
|
||||
|
||||
|
|
@ -645,7 +664,7 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
|
|||
|
||||
if (pp->cfg0_io_shared) {
|
||||
atu.type = PCIE_ATU_TYPE_IO;
|
||||
atu.cpu_addr = pp->io_base;
|
||||
atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
|
||||
atu.pci_addr = pp->io_bus_addr;
|
||||
atu.size = pp->io_size;
|
||||
|
||||
|
|
@ -671,7 +690,7 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
|
|||
|
||||
if (pp->cfg0_io_shared) {
|
||||
atu.type = PCIE_ATU_TYPE_IO;
|
||||
atu.cpu_addr = pp->io_base;
|
||||
atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
|
||||
atu.pci_addr = pp->io_bus_addr;
|
||||
atu.size = pp->io_size;
|
||||
|
||||
|
|
@ -740,7 +759,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
|
|||
|
||||
atu.index = i;
|
||||
atu.type = PCIE_ATU_TYPE_MEM;
|
||||
atu.cpu_addr = entry->res->start;
|
||||
atu.parent_bus_addr = entry->res->start - pci->parent_bus_offset;
|
||||
atu.pci_addr = entry->res->start - entry->offset;
|
||||
|
||||
/* Adjust iATU size if MSG TLP region was allocated before */
|
||||
|
|
@ -762,7 +781,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
|
|||
if (pci->num_ob_windows > ++i) {
|
||||
atu.index = i;
|
||||
atu.type = PCIE_ATU_TYPE_IO;
|
||||
atu.cpu_addr = pp->io_base;
|
||||
atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
|
||||
atu.pci_addr = pp->io_bus_addr;
|
||||
atu.size = pp->io_size;
|
||||
|
||||
|
|
@ -906,13 +925,13 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
|
|||
atu.size = resource_size(pci->pp.msg_res);
|
||||
atu.index = pci->pp.msg_atu_index;
|
||||
|
||||
atu.cpu_addr = pci->pp.msg_res->start;
|
||||
atu.parent_bus_addr = pci->pp.msg_res->start - pci->parent_bus_offset;
|
||||
|
||||
ret = dw_pcie_prog_outbound_atu(pci, &atu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mem = ioremap(atu.cpu_addr, pci->region_align);
|
||||
mem = ioremap(pci->pp.msg_res->start, pci->region_align);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/pcie-dwc.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sizes.h>
|
||||
|
|
@ -516,25 +517,22 @@ static inline u32 dw_pcie_enable_ecrc(u32 val)
|
|||
int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
|
||||
const struct dw_pcie_ob_atu_cfg *atu)
|
||||
{
|
||||
u64 cpu_addr = atu->cpu_addr;
|
||||
u64 parent_bus_addr = atu->parent_bus_addr;
|
||||
u32 retries, val;
|
||||
u64 limit_addr;
|
||||
|
||||
if (pci->ops && pci->ops->cpu_addr_fixup)
|
||||
cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
|
||||
limit_addr = parent_bus_addr + atu->size - 1;
|
||||
|
||||
limit_addr = cpu_addr + atu->size - 1;
|
||||
|
||||
if ((limit_addr & ~pci->region_limit) != (cpu_addr & ~pci->region_limit) ||
|
||||
!IS_ALIGNED(cpu_addr, pci->region_align) ||
|
||||
if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) ||
|
||||
!IS_ALIGNED(parent_bus_addr, pci->region_align) ||
|
||||
!IS_ALIGNED(atu->pci_addr, pci->region_align) || !atu->size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LOWER_BASE,
|
||||
lower_32_bits(cpu_addr));
|
||||
lower_32_bits(parent_bus_addr));
|
||||
dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_UPPER_BASE,
|
||||
upper_32_bits(cpu_addr));
|
||||
upper_32_bits(parent_bus_addr));
|
||||
|
||||
dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LIMIT,
|
||||
lower_32_bits(limit_addr));
|
||||
|
|
@ -548,7 +546,7 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
|
|||
upper_32_bits(atu->pci_addr));
|
||||
|
||||
val = atu->type | atu->routing | PCIE_ATU_FUNC_NUM(atu->func_no);
|
||||
if (upper_32_bits(limit_addr) > upper_32_bits(cpu_addr) &&
|
||||
if (upper_32_bits(limit_addr) > upper_32_bits(parent_bus_addr) &&
|
||||
dw_pcie_ver_is_ge(pci, 460A))
|
||||
val |= PCIE_ATU_INCREASE_REGION_SIZE;
|
||||
if (dw_pcie_ver_is(pci, 490A))
|
||||
|
|
@ -591,13 +589,13 @@ static inline void dw_pcie_writel_atu_ib(struct dw_pcie *pci, u32 index, u32 reg
|
|||
}
|
||||
|
||||
int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
|
||||
u64 cpu_addr, u64 pci_addr, u64 size)
|
||||
u64 parent_bus_addr, u64 pci_addr, u64 size)
|
||||
{
|
||||
u64 limit_addr = pci_addr + size - 1;
|
||||
u32 retries, val;
|
||||
|
||||
if ((limit_addr & ~pci->region_limit) != (pci_addr & ~pci->region_limit) ||
|
||||
!IS_ALIGNED(cpu_addr, pci->region_align) ||
|
||||
!IS_ALIGNED(parent_bus_addr, pci->region_align) ||
|
||||
!IS_ALIGNED(pci_addr, pci->region_align) || !size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -614,9 +612,9 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
|
|||
upper_32_bits(limit_addr));
|
||||
|
||||
dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,
|
||||
lower_32_bits(cpu_addr));
|
||||
lower_32_bits(parent_bus_addr));
|
||||
dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET,
|
||||
upper_32_bits(cpu_addr));
|
||||
upper_32_bits(parent_bus_addr));
|
||||
|
||||
val = type;
|
||||
if (upper_32_bits(limit_addr) > upper_32_bits(pci_addr) &&
|
||||
|
|
@ -643,18 +641,18 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
|
|||
}
|
||||
|
||||
int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
|
||||
int type, u64 cpu_addr, u8 bar, size_t size)
|
||||
int type, u64 parent_bus_addr, u8 bar, size_t size)
|
||||
{
|
||||
u32 retries, val;
|
||||
|
||||
if (!IS_ALIGNED(cpu_addr, pci->region_align) ||
|
||||
!IS_ALIGNED(cpu_addr, size))
|
||||
if (!IS_ALIGNED(parent_bus_addr, pci->region_align) ||
|
||||
!IS_ALIGNED(parent_bus_addr, size))
|
||||
return -EINVAL;
|
||||
|
||||
dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,
|
||||
lower_32_bits(cpu_addr));
|
||||
lower_32_bits(parent_bus_addr));
|
||||
dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET,
|
||||
upper_32_bits(cpu_addr));
|
||||
upper_32_bits(parent_bus_addr));
|
||||
|
||||
dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_REGION_CTRL1, type |
|
||||
PCIE_ATU_FUNC_NUM(func_no));
|
||||
|
|
@ -1151,3 +1149,63 @@ void dw_pcie_setup(struct dw_pcie *pci)
|
|||
|
||||
dw_pcie_link_set_max_link_width(pci, pci->num_lanes);
|
||||
}
|
||||
|
||||
resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
|
||||
const char *reg_name,
|
||||
resource_size_t cpu_phys_addr)
|
||||
{
|
||||
struct device *dev = pci->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
int index;
|
||||
u64 reg_addr, fixup_addr;
|
||||
u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
|
||||
|
||||
/* Look up reg_name address on parent bus */
|
||||
index = of_property_match_string(np, "reg-names", reg_name);
|
||||
|
||||
if (index < 0) {
|
||||
dev_err(dev, "No %s in devicetree \"reg\" property\n", reg_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
of_property_read_reg(np, index, ®_addr, NULL);
|
||||
|
||||
fixup = pci->ops ? pci->ops->cpu_addr_fixup : NULL;
|
||||
if (fixup) {
|
||||
fixup_addr = fixup(pci, cpu_phys_addr);
|
||||
if (reg_addr == fixup_addr) {
|
||||
dev_info(dev, "%s reg[%d] %#010llx == %#010llx == fixup(cpu %#010llx); %ps is redundant with this devicetree\n",
|
||||
reg_name, index, reg_addr, fixup_addr,
|
||||
(unsigned long long) cpu_phys_addr, fixup);
|
||||
} else {
|
||||
dev_warn(dev, "%s reg[%d] %#010llx != %#010llx == fixup(cpu %#010llx); devicetree is broken\n",
|
||||
reg_name, index, reg_addr, fixup_addr,
|
||||
(unsigned long long) cpu_phys_addr);
|
||||
reg_addr = fixup_addr;
|
||||
}
|
||||
|
||||
return cpu_phys_addr - reg_addr;
|
||||
}
|
||||
|
||||
if (pci->use_parent_dt_ranges) {
|
||||
|
||||
/*
|
||||
* This platform once had a fixup, presumably because it
|
||||
* translates between CPU and PCI controller addresses.
|
||||
* Log a note if devicetree didn't describe a translation.
|
||||
*/
|
||||
if (reg_addr == cpu_phys_addr)
|
||||
dev_info(dev, "%s reg[%d] %#010llx == cpu %#010llx\n; no fixup was ever needed for this devicetree\n",
|
||||
reg_name, index, reg_addr,
|
||||
(unsigned long long) cpu_phys_addr);
|
||||
} else {
|
||||
if (reg_addr != cpu_phys_addr) {
|
||||
dev_warn(dev, "%s reg[%d] %#010llx != cpu %#010llx; no fixup and devicetree \"ranges\" is broken, assuming no translation\n",
|
||||
reg_name, index, reg_addr,
|
||||
(unsigned long long) cpu_phys_addr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return cpu_phys_addr - reg_addr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ struct dw_pcie_ob_atu_cfg {
|
|||
u8 func_no;
|
||||
u8 code;
|
||||
u8 routing;
|
||||
u64 cpu_addr;
|
||||
u64 parent_bus_addr;
|
||||
u64 pci_addr;
|
||||
u64 size;
|
||||
};
|
||||
|
|
@ -481,6 +481,7 @@ struct dw_pcie {
|
|||
void __iomem *atu_base;
|
||||
resource_size_t atu_phys_addr;
|
||||
size_t atu_size;
|
||||
resource_size_t parent_bus_offset;
|
||||
u32 num_ib_windows;
|
||||
u32 num_ob_windows;
|
||||
u32 region_align;
|
||||
|
|
@ -502,6 +503,19 @@ struct dw_pcie {
|
|||
struct gpio_desc *pe_rst;
|
||||
bool suspended;
|
||||
struct debugfs_info *debugfs;
|
||||
|
||||
/*
|
||||
* If iATU input addresses are offset from CPU physical addresses,
|
||||
* we previously required .cpu_addr_fixup() to convert them. We
|
||||
* now rely on the devicetree instead. If .cpu_addr_fixup()
|
||||
* exists, we compare its results with devicetree.
|
||||
*
|
||||
* If .cpu_addr_fixup() does not exist, we assume the offset is
|
||||
* zero and warn if devicetree claims otherwise. If we know all
|
||||
* devicetrees correctly describe the offset, set
|
||||
* use_parent_dt_ranges to true to avoid this warning.
|
||||
*/
|
||||
bool use_parent_dt_ranges;
|
||||
};
|
||||
|
||||
#define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
|
||||
|
|
@ -529,14 +543,18 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci);
|
|||
int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
|
||||
const struct dw_pcie_ob_atu_cfg *atu);
|
||||
int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
|
||||
u64 cpu_addr, u64 pci_addr, u64 size);
|
||||
u64 parent_bus_addr, u64 pci_addr, u64 size);
|
||||
int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
|
||||
int type, u64 cpu_addr, u8 bar, size_t size);
|
||||
int type, u64 parent_bus_addr,
|
||||
u8 bar, size_t size);
|
||||
void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index);
|
||||
void dw_pcie_setup(struct dw_pcie *pci);
|
||||
void dw_pcie_iatu_detect(struct dw_pcie *pci);
|
||||
int dw_pcie_edma_detect(struct dw_pcie *pci);
|
||||
void dw_pcie_edma_remove(struct dw_pcie *pci);
|
||||
resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
|
||||
const char *reg_name,
|
||||
resource_size_t cpu_phy_addr);
|
||||
|
||||
static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@
|
|||
PCIE_APP_IRN_INTA | PCIE_APP_IRN_INTB | \
|
||||
PCIE_APP_IRN_INTC | PCIE_APP_IRN_INTD)
|
||||
|
||||
#define BUS_IATU_OFFSET SZ_256M
|
||||
#define RESET_INTERVAL_MS 100
|
||||
|
||||
struct intel_pcie {
|
||||
|
|
@ -381,13 +380,7 @@ static int intel_pcie_rc_init(struct dw_pcie_rp *pp)
|
|||
return intel_pcie_host_setup(pcie);
|
||||
}
|
||||
|
||||
static u64 intel_pcie_cpu_addr(struct dw_pcie *pcie, u64 cpu_addr)
|
||||
{
|
||||
return cpu_addr + BUS_IATU_OFFSET;
|
||||
}
|
||||
|
||||
static const struct dw_pcie_ops intel_pcie_ops = {
|
||||
.cpu_addr_fixup = intel_pcie_cpu_addr,
|
||||
};
|
||||
|
||||
static const struct dw_pcie_host_ops intel_pcie_dw_ops = {
|
||||
|
|
@ -409,6 +402,7 @@ static int intel_pcie_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, pcie);
|
||||
pci = &pcie->pci;
|
||||
pci->dev = dev;
|
||||
pci->use_parent_dt_ranges = true;
|
||||
pp = &pci->pp;
|
||||
|
||||
ret = intel_pcie_get_resources(pdev);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user