From 47f11e0b40e97f373da4efbacee0a9526c816ed5 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Mon, 2 Sep 2019 11:53:01 +0200 Subject: mfd / platform: cros_ec: Move cros-ec core driver out from MFD Now, the ChromeOS EC core driver has nothing related to an MFD device, so move that driver from the MFD subsystem to the platform/chrome subsystem. Signed-off-by: Enric Balletbo i Serra Acked-by: Andy Shevchenko Acked-by: Thierry Reding Acked-by: Mark Brown Acked-by: Wolfram Sang Acked-by: Neil Armstrong Acked-by: Alexandre Belloni Acked-by: Jonathan Cameron Acked-by: Benjamin Tissoires Acked-by: Dmitry Torokhov Acked-by: Sebastian Reichel Acked-by: Chanwoo Choi Reviewed-by: Gwendal Grignou Tested-by: Gwendal Grignou Signed-off-by: Lee Jones --- drivers/extcon/Kconfig | 2 +- drivers/hid/Kconfig | 2 +- drivers/i2c/busses/Kconfig | 2 +- drivers/iio/common/cros_ec_sensors/Kconfig | 2 +- drivers/input/keyboard/Kconfig | 2 +- drivers/media/platform/Kconfig | 3 +- drivers/mfd/Kconfig | 15 +- drivers/mfd/Makefile | 2 - drivers/mfd/cros_ec.c | 280 ----------------------------- drivers/platform/chrome/Kconfig | 21 ++- drivers/platform/chrome/Makefile | 1 + drivers/platform/chrome/cros_ec.c | 280 +++++++++++++++++++++++++++++ drivers/power/supply/Kconfig | 2 +- drivers/pwm/Kconfig | 2 +- drivers/rtc/Kconfig | 2 +- 15 files changed, 309 insertions(+), 309 deletions(-) delete mode 100644 drivers/mfd/cros_ec.c create mode 100644 drivers/platform/chrome/cros_ec.c (limited to 'drivers') diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index fa1804460e8c..aac507bff135 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -181,7 +181,7 @@ config EXTCON_USB_GPIO config EXTCON_USBC_CROS_EC tristate "ChromeOS Embedded Controller EXTCON support" - depends on MFD_CROS_EC + depends on CROS_EC help Say Y here to enable USB Type C cable detection extcon support when using Chrome OS EC based USB Type-C ports. diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 3872e03d9a59..a958b9625bba 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -376,7 +376,7 @@ config HOLTEK_FF config HID_GOOGLE_HAMMER tristate "Google Hammer Keyboard" - depends on USB_HID && LEDS_CLASS && MFD_CROS_EC + depends on USB_HID && LEDS_CLASS && CROS_EC ---help--- Say Y here if you have a Google Hammer device. diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 09367fc014c3..938fe1f2ce31 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1345,7 +1345,7 @@ config I2C_SIBYTE config I2C_CROS_EC_TUNNEL tristate "ChromeOS EC tunnel I2C bus" - depends on MFD_CROS_EC + depends on CROS_EC help If you say yes here you get an I2C bus that will tunnel i2c commands through to the other side of the ChromeOS EC to the i2c bus diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig index bcb58fb76b9f..cdbb29cfb907 100644 --- a/drivers/iio/common/cros_ec_sensors/Kconfig +++ b/drivers/iio/common/cros_ec_sensors/Kconfig @@ -4,7 +4,7 @@ # config IIO_CROS_EC_SENSORS_CORE tristate "ChromeOS EC Sensors Core" - depends on SYSFS && MFD_CROS_EC + depends on SYSFS && CROS_EC select IIO_BUFFER select IIO_TRIGGERED_BUFFER help diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 8e9c3ea9d5e7..861c7a2105a2 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -745,7 +745,7 @@ config KEYBOARD_W90P910 config KEYBOARD_CROS_EC tristate "ChromeOS EC keyboard" select INPUT_MATRIXKMAP - depends on MFD_CROS_EC + depends on CROS_EC help Say Y here to enable the matrix keyboard used by ChromeOS devices and implemented on the ChromeOS EC. You must enable one bus option diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 8a19654b393a..98c3a9a6725e 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -547,10 +547,9 @@ if CEC_PLATFORM_DRIVERS config VIDEO_CROS_EC_CEC tristate "ChromeOS EC CEC driver" - depends on MFD_CROS_EC + depends on CROS_EC select CEC_CORE select CEC_NOTIFIER - select CHROME_PLATFORMS select CROS_EC_PROTO help If you say yes here you will get support for the diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index f129f9678940..d79882b608cf 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -211,21 +211,10 @@ config MFD_AXP20X_RSB components like regulators or the PEK (Power Enable Key) under the corresponding menus. -config MFD_CROS_EC - tristate "ChromeOS Embedded Controller" - select MFD_CORE - select CHROME_PLATFORMS - select CROS_EC_PROTO - depends on X86 || ARM || ARM64 || COMPILE_TEST - help - If you say Y here you get support for the ChromeOS Embedded - Controller (EC) providing keyboard, battery and power services. - You also need to enable the driver for the bus you are using. The - protocol for talking to the EC is defined by the bus driver. - config MFD_CROS_EC_CHARDEV tristate "Chrome OS Embedded Controller userspace device interface" - depends on MFD_CROS_EC + depends on CROS_EC + select MFD_CORE ---help--- This driver adds support to talk with the ChromeOS EC from userspace. diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index f026ada68f6a..59ab5bf51b65 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -13,8 +13,6 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o -cros_ec_core-objs := cros_ec.o -obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o obj-$(CONFIG_MFD_CROS_EC_CHARDEV) += cros_ec_dev.o obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c deleted file mode 100644 index a54ad47c7b02..000000000000 --- a/drivers/mfd/cros_ec.c +++ /dev/null @@ -1,280 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * ChromeOS EC multi-function device - * - * Copyright (C) 2012 Google, Inc - * - * 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 -#include -#include -#include -#include -#include -#include - -#define CROS_EC_DEV_EC_INDEX 0 -#define CROS_EC_DEV_PD_INDEX 1 - -static struct cros_ec_platform ec_p = { - .ec_name = CROS_EC_DEV_NAME, - .cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_EC_INDEX), -}; - -static struct cros_ec_platform pd_p = { - .ec_name = CROS_EC_DEV_PD_NAME, - .cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX), -}; - -static irqreturn_t ec_irq_thread(int irq, void *data) -{ - struct cros_ec_device *ec_dev = data; - bool wake_event = true; - int ret; - - ret = cros_ec_get_next_event(ec_dev, &wake_event); - - /* - * Signal only if wake host events or any interrupt if - * cros_ec_get_next_event() returned an error (default value for - * wake_event is true) - */ - if (wake_event && device_may_wakeup(ec_dev->dev)) - pm_wakeup_event(ec_dev->dev, 0); - - if (ret > 0) - blocking_notifier_call_chain(&ec_dev->event_notifier, - 0, ec_dev); - return IRQ_HANDLED; -} - -static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) -{ - int ret; - struct { - struct cros_ec_command msg; - union { - struct ec_params_host_sleep_event req0; - struct ec_params_host_sleep_event_v1 req1; - struct ec_response_host_sleep_event_v1 resp1; - } u; - } __packed buf; - - memset(&buf, 0, sizeof(buf)); - - if (ec_dev->host_sleep_v1) { - buf.u.req1.sleep_event = sleep_event; - buf.u.req1.suspend_params.sleep_timeout_ms = - EC_HOST_SLEEP_TIMEOUT_DEFAULT; - - buf.msg.outsize = sizeof(buf.u.req1); - if ((sleep_event == HOST_SLEEP_EVENT_S3_RESUME) || - (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) - buf.msg.insize = sizeof(buf.u.resp1); - - buf.msg.version = 1; - - } else { - buf.u.req0.sleep_event = sleep_event; - buf.msg.outsize = sizeof(buf.u.req0); - } - - buf.msg.command = EC_CMD_HOST_SLEEP_EVENT; - - ret = cros_ec_cmd_xfer(ec_dev, &buf.msg); - - /* For now, report failure to transition to S0ix with a warning. */ - if (ret >= 0 && ec_dev->host_sleep_v1 && - (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) { - ec_dev->last_resume_result = - buf.u.resp1.resume_response.sleep_transitions; - - WARN_ONCE(buf.u.resp1.resume_response.sleep_transitions & - EC_HOST_RESUME_SLEEP_TIMEOUT, - "EC detected sleep transition timeout. Total slp_s0 transitions: %d", - buf.u.resp1.resume_response.sleep_transitions & - EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK); - } - - return ret; -} - -int cros_ec_register(struct cros_ec_device *ec_dev) -{ - struct device *dev = ec_dev->dev; - int err = 0; - - BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier); - - ec_dev->max_request = sizeof(struct ec_params_hello); - ec_dev->max_response = sizeof(struct ec_response_get_protocol_info); - ec_dev->max_passthru = 0; - - ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL); - if (!ec_dev->din) - return -ENOMEM; - - ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL); - if (!ec_dev->dout) - return -ENOMEM; - - mutex_init(&ec_dev->lock); - - err = cros_ec_query_all(ec_dev); - if (err) { - dev_err(dev, "Cannot identify the EC: error %d\n", err); - return err; - } - - if (ec_dev->irq) { - err = devm_request_threaded_irq(dev, ec_dev->irq, NULL, - ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "chromeos-ec", ec_dev); - if (err) { - dev_err(dev, "Failed to request IRQ %d: %d", - ec_dev->irq, err); - return err; - } - } - - /* Register a platform device for the main EC instance */ - ec_dev->ec = platform_device_register_data(ec_dev->dev, "cros-ec-dev", - PLATFORM_DEVID_AUTO, &ec_p, - sizeof(struct cros_ec_platform)); - if (IS_ERR(ec_dev->ec)) { - dev_err(ec_dev->dev, - "Failed to create CrOS EC platform device\n"); - return PTR_ERR(ec_dev->ec); - } - - if (ec_dev->max_passthru) { - /* - * Register a platform device for the PD behind the main EC. - * We make the following assumptions: - * - behind an EC, we have a pd - * - only one device added. - * - the EC is responsive at init time (it is not true for a - * sensor hub). - */ - ec_dev->pd = platform_device_register_data(ec_dev->dev, - "cros-ec-dev", - PLATFORM_DEVID_AUTO, &pd_p, - sizeof(struct cros_ec_platform)); - if (IS_ERR(ec_dev->pd)) { - dev_err(ec_dev->dev, - "Failed to create CrOS PD platform device\n"); - platform_device_unregister(ec_dev->ec); - return PTR_ERR(ec_dev->pd); - } - } - - if (IS_ENABLED(CONFIG_OF) && dev->of_node) { - err = devm_of_platform_populate(dev); - if (err) { - platform_device_unregister(ec_dev->pd); - platform_device_unregister(ec_dev->ec); - dev_err(dev, "Failed to register sub-devices\n"); - return err; - } - } - - /* - * Clear sleep event - this will fail harmlessly on platforms that - * don't implement the sleep event host command. - */ - err = cros_ec_sleep_event(ec_dev, 0); - if (err < 0) - dev_dbg(ec_dev->dev, "Error %d clearing sleep event to ec", - err); - - dev_info(dev, "Chrome EC device registered\n"); - - return 0; -} -EXPORT_SYMBOL(cros_ec_register); - -int cros_ec_unregister(struct cros_ec_device *ec_dev) -{ - if (ec_dev->pd) - platform_device_unregister(ec_dev->pd); - platform_device_unregister(ec_dev->ec); - - return 0; -} -EXPORT_SYMBOL(cros_ec_unregister); - -#ifdef CONFIG_PM_SLEEP -int cros_ec_suspend(struct cros_ec_device *ec_dev) -{ - struct device *dev = ec_dev->dev; - int ret; - u8 sleep_event; - - sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ? - HOST_SLEEP_EVENT_S3_SUSPEND : - HOST_SLEEP_EVENT_S0IX_SUSPEND; - - ret = cros_ec_sleep_event(ec_dev, sleep_event); - if (ret < 0) - dev_dbg(ec_dev->dev, "Error %d sending suspend event to ec", - ret); - - if (device_may_wakeup(dev)) - ec_dev->wake_enabled = !enable_irq_wake(ec_dev->irq); - - disable_irq(ec_dev->irq); - ec_dev->was_wake_device = ec_dev->wake_enabled; - ec_dev->suspended = true; - - return 0; -} -EXPORT_SYMBOL(cros_ec_suspend); - -static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev) -{ - while (ec_dev->mkbp_event_supported && - cros_ec_get_next_event(ec_dev, NULL) > 0) - blocking_notifier_call_chain(&ec_dev->event_notifier, - 1, ec_dev); -} - -int cros_ec_resume(struct cros_ec_device *ec_dev) -{ - int ret; - u8 sleep_event; - - ec_dev->suspended = false; - enable_irq(ec_dev->irq); - - sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ? - HOST_SLEEP_EVENT_S3_RESUME : - HOST_SLEEP_EVENT_S0IX_RESUME; - - ret = cros_ec_sleep_event(ec_dev, sleep_event); - if (ret < 0) - dev_dbg(ec_dev->dev, "Error %d sending resume event to ec", - ret); - - if (ec_dev->wake_enabled) { - disable_irq_wake(ec_dev->irq); - ec_dev->wake_enabled = 0; - } - /* - * Let the mfd devices know about events that occur during - * suspend. This way the clients know what to do with them. - */ - cros_ec_report_events_during_suspend(ec_dev); - - - return 0; -} -EXPORT_SYMBOL(cros_ec_resume); - -#endif - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("ChromeOS EC core driver"); diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index 970679d0b6f6..eaeb04e07335 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -50,9 +50,22 @@ config CHROMEOS_TBMC To compile this driver as a module, choose M here: the module will be called chromeos_tbmc. +config CROS_EC + tristate "ChromeOS Embedded Controller" + select CROS_EC_PROTO + depends on X86 || ARM || ARM64 || COMPILE_TEST + help + If you say Y here you get support for the ChromeOS Embedded + Controller (EC) providing keyboard, battery and power services. + You also need to enable the driver for the bus you are using. The + protocol for talking to the EC is defined by the bus driver. + + To compile this driver as a module, choose M here: the + module will be called cros_ec. + config CROS_EC_I2C tristate "ChromeOS Embedded Controller (I2C)" - depends on MFD_CROS_EC && I2C + depends on CROS_EC && I2C help If you say Y here, you get support for talking to the ChromeOS @@ -62,7 +75,7 @@ config CROS_EC_I2C config CROS_EC_RPMSG tristate "ChromeOS Embedded Controller (rpmsg)" - depends on MFD_CROS_EC && RPMSG && OF + depends on CROS_EC && RPMSG && OF help If you say Y here, you get support for talking to the ChromeOS EC through rpmsg. This uses a simple byte-level protocol with a @@ -87,7 +100,7 @@ config CROS_EC_ISHTP config CROS_EC_SPI tristate "ChromeOS Embedded Controller (SPI)" - depends on MFD_CROS_EC && SPI + depends on CROS_EC && SPI ---help--- If you say Y here, you get support for talking to the ChromeOS EC @@ -97,7 +110,7 @@ config CROS_EC_SPI config CROS_EC_LPC tristate "ChromeOS Embedded Controller (LPC)" - depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST) + depends on CROS_EC && ACPI && (X86 || COMPILE_TEST) help If you say Y here, you get support for talking to the ChromeOS EC over an LPC bus, including the LPC Microchip EC (MEC) variant. diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile index fd0af05cc14c..12ff8de5ac7a 100644 --- a/drivers/platform/chrome/Makefile +++ b/drivers/platform/chrome/Makefile @@ -6,6 +6,7 @@ CFLAGS_cros_ec_trace.o:= -I$(src) obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o +obj-$(CONFIG_CROS_EC) += cros_ec.o obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o obj-$(CONFIG_CROS_EC_ISHTP) += cros_ec_ishtp.o obj-$(CONFIG_CROS_EC_RPMSG) += cros_ec_rpmsg.o diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c new file mode 100644 index 000000000000..a54ad47c7b02 --- /dev/null +++ b/drivers/platform/chrome/cros_ec.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ChromeOS EC multi-function device + * + * Copyright (C) 2012 Google, Inc + * + * 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 +#include +#include +#include +#include +#include +#include + +#define CROS_EC_DEV_EC_INDEX 0 +#define CROS_EC_DEV_PD_INDEX 1 + +static struct cros_ec_platform ec_p = { + .ec_name = CROS_EC_DEV_NAME, + .cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_EC_INDEX), +}; + +static struct cros_ec_platform pd_p = { + .ec_name = CROS_EC_DEV_PD_NAME, + .cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX), +}; + +static irqreturn_t ec_irq_thread(int irq, void *data) +{ + struct cros_ec_device *ec_dev = data; + bool wake_event = true; + int ret; + + ret = cros_ec_get_next_event(ec_dev, &wake_event); + + /* + * Signal only if wake host events or any interrupt if + * cros_ec_get_next_event() returned an error (default value for + * wake_event is true) + */ + if (wake_event && device_may_wakeup(ec_dev->dev)) + pm_wakeup_event(ec_dev->dev, 0); + + if (ret > 0) + blocking_notifier_call_chain(&ec_dev->event_notifier, + 0, ec_dev); + return IRQ_HANDLED; +} + +static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) +{ + int ret; + struct { + struct cros_ec_command msg; + union { + struct ec_params_host_sleep_event req0; + struct ec_params_host_sleep_event_v1 req1; + struct ec_response_host_sleep_event_v1 resp1; + } u; + } __packed buf; + + memset(&buf, 0, sizeof(buf)); + + if (ec_dev->host_sleep_v1) { + buf.u.req1.sleep_event = sleep_event; + buf.u.req1.suspend_params.sleep_timeout_ms = + EC_HOST_SLEEP_TIMEOUT_DEFAULT; + + buf.msg.outsize = sizeof(buf.u.req1); + if ((sleep_event == HOST_SLEEP_EVENT_S3_RESUME) || + (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) + buf.msg.insize = sizeof(buf.u.resp1); + + buf.msg.version = 1; + + } else { + buf.u.req0.sleep_event = sleep_event; + buf.msg.outsize = sizeof(buf.u.req0); + } + + buf.msg.command = EC_CMD_HOST_SLEEP_EVENT; + + ret = cros_ec_cmd_xfer(ec_dev, &buf.msg); + + /* For now, report failure to transition to S0ix with a warning. */ + if (ret >= 0 && ec_dev->host_sleep_v1 && + (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) { + ec_dev->last_resume_result = + buf.u.resp1.resume_response.sleep_transitions; + + WARN_ONCE(buf.u.resp1.resume_response.sleep_transitions & + EC_HOST_RESUME_SLEEP_TIMEOUT, + "EC detected sleep transition timeout. Total slp_s0 transitions: %d", + buf.u.resp1.resume_response.sleep_transitions & + EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK); + } + + return ret; +} + +int cros_ec_register(struct cros_ec_device *ec_dev) +{ + struct device *dev = ec_dev->dev; + int err = 0; + + BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier); + + ec_dev->max_request = sizeof(struct ec_params_hello); + ec_dev->max_response = sizeof(struct ec_response_get_protocol_info); + ec_dev->max_passthru = 0; + + ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL); + if (!ec_dev->din) + return -ENOMEM; + + ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL); + if (!ec_dev->dout) + return -ENOMEM; + + mutex_init(&ec_dev->lock); + + err = cros_ec_query_all(ec_dev); + if (err) { + dev_err(dev, "Cannot identify the EC: error %d\n", err); + return err; + } + + if (ec_dev->irq) { + err = devm_request_threaded_irq(dev, ec_dev->irq, NULL, + ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "chromeos-ec", ec_dev); + if (err) { + dev_err(dev, "Failed to request IRQ %d: %d", + ec_dev->irq, err); + return err; + } + } + + /* Register a platform device for the main EC instance */ + ec_dev->ec = platform_device_register_data(ec_dev->dev, "cros-ec-dev", + PLATFORM_DEVID_AUTO, &ec_p, + sizeof(struct cros_ec_platform)); + if (IS_ERR(ec_dev->ec)) { + dev_err(ec_dev->dev, + "Failed to create CrOS EC platform device\n"); + return PTR_ERR(ec_dev->ec); + } + + if (ec_dev->max_passthru) { + /* + * Register a platform device for the PD behind the main EC. + * We make the following assumptions: + * - behind an EC, we have a pd + * - only one device added. + * - the EC is responsive at init time (it is not true for a + * sensor hub). + */ + ec_dev->pd = platform_device_register_data(ec_dev->dev, + "cros-ec-dev", + PLATFORM_DEVID_AUTO, &pd_p, + sizeof(struct cros_ec_platform)); + if (IS_ERR(ec_dev->pd)) { + dev_err(ec_dev->dev, + "Failed to create CrOS PD platform device\n"); + platform_device_unregister(ec_dev->ec); + return PTR_ERR(ec_dev->pd); + } + } + + if (IS_ENABLED(CONFIG_OF) && dev->of_node) { + err = devm_of_platform_populate(dev); + if (err) { + platform_device_unregister(ec_dev->pd); + platform_device_unregister(ec_dev->ec); + dev_err(dev, "Failed to register sub-devices\n"); + return err; + } + } + + /* + * Clear sleep event - this will fail harmlessly on platforms that + * don't implement the sleep event host command. + */ + err = cros_ec_sleep_event(ec_dev, 0); + if (err < 0) + dev_dbg(ec_dev->dev, "Error %d clearing sleep event to ec", + err); + + dev_info(dev, "Chrome EC device registered\n"); + + return 0; +} +EXPORT_SYMBOL(cros_ec_register); + +int cros_ec_unregister(struct cros_ec_device *ec_dev) +{ + if (ec_dev->pd) + platform_device_unregister(ec_dev->pd); + platform_device_unregister(ec_dev->ec); + + return 0; +} +EXPORT_SYMBOL(cros_ec_unregister); + +#ifdef CONFIG_PM_SLEEP +int cros_ec_suspend(struct cros_ec_device *ec_dev) +{ + struct device *dev = ec_dev->dev; + int ret; + u8 sleep_event; + + sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ? + HOST_SLEEP_EVENT_S3_SUSPEND : + HOST_SLEEP_EVENT_S0IX_SUSPEND; + + ret = cros_ec_sleep_event(ec_dev, sleep_event); + if (ret < 0) + dev_dbg(ec_dev->dev, "Error %d sending suspend event to ec", + ret); + + if (device_may_wakeup(dev)) + ec_dev->wake_enabled = !enable_irq_wake(ec_dev->irq); + + disable_irq(ec_dev->irq); + ec_dev->was_wake_device = ec_dev->wake_enabled; + ec_dev->suspended = true; + + return 0; +} +EXPORT_SYMBOL(cros_ec_suspend); + +static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev) +{ + while (ec_dev->mkbp_event_supported && + cros_ec_get_next_event(ec_dev, NULL) > 0) + blocking_notifier_call_chain(&ec_dev->event_notifier, + 1, ec_dev); +} + +int cros_ec_resume(struct cros_ec_device *ec_dev) +{ + int ret; + u8 sleep_event; + + ec_dev->suspended = false; + enable_irq(ec_dev->irq); + + sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ? + HOST_SLEEP_EVENT_S3_RESUME : + HOST_SLEEP_EVENT_S0IX_RESUME; + + ret = cros_ec_sleep_event(ec_dev, sleep_event); + if (ret < 0) + dev_dbg(ec_dev->dev, "Error %d sending resume event to ec", + ret); + + if (ec_dev->wake_enabled) { + disable_irq_wake(ec_dev->irq); + ec_dev->wake_enabled = 0; + } + /* + * Let the mfd devices know about events that occur during + * suspend. This way the clients know what to do with them. + */ + cros_ec_report_events_during_suspend(ec_dev); + + + return 0; +} +EXPORT_SYMBOL(cros_ec_resume); + +#endif + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ChromeOS EC core driver"); diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 5d91b5160b41..5e448b64393d 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -670,7 +670,7 @@ config CHARGER_RT9455 config CHARGER_CROS_USBPD tristate "ChromeOS EC based USBPD charger" - depends on MFD_CROS_EC + depends on CROS_EC default n help Say Y here to enable ChromeOS EC based USBPD charger diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index a7e57516959e..b0e632ba8590 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -145,7 +145,7 @@ config PWM_CRC config PWM_CROS_EC tristate "ChromeOS EC PWM driver" - depends on MFD_CROS_EC + depends on CROS_EC help PWM driver for exposing a PWM attached to the ChromeOS Embedded Controller. diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e72f65b61176..a45175fd8cc4 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1274,7 +1274,7 @@ config RTC_DRV_ZYNQMP config RTC_DRV_CROS_EC tristate "Chrome OS EC RTC driver" - depends on MFD_CROS_EC + depends on CROS_EC help If you say yes here you will get support for the Chrome OS Embedded Controller's RTC. -- cgit v1.2.3-70-g09d2