psci-dt.c 2.9 KB

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