Loading arch/arm/mach-sa1100/Makefile +1 −1 Original line number Original line Diff line number Diff line Loading @@ -3,7 +3,7 @@ # # # Common support # 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 # Specific board support obj-$(CONFIG_SA1100_ASSABET) += assabet.o obj-$(CONFIG_SA1100_ASSABET) += assabet.o Loading arch/arm/mach-sa1100/generic.c +37 −0 Original line number Original line Diff line number Diff line Loading @@ -20,9 +20,12 @@ #include <linux/ioport.h> #include <linux/ioport.h> #include <linux/platform_device.h> #include <linux/platform_device.h> #include <linux/reboot.h> #include <linux/reboot.h> #include <linux/irqchip/irq-sa11x0.h> #include <video/sa1100fb.h> #include <video/sa1100fb.h> #include <soc/sa1100/pwer.h> #include <asm/div64.h> #include <asm/div64.h> #include <asm/mach/map.h> #include <asm/mach/map.h> #include <asm/mach/flash.h> #include <asm/mach/flash.h> Loading Loading @@ -375,6 +378,18 @@ void __init sa1100_timer_init(void) pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x90000000), 3686400); 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 * Disable the memory bus request/grant signals on the SA1110 to * ensure that we don't receive spurious memory requests. We set * ensure that we don't receive spurious memory requests. We set Loading Loading @@ -416,3 +431,25 @@ void sa1110_mb_enable(void) local_irq_restore(flags); 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; } drivers/irqchip/Makefile +1 −0 Original line number Original line Diff line number Diff line Loading @@ -47,3 +47,4 @@ obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o arch/arm/mach-sa1100/irq.c→drivers/irqchip/irq-sa11x0.c +40 −43 Original line number Original line Diff line number Diff line /* /* * linux/arch/arm/mach-sa1100/irq.c * Copyright (C) 2015 Dmitry Eremin-Solenikov * * Copyright (C) 1999-2001 Nicolas Pitre * 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 * 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 * it under the terms of the GNU General Public License version 2 as Loading @@ -15,16 +14,21 @@ #include <linux/io.h> #include <linux/io.h> #include <linux/irq.h> #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/irqdomain.h> #include <linux/ioport.h> #include <linux/syscore_ops.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 <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 * We don't need to ACK IRQs on the SA1100 unless they're GPIOs Loading @@ -32,27 +36,25 @@ */ */ static void sa1100_mask_irq(struct irq_data *d) 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) 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) static int sa1100_set_wake(struct irq_data *d, unsigned int on) { { if (BIT(d->hwirq) == IC_RTCAlrm) { return sa11x0_sc_set_wake(d->hwirq, on); if (on) PWER |= PWER_RTC; else PWER &= ~PWER_RTC; return 0; } return -EINVAL; } } static struct irq_chip sa1100_normal_chip = { static struct irq_chip sa1100_normal_chip = { Loading Loading @@ -80,9 +82,6 @@ static const struct irq_domain_ops sa1100_normal_irqdomain_ops = { static struct irq_domain *sa1100_normal_irqdomain; static struct irq_domain *sa1100_normal_irqdomain; static struct resource irq_resource = DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); static struct sa1100irq_state { static struct sa1100irq_state { unsigned int saved; unsigned int saved; unsigned int icmr; unsigned int icmr; Loading @@ -95,16 +94,14 @@ static int sa1100irq_suspend(void) struct sa1100irq_state *st = &sa1100irq_state; struct sa1100irq_state *st = &sa1100irq_state; st->saved = 1; st->saved = 1; st->icmr = ICMR; st->icmr = readl_relaxed(iobase + ICMR); st->iclr = ICLR; st->iclr = readl_relaxed(iobase + ICLR); st->iccr = ICCR; st->iccr = readl_relaxed(iobase + ICCR); /* /* * Disable all GPIO-based interrupts. * Disable all GPIO-based interrupts. */ */ ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7| writel_relaxed(st->icmr & 0xfffff000, iobase + ICMR); IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2| IC_GPIO1|IC_GPIO0); return 0; return 0; } } Loading @@ -114,10 +111,10 @@ static void sa1100irq_resume(void) struct sa1100irq_state *st = &sa1100irq_state; struct sa1100irq_state *st = &sa1100irq_state; if (st->saved) { if (st->saved) { ICCR = st->iccr; writel_relaxed(st->iccr, iobase + ICCR); ICLR = st->iclr; writel_relaxed(st->iclr, iobase + ICLR); ICMR = st->icmr; writel_relaxed(st->icmr, iobase + ICMR); } } } } Loading @@ -140,8 +137,8 @@ sa1100_handle_irq(struct pt_regs *regs) uint32_t icip, icmr, mask; uint32_t icip, icmr, mask; do { do { icip = (ICIP); icip = readl_relaxed(iobase + ICIP); icmr = (ICMR); icmr = readl_relaxed(iobase + ICMR); mask = icip & icmr; mask = icip & icmr; if (mask == 0) if (mask == 0) Loading @@ -152,27 +149,27 @@ sa1100_handle_irq(struct pt_regs *regs) } while (1); } 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 */ /* disable all IRQs */ ICMR = 0; writel_relaxed(0, iobase + ICMR); /* all IRQs are IRQ, not FIQ */ /* 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 * Whatever the doc says, this has to be set for the wait-on-irq * instruction to work... on a SA1100 rev 9 at least. * 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, sa1100_normal_irqdomain = irq_domain_add_simple(NULL, 32, IRQ_GPIO0_SC, 32, irq_start, &sa1100_normal_irqdomain_ops, NULL); &sa1100_normal_irqdomain_ops, NULL); set_handle_irq(sa1100_handle_irq); set_handle_irq(sa1100_handle_irq); sa1100_init_gpio(); } } include/linux/irqchip/irq-sa11x0.h 0 → 100644 +17 −0 Original line number Original line Diff line number Diff line /* * 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 Loading
arch/arm/mach-sa1100/Makefile +1 −1 Original line number Original line Diff line number Diff line Loading @@ -3,7 +3,7 @@ # # # Common support # 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 # Specific board support obj-$(CONFIG_SA1100_ASSABET) += assabet.o obj-$(CONFIG_SA1100_ASSABET) += assabet.o Loading
arch/arm/mach-sa1100/generic.c +37 −0 Original line number Original line Diff line number Diff line Loading @@ -20,9 +20,12 @@ #include <linux/ioport.h> #include <linux/ioport.h> #include <linux/platform_device.h> #include <linux/platform_device.h> #include <linux/reboot.h> #include <linux/reboot.h> #include <linux/irqchip/irq-sa11x0.h> #include <video/sa1100fb.h> #include <video/sa1100fb.h> #include <soc/sa1100/pwer.h> #include <asm/div64.h> #include <asm/div64.h> #include <asm/mach/map.h> #include <asm/mach/map.h> #include <asm/mach/flash.h> #include <asm/mach/flash.h> Loading Loading @@ -375,6 +378,18 @@ void __init sa1100_timer_init(void) pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x90000000), 3686400); 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 * Disable the memory bus request/grant signals on the SA1110 to * ensure that we don't receive spurious memory requests. We set * ensure that we don't receive spurious memory requests. We set Loading Loading @@ -416,3 +431,25 @@ void sa1110_mb_enable(void) local_irq_restore(flags); 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; }
drivers/irqchip/Makefile +1 −0 Original line number Original line Diff line number Diff line Loading @@ -47,3 +47,4 @@ obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
arch/arm/mach-sa1100/irq.c→drivers/irqchip/irq-sa11x0.c +40 −43 Original line number Original line Diff line number Diff line /* /* * linux/arch/arm/mach-sa1100/irq.c * Copyright (C) 2015 Dmitry Eremin-Solenikov * * Copyright (C) 1999-2001 Nicolas Pitre * 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 * 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 * it under the terms of the GNU General Public License version 2 as Loading @@ -15,16 +14,21 @@ #include <linux/io.h> #include <linux/io.h> #include <linux/irq.h> #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/irqdomain.h> #include <linux/ioport.h> #include <linux/syscore_ops.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 <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 * We don't need to ACK IRQs on the SA1100 unless they're GPIOs Loading @@ -32,27 +36,25 @@ */ */ static void sa1100_mask_irq(struct irq_data *d) 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) 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) static int sa1100_set_wake(struct irq_data *d, unsigned int on) { { if (BIT(d->hwirq) == IC_RTCAlrm) { return sa11x0_sc_set_wake(d->hwirq, on); if (on) PWER |= PWER_RTC; else PWER &= ~PWER_RTC; return 0; } return -EINVAL; } } static struct irq_chip sa1100_normal_chip = { static struct irq_chip sa1100_normal_chip = { Loading Loading @@ -80,9 +82,6 @@ static const struct irq_domain_ops sa1100_normal_irqdomain_ops = { static struct irq_domain *sa1100_normal_irqdomain; static struct irq_domain *sa1100_normal_irqdomain; static struct resource irq_resource = DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); static struct sa1100irq_state { static struct sa1100irq_state { unsigned int saved; unsigned int saved; unsigned int icmr; unsigned int icmr; Loading @@ -95,16 +94,14 @@ static int sa1100irq_suspend(void) struct sa1100irq_state *st = &sa1100irq_state; struct sa1100irq_state *st = &sa1100irq_state; st->saved = 1; st->saved = 1; st->icmr = ICMR; st->icmr = readl_relaxed(iobase + ICMR); st->iclr = ICLR; st->iclr = readl_relaxed(iobase + ICLR); st->iccr = ICCR; st->iccr = readl_relaxed(iobase + ICCR); /* /* * Disable all GPIO-based interrupts. * Disable all GPIO-based interrupts. */ */ ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7| writel_relaxed(st->icmr & 0xfffff000, iobase + ICMR); IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2| IC_GPIO1|IC_GPIO0); return 0; return 0; } } Loading @@ -114,10 +111,10 @@ static void sa1100irq_resume(void) struct sa1100irq_state *st = &sa1100irq_state; struct sa1100irq_state *st = &sa1100irq_state; if (st->saved) { if (st->saved) { ICCR = st->iccr; writel_relaxed(st->iccr, iobase + ICCR); ICLR = st->iclr; writel_relaxed(st->iclr, iobase + ICLR); ICMR = st->icmr; writel_relaxed(st->icmr, iobase + ICMR); } } } } Loading @@ -140,8 +137,8 @@ sa1100_handle_irq(struct pt_regs *regs) uint32_t icip, icmr, mask; uint32_t icip, icmr, mask; do { do { icip = (ICIP); icip = readl_relaxed(iobase + ICIP); icmr = (ICMR); icmr = readl_relaxed(iobase + ICMR); mask = icip & icmr; mask = icip & icmr; if (mask == 0) if (mask == 0) Loading @@ -152,27 +149,27 @@ sa1100_handle_irq(struct pt_regs *regs) } while (1); } 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 */ /* disable all IRQs */ ICMR = 0; writel_relaxed(0, iobase + ICMR); /* all IRQs are IRQ, not FIQ */ /* 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 * Whatever the doc says, this has to be set for the wait-on-irq * instruction to work... on a SA1100 rev 9 at least. * 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, sa1100_normal_irqdomain = irq_domain_add_simple(NULL, 32, IRQ_GPIO0_SC, 32, irq_start, &sa1100_normal_irqdomain_ops, NULL); &sa1100_normal_irqdomain_ops, NULL); set_handle_irq(sa1100_handle_irq); set_handle_irq(sa1100_handle_irq); sa1100_init_gpio(); } }
include/linux/irqchip/irq-sa11x0.h 0 → 100644 +17 −0 Original line number Original line Diff line number Diff line /* * 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