blob: f6084260fe16de8da6856dfe440e65fd47e4b3bc [file] [log] [blame]
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* 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
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/of.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/msm_tz_smmu.h>
static const char * const device_id_mappings[] = {
[TZ_DEVICE_VIDEO] = "VIDEO",
[TZ_DEVICE_MDSS] = "MDSS",
[TZ_DEVICE_LPASS] = "LPASS",
[TZ_DEVICE_MDSS_BOOT] = "MDSS_BOOT",
[TZ_DEVICE_USB1_HS] = "USB1_HS",
[TZ_DEVICE_OCMEM] = "OCMEM",
[TZ_DEVICE_LPASS_CORE] = "LPASS_CORE",
[TZ_DEVICE_VPU] = "VPU",
[TZ_DEVICE_COPSS_SMMU] = "COPSS_SMMU",
[TZ_DEVICE_USB3_0] = "USB3_0",
[TZ_DEVICE_USB3_1] = "USB3_1",
[TZ_DEVICE_PCIE_0] = "PCIE_0",
[TZ_DEVICE_PCIE_1] = "PCIE_1",
[TZ_DEVICE_BCSS] = "BCSS",
[TZ_DEVICE_VCAP] = "VCAP",
[TZ_DEVICE_PCIE20] = "PCIE20",
[TZ_DEVICE_IPA] = "IPA",
[TZ_DEVICE_APPS] = "APPS",
[TZ_DEVICE_GPU] = "GPU",
[TZ_DEVICE_UFS] = "UFS",
[TZ_DEVICE_ICE] = "ICE",
[TZ_DEVICE_ROT] = "ROT",
[TZ_DEVICE_VFE] = "VFE",
[TZ_DEVICE_ANOC0] = "ANOC0",
[TZ_DEVICE_ANOC1] = "ANOC1",
[TZ_DEVICE_ANOC2] = "ANOC2",
[TZ_DEVICE_CPP] = "CPP",
[TZ_DEVICE_JPEG] = "JPEG",
};
#define MAX_DEVICE_ID_NAME_LEN 20
#define TZ_SMMU_PREPARE_ATOS_ID 0x21
#define TZ_SMMU_ATOS_START 1
#define TZ_SMMU_ATOS_END 0
#define SMMU_CHANGE_PAGETABLE_FORMAT 0X01
enum tz_smmu_device_id msm_dev_to_device_id(struct device *dev)
{
const char *device_id;
enum tz_smmu_device_id iter;
if (of_property_read_string(dev->of_node, "qcom,tz-device-id",
&device_id)) {
dev_err(dev, "no qcom,device-id property\n");
return TZ_DEVICE_MAX;
}
for (iter = TZ_DEVICE_START; iter < TZ_DEVICE_MAX; iter++)
if (!strcmp(device_id_mappings[iter], device_id))
return iter;
return TZ_DEVICE_MAX;
}
static int __msm_tz_smmu_atos(struct device *dev, int cb_num, int operation)
{
int ret;
struct scm_desc desc = {0};
enum tz_smmu_device_id devid = msm_dev_to_device_id(dev);
if (devid == TZ_DEVICE_MAX)
return -ENODEV;
desc.args[0] = devid;
desc.args[1] = cb_num;
desc.args[2] = operation;
desc.arginfo = SCM_ARGS(3, SCM_VAL, SCM_VAL, SCM_VAL);
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, TZ_SMMU_PREPARE_ATOS_ID),
&desc);
if (ret)
pr_info("%s: TZ SMMU ATOS %s failed, ret = %d\n",
__func__,
operation == TZ_SMMU_ATOS_START ? "start" : "end",
ret);
return ret;
}
int msm_tz_smmu_atos_start(struct device *dev, int cb_num)
{
return __msm_tz_smmu_atos(dev, cb_num, TZ_SMMU_ATOS_START);
}
int msm_tz_smmu_atos_end(struct device *dev, int cb_num)
{
return __msm_tz_smmu_atos(dev, cb_num, TZ_SMMU_ATOS_END);
}
int msm_tz_set_cb_format(enum tz_smmu_device_id sec_id, int cbndx)
{
struct scm_desc desc = {0};
int ret = 0;
desc.args[0] = sec_id;
desc.args[1] = cbndx;
desc.args[2] = 1; /* Enable */
desc.arginfo = SCM_ARGS(3, SCM_VAL, SCM_VAL, SCM_VAL);
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_SMMU_PROGRAM,
SMMU_CHANGE_PAGETABLE_FORMAT), &desc);
if (ret) {
WARN(1, "Format change failed for CB %d with ret %d\n",
cbndx, ret);
return ret;
}
return 0;
}