Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee15fee0 authored by Se Wang (Patrick) Oh's avatar Se Wang (Patrick) Oh
Browse files

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: default avatarSe Wang (Patrick) Oh <sewango@codeaurora.org>
parent 494ca1d5
Loading
Loading
Loading
Loading
+51 −3
Original line number Diff line number Diff line
@@ -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;