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 target on the bus.
35  */
36 struct i3c_config_target {
37 	/**
38 	 * If the hardware is currently acting as a target device
39 	 * on the bus.
40 	 */
41 	bool enabled;
42 
43 	/**
44 	 * I3C target dynamic address.
45 	 *
46 	 * Currently assigned dynamic address. 0 if no address
47 	 * assigned.
48 	 *
49 	 * @note Only writeable if the hardware acts as a primary
50 	 *       controller
51 	 */
52 	uint8_t dynamic_addr;
53 
54 	/**
55 	 * I3C target static address.
56 	 *
57 	 * Used used when operating as a secondary controller
58 	 * or as a target device.
59 	 */
60 	uint8_t static_addr;
61 
62 	/** Provisioned ID. */
63 	uint64_t pid;
64 
65 	/**
66 	 * True if lower 32-bit of Provisioned ID is random.
67 	 *
68 	 * This sets the bit 32 of Provisioned ID which means
69 	 * the lower 32-bit is random value.
70 	 */
71 	bool pid_random;
72 
73 	/** Bus Characteristics Register (BCR). */
74 	uint8_t bcr;
75 
76 	/** Device Characteristics Register (DCR). */
77 	uint8_t dcr;
78 
79 	/** Maximum Read Length (MRL). */
80 	uint16_t max_read_len;
81 
82 	/** Maximum Write Length (MWL). */
83 	uint16_t max_write_len;
84 
85 	/**
86 	 * Bit mask of supported HDR modes (0 - 7).
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 	 * @brief Function called when an active controller handoffs controlership
267 	 * to this target.
268 	 *
269 	 * This function is invoked by the active controller when it handoffs
270 	 * controllership to this target. This can happen wither the target has
271 	 * requested it or if the active controller chooses to handoff to the
272 	 * controller capable target.
273 	 *
274 	 * @param config Configuration structure associated with the
275 	 *               device to which the operation is addressed.
276 	 *
277 	 * @return Ignored.
278 	 */
279 	int (*controller_handoff_cb)(struct i3c_target_config *config);
280 };
281 
282 __subsystem struct i3c_target_driver_api {
283 	int (*driver_register)(const struct device *dev);
284 	int (*driver_unregister)(const struct device *dev);
285 };
286 
287 /**
288  * @brief Accept or Decline Controller Handoffs
289  *
290  * This sets the target to ACK or NACK handoffs from the active
291  * controller from the CCC GETACCCR.
292  *
293  * @param dev Pointer to the device structure for an I3C controller
294  *            driver configured in target mode.
295  * @param accept True to ACK controller handoffs, False to NACK
296  *
297  * @retval 0 Is successful
298  */
i3c_target_controller_handoff(const struct device * dev,bool accept)299 static inline int i3c_target_controller_handoff(const struct device *dev,
300 				      bool accept)
301 {
302 	const struct i3c_driver_api *api =
303 		(const struct i3c_driver_api *)dev->api;
304 
305 	if (api->target_controller_handoff == NULL) {
306 		return -ENOSYS;
307 	}
308 
309 	return api->target_controller_handoff(dev, accept);
310 }
311 
312 /**
313  * @brief Writes to the target's TX FIFO
314  *
315  * Write to the TX FIFO @p dev I3C bus driver using the provided
316  * buffer and length. Some I3C targets will NACK read requests until data
317  * is written to the TX FIFO. This function will write as much as it can
318  * to the FIFO return the total number of bytes written. It is then up to
319  * the application to utalize the target callbacks to write the remaining
320  * data. Negative returns indicate error.
321  *
322  * Most of the existing hardware allows simultaneous support for master
323  * and target mode. This is however not guaranteed.
324  *
325  * @param dev Pointer to the device structure for an I3C controller
326  *            driver configured in target mode.
327  * @param buf Pointer to the buffer
328  * @param len Length of the buffer
329  * @param hdr_mode HDR mode see @c I3C_MSG_HDR_MODE*
330  *
331  * @retval Total number of bytes written
332  * @retval -ENOTSUP Not in Target Mode or HDR Mode not supported
333  * @retval -ENOSPC No space in Tx FIFO
334  * @retval -ENOSYS If target mode is not implemented
335  */
i3c_target_tx_write(const struct device * dev,uint8_t * buf,uint16_t len,uint8_t hdr_mode)336 static inline int i3c_target_tx_write(const struct device *dev,
337 				      uint8_t *buf, uint16_t len, uint8_t hdr_mode)
338 {
339 	const struct i3c_driver_api *api =
340 		(const struct i3c_driver_api *)dev->api;
341 
342 	if (api->target_tx_write == NULL) {
343 		return -ENOSYS;
344 	}
345 
346 	return api->target_tx_write(dev, buf, len, hdr_mode);
347 }
348 
349 /**
350  * @brief Registers the provided config as target device of a controller.
351  *
352  * Enable I3C target mode for the @p dev I3C bus driver using the provided
353  * config struct (@p cfg) containing the functions and parameters to send bus
354  * events. The I3C target will be registered at the address provided as
355  * @ref i3c_target_config.address struct member. Any I3C bus events related
356  * to the target mode will be passed onto I3C target device driver via a set of
357  * callback functions provided in the 'callbacks' struct member.
358  *
359  * Most of the existing hardware allows simultaneous support for master
360  * and target mode. This is however not guaranteed.
361  *
362  * @param dev Pointer to the device structure for an I3C controller
363  *            driver configured in target mode.
364  * @param cfg Config struct with functions and parameters used by
365  *            the I3C target driver to send bus events
366  *
367  * @retval 0 Is successful
368  * @retval -EINVAL If parameters are invalid
369  * @retval -EIO General input / output error.
370  * @retval -ENOSYS If target mode is not implemented
371  */
i3c_target_register(const struct device * dev,struct i3c_target_config * cfg)372 static inline int i3c_target_register(const struct device *dev,
373 				      struct i3c_target_config *cfg)
374 {
375 	const struct i3c_driver_api *api =
376 		(const struct i3c_driver_api *)dev->api;
377 
378 	if (api->target_register == NULL) {
379 		return -ENOSYS;
380 	}
381 
382 	return api->target_register(dev, cfg);
383 }
384 
385 /**
386  * @brief Unregisters the provided config as target device
387  *
388  * This routine disables I3C target mode for the @p dev I3C bus driver using
389  * the provided config struct (@p cfg) containing the functions and parameters
390  * to send bus events.
391  *
392  * @param dev Pointer to the device structure for an I3C controller
393  *            driver configured in target mode.
394  * @param cfg Config struct with functions and parameters used by
395  *            the I3C target driver to send bus events
396  *
397  * @retval 0 Is successful
398  * @retval -EINVAL If parameters are invalid
399  * @retval -ENOSYS If target mode is not implemented
400  */
i3c_target_unregister(const struct device * dev,struct i3c_target_config * cfg)401 static inline int i3c_target_unregister(const struct device *dev,
402 					struct i3c_target_config *cfg)
403 {
404 	const struct i3c_driver_api *api =
405 		(const struct i3c_driver_api *)dev->api;
406 
407 	if (api->target_unregister == NULL) {
408 		return -ENOSYS;
409 	}
410 
411 	return api->target_unregister(dev, cfg);
412 }
413 
414 #ifdef __cplusplus
415 }
416 #endif
417 
418 /**
419  * @}
420  */
421 
422 #endif /* ZEPHYR_INCLUDE_DRIVERS_I3C_TARGET_DEVICE_H_ */
423