From 6ea9e158f5cdb97b7137cc1d67f145ec0b39b845 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Jirman?= <megi@xff.cz>
Date: Sat, 2 Nov 2019 15:14:10 +0100
Subject: [PATCH 128/463] firmware: scpi: Add support for sending a
 SCPI_CMD_SET_SYS_PWR_STATE msg

This is NOT the right message to signal SCP we want to suspend the
system, but we use it anyway, because we simply want to do a fixed
function suspend sequence, instead of more complicated and granular
cluster/cpu/system power management.

Normally we'd signal system suspend by sending a CSS power state
message. I guess that can be done later, if wanted.

For now, Linux will kill all secondary CPU cores via MCPM, and SCP
will kill the last CPU, and suspend the system.

Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
 drivers/firmware/arm_scpi.c   | 10 ++++++++++
 include/linux/scpi_protocol.h |  1 +
 2 files changed, 11 insertions(+)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 94a6b4e667de1..5f3a6422b02c6 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -187,6 +187,7 @@ enum scpi_drv_cmds {
 	CMD_SENSOR_VALUE,
 	CMD_SET_DEVICE_PWR_STATE,
 	CMD_GET_DEVICE_PWR_STATE,
+	CMD_SET_SYS_PWR_STATE,
 	CMD_MAX_COUNT,
 };
 
@@ -203,6 +204,7 @@ static int scpi_std_commands[CMD_MAX_COUNT] = {
 	SCPI_CMD_SENSOR_VALUE,
 	SCPI_CMD_SET_DEVICE_PWR_STATE,
 	SCPI_CMD_GET_DEVICE_PWR_STATE,
+	SCPI_CMD_SET_SYS_PWR_STATE,
 };
 
 static int scpi_legacy_commands[CMD_MAX_COUNT] = {
@@ -218,6 +220,7 @@ static int scpi_legacy_commands[CMD_MAX_COUNT] = {
 	LEGACY_SCPI_CMD_SENSOR_VALUE,
 	-1, /* SET_DEVICE_PWR_STATE */
 	-1, /* GET_DEVICE_PWR_STATE */
+	LEGACY_SCPI_CMD_SYS_PWR_STATE,
 };
 
 struct scpi_xfer {
@@ -782,6 +785,12 @@ static int scpi_device_set_power_state(u16 dev_id, u8 pstate)
 				 sizeof(dev_set), &stat, sizeof(stat));
 }
 
+static int scpi_sys_set_power_state(u8 pstate)
+{
+	return scpi_send_message(CMD_SET_SYS_PWR_STATE, &pstate,
+				 sizeof(pstate), NULL, 0);
+}
+
 static struct scpi_ops scpi_ops = {
 	.get_version = scpi_get_version,
 	.clk_get_range = scpi_clk_get_range,
@@ -798,6 +807,7 @@ static struct scpi_ops scpi_ops = {
 	.sensor_get_value = scpi_sensor_get_value,
 	.device_get_power_state = scpi_device_get_power_state,
 	.device_set_power_state = scpi_device_set_power_state,
+	.sys_set_power_state = scpi_sys_set_power_state,
 };
 
 struct scpi_ops *get_scpi_ops(void)
diff --git a/include/linux/scpi_protocol.h b/include/linux/scpi_protocol.h
index d2176a56828a4..6169348c3b72d 100644
--- a/include/linux/scpi_protocol.h
+++ b/include/linux/scpi_protocol.h
@@ -76,6 +76,7 @@ struct scpi_ops {
 	int (*sensor_get_value)(u16, u64 *);
 	int (*device_get_power_state)(u16);
 	int (*device_set_power_state)(u16, u8);
+	int (*sys_set_power_state)(u8);
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCPI_PROTOCOL)
-- 
2.46.0

