blob: d75e91669b8fc43d5149a937f261bdda0d0200fb [file]
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef _REALTEK_PSE_MCU_H
#define _REALTEK_PSE_MCU_H
#include <linux/mutex.h>
#include <linux/pse-pd/pse.h>
#include <linux/types.h>
/*
* 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