Software APIs
i2c_testutils.h
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_I2C_TESTUTILS_H_
6 #define OPENTITAN_SW_DEVICE_LIB_TESTING_I2C_TESTUTILS_H_
7 
8 #include <stdint.h>
9 
10 #include "sw/device/lib/base/status.h"
13 
14 /**
15  * Construct an I2C write as an I2C host.
16  *
17  * @param i2c An I2C DIF handle.
18  * @param addr The device address for the transaction.
19  * @param byte_count The number of bytes to be written.
20  * @param data Stream of data bytes to be written.
21  * @param skip_stop Skip the stop bit as this may be chained with a read.
22  * @return The result of the operation.
23  */
25 status_t i2c_testutils_write(const dif_i2c_t *i2c, uint8_t addr,
26  size_t byte_count, const uint8_t *data,
27  bool skip_stop);
28 
29 /**
30  * Construct and issue an I2C read transaction as an I2C host.
31  *
32  * @param i2c An I2C DIF handle.
33  * @param addr The device address for the transaction.
34  * @param byte_count The number of bytes to be read.
35  * @return kOk(nak) Where nak indicates whether the device acknowledged the read
36  * transaction (false) or not (true), otherwise an error.
37  */
39 status_t i2c_testutils_issue_read(const dif_i2c_t *i2c, uint8_t addr,
40  uint8_t byte_count);
41 
42 /**
43  * Check that the target I2C device received the start of a transaction.
44  *
45  * @param i2c An I2C DIF handle.
46  * @param[out] addr The address that was used for the transaction.
47  * @return kOk(dir) Where dir indicates the direction of transaction is signaled
48  * as Read(1) and not Write(0), or an error.
49  */
51 status_t i2c_testutils_target_check_start(const dif_i2c_t *i2c, uint8_t *addr);
52 
53 /**
54  * Check that the target I2C device received the end of a transaction.
55  *
56  * @param i2c An I2C DIF handle.
57  * @param[out] cont_byte The contents of the acquired restart byte if host has
58  * signaled a repeated START, can be null if test doesn't
59  * accept a repeated start.
60  * @return kOk(dir) Where dir indicates that repeated start has signaled that
61  * the transaction should continue and the contents of cont_byte are valid, or
62  * an error.
63  */
65 status_t i2c_testutils_target_check_end(const dif_i2c_t *i2c,
66  uint8_t *cont_byte);
67 
68 /**
69  * Prepare for, and respond to, an I2C read as an I2C device.
70  *
71  * @param i2c An I2C DIF handle.
72  * @param byte_count The number of bytes to be read.
73  * @param data Array of data bytes to be sent.
74  * @return The result of the operation.
75  */
77 status_t i2c_testutils_target_read(const dif_i2c_t *i2c, uint16_t byte_count,
78  const uint8_t *data);
79 
80 /**
81  * Check completion of an I2C read as an I2C device.
82  *
83  * @param i2c An I2C DIF handle.
84  * @param[out] addr Address that received the I2C read.
85  * @param[out] cont_byte received continuation byte. Can be null if test
86  * expects STOP signal.
87  * @return kOk(dir) Where dir indicates that repeated start has signaled that
88  * the transaction should continue and the contents of cont_byte are valid, or
89  * an error.
90  */
92 status_t i2c_testutils_target_check_read(const dif_i2c_t *i2c, uint8_t *addr,
93  uint8_t *cont_byte);
94 
95 /**
96  * Prepare for an I2C write as an I2C device.
97  *
98  * @param i2c A I2C DIF handle.
99  * @param byte_count The number of bytes to be written.
100  * @return The result of the operation.
101  */
103 status_t i2c_testutils_target_write(const dif_i2c_t *i2c, uint16_t byte_count);
104 
105 /**
106  * Check completion of an I2C write as an I2C device.
107  *
108  * @param i2c A I2C DIF handle.
109  * @param byte_count The number of bytes to be written.
110  * @param[out] addr Address that received the I2C write.
111  * @param[out] bytes Array of bytes to stores the result of the write.
112  * @param[out] cont_byte Received continuation byte. Can be null if test expects
113  * STOP signal.
114  * @return kOk(dir) Where dir indicates that repeated START has signaled that
115  * the transaction should continue and the contents of cont_byte are valid, or
116  * an error.
117  */
119 status_t i2c_testutils_target_check_write(const dif_i2c_t *i2c,
120  uint16_t byte_count, uint8_t *addr,
121  uint8_t *bytes, uint8_t *cont_byte);
122 
123 /**
124  * Define the available platforms which i2c is mapped
125  */
126 typedef enum i2c_pinmux_platform_id {
127  I2cPinmuxPlatformIdHyper310 = 0,
128  I2cPinmuxPlatformIdDvsim,
129  I2cPinmuxPlatformIdCw310Pmod,
130  I2cPinmuxPlatformIdCount,
131 } i2c_pinmux_platform_id_t;
132 
133 /**
134  * Connect the i2c pins to mio pins via pinmux based on the platform the test is
135  * running.
136  *
137  * @param pimmux A pinmux handler.
138  * @param kI2cIdx The i2c instance identifier.
139  * @param platform The platform which the test is running.
140  * @return The result of the operation.
141  */
143 status_t i2c_testutils_select_pinmux(const dif_pinmux_t *pinmux,
144  uint8_t kI2cIdx,
145  i2c_pinmux_platform_id_t platform);
146 
147 /**
148  * Disconnect the i2c input pins from mio pads and wire it to zero.
149  *
150  * @param pimmux A pinmux handler.
151  * @param i2c_id The i2c instance identifier.
152  * @return The result of the operation.
153  */
155 status_t i2c_testutils_detach_pinmux(const dif_pinmux_t *pinmux,
156  uint8_t i2c_id);
157 
158 /**
159  * Return whether the fifo is empty.
160  *
161  * @param i2c An I2C DIF handle.
162  * @return `kOk(dir)` Where `dir` is true if the fifo is empty. Or an error.
163  */
165 static inline status_t i2c_testutils_fifo_empty(const dif_i2c_t *i2c) {
167  TRY(dif_i2c_get_status(i2c, &status));
168  return OK_STATUS(status.rx_fifo_empty);
169 }
170 
171 /**
172  * Return whether the tx fifo is full.
173  *
174  * @param i2c An I2C DIF handle.
175  * @return `kOk(dir)` Where `dir` is true if the tx fifo is full. Or an error.
176  */
178 static inline status_t i2c_testutils_tx_fifo_full(const dif_i2c_t *i2c) {
180  TRY(dif_i2c_get_status(i2c, &status));
181  return OK_STATUS(status.tx_fifo_full);
182 }
183 
184 /**
185  * Return whether the tx fifo is empty.
186  *
187  * @param i2c An I2C DIF handle.
188  * @return `kOk(dir)` Where `dir` is true if the tx fifo is empty. Or an error.
189  */
191 static inline status_t i2c_testutils_tx_fifo_empty(const dif_i2c_t *i2c) {
193  TRY(dif_i2c_get_status(i2c, &status));
194  return OK_STATUS(status.tx_fifo_empty);
195 }
196 
197 /**
198  * Return whether the fmt fifo is empty.
199  *
200  * @param i2c An I2C DIF handle.
201  * @return `kOk(dir)` Where `dir` is true if the fmt fifo is empty. Or an error.
202  */
204 static inline status_t i2c_testutils_fmt_fifo_empty(const dif_i2c_t *i2c) {
206  TRY(dif_i2c_get_status(i2c, &status));
207  return OK_STATUS(status.fmt_fifo_empty);
208 }
209 
210 /**
211  * Issue an i2c read transaction, check for a nak and retry until timeout in
212  * case of nak or read the fifo in case of ack.
213  *
214  * @param i2c An I2C DIF handle.
215  * @param addr The device address for the transaction.
216  * @param byte_count The number of bytes to be read.
217  * @param[out] data Buffer to receive the fifo data.
218  * @param timeout Timeout in microseconds.
219  * @return Return an error code if fails to read, otherwise `kOk(nak_count)`,
220  * where `nak_count` is the number of NAKs received or attempts needed before
221  * the success`.
222  */
224 status_t i2c_testutils_read(const dif_i2c_t *i2c, uint8_t addr,
225  size_t byte_count, uint8_t *data, size_t timeout);
226 
227 /**
228  * Set the i2c timing parameters based on the desired speed mode.
229  *
230  * @param i2c An I2C DIF handle.
231  * @param speed The speed mode.
232  * @return The result of the operation.
233  */
235 status_t i2c_testutils_set_speed(const dif_i2c_t *i2c, dif_i2c_speed_t speed);
236 
237 /**
238  * Busy spin until the i2c host get idle.
239  *
240  * @param i2c An I2C DIF handle.
241  * @return The result of the operation.
242  */
244 status_t i2c_testutils_wait_host_idle(const dif_i2c_t *i2c);
245 
246 /**
247  * Busy spin until the fmt_fifo gets empty (meaning that it has finished the all
248  * the transactions issued) or until a controller halted event is detected.
249  * In the latter case, it will not clear the controller halt event.
250  *
251  * @param i2c An I2C DIF handle.
252  * @return Return an error code if something went wrong, otherwise `kOk(halted)`
253  * where `halted` is 1 if the controller was halted and 0 if fmt_fifo was empty.
254  */
255 status_t i2c_testutils_wait_transaction_finish(const dif_i2c_t *i2c);
256 #endif // OPENTITAN_SW_DEVICE_LIB_TESTING_I2C_TESTUTILS_H_