#define pr_fmt(fmt) "psci: " fmt
+#include <linux/arm-smccc.h>
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/of.h>
#include <linux/psci.h>
#include <linux/reboot.h>
#include <linux/suspend.h>
+#include <linux/regulator/machine.h>
#include <uapi/linux/psci.h>
typedef unsigned long (psci_fn)(unsigned long, unsigned long,
unsigned long, unsigned long);
-asmlinkage psci_fn __invoke_psci_fn_hvc;
-asmlinkage psci_fn __invoke_psci_fn_smc;
static psci_fn *invoke_psci_fn;
enum psci_function {
return !(state & ~valid_mask);
}
+static unsigned long __invoke_psci_fn_hvc(unsigned long function_id,
+ unsigned long arg0, unsigned long arg1,
+ unsigned long arg2)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_hvc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ return res.a0;
+}
+
+static unsigned long __invoke_psci_fn_smc(unsigned long function_id,
+ unsigned long arg0, unsigned long arg1,
+ unsigned long arg2)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ return res.a0;
+}
+
static int psci_to_linux_errno(int errno)
{
switch (errno) {
return cpu_suspend(0, psci_system_suspend);
}
+static int psci_system_suspend_prepare(void)
+{
+ return regulator_suspend_prepare(PM_SUSPEND_MEM);
+}
+
+static void psci_system_suspend_finish(void)
+{
+ int ret;
+
+ ret = regulator_suspend_finish();
+ if (ret < 0)
+ pr_warn("regulator_suspend_finish failed (%d)\n", ret);
+}
+
static const struct platform_suspend_ops psci_suspend_ops = {
.valid = suspend_valid_only_mem,
.enter = psci_system_suspend_enter,
+ .prepare = psci_system_suspend_prepare,
+ .finish = psci_system_suspend_finish,
};
static void __init psci_init_system_suspend(void)