mss_ipc_drv.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*
  2. * Copyright (C) 2018 Marvell International Ltd.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. * https://spdx.org/licenses
  6. */
  7. #include <string.h>
  8. #include <common/debug.h>
  9. #include <lib/mmio.h>
  10. #include <plat_marvell.h>
  11. #include <mss_ipc_drv.h>
  12. #define IPC_MSG_BASE_MASK MVEBU_REGS_BASE_MASK
  13. #define IPC_CH_NUM_OF_MSG (16)
  14. #define IPC_CH_MSG_IDX (-1)
  15. unsigned long mv_pm_ipc_msg_base;
  16. unsigned int mv_pm_ipc_queue_size;
  17. unsigned int msg_sync;
  18. int msg_index = IPC_CH_MSG_IDX;
  19. /******************************************************************************
  20. * mss_pm_ipc_init
  21. *
  22. * DESCRIPTION: Initialize PM IPC infrastructure
  23. ******************************************************************************
  24. */
  25. int mv_pm_ipc_init(unsigned long ipc_control_addr)
  26. {
  27. struct mss_pm_ipc_ctrl *ipc_control =
  28. (struct mss_pm_ipc_ctrl *)ipc_control_addr;
  29. /* Initialize PM IPC control block */
  30. mv_pm_ipc_msg_base = ipc_control->msg_base_address |
  31. IPC_MSG_BASE_MASK;
  32. mv_pm_ipc_queue_size = ipc_control->queue_size;
  33. return 0;
  34. }
  35. /******************************************************************************
  36. * mv_pm_ipc_queue_addr_get
  37. *
  38. * DESCRIPTION: Returns the IPC queue address
  39. ******************************************************************************
  40. */
  41. unsigned int mv_pm_ipc_queue_addr_get(void)
  42. {
  43. unsigned int addr;
  44. inv_dcache_range((uint64_t)&msg_index, sizeof(msg_index));
  45. msg_index = msg_index + 1;
  46. if (msg_index >= IPC_CH_NUM_OF_MSG)
  47. msg_index = 0;
  48. addr = (unsigned int)(mv_pm_ipc_msg_base +
  49. (msg_index * mv_pm_ipc_queue_size));
  50. flush_dcache_range((uint64_t)&msg_index, sizeof(msg_index));
  51. return addr;
  52. }
  53. /******************************************************************************
  54. * mv_pm_ipc_msg_rx
  55. *
  56. * DESCRIPTION: Retrieve message from IPC channel
  57. ******************************************************************************
  58. */
  59. int mv_pm_ipc_msg_rx(unsigned int channel_id, struct mss_pm_ipc_msg *msg)
  60. {
  61. unsigned int addr = mv_pm_ipc_queue_addr_get();
  62. msg->msg_reply = mmio_read_32(addr + IPC_MSG_REPLY_LOC);
  63. return 0;
  64. }
  65. /******************************************************************************
  66. * mv_pm_ipc_msg_tx
  67. *
  68. * DESCRIPTION: Send message via IPC channel
  69. ******************************************************************************
  70. */
  71. int mv_pm_ipc_msg_tx(unsigned int channel_id, unsigned int msg_id,
  72. unsigned int cluster_power_state)
  73. {
  74. unsigned int addr = mv_pm_ipc_queue_addr_get();
  75. /* Validate the entry for message placed by the host is free */
  76. if (mmio_read_32(addr + IPC_MSG_STATE_LOC) == IPC_MSG_FREE) {
  77. inv_dcache_range((uint64_t)&msg_sync, sizeof(msg_sync));
  78. msg_sync = msg_sync + 1;
  79. flush_dcache_range((uint64_t)&msg_sync, sizeof(msg_sync));
  80. mmio_write_32(addr + IPC_MSG_SYNC_ID_LOC, msg_sync);
  81. mmio_write_32(addr + IPC_MSG_ID_LOC, msg_id);
  82. mmio_write_32(addr + IPC_MSG_CPU_ID_LOC, channel_id);
  83. mmio_write_32(addr + IPC_MSG_POWER_STATE_LOC,
  84. cluster_power_state);
  85. mmio_write_32(addr + IPC_MSG_STATE_LOC, IPC_MSG_OCCUPY);
  86. } else {
  87. ERROR("%s: FAILED\n", __func__);
  88. }
  89. return 0;
  90. }