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

Commit ea890b21 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ep_pcie: add eDMA support for PCIe EP driver"

parents 4c77e4b6 75f0a9b1
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,
};