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_rstdaa_all(const struct device * controller)105 int i3c_ccc_do_rstdaa_all(const struct device *controller)
106 {
107 	struct i3c_ccc_payload ccc_payload;
108 
109 	__ASSERT_NO_MSG(controller != NULL);
110 
111 	memset(&ccc_payload, 0, sizeof(ccc_payload));
112 	ccc_payload.ccc.id = I3C_CCC_RSTDAA;
113 
114 	return i3c_do_ccc(controller, &ccc_payload);
115 }
116 
i3c_ccc_do_setdasa(const struct i3c_device_desc * target)117 int i3c_ccc_do_setdasa(const struct i3c_device_desc *target)
118 {
119 	struct i3c_driver_data *bus_data = (struct i3c_driver_data *)target->bus->data;
120 	struct i3c_ccc_payload ccc_payload;
121 	struct i3c_ccc_target_payload ccc_tgt_payload;
122 	uint8_t dyn_addr;
123 
124 	__ASSERT_NO_MSG(target != NULL);
125 	__ASSERT_NO_MSG(target->bus != NULL);
126 
127 	if ((target->static_addr == 0U) || (target->dynamic_addr != 0U)) {
128 		return -EINVAL;
129 	}
130 
131 	/*
132 	 * Note that the 7-bit address needs to start at bit 1
133 	 * (aka left-justified). So shift left by 1;
134 	 */
135 	dyn_addr = (target->init_dynamic_addr ?
136 				target->init_dynamic_addr : target->static_addr) << 1;
137 
138 	/* check that initial dynamic address is free before setting it */
139 	if ((target->init_dynamic_addr != 0) &&
140 		(target->init_dynamic_addr != target->static_addr)) {
141 		if (!i3c_addr_slots_is_free(&bus_data->attached_dev.addr_slots, dyn_addr >> 1)) {
142 			return -EINVAL;
143 		}
144 	}
145 
146 	ccc_tgt_payload.addr = target->static_addr;
147 	ccc_tgt_payload.rnw = 0;
148 	ccc_tgt_payload.data = &dyn_addr;
149 	ccc_tgt_payload.data_len = 1;
150 
151 	memset(&ccc_payload, 0, sizeof(ccc_payload));
152 	ccc_payload.ccc.id = I3C_CCC_SETDASA;
153 	ccc_payload.targets.payloads = &ccc_tgt_payload;
154 	ccc_payload.targets.num_targets = 1;
155 
156 	return i3c_do_ccc(target->bus, &ccc_payload);
157 }
158 
i3c_ccc_do_setnewda(const struct i3c_device_desc * target,struct i3c_ccc_address new_da)159 int i3c_ccc_do_setnewda(const struct i3c_device_desc *target, struct i3c_ccc_address new_da)
160 {
161 	struct i3c_driver_data *bus_data = (struct i3c_driver_data *)target->bus->data;
162 	struct i3c_ccc_payload ccc_payload;
163 	struct i3c_ccc_target_payload ccc_tgt_payload;
164 	uint8_t new_dyn_addr;
165 
166 	__ASSERT_NO_MSG(target != NULL);
167 	__ASSERT_NO_MSG(target->bus != NULL);
168 
169 	if (target->dynamic_addr == 0U) {
170 		return -EINVAL;
171 	}
172 
173 	/*
174 	 * Note that the 7-bit address needs to start at bit 1
175 	 * (aka left-justified). So shift left by 1;
176 	 */
177 	new_dyn_addr = new_da.addr << 1;
178 
179 	/* check that initial dynamic address is free before setting it */
180 	if (target->dynamic_addr != new_da.addr) {
181 		if (!i3c_addr_slots_is_free(&bus_data->attached_dev.addr_slots, new_da.addr)) {
182 			return -EINVAL;
183 		}
184 	}
185 
186 	ccc_tgt_payload.addr = target->dynamic_addr;
187 	ccc_tgt_payload.rnw = 0;
188 	ccc_tgt_payload.data = &new_dyn_addr;
189 	ccc_tgt_payload.data_len = 1;
190 
191 	memset(&ccc_payload, 0, sizeof(ccc_payload));
192 	ccc_payload.ccc.id = I3C_CCC_SETNEWDA;
193 	ccc_payload.targets.payloads = &ccc_tgt_payload;
194 	ccc_payload.targets.num_targets = 1;
195 
196 	return i3c_do_ccc(target->bus, &ccc_payload);
197 }
198 
i3c_ccc_do_events_all_set(const struct device * controller,bool enable,struct i3c_ccc_events * events)199 int i3c_ccc_do_events_all_set(const struct device *controller,
200 			      bool enable, struct i3c_ccc_events *events)
201 {
202 	struct i3c_ccc_payload ccc_payload;
203 
204 	__ASSERT_NO_MSG(controller != NULL);
205 
206 	memset(&ccc_payload, 0, sizeof(ccc_payload));
207 
208 	ccc_payload.ccc.id = enable ? I3C_CCC_ENEC(true) : I3C_CCC_DISEC(true);
209 
210 	ccc_payload.ccc.data = &events->events;
211 	ccc_payload.ccc.data_len = sizeof(events->events);
212 
213 	return i3c_do_ccc(controller, &ccc_payload);
214 }
215 
i3c_ccc_do_events_set(struct i3c_device_desc * target,bool enable,struct i3c_ccc_events * events)216 int i3c_ccc_do_events_set(struct i3c_device_desc *target,
217 			  bool enable, struct i3c_ccc_events *events)
218 {
219 	struct i3c_ccc_payload ccc_payload;
220 	struct i3c_ccc_target_payload ccc_tgt_payload;
221 
222 	__ASSERT_NO_MSG(target != NULL);
223 	__ASSERT_NO_MSG(target->bus != NULL);
224 
225 	if (target->dynamic_addr == 0U) {
226 		return -EINVAL;
227 	}
228 
229 	ccc_tgt_payload.addr = target->dynamic_addr;
230 	ccc_tgt_payload.rnw = 0;
231 	ccc_tgt_payload.data = &events->events;
232 	ccc_tgt_payload.data_len = sizeof(events->events);
233 
234 	memset(&ccc_payload, 0, sizeof(ccc_payload));
235 	ccc_payload.ccc.id = enable ? I3C_CCC_ENEC(false) : I3C_CCC_DISEC(false);
236 	ccc_payload.targets.payloads = &ccc_tgt_payload;
237 	ccc_payload.targets.num_targets = 1;
238 
239 	return i3c_do_ccc(target->bus, &ccc_payload);
240 }
241 
i3c_ccc_do_setmwl_all(const struct device * controller,const struct i3c_ccc_mwl * mwl)242 int i3c_ccc_do_setmwl_all(const struct device *controller,
243 			  const struct i3c_ccc_mwl *mwl)
244 {
245 	struct i3c_ccc_payload ccc_payload;
246 	uint8_t data[2];
247 
248 	__ASSERT_NO_MSG(controller != NULL);
249 
250 	memset(&ccc_payload, 0, sizeof(ccc_payload));
251 
252 	ccc_payload.ccc.id = I3C_CCC_SETMWL(true);
253 
254 	ccc_payload.ccc.data = &data[0];
255 	ccc_payload.ccc.data_len = sizeof(data);
256 
257 	/* The actual data is MSB first. So order the data. */
258 	sys_put_be16(mwl->len, data);
259 
260 	return i3c_do_ccc(controller, &ccc_payload);
261 }
262 
i3c_ccc_do_setmwl(const struct i3c_device_desc * target,const struct i3c_ccc_mwl * mwl)263 int i3c_ccc_do_setmwl(const struct i3c_device_desc *target,
264 		      const struct i3c_ccc_mwl *mwl)
265 {
266 	struct i3c_ccc_payload ccc_payload;
267 	struct i3c_ccc_target_payload ccc_tgt_payload;
268 	uint8_t data[2];
269 
270 	__ASSERT_NO_MSG(target != NULL);
271 	__ASSERT_NO_MSG(target->bus != NULL);
272 
273 	memset(&ccc_payload, 0, sizeof(ccc_payload));
274 
275 	ccc_tgt_payload.addr = target->dynamic_addr;
276 	ccc_tgt_payload.rnw = 0;
277 	ccc_tgt_payload.data = &data[0];
278 	ccc_tgt_payload.data_len = sizeof(data);
279 
280 	ccc_payload.ccc.id = I3C_CCC_SETMWL(false);
281 	ccc_payload.targets.payloads = &ccc_tgt_payload;
282 	ccc_payload.targets.num_targets = 1;
283 
284 	/* The actual length is MSB first. So order the data. */
285 	sys_put_be16(mwl->len, data);
286 
287 	return i3c_do_ccc(target->bus, &ccc_payload);
288 }
289 
i3c_ccc_do_getmwl(const struct i3c_device_desc * target,struct i3c_ccc_mwl * mwl)290 int i3c_ccc_do_getmwl(const struct i3c_device_desc *target,
291 		      struct i3c_ccc_mwl *mwl)
292 {
293 	struct i3c_ccc_payload ccc_payload;
294 	struct i3c_ccc_target_payload ccc_tgt_payload;
295 	uint8_t data[2];
296 	int ret;
297 
298 	__ASSERT_NO_MSG(target != NULL);
299 	__ASSERT_NO_MSG(target->bus != NULL);
300 	__ASSERT_NO_MSG(mwl != NULL);
301 
302 	ccc_tgt_payload.addr = target->dynamic_addr;
303 	ccc_tgt_payload.rnw = 1;
304 	ccc_tgt_payload.data = &data[0];
305 	ccc_tgt_payload.data_len = sizeof(data);
306 
307 	memset(&ccc_payload, 0, sizeof(ccc_payload));
308 	ccc_payload.ccc.id = I3C_CCC_GETMWL;
309 	ccc_payload.targets.payloads = &ccc_tgt_payload;
310 	ccc_payload.targets.num_targets = 1;
311 
312 	ret = i3c_do_ccc(target->bus, &ccc_payload);
313 
314 	if (ret == 0) {
315 		/* The actual length is MSB first. So order the data. */
316 		mwl->len = sys_get_be16(data);
317 	}
318 
319 	return ret;
320 }
321 
i3c_ccc_do_setmrl_all(const struct device * controller,const struct i3c_ccc_mrl * mrl,bool has_ibi_size)322 int i3c_ccc_do_setmrl_all(const struct device *controller,
323 			  const struct i3c_ccc_mrl *mrl,
324 			  bool has_ibi_size)
325 {
326 	struct i3c_ccc_payload ccc_payload;
327 	uint8_t data[3];
328 
329 	__ASSERT_NO_MSG(controller != NULL);
330 
331 	memset(&ccc_payload, 0, sizeof(ccc_payload));
332 
333 	ccc_payload.ccc.id = I3C_CCC_SETMRL(true);
334 
335 	ccc_payload.ccc.data = &data[0];
336 	ccc_payload.ccc.data_len = has_ibi_size ? 3 : 2;
337 
338 	/* The actual length is MSB first. So order the data. */
339 	sys_put_be16(mrl->len, data);
340 
341 	if (has_ibi_size) {
342 		data[2] = mrl->ibi_len;
343 	}
344 
345 	return i3c_do_ccc(controller, &ccc_payload);
346 }
347 
i3c_ccc_do_setmrl(const struct i3c_device_desc * target,const struct i3c_ccc_mrl * mrl)348 int i3c_ccc_do_setmrl(const struct i3c_device_desc *target,
349 		      const struct i3c_ccc_mrl *mrl)
350 {
351 	struct i3c_ccc_payload ccc_payload;
352 	struct i3c_ccc_target_payload ccc_tgt_payload;
353 	uint8_t data[3];
354 
355 	__ASSERT_NO_MSG(target != NULL);
356 	__ASSERT_NO_MSG(target->bus != NULL);
357 
358 	memset(&ccc_payload, 0, sizeof(ccc_payload));
359 
360 	ccc_tgt_payload.addr = target->dynamic_addr;
361 	ccc_tgt_payload.rnw = 0;
362 	ccc_tgt_payload.data = &data[0];
363 
364 	ccc_payload.ccc.id = I3C_CCC_SETMRL(false);
365 	ccc_payload.targets.payloads = &ccc_tgt_payload;
366 	ccc_payload.targets.num_targets = 1;
367 
368 	/* The actual length is MSB first. So order the data. */
369 	sys_put_be16(mrl->len, data);
370 
371 	if ((target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
372 	    == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE) {
373 		ccc_tgt_payload.data_len = 3;
374 
375 		data[2] = mrl->ibi_len;
376 	} else {
377 		ccc_tgt_payload.data_len = 2;
378 	}
379 
380 	return i3c_do_ccc(target->bus, &ccc_payload);
381 }
382 
i3c_ccc_do_getmrl(const struct i3c_device_desc * target,struct i3c_ccc_mrl * mrl)383 int i3c_ccc_do_getmrl(const struct i3c_device_desc *target,
384 		      struct i3c_ccc_mrl *mrl)
385 {
386 	struct i3c_ccc_payload ccc_payload;
387 	struct i3c_ccc_target_payload ccc_tgt_payload;
388 	uint8_t data[3];
389 	bool has_ibi_sz;
390 	int ret;
391 
392 	__ASSERT_NO_MSG(target != NULL);
393 	__ASSERT_NO_MSG(target->bus != NULL);
394 	__ASSERT_NO_MSG(mrl != NULL);
395 
396 	has_ibi_sz = (target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
397 		     == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE;
398 
399 	ccc_tgt_payload.addr = target->dynamic_addr;
400 	ccc_tgt_payload.rnw = 1;
401 	ccc_tgt_payload.data = &data[0];
402 	ccc_tgt_payload.data_len = has_ibi_sz ? 3 : 2;
403 
404 	memset(&ccc_payload, 0, sizeof(ccc_payload));
405 	ccc_payload.ccc.id = I3C_CCC_GETMRL;
406 	ccc_payload.targets.payloads = &ccc_tgt_payload;
407 	ccc_payload.targets.num_targets = 1;
408 
409 	ret = i3c_do_ccc(target->bus, &ccc_payload);
410 
411 	if (ret == 0) {
412 		/* The actual length is MSB first. So order the data. */
413 		mrl->len = sys_get_be16(data);
414 
415 		if (has_ibi_sz) {
416 			mrl->ibi_len = data[2];
417 		}
418 	}
419 
420 	return ret;
421 }
422 
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)423 int i3c_ccc_do_getstatus(const struct i3c_device_desc *target,
424 			 union i3c_ccc_getstatus *status,
425 			 enum i3c_ccc_getstatus_fmt fmt,
426 			 enum i3c_ccc_getstatus_defbyte defbyte)
427 {
428 	struct i3c_ccc_payload ccc_payload;
429 	struct i3c_ccc_target_payload ccc_tgt_payload;
430 	uint8_t defining_byte;
431 	uint8_t data[2];
432 	int ret;
433 
434 	__ASSERT_NO_MSG(target != NULL);
435 	__ASSERT_NO_MSG(target->bus != NULL);
436 	__ASSERT_NO_MSG(status != NULL);
437 
438 	ccc_tgt_payload.addr = target->dynamic_addr;
439 	ccc_tgt_payload.rnw = 1;
440 	ccc_tgt_payload.data = &data[0];
441 
442 	if (fmt == GETSTATUS_FORMAT_1) {
443 		ccc_tgt_payload.data_len = 2;
444 	} else if (fmt == GETSTATUS_FORMAT_2) {
445 		switch (defbyte) {
446 		case GETSTATUS_FORMAT_2_TGTSTAT:
447 			__fallthrough;
448 		case GETSTATUS_FORMAT_2_PRECR:
449 			ccc_tgt_payload.data_len = 2;
450 			break;
451 		default:
452 			ret = -EINVAL;
453 			goto out;
454 		}
455 	} else {
456 		ret = -EINVAL;
457 		goto out;
458 	}
459 
460 	memset(&ccc_payload, 0, sizeof(ccc_payload));
461 	ccc_payload.ccc.id = I3C_CCC_GETSTATUS;
462 	ccc_payload.targets.payloads = &ccc_tgt_payload;
463 	ccc_payload.targets.num_targets = 1;
464 
465 	if (fmt == GETSTATUS_FORMAT_2) {
466 		defining_byte = (uint8_t)defbyte;
467 
468 		ccc_payload.ccc.data = &defining_byte;
469 		ccc_payload.ccc.data_len = 1;
470 	}
471 
472 	ret = i3c_do_ccc(target->bus, &ccc_payload);
473 
474 	if (ret == 0) {
475 		/* Received data is MSB first. So order the data. */
476 		if (fmt == GETSTATUS_FORMAT_1) {
477 			status->fmt1.status = sys_get_be16(data);
478 		} else if (fmt == GETSTATUS_FORMAT_2) {
479 			switch (defbyte) {
480 			case GETSTATUS_FORMAT_2_TGTSTAT:
481 				__fallthrough;
482 			case GETSTATUS_FORMAT_2_PRECR:
483 				status->fmt2.raw_u16 = sys_get_be16(data);
484 				break;
485 			default:
486 				break;
487 			}
488 		}
489 	}
490 
491 out:
492 	return ret;
493 }
494 
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)495 int i3c_ccc_do_getcaps(const struct i3c_device_desc *target,
496 			 union i3c_ccc_getcaps *caps,
497 			 enum i3c_ccc_getcaps_fmt fmt,
498 			 enum i3c_ccc_getcaps_defbyte defbyte)
499 {
500 	struct i3c_ccc_payload ccc_payload;
501 	struct i3c_ccc_target_payload ccc_tgt_payload;
502 	uint8_t defining_byte;
503 	uint8_t data[4];
504 	uint8_t len;
505 	int ret;
506 
507 	__ASSERT_NO_MSG(target != NULL);
508 	__ASSERT_NO_MSG(target->bus != NULL);
509 	__ASSERT_NO_MSG(caps != NULL);
510 
511 	ccc_tgt_payload.addr = target->dynamic_addr;
512 	ccc_tgt_payload.rnw = 1;
513 	ccc_tgt_payload.data = &data[0];
514 
515 	if (fmt == GETCAPS_FORMAT_1) {
516 		/* Could be 1-4 Data Bytes Returned */
517 		ccc_tgt_payload.data_len = 4;
518 	} else if (fmt == GETCAPS_FORMAT_2) {
519 		switch (defbyte) {
520 		case GETCAPS_FORMAT_2_CRCAPS:
521 			__fallthrough;
522 		case GETCAPS_FORMAT_2_VTCAPS:
523 			/* Could be 1-2 Data Bytes Returned*/
524 			ccc_tgt_payload.data_len = 2;
525 			break;
526 		case GETCAPS_FORMAT_2_TGTCAPS:
527 			__fallthrough;
528 		case GETCAPS_FORMAT_2_TESTPAT:
529 			/* Could be 1-4 Data Bytes Returned */
530 			ccc_tgt_payload.data_len = 4;
531 			break;
532 		default:
533 			ret = -EINVAL;
534 			goto out;
535 		}
536 	} else {
537 		ret = -EINVAL;
538 		goto out;
539 	}
540 
541 	memset(&ccc_payload, 0, sizeof(ccc_payload));
542 	ccc_payload.ccc.id = I3C_CCC_GETCAPS;
543 	ccc_payload.targets.payloads = &ccc_tgt_payload;
544 	ccc_payload.targets.num_targets = 1;
545 
546 	if (fmt == GETCAPS_FORMAT_2) {
547 		defining_byte = (uint8_t)defbyte;
548 
549 		ccc_payload.ccc.data = &defining_byte;
550 		ccc_payload.ccc.data_len = 1;
551 	}
552 
553 	ret = i3c_do_ccc(target->bus, &ccc_payload);
554 
555 	if (ret == 0) {
556 		/* GETCAPS will return a variable length */
557 		len = ccc_tgt_payload.num_xfer;
558 
559 		if (fmt == GETCAPS_FORMAT_1) {
560 			memcpy(caps->fmt1.getcaps, data, len);
561 			/* for values not received, assume default (1'b0) */
562 			memset(&caps->fmt1.getcaps[len], 0, sizeof(caps->fmt1.getcaps) - len);
563 		} else if (fmt == GETCAPS_FORMAT_2) {
564 			switch (defbyte) {
565 			case GETCAPS_FORMAT_2_CRCAPS:
566 				memcpy(caps->fmt2.crcaps, data, len);
567 				/* for values not received, assume default (1'b0) */
568 				memset(&caps->fmt2.crcaps[len], 0, sizeof(caps->fmt2.crcaps) - len);
569 				break;
570 			case GETCAPS_FORMAT_2_VTCAPS:
571 				memcpy(caps->fmt2.vtcaps, data, len);
572 				/* for values not received, assume default (1'b0) */
573 				memset(&caps->fmt2.vtcaps[len], 0, sizeof(caps->fmt2.vtcaps) - len);
574 				break;
575 			case GETCAPS_FORMAT_2_TGTCAPS:
576 				memcpy(caps->fmt2.tgtcaps, data, len);
577 				/* for values not received, assume default (1'b0) */
578 				memset(&caps->fmt2.tgtcaps[len], 0,
579 				       sizeof(caps->fmt2.tgtcaps) - len);
580 				break;
581 			case GETCAPS_FORMAT_2_TESTPAT:
582 				/* should always be 4 data bytes */
583 				caps->fmt2.testpat = sys_get_be32(data);
584 				break;
585 			default:
586 				break;
587 			}
588 		}
589 	}
590 
591 out:
592 	return ret;
593 }
594