Skip to content

Commit

Permalink
Merge branch 'remotes/lorenzo/pci/controller-misc'
Browse files Browse the repository at this point in the history
  - Remove redundant controller tests for "device_type == pci" (Rob
    Herring)

  - Document R-Car E3 (R8A77990) bindings (Tho Vu)

  - Add device tree support for R-Car r8a7744 (Biju Das)

  - Drop unused mvebu PCIe capability code (Thomas Petazzoni)

  - Add shared PCI bridge emulation code (Thomas Petazzoni)

  - Convert mvebu to use shared PCI bridge emulation (Thomas Petazzoni)

  - Add aardvark Root Port emulation (Thomas Petazzoni)

* remotes/lorenzo/pci/controller-misc:
  PCI: aardvark: Implement emulated root PCI bridge config space
  PCI: mvebu: Convert to PCI emulated bridge config space
  PCI: mvebu: Drop unused PCI express capability code
  PCI: Introduce PCI bridge emulated config space common logic
  dt-bindings: PCI: rcar: Add device tree support for r8a7744
  dt-bindings: PCI: rcar: Add device tree support for r8a7744
  DT: pci: rcar-pci: document R8A77990 bindings
  PCI: Remove unnecessary check of device_type == pci
  • Loading branch information
Bjorn Helgaas committed Oct 20, 2018
2 parents 61ce580 + 8a3ebd8 commit b7c18dc
Show file tree
Hide file tree
Showing 14 changed files with 767 additions and 325 deletions.
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ OHCI and EHCI controllers.

Required properties:
- compatible: "renesas,pci-r8a7743" for the R8A7743 SoC;
"renesas,pci-r8a7744" for the R8A7744 SoC;
"renesas,pci-r8a7745" for the R8A7745 SoC;
"renesas,pci-r8a7790" for the R8A7790 SoC;
"renesas,pci-r8a7791" for the R8A7791 SoC;
Expand Down
2 changes: 2 additions & 0 deletions Documentation/devicetree/bindings/pci/rcar-pci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

Required properties:
compatible: "renesas,pcie-r8a7743" for the R8A7743 SoC;
"renesas,pcie-r8a7744" for the R8A7744 SoC;
"renesas,pcie-r8a7779" for the R8A7779 SoC;
"renesas,pcie-r8a7790" for the R8A7790 SoC;
"renesas,pcie-r8a7791" for the R8A7791 SoC;
"renesas,pcie-r8a7793" for the R8A7793 SoC;
"renesas,pcie-r8a7795" for the R8A7795 SoC;
"renesas,pcie-r8a7796" for the R8A7796 SoC;
"renesas,pcie-r8a77980" for the R8A77980 SoC;
"renesas,pcie-r8a77990" for the R8A77990 SoC;
"renesas,pcie-rcar-gen2" for a generic R-Car Gen2 or
RZ/G1 compatible device.
"renesas,pcie-rcar-gen3" for a generic R-Car Gen3 compatible device.
Expand Down
3 changes: 3 additions & 0 deletions drivers/pci/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ config PCI_ECAM
config PCI_LOCKLESS_CONFIG
bool

config PCI_BRIDGE_EMUL
bool

config PCI_IOV
bool "PCI IOV support"
depends on PCI
Expand Down
1 change: 1 addition & 0 deletions drivers/pci/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
obj-$(CONFIG_PCI_MSI) += msi.o
obj-$(CONFIG_PCI_ATS) += ats.o
obj-$(CONFIG_PCI_IOV) += iov.o
obj-$(CONFIG_PCI_BRIDGE_EMUL) += pci-bridge-emul.o
obj-$(CONFIG_ACPI) += pci-acpi.o
obj-$(CONFIG_PCI_LABEL) += pci-label.o
obj-$(CONFIG_X86_INTEL_MID) += pci-mid.o
Expand Down
2 changes: 2 additions & 0 deletions drivers/pci/controller/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ config PCI_MVEBU
depends on MVEBU_MBUS
depends on ARM
depends on OF
select PCI_BRIDGE_EMUL

config PCI_AARDVARK
bool "Aardvark PCIe controller"
depends on (ARCH_MVEBU && ARM64) || COMPILE_TEST
depends on OF
depends on PCI_MSI_IRQ_DOMAIN
select PCI_BRIDGE_EMUL
help
Add support for Aardvark 64bit PCIe Host Controller. This
controller is part of the South Bridge of the Marvel Armada
Expand Down
129 changes: 126 additions & 3 deletions drivers/pci/controller/pci-aardvark.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@
#include <linux/of_pci.h>

