mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 21:33:00 +00:00
remoteproc updates for v6.11
The maximum amount of DDR memory used by the Mediatek MT8188/MT8195 SCP is increased, to handle new use cases. Handling of optional L1TCM memory is made actually optional. An optimization is introduced to only clear the unused portion of IPI shared buffers, rather than the entire buffer before writing the message. Detection for IPC-only mode in the TI K3 DSP remoteproc driver is corrected. The loglevel of a debug print in the same is lowered from error. Support for attaching to an running remote processor is added to the Xilinx R5F. An in-kernel implementation of the Qualcomm "protected domain mapper" (aka service registry) service is introduced, to remove the dependency on a userspace implementation to detect when the battery monitor and USB Type-C port manager becomes available. This is then integrated with the Qualcomm remoteproc driver. The Qualcomm PAS remoteproc driver gains support for attempting to bust hwspinlocks held by the remote processor when it crashed/stopped. The TI OMAP remoteproc driver is transitioned to use devres helpers for various forms of allocations. Parsing of memory-regions in the i.MX remoteproc driver is improved to avoid a NULL pointer dereference if the phandle reference is empty. of_node reference counting is corrected in the same. -----BEGIN PGP SIGNATURE----- iQJJBAABCAAzFiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmaf9qkVHGFuZGVyc3Nv bkBrZXJuZWwub3JnAAoJEAsfOT8Nma3F7DoQAK6mOFG77jDmRHPwJzFIXmIc2pt5 QlyvoXFQU3tZfUyPgC6ZGuD+DlHeUQdD2cWFUqQhKpp6t3zbwqDec/FuW8CKTFuo Djg1W1gcBpntVrjsoCytJRQJrlErGU+fjeKFkJTX16xLV0sM5I01kAU64yua3JgB CjxlvrDJpCSLxy5KJ2Ieqw5B5xaMcWgrktKegOlrKe7JkveT7I1DUA5YmvZ0ceW1 v9fjhHkn1uqPxhbLk0WfF7yl8kRVnLFDDQIpZANLTLSVOPLw4B9OdNy7L8ZJ/oYU Oal04W6FOaT0BaExnerck/FxsV9EXTeTjFN7pUSnhtwvvjim1icfFG6N01zCm2Lq oMkJ8pE3VbHYKXImbxQHcExOvkbRGxSZ6FJshB8RR7MLE9iMZEyhxaCRnwejRowy FOE3/z70wzEMVDZaDdwCVfjIuiWrvdrZnnjqwvVJaLZrG8qegg1xfCWqqNZ3q3Eh rZDWYX5Aja3L528VgrFC7yHgQZDJCITuuopo6CvJEMwwvL6IQP9DqsYX9NAXFC8A zE1rlnjP30xh/eR+mIWNr8AIpkVjdh7BylqQXAr8eLBaV7FtL+PYNBMGTo19DYs9 +PVN8ByRuxbMJAPxNq/f4czzsByx4TTndmx5ng7OdRVMVKeaRL30P5wGxaSUuWEQ Jq3lC2n9oETXfgMv =b4Do -----END PGP SIGNATURE----- Merge tag 'rproc-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux Pull remoteproc updates from Bjorn Andersson: - The maximum amount of DDR memory used by the Mediatek MT8188/MT8195 SCP is increased to handle new use cases. Handling of optional L1TCM memory is made actually optional. - An optimization is introduced to only clear the unused portion of IPI shared buffers, rather than the entire buffer before writing the message. - Detection for IPC-only mode in the TI K3 DSP remoteproc driver is corrected. The loglevel of a debug print in the same is lowered from error. - Support for attaching to an running remote processor is added to the Xilinx R5F. - An in-kernel implementation of the Qualcomm "protected domain mapper" (aka service registry) service is introduced, to remove the dependency on a userspace implementation to detect when the battery monitor and USB Type-C port manager becomes available. This is then integrated with the Qualcomm remoteproc driver. - The Qualcomm PAS remoteproc driver gains support for attempting to bust hwspinlocks held by the remote processor when it crashed/stopped. - The TI OMAP remoteproc driver is transitioned to use devres helpers for various forms of allocations. - Parsing of memory-regions in the i.MX remoteproc driver is improved to avoid a NULL pointer dereference if the phandle reference is empty. of_node reference counting is corrected in the same. * tag 'rproc-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux: remoteproc: mediatek: Increase MT8188/MT8195 SCP core0 DRAM size remoteproc: k3-dsp: Fix log levels where appropriate remoteproc: xlnx: Add attach detach support remoteproc: qcom: select AUXILIARY_BUS remoteproc: k3-r5: Fix IPC-only mode detection remoteproc: mediatek: Don't attempt to remap l1tcm memory if missing remoteproc: qcom: enable in-kernel PD mapper dt-bindings: remoteproc: imx_rproc: Add minItems for power-domain remoteproc: imx_rproc: Fix refcount mistake in imx_rproc_addr_init remoteproc: omap: Use devm_rproc_add() helper remoteproc: omap: Use devm action to release reserved memory remoteproc: omap: Use devm_rproc_alloc() helper remoteproc: imx_rproc: Skip over memory region when node value is NULL dt-bindings: remoteproc: k3-dsp: Correct optional sram properties for AM62A SoCs remoteproc: qcom_q6v5_pas: Add hwspinlock bust on stop soc: qcom: smem: Add qcom_smem_bust_hwspin_lock_by_host() remoteproc: mediatek: Zero out only remaining bytes of IPI buffer
This commit is contained in:
commit
60c6119cad
@ -59,6 +59,7 @@ properties:
|
||||
maxItems: 32
|
||||
|
||||
power-domains:
|
||||
minItems: 2
|
||||
maxItems: 8
|
||||
|
||||
fsl,auto-boot:
|
||||
@ -99,6 +100,20 @@ allOf:
|
||||
properties:
|
||||
fsl,iomuxc-gpr: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- fsl,imx8qxp-cm4
|
||||
- fsl,imx8qm-cm4
|
||||
then:
|
||||
required:
|
||||
- power-domains
|
||||
else:
|
||||
properties:
|
||||
power-domains: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -25,9 +25,6 @@ description: |
|
||||
host processor (Arm CorePac) to perform the device management of the remote
|
||||
processor and to communicate with the remote processor.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/arm/keystone/ti,k3-sci-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
@ -89,41 +86,57 @@ properties:
|
||||
should be defined as per the generic bindings in,
|
||||
Documentation/devicetree/bindings/sram/sram.yaml
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,j721e-c66-dsp
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: Address and Size of the L2 SRAM internal memory region
|
||||
- description: Address and Size of the L1 PRAM internal memory region
|
||||
- description: Address and Size of the L1 DRAM internal memory region
|
||||
reg-names:
|
||||
items:
|
||||
- const: l2sram
|
||||
- const: l1pram
|
||||
- const: l1dram
|
||||
else:
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,am62a-c7xv-dsp
|
||||
- ti,j721e-c71-dsp
|
||||
- ti,j721s2-c71-dsp
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: Address and Size of the L2 SRAM internal memory region
|
||||
- description: Address and Size of the L1 DRAM internal memory region
|
||||
reg-names:
|
||||
items:
|
||||
- const: l2sram
|
||||
- const: l1dram
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,j721e-c66-dsp
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: Address and Size of the L2 SRAM internal memory region
|
||||
- description: Address and Size of the L1 PRAM internal memory region
|
||||
- description: Address and Size of the L1 DRAM internal memory region
|
||||
reg-names:
|
||||
items:
|
||||
- const: l2sram
|
||||
- const: l1pram
|
||||
- const: l1dram
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,j721e-c71-dsp
|
||||
- ti,j721s2-c71-dsp
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: Address and Size of the L2 SRAM internal memory region
|
||||
- description: Address and Size of the L1 DRAM internal memory region
|
||||
reg-names:
|
||||
items:
|
||||
- const: l2sram
|
||||
- const: l1dram
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,am62a-c7xv-dsp
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: Address and Size of the L2 SRAM internal memory region
|
||||
reg-names:
|
||||
items:
|
||||
- const: l2sram
|
||||
|
||||
- $ref: /schemas/arm/keystone/ti,k3-sci-common.yaml#
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -166,6 +166,7 @@ config QCOM_PIL_INFO
|
||||
|
||||
config QCOM_RPROC_COMMON
|
||||
tristate
|
||||
select AUXILIARY_BUS
|
||||
|
||||
config QCOM_Q6V5_COMMON
|
||||
tristate
|
||||
|
@ -726,31 +726,37 @@ static int imx_rproc_addr_init(struct imx_rproc *priv,
|
||||
struct resource res;
|
||||
|
||||
node = of_parse_phandle(np, "memory-region", a);
|
||||
if (!node)
|
||||
continue;
|
||||
/* Not map vdevbuffer, vdevring region */
|
||||
if (!strncmp(node->name, "vdev", strlen("vdev"))) {
|
||||
of_node_put(node);
|
||||
continue;
|
||||
}
|
||||
err = of_address_to_resource(node, 0, &res);
|
||||
of_node_put(node);
|
||||
if (err) {
|
||||
dev_err(dev, "unable to resolve memory region\n");
|
||||
of_node_put(node);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (b >= IMX_RPROC_MEM_MAX)
|
||||
if (b >= IMX_RPROC_MEM_MAX) {
|
||||
of_node_put(node);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not use resource version, because we might share region */
|
||||
priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, res.start, resource_size(&res));
|
||||
if (!priv->mem[b].cpu_addr) {
|
||||
dev_err(dev, "failed to remap %pr\n", &res);
|
||||
of_node_put(node);
|
||||
return -ENOMEM;
|
||||
}
|
||||
priv->mem[b].sys_addr = res.start;
|
||||
priv->mem[b].size = resource_size(&res);
|
||||
if (!strcmp(node->name, "rsc-table"))
|
||||
priv->rsc_table = priv->mem[b].cpu_addr;
|
||||
of_node_put(node);
|
||||
b++;
|
||||
}
|
||||
|
||||
|
@ -117,8 +117,8 @@ static void scp_ipi_handler(struct mtk_scp *scp)
|
||||
return;
|
||||
}
|
||||
|
||||
memset(scp->share_buf, 0, scp_sizes->ipi_share_buffer_size);
|
||||
memcpy_fromio(scp->share_buf, &rcv_obj->share_buf, len);
|
||||
memset(&scp->share_buf[len], 0, scp_sizes->ipi_share_buffer_size - len);
|
||||
handler(scp->share_buf, len, ipi_desc[id].priv);
|
||||
scp_ipi_unlock(scp, id);
|
||||
|
||||
@ -1344,14 +1344,12 @@ static int scp_probe(struct platform_device *pdev)
|
||||
|
||||
/* l1tcm is an optional memory region */
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "l1tcm");
|
||||
scp_cluster->l1tcm_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(scp_cluster->l1tcm_base)) {
|
||||
ret = PTR_ERR(scp_cluster->l1tcm_base);
|
||||
if (ret != -EINVAL)
|
||||
return dev_err_probe(dev, ret, "Failed to map l1tcm memory\n");
|
||||
if (res) {
|
||||
scp_cluster->l1tcm_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(scp_cluster->l1tcm_base))
|
||||
return dev_err_probe(dev, PTR_ERR(scp_cluster->l1tcm_base),
|
||||
"Failed to map l1tcm memory\n");
|
||||
|
||||
scp_cluster->l1tcm_base = NULL;
|
||||
} else {
|
||||
scp_cluster->l1tcm_size = resource_size(res);
|
||||
scp_cluster->l1tcm_phys = res->start;
|
||||
}
|
||||
@ -1390,7 +1388,7 @@ static const struct mtk_scp_sizes_data default_scp_sizes = {
|
||||
};
|
||||
|
||||
static const struct mtk_scp_sizes_data mt8188_scp_sizes = {
|
||||
.max_dram_size = 0x500000,
|
||||
.max_dram_size = 0x800000,
|
||||
.ipi_share_buffer_size = 600,
|
||||
};
|
||||
|
||||
@ -1399,6 +1397,11 @@ static const struct mtk_scp_sizes_data mt8188_scp_c1_sizes = {
|
||||
.ipi_share_buffer_size = 600,
|
||||
};
|
||||
|
||||
static const struct mtk_scp_sizes_data mt8195_scp_sizes = {
|
||||
.max_dram_size = 0x800000,
|
||||
.ipi_share_buffer_size = 288,
|
||||
};
|
||||
|
||||
static const struct mtk_scp_of_data mt8183_of_data = {
|
||||
.scp_clk_get = mt8183_scp_clk_get,
|
||||
.scp_before_load = mt8183_scp_before_load,
|
||||
@ -1476,7 +1479,7 @@ static const struct mtk_scp_of_data mt8195_of_data = {
|
||||
.scp_da_to_va = mt8192_scp_da_to_va,
|
||||
.host_to_scp_reg = MT8192_GIPC_IN_SET,
|
||||
.host_to_scp_int_bit = MT8192_HOST_IPC_INT_BIT,
|
||||
.scp_sizes = &default_scp_sizes,
|
||||
.scp_sizes = &mt8195_scp_sizes,
|
||||
};
|
||||
|
||||
static const struct mtk_scp_of_data mt8195_of_data_c1 = {
|
||||
|
@ -1277,6 +1277,13 @@ static int omap_rproc_of_get_timers(struct platform_device *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap_rproc_mem_release(void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
|
||||
of_reserved_mem_device_release(dev);
|
||||
}
|
||||
|
||||
static int omap_rproc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
@ -1305,8 +1312,8 @@ static int omap_rproc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev), &omap_rproc_ops,
|
||||
firmware, sizeof(*oproc));
|
||||
rproc = devm_rproc_alloc(&pdev->dev, dev_name(&pdev->dev), &omap_rproc_ops,
|
||||
firmware, sizeof(*oproc));
|
||||
if (!rproc)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1318,15 +1325,15 @@ static int omap_rproc_probe(struct platform_device *pdev)
|
||||
|
||||
ret = omap_rproc_of_get_internal_memories(pdev, rproc);
|
||||
if (ret)
|
||||
goto free_rproc;
|
||||
return ret;
|
||||
|
||||
ret = omap_rproc_get_boot_data(pdev, rproc);
|
||||
if (ret)
|
||||
goto free_rproc;
|
||||
return ret;
|
||||
|
||||
ret = omap_rproc_of_get_timers(pdev, rproc);
|
||||
if (ret)
|
||||
goto free_rproc;
|
||||
return ret;
|
||||
|
||||
init_completion(&oproc->pm_comp);
|
||||
oproc->autosuspend_delay = DEFAULT_AUTOSUSPEND_DELAY;
|
||||
@ -1337,10 +1344,8 @@ static int omap_rproc_probe(struct platform_device *pdev)
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, oproc->autosuspend_delay);
|
||||
|
||||
oproc->fck = devm_clk_get(&pdev->dev, 0);
|
||||
if (IS_ERR(oproc->fck)) {
|
||||
ret = PTR_ERR(oproc->fck);
|
||||
goto free_rproc;
|
||||
}
|
||||
if (IS_ERR(oproc->fck))
|
||||
return PTR_ERR(oproc->fck);
|
||||
|
||||
ret = of_reserved_mem_device_init(&pdev->dev);
|
||||
if (ret) {
|
||||
@ -1348,29 +1353,17 @@ static int omap_rproc_probe(struct platform_device *pdev)
|
||||
dev_warn(&pdev->dev, "Typically this should be provided,\n");
|
||||
dev_warn(&pdev->dev, "only omit if you know what you are doing.\n");
|
||||
}
|
||||
ret = devm_add_action_or_reset(&pdev->dev, omap_rproc_mem_release, &pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, rproc);
|
||||
|
||||
ret = rproc_add(rproc);
|
||||
ret = devm_rproc_add(&pdev->dev, rproc);
|
||||
if (ret)
|
||||
goto release_mem;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
release_mem:
|
||||
of_reserved_mem_device_release(&pdev->dev);
|
||||
free_rproc:
|
||||
rproc_free(rproc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void omap_rproc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rproc *rproc = platform_get_drvdata(pdev);
|
||||
|
||||
rproc_del(rproc);
|
||||
rproc_free(rproc);
|
||||
of_reserved_mem_device_release(&pdev->dev);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops omap_rproc_pm_ops = {
|
||||
@ -1381,7 +1374,6 @@ static const struct dev_pm_ops omap_rproc_pm_ops = {
|
||||
|
||||
static struct platform_driver omap_rproc_driver = {
|
||||
.probe = omap_rproc_probe,
|
||||
.remove_new = omap_rproc_remove,
|
||||
.driver = {
|
||||
.name = "omap-rproc",
|
||||
.pm = &omap_rproc_pm_ops,
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/remoteproc.h>
|
||||
#include <linux/remoteproc/qcom_rproc.h>
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/rpmsg/qcom_glink.h>
|
||||
#include <linux/rpmsg/qcom_smd.h>
|
||||
#include <linux/slab.h>
|
||||
@ -25,6 +26,7 @@
|
||||
#define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
|
||||
#define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
|
||||
#define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
|
||||
#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
|
||||
|
||||
#define MAX_NUM_OF_SS 10
|
||||
#define MAX_REGION_NAME_LENGTH 16
|
||||
@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
|
||||
|
||||
static void pdm_dev_release(struct device *dev)
|
||||
{
|
||||
struct auxiliary_device *adev = to_auxiliary_dev(dev);
|
||||
|
||||
kfree(adev);
|
||||
}
|
||||
|
||||
static int pdm_notify_prepare(struct rproc_subdev *subdev)
|
||||
{
|
||||
struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
|
||||
struct auxiliary_device *adev;
|
||||
int ret;
|
||||
|
||||
adev = kzalloc(sizeof(*adev), GFP_KERNEL);
|
||||
if (!adev)
|
||||
return -ENOMEM;
|
||||
|
||||
adev->dev.parent = pdm->dev;
|
||||
adev->dev.release = pdm_dev_release;
|
||||
adev->name = "pd-mapper";
|
||||
adev->id = pdm->index;
|
||||
|
||||
ret = auxiliary_device_init(adev);
|
||||
if (ret) {
|
||||
kfree(adev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = auxiliary_device_add(adev);
|
||||
if (ret) {
|
||||
auxiliary_device_uninit(adev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pdm->adev = adev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void pdm_notify_unprepare(struct rproc_subdev *subdev)
|
||||
{
|
||||
struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
|
||||
|
||||
if (!pdm->adev)
|
||||
return;
|
||||
|
||||
auxiliary_device_delete(pdm->adev);
|
||||
auxiliary_device_uninit(pdm->adev);
|
||||
pdm->adev = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_add_pdm_subdev() - register PD Mapper subdevice
|
||||
* @rproc: rproc handle
|
||||
* @pdm: PDM subdevice handle
|
||||
*
|
||||
* Register @pdm so that Protection Device mapper service is started when the
|
||||
* DSP is started too.
|
||||
*/
|
||||
void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
|
||||
{
|
||||
pdm->dev = &rproc->dev;
|
||||
pdm->index = rproc->index;
|
||||
|
||||
pdm->subdev.prepare = pdm_notify_prepare;
|
||||
pdm->subdev.unprepare = pdm_notify_unprepare;
|
||||
|
||||
rproc_add_subdev(rproc, &pdm->subdev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
|
||||
|
||||
/**
|
||||
* qcom_remove_pdm_subdev() - remove PD Mapper subdevice
|
||||
* @rproc: rproc handle
|
||||
* @pdm: PDM subdevice handle
|
||||
*
|
||||
* Remove the PD Mapper subdevice.
|
||||
*/
|
||||
void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
|
||||
{
|
||||
rproc_remove_subdev(rproc, &pdm->subdev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
|
||||
|
||||
MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
|
||||
struct qcom_ssr_subsystem *info;
|
||||
};
|
||||
|
||||
struct qcom_rproc_pdm {
|
||||
struct rproc_subdev subdev;
|
||||
struct device *dev;
|
||||
int index;
|
||||
struct auxiliary_device *adev;
|
||||
};
|
||||
|
||||
void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
|
||||
void (*rproc_dumpfn_t)(struct rproc *rproc,
|
||||
struct rproc_dump_segment *segment, void *dest, size_t offset,
|
||||
@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
|
||||
const char *ssr_name);
|
||||
void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
|
||||
|
||||
void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
|
||||
void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_SYSMON)
|
||||
struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
|
||||
const char *name,
|
||||
|
@ -112,6 +112,7 @@ struct qcom_adsp {
|
||||
struct dev_pm_domain_list *pd_list;
|
||||
|
||||
struct qcom_rproc_glink glink_subdev;
|
||||
struct qcom_rproc_pdm pdm_subdev;
|
||||
struct qcom_rproc_ssr ssr_subdev;
|
||||
struct qcom_sysmon *sysmon;
|
||||
|
||||
@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
|
||||
goto disable_pm;
|
||||
|
||||
qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
|
||||
qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
|
||||
qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
|
||||
adsp->sysmon = qcom_add_sysmon_subdev(rproc,
|
||||
desc->sysmon_name,
|
||||
@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
|
||||
|
||||
qcom_q6v5_deinit(&adsp->q6v5);
|
||||
qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
|
||||
qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
|
||||
qcom_remove_sysmon_subdev(adsp->sysmon);
|
||||
qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
|
||||
qcom_rproc_pds_detach(adsp);
|
||||
|
@ -228,6 +228,7 @@ struct q6v5 {
|
||||
|
||||
struct qcom_rproc_glink glink_subdev;
|
||||
struct qcom_rproc_subdev smd_subdev;
|
||||
struct qcom_rproc_pdm pdm_subdev;
|
||||
struct qcom_rproc_ssr ssr_subdev;
|
||||
struct qcom_sysmon *sysmon;
|
||||
struct platform_device *bam_dmux;
|
||||
@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
|
||||
qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
|
||||
qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
|
||||
qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
|
||||
qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
|
||||
qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
|
||||
qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
|
||||
if (IS_ERR(qproc->sysmon)) {
|
||||
@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
|
||||
qcom_q6v5_deinit(&qproc->q6v5);
|
||||
qcom_remove_sysmon_subdev(qproc->sysmon);
|
||||
qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
|
||||
qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
|
||||
qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
|
||||
qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
|
||||
|
||||
|
@ -52,6 +52,7 @@ struct adsp_data {
|
||||
const char *ssr_name;
|
||||
const char *sysmon_name;
|
||||
int ssctl_id;
|
||||
unsigned int smem_host_id;
|
||||
|
||||
int region_assign_idx;
|
||||
int region_assign_count;
|
||||
@ -81,6 +82,7 @@ struct qcom_adsp {
|
||||
int lite_pas_id;
|
||||
unsigned int minidump_id;
|
||||
int crash_reason_smem;
|
||||
unsigned int smem_host_id;
|
||||
bool decrypt_shutdown;
|
||||
const char *info_name;
|
||||
|
||||
@ -109,6 +111,7 @@ struct qcom_adsp {
|
||||
|
||||
struct qcom_rproc_glink glink_subdev;
|
||||
struct qcom_rproc_subdev smd_subdev;
|
||||
struct qcom_rproc_pdm pdm_subdev;
|
||||
struct qcom_rproc_ssr ssr_subdev;
|
||||
struct qcom_sysmon *sysmon;
|
||||
|
||||
@ -399,6 +402,9 @@ static int adsp_stop(struct rproc *rproc)
|
||||
if (handover)
|
||||
qcom_pas_handover(&adsp->q6v5);
|
||||
|
||||
if (adsp->smem_host_id)
|
||||
ret = qcom_smem_bust_hwspin_lock_by_host(adsp->smem_host_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -727,6 +733,7 @@ static int adsp_probe(struct platform_device *pdev)
|
||||
adsp->pas_id = desc->pas_id;
|
||||
adsp->lite_pas_id = desc->lite_pas_id;
|
||||
adsp->info_name = desc->sysmon_name;
|
||||
adsp->smem_host_id = desc->smem_host_id;
|
||||
adsp->decrypt_shutdown = desc->decrypt_shutdown;
|
||||
adsp->region_assign_idx = desc->region_assign_idx;
|
||||
adsp->region_assign_count = min_t(int, MAX_ASSIGN_COUNT, desc->region_assign_count);
|
||||
@ -771,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
|
||||
|
||||
qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
|
||||
qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
|
||||
qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
|
||||
adsp->sysmon = qcom_add_sysmon_subdev(rproc,
|
||||
desc->sysmon_name,
|
||||
desc->ssctl_id);
|
||||
@ -805,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
|
||||
qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
|
||||
qcom_remove_sysmon_subdev(adsp->sysmon);
|
||||
qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
|
||||
qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
|
||||
qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
|
||||
adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
|
||||
device_init_wakeup(adsp->dev, false);
|
||||
@ -1196,6 +1205,7 @@ static const struct adsp_data sm8550_adsp_resource = {
|
||||
.ssr_name = "lpass",
|
||||
.sysmon_name = "adsp",
|
||||
.ssctl_id = 0x14,
|
||||
.smem_host_id = 2,
|
||||
};
|
||||
|
||||
static const struct adsp_data sm8550_cdsp_resource = {
|
||||
@ -1216,6 +1226,7 @@ static const struct adsp_data sm8550_cdsp_resource = {
|
||||
.ssr_name = "cdsp",
|
||||
.sysmon_name = "cdsp",
|
||||
.ssctl_id = 0x17,
|
||||
.smem_host_id = 5,
|
||||
};
|
||||
|
||||
static const struct adsp_data sm8550_mpss_resource = {
|
||||
@ -1236,6 +1247,7 @@ static const struct adsp_data sm8550_mpss_resource = {
|
||||
.ssr_name = "mpss",
|
||||
.sysmon_name = "modem",
|
||||
.ssctl_id = 0x12,
|
||||
.smem_host_id = 1,
|
||||
.region_assign_idx = 2,
|
||||
.region_assign_count = 1,
|
||||
.region_assign_vmid = QCOM_SCM_VMID_MSS_MSA,
|
||||
@ -1275,6 +1287,7 @@ static const struct adsp_data sm8650_cdsp_resource = {
|
||||
.ssr_name = "cdsp",
|
||||
.sysmon_name = "cdsp",
|
||||
.ssctl_id = 0x17,
|
||||
.smem_host_id = 5,
|
||||
.region_assign_idx = 2,
|
||||
.region_assign_count = 1,
|
||||
.region_assign_shared = true,
|
||||
@ -1299,6 +1312,7 @@ static const struct adsp_data sm8650_mpss_resource = {
|
||||
.ssr_name = "mpss",
|
||||
.sysmon_name = "modem",
|
||||
.ssctl_id = 0x12,
|
||||
.smem_host_id = 1,
|
||||
.region_assign_idx = 2,
|
||||
.region_assign_count = 3,
|
||||
.region_assign_vmid = QCOM_SCM_VMID_MSS_MSA,
|
||||
|
@ -148,6 +148,7 @@ struct q6v5_wcss {
|
||||
bool requires_force_stop;
|
||||
|
||||
struct qcom_rproc_glink glink_subdev;
|
||||
struct qcom_rproc_pdm pdm_subdev;
|
||||
struct qcom_rproc_ssr ssr_subdev;
|
||||
};
|
||||
|
||||
@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
|
||||
qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
|
||||
qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
|
||||
qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
|
||||
|
||||
if (desc->ssctl_id)
|
||||
@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
|
||||
struct q6v5_wcss *wcss = rproc->priv;
|
||||
|
||||
qcom_q6v5_deinit(&wcss->q6v5);
|
||||
qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
|
||||
rproc_del(rproc);
|
||||
}
|
||||
|
||||
|
@ -327,7 +327,7 @@ static int k3_dsp_rproc_start(struct rproc *rproc)
|
||||
goto put_mbox;
|
||||
}
|
||||
|
||||
dev_err(dev, "booting DSP core using boot addr = 0x%x\n", boot_addr);
|
||||
dev_dbg(dev, "booting DSP core using boot addr = 0x%x\n", boot_addr);
|
||||
ret = ti_sci_proc_set_config(kproc->tsp, boot_addr, 0, 0);
|
||||
if (ret)
|
||||
goto put_mbox;
|
||||
|
@ -1144,6 +1144,7 @@ static int k3_r5_rproc_configure_mode(struct k3_r5_rproc *kproc)
|
||||
u32 atcm_enable, btcm_enable, loczrama;
|
||||
struct k3_r5_core *core0;
|
||||
enum cluster_mode mode = cluster->mode;
|
||||
int reset_ctrl_status;
|
||||
int ret;
|
||||
|
||||
core0 = list_first_entry(&cluster->cores, struct k3_r5_core, elem);
|
||||
@ -1160,11 +1161,11 @@ static int k3_r5_rproc_configure_mode(struct k3_r5_rproc *kproc)
|
||||
r_state, c_state);
|
||||
}
|
||||
|
||||
ret = reset_control_status(core->reset);
|
||||
if (ret < 0) {
|
||||
reset_ctrl_status = reset_control_status(core->reset);
|
||||
if (reset_ctrl_status < 0) {
|
||||
dev_err(cdev, "failed to get initial local reset status, ret = %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
reset_ctrl_status);
|
||||
return reset_ctrl_status;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1199,7 +1200,7 @@ static int k3_r5_rproc_configure_mode(struct k3_r5_rproc *kproc)
|
||||
* irrelevant if module reset is asserted (POR value has local reset
|
||||
* deasserted), and is deemed as remoteproc mode
|
||||
*/
|
||||
if (c_state && !ret && !halted) {
|
||||
if (c_state && !reset_ctrl_status && !halted) {
|
||||
dev_info(cdev, "configured R5F for IPC-only mode\n");
|
||||
kproc->rproc->state = RPROC_DETACHED;
|
||||
ret = 1;
|
||||
@ -1217,7 +1218,7 @@ static int k3_r5_rproc_configure_mode(struct k3_r5_rproc *kproc)
|
||||
ret = 0;
|
||||
} else {
|
||||
dev_err(cdev, "mismatched mode: local_reset = %s, module_reset = %s, core_state = %s\n",
|
||||
!ret ? "deasserted" : "asserted",
|
||||
!reset_ctrl_status ? "deasserted" : "asserted",
|
||||
c_state ? "deasserted" : "asserted",
|
||||
halted ? "halted" : "unhalted");
|
||||
ret = -EINVAL;
|
||||
|
@ -25,6 +25,10 @@
|
||||
/* RX mailbox client buffer max length */
|
||||
#define MBOX_CLIENT_BUF_MAX (IPI_BUF_LEN_MAX + \
|
||||
sizeof(struct zynqmp_ipi_message))
|
||||
|
||||
#define RSC_TBL_XLNX_MAGIC ((uint32_t)'x' << 24 | (uint32_t)'a' << 16 | \
|
||||
(uint32_t)'m' << 8 | (uint32_t)'p')
|
||||
|
||||
/*
|
||||
* settings for RPU cluster mode which
|
||||
* reflects possible values of xlnx,cluster-mode dt-property
|
||||
@ -73,6 +77,26 @@ struct mbox_info {
|
||||
struct mbox_chan *rx_chan;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rsc_tbl_data
|
||||
*
|
||||
* Platform specific data structure used to sync resource table address.
|
||||
* It's important to maintain order and size of each field on remote side.
|
||||
*
|
||||
* @version: version of data structure
|
||||
* @magic_num: 32-bit magic number.
|
||||
* @comp_magic_num: complement of above magic number
|
||||
* @rsc_tbl_size: resource table size
|
||||
* @rsc_tbl: resource table address
|
||||
*/
|
||||
struct rsc_tbl_data {
|
||||
const int version;
|
||||
const u32 magic_num;
|
||||
const u32 comp_magic_num;
|
||||
const u32 rsc_tbl_size;
|
||||
const uintptr_t rsc_tbl;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Hardcoded TCM bank values. This will stay in driver to maintain backward
|
||||
* compatibility with device-tree that does not have TCM information.
|
||||
@ -95,20 +119,24 @@ static const struct mem_bank_data zynqmp_tcm_banks_lockstep[] = {
|
||||
/**
|
||||
* struct zynqmp_r5_core
|
||||
*
|
||||
* @rsc_tbl_va: resource table virtual address
|
||||
* @dev: device of RPU instance
|
||||
* @np: device node of RPU instance
|
||||
* @tcm_bank_count: number TCM banks accessible to this RPU
|
||||
* @tcm_banks: array of each TCM bank data
|
||||
* @rproc: rproc handle
|
||||
* @rsc_tbl_size: resource table size retrieved from remote
|
||||
* @pm_domain_id: RPU CPU power domain id
|
||||
* @ipi: pointer to mailbox information
|
||||
*/
|
||||
struct zynqmp_r5_core {
|
||||
void __iomem *rsc_tbl_va;
|
||||
struct device *dev;
|
||||
struct device_node *np;
|
||||
int tcm_bank_count;
|
||||
struct mem_bank_data **tcm_banks;
|
||||
struct rproc *rproc;
|
||||
u32 rsc_tbl_size;
|
||||
u32 pm_domain_id;
|
||||
struct mbox_info *ipi;
|
||||
};
|
||||
@ -557,6 +585,14 @@ static int add_tcm_banks(struct rproc *rproc)
|
||||
dev_dbg(dev, "TCM carveout %s addr=%llx, da=0x%x, size=0x%lx",
|
||||
bank_name, bank_addr, da, bank_size);
|
||||
|
||||
/*
|
||||
* In DETACHED state firmware is already running so no need to
|
||||
* request add TCM registers. However, request TCM PD node to let
|
||||
* platform management firmware know that TCM is in use.
|
||||
*/
|
||||
if (rproc->state == RPROC_DETACHED)
|
||||
continue;
|
||||
|
||||
rproc_mem = rproc_mem_entry_init(dev, NULL, bank_addr,
|
||||
bank_size, da,
|
||||
tcm_mem_map, tcm_mem_unmap,
|
||||
@ -662,6 +698,107 @@ static int zynqmp_r5_rproc_unprepare(struct rproc *rproc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct resource_table *zynqmp_r5_get_loaded_rsc_table(struct rproc *rproc,
|
||||
size_t *size)
|
||||
{
|
||||
struct zynqmp_r5_core *r5_core;
|
||||
|
||||
r5_core = rproc->priv;
|
||||
|
||||
*size = r5_core->rsc_tbl_size;
|
||||
|
||||
return (struct resource_table *)r5_core->rsc_tbl_va;
|
||||
}
|
||||
|
||||
static int zynqmp_r5_get_rsc_table_va(struct zynqmp_r5_core *r5_core)
|
||||
{
|
||||
struct resource_table *rsc_tbl_addr;
|
||||
struct device *dev = r5_core->dev;
|
||||
struct rsc_tbl_data *rsc_data_va;
|
||||
struct resource res_mem;
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* It is expected from remote processor firmware to provide resource
|
||||
* table address via struct rsc_tbl_data data structure.
|
||||
* Start address of first entry under "memory-region" property list
|
||||
* contains that data structure which holds resource table address, size
|
||||
* and some magic number to validate correct resource table entry.
|
||||
*/
|
||||
np = of_parse_phandle(r5_core->np, "memory-region", 0);
|
||||
if (!np) {
|
||||
dev_err(dev, "failed to get memory region dev node\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(np, 0, &res_mem);
|
||||
of_node_put(np);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get memory-region resource addr\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rsc_data_va = (struct rsc_tbl_data *)ioremap_wc(res_mem.start,
|
||||
sizeof(struct rsc_tbl_data));
|
||||
if (!rsc_data_va) {
|
||||
dev_err(dev, "failed to map resource table data address\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* If RSC_TBL_XLNX_MAGIC number and its complement isn't found then
|
||||
* do not consider resource table address valid and don't attach
|
||||
*/
|
||||
if (rsc_data_va->magic_num != RSC_TBL_XLNX_MAGIC ||
|
||||
rsc_data_va->comp_magic_num != ~RSC_TBL_XLNX_MAGIC) {
|
||||
dev_dbg(dev, "invalid magic number, won't attach\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r5_core->rsc_tbl_va = ioremap_wc(rsc_data_va->rsc_tbl,
|
||||
rsc_data_va->rsc_tbl_size);
|
||||
if (!r5_core->rsc_tbl_va) {
|
||||
dev_err(dev, "failed to get resource table va\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rsc_tbl_addr = (struct resource_table *)r5_core->rsc_tbl_va;
|
||||
|
||||
/*
|
||||
* As of now resource table version 1 is expected. Don't fail to attach
|
||||
* but warn users about it.
|
||||
*/
|
||||
if (rsc_tbl_addr->ver != 1)
|
||||
dev_warn(dev, "unexpected resource table version %d\n",
|
||||
rsc_tbl_addr->ver);
|
||||
|
||||
r5_core->rsc_tbl_size = rsc_data_va->rsc_tbl_size;
|
||||
|
||||
iounmap((void __iomem *)rsc_data_va);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zynqmp_r5_attach(struct rproc *rproc)
|
||||
{
|
||||
dev_dbg(&rproc->dev, "rproc %d attached\n", rproc->index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zynqmp_r5_detach(struct rproc *rproc)
|
||||
{
|
||||
/*
|
||||
* Generate last notification to remote after clearing virtio flag.
|
||||
* Remote can avoid polling on virtio reset flag if kick is generated
|
||||
* during detach by host and check virtio reset flag on kick interrupt.
|
||||
*/
|
||||
zynqmp_r5_rproc_kick(rproc, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rproc_ops zynqmp_r5_rproc_ops = {
|
||||
.prepare = zynqmp_r5_rproc_prepare,
|
||||
.unprepare = zynqmp_r5_rproc_unprepare,
|
||||
@ -673,6 +810,9 @@ static const struct rproc_ops zynqmp_r5_rproc_ops = {
|
||||
.sanity_check = rproc_elf_sanity_check,
|
||||
.get_boot_addr = rproc_elf_get_boot_addr,
|
||||
.kick = zynqmp_r5_rproc_kick,
|
||||
.get_loaded_rsc_table = zynqmp_r5_get_loaded_rsc_table,
|
||||
.attach = zynqmp_r5_attach,
|
||||
.detach = zynqmp_r5_detach,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -723,6 +863,16 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
|
||||
goto free_rproc;
|
||||
}
|
||||
|
||||
/*
|
||||
* If firmware is already available in the memory then move rproc state
|
||||
* to DETACHED. Firmware can be preloaded via debugger or by any other
|
||||
* agent (processors) in the system.
|
||||
* If firmware isn't available in the memory and resource table isn't
|
||||
* found, then rproc state remains OFFLINE.
|
||||
*/
|
||||
if (!zynqmp_r5_get_rsc_table_va(r5_core))
|
||||
r5_rproc->state = RPROC_DETACHED;
|
||||
|
||||
r5_core->rproc = r5_rproc;
|
||||
return r5_core;
|
||||
|
||||
@ -1134,6 +1284,7 @@ static void zynqmp_r5_cluster_exit(void *data)
|
||||
for (i = 0; i < cluster->core_count; i++) {
|
||||
r5_core = cluster->r5_cores[i];
|
||||
zynqmp_r5_free_mbox(r5_core->ipi);
|
||||
iounmap(r5_core->rsc_tbl_va);
|
||||
of_reserved_mem_device_release(r5_core->dev);
|
||||
put_device(r5_core->dev);
|
||||
rproc_del(r5_core->rproc);
|
||||
|
@ -359,6 +359,32 @@ static struct qcom_smem *__smem;
|
||||
/* Timeout (ms) for the trylock of remote spinlocks */
|
||||
#define HWSPINLOCK_TIMEOUT 1000
|
||||
|
||||
/* The qcom hwspinlock id is always plus one from the smem host id */
|
||||
#define SMEM_HOST_ID_TO_HWSPINLOCK_ID(__x) ((__x) + 1)
|
||||
|
||||
/**
|
||||
* qcom_smem_bust_hwspin_lock_by_host() - bust the smem hwspinlock for a host
|
||||
* @host: remote processor id
|
||||
*
|
||||
* Busts the hwspin_lock for the given smem host id. This helper is intended
|
||||
* for remoteproc drivers that manage remoteprocs with an equivalent smem
|
||||
* driver instance in the remote firmware. Drivers can force a release of the
|
||||
* smem hwspin_lock if the rproc unexpectedly goes into a bad state.
|
||||
*
|
||||
* Context: Process context.
|
||||
*
|
||||
* Returns: 0 on success, otherwise negative errno.
|
||||
*/
|
||||
int qcom_smem_bust_hwspin_lock_by_host(unsigned int host)
|
||||
{
|
||||
/* This function is for remote procs, so ignore SMEM_HOST_APPS */
|
||||
if (host == SMEM_HOST_APPS || host >= SMEM_HOST_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
return hwspin_lock_bust(__smem->hwlock, SMEM_HOST_ID_TO_HWSPINLOCK_ID(host));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_smem_bust_hwspin_lock_by_host);
|
||||
|
||||
/**
|
||||
* qcom_smem_is_available() - Check if SMEM is available
|
||||
*
|
||||
|
@ -15,4 +15,6 @@ phys_addr_t qcom_smem_virt_to_phys(void *p);
|
||||
int qcom_smem_get_soc_id(u32 *id);
|
||||
int qcom_smem_get_feature_code(u32 *code);
|
||||
|
||||
int qcom_smem_bust_hwspin_lock_by_host(unsigned int host);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user