1/*
2 * arch/powerpc/sysdev/ipic.c
3 *
4 * IPIC routines implementations.
5 *
6 * Copyright 2005 Freescale Semiconductor, Inc.
7 *
8 * This program is free software; you can redistribute  it and/or modify it
9 * under  the terms of  the GNU General  Public License as published by the
10 * Free Software Foundation;  either version 2 of the  License, or (at your
11 * option) any later version.
12 */
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/errno.h>
16#include <linux/reboot.h>
17#include <linux/slab.h>
18#include <linux/stddef.h>
19#include <linux/sched.h>
20#include <linux/signal.h>
21#include <linux/sysdev.h>
22#include <linux/device.h>
23#include <linux/bootmem.h>
24#include <linux/spinlock.h>
25#include <asm/irq.h>
26#include <asm/io.h>
27#include <asm/prom.h>
28#include <asm/ipic.h>
29
30#include "ipic.h"
31
32static struct ipic * primary_ipic;
33static DEFINE_SPINLOCK(ipic_lock);
34
35static struct ipic_info ipic_info[] = {
36	[9] = {
37		.pend	= IPIC_SIPNR_H,
38		.mask	= IPIC_SIMSR_H,
39		.prio	= IPIC_SIPRR_D,
40		.force	= IPIC_SIFCR_H,
41		.bit	= 24,
42		.prio_mask = 0,
43	},
44	[10] = {
45		.pend	= IPIC_SIPNR_H,
46		.mask	= IPIC_SIMSR_H,
47		.prio	= IPIC_SIPRR_D,
48		.force	= IPIC_SIFCR_H,
49		.bit	= 25,
50		.prio_mask = 1,
51	},
52	[11] = {
53		.pend	= IPIC_SIPNR_H,
54		.mask	= IPIC_SIMSR_H,
55		.prio	= IPIC_SIPRR_D,
56		.force	= IPIC_SIFCR_H,
57		.bit	= 26,
58		.prio_mask = 2,
59	},
60	[14] = {
61		.pend	= IPIC_SIPNR_H,
62		.mask	= IPIC_SIMSR_H,
63		.prio	= IPIC_SIPRR_D,
64		.force	= IPIC_SIFCR_H,
65		.bit	= 29,
66		.prio_mask = 5,
67	},
68	[15] = {
69		.pend	= IPIC_SIPNR_H,
70		.mask	= IPIC_SIMSR_H,
71		.prio	= IPIC_SIPRR_D,
72		.force	= IPIC_SIFCR_H,
73		.bit	= 30,
74		.prio_mask = 6,
75	},
76	[16] = {
77		.pend	= IPIC_SIPNR_H,
78		.mask	= IPIC_SIMSR_H,
79		.prio	= IPIC_SIPRR_D,
80		.force	= IPIC_SIFCR_H,
81		.bit	= 31,
82		.prio_mask = 7,
83	},
84	[17] = {
85		.pend	= IPIC_SEPNR,
86		.mask	= IPIC_SEMSR,
87		.prio	= IPIC_SMPRR_A,
88		.force	= IPIC_SEFCR,
89		.bit	= 1,
90		.prio_mask = 5,
91	},
92	[18] = {
93		.pend	= IPIC_SEPNR,
94		.mask	= IPIC_SEMSR,
95		.prio	= IPIC_SMPRR_A,
96		.force	= IPIC_SEFCR,
97		.bit	= 2,
98		.prio_mask = 6,
99	},
100	[19] = {
101		.pend	= IPIC_SEPNR,
102		.mask	= IPIC_SEMSR,
103		.prio	= IPIC_SMPRR_A,
104		.force	= IPIC_SEFCR,
105		.bit	= 3,
106		.prio_mask = 7,
107	},
108	[20] = {
109		.pend	= IPIC_SEPNR,
110		.mask	= IPIC_SEMSR,
111		.prio	= IPIC_SMPRR_B,
112		.force	= IPIC_SEFCR,
113		.bit	= 4,
114		.prio_mask = 4,
115	},
116	[21] = {
117		.pend	= IPIC_SEPNR,
118		.mask	= IPIC_SEMSR,
119		.prio	= IPIC_SMPRR_B,
120		.force	= IPIC_SEFCR,
121		.bit	= 5,
122		.prio_mask = 5,
123	},
124	[22] = {
125		.pend	= IPIC_SEPNR,
126		.mask	= IPIC_SEMSR,
127		.prio	= IPIC_SMPRR_B,
128		.force	= IPIC_SEFCR,
129		.bit	= 6,
130		.prio_mask = 6,
131	},
132	[23] = {
133		.pend	= IPIC_SEPNR,
134		.mask	= IPIC_SEMSR,
135		.prio	= IPIC_SMPRR_B,
136		.force	= IPIC_SEFCR,
137		.bit	= 7,
138		.prio_mask = 7,
139	},
140	[32] = {
141		.pend	= IPIC_SIPNR_H,
142		.mask	= IPIC_SIMSR_H,
143		.prio	= IPIC_SIPRR_A,
144		.force	= IPIC_SIFCR_H,
145		.bit	= 0,
146		.prio_mask = 0,
147	},
148	[33] = {
149		.pend	= IPIC_SIPNR_H,
150		.mask	= IPIC_SIMSR_H,
151		.prio	= IPIC_SIPRR_A,
152		.force	= IPIC_SIFCR_H,
153		.bit	= 1,
154		.prio_mask = 1,
155	},
156	[34] = {
157		.pend	= IPIC_SIPNR_H,
158		.mask	= IPIC_SIMSR_H,
159		.prio	= IPIC_SIPRR_A,
160		.force	= IPIC_SIFCR_H,
161		.bit	= 2,
162		.prio_mask = 2,
163	},
164	[35] = {
165		.pend	= IPIC_SIPNR_H,
166		.mask	= IPIC_SIMSR_H,
167		.prio	= IPIC_SIPRR_A,
168		.force	= IPIC_SIFCR_H,
169		.bit	= 3,
170		.prio_mask = 3,
171	},
172	[36] = {
173		.pend	= IPIC_SIPNR_H,
174		.mask	= IPIC_SIMSR_H,
175		.prio	= IPIC_SIPRR_A,
176		.force	= IPIC_SIFCR_H,
177		.bit	= 4,
178		.prio_mask = 4,
179	},
180	[37] = {
181		.pend	= IPIC_SIPNR_H,
182		.mask	= IPIC_SIMSR_H,
183		.prio	= IPIC_SIPRR_A,
184		.force	= IPIC_SIFCR_H,
185		.bit	= 5,
186		.prio_mask = 5,
187	},
188	[38] = {
189		.pend	= IPIC_SIPNR_H,
190		.mask	= IPIC_SIMSR_H,
191		.prio	= IPIC_SIPRR_A,
192		.force	= IPIC_SIFCR_H,
193		.bit	= 6,
194		.prio_mask = 6,
195	},
196	[39] = {
197		.pend	= IPIC_SIPNR_H,
198		.mask	= IPIC_SIMSR_H,
199		.prio	= IPIC_SIPRR_A,
200		.force	= IPIC_SIFCR_H,
201		.bit	= 7,
202		.prio_mask = 7,
203	},
204	[48] = {
205		.pend	= IPIC_SEPNR,
206		.mask	= IPIC_SEMSR,
207		.prio	= IPIC_SMPRR_A,
208		.force	= IPIC_SEFCR,
209		.bit	= 0,
210		.prio_mask = 4,
211	},
212	[64] = {
213		.pend	= IPIC_SIPNR_L,
214		.mask	= IPIC_SIMSR_L,
215		.prio	= IPIC_SMPRR_A,
216		.force	= IPIC_SIFCR_L,
217		.bit	= 0,
218		.prio_mask = 0,
219	},
220	[65] = {
221		.pend	= IPIC_SIPNR_L,
222		.mask	= IPIC_SIMSR_L,
223		.prio	= IPIC_SMPRR_A,
224		.force	= IPIC_SIFCR_L,
225		.bit	= 1,
226		.prio_mask = 1,
227	},
228	[66] = {
229		.pend	= IPIC_SIPNR_L,
230		.mask	= IPIC_SIMSR_L,
231		.prio	= IPIC_SMPRR_A,
232		.force	= IPIC_SIFCR_L,
233		.bit	= 2,
234		.prio_mask = 2,
235	},
236	[67] = {
237		.pend	= IPIC_SIPNR_L,
238		.mask	= IPIC_SIMSR_L,
239		.prio	= IPIC_SMPRR_A,
240		.force	= IPIC_SIFCR_L,
241		.bit	= 3,
242		.prio_mask = 3,
243	},
244	[68] = {
245		.pend	= IPIC_SIPNR_L,
246		.mask	= IPIC_SIMSR_L,
247		.prio	= IPIC_SMPRR_B,
248		.force	= IPIC_SIFCR_L,
249		.bit	= 4,
250		.prio_mask = 0,
251	},
252	[69] = {
253		.pend	= IPIC_SIPNR_L,
254		.mask	= IPIC_SIMSR_L,
255		.prio	= IPIC_SMPRR_B,
256		.force	= IPIC_SIFCR_L,
257		.bit	= 5,
258		.prio_mask = 1,
259	},
260	[70] = {
261		.pend	= IPIC_SIPNR_L,
262		.mask	= IPIC_SIMSR_L,
263		.prio	= IPIC_SMPRR_B,
264		.force	= IPIC_SIFCR_L,
265		.bit	= 6,
266		.prio_mask = 2,
267	},
268	[71] = {
269		.pend	= IPIC_SIPNR_L,
270		.mask	= IPIC_SIMSR_L,
271		.prio	= IPIC_SMPRR_B,
272		.force	= IPIC_SIFCR_L,
273		.bit	= 7,
274		.prio_mask = 3,
275	},
276	[72] = {
277		.pend	= IPIC_SIPNR_L,
278		.mask	= IPIC_SIMSR_L,
279		.prio	= 0,
280		.force	= IPIC_SIFCR_L,
281		.bit	= 8,
282	},
283	[73] = {
284		.pend	= IPIC_SIPNR_L,
285		.mask	= IPIC_SIMSR_L,
286		.prio	= 0,
287		.force	= IPIC_SIFCR_L,
288		.bit	= 9,
289	},
290	[74] = {
291		.pend	= IPIC_SIPNR_L,
292		.mask	= IPIC_SIMSR_L,
293		.prio	= 0,
294		.force	= IPIC_SIFCR_L,
295		.bit	= 10,
296	},
297	[75] = {
298		.pend	= IPIC_SIPNR_L,
299		.mask	= IPIC_SIMSR_L,
300		.prio	= 0,
301		.force	= IPIC_SIFCR_L,
302		.bit	= 11,
303	},
304	[76] = {
305		.pend	= IPIC_SIPNR_L,
306		.mask	= IPIC_SIMSR_L,
307		.prio	= 0,
308		.force	= IPIC_SIFCR_L,
309		.bit	= 12,
310	},
311	[77] = {
312		.pend	= IPIC_SIPNR_L,
313		.mask	= IPIC_SIMSR_L,
314		.prio	= 0,
315		.force	= IPIC_SIFCR_L,
316		.bit	= 13,
317	},
318	[78] = {
319		.pend	= IPIC_SIPNR_L,
320		.mask	= IPIC_SIMSR_L,
321		.prio	= 0,
322		.force	= IPIC_SIFCR_L,
323		.bit	= 14,
324	},
325	[79] = {
326		.pend	= IPIC_SIPNR_L,
327		.mask	= IPIC_SIMSR_L,
328		.prio	= 0,
329		.force	= IPIC_SIFCR_L,
330		.bit	= 15,
331	},
332	[80] = {
333		.pend	= IPIC_SIPNR_L,
334		.mask	= IPIC_SIMSR_L,
335		.prio	= 0,
336		.force	= IPIC_SIFCR_L,
337		.bit	= 16,
338	},
339	[84] = {
340		.pend	= IPIC_SIPNR_L,
341		.mask	= IPIC_SIMSR_L,
342		.prio	= 0,
343		.force	= IPIC_SIFCR_L,
344		.bit	= 20,
345	},
346	[85] = {
347		.pend	= IPIC_SIPNR_L,
348		.mask	= IPIC_SIMSR_L,
349		.prio	= 0,
350		.force	= IPIC_SIFCR_L,
351		.bit	= 21,
352	},
353	[90] = {
354		.pend	= IPIC_SIPNR_L,
355		.mask	= IPIC_SIMSR_L,
356		.prio	= 0,
357		.force	= IPIC_SIFCR_L,
358		.bit	= 26,
359	},
360	[91] = {
361		.pend	= IPIC_SIPNR_L,
362		.mask	= IPIC_SIMSR_L,
363		.prio	= 0,
364		.force	= IPIC_SIFCR_L,
365		.bit	= 27,
366	},
367};
368
369static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
370{
371	return in_be32(base + (reg >> 2));
372}
373
374static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
375{
376	out_be32(base + (reg >> 2), value);
377}
378
379static inline struct ipic * ipic_from_irq(unsigned int virq)
380{
381	return primary_ipic;
382}
383
384#define ipic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
385
386static void ipic_unmask_irq(unsigned int virq)
387{
388	struct ipic *ipic = ipic_from_irq(virq);
389	unsigned int src = ipic_irq_to_hw(virq);
390	unsigned long flags;
391	u32 temp;
392
393	spin_lock_irqsave(&ipic_lock, flags);
394
395	temp = ipic_read(ipic->regs, ipic_info[src].mask);
396	temp |= (1 << (31 - ipic_info[src].bit));
397	ipic_write(ipic->regs, ipic_info[src].mask, temp);
398
399	spin_unlock_irqrestore(&ipic_lock, flags);
400}
401
402static void ipic_mask_irq(unsigned int virq)
403{
404	struct ipic *ipic = ipic_from_irq(virq);
405	unsigned int src = ipic_irq_to_hw(virq);
406	unsigned long flags;
407	u32 temp;
408
409	spin_lock_irqsave(&ipic_lock, flags);
410
411	temp = ipic_read(ipic->regs, ipic_info[src].mask);
412	temp &= ~(1 << (31 - ipic_info[src].bit));
413	ipic_write(ipic->regs, ipic_info[src].mask, temp);
414
415	spin_unlock_irqrestore(&ipic_lock, flags);
416}
417
418static void ipic_ack_irq(unsigned int virq)
419{
420	struct ipic *ipic = ipic_from_irq(virq);
421	unsigned int src = ipic_irq_to_hw(virq);
422	unsigned long flags;
423	u32 temp;
424
425	spin_lock_irqsave(&ipic_lock, flags);
426
427	temp = ipic_read(ipic->regs, ipic_info[src].pend);
428	temp |= (1 << (31 - ipic_info[src].bit));
429	ipic_write(ipic->regs, ipic_info[src].pend, temp);
430
431	spin_unlock_irqrestore(&ipic_lock, flags);
432}
433
434static void ipic_mask_irq_and_ack(unsigned int virq)
435{
436	struct ipic *ipic = ipic_from_irq(virq);
437	unsigned int src = ipic_irq_to_hw(virq);
438	unsigned long flags;
439	u32 temp;
440
441	spin_lock_irqsave(&ipic_lock, flags);
442
443	temp = ipic_read(ipic->regs, ipic_info[src].mask);
444	temp &= ~(1 << (31 - ipic_info[src].bit));
445	ipic_write(ipic->regs, ipic_info[src].mask, temp);
446
447	temp = ipic_read(ipic->regs, ipic_info[src].pend);
448	temp |= (1 << (31 - ipic_info[src].bit));
449	ipic_write(ipic->regs, ipic_info[src].pend, temp);
450
451	spin_unlock_irqrestore(&ipic_lock, flags);
452}
453
454static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
455{
456	struct ipic *ipic = ipic_from_irq(virq);
457	unsigned int src = ipic_irq_to_hw(virq);
458	struct irq_desc *desc = get_irq_desc(virq);
459	unsigned int vold, vnew, edibit;
460
461	if (flow_type == IRQ_TYPE_NONE)
462		flow_type = IRQ_TYPE_LEVEL_LOW;
463
464	/* ipic supports only low assertion and high-to-low change senses
465	 */
466	if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
467		printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
468			flow_type);
469		return -EINVAL;
470	}
471
472	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
473	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
474	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
475		desc->status |= IRQ_LEVEL;
476		desc->handle_irq = handle_level_irq;
477	} else {
478		desc->handle_irq = handle_edge_irq;
479	}
480
481	/* only EXT IRQ senses are programmable on ipic
482	 * internal IRQ senses are LEVEL_LOW
483	 */
484	if (src == IPIC_IRQ_EXT0)
485		edibit = 15;
486	else
487		if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
488			edibit = (14 - (src - IPIC_IRQ_EXT1));
489		else
490			return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
491
492	vold = ipic_read(ipic->regs, IPIC_SECNR);
493	if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
494		vnew = vold | (1 << edibit);
495	} else {
496		vnew = vold & ~(1 << edibit);
497	}
498	if (vold != vnew)
499		ipic_write(ipic->regs, IPIC_SECNR, vnew);
500	return 0;
501}
502
503static struct irq_chip ipic_irq_chip = {
504	.typename	= " IPIC  ",
505	.unmask		= ipic_unmask_irq,
506	.mask		= ipic_mask_irq,
507	.mask_ack	= ipic_mask_irq_and_ack,
508	.ack		= ipic_ack_irq,
509	.set_type	= ipic_set_irq_type,
510};
511
512static int ipic_host_match(struct irq_host *h, struct device_node *node)
513{
514	struct ipic *ipic = h->host_data;
515
516	/* Exact match, unless ipic node is NULL */
517	return ipic->of_node == NULL || ipic->of_node == node;
518}
519
520static int ipic_host_map(struct irq_host *h, unsigned int virq,
521			 irq_hw_number_t hw)
522{
523	struct ipic *ipic = h->host_data;
524	struct irq_chip *chip;
525
526	/* Default chip */
527	chip = &ipic->hc_irq;
528
529	set_irq_chip_data(virq, ipic);
530	set_irq_chip_and_handler(virq, chip, handle_level_irq);
531
532	/* Set default irq type */
533	set_irq_type(virq, IRQ_TYPE_NONE);
534
535	return 0;
536}
537
538static int ipic_host_xlate(struct irq_host *h, struct device_node *ct,
539			   u32 *intspec, unsigned int intsize,
540			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
541
542{
543	/* interrupt sense values coming from the device tree equal either
544	 * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change)
545	 */
546	*out_hwirq = intspec[0];
547	if (intsize > 1)
548		*out_flags = intspec[1];
549	else
550		*out_flags = IRQ_TYPE_NONE;
551	return 0;
552}
553
554static struct irq_host_ops ipic_host_ops = {
555	.match	= ipic_host_match,
556	.map	= ipic_host_map,
557	.xlate	= ipic_host_xlate,
558};
559
560struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
561{
562	struct ipic	*ipic;
563	struct resource res;
564	u32 temp = 0, ret;
565
566	ipic = alloc_bootmem(sizeof(struct ipic));
567	if (ipic == NULL)
568		return NULL;
569
570	memset(ipic, 0, sizeof(struct ipic));
571	ipic->of_node = of_node_get(node);
572
573	ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
574				       NR_IPIC_INTS,
575				       &ipic_host_ops, 0);
576	if (ipic->irqhost == NULL) {
577		of_node_put(node);
578		return NULL;
579	}
580
581	ret = of_address_to_resource(node, 0, &res);
582	if (ret) {
583		of_node_put(node);
584		return NULL;
585	}
586
587	ipic->regs = ioremap(res.start, res.end - res.start + 1);
588
589	ipic->irqhost->host_data = ipic;
590	ipic->hc_irq = ipic_irq_chip;
591
592	/* init hw */
593	ipic_write(ipic->regs, IPIC_SICNR, 0x0);
594
595	/* default priority scheme is grouped. If spread mode is required
596	 * configure SICFR accordingly */
597	if (flags & IPIC_SPREADMODE_GRP_A)
598		temp |= SICFR_IPSA;
599	if (flags & IPIC_SPREADMODE_GRP_D)
600		temp |= SICFR_IPSD;
601	if (flags & IPIC_SPREADMODE_MIX_A)
602		temp |= SICFR_MPSA;
603	if (flags & IPIC_SPREADMODE_MIX_B)
604		temp |= SICFR_MPSB;
605
606	ipic_write(ipic->regs, IPIC_SICNR, temp);
607
608	/* handle MCP route */
609	temp = 0;
610	if (flags & IPIC_DISABLE_MCP_OUT)
611		temp = SERCR_MCPR;
612	ipic_write(ipic->regs, IPIC_SERCR, temp);
613
614	/* handle routing of IRQ0 to MCP */
615	temp = ipic_read(ipic->regs, IPIC_SEMSR);
616
617	if (flags & IPIC_IRQ0_MCP)
618		temp |= SEMSR_SIRQ0;
619	else
620		temp &= ~SEMSR_SIRQ0;
621
622	ipic_write(ipic->regs, IPIC_SEMSR, temp);
623
624	primary_ipic = ipic;
625	irq_set_default_host(primary_ipic->irqhost);
626
627	printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
628			primary_ipic->regs);
629
630	return ipic;
631}
632
633int ipic_set_priority(unsigned int virq, unsigned int priority)
634{
635	struct ipic *ipic = ipic_from_irq(virq);
636	unsigned int src = ipic_irq_to_hw(virq);
637	u32 temp;
638
639	if (priority > 7)
640		return -EINVAL;
641	if (src > 127)
642		return -EINVAL;
643	if (ipic_info[src].prio == 0)
644		return -EINVAL;
645
646	temp = ipic_read(ipic->regs, ipic_info[src].prio);
647
648	if (priority < 4) {
649		temp &= ~(0x7 << (20 + (3 - priority) * 3));
650		temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
651	} else {
652		temp &= ~(0x7 << (4 + (7 - priority) * 3));
653		temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
654	}
655
656	ipic_write(ipic->regs, ipic_info[src].prio, temp);
657
658	return 0;
659}
660
661void ipic_set_highest_priority(unsigned int virq)
662{
663	struct ipic *ipic = ipic_from_irq(virq);
664	unsigned int src = ipic_irq_to_hw(virq);
665	u32 temp;
666
667	temp = ipic_read(ipic->regs, IPIC_SICFR);
668
669	/* clear and set HPI */
670	temp &= 0x7f000000;
671	temp |= (src & 0x7f) << 24;
672
673	ipic_write(ipic->regs, IPIC_SICFR, temp);
674}
675
676void ipic_set_default_priority(void)
677{
678	ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT);
679	ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT);
680	ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT);
681	ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT);
682}
683
684void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
685{
686	struct ipic *ipic = primary_ipic;
687	u32 temp;
688
689	temp = ipic_read(ipic->regs, IPIC_SERMR);
690	temp |= (1 << (31 - mcp_irq));
691	ipic_write(ipic->regs, IPIC_SERMR, temp);
692}
693
694void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
695{
696	struct ipic *ipic = primary_ipic;
697	u32 temp;
698
699	temp = ipic_read(ipic->regs, IPIC_SERMR);
700	temp &= (1 << (31 - mcp_irq));
701	ipic_write(ipic->regs, IPIC_SERMR, temp);
702}
703
704u32 ipic_get_mcp_status(void)
705{
706	return ipic_read(primary_ipic->regs, IPIC_SERMR);
707}
708
709void ipic_clear_mcp_status(u32 mask)
710{
711	ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
712}
713
714/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
715unsigned int ipic_get_irq(void)
716{
717	int irq;
718
719	BUG_ON(primary_ipic == NULL);
720
721#define IPIC_SIVCR_VECTOR_MASK	0x7f
722	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
723
724	if (irq == 0)    /* 0 --> no irq is pending */
725		return NO_IRQ;
726
727	return irq_linear_revmap(primary_ipic->irqhost, irq);
728}
729
730static struct sysdev_class ipic_sysclass = {
731	set_kset_name("ipic"),
732};
733
734static struct sys_device device_ipic = {
735	.id		= 0,
736	.cls		= &ipic_sysclass,
737};
738
739static int __init init_ipic_sysfs(void)
740{
741	int rc;
742
743	if (!primary_ipic->regs)
744		return -ENODEV;
745	printk(KERN_DEBUG "Registering ipic with sysfs...\n");
746
747	rc = sysdev_class_register(&ipic_sysclass);
748	if (rc) {
749		printk(KERN_ERR "Failed registering ipic sys class\n");
750		return -ENODEV;
751	}
752	rc = sysdev_register(&device_ipic);
753	if (rc) {
754		printk(KERN_ERR "Failed registering ipic sys device\n");
755		return -ENODEV;
756	}
757	return 0;
758}
759
760subsys_initcall(init_ipic_sysfs);
761