summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gonzalez <alex.gonzalez@digi.com>2011-12-16 12:16:46 +0100
committerAlex Gonzalez <alex.gonzalez@digi.com>2011-12-16 12:16:46 +0100
commit02448c5ada2d2de22acd74152b69bb2a815b5f79 (patch)
tree66040c10f9fad59b5b4d92b871a30d41277d1995
parent3bbebc65ced52b2a5efd6703acc0b8a841d1db5d (diff)
ccxmx5x: Add support for power button.
-rw-r--r--arch/arm/configs/imx5_ccwmx53js_defconfig15
-rw-r--r--arch/arm/mach-mx5/Kconfig1
-rw-r--r--drivers/input/misc/da9052_onkey.c75
3 files changed, 89 insertions, 2 deletions
diff --git a/arch/arm/configs/imx5_ccwmx53js_defconfig b/arch/arm/configs/imx5_ccwmx53js_defconfig
index 58480c1c16be..969437651c25 100644
--- a/arch/arm/configs/imx5_ccwmx53js_defconfig
+++ b/arch/arm/configs/imx5_ccwmx53js_defconfig
@@ -944,7 +944,20 @@ CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_P1003 is not set
CONFIG_TOUCHSCREEN_DA9052=y
# CONFIG_TOUCHSCREEN_MAX11801 is not set
-# CONFIG_INPUT_MISC is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_MMA7455L is not set
+CONFIG_INPUT_DA9052_ONKEY=y
+# CONFIG_INPUT_ISL29023 is not set
#
# Hardware I/O ports
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 760388704c1d..91ebe7ad9ea0 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -285,6 +285,7 @@ config MXC_DISABLE_WARM_RESET
config CCXMX5X_PM_POWER_BUTTON
bool "Enable power button for suspend/resume to RAM"
+ depends on MODULE_CCXMX51 || (MODULE_CCXMX53 && (INPUT_DA9052_ONKEY || INPUT_DA9052_ONKEY_MODULE))
default y
help
This option will enable the usage of the power button to suspend
diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c
index dc3bf46420fb..54450f09e91e 100644
--- a/drivers/input/misc/da9052_onkey.c
+++ b/drivers/input/misc/da9052_onkey.c
@@ -7,6 +7,10 @@
#include <linux/mfd/da9052/da9052.h>
#include <linux/mfd/da9052/reg.h>
+#ifdef CONFIG_CCXMX5X_PM_POWER_BUTTON
+#include <linux/suspend.h>
+#endif
+
#define DRIVER_NAME "da9052-onkey"
struct da9052_onkey_data {
@@ -16,6 +20,59 @@ struct da9052_onkey_data {
struct delayed_work polling_work;
};
+#ifdef CONFIG_CCXMX5X_PM_POWER_BUTTON
+enum power_on_state {
+ PWRON_FROM_RESUME,
+ PWRON_FALLING_EDGE,
+ PWRON_FROM_SUSPEND
+};
+
+static int pwron_state = PWRON_FROM_RESUME;
+
+static void da9052_power_button( struct da9052 *da9052 , int value )
+{
+ struct da9052_ssc_msg ssc_msg;
+ unsigned int ret;
+
+ switch (pwron_state){
+ case PWRON_FROM_RESUME:
+ // Are we waking up from a non power button suspend
+ // and this is the falling edge already?
+ if( !value )
+ pwron_state = PWRON_FROM_RESUME;
+ else
+ // Skipping falling edge
+ pwron_state = PWRON_FALLING_EDGE;
+ break;
+ case PWRON_FALLING_EDGE:
+ // Suspend on rising edge
+ pm_suspend(PM_SUSPEND_MEM);
+ // Did we wake by a power button press?
+ da9052_lock(da9052);
+ ssc_msg.addr = DA9052_EVENTB_REG;
+ ret = da9052->read(da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(da9052);
+ pwron_state = PWRON_FROM_RESUME;
+ return;
+ }
+ da9052_unlock(da9052);
+ if( ssc_msg.data | DA9052_EVENTB_ENONKEY )
+ pwron_state = PWRON_FROM_SUSPEND;
+ else
+ // Waken by other source
+ pwron_state = PWRON_FROM_RESUME;
+ break;
+ case PWRON_FROM_SUSPEND:
+ // Ignoring raising edge
+ pwron_state = PWRON_FROM_RESUME;
+ break;
+ default:
+ pr_err("power_on_evt_handler: Unitialized state\n");
+ }
+}
+#endif
+
static void da9052_onkey_work_func(struct work_struct *work)
{
struct da9052_onkey_data *da9052_onkey =
@@ -37,6 +94,10 @@ static void da9052_onkey_work_func(struct work_struct *work)
input_report_key(da9052_onkey->input, KEY_POWER, value);
input_sync(da9052_onkey->input);
+#ifdef CONFIG_CCXMX5X_PM_POWER_BUTTON
+ da9052_power_button( da9052_onkey->da9052 , value );
+#endif
+
/* if key down, polling for up */
if (value)
schedule_delayed_work(&da9052_onkey->polling_work, HZ/10);
@@ -55,7 +116,8 @@ static void da9052_onkey_report_event(struct da9052_eh_nb *eh_data,
static int __devinit da9052_onkey_probe(struct platform_device *pdev)
{
struct da9052_onkey_data *da9052_onkey;
- int error;
+ int error,ret;
+ struct da9052_ssc_msg msg;
da9052_onkey = kzalloc(sizeof(*da9052_onkey), GFP_KERNEL);
da9052_onkey->input = input_allocate_device();
@@ -97,6 +159,17 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, da9052_onkey);
+ // Unmask IRQ
+ da9052_lock(da9052_onkey->da9052);
+ msg.addr = DA9052_IRQMASKB_REG;
+ ret = da9052_onkey->da9052->read(da9052_onkey->da9052, &msg);
+ if (ret) {
+ da9052_unlock(da9052_onkey->da9052);
+ return 0;
+ }
+ msg.data &= ~DA9052_IRQMASKB_MNONKEY;
+ da9052_onkey->da9052->write(da9052_onkey->da9052, &msg);
+ da9052_unlock(da9052_onkey->da9052);
return 0;
fail3: