diff options
| author | Jim Wylder <jwylder@motorola.com> | 2014-05-26 08:48:21 -0500 |
|---|---|---|
| committer | James Wylder <jwylder@motorola.com> | 2014-05-27 20:28:40 +0000 |
| commit | dc20078f157d09c98a4daa26f2cdec578a96a1d3 (patch) | |
| tree | 26afd16eaabb0579568b0f7724b13af30c795f83 | |
| parent | 26ab718ff0710b300cfa8c87443b7210bd6ef967 (diff) | |
| download | olio-linux-3.10-dc20078f157d09c98a4daa26f2cdec578a96a1d3.tar.xz olio-linux-3.10-dc20078f157d09c98a4daa26f2cdec578a96a1d3.zip | |
IKXCLOCK-1705 arm: omap2: padwkup interrupt handler
This change replaces the previous, of signaling an interrupt
for the gpio bank with a pure software call.
Change-Id: I3380acf3745a9ff823cd3a0028f8b7be9190f20f
Signed-off-by: Jim Wylder <jwylder@motorola.com>
| -rw-r--r-- | Documentation/devicetree/bindings/ti-pad_wkup.txt | 17 | ||||
| -rw-r--r-- | arch/arm/configs/minnow_defconfig | 1 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/Kconfig | 12 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/pad_wkup.c | 140 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/pad_wkup.h | 5 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 5 |
7 files changed, 180 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/ti-pad_wkup.txt b/Documentation/devicetree/bindings/ti-pad_wkup.txt new file mode 100644 index 00000000000..19df431be3a --- /dev/null +++ b/Documentation/devicetree/bindings/ti-pad_wkup.txt @@ -0,0 +1,17 @@ +OMAP3 pad wkup generator + +Functionality to map omap pad wkup status to irq events; + +Required properties: +- ti,pad_irq Maps a pad offset to a IRQ + on omap, the irqs are calculated as follows: + for the 96 intc IRQs + irq = 16 + irq_offset (from TRM sec 12.3.2) + for a gpio IRQ (banks numbered 1 to 6 + irq = 16 + 96 + (gpio_bank - 1) * 32 + + ti,pad_irq = <0x008e 171>, /* m4sensor hub */ + <0x00e6 211>, /* touch */ + <0x013c 252>, /* battery */ + <0x0140 254>, /* USB */ + <0x01a2 288>; /* gpio-charger */ diff --git a/arch/arm/configs/minnow_defconfig b/arch/arm/configs/minnow_defconfig index 478dad042d7..6b8e6d91772 100644 --- a/arch/arm/configs/minnow_defconfig +++ b/arch/arm/configs/minnow_defconfig @@ -351,6 +351,7 @@ CONFIG_OMAP_PACKAGE_CBP=y CONFIG_MACH_MINNOW=y # CONFIG_OMAP3_EMU is not set # CONFIG_OMAP3_SDRC_AC_TIMING is not set +# CONFIG_OMAP3_PAD_WKUP_IO is not set CONFIG_DISABLE_OMAP_ERRATA_i583=y # CONFIG_ARCH_SOCFPGA is not set # CONFIG_PLAT_SPEAR is not set diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 281a0a7614a..0168b07ce0c 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -420,8 +420,18 @@ config OMAP3_SDRC_AC_TIMING wish to say no. Selecting yes without understanding what is going on could result in system crashes; + +config OMAP3_PAD_WKUP_IO + bool "Enable Generation of IRQ from pad status" + depends on ARCH_OMAP3 + default n + help + For offmode, gpio (and possibly other) domains can wakeup the system + but will not retain their irq status internally. This function generates + the configured irq on each time the io irq (315) fires. + config DISABLE_OMAP_ERRATA_i583 - bool "Override errata i583 + bool "Override errata i583" depends on ARCH_OMAP3 default n help diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 731e039bef0..ff5c4457325 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -8,7 +8,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ # Common support obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o gpmc.o timer.o pm.o \ common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \ - omap_device.o sram.o + omap_device.o sram.o pad_wkup.o omap-2-3-common = irq.o hwmod-common = omap_hwmod.o omap_hwmod_reset.o \ diff --git a/arch/arm/mach-omap2/pad_wkup.c b/arch/arm/mach-omap2/pad_wkup.c new file mode 100644 index 00000000000..6342ca91106 --- /dev/null +++ b/arch/arm/mach-omap2/pad_wkup.c @@ -0,0 +1,140 @@ +/* + * OMAP3 Pad Wakeup Handler + * + * Copyright (C) 2014-2008 Motorola, LLC. + * + * 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. + */ + +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/list.h> +#include <linux/err.h> + +#include "soc.h" +#include "common.h" +#include "mux34xx.h" +#include "prm3xxx.h" +#include "iomap.h" + +#include "pad_wkup.h" + +#define WAKEUPEVENT 0x8000 +struct offmode_wkup { + struct list_head node; + u32 irq; + u32 pad; + u32 pad_shift; +}; +LIST_HEAD(offmode_wkup_list); + +static void omap_register_pad_wkup(struct device *dev, u32 pad, u32 irq) +{ + struct offmode_wkup *wkup; + + pr_info("register pad (0x%04x, %u)\n", pad, irq); + + wkup = devm_kzalloc(dev, sizeof(struct offmode_wkup), GFP_KERNEL); + if (wkup) { + wkup->irq = irq; + wkup->pad = pad & 0xFFFFFFFC; + wkup->pad_shift = pad % 4 ? 16 : 0; + list_add_tail(&wkup->node, &offmode_wkup_list); + } +} + +static inline int is_pad_wkup(const struct offmode_wkup *wkup) +{ + int pad = __raw_readl( + OMAP2_L4_IO_ADDRESS(OMAP3_CONTROL_PADCONF_MUX_PBASE)+ wkup->pad); + pad = pad >> wkup->pad_shift; + + return (pad & WAKEUPEVENT) ? 1 : 0; +} + +void prcm_handle_pad_wkup(void) +{ + struct offmode_wkup *wkup; + + list_for_each_entry(wkup, &offmode_wkup_list, node) { + if (is_pad_wkup(wkup)) { + pr_info("%s IRQ = %d\n", __func__, wkup->irq); + generic_handle_irq(wkup->irq); + } + } +} + +#ifdef CONFIG_OMAP3_PAD_WKUP_IO +static irqreturn_t omap3_pad_wkup_handle_irq(int irq, void *unused) +{ + prcm_handle_pad_wkup(); + + return IRQ_HANDLED; +} +#endif + +static int omap3_pad_wkup_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + int ndx = 0; + u32 pad, irq; + int ret = 0; + + if (!node) + return -ENODEV; + + do { + if (of_property_read_u32_index(node, "ti,pad_irq", ndx, &pad)) + break; + ndx++; + if (of_property_read_u32_index(node, "ti,pad_irq", ndx, &irq)) + break; + ndx++; + omap_register_pad_wkup(&pdev->dev, pad, irq); + } while (1); + +#ifdef CONFIG_OMAP3_PAD_WKUP_IO + if (ndx > 1) { + dev_info(&pdev->dev, "request pad_wkup_io\n"); + ret = request_irq(omap_prcm_event_to_irq("io"), + omap3_pad_wkup_handle_irq, + IRQF_SHARED | IRQF_NO_SUSPEND, + "pad_wkup_io", &pdev->dev); + + if (ret) + pr_warning("wkup: Failed to setup pad_wkup_io irq %d\n", + ret); + } +#endif + + return ret; +} + +static int omap3_pad_wkup_remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct of_device_id omap3_pad_wkup_table[] = { + { .compatible = "ti,pad-wkup", }, + { }, +}; +MODULE_DEVICE_TABLE(of, omap3_pad_wkup_table); + +static struct platform_driver omap3_pad_wkup_driver = { + .probe = omap3_pad_wkup_probe, + .remove = omap3_pad_wkup_remove, + .driver = { + .name = "omap3_pad_wkup", + .owner = THIS_MODULE, + .of_match_table = omap3_pad_wkup_table, + }, +}; + +static int __init omap_pad_wkup_init(void) +{ + return platform_driver_register(&omap3_pad_wkup_driver); +} +omap_late_initcall(omap_pad_wkup_init); diff --git a/arch/arm/mach-omap2/pad_wkup.h b/arch/arm/mach-omap2/pad_wkup.h new file mode 100644 index 00000000000..9a3b402e411 --- /dev/null +++ b/arch/arm/mach-omap2/pad_wkup.h @@ -0,0 +1,5 @@ +#ifndef __OMAP_PADWKUP_H__ +#define __OMAP_PADWKUP_H__ + +extern void prcm_handle_pad_wkup(void); +#endif diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 46182a5293d..939e92c11db 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -54,6 +54,8 @@ #include "pm-debug-regs.h" #include "iomap.h" +#include "pad_wkup.h" + /* pm34xx errata defined in pm.h */ u16 pm34xx_errata; bool suspend_debug; @@ -375,6 +377,7 @@ void omap_sram_idle(bool in_suspend) /* PER */ if (per_next_state < PWRDM_POWER_ON) omap2_gpio_resume_after_idle(in_suspend); + } static void omap3_pm_idle(void) @@ -412,6 +415,8 @@ static int omap3_pm_suspend(void) omap_sram_idle(true); + prcm_handle_pad_wkup(); + restore: /* Restore next_pwrsts */ list_for_each_entry(pwrst, &pwrst_list, node) { |