summaryrefslogtreecommitdiff
path: root/sys/arch/armv7
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2016-10-09 23:46:24 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2016-10-09 23:46:24 +0000
commit9a464c85a407c0dc5cba952a1c4f8ac4565750d4 (patch)
tree101a821b6de0d52e93b9c7635108593099c110aa /sys/arch/armv7
parent7da283ab139fd9e6cb2e387853f7eacd15455a19 (diff)
Add psci(4) a driver for the reset and power down portion of the
ARM Power State Coordination Interface (PSCI) specification. Tested with qemu-system-arm -M virt. Feedback from patrick@, ok kettenis@ tom@
Diffstat (limited to 'sys/arch/armv7')
-rw-r--r--sys/arch/armv7/armv7/armv7_start.S11
-rw-r--r--sys/arch/armv7/conf/GENERIC4
-rw-r--r--sys/arch/armv7/conf/RAMDISK4
-rw-r--r--sys/arch/armv7/conf/files.armv76
-rw-r--r--sys/arch/armv7/dev/psci.c101
5 files changed, 122 insertions, 4 deletions
diff --git a/sys/arch/armv7/armv7/armv7_start.S b/sys/arch/armv7/armv7/armv7_start.S
index 058e7ef6286..1db3e58dde3 100644
--- a/sys/arch/armv7/armv7/armv7_start.S
+++ b/sys/arch/armv7/armv7/armv7_start.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: armv7_start.S,v 1.11 2016/10/09 11:01:31 jsg Exp $ */
+/* $OpenBSD: armv7_start.S,v 1.12 2016/10/09 23:46:23 jsg Exp $ */
/* $NetBSD: lubbock_start.S,v 1.1 2003/06/18 10:51:15 bsh Exp $ */
/*
@@ -40,6 +40,7 @@
#define ELR .long 0xe12ef30e @ msr ELR_hyp, lr
#define ERET .long 0xe160006e @ eret
+#define HVC .word 0xe1400070 @ hvc
/*
* CPWAIT -- Canonical method to wait for CP15 update.
@@ -193,6 +194,14 @@ mmu_init_table2:
.text
+ENTRY(smc_call)
+ smc #0
+ bx lr
+
+ENTRY(hvc_call)
+ HVC
+ bx lr
+
/*-
* Copyright (c) 2011
* Ben Gray <ben.r.gray@gmail.com>.
diff --git a/sys/arch/armv7/conf/GENERIC b/sys/arch/armv7/conf/GENERIC
index 2dbf06b8e91..c484c0ba99d 100644
--- a/sys/arch/armv7/conf/GENERIC
+++ b/sys/arch/armv7/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.65 2016/10/09 11:14:22 kettenis Exp $
+# $OpenBSD: GENERIC,v 1.66 2016/10/09 23:46:23 jsg Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -109,6 +109,8 @@ pluart* at fdt?
plrtc* at fdt?
virtio* at fdt?
+psci* at fdt?
+
# Exynos
exynos0 at mainbus?
exdisplay* at exynos?
diff --git a/sys/arch/armv7/conf/RAMDISK b/sys/arch/armv7/conf/RAMDISK
index 5885873a71a..85530fca867 100644
--- a/sys/arch/armv7/conf/RAMDISK
+++ b/sys/arch/armv7/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.60 2016/10/09 11:14:22 kettenis Exp $
+# $OpenBSD: RAMDISK,v 1.61 2016/10/09 23:46:23 jsg Exp $
machine armv7 arm
@@ -107,6 +107,8 @@ pluart* at fdt?
plrtc* at fdt?
virtio* at fdt?
+psci* at fdt?
+
# Exynos
exynos0 at mainbus?
exdisplay* at exynos?
diff --git a/sys/arch/armv7/conf/files.armv7 b/sys/arch/armv7/conf/files.armv7
index 02dca442ecc..81e754ebf0a 100644
--- a/sys/arch/armv7/conf/files.armv7
+++ b/sys/arch/armv7/conf/files.armv7
@@ -1,4 +1,4 @@
-# $OpenBSD: files.armv7,v 1.27 2016/10/07 07:24:21 patrick Exp $
+# $OpenBSD: files.armv7,v 1.28 2016/10/09 23:46:23 jsg Exp $
maxpartitions 16
maxusers 2 8 64
@@ -87,3 +87,7 @@ file arch/armv7/dev/pluart.c pluart
device plrtc
attach plrtc at fdt
file arch/armv7/dev/plrtc.c plrtc
+
+device psci
+attach psci at fdt
+file arch/armv7/dev/psci.c psci
diff --git a/sys/arch/armv7/dev/psci.c b/sys/arch/armv7/dev/psci.c
new file mode 100644
index 00000000000..83f119b0954
--- /dev/null
+++ b/sys/arch/armv7/dev/psci.c
@@ -0,0 +1,101 @@
+/* $OpenBSD: psci.c,v 1.1 2016/10/09 23:46:23 jsg Exp $ */
+
+/*
+ * Copyright (c) 2016 Jonathan Gray <jsg@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <armv7/armv7/armv7var.h>
+#include <armv7/armv7/armv7_machdep.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+#define SYSTEM_OFF 0x84000008
+#define SYSTEM_RESET 0x84000009
+
+struct psci_softc {
+ struct device sc_dev;
+ void (*callfn)(uint32_t, uint32_t, uint32_t, uint32_t);
+};
+
+struct psci_softc *psci_sc;
+
+int psci_match(struct device *, void *, void *);
+void psci_attach(struct device *, struct device *, void *);
+void psci_reset(void);
+void psci_powerdown(void);
+
+extern void hvc_call(uint32_t, uint32_t, uint32_t, uint32_t);
+extern void smc_call(uint32_t, uint32_t, uint32_t, uint32_t);
+
+struct cfattach psci_ca = {
+ sizeof(struct psci_softc), psci_match, psci_attach
+};
+
+struct cfdriver psci_cd = {
+ NULL, "psci", DV_DULL
+};
+
+int
+psci_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ /* reset and shutdown added in 0.2 */
+ return OF_is_compatible(faa->fa_node, "arm,psci-0.2");
+}
+
+void
+psci_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct psci_softc *sc = (struct psci_softc *) self;
+ struct fdt_attach_args *faa = aux;
+ char method[128];
+
+ if (OF_getprop(faa->fa_node, "method", method, sizeof(method))) {
+ if (strcmp(method, "hvc") == 0)
+ sc->callfn = hvc_call;
+ else if (strcmp(method, "smc") == 0)
+ sc->callfn = smc_call;
+ }
+
+ printf("\n");
+
+ psci_sc = sc;
+ cpuresetfn = psci_reset;
+ powerdownfn = psci_powerdown;
+}
+
+void
+psci_reset(void)
+{
+ struct psci_softc *sc = psci_sc;
+ if (sc->callfn)
+ (*sc->callfn)(SYSTEM_RESET, 0, 0, 0);
+}
+
+void
+psci_powerdown(void)
+{
+ struct psci_softc *sc = psci_sc;
+ if (sc->callfn)
+ (*sc->callfn)(SYSTEM_OFF, 0, 0, 0);
+}