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

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

Merge "ARM: dts: msm: Switch to new SMMU devicetree format for CNSS"

parents ee0388a4 10616b83
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -3247,9 +3247,8 @@

	qcom,cnss-qca6390@a0000000 {
		compatible = "qcom,cnss-qca6390";
		reg = <0xa0000000 0x10000000>,
		      <0xb0000000 0x10000>;
		reg-names = "smmu_iova_base", "smmu_iova_ipa";
		reg = <0xb0000000 0x10000>;
		reg-names = "smmu_iova_ipa";
		wlan-en-gpio = <&tlmm 20 0>;
		pinctrl-names = "wlan_en_active", "wlan_en_sleep";
		pinctrl-0 = <&cnss_wlan_en_active>;
@@ -3375,7 +3374,16 @@

	cnss_pci: cnss_pci {
		reg = <0 0 0 0 0>;
		qcom,iommu-dma = "disabled";
		qcom,iommu-group = <&cnss_pci_iommu_group>;

		#address-cells = <1>;
		#size-cells = <1>;

		cnss_pci_iommu_group: cnss_pci_iommu_group {
			qcom,iommu-dma-addr-pool = <0xa0000000 0x10000000>;
			qcom,iommu-dma = "fastmap";
			qcom,iommu-pagetable = "coherent";
		};
	};
};

+50 −117
Original line number Diff line number Diff line
@@ -934,99 +934,6 @@ int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv)
	return 0;
}

static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv)
{
	int ret = 0;
	struct device *dev;
	struct dma_iommu_mapping *mapping;
	int atomic_ctx = 1, s1_bypass = 1, fast = 1, cb_stall_disable = 1,
		no_cfre = 1;

	cnss_pr_dbg("Initializing SMMU\n");

	dev = &pci_priv->pci_dev->dev;

	mapping = __depr_arm_iommu_create_mapping(dev->bus,
						  pci_priv->smmu_iova_start,
						  pci_priv->smmu_iova_len);
	if (IS_ERR(mapping)) {
		ret = PTR_ERR(mapping);
		cnss_pr_err("Failed to create SMMU mapping, err = %d\n", ret);
		goto out;
	}

	if (pci_priv->smmu_s1_enable) {
		cnss_pr_dbg("Enabling SMMU S1 stage\n");

		ret = iommu_domain_set_attr(mapping->domain,
					    DOMAIN_ATTR_ATOMIC,
					    &atomic_ctx);
		if (ret) {
			pr_err("Failed to set SMMU atomic_ctx attribute, err = %d\n",
			       ret);
			goto release_mapping;
		}

		ret = iommu_domain_set_attr(mapping->domain,
					    DOMAIN_ATTR_FAST,
					    &fast);
		if (ret) {
			pr_err("Failed to set SMMU fast attribute, err = %d\n",
			       ret);
			goto release_mapping;
		}

		ret = iommu_domain_set_attr(mapping->domain,
					    DOMAIN_ATTR_CB_STALL_DISABLE,
					    &cb_stall_disable);
		if (ret) {
			pr_err("Failed to set SMMU cb_stall_disable attribute, err = %d\n",
			       ret);
			goto release_mapping;
		}

		ret = iommu_domain_set_attr(mapping->domain,
					    DOMAIN_ATTR_NO_CFRE,
					    &no_cfre);
		if (ret) {
			pr_err("Failed to set SMMU no_cfre attribute, err = %d\n",
			       ret);
			goto release_mapping;
		}
	} else {
		ret = iommu_domain_set_attr(mapping->domain,
					    DOMAIN_ATTR_S1_BYPASS,
					    &s1_bypass);
		if (ret) {
			pr_err("Failed to set SMMU s1_bypass attribute, err = %d\n",
			       ret);
			goto release_mapping;
		}
	}

	ret = __depr_arm_iommu_attach_device(dev, mapping);
	if (ret) {
		pr_err("Failed to attach SMMU device, err = %d\n", ret);
		goto release_mapping;
	}

	pci_priv->smmu_mapping = mapping;

	return ret;
release_mapping:
	__depr_arm_iommu_release_mapping(mapping);
out:
	return ret;
}

static void cnss_pci_deinit_smmu(struct cnss_pci_data *pci_priv)
{
	__depr_arm_iommu_detach_device(&pci_priv->pci_dev->dev);
	__depr_arm_iommu_release_mapping(pci_priv->smmu_mapping);

	pci_priv->smmu_mapping = NULL;
}

