1 /* 2 * PSCI API 3 * From arch/arm[64]/kernel/psci.c 4 * 5 * Copyright (C) 2015, Red Hat Inc, Andrew Jones <drjones@redhat.com> 6 * 7 * This work is licensed under the terms of the GNU LGPL, version 2. 8 */ 9 #include <asm/psci.h> 10 #include <asm/setup.h> 11 #include <asm/page.h> 12 #include <asm/smp.h> 13 14 __attribute__((noinline)) 15 int psci_invoke(unsigned long function_id, unsigned long arg0, 16 unsigned long arg1, unsigned long arg2) 17 { 18 asm volatile( 19 "hvc #0" 20 : "+r" (function_id) 21 : "r" (arg0), "r" (arg1), "r" (arg2)); 22 return function_id; 23 } 24 25 int psci_cpu_on(unsigned long cpuid, unsigned long entry_point) 26 { 27 #ifdef __arm__ 28 return psci_invoke(PSCI_0_2_FN_CPU_ON, cpuid, entry_point, 0); 29 #else 30 return psci_invoke(PSCI_0_2_FN64_CPU_ON, cpuid, entry_point, 0); 31 #endif 32 } 33 34 extern void secondary_entry(void); 35 int cpu_psci_cpu_boot(unsigned int cpu) 36 { 37 int err = psci_cpu_on(cpus[cpu], __pa(secondary_entry)); 38 if (err) 39 printf("failed to boot CPU%d (%d)\n", cpu, err); 40 return err; 41 } 42 43 void cpu_psci_cpu_die(void) 44 { 45 int err = psci_invoke(PSCI_0_2_FN_CPU_OFF, 0, 0, 0); 46 printf("CPU%d unable to power off (error = %d)\n", smp_processor_id(), err); 47 } 48 49 void psci_system_reset(void) 50 { 51 psci_invoke(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0); 52 } 53 54 void psci_system_off(void) 55 { 56 int err = psci_invoke(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); 57 printf("CPU%d unable to do system off (error = %d)\n", smp_processor_id(), err); 58 } 59