diff options
-rw-r--r-- | arch/arm/mach-sa1100/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/generic.c | 37 | ||||
-rw-r--r-- | drivers/irqchip/Makefile | 1 | ||||
-rw-r--r-- | drivers/irqchip/irq-sa11x0.c (renamed from arch/arm/mach-sa1100/irq.c) | 83 | ||||
-rw-r--r-- | include/linux/irqchip/irq-sa11x0.h | 17 | ||||
-rw-r--r-- | include/soc/sa1100/pwer.h | 15 |
6 files changed, 111 insertions, 44 deletions
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index 61ff91e76e0a..ebc4d58e1a32 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := clock.o generic.o irq.o #nmi-oopser.o +obj-y := clock.o generic.o #nmi-oopser.o # Specific board support obj-$(CONFIG_SA1100_ASSABET) += assabet.o diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 40e0d8619a2d..345e63f4eb71 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -20,9 +20,12 @@ #include <linux/ioport.h> #include <linux/platform_device.h> #include <linux/reboot.h> +#include <linux/irqchip/irq-sa11x0.h> #include <video/sa1100fb.h> +#include <soc/sa1100/pwer.h> + #include <asm/div64.h> #include <asm/mach/map.h> #include <asm/mach/flash.h> @@ -375,6 +378,18 @@ void __init sa1100_timer_init(void) pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x90000000), 3686400); } +static struct resource irq_resource = + DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); + +void __init sa1100_init_irq(void) +{ + request_resource(&iomem_resource, &irq_resource); + + sa11x0_init_irq_nodt(IRQ_GPIO0_SC, irq_resource.start); + + sa1100_init_gpio(); +} + /* * Disable the memory bus request/grant signals on the SA1110 to * ensure that we don't receive spurious memory requests. We set @@ -416,3 +431,25 @@ void sa1110_mb_enable(void) local_irq_restore(flags); } +int sa11x0_gpio_set_wake(unsigned int gpio, unsigned int on) +{ + if (on) + PWER |= BIT(gpio); + else + PWER &= ~BIT(gpio); + + return 0; +} + +int sa11x0_sc_set_wake(unsigned int irq, unsigned int on) +{ + if (BIT(irq) != IC_RTCAlrm) + return -EINVAL; + + if (on) + PWER |= PWER_RTC; + else + PWER &= ~PWER_RTC; + + return 0; +} diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index dda4927e47a6..49f372a168f9 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -47,3 +47,4 @@ obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o +obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o diff --git a/arch/arm/mach-sa1100/irq.c b/drivers/irqchip/irq-sa11x0.c index ea3eb4144b66..46df2875dc1c 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/drivers/irqchip/irq-sa11x0.c @@ -1,9 +1,8 @@ /* - * linux/arch/arm/mach-sa1100/irq.c - * + * Copyright (C) 2015 Dmitry Eremin-Solenikov * Copyright (C) 1999-2001 Nicolas Pitre * - * Generic IRQ handling for the SA11x0, GPIO 11-27 IRQ demultiplexing. + * Generic IRQ handling for the SA11x0. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,16 +14,21 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/irqdomain.h> -#include <linux/ioport.h> #include <linux/syscore_ops.h> +#include <linux/irqchip/irq-sa11x0.h> + +#include <soc/sa1100/pwer.h> -#include <mach/hardware.h> -#include <mach/irqs.h> -#include <asm/mach/irq.h> #include <asm/exception.h> -#include "generic.h" +#define ICIP 0x00 /* IC IRQ Pending reg. */ +#define ICMR 0x04 /* IC Mask Reg. */ +#define ICLR 0x08 /* IC Level Reg. */ +#define ICCR 0x0C /* IC Control Reg. */ +#define ICFP 0x10 /* IC FIQ Pending reg. */ +#define ICPR 0x20 /* IC Pending Reg. */ +static void __iomem *iobase; /* * We don't need to ACK IRQs on the SA1100 unless they're GPIOs @@ -32,27 +36,25 @@ */ static void sa1100_mask_irq(struct irq_data *d) { - ICMR &= ~BIT(d->hwirq); + u32 reg; + + reg = readl_relaxed(iobase + ICMR); + reg &= ~BIT(d->hwirq); + writel_relaxed(reg, iobase + ICMR); } static void sa1100_unmask_irq(struct irq_data *d) { - ICMR |= BIT(d->hwirq); + u32 reg; + + reg = readl_relaxed(iobase + ICMR); + reg |= BIT(d->hwirq); + writel_relaxed(reg, iobase + ICMR); } -/* - * Apart form GPIOs, only the RTC alarm can be a wakeup event. - */ static int sa1100_set_wake(struct irq_data *d, unsigned int on) { - if (BIT(d->hwirq) == IC_RTCAlrm) { - if (on) - PWER |= PWER_RTC; - else - PWER &= ~PWER_RTC; - return 0; - } - return -EINVAL; + return sa11x0_sc_set_wake(d->hwirq, on); } static struct irq_chip sa1100_normal_chip = { @@ -80,9 +82,6 @@ static const struct irq_domain_ops sa1100_normal_irqdomain_ops = { static struct irq_domain *sa1100_normal_irqdomain; -static struct resource irq_resource = - DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); - static struct sa1100irq_state { unsigned int saved; unsigned int icmr; @@ -95,16 +94,14 @@ static int sa1100irq_suspend(void) struct sa1100irq_state *st = &sa1100irq_state; st->saved = 1; - st->icmr = ICMR; - st->iclr = ICLR; - st->iccr = ICCR; + st->icmr = readl_relaxed(iobase + ICMR); + st->iclr = readl_relaxed(iobase + ICLR); + st->iccr = readl_relaxed(iobase + ICCR); /* * Disable all GPIO-based interrupts. */ - ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7| - IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2| - IC_GPIO1|IC_GPIO0); + writel_relaxed(st->icmr & 0xfffff000, iobase + ICMR); return 0; } @@ -114,10 +111,10 @@ static void sa1100irq_resume(void) struct sa1100irq_state *st = &sa1100irq_state; if (st->saved) { - ICCR = st->iccr; - ICLR = st->iclr; + writel_relaxed(st->iccr, iobase + ICCR); + writel_relaxed(st->iclr, iobase + ICLR); - ICMR = st->icmr; + writel_relaxed(st->icmr, iobase + ICMR); } } @@ -140,8 +137,8 @@ sa1100_handle_irq(struct pt_regs *regs) uint32_t icip, icmr, mask; do { - icip = (ICIP); - icmr = (ICMR); + icip = readl_relaxed(iobase + ICIP); + icmr = readl_relaxed(iobase + ICMR); mask = icip & icmr; if (mask == 0) @@ -152,27 +149,27 @@ sa1100_handle_irq(struct pt_regs *regs) } while (1); } -void __init sa1100_init_irq(void) +void __init sa11x0_init_irq_nodt(int irq_start, resource_size_t io_start) { - request_resource(&iomem_resource, &irq_resource); + iobase = ioremap(io_start, SZ_64K); + if (WARN_ON(!iobase)) + return; /* disable all IRQs */ - ICMR = 0; + writel_relaxed(0, iobase + ICMR); /* all IRQs are IRQ, not FIQ */ - ICLR = 0; + writel_relaxed(0, iobase + ICLR); /* * Whatever the doc says, this has to be set for the wait-on-irq * instruction to work... on a SA1100 rev 9 at least. */ - ICCR = 1; + writel_relaxed(1, iobase + ICCR); sa1100_normal_irqdomain = irq_domain_add_simple(NULL, - 32, IRQ_GPIO0_SC, + 32, irq_start, &sa1100_normal_irqdomain_ops, NULL); set_handle_irq(sa1100_handle_irq); - - sa1100_init_gpio(); } diff --git a/include/linux/irqchip/irq-sa11x0.h b/include/linux/irqchip/irq-sa11x0.h new file mode 100644 index 000000000000..15db6829c1e4 --- /dev/null +++ b/include/linux/irqchip/irq-sa11x0.h @@ -0,0 +1,17 @@ +/* + * Generic IRQ handling for the SA11x0. + * + * Copyright (C) 2015 Dmitry Eremin-Solenikov + * Copyright (C) 1999-2001 Nicolas Pitre + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_SA11x0_H +#define __INCLUDE_LINUX_IRQCHIP_IRQ_SA11x0_H + +void __init sa11x0_init_irq_nodt(int irq_start, resource_size_t io_start); + +#endif diff --git a/include/soc/sa1100/pwer.h b/include/soc/sa1100/pwer.h new file mode 100644 index 000000000000..15a545b5a1f6 --- /dev/null +++ b/include/soc/sa1100/pwer.h @@ -0,0 +1,15 @@ +#ifndef SOC_SA1100_PWER_H +#define SOC_SA1100_PWER_H + +/* + * Copyright (C) 2015, Dmitry Eremin-Solenikov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +int sa11x0_gpio_set_wake(unsigned int gpio, unsigned int on); +int sa11x0_sc_set_wake(unsigned int irq, unsigned int on); + +#endif |