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

Commit 4fae0d13 authored by Frank Liu's avatar Frank Liu
Browse files

cnss2: Add support for PCIe WLAN IPA uc SMMU feature



To add support for PCIe WLAN IPA uc SMMU feature, prvoide related
platform api for wlan driver to get the smmu map handle and do the
mapping.

Change-Id: I672b1a48879ada65b3ddb3f16c4bd787dc1b70a6
Signed-off-by: default avatarFrank Liu <qiliu@codeaurora.org>
parent a4cb23ac
Loading
Loading
Loading
Loading
+66 −0
Original line number Diff line number Diff line
@@ -1357,6 +1357,61 @@ void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv)
			       CNSS_REASON_TIMEOUT);
}

struct dma_iommu_mapping *cnss_smmu_get_mapping(struct device *dev)
{
	struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev));

	if (!pci_priv)
		return NULL;

	return pci_priv->smmu_mapping;
}
EXPORT_SYMBOL(cnss_smmu_get_mapping);

int cnss_smmu_map(struct device *dev,
		  phys_addr_t paddr, uint32_t *iova_addr, size_t size)
{
	struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev));
	unsigned long iova;
	size_t len;
	int ret = 0;

	if (!pci_priv)
		return -ENODEV;

	if (!iova_addr) {
		cnss_pr_err("iova_addr is NULL, paddr %pa, size %zu\n",
			    &paddr, size);
		return -EINVAL;
	}

	len = roundup(size + paddr - rounddown(paddr, PAGE_SIZE), PAGE_SIZE);
	iova = roundup(pci_priv->smmu_iova_ipa_start, PAGE_SIZE);

	if (iova >=
	    (pci_priv->smmu_iova_ipa_start + pci_priv->smmu_iova_ipa_len)) {
		cnss_pr_err("No IOVA space to map, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n",
			    iova,
			    &pci_priv->smmu_iova_ipa_start,
			    pci_priv->smmu_iova_ipa_len);
		return -ENOMEM;
	}

	ret = iommu_map(pci_priv->smmu_mapping->domain, iova,
			rounddown(paddr, PAGE_SIZE), len,
			IOMMU_READ | IOMMU_WRITE);
	if (ret) {
		cnss_pr_err("PA to IOVA mapping failed, ret %d\n", ret);
		return ret;
	}

	pci_priv->smmu_iova_ipa_start = iova + len;
	*iova_addr = (uint32_t)(iova + paddr - rounddown(paddr, PAGE_SIZE));

	return 0;
}
EXPORT_SYMBOL(cnss_smmu_map);

int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info)
{
	struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev));
@@ -2150,6 +2205,17 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
			    &pci_priv->smmu_iova_start,
			    pci_priv->smmu_iova_len);

		res = platform_get_resource_byname(plat_priv->plat_dev,
						   IORESOURCE_MEM,
						   "smmu_iova_ipa");
		if (res) {
			pci_priv->smmu_iova_ipa_start = res->start;
			pci_priv->smmu_iova_ipa_len = resource_size(res);
			cnss_pr_dbg("smmu_iova_ipa_start: %pa, smmu_iova_ipa_len: %zu\n",
				    &pci_priv->smmu_iova_ipa_start,
				    pci_priv->smmu_iova_ipa_len);
		}

		ret = cnss_pci_init_smmu(pci_priv);
		if (ret) {
			cnss_pr_err("Failed to init SMMU, err = %d\n", ret);
+2 −0
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@ struct cnss_pci_data {
	bool smmu_s1_enable;
	dma_addr_t smmu_iova_start;
	size_t smmu_iova_len;
	dma_addr_t smmu_iova_ipa_start;
	size_t smmu_iova_ipa_len;
	void __iomem *bar;
	struct cnss_msi_config *msi_config;
	u32 msi_ep_base_data;
+3 −0
Original line number Diff line number Diff line
@@ -159,6 +159,9 @@ extern int cnss_get_fw_files_for_target(struct device *dev,
					u32 target_type, u32 target_version);
extern int cnss_get_platform_cap(struct device *dev,
				 struct cnss_platform_cap *cap);
extern struct dma_iommu_mapping *cnss_smmu_get_mapping(struct device *dev);
extern int cnss_smmu_map(struct device *dev,
			 phys_addr_t paddr, uint32_t *iova_addr, size_t size);
extern int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info);
extern int cnss_request_bus_bandwidth(struct device *dev, int bandwidth);
extern int cnss_power_up(struct device *dev);