Skip to content

Commit 8a3ebd8

Browse files
Zachary ZhangLorenzo Pieralisi
authored andcommitted
PCI: aardvark: Implement emulated root PCI bridge config space
The PCI controller in the Marvell Armada 3720 does not implement a software-accessible root port PCI bridge configuration space. This causes a number of problems when using PCIe switches or when the Max Payload size needs to be aligned between the root complex and the endpoint. Implementing an emulated root PCI bridge, like is already done in the pci-mvebu driver for older Marvell platforms allows to solve those issues, and also to support features such as ASR, PME, VC, HP. Signed-off-by: Zachary Zhang <[email protected]> [Thomas: convert to the common emulated PCI bridge logic.] Signed-off-by: Thomas Petazzoni <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]>
1 parent 1f08673 commit 8a3ebd8

File tree

2 files changed

+127
-3
lines changed

2 files changed

+127
-3
lines changed

drivers/pci/controller/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ config PCI_AARDVARK
1616
depends on (ARCH_MVEBU && ARM64) || COMPILE_TEST
1717
depends on OF
1818
depends on PCI_MSI_IRQ_DOMAIN
19+
select PCI_BRIDGE_EMUL
1920
help
2021
Add support for Aardvark 64bit PCIe Host Controller. This
2122
controller is part of the South Bridge of the Marvel Armada

drivers/pci/controller/pci-aardvark.c

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@
2020
#include <linux/of_pci.h>
2121

2222
#include "../pci.h"
23+
#include "../pci-bridge-emul.h"
2324

2425
/* PCIe core registers */
26+
#define PCIE_CORE_DEV_ID_REG 0x0
2527
#define PCIE_CORE_CMD_STATUS_REG 0x4
2628
#define PCIE_CORE_CMD_IO_ACCESS_EN BIT(0)
2729
#define PCIE_CORE_CMD_MEM_ACCESS_EN BIT(1)
2830
#define PCIE_CORE_CMD_MEM_IO_REQ_EN BIT(2)
31+
#define PCIE_CORE_DEV_REV_REG 0x8
32+
#define PCIE_CORE_PCIEXP_CAP 0xc0
2933
#define PCIE_CORE_DEV_CTRL_STATS_REG 0xc8
3034
#define PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE (0 << 4)
3135
#define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT 5
@@ -41,7 +45,10 @@
4145
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN BIT(6)
4246
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK BIT(7)
4347
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK_RCV BIT(8)
44-
48+
#define PCIE_CORE_INT_A_ASSERT_ENABLE 1
49+
#define PCIE_CORE_INT_B_ASSERT_ENABLE 2
50+
#define PCIE_CORE_INT_C_ASSERT_ENABLE 3
51+
#define PCIE_CORE_INT_D_ASSERT_ENABLE 4
4552
/* PIO registers base address and register offsets */
4653
#define PIO_BASE_ADDR 0x4000
4754
#define PIO_CTRL (PIO_BASE_ADDR + 0x0)
@@ -93,7 +100,9 @@
93100
#define PCIE_CORE_CTRL2_STRICT_ORDER_ENABLE BIT(5)
94101
#define PCIE_CORE_CTRL2_OB_WIN_ENABLE BIT(6)
95102
#define PCIE_CORE_CTRL2_MSI_ENABLE BIT(10)
103+
#define PCIE_MSG_LOG_REG (CONTROL_BASE_ADDR + 0x30)
96104
#define PCIE_ISR0_REG (CONTROL_BASE_ADDR + 0x40)
105+
#define PCIE_MSG_PM_PME_MASK BIT(7)
97106
#define PCIE_ISR0_MASK_REG (CONTROL_BASE_ADDR + 0x44)
98107
#define PCIE_ISR0_MSI_INT_PENDING BIT(24)
99108
#define PCIE_ISR0_INTX_ASSERT(val) BIT(16 + (val))
@@ -189,6 +198,7 @@ struct advk_pcie {
189198
struct mutex msi_used_lock;
190199
u16 msi_msg;
191200
int root_bus_nr;
201+
struct pci_bridge_emul bridge;
192202
};
193203

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

