diff options
Diffstat (limited to 'drivers/pci/controller/dwc')
| -rw-r--r-- | drivers/pci/controller/dwc/pci-imx6.c | 33 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-host.c | 28 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware.h | 1 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-kirin.c | 4 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom-ep.c | 164 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom.c | 128 | 
6 files changed, 217 insertions, 141 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 6e5debdbc55b..2616585ca5f8 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -51,6 +51,7 @@ enum imx6_pcie_variants {  	IMX7D,  	IMX8MQ,  	IMX8MM, +	IMX8MP,  };  #define IMX6_PCIE_FLAG_IMX6_PHY			BIT(0) @@ -61,6 +62,7 @@ struct imx6_pcie_drvdata {  	enum imx6_pcie_variants variant;  	u32 flags;  	int dbi_length; +	const char *gpr;  };  struct imx6_pcie { @@ -150,7 +152,8 @@ struct imx6_pcie {  static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie)  {  	WARN_ON(imx6_pcie->drvdata->variant != IMX8MQ && -		imx6_pcie->drvdata->variant != IMX8MM); +		imx6_pcie->drvdata->variant != IMX8MM && +		imx6_pcie->drvdata->variant != IMX8MP);  	return imx6_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14;  } @@ -301,6 +304,7 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)  {  	switch (imx6_pcie->drvdata->variant) {  	case IMX8MM: +	case IMX8MP:  		/*  		 * The PHY initialization had been done in the PHY  		 * driver, break here directly. @@ -558,6 +562,7 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)  		break;  	case IMX8MM:  	case IMX8MQ: +	case IMX8MP:  		ret = clk_prepare_enable(imx6_pcie->pcie_aux);  		if (ret) {  			dev_err(dev, "unable to enable pcie_aux clock\n"); @@ -602,6 +607,7 @@ static void imx6_pcie_disable_ref_clk(struct imx6_pcie *imx6_pcie)  		break;  	case IMX8MM:  	case IMX8MQ: +	case IMX8MP:  		clk_disable_unprepare(imx6_pcie->pcie_aux);  		break;  	default: @@ -669,6 +675,7 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)  		reset_control_assert(imx6_pcie->pciephy_reset);  		fallthrough;  	case IMX8MM: +	case IMX8MP:  		reset_control_assert(imx6_pcie->apps_reset);  		break;  	case IMX6SX: @@ -744,6 +751,7 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)  		break;  	case IMX6Q:		/* Nothing to do */  	case IMX8MM: +	case IMX8MP:  		break;  	} @@ -793,6 +801,7 @@ static void imx6_pcie_ltssm_enable(struct device *dev)  	case IMX7D:  	case IMX8MQ:  	case IMX8MM: +	case IMX8MP:  		reset_control_deassert(imx6_pcie->apps_reset);  		break;  	} @@ -812,6 +821,7 @@ static void imx6_pcie_ltssm_disable(struct device *dev)  	case IMX7D:  	case IMX8MQ:  	case IMX8MM: +	case IMX8MP:  		reset_control_assert(imx6_pcie->apps_reset);  		break;  	} @@ -935,7 +945,7 @@ static int imx6_pcie_host_init(struct dw_pcie_rp *pp)  	}  	if (imx6_pcie->phy) { -		ret = phy_power_on(imx6_pcie->phy); +		ret = phy_init(imx6_pcie->phy);  		if (ret) {  			dev_err(dev, "pcie PHY power up failed\n");  			goto err_clk_disable; @@ -949,7 +959,7 @@ static int imx6_pcie_host_init(struct dw_pcie_rp *pp)  	}  	if (imx6_pcie->phy) { -		ret = phy_init(imx6_pcie->phy); +		ret = phy_power_on(imx6_pcie->phy);  		if (ret) {  			dev_err(dev, "waiting for PHY ready timeout!\n");  			goto err_phy_off; @@ -961,7 +971,7 @@ static int imx6_pcie_host_init(struct dw_pcie_rp *pp)  err_phy_off:  	if (imx6_pcie->phy) -		phy_power_off(imx6_pcie->phy); +		phy_exit(imx6_pcie->phy);  err_clk_disable:  	imx6_pcie_clk_disable(imx6_pcie);  err_reg_disable: @@ -1179,6 +1189,7 @@ static int imx6_pcie_probe(struct platform_device *pdev)  		}  		break;  	case IMX8MM: +	case IMX8MP:  		imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux");  		if (IS_ERR(imx6_pcie->pcie_aux))  			return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux), @@ -1216,7 +1227,7 @@ static int imx6_pcie_probe(struct platform_device *pdev)  	/* Grab GPR config register range */  	imx6_pcie->iomuxc_gpr = -		 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); +		 syscon_regmap_lookup_by_compatible(imx6_pcie->drvdata->gpr);  	if (IS_ERR(imx6_pcie->iomuxc_gpr)) {  		dev_err(dev, "unable to find iomuxc registers\n");  		return PTR_ERR(imx6_pcie->iomuxc_gpr); @@ -1295,12 +1306,14 @@ static const struct imx6_pcie_drvdata drvdata[] = {  		.flags = IMX6_PCIE_FLAG_IMX6_PHY |  			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,  		.dbi_length = 0x200, +		.gpr = "fsl,imx6q-iomuxc-gpr",  	},  	[IMX6SX] = {  		.variant = IMX6SX,  		.flags = IMX6_PCIE_FLAG_IMX6_PHY |  			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE |  			 IMX6_PCIE_FLAG_SUPPORTS_SUSPEND, +		.gpr = "fsl,imx6q-iomuxc-gpr",  	},  	[IMX6QP] = {  		.variant = IMX6QP, @@ -1308,17 +1321,26 @@ static const struct imx6_pcie_drvdata drvdata[] = {  			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE |  			 IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,  		.dbi_length = 0x200, +		.gpr = "fsl,imx6q-iomuxc-gpr",  	},  	[IMX7D] = {  		.variant = IMX7D,  		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND, +		.gpr = "fsl,imx7d-iomuxc-gpr",  	},  	[IMX8MQ] = {  		.variant = IMX8MQ, +		.gpr = "fsl,imx8mq-iomuxc-gpr",  	},  	[IMX8MM] = {  		.variant = IMX8MM,  		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND, +		.gpr = "fsl,imx8mm-iomuxc-gpr", +	}, +	[IMX8MP] = { +		.variant = IMX8MP, +		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND, +		.gpr = "fsl,imx8mp-iomuxc-gpr",  	},  }; @@ -1329,6 +1351,7 @@ static const struct of_device_id imx6_pcie_of_match[] = {  	{ .compatible = "fsl,imx7d-pcie",  .data = &drvdata[IMX7D],  },  	{ .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], },  	{ .compatible = "fsl,imx8mm-pcie", .data = &drvdata[IMX8MM], }, +	{ .compatible = "fsl,imx8mp-pcie", .data = &drvdata[IMX8MP], },  	{},  }; diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 7746f94a715f..39f3b37d4033 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -267,15 +267,6 @@ static void dw_pcie_free_msi(struct dw_pcie_rp *pp)  	irq_domain_remove(pp->msi_domain);  	irq_domain_remove(pp->irq_domain); - -	if (pp->msi_data) { -		struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -		struct device *dev = pci->dev; - -		dma_unmap_page(dev, pp->msi_data, PAGE_SIZE, DMA_FROM_DEVICE); -		if (pp->msi_page) -			__free_page(pp->msi_page); -	}  }  static void dw_pcie_msi_init(struct dw_pcie_rp *pp) @@ -336,6 +327,7 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	struct device *dev = pci->dev;  	struct platform_device *pdev = to_platform_device(dev); +	u64 *msi_vaddr;  	int ret;  	u32 ctrl, num_ctrls; @@ -375,22 +367,16 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)  						    dw_chained_msi_isr, pp);  	} -	ret = dma_set_mask(dev, DMA_BIT_MASK(32)); +	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));  	if (ret)  		dev_warn(dev, "Failed to set DMA mask to 32-bit. Devices with only 32-bit MSI support may not work properly\n"); -	pp->msi_page = alloc_page(GFP_DMA32); -	pp->msi_data = dma_map_page(dev, pp->msi_page, 0, -				    PAGE_SIZE, DMA_FROM_DEVICE); -	ret = dma_mapping_error(dev, pp->msi_data); -	if (ret) { -		dev_err(pci->dev, "Failed to map MSI data\n"); -		__free_page(pp->msi_page); -		pp->msi_page = NULL; -		pp->msi_data = 0; +	msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data, +					GFP_KERNEL); +	if (!msi_vaddr) { +		dev_err(dev, "Failed to alloc and map MSI data\n");  		dw_pcie_free_msi(pp); - -		return ret; +		return -ENOMEM;  	}  	return 0; diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 09b887093a84..a871ae7eb59e 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -243,7 +243,6 @@ struct dw_pcie_rp {  	struct irq_domain	*irq_domain;  	struct irq_domain	*msi_domain;  	dma_addr_t		msi_data; -	struct page		*msi_page;  	struct irq_chip		*msi_irq_chip;  	u32			num_vectors;  	u32			irq_mask[MAX_MSI_CTRLS]; diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c index 7f67aad71df4..d09507f822a7 100644 --- a/drivers/pci/controller/dwc/pcie-kirin.c +++ b/drivers/pci/controller/dwc/pcie-kirin.c @@ -13,6 +13,7 @@  #include <linux/delay.h>  #include <linux/err.h>  #include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/interrupt.h>  #include <linux/mfd/syscon.h>  #include <linux/of_address.h> @@ -366,12 +367,11 @@ static int kirin_pcie_get_gpio_enable(struct kirin_pcie *pcie,  				      struct platform_device *pdev)  {  	struct device *dev = &pdev->dev; -	struct device_node *np = dev->of_node;  	char name[32];  	int ret, i;  	/* This is an optional property */ -	ret = of_gpio_named_count(np, "hisilicon,clken-gpios"); +	ret = gpiod_count(dev, "hisilicon,clken");  	if (ret < 0)  		return 0; diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c index ec99116ad05c..6d0d1b759ca2 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c @@ -10,6 +10,7 @@   */  #include <linux/clk.h> +#include <linux/debugfs.h>  #include <linux/delay.h>  #include <linux/gpio/consumer.h>  #include <linux/mfd/syscon.h> @@ -26,6 +27,7 @@  #define PARF_SYS_CTRL				0x00  #define PARF_DB_CTRL				0x10  #define PARF_PM_CTRL				0x20 +#define PARF_MHI_CLOCK_RESET_CTRL		0x174  #define PARF_MHI_BASE_ADDR_LOWER		0x178  #define PARF_MHI_BASE_ADDR_UPPER		0x17c  #define PARF_DEBUG_INT_EN			0x190 @@ -45,6 +47,11 @@  #define PARF_ATU_BASE_ADDR			0x634  #define PARF_ATU_BASE_ADDR_HI			0x638  #define PARF_SRIS_MODE				0x644 +#define PARF_DEBUG_CNT_PM_LINKST_IN_L2		0xc04 +#define PARF_DEBUG_CNT_PM_LINKST_IN_L1		0xc0c +#define PARF_DEBUG_CNT_PM_LINKST_IN_L0S		0xc10 +#define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1	0xc84 +#define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2	0xc88  #define PARF_DEVICE_TYPE			0x1000  #define PARF_BDF_TO_SID_CFG			0x2c00 @@ -83,6 +90,9 @@  #define PARF_PM_CTRL_READY_ENTR_L23		BIT(2)  #define PARF_PM_CTRL_REQ_NOT_ENTR_L1		BIT(5) +/* PARF_MHI_CLOCK_RESET_CTRL fields */ +#define PARF_MSTR_AXI_CLK_EN			BIT(1) +  /* PARF_AXI_MSTR_RD_HALT_NO_WRITES register fields */  #define PARF_AXI_MSTR_RD_HALT_NO_WRITE_EN	BIT(0) @@ -95,6 +105,7 @@  /* PARF_SYS_CTRL register fields */  #define PARF_SYS_CTRL_AUX_PWR_DET		BIT(4)  #define PARF_SYS_CTRL_CORE_CLK_CGC_DIS		BIT(6) +#define PARF_SYS_CTRL_MSTR_ACLK_CGC_DIS		BIT(10)  #define PARF_SYS_CTRL_SLV_DBI_WAKE_DISABLE	BIT(11)  /* PARF_DB_CTRL register fields */ @@ -130,21 +141,33 @@ enum qcom_pcie_ep_link_status {  	QCOM_PCIE_EP_LINK_DOWN,  }; -static struct clk_bulk_data qcom_pcie_ep_clks[] = { -	{ .id = "cfg" }, -	{ .id = "aux" }, -	{ .id = "bus_master" }, -	{ .id = "bus_slave" }, -	{ .id = "ref" }, -	{ .id = "sleep" }, -	{ .id = "slave_q2a" }, -}; - +/** + * struct qcom_pcie_ep - Qualcomm PCIe Endpoint Controller + * @pci: Designware PCIe controller struct + * @parf: Qualcomm PCIe specific PARF register base + * @elbi: Designware PCIe specific ELBI register base + * @mmio: MMIO register base + * @perst_map: PERST regmap + * @mmio_res: MMIO region resource + * @core_reset: PCIe Endpoint core reset + * @reset: PERST# GPIO + * @wake: WAKE# GPIO + * @phy: PHY controller block + * @debugfs: PCIe Endpoint Debugfs directory + * @clks: PCIe clocks + * @num_clks: PCIe clocks count + * @perst_en: Flag for PERST enable + * @perst_sep_en: Flag for PERST separation enable + * @link_status: PCIe Link status + * @global_irq: Qualcomm PCIe specific Global IRQ + * @perst_irq: PERST# IRQ + */  struct qcom_pcie_ep {  	struct dw_pcie pci;  	void __iomem *parf;  	void __iomem *elbi; +	void __iomem *mmio;  	struct regmap *perst_map;  	struct resource *mmio_res; @@ -152,6 +175,10 @@ struct qcom_pcie_ep {  	struct gpio_desc *reset;  	struct gpio_desc *wake;  	struct phy *phy; +	struct dentry *debugfs; + +	struct clk_bulk_data *clks; +	int num_clks;  	u32 perst_en;  	u32 perst_sep_en; @@ -193,8 +220,10 @@ static int qcom_pcie_ep_core_reset(struct qcom_pcie_ep *pcie_ep)   */  static void qcom_pcie_ep_configure_tcsr(struct qcom_pcie_ep *pcie_ep)  { -	regmap_write(pcie_ep->perst_map, pcie_ep->perst_en, 0); -	regmap_write(pcie_ep->perst_map, pcie_ep->perst_sep_en, 0); +	if (pcie_ep->perst_map) { +		regmap_write(pcie_ep->perst_map, pcie_ep->perst_en, 0); +		regmap_write(pcie_ep->perst_map, pcie_ep->perst_sep_en, 0); +	}  }  static int qcom_pcie_dw_link_up(struct dw_pcie *pci) @@ -227,8 +256,7 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)  {  	int ret; -	ret = clk_bulk_prepare_enable(ARRAY_SIZE(qcom_pcie_ep_clks), -				      qcom_pcie_ep_clks); +	ret = clk_bulk_prepare_enable(pcie_ep->num_clks, pcie_ep->clks);  	if (ret)  		return ret; @@ -249,8 +277,7 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)  err_phy_exit:  	phy_exit(pcie_ep->phy);  err_disable_clk: -	clk_bulk_disable_unprepare(ARRAY_SIZE(qcom_pcie_ep_clks), -				   qcom_pcie_ep_clks); +	clk_bulk_disable_unprepare(pcie_ep->num_clks, pcie_ep->clks);  	return ret;  } @@ -259,8 +286,7 @@ static void qcom_pcie_disable_resources(struct qcom_pcie_ep *pcie_ep)  {  	phy_power_off(pcie_ep->phy);  	phy_exit(pcie_ep->phy); -	clk_bulk_disable_unprepare(ARRAY_SIZE(qcom_pcie_ep_clks), -				   qcom_pcie_ep_clks); +	clk_bulk_disable_unprepare(pcie_ep->num_clks, pcie_ep->clks);  }  static int qcom_pcie_perst_deassert(struct dw_pcie *pci) @@ -318,8 +344,14 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)  	val &= ~PARF_Q2A_FLUSH_EN;  	writel_relaxed(val, pcie_ep->parf + PARF_Q2A_FLUSH); -	/* Disable DBI Wakeup, core clock CGC and enable AUX power */ +	/* +	 * Disable Master AXI clock during idle.  Do not allow DBI access +	 * to take the core out of L1.  Disable core clock gating that +	 * gates PIPE clock from propagating to core clock.  Report to the +	 * host that Vaux is present. +	 */  	val = readl_relaxed(pcie_ep->parf + PARF_SYS_CTRL); +	val &= ~PARF_SYS_CTRL_MSTR_ACLK_CGC_DIS;  	val |= PARF_SYS_CTRL_SLV_DBI_WAKE_DISABLE |  	       PARF_SYS_CTRL_CORE_CLK_CGC_DIS |  	       PARF_SYS_CTRL_AUX_PWR_DET; @@ -375,6 +407,11 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)  		       pcie_ep->parf + PARF_MHI_BASE_ADDR_LOWER);  	writel_relaxed(0, pcie_ep->parf + PARF_MHI_BASE_ADDR_UPPER); +	/* Gate Master AXI clock to MHI bus during L1SS */ +	val = readl_relaxed(pcie_ep->parf + PARF_MHI_CLOCK_RESET_CTRL); +	val &= ~PARF_MSTR_AXI_CLK_EN; +	val = readl_relaxed(pcie_ep->parf + PARF_MHI_CLOCK_RESET_CTRL); +  	dw_pcie_ep_init_notify(&pcie_ep->pci.ep);  	/* Enable LTSSM */ @@ -437,11 +474,19 @@ static int qcom_pcie_ep_get_io_resources(struct platform_device *pdev,  	pcie_ep->mmio_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,  							 "mmio"); +	if (!pcie_ep->mmio_res) { +		dev_err(dev, "Failed to get mmio resource\n"); +		return -EINVAL; +	} + +	pcie_ep->mmio = devm_pci_remap_cfg_resource(dev, pcie_ep->mmio_res); +	if (IS_ERR(pcie_ep->mmio)) +		return PTR_ERR(pcie_ep->mmio);  	syscon = of_parse_phandle(dev->of_node, "qcom,perst-regs", 0);  	if (!syscon) { -		dev_err(dev, "Failed to parse qcom,perst-regs\n"); -		return -EINVAL; +		dev_dbg(dev, "PERST separation not available\n"); +		return 0;  	}  	pcie_ep->perst_map = syscon_node_to_regmap(syscon); @@ -474,14 +519,15 @@ static int qcom_pcie_ep_get_resources(struct platform_device *pdev,  	ret = qcom_pcie_ep_get_io_resources(pdev, pcie_ep);  	if (ret) { -		dev_err(&pdev->dev, "Failed to get io resources %d\n", ret); +		dev_err(dev, "Failed to get io resources %d\n", ret);  		return ret;  	} -	ret = devm_clk_bulk_get(dev, ARRAY_SIZE(qcom_pcie_ep_clks), -				qcom_pcie_ep_clks); -	if (ret) -		return ret; +	pcie_ep->num_clks = devm_clk_bulk_get_all(dev, &pcie_ep->clks); +	if (pcie_ep->num_clks < 0) { +		dev_err(dev, "Failed to get clocks\n"); +		return pcie_ep->num_clks; +	}  	pcie_ep->core_reset = devm_reset_control_get_exclusive(dev, "core");  	if (IS_ERR(pcie_ep->core_reset)) @@ -495,7 +541,7 @@ static int qcom_pcie_ep_get_resources(struct platform_device *pdev,  	if (IS_ERR(pcie_ep->wake))  		return PTR_ERR(pcie_ep->wake); -	pcie_ep->phy = devm_phy_optional_get(&pdev->dev, "pciephy"); +	pcie_ep->phy = devm_phy_optional_get(dev, "pciephy");  	if (IS_ERR(pcie_ep->phy))  		ret = PTR_ERR(pcie_ep->phy); @@ -571,13 +617,13 @@ static irqreturn_t qcom_pcie_ep_perst_irq_thread(int irq, void *data)  static int qcom_pcie_ep_enable_irq_resources(struct platform_device *pdev,  					     struct qcom_pcie_ep *pcie_ep)  { -	int irq, ret; +	int ret; -	irq = platform_get_irq_byname(pdev, "global"); -	if (irq < 0) -		return irq; +	pcie_ep->global_irq = platform_get_irq_byname(pdev, "global"); +	if (pcie_ep->global_irq < 0) +		return pcie_ep->global_irq; -	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, +	ret = devm_request_threaded_irq(&pdev->dev, pcie_ep->global_irq, NULL,  					qcom_pcie_ep_global_irq_thread,  					IRQF_ONESHOT,  					"global_irq", pcie_ep); @@ -594,7 +640,7 @@ static int qcom_pcie_ep_enable_irq_resources(struct platform_device *pdev,  					"perst_irq", pcie_ep);  	if (ret) {  		dev_err(&pdev->dev, "Failed to request PERST IRQ\n"); -		disable_irq(irq); +		disable_irq(pcie_ep->global_irq);  		return ret;  	} @@ -617,6 +663,37 @@ static int qcom_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,  	}  } +static int qcom_pcie_ep_link_transition_count(struct seq_file *s, void *data) +{ +	struct qcom_pcie_ep *pcie_ep = (struct qcom_pcie_ep *) +				     dev_get_drvdata(s->private); + +	seq_printf(s, "L0s transition count: %u\n", +		   readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_PM_LINKST_IN_L0S)); + +	seq_printf(s, "L1 transition count: %u\n", +		   readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_PM_LINKST_IN_L1)); + +	seq_printf(s, "L1.1 transition count: %u\n", +		   readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1)); + +	seq_printf(s, "L1.2 transition count: %u\n", +		   readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2)); + +	seq_printf(s, "L2 transition count: %u\n", +		   readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_PM_LINKST_IN_L2)); + +	return 0; +} + +static void qcom_pcie_ep_init_debugfs(struct qcom_pcie_ep *pcie_ep) +{ +	struct dw_pcie *pci = &pcie_ep->pci; + +	debugfs_create_devm_seqfile(pci->dev, "link_transition_count", pcie_ep->debugfs, +				    qcom_pcie_ep_link_transition_count); +} +  static const struct pci_epc_features qcom_pcie_epc_features = {  	.linkup_notifier = true,  	.core_init_notifier = true, @@ -649,6 +726,7 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev)  {  	struct device *dev = &pdev->dev;  	struct qcom_pcie_ep *pcie_ep; +	char *name;  	int ret;  	pcie_ep = devm_kzalloc(dev, sizeof(*pcie_ep), GFP_KERNEL); @@ -680,8 +758,21 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev)  	if (ret)  		goto err_disable_resources; +	name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node); +	if (!name) { +		ret = -ENOMEM; +		goto err_disable_irqs; +	} + +	pcie_ep->debugfs = debugfs_create_dir(name, NULL); +	qcom_pcie_ep_init_debugfs(pcie_ep); +  	return 0; +err_disable_irqs: +	disable_irq(pcie_ep->global_irq); +	disable_irq(pcie_ep->perst_irq); +  err_disable_resources:  	qcom_pcie_disable_resources(pcie_ep); @@ -692,6 +783,11 @@ static int qcom_pcie_ep_remove(struct platform_device *pdev)  {  	struct qcom_pcie_ep *pcie_ep = platform_get_drvdata(pdev); +	disable_irq(pcie_ep->global_irq); +	disable_irq(pcie_ep->perst_irq); + +	debugfs_remove_recursive(pcie_ep->debugfs); +  	if (pcie_ep->link_status == QCOM_PCIE_EP_LINK_DISABLED)  		return 0; @@ -702,8 +798,10 @@ static int qcom_pcie_ep_remove(struct platform_device *pdev)  static const struct of_device_id qcom_pcie_ep_match[] = {  	{ .compatible = "qcom,sdx55-pcie-ep", }, +	{ .compatible = "qcom,sm8450-pcie-ep", },  	{ }  }; +MODULE_DEVICE_TABLE(of, qcom_pcie_ep_match);  static struct platform_driver qcom_pcie_ep_driver = {  	.probe	= qcom_pcie_ep_probe, diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 66886dc6e777..f711acacaeaf 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -180,7 +180,7 @@ struct qcom_pcie_resources_2_3_3 {  /* 6 clocks typically, 7 for sm8250 */  struct qcom_pcie_resources_2_7_0 { -	struct clk_bulk_data clks[9]; +	struct clk_bulk_data clks[12];  	int num_clks;  	struct regulator_bulk_data supplies[2];  	struct reset_control *pci_reset; @@ -208,17 +208,12 @@ struct qcom_pcie_ops {  	int (*init)(struct qcom_pcie *pcie);  	int (*post_init)(struct qcom_pcie *pcie);  	void (*deinit)(struct qcom_pcie *pcie); -	void (*post_deinit)(struct qcom_pcie *pcie);  	void (*ltssm_enable)(struct qcom_pcie *pcie);  	int (*config_sid)(struct qcom_pcie *pcie);  };  struct qcom_pcie_cfg {  	const struct qcom_pcie_ops *ops; -	unsigned int has_tbu_clk:1; -	unsigned int has_ddrss_sf_tbu_clk:1; -	unsigned int has_aggre0_clk:1; -	unsigned int has_aggre1_clk:1;  };  struct qcom_pcie { @@ -1175,6 +1170,7 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)  	struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;  	struct dw_pcie *pci = pcie->pci;  	struct device *dev = pci->dev; +	unsigned int num_clks, num_opt_clks;  	unsigned int idx;  	int ret; @@ -1195,18 +1191,25 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)  	res->clks[idx++].id = "bus_master";  	res->clks[idx++].id = "bus_slave";  	res->clks[idx++].id = "slave_q2a"; -	if (pcie->cfg->has_tbu_clk) -		res->clks[idx++].id = "tbu"; -	if (pcie->cfg->has_ddrss_sf_tbu_clk) -		res->clks[idx++].id = "ddrss_sf_tbu"; -	if (pcie->cfg->has_aggre0_clk) -		res->clks[idx++].id = "aggre0"; -	if (pcie->cfg->has_aggre1_clk) -		res->clks[idx++].id = "aggre1"; +	num_clks = idx; + +	ret = devm_clk_bulk_get(dev, num_clks, res->clks); +	if (ret < 0) +		return ret; + +	res->clks[idx++].id = "tbu"; +	res->clks[idx++].id = "ddrss_sf_tbu"; +	res->clks[idx++].id = "aggre0"; +	res->clks[idx++].id = "aggre1"; +	res->clks[idx++].id = "noc_aggr_4"; +	res->clks[idx++].id = "noc_aggr_south_sf"; +	res->clks[idx++].id = "cnoc_qx"; + +	num_opt_clks = idx - num_clks;  	res->num_clks = idx; -	ret = devm_clk_bulk_get(dev, res->num_clks, res->clks); +	ret = devm_clk_bulk_get_optional(dev, num_opt_clks, res->clks + num_clks);  	if (ret < 0)  		return ret; @@ -1509,15 +1512,13 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp)  	if (pcie->cfg->ops->config_sid) {  		ret = pcie->cfg->ops->config_sid(pcie);  		if (ret) -			goto err; +			goto err_assert_reset;  	}  	return 0; -err: +err_assert_reset:  	qcom_ep_reset_assert(pcie); -	if (pcie->cfg->ops->post_deinit) -		pcie->cfg->ops->post_deinit(pcie);  err_disable_phy:  	phy_power_off(pcie->phy);  err_deinit: @@ -1601,68 +1602,35 @@ static const struct qcom_pcie_ops ops_2_9_0 = {  	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,  }; -static const struct qcom_pcie_cfg apq8084_cfg = { +static const struct qcom_pcie_cfg cfg_1_0_0 = {  	.ops = &ops_1_0_0,  }; -static const struct qcom_pcie_cfg ipq8064_cfg = { +static const struct qcom_pcie_cfg cfg_1_9_0 = { +	.ops = &ops_1_9_0, +}; + +static const struct qcom_pcie_cfg cfg_2_1_0 = {  	.ops = &ops_2_1_0,  }; -static const struct qcom_pcie_cfg msm8996_cfg = { +static const struct qcom_pcie_cfg cfg_2_3_2 = {  	.ops = &ops_2_3_2,  }; -static const struct qcom_pcie_cfg ipq8074_cfg = { +static const struct qcom_pcie_cfg cfg_2_3_3 = {  	.ops = &ops_2_3_3,  }; -static const struct qcom_pcie_cfg ipq4019_cfg = { +static const struct qcom_pcie_cfg cfg_2_4_0 = {  	.ops = &ops_2_4_0,  }; -static const struct qcom_pcie_cfg sdm845_cfg = { +static const struct qcom_pcie_cfg cfg_2_7_0 = {  	.ops = &ops_2_7_0, -	.has_tbu_clk = true, -}; - -static const struct qcom_pcie_cfg sm8150_cfg = { -	/* sm8150 has qcom IP rev 1.5.0. However 1.5.0 ops are same as -	 * 1.9.0, so reuse the same. -	 */ -	.ops = &ops_1_9_0, -}; - -static const struct qcom_pcie_cfg sm8250_cfg = { -	.ops = &ops_1_9_0, -	.has_tbu_clk = true, -	.has_ddrss_sf_tbu_clk = true, -}; - -static const struct qcom_pcie_cfg sm8450_pcie0_cfg = { -	.ops = &ops_1_9_0, -	.has_ddrss_sf_tbu_clk = true, -	.has_aggre0_clk = true, -	.has_aggre1_clk = true, -}; - -static const struct qcom_pcie_cfg sm8450_pcie1_cfg = { -	.ops = &ops_1_9_0, -	.has_ddrss_sf_tbu_clk = true, -	.has_aggre1_clk = true, -}; - -static const struct qcom_pcie_cfg sc7280_cfg = { -	.ops = &ops_1_9_0, -	.has_tbu_clk = true, -}; - -static const struct qcom_pcie_cfg sc8180x_cfg = { -	.ops = &ops_1_9_0, -	.has_tbu_clk = true,  }; -static const struct qcom_pcie_cfg ipq6018_cfg = { +static const struct qcom_pcie_cfg cfg_2_9_0 = {  	.ops = &ops_2_9_0,  }; @@ -1761,22 +1729,24 @@ err_pm_runtime_put:  }  static const struct of_device_id qcom_pcie_match[] = { -	{ .compatible = "qcom,pcie-apq8084", .data = &apq8084_cfg }, -	{ .compatible = "qcom,pcie-ipq8064", .data = &ipq8064_cfg }, -	{ .compatible = "qcom,pcie-ipq8064-v2", .data = &ipq8064_cfg }, -	{ .compatible = "qcom,pcie-apq8064", .data = &ipq8064_cfg }, -	{ .compatible = "qcom,pcie-msm8996", .data = &msm8996_cfg }, -	{ .compatible = "qcom,pcie-ipq8074", .data = &ipq8074_cfg }, -	{ .compatible = "qcom,pcie-ipq4019", .data = &ipq4019_cfg }, -	{ .compatible = "qcom,pcie-qcs404", .data = &ipq4019_cfg }, -	{ .compatible = "qcom,pcie-sdm845", .data = &sdm845_cfg }, -	{ .compatible = "qcom,pcie-sm8150", .data = &sm8150_cfg }, -	{ .compatible = "qcom,pcie-sm8250", .data = &sm8250_cfg }, -	{ .compatible = "qcom,pcie-sc8180x", .data = &sc8180x_cfg }, -	{ .compatible = "qcom,pcie-sm8450-pcie0", .data = &sm8450_pcie0_cfg }, -	{ .compatible = "qcom,pcie-sm8450-pcie1", .data = &sm8450_pcie1_cfg }, -	{ .compatible = "qcom,pcie-sc7280", .data = &sc7280_cfg }, -	{ .compatible = "qcom,pcie-ipq6018", .data = &ipq6018_cfg }, +	{ .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 }, +	{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 }, +	{ .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_0 }, +	{ .compatible = "qcom,pcie-ipq6018", .data = &cfg_2_9_0 }, +	{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 }, +	{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 }, +	{ .compatible = "qcom,pcie-ipq8074", .data = &cfg_2_3_3 }, +	{ .compatible = "qcom,pcie-msm8996", .data = &cfg_2_3_2 }, +	{ .compatible = "qcom,pcie-qcs404", .data = &cfg_2_4_0 }, +	{ .compatible = "qcom,pcie-sa8540p", .data = &cfg_1_9_0 }, +	{ .compatible = "qcom,pcie-sc7280", .data = &cfg_1_9_0 }, +	{ .compatible = "qcom,pcie-sc8180x", .data = &cfg_1_9_0 }, +	{ .compatible = "qcom,pcie-sc8280xp", .data = &cfg_1_9_0 }, +	{ .compatible = "qcom,pcie-sdm845", .data = &cfg_2_7_0 }, +	{ .compatible = "qcom,pcie-sm8150", .data = &cfg_1_9_0 }, +	{ .compatible = "qcom,pcie-sm8250", .data = &cfg_1_9_0 }, +	{ .compatible = "qcom,pcie-sm8450-pcie0", .data = &cfg_1_9_0 }, +	{ .compatible = "qcom,pcie-sm8450-pcie1", .data = &cfg_1_9_0 },  	{ }  };  | 
