psci-dt.c 2.6 KB

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