0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/io.h>
0018 #include <linux/irq.h>
0019 #include <linux/irqchip.h>
0020 #include <linux/of.h>
0021 #include <linux/of_address.h>
0022 #include <linux/of_irq.h>
0023
0024 #include <asm/exception.h>
0025
0026 #define SUN4I_IRQ_VECTOR_REG 0x00
0027 #define SUN4I_IRQ_PROTECTION_REG 0x08
0028 #define SUN4I_IRQ_NMI_CTRL_REG 0x0c
0029 #define SUN4I_IRQ_PENDING_REG(x) (0x10 + 0x4 * x)
0030 #define SUN4I_IRQ_FIQ_PENDING_REG(x) (0x20 + 0x4 * x)
0031 #define SUN4I_IRQ_ENABLE_REG(data, x) ((data)->enable_reg_offset + 0x4 * x)
0032 #define SUN4I_IRQ_MASK_REG(data, x) ((data)->mask_reg_offset + 0x4 * x)
0033 #define SUN4I_IRQ_ENABLE_REG_OFFSET 0x40
0034 #define SUN4I_IRQ_MASK_REG_OFFSET 0x50
0035 #define SUNIV_IRQ_ENABLE_REG_OFFSET 0x20
0036 #define SUNIV_IRQ_MASK_REG_OFFSET 0x30
0037
0038 struct sun4i_irq_chip_data {
0039 void __iomem *irq_base;
0040 struct irq_domain *irq_domain;
0041 u32 enable_reg_offset;
0042 u32 mask_reg_offset;
0043 };
0044
0045 static struct sun4i_irq_chip_data *irq_ic_data;
0046
0047 static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs);
0048
0049 static void sun4i_irq_ack(struct irq_data *irqd)
0050 {
0051 unsigned int irq = irqd_to_hwirq(irqd);
0052
0053 if (irq != 0)
0054 return;
0055
0056 writel(BIT(0), irq_ic_data->irq_base + SUN4I_IRQ_PENDING_REG(0));
0057 }
0058
0059 static void sun4i_irq_mask(struct irq_data *irqd)
0060 {
0061 unsigned int irq = irqd_to_hwirq(irqd);
0062 unsigned int irq_off = irq % 32;
0063 int reg = irq / 32;
0064 u32 val;
0065
0066 val = readl(irq_ic_data->irq_base +
0067 SUN4I_IRQ_ENABLE_REG(irq_ic_data, reg));
0068 writel(val & ~(1 << irq_off),
0069 irq_ic_data->irq_base + SUN4I_IRQ_ENABLE_REG(irq_ic_data, reg));
0070 }
0071
0072 static void sun4i_irq_unmask(struct irq_data *irqd)
0073 {
0074 unsigned int irq = irqd_to_hwirq(irqd);
0075 unsigned int irq_off = irq % 32;
0076 int reg = irq / 32;
0077 u32 val;
0078
0079 val = readl(irq_ic_data->irq_base +
0080 SUN4I_IRQ_ENABLE_REG(irq_ic_data, reg));
0081 writel(val | (1 << irq_off),
0082 irq_ic_data->irq_base + SUN4I_IRQ_ENABLE_REG(irq_ic_data, reg));
0083 }
0084
0085 static struct irq_chip sun4i_irq_chip = {
0086 .name = "sun4i_irq",
0087 .irq_eoi = sun4i_irq_ack,
0088 .irq_mask = sun4i_irq_mask,
0089 .irq_unmask = sun4i_irq_unmask,
0090 .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED,
0091 };
0092
0093 static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
0094 irq_hw_number_t hw)
0095 {
0096 irq_set_chip_and_handler(virq, &sun4i_irq_chip, handle_fasteoi_irq);
0097 irq_set_probe(virq);
0098
0099 return 0;
0100 }
0101
0102 static const struct irq_domain_ops sun4i_irq_ops = {
0103 .map = sun4i_irq_map,
0104 .xlate = irq_domain_xlate_onecell,
0105 };
0106
0107 static int __init sun4i_of_init(struct device_node *node,
0108 struct device_node *parent)
0109 {
0110 irq_ic_data->irq_base = of_iomap(node, 0);
0111 if (!irq_ic_data->irq_base)
0112 panic("%pOF: unable to map IC registers\n",
0113 node);
0114
0115
0116 writel(0, irq_ic_data->irq_base + SUN4I_IRQ_ENABLE_REG(irq_ic_data, 0));
0117 writel(0, irq_ic_data->irq_base + SUN4I_IRQ_ENABLE_REG(irq_ic_data, 1));
0118 writel(0, irq_ic_data->irq_base + SUN4I_IRQ_ENABLE_REG(irq_ic_data, 2));
0119
0120
0121 writel(0, irq_ic_data->irq_base + SUN4I_IRQ_MASK_REG(irq_ic_data, 0));
0122 writel(0, irq_ic_data->irq_base + SUN4I_IRQ_MASK_REG(irq_ic_data, 1));
0123 writel(0, irq_ic_data->irq_base + SUN4I_IRQ_MASK_REG(irq_ic_data, 2));
0124
0125
0126 writel(0xffffffff, irq_ic_data->irq_base + SUN4I_IRQ_PENDING_REG(0));
0127 writel(0xffffffff, irq_ic_data->irq_base + SUN4I_IRQ_PENDING_REG(1));
0128 writel(0xffffffff, irq_ic_data->irq_base + SUN4I_IRQ_PENDING_REG(2));
0129
0130
0131 writel(0x01, irq_ic_data->irq_base + SUN4I_IRQ_PROTECTION_REG);
0132
0133
0134 writel(0x00, irq_ic_data->irq_base + SUN4I_IRQ_NMI_CTRL_REG);
0135
0136 irq_ic_data->irq_domain = irq_domain_add_linear(node, 3 * 32,
0137 &sun4i_irq_ops, NULL);
0138 if (!irq_ic_data->irq_domain)
0139 panic("%pOF: unable to create IRQ domain\n", node);
0140
0141 set_handle_irq(sun4i_handle_irq);
0142
0143 return 0;
0144 }
0145
0146 static int __init sun4i_ic_of_init(struct device_node *node,
0147 struct device_node *parent)
0148 {
0149 irq_ic_data = kzalloc(sizeof(struct sun4i_irq_chip_data), GFP_KERNEL);
0150 if (!irq_ic_data)
0151 return -ENOMEM;
0152
0153 irq_ic_data->enable_reg_offset = SUN4I_IRQ_ENABLE_REG_OFFSET;
0154 irq_ic_data->mask_reg_offset = SUN4I_IRQ_MASK_REG_OFFSET;
0155
0156 return sun4i_of_init(node, parent);
0157 }
0158
0159 IRQCHIP_DECLARE(allwinner_sun4i_ic, "allwinner,sun4i-a10-ic", sun4i_ic_of_init);
0160
0161 static int __init suniv_ic_of_init(struct device_node *node,
0162 struct device_node *parent)
0163 {
0164 irq_ic_data = kzalloc(sizeof(struct sun4i_irq_chip_data), GFP_KERNEL);
0165 if (!irq_ic_data)
0166 return -ENOMEM;
0167
0168 irq_ic_data->enable_reg_offset = SUNIV_IRQ_ENABLE_REG_OFFSET;
0169 irq_ic_data->mask_reg_offset = SUNIV_IRQ_MASK_REG_OFFSET;
0170
0171 return sun4i_of_init(node, parent);
0172 }
0173
0174 IRQCHIP_DECLARE(allwinner_sunvi_ic, "allwinner,suniv-f1c100s-ic",
0175 suniv_ic_of_init);
0176
0177 static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs)
0178 {
0179 u32 hwirq;
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 hwirq = readl(irq_ic_data->irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
0192 if (hwirq == 0 &&
0193 !(readl(irq_ic_data->irq_base + SUN4I_IRQ_PENDING_REG(0)) &
0194 BIT(0)))
0195 return;
0196
0197 do {
0198 generic_handle_domain_irq(irq_ic_data->irq_domain, hwirq);
0199 hwirq = readl(irq_ic_data->irq_base +
0200 SUN4I_IRQ_VECTOR_REG) >> 2;
0201 } while (hwirq != 0);
0202 }