From: Kevin Hilman <khilman@deeprootsystems.com>
To: Kim Kyuwon <chammoru@gmail.com>
Cc: q1.kim@samsung.com, OMAP <linux-omap@vger.kernel.org>
Subject: Re: About two patches that I sent recently.
Date: Tue, 17 Mar 2009 08:18:49 -0700 [thread overview]
Message-ID: <87ljr4fa92.fsf@deeprootsystems.com> (raw)
In-Reply-To: <4d34a0a70903152159y6b20bb57qfbab3f05399bd9a7@mail.gmail.com> (Kim Kyuwon's message of "Mon\, 16 Mar 2009 13\:59\:04 +0900")
Kim Kyuwon <chammoru@gmail.com> writes:
> Hi, Kevin
>
> On Tue, Mar 10, 2009 at 2:21 AM, Kevin Hilman
> <khilman@deeprootsystems.com> wrote:
>> Kim Kyuwon <chammoru@gmail.com> writes:
>>
>>> Hi, Kevin Hilman.
>>>
>>> I'm sending this mail to tell you a few things about two recent
>>> fetches that I sent.
>>>
>>> 1. [OMAP: GPIO: Remove enable_irq_wake() and disable_irq_wake() in
>>> _set_gpio_wakeup() function]
>>> I just found that you already sent the same patch in [OMAP2/3: GPIO:
>>> remove recursion in IRQ wakeup path]. Sorry, I didn't know that. I
>>> will cancel my patch. But can I know when your patch will be applied?
>>
>> I need to update the description of mine and resend after
>> incorporating some review comments.
>>
>>> 2. [OMAP3: PM: Add the wakeup source driver]
>>> Would you please review this patch? If something is unclear or need to
>>> change, please let me know. I would answer with please.
>>
>> Yes, I will review this week.
>
> Can I ask again when I can get your review? :)
Hi Kim, I'm sorry for the delay on reviewing your patch. I've been
delaying because not only do I want to review it, I want to try it
out. I will do both today.
Kevin
> And I'm resending the patch which is made for PM branch and added a
> few trivial changes.
> I really want to hear your opinion.
>
> Thanks & Regards,
>
> --
> Kyuwon
>
> --
> [PATCH] OMAP3: PM: Add the wakeup source driver
>
> Sometimes, it is necessary to find out "what does wake up my board?".
> Notifying wake-up source feature may be used to blame unexpected
> wake-up events which increase power consumption. And user mode
> applications can act smartly according to the wake-up event to
> minimize power consumption. This driver uses sysfs interface to give
> information to user mode applications like:
>
> cat /sys/power/wakeup_irq
> cat /sys/power/wakeup_event
>
> This driver also privides the unified GPIO wake-up source
> configuration. specific GPIO settings in the board files are:
>
> /* Wakeup source configuration */
> static struct gpio_wake boardname_gpio_wake[] = {
> { 23, IRQF_TRIGGER_RISING | IRQF_SHARED, "BT_WAKEUP", 1},
> { 24, IRQF_TRIGGER_RISING | IRQF_SHARED, "USB_DETECT", 1},
> };
>
> static struct omap_wake_platform_data boardname_wake_data = {
> .qpio_wakes = boardname_gpio_wake,
> .gpio_wake_num = ARRAY_SIZE(boardname_gpio_wake),
> };
>
> static struct platform_device boardname_wakeup = {
> .name = "omap-wake",
> .id = -1,
> .dev = {
> .platform_data = &boardname_wake_data,
> },
> };
>
> The patch adds Kconfig options "OMAP34xx wakeup source support" under
> "System type"->"TI OMAP implementations" menu.
>
> Signed-off-by: Kim Kyuwon <q1.kim@samsung.com>
> ---
> arch/arm/mach-omap2/Makefile | 1 +
> arch/arm/mach-omap2/irq.c | 41 +++
> arch/arm/mach-omap2/prcm-common.h | 4 +
> arch/arm/mach-omap2/prm-regbits-34xx.h | 6 +
> arch/arm/mach-omap2/wake34xx.c | 474 ++++++++++++++++++++++++++++++++
> arch/arm/plat-omap/Kconfig | 9 +
> arch/arm/plat-omap/include/mach/irqs.h | 1 +
> arch/arm/plat-omap/include/mach/wake.h | 30 ++
> 8 files changed, 566 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-omap2/wake34xx.c
> create mode 100644 arch/arm/plat-omap/include/mach/wake.h
>
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index 16c6fb8..29ad0f1 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -25,6 +25,7 @@ obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
> obj-$(CONFIG_ARCH_OMAP24XX) += sleep24xx.o
> obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o cpuidle34xx.o
> obj-$(CONFIG_PM_DEBUG) += pm-debug.o
> +obj-$(CONFIG_OMAP_WAKE) += wake34xx.o
> endif
>
> # SmartReflex driver
> diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
> index be4b596..e3a2b53 100644
> --- a/arch/arm/mach-omap2/irq.c
> +++ b/arch/arm/mach-omap2/irq.c
> @@ -193,6 +193,47 @@ int omap_irq_pending(void)
> return 0;
> }
>
> +/*
> + * Get the first pending MPU IRQ number from 'irq_start'.
> + * If none, return -1.
> + */
> +int omap_get_pending_mpu_irq(unsigned int irq_start)
> +{
> + struct omap_irq_bank *bank = irq_banks;
> + int irq, bits_skip, bit_start;
> +
> + if (irq_start >= bank->nr_irqs)
> + return -1;
> +
> + bits_skip = irq_start % IRQ_BITS_PER_REG;
> + bit_start = irq_start - bits_skip;
> +
> + for (irq = bit_start; irq < bank->nr_irqs; irq += IRQ_BITS_PER_REG) {
> + int ret, i, limit, offset = irq & (~(IRQ_BITS_PER_REG - 1));
> +
> + ret = intc_bank_read_reg(bank, (INTC_PENDING_IRQ0 + offset));
> + if (!ret)
> + continue;
> +
> + limit = IRQ_BITS_PER_REG;
> +
> + if (bit_start == irq) {
> + ret >>= bits_skip;
> + limit -= bits_skip;
> + } else
> + bits_skip = 0;
> +
> + for (i = 0; i < limit; i++) {
> + if (ret & 0x1)
> + return irq + i + bits_skip;
> + else
> + ret >>= 1;
> + }
> + }
> +
> + return -1;
> +}
> +
> void __init omap_init_irq(void)
> {
> unsigned long nr_of_irqs = 0;
> diff --git a/arch/arm/mach-omap2/prcm-common.h
> b/arch/arm/mach-omap2/prcm-common.h
> index cb1ae84..1f340aa 100644
> --- a/arch/arm/mach-omap2/prcm-common.h
> +++ b/arch/arm/mach-omap2/prcm-common.h
> @@ -273,6 +273,10 @@
> #define OMAP3430_ST_D2D_SHIFT 3
> #define OMAP3430_ST_D2D_MASK (1 << 3)
>
> +/* PM_WKST3_CORE, CM_IDLEST3_CORE shared bits */
> +#define OMAP3430_ST_USBTLL_SHIFT 2
> +#define OMAP3430_ST_USBTLL_MASK (1 << 2)
> +
> /* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
> #define OMAP3430_EN_GPIO1 (1 << 3)
> #define OMAP3430_EN_GPIO1_SHIFT 3
> diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h
> b/arch/arm/mach-omap2/prm-regbits-34xx.h
> index cb648f9..6066032 100644
> --- a/arch/arm/mach-omap2/prm-regbits-34xx.h
> +++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
> @@ -332,6 +332,8 @@
> /* PM_IVA2GRPSEL1_CORE specific bits */
>
> /* PM_WKST1_CORE specific bits */
> +#define OMAP3430_ST_MMC3_SHIFT 30
> +#define OMAP3430_ST_MMC3_MASK (1 << 30)
>
> /* PM_PWSTCTRL_CORE specific bits */
> #define OMAP3430_MEM2ONSTATE_SHIFT 18
> @@ -373,6 +375,7 @@
> /* PM_IVA2GRPSEL_WKUP specific bits */
>
> /* PM_WKST_WKUP specific bits */
> +#define OMAP3430_ST_IO_CHAIN (1 << 16)
> #define OMAP3430_ST_IO (1 << 8)
>
> /* PRM_CLKSEL */
> @@ -430,6 +433,9 @@
>
> /* PM_PREPWSTST_PER specific bits */
>
> +/* PM_WKST_USBHOST specific bits */
> +#define OMAP3430_ST_USBHOST (1 << 0)
> +
> /* RM_RSTST_EMU specific bits */
>
> /* PM_PWSTST_EMU specific bits */
> diff --git a/arch/arm/mach-omap2/wake34xx.c b/arch/arm/mach-omap2/wake34xx.c
> new file mode 100644
> index 0000000..c352d08
> --- /dev/null
> +++ b/arch/arm/mach-omap2/wake34xx.c
> @@ -0,0 +1,474 @@
> +/*
> + * wake34xx.c
> + *
> + * Copyright (c) 2009 Samsung Eletronics
> + *
> + * Author: Kim Kyuwon <q1.kim@samsung.com>
> + *
> + * 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/kernel.h>
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
> +
> +#include <mach/gpio.h>
> +#include <mach/wake.h>
> +
> +#include "prm-regbits-34xx.h"
> +
> +/*
> + * Sometimes, it is necessary to find out "what does wake up my board?"
> + * Notifying wake-up source feature may be used to blame unexpected wake-up
> + * events which increase power consumption. And user mode applications can
> + * act smartly according to the wake-up event to minimize power consumption.
> + * This driver uses sysfs interface to give information to user mode
> + * applications.
> + */
> +
> +#define WAKE_STR_LEN 64
> +#define WAKE_BUF_LEN 32
> +
> +char wakeup_irq[WAKE_STR_LEN] = "None";
> +char wakeup_event[WAKE_STR_LEN] = "None";
> +
> +struct wake_event {
> + int index;
> + const char *name;
> +};
> +
> +static struct wake_event omap3_wkup_events[] = {
> + { OMAP3430_ST_IO_CHAIN, "ST_IO" },
> + { OMAP3430_ST_IO, "ST_SR2" },
> + { OMAP3430_ST_SR2_MASK, "ST_SR2" },
> + { OMAP3430_ST_SR1_MASK, "ST_SR1" },
> + { OMAP3430_ST_GPIO1_MASK, "ST_GPIO1" },
> + { OMAP3430_ST_GPT12_MASK, "ST_GPT12" },
> + { OMAP3430_ST_GPT1_MASK, "ST_GPT1" },
> +};
> +
> +static struct wake_event omap3_per_events[] = {
> + { OMAP3430_ST_GPIO6_MASK, "ST_GPIO6" },
> + { OMAP3430_ST_GPIO5_MASK, "ST_GPIO5" },
> + { OMAP3430_ST_GPIO4_MASK, "ST_GPIO4" },
> + { OMAP3430_ST_GPIO3_MASK, "ST_GPIO3" },
> + { OMAP3430_ST_GPIO2_MASK, "ST_GPIO2" },
> + { OMAP3430_ST_UART3_MASK, "ST_UART3" },
> + { OMAP3430_ST_GPT9_MASK, "ST_GPT9" },
> + { OMAP3430_ST_GPT8_MASK, "ST_GPT8" },
> + { OMAP3430_ST_GPT7_MASK, "ST_GPT7" },
> + { OMAP3430_ST_GPT6_MASK, "ST_GPT6" },
> + { OMAP3430_ST_GPT5_MASK, "ST_GPT5" },
> + { OMAP3430_ST_GPT4_MASK, "ST_GPT4" },
> + { OMAP3430_ST_GPT3_MASK, "ST_GPT3" },
> + { OMAP3430_ST_GPT2_MASK, "ST_GPT2" },
> + { OMAP3430_EN_MCBSP4, "EN_MCBSP4" },
> + { OMAP3430_EN_MCBSP3, "EN_MCBSP3" },
> + { OMAP3430_EN_MCBSP2, "EN_MCBSP2" },
> +};
> +
> +static struct wake_event omap3_core1_events[] = {
> + { OMAP3430_ST_MMC3_MASK, "ST_MMC3" },
> + { OMAP3430_ST_MMC2_MASK, "ST_MMC2" },
> + { OMAP3430_ST_MMC1_MASK, "ST_MMC1" },
> + { OMAP3430_ST_MCSPI4_MASK, "ST_MCSPI4" },
> + { OMAP3430_ST_MCSPI3_MASK, "ST_MCSPI3" },
> + { OMAP3430_ST_MCSPI2_MASK, "ST_MCSPI2" },
> + { OMAP3430_ST_MCSPI1_MASK, "ST_MCSPI1" },
> + { OMAP3430_ST_I2C3_MASK, "ST_I2C3" },
> + { OMAP3430_ST_I2C2_MASK, "ST_I2C2" },
> + { OMAP3430_ST_I2C1_MASK, "ST_I2C1" },
> + { OMAP3430_ST_UART1_MASK, "ST_UART1" },
> + { OMAP3430_ST_GPT11_MASK, "ST_GPT11" },
> + { OMAP3430_ST_GPT10_MASK, "ST_GPT10" },
> + { OMAP3430_ST_MCBSP5_MASK, "ST_MCBSP5" },
> + { OMAP3430_ST_MCBSP1_MASK, "ST_MCBSP1" },
> +};
> +
> +static struct wake_event omap3es1_core1_events[] = {
> + { OMAP3430ES1_ST_FSHOSTUSB_MASK, "ST_FSHOSTUSB" },
> + { OMAP3430ES1_ST_HSOTGUSB_MASK, "ST_HSOTGUSB" },
> + { OMAP3430_ST_D2D_MASK, "ST_D2D" },
> +};
> +
> +static struct wake_event omap3es2_core1_events[] = {
> + { OMAP3430ES2_ST_HSOTGUSB_STDBY_MASK, "ST_HSOTGUSB" },
> +};
> +
> +static struct wake_event omap3_core2_events[] = {
> + { OMAP3430_ST_USBTLL_MASK, "ST_USBTLL" },
> +};
> +
> +static struct wake_event omap3_usbhost_events[] = {
> + { OMAP3430_ST_USBHOST, "ST_USBHOST" },
> +};
> +
> +static ssize_t wakeup_source_show(struct kobject *kobj,
> + struct kobj_attribute *attr, char *buf);
> +
> +static void omap_wake_update_event(char *event)
> +{
> + int len;
> +
> + if (wakeup_event[0])
> + len = strlen(wakeup_event) + strlen(event) + 2;
> + else
> + len = strlen(wakeup_event) + strlen(event);
> +
> + if (len > WAKE_STR_LEN - 1) {
> + printk(KERN_ERR "Can't record the wakeup event: %s\n", event);
> + return;
> + }
> +
> + if (wakeup_event[0])
> + strcat(wakeup_event, ", ");
> + strcat(wakeup_event, event);
> +}
> +
> +static void omap_wake_detect_wkup(u32 wkst, char *event)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(omap3_wkup_events); i++)
> + if (wkst & omap3_wkup_events[i].index) {
> + strncpy(event, omap3_wkup_events[i].name,
> + WAKE_BUF_LEN - 1);
> + return;
> + }
> +
> + snprintf(event, WAKE_BUF_LEN, "WKUP:0x%08x", wkst);
> +}
> +
> +static void omap_wake_detect_per(u32 wkst, char *event)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(omap3_per_events); i++)
> + if (wkst & omap3_per_events[i].index) {
> + strncpy(event, omap3_per_events[i].name,
> + WAKE_BUF_LEN - 1);
> + return;
> + }
> +
> + snprintf(event, WAKE_BUF_LEN, "PER:0x%08x", wkst);
> +}
> +
> +static void omap_wake_detect_core1(u32 wkst, char *event)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(omap3_core1_events); i++)
> + if (wkst & omap3_core1_events[i].index) {
> + strncpy(event, omap3_core1_events[i].name,
> + WAKE_BUF_LEN - 1);
> + return;
> + }
> +
> + if (omap_rev() == OMAP3430_REV_ES1_0) {
> + for (i = 0; i < ARRAY_SIZE(omap3es1_core1_events); i++) {
> + if (wkst & omap3es1_core1_events[i].index) {
> + strncpy(event, omap3es1_core1_events[i].name,
> + WAKE_BUF_LEN - 1);
> + return;
> + }
> + }
> + } else {
> + for (i = 0; i < ARRAY_SIZE(omap3es2_core1_events); i++) {
> + if (wkst & omap3es2_core1_events[i].index) {
> + strncpy(event, omap3es2_core1_events[i].name,
> + WAKE_BUF_LEN - 1);
> + return;
> + }
> + }
> + }
> +
> + snprintf(event, WAKE_BUF_LEN, "CORE1:0x%08x", wkst);
> +}
> +
> +static void omap_wake_detect_core2(u32 wkst, char *event)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(omap3_core2_events); i++)
> + if (wkst & omap3_core2_events[i].index) {
> + strncpy(event, omap3_core2_events[i].name,
> + WAKE_BUF_LEN - 1);
> + return;
> + }
> +
> + snprintf(event, WAKE_BUF_LEN, "CORE2:0x%08x", wkst);
> +}
> +
> +static void omap_wake_detect_usbhost(u32 wkst, char *event)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(omap3_usbhost_events); i++)
> + if (wkst & omap3_usbhost_events[i].index) {
> + strncpy(event, omap3_usbhost_events[i].name,
> + WAKE_BUF_LEN - 1);
> + return;
> + }
> +
> + snprintf(event, WAKE_BUF_LEN, "USBHOST:0x%08x", wkst);
> +}
> +
> +/* Detect wake-up events */
> +static void omap_wake_detect_wakeup(void)
> +{
> + u32 wkst;
> + char buf[WAKE_BUF_LEN] = {0, };
> + int irq, len, prcm_irq = 0;
> +
> + /* Initialize global string variables */
> + memset(wakeup_irq, 0x0, WAKE_STR_LEN);
> + memset(wakeup_event, 0x0, WAKE_STR_LEN);
> +
> + /* IRQ */
> + irq = omap_get_pending_mpu_irq(0);
> + while (irq >= 0) {
> + if (irq == INT_34XX_SYS_NIRQ)
> + omap_wake_update_event("sys_nirq");
> + else if (irq == INT_34XX_PRCM_MPU_IRQ)
> + prcm_irq = 1;
> +
> + len = strlen(wakeup_irq) +
> + snprintf(buf, WAKE_BUF_LEN, "%d", irq);
> + if (len > WAKE_STR_LEN - 1)
> + break;
> +
> + strcat(wakeup_irq, buf);
> +
> + irq = omap_get_pending_mpu_irq(irq + 1);
> + if (irq >= 0) {
> + len = strlen(wakeup_irq) + 2;
> + if (len > WAKE_STR_LEN - 1)
> + break;
> +
> + strcat(wakeup_irq, ", ");
> + }
> + }
> + if (!wakeup_irq[0])
> + strncpy(wakeup_irq, "Unknown", WAKE_STR_LEN - 1);
> + printk(KERN_INFO "Wake-up IRQ: %s\n", wakeup_irq);
> +
> + if (!prcm_irq)
> + goto end_detect;
> +
> + /* WKUP */
> + wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST);
> + if (wkst) {
> + omap_wake_detect_wkup(wkst, buf);
> + omap_wake_update_event(buf);
> + }
> +
> + /* PER */
> + wkst = prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST);
> + if (wkst) {
> + omap_wake_detect_per(wkst, buf);
> + omap_wake_update_event(buf);
> + }
> +
> + /* CORE */
> + wkst = prm_read_mod_reg(CORE_MOD, PM_WKST1);
> + if (wkst) {
> + omap_wake_detect_core1(wkst, buf);
> + omap_wake_update_event(buf);
> + }
> + wkst = prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3);
> + if (wkst) {
> + omap_wake_detect_core2(wkst, buf);
> + omap_wake_update_event(buf);
> + }
> +
> + /* USBHOST */
> + wkst = prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST);
> + if (wkst) {
> + omap_wake_detect_usbhost(wkst, buf);
> + omap_wake_update_event(buf);
> + }
> +
> +end_detect:
> + if (!wakeup_event[0])
> + strncpy(wakeup_event, "Unknown", WAKE_STR_LEN - 1);
> +}
> +
> +static struct kobj_attribute wakeup_irq_attr =
> + __ATTR(wakeup_irq, 0644, wakeup_source_show, NULL);
> +
> +static struct kobj_attribute wakeup_event_attr =
> + __ATTR(wakeup_event, 0644, wakeup_source_show, NULL);
> +
> +static ssize_t wakeup_source_show(struct kobject *kobj,
> + struct kobj_attribute *attr, char *buf)
> +{
> + if (attr == &wakeup_irq_attr)
> + return sprintf(buf, "%s\n", wakeup_irq);
> + else if (attr == &wakeup_event_attr)
> + return sprintf(buf, "%s\n", wakeup_event);
> + else
> + return -EINVAL;
> +}
> +
> +static irqreturn_t omap_wake_detect_gpio(int irq, void *dev_id)
> +{
> + if (!strncmp(wakeup_event, "Unknown", WAKE_STR_LEN - 1))
> + strncpy(wakeup_event, dev_id, WAKE_STR_LEN - 1);
> + else
> + omap_wake_update_event(dev_id);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int __devinit omap_wake_probe(struct platform_device *pdev)
> +{
> + struct omap_wake_platform_data *pdata = pdev->dev.platform_data;
> + struct gpio_wake *gw;
> + int i, ret;
> +
> + /*
> + * It may be good to configure GPIO wake-up sources in each driver.
> + * Buf if the specific device driver doesn't exist, you can use
> + * omap-wake driver to configure gpio wake-up sources.
> + */
> + for (i = 0; i < pdata->gpio_wake_num; i++) {
> + gw = pdata->qpio_wakes + i;
> +
> + if (gw->request) {
> + ret = gpio_request(gw->gpio, gw->name);
> + if (ret) {
> + dev_err(&pdev->dev, "can't request gpio%d"
> + ", return %d\n", gw->gpio, ret);
> + goto failed_free_gpio;
> + }
> + }
> + gpio_direction_input(gw->gpio);
> + enable_irq_wake(gpio_to_irq(gw->gpio));
> + }
> +
> + ret = sysfs_create_file(power_kobj, &wakeup_irq_attr.attr);
> + if (ret)
> + dev_err(&pdev->dev, "sysfs_create_file %s failed: %d\n",
> + wakeup_irq_attr.attr.name, ret);
> +
> + ret = sysfs_create_file(power_kobj, &wakeup_event_attr.attr);
> + if (ret)
> + dev_err(&pdev->dev, "sysfs_create_file %s failed: %d\n",
> + wakeup_event_attr.attr.name, ret);
> +
> + return 0;
> +
> +failed_free_gpio:
> + for (i--; i >= 0; i--) {
> + gw = pdata->qpio_wakes + i;
> +
> + if (gw->request)
> + gpio_free(gw->gpio);
> + }
> +
> + return ret;
> +}
> +
> +static int __devexit omap_wake_remove(struct platform_device *pdev)
> +{
> + struct omap_wake_platform_data *pdata = pdev->dev.platform_data;
> + struct gpio_wake *gw;
> + int i;
> +
> + for (i = 0; i < pdata->gpio_wake_num; i++) {
> + gw = pdata->qpio_wakes + i;
> +
> + if (gw->request)
> + gpio_free(gw->gpio);
> +
> + disable_irq_wake(gpio_to_irq(gw->gpio));
> + }
> +
> + return 0;
> +}
> +
> +static int omap_wake_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> + struct omap_wake_platform_data *pdata = pdev->dev.platform_data;
> + struct gpio_wake *gw;
> + int i, ret;
> +
> + for (i = 0; i < pdata->gpio_wake_num; i++) {
> + gw = pdata->qpio_wakes + i;
> +
> + ret = request_irq(gpio_to_irq(gw->gpio), omap_wake_detect_gpio,
> + gw->irqflag, gw->name, (void *)gw->name);
> + if (ret) {
> + dev_err(&pdev->dev, "can't get IRQ%d, return %d\n",
> + gpio_to_irq(gw->gpio), ret);
> + goto failed_free_irq;
> + }
> + }
> +
> + return 0;
> +
> +failed_free_irq:
> + for (i--; i >= 0; i--) {
> + gw = pdata->qpio_wakes + i;
> + free_irq(gpio_to_irq(gw->gpio), (void *)gw->name);
> + }
> +
> + return ret;
> +}
> +
> +static int omap_wake_resume_early(struct platform_device *pdev)
> +{
> + omap_wake_detect_wakeup();
> +
> + return 0;
> +}
> +
> +static int omap_wake_resume(struct platform_device *pdev)
> +{
> + struct omap_wake_platform_data *pdata = pdev->dev.platform_data;
> + struct gpio_wake *gw;
> + int i;
> +
> + for (i = 0; i < pdata->gpio_wake_num; i++) {
> + gw = pdata->qpio_wakes + i;
> +
> + free_irq(gpio_to_irq(gw->gpio), (void *)gw->name);
> + }
> +
> + printk(KERN_INFO "Wake-up event: %s\n", wakeup_event);
> +
> + return 0;
> +}
> +
> +static struct platform_driver omap_wake_driver = {
> + .probe = omap_wake_probe,
> + .remove = __devexit_p(omap_wake_remove),
> + .suspend = omap_wake_suspend,
> + .resume_early = omap_wake_resume_early,
> + .resume = omap_wake_resume,
> + .driver = {
> + .name = "omap-wake",
> + .owner = THIS_MODULE,
> + },
> +};
> +
> +static int __init omap_wake_init(void)
> +{
> + return platform_driver_register(&omap_wake_driver);
> +}
> +
> +module_init(omap_wake_init);
> +
> +static void __exit omap_wake_exit(void)
> +{
> + platform_driver_unregister(&omap_wake_driver);
> +}
> +module_exit(omap_wake_exit);
> +
> +MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>");
> +MODULE_DESCRIPTION("OMAP34xx wakeup driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
> index b8f1298..f89efaa 100644
> --- a/arch/arm/plat-omap/Kconfig
> +++ b/arch/arm/plat-omap/Kconfig
> @@ -184,6 +184,15 @@ config OMAP_IOMMU
> Say Y here if you want to use OMAP IOMMU support for IVA2 and
> Camera in OMAP3.
>
> +config OMAP_WAKE
> + tristate "OMAP34xx wakeup source support"
> + depends on ARCH_OMAP34XX && PM
> + default n
> + help
> + Select this option if you want to know what kind of wake-up event
> + wakes up your board from the low power mode. And this option
> + provides the unified GPIO wake-up source configuration.
> +
> choice
> prompt "System timer"
> default OMAP_MPU_TIMER
> diff --git a/arch/arm/plat-omap/include/mach/irqs.h
> b/arch/arm/plat-omap/include/mach/irqs.h
> index c9a5b19..d7961d4 100644
> --- a/arch/arm/plat-omap/include/mach/irqs.h
> +++ b/arch/arm/plat-omap/include/mach/irqs.h
> @@ -388,6 +388,7 @@
> #ifndef __ASSEMBLY__
> extern void omap_init_irq(void);
> extern int omap_irq_pending(void);
> +extern int omap_get_pending_mpu_irq(unsigned int irq_start);
> void omap3_intc_save_context(void);
> void omap3_intc_restore_context(void);
> #endif
> diff --git a/arch/arm/plat-omap/include/mach/wake.h
> b/arch/arm/plat-omap/include/mach/wake.h
> new file mode 100644
> index 0000000..713d89a
> --- /dev/null
> +++ b/arch/arm/plat-omap/include/mach/wake.h
> @@ -0,0 +1,30 @@
> +/*
> + * wake.h
> + *
> + * Copyright (c) 2009 Samsung Eletronics
> + *
> + * Author: Kim Kyuwon <q1.kim@samsung.com>
> + *
> + * 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 _WAKE_H_
> +#define _WAKE_H_
> +
> +struct gpio_wake {
> + unsigned int gpio;
> + unsigned long irqflag;
> + const char *name;
> + int request;
> +};
> +
> +struct omap_wake_platform_data{
> + struct gpio_wake *qpio_wakes;
> + int gpio_wake_num;
> +};
> +
> +#endif /* _WAKE_H_ */
> +
> --
> 1.5.2.5
prev parent reply other threads:[~2009-03-17 15:18 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <4d34a0a70903081708p36a6e16crb5a7f7603c75a813@mail.gmail.com>
[not found] ` <87d4cqzk69.fsf@deeprootsystems.com>
2009-03-16 4:59 ` About two patches that I sent recently Kim Kyuwon
2009-03-17 15:18 ` Kevin Hilman [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87ljr4fa92.fsf@deeprootsystems.com \
--to=khilman@deeprootsystems.com \
--cc=chammoru@gmail.com \
--cc=linux-omap@vger.kernel.org \
--cc=q1.kim@samsung.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.