wrap_handoff_soc64.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
  4. *
  5. */
  6. #include <asm/arch/handoff_soc64.h>
  7. #include <asm/io.h>
  8. #include <common.h>
  9. #include <errno.h>
  10. #include "log.h"
  11. static enum endianness check_endianness(u32 handoff)
  12. {
  13. switch (handoff) {
  14. case SOC64_HANDOFF_MAGIC_BOOT:
  15. case SOC64_HANDOFF_MAGIC_MUX:
  16. case SOC64_HANDOFF_MAGIC_IOCTL:
  17. case SOC64_HANDOFF_MAGIC_FPGA:
  18. case SOC64_HANDOFF_MAGIC_DELAY:
  19. case SOC64_HANDOFF_MAGIC_CLOCK:
  20. case SOC64_HANDOFF_MAGIC_MISC:
  21. return BIG_ENDIAN;
  22. #if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
  23. case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
  24. debug("%s: umctl2 handoff data\n", __func__);
  25. return LITTLE_ENDIAN;
  26. case SOC64_HANDOFF_DDR_PHY_MAGIC:
  27. debug("%s: PHY handoff data\n", __func__);
  28. return LITTLE_ENDIAN;
  29. case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
  30. debug("%s: PHY engine handoff data\n", __func__);
  31. return LITTLE_ENDIAN;
  32. #endif
  33. default:
  34. debug("%s: Unknown endianness!!\n", __func__);
  35. return UNKNOWN_ENDIANNESS;
  36. }
  37. }
  38. static int getting_endianness(void *handoff_address, enum endianness *endian_t)
  39. {
  40. /* Checking handoff data is little endian ? */
  41. *endian_t = check_endianness(readl(handoff_address));
  42. if (*endian_t == UNKNOWN_ENDIANNESS) {
  43. /* Trying to check handoff data is big endian? */
  44. *endian_t = check_endianness(swab32(readl(handoff_address)));
  45. if (*endian_t == UNKNOWN_ENDIANNESS) {
  46. debug("%s: Cannot find HANDOFF MAGIC ", __func__);
  47. debug("at addr 0x%p\n", (u32 *)handoff_address);
  48. return -EPERM;
  49. }
  50. }
  51. return 0;
  52. }
  53. int socfpga_get_handoff_size(void *handoff_address)
  54. {
  55. u32 size;
  56. int ret;
  57. enum endianness endian_t;
  58. ret = getting_endianness(handoff_address, &endian_t);
  59. if (ret)
  60. return ret;
  61. size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
  62. if (endian_t == BIG_ENDIAN)
  63. size = swab32(size);
  64. size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
  65. debug("%s: handoff address = 0x%p handoff size = 0x%08x\n", __func__,
  66. (u32 *)handoff_address, size);
  67. return size;
  68. }
  69. int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
  70. {
  71. u32 temp;
  72. u32 *table_x32 = table;
  73. u32 i = 0;
  74. int ret;
  75. enum endianness endian_t;
  76. ret = getting_endianness(handoff_address, &endian_t);
  77. if (ret)
  78. return ret;
  79. temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
  80. (i * sizeof(u32)));
  81. if (endian_t == BIG_ENDIAN) {
  82. debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
  83. debug("Handoff table address = 0x%p ", table_x32);
  84. debug("table length = 0x%x\n", table_len);
  85. debug("%s: handoff data =\n{\n", __func__);
  86. *table_x32 = swab32(temp);
  87. } else if (endian_t == LITTLE_ENDIAN) {
  88. debug(" {\n");
  89. *table_x32 = temp;
  90. }
  91. debug(" No.%d Addr 0x%08x: ", i, *table_x32);
  92. for (i = 1; i < table_len; i++) {
  93. table_x32++;
  94. temp = readl(handoff_address +
  95. SOC64_HANDOFF_OFFSET_DATA +
  96. (i * sizeof(u32)));
  97. if (endian_t == BIG_ENDIAN)
  98. *table_x32 = swab32(temp);
  99. else if (endian_t == LITTLE_ENDIAN)
  100. *table_x32 = temp;
  101. if (!(i % 2))
  102. debug(" No.%d Addr 0x%08x: ", i,
  103. *table_x32);
  104. else
  105. debug(" 0x%08x\n", *table_x32);
  106. }
  107. debug("\n}\n");
  108. return 0;
  109. }