cpc700_pic.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * arch/ppc/platforms/cpc700_pic.c
  3.  * 
  4.  * Interrupt controller support for IBM Spruce
  5.  *
  6.  * Authors: Mark Greer, Matt Porter, and Johnnie Peters
  7.  *     mgreer@mvista.com
  8.  *          mporter@mvista.com
  9.  *          jpeters@mvista.com
  10.  *
  11.  * Copyright 2001-2002 MontaVista Software Inc.
  12.  *
  13.  * This program is free software; you can redistribute  it and/or modify it
  14.  * under  the terms of  the GNU General Public License as published by the
  15.  * Free Software Foundation;  either version 2 of the  License, or (at your
  16.  * option) any later version.
  17.  *
  18.  * THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
  19.  * WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  20.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  21.  * NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
  22.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23.  * NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  24.  * USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  25.  * ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  *
  29.  * You should have received a copy of the  GNU General Public License along
  30.  * with this program; if not, write  to the Free Software Foundation, Inc.,
  31.  * 675 Mass Ave, Cambridge, MA 02139, USA.
  32.  */
  33. #include <linux/stddef.h>
  34. #include <linux/init.h>
  35. #include <linux/sched.h>
  36. #include <linux/signal.h>
  37. #include <linux/irq.h>
  38. #include <asm/io.h>
  39. #include <asm/processor.h>
  40. #include <asm/system.h>
  41. #include <asm/irq.h>
  42. #include "cpc700.h"
  43. static void
  44. cpc700_unmask_irq(unsigned int irq)
  45. {
  46. unsigned int tr_bits;
  47. /*
  48.  * IRQ 31 is largest IRQ supported.
  49.  * IRQs 17-19 are reserved.
  50.  */
  51. if ((irq <= 31) && ((irq < 17) || (irq > 19))) {
  52. tr_bits = CPC700_IN_32(CPC700_UIC_UICTR);
  53. if ((tr_bits & (1 << (31 - irq))) == 0) {
  54. /* level trigger interrupt, clear bit in status
  55.  * register */
  56. CPC700_OUT_32(CPC700_UIC_UICSR, 1 << (31 - irq));
  57. }
  58. /* Know IRQ fits in entry 0 of ppc_cached_irq_mask[] */
  59. ppc_cached_irq_mask[0] |= CPC700_UIC_IRQ_BIT(irq);
  60. CPC700_OUT_32(CPC700_UIC_UICER, ppc_cached_irq_mask[0]);
  61. }
  62. return;
  63. }
  64. static void
  65. cpc700_mask_irq(unsigned int irq)
  66. {
  67. /*
  68.  * IRQ 31 is largest IRQ supported.
  69.  * IRQs 17-19 are reserved.
  70.  */
  71. if ((irq <= 31) && ((irq < 17) || (irq > 19))) {
  72. /* Know IRQ fits in entry 0 of ppc_cached_irq_mask[] */
  73. ppc_cached_irq_mask[0] &=
  74. ~CPC700_UIC_IRQ_BIT(irq);
  75. CPC700_OUT_32(CPC700_UIC_UICER, ppc_cached_irq_mask[0]);
  76. }
  77. return;
  78. }
  79. static void
  80. cpc700_mask_and_ack_irq(unsigned int irq)
  81. {
  82. u_int bit;
  83. /*
  84.  * IRQ 31 is largest IRQ supported.
  85.  * IRQs 17-19 are reserved.
  86.  */
  87. if ((irq <= 31) && ((irq < 17) || (irq > 19))) {
  88. /* Know IRQ fits in entry 0 of ppc_cached_irq_mask[] */
  89. bit = CPC700_UIC_IRQ_BIT(irq);
  90. ppc_cached_irq_mask[0] &= ~bit;
  91. CPC700_OUT_32(CPC700_UIC_UICER, ppc_cached_irq_mask[0]);
  92. CPC700_OUT_32(CPC700_UIC_UICSR, bit); /* Write 1 clears IRQ */
  93. }
  94. return;
  95. }
  96. static struct hw_interrupt_type cpc700_pic = {
  97. "CPC700 PIC",
  98. NULL,
  99. NULL,
  100. cpc700_unmask_irq,
  101. cpc700_mask_irq,
  102. cpc700_mask_and_ack_irq,
  103. NULL,
  104. NULL
  105. };
  106. __init static void
  107. cpc700_pic_init_irq(unsigned int irq)
  108. {
  109. unsigned int tmp;
  110. /* Set interrupt sense */
  111. tmp = CPC700_IN_32(CPC700_UIC_UICTR);
  112. if (cpc700_irq_assigns[irq][0] == 0) {
  113. tmp &= ~CPC700_UIC_IRQ_BIT(irq);
  114. } else {
  115. tmp |= CPC700_UIC_IRQ_BIT(irq);
  116. }
  117. CPC700_OUT_32(CPC700_UIC_UICTR, tmp);
  118. /* Set interrupt polarity */
  119. tmp = CPC700_IN_32(CPC700_UIC_UICPR);
  120. if (cpc700_irq_assigns[irq][1]) {
  121. tmp |= CPC700_UIC_IRQ_BIT(irq);
  122. } else {
  123. tmp &= ~CPC700_UIC_IRQ_BIT(irq);
  124. }
  125. CPC700_OUT_32(CPC700_UIC_UICPR, tmp);
  126. /* Set interrupt critical */
  127. tmp = CPC700_IN_32(CPC700_UIC_UICCR);
  128. tmp |= CPC700_UIC_IRQ_BIT(irq);
  129. CPC700_OUT_32(CPC700_UIC_UICCR, tmp);
  130. return;
  131. }
  132. __init void
  133. cpc700_init_IRQ(void)
  134. {
  135. int i;
  136. ppc_cached_irq_mask[0] = 0;
  137. CPC700_OUT_32(CPC700_UIC_UICER, 0x00000000);    /* Disable all irq's */
  138. CPC700_OUT_32(CPC700_UIC_UICSR, 0xffffffff);    /* Clear cur intrs */
  139. CPC700_OUT_32(CPC700_UIC_UICCR, 0xffffffff);    /* Gen INT not MCP */
  140. CPC700_OUT_32(CPC700_UIC_UICPR, 0x00000000);    /* Active low */
  141. CPC700_OUT_32(CPC700_UIC_UICTR, 0x00000000);    /* Level Sensitive */
  142. CPC700_OUT_32(CPC700_UIC_UICVR, CPC700_UIC_UICVCR_0_HI);
  143.         /* IRQ 0 is highest */
  144. for (i = 0; i < 17; i++) {
  145. irq_desc[i].handler = &cpc700_pic;
  146. cpc700_pic_init_irq(i);
  147. }
  148. for (i = 20; i < 32; i++) {
  149. irq_desc[i].handler = &cpc700_pic;
  150. cpc700_pic_init_irq(i);
  151. }
  152. return;
  153. }
  154. /*
  155.  * Find the highest IRQ that generating an interrupt, if any.
  156.  */
  157. int
  158. cpc700_get_irq(struct pt_regs *regs)
  159. {
  160. int irq = 0;
  161. u_int irq_status, irq_test = 1;
  162. irq_status = CPC700_IN_32(CPC700_UIC_UICMSR);
  163. do
  164. {
  165. if (irq_status & irq_test)
  166. break;
  167. irq++;
  168. irq_test <<= 1;
  169. } while (irq < NR_IRQS);
  170. if (irq == NR_IRQS)
  171.     irq = 33;
  172. return (31 - irq);
  173. }