From 051df5bd9bd02b93b6ea47e326ad6c570fa2469a Mon Sep 17 00:00:00 2001 From: "Se Wang (Patrick) Oh" Date: Wed, 21 Oct 2015 18:21:23 -0700 Subject: [PATCH] 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 --- drivers/soc/qcom/scm-errata.c | 54 +++++++++++++++++++++++++++++++++-- 1 file 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 #include -#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;