Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  1/*
  2 * ChromeOS EC multi-function device
  3 *
  4 * Copyright (C) 2017 Google, Inc
  5 *
  6 * This software is licensed under the terms of the GNU General Public
  7 * License version 2, as published by the Free Software Foundation, and
  8 * may be copied, distributed, and modified under those terms.
  9 *
 10 * This program is distributed in the hope that it will be useful,
 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 * GNU General Public License for more details.
 14 *
 15 * The ChromeOS EC multi function device is used to mux all the requests
 16 * to the EC device for its multiple features: keyboard controller,
 17 * battery charging and regulator control, firmware update.
 18 */
 19#include <linux/acpi.h>
 20
 21#define ACPI_LID_DEVICE      "LID0"
 22
 23static int ec_wake_gpe = -EINVAL;
 24
 25/*
 26 * This handler indicates to ACPI core that this GPE should stay enabled for
 27 * lid to work in suspend to idle path.
 28 */
 29static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
 30			       void *data)
 31{
 32	return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
 33}
 34
 35/*
 36 * Get ACPI GPE for LID0 device.
 37 */
 38static int cros_ec_get_ec_wake_gpe(struct device *dev)
 39{
 40	struct acpi_device *cros_acpi_dev;
 41	struct acpi_device *adev;
 42	acpi_handle handle;
 43	acpi_status status;
 44	int ret;
 45
 46	cros_acpi_dev = ACPI_COMPANION(dev);
 47
 48	if (!cros_acpi_dev || !cros_acpi_dev->parent ||
 49	   !cros_acpi_dev->parent->handle)
 50		return -EINVAL;
 51
 52	status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
 53				 &handle);
 54	if (ACPI_FAILURE(status))
 55		return -EINVAL;
 56
 57	ret = acpi_bus_get_device(handle, &adev);
 58	if (ret)
 59		return ret;
 60
 61	return adev->wakeup.gpe_number;
 62}
 63
 64int cros_ec_acpi_install_gpe_handler(struct device *dev)
 65{
 66	acpi_status status;
 67
 68	ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
 69
 70	if (ec_wake_gpe < 0)
 71		return ec_wake_gpe;
 72
 73	status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
 74					  ACPI_GPE_EDGE_TRIGGERED,
 75					  &cros_ec_gpe_handler, NULL);
 76	if (ACPI_FAILURE(status))
 77		return -ENODEV;
 78
 79	dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
 80
 81	return 0;
 82}
 83
 84void cros_ec_acpi_remove_gpe_handler(void)
 85{
 86	acpi_status status;
 87
 88	if (ec_wake_gpe < 0)
 89		return;
 90
 91	status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
 92						 &cros_ec_gpe_handler);
 93	if (ACPI_FAILURE(status))
 94		pr_err("failed to remove gpe handler\n");
 95}
 96
 97void cros_ec_acpi_clear_gpe(void)
 98{
 99	if (ec_wake_gpe < 0)
100		return;
101
102	acpi_clear_gpe(NULL, ec_wake_gpe);
103}