Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75f0a9b1 authored by Rama Krishna Phani A's avatar Rama Krishna Phani A Committed by Gerrit - the friendly Code Review server
Browse files

msm: ep_pcie: add eDMA support for PCIe EP driver



Add support to initialize eDMA driver during EP PCIe
probe for eDMA supported targets. Unmask eDMA interrupt
in PCIe global IRQ. Add support to bypass SMMU for
PCIe eDMA.

Change-Id: I68a73a0f8c2c2f9f14e17168e2bf5e04f6de1a15
Signed-off-by: default avatarRama Krishna Phani A <rphani@codeaurora.org>
Signed-off-by: default avatarChandra Devireddy <cdevired@codeaurora.org>
parent 2dda6ec0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ Optional Properties:
    1, 2 or 3.
  - qcom,pcie-active-config: boolean type; active configuration of PCIe
    addressing.
  - qcom,pcie-edma: boolean type; edma usage for PCIe.
  - qcom,pcie-aggregated-irq: boolean type; interrupts are aggregated.
  - qcom,pcie-mhi-a7-irq: boolean type; MHI a7 has separate irq.
  - qcom,pcie-perst-enum: Link enumeration will be triggered by PERST
+7 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/msm_ep_pcie.h>
#include <linux/iommu.h>

#define PCIE20_PARF_SYS_CTRL           0x00
#define PCIE20_PARF_DB_CTRL            0x10
@@ -56,6 +57,8 @@
#define PCIE20_PARF_ATU_BASE_ADDR      0x634
#define PCIE20_PARF_ATU_BASE_ADDR_HI   0x638
#define PCIE20_PARF_DEVICE_TYPE        0x1000
#define PCIE20_PARF_EDMA_BASE_ADDR      0x64C
#define PCIE20_PARF_EDMA_BASE_ADDR_HI   0x650

#define PCIE20_ELBI_VERSION            0x00
#define PCIE20_ELBI_SYS_CTRL           0x04
@@ -229,6 +232,7 @@ enum ep_pcie_res {
	EP_PCIE_RES_DM_CORE,
	EP_PCIE_RES_ELBI,
	EP_PCIE_RES_IATU,
	EP_PCIE_RES_EDMA,
	EP_PCIE_MAX_RES,
};

@@ -318,6 +322,7 @@ struct ep_pcie_dev_t {
	void __iomem                 *mmio;
	void __iomem                 *msi;
	void __iomem                 *dm_core;
	void __iomem                 *edma;
	void __iomem                 *elbi;
	void __iomem                 *iatu;

@@ -327,6 +332,7 @@ struct ep_pcie_dev_t {
	bool                         active_config;
	bool                         aggregated_irq;
	bool                         mhi_a7_irq;
	bool                         pcie_edma;
	u32                          dbi_base_reg;
	u32                          slv_space_reg;
	u32                          phy_status_reg;
@@ -418,5 +424,6 @@ extern bool ep_pcie_phy_is_ready(struct ep_pcie_dev_t *dev);
extern void ep_pcie_reg_dump(struct ep_pcie_dev_t *dev, u32 sel, bool linkdown);
extern void ep_pcie_debugfs_init(struct ep_pcie_dev_t *ep_dev);
extern void ep_pcie_debugfs_exit(void);
extern int qcom_edma_init(struct device *dev);

#endif
+76 −2
Original line number Diff line number Diff line
@@ -35,6 +35,9 @@
#include <linux/irq.h>

#include "ep_pcie_com.h"
#include <asm/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>

/* debug mask sys interface */
static int ep_pcie_debug_mask;
@@ -92,6 +95,7 @@ static const struct ep_pcie_res_info_t ep_pcie_res_info[EP_PCIE_MAX_RES] = {
	{"dm_core",	NULL, NULL},
	{"elbi",	NULL, NULL},
	{"iatu",	NULL, NULL},
	{"edma",	NULL, NULL},
};

static const struct ep_pcie_irq_info_t ep_pcie_irq_info[EP_PCIE_MAX_IRQ] = {
@@ -597,6 +601,25 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
				"PCIe V%d: LSB of ATU base:0x%x\n",
				dev->rev, readl_relaxed(dev->parf
						+ PCIE20_PARF_ATU_BASE_ADDR));
			if (dev->pcie_edma) {
				struct resource *edma =
					dev->res[EP_PCIE_RES_EDMA].resource;
				u32 edma_lo = edma->start;

				ep_pcie_write_reg(dev->parf,
					PCIE20_PARF_EDMA_BASE_ADDR_HI, 0x100);
				EP_PCIE_DBG(dev,
					"PCIe V%d: EDMA base HI :0x%x\n",
					dev->rev, readl_relaxed(dev->parf +
					PCIE20_PARF_EDMA_BASE_ADDR_HI));

				ep_pcie_write_reg(dev->parf,
					PCIE20_PARF_EDMA_BASE_ADDR, edma_lo);
				EP_PCIE_DBG(dev,
					"PCIe V%d: EDMA base:0x%x\n", dev->rev,
						readl_relaxed(dev->parf +
						PCIE20_PARF_EDMA_BASE_ADDR));
			}
		}
	}

