sq_mhu.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <platform_def.h>
  8. #include <arch_helpers.h>
  9. #include <lib/bakery_lock.h>
  10. #include <lib/mmio.h>
  11. #include <sq_common.h>
  12. #include "sq_mhu.h"
  13. /* SCP MHU secure channel registers */
  14. #define SCP_INTR_S_STAT 0x200
  15. #define SCP_INTR_S_SET 0x208
  16. #define SCP_INTR_S_CLEAR 0x210
  17. /* CPU MHU secure channel registers */
  18. #define CPU_INTR_S_STAT 0x300
  19. #define CPU_INTR_S_SET 0x308
  20. #define CPU_INTR_S_CLEAR 0x310
  21. DEFINE_BAKERY_LOCK(sq_lock);
  22. /*
  23. * Slot 31 is reserved because the MHU hardware uses this register bit to
  24. * indicate a non-secure access attempt. The total number of available slots is
  25. * therefore 31 [30:0].
  26. */
  27. #define MHU_MAX_SLOT_ID 30
  28. void mhu_secure_message_start(unsigned int slot_id)
  29. {
  30. assert(slot_id <= MHU_MAX_SLOT_ID);
  31. bakery_lock_get(&sq_lock);
  32. /* Make sure any previous command has finished */
  33. while (mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
  34. (1 << slot_id))
  35. ;
  36. }
  37. void mhu_secure_message_send(unsigned int slot_id)
  38. {
  39. assert(slot_id <= MHU_MAX_SLOT_ID);
  40. assert(!(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
  41. (1 << slot_id)));
  42. /* Send command to SCP */
  43. mmio_write_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
  44. }
  45. uint32_t mhu_secure_message_wait(void)
  46. {
  47. uint32_t response;
  48. /* Wait for response from SCP */
  49. while (!(response = mmio_read_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_STAT)))
  50. ;
  51. return response;
  52. }
  53. void mhu_secure_message_end(unsigned int slot_id)
  54. {
  55. assert(slot_id <= MHU_MAX_SLOT_ID);
  56. /*
  57. * Clear any response we got by writing one in the relevant slot bit to
  58. * the CLEAR register
  59. */
  60. mmio_write_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
  61. bakery_lock_release(&sq_lock);
  62. }
  63. void mhu_secure_init(void)
  64. {
  65. bakery_lock_init(&sq_lock);
  66. /*
  67. * The STAT register resets to zero. Ensure it is in the expected state,
  68. * as a stale or garbage value would make us think it's a message we've
  69. * already sent.
  70. */
  71. assert(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) == 0);
  72. }
  73. void plat_sq_pwrc_setup(void)
  74. {
  75. mhu_secure_init();
  76. }