#include "../pci.h"
#include "../pci-bridge-emul.h"

/* PCIe core registers */
#define PCIE_CORE_DEV_ID_REG 0x0
#define PCIE_CORE_CMD_STATUS_REG 0x4
#define PCIE_CORE_CMD_IO_ACCESS_EN BIT(0)
#define PCIE_CORE_CMD_MEM_ACCESS_EN BIT(1)
#define PCIE_CORE_CMD_MEM_IO_REQ_EN BIT(2)
#define PCIE_CORE_DEV_REV_REG 0x8
#define PCIE_CORE_PCIEXP_CAP 0xc0
#define PCIE_CORE_DEV_CTRL_STATS_REG 0xc8
#define PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE (0 << 4)
#define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT 5
Expand All @@ -41,7 +45,10 @@
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN BIT(6)
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK BIT(7)
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK_RCV BIT(8)

#define PCIE_CORE_INT_A_ASSERT_ENABLE 1
#define PCIE_CORE_INT_B_ASSERT_ENABLE 2
#define PCIE_CORE_INT_C_ASSERT_ENABLE 3
#define PCIE_CORE_INT_D_ASSERT_ENABLE 4
/* PIO registers base address and register offsets */
#define PIO_BASE_ADDR 0x4000
#define PIO_CTRL (PIO_BASE_ADDR + 0x0)
Expand Down Expand Up @@ -93,7 +100,9 @@
#define PCIE_CORE_CTRL2_STRICT_ORDER_ENABLE BIT(5)
#define PCIE_CORE_CTRL2_OB_WIN_ENABLE BIT(6)
#define PCIE_CORE_CTRL2_MSI_ENABLE BIT(10)
#define PCIE_MSG_LOG_REG (CONTROL_BASE_ADDR + 0x30)
#define PCIE_ISR0_REG (CONTROL_BASE_ADDR + 0x40)
#define PCIE_MSG_PM_PME_MASK BIT(7)
#define PCIE_ISR0_MASK_REG (CONTROL_BASE_ADDR + 0x44)
#define PCIE_ISR0_MSI_INT_PENDING BIT(24)
#define PCIE_ISR0_INTX_ASSERT(val) BIT(16 + (val))
Expand Down Expand Up @@ -189,6 +198,7 @@ struct advk_pcie {
struct mutex msi_used_lock;
u16 msi_msg;
int root_bus_nr;
struct pci_bridge_emul bridge;
};

static inline void advk_writel(struct advk_pcie *pcie, u32 val, u64 reg)
Expand Down Expand Up @@ -390,6 +400,109 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie)
return -ETIMEDOUT;
}


static pci_bridge_emul_read_status_t
advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
int reg, u32 *value)
{
struct advk_pcie *pcie = bridge->data;


switch (reg) {
case PCI_EXP_SLTCTL:
*value = PCI_EXP_SLTSTA_PDS << 16;
return PCI_BRIDGE_EMUL_HANDLED;

case PCI_EXP_RTCTL: {
u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
*value = (val & PCIE_MSG_PM_PME_MASK) ? PCI_EXP_RTCTL_PMEIE : 0;
return PCI_BRIDGE_EMUL_HANDLED;
}

case PCI_EXP_RTSTA: {
u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG);
u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG);
*value = (isr0 & PCIE_MSG_PM_PME_MASK) << 16 | (msglog >> 16);
return PCI_BRIDGE_EMUL_HANDLED;
}

case PCI_CAP_LIST_ID:
case PCI_EXP_DEVCAP:
case PCI_EXP_DEVCTL:
case PCI_EXP_LNKCAP:
case PCI_EXP_LNKCTL:
*value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
return PCI_BRIDGE_EMUL_HANDLED;
default:
return PCI_BRIDGE_EMUL_NOT_HANDLED;
}

}

static void
advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
int reg, u32 old, u32 new, u32 mask)
{
struct advk_pcie *pcie = bridge->data;

switch (reg) {
case PCI_EXP_DEVCTL:
case PCI_EXP_LNKCTL:
advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
break;

case PCI_EXP_RTCTL:
new = (new & PCI_EXP_RTCTL_PMEIE) << 3;
advk_writel(pcie, new, PCIE_ISR0_MASK_REG);
break;

case PCI_EXP_RTSTA:
new = (new & PCI_EXP_RTSTA_PME) >> 9;
advk_writel(pcie, new, PCIE_ISR0_REG);
break;

default:
break;
}
}

struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {
.read_pcie = advk_pci_bridge_emul_pcie_conf_read,
.write_pcie = advk_pci_bridge_emul_pcie_conf_write,
};

/*
* Initialize the configuration space of the PCI-to-PCI bridge
* associated with the given PCIe interface.
*/
static void advk_sw_pci_bridge_init(struct advk_pcie *pcie)
{
struct pci_bridge_emul *bridge = &pcie->bridge;

bridge->conf.vendor = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff;
bridge->conf.device = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) >> 16;
bridge->conf.class_revision =
advk_readl(pcie, PCIE_CORE_DEV_REV_REG) & 0xff;

/* Support 32 bits I/O addressing */
bridge->conf.iobase = PCI_IO_RANGE_TYPE_32;
bridge->conf.iolimit = PCI_IO_RANGE_TYPE_32;

/* Support 64 bits memory pref */
bridge->conf.pref_mem_base = PCI_PREF_RANGE_TYPE_64;
bridge->conf.pref_mem_limit = PCI_PREF_RANGE_TYPE_64;

/* Support interrupt A for MSI feature */
bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE;

bridge->has_pcie = true;
bridge->data = pcie;
bridge->ops = &advk_pci_bridge_emul_ops;

pci_bridge_emul_init(bridge);

}

static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus,
int devfn)
{
Expand All @@ -411,14 +524,18 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
return PCIBIOS_DEVICE_NOT_FOUND;
}

if (bus->number == pcie->root_bus_nr)
return pci_bridge_emul_conf_read(&pcie->bridge, where,
size, val);

/* Start PIO */
advk_writel(pcie, 0, PIO_START);
advk_writel(pcie, 1, PIO_ISR);

/* Program the control register */
reg = advk_readl(pcie, PIO_CTRL);
reg &= ~PIO_CTRL_TYPE_MASK;
if (bus->number == pcie->root_bus_nr)
if (bus->primary == pcie->root_bus_nr)
reg |= PCIE_CONFIG_RD_TYPE0;
else
reg |= PCIE_CONFIG_RD_TYPE1;
Expand Down Expand Up @@ -463,6 +580,10 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
if (!advk_pcie_valid_device(pcie, bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;

if (bus->number == pcie->root_bus_nr)
return pci_bridge_emul_conf_write(&pcie->bridge, where,
size, val);

if (where % size)
return PCIBIOS_SET_FAILED;

Expand All @@ -473,7 +594,7 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
/* Program the control register */
reg = advk_readl(pcie, PIO_CTRL);
reg &= ~PIO_CTRL_TYPE_MASK;
if (bus->number == pcie->root_bus_nr)
if (bus->primary == pcie->root_bus_nr)
reg |= PCIE_CONFIG_WR_TYPE0;
else
reg |= PCIE_CONFIG_WR_TYPE1;
Expand Down Expand Up @@ -875,6 +996,8 @@ static int advk_pcie_probe(struct platform_device *pdev)

advk_pcie_setup_hw(pcie);

advk_sw_pci_bridge_init(pcie);

ret = advk_pcie_init_irq_domain(pcie);
if (ret) {
dev_err(dev, "Failed to initialize irq\n");
Expand Down
8 changes: 0 additions & 8 deletions drivers/pci/controller/pci-host-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ static struct pci_config_window *gen_pci_init(struct device *dev,
int pci_host_common_probe(struct platform_device *pdev,
struct pci_ecam_ops *ops)
{
const char *type;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct pci_host_bridge *bridge;
struct pci_config_window *cfg;
struct list_head resources;
Expand All @@ -70,12 +68,6 @@ int pci_host_common_probe(struct platform_device *pdev,
if (!bridge)
return -ENOMEM;

type = of_get_property(np, "device_type", NULL);
if (!type || strcmp(type, "pci")) {
dev_err(dev, "invalid \"device_type\" %s\n", type);
return -EINVAL;
}

of_pci_check_probe_only();

/* Parse and map our Configuration Space windows */
Expand Down
Loading

0 comments on commit b7c18dc

Please sign in to comment.