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

Commit e4e84805 authored by Puja Gupta's avatar Puja Gupta
Browse files

soc: qcom: pil: Allow the MBA memory to be dynamic or a carveout



Currently, the MBA is expected to be loadable at any
region in DDR. However, due to limitations in the modem
PBL or MBA image, this is not always possible. Allow
the modem to be loaded in a carved out CMA heap if specified
in device tree. Current memory APIs do not allow the association
of more than one memory region with a device; therefore
allow the existence of an optional sub-device node that
will contain the memory region property for the MBA.

CRs-Fixed: 1007329
Change-Id: Ia2b52be55f0b3f23278e1f71106fdb46de1d0fe1
Signed-off-by: default avatarVikram Mulukutla <markivx@codeaurora.org>
Signed-off-by: default avatarPuja Gupta <pujag@codeaurora.org>
parent 8070c055
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -84,6 +84,13 @@ Optional properties:
- qcom,qdsp6v56-1-10: Boolean- Present if the qdsp version is v56 1.10
- qcom,override-acc-1: Override the default ACC settings with this value if present.

One child node to represent the MBA image may be specified, when the MBA image
needs to be loaded in a specifically carved out memory region.

Required properties:
- compatible: Must be "qcom,pil-mba-mem"
- memory-region: A phandle that points to a reserved memory where the MBA image will be loaded.

Example:
	qcom,mss@fc880000 {
		compatible = "qcom,pil-q6v5-mss";
@@ -123,4 +130,9 @@ Example:
		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
		qcom,ssctl-instance-id = <12>;
		qcom,sysmon-id = <0>;

		qcom,mba-mem@0 {
			compatible = "qcom,pil-mba-mem";
			memory-region = <&peripheral_mem>;
		};
	};
+21 −16
Original line number Diff line number Diff line
@@ -316,6 +316,7 @@ int __pil_mss_deinit_image(struct pil_desc *pil, bool err_path)
	struct modem_data *drv = dev_get_drvdata(pil->dev);
	struct q6v5_data *q6_drv = container_of(pil, struct q6v5_data, desc);
	int ret = 0;
	struct device *dma_dev = drv->mba_mem_dev_fixed ?: &drv->mba_mem_dev;
	s32 status;

	if (err_path) {
@@ -342,7 +343,7 @@ int __pil_mss_deinit_image(struct pil_desc *pil, bool err_path)
		if (pil->subsys_vmid > 0)
			pil_assign_mem_to_linux(pil, drv->q6->mba_dp_phys,
						drv->q6->mba_dp_size);
		dma_free_attrs(&drv->mba_mem_dev, drv->q6->mba_dp_size,
		dma_free_attrs(dma_dev, drv->q6->mba_dp_size,
				drv->q6->mba_dp_virt, drv->q6->mba_dp_phys,
				&drv->attrs_dma);
		drv->q6->mba_dp_virt = NULL;
@@ -533,6 +534,7 @@ int pil_mss_reset_load_mba(struct pil_desc *pil)
	dma_addr_t mba_dp_phys, mba_dp_phys_end;
	int ret, count;
	const u8 *data;
	struct device *dma_dev = md->mba_mem_dev_fixed ?: &md->mba_mem_dev;

	fw_name_p = drv->non_elf_image ? fw_name_legacy : fw_name;
	ret = request_firmware(&fw, fw_name_p, pil->dev);
@@ -550,9 +552,9 @@ int pil_mss_reset_load_mba(struct pil_desc *pil)
	}

	drv->mba_dp_size = SZ_1M;
	md->mba_mem_dev.coherent_dma_mask =
		DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
	dma_dev->coherent_dma_mask = DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
	init_dma_attrs(&md->attrs_dma);
	dma_set_attr(DMA_ATTR_SKIP_ZEROING, &md->attrs_dma);
	dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &md->attrs_dma);

	ret = request_firmware(&dp_fw, dp_name, pil->dev);
