summaryrefslogtreecommitdiff
path: root/zephyr/include/emul/emul_tcpci.h
blob: 98a3495b025c8d1be5a523fa9cf28ea09148ac31 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/* Copyright 2021 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/**
 * @file
 *
 * @brief Backend API for TCPCI emulator
 */

#ifndef __EMUL_TCPCI_H
#define __EMUL_TCPCI_H

#include <emul.h>
#include <drivers/i2c.h>
#include <drivers/i2c_emul.h>
#include <usb_pd_tcpm.h>

/**
 * @brief TCPCI emulator backend API
 * @defgroup tcpci_emul TCPCI emulator
 * @{
 *
 * TCPCI emulator supports access to its registers using I2C messages.
 * It follows Type-C Port Controller Interface Specification. It is possible
 * to use this emulator as base for implementation of specific TCPC emulator
 * which follows TCPCI specification. Emulator allows to set callbacks
 * on change of CC status or transmitting message to implement partner emulator.
 * There is also callback used to inform about alert line state change.
 * Application may alter emulator state:
 *
 * - call @ref tcpci_emul_set_reg and @ref tcpci_emul_get_reg to set and get
 *   value of TCPCI registers
 * - call functions from emul_common_i2c.h to setup custom handlers for I2C
 *   messages
 * - call @ref tcpci_emul_add_rx_msg to setup received SOP messages
 * - call @ref tcpci_emul_get_tx_msg to examine sended message
 * - call @ref tcpci_emul_set_rev to set revision of emulated TCPCI
 */

/** SOP message structure */
struct tcpci_emul_msg {
	/** Pointer to buffer for header and message */
	uint8_t *buf;
	/** Number of bytes in buf */
	int cnt;
	/** Type of message (SOP, SOP', etc) */
	uint8_t type;
	/** Index used to mark accessed byte */
	int idx;
	/** Pointer to optional second message */
	struct tcpci_emul_msg *next;
};

/**
 * @brief Function type that is used by TCPCI emulator to provide information
 *        about alert line state
 *
 * @param emul Pointer to emulator
 * @param alert State of alert line (false - low, true - high)
 * @param data Pointer to custom function data
 */
typedef void (*tcpci_emul_alert_state_func)(const struct emul *emul, bool alert,
					    void *data);

/** Response from TCPCI specific device operations */
enum tcpci_emul_ops_resp {
	TCPCI_EMUL_CONTINUE = 0,
	TCPCI_EMUL_DONE,
	TCPCI_EMUL_ERROR
};

/** Revisions supported by TCPCI emaluator */
enum tcpci_emul_rev {
	TCPCI_EMUL_REV1_0_VER1_0 = 0,
	TCPCI_EMUL_REV2_0_VER1_1
};

/** TCPCI specific device operations. Not all of them need to be implemented. */
struct tcpci_emul_dev_ops {
	/**
	 * @brief Function called for each byte of read message
	 *
	 * @param emul Pointer to TCPCI emulator
	 * @param ops Pointer to device operations structure
	 * @param reg First byte of last write message
	 * @param val Pointer where byte to read should be stored
	 * @param bytes Number of bytes already readded
	 *
	 * @return TCPCI_EMUL_CONTINUE to continue with default handler
	 * @return TCPCI_EMUL_DONE to immedietly return success
	 * @return TCPCI_EMUL_ERROR to immedietly return error
	 */
	enum tcpci_emul_ops_resp (*read_byte)(const struct emul *emul,
					const struct tcpci_emul_dev_ops *ops,
					int reg, uint8_t *val, int bytes);

	/**
	 * @brief Function called for each byte of write message
	 *
	 * @param emul Pointer to TCPCI emulator
	 * @param ops Pointer to device operations structure
	 * @param reg First byte of write message
	 * @param val Received byte of write message
	 * @param bytes Number of bytes already received
	 *
	 * @return TCPCI_EMUL_CONTINUE to continue with default handler
	 * @return TCPCI_EMUL_DONE to immedietly return success
	 * @return TCPCI_EMUL_ERROR to immedietly return error
	 */
	enum tcpci_emul_ops_resp (*write_byte)(const struct emul *emul,
					const struct tcpci_emul_dev_ops *ops,
					int reg, uint8_t val, int bytes);

