Blame view

arch/powerpc/sysdev/mpc8xx_pic.c 4.1 KB
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
1
  #include <linux/kernel.h>
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
2
3
4
5
6
7
8
9
10
11
  #include <linux/stddef.h>
  #include <linux/init.h>
  #include <linux/sched.h>
  #include <linux/signal.h>
  #include <linux/irq.h>
  #include <linux/dma-mapping.h>
  #include <asm/prom.h>
  #include <asm/irq.h>
  #include <asm/io.h>
  #include <asm/8xx_immap.h>
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
12
13
14
15
16
17
18
  
  #include "mpc8xx_pic.h"
  
  
  #define PIC_VEC_SPURRIOUS      15
  
  extern int cpm_get_irq(struct pt_regs *regs);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
19
20
21
  static struct irq_host *mpc8xx_pic_host;
  #define NR_MASK_WORDS   ((NR_IRQS + 31) / 32)
  static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
fb533d0c5   Scott Wood   [POWERPC] 8xx: In...
22
  static sysconf8xx_t __iomem *siu_reg;
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
23
24
  
  int cpm_get_irq(struct pt_regs *regs);
febd40178   Lennert Buytenhek   powerpc: sysdev/m...
25
  static void mpc8xx_unmask_irq(struct irq_data *d)
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
26
27
  {
  	int	bit, word;
476eb4912   Grant Likely   powerpc/irq: Stop...
28
  	unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
29
30
31
32
33
34
35
  
  	bit = irq_nr & 0x1f;
  	word = irq_nr >> 5;
  
  	ppc_cached_irq_mask[word] |= (1 << (31-bit));
  	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
  }
febd40178   Lennert Buytenhek   powerpc: sysdev/m...
36
  static void mpc8xx_mask_irq(struct irq_data *d)
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
37
38
  {
  	int	bit, word;
476eb4912   Grant Likely   powerpc/irq: Stop...
39
  	unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
40
41
42
43
44
45
46
  
  	bit = irq_nr & 0x1f;
  	word = irq_nr >> 5;
  
  	ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
  	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
  }
febd40178   Lennert Buytenhek   powerpc: sysdev/m...
47
  static void mpc8xx_ack(struct irq_data *d)
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
48
49
  {
  	int	bit;
476eb4912   Grant Likely   powerpc/irq: Stop...
50
  	unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
51
52
53
54
  
  	bit = irq_nr & 0x1f;
  	out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
  }
febd40178   Lennert Buytenhek   powerpc: sysdev/m...
55
  static void mpc8xx_end_irq(struct irq_data *d)
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
56
57
  {
  	int bit, word;
476eb4912   Grant Likely   powerpc/irq: Stop...
58
  	unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
59
60
61
62
63
64
65
  
  	bit = irq_nr & 0x1f;
  	word = irq_nr >> 5;
  
  	ppc_cached_irq_mask[word] |= (1 << (31-bit));
  	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
  }
febd40178   Lennert Buytenhek   powerpc: sysdev/m...
66
  static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
