OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [powerpc/] [sysdev/] [xilinx_intc.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * Interrupt controller driver for Xilinx Virtex FPGAs
3
 *
4
 * Copyright (C) 2007 Secret Lab Technologies Ltd.
5
 *
6
 * This file is licensed under the terms of the GNU General Public License
7
 * version 2. This program is licensed "as is" without any warranty of any
8
 * kind, whether express or implied.
9
 *
10
 */
11
 
12
/*
13
 * This is a driver for the interrupt controller typically found in
14
 * Xilinx Virtex FPGA designs.
15
 *
16
 * The interrupt sense levels are hard coded into the FPGA design with
17
 * typically a 1:1 relationship between irq lines and devices (no shared
18
 * irq lines).  Therefore, this driver does not attempt to handle edge
19
 * and level interrupts differently.
20
 */
21
#undef DEBUG
22
 
23
#include <linux/kernel.h>
24
#include <linux/irq.h>
25
#include <linux/of.h>
26
#include <asm/io.h>
27
#include <asm/processor.h>
28
#include <asm/irq.h>
29
 
30
/*
31
 * INTC Registers
32
 */
33
#define XINTC_ISR       0        /* Interrupt Status */
34
#define XINTC_IPR       4       /* Interrupt Pending */
35
#define XINTC_IER       8       /* Interrupt Enable */
36
#define XINTC_IAR       12      /* Interrupt Acknowledge */
37
#define XINTC_SIE       16      /* Set Interrupt Enable bits */
38
#define XINTC_CIE       20      /* Clear Interrupt Enable bits */
39
#define XINTC_IVR       24      /* Interrupt Vector */
40
#define XINTC_MER       28      /* Master Enable */
41
 
42
static struct irq_host *master_irqhost;
43
 
44
/*
45
 * IRQ Chip operations
46
 */
47
static void xilinx_intc_mask(unsigned int virq)
48
{
49
        int irq = virq_to_hw(virq);
50
        void * regs = get_irq_chip_data(virq);
51
        pr_debug("mask: %d\n", irq);
52
        out_be32(regs + XINTC_CIE, 1 << irq);
53
}
54
 
55
static void xilinx_intc_unmask(unsigned int virq)
56
{
57
        int irq = virq_to_hw(virq);
58
        void * regs = get_irq_chip_data(virq);
59
        pr_debug("unmask: %d\n", irq);
60
        out_be32(regs + XINTC_SIE, 1 << irq);
61
}
62
 
63
static void xilinx_intc_ack(unsigned int virq)
64
{
65
        int irq = virq_to_hw(virq);
66
        void * regs = get_irq_chip_data(virq);
67
        pr_debug("ack: %d\n", irq);
68
        out_be32(regs + XINTC_IAR, 1 << irq);
69
}
70
 
71
static struct irq_chip xilinx_intc_irqchip = {
72
        .typename = "Xilinx INTC",
73
        .mask = xilinx_intc_mask,
74
        .unmask = xilinx_intc_unmask,
75
        .ack = xilinx_intc_ack,
76
};
77
 
78
/*
79
 * IRQ Host operations
80
 */
81
static int xilinx_intc_map(struct irq_host *h, unsigned int virq,
82
                                  irq_hw_number_t irq)
83
{
84
        set_irq_chip_data(virq, h->host_data);
85
        set_irq_chip_and_handler(virq, &xilinx_intc_irqchip, handle_level_irq);
86
        set_irq_type(virq, IRQ_TYPE_NONE);
87
        return 0;
88
}
89
 
90
static struct irq_host_ops xilinx_intc_ops = {
91
        .map = xilinx_intc_map,
92
};
93
 
94
struct irq_host * __init
95
xilinx_intc_init(struct device_node *np)
96
{
97
        struct irq_host * irq;
98
        struct resource res;
99
        void * regs;
100
        int rc;
101
 
102
        /* Find and map the intc registers */
103
        rc = of_address_to_resource(np, 0, &res);
104
        if (rc) {
105
                printk(KERN_ERR __FILE__ ": of_address_to_resource() failed\n");
106
                return NULL;
107
        }
108
        regs = ioremap(res.start, 32);
109
 
110
        printk(KERN_INFO "Xilinx intc at 0x%08X mapped to 0x%p\n",
111
                res.start, regs);
112
 
113
        /* Setup interrupt controller */
114
        out_be32(regs + XINTC_IER, 0); /* disable all irqs */
115
        out_be32(regs + XINTC_IAR, ~(u32) 0); /* Acknowledge pending irqs */
116
        out_be32(regs + XINTC_MER, 0x3UL); /* Turn on the Master Enable. */
117
 
118
        /* Allocate and initialize an irq_host structure. */
119
        irq = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, 32, &xilinx_intc_ops, -1);
120
        if (!irq)
121
                panic(__FILE__ ": Cannot allocate IRQ host\n");
122
        irq->host_data = regs;
123
        return irq;
124
}
125
 
126
int xilinx_intc_get_irq(void)
127
{
128
        void * regs = master_irqhost->host_data;
129
        pr_debug("get_irq:\n");
130
        return irq_linear_revmap(master_irqhost, in_be32(regs + XINTC_IVR));
131
}
132
 
133
void __init xilinx_intc_init_tree(void)
134
{
135
        struct device_node *np;
136
 
137
        /* find top level interrupt controller */
138
        for_each_compatible_node(np, NULL, "xilinx,intc") {
139
                if (!of_get_property(np, "interrupts", NULL))
140
                        break;
141
        }
142
 
143
        /* xilinx interrupt controller needs to be top level */
144
        BUG_ON(!np);
145
 
146
        master_irqhost = xilinx_intc_init(np);
147
        BUG_ON(!master_irqhost);
148
 
149
        irq_set_default_host(master_irqhost);
150
        of_node_put(np);
151
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.