aclint_mswi.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2021 Western Digital Corporation or its affiliates.
  5. *
  6. * Authors:
  7. * Anup Patel <anup.patel@wdc.com>
  8. */
  9. #include <sbi/riscv_asm.h>
  10. #include <sbi/riscv_atomic.h>
  11. #include <sbi/riscv_io.h>
  12. #include <sbi/sbi_domain.h>
  13. #include <sbi/sbi_error.h>
  14. #include <sbi/sbi_hartmask.h>
  15. #include <sbi/sbi_ipi.h>
  16. #include <sbi/sbi_timer.h>
  17. #include <sbi_utils/ipi/aclint_mswi.h>
  18. static struct aclint_mswi_data *mswi_hartid2data[SBI_HARTMASK_MAX_BITS];
  19. static void mswi_ipi_send(u32 target_hart)
  20. {
  21. u32 *msip;
  22. struct aclint_mswi_data *mswi;
  23. if (SBI_HARTMASK_MAX_BITS <= target_hart)
  24. return;
  25. mswi = mswi_hartid2data[target_hart];
  26. if (!mswi)
  27. return;
  28. /* Set ACLINT IPI */
  29. msip = (void *)mswi->addr;
  30. writel(1, &msip[target_hart - mswi->first_hartid]);
  31. }
  32. static void mswi_ipi_clear(u32 target_hart)
  33. {
  34. u32 *msip;
  35. struct aclint_mswi_data *mswi;
  36. if (SBI_HARTMASK_MAX_BITS <= target_hart)
  37. return;
  38. mswi = mswi_hartid2data[target_hart];
  39. if (!mswi)
  40. return;
  41. /* Clear ACLINT IPI */
  42. msip = (void *)mswi->addr;
  43. writel(0, &msip[target_hart - mswi->first_hartid]);
  44. }
  45. static struct sbi_ipi_device aclint_mswi = {
  46. .name = "aclint-mswi",
  47. .ipi_send = mswi_ipi_send,
  48. .ipi_clear = mswi_ipi_clear
  49. };
  50. int aclint_mswi_warm_init(void)
  51. {
  52. /* Clear IPI for current HART */
  53. mswi_ipi_clear(current_hartid());
  54. return 0;
  55. }
  56. int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
  57. {
  58. u32 i;
  59. int rc;
  60. unsigned long pos, region_size;
  61. struct sbi_domain_memregion reg;
  62. /* Sanity checks */
  63. if (!mswi || (mswi->addr & (ACLINT_MSWI_ALIGN - 1)) ||
  64. (mswi->size < (mswi->hart_count * sizeof(u32))) ||
  65. (mswi->first_hartid >= SBI_HARTMASK_MAX_BITS) ||
  66. (mswi->hart_count > ACLINT_MSWI_MAX_HARTS))
  67. return SBI_EINVAL;
  68. /* Update MSWI hartid table */
  69. for (i = 0; i < mswi->hart_count; i++)
  70. mswi_hartid2data[mswi->first_hartid + i] = mswi;
  71. /* Add MSWI regions to the root domain */
  72. for (pos = 0; pos < mswi->size; pos += ACLINT_MSWI_ALIGN) {
  73. region_size = ((mswi->size - pos) < ACLINT_MSWI_ALIGN) ?
  74. (mswi->size - pos) : ACLINT_MSWI_ALIGN;
  75. sbi_domain_memregion_init(mswi->addr + pos, region_size,
  76. (SBI_DOMAIN_MEMREGION_MMIO |
  77. SBI_DOMAIN_MEMREGION_M_READABLE |
  78. SBI_DOMAIN_MEMREGION_M_WRITABLE),
  79. &reg);
  80. rc = sbi_domain_root_add_memregion(&reg);
  81. if (rc)
  82. return rc;
  83. }
  84. sbi_ipi_set_device(&aclint_mswi);
  85. return 0;
  86. }