diff options
Diffstat (limited to 'drivers/irqchip/irq-sunxi-nmi.c')
-rw-r--r-- | drivers/irqchip/irq-sunxi-nmi.c | 68 |
1 files changed, 54 insertions, 14 deletions
diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c index 668730c5cb66..a412b5d5d0fa 100644 --- a/drivers/irqchip/irq-sunxi-nmi.c +++ b/drivers/irqchip/irq-sunxi-nmi.c @@ -25,6 +25,29 @@ #define SUNXI_NMI_SRC_TYPE_MASK 0x00000003 +#define SUNXI_NMI_IRQ_BIT BIT(0) + +#define SUN6I_R_INTC_CTRL 0x0c +#define SUN6I_R_INTC_PENDING 0x10 +#define SUN6I_R_INTC_ENABLE 0x40 + +/* + * For deprecated sun6i-a31-sc-nmi compatible. + * Registers are offset by 0x0c. + */ +#define SUN6I_R_INTC_NMI_OFFSET 0x0c +#define SUN6I_NMI_CTRL (SUN6I_R_INTC_CTRL - SUN6I_R_INTC_NMI_OFFSET) +#define SUN6I_NMI_PENDING (SUN6I_R_INTC_PENDING - SUN6I_R_INTC_NMI_OFFSET) +#define SUN6I_NMI_ENABLE (SUN6I_R_INTC_ENABLE - SUN6I_R_INTC_NMI_OFFSET) + +#define SUN7I_NMI_CTRL 0x00 +#define SUN7I_NMI_PENDING 0x04 +#define SUN7I_NMI_ENABLE 0x08 + +#define SUN9I_NMI_CTRL 0x00 +#define SUN9I_NMI_ENABLE 0x04 +#define SUN9I_NMI_PENDING 0x08 + enum { SUNXI_SRC_TYPE_LEVEL_LOW = 0, SUNXI_SRC_TYPE_EDGE_FALLING, @@ -38,22 +61,28 @@ struct sunxi_sc_nmi_reg_offs { u32 enable; }; -static struct sunxi_sc_nmi_reg_offs sun7i_reg_offs = { - .ctrl = 0x00, - .pend = 0x04, - .enable = 0x08, +static const struct sunxi_sc_nmi_reg_offs sun6i_r_intc_reg_offs __initconst = { + .ctrl = SUN6I_R_INTC_CTRL, + .pend = SUN6I_R_INTC_PENDING, + .enable = SUN6I_R_INTC_ENABLE, }; -static struct sunxi_sc_nmi_reg_offs sun6i_reg_offs = { - .ctrl = 0x00, - .pend = 0x04, - .enable = 0x34, +static const struct sunxi_sc_nmi_reg_offs sun6i_reg_offs __initconst = { + .ctrl = SUN6I_NMI_CTRL, + .pend = SUN6I_NMI_PENDING, + .enable = SUN6I_NMI_ENABLE, }; -static struct sunxi_sc_nmi_reg_offs sun9i_reg_offs = { - .ctrl = 0x00, - .pend = 0x08, - .enable = 0x04, +static const struct sunxi_sc_nmi_reg_offs sun7i_reg_offs __initconst = { + .ctrl = SUN7I_NMI_CTRL, + .pend = SUN7I_NMI_PENDING, + .enable = SUN7I_NMI_ENABLE, +}; + +static const struct sunxi_sc_nmi_reg_offs sun9i_reg_offs __initconst = { + .ctrl = SUN9I_NMI_CTRL, + .pend = SUN9I_NMI_PENDING, + .enable = SUN9I_NMI_ENABLE, }; static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off, @@ -128,7 +157,7 @@ static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type) } static int __init sunxi_sc_nmi_irq_init(struct device_node *node, - struct sunxi_sc_nmi_reg_offs *reg_offs) + const struct sunxi_sc_nmi_reg_offs *reg_offs) { struct irq_domain *domain; struct irq_chip_generic *gc; @@ -187,8 +216,11 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node, gc->chip_types[1].regs.type = reg_offs->ctrl; gc->chip_types[1].handler = handle_edge_irq; + /* Disable any active interrupts */ sunxi_sc_nmi_write(gc, reg_offs->enable, 0); - sunxi_sc_nmi_write(gc, reg_offs->pend, 0x1); + + /* Clear any pending NMI interrupts */ + sunxi_sc_nmi_write(gc, reg_offs->pend, SUNXI_NMI_IRQ_BIT); irq_set_chained_handler_and_data(irq, sunxi_sc_nmi_handle_irq, domain); @@ -200,6 +232,14 @@ fail_irqd_remove: return ret; } +static int __init sun6i_r_intc_irq_init(struct device_node *node, + struct device_node *parent) +{ + return sunxi_sc_nmi_irq_init(node, &sun6i_r_intc_reg_offs); +} +IRQCHIP_DECLARE(sun6i_r_intc, "allwinner,sun6i-a31-r-intc", + sun6i_r_intc_irq_init); + static int __init sun6i_sc_nmi_irq_init(struct device_node *node, struct device_node *parent) { |