If IRQs are left on, one will fire before the rest of the system is up
enough to process it if there has been a pending keypress. So we need to
disable interrupts across suspend/resume.
Also, enable wake source, and register the pm event.
BUG=chrome-os-partner:11625
TEST=powerd_suspend + wake from keyboard
Change-Id: I9996f766ffd1c49f7e45ba8f76f273884151d593
Signed-off-by: Olof Johansson <olofj@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/28127
Reviewed-by: Benson Leung <bleung@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
#define COMMAND_MAX_TRIES 3
#define COMMAND_MAX_TRIES 3
+static inline struct chromeos_ec_device *to_ec_dev(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return i2c_get_clientdata(client);
+}
+
static int cros_ec_command_xfer_noretry(struct chromeos_ec_device *ec_dev,
struct chromeos_ec_msg *msg)
{
static int cros_ec_command_xfer_noretry(struct chromeos_ec_device *ec_dev,
struct chromeos_ec_msg *msg)
{
if (ret >= 0)
return ret;
}
if (ret >= 0)
return ret;
}
- dev_err(ec_dev->dev, "mkbp_command failed with %d (%d tries)\n",
+ dev_err(ec_dev->dev, "ec_command failed with %d (%d tries)\n",
ret, tries);
return ret;
}
ret, tries);
return ret;
}
{
struct chromeos_ec_device *ec = data;
{
struct chromeos_ec_device *ec = data;
+ if (device_may_wakeup(ec->dev))
+ pm_wakeup_event(ec->dev, 0);
+
blocking_notifier_call_chain(&ec->event_notifier, 1, ec);
return IRQ_HANDLED;
blocking_notifier_call_chain(&ec->event_notifier, 1, ec);
return IRQ_HANDLED;
#ifdef CONFIG_PM_SLEEP
static int cros_ec_suspend(struct device *dev)
{
#ifdef CONFIG_PM_SLEEP
static int cros_ec_suspend(struct device *dev)
{
+ struct chromeos_ec_device *ec = to_ec_dev(dev);
+
+ if (device_may_wakeup(dev))
+ ec->wake_enabled = !enable_irq_wake(ec->irq);
+
+ disable_irq(ec->irq);
+
return 0;
}
static int cros_ec_resume(struct device *dev)
{
return 0;
}
static int cros_ec_resume(struct device *dev)
{
+ struct chromeos_ec_device *ec = to_ec_dev(dev);
+
+ enable_irq(ec->irq);
+
+ if (ec->wake_enabled) {
+ disable_irq_wake(ec->irq);
+ ec->wake_enabled = 0;
+ }
+
struct device *dev;
struct i2c_client *client;
int irq;
struct device *dev;
struct i2c_client *client;
int irq;
struct blocking_notifier_head event_notifier;
int (*command_send)(struct chromeos_ec_device *ec,
char cmd, void *out_buf, int out_len);
struct blocking_notifier_head event_notifier;
int (*command_send)(struct chromeos_ec_device *ec,
char cmd, void *out_buf, int out_len);