diff options
Diffstat (limited to 'drivers/pci/controller')
| -rw-r--r-- | drivers/pci/controller/cadence/pcie-cadence-ep.c | 2 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-host.c | 28 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom.c | 100 | ||||
| -rw-r--r-- | drivers/pci/controller/vmd.c | 13 | 
4 files changed, 70 insertions, 73 deletions
diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c index 1eac012a8226..c0e1194a936b 100644 --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c @@ -255,7 +255,7 @@ static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)  	u16 flags, mme;  	u8 cap; -	cap = cdns_pcie_find_capability(pcie, PCI_CAP_ID_MSIX); +	cap = cdns_pcie_find_capability(pcie, PCI_CAP_ID_MSI);  	fn = cdns_pcie_get_fn_from_vfn(pcie, fn, vfn);  	/* Validate that the MSI feature is actually enabled. */ diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 20c9333bcb1c..e92513c5bda5 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -23,6 +23,7 @@  #include "pcie-designware.h"  static struct pci_ops dw_pcie_ops; +static struct pci_ops dw_pcie_ecam_ops;  static struct pci_ops dw_child_pcie_ops;  #define DW_PCIE_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS		| \ @@ -471,9 +472,6 @@ static int dw_pcie_create_ecam_window(struct dw_pcie_rp *pp, struct resource *re  	if (IS_ERR(pp->cfg))  		return PTR_ERR(pp->cfg); -	pci->dbi_base = pp->cfg->win; -	pci->dbi_phys_addr = res->start; -  	return 0;  } @@ -529,7 +527,7 @@ static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp)  		if (ret)  			return ret; -		pp->bridge->ops = (struct pci_ops *)&pci_generic_ecam_ops.pci_ops; +		pp->bridge->ops = &dw_pcie_ecam_ops;  		pp->bridge->sysdata = pp->cfg;  		pp->cfg->priv = pp;  	} else { @@ -842,12 +840,34 @@ void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, unsigned int devfn,  }  EXPORT_SYMBOL_GPL(dw_pcie_own_conf_map_bus); +static void __iomem *dw_pcie_ecam_conf_map_bus(struct pci_bus *bus, unsigned int devfn, int where) +{ +	struct pci_config_window *cfg = bus->sysdata; +	struct dw_pcie_rp *pp = cfg->priv; +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +	unsigned int busn = bus->number; + +	if (busn > 0) +		return pci_ecam_map_bus(bus, devfn, where); + +	if (PCI_SLOT(devfn) > 0) +		return NULL; + +	return pci->dbi_base + where; +} +  static struct pci_ops dw_pcie_ops = {  	.map_bus = dw_pcie_own_conf_map_bus,  	.read = pci_generic_config_read,  	.write = pci_generic_config_write,  }; +static struct pci_ops dw_pcie_ecam_ops = { +	.map_bus = dw_pcie_ecam_conf_map_bus, +	.read = pci_generic_config_read, +	.write = pci_generic_config_write, +}; +  static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)  {  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 805edbbfe7eb..c48a20602d7f 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -55,7 +55,6 @@  #define PARF_AXI_MSTR_WR_ADDR_HALT_V2		0x1a8  #define PARF_Q2A_FLUSH				0x1ac  #define PARF_LTSSM				0x1b0 -#define PARF_SLV_DBI_ELBI			0x1b4  #define PARF_INT_ALL_STATUS			0x224  #define PARF_INT_ALL_CLEAR			0x228  #define PARF_INT_ALL_MASK			0x22c @@ -65,16 +64,6 @@  #define PARF_DBI_BASE_ADDR_V2_HI		0x354  #define PARF_SLV_ADDR_SPACE_SIZE_V2		0x358  #define PARF_SLV_ADDR_SPACE_SIZE_V2_HI		0x35c -#define PARF_BLOCK_SLV_AXI_WR_BASE		0x360 -#define PARF_BLOCK_SLV_AXI_WR_BASE_HI		0x364 -#define PARF_BLOCK_SLV_AXI_WR_LIMIT		0x368 -#define PARF_BLOCK_SLV_AXI_WR_LIMIT_HI		0x36c -#define PARF_BLOCK_SLV_AXI_RD_BASE		0x370 -#define PARF_BLOCK_SLV_AXI_RD_BASE_HI		0x374 -#define PARF_BLOCK_SLV_AXI_RD_LIMIT		0x378 -#define PARF_BLOCK_SLV_AXI_RD_LIMIT_HI		0x37c -#define PARF_ECAM_BASE				0x380 -#define PARF_ECAM_BASE_HI			0x384  #define PARF_NO_SNOOP_OVERRIDE			0x3d4  #define PARF_ATU_BASE_ADDR			0x634  #define PARF_ATU_BASE_ADDR_HI			0x638 @@ -98,7 +87,6 @@  /* PARF_SYS_CTRL register fields */  #define MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN	BIT(29) -#define PCIE_ECAM_BLOCKER_EN			BIT(26)  #define MST_WAKEUP_EN				BIT(13)  #define SLV_WAKEUP_EN				BIT(12)  #define MSTR_ACLK_CGC_DIS			BIT(10) @@ -146,9 +134,6 @@  /* PARF_LTSSM register fields */  #define LTSSM_EN				BIT(8) -/* PARF_SLV_DBI_ELBI */ -#define SLV_DBI_ELBI_ADDR_BASE			GENMASK(11, 0) -  /* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */  #define PARF_INT_ALL_LINK_UP			BIT(13)  #define PARF_INT_MSI_DEV_0_7			GENMASK(30, 23) @@ -262,6 +247,7 @@ struct qcom_pcie_ops {  	int (*get_resources)(struct qcom_pcie *pcie);  	int (*init)(struct qcom_pcie *pcie);  	int (*post_init)(struct qcom_pcie *pcie); +	void (*host_post_init)(struct qcom_pcie *pcie);  	void (*deinit)(struct qcom_pcie *pcie);  	void (*ltssm_enable)(struct qcom_pcie *pcie);  	int (*config_sid)(struct qcom_pcie *pcie); @@ -326,47 +312,6 @@ static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)  	qcom_perst_assert(pcie, false);  } -static void qcom_pci_config_ecam(struct dw_pcie_rp *pp) -{ -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct qcom_pcie *pcie = to_qcom_pcie(pci); -	u64 addr, addr_end; -	u32 val; - -	writel_relaxed(lower_32_bits(pci->dbi_phys_addr), pcie->parf + PARF_ECAM_BASE); -	writel_relaxed(upper_32_bits(pci->dbi_phys_addr), pcie->parf + PARF_ECAM_BASE_HI); - -	/* -	 * The only device on the root bus is a single Root Port. If we try to -	 * access any devices other than Device/Function 00.0 on Bus 0, the TLP -	 * will go outside of the controller to the PCI bus. But with CFG Shift -	 * Feature (ECAM) enabled in iATU, there is no guarantee that the -	 * response is going to be all F's. Hence, to make sure that the -	 * requester gets all F's response for accesses other than the Root -	 * Port, configure iATU to block the transactions starting from -	 * function 1 of the root bus to the end of the root bus (i.e., from -	 * dbi_base + 4KB to dbi_base + 1MB). -	 */ -	addr = pci->dbi_phys_addr + SZ_4K; -	writel_relaxed(lower_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_WR_BASE); -	writel_relaxed(upper_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_WR_BASE_HI); - -	writel_relaxed(lower_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_RD_BASE); -	writel_relaxed(upper_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_RD_BASE_HI); - -	addr_end = pci->dbi_phys_addr + SZ_1M - 1; - -	writel_relaxed(lower_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_WR_LIMIT); -	writel_relaxed(upper_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_WR_LIMIT_HI); - -	writel_relaxed(lower_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_RD_LIMIT); -	writel_relaxed(upper_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_RD_LIMIT_HI); - -	val = readl_relaxed(pcie->parf + PARF_SYS_CTRL); -	val |= PCIE_ECAM_BLOCKER_EN; -	writel_relaxed(val, pcie->parf + PARF_SYS_CTRL); -} -  static int qcom_pcie_start_link(struct dw_pcie *pci)  {  	struct qcom_pcie *pcie = to_qcom_pcie(pci); @@ -1094,6 +1039,25 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)  	return 0;  } +static int qcom_pcie_enable_aspm(struct pci_dev *pdev, void *userdata) +{ +	/* +	 * Downstream devices need to be in D0 state before enabling PCI PM +	 * substates. +	 */ +	pci_set_power_state_locked(pdev, PCI_D0); +	pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); + +	return 0; +} + +static void qcom_pcie_host_post_init_2_7_0(struct qcom_pcie *pcie) +{ +	struct dw_pcie_rp *pp = &pcie->pci->pp; + +	pci_walk_bus(pp->bridge->bus, qcom_pcie_enable_aspm, NULL); +} +  static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie)  {  	struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; @@ -1320,7 +1284,6 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp)  {  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	struct qcom_pcie *pcie = to_qcom_pcie(pci); -	u16 offset;  	int ret;  	qcom_ep_reset_assert(pcie); @@ -1329,17 +1292,6 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp)  	if (ret)  		return ret; -	if (pp->ecam_enabled) { -		/* -		 * Override ELBI when ECAM is enabled, as when ECAM is enabled, -		 * ELBI moves under the 'config' space. -		 */ -		offset = FIELD_GET(SLV_DBI_ELBI_ADDR_BASE, readl(pcie->parf + PARF_SLV_DBI_ELBI)); -		pci->elbi_base = pci->dbi_base + offset; - -		qcom_pci_config_ecam(pp); -	} -  	ret = qcom_pcie_phy_power_on(pcie);  	if (ret)  		goto err_deinit; @@ -1380,9 +1332,19 @@ static void qcom_pcie_host_deinit(struct dw_pcie_rp *pp)  	pcie->cfg->ops->deinit(pcie);  } +static void qcom_pcie_host_post_init(struct dw_pcie_rp *pp) +{ +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +	struct qcom_pcie *pcie = to_qcom_pcie(pci); + +	if (pcie->cfg->ops->host_post_init) +		pcie->cfg->ops->host_post_init(pcie); +} +  static const struct dw_pcie_host_ops qcom_pcie_dw_ops = {  	.init		= qcom_pcie_host_init,  	.deinit		= qcom_pcie_host_deinit, +	.post_init	= qcom_pcie_host_post_init,  };  /* Qcom IP rev.: 2.1.0	Synopsys IP rev.: 4.01a */ @@ -1444,6 +1406,7 @@ static const struct qcom_pcie_ops ops_1_9_0 = {  	.get_resources = qcom_pcie_get_resources_2_7_0,  	.init = qcom_pcie_init_2_7_0,  	.post_init = qcom_pcie_post_init_2_7_0, +	.host_post_init = qcom_pcie_host_post_init_2_7_0,  	.deinit = qcom_pcie_deinit_2_7_0,  	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,  	.config_sid = qcom_pcie_config_sid_1_9_0, @@ -1454,6 +1417,7 @@ static const struct qcom_pcie_ops ops_1_21_0 = {  	.get_resources = qcom_pcie_get_resources_2_7_0,  	.init = qcom_pcie_init_2_7_0,  	.post_init = qcom_pcie_post_init_2_7_0, +	.host_post_init = qcom_pcie_host_post_init_2_7_0,  	.deinit = qcom_pcie_deinit_2_7_0,  	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,  }; diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index 1bd5bf4a6097..b4b62b9ccc45 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -192,6 +192,12 @@ static void vmd_pci_msi_enable(struct irq_data *data)  	data->chip->irq_unmask(data);  } +static unsigned int vmd_pci_msi_startup(struct irq_data *data) +{ +	vmd_pci_msi_enable(data); +	return 0; +} +  static void vmd_irq_disable(struct irq_data *data)  {  	struct vmd_irq *vmdirq = data->chip_data; @@ -210,6 +216,11 @@ static void vmd_pci_msi_disable(struct irq_data *data)  	vmd_irq_disable(data->parent_data);  } +static void vmd_pci_msi_shutdown(struct irq_data *data) +{ +	vmd_pci_msi_disable(data); +} +  static struct irq_chip vmd_msi_controller = {  	.name			= "VMD-MSI",  	.irq_compose_msi_msg	= vmd_compose_msi_msg, @@ -309,6 +320,8 @@ static bool vmd_init_dev_msi_info(struct device *dev, struct irq_domain *domain,  	if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info))  		return false; +	info->chip->irq_startup		= vmd_pci_msi_startup; +	info->chip->irq_shutdown	= vmd_pci_msi_shutdown;  	info->chip->irq_enable		= vmd_pci_msi_enable;  	info->chip->irq_disable		= vmd_pci_msi_disable;  	return true;  | 