	/**
	 * @brief Function called on the end of write message
	 *
	 * @param emul Pointer to TCPCI emulator
	 * @param ops Pointer to device operations structure
	 * @param reg Register which is written
	 * @param msg_len Length of handled I2C message
	 *
	 * @return TCPCI_EMUL_CONTINUE to continue with default handler
	 * @return TCPCI_EMUL_DONE to immedietly return success
	 * @return TCPCI_EMUL_ERROR to immedietly return error
	 */
	enum tcpci_emul_ops_resp (*handle_write)(const struct emul *emul,
					const struct tcpci_emul_dev_ops *ops,
					int reg, int msg_len);

	/**
	 * @brief Function called on reset
	 *
	 * @param emul Pointer to TCPCI emulator
	 * @param ops Pointer to device operations structure
	 */
	void (*reset)(const struct emul *emul, struct tcpci_emul_dev_ops *ops);
};

/** TCPCI partner operations. Not all of them need to be implemented. */
struct tcpci_emul_partner_ops {
	/**
	 * @brief Function called when TCPM wants to transmit message to partner
	 *        connected to TCPCI
	 *
	 * @param emul Pointer to TCPCI emulator
	 * @param ops Pointer to partner operations structure
	 * @param tx_msg Pointer to TX message buffer
	 * @param type Type of message
	 * @param retry Count of retries
	 */
	void (*transmit)(const struct emul *emul,
			 const struct tcpci_emul_partner_ops *ops,
			 const struct tcpci_emul_msg *tx_msg,
			 enum tcpci_msg_type type,
			 int retry);

	/**
	 * @brief Function called when control settings change to allow partner
	 *        to react
	 *
	 * @param emul Pointer to TCPCI emulator
	 * @param ops Pointer to partner operations structure
	 */
	void (*control_change)(const struct emul *emul,
			       const struct tcpci_emul_partner_ops *ops);
};

/**
 * @brief Get i2c_emul for TCPCI emulator
 *
 * @param emul Pointer to TCPCI emulator
 *
 * @return Pointer to I2C TCPCI emulator
 */
struct i2c_emul *tcpci_emul_get_i2c_emul(const struct emul *emul);

/**
 * @brief Set value of given register of TCPCI
 *
 * @param emul Pointer to TCPCI emulator
 * @param reg Register address which value will be changed
 * @param val New value of the register
 *
 * @return 0 on success
 * @return -EINVAL when register is out of range defined in TCPCI specification
 */
int tcpci_emul_set_reg(const struct emul *emul, int reg, uint16_t val);

/**
 * @brief Get value of given register of TCPCI
 *
 * @param emul Pointer to TCPCI emulator
 * @param reg Register address
 * @param val Pointer where value should be stored
 *
 * @return 0 on success
 * @return -EINVAL when register is out of range defined in TCPCI specification
 *                 or val is NULL
 */
int tcpci_emul_get_reg(const struct emul *emul, int reg, uint16_t *val);

/**
 * @brief Add up to two SOP RX messages
 *
 * @param emul Pointer to TCPCI emulator
 * @param rx_msg Pointer to message that is added
 * @param alert Select if alert register should be updated
 *
 * @return 0 on success
 * @return -EINVAL on error (too long message or adding third message)
 */
int tcpci_emul_add_rx_msg(const struct emul *emul,
			  struct tcpci_emul_msg *rx_msg, bool alert);

/**
 * @brief Get SOP TX message to examine what was sended by TCPM
 *
 * @param emul Pointer to TCPCI emulator
 *
 * @return Pointer to TX message
 */
struct tcpci_emul_msg *tcpci_emul_get_tx_msg(const struct emul *emul);

/**
 * @brief Set TCPCI revision in PD_INT_REV register
 *
 * @param emul Pointer to TCPCI emulator
 * @param rev Requested revision
 */
void tcpci_emul_set_rev(const struct emul *emul, enum tcpci_emul_rev rev);

/**
 * @}
 */

#endif /* __EMUL_TCPCI */