All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] mfd: cros_ec: Add ACPI GPE handler for LID0 devices
@ 2017-02-01 16:22 Thierry Escande
  2017-02-08 11:10 ` Lee Jones
  0 siblings, 1 reply; 2+ messages in thread
From: Thierry Escande @ 2017-02-01 16:22 UTC (permalink / raw)
  To: Lee Jones; +Cc: linux-kernel

From: Archana Patni <archana.patni@intel.com>

This patch installs an ACPI GPE handler for LID0 ACPI device to indicate
ACPI core that this GPE should stay enabled for lid to work in suspend
to idle path.

Signed-off-by: Archana Patni <archana.patni@intel.com>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
---

This patch depends on https://lkml.org/lkml/2017/1/13/446

v2:
- Sent as a separate patch as the other patches from the v1 patchset
  have already been merged.
- Moved ACPI specific APIs in a specific file so it's compiled only if
  CONFIG_ACPI is enabled.

 drivers/mfd/Makefile           |   4 +-
 drivers/mfd/cros_ec.c          |  15 ++++--
 drivers/mfd/cros_ec_acpi_gpe.c | 103 +++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/cros_ec.h    |  18 +++++++
 4 files changed, 136 insertions(+), 4 deletions(-)
 create mode 100644 drivers/mfd/cros_ec_acpi_gpe.c

diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index dda4d4f..7f48c00 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -10,7 +10,9 @@ obj-$(CONFIG_MFD_ACT8945A)	+= act8945a.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
 obj-$(CONFIG_MFD_BCM590XX)	+= bcm590xx.o
-obj-$(CONFIG_MFD_CROS_EC)	+= cros_ec.o
+cros_ec_core-objs		:= cros_ec.o
+cros_ec_core-$(CONFIG_ACPI)	+= cros_ec_acpi_gpe.o
+obj-$(CONFIG_MFD_CROS_EC)	+= cros_ec_core.o
 obj-$(CONFIG_MFD_CROS_EC_I2C)	+= cros_ec_i2c.o
 obj-$(CONFIG_MFD_CROS_EC_SPI)	+= cros_ec_spi.o
 obj-$(CONFIG_MFD_EXYNOS_LPASS)	+= exynos-lpass.o
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 9b66a98..d4a407e 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -166,6 +166,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 
 	dev_info(dev, "Chrome EC device registered\n");
 
+	cros_ec_acpi_install_gpe_handler(dev);
+
 	return 0;
 
 fail_mfd:
@@ -179,6 +181,8 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
 {
 	mfd_remove_devices(ec_dev->dev);
 
+	cros_ec_acpi_remove_gpe_handler();
+
 	return 0;
 }
 EXPORT_SYMBOL(cros_ec_remove);
@@ -190,9 +194,14 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
 	int ret;
 	u8 sleep_event;
 
-	sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
-		      HOST_SLEEP_EVENT_S3_RESUME :
-		      HOST_SLEEP_EVENT_S0IX_RESUME;
+	if (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) {
+		sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND;
+	} else {
+		sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND;
+
+		/* Clearing the GPE status for any pending event */
+		cros_ec_acpi_clear_gpe();
+	}
 
 	ret = cros_ec_sleep_event(ec_dev, sleep_event);
 	if (ret < 0)
diff --git a/drivers/mfd/cros_ec_acpi_gpe.c b/drivers/mfd/cros_ec_acpi_gpe.c
new file mode 100644
index 0000000..56d305d
--- /dev/null
+++ b/drivers/mfd/cros_ec_acpi_gpe.c
@@ -0,0 +1,103 @@
+/*
+ * ChromeOS EC multi-function device
+ *
+ * Copyright (C) 2017 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * The ChromeOS EC multi function device is used to mux all the requests
+ * to the EC device for its multiple features: keyboard controller,
+ * battery charging and regulator control, firmware update.
+ */
+#include <linux/acpi.h>
+
+#define ACPI_LID_DEVICE      "LID0"
+
+static int ec_wake_gpe = -EINVAL;
+
+/*
+ * This handler indicates to ACPI core that this GPE should stay enabled for
+ * lid to work in suspend to idle path.
+ */
+static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
+			       void *data)
+{
+	return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
+}
+
+/*
+ * Get ACPI GPE for LID0 device.
+ */
+static int cros_ec_get_ec_wake_gpe(struct device *dev)
+{
+	struct acpi_device *cros_acpi_dev;
+	struct acpi_device *adev;
+	acpi_handle handle;
+	acpi_status status;
+	int ret;
+
+	cros_acpi_dev = ACPI_COMPANION(dev);
+
+	if (!cros_acpi_dev || !cros_acpi_dev->parent ||
+	   !cros_acpi_dev->parent->handle)
+		return -EINVAL;
+
+	status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
+				 &handle);
+	if (ACPI_FAILURE(status))
+		return -EINVAL;
+
+	ret = acpi_bus_get_device(handle, &adev);
+	if (ret)
+		return ret;
+
+	return adev->wakeup.gpe_number;
+}
+
+int cros_ec_acpi_install_gpe_handler(struct device *dev)
+{
+	acpi_status status;
+
+	ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
+
+	if (ec_wake_gpe < 0)
+		return ec_wake_gpe;
+
+	status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
+					  ACPI_GPE_EDGE_TRIGGERED,
+					  &cros_ec_gpe_handler, NULL);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
+
+	return 0;
+}
+
+void cros_ec_acpi_remove_gpe_handler(void)
+{
+	acpi_status status;
+
+	if (ec_wake_gpe < 0)
+		return;
+
+	status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
+						 &cros_ec_gpe_handler);
+	if (ACPI_FAILURE(status))
+		pr_err("failed to remove gpe handler\n");
+}
+
+void cros_ec_acpi_clear_gpe(void)
+{
+	if (ec_wake_gpe < 0)
+		return;
+
+	acpi_clear_gpe(NULL, ec_wake_gpe);
+}
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 7a01c94..b3d04de 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -304,4 +304,22 @@ extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
 extern struct attribute_group cros_ec_vbc_attr_group;
 
+/* ACPI GPE handler */
+#ifdef CONFIG_ACPI
+
+int cros_ec_acpi_install_gpe_handler(struct device *dev);
+void cros_ec_acpi_remove_gpe_handler(void);
+void cros_ec_acpi_clear_gpe(void);
+
+#else /* CONFIG_ACPI */
+
+static inline int cros_ec_acpi_install_gpe_handler(struct device *dev)
+{
+	return -ENODEV;
+}
+static inline void cros_ec_acpi_remove_gpe_handler(void) {}
+static inline void cros_ec_acpi_clear_gpe(void) {}
+
+#endif /* CONFIG_ACPI */
+
 #endif /* __LINUX_MFD_CROS_EC_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] mfd: cros_ec: Add ACPI GPE handler for LID0 devices
  2017-02-01 16:22 [PATCH v2] mfd: cros_ec: Add ACPI GPE handler for LID0 devices Thierry Escande
@ 2017-02-08 11:10 ` Lee Jones
  0 siblings, 0 replies; 2+ messages in thread
