xics.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.xics.c 1.8 12/19/01 09:48:40 trini
  3.  */
  4. /*
  5.  * arch/ppc/kernel/xics.c
  6.  *
  7.  * Copyright 2000 IBM Corporation.
  8.  *
  9.  *  This program is free software; you can redistribute it and/or
  10.  *  modify it under the terms of the GNU General Public License
  11.  *  as published by the Free Software Foundation; either version
  12.  *  2 of the License, or (at your option) any later version.
  13.  */
  14. #include <linux/config.h>
  15. #include <linux/types.h>
  16. #include <linux/threads.h>
  17. #include <linux/kernel.h>
  18. #include <linux/sched.h>
  19. #include <asm/prom.h>
  20. #include <asm/io.h>
  21. #include "i8259.h"
  22. #include "xics.h"
  23. void xics_enable_irq(u_int irq);
  24. void xics_disable_irq(u_int irq);
  25. void xics_mask_and_ack_irq(u_int irq);
  26. void xics_end_irq(u_int irq);
  27. struct hw_interrupt_type xics_pic = {
  28. " XICS     ",
  29. NULL,
  30. NULL,
  31. xics_enable_irq,
  32. xics_disable_irq,
  33. xics_mask_and_ack_irq,
  34. xics_end_irq
  35. };
  36. struct hw_interrupt_type xics_8259_pic = {
  37. " XICS/8259",
  38. NULL,
  39. NULL,
  40. NULL,
  41. NULL,
  42. xics_mask_and_ack_irq,
  43. NULL
  44. };
  45. #define XICS_IPI 2
  46. #define XICS_IRQ_8259_CASCADE 0x2c
  47. #define XICS_IRQ_OFFSET 16
  48. #define XICS_IRQ_SPURIOUS 0
  49. #define DEFAULT_SERVER 0
  50. #define DEFAULT_PRIORITY 0
  51. struct xics_ipl {
  52. union {
  53. u32 word;
  54. u8 bytes[4];
  55. } xirr_poll;
  56. union {
  57. u32 word;
  58. u8 bytes[4];
  59. } xirr;
  60. u32 dummy;
  61. union {
  62. u32 word;
  63. u8 bytes[4];
  64. } qirr;
  65. };
  66. struct xics_info {
  67. volatile struct xics_ipl * per_cpu[NR_CPUS];
  68. };
  69. struct xics_info xics_info;
  70. #define xirr_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr.word)
  71. #define cppr_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr.bytes[0])
  72. #define poll_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr_poll.word)
  73. #define qirr_info(n_cpu) (xics_info.per_cpu[n_cpu]->qirr.bytes[0])
  74. void
  75. xics_enable_irq(
  76. u_int irq
  77. )
  78. {
  79. int status;
  80. int call_status;
  81. irq -= XICS_IRQ_OFFSET;
  82. if (irq == XICS_IPI)
  83. return;
  84. call_status = call_rtas("ibm,set-xive", 3, 1, (ulong*)&status,
  85. irq, DEFAULT_SERVER, DEFAULT_PRIORITY);
  86. if( call_status != 0 ) {
  87. printk("xics_enable_irq: irq=%x: call_rtas failed; retn=%x, status=%xn",
  88.        irq, call_status, status);
  89. return;
  90. }
  91. }
  92. void
  93. xics_disable_irq(
  94. u_int irq
  95. )
  96. {
  97. int status;
  98. int call_status;
  99. irq -= XICS_IRQ_OFFSET;
  100. call_status = call_rtas("ibm,int-off", 1, 1, (ulong*)&status, irq);
  101. if( call_status != 0 ) {
  102. printk("xics_disable_irq: irq=%x: call_rtas failed, retn=%xn",
  103.        irq, call_status);
  104. return;
  105. }
  106. }
  107. void
  108. xics_end_irq(
  109. u_int irq
  110. )
  111. {
  112. int cpu = smp_processor_id();
  113. cppr_info(cpu) = 0; /* actually the value overwritten by ack */
  114. xirr_info(cpu) = (0xff<<24) | (irq-XICS_IRQ_OFFSET);
  115. }
  116. void
  117. xics_mask_and_ack_irq(
  118. u_int irq
  119. )
  120. {
  121. int cpu = smp_processor_id();
  122. if( irq < XICS_IRQ_OFFSET ) {
  123. i8259_pic.ack(irq);
  124. xirr_info(cpu) = (0xff<<24) | XICS_IRQ_8259_CASCADE;
  125. }
  126. else {
  127. cppr_info(cpu) = 0xff;
  128. }
  129. }
  130. int
  131. xics_get_irq(struct pt_regs *regs)
  132. {
  133. u_int cpu = smp_processor_id();
  134. u_int vec;
  135. int irq;
  136.   
  137. vec = xirr_info(cpu);
  138. /*  (vec >> 24) == old priority */
  139. vec &= 0x00ffffff;
  140. /* for sanity, this had better be < NR_IRQS - 16 */
  141. if( vec == XICS_IRQ_8259_CASCADE )
  142. irq = i8259_poll();
  143. else if( vec == XICS_IRQ_SPURIOUS )
  144. irq = -1;
  145. else
  146. irq = vec + XICS_IRQ_OFFSET;
  147. return irq;
  148. }
  149. #ifdef CONFIG_SMP
  150. void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
  151. {
  152. qirr_info(smp_processor_id()) = 0xff;
  153. smp_message_recv(MSG_RESCHEDULE, regs);
  154. }
  155. void xics_cause_IPI(int cpu)
  156. {
  157. qirr_info(cpu) = 0;
  158. }
  159. void xics_setup_cpu(void)
  160. {
  161. int cpu = smp_processor_id();
  162. cppr_info(cpu) = 0xff;
  163. }
  164. #endif /* CONFIG_SMP */
  165. void
  166. xics_init_IRQ( void )
  167. {
  168. int i;
  169. extern unsigned long smp_chrp_cpu_nr;
  170. #ifdef CONFIG_SMP
  171. for (i = 0; i < smp_chrp_cpu_nr; ++i)
  172. xics_info.per_cpu[i] =
  173. ioremap(0xfe000000 + smp_hw_index[i] * 0x1000, 0x20);
  174. #else
  175. xics_info.per_cpu[0] = ioremap(0xfe000000, 0x20);
  176. #endif /* CONFIG_SMP */
  177. xics_8259_pic.enable = i8259_pic.enable;
  178. xics_8259_pic.disable = i8259_pic.disable;
  179. for (i = 0; i < 16; ++i)
  180. irq_desc[i].handler = &xics_8259_pic;
  181. for (; i < NR_IRQS; ++i)
  182. irq_desc[i].handler = &xics_pic;
  183. cppr_info(0) = 0xff;
  184. if (request_irq(XICS_IRQ_8259_CASCADE + XICS_IRQ_OFFSET, no_action,
  185. 0, "8259 cascade", 0))
  186. printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascaden");
  187. i8259_init();
  188. #ifdef CONFIG_SMP
  189. request_irq(XICS_IPI + XICS_IRQ_OFFSET, xics_ipi_action, 0, "IPI", 0);
  190. #endif
  191. }