]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
firmware: qcom: scm: Support IOMMU scm calls
authorStanimir Varbanov <stanimir.varbanov@linaro.org>
Tue, 28 Apr 2015 11:05:33 +0000 (14:05 +0300)
committerKhalid Elmously <khalid.elmously@canonical.com>
Wed, 14 Mar 2018 02:42:09 +0000 (02:42 +0000)
Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
Conflicts:
drivers/firmware/qcom_scm-64.c
drivers/firmware/qcom_scm.c

drivers/firmware/qcom_scm-32.c
drivers/firmware/qcom_scm-64.c
drivers/firmware/qcom_scm.c
drivers/firmware/qcom_scm.h
include/linux/qcom_scm.h

index c103437195bd845b7eafce957d55dc88bbd97a0e..c6ec8954835416e53a9931107c219fba392e9b33 100644 (file)
 #define QCOM_SCM_FLAG_WARMBOOT_CPU2    0x10
 #define QCOM_SCM_FLAG_WARMBOOT_CPU3    0x40
 
+#define IOMMU_SECURE_PTBL_SIZE         3
+#define IOMMU_SECURE_PTBL_INIT         4
+#define IOMMU_SET_CP_POOL_SIZE         5
+#define IOMMU_SECURE_MAP               6
+#define IOMMU_SECURE_UNMAP             7
+#define IOMMU_SECURE_MAP2              0xb
+#define IOMMU_SECURE_MAP2_FLAT         0x12
+#define IOMMU_SECURE_UNMAP2            0xc
+
 struct qcom_scm_entry {
        int flag;
        void *entry;
@@ -658,3 +667,171 @@ int __qcom_scm_pil_shutdown_cmd(u32 proc)
 
        return scm_ret;
 }
+
+#define SCM_SVC_UTIL                   0x3
+#define SCM_SVC_MP                     0xc
+#define IOMMU_DUMP_SMMU_FAULT_REGS     0x0c
+
+int __qcom_scm_iommu_dump_fault_regs(u32 id, u32 context, u64 addr, u32 len)
+{
+       struct {
+               u32 id;
+               u32 cb_num;
+               u32 buff;
+               u32 len;
+       } req;
+       int resp = 0;
+
+       return qcom_scm_call(SCM_SVC_UTIL, IOMMU_DUMP_SMMU_FAULT_REGS,
+                      &req, sizeof(req), &resp, 1);
+}
+
+int __qcom_scm_iommu_set_cp_pool_size(u32 size, u32 spare)
+{
+       struct {
+               u32 size;
+               u32 spare;
+       } req;
+       int retval;
+
+       req.size = size;
+       req.spare = spare;
+
+       return qcom_scm_call(SCM_SVC_MP, IOMMU_SET_CP_POOL_SIZE,
+                            &req, sizeof(req), &retval, sizeof(retval));
+}
+
+int __qcom_scm_iommu_secure_ptbl_size(u32 spare, int psize[2])
+{
+       struct {
+               u32 spare;
+       } req;
+
+       req.spare = spare;
+
+       return qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_SIZE, &req,
+                            sizeof(req), psize, sizeof(psize));
+}
+
+int __qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
+{
+       struct {
+               u32 addr;
+               u32 size;
+               u32 spare;
+       } req = {0};
+       int ret, ptbl_ret = 0;
+
+       req.addr = addr;
+       req.size = size;
+       req.spare = spare;
+
+       ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_INIT, &req,
+                           sizeof(req), &ptbl_ret, sizeof(ptbl_ret));
+
+       if (ret)
+               return ret;
+
+       if (ptbl_ret)
+               return ptbl_ret;
+
+       return 0;
+}
+
+int __qcom_scm_iommu_secure_map(u64 list, u32 list_size, u32 size,
+                               u32 id, u32 ctx_id, u64 va, u32 info_size,
+                               u32 flags)
+{
+       struct {
+               struct {
+                       unsigned int list;
+                       unsigned int list_size;
+                       unsigned int size;
+               } plist;
+               struct {
+                       unsigned int id;
+                       unsigned int ctx_id;
+                       unsigned int va;
+                       unsigned int size;
+               } info;
+               unsigned int flags;
+       } req;
+       u32 resp;
+       int ret;
+
+       req.plist.list = list;
+       req.plist.list_size = list_size;
+       req.plist.size = size;
+       req.info.id = id;
+       req.info.ctx_id = ctx_id;
+       req.info.va = va;
+       req.info.size = info_size;
+       req.flags = flags;
+
+       ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2, &req, sizeof(req),
+                           &resp, sizeof(resp));
+
+       if (ret || resp)
+               return -EINVAL;
+
+       return 0;
+}
+
+int __qcom_scm_iommu_secure_unmap(u32 id, u32 ctx_id, u64 va,
+                                 u32 size, u32 flags)
+{
+       struct {
+               struct {
+                       unsigned int id;
+                       unsigned int ctx_id;
+                       unsigned int va;
+                       unsigned int size;
+               } info;
+               unsigned int flags;
+       } req;
+       int ret, scm_ret;
+
+       req.info.id = id;
+       req.info.ctx_id = ctx_id;
+       req.info.va = va;
+       req.info.size = size;
+       req.flags = flags;
+
+       return qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_UNMAP2, &req,
+                            sizeof(req), &scm_ret, sizeof(scm_ret));
+}
+
+int __qcom_scm_get_feat_version(u32 feat)
+{
+       int ret;
+
+       if (__qcom_scm_is_call_available(SCM_SVC_INFO, GET_FEAT_VERSION_CMD)) {
+               u32 version;
+
+               if (!qcom_scm_call(SCM_SVC_INFO, GET_FEAT_VERSION_CMD, &feat,
+                                  sizeof(feat), &version, sizeof(version)))
+                       return version;
+       }
+
+       return 0;
+}
+
+#define RESTORE_SEC_CFG                2
+int __qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
+{
+       struct {
+               u32 device_id;
+               u32 spare;
+       } req;
+       int ret, scm_ret = 0;
+
+       req.device_id = device_id;
+       req.spare = spare;
+
+       ret = qcom_scm_call(SCM_SVC_MP, RESTORE_SEC_CFG, &req, sizeof(req),
+                           scm_ret, sizeof(scm_ret));
+       if (ret || scm_ret)
+               return ret ? ret : -EINVAL;
+
+       return 0;
+}
index f430e0c3e6985f85f2fe8f0950140e95707b1c83..2584336105c07a1afcdbb93906bd6a15f07b2a24 100644 (file)
@@ -635,6 +635,167 @@ int __qcom_scm_pil_shutdown_cmd(u32 proc)
 
        return scm_ret;
 }
