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

Commit cd2830bf authored by Matt Wagantall's avatar Matt Wagantall
Browse files

soc: qcom: add scm-errata driver



This driver exposes a debugfs interface intended for advanced
system debugging/profiling usecases where it may be desirable
to enable or disable certain hardware errata workarounds at
runtime, via an scm call.

Presently, a single debugfs node is implemented:
  /sys/kernel/debug/scm_errata/kryo_e74_e75
This allows Kryo errata 74 and 75 workarounds to be toggled
off or on (on affected devices) by echoing 0 or 1 to the file.

Change-Id: I6edf39757416130a7b716dcdab1a601f27dfac5a
Signed-off-by: default avatarMatt Wagantall <mattw@codeaurora.org>
parent 0487d9a0
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -297,6 +297,17 @@ endchoice

endif

config MSM_SCM_ERRATA
	depends on DEBUG_FS
	depends on MSM_SCM
	bool "Support for enabling/disabling errata workarounds via debugfs"
	help
	  Exposes a debugfs interface intended for advanced system debugging
	  where it may be desirable to enable or disable certain hardware
	  errata workarounds at runtime.

	  If unsure, say N.

config MSM_MPM_OF
       bool "Modem Power Manager"
       depends on OF
+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ obj-$(CONFIG_MSM_PIL) += peripheral-loader.o
obj-$(CONFIG_MSM_PIL_SSR_GENERIC) += subsys-pil-tz.o
obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-msa.o pil-q6v5-mss.o
obj-$(CONFIG_MSM_CORE_CTL_HELPER) += core_ctl_helper.o

obj-$(CONFIG_MSM_SCM_ERRATA) += scm-errata.o
obj-$(CONFIG_MSM_PERFORMANCE) += msm_performance.o

ifdef CONFIG_MSM_SUBSYSTEM_RESTART
+104 −0
Original line number Diff line number Diff line
/* Copyright (c) 2015, 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/init.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/debugfs.h>
#include <linux/cpu.h>
#include <soc/qcom/scm.h>

#define KRYO_ERRATA_74_75_ID	0x12
#define ERRATA_WA_DISABLE	0
#define ERRATA_WA_ENABLE	1

static struct dentry *debugfs_base;
static bool kryo_e74_e75_wa = true;

static void kryo_e74_e75_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;

	ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT, KRYO_ERRATA_74_75_ID),
				&desc);
	if (ret)
		pr_err("Failed to %s ERRATA_74_75 workaround\n",
			enable ? "enable" : "disable");
}

static int kryo_e74_e75_set(void *data, u64 val)
{
	if ((val && kryo_e74_e75_wa) || (!val && !kryo_e74_e75_wa))
		return 0;

	kryo_e74_e75_wa = !!val;

	get_cpu();
	on_each_cpu(kryo_e74_e75_scm, (void *)kryo_e74_e75_wa, 1);
	put_cpu();

	return 0;
}

static int kryo_e74_e75_get(void *data, u64 *val)
{
	*val = kryo_e74_e75_wa;
	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(kryo_e74_e75_fops, kryo_e74_e75_get,
			kryo_e74_e75_set, "%llu\n");

static int scm_errata_notifier_callback(struct notifier_block *nfb,
					unsigned long action, void *hcpu)
{
	switch (action & ~CPU_TASKS_FROZEN) {
	case CPU_STARTING:
		kryo_e74_e75_scm((void *)kryo_e74_e75_wa);
		break;
	}
	return 0;
}

static struct notifier_block scm_errata_notifier = {
	.notifier_call = scm_errata_notifier_callback,
};

static int __init scm_errata_init(void)
{
	int ret;

	debugfs_base = debugfs_create_dir("scm_errata", NULL);
	if (!debugfs_base)
		return -ENOMEM;

	if (!debugfs_create_file("kryo_e74_e75", S_IRUGO | S_IWUSR,
			debugfs_base, NULL, &kryo_e74_e75_fops))
		goto err;

	ret = register_hotcpu_notifier(&scm_errata_notifier);
	if (ret)
		goto err;

	return 0;
err:
	debugfs_remove_recursive(debugfs_base);
	return ret;
}
device_initcall(scm_errata_init);