/* 88PM80x gives us an interrupt when ONKEY is held */ static irqreturn_t pm80x_onkey_handler(int irq, void *data) { struct pm80x_onkey_info *info = data; int ret = 0; unsigned int val; ret = regmap_read(info->map, PM800_STATUS_1, &val); if (ret < 0) { dev_err(info->idev->dev.parent, "failed to read status: %d\n", ret); return IRQ_NONE; } val &= PM800_ONKEY_STS1; /* * HW workaround: There is bug of LONG_ONKEY_EVENT will be detected wrongly, * then it will trigger power down/power up cycle unexpectedly. * Sw will reset the LONG_ONKEY timer to avoid this kind of issue. */ regmap_update_bits(info->map, PM800_WAKEUP1, PM800_LONGKEY_RESET, PM800_LONGKEY_RESET); #ifdef CONFIG_FAKE_SYSTEMOFF if (fake_sysoff_block_onkey()) goto out; if (fake_sysoff_status_query()) { if (val) { /*down key*/ if (!atomic_cmpxchg(&longpress_work_state, 0, 1)) { schedule_delayed_work(&presscheck_work, LONGPRESS_INTERVAL); /* Think about following case: onkey down/up-> * kernel will awake 5s ->after 4s-> * user long down on key -> after 1s, suspend * -> have no chance for 3s timeout*/ __pm_wakeup_event(&suspend_longkey_lock, jiffies_to_msecs(LONGPRESS_INTERVAL + HZ)); } } else { /*up key*/ if (atomic_cmpxchg(&longpress_work_state, 1, 0)) { /* short press */ cancel_delayed_work_sync(&presscheck_work); } } } else { #endif #if defined(CONFIG_KERNEL_DEBUG_SEC) && (defined(CONFIG_MACH_LT02) || defined(CONFIG_MACH_COCOA7)) key_dbg("%s state = %d\n", __func__, val); gpio_keys_setstate(KEY_POWER, val ? true : false); if (val && gpio_keys_getstate(KEY_VOLUMEUP) && jack_is_detected) gpio_keys_start_upload_modtimer(); #endif input_report_key(info->idev, KEY_POWER, val); input_sync(info->idev); #ifdef CONFIG_FAKE_SYSTEMOFF } out: #endif is_power_key_pressed = val; // AT+KEYSHORT cmd return IRQ_HANDLED; }
/* 88PM822 gives us an interrupt when ONKEY is held */ static irqreturn_t pm822_onkey_handler(int irq, void *data) { struct pm822_onkey_info *info = data; int ret = 0; unsigned int val; ret = regmap_read(info->map, PM822_STATUS1, &val); if (ret < 0) { dev_err(info->idev->dev.parent, "failed to read status: %d\n", ret); return IRQ_NONE; } val &= PM822_ONKEY_STS1; #ifdef CONFIG_FAKE_SYSTEMOFF if (fake_sysoff_block_onkey()) goto out; if (fake_sysoff_status_query()) { if (val) { /*down key*/ if (!atomic_cmpxchg(&longpress_work_state, 0, 1)) { schedule_delayed_work(&presscheck_work, LONGPRESS_INTERVAL); /* Think about following case: onkey down/up-> * kernel will awake 5s ->after 4s-> * user long down on key -> after 1s, suspend * -> have no chance for 3s timeout*/ __pm_wakeup_event(&suspend_longkey_lock, jiffies_to_msecs(LONGPRESS_INTERVAL + HZ)); } } else { /*up key*/ if (atomic_cmpxchg(&longpress_work_state, 1, 0)) { /* short press */ cancel_delayed_work_sync(&presscheck_work); } } } else { #endif #if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP) printk("power key val =%d\n",val); #endif input_report_key(info->idev, KEY_POWER, val); input_sync(info->idev); #ifdef CONFIG_FAKE_SYSTEMOFF } out: #endif is_power_key_pressed = val; // AT+KEYSHORT cmd return IRQ_HANDLED; }