return ret ? false : !!ret_val;
}
-int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, const void *metadata, size_t size)
+int __qcom_scm_pas_init_image(u32 peripheral, dma_addr_t metadata_phys)
{
- dma_addr_t mdata_phys;
- void *mdata_buf;
- u32 scm_ret;
+ __le32 scm_ret;
int ret;
- struct pas_init_image_req {
- u32 proc;
- u32 image_addr;
+ struct {
+ __le32 proc;
+ __le32 image_addr;
} request;
- /*
- * During the scm call memory protection will be enabled for the meta
- * data blob, so make sure it's physically contiguous, 4K aligned and
- * non-cachable to avoid XPU violations.
- */
- mdata_buf = dma_alloc_coherent(dev, size, &mdata_phys, GFP_KERNEL);
- if (!mdata_buf) {
- pr_err("Allocation of metadata buffer failed.\n");
- return -ENOMEM;
- }
- memcpy(mdata_buf, metadata, size);
-
- request.proc = peripheral;
- request.image_addr = mdata_phys;
+ request.proc = cpu_to_le32(peripheral);
+ request.image_addr = cpu_to_le32(metadata_phys);
ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD,
&request, sizeof(request),
&scm_ret, sizeof(scm_ret));
- dma_free_coherent(dev, size, mdata_buf, mdata_phys);
-
- return ret ? : scm_ret;
+ return ret ? : le32_to_cpu(scm_ret);
}
int __qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
return ret ? false : !!desc.ret[0];
}
-int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, const void *metadata, size_t size)
+int __qcom_scm_pas_init_image(u32 peripheral, dma_addr_t metadata_phys)
{
int ret;
struct qcom_scm_desc desc = {0};
u32 scm_ret;
- dma_addr_t mdata_phys;
- void *mdata_buf;
-
-dev->coherent_dma_mask = DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
-
- /*
- * During the scm call memory protection will be enabled for the meta
- * data blob, so make sure it's physically contiguous, 4K aligned and
- * non-cachable to avoid XPU violations.
- */
- mdata_buf = dma_alloc_coherent(dev, size, &mdata_phys, GFP_KERNEL);
- if (!mdata_buf) {
- pr_err("Allocation of metadata buffer failed.\n");
- return -ENOMEM;
- }
- memcpy(mdata_buf, metadata, size);
desc.args[0] = peripheral;
- desc.args[1] = mdata_phys;
+ desc.args[1] = metadata_phys;
desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW);
ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD,
&desc);
scm_ret = desc.ret[0];
- dma_free_coherent(dev, size, mdata_buf, mdata_phys);
return ret ? : scm_ret;
}
#include <linux/module.h>
#include <linux/cpumask.h>
#include <linux/export.h>
+#include <linux/dma-mapping.h>
#include <linux/types.h>
#include <linux/qcom_scm.h>
#include <linux/of.h>
#include "qcom_scm.h"
struct qcom_scm {
+ struct device *dev;
struct clk *core_clk;
struct clk *iface_clk;
struct clk *bus_clk;
{
int ret;
- if(__scm->core_clk) {
- ret = clk_prepare_enable(__scm->core_clk);
- if (ret)
- goto bail;
- }
-
- if(__scm->iface_clk) {
- ret = clk_prepare_enable(__scm->iface_clk);
- if (ret)
- goto disable_core;
- }
-
- if(__scm->bus_clk) {
- ret = clk_prepare_enable(__scm->bus_clk);
- if (ret)
- goto disable_iface;
- }
+ ret = clk_prepare_enable(__scm->core_clk);
+ if (ret)
+ goto bail;
+ ret = clk_prepare_enable(__scm->iface_clk);
+ if (ret)
+ goto disable_core;
+ ret = clk_prepare_enable(__scm->bus_clk);
+ if (ret)
+ goto disable_iface;
return 0;
disable_iface:
- if(__scm->iface_clk)
- clk_disable_unprepare(__scm->iface_clk);
+ clk_disable_unprepare(__scm->iface_clk);
disable_core:
- if(__scm->core_clk)
- clk_disable_unprepare(__scm->core_clk);
+ clk_disable_unprepare(__scm->core_clk);
bail:
return ret;
}
static void qcom_scm_clk_disable(void)
{
- if(__scm->core_clk)
- clk_disable_unprepare(__scm->core_clk);
- if(__scm->iface_clk)
- clk_disable_unprepare(__scm->iface_clk);
- if(__scm->bus_clk)
- clk_disable_unprepare(__scm->bus_clk);
+ clk_disable_unprepare(__scm->core_clk);
+ clk_disable_unprepare(__scm->iface_clk);
+ clk_disable_unprepare(__scm->bus_clk);
}
/**
int qcom_scm_restart_proc(u32 pid, int restart, u32 *resp)
{
- return __qcom_scm_restart_proc(pid, restart, resp);
+ int ret;
+
+ ret = qcom_scm_clk_enable();
+ if (ret)
+ return ret;
+
+ ret = __qcom_scm_restart_proc(pid, restart, resp);
+ qcom_scm_clk_disable();
+ return ret;
}
EXPORT_SYMBOL(qcom_scm_restart_proc);
/**
*
* Returns 0 on success.
*/
-int qcom_scm_pas_init_image(struct device *dev, u32 peripheral, const void *metadata, size_t size)
+int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
{
- return __qcom_scm_pas_init_image(dev, peripheral, metadata, size);
+ dma_addr_t mdata_phys;
+ void *mdata_buf;
+ int ret;
+
+ /*
+ * During the scm call memory protection will be enabled for the meta
+ * data blob, so make sure it's physically contiguous, 4K aligned and
+ * non-cachable to avoid XPU violations.
+ */
+ mdata_buf = dma_alloc_coherent(__scm->dev, size, &mdata_phys, GFP_KERNEL);
+ if (!mdata_buf) {
+ dev_err(__scm->dev, "Allocation of metadata buffer failed.\n");
+ return -ENOMEM;
+ }
+ memcpy(mdata_buf, metadata, size);
+
+ ret = qcom_scm_clk_enable();
+ if (ret)
+ goto free_metadata;
+
+ ret = __qcom_scm_pas_init_image(peripheral, mdata_phys);
+
+ qcom_scm_clk_disable();
+
+free_metadata:
+ dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
+
+ return ret;
}
EXPORT_SYMBOL(qcom_scm_pas_init_image);
*/
int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
{
- return __qcom_scm_pas_mem_setup(peripheral, addr, size);
+ int ret;
+
+ ret = qcom_scm_clk_enable();
+ if (ret)
+ return ret;
+
+ ret = __qcom_scm_pas_mem_setup(peripheral, addr, size);
+ qcom_scm_clk_disable();
+
+ return ret;
}
EXPORT_SYMBOL(qcom_scm_pas_mem_setup);
*/
int qcom_scm_pas_auth_and_reset(u32 peripheral)
{
- return __qcom_scm_pas_auth_and_reset(peripheral);
+ int ret;
+
+ ret = qcom_scm_clk_enable();
+ if (ret)
+ return ret;
+
+ ret = __qcom_scm_pas_auth_and_reset(peripheral);
+ qcom_scm_clk_disable();
+
+ return ret;
}
EXPORT_SYMBOL(qcom_scm_pas_auth_and_reset);
*/
int qcom_scm_pas_shutdown(u32 peripheral)
{
- return __qcom_scm_pas_shutdown(peripheral);
+ int ret;
+
+ ret = qcom_scm_clk_enable();
+ if (ret)
+ return ret;
+
+ ret = __qcom_scm_pas_shutdown(peripheral);
+ qcom_scm_clk_disable();
+
+ return ret;
}
EXPORT_SYMBOL(qcom_scm_pas_shutdown);
if (!scm)
return -ENOMEM;
+ scm->dev = &pdev->dev;
+
scm->core_clk = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(scm->core_clk)) {
- if (PTR_ERR(scm->core_clk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "failed to acquire core clk\n");
+ if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_err(&pdev->dev, "failed to acquire core clk\n");
scm->core_clk = NULL;
}
scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
if (IS_ERR(scm->iface_clk)) {
- if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "failed to acquire iface clk\n");
+ if (PTR_ERR(scm->iface_clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_err(&pdev->dev, "failed to acquire iface clk\n");
scm->iface_clk = NULL;
}
scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
if (IS_ERR(scm->bus_clk)) {
- if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "failed to acquire bus clk\n");
+ if (PTR_ERR(scm->bus_clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "failed to acquire bus clk\n");
scm->bus_clk = NULL;
}
- if (scm->core_clk) {
/* vote for max clk rate for highest performance */
- rate = clk_round_rate(scm->core_clk, INT_MAX);
- ret = clk_set_rate(scm->core_clk, rate);
- if (ret)
- return ret;
- }
+ rate = clk_round_rate(scm->core_clk, INT_MAX);
+ ret = clk_set_rate(scm->core_clk, rate);
+ if (ret)
+ return ret;
__scm = scm;