1 /*
2  * Copyright (c) 2022 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 
9 #include <zephyr/toolchain.h>
10 #include <zephyr/sys/byteorder.h>
11 #include <zephyr/sys/__assert.h>
12 
13 #include <zephyr/drivers/i3c.h>
14 
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_DECLARE(i3c, CONFIG_I3C_LOG_LEVEL);
17 
i3c_ccc_do_getbcr(struct i3c_device_desc * target,struct i3c_ccc_getbcr * bcr)18 int i3c_ccc_do_getbcr(struct i3c_device_desc *target,
19 		      struct i3c_ccc_getbcr *bcr)
20 {
21 	struct i3c_ccc_payload ccc_payload;
22 	struct i3c_ccc_target_payload ccc_tgt_payload;
23 
24 	__ASSERT_NO_MSG(target != NULL);
25 	__ASSERT_NO_MSG(target->bus != NULL);
26 	__ASSERT_NO_MSG(bcr != NULL);
27 
28 	ccc_tgt_payload.addr = target->dynamic_addr;
29 	ccc_tgt_payload.rnw = 1;
30 	ccc_tgt_payload.data = &bcr->bcr;
31 	ccc_tgt_payload.data_len = sizeof(bcr->bcr);
32 
33 	memset(&ccc_payload, 0, sizeof(ccc_payload));
34 	ccc_payload.ccc.id = I3C_CCC_GETBCR;
35 	ccc_payload.targets.payloads = &ccc_tgt_payload;
36 	ccc_payload.targets.num_targets = 1;
37 
38 	return i3c_do_ccc(target->bus, &ccc_payload);
39 }
40 
i3c_ccc_do_getdcr(struct i3c_device_desc * target,struct i3c_ccc_getdcr * dcr)41 int i3c_ccc_do_getdcr(struct i3c_device_desc *target,
42 		      struct i3c_ccc_getdcr *dcr)
43 {
44 	struct i3c_ccc_payload ccc_payload;
45 	struct i3c_ccc_target_payload ccc_tgt_payload;
46 
47 	__ASSERT_NO_MSG(target != NULL);
48 	__ASSERT_NO_MSG(target->bus != NULL);
49 	__ASSERT_NO_MSG(dcr != NULL);
50 
51 	ccc_tgt_payload.addr = target->dynamic_addr;
52 	ccc_tgt_payload.rnw = 1;
53 	ccc_tgt_payload.data = &dcr->dcr;
54 	ccc_tgt_payload.data_len = sizeof(dcr->dcr);
55 
56 	memset(&ccc_payload, 0, sizeof(ccc_payload));
57 	ccc_payload.ccc.id = I3C_CCC_GETDCR;
58 	ccc_payload.targets.payloads = &ccc_tgt_payload;
59 	ccc_payload.targets.num_targets = 1;
60 
61 	return i3c_do_ccc(target->bus, &ccc_payload);
62 }
63 
i3c_ccc_do_getpid(struct i3c_device_desc * target,struct i3c_ccc_getpid * pid)64 int i3c_ccc_do_getpid(struct i3c_device_desc *target,
65 		      struct i3c_ccc_getpid *pid)
66 {
67 	struct i3c_ccc_payload ccc_payload;
68 	struct i3c_ccc_target_payload ccc_tgt_payload;
69 
70 	__ASSERT_NO_MSG(target != NULL);
71 	__ASSERT_NO_MSG(target->bus != NULL);
72 	__ASSERT_NO_MSG(pid != NULL);
73 
74 	ccc_tgt_payload.addr = target->dynamic_addr;
75 	ccc_tgt_payload.rnw = 1;
76 	ccc_tgt_payload.data = &pid->pid[0];
77 	ccc_tgt_payload.data_len = sizeof(pid->pid);
78 
79 	memset(&ccc_payload, 0, sizeof(ccc_payload));
80 	ccc_payload.ccc.id = I3C_CCC_GETPID;
81 	ccc_payload.targets.payloads = &ccc_tgt_payload;
82 	ccc_payload.targets.num_targets = 1;
83 
84 	return i3c_do_ccc(target->bus, &ccc_payload);
85 }
86 
i3c_ccc_do_rstact_all(const struct device * controller,enum i3c_ccc_rstact_defining_byte action)87 int i3c_ccc_do_rstact_all(const struct device *controller,
88 			  enum i3c_ccc_rstact_defining_byte action)
89 {
90 	struct i3c_ccc_payload ccc_payload;
91 	uint8_t def_byte;
92 
93 	__ASSERT_NO_MSG(controller != NULL);
94 
95 	memset(&ccc_payload, 0, sizeof(ccc_payload));
96 	ccc_payload.ccc.id = I3C_CCC_RSTACT(true);
97 
98 	def_byte = (uint8_t)action;
99 	ccc_payload.ccc.data = &def_byte;
100 	ccc_payload.ccc.data_len = 1U;
101 
102 	return i3c_do_ccc(controller, &ccc_payload);
103 }
104 
i3c_ccc_do_rstact(const struct i3c_device_desc * target,enum i3c_ccc_rstact_defining_byte action,bool get,uint8_t * data)105 int i3c_ccc_do_rstact(const struct i3c_device_desc *target,
106 			  enum i3c_ccc_rstact_defining_byte action,
107 			  bool get,
108 			  uint8_t *data)
109 {
110 	struct i3c_ccc_payload ccc_payload;
111 	struct i3c_ccc_target_payload ccc_tgt_payload;
112 	uint8_t def_byte;
113 
114 	__ASSERT_NO_MSG(target != NULL);
115 	__ASSERT_NO_MSG(target->bus != NULL);
116 
117 	memset(&ccc_payload, 0, sizeof(ccc_payload));
118 
119 	ccc_tgt_payload.addr = target->dynamic_addr;
120 	if (get) {
121 		__ASSERT_NO_MSG(data != NULL);
122 
123 		ccc_tgt_payload.rnw = 1;
124 		ccc_tgt_payload.data = data;
125 		ccc_tgt_payload.data_len = sizeof(*data);
126 	} else {
127 		ccc_tgt_payload.rnw = 0;
128 	}
129 
130 	ccc_payload.ccc.id = I3C_CCC_RSTACT(false);
131 	def_byte = (uint8_t)action;
132 	ccc_payload.ccc.data = &def_byte;
133 	ccc_payload.ccc.data_len = 1U;
134 	ccc_payload.targets.payloads = &ccc_tgt_payload;
135 	ccc_payload.targets.num_targets = 1;
136 
137 	return i3c_do_ccc(target->bus, &ccc_payload);
138 }
139 
i3c_ccc_do_rstdaa_all(const struct device * controller)140 int i3c_ccc_do_rstdaa_all(const struct device *controller)
141 {
142 	struct i3c_ccc_payload ccc_payload;
143 
144 	__ASSERT_NO_MSG(controller != NULL);
145 
146 	memset(&ccc_payload, 0, sizeof(ccc_payload));
147 	ccc_payload.ccc.id = I3C_CCC_RSTDAA;
148 
149 	return i3c_do_ccc(controller, &ccc_payload);
150 }
151 
i3c_ccc_do_setdasa(const struct i3c_device_desc * target,struct i3c_ccc_address da)152 int i3c_ccc_do_setdasa(const struct i3c_device_desc *target, struct i3c_ccc_address da)
153 {
154 	struct i3c_ccc_payload ccc_payload;
155 	struct i3c_ccc_target_payload ccc_tgt_payload;
156 
157 	__ASSERT_NO_MSG(target != NULL);
158 	__ASSERT_NO_MSG(target->bus != NULL);
159 
160 	if ((target->static_addr == 0U) || (target->dynamic_addr != 0U)) {
161 		return -EINVAL;
162 	}
163 
164 	ccc_tgt_payload.addr = target->static_addr;
165 	ccc_tgt_payload.rnw = 0;
166 	ccc_tgt_payload.data = (uint8_t *)&da.addr;
167 	ccc_tgt_payload.data_len = 1;
168 
169 	memset(&ccc_payload, 0, sizeof(ccc_payload));
170 	ccc_payload.ccc.id = I3C_CCC_SETDASA;
171 	ccc_payload.targets.payloads = &ccc_tgt_payload;
172 	ccc_payload.targets.num_targets = 1;
173 
174 	return i3c_do_ccc(target->bus, &ccc_payload);
175 }
176 
i3c_ccc_do_setnewda(const struct i3c_device_desc * target,struct i3c_ccc_address new_da)177 int i3c_ccc_do_setnewda(const struct i3c_device_desc *target, struct i3c_ccc_address new_da)
178 {
179 	struct i3c_ccc_payload ccc_payload;
180 	struct i3c_ccc_target_payload ccc_tgt_payload;
181 
182 	__ASSERT_NO_MSG(target != NULL);
183 	__ASSERT_NO_MSG(target->bus != NULL);
184 
185 	if (target->dynamic_addr == 0U) {
186 		return -EINVAL;
187 	}
188 
189 	ccc_tgt_payload.addr = target->dynamic_addr;
190 	ccc_tgt_payload.rnw = 0;
191 	ccc_tgt_payload.data = (uint8_t *)&new_da.addr;
192 	ccc_tgt_payload.data_len = 1;
193 
194 	memset(&ccc_payload, 0, sizeof(ccc_payload));
195 	ccc_payload.ccc.id = I3C_CCC_SETNEWDA;
196 	ccc_payload.targets.payloads = &ccc_tgt_payload;
197 	ccc_payload.targets.num_targets = 1;
198 
199 	return i3c_do_ccc(target->bus, &ccc_payload);
200 }
201 
i3c_ccc_do_events_all_set(const struct device * controller,bool enable,struct i3c_ccc_events * events)202 int i3c_ccc_do_events_all_set(const struct device *controller,
203 			      bool enable, struct i3c_ccc_events *events)
204 {
205 	struct i3c_ccc_payload ccc_payload;
206 
207 	__ASSERT_NO_MSG(controller != NULL);
208 
209 	memset(&ccc_payload, 0, sizeof(ccc_payload));
210 
211 	ccc_payload.ccc.id = enable ? I3C_CCC_ENEC(true) : I3C_CCC_DISEC(true);
212 
213 	ccc_payload.ccc.data = &events->events;
214 	ccc_payload.ccc.data_len = sizeof(events->events);
215 
216 	return i3c_do_ccc(controller, &ccc_payload);
217 }
218 
i3c_ccc_do_events_set(struct i3c_device_desc * target,bool enable,struct i3c_ccc_events * events)219 int i3c_ccc_do_events_set(struct i3c_device_desc *target,
220 			  bool enable, struct i3c_ccc_events *events)
221 {
222 	struct i3c_ccc_payload ccc_payload;
223 	struct i3c_ccc_target_payload ccc_tgt_payload;
224 
225 	__ASSERT_NO_MSG(target != NULL);
226 	__ASSERT_NO_MSG(target->bus != NULL);
227 
228 	if (target->dynamic_addr == 0U) {
229 		return -EINVAL;
230 	}
231 
232 	ccc_tgt_payload.addr = target->dynamic_addr;
233 	ccc_tgt_payload.rnw = 0;
234 	ccc_tgt_payload.data = &events->events;
235 	ccc_tgt_payload.data_len = sizeof(events->events);
236 
237 	memset(&ccc_payload, 0, sizeof(ccc_payload));
238 	ccc_payload.ccc.id = enable ? I3C_CCC_ENEC(false) : I3C_CCC_DISEC(false);
239 	ccc_payload.targets.payloads = &ccc_tgt_payload;
240 	ccc_payload.targets.num_targets = 1;
241 
242 	return i3c_do_ccc(target->bus, &ccc_payload);
243 }
244 
i3c_ccc_do_entas(const struct i3c_device_desc * target,uint8_t as)245 int i3c_ccc_do_entas(const struct i3c_device_desc *target, uint8_t as)
246 {
247 	struct i3c_ccc_payload ccc_payload;
248 	struct i3c_ccc_target_payload ccc_tgt_payload;
249 
250 	__ASSERT_NO_MSG(target != NULL);
251 	__ASSERT_NO_MSG(target->bus != NULL);
252 	__ASSERT_NO_MSG(as <= 3);
253 
254 	memset(&ccc_payload, 0, sizeof(ccc_payload));
255 
256 	ccc_tgt_payload.addr = target->dynamic_addr;
257 	ccc_tgt_payload.rnw = 0;
258 
259 	ccc_payload.ccc.id = I3C_CCC_ENTAS(as, false);
260 	ccc_payload.targets.payloads = &ccc_tgt_payload;
261 	ccc_payload.targets.num_targets = 1;
262 
263 	return i3c_do_ccc(target->bus, &ccc_payload);
264 }
265 
i3c_ccc_do_entas_all(const struct device * controller,uint8_t as)266 int i3c_ccc_do_entas_all(const struct device *controller, uint8_t as)
267 {
268 	struct i3c_ccc_payload ccc_payload;
269 
270 	__ASSERT_NO_MSG(controller != NULL);
271 	__ASSERT_NO_MSG(as <= 3);
272 
273 	memset(&ccc_payload, 0, sizeof(ccc_payload));
274 	ccc_payload.ccc.id = I3C_CCC_ENTAS(as, true);
275 
276 	return i3c_do_ccc(controller, &ccc_payload);
277 }
278 
i3c_ccc_do_setmwl_all(const struct device * controller,const struct i3c_ccc_mwl * mwl)279 int i3c_ccc_do_setmwl_all(const struct device *controller,
280 			  const struct i3c_ccc_mwl *mwl)
281 {
282 	struct i3c_ccc_payload ccc_payload;
283 	uint8_t data[2];
284 
285 	__ASSERT_NO_MSG(controller != NULL);
286 
287 	memset(&ccc_payload, 0, sizeof(ccc_payload));
288 
289 	ccc_payload.ccc.id = I3C_CCC_SETMWL(true);
290 
291 	ccc_payload.ccc.data = &data[0];
292 	ccc_payload.ccc.data_len = sizeof(data);
293 
294 	/* The actual data is MSB first. So order the data. */
295 	sys_put_be16(mwl->len, data);
296 
297 	return i3c_do_ccc(controller, &ccc_payload);
298 }
299 
i3c_ccc_do_setmwl(const struct i3c_device_desc * target,const struct i3c_ccc_mwl * mwl)300 int i3c_ccc_do_setmwl(const struct i3c_device_desc *target,
301 		      const struct i3c_ccc_mwl *mwl)
302 {
303 	struct i3c_ccc_payload ccc_payload;
304 	struct i3c_ccc_target_payload ccc_tgt_payload;
305 	uint8_t data[2];
306 
307 	__ASSERT_NO_MSG(target != NULL);
308 	__ASSERT_NO_MSG(target->bus != NULL);
309 
310 	memset(&ccc_payload, 0, sizeof(ccc_payload));
311 
312 	ccc_tgt_payload.addr = target->dynamic_addr;
313 	ccc_tgt_payload.rnw = 0;
314 	ccc_tgt_payload.data = &data[0];
315 	ccc_tgt_payload.data_len = sizeof(data);
316 
317 	ccc_payload.ccc.id = I3C_CCC_SETMWL(false);
318 	ccc_payload.targets.payloads = &ccc_tgt_payload;
319 	ccc_payload.targets.num_targets = 1;
320 
321 	/* The actual length is MSB first. So order the data. */
322 	sys_put_be16(mwl->len, data);
323 
324 	return i3c_do_ccc(target->bus, &ccc_payload);
325 }
326 
i3c_ccc_do_getmwl(const struct i3c_device_desc * target,struct i3c_ccc_mwl * mwl)327 int i3c_ccc_do_getmwl(const struct i3c_device_desc *target,
328 		      struct i3c_ccc_mwl *mwl)
329 {
330 	struct i3c_ccc_payload ccc_payload;
331 	struct i3c_ccc_target_payload ccc_tgt_payload;
332 	uint8_t data[2];
333 	int ret;
334 
335 	__ASSERT_NO_MSG(target != NULL);
336 	__ASSERT_NO_MSG(target->bus != NULL);
337 	__ASSERT_NO_MSG(mwl != NULL);
338 
339 	ccc_tgt_payload.addr = target->dynamic_addr;
340 	ccc_tgt_payload.rnw = 1;
341 	ccc_tgt_payload.data = &data[0];
342 	ccc_tgt_payload.data_len = sizeof(data);
343 
344 	memset(&ccc_payload, 0, sizeof(ccc_payload));
345 	ccc_payload.ccc.id = I3C_CCC_GETMWL;
346 	ccc_payload.targets.payloads = &ccc_tgt_payload;
347 	ccc_payload.targets.num_targets = 1;
348 
349 	ret = i3c_do_ccc(target->bus, &ccc_payload);
350 
351 	if (ret == 0) {
352 		/* The actual length is MSB first. So order the data. */
353 		mwl->len = sys_get_be16(data);
354 	}
355 
356 	return ret;
357 }
358 
i3c_ccc_do_setmrl_all(const struct device * controller,const struct i3c_ccc_mrl * mrl,bool has_ibi_size)359 int i3c_ccc_do_setmrl_all(const struct device *controller,
360 			  const struct i3c_ccc_mrl *mrl,
361 			  bool has_ibi_size)
362 {
363 	struct i3c_ccc_payload ccc_payload;
364 	uint8_t data[3];
365 
366 	__ASSERT_NO_MSG(controller != NULL);
367 
368 	memset(&ccc_payload, 0, sizeof(ccc_payload));
369 
370 	ccc_payload.ccc.id = I3C_CCC_SETMRL(true);
371 
372 	ccc_payload.ccc.data = &data[0];
373 	ccc_payload.ccc.data_len = has_ibi_size ? 3 : 2;
374 
375 	/* The actual length is MSB first. So order the data. */
376 	sys_put_be16(mrl->len, data);
377 
378 	if (has_ibi_size) {
379 		data[2] = mrl->ibi_len;
380 	}
381 
382 	return i3c_do_ccc(controller, &ccc_payload);
383 }
384 
i3c_ccc_do_setmrl(const struct i3c_device_desc * target,const struct i3c_ccc_mrl * mrl)385 int i3c_ccc_do_setmrl(const struct i3c_device_desc *target,
386 		      const struct i3c_ccc_mrl *mrl)
387 {
388 	struct i3c_ccc_payload ccc_payload;
389 	struct i3c_ccc_target_payload ccc_tgt_payload;
390 	uint8_t data[3];
391 
392 	__ASSERT_NO_MSG(target != NULL);
393 	__ASSERT_NO_MSG(target->bus != NULL);
394 
395 	memset(&ccc_payload, 0, sizeof(ccc_payload));
396 
397 	ccc_tgt_payload.addr = target->dynamic_addr;
398 	ccc_tgt_payload.rnw = 0;
399 	ccc_tgt_payload.data = &data[0];
400 
401 	ccc_payload.ccc.id = I3C_CCC_SETMRL(false);
402 	ccc_payload.targets.payloads = &ccc_tgt_payload;
403 	ccc_payload.targets.num_targets = 1;
404 
405 	/* The actual length is MSB first. So order the data. */
406 	sys_put_be16(mrl->len, data);
407 
408 	if ((target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
409 	    == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE) {
410 		ccc_tgt_payload.data_len = 3;
411 
412 		data[2] = mrl->ibi_len;
413 	} else {
414 		ccc_tgt_payload.data_len = 2;
415 	}
416 
417 	return i3c_do_ccc(target->bus, &ccc_payload);
418 }
419 
i3c_ccc_do_getmrl(const struct i3c_device_desc * target,struct i3c_ccc_mrl * mrl)420 int i3c_ccc_do_getmrl(const struct i3c_device_desc *target,
421 		      struct i3c_ccc_mrl *mrl)
422 {
423 	struct i3c_ccc_payload ccc_payload;
424 	struct i3c_ccc_target_payload ccc_tgt_payload;
425 	uint8_t data[3];
426 	bool has_ibi_sz;
427 	int ret;
428 
429 	__ASSERT_NO_MSG(target != NULL);
430 	__ASSERT_NO_MSG(target->bus != NULL);
431 	__ASSERT_NO_MSG(mrl != NULL);
432 
433 	has_ibi_sz = (target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
434 		     == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE;
435 
436 	ccc_tgt_payload.addr = target->dynamic_addr;
437 	ccc_tgt_payload.rnw = 1;
438 	ccc_tgt_payload.data = &data[0];
439 	ccc_tgt_payload.data_len = has_ibi_sz ? 3 : 2;
440 
441 	memset(&ccc_payload, 0, sizeof(ccc_payload));
442 	ccc_payload.ccc.id = I3C_CCC_GETMRL;
443 	ccc_payload.targets.payloads = &ccc_tgt_payload;
444 	ccc_payload.targets.num_targets = 1;
445 
446 	ret = i3c_do_ccc(target->bus, &ccc_payload);
447 
448 	if (ret == 0) {
449 		/* The actual length is MSB first. So order the data. */
450 		mrl->len = sys_get_be16(data);
451 
452 		if (has_ibi_sz) {
453 			mrl->ibi_len = data[2];
454 		}
455 	}
456 
457 	return ret;
458 }
459 
i3c_ccc_do_enttm(const struct device * controller,enum i3c_ccc_enttm_defbyte defbyte)460 int i3c_ccc_do_enttm(const struct device *controller,
461 			  enum i3c_ccc_enttm_defbyte defbyte)
462 {
463 	struct i3c_ccc_payload ccc_payload;
464 	uint8_t def_byte;
465 
466 	__ASSERT_NO_MSG(controller != NULL);
467 
468 	memset(&ccc_payload, 0, sizeof(ccc_payload));
469 	ccc_payload.ccc.id = I3C_CCC_ENTTM;
470 
471 	def_byte = (uint8_t)defbyte;
472 	ccc_payload.ccc.data = &def_byte;
473 	ccc_payload.ccc.data_len = 1U;
474 
475 	return i3c_do_ccc(controller, &ccc_payload);
476 }
477 
i3c_ccc_do_deftgts_all(const struct device * controller,struct i3c_ccc_deftgts * deftgts)478 int i3c_ccc_do_deftgts_all(const struct device *controller,
479 			   struct i3c_ccc_deftgts *deftgts)
480 {
481 	struct i3c_ccc_payload ccc_payload;
482 
483 	__ASSERT_NO_MSG(controller != NULL);
484 	__ASSERT_NO_MSG(deftgts != NULL);
485 
486 	memset(&ccc_payload, 0, sizeof(ccc_payload));
487 	ccc_payload.ccc.id = I3C_CCC_DEFTGTS;
488 
489 	ccc_payload.ccc.data = (uint8_t *)deftgts;
490 	ccc_payload.ccc.data_len = sizeof(uint8_t) +
491 				   sizeof(struct i3c_ccc_deftgts_active_controller) +
492 				   (deftgts->count * sizeof(struct i3c_ccc_deftgts_target));
493 
494 	return i3c_do_ccc(controller, &ccc_payload);
495 }
496 
i3c_ccc_do_getstatus(const struct i3c_device_desc * target,union i3c_ccc_getstatus * status,enum i3c_ccc_getstatus_fmt fmt,enum i3c_ccc_getstatus_defbyte defbyte)497 int i3c_ccc_do_getstatus(const struct i3c_device_desc *target,
498 			 union i3c_ccc_getstatus *status,
499 			 enum i3c_ccc_getstatus_fmt fmt,
500 			 enum i3c_ccc_getstatus_defbyte defbyte)
501 {
502 	struct i3c_ccc_payload ccc_payload;
503 	struct i3c_ccc_target_payload ccc_tgt_payload;
504 	uint8_t defining_byte;
505 	uint8_t data[2];
506 	int ret;
507 
508 	__ASSERT_NO_MSG(target != NULL);
509 	__ASSERT_NO_MSG(target->bus != NULL);
510 	__ASSERT_NO_MSG(status != NULL);
511 
512 	ccc_tgt_payload.addr = target->dynamic_addr;
513 	ccc_tgt_payload.rnw = 1;
514 	ccc_tgt_payload.data = &data[0];
515 
516 	if (fmt == GETSTATUS_FORMAT_1) {
517 		ccc_tgt_payload.data_len = 2;
518 	} else if (fmt == GETSTATUS_FORMAT_2) {
519 		switch (defbyte) {
520 		case GETSTATUS_FORMAT_2_TGTSTAT:
521 			__fallthrough;
522 		case GETSTATUS_FORMAT_2_PRECR:
523 			ccc_tgt_payload.data_len = 2;
524 			break;
525 		default:
526 			ret = -EINVAL;
527 			goto out;
528 		}
529 	} else {
530 		ret = -EINVAL;
531 		goto out;
532 	}
533 
534 	memset(&ccc_payload, 0, sizeof(ccc_payload));
535 	ccc_payload.ccc.id = I3C_CCC_GETSTATUS;
536 	ccc_payload.targets.payloads = &ccc_tgt_payload;
537 	ccc_payload.targets.num_targets = 1;
538 
539 	if (fmt == GETSTATUS_FORMAT_2) {
540 		defining_byte = (uint8_t)defbyte;
541 
542 		ccc_payload.ccc.data = &defining_byte;
543 		ccc_payload.ccc.data_len = 1;
544 	}
545 
546 	ret = i3c_do_ccc(target->bus, &ccc_payload);
547 
548 	if (ret == 0) {
549 		/* Received data is MSB first. So order the data. */
550 		if (fmt == GETSTATUS_FORMAT_1) {
551 			status->fmt1.status = sys_get_be16(data);
552 		} else if (fmt == GETSTATUS_FORMAT_2) {
553 			switch (defbyte) {
554 			case GETSTATUS_FORMAT_2_TGTSTAT:
555 				__fallthrough;
556 			case GETSTATUS_FORMAT_2_PRECR:
557 				status->fmt2.raw_u16 = sys_get_be16(data);
558 				break;
559 			default:
560 				break;
561 			}
562 		}
563 	}
564 
565 out:
566 	return ret;
567 }
568 
i3c_ccc_do_getcaps(const struct i3c_device_desc * target,union i3c_ccc_getcaps * caps,enum i3c_ccc_getcaps_fmt fmt,enum i3c_ccc_getcaps_defbyte defbyte)569 int i3c_ccc_do_getcaps(const struct i3c_device_desc *target,
570 			 union i3c_ccc_getcaps *caps,
571 			 enum i3c_ccc_getcaps_fmt fmt,
572 			 enum i3c_ccc_getcaps_defbyte defbyte)
573 {
574 	struct i3c_ccc_payload ccc_payload;
575 	struct i3c_ccc_target_payload ccc_tgt_payload;
576 	uint8_t defining_byte;
577 	uint8_t data[4];
578 	uint8_t len;
579 	int ret;
580 
581 	__ASSERT_NO_MSG(target != NULL);
582 	__ASSERT_NO_MSG(target->bus != NULL);
583 	__ASSERT_NO_MSG(caps != NULL);
584 
585 	ccc_tgt_payload.addr = target->dynamic_addr;
586 	ccc_tgt_payload.rnw = 1;
587 	ccc_tgt_payload.data = &data[0];
588 
589 	if (fmt == GETCAPS_FORMAT_1) {
590 		/* Could be 1-4 Data Bytes Returned */
591 		ccc_tgt_payload.data_len = 4;
592 	} else if (fmt == GETCAPS_FORMAT_2) {
593 		switch (defbyte) {
594 		case GETCAPS_FORMAT_2_CRCAPS:
595 			__fallthrough;
596 		case GETCAPS_FORMAT_2_VTCAPS:
597 			/* Could be 1-2 Data Bytes Returned*/
598 			ccc_tgt_payload.data_len = 2;
599 			break;
600 		case GETCAPS_FORMAT_2_TGTCAPS:
601 			__fallthrough;
602 		case GETCAPS_FORMAT_2_TESTPAT:
603 			/* Could be 1-4 Data Bytes Returned */
604 			ccc_tgt_payload.data_len = 4;
605 			break;
606 		default:
607 			ret = -EINVAL;
608 			goto out;
609 		}
610 	} else {
611 		ret = -EINVAL;
612 		goto out;
613 	}
614 
615 	memset(&ccc_payload, 0, sizeof(ccc_payload));
616 	ccc_payload.ccc.id = I3C_CCC_GETCAPS;
617 	ccc_payload.targets.payloads = &ccc_tgt_payload;
618 	ccc_payload.targets.num_targets = 1;
619 
620 	if (fmt == GETCAPS_FORMAT_2) {
621 		defining_byte = (uint8_t)defbyte;
622 
623 		ccc_payload.ccc.data = &defining_byte;
624 		ccc_payload.ccc.data_len = 1;
625 	}
626 
627 	ret = i3c_do_ccc(target->bus, &ccc_payload);
628 
629 	if (ret == 0) {
630 		/* GETCAPS will return a variable length */
631 		len = ccc_tgt_payload.num_xfer;
632 
633 		if (fmt == GETCAPS_FORMAT_1) {
634 			memcpy(caps->fmt1.getcaps, data, len);
635 			/* for values not received, assume default (1'b0) */
636 			memset(&caps->fmt1.getcaps[len], 0, sizeof(caps->fmt1.getcaps) - len);
637 		} else if (fmt == GETCAPS_FORMAT_2) {
638 			switch (defbyte) {
639 			case GETCAPS_FORMAT_2_CRCAPS:
640 				memcpy(caps->fmt2.crcaps, data, len);
641 				/* for values not received, assume default (1'b0) */
642 				memset(&caps->fmt2.crcaps[len], 0, sizeof(caps->fmt2.crcaps) - len);
643 				break;
644 			case GETCAPS_FORMAT_2_VTCAPS:
645 				memcpy(caps->fmt2.vtcaps, data, len);
646 				/* for values not received, assume default (1'b0) */
647 				memset(&caps->fmt2.vtcaps[len], 0, sizeof(caps->fmt2.vtcaps) - len);
648 				break;
649 			case GETCAPS_FORMAT_2_TGTCAPS:
650 				memcpy(caps->fmt2.tgtcaps, data, len);
651 				/* for values not received, assume default (1'b0) */
652 				memset(&caps->fmt2.tgtcaps[len], 0,
653 				       sizeof(caps->fmt2.tgtcaps) - len);
654 				break;
655 			case GETCAPS_FORMAT_2_TESTPAT:
656 				/* should always be 4 data bytes */
657 				caps->fmt2.testpat = sys_get_be32(data);
658 				break;
659 			default:
660 				break;
661 			}
662 		}
663 	}
664 
665 out:
666 	return ret;
667 }
668 
i3c_ccc_do_setvendor(const struct i3c_device_desc * target,uint8_t id,uint8_t * payload,size_t len)669 int i3c_ccc_do_setvendor(const struct i3c_device_desc *target,
670 			 uint8_t id,
671 			 uint8_t *payload,
672 			 size_t len)
673 {
674 	struct i3c_ccc_payload ccc_payload;
675 
676 	__ASSERT_NO_MSG(target != NULL);
677 
678 	/* CCC must be between 0xE0 and 0xFE, the total range of this is 0x1E */
679 	if (id > 0x1E) {
680 		return -EINVAL;
681 	}
682 
683 	memset(&ccc_payload, 0, sizeof(ccc_payload));
684 	ccc_payload.ccc.id = I3C_CCC_VENDOR(false, id);
685 	ccc_payload.ccc.data = payload;
686 	ccc_payload.ccc.data_len = len;
687 
688 	return i3c_do_ccc(target->bus, &ccc_payload);
689 }
690 
i3c_ccc_do_getvendor(const struct i3c_device_desc * target,uint8_t id,uint8_t * payload,size_t len,size_t * num_xfer)691 int i3c_ccc_do_getvendor(const struct i3c_device_desc *target,
692 			 uint8_t id,
693 			 uint8_t *payload,
694 			 size_t len,
695 			 size_t *num_xfer)
696 {
697 	struct i3c_ccc_payload ccc_payload;
698 	struct i3c_ccc_target_payload ccc_tgt_payload;
699 	int ret;
700 
701 	__ASSERT_NO_MSG(target != NULL);
702 
703 	/* CCC must be between 0xE0 and 0xFE, the total range of this is 0x1E */
704 	if (id > 0x1E) {
705 		return -EINVAL;
706 	}
707 
708 	ccc_tgt_payload.addr = target->dynamic_addr;
709 	ccc_tgt_payload.rnw = 1;
710 	ccc_tgt_payload.data = payload;
711 	ccc_tgt_payload.data_len = len;
712 
713 	memset(&ccc_payload, 0, sizeof(ccc_payload));
714 	ccc_payload.ccc.id = I3C_CCC_VENDOR(false, id);
715 	ccc_payload.targets.payloads = &ccc_tgt_payload;
716 	ccc_payload.targets.num_targets = 1;
717 
718 	ret = i3c_do_ccc(target->bus, &ccc_payload);
719 
720 	if (ret == 0) {
721 		*num_xfer = ccc_tgt_payload.num_xfer;
722 	}
723 
724 	return ret;
725 }
726 
i3c_ccc_do_getvendor_defbyte(const struct i3c_device_desc * target,uint8_t id,uint8_t defbyte,uint8_t * payload,size_t len,size_t * num_xfer)727 int i3c_ccc_do_getvendor_defbyte(const struct i3c_device_desc *target,
728 				 uint8_t id,
729 				 uint8_t defbyte,
730 				 uint8_t *payload,
731 				 size_t len,
732 				 size_t *num_xfer)
733 {
734 	struct i3c_ccc_payload ccc_payload;
735 	struct i3c_ccc_target_payload ccc_tgt_payload;
736 	int ret;
737 
738 	__ASSERT_NO_MSG(target != NULL);
739 
740 	/* CCC must be between 0xE0 and 0xFE, the total range of this is 0x1E */
741 	if (id > 0x1E) {
742 		return -EINVAL;
743 	}
744 
745 	ccc_tgt_payload.addr = target->dynamic_addr;
746 	ccc_tgt_payload.rnw = 1;
747 	ccc_tgt_payload.data = payload;
748 	ccc_tgt_payload.data_len = len;
749 
750 	memset(&ccc_payload, 0, sizeof(ccc_payload));
751 	ccc_payload.ccc.id = I3C_CCC_VENDOR(false, id);
752 	ccc_payload.ccc.data = &defbyte;
753 	ccc_payload.ccc.data_len = 1;
754 	ccc_payload.targets.payloads = &ccc_tgt_payload;
755 	ccc_payload.targets.num_targets = 1;
756 
757 	ret = i3c_do_ccc(target->bus, &ccc_payload);
758 
759 	if (ret == 0) {
760 		*num_xfer = ccc_tgt_payload.num_xfer;
761 	}
762 
763 	return ret;
764 }
765 
i3c_ccc_do_setvendor_all(const struct device * controller,uint8_t id,uint8_t * payload,size_t len)766 int i3c_ccc_do_setvendor_all(const struct device *controller,
767 				 uint8_t id,
768 				 uint8_t *payload,
769 				 size_t len)
770 {
771 	struct i3c_ccc_payload ccc_payload;
772 
773 	__ASSERT_NO_MSG(controller != NULL);
774 
775 	/* CCC must be between 0x61 and 0x7F, the total range of this is 0x1E */
776 	if (id > 0x1E) {
777 		return -EINVAL;
778 	}
779 
780 	memset(&ccc_payload, 0, sizeof(ccc_payload));
781 	ccc_payload.ccc.id = I3C_CCC_VENDOR(true, id);
782 	ccc_payload.ccc.data = payload;
783 	ccc_payload.ccc.data_len = len;
784 
785 	return i3c_do_ccc(controller, &ccc_payload);
786 }
787 
i3c_ccc_do_setaasa_all(const struct device * controller)788 int i3c_ccc_do_setaasa_all(const struct device *controller)
789 {
790 	struct i3c_ccc_payload ccc_payload;
791 
792 	__ASSERT_NO_MSG(controller != NULL);
793 
794 	memset(&ccc_payload, 0, sizeof(ccc_payload));
795 	ccc_payload.ccc.id = I3C_CCC_SETAASA;
796 
797 	return i3c_do_ccc(controller, &ccc_payload);
798 }
799 
i3c_ccc_do_getmxds(const struct i3c_device_desc * target,union i3c_ccc_getmxds * mxds,enum i3c_ccc_getmxds_fmt fmt,enum i3c_ccc_getmxds_defbyte defbyte)800 int i3c_ccc_do_getmxds(const struct i3c_device_desc *target,
801 			 union i3c_ccc_getmxds *mxds,
802 			 enum i3c_ccc_getmxds_fmt fmt,
803 			 enum i3c_ccc_getmxds_defbyte defbyte)
804 {
805 	struct i3c_ccc_payload ccc_payload;
806 	struct i3c_ccc_target_payload ccc_tgt_payload;
807 	uint8_t defining_byte;
808 	uint8_t data[5];
809 	uint8_t len;
810 	int ret;
811 
812 	__ASSERT_NO_MSG(target != NULL);
813 	__ASSERT_NO_MSG(target->bus != NULL);
814 	__ASSERT_NO_MSG(mxds != NULL);
815 
816 	ccc_tgt_payload.addr = target->dynamic_addr;
817 	ccc_tgt_payload.rnw = 1;
818 	ccc_tgt_payload.data = &data[0];
819 
820 	if ((fmt == GETMXDS_FORMAT_1) || (fmt == GETMXDS_FORMAT_2)) {
821 		/* Could be 2 or 5 Data Bytes Returned */
822 		ccc_tgt_payload.data_len = sizeof(((union i3c_ccc_getmxds *)0)->fmt2);
823 	} else if (fmt == GETMXDS_FORMAT_3) {
824 		switch (defbyte) {
825 		case GETMXDS_FORMAT_3_WRRDTURN:
826 			/* Could be 2 or 5 Data Bytes Returned */
827 			ccc_tgt_payload.data_len =
828 				sizeof(((union i3c_ccc_getmxds *)0)->fmt3.wrrdturn);
829 			break;
830 		case GETMXDS_FORMAT_3_CRHDLY:
831 			/* Only 1 Byte returned */
832 			ccc_tgt_payload.data_len =
833 				sizeof(((union i3c_ccc_getmxds *)0)->fmt3.crhdly1);
834 			break;
835 		default:
836 			ret = -EINVAL;
837 			goto out;
838 		}
839 	} else {
840 		ret = -EINVAL;
841 		goto out;
842 	}
843 
844 	memset(&ccc_payload, 0, sizeof(ccc_payload));
845 	ccc_payload.ccc.id = I3C_CCC_GETMXDS;
846 	ccc_payload.targets.payloads = &ccc_tgt_payload;
847 	ccc_payload.targets.num_targets = 1;
848 
849 	if (fmt == GETMXDS_FORMAT_3) {
850 		defining_byte = (uint8_t)defbyte;
851 
852 		ccc_payload.ccc.data = &defining_byte;
853 		ccc_payload.ccc.data_len = 1;
854 	}
855 
856 	ret = i3c_do_ccc(target->bus, &ccc_payload);
857 
858 	if (ret == 0) {
859 		/* GETMXDS will return a variable length */
860 		len = ccc_tgt_payload.num_xfer;
861 
862 		if ((fmt == GETMXDS_FORMAT_1) || (fmt == GETMXDS_FORMAT_2)) {
863 			if (len == sizeof(((union i3c_ccc_getmxds *)0)->fmt1)) {
864 				mxds->fmt1.maxwr = data[0];
865 				mxds->fmt1.maxrd = data[1];
866 				/* It is unknown wither format 1 or format 2 is returned ahead of
867 				 * time
868 				 */
869 				memset(&mxds->fmt2.maxrdturn, 0, sizeof(mxds->fmt2.maxrdturn));
870 			} else if (len == sizeof(((union i3c_ccc_getmxds *)0)->fmt2)) {
871 				mxds->fmt2.maxwr = data[0];
872 				mxds->fmt2.maxrd = data[1];
873 				memcpy(&mxds->fmt2.maxrdturn, &data[2],
874 				       sizeof(mxds->fmt2.maxrdturn));
875 			}
876 		} else if (fmt == GETMXDS_FORMAT_3) {
877 			switch (defbyte) {
878 			case GETMXDS_FORMAT_3_WRRDTURN:
879 				memcpy(mxds->fmt3.wrrdturn, data, len);
880 				/* for values not received, assume default (1'b0) */
881 				memset(&mxds->fmt3.wrrdturn[len], 0,
882 				       sizeof(mxds->fmt3.wrrdturn) - len);
883 				break;
884 			case GETMXDS_FORMAT_3_CRHDLY:
885 				mxds->fmt3.crhdly1 = data[0];
886 				break;
887 			default:
888 				break;
889 			}
890 		}
891 	}
892 
893 out:
894 	return ret;
895 }
896 
i3c_ccc_do_setbuscon(const struct device * controller,uint8_t * context,uint16_t length)897 int i3c_ccc_do_setbuscon(const struct device *controller,
898 				uint8_t *context, uint16_t length)
899 {
900 	struct i3c_ccc_payload ccc_payload;
901 
902 	__ASSERT_NO_MSG(controller != NULL);
903 	__ASSERT_NO_MSG(context != NULL);
904 
905 	memset(&ccc_payload, 0, sizeof(ccc_payload));
906 	ccc_payload.ccc.id = I3C_CCC_SETBUSCON;
907 
908 	ccc_payload.ccc.data = context;
909 	ccc_payload.ccc.data_len = length;
910 
911 	return i3c_do_ccc(controller, &ccc_payload);
912 }
913