@@ -569,8 +571,8 @@ int pil_mss_reset_load_mba(struct pil_desc *pil)
		drv->mba_dp_size += drv->dp_size;
	}

	mba_dp_virt = dma_alloc_attrs(&md->mba_mem_dev, drv->mba_dp_size,
			&mba_dp_phys, GFP_KERNEL, &md->attrs_dma);
	mba_dp_virt = dma_alloc_attrs(dma_dev, drv->mba_dp_size, &mba_dp_phys,
				   GFP_KERNEL, &md->attrs_dma);
	if (!mba_dp_virt) {
		dev_err(pil->dev, "%s MBA metadata buffer allocation %zx bytes failed\n",
				 __func__, drv->mba_dp_size);
@@ -628,7 +630,7 @@ err_mss_reset:
		pil_assign_mem_to_linux(pil, drv->mba_dp_phys,
							drv->mba_dp_size);
err_mba_data:
	dma_free_attrs(&md->mba_mem_dev, drv->mba_dp_size, drv->mba_dp_virt,
	dma_free_attrs(dma_dev, drv->mba_dp_size, drv->mba_dp_virt,
				drv->mba_dp_phys, &md->attrs_dma);
err_invalid_fw:
	if (dp_fw)
@@ -646,14 +648,16 @@ static int pil_msa_auth_modem_mdt(struct pil_desc *pil, const u8 *metadata,
	dma_addr_t mdata_phys;
	s32 status;
	int ret;
	struct device *dma_dev = drv->mba_mem_dev_fixed ?: &drv->mba_mem_dev;
	DEFINE_DMA_ATTRS(attrs);

	drv->mba_mem_dev.coherent_dma_mask =
		DMA_BIT_MASK(sizeof(dma_addr_t) * 8);

	dma_dev->coherent_dma_mask = DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
	dma_set_attr(DMA_ATTR_SKIP_ZEROING, &attrs);
	dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &attrs);
	/* Make metadata physically contiguous and 4K aligned. */
	mdata_virt = dma_alloc_attrs(&drv->mba_mem_dev, size, &mdata_phys,
					GFP_KERNEL, &attrs);
	mdata_virt = dma_alloc_attrs(dma_dev, size, &mdata_phys, GFP_KERNEL,
				     &attrs);
	if (!mdata_virt) {
		dev_err(pil->dev, "%s MBA metadata buffer allocation %zx bytes failed\n",
			 __func__, size);
@@ -669,7 +673,7 @@ static int pil_msa_auth_modem_mdt(struct pil_desc *pil, const u8 *metadata,
							ALIGN(size, SZ_4K));
		if (ret) {
			pr_err("scm_call to unprotect modem metadata mem failed\n");
			dma_free_attrs(&drv->mba_mem_dev, size, mdata_virt,
			dma_free_attrs(dma_dev, size, mdata_virt,
							mdata_phys, &attrs);
			goto fail;
		}
@@ -695,7 +699,7 @@ static int pil_msa_auth_modem_mdt(struct pil_desc *pil, const u8 *metadata,
	if (pil->subsys_vmid > 0)
		pil_assign_mem_to_linux(pil, mdata_phys, ALIGN(size, SZ_4K));

	dma_free_attrs(&drv->mba_mem_dev, size, mdata_virt, mdata_phys, &attrs);
	dma_free_attrs(dma_dev, size, mdata_virt, mdata_phys, &attrs);

	if (!ret)
		return ret;
@@ -707,7 +711,7 @@ fail:
		if (pil->subsys_vmid > 0)
			pil_assign_mem_to_linux(pil, drv->q6->mba_dp_phys,
						drv->q6->mba_dp_size);
		dma_free_attrs(&drv->mba_mem_dev, drv->q6->mba_dp_size,
		dma_free_attrs(dma_dev, drv->q6->mba_dp_size,
				drv->q6->mba_dp_virt, drv->q6->mba_dp_phys,
				&drv->attrs_dma);
		drv->q6->mba_dp_virt = NULL;
@@ -759,6 +763,7 @@ static int pil_msa_mba_auth(struct pil_desc *pil)
	struct modem_data *drv = dev_get_drvdata(pil->dev);
	struct q6v5_data *q6_drv = container_of(pil, struct q6v5_data, desc);
	int ret;
	struct device *dma_dev = drv->mba_mem_dev_fixed ?: &drv->mba_mem_dev;
	s32 status;

	/* Wait for all segments to be authenticated or an error to occur */
@@ -779,9 +784,9 @@ static int pil_msa_mba_auth(struct pil_desc *pil)
				pil_assign_mem_to_linux(pil,
					drv->q6->mba_dp_phys,
					drv->q6->mba_dp_size);
			dma_free_attrs(&drv->mba_mem_dev, drv->q6->mba_dp_size,
					drv->q6->mba_dp_virt,
					drv->q6->mba_dp_phys, &drv->attrs_dma);
			dma_free_attrs(dma_dev, drv->q6->mba_dp_size,
				drv->q6->mba_dp_virt, drv->q6->mba_dp_phys,
				&drv->attrs_dma);

			drv->q6->mba_dp_virt = NULL;
		}
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ struct modem_data {
	struct clk *xo;
	struct pil_desc desc;
	struct device mba_mem_dev;
	struct device *mba_mem_dev_fixed;
	struct dma_attrs attrs_dma;
};

+39 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/ioport.h>
@@ -374,6 +375,11 @@ static int pil_mss_driver_probe(struct platform_device *pdev)
	}
	init_completion(&drv->stop_ack);

	/* Probe the MBA mem device if present */
	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
	if (ret)
		return ret;

	return pil_subsys_init(drv, pdev);
}

@@ -387,6 +393,33 @@ static int pil_mss_driver_exit(struct platform_device *pdev)
	return 0;
}

static int pil_mba_mem_driver_probe(struct platform_device *pdev)
{
	struct modem_data *drv;

	if (!pdev->dev.parent) {
		pr_err("No parent found.\n");
		return -EINVAL;
	}
	drv = dev_get_drvdata(pdev->dev.parent);
	drv->mba_mem_dev_fixed = &pdev->dev;
	return 0;
}

static struct of_device_id mba_mem_match_table[] = {
	{ .compatible = "qcom,pil-mba-mem" },
	{}
};

static struct platform_driver pil_mba_mem_driver = {
	.probe = pil_mba_mem_driver_probe,
	.driver = {
		.name = "pil-mba-mem",
		.of_match_table = mba_mem_match_table,
		.owner = THIS_MODULE,
	},
};

static struct of_device_id mss_match_table[] = {
	{ .compatible = "qcom,pil-q6v5-mss" },
	{ .compatible = "qcom,pil-q6v55-mss" },
@@ -406,7 +439,12 @@ static struct platform_driver pil_mss_driver = {

static int __init pil_mss_init(void)
{
	return platform_driver_register(&pil_mss_driver);
	int ret;

	ret = platform_driver_register(&pil_mba_mem_driver);
	if (!ret)
		ret = platform_driver_register(&pil_mss_driver);
	return ret;
}
module_init(pil_mss_init);