75 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			75 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * s6000 irq crossbar
 | 
						|
 *
 | 
						|
 * Copyright (c) 2009 emlix GmbH
 | 
						|
 * Authors:	Johannes Weiner <jw@emlix.com>
 | 
						|
 *		Oskar Schirmer <os@emlix.com>
 | 
						|
 */
 | 
						|
#include <linux/io.h>
 | 
						|
#include <asm/irq.h>
 | 
						|
#include <variant/hardware.h>
 | 
						|
 | 
						|
/* S6_REG_INTC */
 | 
						|
#define INTC_STATUS	0x000
 | 
						|
#define INTC_RAW	0x010
 | 
						|
#define INTC_STATUS_AG	0x100
 | 
						|
#define INTC_CFG(n)	(0x200 + 4 * (n))
 | 
						|
 | 
						|
/*
 | 
						|
 * The s6000 has a crossbar that multiplexes interrupt output lines
 | 
						|
 * from the peripherals to input lines on the xtensa core.
 | 
						|
 *
 | 
						|
 * We leave the mapping decisions to the platform as it depends on the
 | 
						|
 * actually connected peripherals which distribution makes sense.
 | 
						|
 */
 | 
						|
extern const signed char *platform_irq_mappings[NR_IRQS];
 | 
						|
 | 
						|
static unsigned long scp_to_intc_enable[] = {
 | 
						|
#define	TO_INTC_ENABLE(n)	(((n) << 1) + 1)
 | 
						|
	TO_INTC_ENABLE(0),
 | 
						|
	TO_INTC_ENABLE(1),
 | 
						|
	TO_INTC_ENABLE(2),
 | 
						|
	TO_INTC_ENABLE(3),
 | 
						|
	TO_INTC_ENABLE(4),
 | 
						|
	TO_INTC_ENABLE(5),
 | 
						|
	TO_INTC_ENABLE(6),
 | 
						|
	TO_INTC_ENABLE(7),
 | 
						|
	TO_INTC_ENABLE(8),
 | 
						|
	TO_INTC_ENABLE(9),
 | 
						|
	TO_INTC_ENABLE(10),
 | 
						|
	TO_INTC_ENABLE(11),
 | 
						|
	TO_INTC_ENABLE(12),
 | 
						|
	-1,
 | 
						|
	-1,
 | 
						|
	TO_INTC_ENABLE(13),
 | 
						|
	-1,
 | 
						|
	TO_INTC_ENABLE(14),
 | 
						|
	-1,
 | 
						|
	TO_INTC_ENABLE(15),
 | 
						|
#undef	TO_INTC_ENABLE
 | 
						|
};
 | 
						|
 | 
						|
static void irq_set(unsigned int irq, int enable)
 | 
						|
{
 | 
						|
	unsigned long en;
 | 
						|
	const signed char *m = platform_irq_mappings[irq];
 | 
						|
 | 
						|
	if (!m)
 | 
						|
		return;
 | 
						|
	en = enable ? scp_to_intc_enable[irq] : 0;
 | 
						|
	while (*m >= 0) {
 | 
						|
		writel(en, S6_REG_INTC + INTC_CFG(*m));
 | 
						|
		m++;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void variant_irq_enable(unsigned int irq)
 | 
						|
{
 | 
						|
	irq_set(irq, 1);
 | 
						|
}
 | 
						|
 | 
						|
void variant_irq_disable(unsigned int irq)
 | 
						|
{
 | 
						|
	irq_set(irq, 0);
 | 
						|
}
 |