67
  {
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
68
  	if (flow_type & IRQ_TYPE_EDGE_FALLING) {
476eb4912   Grant Likely   powerpc/irq: Stop...
69
  		irq_hw_number_t hw = (unsigned int)irqd_to_hwirq(d);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
70
71
72
73
74
75
  		unsigned int siel = in_be32(&siu_reg->sc_siel);
  
  		/* only external IRQ senses are programmable */
  		if ((hw & 1) == 0) {
  			siel |= (0x80000000 >> hw);
  			out_be32(&siu_reg->sc_siel, siel);
b3cf2bb3d   Benjamin Herrenschmidt   powerpc/8xx: Fix ...
76
  			__irq_set_handler_locked(d->irq, handle_edge_irq);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
77
78
79
80
81
82
  		}
  	}
  	return 0;
  }
  
  static struct irq_chip mpc8xx_pic = {
fc380c0c8   Anton Blanchard   powerpc: Remove w...
83
  	.name = "MPC8XX SIU",
febd40178   Lennert Buytenhek   powerpc: sysdev/m...
84
85
86
87
88
  	.irq_unmask = mpc8xx_unmask_irq,
  	.irq_mask = mpc8xx_mask_irq,
  	.irq_ack = mpc8xx_ack,
  	.irq_eoi = mpc8xx_end_irq,
  	.irq_set_type = mpc8xx_set_irq_type,
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  };
  
  unsigned int mpc8xx_get_irq(void)
  {
  	int irq;
  
  	/* For MPC8xx, read the SIVEC register and shift the bits down
  	 * to get the irq number.
  	 */
  	irq = in_be32(&siu_reg->sc_sivec) >> 26;
  
  	if (irq == PIC_VEC_SPURRIOUS)
  		irq = NO_IRQ;
  
          return irq_linear_revmap(mpc8xx_pic_host, irq);
  
  }
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
106
107
108
109
110
111
112
  static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq,
  			  irq_hw_number_t hw)
  {
  	pr_debug("mpc8xx_pic_host_map(%d, 0x%lx)
  ", virq, hw);
  
  	/* Set default irq handle */
ec775d0e7   Thomas Gleixner   powerpc: Convert ...
113
  	irq_set_chip_and_handler(virq, &mpc8xx_pic, handle_level_irq);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
114
115
116
117
118
  	return 0;
  }
  
  
  static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct,
40d50cf7c   Roman Fietze   powerpc: Make "in...
119
  			    const u32 *intspec, unsigned int intsize,
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  			    irq_hw_number_t *out_hwirq, unsigned int *out_flags)
  {
  	static unsigned char map_pic_senses[4] = {
  		IRQ_TYPE_EDGE_RISING,
  		IRQ_TYPE_LEVEL_LOW,
  		IRQ_TYPE_LEVEL_HIGH,
  		IRQ_TYPE_EDGE_FALLING,
  	};
  
  	*out_hwirq = intspec[0];
  	if (intsize > 1 && intspec[1] < 4)
  		*out_flags = map_pic_senses[intspec[1]];
  	else
  		*out_flags = IRQ_TYPE_NONE;
  
  	return 0;
  }
  
  
  static struct irq_host_ops mpc8xx_pic_host_ops = {
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
140
141
142
143
144
145
146
  	.map = mpc8xx_pic_host_map,
  	.xlate = mpc8xx_pic_host_xlate,
  };
  
  int mpc8xx_pic_init(void)
  {
  	struct resource res;
fb533d0c5   Scott Wood   [POWERPC] 8xx: In...
147
  	struct device_node *np;
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
148
  	int ret;
fb533d0c5   Scott Wood   [POWERPC] 8xx: In...
149
150
151
  	np = of_find_compatible_node(NULL, NULL, "fsl,pq1-pic");
  	if (np == NULL)
  		np = of_find_node_by_type(NULL, "mpc8xx-pic");
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
152
  	if (np == NULL) {
fb533d0c5   Scott Wood   [POWERPC] 8xx: In...
153
154
  		printk(KERN_ERR "Could not find fsl,pq1-pic node
  ");
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
155
156
  		return -ENOMEM;
  	}
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
157
  	ret = of_address_to_resource(np, 0, &res);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
158
  	if (ret)
52964f87c   Michael Ellerman   [POWERPC] Add an ...
159
  		goto out;
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
160

28f65c11f   Joe Perches   treewide: Convert...
161
  	siu_reg = ioremap(res.start, resource_size(&res));
b1725c931   Julia Lawall   [POWERPC] arch/po...
162
163
164
165
  	if (siu_reg == NULL) {
  		ret = -EINVAL;
  		goto out;
  	}
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
166

b1725c931   Julia Lawall   [POWERPC] arch/po...
167
  	mpc8xx_pic_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
52964f87c   Michael Ellerman   [POWERPC] Add an ...
168
  					 64, &mpc8xx_pic_host_ops, 64);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
169
170
171
172
  	if (mpc8xx_pic_host == NULL) {
  		printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!
  ");
  		ret = -ENOMEM;
b1725c931   Julia Lawall   [POWERPC] arch/po...
173
  		goto out;
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
174
  	}
b1725c931   Julia Lawall   [POWERPC] arch/po...
175
  	return 0;
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
176

52964f87c   Michael Ellerman   [POWERPC] Add an ...
177
178
  out:
  	of_node_put(np);
f2a0bd375   Vitaly Bordug   [POWERPC] 8xx: po...
179
180
  	return ret;
  }