~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/frv/kernel/irq-mb93093.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* irq-mb93093.c: MB93093 FPGA interrupt handling
 
2
 *
 
3
 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
 
4
 * Written by David Howells (dhowells@redhat.com)
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version
 
9
 * 2 of the License, or (at your option) any later version.
 
10
 */
 
11
 
 
12
#include <linux/ptrace.h>
 
13
#include <linux/errno.h>
 
14
#include <linux/signal.h>
 
15
#include <linux/sched.h>
 
16
#include <linux/ioport.h>
 
17
#include <linux/interrupt.h>
 
18
#include <linux/init.h>
 
19
#include <linux/irq.h>
 
20
#include <linux/bitops.h>
 
21
 
 
22
#include <asm/io.h>
 
23
#include <asm/system.h>
 
24
#include <asm/delay.h>
 
25
#include <asm/irq.h>
 
26
#include <asm/irc-regs.h>
 
27
 
 
28
#define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR)))
 
29
 
 
30
#define __get_IMR()     ({ __reg16(0x0a); })
 
31
#define __set_IMR(M)    do { __reg16(0x0a) = (M);  wmb(); } while(0)
 
32
#define __get_IFR()     ({ __reg16(0x02); })
 
33
#define __clr_IFR(M)    do { __reg16(0x02) = ~(M); wmb(); } while(0)
 
34
 
 
35
/*
 
36
 * off-CPU FPGA PIC operations
 
37
 */
 
38
static void frv_fpga_mask(struct irq_data *d)
 
39
{
 
40
        uint16_t imr = __get_IMR();
 
41
 
 
42
        imr |= 1 << (d->irq - IRQ_BASE_FPGA);
 
43
        __set_IMR(imr);
 
44
}
 
45
 
 
46
static void frv_fpga_ack(struct irq_data *d)
 
47
{
 
48
        __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 
49
}
 
50
 
 
51
static void frv_fpga_mask_ack(struct irq_data *d)
 
52
{
 
53
        uint16_t imr = __get_IMR();
 
54
 
 
55
        imr |= 1 << (d->irq - IRQ_BASE_FPGA);
 
56
        __set_IMR(imr);
 
57
 
 
58
        __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 
59
}
 
60
 
 
61
static void frv_fpga_unmask(struct irq_data *d)
 
62
{
 
63
        uint16_t imr = __get_IMR();
 
64
 
 
65
        imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
 
66
 
 
67
        __set_IMR(imr);
 
68
}
 
69
 
 
70
static struct irq_chip frv_fpga_pic = {
 
71
        .name           = "mb93093",
 
72
        .irq_ack        = frv_fpga_ack,
 
73
        .irq_mask       = frv_fpga_mask,
 
74
        .irq_mask_ack   = frv_fpga_mask_ack,
 
75
        .irq_unmask     = frv_fpga_unmask,
 
76
};
 
77
 
 
78
/*
 
79
 * FPGA PIC interrupt handler
 
80
 */
 
81
static irqreturn_t fpga_interrupt(int irq, void *_mask)
 
82
{
 
83
        uint16_t imr, mask = (unsigned long) _mask;
 
84
 
 
85
        imr = __get_IMR();
 
86
        mask = mask & ~imr & __get_IFR();
 
87
 
 
88
        /* poll all the triggered IRQs */
 
89
        while (mask) {
 
90
                int irq;
 
91
 
 
92
                asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
 
93
                irq = 31 - irq;
 
94
                mask &= ~(1 << irq);
 
95
 
 
96
                generic_handle_irq(IRQ_BASE_FPGA + irq);
 
97
        }
 
98
 
 
99
        return IRQ_HANDLED;
 
100
}
 
101
 
 
102
/*
 
103
 * define an interrupt action for each FPGA PIC output
 
104
 * - use dev_id to indicate the FPGA PIC input to output mappings
 
105
 */
 
106
static struct irqaction fpga_irq[1]  = {
 
107
        [0] = {
 
108
                .handler        = fpga_interrupt,
 
109
                .flags          = IRQF_DISABLED,
 
110
                .name           = "fpga.0",
 
111
                .dev_id         = (void *) 0x0700UL,
 
112
        }
 
113
};
 
114
 
 
115
/*
 
116
 * initialise the motherboard FPGA's PIC
 
117
 */
 
118
void __init fpga_init(void)
 
119
{
 
120
        int irq;
 
121
 
 
122
        /* all PIC inputs are all set to be edge triggered */
 
123
        __set_IMR(0x0700);
 
124
        __clr_IFR(0x0000);
 
125
 
 
126
        for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++)
 
127
                irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);
 
128
 
 
129
        /* the FPGA drives external IRQ input #2 on the CPU PIC */
 
130
        setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]);
 
131
}