123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- /*
- * 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);
- }
|