summaryrefslogtreecommitdiff
path: root/drivers/soc/qcom/scm-errata.c
diff options
context:
space:
mode:
authorSe Wang (Patrick) Oh <sewango@codeaurora.org>2015-10-21 18:21:23 -0700
committerRohit Vaswani <rvaswani@codeaurora.org>2016-03-01 12:22:21 -0800
commit051df5bd9bd02b93b6ea47e326ad6c570fa2469a (patch)
tree443ca8113d536e151b5111f521aec73b0f37073d /drivers/soc/qcom/scm-errata.c
parent32b29d83ff2b0d588d6e81830731b00fe56f8ee6 (diff)
soc: qcom: add kryo_e76 debugfs node
To disable and enable Kryo hardware errata 76 workaround at runtime, expose a debugfs interface. Wrote codes using e74/e76 API and data as a starting point. /sys/kernel/debug/scm_errata/kryo_e76 This allows Kryo errata 76 workaround to be toggled off or on (on affected devices) by echoing 0 or 1 to the file. Change-Id: I3d682021aa98eef5421ac2e7578da02f2ea98081 Signed-off-by: Se Wang (Patrick) Oh <sewango@codeaurora.org>
Diffstat (limited to 'drivers/soc/qcom/scm-errata.c')
-rw-r--r--drivers/soc/qcom/scm-errata.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/drivers/soc/qcom/scm-errata.c b/drivers/soc/qcom/scm-errata.c
index 041f26b7b131..f68d88829336 100644
--- a/drivers/soc/qcom/scm-errata.c
+++ b/drivers/soc/qcom/scm-errata.c
@@ -17,12 +17,15 @@
#include <linux/cpu.h>
#include <soc/qcom/scm.h>
-#define KRYO_ERRATA_74_75_ID 0x12
+#define SCM_KRYO_ERRATA_ID 0x12
#define ERRATA_WA_DISABLE 0
#define ERRATA_WA_ENABLE 1
+#define ERRATA_74_75_ID_BIT 0x000
+#define ERRATA_76_ID_BIT 0x100
static struct dentry *debugfs_base;
static bool kryo_e74_e75_wa = true;
+static bool kryo_e76_wa;
static void kryo_e74_e75_scm(void *enable)
{
@@ -34,8 +37,9 @@ static void kryo_e74_e75_scm(void *enable)
desc.arginfo = SCM_ARGS(1);
desc.args[0] = enable ? ERRATA_WA_ENABLE : ERRATA_WA_DISABLE;
+ desc.args[0] |= ERRATA_74_75_ID_BIT;
- ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT, KRYO_ERRATA_74_75_ID),
+ ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT, SCM_KRYO_ERRATA_ID),
&desc);
if (ret)
pr_err("Failed to %s ERRATA_74_75 workaround\n",
@@ -62,8 +66,49 @@ static int kryo_e74_e75_get(void *data, u64 *val)
return 0;
}
+static void kryo_e76_scm(void *enable)
+{
+ int ret;
+ struct scm_desc desc = {0};
+
+ if (!is_scm_armv8())
+ return;
+
+ desc.arginfo = SCM_ARGS(1);
+ desc.args[0] = enable ? ERRATA_WA_ENABLE : ERRATA_WA_DISABLE;
+ desc.args[0] |= ERRATA_76_ID_BIT;
+
+ ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT, SCM_KRYO_ERRATA_ID),
+ &desc);
+ if (ret)
+ pr_err("Failed to %s ERRATA_76 workaround\n",
+ enable ? "enable" : "disable");
+}
+
+static int kryo_e76_set(void *data, u64 val)
+{
+ if ((val && kryo_e76_wa) || (!val && !kryo_e76_wa))
+ return 0;
+
+ kryo_e76_wa = !!val;
+
+ get_cpu();
+ on_each_cpu(kryo_e76_scm, (void *)kryo_e76_wa, 1);
+ put_cpu();
+
+ return 0;
+}
+
+static int kryo_e76_get(void *data, u64 *val)
+{
+ *val = kryo_e76_wa;
+ return 0;
+}
+
DEFINE_SIMPLE_ATTRIBUTE(kryo_e74_e75_fops, kryo_e74_e75_get,
kryo_e74_e75_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(kryo_e76_fops, kryo_e76_get,
+ kryo_e76_set, "%llu\n");
static int scm_errata_notifier_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
@@ -71,6 +116,7 @@ static int scm_errata_notifier_callback(struct notifier_block *nfb,
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_STARTING:
kryo_e74_e75_scm((void *)kryo_e74_e75_wa);
+ kryo_e76_scm((void *)kryo_e76_wa);
break;
}
return 0;
@@ -91,7 +137,9 @@ static int __init scm_errata_init(void)
if (!debugfs_create_file("kryo_e74_e75", S_IRUGO | S_IWUSR,
debugfs_base, NULL, &kryo_e74_e75_fops))
goto err;
-
+ if (!debugfs_create_file("kryo_e76", S_IRUGO | S_IWUSR,
+ debugfs_base, NULL, &kryo_e76_fops))
+ goto err;
ret = register_hotcpu_notifier(&scm_errata_notifier);
if (ret)
goto err;