arm64: power: Add new PSCI PowerOps provider
authorJulius Werner <jwerner@chromium.org>
Thu, 7 Jul 2016 23:57:43 +0000 (16:57 -0700)
committerchrome-bot <chrome-bot@chromium.org>
Fri, 8 Jul 2016 07:21:45 +0000 (00:21 -0700)
ARM64 systems are by design required to support power-off and reboot
functionality in ARM Trusted Firmware through PSCI calls. Rather than
reimplement the same functionality in depthcharge for every individual
board, we can leverage this by just calling the same code with an SMC.

This patch adds rudimentary SMC functionality to depthcharge and uses it
to implement a PSCI PowerOps provider using the SYSTEM_RESET and
SYSTEM_OFF PSCI calls to reboot and power down, respectively.

BRANCH=None
BUG=None
TEST=Triggered reboot and power-off reasons on Kevin, observed how
system reacted correctly (with follow-up patch).

Change-Id: I5983b19229cdaa3c8e8fb5e49c778d534d8acbb1
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/358922
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
src/arch/arm/Makefile.inc
src/arch/arm/smc.S [new file with mode: 0644]
src/arch/arm/smc.h [new file with mode: 0644]
src/drivers/power/Makefile.inc
src/drivers/power/psci.c [new file with mode: 0644]
src/drivers/power/psci.h [new file with mode: 0644]

index d01f849..ac228e7 100644 (file)
@@ -12,7 +12,7 @@
 ##
 
 ifeq ($(CONFIG_ARCH_ARM_V8),y)
-depthcharge-y += boot_asm64.S physmem_arm64.c boot64.c
+depthcharge-y += boot_asm64.S physmem_arm64.c boot64.c smc.S
 else
 depthcharge-y += boot_asm.S enter_trampoline.c physmem.c boot.c
 endif
diff --git a/src/arch/arm/smc.S b/src/arch/arm/smc.S
new file mode 100644 (file)
index 0000000..f3e90be
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+       .global smc
+       .type smc, function
+smc:
+       /* X0-X3 passed through as call parameters. X0 is always Function ID. */
+       smc     #0
+       ret                     /* X0 passed through as return value */
diff --git a/src/arch/arm/smc.h b/src/arch/arm/smc.h
new file mode 100644 (file)
index 0000000..22851d0
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_SMC_H__
+#define __ARCH_ARM_SMC_H__
+
+#include <stdint.h>
+
+// From ARM PSCI specification (ARM DEN 0022C). Expand as needed.
+enum psci_function_id {
+       PSCI_SYSTEM_OFF = 0x84000008,
+       PSCI_SYSTEM_RESET = 0x84000009,
+};
+
+// Conforms to ARM SMC Calling Convention (ARM DEN 0028A).
+uint64_t smc(uint64_t function_id, uint64_t arg1, uint64_t arg2, uint64_t arg3);
+
+#endif /* __ARCH_ARM_SMC_H__ */
index 10704b1..fcfc660 100644 (file)
@@ -23,3 +23,4 @@ depthcharge-$(CONFIG_DRIVER_POWER_MT6397) += mt6397.c
 depthcharge-$(CONFIG_DRIVER_POWER_ARMADA38X) += armada38x.c
 depthcharge-y += power.c
 depthcharge-y += sysinfo.c
+depthcharge-$(CONFIG_ARCH_ARM_V8) += psci.c
diff --git a/src/drivers/power/psci.c b/src/drivers/power/psci.c
new file mode 100644 (file)
index 0000000..7d15b2c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 <libpayload.h>
+
+#include "arch/arm/smc.h"
+#include "drivers/power/psci.h"
+
+static int psci_reset(PowerOps *me)
+{
+       smc(PSCI_SYSTEM_RESET, 0, 0, 0);
+       halt();
+}
+
+static int psci_off(PowerOps *me)
+{
+       smc(PSCI_SYSTEM_OFF, 0, 0, 0);
+       halt();
+}
+
+PowerOps psci_power_ops = {
+       .cold_reboot = &psci_reset,
+       .power_off = &psci_off,
+};
diff --git a/src/drivers/power/psci.h b/src/drivers/power/psci.h
new file mode 100644 (file)
index 0000000..bd833d6
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#ifndef __DRIVERS_POWER_PSCI_H__
+#define __DRIVERS_POWER_PSCI_H__
+
+#include "drivers/power/power.h"
+
+PowerOps psci_power_ops;
+
+#endif /* __DRIVERS_POWER_PSCI_H__ */