Skip to content

Commit 800cee8

Browse files
committed
Merge branch 'remotes/lorenzo/pci/aardvark'
- Add bridge emulation definitions for PCIe DEVCAP2, DEVCTL2, DEVSTA2, LNKCAP2, LNKCTL2, LNKSTA2, SLTCAP2, SLTCTL2, SLTSTA2 (Pali Rohár) - Add aardvark support for DEVCAP2, DEVCTL2, LNKCAP2 and LNKCTL2 registers (Pali Rohár) - Clear all MSIs at setup to avoid spurious interrupts (Pali Rohár) - Disable bus mastering when unbinding host controller driver (Pali Rohár) - Mask all interrupts when unbinding host controller driver (Pali Rohár) - Fix memory leak in host controller unbind (Pali Rohár) - Assert PERST# when unbinding host controller driver (Pali Rohár) - Disable link training when unbinding host controller driver (Pali Rohár) - Disable common PHY when unbinding host controller driver (Pali Rohár) - Fix resource type checking to check only IORESOURCE_MEM, not IORESOURCE_MEM_64, which is a flavor of IORESOURCE_MEM (Pali Rohár) * remotes/lorenzo/pci/aardvark: PCI: aardvark: Fix checking for MEM resource type PCI: aardvark: Disable common PHY when unbinding driver PCI: aardvark: Disable link training when unbinding driver PCI: aardvark: Assert PERST# when unbinding driver PCI: aardvark: Fix memory leak in driver unbind PCI: aardvark: Mask all interrupts when unbinding driver PCI: aardvark: Disable bus mastering when unbinding driver PCI: aardvark: Comment actions in driver remove method PCI: aardvark: Clear all MSIs at setup PCI: aardvark: Add support for DEVCAP2, DEVCTL2, LNKCAP2 and LNKCTL2 registers on emulated bridge PCI: pci-bridge-emul: Add definitions for missing capabilities registers PCI: pci-bridge-emul: Add description for class_revision field
2 parents d03f92c + 2070b2d commit 800cee8

File tree

2 files changed

+109
-11
lines changed

2 files changed

+109
-11
lines changed

drivers/pci/controller/pci-aardvark.c

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
#define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54)
117117
#define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58)
118118
#define PCIE_MSI_MASK_REG (CONTROL_BASE_ADDR + 0x5C)
119+
#define PCIE_MSI_ALL_MASK GENMASK(31, 0)
119120
#define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C)
120121
#define PCIE_MSI_DATA_MASK GENMASK(15, 0)
121122

@@ -571,6 +572,7 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
571572
advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
572573

573574
/* Clear all interrupts */
575+
advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG);
574576
advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG);
575577
advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG);
576578
advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
@@ -583,7 +585,7 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
583585
advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
584586

585587
/* Unmask all MSIs */
586-
advk_writel(pcie, 0, PCIE_MSI_MASK_REG);
588+
advk_writel(pcie, ~(u32)PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
587589

588590
/* Enable summary interrupt for GIC SPI source */
589591
reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK);
@@ -884,8 +886,13 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
884886
case PCI_CAP_LIST_ID:
885887
case PCI_EXP_DEVCAP:
886888
case PCI_EXP_DEVCTL:
889+
case PCI_EXP_DEVCAP2:
890+
case PCI_EXP_DEVCTL2:
891+
case PCI_EXP_LNKCAP2:
892+
case PCI_EXP_LNKCTL2:
887893
*value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
888894
return PCI_BRIDGE_EMUL_HANDLED;
895+
889896
default:
890897
return PCI_BRIDGE_EMUL_NOT_HANDLED;
891898
}
@@ -899,10 +906,6 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
899906
struct advk_pcie *pcie = bridge->data;
900907

901908
switch (reg) {
902-
case PCI_EXP_DEVCTL:
903-
advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
904-
break;
905-
906909
case PCI_EXP_LNKCTL:
907910
advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
908911
if (new & PCI_EXP_LNKCTL_RL)
@@ -924,6 +927,12 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
924927
advk_writel(pcie, new, PCIE_ISR0_REG);
925928
break;
926929

930+
case PCI_EXP_DEVCTL:
931+
case PCI_EXP_DEVCTL2:
932+
case PCI_EXP_LNKCTL2:
933+
advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
934+
break;
935+
927936
default:
928937
break;
929938
}
@@ -1392,7 +1401,7 @@ static void advk_pcie_handle_msi(struct advk_pcie *pcie)
13921401

13931402
msi_mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
13941403
msi_val = advk_readl(pcie, PCIE_MSI_STATUS_REG);
1395-
msi_status = msi_val & ~msi_mask;
1404+
msi_status = msi_val & ((~msi_mask) & PCIE_MSI_ALL_MASK);
13961405

