/* SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef _REALTEK_PSE_MCU_H #define _REALTEK_PSE_MCU_H #include #include #include /* * Time the MCU itself needs between accepting a request and having a * response ready. These are properties of the MCU firmware, not of the * underlying transport: the core paces transactions by RTPSE_MCU_RESPONSE_MS * and both transports size their per-transaction recv ceiling from * RTPSE_MCU_RESPONSE_MAX_MS, since some commands are documented as * needing up to ~1s to produce a reply. */ #define RTPSE_MCU_RESPONSE_MS 25 #define RTPSE_MCU_RESPONSE_MAX_MS 1000 /* * Total time to keep retrying the first MCU read at probe, and the pause * between attempts. Right after reset-gpios is deasserted the MCU may not * answer on the bus yet; give it a bounded window to come up before * declaring the probe failed. */ #define RTPSE_MCU_BOOT_TIMEOUT_MS 3000 #define RTPSE_MCU_BOOT_RETRY_MS 100 #define RTPSE_MCU_MSG_SIZE 12 struct rtpse_mcu_msg { u8 opcode; u8 seq_num; u8 payload[9]; u8 checksum; } __packed; /* * MCU status opcodes (seen on the Gen1 dialect; Gen2 never emits them). * INCOMPLETE/BAD_CSUM are terminal; NOT_READY is transient. */ #define RTPSE_MCU_OPCODE_INCOMPLETE 0xfd /* -EBADE */ #define RTPSE_MCU_OPCODE_BAD_CSUM 0xfe /* -EBADMSG */ #define RTPSE_MCU_OPCODE_NOT_READY 0xff /* -EAGAIN */ /* * A polling transport can stop here: the reply to this request (opcode and * seq_num) or a terminal error. The seq_num rejects a stale normal reply; the * terminal errors match unconditionally, as a request the MCU couldn't parse * carries no seq_num to correlate against. */ static inline bool rtpse_mcu_resp_is_final(const struct rtpse_mcu_msg *req, const struct rtpse_mcu_msg *resp) { return (resp->opcode == req->opcode && resp->seq_num == req->seq_num) || resp->opcode == RTPSE_MCU_OPCODE_INCOMPLETE || resp->opcode == RTPSE_MCU_OPCODE_BAD_CSUM; } /* Opaque to transports; defined in realtek-pse-mcu-core.c. */ struct rtpse_mcu_dialect; struct rtpse_mcu_chip_info; struct rtpse_mcu_ctrl; /* Per-compatible match data (the of_match .data). */ struct rtpse_mcu_match_data { const struct rtpse_mcu_dialect *dialect; bool native_i2c; /* raw-I2C framing (vs SMBus); I2C transport only */ }; struct rtpse_mcu_transport_ops { int (*send)(struct rtpse_mcu_ctrl *pse, const struct rtpse_mcu_msg *req); int (*recv)(struct rtpse_mcu_ctrl *pse, const struct rtpse_mcu_msg *req, struct rtpse_mcu_msg *resp); }; struct rtpse_mcu_ctrl { struct device *dev; struct pse_controller_dev pcdev; struct mutex mutex; /* serializes MCU request/response transactions */ const struct rtpse_mcu_dialect *dialect; const struct rtpse_mcu_chip_info *chip; const struct rtpse_mcu_transport_ops *transport; u8 seq; /* rolling request seq_num, echoed by the MCU */ }; int rtpse_mcu_register(struct rtpse_mcu_ctrl *pse); extern const struct rtpse_mcu_match_data rtpse_mcu_gen1_data; extern const struct rtpse_mcu_match_data rtpse_mcu_gen2_data; extern const struct rtpse_mcu_match_data rtpse_mcu_gen2_i2c_data; #endif