irq-mv6434x.c 2.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 * Copyright 2002 Momentum Computer
 * Author: mdharm@momenco.com
4
 * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14
 *
 * 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.
 */
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/kernel_stat.h>
15 16 17
#include <linux/mv643xx.h>
#include <linux/sched.h>

L
Linus Torvalds 已提交
18 19
#include <asm/io.h>
#include <asm/irq.h>
20
#include <asm/marvell.h>
L
Linus Torvalds 已提交
21 22 23 24 25

static unsigned int irq_base;

static inline int ls1bit32(unsigned int x)
{
R
Ralf Baechle 已提交
26
	int b = 31, s;
L
Linus Torvalds 已提交
27

R
Ralf Baechle 已提交
28 29 30 31 32
	s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
	s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
	s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
	s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
	s =  1; if (x <<  1 == 0) s = 0; b -= s;
L
Linus Torvalds 已提交
33 34 35 36 37 38 39 40 41 42 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

        return b;
}

/* mask off an interrupt -- 1 is enable, 0 is disable */
static inline void mask_mv64340_irq(unsigned int irq)
{
	uint32_t value;

	if (irq < (irq_base + 32)) {
		value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
		value &= ~(1 << (irq - irq_base));
		MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
	} else {
		value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
		value &= ~(1 << (irq - irq_base - 32));
		MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
	}
}

/* unmask an interrupt -- 1 is enable, 0 is disable */
static inline void unmask_mv64340_irq(unsigned int irq)
{
	uint32_t value;

	if (irq < (irq_base + 32)) {
		value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
		value |= 1 << (irq - irq_base);
		MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
	} else {
		value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
		value |= 1 << (irq - irq_base - 32);
		MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
	}
}

/*
 * Interrupt handler for interrupts coming from the Marvell chip.
 * It could be built in ethernet ports etc...
 */
73
void ll_mv64340_irq(void)
L
Linus Torvalds 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
{
	unsigned int irq_src_low, irq_src_high;
 	unsigned int irq_mask_low, irq_mask_high;

	/* read the interrupt status registers */
	irq_mask_low = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
	irq_mask_high = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
	irq_src_low = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_LOW);
	irq_src_high = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_HIGH);

	/* mask for just the interrupts we want */
	irq_src_low &= irq_mask_low;
	irq_src_high &= irq_mask_high;

	if (irq_src_low)
89
		do_IRQ(ls1bit32(irq_src_low) + irq_base);
L
Linus Torvalds 已提交
90
	else
91
		do_IRQ(ls1bit32(irq_src_high) + irq_base + 32);
L
Linus Torvalds 已提交
92 93
}

94
struct irq_chip mv64340_irq_type = {
95
	.name = "MV-64340",
A
Atsushi Nemoto 已提交
96 97 98 99
	.ack = mask_mv64340_irq,
	.mask = mask_mv64340_irq,
	.mask_ack = mask_mv64340_irq,
	.unmask = unmask_mv64340_irq,
L
Linus Torvalds 已提交
100 101 102 103 104 105
};

void __init mv64340_irq_init(unsigned int base)
{
	int i;

A
Atsushi Nemoto 已提交
106
	for (i = base; i < base + 64; i++)
107 108
		set_irq_chip_and_handler(i, &mv64340_irq_type,
					 handle_level_irq);
L
Linus Torvalds 已提交
109 110 111

	irq_base = base;
}