uniphier_scp.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <lib/mmio.h>
  7. #include <lib/utils_def.h>
  8. #include "uniphier.h"
  9. #define UNIPHIER_ROM_RSV3 0x5980120c
  10. #define UNIPHIER_STMBE2COM 0x5f800030
  11. #define UNIPHIER_STMTOBEIRQ 0x5f800060
  12. #define UNIPHIER_BETOSTMIRQ0PT 0x5f800070
  13. #define UNIPHIER_BEIRQCLRPT 0x5f800072
  14. #define UNIPHIER_SCP_READY_MAGIC 0x0000b6a5
  15. #define UNIPHIER_SCP_PACKET_START 0xA0
  16. #define UNIPHIER_SCP_PACKET_END 0xA5
  17. #define UNIPHIER_SCP_PACKET_ESC 0xA6
  18. #define UNIPHIER_SCP_IS_CTRL_CODE(c) (0xA0 <= (c) && (c) <= 0xA6)
  19. int uniphier_scp_is_running(void)
  20. {
  21. return mmio_read_32(UNIPHIER_STMBE2COM) == UNIPHIER_SCP_READY_MAGIC;
  22. }
  23. void uniphier_scp_start(uint32_t scp_base)
  24. {
  25. uint32_t tmp;
  26. mmio_write_32(UNIPHIER_STMBE2COM + 4, scp_base);
  27. mmio_write_32(UNIPHIER_STMBE2COM, UNIPHIER_SCP_READY_MAGIC);
  28. do {
  29. tmp = mmio_read_32(UNIPHIER_ROM_RSV3);
  30. } while (!(tmp & BIT(8)));
  31. mmio_write_32(UNIPHIER_ROM_RSV3, tmp | BIT(9));
  32. }
  33. static void uniphier_scp_send_packet(const uint8_t *packet, int packet_len)
  34. {
  35. uintptr_t reg = UNIPHIER_STMBE2COM;
  36. uint32_t word;
  37. int len, i;
  38. while (packet_len) {
  39. len = MIN(packet_len, 4);
  40. word = 0;
  41. for (i = 0; i < len; i++)
  42. word |= *packet++ << (8 * i);
  43. mmio_write_32(reg, word);
  44. reg += 4;
  45. packet_len -= len;
  46. }
  47. mmio_write_8(UNIPHIER_BETOSTMIRQ0PT, 0x55);
  48. while (!(mmio_read_32(UNIPHIER_STMTOBEIRQ) & BIT(1)))
  49. ;
  50. mmio_write_8(UNIPHIER_BEIRQCLRPT, BIT(1) | BIT(0));
  51. }
  52. static void uniphier_scp_send_cmd(const uint8_t *cmd, int cmd_len)
  53. {
  54. uint8_t packet[32]; /* long enough */
  55. uint8_t *p = packet;
  56. uint8_t c;
  57. int i;
  58. *p++ = UNIPHIER_SCP_PACKET_START;
  59. *p++ = cmd_len;
  60. for (i = 0; i < cmd_len; i++) {
  61. c = *cmd++;
  62. if (UNIPHIER_SCP_IS_CTRL_CODE(c)) {
  63. *p++ = UNIPHIER_SCP_PACKET_ESC;
  64. *p++ = c ^ BIT(7);
  65. } else {
  66. *p++ = c;
  67. }
  68. }
  69. *p++ = UNIPHIER_SCP_PACKET_END;
  70. uniphier_scp_send_packet(packet, p - packet);
  71. }
  72. #define UNIPHIER_SCP_CMD(name, ...) \
  73. static const uint8_t __uniphier_scp_##name##_cmd[] = { \
  74. __VA_ARGS__ \
  75. }; \
  76. void uniphier_scp_##name(void) \
  77. { \
  78. uniphier_scp_send_cmd(__uniphier_scp_##name##_cmd, \
  79. ARRAY_SIZE(__uniphier_scp_##name##_cmd)); \
  80. }
  81. UNIPHIER_SCP_CMD(open_com, 0x00, 0x00, 0x05)
  82. UNIPHIER_SCP_CMD(system_off, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01)
  83. UNIPHIER_SCP_CMD(system_reset, 0x00, 0x02, 0x00)