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