bast-irq.c 3.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2
/* linux/arch/arm/mach-s3c2410/bast-irq.c
 *
3
 * Copyright (c) 2003,2005 Simtec Electronics
L
Linus Torvalds 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *   Ben Dooks <ben@simtec.co.uk>
 *
 * http://www.simtec.co.uk/products/EB2410ITX/
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
*/
L
Linus Torvalds 已提交
22 23 24 25 26 27 28 29


#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/ptrace.h>
#include <linux/sysdev.h>

30 31
#include <asm/mach-types.h>

L
Linus Torvalds 已提交
32 33 34 35 36
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>

#include <asm/mach/irq.h>
37 38 39 40 41 42

#include <asm/arch/regs-irq.h>
#include <asm/arch/bast-map.h>
#include <asm/arch/bast-irq.h>

#include "irq.h"
L
Linus Torvalds 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55 56 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 87 88

#if 0
#include <asm/debug-ll.h>
#endif

#define irqdbf(x...)
#define irqdbf2(x...)


/* handle PC104 ISA interrupts from the system CPLD */

/* table of ISA irq nos to the relevant mask... zero means
 * the irq is not implemented
*/
static unsigned char bast_pc104_irqmasks[] = {
	0,   /* 0 */
	0,   /* 1 */
	0,   /* 2 */
	1,   /* 3 */
	0,   /* 4 */
	2,   /* 5 */
	0,   /* 6 */
	4,   /* 7 */
	0,   /* 8 */
	0,   /* 9 */
	8,   /* 10 */
	0,   /* 11 */
	0,   /* 12 */
	0,   /* 13 */
	0,   /* 14 */
	0,   /* 15 */
};

static unsigned char bast_pc104_irqs[] = { 3, 5, 7, 10 };

static void
bast_pc104_mask(unsigned int irqno)
{
	unsigned long temp;

	temp = __raw_readb(BAST_VA_PC104_IRQMASK);
	temp &= ~bast_pc104_irqmasks[irqno];
	__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
}

static void
89
bast_pc104_maskack(unsigned int irqno)
L
Linus Torvalds 已提交
90
{
91
	struct irq_desc *desc = irq_desc + IRQ_ISA;
92 93 94

	bast_pc104_mask(irqno);
	desc->chip->ack(IRQ_ISA);
L
Linus Torvalds 已提交
95 96 97 98 99 100 101 102 103 104 105 106
}

static void
bast_pc104_unmask(unsigned int irqno)
{
	unsigned long temp;

	temp = __raw_readb(BAST_VA_PC104_IRQMASK);
	temp |= bast_pc104_irqmasks[irqno];
	__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
}

107
static struct irq_chip  bast_pc104_chip = {
L
Linus Torvalds 已提交
108 109
	.mask	     = bast_pc104_mask,
	.unmask	     = bast_pc104_unmask,
110
	.ack	     = bast_pc104_maskack
L
Linus Torvalds 已提交
111 112 113 114
};

static void
bast_irq_pc104_demux(unsigned int irq,
115
		     struct irq_desc *desc)
L
Linus Torvalds 已提交
116 117 118 119 120 121 122
{
	unsigned int stat;
	unsigned int irqno;
	int i;

	stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;

123 124 125 126 127 128 129 130 131 132 133
	if (unlikely(stat == 0)) {
		/* ack if we get an irq with nothing (ie, startup) */

		desc = irq_desc + IRQ_ISA;
		desc->chip->ack(IRQ_ISA);
	} else {
		/* handle the IRQ */

		for (i = 0; stat != 0; i++, stat >>= 1) {
			if (stat & 1) {
				irqno = bast_pc104_irqs[i];
134
				desc = irq_desc + irqno;
135
				desc_handle_irq(irqno, desc);
136
			}
L
Linus Torvalds 已提交
137
		}
138 139
	}
}
L
Linus Torvalds 已提交
140

141 142 143 144 145 146 147 148 149 150 151 152 153
static __init int bast_irq_init(void)
{
	unsigned int i;

	if (machine_is_bast()) {
		printk(KERN_INFO "BAST PC104 IRQ routing, (c) 2005 Simtec Electronics\n");

		/* zap all the IRQs */

		__raw_writeb(0x0, BAST_VA_PC104_IRQMASK);

		set_irq_chained_handler(IRQ_ISA, bast_irq_pc104_demux);

154
		/* register our IRQs */
155 156 157 158 159

		for (i = 0; i < 4; i++) {
			unsigned int irqno = bast_pc104_irqs[i];

			set_irq_chip(irqno, &bast_pc104_chip);
160
			set_irq_handler(irqno, handle_level_irq);
161 162
			set_irq_flags(irqno, IRQF_VALID);
		}
L
Linus Torvalds 已提交
163
	}
164 165

	return 0;
L
Linus Torvalds 已提交
166
}
167 168

arch_initcall(bast_irq_init);