@@ -710,6 +733,10 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
			ep_pcie_write_mask(dev->parf +
				PCIE20_PARF_INT_ALL_MASK, 0,
				BIT(EP_PCIE_INT_EVT_MHI_A7));
		if (dev->pcie_edma)
			ep_pcie_write_mask(dev->parf +
				PCIE20_PARF_INT_ALL_MASK, 0,
				BIT(EP_PCIE_INT_EVT_EDMA));

		EP_PCIE_DBG(dev, "PCIe V%d: PCIE20_PARF_INT_ALL_MASK:0x%x\n",
			dev->rev,
@@ -806,8 +833,15 @@ static void ep_pcie_config_outbound_iatu_entry(struct ep_pcie_dev_t *dev,
					tgt_lower);
		ep_pcie_write_reg(dev->iatu, PCIE20_IATU_O_UTAR(region),
					tgt_upper);
		ep_pcie_write_mask(dev->iatu + PCIE20_IATU_O_CTRL2(region),
					0, BIT(31));
		/* Set DMA Bypass bit for eDMA */
		if (dev->pcie_edma)
			ep_pcie_write_mask(dev->iatu +
				PCIE20_IATU_O_CTRL2(region), 0,
				BIT(31)|BIT(27));
		else
			ep_pcie_write_mask(dev->iatu +
				PCIE20_IATU_O_CTRL2(region), 0,
				BIT(31));

		EP_PCIE_DBG(dev,
			"PCIe V%d: Outbound iATU configuration\n", dev->rev);
@@ -1166,6 +1200,7 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev,
	dev->mmio = dev->res[EP_PCIE_RES_MMIO].base;
	dev->msi = dev->res[EP_PCIE_RES_MSI].base;
	dev->dm_core = dev->res[EP_PCIE_RES_DM_CORE].base;
	dev->edma = dev->res[EP_PCIE_RES_EDMA].base;
	dev->elbi = dev->res[EP_PCIE_RES_ELBI].base;
	dev->iatu = dev->res[EP_PCIE_RES_IATU].base;

@@ -1179,6 +1214,7 @@ static void ep_pcie_release_resources(struct ep_pcie_dev_t *dev)
	dev->parf = NULL;
	dev->elbi = NULL;
	dev->dm_core = NULL;
	dev->edma = NULL;
	dev->phy = NULL;
	dev->mmio = NULL;
	dev->msi = NULL;
@@ -2459,6 +2495,8 @@ struct ep_pcie_hw hw_drv = {
static int ep_pcie_probe(struct platform_device *pdev)
{
	int ret;
	struct dma_iommu_mapping *mapping;
	int bypass_en = 1;

	pr_debug("%s\n", __func__);

@@ -2519,6 +2557,12 @@ static int ep_pcie_probe(struct platform_device *pdev)
		EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: pcie-phy-ver:%d\n",
			ep_pcie_dev.rev, ep_pcie_dev.phy_rev);

	ep_pcie_dev.pcie_edma = of_property_read_bool((&pdev->dev)->of_node,
				"qcom,pcie-edma");
	EP_PCIE_DBG(&ep_pcie_dev,
		"PCIe V%d: pcie edma is %s enabled\n",
		ep_pcie_dev.rev, ep_pcie_dev.pcie_edma ? "" : "not");

	ep_pcie_dev.active_config = of_property_read_bool((&pdev->dev)->of_node,
				"qcom,pcie-active-config");
	EP_PCIE_DBG(&ep_pcie_dev,
@@ -2602,7 +2646,37 @@ static int ep_pcie_probe(struct platform_device *pdev)
		"PCIe V%d: %s got resources successfully; start turning on the link\n",
		ep_pcie_dev.rev, dev_name(&(pdev->dev)));

	if (ep_pcie_dev.pcie_edma) {
		mapping = arm_iommu_create_mapping
					(&platform_bus_type, 0, SZ_4K);
		if (IS_ERR_OR_NULL(mapping)) {
			EP_PCIE_ERR(&ep_pcie_dev,
				"PCIe V%d: Failed to create_mapping\n",
					ep_pcie_dev.rev);
			goto skip_mapping;
		}

		ret = iommu_domain_set_attr(mapping->domain,
				DOMAIN_ATTR_S1_BYPASS, &bypass_en);
		if (ret < 0)
			EP_PCIE_ERR(&ep_pcie_dev,
				"PCIe V%d: Failed to set bypass\n",
					ep_pcie_dev.rev);

		ret = arm_iommu_attach_device(&pdev->dev, mapping);
		if (ret)
			EP_PCIE_ERR(&ep_pcie_dev,
				"PCIe V%d: arm_iommu_attach_device failed %d\n",
					ep_pcie_dev.rev, ret);
		else
			EP_PCIE_ERR(&ep_pcie_dev,
				"PCIe V%d: arm_iommu_attach_device successful\n",
					ep_pcie_dev.rev);
	}
skip_mapping:
	ret = ep_pcie_enumeration(&ep_pcie_dev);
	if (IS_ENABLED(CONFIG_QCOM_PCI_EDMA))
		qcom_edma_init(&pdev->dev);

	if (!ret || ep_pcie_debug_keep_resource)
		return 0;
+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015, 2017, 2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -47,6 +47,7 @@ enum ep_pcie_irq_event {
	EP_PCIE_INT_EVT_CFG_WRITE,
	EP_PCIE_INT_EVT_BRIDGE_FLUSH_N,
	EP_PCIE_INT_EVT_LINK_UP,
	EP_PCIE_INT_EVT_EDMA = 22,
	EP_PCIE_INT_EVT_MAX = 13,
};