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: 2006100 Change-Id: Ia2b52be55f0b3f23278e1f71106fdb46de1d0fe1 Signed-off-by: Vikram Mulukutla <markivx@codeaurora.org> Signed-off-by: Puja Gupta <pujag@codeaurora.org>
This commit is contained in:
parent
3a7e752617
commit
11bc358160
4 changed files with 80 additions and 23 deletions
|
@ -89,6 +89,13 @@ Optional properties:
|
||||||
- qcom,cx-ipeak-vote: Boolean- Present if we need to set bit 5 of cxip_lm_vote_clear
|
- qcom,cx-ipeak-vote: Boolean- Present if we need to set bit 5 of cxip_lm_vote_clear
|
||||||
during modem shutdown
|
during modem shutdown
|
||||||
|
|
||||||
|
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:
|
Example:
|
||||||
qcom,mss@fc880000 {
|
qcom,mss@fc880000 {
|
||||||
compatible = "qcom,pil-q6v5-mss";
|
compatible = "qcom,pil-q6v5-mss";
|
||||||
|
@ -128,4 +135,9 @@ Example:
|
||||||
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
|
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
|
||||||
qcom,ssctl-instance-id = <12>;
|
qcom,ssctl-instance-id = <12>;
|
||||||
qcom,sysmon-id = <0>;
|
qcom,sysmon-id = <0>;
|
||||||
|
|
||||||
|
qcom,mba-mem@0 {
|
||||||
|
compatible = "qcom,pil-mba-mem";
|
||||||
|
memory-region = <&peripheral_mem>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -332,6 +332,7 @@ int __pil_mss_deinit_image(struct pil_desc *pil, bool err_path)
|
||||||
struct modem_data *drv = dev_get_drvdata(pil->dev);
|
struct modem_data *drv = dev_get_drvdata(pil->dev);
|
||||||
struct q6v5_data *q6_drv = container_of(pil, struct q6v5_data, desc);
|
struct q6v5_data *q6_drv = container_of(pil, struct q6v5_data, desc);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
struct device *dma_dev = drv->mba_mem_dev_fixed ?: &drv->mba_mem_dev;
|
||||||
s32 status;
|
s32 status;
|
||||||
u64 val = is_timeout_disabled() ? 0 : pbl_mba_boot_timeout_ms * 1000;
|
u64 val = is_timeout_disabled() ? 0 : pbl_mba_boot_timeout_ms * 1000;
|
||||||
|
|
||||||
|
@ -360,7 +361,7 @@ int __pil_mss_deinit_image(struct pil_desc *pil, bool err_path)
|
||||||
if (pil->subsys_vmid > 0)
|
if (pil->subsys_vmid > 0)
|
||||||
pil_assign_mem_to_linux(pil, drv->q6->mba_dp_phys,
|
pil_assign_mem_to_linux(pil, drv->q6->mba_dp_phys,
|
||||||
drv->q6->mba_dp_size);
|
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->q6->mba_dp_virt, drv->q6->mba_dp_phys,
|
||||||
&drv->attrs_dma);
|
&drv->attrs_dma);
|
||||||
drv->q6->mba_dp_virt = NULL;
|
drv->q6->mba_dp_virt = NULL;
|
||||||
|
@ -552,6 +553,7 @@ int pil_mss_reset_load_mba(struct pil_desc *pil)
|
||||||
dma_addr_t mba_dp_phys, mba_dp_phys_end;
|
dma_addr_t mba_dp_phys, mba_dp_phys_end;
|
||||||
int ret, count;
|
int ret, count;
|
||||||
const u8 *data;
|
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;
|
fw_name_p = drv->non_elf_image ? fw_name_legacy : fw_name;
|
||||||
ret = request_firmware(&fw, fw_name_p, pil->dev);
|
ret = request_firmware(&fw, fw_name_p, pil->dev);
|
||||||
|
@ -570,11 +572,12 @@ int pil_mss_reset_load_mba(struct pil_desc *pil)
|
||||||
|
|
||||||
drv->mba_dp_size = SZ_1M;
|
drv->mba_dp_size = SZ_1M;
|
||||||
|
|
||||||
arch_setup_dma_ops(&md->mba_mem_dev, 0, 0, NULL, 0);
|
arch_setup_dma_ops(dma_dev, 0, 0, NULL, 0);
|
||||||
|
|
||||||
|
dma_dev->coherent_dma_mask = DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
|
||||||
|
|
||||||
md->mba_mem_dev.coherent_dma_mask =
|
|
||||||
DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
|
|
||||||
init_dma_attrs(&md->attrs_dma);
|
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);
|
dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &md->attrs_dma);
|
||||||
|
|
||||||
ret = request_firmware(&dp_fw, dp_name, pil->dev);
|
ret = request_firmware(&dp_fw, dp_name, pil->dev);
|
||||||
|
@ -591,10 +594,10 @@ int pil_mss_reset_load_mba(struct pil_desc *pil)
|
||||||
drv->mba_dp_size += drv->dp_size;
|
drv->mba_dp_size += drv->dp_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
mba_dp_virt = dma_alloc_attrs(&md->mba_mem_dev, drv->mba_dp_size,
|
mba_dp_virt = dma_alloc_attrs(dma_dev, drv->mba_dp_size, &mba_dp_phys,
|
||||||
&mba_dp_phys, GFP_KERNEL, &md->attrs_dma);
|
GFP_KERNEL, &md->attrs_dma);
|
||||||
if (!mba_dp_virt) {
|
if (!mba_dp_virt) {
|
||||||
dev_err(pil->dev, "%s MBA metadata buffer allocation %zx bytes failed\n",
|
dev_err(pil->dev, "%s MBA/DP buffer allocation %zx bytes failed\n",
|
||||||
__func__, drv->mba_dp_size);
|
__func__, drv->mba_dp_size);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err_invalid_fw;
|
goto err_invalid_fw;
|
||||||
|
@ -651,7 +654,7 @@ err_mss_reset:
|
||||||
pil_assign_mem_to_linux(pil, drv->mba_dp_phys,
|
pil_assign_mem_to_linux(pil, drv->mba_dp_phys,
|
||||||
drv->mba_dp_size);
|
drv->mba_dp_size);
|
||||||
err_mba_data:
|
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);
|
drv->mba_dp_phys, &md->attrs_dma);
|
||||||
err_invalid_fw:
|
err_invalid_fw:
|
||||||
if (dp_fw)
|
if (dp_fw)
|
||||||
|
@ -670,14 +673,16 @@ static int pil_msa_auth_modem_mdt(struct pil_desc *pil, const u8 *metadata,
|
||||||
s32 status;
|
s32 status;
|
||||||
int ret;
|
int ret;
|
||||||
u64 val = is_timeout_disabled() ? 0 : modem_auth_timeout_ms * 1000;
|
u64 val = is_timeout_disabled() ? 0 : modem_auth_timeout_ms * 1000;
|
||||||
|
struct device *dma_dev = drv->mba_mem_dev_fixed ?: &drv->mba_mem_dev;
|
||||||
DEFINE_DMA_ATTRS(attrs);
|
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);
|
dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &attrs);
|
||||||
/* Make metadata physically contiguous and 4K aligned. */
|
/* Make metadata physically contiguous and 4K aligned. */
|
||||||
mdata_virt = dma_alloc_attrs(&drv->mba_mem_dev, size, &mdata_phys,
|
mdata_virt = dma_alloc_attrs(dma_dev, size, &mdata_phys, GFP_KERNEL,
|
||||||
GFP_KERNEL, &attrs);
|
&attrs);
|
||||||
if (!mdata_virt) {
|
if (!mdata_virt) {
|
||||||
dev_err(pil->dev, "%s MBA metadata buffer allocation %zx bytes failed\n",
|
dev_err(pil->dev, "%s MBA metadata buffer allocation %zx bytes failed\n",
|
||||||
__func__, size);
|
__func__, size);
|
||||||
|
@ -694,8 +699,8 @@ static int pil_msa_auth_modem_mdt(struct pil_desc *pil, const u8 *metadata,
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("scm_call to unprotect modem metadata mem failed(rc:%d)\n",
|
pr_err("scm_call to unprotect modem metadata mem failed(rc:%d)\n",
|
||||||
ret);
|
ret);
|
||||||
dma_free_attrs(&drv->mba_mem_dev, size, mdata_virt,
|
dma_free_attrs(dma_dev, size, mdata_virt, mdata_phys,
|
||||||
mdata_phys, &attrs);
|
&attrs);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -721,7 +726,7 @@ static int pil_msa_auth_modem_mdt(struct pil_desc *pil, const u8 *metadata,
|
||||||
if (pil->subsys_vmid > 0)
|
if (pil->subsys_vmid > 0)
|
||||||
pil_assign_mem_to_linux(pil, mdata_phys, ALIGN(size, SZ_4K));
|
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)
|
if (!ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -733,7 +738,7 @@ fail:
|
||||||
if (pil->subsys_vmid > 0)
|
if (pil->subsys_vmid > 0)
|
||||||
pil_assign_mem_to_linux(pil, drv->q6->mba_dp_phys,
|
pil_assign_mem_to_linux(pil, drv->q6->mba_dp_phys,
|
||||||
drv->q6->mba_dp_size);
|
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->q6->mba_dp_virt, drv->q6->mba_dp_phys,
|
||||||
&drv->attrs_dma);
|
&drv->attrs_dma);
|
||||||
drv->q6->mba_dp_virt = NULL;
|
drv->q6->mba_dp_virt = NULL;
|
||||||
|
@ -785,6 +790,7 @@ static int pil_msa_mba_auth(struct pil_desc *pil)
|
||||||
struct modem_data *drv = dev_get_drvdata(pil->dev);
|
struct modem_data *drv = dev_get_drvdata(pil->dev);
|
||||||
struct q6v5_data *q6_drv = container_of(pil, struct q6v5_data, desc);
|
struct q6v5_data *q6_drv = container_of(pil, struct q6v5_data, desc);
|
||||||
int ret;
|
int ret;
|
||||||
|
struct device *dma_dev = drv->mba_mem_dev_fixed ?: &drv->mba_mem_dev;
|
||||||
s32 status;
|
s32 status;
|
||||||
u64 val = is_timeout_disabled() ? 0 : modem_auth_timeout_ms * 1000;
|
u64 val = is_timeout_disabled() ? 0 : modem_auth_timeout_ms * 1000;
|
||||||
|
|
||||||
|
@ -806,9 +812,9 @@ static int pil_msa_mba_auth(struct pil_desc *pil)
|
||||||
pil_assign_mem_to_linux(pil,
|
pil_assign_mem_to_linux(pil,
|
||||||
drv->q6->mba_dp_phys,
|
drv->q6->mba_dp_phys,
|
||||||
drv->q6->mba_dp_size);
|
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_virt, drv->q6->mba_dp_phys,
|
||||||
drv->q6->mba_dp_phys, &drv->attrs_dma);
|
&drv->attrs_dma);
|
||||||
|
|
||||||
drv->q6->mba_dp_virt = NULL;
|
drv->q6->mba_dp_virt = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -32,6 +32,7 @@ struct modem_data {
|
||||||
struct clk *xo;
|
struct clk *xo;
|
||||||
struct pil_desc desc;
|
struct pil_desc desc;
|
||||||
struct device mba_mem_dev;
|
struct device mba_mem_dev;
|
||||||
|
struct device *mba_mem_dev_fixed;
|
||||||
struct dma_attrs attrs_dma;
|
struct dma_attrs attrs_dma;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
|
@ -394,6 +395,11 @@ static int pil_mss_driver_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
init_completion(&drv->stop_ack);
|
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);
|
return pil_subsys_init(drv, pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,6 +413,33 @@ static int pil_mss_driver_exit(struct platform_device *pdev)
|
||||||
return 0;
|
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 const 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[] = {
|
static struct of_device_id mss_match_table[] = {
|
||||||
{ .compatible = "qcom,pil-q6v5-mss" },
|
{ .compatible = "qcom,pil-q6v5-mss" },
|
||||||
{ .compatible = "qcom,pil-q6v55-mss" },
|
{ .compatible = "qcom,pil-q6v55-mss" },
|
||||||
|
@ -426,7 +459,12 @@ static struct platform_driver pil_mss_driver = {
|
||||||
|
|
||||||
static int __init pil_mss_init(void)
|
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);
|
module_init(pil_mss_init);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue