Blame view

arch/frv/kernel/irq-mb93091.c 3.62 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
  /* irq-mb93091.c: MB93091 FPGA interrupt handling
   *
   * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version
   * 2 of the License, or (at your option) any later version.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
15
16
17
18
  #include <linux/ptrace.h>
  #include <linux/errno.h>
  #include <linux/signal.h>
  #include <linux/sched.h>
  #include <linux/ioport.h>
  #include <linux/interrupt.h>
  #include <linux/init.h>
  #include <linux/irq.h>
1977f0327   Jiri Slaby   remove asm/bitops...
19
  #include <linux/bitops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
  
  #include <asm/io.h>
  #include <asm/system.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
  #include <asm/delay.h>
  #include <asm/irq.h>
  #include <asm/irc-regs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
31
32
  
  #define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))
  
  #define __get_IMR()	({ __reg16(0xffc00004); })
  #define __set_IMR(M)	do { __reg16(0xffc00004) = (M); wmb(); } while(0)
  #define __get_IFR()	({ __reg16(0xffc0000c); })
  #define __clr_IFR(M)	do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  /*
1bcbba306   David Howells   [PATCH] FRV: Use ...
35
   * on-motherboard FPGA PIC operations
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
   */
193e7a5f8   Thomas Gleixner   frv: Convert mb93...
37
  static void frv_fpga_mask(struct irq_data *d)
