interrupts.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
  3. * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <asm/types.h>
  9. #include <asm/ptrace.h>
  10. #include <asm/system.h>
  11. #include <asm/openrisc_exc.h>
  12. struct irq_action {
  13. interrupt_handler_t *handler;
  14. void *arg;
  15. int count;
  16. };
  17. static struct irq_action handlers[32];
  18. void interrupt_handler(void)
  19. {
  20. int irq;
  21. while ((irq = ffs(mfspr(SPR_PICSR)))) {
  22. if (handlers[--irq].handler) {
  23. handlers[irq].handler(handlers[irq].arg);
  24. handlers[irq].count++;
  25. } else {
  26. /* disable the interrupt */
  27. mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1 << irq));
  28. printf("Unhandled interrupt: %d\n", irq);
  29. }
  30. /* clear the interrupt */
  31. mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1 << irq));
  32. }
  33. }
  34. int interrupt_init(void)
  35. {
  36. /* install handler for external interrupt exception */
  37. exception_install_handler(EXC_EXT_IRQ, interrupt_handler);
  38. /* Enable interrupts in supervisor register */
  39. mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
  40. return 0;
  41. }
  42. void enable_interrupts(void)
  43. {
  44. /* Set interrupt enable bit in supervisor register */
  45. mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
  46. /* Enable timer exception */
  47. mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_TEE);
  48. }
  49. int disable_interrupts(void)
  50. {
  51. /* Clear interrupt enable bit in supervisor register */
  52. mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_IEE);
  53. /* Disable timer exception */
  54. mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_TEE);
  55. return 0;
  56. }
  57. void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)
  58. {
  59. if (irq < 0 || irq > 31)
  60. return;
  61. handlers[irq].handler = handler;
  62. handlers[irq].arg = arg;
  63. }
  64. void irq_free_handler(int irq)
  65. {
  66. if (irq < 0 || irq > 31)
  67. return;
  68. handlers[irq].handler = 0;
  69. handlers[irq].arg = 0;
  70. }
  71. #if defined(CONFIG_CMD_IRQ)
  72. int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  73. {
  74. int i;
  75. printf("\nInterrupt-Information:\n\n");
  76. printf("Nr Routine Arg Count\n");
  77. printf("-----------------------------\n");
  78. for (i = 0; i < 32; i++) {
  79. if (handlers[i].handler) {
  80. printf("%02d %08lx %08lx %d\n",
  81. i,
  82. (ulong)handlers[i].handler,
  83. (ulong)handlers[i].arg,
  84. handlers[i].count);
  85. }
  86. }
  87. printf("\n");
  88. return 0;
  89. }
  90. #endif