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