// SPDX-License-Identifier: GPL-2.0 // SPI interface for ChromeOS Embedded Controller // // Copyright (C) 2012 Google, Inc #include <linux/delay.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_data/cros_ec_commands.h> #include <linux/platform_data/cros_ec_proto.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/spi/spi.h> #include <uapi/linux/sched/types.h> #include "cros_ec.h" /* The header byte, which follows the preamble */ #define EC_MSG_HEADER … /* * Number of EC preamble bytes we read at a time. Since it takes * about 400-500us for the EC to respond there is not a lot of * point in tuning this. If the EC could respond faster then * we could increase this so that might expect the preamble and * message to occur in a single transaction. However, the maximum * SPI transfer size is 256 bytes, so at 5MHz we need a response * time of perhaps <320us (200 bytes / 1600 bits). */ #define EC_MSG_PREAMBLE_COUNT … /* * Allow for a long time for the EC to respond. We support i2c * tunneling and support fairly long messages for the tunnel (249 * bytes long at the moment). If we're talking to a 100 kHz device * on the other end and need to transfer ~256 bytes, then we need: * 10 us/bit * ~10 bits/byte * ~256 bytes = ~25ms * * We'll wait 8 times that to handle clock stretching and other * paranoia. Note that some battery gas gauge ICs claim to have a * clock stretch of 144ms in rare situations. That's incentive for * not directly passing i2c through, but it's too late for that for * existing hardware. * * It's pretty unlikely that we'll really see a 249 byte tunnel in * anything other than testing. If this was more common we might * consider having slow commands like this require a GET_STATUS * wait loop. The 'flash write' command would be another candidate * for this, clocking in at 2-3ms. */ #define EC_MSG_DEADLINE_MS … /* * Time between raising the SPI chip select (for the end of a * transaction) and dropping it again (for the next transaction). * If we go too fast, the EC will miss the transaction. We know that we * need at least 70 us with the 16 MHz STM32 EC, so go with 200 us to be * safe. */ #define EC_SPI_RECOVERY_TIME_NS … /** * struct cros_ec_spi - information about a SPI-connected EC * * @spi: SPI device we are connected to * @last_transfer_ns: time that we last finished a transfer. * @start_of_msg_delay: used to set the delay_usecs on the spi_transfer that * is sent when we want to turn on CS at the start of a transaction. * @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that * is sent when we want to turn off CS at the end of a transaction. * @high_pri_worker: Used to schedule high priority work. */ struct cros_ec_spi { … }; cros_ec_xfer_fn_t; /** * struct cros_ec_xfer_work_params - params for our high priority workers * * @work: The work_struct needed to queue work * @fn: The function to use to transfer * @ec_dev: ChromeOS EC device * @ec_msg: Message to transfer * @ret: The return value of the function */ struct cros_ec_xfer_work_params { … }; static void debug_packet(struct device *dev, const char *name, u8 *ptr, int len) { … } static int terminate_request(struct cros_ec_device *ec_dev) { … } /** * receive_n_bytes - receive n bytes from the EC. * * Assumes buf is a pointer into the ec_dev->din buffer * * @ec_dev: ChromeOS EC device. * @buf: Pointer to the buffer receiving the data. * @n: Number of bytes received. */ static int receive_n_bytes(struct cros_ec_device *ec_dev, u8 *buf, int n) { … } /** * cros_ec_spi_receive_packet - Receive a packet from the EC. * * This function has two phases: reading the preamble bytes (since if we read * data from the EC before it is ready to send, we just get preamble) and * reading the actual message. * * The received data is placed into ec_dev->din. * * @ec_dev: ChromeOS EC device * @need_len: Number of message bytes we need to read */ static int cros_ec_spi_receive_packet(struct cros_ec_device *ec_dev, int need_len) { … } /** * cros_ec_spi_receive_response - Receive a response from the EC. * * This function has two phases: reading the preamble bytes (since if we read * data from the EC before it is ready to send, we just get preamble) and * reading the actual message. * * The received data is placed into ec_dev->din. * * @ec_dev: ChromeOS EC device * @need_len: Number of message bytes we need to read */ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev, int need_len) { … } /** * do_cros_ec_pkt_xfer_spi - Transfer a packet over SPI and receive the reply * * @ec_dev: ChromeOS EC device * @ec_msg: Message to transfer */ static int do_cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, struct cros_ec_command *ec_msg) { … } /** * do_cros_ec_cmd_xfer_spi - Transfer a message over SPI and receive the reply * * @ec_dev: ChromeOS EC device * @ec_msg: Message to transfer */ static int do_cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, struct cros_ec_command *ec_msg) { … } static void cros_ec_xfer_high_pri_work(struct kthread_work *work) { … } static int cros_ec_xfer_high_pri(struct cros_ec_device *ec_dev, struct cros_ec_command *ec_msg, cros_ec_xfer_fn_t fn) { … } static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, struct cros_ec_command *ec_msg) { … } static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, struct cros_ec_command *ec_msg) { … } static void cros_ec_spi_dt_probe(struct cros_ec_spi *ec_spi, struct device *dev) { … } static void cros_ec_spi_high_pri_release(void *worker) { … } static int cros_ec_spi_devm_high_pri_alloc(struct device *dev, struct cros_ec_spi *ec_spi) { … } static int cros_ec_spi_probe(struct spi_device *spi) { … } static void cros_ec_spi_remove(struct spi_device *spi) { … } #ifdef CONFIG_PM_SLEEP static int cros_ec_spi_suspend(struct device *dev) { … } static int cros_ec_spi_resume(struct device *dev) { … } #endif static SIMPLE_DEV_PM_OPS(cros_ec_spi_pm_ops, cros_ec_spi_suspend, cros_ec_spi_resume); static const struct of_device_id cros_ec_spi_of_match[] = …; MODULE_DEVICE_TABLE(of, cros_ec_spi_of_match); static const struct spi_device_id cros_ec_spi_id[] = …; MODULE_DEVICE_TABLE(spi, cros_ec_spi_id); static struct spi_driver cros_ec_driver_spi = …; module_spi_driver(…) …; MODULE_LICENSE(…) …; MODULE_DESCRIPTION(…) …;