1 /*
2 * Copyright 2022 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_I3C_TARGET_DEVICE_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_I3C_TARGET_DEVICE_H_
9
10 /**
11 * @brief I3C Target Device API
12 * @defgroup i3c_target_device I3C Target Device API
13 * @ingroup i3c_interface
14 * @{
15 */
16
17 #include <errno.h>
18 #include <stddef.h>
19 #include <stdint.h>
20
21 #include <zephyr/device.h>
22 #include <zephyr/sys/slist.h>
23
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27
28 struct i3c_driver_api;
29
30 /**
31 * @brief Configuration parameters for I3C hardware to act as target device.
32 *
33 * This can also be used to configure the controller if it is to act as
34 * a secondary controller on the bus.
35 */
36 struct i3c_config_target {
37 /**
38 * If the hardware is to act as a target device
39 * on the bus.
40 */
41 bool enable;
42
43 /**
44 * I3C target dynamic address.
45 *
46 * Used when operates as secondary controller
47 * or as a target device.
48 */
49 uint8_t dynamic_addr;
50
51 /**
52 * I3C target static address.
53 *
54 * Used used when operates as secondary controller
55 * or as a target device.
56 */
57 uint8_t static_addr;
58
59 /** Provisioned ID. */
60 uint64_t pid;
61
62 /**
63 * True if lower 32-bit of Provisioned ID is random.
64 *
65 * This sets the bit 32 of Provisioned ID which means
66 * the lower 32-bit is random value.
67 */
68 bool pid_random;
69
70 /** Bus Characteristics Register (BCR). */
71 uint8_t bcr;
72
73 /** Device Characteristics Register (DCR). */
74 uint8_t dcr;
75
76 /** Maximum Read Length (MRL). */
77 uint16_t max_read_len;
78
79 /** Maximum Write Length (MWL). */
80 uint16_t max_write_len;
81
82 /**
83 * Bit mask of supported HDR modes (0 - 7).
84 *
85 * This can be used to enable or disable HDR mode
86 * supported by the hardware at runtime.
87 */
88 uint8_t supported_hdr;
89 };
90
91 /**
92 * @brief Structure describing a device that supports the I3C target API.
93 *
94 * Instances of this are passed to the i3c_target_register() and
95 * i3c_target_unregister() functions to indicate addition and removal
96 * of a target device, respective.
97 *
98 * Fields other than @c node must be initialized by the module that
99 * implements the device behavior prior to passing the object
100 * reference to i3c_target_register().
101 */
102 struct i3c_target_config {
103 sys_snode_t node;
104
105 /**
106 * Flags for the target device defined by I3C_TARGET_FLAGS_*
107 * constants.
108 */
109 uint8_t flags;
110
111 /** Address for this target device */
112 uint8_t address;
113
114 /** Callback functions */
115 const struct i3c_target_callbacks *callbacks;
116 };
117
118 struct i3c_target_callbacks {
119 /**
120 * @brief Function called when a write to the device is initiated.
121 *
122 * This function is invoked by the controller when the bus completes
123 * a start condition for a write operation to the address associated
124 * with a particular device.
125 *
126 * A success return shall cause the controller to ACK the next byte
127 * received. An error return shall cause the controller to NACK the
128 * next byte received.
129 *
130 * @param config Configuration structure associated with the
131 * device to which the operation is addressed.
132 *
133 * @return 0 if the write is accepted, or a negative error code.
134 */
135 int (*write_requested_cb)(struct i3c_target_config *config);
136
137 /**
138 * @brief Function called when a write to the device is continued.
139 *
140 * This function is invoked by the controller when it completes
141 * reception of a byte of data in an ongoing write operation to the
142 * device.
143 *
144 * A success return shall cause the controller to ACK the next byte
145 * received. An error return shall cause the controller to NACK the
146 * next byte received.
147 *
148 * @param config Configuration structure associated with the
149 * device to which the operation is addressed.
150 *
151 * @param val the byte received by the controller.
152 *
153 * @return 0 if more data can be accepted, or a negative error
154 * code.
155 */
156 int (*write_received_cb)(struct i3c_target_config *config,
157 uint8_t val);
158
159 /**
160 * @brief Function called when a read from the device is initiated.
161 *
162 * This function is invoked by the controller when the bus completes a
163 * start condition for a read operation from the address associated
164 * with a particular device.
165 *
166 * The value returned in @p val will be transmitted. A success
167 * return shall cause the controller to react to additional read
168 * operations. An error return shall cause the controller to ignore
169 * bus operations until a new start condition is received.
170 *
171 * @param config Configuration structure associated with the
172 * device to which the operation is addressed.
173 *
174 * @param val Pointer to storage for the first byte of data to return
175 * for the read request.
176 *
177 * @return 0 if more data can be requested, or a negative error code.
178 */
179 int (*read_requested_cb)(struct i3c_target_config *config,
180 uint8_t *val);
181
182 /**
183 * @brief Function called when a read from the device is continued.
184 *
185 * This function is invoked by the controller when the bus is ready to
186 * provide additional data for a read operation from the address
187 * associated with the device device.
188 *
189 * The value returned in @p val will be transmitted. A success
190 * return shall cause the controller to react to additional read
191 * operations. An error return shall cause the controller to ignore
192 * bus operations until a new start condition is received.
193 *
194 * @param config Configuration structure associated with the
195 * device to which the operation is addressed.
196 *
197 * @param val Pointer to storage for the next byte of data to return
198 * for the read request.
199 *
200 * @return 0 if data has been provided, or a negative error code.
201 */
202 int (*read_processed_cb)(struct i3c_target_config *config,
203 uint8_t *val);
204
205 #ifdef CONFIG_I3C_TARGET_BUFFER_MODE
206 /** @brief Function called when a write to the device is completed.
207 *
208 * This function is invoked by the controller when it completes
209 * reception of data from the source buffer to the destination
210 * buffer in an ongoing write operation to the device.
211 *
212 * @param config Configuration structure associated with the
213 * device to which the operation is addressed.
214 *
215 * @param ptr pointer to the buffer that contains the data to be transferred.
216 *
217 * @param len the length of the data to be transferred.
218 */
219 void (*buf_write_received_cb)(struct i3c_target_config *config, uint8_t *ptr, uint32_t len);
220
221 /** @brief Function called when a read from the device is initiated.
222 *
223 * This function is invoked by the controller when the bus is ready to
224 * provide additional data by buffer for a read operation from the address
225 * associated with the device.
226 *
227 * The value returned in @p **ptr and @p *len will be transmitted. A success
228 * return shall cause the controller to react to additional read operations.
229 * An error return shall cause the controller to ignore bus operations until
230 * a new start condition is received.
231 *
232 * @param config the configuration structure associated with the
233 * device to which the operation is addressed.
234 *
235 * @param ptr pointer to storage for the address of data buffer to return
236 * for the read request.
237 *
238 * @param len pointer to storage for the length of the data to be transferred
239 * for the read request.
240 *
241 * @param hdr_mode HDR mode
242 *
243 * @return 0 if data has been provided, or a negative error code.
244 */
245 int (*buf_read_requested_cb)(struct i3c_target_config *config, uint8_t **ptr, uint32_t *len,
246 uint8_t *hdr_mode);
247 #endif
248 /**
249 * @brief Function called when a stop condition is observed after a
250 * start condition addressed to a particular device.
251 *
252 * This function is invoked by the controller when the bus is ready to
253 * provide additional data for a read operation from the address
254 * associated with the device device. After the function returns the
255 * controller shall enter a state where it is ready to react to new
256 * start conditions.
257 *
258 * @param config Configuration structure associated with the
259 * device to which the operation is addressed.
260 *
261 * @return Ignored.
262 */
263 int (*stop_cb)(struct i3c_target_config *config);
264 };
265
266 __subsystem struct i3c_target_driver_api {
267 int (*driver_register)(const struct device *dev);
268 int (*driver_unregister)(const struct device *dev);
269 };
270
271 /**
272 * @brief Writes to the target's TX FIFO
273 *
274 * Write to the TX FIFO @p dev I3C bus driver using the provided
275 * buffer and length. Some I3C targets will NACK read requests until data
276 * is written to the TX FIFO. This function will write as much as it can
277 * to the FIFO return the total number of bytes written. It is then up to
278 * the application to utalize the target callbacks to write the remaining
279 * data. Negative returns indicate error.
280 *
281 * Most of the existing hardware allows simultaneous support for master
282 * and target mode. This is however not guaranteed.
283 *
284 * @param dev Pointer to the device structure for an I3C controller
285 * driver configured in target mode.
286 * @param buf Pointer to the buffer
287 * @param len Length of the buffer
288 * @param hdr_mode HDR mode see @c I3C_MSG_HDR_MODE*
289 *
290 * @retval Total number of bytes written
291 * @retval -ENOTSUP Not in Target Mode or HDR Mode not supported
292 * @retval -ENOSPC No space in Tx FIFO
293 * @retval -ENOSYS If target mode is not implemented
294 */
i3c_target_tx_write(const struct device * dev,uint8_t * buf,uint16_t len,uint8_t hdr_mode)295 static inline int i3c_target_tx_write(const struct device *dev,
296 uint8_t *buf, uint16_t len, uint8_t hdr_mode)
297 {
298 const struct i3c_driver_api *api =
299 (const struct i3c_driver_api *)dev->api;
300
301 if (api->target_tx_write == NULL) {
302 return -ENOSYS;
303 }
304
305 return api->target_tx_write(dev, buf, len, hdr_mode);
306 }
307
308 /**
309 * @brief Registers the provided config as target device of a controller.
310 *
311 * Enable I3C target mode for the @p dev I3C bus driver using the provided
312 * config struct (@p cfg) containing the functions and parameters to send bus
313 * events. The I3C target will be registered at the address provided as
314 * @ref i3c_target_config.address struct member. Any I3C bus events related
315 * to the target mode will be passed onto I3C target device driver via a set of
316 * callback functions provided in the 'callbacks' struct member.
317 *
318 * Most of the existing hardware allows simultaneous support for master
319 * and target mode. This is however not guaranteed.
320 *
321 * @param dev Pointer to the device structure for an I3C controller
322 * driver configured in target mode.
323 * @param cfg Config struct with functions and parameters used by
324 * the I3C target driver to send bus events
325 *
326 * @retval 0 Is successful
327 * @retval -EINVAL If parameters are invalid
328 * @retval -EIO General input / output error.
329 * @retval -ENOSYS If target mode is not implemented
330 */
i3c_target_register(const struct device * dev,struct i3c_target_config * cfg)331 static inline int i3c_target_register(const struct device *dev,
332 struct i3c_target_config *cfg)
333 {
334 const struct i3c_driver_api *api =
335 (const struct i3c_driver_api *)dev->api;
336
337 if (api->target_register == NULL) {
338 return -ENOSYS;
339 }
340
341 return api->target_register(dev, cfg);
342 }
343
344 /**
345 * @brief Unregisters the provided config as target device
346 *
347 * This routine disables I3C target mode for the @p dev I3C bus driver using
348 * the provided config struct (@p cfg) containing the functions and parameters
349 * to send bus events.
350 *
351 * @param dev Pointer to the device structure for an I3C controller
352 * driver configured in target mode.
353 * @param cfg Config struct with functions and parameters used by
354 * the I3C target driver to send bus events
355 *
356 * @retval 0 Is successful
357 * @retval -EINVAL If parameters are invalid
358 * @retval -ENOSYS If target mode is not implemented
359 */
i3c_target_unregister(const struct device * dev,struct i3c_target_config * cfg)360 static inline int i3c_target_unregister(const struct device *dev,
361 struct i3c_target_config *cfg)
362 {
363 const struct i3c_driver_api *api =
364 (const struct i3c_driver_api *)dev->api;
365
366 if (api->target_unregister == NULL) {
367 return -ENOSYS;
368 }
369
370 return api->target_unregister(dev, cfg);
371 }
372
373 #ifdef __cplusplus
374 }
375 #endif
376
377 /**
378 * @}
379 */
380
381 #endif /* ZEPHYR_INCLUDE_DRIVERS_I3C_TARGET_DEVICE_H_ */
382