1 /* 2 * Copyright 2016 NXP Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <libfdt.h> 9 #include <fdt_support.h> 10 #include <linux/sizes.h> 11 #include <linux/kernel.h> 12 #include <asm/psci.h> 13 #ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT 14 #include <asm/armv8/sec_firmware.h> 15 #endif 16 17 int fdt_psci(void *fdt) 18 { 19 #if defined(CONFIG_ARMV8_PSCI) || defined(CONFIG_ARMV7_PSCI) 20 int nodeoff; 21 unsigned int psci_ver = 0; 22 char *psci_compt; 23 int tmp; 24 25 nodeoff = fdt_path_offset(fdt, "/cpus"); 26 if (nodeoff < 0) { 27 printf("couldn't find /cpus\n"); 28 return nodeoff; 29 } 30 31 /* add 'enable-method = "psci"' to each cpu node */ 32 for (tmp = fdt_first_subnode(fdt, nodeoff); 33 tmp >= 0; 34 tmp = fdt_next_subnode(fdt, tmp)) { 35 const struct fdt_property *prop; 36 int len; 37 38 prop = fdt_get_property(fdt, tmp, "device_type", &len); 39 if (!prop) 40 continue; 41 if (len < 4) 42 continue; 43 if (strcmp(prop->data, "cpu")) 44 continue; 45 46 /* 47 * Not checking rv here, our approach is to skip over errors in 48 * individual cpu nodes, hopefully some of the nodes are 49 * processed correctly and those will boot 50 */ 51 fdt_setprop_string(fdt, tmp, "enable-method", "psci"); 52 } 53 54 nodeoff = fdt_path_offset(fdt, "/psci"); 55 if (nodeoff >= 0) 56 goto init_psci_node; 57 58 nodeoff = fdt_path_offset(fdt, "/"); 59 if (nodeoff < 0) 60 return nodeoff; 61 62 nodeoff = fdt_add_subnode(fdt, nodeoff, "psci"); 63 if (nodeoff < 0) 64 return nodeoff; 65 66 init_psci_node: 67 #ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT 68 psci_ver = sec_firmware_support_psci_version(); 69 #endif 70 switch (psci_ver) { 71 case 0x00010000: 72 psci_compt = "arm,psci-1.0"; 73 break; 74 case 0x00000002: 75 psci_compt = "arm,psci-0.2"; 76 break; 77 default: 78 psci_compt = "arm,psci"; 79 break; 80 } 81 82 tmp = fdt_setprop_string(fdt, nodeoff, "compatible", psci_compt); 83 if (tmp) 84 return tmp; 85 tmp = fdt_setprop_string(fdt, nodeoff, "method", "smc"); 86 if (tmp) 87 return tmp; 88 89 #ifdef CONFIG_ARMV7_PSCI 90 tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_suspend", 91 ARM_PSCI_FN_CPU_SUSPEND); 92 if (tmp) 93 return tmp; 94 tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_off", ARM_PSCI_FN_CPU_OFF); 95 if (tmp) 96 return tmp; 97 tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_on", ARM_PSCI_FN_CPU_ON); 98 if (tmp) 99 return tmp; 100 tmp = fdt_setprop_u32(fdt, nodeoff, "migrate", ARM_PSCI_FN_MIGRATE); 101 if (tmp) 102 return tmp; 103 #endif 104 #endif 105 return 0; 106 } 107