diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-14 13:37:29 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-14 13:37:29 -0700 |
commit | 6c118e43dc513a7118b49b9ff953fe61e14515dc (patch) | |
tree | ef654ba1982c17a516697d25b3d0405acb6aeac1 /arch/avr32/mach-at32ap/intc.c | |
parent | 847106ff628805e1a0aa91e7f53381f3fdfcd839 (diff) | |
parent | 72f6befeea7dc634a83219287d5b874734b85637 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6: (31 commits)
avr32: Fix typo of IFSR in a comment in the PIO header file
avr32: Power Management support ("standby" and "mem" modes)
avr32: Add system device for the internal interrupt controller (intc)
avr32: Add simple SRAM allocator
avr32: Enable SDRAMC clock at startup
rtc-at32ap700x: Enable wakeup
macb: Basic suspend/resume support
atmel_serial: Drain console TX shifter before suspending
atmel_serial: Fix build on avr32 with CONFIG_PM enabled
avr32: Use a quicklist for PTE allocation as well
avr32: Use a quicklist for PGD allocation
avr32: Cover the kernel page tables in the user PGDs
avr32: Store virtual addresses in the PGD
avr32: Remove useless zeroing of swapper_pg_dir at startup
avr32: Clean up and optimize the TLB operations
avr32: Rename at32ap.c -> pdc.c
avr32: Move setup_platform() into chip-specific file
avr32: Kill special exception handler sections
avr32: Kill unneeded #include <asm/pgalloc.h> from asm/mmu_context.h
avr32: Clean up time.c #includes
...
Diffstat (limited to 'arch/avr32/mach-at32ap/intc.c')
-rw-r--r-- | arch/avr32/mach-at32ap/intc.c | 80 |
1 files changed, 77 insertions, 3 deletions
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c index 097cf4e8405..994c4545e2b 100644 --- a/arch/avr32/mach-at32ap/intc.c +++ b/arch/avr32/mach-at32ap/intc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Atmel Corporation + * Copyright (C) 2006, 2008 Atmel Corporation * * 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 @@ -12,14 +12,20 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/platform_device.h> +#include <linux/sysdev.h> #include <asm/io.h> #include "intc.h" struct intc { - void __iomem *regs; - struct irq_chip chip; + void __iomem *regs; + struct irq_chip chip; + struct sys_device sysdev; +#ifdef CONFIG_PM + unsigned long suspend_ipr; + unsigned long saved_ipr[64]; +#endif }; extern struct platform_device at32_intc0_device; @@ -136,6 +142,74 @@ fail: panic("Interrupt controller initialization failed!\n"); } +#ifdef CONFIG_PM +void intc_set_suspend_handler(unsigned long offset) +{ + intc0.suspend_ipr = offset; +} + +static int intc_suspend(struct sys_device *sdev, pm_message_t state) +{ + struct intc *intc = container_of(sdev, struct intc, sysdev); + int i; + + if (unlikely(!irqs_disabled())) { + pr_err("intc_suspend: called with interrupts enabled\n"); + return -EINVAL; + } + + if (unlikely(!intc->suspend_ipr)) { + pr_err("intc_suspend: suspend_ipr not initialized\n"); + return -EINVAL; + } + + for (i = 0; i < 64; i++) { + intc->saved_ipr[i] = intc_readl(intc, INTPR0 + 4 * i); + intc_writel(intc, INTPR0 + 4 * i, intc->suspend_ipr); + } + + return 0; +} + +static int intc_resume(struct sys_device *sdev) +{ + struct intc *intc = container_of(sdev, struct intc, sysdev); + int i; + + WARN_ON(!irqs_disabled()); + + for (i = 0; i < 64; i++) + intc_writel(intc, INTPR0 + 4 * i, intc->saved_ipr[i]); + + return 0; +} +#else +#define intc_suspend NULL +#define intc_resume NULL +#endif + +static struct sysdev_class intc_class = { + .name = "intc", + .suspend = intc_suspend, + .resume = intc_resume, +}; + +static int __init intc_init_sysdev(void) +{ + int ret; + + ret = sysdev_class_register(&intc_class); + if (ret) + return ret; + + intc0.sysdev.id = 0; + intc0.sysdev.cls = &intc_class; + ret = sysdev_register(&intc0.sysdev); + + return ret; +} +device_initcall(intc_init_sysdev); + unsigned long intc_get_pending(unsigned int group) { return intc_readl(&intc0, INTREQ0 + 4 * group); |