1bcbba306   David Howells   [PATCH] FRV: Use ...
38
39
  {
  	uint16_t imr = __get_IMR();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40

193e7a5f8   Thomas Gleixner   frv: Convert mb93...
41
  	imr |= 1 << (d->irq - IRQ_BASE_FPGA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42

1bcbba306   David Howells   [PATCH] FRV: Use ...
43
44
  	__set_IMR(imr);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

193e7a5f8   Thomas Gleixner   frv: Convert mb93...
46
  static void frv_fpga_ack(struct irq_data *d)
88d6e1990   David Howells   [PATCH] FRV: impr...
47
  {
193e7a5f8   Thomas Gleixner   frv: Convert mb93...
48
  	__clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
88d6e1990   David Howells   [PATCH] FRV: impr...
49
  }
193e7a5f8   Thomas Gleixner   frv: Convert mb93...
50
  static void frv_fpga_mask_ack(struct irq_data *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  {
  	uint16_t imr = __get_IMR();
193e7a5f8   Thomas Gleixner   frv: Convert mb93...
53
  	imr |= 1 << (d->irq - IRQ_BASE_FPGA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
  	__set_IMR(imr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55

193e7a5f8   Thomas Gleixner   frv: Convert mb93...
56
  	__clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
1bcbba306   David Howells   [PATCH] FRV: Use ...
57
  }
193e7a5f8   Thomas Gleixner   frv: Convert mb93...
58
  static void frv_fpga_unmask(struct irq_data *d)
1bcbba306   David Howells   [PATCH] FRV: Use ...
59
  {
88d6e1990   David Howells   [PATCH] FRV: impr...
60
  	uint16_t imr = __get_IMR();
193e7a5f8   Thomas Gleixner   frv: Convert mb93...
61
  	imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
88d6e1990   David Howells   [PATCH] FRV: impr...
62
63
  
  	__set_IMR(imr);
1bcbba306   David Howells   [PATCH] FRV: Use ...
64
65
66
67
  }
  
  static struct irq_chip frv_fpga_pic = {
  	.name		= "mb93091",
193e7a5f8   Thomas Gleixner   frv: Convert mb93...
68
69
70
71
  	.irq_ack	= frv_fpga_ack,
  	.irq_mask	= frv_fpga_mask,
  	.irq_mask_ack	= frv_fpga_mask_ack,
  	.irq_unmask	= frv_fpga_unmask,
1bcbba306   David Howells   [PATCH] FRV: Use ...
72
73
74
75
76
  };
  
  /*
   * FPGA PIC interrupt handler
   */
7d12e780e   David Howells   IRQ: Maintain reg...
77
  static irqreturn_t fpga_interrupt(int irq, void *_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  {
1bcbba306   David Howells   [PATCH] FRV: Use ...
79
  	uint16_t imr, mask = (unsigned long) _mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
  
  	imr = __get_IMR();
1bcbba306   David Howells   [PATCH] FRV: Use ...
82
83
84
85
86
87
88
89
90
  	mask = mask & ~imr & __get_IFR();
  
  	/* poll all the triggered IRQs */
  	while (mask) {
  		int irq;
  
  		asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
  		irq = 31 - irq;
  		mask &= ~(1 << irq);
7d12e780e   David Howells   IRQ: Maintain reg...
91
  		generic_handle_irq(IRQ_BASE_FPGA + irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  	}
1bcbba306   David Howells   [PATCH] FRV: Use ...
93

88d6e1990   David Howells   [PATCH] FRV: impr...
94
  	return IRQ_HANDLED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  }
1bcbba306   David Howells   [PATCH] FRV: Use ...
96
97
98
99
100
101
102
103
  /*
   * define an interrupt action for each FPGA PIC output
   * - use dev_id to indicate the FPGA PIC input to output mappings
   */
  static struct irqaction fpga_irq[4]  = {
  	[0] = {
  		.handler	= fpga_interrupt,
  		.flags		= IRQF_DISABLED | IRQF_SHARED,
1bcbba306   David Howells   [PATCH] FRV: Use ...
104
105
106
107
108
109
  		.name		= "fpga.0",
  		.dev_id		= (void *) 0x0028UL,
  	},
  	[1] = {
  		.handler	= fpga_interrupt,
  		.flags		= IRQF_DISABLED | IRQF_SHARED,
1bcbba306   David Howells   [PATCH] FRV: Use ...
110
111
112
113
114
115
  		.name		= "fpga.1",
  		.dev_id		= (void *) 0x0050UL,
  	},
  	[2] = {
  		.handler	= fpga_interrupt,
  		.flags		= IRQF_DISABLED | IRQF_SHARED,
1bcbba306   David Howells   [PATCH] FRV: Use ...
116
117
118
119
120
121
  		.name		= "fpga.2",
  		.dev_id		= (void *) 0x1c00UL,
  	},
  	[3] = {
  		.handler	= fpga_interrupt,
  		.flags		= IRQF_DISABLED | IRQF_SHARED,
1bcbba306   David Howells   [PATCH] FRV: Use ...
122
123
124
125
126
127
128
129
  		.name		= "fpga.3",
  		.dev_id		= (void *) 0x6386UL,
  	}
  };
  
  /*
   * initialise the motherboard FPGA's PIC
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
  void __init fpga_init(void)
  {
1bcbba306   David Howells   [PATCH] FRV: Use ...
132
133
134
135
136
  	int irq;
  
  	/* all PIC inputs are all set to be low-level driven, apart from the
  	 * NMI button (15) which is fixed at falling-edge
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
  	__set_IMR(0x7ffe);
  	__clr_IFR(0x0000);
1bcbba306   David Howells   [PATCH] FRV: Use ...
139
  	for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++)
60af3ab1e   Thomas Gleixner   FRV: Convert geni...
140
  		irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
1bcbba306   David Howells   [PATCH] FRV: Use ...
141

60af3ab1e   Thomas Gleixner   FRV: Convert geni...
142
  	irq_set_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq);
1bcbba306   David Howells   [PATCH] FRV: Use ...
143
144
145
146
147
148
  
  	/* the FPGA drives the first four external IRQ inputs on the CPU PIC */
  	setup_irq(IRQ_CPU_EXTERNAL0, &fpga_irq[0]);
  	setup_irq(IRQ_CPU_EXTERNAL1, &fpga_irq[1]);
  	setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[2]);
  	setup_irq(IRQ_CPU_EXTERNAL3, &fpga_irq[3]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  }