brcm_mhu.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <arch_helpers.h>
  8. #include <drivers/delay_timer.h>
  9. #include <lib/bakery_lock.h>
  10. #include <brcm_mhu.h>
  11. #include <platform_def.h>
  12. #include "m0_ipc.h"
  13. #define PLAT_MHU_INTR_REG AP_TO_SCP_MAILBOX1
  14. /* SCP MHU secure channel registers */
  15. #define SCP_INTR_S_STAT CRMU_IHOST_SW_PERSISTENT_REG11
  16. #define SCP_INTR_S_SET CRMU_IHOST_SW_PERSISTENT_REG11
  17. #define SCP_INTR_S_CLEAR CRMU_IHOST_SW_PERSISTENT_REG11
  18. /* CPU MHU secure channel registers */
  19. #define CPU_INTR_S_STAT CRMU_IHOST_SW_PERSISTENT_REG10
  20. #define CPU_INTR_S_SET CRMU_IHOST_SW_PERSISTENT_REG10
  21. #define CPU_INTR_S_CLEAR CRMU_IHOST_SW_PERSISTENT_REG10
  22. static DEFINE_BAKERY_LOCK(bcm_lock);
  23. /*
  24. * Slot 31 is reserved because the MHU hardware uses this register bit to
  25. * indicate a non-secure access attempt. The total number of available slots is
  26. * therefore 31 [30:0].
  27. */
  28. #define MHU_MAX_SLOT_ID 30
  29. void mhu_secure_message_start(unsigned int slot_id)
  30. {
  31. int iter = 1000000;
  32. assert(slot_id <= MHU_MAX_SLOT_ID);
  33. bakery_lock_get(&bcm_lock);
  34. /* Make sure any previous command has finished */
  35. do {
  36. if (!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) &
  37. (1 << slot_id)))
  38. break;
  39. udelay(1);
  40. } while (--iter);
  41. assert(iter != 0);
  42. }
  43. void mhu_secure_message_send(unsigned int slot_id)
  44. {
  45. uint32_t response, iter = 1000000;
  46. assert(slot_id <= MHU_MAX_SLOT_ID);
  47. assert(!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) &
  48. (1 << slot_id)));
  49. /* Send command to SCP */
  50. mmio_setbits_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
  51. mmio_write_32(CRMU_MAIL_BOX0, MCU_IPC_MCU_CMD_SCPI);
  52. mmio_write_32(PLAT_BRCM_MHU_BASE + PLAT_MHU_INTR_REG, 0x1);
  53. /* Wait until IPC transport acknowledges reception of SCP command */
  54. do {
  55. response = mmio_read_32(CRMU_MAIL_BOX0);
  56. if ((response & ~MCU_IPC_CMD_REPLY_MASK) ==
  57. (MCU_IPC_CMD_DONE_MASK | MCU_IPC_MCU_CMD_SCPI))
  58. break;
  59. udelay(1);
  60. } while (--iter);
  61. assert(iter != 0);
  62. }
  63. uint32_t mhu_secure_message_wait(void)
  64. {
  65. /* Wait for response from SCP */
  66. uint32_t response, iter = 1000000;
  67. do {
  68. response = mmio_read_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT);
  69. if (!response)
  70. break;
  71. udelay(1);
  72. } while (--iter);
  73. assert(iter != 0);
  74. return response;
  75. }
  76. void mhu_secure_message_end(unsigned int slot_id)
  77. {
  78. assert(slot_id <= MHU_MAX_SLOT_ID);
  79. /*
  80. * Clear any response we got by writing one in the relevant slot bit to
  81. * the CLEAR register
  82. */
  83. mmio_clrbits_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
  84. bakery_lock_release(&bcm_lock);
  85. }
  86. void mhu_secure_init(void)
  87. {
  88. bakery_lock_init(&bcm_lock);
  89. /*
  90. * The STAT register resets to zero. Ensure it is in the expected state,
  91. * as a stale or garbage value would make us think it's a message we've
  92. * already sent.
  93. */
  94. mmio_write_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT, 0);
  95. mmio_write_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT, 0);
  96. }
  97. void plat_brcm_pwrc_setup(void)
  98. {
  99. mhu_secure_init();
  100. }