Blame view

drivers/irqchip/irq-zevio.c 3.15 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
397e7b515   Daniel Tang   irqchip: Add supp...
2
3
4
5
  /*
   *  linux/drivers/irqchip/irq-zevio.c
   *
   *  Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
397e7b515   Daniel Tang   irqchip: Add supp...
6
7
8
9
   */
  
  #include <linux/io.h>
  #include <linux/irq.h>
41a83e06e   Joel Porquet   irqchip: Prepare ...
10
  #include <linux/irqchip.h>
397e7b515   Daniel Tang   irqchip: Add supp...
11
12
13
14
15
16
  #include <linux/of.h>
  #include <linux/of_address.h>
  #include <linux/of_irq.h>
  
  #include <asm/mach/irq.h>
  #include <asm/exception.h>
397e7b515   Daniel Tang   irqchip: Add supp...
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  #define IO_STATUS	0x000
  #define IO_RAW_STATUS	0x004
  #define IO_ENABLE	0x008
  #define IO_DISABLE	0x00C
  #define IO_CURRENT	0x020
  #define IO_RESET	0x028
  #define IO_MAX_PRIOTY	0x02C
  
  #define IO_IRQ_BASE	0x000
  #define IO_FIQ_BASE	0x100
  
  #define IO_INVERT_SEL	0x200
  #define IO_STICKY_SEL	0x204
  #define IO_PRIORITY_SEL	0x300
  
  #define MAX_INTRS	32
  #define FIQ_START	MAX_INTRS
  
  static struct irq_domain *zevio_irq_domain;
  static void __iomem *zevio_irq_io;
  
  static void zevio_irq_ack(struct irq_data *irqd)
  {
  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(irqd);
1fd9a7107   Geliang Tang   irqchip/zevio: Us...
41
  	struct irq_chip_regs *regs = &irq_data_get_chip_type(irqd)->regs;
397e7b515   Daniel Tang   irqchip: Add supp...
42
43
44
  
  	readl(gc->reg_base + regs->ack);
  }
8783dd3a3   Stephen Boyd   irqchip: Remove a...
45
  static void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs)
397e7b515   Daniel Tang   irqchip: Add supp...
46
47
48
49
50
  {
  	int irqnr;
  
  	while (readl(zevio_irq_io + IO_STATUS)) {
  		irqnr = readl(zevio_irq_io + IO_CURRENT);
d8c0ffa56   Marc Zyngier   irqchip: zevio: C...
51
  		handle_domain_irq(zevio_irq_domain, irqnr, regs);
2c5424261   Daode Huang   irqchip: Remove r...
52
  	}
397e7b515   Daniel Tang   irqchip: Add supp...
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  }
  
  static void __init zevio_init_irq_base(void __iomem *base)
  {
  	/* Disable all interrupts */
  	writel(~0, base + IO_DISABLE);
  
  	/* Accept interrupts of all priorities */
  	writel(0xF, base + IO_MAX_PRIOTY);
  
  	/* Reset existing interrupts */
  	readl(base + IO_RESET);
  }
  
  static int __init zevio_of_init(struct device_node *node,
  				struct device_node *parent)
  {
  	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
  	struct irq_chip_generic *gc;
  	int ret;
  
  	if (WARN_ON(zevio_irq_io || zevio_irq_domain))
  		return -EBUSY;
  
  	zevio_irq_io = of_iomap(node, 0);
  	BUG_ON(!zevio_irq_io);
  
  	/* Do not invert interrupt status bits */
  	writel(~0, zevio_irq_io + IO_INVERT_SEL);
  
  	/* Disable sticky interrupts */
  	writel(0, zevio_irq_io + IO_STICKY_SEL);
  
  	/* We don't use IRQ priorities. Set each IRQ to highest priority. */
  	memset_io(zevio_irq_io + IO_PRIORITY_SEL, 0, MAX_INTRS * sizeof(u32));
  
  	/* Init IRQ and FIQ */
  	zevio_init_irq_base(zevio_irq_io + IO_IRQ_BASE);
  	zevio_init_irq_base(zevio_irq_io + IO_FIQ_BASE);
  
  	zevio_irq_domain = irq_domain_add_linear(node, MAX_INTRS,
  						 &irq_generic_chip_ops, NULL);
  	BUG_ON(!zevio_irq_domain);
  
  	ret = irq_alloc_domain_generic_chips(zevio_irq_domain, MAX_INTRS, 1,
  					     "zevio_intc", handle_level_irq,
  					     clr, 0, IRQ_GC_INIT_MASK_CACHE);
  	BUG_ON(ret);
  
  	gc = irq_get_domain_generic_chip(zevio_irq_domain, 0);
  	gc->reg_base				= zevio_irq_io;
  	gc->chip_types[0].chip.irq_ack		= zevio_irq_ack;
  	gc->chip_types[0].chip.irq_mask		= irq_gc_mask_disable_reg;
  	gc->chip_types[0].chip.irq_unmask	= irq_gc_unmask_enable_reg;
  	gc->chip_types[0].regs.mask		= IO_IRQ_BASE + IO_ENABLE;
  	gc->chip_types[0].regs.enable		= IO_IRQ_BASE + IO_ENABLE;
  	gc->chip_types[0].regs.disable		= IO_IRQ_BASE + IO_DISABLE;
  	gc->chip_types[0].regs.ack		= IO_IRQ_BASE + IO_RESET;
  
  	set_handle_irq(zevio_handle_irq);
  
  	pr_info("TI-NSPIRE classic IRQ controller
  ");
  	return 0;
  }
  
  IRQCHIP_DECLARE(zevio_irq, "lsi,zevio-intc", zevio_of_init);