blob: d75e91669b8fc43d5149a937f261bdda0d0200fb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
/* 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
|