plic.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-05-20 bigmagic first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <stdint.h>
  13. #include "plic.h"
  14. #include <riscv_io.h>
  15. #include "encoding.h"
  16. #include <riscv.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. /*
  20. * Each PLIC interrupt source can be assigned a priority by writing
  21. * to its 32-bit memory-mapped priority register.
  22. * The QEMU-virt (the same as FU540-C000) supports 7 levels of priority.
  23. * A priority value of 0 is reserved to mean "never interrupt" and
  24. * effectively disables the interrupt.
  25. * Priority 1 is the lowest active priority, and priority 7 is the highest.
  26. * Ties between global interrupts of the same priority are broken by
  27. * the Interrupt ID; interrupts with the lowest ID have the highest
  28. * effective priority.
  29. */
  30. void plic_set_priority(int irq, int priority)
  31. {
  32. *(uint32_t*)PLIC_PRIORITY(irq) = priority;
  33. }
  34. /*
  35. * Each global interrupt can be enabled by setting the corresponding
  36. * bit in the enables registers.
  37. */
  38. void plic_irq_enable(int irq)
  39. {
  40. int hart = __raw_hartid();
  41. *(uint32_t*)PLIC_ENABLE(hart) = ((*(uint32_t*)PLIC_ENABLE(hart)) | (1 << irq));
  42. #ifdef RISCV_S_MODE
  43. set_csr(sie, read_csr(sie) | MIP_SEIP);
  44. #else
  45. set_csr(mie, read_csr(mie) | MIP_MEIP);
  46. #endif
  47. }
  48. void plic_irq_disable(int irq)
  49. {
  50. int hart = __raw_hartid();
  51. *(uint32_t*)PLIC_ENABLE(hart) = (((*(uint32_t*)PLIC_ENABLE(hart)) & (~(1 << irq))));
  52. }
  53. /*
  54. * PLIC will mask all interrupts of a priority less than or equal to threshold.
  55. * Maximum threshold is 7.
  56. * For example, a threshold value of zero permits all interrupts with
  57. * non-zero priority, whereas a value of 7 masks all interrupts.
  58. * Notice, the threshold is global for PLIC, not for each interrupt source.
  59. */
  60. void plic_set_threshold(int threshold)
  61. {
  62. int hart = __raw_hartid();
  63. *(uint32_t*)PLIC_THRESHOLD(hart) = threshold;
  64. }
  65. /*
  66. * DESCRIPTION:
  67. * Query the PLIC what interrupt we should serve.
  68. * Perform an interrupt claim by reading the claim register, which
  69. * returns the ID of the highest-priority pending interrupt or zero if there
  70. * is no pending interrupt.
  71. * A successful claim also atomically clears the corresponding pending bit
  72. * on the interrupt source.
  73. * RETURN VALUE:
  74. * the ID of the highest-priority pending interrupt or zero if there
  75. * is no pending interrupt.
  76. */
  77. int plic_claim(void)
  78. {
  79. int hart = __raw_hartid();
  80. int irq = *(uint32_t*)PLIC_CLAIM(hart);
  81. return irq;
  82. }
  83. /*
  84. * DESCRIPTION:
  85. * Writing the interrupt ID it received from the claim (irq) to the
  86. * complete register would signal the PLIC we've served this IRQ.
  87. * The PLIC does not check whether the completion ID is the same as the
  88. * last claim ID for that target. If the completion ID does not match an
  89. * interrupt source that is currently enabled for the target, the completion
  90. * is silently ignored.
  91. * RETURN VALUE: none
  92. */
  93. void plic_complete(int irq)
  94. {
  95. int hart = __raw_hartid();
  96. *(uint32_t*)PLIC_COMPLETE(hart) = irq;
  97. }
  98. void plic_set_ie(rt_uint32_t word_index, rt_uint32_t val)
  99. {
  100. volatile void *plic_ie = (void *)(rt_size_t)(PLIC_BASE_ADDR + PLIC_ENABLE_BASE + word_index * 4);
  101. writel(val, plic_ie);
  102. }
  103. void plic_init()
  104. {
  105. int i;
  106. plic_set_threshold(0);
  107. for(i = 0;i < 128;i++)
  108. {
  109. plic_set_priority(i,7);
  110. }
  111. plic_set_ie(0,0xffffffff);
  112. plic_set_ie(1,0xffffffff);
  113. plic_set_ie(2,0xffffffff);
  114. plic_set_ie(3,0xffffffff);
  115. rt_uint64_t addr;
  116. for(addr = 0xC001000;addr <= 0xC1F1F80;addr += 4)
  117. {
  118. *((rt_uint32_t *)addr) = 0xffffffff;
  119. }
  120. }