Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ChromeOS EC multi-function device
0004  *
0005  * Copyright (C) 2012 Google, Inc
0006  *
0007  * The ChromeOS EC multi function device is used to mux all the requests
0008  * to the EC device for its multiple features: keyboard controller,
0009  * battery charging and regulator control, firmware update.
0010  */
0011 
0012 #include <linux/interrupt.h>
0013 #include <linux/module.h>
0014 #include <linux/of_platform.h>
0015 #include <linux/platform_data/cros_ec_commands.h>
0016 #include <linux/platform_data/cros_ec_proto.h>
0017 #include <linux/slab.h>
0018 #include <linux/suspend.h>
0019 
0020 #include "cros_ec.h"
0021 
0022 static struct cros_ec_platform ec_p = {
0023     .ec_name = CROS_EC_DEV_NAME,
0024     .cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_EC_INDEX),
0025 };
0026 
0027 static struct cros_ec_platform pd_p = {
0028     .ec_name = CROS_EC_DEV_PD_NAME,
0029     .cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
0030 };
0031 
0032 /**
0033  * cros_ec_irq_handler() - top half part of the interrupt handler
0034  * @irq: IRQ id
0035  * @data: (ec_dev) Device with events to process.
0036  *
0037  * Return: Wakeup the bottom half
0038  */
0039 static irqreturn_t cros_ec_irq_handler(int irq, void *data)
0040 {
0041     struct cros_ec_device *ec_dev = data;
0042 
0043     ec_dev->last_event_time = cros_ec_get_time_ns();
0044 
0045     return IRQ_WAKE_THREAD;
0046 }
0047 
0048 /**
0049  * cros_ec_handle_event() - process and forward pending events on EC
0050  * @ec_dev: Device with events to process.
0051  *
0052  * Call this function in a loop when the kernel is notified that the EC has
0053  * pending events.
0054  *
0055  * Return: true if more events are still pending and this function should be
0056  * called again.
0057  */
0058 static bool cros_ec_handle_event(struct cros_ec_device *ec_dev)
0059 {
0060     bool wake_event;
0061     bool ec_has_more_events;
0062     int ret;
0063 
0064     ret = cros_ec_get_next_event(ec_dev, &wake_event, &ec_has_more_events);
0065 
0066     /*
0067      * Signal only if wake host events or any interrupt if
0068      * cros_ec_get_next_event() returned an error (default value for
0069      * wake_event is true)
0070      */
0071     if (wake_event && device_may_wakeup(ec_dev->dev))
0072         pm_wakeup_event(ec_dev->dev, 0);
0073 
0074     if (ret > 0)
0075         blocking_notifier_call_chain(&ec_dev->event_notifier,
0076                          0, ec_dev);
0077 
0078     return ec_has_more_events;
0079 }
0080 
0081 /**
0082  * cros_ec_irq_thread() - bottom half part of the interrupt handler
0083  * @irq: IRQ id
0084  * @data: (ec_dev) Device with events to process.
0085  *
0086  * Return: Interrupt handled.
0087  */
0088 irqreturn_t cros_ec_irq_thread(int irq, void *data)
0089 {
0090     struct cros_ec_device *ec_dev = data;
0091     bool ec_has_more_events;
0092 
0093     do {
0094         ec_has_more_events = cros_ec_handle_event(ec_dev);
0095     } while (ec_has_more_events);
0096 
0097     return IRQ_HANDLED;
0098 }
0099 EXPORT_SYMBOL(cros_ec_irq_thread);
0100 
0101 static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event)
0102 {
0103     int ret;
0104     struct {
0105         struct cros_ec_command msg;
0106         union {
0107             struct ec_params_host_sleep_event req0;
0108             struct ec_params_host_sleep_event_v1 req1;
0109             struct ec_response_host_sleep_event_v1 resp1;
0110         } u;
0111     } __packed buf;
0112 
0113     memset(&buf, 0, sizeof(buf));
0114 
0115     if (ec_dev->host_sleep_v1) {
0116         buf.u.req1.sleep_event = sleep_event;
0117         buf.u.req1.suspend_params.sleep_timeout_ms =
0118                 EC_HOST_SLEEP_TIMEOUT_DEFAULT;
0119 
0120         buf.msg.outsize = sizeof(buf.u.req1);
0121         if ((sleep_event == HOST_SLEEP_EVENT_S3_RESUME) ||
0122             (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME))
0123             buf.msg.insize = sizeof(buf.u.resp1);
0124 
0125         buf.msg.version = 1;
0126 
0127     } else {
0128         buf.u.req0.sleep_event = sleep_event;
0129         buf.msg.outsize = sizeof(buf.u.req0);
0130     }
0131 
0132     buf.msg.command = EC_CMD_HOST_SLEEP_EVENT;
0133 
0134     ret = cros_ec_cmd_xfer_status(ec_dev, &buf.msg);
0135     /* Report failure to transition to system wide suspend with a warning. */
0136     if (ret >= 0 && ec_dev->host_sleep_v1 &&
0137         (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME ||
0138          sleep_event == HOST_SLEEP_EVENT_S3_RESUME)) {
0139         ec_dev->last_resume_result =
0140             buf.u.resp1.resume_response.sleep_transitions;
0141 
0142         WARN_ONCE(buf.u.resp1.resume_response.sleep_transitions &
0143               EC_HOST_RESUME_SLEEP_TIMEOUT,
0144               "EC detected sleep transition timeout. Total sleep transitions: %d",
0145               buf.u.resp1.resume_response.sleep_transitions &
0146               EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK);
0147     }
0148 
0149     return ret;
0150 }
0151 
0152 static int cros_ec_ready_event(struct notifier_block *nb,
0153                    unsigned long queued_during_suspend,
0154                    void *_notify)
0155 {
0156     struct cros_ec_device *ec_dev = container_of(nb, struct cros_ec_device,
0157                              notifier_ready);
0158     u32 host_event = cros_ec_get_host_event(ec_dev);
0159 
0160     if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_INTERFACE_READY)) {
0161         mutex_lock(&ec_dev->lock);
0162         cros_ec_query_all(ec_dev);
0163         mutex_unlock(&ec_dev->lock);
0164         return NOTIFY_OK;
0165     }
0166 
0167     return NOTIFY_DONE;
0168 }
0169 
0170 /**
0171  * cros_ec_register() - Register a new ChromeOS EC, using the provided info.
0172  * @ec_dev: Device to register.
0173  *
0174  * Before calling this, allocate a pointer to a new device and then fill
0175  * in all the fields up to the --private-- marker.
0176  *
0177  * Return: 0 on success or negative error code.
0178  */
0179 int cros_ec_register(struct cros_ec_device *ec_dev)
0180 {
0181     struct device *dev = ec_dev->dev;
0182     int err = 0;
0183 
0184     BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
0185 
0186     ec_dev->max_request = sizeof(struct ec_params_hello);
0187     ec_dev->max_response = sizeof(struct ec_response_get_protocol_info);
0188     ec_dev->max_passthru = 0;
0189     ec_dev->ec = NULL;
0190     ec_dev->pd = NULL;
0191 
0192     ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
0193     if (!ec_dev->din)
0194         return -ENOMEM;
0195 
0196     ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL);
0197     if (!ec_dev->dout)
0198         return -ENOMEM;
0199 
0200     mutex_init(&ec_dev->lock);
0201 
0202     err = cros_ec_query_all(ec_dev);
0203     if (err) {
0204         dev_err(dev, "Cannot identify the EC: error %d\n", err);
0205         return err;
0206     }
0207 
0208     if (ec_dev->irq > 0) {
0209         err = devm_request_threaded_irq(dev, ec_dev->irq,
0210                         cros_ec_irq_handler,
0211                         cros_ec_irq_thread,
0212                         IRQF_TRIGGER_LOW | IRQF_ONESHOT,
0213                         "chromeos-ec", ec_dev);
0214         if (err) {
0215             dev_err(dev, "Failed to request IRQ %d: %d\n",
0216                 ec_dev->irq, err);
0217             return err;
0218         }
0219     }
0220 
0221     /* Register a platform device for the main EC instance */
0222     ec_dev->ec = platform_device_register_data(ec_dev->dev, "cros-ec-dev",
0223                     PLATFORM_DEVID_AUTO, &ec_p,
0224                     sizeof(struct cros_ec_platform));
0225     if (IS_ERR(ec_dev->ec)) {
0226         dev_err(ec_dev->dev,
0227             "Failed to create CrOS EC platform device\n");
0228         return PTR_ERR(ec_dev->ec);
0229     }
0230 
0231     if (ec_dev->max_passthru) {
0232         /*
0233          * Register a platform device for the PD behind the main EC.
0234          * We make the following assumptions:
0235          * - behind an EC, we have a pd
0236          * - only one device added.
0237          * - the EC is responsive at init time (it is not true for a
0238          *   sensor hub).
0239          */
0240         ec_dev->pd = platform_device_register_data(ec_dev->dev,
0241                     "cros-ec-dev",
0242                     PLATFORM_DEVID_AUTO, &pd_p,
0243                     sizeof(struct cros_ec_platform));
0244         if (IS_ERR(ec_dev->pd)) {
0245             dev_err(ec_dev->dev,
0246                 "Failed to create CrOS PD platform device\n");
0247             err = PTR_ERR(ec_dev->pd);
0248             goto exit;
0249         }
0250     }
0251 
0252     if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
0253         err = devm_of_platform_populate(dev);
0254         if (err) {
0255             dev_err(dev, "Failed to register sub-devices\n");
0256             goto exit;
0257         }
0258     }
0259 
0260     /*
0261      * Clear sleep event - this will fail harmlessly on platforms that
0262      * don't implement the sleep event host command.
0263      */
0264     err = cros_ec_sleep_event(ec_dev, 0);
0265     if (err < 0)
0266         dev_dbg(ec_dev->dev, "Error %d clearing sleep event to ec\n",
0267             err);
0268 
0269     if (ec_dev->mkbp_event_supported) {
0270         /*
0271          * Register the notifier for EC_HOST_EVENT_INTERFACE_READY
0272          * event.
0273          */
0274         ec_dev->notifier_ready.notifier_call = cros_ec_ready_event;
0275         err = blocking_notifier_chain_register(&ec_dev->event_notifier,
0276                               &ec_dev->notifier_ready);
0277         if (err)
0278             goto exit;
0279     }
0280 
0281     dev_info(dev, "Chrome EC device registered\n");
0282 
0283     /*
0284      * Unlock EC that may be waiting for AP to process MKBP events.
0285      * If the AP takes to long to answer, the EC would stop sending events.
0286      */
0287     if (ec_dev->mkbp_event_supported)
0288         cros_ec_irq_thread(0, ec_dev);
0289 
0290     return 0;
0291 exit:
0292     platform_device_unregister(ec_dev->ec);
0293     platform_device_unregister(ec_dev->pd);
0294     return err;
0295 }
0296 EXPORT_SYMBOL(cros_ec_register);
0297 
0298 /**
0299  * cros_ec_unregister() - Remove a ChromeOS EC.
0300  * @ec_dev: Device to unregister.
0301  *
0302  * Call this to deregister a ChromeOS EC, then clean up any private data.
0303  *
0304  * Return: 0 on success or negative error code.
0305  */
0306 void cros_ec_unregister(struct cros_ec_device *ec_dev)
0307 {
0308     if (ec_dev->pd)
0309         platform_device_unregister(ec_dev->pd);
0310     platform_device_unregister(ec_dev->ec);
0311 }
0312 EXPORT_SYMBOL(cros_ec_unregister);
0313 
0314 #ifdef CONFIG_PM_SLEEP
0315 /**
0316  * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
0317  * @ec_dev: Device to suspend.
0318  *
0319  * This can be called by drivers to handle a suspend event.
0320  *
0321  * Return: 0 on success or negative error code.
0322  */
0323 int cros_ec_suspend(struct cros_ec_device *ec_dev)
0324 {
0325     struct device *dev = ec_dev->dev;
0326     int ret;
0327     u8 sleep_event;
0328 
0329     sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
0330               HOST_SLEEP_EVENT_S3_SUSPEND :
0331               HOST_SLEEP_EVENT_S0IX_SUSPEND;
0332 
0333     ret = cros_ec_sleep_event(ec_dev, sleep_event);
0334     if (ret < 0)
0335         dev_dbg(ec_dev->dev, "Error %d sending suspend event to ec\n",
0336             ret);
0337 
0338     if (device_may_wakeup(dev))
0339         ec_dev->wake_enabled = !enable_irq_wake(ec_dev->irq);
0340     else
0341         ec_dev->wake_enabled = false;
0342 
0343     disable_irq(ec_dev->irq);
0344     ec_dev->suspended = true;
0345 
0346     return 0;
0347 }
0348 EXPORT_SYMBOL(cros_ec_suspend);
0349 
0350 static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev)
0351 {
0352     while (ec_dev->mkbp_event_supported &&
0353            cros_ec_get_next_event(ec_dev, NULL, NULL) > 0)
0354         blocking_notifier_call_chain(&ec_dev->event_notifier,
0355                          1, ec_dev);
0356 }
0357 
0358 /**
0359  * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
0360  * @ec_dev: Device to resume.
0361  *
0362  * This can be called by drivers to handle a resume event.
0363  *
0364  * Return: 0 on success or negative error code.
0365  */
0366 int cros_ec_resume(struct cros_ec_device *ec_dev)
0367 {
0368     int ret;
0369     u8 sleep_event;
0370 
0371     ec_dev->suspended = false;
0372     enable_irq(ec_dev->irq);
0373 
0374     sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
0375               HOST_SLEEP_EVENT_S3_RESUME :
0376               HOST_SLEEP_EVENT_S0IX_RESUME;
0377 
0378     ret = cros_ec_sleep_event(ec_dev, sleep_event);
0379     if (ret < 0)
0380         dev_dbg(ec_dev->dev, "Error %d sending resume event to ec\n",
0381             ret);
0382 
0383     if (ec_dev->wake_enabled)
0384         disable_irq_wake(ec_dev->irq);
0385 
0386     /*
0387      * Let the mfd devices know about events that occur during
0388      * suspend. This way the clients know what to do with them.
0389      */
0390     cros_ec_report_events_during_suspend(ec_dev);
0391 
0392 
0393     return 0;
0394 }
0395 EXPORT_SYMBOL(cros_ec_resume);
0396 
0397 #endif
0398 
0399 MODULE_LICENSE("GPL");
0400 MODULE_DESCRIPTION("ChromeOS EC core driver");