0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/interrupt.h>
0011 #include <linux/irq.h>
0012 #include <linux/ioport.h>
0013 #include <linux/of_address.h>
0014 #include <linux/of_irq.h>
0015 #include <linux/pgtable.h>
0016
0017 #include <asm/io.h>
0018
0019 #include "interrupt.h"
0020
0021
0022 enum {
0023 TIR_DEN = 0x004,
0024 TIR_MSK = 0x084,
0025 TIR_EDC = 0x0c0,
0026 TIR_PNDA = 0x100,
0027 TIR_PNDB = 0x104,
0028 TIR_CS = 0x144,
0029 TIR_LCSA = 0x150,
0030 TIR_LCSB = 0x154,
0031 TIR_LCSC = 0x158,
0032 TIR_LCSD = 0x15c,
0033 TIR_CFGA = 0x200,
0034 TIR_CFGB = 0x204,
0035
0036 TIR_PPNDA = 0x400,
0037 TIR_PPNDB = 0x404,
0038 TIR_PIERA = 0x408,
0039 TIR_PIERB = 0x40c,
0040 TIR_PIEN = 0x444,
0041 TIR_PIPND = 0x454,
0042 TIRDID = 0x484,
0043 REISTIM = 0x500,
0044 REISTIMEN = 0x504,
0045 REISWAITEN = 0x508,
0046 };
0047
0048 #define SPIDER_CHIP_COUNT 4
0049 #define SPIDER_SRC_COUNT 64
0050 #define SPIDER_IRQ_INVALID 63
0051
0052 struct spider_pic {
0053 struct irq_domain *host;
0054 void __iomem *regs;
0055 unsigned int node_id;
0056 };
0057 static struct spider_pic spider_pics[SPIDER_CHIP_COUNT];
0058
0059 static struct spider_pic *spider_irq_data_to_pic(struct irq_data *d)
0060 {
0061 return irq_data_get_irq_chip_data(d);
0062 }
0063
0064 static void __iomem *spider_get_irq_config(struct spider_pic *pic,
0065 unsigned int src)
0066 {
0067 return pic->regs + TIR_CFGA + 8 * src;
0068 }
0069
0070 static void spider_unmask_irq(struct irq_data *d)
0071 {
0072 struct spider_pic *pic = spider_irq_data_to_pic(d);
0073 void __iomem *cfg = spider_get_irq_config(pic, irqd_to_hwirq(d));
0074
0075 out_be32(cfg, in_be32(cfg) | 0x30000000u);
0076 }
0077
0078 static void spider_mask_irq(struct irq_data *d)
0079 {
0080 struct spider_pic *pic = spider_irq_data_to_pic(d);
0081 void __iomem *cfg = spider_get_irq_config(pic, irqd_to_hwirq(d));
0082
0083 out_be32(cfg, in_be32(cfg) & ~0x30000000u);
0084 }
0085
0086 static void spider_ack_irq(struct irq_data *d)
0087 {
0088 struct spider_pic *pic = spider_irq_data_to_pic(d);
0089 unsigned int src = irqd_to_hwirq(d);
0090
0091
0092
0093 if (irqd_is_level_type(d))
0094 return;
0095
0096
0097 if (src < 47 || src > 50)
0098 return;
0099
0100
0101 out_be32(pic->regs + TIR_EDC, 0x100 | (src & 0xf));
0102 }
0103
0104 static int spider_set_irq_type(struct irq_data *d, unsigned int type)
0105 {
0106 unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
0107 struct spider_pic *pic = spider_irq_data_to_pic(d);
0108 unsigned int hw = irqd_to_hwirq(d);
0109 void __iomem *cfg = spider_get_irq_config(pic, hw);
0110 u32 old_mask;
0111 u32 ic;
0112
0113
0114 if (sense != IRQ_TYPE_NONE && sense != IRQ_TYPE_LEVEL_HIGH &&
0115 (hw < 47 || hw > 50))
0116 return -EINVAL;
0117
0118
0119 switch(sense) {
0120 case IRQ_TYPE_EDGE_RISING:
0121 ic = 0x3;
0122 break;
0123 case IRQ_TYPE_EDGE_FALLING:
0124 ic = 0x2;
0125 break;
0126 case IRQ_TYPE_LEVEL_LOW:
0127 ic = 0x0;
0128 break;
0129 case IRQ_TYPE_LEVEL_HIGH:
0130 case IRQ_TYPE_NONE:
0131 ic = 0x1;
0132 break;
0133 default:
0134 return -EINVAL;
0135 }
0136
0137
0138
0139
0140
0141
0142
0143 old_mask = in_be32(cfg) & 0x30000000u;
0144 out_be32(cfg, old_mask | (ic << 24) | (0x7 << 16) |
0145 (pic->node_id << 4) | 0xe);
0146 out_be32(cfg + 4, (0x2 << 16) | (hw & 0xff));
0147
0148 return 0;
0149 }
0150
0151 static struct irq_chip spider_pic = {
0152 .name = "SPIDER",
0153 .irq_unmask = spider_unmask_irq,
0154 .irq_mask = spider_mask_irq,
0155 .irq_ack = spider_ack_irq,
0156 .irq_set_type = spider_set_irq_type,
0157 };
0158
0159 static int spider_host_map(struct irq_domain *h, unsigned int virq,
0160 irq_hw_number_t hw)
0161 {
0162 irq_set_chip_data(virq, h->host_data);
0163 irq_set_chip_and_handler(virq, &spider_pic, handle_level_irq);
0164
0165
0166 irq_set_irq_type(virq, IRQ_TYPE_NONE);
0167
0168 return 0;
0169 }
0170
0171 static int spider_host_xlate(struct irq_domain *h, struct device_node *ct,
0172 const u32 *intspec, unsigned int intsize,
0173 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
0174
0175 {
0176
0177
0178
0179
0180 *out_hwirq = intspec[0] & 0x3f;
0181 *out_flags = IRQ_TYPE_LEVEL_HIGH;
0182 return 0;
0183 }
0184
0185 static const struct irq_domain_ops spider_host_ops = {
0186 .map = spider_host_map,
0187 .xlate = spider_host_xlate,
0188 };
0189
0190 static void spider_irq_cascade(struct irq_desc *desc)
0191 {
0192 struct irq_chip *chip = irq_desc_get_chip(desc);
0193 struct spider_pic *pic = irq_desc_get_handler_data(desc);
0194 unsigned int cs;
0195
0196 cs = in_be32(pic->regs + TIR_CS) >> 24;
0197 if (cs != SPIDER_IRQ_INVALID)
0198 generic_handle_domain_irq(pic->host, cs);
0199
0200 chip->irq_eoi(&desc->irq_data);
0201 }
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211 static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
0212 {
0213 unsigned int virq;
0214 const u32 *imap, *tmp;
0215 int imaplen, intsize, unit;
0216 struct device_node *iic;
0217 struct device_node *of_node;
0218
0219 of_node = irq_domain_get_of_node(pic->host);
0220
0221
0222
0223
0224 virq = irq_of_parse_and_map(of_node, 0);
0225 if (virq)
0226 return virq;
0227
0228
0229 tmp = of_get_property(of_node, "#interrupt-cells", NULL);
0230 if (tmp == NULL)
0231 return 0;
0232 intsize = *tmp;
0233 imap = of_get_property(of_node, "interrupt-map", &imaplen);
0234 if (imap == NULL || imaplen < (intsize + 1))
0235 return 0;
0236 iic = of_find_node_by_phandle(imap[intsize]);
0237 if (iic == NULL)
0238 return 0;
0239 imap += intsize + 1;
0240 tmp = of_get_property(iic, "#interrupt-cells", NULL);
0241 if (tmp == NULL) {
0242 of_node_put(iic);
0243 return 0;
0244 }
0245 intsize = *tmp;
0246
0247 unit = imap[intsize - 1];
0248
0249 tmp = of_get_property(iic, "ibm,interrupt-server-ranges", NULL);
0250 if (tmp == NULL) {
0251 of_node_put(iic);
0252 return 0;
0253 }
0254
0255 pic->node_id = (*tmp) >> 1;
0256 of_node_put(iic);
0257
0258
0259
0260
0261
0262
0263 virq = irq_create_mapping(NULL,
0264 (pic->node_id << IIC_IRQ_NODE_SHIFT) |
0265 (2 << IIC_IRQ_CLASS_SHIFT) |
0266 unit);
0267 if (!virq)
0268 printk(KERN_ERR "spider_pic: failed to map cascade !");
0269 return virq;
0270 }
0271
0272
0273 static void __init spider_init_one(struct device_node *of_node, int chip,
0274 unsigned long addr)
0275 {
0276 struct spider_pic *pic = &spider_pics[chip];
0277 int i, virq;
0278
0279
0280 pic->regs = ioremap(addr, 0x1000);
0281 if (pic->regs == NULL)
0282 panic("spider_pic: can't map registers !");
0283
0284
0285 pic->host = irq_domain_add_linear(of_node, SPIDER_SRC_COUNT,
0286 &spider_host_ops, pic);
0287 if (pic->host == NULL)
0288 panic("spider_pic: can't allocate irq host !");
0289
0290
0291 for (i = 0; i < SPIDER_SRC_COUNT; i++) {
0292 void __iomem *cfg = pic->regs + TIR_CFGA + 8 * i;
0293 out_be32(cfg, in_be32(cfg) & ~0x30000000u);
0294 }
0295
0296
0297 out_be32(pic->regs + TIR_MSK, 0x0);
0298
0299
0300 out_be32(pic->regs + TIR_PIEN, in_be32(pic->regs + TIR_PIEN) | 0x1);
0301
0302
0303 virq = spider_find_cascade_and_node(pic);
0304 if (!virq)
0305 return;
0306 irq_set_handler_data(virq, pic);
0307 irq_set_chained_handler(virq, spider_irq_cascade);
0308
0309 printk(KERN_INFO "spider_pic: node %d, addr: 0x%lx %pOF\n",
0310 pic->node_id, addr, of_node);
0311
0312
0313 out_be32(pic->regs + TIR_DEN, in_be32(pic->regs + TIR_DEN) | 0x1);
0314 }
0315
0316 void __init spider_init_IRQ(void)
0317 {
0318 struct resource r;
0319 struct device_node *dn;
0320 int chip = 0;
0321
0322
0323
0324
0325
0326
0327
0328
0329 for_each_node_by_name(dn, "interrupt-controller") {
0330 if (of_device_is_compatible(dn, "CBEA,platform-spider-pic")) {
0331 if (of_address_to_resource(dn, 0, &r)) {
0332 printk(KERN_WARNING "spider-pic: Failed\n");
0333 continue;
0334 }
0335 } else if (of_device_is_compatible(dn, "sti,platform-spider-pic")
0336 && (chip < 2)) {
0337 static long hard_coded_pics[] =
0338 { 0x24000008000ul, 0x34000008000ul};
0339 r.start = hard_coded_pics[chip];
0340 } else
0341 continue;
0342 spider_init_one(dn, chip++, r.start);
0343 }
0344 }