mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
Merge branches 'pci/host-designware', 'pci/host-imx6', 'pci/host-mvebu' and 'pci/host-tegra' into next
* pci/host-designware: PCI: designware: Remove unnecessary use of 'conf_lock' spinlock PCI: designware: Use new OF interrupt mapping when possible PCI: designware: Fix iATU programming for cfg1, io and mem viewport PCI: designware: Fix comment for setting number of lanes * pci/host-imx6: PCI: designware: Split Exynos and i.MX bindings * pci/host-mvebu: PCI: mvebu: Use '%pa' for printing 'phys_addr_t' type PCI: mvebu: Remove unnecessary use of 'conf_lock' spinlock PCI: mvebu: split PCIe BARs into multiple MBus windows when needed bus: mvebu-mbus: allow several windows with the same target/attribute bus: mvebu-mbus: Avoid setting an undefined window size PCI: mvebu: fix off-by-one in the computed size of the mbus windows * pci/host-tegra: PCI: tegra: Use new OF interrupt mapping when possible
This commit is contained in:
commit
843a85ced9
10 changed files with 222 additions and 115 deletions
|
|
@ -545,7 +545,6 @@ static int __init add_pcie_port(struct pcie_port *pp,
|
|||
pp->root_bus_nr = -1;
|
||||
pp->ops = &exynos_pcie_host_ops;
|
||||
|
||||
spin_lock_init(&pp->conf_lock);
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize host\n");
|
||||
|
|
|
|||
|
|
@ -507,7 +507,6 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
|
|||
pp->root_bus_nr = -1;
|
||||
pp->ops = &imx6_pcie_host_ops;
|
||||
|
||||
spin_lock_init(&pp->conf_lock);
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize host\n");
|
||||
|
|
|
|||
|
|
@ -113,7 +113,6 @@ struct mvebu_pcie {
|
|||
struct mvebu_pcie_port {
|
||||
char *name;
|
||||
void __iomem *base;
|
||||
spinlock_t conf_lock;
|
||||
u32 port;
|
||||
u32 lane;
|
||||
int devfn;
|
||||
|
|
@ -293,6 +292,60 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
|
|||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove windows, starting from the largest ones to the smallest
|
||||
* ones.
|
||||
*/
|
||||
static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port,
|
||||
phys_addr_t base, size_t size)
|
||||
{
|
||||
while (size) {
|
||||
size_t sz = 1 << (fls(size) - 1);
|
||||
|
||||
mvebu_mbus_del_window(base, sz);
|
||||
base += sz;
|
||||
size -= sz;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* MBus windows can only have a power of two size, but PCI BARs do not
|
||||
* have this constraint. Therefore, we have to split the PCI BAR into
|
||||
* areas each having a power of two size. We start from the largest
|
||||
* one (i.e highest order bit set in the size).
|
||||
*/
|
||||
static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port,
|
||||
unsigned int target, unsigned int attribute,
|
||||
phys_addr_t base, size_t size,
|
||||
phys_addr_t remap)
|
||||
{
|
||||
size_t size_mapped = 0;
|
||||
|
||||
while (size) {
|
||||
size_t sz = 1 << (fls(size) - 1);
|
||||
int ret;
|
||||
|
||||
ret = mvebu_mbus_add_window_remap_by_id(target, attribute, base,
|
||||
sz, remap);
|
||||
if (ret) {
|
||||
phys_addr_t end = base + sz - 1;
|
||||
|
||||
dev_err(&port->pcie->pdev->dev,
|
||||
"Could not create MBus window at [mem %pa-%pa]: %d\n",
|
||||
&base, &end, ret);
|
||||
mvebu_pcie_del_windows(port, base - size_mapped,
|
||||
size_mapped);
|
||||
return;
|
||||
}
|
||||
|
||||
size -= sz;
|
||||
size_mapped += sz;
|
||||
base += sz;
|
||||
if (remap != MVEBU_MBUS_NO_REMAP)
|
||||
remap += sz;
|
||||
}
|
||||
}
|
||||
|
||||
static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
|
||||
{
|
||||
phys_addr_t iobase;
|
||||
|
|
@ -304,8 +357,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
|
|||
|
||||
/* If a window was configured, remove it */
|
||||
if (port->iowin_base) {
|
||||
mvebu_mbus_del_window(port->iowin_base,
|
||||
port->iowin_size);
|
||||
mvebu_pcie_del_windows(port, port->iowin_base,
|
||||
port->iowin_size);
|
||||
port->iowin_base = 0;
|
||||
port->iowin_size = 0;
|
||||
}
|
||||
|
|
@ -331,11 +384,11 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
|
|||
port->iowin_base = port->pcie->io.start + iobase;
|
||||
port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) |
|
||||
(port->bridge.iolimitupper << 16)) -
|
||||
iobase);
|
||||
iobase) + 1;
|
||||
|
||||
mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr,
|
||||
port->iowin_base, port->iowin_size,
|
||||
iobase);
|
||||
mvebu_pcie_add_windows(port, port->io_target, port->io_attr,
|
||||
port->iowin_base, port->iowin_size,
|
||||
iobase);
|
||||
}
|
||||
|
||||
static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
|
||||
|
|
@ -346,8 +399,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
|
|||
|
||||
/* If a window was configured, remove it */
|
||||
if (port->memwin_base) {
|
||||
mvebu_mbus_del_window(port->memwin_base,
|
||||
port->memwin_size);
|
||||
mvebu_pcie_del_windows(port, port->memwin_base,
|
||||
port->memwin_size);
|
||||
port->memwin_base = 0;
|
||||
port->memwin_size = 0;
|
||||
}
|
||||
|
|
@ -364,10 +417,11 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
|
|||
port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16);
|
||||
port->memwin_size =
|
||||
(((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) -
|
||||
port->memwin_base;
|
||||
port->memwin_base + 1;
|
||||
|
||||
mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr,
|
||||
port->memwin_base, port->memwin_size);
|
||||
mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr,
|
||||
port->memwin_base, port->memwin_size,
|
||||
MVEBU_MBUS_NO_REMAP);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -585,7 +639,6 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
|
|||
{
|
||||
struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
|
||||
struct mvebu_pcie_port *port;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
port = mvebu_pcie_find_port(pcie, bus, devfn);
|
||||
|
|
@ -611,10 +664,8 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
|
|||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
/* Access the real PCIe interface */
|
||||
spin_lock_irqsave(&port->conf_lock, flags);
|
||||
ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
|
||||
where, size, val);
|
||||
spin_unlock_irqrestore(&port->conf_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -625,7 +676,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
|
|||
{
|
||||
struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
|
||||
struct mvebu_pcie_port *port;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
port = mvebu_pcie_find_port(pcie, bus, devfn);
|
||||
|
|
@ -657,10 +707,8 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
|
|||
}
|
||||
|
||||
/* Access the real PCIe interface */
|
||||
spin_lock_irqsave(&port->conf_lock, flags);
|
||||
ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
|
||||
where, size, val);
|
||||
spin_unlock_irqrestore(&port->conf_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -743,14 +791,21 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
|
|||
|
||||
/*
|
||||
* On the PCI-to-PCI bridge side, the I/O windows must have at
|
||||
* least a 64 KB size and be aligned on their size, and the
|
||||
* memory windows must have at least a 1 MB size and be
|
||||
* aligned on their size
|
||||
* least a 64 KB size and the memory windows must have at
|
||||
* least a 1 MB size. Moreover, MBus windows need to have a
|
||||
* base address aligned on their size, and their size must be
|
||||
* a power of two. This means that if the BAR doesn't have a
|
||||
* power of two size, several MBus windows will actually be
|
||||
* created. We need to ensure that the biggest MBus window
|
||||
* (which will be the first one) is aligned on its size, which
|
||||
* explains the rounddown_pow_of_two() being done here.
|
||||
*/
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
return round_up(start, max_t(resource_size_t, SZ_64K, size));
|
||||
return round_up(start, max_t(resource_size_t, SZ_64K,
|
||||
rounddown_pow_of_two(size)));
|
||||
else if (res->flags & IORESOURCE_MEM)
|
||||
return round_up(start, max_t(resource_size_t, SZ_1M, size));
|
||||
return round_up(start, max_t(resource_size_t, SZ_1M,
|
||||
rounddown_pow_of_two(size)));
|
||||
else
|
||||
return start;
|
||||
}
|
||||
|
|
@ -1000,7 +1055,6 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
|
|||
mvebu_pcie_set_local_dev_nr(port, 1);
|
||||
|
||||
port->dn = child;
|
||||
spin_lock_init(&port->conf_lock);
|
||||
mvebu_sw_pci_bridge_init(port);
|
||||
i++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -639,10 +639,15 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
|
|||
static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
|
||||
{
|
||||
struct tegra_pcie *pcie = sys_to_pcie(pdev->bus->sysdata);
|
||||
int irq;
|
||||
|
||||
tegra_cpuidle_pcie_irqs_in_use();
|
||||
|
||||
return pcie->irq;
|
||||
irq = of_irq_parse_and_map_pci(pdev, slot, pin);
|
||||
if (!irq)
|
||||
irq = pcie->irq;
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static void tegra_pcie_add_bus(struct pci_bus *bus)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_pci.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci_regs.h>
|
||||
#include <linux/types.h>
|
||||
|
|
@ -494,7 +495,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
|
|||
dw_pci.nr_controllers = 1;
|
||||
dw_pci.private_data = (void **)&pp;
|
||||
|
||||
pci_common_init(&dw_pci);
|
||||
pci_common_init_dev(pp->dev, &dw_pci);
|
||||
pci_assign_unassigned_resources();
|
||||
#ifdef CONFIG_PCI_DOMAINS
|
||||
dw_pci.domain++;
|
||||
|
|
@ -524,13 +525,13 @@ static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev)
|
|||
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
|
||||
PCIE_ATU_VIEWPORT);
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1);
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
|
||||
dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE);
|
||||
dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE);
|
||||
dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1,
|
||||
PCIE_ATU_LIMIT);
|
||||
dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
|
||||
dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
|
||||
}
|
||||
|
||||
static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
|
||||
|
|
@ -539,7 +540,6 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
|
|||
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
|
||||
PCIE_ATU_VIEWPORT);
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1);
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
|
||||
dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE);
|
||||
dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE);
|
||||
dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1,
|
||||
|
|
@ -547,6 +547,7 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
|
|||
dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET);
|
||||
dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr),
|
||||
PCIE_ATU_UPPER_TARGET);
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
|
||||
}
|
||||
|
||||
static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
|
||||
|
|
@ -555,7 +556,6 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
|
|||
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
|
||||
PCIE_ATU_VIEWPORT);
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1);
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
|
||||
dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE);
|
||||
dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE);
|
||||
dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1,
|
||||
|
|
@ -563,6 +563,7 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
|
|||
dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET);
|
||||
dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr),
|
||||
PCIE_ATU_UPPER_TARGET);
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
|
||||
}
|
||||
|
||||
static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
|
||||
|
|
@ -642,7 +643,6 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
|
|||
int size, u32 *val)
|
||||
{
|
||||
struct pcie_port *pp = sys_to_pcie(bus->sysdata);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (!pp) {
|
||||
|
|
@ -655,13 +655,11 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
|
|||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&pp->conf_lock, flags);
|
||||
if (bus->number != pp->root_bus_nr)
|
||||
ret = dw_pcie_rd_other_conf(pp, bus, devfn,
|
||||
where, size, val);
|
||||
else
|
||||
ret = dw_pcie_rd_own_conf(pp, where, size, val);
|
||||
spin_unlock_irqrestore(&pp->conf_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -670,7 +668,6 @@ static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
|
|||
int where, int size, u32 val)
|
||||
{
|
||||
struct pcie_port *pp = sys_to_pcie(bus->sysdata);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (!pp) {
|
||||
|
|
@ -681,13 +678,11 @@ static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
|
|||
if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
spin_lock_irqsave(&pp->conf_lock, flags);
|
||||
if (bus->number != pp->root_bus_nr)
|
||||
ret = dw_pcie_wr_other_conf(pp, bus, devfn,
|
||||
where, size, val);
|
||||
else
|
||||
ret = dw_pcie_wr_own_conf(pp, where, size, val);
|
||||
spin_unlock_irqrestore(&pp->conf_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -727,7 +722,7 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
|
|||
|
||||
if (pp) {
|
||||
pp->root_bus_nr = sys->busnr;
|
||||
bus = pci_scan_root_bus(NULL, sys->busnr, &dw_pcie_ops,
|
||||
bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops,
|
||||
sys, &sys->resources);
|
||||
} else {
|
||||
bus = NULL;
|
||||
|
|
@ -740,8 +735,13 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
|
|||
static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
|
||||
int irq;
|
||||
|
||||
return pp->irq;
|
||||
irq = of_irq_parse_and_map_pci(dev, slot, pin);
|
||||
if (!irq)
|
||||
irq = pp->irq;
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static void dw_pcie_add_bus(struct pci_bus *bus)
|
||||
|
|
@ -768,7 +768,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
|
|||
u32 membase;
|
||||
u32 memlimit;
|
||||
|
||||
/* set the number of lines as 4 */
|
||||
/* set the number of lanes */
|
||||
dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val);
|
||||
val &= ~PORT_LINK_MODE_MASK;
|
||||
switch (pp->lanes) {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ struct pcie_port {
|
|||
void __iomem *va_cfg1_base;
|
||||
u64 io_base;
|
||||
u64 mem_base;
|
||||
spinlock_t conf_lock;
|
||||
struct resource cfg;
|
||||
struct resource io;
|
||||
struct resource mem;
|
||||
|
|
|
|||
Loading…
Reference in a new issue