0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/export.h>
0010 #include <linux/init.h>
0011 #include <linux/list.h>
0012 #include <linux/io.h>
0013 #include <linux/irq.h>
0014 #include <linux/irqchip.h>
0015 #include <linux/irqchip/chained_irq.h>
0016 #include <linux/irqdomain.h>
0017 #include <linux/of.h>
0018 #include <linux/of_address.h>
0019 #include <linux/of_irq.h>
0020 #include <linux/syscore_ops.h>
0021 #include <linux/device.h>
0022 #include <linux/amba/bus.h>
0023 #include <linux/irqchip/arm-vic.h>
0024
0025 #include <asm/exception.h>
0026 #include <asm/irq.h>
0027
0028 #define VIC_IRQ_STATUS 0x00
0029 #define VIC_FIQ_STATUS 0x04
0030 #define VIC_RAW_STATUS 0x08
0031 #define VIC_INT_SELECT 0x0c
0032 #define VIC_INT_ENABLE 0x10
0033 #define VIC_INT_ENABLE_CLEAR 0x14
0034 #define VIC_INT_SOFT 0x18
0035 #define VIC_INT_SOFT_CLEAR 0x1c
0036 #define VIC_PROTECT 0x20
0037 #define VIC_PL190_VECT_ADDR 0x30
0038 #define VIC_PL190_DEF_VECT_ADDR 0x34
0039
0040 #define VIC_VECT_ADDR0 0x100
0041 #define VIC_VECT_CNTL0 0x200
0042 #define VIC_ITCR 0x300
0043
0044 #define VIC_VECT_CNTL_ENABLE (1 << 5)
0045
0046 #define VIC_PL192_VECT_ADDR 0xF00
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 struct vic_device {
0063 void __iomem *base;
0064 int irq;
0065 u32 valid_sources;
0066 u32 resume_sources;
0067 u32 resume_irqs;
0068 u32 int_select;
0069 u32 int_enable;
0070 u32 soft_int;
0071 u32 protect;
0072 struct irq_domain *domain;
0073 };
0074
0075
0076 static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
0077
0078 static int vic_id;
0079
0080 static void vic_handle_irq(struct pt_regs *regs);
0081
0082
0083
0084
0085
0086
0087
0088
0089 static void vic_init2(void __iomem *base)
0090 {
0091 int i;
0092
0093 for (i = 0; i < 16; i++) {
0094 void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
0095 writel(VIC_VECT_CNTL_ENABLE | i, reg);
0096 }
0097
0098 writel(32, base + VIC_PL190_DEF_VECT_ADDR);
0099 }
0100
0101 #ifdef CONFIG_PM
0102 static void resume_one_vic(struct vic_device *vic)
0103 {
0104 void __iomem *base = vic->base;
0105
0106 printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base);
0107
0108
0109 vic_init2(base);
0110
0111 writel(vic->int_select, base + VIC_INT_SELECT);
0112 writel(vic->protect, base + VIC_PROTECT);
0113
0114
0115 writel(vic->int_enable, base + VIC_INT_ENABLE);
0116 writel(~vic->int_enable, base + VIC_INT_ENABLE_CLEAR);
0117
0118
0119
0120 writel(vic->soft_int, base + VIC_INT_SOFT);
0121 writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR);
0122 }
0123
0124 static void vic_resume(void)
0125 {
0126 int id;
0127
0128 for (id = vic_id - 1; id >= 0; id--)
0129 resume_one_vic(vic_devices + id);
0130 }
0131
0132 static void suspend_one_vic(struct vic_device *vic)
0133 {
0134 void __iomem *base = vic->base;
0135
0136 printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base);
0137
0138 vic->int_select = readl(base + VIC_INT_SELECT);
0139 vic->int_enable = readl(base + VIC_INT_ENABLE);
0140 vic->soft_int = readl(base + VIC_INT_SOFT);
0141 vic->protect = readl(base + VIC_PROTECT);
0142
0143
0144
0145
0146 writel(vic->resume_irqs, base + VIC_INT_ENABLE);
0147 writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR);
0148 }
0149
0150 static int vic_suspend(void)
0151 {
0152 int id;
0153
0154 for (id = 0; id < vic_id; id++)
0155 suspend_one_vic(vic_devices + id);
0156
0157 return 0;
0158 }
0159
0160 static struct syscore_ops vic_syscore_ops = {
0161 .suspend = vic_suspend,
0162 .resume = vic_resume,
0163 };
0164
0165
0166
0167
0168
0169
0170
0171
0172 static int __init vic_pm_init(void)
0173 {
0174 if (vic_id > 0)
0175 register_syscore_ops(&vic_syscore_ops);
0176
0177 return 0;
0178 }
0179 late_initcall(vic_pm_init);
0180 #endif
0181
0182 static struct irq_chip vic_chip;
0183
0184 static int vic_irqdomain_map(struct irq_domain *d, unsigned int irq,
0185 irq_hw_number_t hwirq)
0186 {
0187 struct vic_device *v = d->host_data;
0188
0189
0190 if (!(v->valid_sources & (1 << hwirq)))
0191 return -EPERM;
0192 irq_set_chip_and_handler(irq, &vic_chip, handle_level_irq);
0193 irq_set_chip_data(irq, v->base);
0194 irq_set_probe(irq);
0195 return 0;
0196 }
0197
0198
0199
0200
0201
0202
0203
0204 static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
0205 {
0206 u32 stat, irq;
0207 int handled = 0;
0208
0209 while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
0210 irq = ffs(stat) - 1;
0211 generic_handle_domain_irq(vic->domain, irq);
0212 handled = 1;
0213 }
0214
0215 return handled;
0216 }
0217
0218 static void vic_handle_irq_cascaded(struct irq_desc *desc)
0219 {
0220 u32 stat, hwirq;
0221 struct irq_chip *host_chip = irq_desc_get_chip(desc);
0222 struct vic_device *vic = irq_desc_get_handler_data(desc);
0223
0224 chained_irq_enter(host_chip, desc);
0225
0226 while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
0227 hwirq = ffs(stat) - 1;
0228 generic_handle_domain_irq(vic->domain, hwirq);
0229 }
0230
0231 chained_irq_exit(host_chip, desc);
0232 }
0233
0234
0235
0236
0237
0238 static void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
0239 {
0240 int i, handled;
0241
0242 do {
0243 for (i = 0, handled = 0; i < vic_id; ++i)
0244 handled |= handle_one_vic(&vic_devices[i], regs);
0245 } while (handled);
0246 }
0247
0248 static const struct irq_domain_ops vic_irqdomain_ops = {
0249 .map = vic_irqdomain_map,
0250 .xlate = irq_domain_xlate_onetwocell,
0251 };
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268 static void __init vic_register(void __iomem *base, unsigned int parent_irq,
0269 unsigned int irq,
0270 u32 valid_sources, u32 resume_sources,
0271 struct device_node *node)
0272 {
0273 struct vic_device *v;
0274 int i;
0275
0276 if (vic_id >= ARRAY_SIZE(vic_devices)) {
0277 printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
0278 return;
0279 }
0280
0281 v = &vic_devices[vic_id];
0282 v->base = base;
0283 v->valid_sources = valid_sources;
0284 v->resume_sources = resume_sources;
0285 set_handle_irq(vic_handle_irq);
0286 vic_id++;
0287
0288 if (parent_irq) {
0289 irq_set_chained_handler_and_data(parent_irq,
0290 vic_handle_irq_cascaded, v);
0291 }
0292
0293 v->domain = irq_domain_add_simple(node, fls(valid_sources), irq,
0294 &vic_irqdomain_ops, v);
0295
0296 for (i = 0; i < fls(valid_sources); i++)
0297 if (valid_sources & (1 << i))
0298 irq_create_mapping(v->domain, i);
0299
0300 if (irq)
0301 v->irq = irq;
0302 else
0303 v->irq = irq_find_mapping(v->domain, 0);
0304 }
0305
0306 static void vic_ack_irq(struct irq_data *d)
0307 {
0308 void __iomem *base = irq_data_get_irq_chip_data(d);
0309 unsigned int irq = d->hwirq;
0310 writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
0311
0312 writel(1 << irq, base + VIC_INT_SOFT_CLEAR);
0313 }
0314
0315 static void vic_mask_irq(struct irq_data *d)
0316 {
0317 void __iomem *base = irq_data_get_irq_chip_data(d);
0318 unsigned int irq = d->hwirq;
0319 writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
0320 }
0321
0322 static void vic_unmask_irq(struct irq_data *d)
0323 {
0324 void __iomem *base = irq_data_get_irq_chip_data(d);
0325 unsigned int irq = d->hwirq;
0326 writel(1 << irq, base + VIC_INT_ENABLE);
0327 }
0328
0329 #if defined(CONFIG_PM)
0330 static struct vic_device *vic_from_irq(unsigned int irq)
0331 {
0332 struct vic_device *v = vic_devices;
0333 unsigned int base_irq = irq & ~31;
0334 int id;
0335
0336 for (id = 0; id < vic_id; id++, v++) {
0337 if (v->irq == base_irq)
0338 return v;
0339 }
0340
0341 return NULL;
0342 }
0343
0344 static int vic_set_wake(struct irq_data *d, unsigned int on)
0345 {
0346 struct vic_device *v = vic_from_irq(d->irq);
0347 unsigned int off = d->hwirq;
0348 u32 bit = 1 << off;
0349
0350 if (!v)
0351 return -EINVAL;
0352
0353 if (!(bit & v->resume_sources))
0354 return -EINVAL;
0355
0356 if (on)
0357 v->resume_irqs |= bit;
0358 else
0359 v->resume_irqs &= ~bit;
0360
0361 return 0;
0362 }
0363 #else
0364 #define vic_set_wake NULL
0365 #endif
0366
0367 static struct irq_chip vic_chip = {
0368 .name = "VIC",
0369 .irq_ack = vic_ack_irq,
0370 .irq_mask = vic_mask_irq,
0371 .irq_unmask = vic_unmask_irq,
0372 .irq_set_wake = vic_set_wake,
0373 };
0374
0375 static void __init vic_disable(void __iomem *base)
0376 {
0377 writel(0, base + VIC_INT_SELECT);
0378 writel(0, base + VIC_INT_ENABLE);
0379 writel(~0, base + VIC_INT_ENABLE_CLEAR);
0380 writel(0, base + VIC_ITCR);
0381 writel(~0, base + VIC_INT_SOFT_CLEAR);
0382 }
0383
0384 static void __init vic_clear_interrupts(void __iomem *base)
0385 {
0386 unsigned int i;
0387
0388 writel(0, base + VIC_PL190_VECT_ADDR);
0389 for (i = 0; i < 19; i++) {
0390 unsigned int value;
0391
0392 value = readl(base + VIC_PL190_VECT_ADDR);
0393 writel(value, base + VIC_PL190_VECT_ADDR);
0394 }
0395 }
0396
0397
0398
0399
0400
0401
0402
0403
0404 static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
0405 u32 vic_sources, struct device_node *node)
0406 {
0407 unsigned int i;
0408 int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0;
0409
0410
0411 vic_disable(base);
0412
0413
0414
0415
0416
0417
0418
0419 if (vic_2nd_block) {
0420 vic_clear_interrupts(base);
0421
0422
0423 for (i = 0; i < 16; i++) {
0424 void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
0425 writel(0, reg);
0426 }
0427
0428 writel(32, base + VIC_PL190_DEF_VECT_ADDR);
0429 }
0430
0431 vic_register(base, 0, irq_start, vic_sources, 0, node);
0432 }
0433
0434 static void __init __vic_init(void __iomem *base, int parent_irq, int irq_start,
0435 u32 vic_sources, u32 resume_sources,
0436 struct device_node *node)
0437 {
0438 unsigned int i;
0439 u32 cellid = 0;
0440 enum amba_vendor vendor;
0441
0442
0443 for (i = 0; i < 4; i++) {
0444 void __iomem *addr;
0445 addr = (void __iomem *)((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
0446 cellid |= (readl(addr) & 0xff) << (8 * i);
0447 }
0448 vendor = (cellid >> 12) & 0xff;
0449 printk(KERN_INFO "VIC @%p: id 0x%08x, vendor 0x%02x\n",
0450 base, cellid, vendor);
0451
0452 switch(vendor) {
0453 case AMBA_VENDOR_ST:
0454 vic_init_st(base, irq_start, vic_sources, node);
0455 return;
0456 default:
0457 printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n");
0458 fallthrough;
0459 case AMBA_VENDOR_ARM:
0460 break;
0461 }
0462
0463
0464 vic_disable(base);
0465
0466
0467 vic_clear_interrupts(base);
0468
0469 vic_init2(base);
0470
0471 vic_register(base, parent_irq, irq_start, vic_sources, resume_sources, node);
0472 }
0473
0474
0475
0476
0477
0478
0479
0480
0481 void __init vic_init(void __iomem *base, unsigned int irq_start,
0482 u32 vic_sources, u32 resume_sources)
0483 {
0484 __vic_init(base, 0, irq_start, vic_sources, resume_sources, NULL);
0485 }
0486
0487 #ifdef CONFIG_OF
0488 static int __init vic_of_init(struct device_node *node,
0489 struct device_node *parent)
0490 {
0491 void __iomem *regs;
0492 u32 interrupt_mask = ~0;
0493 u32 wakeup_mask = ~0;
0494 int parent_irq;
0495
0496 regs = of_iomap(node, 0);
0497 if (WARN_ON(!regs))
0498 return -EIO;
0499
0500 of_property_read_u32(node, "valid-mask", &interrupt_mask);
0501 of_property_read_u32(node, "valid-wakeup-mask", &wakeup_mask);
0502 parent_irq = of_irq_get(node, 0);
0503 if (parent_irq < 0)
0504 parent_irq = 0;
0505
0506
0507
0508
0509 __vic_init(regs, parent_irq, 0, interrupt_mask, wakeup_mask, node);
0510
0511 return 0;
0512 }
0513 IRQCHIP_DECLARE(arm_pl190_vic, "arm,pl190-vic", vic_of_init);
0514 IRQCHIP_DECLARE(arm_pl192_vic, "arm,pl192-vic", vic_of_init);
0515 IRQCHIP_DECLARE(arm_versatile_vic, "arm,versatile-vic", vic_of_init);
0516 #endif