13971406
for (msi_idx = 0; msi_idx < MSI_IRQ_NUM; msi_idx++) {
13981407
if (!(BIT(msi_idx) & msi_status))
@@ -1544,17 +1553,15 @@ static int advk_pcie_probe(struct platform_device *pdev)
15441553
* only PIO for issuing configuration transfers which does
15451554
* not use PCIe window configuration.
15461555
*/
1547-
if (type != IORESOURCE_MEM && type != IORESOURCE_MEM_64 &&
1548-
type != IORESOURCE_IO)
1556+
if (type != IORESOURCE_MEM && type != IORESOURCE_IO)
15491557
continue;
15501558

15511559
/*
15521560
* Skip transparent memory resources. Default outbound access
15531561
* configuration is set to transparent memory access so it
15541562
* does not need window configuration.
15551563
*/
1556-
if ((type == IORESOURCE_MEM || type == IORESOURCE_MEM_64) &&
1557-
entry->offset == 0)
1564+
if (type == IORESOURCE_MEM && entry->offset == 0)
15581565
continue;
15591566

15601567
/*
@@ -1686,20 +1693,64 @@ static int advk_pcie_remove(struct platform_device *pdev)
16861693
{
16871694
struct advk_pcie *pcie = platform_get_drvdata(pdev);
16881695
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
1696+
u32 val;
16891697
int i;
16901698

1699+
/* Remove PCI bus with all devices */
16911700
pci_lock_rescan_remove();
16921701
pci_stop_root_bus(bridge->bus);
16931702
pci_remove_root_bus(bridge->bus);
16941703
pci_unlock_rescan_remove();
16951704

1705+
/* Disable Root Bridge I/O space, memory space and bus mastering */
1706+
val = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
1707+
val &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
1708+
advk_writel(pcie, val, PCIE_CORE_CMD_STATUS_REG);
1709+
1710+
/* Disable MSI */
1711+
val = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
1712+
val &= ~PCIE_CORE_CTRL2_MSI_ENABLE;
1713+
advk_writel(pcie, val, PCIE_CORE_CTRL2_REG);
1714+
1715+
/* Clear MSI address */
1716+
advk_writel(pcie, 0, PCIE_MSI_ADDR_LOW_REG);
1717+
advk_writel(pcie, 0, PCIE_MSI_ADDR_HIGH_REG);
1718+
1719+
/* Mask all interrupts */
1720+
advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
1721+
advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG);
1722+
advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
1723+
advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_MASK_REG);
1724+
1725+
/* Clear all interrupts */
1726+
advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG);
1727+
advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG);
1728+
advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG);
1729+
advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
1730+
1731+
/* Remove IRQ domains */
16961732
advk_pcie_remove_msi_irq_domain(pcie);
16971733
advk_pcie_remove_irq_domain(pcie);
16981734

1735+
/* Free config space for emulated root bridge */
1736+
pci_bridge_emul_cleanup(&pcie->bridge);
1737+
1738+
/* Assert PERST# signal which prepares PCIe card for power down */
1739+
if (pcie->reset_gpio)
1740+
gpiod_set_value_cansleep(pcie->reset_gpio, 1);
1741+
1742+
/* Disable link training */
1743+
val = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
1744+
val &= ~LINK_TRAINING_EN;
1745+
advk_writel(pcie, val, PCIE_CORE_CTRL0_REG);
1746+
16991747
/* Disable outbound address windows mapping */
17001748
for (i = 0; i < OB_WIN_COUNT; i++)
17011749
advk_pcie_disable_ob_win(pcie, i);
17021750

1751+
/* Disable phy */
1752+
advk_pcie_disable_phy(pcie);
1753+
17031754
return 0;
17041755
}
17051756

drivers/pci/pci-bridge-emul.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,49 @@ struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] =
251251
.ro = GENMASK(15, 0) | PCI_EXP_RTSTA_PENDING,
252252
.w1c = PCI_EXP_RTSTA_PME,
253253
},
254+
255+
[PCI_EXP_DEVCAP2 / 4] = {
256+
/*
257+
* Device capabilities 2 register has reserved bits [30:27].
258+
* Also bits [26:24] are reserved for non-upstream ports.
259+
*/
260+
.ro = BIT(31) | GENMASK(23, 0),
261+
},
262+
263+
[PCI_EXP_DEVCTL2 / 4] = {
264+
/*
265+
* Device control 2 register is RW. Bit 11 is reserved for
266+
* non-upstream ports.
267+
*
268+
* Device status 2 register is reserved.
269+
*/
270+
.rw = GENMASK(15, 12) | GENMASK(10, 0),
271+
},
272+
273+
[PCI_EXP_LNKCAP2 / 4] = {
274+
/* Link capabilities 2 register has reserved bits [30:25] and 0. */
275+
.ro = BIT(31) | GENMASK(24, 1),
276+
},
277+
278+
[PCI_EXP_LNKCTL2 / 4] = {
279+
/*
280+
* Link control 2 register is RW.
281+
*
282+
* Link status 2 register has bits 5, 15 W1C;
283+
* bits 10, 11 reserved and others are RO.
284+
*/
285+
.rw = GENMASK(15, 0),
286+
.w1c = (BIT(15) | BIT(5)) << 16,
287+
.ro = (GENMASK(14, 12) | GENMASK(9, 6) | GENMASK(4, 0)) << 16,
288+
},
289+
290+
[PCI_EXP_SLTCAP2 / 4] = {
291+
/* Slot capabilities 2 register is reserved. */
292+
},
293+
294+
[PCI_EXP_SLTCTL2 / 4] = {
295+
/* Both Slot control 2 and Slot status 2 registers are reserved. */
296+
},
254297
};
255298

256299
/*
@@ -265,7 +308,11 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
265308
{
266309
BUILD_BUG_ON(sizeof(bridge->conf) != PCI_BRIDGE_CONF_END);
267310

268-
bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16);
311+
/*
312+
* class_revision: Class is high 24 bits and revision is low 8 bit of this member,
313+
* while class for PCI Bridge Normal Decode has the 24-bit value: PCI_CLASS_BRIDGE_PCI << 8
314+
*/
315+
bridge->conf.class_revision |= cpu_to_le32((PCI_CLASS_BRIDGE_PCI << 8) << 8);
269316
bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE;
270317
bridge->conf.cache_line_size = 0x10;
271318
bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST);

0 commit comments

Comments
 (0)