static void cnss_pci_event_cb(struct msm_pcie_notify *notify)
{
	unsigned long flags;
@@ -1709,10 +1616,21 @@ struct dma_iommu_mapping *cnss_smmu_get_mapping(struct device *dev)
	if (!pci_priv)
		return NULL;

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

struct iommu_domain *cnss_smmu_get_domain(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->iommu_domain;
}
EXPORT_SYMBOL(cnss_smmu_get_domain);

int cnss_smmu_map(struct device *dev,
		  phys_addr_t paddr, uint32_t *iova_addr, size_t size)
{
@@ -1742,7 +1660,7 @@ int cnss_smmu_map(struct device *dev,
		return -ENOMEM;
	}

	ret = iommu_map(pci_priv->smmu_mapping->domain, iova,
	ret = iommu_map(pci_priv->iommu_domain, iova,
			rounddown(paddr, PAGE_SIZE), len,
			IOMMU_READ | IOMMU_WRITE);
	if (ret) {
@@ -2615,6 +2533,9 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
	struct cnss_pci_data *pci_priv;
	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
	struct resource *res;
	struct device_node *of_node;
	const char *iommu_dma_type;
	u32 addr_win[2];

	cnss_pr_dbg("PCI is probing, vendor ID: 0x%x, device ID: 0x%x\n",
		    id->vendor, pci_dev->device);
@@ -2645,16 +2566,34 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
	if (ret)
		goto unregister_subsys;

	res = platform_get_resource_byname(plat_priv->plat_dev, IORESOURCE_MEM,
					   "smmu_iova_base");
	if (res) {
		if (of_property_read_bool(plat_priv->plat_dev->dev.of_node,
					  "qcom,smmu-s1-enable"))
	of_node = of_parse_phandle(pci_priv->pci_dev->dev.of_node,
				   "qcom,iommu-group", 0);
	if (of_node) {
		pci_priv->iommu_domain =
			iommu_get_domain_for_dev(&pci_dev->dev);
		pci_priv->smmu_mapping.domain = pci_priv->iommu_domain;
		ret = of_property_read_string(of_node, "qcom,iommu-dma",
					      &iommu_dma_type);
		if (!ret) {
			if (!strcmp("fastmap", iommu_dma_type)) {
				cnss_pr_dbg("Enabling SMMU S1 stage\n");
				pci_priv->smmu_s1_enable = true;
			}
		}

		pci_priv->smmu_iova_start = res->start;
		pci_priv->smmu_iova_len = resource_size(res);
		cnss_pr_dbg("smmu_iova_start: %pa, smmu_iova_len: %zu\n",
		ret = of_property_read_u32_array(of_node,
						 "qcom,iommu-dma-addr-pool",
						 addr_win,
						 ARRAY_SIZE(addr_win));
		if (ret) {
			cnss_pr_err("Invalid smmu size window, ret %d\n", ret);
			of_node_put(of_node);
			goto unregister_ramdump;
		}

		pci_priv->smmu_iova_start = addr_win[0];
		pci_priv->smmu_iova_len = addr_win[1];
		cnss_pr_dbg("smmu_iova_start: %pa, smmu_iova_len: 0x%zx\n",
			    &pci_priv->smmu_iova_start,
			    pci_priv->smmu_iova_len);

@@ -2664,22 +2603,17 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
		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",
			cnss_pr_dbg("smmu_iova_ipa_start: %pa, smmu_iova_ipa_len: 0x%zx\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);
			goto unregister_ramdump;
		}
		of_node_put(of_node);
	}

	ret = cnss_reg_pci_event(pci_priv);
	if (ret) {
		cnss_pr_err("Failed to register PCI event, err = %d\n", ret);
		goto deinit_smmu;
		goto unregister_ramdump;
	}

	ret = cnss_pci_enable_bus(pci_priv);
@@ -2733,10 +2667,9 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
	cnss_pci_disable_bus(pci_priv);
dereg_pci_event:
	cnss_dereg_pci_event(pci_priv);
deinit_smmu:
	if (pci_priv->smmu_mapping)
		cnss_pci_deinit_smmu(pci_priv);
unregister_ramdump:
	pci_priv->iommu_domain = NULL;
	pci_priv->smmu_mapping.domain = NULL;
	cnss_unregister_ramdump(plat_priv);
unregister_subsys:
	cnss_unregister_subsys(plat_priv);
@@ -2770,8 +2703,8 @@ static void cnss_pci_remove(struct pci_dev *pci_dev)

	cnss_pci_disable_bus(pci_priv);
	cnss_dereg_pci_event(pci_priv);
	if (pci_priv->smmu_mapping)
		cnss_pci_deinit_smmu(pci_priv);
	pci_priv->iommu_domain = NULL;
	pci_priv->smmu_mapping.domain = NULL;
	cnss_unregister_ramdump(plat_priv);
	cnss_unregister_subsys(plat_priv);
	plat_priv->bus_priv = NULL;
+2 −1
Original line number Diff line number Diff line
@@ -56,7 +56,8 @@ struct cnss_pci_data {
	struct msm_pcie_register_event msm_pci_event;
	atomic_t auto_suspended;
	u8 monitor_wake_intr;
	struct dma_iommu_mapping *smmu_mapping;
	struct dma_iommu_mapping smmu_mapping;
	struct iommu_domain *iommu_domain;
	u8 smmu_s1_enable;
	dma_addr_t smmu_iova_start;
	size_t smmu_iova_len;
+1 −0
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ extern int cnss_get_fw_files_for_target(struct device *dev,
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 struct iommu_domain *cnss_smmu_get_domain(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);