403+
404+
static pci_bridge_emul_read_status_t
405+
advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
406+
int reg, u32 *value)
407+
{
408+
struct advk_pcie *pcie = bridge->data;
409+
410+
411+
switch (reg) {
412+
case PCI_EXP_SLTCTL:
413+
*value = PCI_EXP_SLTSTA_PDS << 16;
414+
return PCI_BRIDGE_EMUL_HANDLED;
415+
416+
case PCI_EXP_RTCTL: {
417+
u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
418+
*value = (val & PCIE_MSG_PM_PME_MASK) ? PCI_EXP_RTCTL_PMEIE : 0;
419+
return PCI_BRIDGE_EMUL_HANDLED;
420+
}
421+
422+
case PCI_EXP_RTSTA: {
423+
u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG);
424+
u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG);
425+
*value = (isr0 & PCIE_MSG_PM_PME_MASK) << 16 | (msglog >> 16);
426+
return PCI_BRIDGE_EMUL_HANDLED;
427+
}
428+
429+
case PCI_CAP_LIST_ID:
430+
case PCI_EXP_DEVCAP:
431+
case PCI_EXP_DEVCTL:
432+
case PCI_EXP_LNKCAP:
433+
case PCI_EXP_LNKCTL:
434+
*value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
435+
return PCI_BRIDGE_EMUL_HANDLED;
436+
default:
437+
return PCI_BRIDGE_EMUL_NOT_HANDLED;
438+
}
439+
440+
}
441+
442+
static void
443+
advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
444+
int reg, u32 old, u32 new, u32 mask)
445+
{
446+
struct advk_pcie *pcie = bridge->data;
447+
448+
switch (reg) {
449+
case PCI_EXP_DEVCTL:
450+
case PCI_EXP_LNKCTL:
451+
advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
452+
break;
453+
454+
case PCI_EXP_RTCTL:
455+
new = (new & PCI_EXP_RTCTL_PMEIE) << 3;
456+
advk_writel(pcie, new, PCIE_ISR0_MASK_REG);
457+
break;
458+
459+
case PCI_EXP_RTSTA:
460+
new = (new & PCI_EXP_RTSTA_PME) >> 9;
461+
advk_writel(pcie, new, PCIE_ISR0_REG);
462+
break;
463+
464+
default:
465+
break;
466+
}
467+
}
468+
469+
struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {
470+
.read_pcie = advk_pci_bridge_emul_pcie_conf_read,
471+
.write_pcie = advk_pci_bridge_emul_pcie_conf_write,
472+
};
473+
474+
/*
475+
* Initialize the configuration space of the PCI-to-PCI bridge
476+
* associated with the given PCIe interface.
477+
*/
478+
static void advk_sw_pci_bridge_init(struct advk_pcie *pcie)
479+
{
480+
struct pci_bridge_emul *bridge = &pcie->bridge;
481+
482+
bridge->conf.vendor = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff;
483+
bridge->conf.device = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) >> 16;
484+
bridge->conf.class_revision =
485+
advk_readl(pcie, PCIE_CORE_DEV_REV_REG) & 0xff;
486+
487+
/* Support 32 bits I/O addressing */
488+
bridge->conf.iobase = PCI_IO_RANGE_TYPE_32;
489+
bridge->conf.iolimit = PCI_IO_RANGE_TYPE_32;
490+
491+
/* Support 64 bits memory pref */
492+
bridge->conf.pref_mem_base = PCI_PREF_RANGE_TYPE_64;
493+
bridge->conf.pref_mem_limit = PCI_PREF_RANGE_TYPE_64;
494+
495+
/* Support interrupt A for MSI feature */
496+
bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE;
497+
498+
bridge->has_pcie = true;
499+
bridge->data = pcie;
500+
bridge->ops = &advk_pci_bridge_emul_ops;
501+
502+
pci_bridge_emul_init(bridge);
503+
504+
}
505+
393506
static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus,
394507
int devfn)
395508
{
@@ -411,14 +524,18 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
411524
return PCIBIOS_DEVICE_NOT_FOUND;
412525
}
413526

527+
if (bus->number == pcie->root_bus_nr)
528+
return pci_bridge_emul_conf_read(&pcie->bridge, where,
529+
size, val);
530+
414531
/* Start PIO */
415532
advk_writel(pcie, 0, PIO_START);
416533
advk_writel(pcie, 1, PIO_ISR);
417534

418535
/* Program the control register */
419536
reg = advk_readl(pcie, PIO_CTRL);
420537
reg &= ~PIO_CTRL_TYPE_MASK;
421-
if (bus->number == pcie->root_bus_nr)
538+
if (bus->primary == pcie->root_bus_nr)
422539
reg |= PCIE_CONFIG_RD_TYPE0;
423540
else
424541
reg |= PCIE_CONFIG_RD_TYPE1;
@@ -463,6 +580,10 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
463580
if (!advk_pcie_valid_device(pcie, bus, devfn))
464581
return PCIBIOS_DEVICE_NOT_FOUND;
465582

583+
if (bus->number == pcie->root_bus_nr)
584+
return pci_bridge_emul_conf_write(&pcie->bridge, where,
585+
size, val);
586+
466587
if (where % size)
467588
return PCIBIOS_SET_FAILED;
468589

@@ -473,7 +594,7 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
473594
/* Program the control register */
474595
reg = advk_readl(pcie, PIO_CTRL);
475596
reg &= ~PIO_CTRL_TYPE_MASK;
476-
if (bus->number == pcie->root_bus_nr)
597+
if (bus->primary == pcie->root_bus_nr)
477598
reg |= PCIE_CONFIG_WR_TYPE0;
478599
else
479600
reg |= PCIE_CONFIG_WR_TYPE1;
@@ -875,6 +996,8 @@ static int advk_pcie_probe(struct platform_device *pdev)
875996

876997
advk_pcie_setup_hw(pcie);
877998

999+
advk_sw_pci_bridge_init(pcie);
1000+
8781001
ret = advk_pcie_init_irq_domain(pcie);
8791002
if (ret) {
8801003
dev_err(dev, "Failed to initialize irq\n");

0 commit comments

Comments
 (0)