+
+#define SCM_SVC_UTIL                   0x3
+#define SCM_SVC_MP                     0xc
+#define IOMMU_DUMP_SMMU_FAULT_REGS     0xc
+
+#define IOMMU_SECURE_PTBL_SIZE         3
+#define IOMMU_SECURE_PTBL_INIT         4
+#define IOMMU_SET_CP_POOL_SIZE         5
+#define IOMMU_SECURE_MAP               6
+#define IOMMU_SECURE_UNMAP             7
+#define IOMMU_SECURE_MAP2              0xb
+#define IOMMU_SECURE_MAP2_FLAT         0x12
+#define IOMMU_SECURE_UNMAP2            0xc
+#define IOMMU_SECURE_UNMAP2_FLAT       0x13
+
+int __qcom_scm_iommu_dump_fault_regs(u32 id, u32 context, u64 addr, u32 len)
+{
+       struct qcom_scm_desc desc = {0};
+
+       desc.args[0] = id;
+       desc.args[1] = context;
+       desc.args[2] = addr;
+       desc.args[3] = len;
+       desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL);
+
+       return qcom_scm_call(SCM_SVC_UTIL, IOMMU_DUMP_SMMU_FAULT_REGS, &desc);
+}
+
+int __qcom_scm_iommu_set_cp_pool_size(u32 size, u32 spare)
+{
+       struct qcom_scm_desc desc = {0};
+
+       desc.args[0] = size;
+       desc.args[1] = spare;
+       desc.arginfo = QCOM_SCM_ARGS(2);
+
+       return qcom_scm_call(SCM_SVC_MP, IOMMU_SET_CP_POOL_SIZE, &desc);
+}
+
+int __qcom_scm_iommu_secure_ptbl_size(u32 spare, int psize[2])
+{
+       struct qcom_scm_desc desc = {0};
+       int ret;
+       desc.args[0] = spare;
+       desc.arginfo = QCOM_SCM_ARGS(1);
+
+       ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_SIZE, &desc);
+
+       psize[0] = desc.ret[0];
+       psize[1] = desc.ret[1];
+
+       return ret;
+}
+
+int __qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
+{
+       struct qcom_scm_desc desc = {0};
+       int ret;
+       u64 ptbl_ret;
+
+       desc.args[0] = addr;
+       desc.args[1] = size;
+       desc.args[2] = spare;
+       desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL);
+
+       ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_INIT, &desc);
+
+       ptbl_ret = desc.ret[0];
+
+       if (ret)
+               return ret;
+
+       if (ptbl_ret)
+               return ptbl_ret;
+
+       return 0;
+}
+
+int __qcom_scm_iommu_secure_map(u64 list, u32 list_size, u32 size,
+                               u32 id, u32 ctx_id, u64 va, u32 info_size,
+                               u32 flags)
+{
+       struct qcom_scm_desc desc = {0};
+       u32 resp;
+       int ret;
+
+       desc.args[0] = list;
+       desc.args[1] = list_size;
+       desc.args[2] = size;
+       desc.args[3] = id;
+       desc.args[4] = ctx_id;
+       desc.args[5] = va;
+       desc.args[6] = info_size;
+       desc.args[7] = flags;
+       desc.arginfo = QCOM_SCM_ARGS(8, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL,
+                                    QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL);
+
+       ret = qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2_FLAT, &desc);
+
+       resp = desc.ret[0];
+
+       if (ret || resp)
+               return -EINVAL;
+
+       return 0;
+}
+
+int __qcom_scm_iommu_secure_unmap(u32 id, u32 ctx_id, u64 va,
+                                 u32 size, u32 flags)
+{
+       struct qcom_scm_desc desc = {0};
+
+       desc.args[0] = id;
+       desc.args[1] = ctx_id;
+       desc.args[2] = va;
+       desc.args[3] = size;
+       desc.args[4] = flags;
+       desc.arginfo = QCOM_SCM_ARGS(5);
+
+       return qcom_scm_call(SCM_SVC_MP, IOMMU_SECURE_UNMAP2_FLAT, &desc);
+}
+
+int __qcom_scm_get_feat_version(u32 feat)
+{
+       struct qcom_scm_desc desc = {0};
+       int ret;
+
+       ret = __qcom_scm_is_call_available(SCM_SVC_INFO, GET_FEAT_VERSION_CMD);
+       if (ret <= 0)
+               return 0;
+
+       desc.args[0] = feat;
+       desc.arginfo = QCOM_SCM_ARGS(1);
+
+       ret = qcom_scm_call(SCM_SVC_INFO, GET_FEAT_VERSION_CMD, &desc);
+       if (!ret)
+               return desc.ret[0];
+
+       return 0;
+}
+
+#define RESTORE_SEC_CFG                2
+int __qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
+{
+       struct qcom_scm_desc desc = {0};
+       int ret, scm_ret = 0;
+
+       desc.args[0] = device_id;
+       desc.args[1] = spare;
+       desc.arginfo = QCOM_SCM_ARGS(2);
+
+       ret = qcom_scm_call(SCM_SVC_MP, RESTORE_SEC_CFG, &desc);
+
+       scm_ret = desc.ret[0];
+
+       if (ret || scm_ret)
+               return ret ? ret : -EINVAL;
+
+       return 0;
+}
+
 #define QCOM_SCM_SVC_INFO              0x6
 static int __init qcom_scm_init(void)
 {
index 655550b402a7228838d7f2bb535af55e6eb57994..34477a827836fafdc128bd905a307c89dfc0bdce 100644 (file)
@@ -196,4 +196,61 @@ int qcom_scm_pil_shutdown_cmd(u32 proc)
 {
        return __qcom_scm_pil_shutdown_cmd(proc);
 }
-EXPORT_SYMBOL(qcom_scm_pil_shutdown_cmd);
\ No newline at end of file
+EXPORT_SYMBOL(qcom_scm_pil_shutdown_cmd);
+
+int qcom_scm_iommu_dump_fault_regs(u32 id, u32 context, u64 addr, u32 len)
+{
+       return __qcom_scm_iommu_dump_fault_regs(id, context, addr, len);
+}
+EXPORT_SYMBOL(qcom_scm_iommu_dump_fault_regs);
+
+int qcom_scm_iommu_set_cp_pool_size(u32 size, u32 spare)
+{
+       return __qcom_scm_iommu_set_cp_pool_size(size, spare);
+}
+EXPORT_SYMBOL(qcom_scm_iommu_set_cp_pool_size);
+
+int qcom_scm_iommu_secure_ptbl_size(u32 spare, int psize[2])
+{
+       return __qcom_scm_iommu_secure_ptbl_size(spare, psize);
+}
+EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size);
+
+int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
+{
+       return __qcom_scm_iommu_secure_ptbl_init(addr, size, spare);
+}
+EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init);
+
+int qcom_scm_iommu_secure_map(u64 list, u32 list_size, u32 size,
+                             u32 id, u32 ctx_id, u64 va, u32 info_size,
+                             u32 flags)
+{
+       return __qcom_scm_iommu_secure_map(list, list_size, size, id,
+                                          ctx_id, va, info_size, flags);
+}
+EXPORT_SYMBOL(qcom_scm_iommu_secure_map);
+
+int qcom_scm_iommu_secure_unmap(u32 id, u32 ctx_id, u64 va, u32 size, u32 flags)
+{
+       return __qcom_scm_iommu_secure_unmap(id, ctx_id, va, size, flags);
+}
+EXPORT_SYMBOL(qcom_scm_iommu_secure_unmap);
+
+int qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
+{
+       return __qcom_scm_is_call_available(svc_id, cmd_id);
+}
+EXPORT_SYMBOL(qcom_scm_is_call_available);
+
+int qcom_scm_get_feat_version(u32 feat)
+{
+       return __qcom_scm_get_feat_version(feat);
+}
+EXPORT_SYMBOL(qcom_scm_get_feat_version);
+
+int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
+{
+       return __qcom_scm_restore_sec_cfg(device_id, spare);
+}
+EXPORT_SYMBOL(qcom_scm_restore_sec_cfg);
index c91ddbba701e8fb2c989d86c0817de4a66933a29..3730201661c4346dbcd8ff5fc214f971f5c64431 100644 (file)
@@ -86,11 +86,29 @@ enum scm_cmd {
        PAS_SHUTDOWN_CMD,
 };
 
