irq.c 2.2 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 * linux/arch/arm/mach-iop32x/irq.c
L
Linus Torvalds 已提交
3
 *
4
 * Generic IOP32X IRQ handling functionality
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
 *
 * Author: Rory Bolt <rorybolt@pacbell.net>
 * Copyright (C) 2002 Rory Bolt
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Added IOP3XX chipset and IQ80321 board masking code.
 *
 */
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/list.h>

#include <asm/mach/irq.h>
#include <asm/irq.h>
#include <asm/hardware.h>

#include <asm/mach-types.h>

static u32 iop321_mask /* = 0 */;

static inline void intctl_write(u32 val)
{
	asm volatile("mcr p6,0,%0,c0,c0,0"::"r" (val));
}

static inline void intstr_write(u32 val)
{
	asm volatile("mcr p6,0,%0,c4,c0,0"::"r" (val));
}

static void
iop321_irq_mask (unsigned int irq)
{

	iop321_mask &= ~(1 << (irq - IOP321_IRQ_OFS));

	intctl_write(iop321_mask);
}

static void
iop321_irq_unmask (unsigned int irq)
{
	iop321_mask |= (1 << (irq - IOP321_IRQ_OFS));

	intctl_write(iop321_mask);
}

55 56
struct irq_chip ext_chip = {
	.name	= "IOP",
L
Linus Torvalds 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
	.ack    = iop321_irq_mask,
	.mask   = iop321_irq_mask,
	.unmask = iop321_irq_unmask,
};

void __init iop321_init_irq(void)
{
	unsigned int i, tmp;

	/* Enable access to coprocessor 6 for dealing with IRQs.
	 * From RMK:
	 * Basically, the Intel documentation here is poor.  It appears that
	 * you need to set the bit to be able to access the coprocessor from
	 * SVC mode.  Whether that allows access from user space or not is
	 * unclear.
	 */
	asm volatile (
		"mrc p15, 0, %0, c15, c1, 0\n\t"
		"orr %0, %0, %1\n\t"
		"mcr p15, 0, %0, c15, c1, 0\n\t"
		/* The action is delayed, so we have to do this: */
		"mrc p15, 0, %0, c15, c1, 0\n\t"
		"mov %0, %0\n\t"
		"sub pc, pc, #4"
		: "=r" (tmp) : "i" (1 << 6) );

	intctl_write(0);		// disable all interrupts
	intstr_write(0);		// treat all as IRQ
	if(machine_is_iq80321() ||
	   machine_is_iq31244()) 	// all interrupts are inputs to chip
87
		*IOP3XX_PCIIRSR = 0x0f;
L
Linus Torvalds 已提交
88

89
	for(i = IOP321_IRQ_OFS; i < NR_IRQS; i++)
L
Linus Torvalds 已提交
90 91 92 93 94 95 96 97
	{
		set_irq_chip(i, &ext_chip);
		set_irq_handler(i, do_level_IRQ);
		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);

	}
}