0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/stddef.h>
0014 #include <linux/kernel.h>
0015 #include <linux/init.h>
0016 #include <linux/irq.h>
0017 #include <linux/irqdomain.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/of_address.h>
0020 #include <linux/of_irq.h>
0021 #include <linux/spinlock.h>
0022
0023 #include <asm/byteorder.h>
0024 #include <asm/io.h>
0025 #include <asm/irq.h>
0026
0027 #include "ge_pic.h"
0028
0029 #define DEBUG
0030 #undef DEBUG
0031
0032 #ifdef DEBUG
0033 #define DBG(fmt...) do { printk(KERN_DEBUG "gef_pic: " fmt); } while (0)
0034 #else
0035 #define DBG(fmt...) do { } while (0)
0036 #endif
0037
0038 #define GEF_PIC_NUM_IRQS 32
0039
0040
0041 #define GEF_PIC_INTR_STATUS 0x0000
0042
0043 #define GEF_PIC_INTR_MASK(cpu) (0x0010 + (0x4 * cpu))
0044 #define GEF_PIC_CPU0_INTR_MASK GEF_PIC_INTR_MASK(0)
0045 #define GEF_PIC_CPU1_INTR_MASK GEF_PIC_INTR_MASK(1)
0046
0047 #define GEF_PIC_MCP_MASK(cpu) (0x0018 + (0x4 * cpu))
0048 #define GEF_PIC_CPU0_MCP_MASK GEF_PIC_MCP_MASK(0)
0049 #define GEF_PIC_CPU1_MCP_MASK GEF_PIC_MCP_MASK(1)
0050
0051
0052 static DEFINE_RAW_SPINLOCK(gef_pic_lock);
0053
0054 static void __iomem *gef_pic_irq_reg_base;
0055 static struct irq_domain *gef_pic_irq_host;
0056 static int gef_pic_cascade_irq;
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 static void gef_pic_cascade(struct irq_desc *desc)
0097 {
0098 struct irq_chip *chip = irq_desc_get_chip(desc);
0099 unsigned int cascade_irq;
0100
0101
0102
0103
0104
0105 cascade_irq = gef_pic_get_irq();
0106
0107 if (cascade_irq)
0108 generic_handle_irq(cascade_irq);
0109
0110 chip->irq_eoi(&desc->irq_data);
0111 }
0112
0113 static void gef_pic_mask(struct irq_data *d)
0114 {
0115 unsigned long flags;
0116 unsigned int hwirq = irqd_to_hwirq(d);
0117 u32 mask;
0118
0119 raw_spin_lock_irqsave(&gef_pic_lock, flags);
0120 mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
0121 mask &= ~(1 << hwirq);
0122 out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
0123 raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
0124 }
0125
0126 static void gef_pic_mask_ack(struct irq_data *d)
0127 {
0128
0129
0130
0131 gef_pic_mask(d);
0132 }
0133
0134 static void gef_pic_unmask(struct irq_data *d)
0135 {
0136 unsigned long flags;
0137 unsigned int hwirq = irqd_to_hwirq(d);
0138 u32 mask;
0139
0140 raw_spin_lock_irqsave(&gef_pic_lock, flags);
0141 mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
0142 mask |= (1 << hwirq);
0143 out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
0144 raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
0145 }
0146
0147 static struct irq_chip gef_pic_chip = {
0148 .name = "gefp",
0149 .irq_mask = gef_pic_mask,
0150 .irq_mask_ack = gef_pic_mask_ack,
0151 .irq_unmask = gef_pic_unmask,
0152 };
0153
0154
0155
0156
0157
0158 static int gef_pic_host_map(struct irq_domain *h, unsigned int virq,
0159 irq_hw_number_t hwirq)
0160 {
0161
0162 irq_set_status_flags(virq, IRQ_LEVEL);
0163 irq_set_chip_and_handler(virq, &gef_pic_chip, handle_level_irq);
0164
0165 return 0;
0166 }
0167
0168 static int gef_pic_host_xlate(struct irq_domain *h, struct device_node *ct,
0169 const u32 *intspec, unsigned int intsize,
0170 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
0171 {
0172
0173 *out_hwirq = intspec[0];
0174 if (intsize > 1)
0175 *out_flags = intspec[1];
0176 else
0177 *out_flags = IRQ_TYPE_LEVEL_HIGH;
0178
0179 return 0;
0180 }
0181
0182 static const struct irq_domain_ops gef_pic_host_ops = {
0183 .map = gef_pic_host_map,
0184 .xlate = gef_pic_host_xlate,
0185 };
0186
0187
0188
0189
0190
0191 void __init gef_pic_init(struct device_node *np)
0192 {
0193 unsigned long flags;
0194
0195
0196 gef_pic_irq_reg_base = of_iomap(np, 0);
0197
0198 raw_spin_lock_irqsave(&gef_pic_lock, flags);
0199
0200
0201 out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_INTR_MASK, 0);
0202 out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_INTR_MASK, 0);
0203
0204 out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_MCP_MASK, 0);
0205 out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_MCP_MASK, 0);
0206
0207 raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
0208
0209
0210 gef_pic_cascade_irq = irq_of_parse_and_map(np, 0);
0211 if (!gef_pic_cascade_irq) {
0212 printk(KERN_ERR "SBC610: failed to map cascade interrupt");
0213 return;
0214 }
0215
0216
0217 gef_pic_irq_host = irq_domain_add_linear(np, GEF_PIC_NUM_IRQS,
0218 &gef_pic_host_ops, NULL);
0219 if (gef_pic_irq_host == NULL)
0220 return;
0221
0222
0223 irq_set_chained_handler(gef_pic_cascade_irq, gef_pic_cascade);
0224 }
0225
0226
0227
0228
0229
0230 unsigned int gef_pic_get_irq(void)
0231 {
0232 u32 cause, mask, active;
0233 unsigned int virq = 0;
0234 int hwirq;
0235
0236 cause = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_STATUS);
0237
0238 mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
0239
0240 active = cause & mask;
0241
0242 if (active) {
0243 for (hwirq = GEF_PIC_NUM_IRQS - 1; hwirq > -1; hwirq--) {
0244 if (active & (0x1 << hwirq))
0245 break;
0246 }
0247 virq = irq_linear_revmap(gef_pic_irq_host,
0248 (irq_hw_number_t)hwirq);
0249 }
0250
0251 return virq;
0252 }
0253