// SPDX-License-Identifier: GPL-2.0-only /* * UART interface for ChromeOS Embedded Controller * * Copyright 2020-2022 Google LLC. */ #include <linux/acpi.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_data/cros_ec_proto.h> #include <linux/serdev.h> #include <linux/slab.h> #include <uapi/linux/sched/types.h> #include "cros_ec.h" /* * EC sends contiguous bytes of response packet on UART AP RX. * TTY driver in AP accumulates incoming bytes and calls the registered callback * function. Byte count can range from 1 to MAX bytes supported by EC. * This driver should wait for long time for all callbacks to be processed. * Considering the worst case scenario, wait for 500 msec. This timeout should * account for max latency and some additional guard time. * Best case: Entire packet is received in ~200 ms, wait queue will be released * and packet will be processed. * Worst case: TTY driver sends bytes in multiple callbacks. In this case this * driver will wait for ~1 sec beyond which it will timeout. * This timeout value should not exceed ~500 msec because in case if * EC_CMD_REBOOT_EC sent, high level driver should be able to intercept EC * in RO. */ #define EC_MSG_DEADLINE_MS … /** * struct response_info - Encapsulate EC response related * information for passing between function * cros_ec_uart_pkt_xfer() and cros_ec_uart_rx_bytes() * callback. * @data: Copy the data received from EC here. * @max_size: Max size allocated for the @data buffer. If the * received data exceeds this value, we log an error. * @size: Actual size of data received from EC. This is also * used to accumulate byte count with response is received * in dma chunks. * @exp_len: Expected bytes of response from EC including header. * @status: Re-init to 0 before sending a cmd. Updated to 1 when * a response is successfully received, or an error number * on failure. * @wait_queue: Wait queue EC response where the cros_ec sends request * to EC and waits */ struct response_info { … }; /** * struct cros_ec_uart - information about a uart-connected EC * * @serdev: serdev uart device we are connected to. * @baudrate: UART baudrate of attached EC device. * @flowcontrol: UART flowcontrol of attached device. * @irq: Linux IRQ number of associated serial device. * @response: Response info passing between cros_ec_uart_pkt_xfer() * and cros_ec_uart_rx_bytes() */ struct cros_ec_uart { … }; static size_t cros_ec_uart_rx_bytes(struct serdev_device *serdev, const u8 *data, size_t count) { … } static int cros_ec_uart_pkt_xfer(struct cros_ec_device *ec_dev, struct cros_ec_command *ec_msg) { … } static int cros_ec_uart_resource(struct acpi_resource *ares, void *data) { … } static int cros_ec_uart_acpi_probe(struct cros_ec_uart *ec_uart) { … } static const struct serdev_device_ops cros_ec_uart_client_ops = …; static int cros_ec_uart_probe(struct serdev_device *serdev) { … } static void cros_ec_uart_remove(struct serdev_device *serdev) { struct cros_ec_device *ec_dev = serdev_device_get_drvdata(serdev); cros_ec_unregister(ec_dev); }; static int __maybe_unused cros_ec_uart_suspend(struct device *dev) { … } static int __maybe_unused cros_ec_uart_resume(struct device *dev) { … } static SIMPLE_DEV_PM_OPS(cros_ec_uart_pm_ops, cros_ec_uart_suspend, cros_ec_uart_resume); static const struct of_device_id cros_ec_uart_of_match[] = …; MODULE_DEVICE_TABLE(of, cros_ec_uart_of_match); #ifdef CONFIG_ACPI static const struct acpi_device_id cros_ec_uart_acpi_id[] = …; MODULE_DEVICE_TABLE(acpi, cros_ec_uart_acpi_id); #endif static struct serdev_device_driver cros_ec_uart_driver = …; module_serdev_device_driver(…) …; MODULE_LICENSE(…) …; MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …;