diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2016-10-09 23:46:24 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2016-10-09 23:46:24 +0000 |
commit | 9a464c85a407c0dc5cba952a1c4f8ac4565750d4 (patch) | |
tree | 101a821b6de0d52e93b9c7635108593099c110aa /sys/arch/armv7 | |
parent | 7da283ab139fd9e6cb2e387853f7eacd15455a19 (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.S | 11 | ||||
-rw-r--r-- | sys/arch/armv7/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/armv7/conf/RAMDISK | 4 | ||||
-rw-r--r-- | sys/arch/armv7/conf/files.armv7 | 6 | ||||
-rw-r--r-- | sys/arch/armv7/dev/psci.c | 101 |
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); +} |