0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/bitops.h>
0011 #include <linux/irq.h>
0012 #include <linux/io.h>
0013 #include <linux/irqchip.h>
0014 #include <linux/irqdomain.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/of_address.h>
0018 #include <linux/of_irq.h>
0019 #include <linux/cpu.h>
0020
0021 #include <asm/exception.h>
0022 #include <asm/mach/irq.h>
0023
0024 #define FT010_NUM_IRQS 32
0025
0026 #define FT010_IRQ_SOURCE(base_addr) (base_addr + 0x00)
0027 #define FT010_IRQ_MASK(base_addr) (base_addr + 0x04)
0028 #define FT010_IRQ_CLEAR(base_addr) (base_addr + 0x08)
0029
0030 #define FT010_IRQ_MODE(base_addr) (base_addr + 0x0C)
0031
0032 #define FT010_IRQ_POLARITY(base_addr) (base_addr + 0x10)
0033 #define FT010_IRQ_STATUS(base_addr) (base_addr + 0x14)
0034 #define FT010_FIQ_SOURCE(base_addr) (base_addr + 0x20)
0035 #define FT010_FIQ_MASK(base_addr) (base_addr + 0x24)
0036 #define FT010_FIQ_CLEAR(base_addr) (base_addr + 0x28)
0037 #define FT010_FIQ_MODE(base_addr) (base_addr + 0x2C)
0038 #define FT010_FIQ_POLARITY(base_addr) (base_addr + 0x30)
0039 #define FT010_FIQ_STATUS(base_addr) (base_addr + 0x34)
0040
0041
0042
0043
0044
0045
0046
0047 struct ft010_irq_data {
0048 void __iomem *base;
0049 struct irq_chip chip;
0050 struct irq_domain *domain;
0051 };
0052
0053 static void ft010_irq_mask(struct irq_data *d)
0054 {
0055 struct ft010_irq_data *f = irq_data_get_irq_chip_data(d);
0056 unsigned int mask;
0057
0058 mask = readl(FT010_IRQ_MASK(f->base));
0059 mask &= ~BIT(irqd_to_hwirq(d));
0060 writel(mask, FT010_IRQ_MASK(f->base));
0061 }
0062
0063 static void ft010_irq_unmask(struct irq_data *d)
0064 {
0065 struct ft010_irq_data *f = irq_data_get_irq_chip_data(d);
0066 unsigned int mask;
0067
0068 mask = readl(FT010_IRQ_MASK(f->base));
0069 mask |= BIT(irqd_to_hwirq(d));
0070 writel(mask, FT010_IRQ_MASK(f->base));
0071 }
0072
0073 static void ft010_irq_ack(struct irq_data *d)
0074 {
0075 struct ft010_irq_data *f = irq_data_get_irq_chip_data(d);
0076
0077 writel(BIT(irqd_to_hwirq(d)), FT010_IRQ_CLEAR(f->base));
0078 }
0079
0080 static int ft010_irq_set_type(struct irq_data *d, unsigned int trigger)
0081 {
0082 struct ft010_irq_data *f = irq_data_get_irq_chip_data(d);
0083 int offset = irqd_to_hwirq(d);
0084 u32 mode, polarity;
0085
0086 mode = readl(FT010_IRQ_MODE(f->base));
0087 polarity = readl(FT010_IRQ_POLARITY(f->base));
0088
0089 if (trigger & (IRQ_TYPE_LEVEL_LOW)) {
0090 irq_set_handler_locked(d, handle_level_irq);
0091 mode &= ~BIT(offset);
0092 polarity |= BIT(offset);
0093 } else if (trigger & (IRQ_TYPE_LEVEL_HIGH)) {
0094 irq_set_handler_locked(d, handle_level_irq);
0095 mode &= ~BIT(offset);
0096 polarity &= ~BIT(offset);
0097 } else if (trigger & IRQ_TYPE_EDGE_FALLING) {
0098 irq_set_handler_locked(d, handle_edge_irq);
0099 mode |= BIT(offset);
0100 polarity |= BIT(offset);
0101 } else if (trigger & IRQ_TYPE_EDGE_RISING) {
0102 irq_set_handler_locked(d, handle_edge_irq);
0103 mode |= BIT(offset);
0104 polarity &= ~BIT(offset);
0105 } else {
0106 irq_set_handler_locked(d, handle_bad_irq);
0107 pr_warn("Faraday IRQ: no supported trigger selected for line %d\n",
0108 offset);
0109 }
0110
0111 writel(mode, FT010_IRQ_MODE(f->base));
0112 writel(polarity, FT010_IRQ_POLARITY(f->base));
0113
0114 return 0;
0115 }
0116
0117 static struct irq_chip ft010_irq_chip = {
0118 .name = "FTINTC010",
0119 .irq_ack = ft010_irq_ack,
0120 .irq_mask = ft010_irq_mask,
0121 .irq_unmask = ft010_irq_unmask,
0122 .irq_set_type = ft010_irq_set_type,
0123 };
0124
0125
0126 static struct ft010_irq_data firq;
0127
0128 asmlinkage void __exception_irq_entry ft010_irqchip_handle_irq(struct pt_regs *regs)
0129 {
0130 struct ft010_irq_data *f = &firq;
0131 int irq;
0132 u32 status;
0133
0134 while ((status = readl(FT010_IRQ_STATUS(f->base)))) {
0135 irq = ffs(status) - 1;
0136 generic_handle_domain_irq(f->domain, irq);
0137 }
0138 }
0139
0140 static int ft010_irqdomain_map(struct irq_domain *d, unsigned int irq,
0141 irq_hw_number_t hwirq)
0142 {
0143 struct ft010_irq_data *f = d->host_data;
0144
0145 irq_set_chip_data(irq, f);
0146
0147 irq_set_chip_and_handler(irq, &ft010_irq_chip, handle_bad_irq);
0148 irq_set_probe(irq);
0149
0150 return 0;
0151 }
0152
0153 static void ft010_irqdomain_unmap(struct irq_domain *d, unsigned int irq)
0154 {
0155 irq_set_chip_and_handler(irq, NULL, NULL);
0156 irq_set_chip_data(irq, NULL);
0157 }
0158
0159 static const struct irq_domain_ops ft010_irqdomain_ops = {
0160 .map = ft010_irqdomain_map,
0161 .unmap = ft010_irqdomain_unmap,
0162 .xlate = irq_domain_xlate_onetwocell,
0163 };
0164
0165 int __init ft010_of_init_irq(struct device_node *node,
0166 struct device_node *parent)
0167 {
0168 struct ft010_irq_data *f = &firq;
0169
0170
0171
0172
0173
0174 cpu_idle_poll_ctrl(true);
0175
0176 f->base = of_iomap(node, 0);
0177 WARN(!f->base, "unable to map gemini irq registers\n");
0178
0179
0180 writel(0, FT010_IRQ_MASK(f->base));
0181 writel(0, FT010_FIQ_MASK(f->base));
0182
0183 f->domain = irq_domain_add_simple(node, FT010_NUM_IRQS, 0,
0184 &ft010_irqdomain_ops, f);
0185 set_handle_irq(ft010_irqchip_handle_irq);
0186
0187 return 0;
0188 }
0189 IRQCHIP_DECLARE(faraday, "faraday,ftintc010",
0190 ft010_of_init_irq);
0191 IRQCHIP_DECLARE(gemini, "cortina,gemini-interrupt-controller",
0192 ft010_of_init_irq);
0193 IRQCHIP_DECLARE(moxa, "moxa,moxart-ic",
0194 ft010_of_init_irq);