From: Lee Jones @ 2017-02-08 11:10 UTC (permalink / raw)
  To: Thierry Escande; +Cc: linux-kernel

On Wed, 01 Feb 2017, Thierry Escande wrote:

> From: Archana Patni <archana.patni@intel.com>
> 
> This patch installs an ACPI GPE handler for LID0 ACPI device to indicate
> ACPI core that this GPE should stay enabled for lid to work in suspend
> to idle path.
> 
> Signed-off-by: Archana Patni <archana.patni@intel.com>
> Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
> ---
> 
> This patch depends on https://lkml.org/lkml/2017/1/13/446
> 
> v2:
> - Sent as a separate patch as the other patches from the v1 patchset
>   have already been merged.
> - Moved ACPI specific APIs in a specific file so it's compiled only if
>   CONFIG_ACPI is enabled.
> 
>  drivers/mfd/Makefile           |   4 +-
>  drivers/mfd/cros_ec.c          |  15 ++++--
>  drivers/mfd/cros_ec_acpi_gpe.c | 103 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/cros_ec.h    |  18 +++++++
>  4 files changed, 136 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/mfd/cros_ec_acpi_gpe.c

Applied, thanks.

> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index dda4d4f..7f48c00 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -10,7 +10,9 @@ obj-$(CONFIG_MFD_ACT8945A)	+= act8945a.o
>  obj-$(CONFIG_MFD_SM501)		+= sm501.o
>  obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
>  obj-$(CONFIG_MFD_BCM590XX)	+= bcm590xx.o
> -obj-$(CONFIG_MFD_CROS_EC)	+= cros_ec.o
> +cros_ec_core-objs		:= cros_ec.o
> +cros_ec_core-$(CONFIG_ACPI)	+= cros_ec_acpi_gpe.o
> +obj-$(CONFIG_MFD_CROS_EC)	+= cros_ec_core.o
>  obj-$(CONFIG_MFD_CROS_EC_I2C)	+= cros_ec_i2c.o
>  obj-$(CONFIG_MFD_CROS_EC_SPI)	+= cros_ec_spi.o
>  obj-$(CONFIG_MFD_EXYNOS_LPASS)	+= exynos-lpass.o
> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
> index 9b66a98..d4a407e 100644
> --- a/drivers/mfd/cros_ec.c
> +++ b/drivers/mfd/cros_ec.c
> @@ -166,6 +166,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
>  
>  	dev_info(dev, "Chrome EC device registered\n");
>  
> +	cros_ec_acpi_install_gpe_handler(dev);
> +
>  	return 0;
>  
>  fail_mfd:
> @@ -179,6 +181,8 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
>  {
>  	mfd_remove_devices(ec_dev->dev);
>  
> +	cros_ec_acpi_remove_gpe_handler();
> +
>  	return 0;
>  }
>  EXPORT_SYMBOL(cros_ec_remove);
> @@ -190,9 +194,14 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
>  	int ret;
>  	u8 sleep_event;
>  
> -	sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
> -		      HOST_SLEEP_EVENT_S3_RESUME :
> -		      HOST_SLEEP_EVENT_S0IX_RESUME;
> +	if (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) {
> +		sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND;
> +	} else {
> +		sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND;
> +
> +		/* Clearing the GPE status for any pending event */
> +		cros_ec_acpi_clear_gpe();
> +	}
>  
>  	ret = cros_ec_sleep_event(ec_dev, sleep_event);
>  	if (ret < 0)
> diff --git a/drivers/mfd/cros_ec_acpi_gpe.c b/drivers/mfd/cros_ec_acpi_gpe.c
> new file mode 100644
> index 0000000..56d305d
> --- /dev/null
> +++ b/drivers/mfd/cros_ec_acpi_gpe.c
> @@ -0,0 +1,103 @@
> +/*
> + * ChromeOS EC multi-function device
> + *
> + * Copyright (C) 2017 Google, Inc
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * The ChromeOS EC multi function device is used to mux all the requests
> + * to the EC device for its multiple features: keyboard controller,
> + * battery charging and regulator control, firmware update.
> + */
> +#include <linux/acpi.h>
> +
> +#define ACPI_LID_DEVICE      "LID0"
> +
> +static int ec_wake_gpe = -EINVAL;
> +
> +/*
> + * This handler indicates to ACPI core that this GPE should stay enabled for
> + * lid to work in suspend to idle path.
> + */
> +static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
> +			       void *data)
> +{
> +	return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
> +}
> +
> +/*
> + * Get ACPI GPE for LID0 device.
> + */
> +static int cros_ec_get_ec_wake_gpe(struct device *dev)
> +{
> +	struct acpi_device *cros_acpi_dev;
> +	struct acpi_device *adev;
> +	acpi_handle handle;
> +	acpi_status status;
> +	int ret;
> +
> +	cros_acpi_dev = ACPI_COMPANION(dev);
> +
> +	if (!cros_acpi_dev || !cros_acpi_dev->parent ||
> +	   !cros_acpi_dev->parent->handle)
> +		return -EINVAL;
> +
> +	status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
> +				 &handle);
> +	if (ACPI_FAILURE(status))
> +		return -EINVAL;
> +
> +	ret = acpi_bus_get_device(handle, &adev);
> +	if (ret)
> +		return ret;
> +
> +	return adev->wakeup.gpe_number;
> +}
> +
> +int cros_ec_acpi_install_gpe_handler(struct device *dev)
> +{
> +	acpi_status status;
> +
> +	ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
> +
> +	if (ec_wake_gpe < 0)
> +		return ec_wake_gpe;
> +
> +	status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
> +					  ACPI_GPE_EDGE_TRIGGERED,
> +					  &cros_ec_gpe_handler, NULL);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
> +
> +	return 0;
> +}
> +
> +void cros_ec_acpi_remove_gpe_handler(void)
> +{
> +	acpi_status status;
> +
> +	if (ec_wake_gpe < 0)
> +		return;
> +
> +	status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
> +						 &cros_ec_gpe_handler);
> +	if (ACPI_FAILURE(status))
> +		pr_err("failed to remove gpe handler\n");
> +}
> +
> +void cros_ec_acpi_clear_gpe(void)
> +{
> +	if (ec_wake_gpe < 0)
> +		return;
> +
> +	acpi_clear_gpe(NULL, ec_wake_gpe);
> +}
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index 7a01c94..b3d04de 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -304,4 +304,22 @@ extern struct attribute_group cros_ec_attr_group;
>  extern struct attribute_group cros_ec_lightbar_attr_group;
>  extern struct attribute_group cros_ec_vbc_attr_group;
>  
> +/* ACPI GPE handler */
> +#ifdef CONFIG_ACPI
> +
> +int cros_ec_acpi_install_gpe_handler(struct device *dev);
> +void cros_ec_acpi_remove_gpe_handler(void);
> +void cros_ec_acpi_clear_gpe(void);
> +
> +#else /* CONFIG_ACPI */
> +
> +static inline int cros_ec_acpi_install_gpe_handler(struct device *dev)
> +{
> +	return -ENODEV;
> +}
> +static inline void cros_ec_acpi_remove_gpe_handler(void) {}
> +static inline void cros_ec_acpi_clear_gpe(void) {}
> +
> +#endif /* CONFIG_ACPI */
> +
>  #endif /* __LINUX_MFD_CROS_EC_H */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-02-08 11:13 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-01 16:22 [PATCH v2] mfd: cros_ec: Add ACPI GPE handler for LID0 devices Thierry Escande
2017-02-08 11:10 ` Lee Jones

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.