0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/io.h>
0015 #include <linux/irq.h>
0016 #include <linux/irqchip.h>
0017 #include <linux/irqchip/chained_irq.h>
0018 #include <linux/of_address.h>
0019 #include <linux/of_irq.h>
0020 #include <linux/interrupt.h>
0021
0022 #define APB_INT_ENABLE_L 0x00
0023 #define APB_INT_ENABLE_H 0x04
0024 #define APB_INT_MASK_L 0x08
0025 #define APB_INT_MASK_H 0x0c
0026 #define APB_INT_FINALSTATUS_L 0x30
0027 #define APB_INT_FINALSTATUS_H 0x34
0028 #define APB_INT_BASE_OFFSET 0x04
0029
0030
0031 static struct irq_domain *dw_apb_ictl_irq_domain;
0032
0033 static void __irq_entry dw_apb_ictl_handle_irq(struct pt_regs *regs)
0034 {
0035 struct irq_domain *d = dw_apb_ictl_irq_domain;
0036 int n;
0037
0038 for (n = 0; n < d->revmap_size; n += 32) {
0039 struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, n);
0040 u32 stat = readl_relaxed(gc->reg_base + APB_INT_FINALSTATUS_L);
0041
0042 while (stat) {
0043 u32 hwirq = ffs(stat) - 1;
0044
0045 generic_handle_domain_irq(d, hwirq);
0046 stat &= ~BIT(hwirq);
0047 }
0048 }
0049 }
0050
0051 static void dw_apb_ictl_handle_irq_cascaded(struct irq_desc *desc)
0052 {
0053 struct irq_domain *d = irq_desc_get_handler_data(desc);
0054 struct irq_chip *chip = irq_desc_get_chip(desc);
0055 int n;
0056
0057 chained_irq_enter(chip, desc);
0058
0059 for (n = 0; n < d->revmap_size; n += 32) {
0060 struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, n);
0061 u32 stat = readl_relaxed(gc->reg_base + APB_INT_FINALSTATUS_L);
0062
0063 while (stat) {
0064 u32 hwirq = ffs(stat) - 1;
0065 generic_handle_domain_irq(d, gc->irq_base + hwirq);
0066
0067 stat &= ~BIT(hwirq);
0068 }
0069 }
0070
0071 chained_irq_exit(chip, desc);
0072 }
0073
0074 static int dw_apb_ictl_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
0075 unsigned int nr_irqs, void *arg)
0076 {
0077 int i, ret;
0078 irq_hw_number_t hwirq;
0079 unsigned int type = IRQ_TYPE_NONE;
0080 struct irq_fwspec *fwspec = arg;
0081
0082 ret = irq_domain_translate_onecell(domain, fwspec, &hwirq, &type);
0083 if (ret)
0084 return ret;
0085
0086 for (i = 0; i < nr_irqs; i++)
0087 irq_map_generic_chip(domain, virq + i, hwirq + i);
0088
0089 return 0;
0090 }
0091
0092 static const struct irq_domain_ops dw_apb_ictl_irq_domain_ops = {
0093 .translate = irq_domain_translate_onecell,
0094 .alloc = dw_apb_ictl_irq_domain_alloc,
0095 .free = irq_domain_free_irqs_top,
0096 };
0097
0098 #ifdef CONFIG_PM
0099 static void dw_apb_ictl_resume(struct irq_data *d)
0100 {
0101 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0102 struct irq_chip_type *ct = irq_data_get_chip_type(d);
0103
0104 irq_gc_lock(gc);
0105 writel_relaxed(~0, gc->reg_base + ct->regs.enable);
0106 writel_relaxed(*ct->mask_cache, gc->reg_base + ct->regs.mask);
0107 irq_gc_unlock(gc);
0108 }
0109 #else
0110 #define dw_apb_ictl_resume NULL
0111 #endif
0112
0113 static int __init dw_apb_ictl_init(struct device_node *np,
0114 struct device_node *parent)
0115 {
0116 const struct irq_domain_ops *domain_ops;
0117 unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
0118 struct resource r;
0119 struct irq_domain *domain;
0120 struct irq_chip_generic *gc;
0121 void __iomem *iobase;
0122 int ret, nrirqs, parent_irq, i;
0123 u32 reg;
0124
0125 if (!parent) {
0126
0127 parent_irq = 0;
0128 domain_ops = &dw_apb_ictl_irq_domain_ops;
0129 } else {
0130
0131 parent_irq = irq_of_parse_and_map(np, 0);
0132 if (parent_irq <= 0) {
0133 pr_err("%pOF: unable to parse irq\n", np);
0134 return -EINVAL;
0135 }
0136 domain_ops = &irq_generic_chip_ops;
0137 }
0138
0139 ret = of_address_to_resource(np, 0, &r);
0140 if (ret) {
0141 pr_err("%pOF: unable to get resource\n", np);
0142 return ret;
0143 }
0144
0145 if (!request_mem_region(r.start, resource_size(&r), np->full_name)) {
0146 pr_err("%pOF: unable to request mem region\n", np);
0147 return -ENOMEM;
0148 }
0149
0150 iobase = ioremap(r.start, resource_size(&r));
0151 if (!iobase) {
0152 pr_err("%pOF: unable to map resource\n", np);
0153 ret = -ENOMEM;
0154 goto err_release;
0155 }
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 writel_relaxed(~0, iobase + APB_INT_MASK_L);
0166 writel_relaxed(~0, iobase + APB_INT_MASK_H);
0167 writel_relaxed(~0, iobase + APB_INT_ENABLE_L);
0168 writel_relaxed(~0, iobase + APB_INT_ENABLE_H);
0169
0170 reg = readl_relaxed(iobase + APB_INT_ENABLE_H);
0171 if (reg)
0172 nrirqs = 32 + fls(reg);
0173 else
0174 nrirqs = fls(readl_relaxed(iobase + APB_INT_ENABLE_L));
0175
0176 domain = irq_domain_add_linear(np, nrirqs, domain_ops, NULL);
0177 if (!domain) {
0178 pr_err("%pOF: unable to add irq domain\n", np);
0179 ret = -ENOMEM;
0180 goto err_unmap;
0181 }
0182
0183 ret = irq_alloc_domain_generic_chips(domain, 32, 1, np->name,
0184 handle_level_irq, clr, 0,
0185 IRQ_GC_INIT_MASK_CACHE);
0186 if (ret) {
0187 pr_err("%pOF: unable to alloc irq domain gc\n", np);
0188 goto err_unmap;
0189 }
0190
0191 for (i = 0; i < DIV_ROUND_UP(nrirqs, 32); i++) {
0192 gc = irq_get_domain_generic_chip(domain, i * 32);
0193 gc->reg_base = iobase + i * APB_INT_BASE_OFFSET;
0194 gc->chip_types[0].regs.mask = APB_INT_MASK_L;
0195 gc->chip_types[0].regs.enable = APB_INT_ENABLE_L;
0196 gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
0197 gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
0198 gc->chip_types[0].chip.irq_resume = dw_apb_ictl_resume;
0199 }
0200
0201 if (parent_irq) {
0202 irq_set_chained_handler_and_data(parent_irq,
0203 dw_apb_ictl_handle_irq_cascaded, domain);
0204 } else {
0205 dw_apb_ictl_irq_domain = domain;
0206 set_handle_irq(dw_apb_ictl_handle_irq);
0207 }
0208
0209 return 0;
0210
0211 err_unmap:
0212 iounmap(iobase);
0213 err_release:
0214 release_mem_region(r.start, resource_size(&r));
0215 return ret;
0216 }
0217 IRQCHIP_DECLARE(dw_apb_ictl,
0218 "snps,dw-apb-ictl", dw_apb_ictl_init);