plic_driver.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #include "sifive/devices/plic.h"
  2. #include "plic_driver.h"
  3. #include "platform.h"
  4. #include "encoding.h"
  5. #include <string.h>
  6. void volatile_memzero(uint8_t * base, unsigned int size)
  7. {
  8. volatile uint8_t * ptr;
  9. for (ptr = base; ptr < (base + size); ptr++){
  10. *ptr = 0;
  11. }
  12. }
  13. void PLIC_init (
  14. plic_instance_t * this_plic,
  15. uintptr_t base_addr,
  16. uint32_t num_sources,
  17. uint32_t num_priorities
  18. )
  19. {
  20. this_plic->base_addr = base_addr;
  21. this_plic->num_sources = num_sources;
  22. this_plic->num_priorities = num_priorities;
  23. // Disable all interrupts (don't assume that these registers are reset).
  24. unsigned long hart_id = read_csr(mhartid);
  25. volatile_memzero((uint8_t*) (this_plic->base_addr +
  26. PLIC_ENABLE_OFFSET +
  27. (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)),
  28. (num_sources + 8) / 8);
  29. // Set all priorities to 0 (equal priority -- don't assume that these are reset).
  30. volatile_memzero ((uint8_t *)(this_plic->base_addr +
  31. PLIC_PRIORITY_OFFSET),
  32. (num_sources + 1) << PLIC_PRIORITY_SHIFT_PER_SOURCE);
  33. // Set the threshold to 0.
  34. volatile plic_threshold* threshold = (plic_threshold*)
  35. (this_plic->base_addr +
  36. PLIC_THRESHOLD_OFFSET +
  37. (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
  38. *threshold = 0;
  39. }
  40. void PLIC_set_threshold (plic_instance_t * this_plic,
  41. plic_threshold threshold){
  42. unsigned long hart_id = read_csr(mhartid);
  43. volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr +
  44. PLIC_THRESHOLD_OFFSET +
  45. (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
  46. *threshold_ptr = threshold;
  47. }
  48. void PLIC_enable_interrupt (plic_instance_t * this_plic, plic_source source){
  49. unsigned long hart_id = read_csr(mhartid);
  50. volatile uint8_t * current_ptr = (volatile uint8_t *)(this_plic->base_addr +
  51. PLIC_ENABLE_OFFSET +
  52. (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
  53. (source >> 3));
  54. uint8_t current = *current_ptr;
  55. current = current | ( 1 << (source & 0x7));
  56. *current_ptr = current;
  57. }
  58. void PLIC_disable_interrupt (plic_instance_t * this_plic, plic_source source){
  59. unsigned long hart_id = read_csr(mhartid);
  60. volatile uint8_t * current_ptr = (volatile uint8_t *) (this_plic->base_addr +
  61. PLIC_ENABLE_OFFSET +
  62. (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
  63. (source >> 3));
  64. uint8_t current = *current_ptr;
  65. current = current & ~(( 1 << (source & 0x7)));
  66. *current_ptr = current;
  67. }
  68. void PLIC_set_priority (plic_instance_t * this_plic, plic_source source, plic_priority priority){
  69. if (this_plic->num_priorities > 0) {
  70. volatile plic_priority * priority_ptr = (volatile plic_priority *)
  71. (this_plic->base_addr +
  72. PLIC_PRIORITY_OFFSET +
  73. (source << PLIC_PRIORITY_SHIFT_PER_SOURCE));
  74. *priority_ptr = priority;
  75. }
  76. }
  77. plic_source PLIC_claim_interrupt(plic_instance_t * this_plic){
  78. unsigned long hart_id = read_csr(mhartid);
  79. volatile plic_source * claim_addr = (volatile plic_source * )
  80. (this_plic->base_addr +
  81. PLIC_CLAIM_OFFSET +
  82. (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
  83. return *claim_addr;
  84. }
  85. void PLIC_complete_interrupt(plic_instance_t * this_plic, plic_source source){
  86. unsigned long hart_id = read_csr(mhartid);
  87. volatile plic_source * claim_addr = (volatile plic_source *) (this_plic->base_addr +
  88. PLIC_CLAIM_OFFSET +
  89. (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
  90. *claim_addr = source;
  91. }