-#define SCM_SVC_PIL    0x2
+#define SCM_SVC_PIL            0x2
+#define SCM_SVC_INFO           0x6
+
+#define GET_FEAT_VERSION_CMD   3
 
 extern int __qcom_scm_pil_init_image_cmd(u32 proc, u64 image_addr);
 extern int __qcom_scm_pil_mem_setup_cmd(u32 proc, u64 start_addr, u32 len);
 extern int __qcom_scm_pil_auth_and_reset_cmd(u32 proc);
 extern int __qcom_scm_pil_shutdown_cmd(u32 proc);
 
+extern int __qcom_scm_iommu_dump_fault_regs(u32 id, u32 context, u64 addr,
+                                           u32 len);
+extern int __qcom_scm_iommu_set_cp_pool_size(u32 size, u32 spare);
+extern int __qcom_scm_iommu_secure_ptbl_size(u32 spare, int psize[2]);
+extern int __qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);
+extern int __qcom_scm_iommu_secure_map(u64 list, u32 list_size, u32 size,
+                                      u32 id, u32 ctx_id, u64 va,
+                                      u32 info_size, u32 flags);
+extern int __qcom_scm_iommu_secure_unmap(u32 id, u32 ctx_id, u64 va,
+                                        u32 size, u32 flags);
+
+extern int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id);
+extern int __qcom_scm_get_feat_version(u32 feat);
+extern int __qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);
+
 #endif
index aa3441cb91a781a2f5177a893164c3dcfaa768c1..5b613ac14961995aef7c596bbb92b0435340a026 100644 (file)
@@ -51,4 +51,19 @@ extern int qcom_scm_pil_mem_setup_cmd(u32 proc, u64 start_addr, u32 len);
 extern int qcom_scm_pil_auth_and_reset_cmd(u32 proc);
 extern int qcom_scm_pil_shutdown_cmd(u32 proc);
 
+extern int qcom_scm_iommu_dump_fault_regs(u32 id, u32 context, u64 addr,
+                                         u32 len);
+extern int qcom_scm_iommu_set_cp_pool_size(u32 size, u32 spare);
+extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, int psize[2]);
+extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);
+extern int qcom_scm_iommu_secure_map(u64 list, u32 list_size, u32 size,
+                                    u32 id, u32 ctx_id, u64 va,
+                                    u32 info_size, u32 flags);
+extern int qcom_scm_iommu_secure_unmap(u32 id, u32 ctx_id, u64 va,
+                                      u32 size, u32 flags);
+
+extern int qcom_scm_is_call_available(u32 svc_id, u32 cmd_id);
+extern int qcom_scm_get_feat_version(u32 feat);
+extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);
+
 #endif