mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-27 06:34:11 +08:00
Merge branch 'pci/host-mvebu' into next
* pci/host-mvebu: PCI: mvebu: Remove duplicate of_clk_get_by_name() call PCI: mvebu: Support a bridge with no IO port window PCI: mvebu: Obey bridge PCI_COMMAND_MEM and PCI_COMMAND_IO bits PCI: mvebu: Drop writes to bridge Secondary Status register
This commit is contained in:
commit
7160266a26
@ -150,6 +150,11 @@ static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg)
|
|||||||
return readl(port->base + reg);
|
return readl(port->base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool mvebu_has_ioport(struct mvebu_pcie_port *port)
|
||||||
|
{
|
||||||
|
return port->io_target != -1 && port->io_attr != -1;
|
||||||
|
}
|
||||||
|
|
||||||
static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port)
|
static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port)
|
||||||
{
|
{
|
||||||
return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
|
return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
|
||||||
@ -300,7 +305,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
|
|||||||
|
|
||||||
/* Are the new iobase/iolimit values invalid? */
|
/* Are the new iobase/iolimit values invalid? */
|
||||||
if (port->bridge.iolimit < port->bridge.iobase ||
|
if (port->bridge.iolimit < port->bridge.iobase ||
|
||||||
port->bridge.iolimitupper < port->bridge.iobaseupper) {
|
port->bridge.iolimitupper < port->bridge.iobaseupper ||
|
||||||
|
!(port->bridge.command & PCI_COMMAND_IO)) {
|
||||||
|
|
||||||
/* If a window was configured, remove it */
|
/* If a window was configured, remove it */
|
||||||
if (port->iowin_base) {
|
if (port->iowin_base) {
|
||||||
@ -313,6 +319,12 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mvebu_has_ioport(port)) {
|
||||||
|
dev_WARN(&port->pcie->pdev->dev,
|
||||||
|
"Attempt to set IO when IO is disabled\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We read the PCI-to-PCI bridge emulated registers, and
|
* We read the PCI-to-PCI bridge emulated registers, and
|
||||||
* calculate the base address and size of the address decoding
|
* calculate the base address and size of the address decoding
|
||||||
@ -337,7 +349,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
|
|||||||
static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
|
static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
|
||||||
{
|
{
|
||||||
/* Are the new membase/memlimit values invalid? */
|
/* Are the new membase/memlimit values invalid? */
|
||||||
if (port->bridge.memlimit < port->bridge.membase) {
|
if (port->bridge.memlimit < port->bridge.membase ||
|
||||||
|
!(port->bridge.command & PCI_COMMAND_MEMORY)) {
|
||||||
|
|
||||||
/* If a window was configured, remove it */
|
/* If a window was configured, remove it */
|
||||||
if (port->memwin_base) {
|
if (port->memwin_base) {
|
||||||
@ -426,9 +439,12 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_IO_BASE:
|
case PCI_IO_BASE:
|
||||||
*value = (bridge->secondary_status << 16 |
|
if (!mvebu_has_ioport(port))
|
||||||
bridge->iolimit << 8 |
|
*value = bridge->secondary_status << 16;
|
||||||
bridge->iobase);
|
else
|
||||||
|
*value = (bridge->secondary_status << 16 |
|
||||||
|
bridge->iolimit << 8 |
|
||||||
|
bridge->iobase);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_MEMORY_BASE:
|
case PCI_MEMORY_BASE:
|
||||||
@ -490,8 +506,19 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
|
|||||||
|
|
||||||
switch (where & ~3) {
|
switch (where & ~3) {
|
||||||
case PCI_COMMAND:
|
case PCI_COMMAND:
|
||||||
|
{
|
||||||
|
u32 old = bridge->command;
|
||||||
|
|
||||||
|
if (!mvebu_has_ioport(port))
|
||||||
|
value &= ~PCI_COMMAND_IO;
|
||||||
|
|
||||||
bridge->command = value & 0xffff;
|
bridge->command = value & 0xffff;
|
||||||
|
if ((old ^ bridge->command) & PCI_COMMAND_IO)
|
||||||
|
mvebu_pcie_handle_iobase_change(port);
|
||||||
|
if ((old ^ bridge->command) & PCI_COMMAND_MEMORY)
|
||||||
|
mvebu_pcie_handle_membase_change(port);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
|
case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
|
||||||
bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value;
|
bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value;
|
||||||
@ -505,7 +532,6 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
|
|||||||
*/
|
*/
|
||||||
bridge->iobase = (value & 0xff) | PCI_IO_RANGE_TYPE_32;
|
bridge->iobase = (value & 0xff) | PCI_IO_RANGE_TYPE_32;
|
||||||
bridge->iolimit = ((value >> 8) & 0xff) | PCI_IO_RANGE_TYPE_32;
|
bridge->iolimit = ((value >> 8) & 0xff) | PCI_IO_RANGE_TYPE_32;
|
||||||
bridge->secondary_status = value >> 16;
|
|
||||||
mvebu_pcie_handle_iobase_change(port);
|
mvebu_pcie_handle_iobase_change(port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -656,7 +682,9 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
|
|||||||
struct mvebu_pcie *pcie = sys_to_pcie(sys);
|
struct mvebu_pcie *pcie = sys_to_pcie(sys);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
pci_add_resource_offset(&sys->resources, &pcie->realio, sys->io_offset);
|
if (resource_size(&pcie->realio) != 0)
|
||||||
|
pci_add_resource_offset(&sys->resources, &pcie->realio,
|
||||||
|
sys->io_offset);
|
||||||
pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
|
pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
|
||||||
pci_add_resource(&sys->resources, &pcie->busn);
|
pci_add_resource(&sys->resources, &pcie->busn);
|
||||||
|
|
||||||
@ -757,12 +785,17 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev,
|
|||||||
#define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF)
|
#define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF)
|
||||||
|
|
||||||
static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
|
static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
|
||||||
unsigned long type, int *tgt, int *attr)
|
unsigned long type,
|
||||||
|
unsigned int *tgt,
|
||||||
|
unsigned int *attr)
|
||||||
{
|
{
|
||||||
const int na = 3, ns = 2;
|
const int na = 3, ns = 2;
|
||||||
const __be32 *range;
|
const __be32 *range;
|
||||||
int rlen, nranges, rangesz, pna, i;
|
int rlen, nranges, rangesz, pna, i;
|
||||||
|
|
||||||
|
*tgt = -1;
|
||||||
|
*attr = -1;
|
||||||
|
|
||||||
range = of_get_property(np, "ranges", &rlen);
|
range = of_get_property(np, "ranges", &rlen);
|
||||||
if (!range)
|
if (!range)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -832,16 +865,15 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mvebu_mbus_get_pcie_io_aperture(&pcie->io);
|
mvebu_mbus_get_pcie_io_aperture(&pcie->io);
|
||||||
if (resource_size(&pcie->io) == 0) {
|
|
||||||
dev_err(&pdev->dev, "invalid I/O aperture size\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pcie->realio.flags = pcie->io.flags;
|
if (resource_size(&pcie->io) != 0) {
|
||||||
pcie->realio.start = PCIBIOS_MIN_IO;
|
pcie->realio.flags = pcie->io.flags;
|
||||||
pcie->realio.end = min_t(resource_size_t,
|
pcie->realio.start = PCIBIOS_MIN_IO;
|
||||||
IO_SPACE_LIMIT,
|
pcie->realio.end = min_t(resource_size_t,
|
||||||
resource_size(&pcie->io));
|
IO_SPACE_LIMIT,
|
||||||
|
resource_size(&pcie->io));
|
||||||
|
} else
|
||||||
|
pcie->realio = pcie->io;
|
||||||
|
|
||||||
/* Get the bus range */
|
/* Get the bus range */
|
||||||
ret = of_pci_parse_bus_range(np, &pcie->busn);
|
ret = of_pci_parse_bus_range(np, &pcie->busn);
|
||||||
@ -900,12 +932,12 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO,
|
if (resource_size(&pcie->io) != 0)
|
||||||
&port->io_target, &port->io_attr);
|
mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO,
|
||||||
if (ret < 0) {
|
&port->io_target, &port->io_attr);
|
||||||
dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n",
|
else {
|
||||||
port->port, port->lane);
|
port->io_target = -1;
|
||||||
continue;
|
port->io_attr = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
port->reset_gpio = of_get_named_gpio_flags(child,
|
port->reset_gpio = of_get_named_gpio_flags(child,
|
||||||
@ -954,14 +986,6 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
mvebu_pcie_set_local_dev_nr(port, 1);
|
mvebu_pcie_set_local_dev_nr(port, 1);
|
||||||
|
|
||||||
port->clk = of_clk_get_by_name(child, NULL);
|
|
||||||
if (IS_ERR(port->clk)) {
|
|
||||||
dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
|
|
||||||
port->port, port->lane);
|
|
||||||
iounmap(port->base);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
port->dn = child;
|
port->dn = child;
|
||||||
spin_lock_init(&port->conf_lock);
|
spin_lock_init(&port->conf_lock);
|
||||||
mvebu_sw_pci_bridge_init(port);
|
mvebu_sw_pci_bridge_init(port);
|
||||||
|
Loading…
Reference in New Issue
Block a user