#include <xen/smp.h>
#include <asm/psci.h>
-bool_t psci_available;
+uint32_t psci_ver;
#ifdef CONFIG_ARM_32
#define REG_PREFIX "r"
cpu_logical_map(cpu), __pa(init_secondary), 0);
}
-int __init psci_init(void)
+void call_psci_system_off(void)
+{
+ if ( psci_ver > XEN_PSCI_V_0_1 )
+ __invoke_psci_fn_smc(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+}
+
+void call_psci_system_reset(void)
+{
+ if ( psci_ver > XEN_PSCI_V_0_1 )
+ __invoke_psci_fn_smc(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
+}
+
+int __init psci_is_smc_method(const struct dt_device_node *psci)
{
- const struct dt_device_node *psci;
int ret;
const char *prop_str;
- psci = dt_find_compatible_node(NULL, NULL, "arm,psci");
- if ( !psci )
- return -ENODEV;
-
ret = dt_property_read_string(psci, "method", &prop_str);
if ( ret )
{
return -EINVAL;
}
+ return 0;
+}
+
+int __init psci_init_0_1(void)
+{
+ int ret;
+ const struct dt_device_node *psci;
+
+ psci = dt_find_compatible_node(NULL, NULL, "arm,psci");
+ if ( !psci )
+ return -EOPNOTSUPP;
+
+ ret = psci_is_smc_method(psci);
+ if ( ret )
+ return -EINVAL;
+
if ( !dt_property_read_u32(psci, "cpu_on", &psci_cpu_on_nr) )
{
printk("/psci node is missing the \"cpu_on\" property\n");
return -ENOENT;
}
- psci_available = 1;
+ psci_ver = XEN_PSCI_V_0_1;
+
+ printk(XENLOG_INFO "Using PSCI-0.1 for SMP bringup\n");
+
+ return 0;
+}
+
+int __init psci_init_0_2(void)
+{
+ int ret;
+ const struct dt_device_node *psci;
+
+ psci = dt_find_compatible_node(NULL, NULL, "arm,psci-0.2");
+ if ( !psci )
+ return -EOPNOTSUPP;
+
+ ret = psci_is_smc_method(psci);
+ if ( ret )
+ return -EINVAL;
+
+ psci_ver = __invoke_psci_fn_smc(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
+
+ if ( psci_ver != XEN_PSCI_V_0_2 )
+ {
+ printk("Error: PSCI version %#x is not supported.\n", psci_ver);
+ return -EOPNOTSUPP;
+ }
+
+ psci_cpu_on_nr = PSCI_0_2_FN_CPU_ON;
- printk(XENLOG_INFO "Using PSCI for SMP bringup\n");
+ printk(XENLOG_INFO "Using PSCI-0.2 for SMP bringup\n");
return 0;
}
+int __init psci_init(void)
+{
+ int ret;
+
+ ret = psci_init_0_2();
+ if ( ret )
+ ret = psci_init_0_1();
+
+ return ret;
+}
+
/*
* Local variables:
* mode: C
#define PSCI_DISABLED -8
/* availability of PSCI on the host for SMP bringup */
-extern bool_t psci_available;
+extern uint32_t psci_ver;
int psci_init(void);
int call_psci_cpu_on(int cpu);
+void call_psci_system_off(void);
+void call_psci_system_reset(void);
/* functions to handle guest PSCI requests */
int32_t do_psci_cpu_on(uint32_t vcpuid, register_t entry_point);