diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c index 26050e768ce8..e5a337e29fdb 100644 --- a/sys/arm64/arm64/vm_machdep.c +++ b/sys/arm64/arm64/vm_machdep.c @@ -1,266 +1,276 @@ /*- * Copyright (c) 2014 Andrew Turner * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ +#include "opt_platform.h" + #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef VFP #include #endif +#ifdef DEV_PSCI +#include +#endif + /* * Finish a fork operation, with process p2 nearly set up. * Copy and update the pcb, set up the stack so that the child * ready to run and return to user mode. */ void cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) { struct pcb *pcb2; struct trapframe *tf; if ((flags & RFPROC) == 0) return; if (td1 == curthread) { /* * Save the tpidr_el0 and the vfp state, these normally happen * in cpu_switch, but if userland changes these then forks * this may not have happened. */ td1->td_pcb->pcb_tpidr_el0 = READ_SPECIALREG(tpidr_el0); #ifdef VFP if ((td1->td_pcb->pcb_fpflags & PCB_FP_STARTED) != 0) vfp_save_state(td1, td1->td_pcb); #endif } pcb2 = (struct pcb *)(td2->td_kstack + td2->td_kstack_pages * PAGE_SIZE) - 1; td2->td_pcb = pcb2; bcopy(td1->td_pcb, pcb2, sizeof(*pcb2)); td2->td_pcb->pcb_l0addr = vtophys(vmspace_pmap(td2->td_proc->p_vmspace)->pm_l0); tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1); bcopy(td1->td_frame, tf, sizeof(*tf)); tf->tf_x[0] = 0; tf->tf_x[1] = 0; tf->tf_spsr = 0; td2->td_frame = tf; /* Set the return value registers for fork() */ td2->td_pcb->pcb_x[8] = (uintptr_t)fork_return; td2->td_pcb->pcb_x[9] = (uintptr_t)td2; td2->td_pcb->pcb_x[PCB_LR] = (uintptr_t)fork_trampoline; td2->td_pcb->pcb_sp = (uintptr_t)td2->td_frame; td2->td_pcb->pcb_fpusaved = &td2->td_pcb->pcb_fpustate; td2->td_pcb->pcb_vfpcpu = UINT_MAX; /* Setup to release spin count in fork_exit(). */ td2->td_md.md_spinlock_count = 1; td2->td_md.md_saved_daif = 0; } void cpu_reset(void) { - printf("cpu_reset"); +#ifdef DEV_PSCI + psci_reset(); +#endif + + printf("cpu_reset failed"); while(1) __asm volatile("wfi" ::: "memory"); } void cpu_thread_swapin(struct thread *td) { } void cpu_thread_swapout(struct thread *td) { } void cpu_set_syscall_retval(struct thread *td, int error) { struct trapframe *frame; frame = td->td_frame; switch (error) { case 0: frame->tf_x[0] = td->td_retval[0]; frame->tf_x[1] = td->td_retval[1]; frame->tf_spsr &= ~PSR_C; /* carry bit */ break; case ERESTART: frame->tf_elr -= 4; break; case EJUSTRETURN: break; default: frame->tf_spsr |= PSR_C; /* carry bit */ frame->tf_x[0] = error; break; } } /* * Initialize machine state, mostly pcb and trap frame for a new * thread, about to return to userspace. Put enough state in the new * thread's PCB to get it to go back to the fork_return(), which * finalizes the thread state and handles peculiarities of the first * return to userspace for the new thread. */ void cpu_copy_thread(struct thread *td, struct thread *td0) { bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe)); bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb)); td->td_pcb->pcb_x[8] = (uintptr_t)fork_return; td->td_pcb->pcb_x[9] = (uintptr_t)td; td->td_pcb->pcb_x[PCB_LR] = (uintptr_t)fork_trampoline; td->td_pcb->pcb_sp = (uintptr_t)td->td_frame; td->td_pcb->pcb_fpusaved = &td->td_pcb->pcb_fpustate; td->td_pcb->pcb_vfpcpu = UINT_MAX; /* Setup to release spin count in fork_exit(). */ td->td_md.md_spinlock_count = 1; td->td_md.md_saved_daif = 0; } /* * Set that machine state for performing an upcall that starts * the entry function with the given argument. */ void cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg, stack_t *stack) { struct trapframe *tf = td->td_frame; tf->tf_sp = STACKALIGN((uintptr_t)stack->ss_sp + stack->ss_size); tf->tf_elr = (register_t)entry; tf->tf_x[0] = (register_t)arg; } int cpu_set_user_tls(struct thread *td, void *tls_base) { struct pcb *pcb; if ((uintptr_t)tls_base >= VM_MAXUSER_ADDRESS) return (EINVAL); pcb = td->td_pcb; pcb->pcb_tpidr_el0 = (register_t)tls_base; if (td == curthread) WRITE_SPECIALREG(tpidr_el0, tls_base); return (0); } void cpu_thread_exit(struct thread *td) { } void cpu_thread_alloc(struct thread *td) { td->td_pcb = (struct pcb *)(td->td_kstack + td->td_kstack_pages * PAGE_SIZE) - 1; td->td_frame = (struct trapframe *)STACKALIGN( td->td_pcb - 1); } void cpu_thread_free(struct thread *td) { } void cpu_thread_clean(struct thread *td) { } /* * Intercept the return address from a freshly forked process that has NOT * been scheduled yet. * * This is needed to make kernel threads stay in kernel mode. */ void cpu_fork_kthread_handler(struct thread *td, void (*func)(void *), void *arg) { td->td_pcb->pcb_x[8] = (uintptr_t)func; td->td_pcb->pcb_x[9] = (uintptr_t)arg; td->td_pcb->pcb_x[PCB_LR] = (uintptr_t)fork_trampoline; td->td_pcb->pcb_sp = (uintptr_t)td->td_frame; td->td_pcb->pcb_fpusaved = &td->td_pcb->pcb_fpustate; td->td_pcb->pcb_vfpcpu = UINT_MAX; } void cpu_exit(struct thread *td) { } void swi_vm(void *v) { if (busdma_swi_pending != 0) busdma_swi(); } diff --git a/sys/conf/options.arm64 b/sys/conf/options.arm64 index ad68292d61fc..29a20c533fc4 100644 --- a/sys/conf/options.arm64 +++ b/sys/conf/options.arm64 @@ -1,14 +1,16 @@ # $FreeBSD$ ARM64 opt_global.h INTRNG opt_global.h SOCDEV_PA opt_global.h SOCDEV_VA opt_global.h THUNDERX_PASS_1_1_ERRATA opt_global.h VFP opt_global.h +DEV_PSCI opt_platform.h + # SoC Support SOC_ALLWINNER_A64 opt_soc.h SOC_BRCM_BCM2837 opt_soc.h SOC_CAVM_THUNDERX opt_soc.h SOC_HISI_HI6220 opt_soc.h diff --git a/sys/dev/psci/psci.c b/sys/dev/psci/psci.c index 4452fb45955d..4ae97eccc45a 100644 --- a/sys/dev/psci/psci.c +++ b/sys/dev/psci/psci.c @@ -1,502 +1,509 @@ /*- * Copyright (c) 2014 Robin Randhawa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * This implements support for ARM's Power State Co-ordination Interface * [PSCI]. The implementation adheres to version 0.2 of the PSCI specification * but also supports v0.1. PSCI standardizes operations such as system reset, CPU * on/off/suspend. PSCI requires a compliant firmware implementation. * * The PSCI specification used for this implementation is available at: * * . * * TODO: * - Add support for remaining PSCI calls [this implementation only * supports get_version, system_reset and cpu_on]. */ #include __FBSDID("$FreeBSD$"); #include "opt_acpi.h" #include "opt_platform.h" #include #include #include #include #include #include #include #include #include #ifdef DEV_ACPI #include #include #endif #ifdef FDT #include #include #include #include #endif #include struct psci_softc { device_t dev; psci_callfn_t psci_call; uint32_t psci_fnids[PSCI_FN_MAX]; }; #ifdef FDT static int psci_v0_1_init(device_t dev); #endif static int psci_v0_2_init(device_t dev); struct psci_softc *psci_softc = NULL; #ifdef __arm__ #define USE_ACPI 0 #define USE_FDT 1 #elif defined(__aarch64__) #define USE_ACPI (arm64_bus_method == ARM64_BUS_ACPI) #define USE_FDT (arm64_bus_method == ARM64_BUS_FDT) #else #error Unknown architecture #endif #ifdef FDT static struct ofw_compat_data compat_data[] = { {"arm,psci-0.2", (uintptr_t)psci_v0_2_init}, {"arm,psci", (uintptr_t)psci_v0_1_init}, {NULL, 0} }; #endif static int psci_attach(device_t, psci_initfn_t); static void psci_shutdown(void *, int); #ifdef FDT static int psci_fdt_probe(device_t dev); static int psci_fdt_attach(device_t dev); static device_method_t psci_fdt_methods[] = { DEVMETHOD(device_probe, psci_fdt_probe), DEVMETHOD(device_attach, psci_fdt_attach), DEVMETHOD_END }; static driver_t psci_fdt_driver = { "psci", psci_fdt_methods, sizeof(struct psci_softc), }; static devclass_t psci_fdt_devclass; EARLY_DRIVER_MODULE(psci, simplebus, psci_fdt_driver, psci_fdt_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_FIRST); EARLY_DRIVER_MODULE(psci, ofwbus, psci_fdt_driver, psci_fdt_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_FIRST); static psci_callfn_t psci_fdt_get_callfn(phandle_t node) { char method[16]; if ((OF_getprop(node, "method", method, sizeof(method))) > 0) { if (strcmp(method, "hvc") == 0) return (psci_hvc_despatch); else if (strcmp(method, "smc") == 0) return (psci_smc_despatch); else printf("psci: PSCI conduit \"%s\" invalid\n", method); } else printf("psci: PSCI conduit not supplied in the device tree\n"); return (NULL); } static int psci_fdt_probe(device_t dev) { const struct ofw_compat_data *ocd; if (!ofw_bus_status_okay(dev)) return (ENXIO); ocd = ofw_bus_search_compatible(dev, compat_data); if (ocd->ocd_str == NULL) return (ENXIO); device_set_desc(dev, "ARM Power State Co-ordination Interface Driver"); return (BUS_PROBE_SPECIFIC); } static int psci_fdt_attach(device_t dev) { struct psci_softc *sc = device_get_softc(dev); const struct ofw_compat_data *ocd; psci_initfn_t psci_init; phandle_t node; ocd = ofw_bus_search_compatible(dev, compat_data); psci_init = (psci_initfn_t)ocd->ocd_data; node = ofw_bus_get_node(dev); sc->psci_call = psci_fdt_get_callfn(node); return (psci_attach(dev, psci_init)); } #endif #ifdef DEV_ACPI static void psci_acpi_identify(driver_t *, device_t); static int psci_acpi_probe(device_t); static int psci_acpi_attach(device_t); static device_method_t psci_acpi_methods[] = { /* Device interface */ DEVMETHOD(device_identify, psci_acpi_identify), DEVMETHOD(device_probe, psci_acpi_probe), DEVMETHOD(device_attach, psci_acpi_attach), DEVMETHOD_END }; static driver_t psci_acpi_driver = { "psci", psci_acpi_methods, sizeof(struct psci_softc), }; static devclass_t psci_acpi_devclass; EARLY_DRIVER_MODULE(psci, acpi, psci_acpi_driver, psci_acpi_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_FIRST); static int psci_acpi_bootflags(void) { ACPI_TABLE_FADT *fadt; vm_paddr_t physaddr; int flags; physaddr = acpi_find_table(ACPI_SIG_FADT); if (physaddr == 0) return (0); fadt = acpi_map_table(physaddr, ACPI_SIG_FADT); if (fadt == NULL) { printf("psci: Unable to map the FADT\n"); return (0); } flags = fadt->ArmBootFlags; acpi_unmap_table(fadt); return (flags); } static psci_callfn_t psci_acpi_get_callfn(int flags) { if ((flags & ACPI_FADT_PSCI_COMPLIANT) != 0) { if ((flags & ACPI_FADT_PSCI_USE_HVC) != 0) return (psci_hvc_despatch); else return (psci_smc_despatch); } else { printf("psci: PSCI conduit not supplied in the device tree\n"); } return (NULL); } static void psci_acpi_identify(driver_t *driver, device_t parent) { device_t dev; int flags; flags = psci_acpi_bootflags(); if ((flags & ACPI_FADT_PSCI_COMPLIANT) != 0) { dev = BUS_ADD_CHILD(parent, BUS_PASS_CPU + BUS_PASS_ORDER_FIRST, "psci", -1); if (dev != NULL) acpi_set_private(dev, (void *)(uintptr_t)flags); } } static int psci_acpi_probe(device_t dev) { uintptr_t flags; flags = (uintptr_t)acpi_get_private(dev); if ((flags & ACPI_FADT_PSCI_COMPLIANT) == 0) return (ENXIO); device_set_desc(dev, "ARM Power State Co-ordination Interface Driver"); return (BUS_PROBE_SPECIFIC); } static int psci_acpi_attach(device_t dev) { struct psci_softc *sc = device_get_softc(dev); uintptr_t flags; flags = (uintptr_t)acpi_get_private(dev); if ((flags & ACPI_FADT_PSCI_USE_HVC) != 0) sc->psci_call = psci_hvc_despatch; else sc->psci_call = psci_smc_despatch; return (psci_attach(dev, psci_v0_2_init)); } #endif static int psci_attach(device_t dev, psci_initfn_t psci_init) { struct psci_softc *sc = device_get_softc(dev); if (psci_softc != NULL) return (ENXIO); if (sc->psci_call == NULL) return (ENXIO); KASSERT(psci_init != NULL, ("PSCI init function cannot be NULL")); if (psci_init(dev)) return (ENXIO); psci_softc = sc; return (0); } static int psci_get_version(struct psci_softc *sc) { uint32_t fnid; /* PSCI version wasn't supported in v0.1. */ fnid = sc->psci_fnids[PSCI_FN_VERSION]; if (fnid) return (sc->psci_call(fnid, 0, 0, 0)); return (PSCI_RETVAL_NOT_SUPPORTED); } #ifdef FDT static int psci_fdt_callfn(psci_callfn_t *callfn) { phandle_t node; node = ofw_bus_find_compatible(OF_peer(0), "arm,psci-0.2"); if (node == 0) /* TODO: Handle psci 0.1 */ return (PSCI_MISSING); *callfn = psci_fdt_get_callfn(node); return (0); } #endif #ifdef DEV_ACPI static int psci_acpi_callfn(psci_callfn_t *callfn) { int flags; flags = psci_acpi_bootflags(); if ((flags & ACPI_FADT_PSCI_COMPLIANT) == 0) return (PSCI_MISSING); *callfn = psci_acpi_get_callfn(flags); return (0); } #endif int psci_cpu_on(unsigned long cpu, unsigned long entry, unsigned long context_id) { psci_callfn_t callfn; uint32_t fnid; int error; if (psci_softc == NULL) { fnid = PSCI_FNID_CPU_ON; callfn = NULL; #ifdef FDT if (USE_FDT) { error = psci_fdt_callfn(&callfn); if (error != 0) return (error); } #endif #ifdef DEV_ACPI if (callfn == NULL && USE_ACPI) { error = psci_acpi_callfn(&callfn); if (error != 0) return (error); } #endif if (callfn == NULL) return (PSCI_MISSING); } else { callfn = psci_softc->psci_call; fnid = psci_softc->psci_fnids[PSCI_FN_CPU_ON]; } /* PSCI v0.1 and v0.2 both support cpu_on. */ return (callfn(fnid, cpu, entry, context_id)); } static void psci_shutdown(void *xsc, int howto) { uint32_t fn = 0; if (psci_softc == NULL) return; /* PSCI system_off and system_reset werent't supported in v0.1. */ if ((howto & RB_POWEROFF) != 0) fn = psci_softc->psci_fnids[PSCI_FN_SYSTEM_OFF]; else if ((howto & RB_HALT) == 0) fn = psci_softc->psci_fnids[PSCI_FN_SYSTEM_RESET]; if (fn) psci_softc->psci_call(fn, 0, 0, 0); /* System reset and off do not return. */ } +void +psci_reset(void) +{ + + psci_shutdown(NULL, 0); +} + #ifdef FDT /* Only support PSCI 0.1 on FDT */ static int psci_v0_1_init(device_t dev) { struct psci_softc *sc = device_get_softc(dev); int psci_fn; uint32_t psci_fnid; phandle_t node; int len; /* Zero out the function ID table - Is this needed ? */ for (psci_fn = PSCI_FN_VERSION, psci_fnid = PSCI_FNID_VERSION; psci_fn < PSCI_FN_MAX; psci_fn++, psci_fnid++) sc->psci_fnids[psci_fn] = 0; /* PSCI v0.1 doesn't specify function IDs. Get them from DT */ node = ofw_bus_get_node(dev); if ((len = OF_getproplen(node, "cpu_suspend")) > 0) { OF_getencprop(node, "cpu_suspend", &psci_fnid, len); sc->psci_fnids[PSCI_FN_CPU_SUSPEND] = psci_fnid; } if ((len = OF_getproplen(node, "cpu_on")) > 0) { OF_getencprop(node, "cpu_on", &psci_fnid, len); sc->psci_fnids[PSCI_FN_CPU_ON] = psci_fnid; } if ((len = OF_getproplen(node, "cpu_off")) > 0) { OF_getencprop(node, "cpu_off", &psci_fnid, len); sc->psci_fnids[PSCI_FN_CPU_OFF] = psci_fnid; } if ((len = OF_getproplen(node, "migrate")) > 0) { OF_getencprop(node, "migrate", &psci_fnid, len); sc->psci_fnids[PSCI_FN_MIGRATE] = psci_fnid; } if (bootverbose) device_printf(dev, "PSCI version 0.1 available\n"); return(0); } #endif static int psci_v0_2_init(device_t dev) { struct psci_softc *sc = device_get_softc(dev); int version; /* PSCI v0.2 specifies explicit function IDs. */ sc->psci_fnids[PSCI_FN_VERSION] = PSCI_FNID_VERSION; sc->psci_fnids[PSCI_FN_CPU_SUSPEND] = PSCI_FNID_CPU_SUSPEND; sc->psci_fnids[PSCI_FN_CPU_OFF] = PSCI_FNID_CPU_OFF; sc->psci_fnids[PSCI_FN_CPU_ON] = PSCI_FNID_CPU_ON; sc->psci_fnids[PSCI_FN_AFFINITY_INFO] = PSCI_FNID_AFFINITY_INFO; sc->psci_fnids[PSCI_FN_MIGRATE] = PSCI_FNID_MIGRATE; sc->psci_fnids[PSCI_FN_MIGRATE_INFO_TYPE] = PSCI_FNID_MIGRATE_INFO_TYPE; sc->psci_fnids[PSCI_FN_MIGRATE_INFO_UP_CPU] = PSCI_FNID_MIGRATE_INFO_UP_CPU; sc->psci_fnids[PSCI_FN_SYSTEM_OFF] = PSCI_FNID_SYSTEM_OFF; sc->psci_fnids[PSCI_FN_SYSTEM_RESET] = PSCI_FNID_SYSTEM_RESET; version = psci_get_version(sc); if (version == PSCI_RETVAL_NOT_SUPPORTED) return (1); if ((PSCI_VER_MAJOR(version) == 0 && PSCI_VER_MINOR(version) == 2) || (PSCI_VER_MAJOR(version) == 1 && PSCI_VER_MINOR(version) == 0)) { if (bootverbose) device_printf(dev, "PSCI version 0.2 available\n"); /* * We only register this for v0.2 since v0.1 doesn't support * system_reset. */ EVENTHANDLER_REGISTER(shutdown_final, psci_shutdown, sc, SHUTDOWN_PRI_LAST); return (0); } device_printf(dev, "PSCI version number mismatched with DT\n"); return (1); } diff --git a/sys/dev/psci/psci.h b/sys/dev/psci/psci.h index 7f447abaf444..af777bb6c380 100644 --- a/sys/dev/psci/psci.h +++ b/sys/dev/psci/psci.h @@ -1,106 +1,106 @@ /*- * Copyright (c) 2013, 2014 Robin Randhawa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_PSCI_H_ #define _MACHINE_PSCI_H_ #include typedef int (*psci_initfn_t)(device_t dev); typedef int (*psci_callfn_t)(register_t, register_t, register_t, register_t); extern int psci_present; -void psci_system_reset(void); +void psci_reset(void); int psci_cpu_on(unsigned long, unsigned long, unsigned long); int psci_hvc_despatch(register_t, register_t, register_t, register_t); int psci_smc_despatch(register_t, register_t, register_t, register_t); /* * PSCI return codes. */ #define PSCI_RETVAL_SUCCESS 0 #define PSCI_RETVAL_NOT_SUPPORTED -1 #define PSCI_RETVAL_INVALID_PARAMS -2 #define PSCI_RETVAL_DENIED -3 #define PSCI_RETVAL_ALREADY_ON -4 #define PSCI_RETVAL_ON_PENDING -5 #define PSCI_RETVAL_INTERNAL_FAILURE -6 #define PSCI_RETVAL_NOT_PRESENT -7 #define PSCI_RETVAL_DISABLED -8 /* * Used to signal PSCI is not available, e.g. to start a CPU. */ #define PSCI_MISSING 1 /* * PSCI function codes (as per PSCI v0.2). */ #ifdef __aarch64__ #define PSCI_FNID_VERSION 0x84000000 #define PSCI_FNID_CPU_SUSPEND 0xc4000001 #define PSCI_FNID_CPU_OFF 0x84000002 #define PSCI_FNID_CPU_ON 0xc4000003 #define PSCI_FNID_AFFINITY_INFO 0xc4000004 #define PSCI_FNID_MIGRATE 0xc4000005 #define PSCI_FNID_MIGRATE_INFO_TYPE 0x84000006 #define PSCI_FNID_MIGRATE_INFO_UP_CPU 0xc4000007 #define PSCI_FNID_SYSTEM_OFF 0x84000008 #define PSCI_FNID_SYSTEM_RESET 0x84000009 #else #define PSCI_FNID_VERSION 0x84000000 #define PSCI_FNID_CPU_SUSPEND 0x84000001 #define PSCI_FNID_CPU_OFF 0x84000002 #define PSCI_FNID_CPU_ON 0x84000003 #define PSCI_FNID_AFFINITY_INFO 0x84000004 #define PSCI_FNID_MIGRATE 0x84000005 #define PSCI_FNID_MIGRATE_INFO_TYPE 0x84000006 #define PSCI_FNID_MIGRATE_INFO_UP_CPU 0x84000007 #define PSCI_FNID_SYSTEM_OFF 0x84000008 #define PSCI_FNID_SYSTEM_RESET 0x84000009 #endif #define PSCI_VER_MAJOR(v) (((v) >> 16) & 0xFF) #define PSCI_VER_MINOR(v) ((v) & 0xFF) enum psci_fn { PSCI_FN_VERSION, PSCI_FN_CPU_SUSPEND, PSCI_FN_CPU_OFF, PSCI_FN_CPU_ON, PSCI_FN_AFFINITY_INFO, PSCI_FN_MIGRATE, PSCI_FN_MIGRATE_INFO_TYPE, PSCI_FN_MIGRATE_INFO_UP_CPU, PSCI_FN_SYSTEM_OFF, PSCI_FN_SYSTEM_RESET, PSCI_FN_MAX }; #endif /* _MACHINE_PSCI_H_ */