diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/clocksource/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/clocksource/Makefile | 2 | ||||
| -rw-r--r-- | drivers/clocksource/clksrc-of.c | 3 | ||||
| -rw-r--r-- | drivers/clocksource/sun4i_timer.c (renamed from drivers/clocksource/sunxi_timer.c) | 94 | ||||
| -rw-r--r-- | drivers/clocksource/vt8500_timer.c | 2 | ||||
| -rw-r--r-- | drivers/irqchip/Makefile | 2 | ||||
| -rw-r--r-- | drivers/irqchip/irq-sun4i.c | 149 | ||||
| -rw-r--r-- | drivers/irqchip/irq-sunxi.c | 151 | 
8 files changed, 196 insertions, 209 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index e507ab7df60..9002185a0a1 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -25,7 +25,7 @@ config DW_APB_TIMER_OF  config ARMADA_370_XP_TIMER  	bool -config SUNXI_TIMER +config SUN4I_TIMER  	bool  config VT8500_TIMER diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 89c5adc498b..98f220a7a92 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -17,7 +17,7 @@ obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o  obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o  obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o  obj-$(CONFIG_ARCH_MXS)		+= mxs_timer.o -obj-$(CONFIG_SUNXI_TIMER)	+= sunxi_timer.o +obj-$(CONFIG_SUN4I_TIMER)	+= sun4i_timer.o  obj-$(CONFIG_ARCH_TEGRA)	+= tegra20_timer.o  obj-$(CONFIG_VT8500_TIMER)	+= vt8500_timer.o diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c index 3ef11fba781..37f5325bec9 100644 --- a/drivers/clocksource/clksrc-of.c +++ b/drivers/clocksource/clksrc-of.c @@ -16,6 +16,7 @@  #include <linux/init.h>  #include <linux/of.h> +#include <linux/clocksource.h>  extern struct of_device_id __clksrc_of_table[]; @@ -26,7 +27,7 @@ void __init clocksource_of_init(void)  {  	struct device_node *np;  	const struct of_device_id *match; -	void (*init_func)(struct device_node *); +	clocksource_of_init_fn init_func;  	for_each_matching_node_and_match(np, __clksrc_of_table, &match) {  		init_func = match->data; diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sun4i_timer.c index 0ce85e29769..d4674e78ef3 100644 --- a/drivers/clocksource/sunxi_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -22,66 +22,64 @@  #include <linux/of.h>  #include <linux/of_address.h>  #include <linux/of_irq.h> -#include <linux/sunxi_timer.h> -#include <linux/clk/sunxi.h> -#define TIMER_CTL_REG		0x00 -#define TIMER_CTL_ENABLE		(1 << 0) +#define TIMER_IRQ_EN_REG	0x00 +#define TIMER_IRQ_EN(val)		(1 << val)  #define TIMER_IRQ_ST_REG	0x04 -#define TIMER0_CTL_REG		0x10 -#define TIMER0_CTL_ENABLE		(1 << 0) -#define TIMER0_CTL_AUTORELOAD		(1 << 1) -#define TIMER0_CTL_ONESHOT		(1 << 7) -#define TIMER0_INTVAL_REG	0x14 -#define TIMER0_CNTVAL_REG	0x18 +#define TIMER_CTL_REG(val)	(0x10 * val + 0x10) +#define TIMER_CTL_ENABLE		(1 << 0) +#define TIMER_CTL_AUTORELOAD		(1 << 1) +#define TIMER_CTL_ONESHOT		(1 << 7) +#define TIMER_INTVAL_REG(val)	(0x10 * val + 0x14) +#define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)  #define TIMER_SCAL		16  static void __iomem *timer_base; -static void sunxi_clkevt_mode(enum clock_event_mode mode, +static void sun4i_clkevt_mode(enum clock_event_mode mode,  			      struct clock_event_device *clk)  { -	u32 u = readl(timer_base + TIMER0_CTL_REG); +	u32 u = readl(timer_base + TIMER_CTL_REG(0));  	switch (mode) {  	case CLOCK_EVT_MODE_PERIODIC: -		u &= ~(TIMER0_CTL_ONESHOT); -		writel(u | TIMER0_CTL_ENABLE, timer_base + TIMER0_CTL_REG); +		u &= ~(TIMER_CTL_ONESHOT); +		writel(u | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0));  		break;  	case CLOCK_EVT_MODE_ONESHOT: -		writel(u | TIMER0_CTL_ONESHOT, timer_base + TIMER0_CTL_REG); +		writel(u | TIMER_CTL_ONESHOT, timer_base + TIMER_CTL_REG(0));  		break;  	case CLOCK_EVT_MODE_UNUSED:  	case CLOCK_EVT_MODE_SHUTDOWN:  	default: -		writel(u & ~(TIMER0_CTL_ENABLE), timer_base + TIMER0_CTL_REG); +		writel(u & ~(TIMER_CTL_ENABLE), timer_base + TIMER_CTL_REG(0));  		break;  	}  } -static int sunxi_clkevt_next_event(unsigned long evt, +static int sun4i_clkevt_next_event(unsigned long evt,  				   struct clock_event_device *unused)  { -	u32 u = readl(timer_base + TIMER0_CTL_REG); -	writel(evt, timer_base + TIMER0_CNTVAL_REG); -	writel(u | TIMER0_CTL_ENABLE | TIMER0_CTL_AUTORELOAD, -	       timer_base + TIMER0_CTL_REG); +	u32 u = readl(timer_base + TIMER_CTL_REG(0)); +	writel(evt, timer_base + TIMER_CNTVAL_REG(0)); +	writel(u | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD, +	       timer_base + TIMER_CTL_REG(0));  	return 0;  } -static struct clock_event_device sunxi_clockevent = { -	.name = "sunxi_tick", +static struct clock_event_device sun4i_clockevent = { +	.name = "sun4i_tick",  	.rating = 300,  	.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, -	.set_mode = sunxi_clkevt_mode, -	.set_next_event = sunxi_clkevt_next_event, +	.set_mode = sun4i_clkevt_mode, +	.set_next_event = sun4i_clkevt_next_event,  }; -static irqreturn_t sunxi_timer_interrupt(int irq, void *dev_id) +static irqreturn_t sun4i_timer_interrupt(int irq, void *dev_id)  {  	struct clock_event_device *evt = (struct clock_event_device *)dev_id; @@ -91,30 +89,20 @@ static irqreturn_t sunxi_timer_interrupt(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static struct irqaction sunxi_timer_irq = { -	.name = "sunxi_timer0", +static struct irqaction sun4i_timer_irq = { +	.name = "sun4i_timer0",  	.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, -	.handler = sunxi_timer_interrupt, -	.dev_id = &sunxi_clockevent, -}; - -static struct of_device_id sunxi_timer_dt_ids[] = { -	{ .compatible = "allwinner,sunxi-timer" }, -	{ } +	.handler = sun4i_timer_interrupt, +	.dev_id = &sun4i_clockevent,  }; -void __init sunxi_timer_init(void) +static void __init sun4i_timer_init(struct device_node *node)  { -	struct device_node *node;  	unsigned long rate = 0;  	struct clk *clk;  	int ret, irq;  	u32 val; -	node = of_find_matching_node(NULL, sunxi_timer_dt_ids); -	if (!node) -		panic("No sunxi timer node"); -  	timer_base = of_iomap(node, 0);  	if (!timer_base)  		panic("Can't map registers"); @@ -123,8 +111,6 @@ void __init sunxi_timer_init(void)  	if (irq <= 0)  		panic("Can't parse IRQ"); -	sunxi_init_clocks(); -  	clk = of_clk_get(node, 0);  	if (IS_ERR(clk))  		panic("Can't get timer clock"); @@ -132,29 +118,31 @@ void __init sunxi_timer_init(void)  	rate = clk_get_rate(clk);  	writel(rate / (TIMER_SCAL * HZ), -	       timer_base + TIMER0_INTVAL_REG); +	       timer_base + TIMER_INTVAL_REG(0));  	/* set clock source to HOSC, 16 pre-division */ -	val = readl(timer_base + TIMER0_CTL_REG); +	val = readl(timer_base + TIMER_CTL_REG(0));  	val &= ~(0x07 << 4);  	val &= ~(0x03 << 2);  	val |= (4 << 4) | (1 << 2); -	writel(val, timer_base + TIMER0_CTL_REG); +	writel(val, timer_base + TIMER_CTL_REG(0));  	/* set mode to auto reload */ -	val = readl(timer_base + TIMER0_CTL_REG); -	writel(val | TIMER0_CTL_AUTORELOAD, timer_base + TIMER0_CTL_REG); +	val = readl(timer_base + TIMER_CTL_REG(0)); +	writel(val | TIMER_CTL_AUTORELOAD, timer_base + TIMER_CTL_REG(0)); -	ret = setup_irq(irq, &sunxi_timer_irq); +	ret = setup_irq(irq, &sun4i_timer_irq);  	if (ret)  		pr_warn("failed to setup irq %d\n", irq);  	/* Enable timer0 interrupt */ -	val = readl(timer_base + TIMER_CTL_REG); -	writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG); +	val = readl(timer_base + TIMER_IRQ_EN_REG); +	writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); -	sunxi_clockevent.cpumask = cpumask_of(0); +	sun4i_clockevent.cpumask = cpumask_of(0); -	clockevents_config_and_register(&sunxi_clockevent, rate / TIMER_SCAL, +	clockevents_config_and_register(&sun4i_clockevent, rate / TIMER_SCAL,  					0x1, 0xff);  } +CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer", +		       sun4i_timer_init); diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c index 24225528559..64f553f04fa 100644 --- a/drivers/clocksource/vt8500_timer.c +++ b/drivers/clocksource/vt8500_timer.c @@ -165,4 +165,4 @@ static void __init vt8500_timer_init(struct device_node *np)  					4, 0xf0000000);  } -CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init) +CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init); diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 9d8f4f1c6e3..d5e119ca942 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_ARCH_EXYNOS)		+= exynos-combiner.o  obj-$(CONFIG_ARCH_MXS)			+= irq-mxs.o  obj-$(CONFIG_METAG)			+= irq-metag-ext.o  obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)	+= irq-metag.o -obj-$(CONFIG_ARCH_SUNXI)		+= irq-sunxi.o +obj-$(CONFIG_ARCH_SUNXI)		+= irq-sun4i.o  obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o  obj-$(CONFIG_ARM_GIC)			+= irq-gic.o  obj-$(CONFIG_ARM_VIC)			+= irq-vic.o diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c new file mode 100644 index 00000000000..b66d4ae0689 --- /dev/null +++ b/drivers/irqchip/irq-sun4i.c @@ -0,0 +1,149 @@ +/* + * Allwinner A1X SoCs IRQ chip driver. + * + * Copyright (C) 2012 Maxime Ripard + * + * Maxime Ripard <maxime.ripard@free-electrons.com> + * + * Based on code from + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Benn Huang <benn@allwinnertech.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2.  This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> + +#include <asm/exception.h> +#include <asm/mach/irq.h> + +#include "irqchip.h" + +#define SUN4I_IRQ_VECTOR_REG		0x00 +#define SUN4I_IRQ_PROTECTION_REG	0x08 +#define SUN4I_IRQ_NMI_CTRL_REG		0x0c +#define SUN4I_IRQ_PENDING_REG(x)	(0x10 + 0x4 * x) +#define SUN4I_IRQ_FIQ_PENDING_REG(x)	(0x20 + 0x4 * x) +#define SUN4I_IRQ_ENABLE_REG(x)		(0x40 + 0x4 * x) +#define SUN4I_IRQ_MASK_REG(x)		(0x50 + 0x4 * x) + +static void __iomem *sun4i_irq_base; +static struct irq_domain *sun4i_irq_domain; + +static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs); + +void sun4i_irq_ack(struct irq_data *irqd) +{ +	unsigned int irq = irqd_to_hwirq(irqd); +	unsigned int irq_off = irq % 32; +	int reg = irq / 32; +	u32 val; + +	val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg)); +	writel(val | (1 << irq_off), +	       sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg)); +} + +static void sun4i_irq_mask(struct irq_data *irqd) +{ +	unsigned int irq = irqd_to_hwirq(irqd); +	unsigned int irq_off = irq % 32; +	int reg = irq / 32; +	u32 val; + +	val = readl(sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg)); +	writel(val & ~(1 << irq_off), +	       sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg)); +} + +static void sun4i_irq_unmask(struct irq_data *irqd) +{ +	unsigned int irq = irqd_to_hwirq(irqd); +	unsigned int irq_off = irq % 32; +	int reg = irq / 32; +	u32 val; + +	val = readl(sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg)); +	writel(val | (1 << irq_off), +	       sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg)); +} + +static struct irq_chip sun4i_irq_chip = { +	.name		= "sun4i_irq", +	.irq_ack	= sun4i_irq_ack, +	.irq_mask	= sun4i_irq_mask, +	.irq_unmask	= sun4i_irq_unmask, +}; + +static int sun4i_irq_map(struct irq_domain *d, unsigned int virq, +			 irq_hw_number_t hw) +{ +	irq_set_chip_and_handler(virq, &sun4i_irq_chip, +				 handle_level_irq); +	set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); + +	return 0; +} + +static struct irq_domain_ops sun4i_irq_ops = { +	.map = sun4i_irq_map, +	.xlate = irq_domain_xlate_onecell, +}; + +static int __init sun4i_of_init(struct device_node *node, +				struct device_node *parent) +{ +	sun4i_irq_base = of_iomap(node, 0); +	if (!sun4i_irq_base) +		panic("%s: unable to map IC registers\n", +			node->full_name); + +	/* Disable all interrupts */ +	writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(0)); +	writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1)); +	writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2)); + +	/* Mask all the interrupts */ +	writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0)); +	writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1)); +	writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2)); + +	/* Clear all the pending interrupts */ +	writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0)); +	writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(1)); +	writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(2)); + +	/* Enable protection mode */ +	writel(0x01, sun4i_irq_base + SUN4I_IRQ_PROTECTION_REG); + +	/* Configure the external interrupt source type */ +	writel(0x00, sun4i_irq_base + SUN4I_IRQ_NMI_CTRL_REG); + +	sun4i_irq_domain = irq_domain_add_linear(node, 3 * 32, +						 &sun4i_irq_ops, NULL); +	if (!sun4i_irq_domain) +		panic("%s: unable to create IRQ domain\n", node->full_name); + +	set_handle_irq(sun4i_handle_irq); + +	return 0; +} +IRQCHIP_DECLARE(allwinner_sun4i_ic, "allwinner,sun4i-ic", sun4i_of_init); + +static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs) +{ +	u32 irq, hwirq; + +	hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; +	while (hwirq != 0) { +		irq = irq_find_mapping(sun4i_irq_domain, hwirq); +		handle_IRQ(irq, regs); +		hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; +	} +} diff --git a/drivers/irqchip/irq-sunxi.c b/drivers/irqchip/irq-sunxi.c deleted file mode 100644 index 10974fa4265..00000000000 --- a/drivers/irqchip/irq-sunxi.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Allwinner A1X SoCs IRQ chip driver. - * - * Copyright (C) 2012 Maxime Ripard - * - * Maxime Ripard <maxime.ripard@free-electrons.com> - * - * Based on code from - * Allwinner Technology Co., Ltd. <www.allwinnertech.com> - * Benn Huang <benn@allwinnertech.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2.  This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> - -#include <linux/irqchip/sunxi.h> - -#define SUNXI_IRQ_VECTOR_REG		0x00 -#define SUNXI_IRQ_PROTECTION_REG	0x08 -#define SUNXI_IRQ_NMI_CTRL_REG		0x0c -#define SUNXI_IRQ_PENDING_REG(x)	(0x10 + 0x4 * x) -#define SUNXI_IRQ_FIQ_PENDING_REG(x)	(0x20 + 0x4 * x) -#define SUNXI_IRQ_ENABLE_REG(x)		(0x40 + 0x4 * x) -#define SUNXI_IRQ_MASK_REG(x)		(0x50 + 0x4 * x) - -static void __iomem *sunxi_irq_base; -static struct irq_domain *sunxi_irq_domain; - -void sunxi_irq_ack(struct irq_data *irqd) -{ -	unsigned int irq = irqd_to_hwirq(irqd); -	unsigned int irq_off = irq % 32; -	int reg = irq / 32; -	u32 val; - -	val = readl(sunxi_irq_base + SUNXI_IRQ_PENDING_REG(reg)); -	writel(val | (1 << irq_off), -	       sunxi_irq_base + SUNXI_IRQ_PENDING_REG(reg)); -} - -static void sunxi_irq_mask(struct irq_data *irqd) -{ -	unsigned int irq = irqd_to_hwirq(irqd); -	unsigned int irq_off = irq % 32; -	int reg = irq / 32; -	u32 val; - -	val = readl(sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg)); -	writel(val & ~(1 << irq_off), -	       sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg)); -} - -static void sunxi_irq_unmask(struct irq_data *irqd) -{ -	unsigned int irq = irqd_to_hwirq(irqd); -	unsigned int irq_off = irq % 32; -	int reg = irq / 32; -	u32 val; - -	val = readl(sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg)); -	writel(val | (1 << irq_off), -	       sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg)); -} - -static struct irq_chip sunxi_irq_chip = { -	.name		= "sunxi_irq", -	.irq_ack	= sunxi_irq_ack, -	.irq_mask	= sunxi_irq_mask, -	.irq_unmask	= sunxi_irq_unmask, -}; - -static int sunxi_irq_map(struct irq_domain *d, unsigned int virq, -			 irq_hw_number_t hw) -{ -	irq_set_chip_and_handler(virq, &sunxi_irq_chip, -				 handle_level_irq); -	set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); - -	return 0; -} - -static struct irq_domain_ops sunxi_irq_ops = { -	.map = sunxi_irq_map, -	.xlate = irq_domain_xlate_onecell, -}; - -static int __init sunxi_of_init(struct device_node *node, -				struct device_node *parent) -{ -	sunxi_irq_base = of_iomap(node, 0); -	if (!sunxi_irq_base) -		panic("%s: unable to map IC registers\n", -			node->full_name); - -	/* Disable all interrupts */ -	writel(0, sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(0)); -	writel(0, sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(1)); -	writel(0, sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(2)); - -	/* Mask all the interrupts */ -	writel(0, sunxi_irq_base + SUNXI_IRQ_MASK_REG(0)); -	writel(0, sunxi_irq_base + SUNXI_IRQ_MASK_REG(1)); -	writel(0, sunxi_irq_base + SUNXI_IRQ_MASK_REG(2)); - -	/* Clear all the pending interrupts */ -	writel(0xffffffff, sunxi_irq_base + SUNXI_IRQ_PENDING_REG(0)); -	writel(0xffffffff, sunxi_irq_base + SUNXI_IRQ_PENDING_REG(1)); -	writel(0xffffffff, sunxi_irq_base + SUNXI_IRQ_PENDING_REG(2)); - -	/* Enable protection mode */ -	writel(0x01, sunxi_irq_base + SUNXI_IRQ_PROTECTION_REG); - -	/* Configure the external interrupt source type */ -	writel(0x00, sunxi_irq_base + SUNXI_IRQ_NMI_CTRL_REG); - -	sunxi_irq_domain = irq_domain_add_linear(node, 3 * 32, -						 &sunxi_irq_ops, NULL); -	if (!sunxi_irq_domain) -		panic("%s: unable to create IRQ domain\n", node->full_name); - -	return 0; -} - -static struct of_device_id sunxi_irq_dt_ids[] __initconst = { -	{ .compatible = "allwinner,sunxi-ic", .data = sunxi_of_init }, -	{ } -}; - -void __init sunxi_init_irq(void) -{ -	of_irq_init(sunxi_irq_dt_ids); -} - -asmlinkage void __exception_irq_entry sunxi_handle_irq(struct pt_regs *regs) -{ -	u32 irq, hwirq; - -	hwirq = readl(sunxi_irq_base + SUNXI_IRQ_VECTOR_REG) >> 2; -	while (hwirq != 0) { -		irq = irq_find_mapping(sunxi_irq_domain, hwirq); -		handle_IRQ(irq, regs); -		hwirq = readl(sunxi_irq_base + SUNXI_IRQ_VECTOR_REG) >> 2; -	} -}  |