1 /*
2  * Copyright 2022 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_I3C_IBI_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_I3C_IBI_H_
9 
10 /**
11  * @brief I3C In-Band Interrupts
12  * @defgroup i3c_ibi I3C In-Band Interrupts
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 #ifndef CONFIG_I3C_IBI_MAX_PAYLOAD_SIZE
23 #define CONFIG_I3C_IBI_MAX_PAYLOAD_SIZE 0
24 #endif
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 struct i3c_device_desc;
31 
32 /**
33  * @brief IBI Types.
34  */
35 enum i3c_ibi_type {
36 	/** Target interrupt */
37 	I3C_IBI_TARGET_INTR,
38 
39 	/** Controller Role Request */
40 	I3C_IBI_CONTROLLER_ROLE_REQUEST,
41 
42 	/** Hot Join Request */
43 	I3C_IBI_HOTJOIN,
44 
45 	I3C_IBI_TYPE_MAX = I3C_IBI_HOTJOIN,
46 
47 	/**
48 	 * Not an actual IBI type, but simply used by
49 	 * the IBI workq for generic callbacks.
50 	 */
51 	I3C_IBI_WORKQUEUE_CB,
52 };
53 
54 /**
55  * @brief Struct for IBI request.
56  */
57 struct i3c_ibi {
58 	/** Type of IBI. */
59 	enum i3c_ibi_type	ibi_type;
60 
61 	/** Pointer to payload of IBI. */
62 	uint8_t			*payload;
63 
64 	/** Length in bytes of the IBI payload. */
65 	uint8_t			payload_len;
66 };
67 
68 /**
69  * @brief Structure of payload buffer for IBI.
70  *
71  * This is used for the IBI callback.
72  */
73 struct i3c_ibi_payload {
74 	/**
75 	 * Length of available data in the payload buffer.
76 	 */
77 	uint8_t payload_len;
78 
79 	/**
80 	 * Pointer to byte array as payload buffer.
81 	 */
82 	uint8_t payload[CONFIG_I3C_IBI_MAX_PAYLOAD_SIZE];
83 };
84 
85 /**
86  * @brief Node about a queued IBI.
87  */
88 struct i3c_ibi_work {
89 	/**
90 	 * @cond INTERNAL_HIDDEN
91 	 *
92 	 * Used for keeping track of work in a queue.
93 	 */
94 	sys_snode_t node;
95 	/** @endcond */
96 
97 	/**
98 	 * k_work struct.
99 	 */
100 	struct k_work work;
101 
102 	/**
103 	 * IBI type.
104 	 */
105 	enum i3c_ibi_type type;
106 
107 	union {
108 		/**
109 		 * Use for @see I3C_IBI_HOTJOIN.
110 		 */
111 		const struct device *controller;
112 
113 		/**
114 		 * Use for @see I3C_IBI_TARGET_INTR,
115 		 * and @see I3C_IBI_CONTROLLER_ROLE_REQUEST.
116 		 */
117 		struct i3c_device_desc *target;
118 	};
119 
120 	union {
121 		/**
122 		 * IBI payload.
123 		 */
124 		struct i3c_ibi_payload payload;
125 
126 		/**
127 		 * Generic workqueue callback when
128 		 * type is I3C_IBI_WORKQUEUE_CB.
129 		 */
130 		k_work_handler_t work_cb;
131 	};
132 };
133 
134 /**
135  * @brief Function called when In-Band Interrupt received from target device.
136  *
137  * This function is invoked by the controller when the controller
138  * receives an In-Band Interrupt from the target device.
139  *
140  * A success return shall cause the controller to ACK the next byte
141  * received.  An error return shall cause the controller to NACK the
142  * next byte received.
143  *
144  * @param target the device description structure associated with the
145  *               device to which the operation is addressed.
146  * @param payload Payload associated with the IBI. NULL if there is
147  *                no payload.
148  *
149  * @return 0 if the IBI is accepted, or a negative error code.
150  */
151 typedef int (*i3c_target_ibi_cb_t)(struct i3c_device_desc *target,
152 				   struct i3c_ibi_payload *payload);
153 
154 
155 /**
156  * @brief Queue an IBI work item for future processing.
157  *
158  * This queues up an IBI work item in the IBI workqueue
159  * for future processing.
160  *
161  * Note that this will copy the @p ibi_work struct into
162  * internal structure. If there is not enough space to
163  * copy the @p ibi_work struct, this returns -ENOMEM.
164  *
165  * @param ibi_work Pointer to the IBI work item struct.
166  *
167  * @retval 0 If work item is successfully queued.
168  * @retval -ENOMEM If no more free internal node to
169  *                 store IBI work item.
170  * @retval Others @see k_work_submit_to_queue
171  */
172 int i3c_ibi_work_enqueue(struct i3c_ibi_work *ibi_work);
173 
174 /**
175  * @brief Queue a target interrupt IBI for future processing.
176  *
177  * This queues up a target interrupt IBI in the IBI workqueue
178  * for future processing.
179  *
180  * @param target Pointer to target device descriptor.
181  * @param payload Pointer to IBI payload byte array.
182  * @param payload_len Length of payload byte array.
183  *
184  * @retval 0 If work item is successfully queued.
185  * @retval -ENOMEM If no more free internal node to
186  *                 store IBI work item.
187  * @retval Others @see k_work_submit_to_queue
188  */
189 int i3c_ibi_work_enqueue_target_irq(struct i3c_device_desc *target,
190 				    uint8_t *payload, size_t payload_len);
191 
192 /**
193  * @brief Queue a hot join IBI for future processing.
194  *
195  * This queues up a hot join IBI in the IBI workqueue
196  * for future processing.
197  *
198  * @param dev Pointer to controller device driver instance.
199  *
200  * @retval 0 If work item is successfully queued.
201  * @retval -ENOMEM If no more free internal node to
202  *                 store IBI work item.
203  * @retval Others @see k_work_submit_to_queue
204  */
205 int i3c_ibi_work_enqueue_hotjoin(const struct device *dev);
206 
207 /**
208  * @brief Queue a generic callback for future processing.
209  *
210  * This queues up a generic callback in the IBI workqueue
211  * for future processing.
212  *
213  * @param dev Pointer to controller device driver instance.
214  * @param work_cb Callback function.
215  *
216  * @retval 0 If work item is successfully queued.
217  * @retval -ENOMEM If no more free internal node to
218  *                 store IBI work item.
219  * @retval Others @see k_work_submit_to_queue
220  */
221 int i3c_ibi_work_enqueue_cb(const struct device *dev,
222 			    k_work_handler_t work_cb);
223 
224 #ifdef __cplusplus
225 }
226 #endif
227 
228 /**
229  * @}
230  */
231 
232 #endif /* ZEPHYR_INCLUDE_DRIVERS_I3C_IBI_H_ */
233