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/__assert.h>
11 #include <zephyr/sys/slist.h>
12 
13 #include <zephyr/drivers/i3c.h>
14 
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(i3c, CONFIG_I3C_LOG_LEVEL);
17 
i3c_dump_msgs(const char * name,const struct i3c_msg * msgs,uint8_t num_msgs,struct i3c_device_desc * target)18 void i3c_dump_msgs(const char *name, const struct i3c_msg *msgs,
19 		   uint8_t num_msgs, struct i3c_device_desc *target)
20 {
21 	LOG_DBG("I3C msg: %s, addr=%x", name, target->dynamic_addr);
22 	for (unsigned int i = 0; i < num_msgs; i++) {
23 		const struct i3c_msg *msg = &msgs[i];
24 
25 		LOG_DBG("   %c len=%02x: ",
26 			msg->flags & I3C_MSG_READ ? 'R' : 'W', msg->len);
27 		if (!(msg->flags & I3C_MSG_READ)) {
28 			LOG_HEXDUMP_DBG(msg->buf, msg->len, "contents:");
29 		}
30 	}
31 }
32 
i3c_addr_slots_set(struct i3c_addr_slots * slots,uint8_t dev_addr,enum i3c_addr_slot_status status)33 void i3c_addr_slots_set(struct i3c_addr_slots *slots,
34 			uint8_t dev_addr,
35 			enum i3c_addr_slot_status status)
36 {
37 	int bitpos;
38 	int idx;
39 
40 	__ASSERT_NO_MSG(slots != NULL);
41 
42 	if (dev_addr > I3C_MAX_ADDR) {
43 		/* Invalid address. Do nothing. */
44 		return;
45 	}
46 
47 	bitpos = dev_addr * 2;
48 	idx = bitpos / BITS_PER_LONG;
49 
50 	slots->slots[idx] &= ~((unsigned long)I3C_ADDR_SLOT_STATUS_MASK <<
51 			       (bitpos % BITS_PER_LONG));
52 	slots->slots[idx] |= status << (bitpos % BITS_PER_LONG);
53 }
54 
55 enum i3c_addr_slot_status
i3c_addr_slots_status(struct i3c_addr_slots * slots,uint8_t dev_addr)56 i3c_addr_slots_status(struct i3c_addr_slots *slots,
57 		      uint8_t dev_addr)
58 {
59 	unsigned long status;
60 	int bitpos;
61 	int idx;
62 
63 	__ASSERT_NO_MSG(slots != NULL);
64 
65 	if (dev_addr > I3C_MAX_ADDR) {
66 		/* Invalid address.
67 		 * Simply says it's reserved so it will not be
68 		 * used for anything.
69 		 */
70 		return I3C_ADDR_SLOT_STATUS_RSVD;
71 	}
72 
73 	bitpos = dev_addr * 2;
74 	idx = bitpos / BITS_PER_LONG;
75 
76 	status = slots->slots[idx] >> (bitpos % BITS_PER_LONG);
77 	status &= I3C_ADDR_SLOT_STATUS_MASK;
78 
79 	return status;
80 }
81 
82 
i3c_addr_slots_init(const struct device * dev)83 int i3c_addr_slots_init(const struct device *dev)
84 {
85 	struct i3c_driver_data *data =
86 		(struct i3c_driver_data *)dev->data;
87 	const struct i3c_driver_config *config =
88 		(const struct i3c_driver_config *)dev->config;
89 	int i, ret = 0;
90 	struct i3c_device_desc *i3c_dev;
91 	struct i3c_i2c_device_desc *i2c_dev;
92 
93 	__ASSERT_NO_MSG(dev != NULL);
94 
95 	(void)memset(&data->attached_dev.addr_slots, 0, sizeof(data->attached_dev.addr_slots));
96 	sys_slist_init(&data->attached_dev.devices.i3c);
97 	sys_slist_init(&data->attached_dev.devices.i2c);
98 
99 	for (i = 0; i <= 7; i++) {
100 		/* Addresses 0 to 7 are reserved */
101 		i3c_addr_slots_set(&data->attached_dev.addr_slots, i, I3C_ADDR_SLOT_STATUS_RSVD);
102 
103 		/*
104 		 * Addresses within a single bit error of broadcast address
105 		 * are also reserved.
106 		 */
107 		i3c_addr_slots_set(&data->attached_dev.addr_slots, I3C_BROADCAST_ADDR ^ BIT(i),
108 				   I3C_ADDR_SLOT_STATUS_RSVD);
109 
110 	}
111 
112 	/* The broadcast address is reserved */
113 	i3c_addr_slots_set(&data->attached_dev.addr_slots, I3C_BROADCAST_ADDR,
114 			   I3C_ADDR_SLOT_STATUS_RSVD);
115 
116 	/*
117 	 * Mark all I2C addresses first.
118 	 */
119 	for (i = 0; i < config->dev_list.num_i2c; i++) {
120 		i2c_dev = &config->dev_list.i2c[i];
121 		ret = i3c_attach_i2c_device(i2c_dev);
122 		if (ret != 0) {
123 			/* Address slot is not free */
124 			ret = -EINVAL;
125 			goto out;
126 		}
127 	}
128 
129 	/*
130 	 * If there is a static address for the I3C devices, check
131 	 * if this address is free, and there is no other devices of
132 	 * the same (pre-assigned) address on the bus.
133 	 */
134 	for (i = 0; i < config->dev_list.num_i3c; i++) {
135 		i3c_dev = &config->dev_list.i3c[i];
136 		ret = i3c_attach_i3c_device(i3c_dev);
137 		if (ret != 0) {
138 			/* Address slot is not free */
139 			ret = -EINVAL;
140 			goto out;
141 		}
142 	}
143 
144 out:
145 	return ret;
146 }
147 
i3c_addr_slots_is_free(struct i3c_addr_slots * slots,uint8_t dev_addr)148 bool i3c_addr_slots_is_free(struct i3c_addr_slots *slots,
149 			    uint8_t dev_addr)
150 {
151 	enum i3c_addr_slot_status status;
152 
153 	__ASSERT_NO_MSG(slots != NULL);
154 
155 	status = i3c_addr_slots_status(slots, dev_addr);
156 
157 	return (status == I3C_ADDR_SLOT_STATUS_FREE);
158 }
159 
i3c_addr_slots_next_free_find(struct i3c_addr_slots * slots,uint8_t start_addr)160 uint8_t i3c_addr_slots_next_free_find(struct i3c_addr_slots *slots, uint8_t start_addr)
161 {
162 	uint8_t addr;
163 	enum i3c_addr_slot_status status;
164 
165 	/* Addresses 0 to 7 are reserved. So start at 8. */
166 	for (addr = MAX(start_addr, 8); addr < I3C_MAX_ADDR; addr++) {
167 		status = i3c_addr_slots_status(slots, addr);
168 		if (status == I3C_ADDR_SLOT_STATUS_FREE) {
169 			return addr;
170 		}
171 	}
172 
173 	return 0;
174 }
175 
i3c_dev_list_find(const struct i3c_dev_list * dev_list,const struct i3c_device_id * id)176 struct i3c_device_desc *i3c_dev_list_find(const struct i3c_dev_list *dev_list,
177 					  const struct i3c_device_id *id)
178 {
179 	int i;
180 	struct i3c_device_desc *ret = NULL;
181 
182 	__ASSERT_NO_MSG(dev_list != NULL);
183 
184 	/* this only searches known I3C PIDs */
185 	for (i = 0; i < dev_list->num_i3c; i++) {
186 		struct i3c_device_desc *desc = &dev_list->i3c[i];
187 
188 		if (desc->pid == id->pid) {
189 			ret = desc;
190 			break;
191 		}
192 	}
193 
194 	return ret;
195 }
196 
i3c_dev_list_i3c_addr_find(struct i3c_dev_attached_list * dev_list,uint8_t addr)197 struct i3c_device_desc *i3c_dev_list_i3c_addr_find(struct i3c_dev_attached_list *dev_list,
198 						   uint8_t addr)
199 {
200 	sys_snode_t *node;
201 	struct i3c_device_desc *ret = NULL;
202 
203 	__ASSERT_NO_MSG(dev_list != NULL);
204 
205 	SYS_SLIST_FOR_EACH_NODE(&dev_list->devices.i3c, node) {
206 		struct i3c_device_desc *desc = (void *)node;
207 
208 		if (desc->dynamic_addr == addr) {
209 			ret = desc;
210 			break;
211 		}
212 	}
213 
214 	return ret;
215 }
216 
i3c_dev_list_i2c_addr_find(struct i3c_dev_attached_list * dev_list,uint16_t addr)217 struct i3c_i2c_device_desc *i3c_dev_list_i2c_addr_find(struct i3c_dev_attached_list *dev_list,
218 							   uint16_t addr)
219 {
220 	sys_snode_t *node;
221 	struct i3c_i2c_device_desc *ret = NULL;
222 
223 	__ASSERT_NO_MSG(dev_list != NULL);
224 
225 	SYS_SLIST_FOR_EACH_NODE(&dev_list->devices.i2c, node) {
226 		struct i3c_i2c_device_desc *desc = (void *)node;
227 
228 		if (desc->addr == addr) {
229 			ret = desc;
230 			break;
231 		}
232 	}
233 
234 	return ret;
235 }
236 
i3c_determine_default_addr(struct i3c_device_desc * target,uint8_t * addr)237 int i3c_determine_default_addr(struct i3c_device_desc *target, uint8_t *addr)
238 {
239 	struct i3c_driver_data *data = (struct i3c_driver_data *)target->bus->data;
240 
241 	/* If dynamic addr is set, then it assumed that it was assigned by a primary controller */
242 	if (target->dynamic_addr == 0) {
243 		/* It is assumed that SETDASA or ENTDAA will be run after this */
244 		if (target->init_dynamic_addr != 0U) {
245 			/* initial dynamic address is requested */
246 			if (target->static_addr == 0) {
247 				/* SA is set to 0, so DA will be set with ENTDAA */
248 				if (i3c_addr_slots_is_free(&data->attached_dev.addr_slots,
249 							   target->init_dynamic_addr)) {
250 					/* Set DA during ENTDAA */
251 					*addr = target->init_dynamic_addr;
252 				} else {
253 					/* address is not free, get the next one */
254 					*addr = i3c_addr_slots_next_free_find(
255 						&data->attached_dev.addr_slots, 0);
256 				}
257 			} else {
258 				/* Use the init dynamic address as it's DA, but the RR will need to
259 				 * be first set with it's SA to run SETDASA, the RR address will
260 				 * need be updated after SETDASA with the request dynamic address
261 				 */
262 				if (i3c_addr_slots_is_free(&data->attached_dev.addr_slots,
263 							   target->static_addr)) {
264 					*addr = target->static_addr;
265 				} else {
266 					/* static address has already been taken */
267 					return -EINVAL;
268 				}
269 			}
270 		} else {
271 			/* no init dynamic address is requested */
272 			if (target->static_addr != 0) {
273 				if (i3c_addr_slots_is_free(&data->attached_dev.addr_slots,
274 							   target->static_addr)) {
275 					/* static exists, set DA with same SA during SETDASA*/
276 					*addr = target->static_addr;
277 				} else {
278 					/* static address has already been taken */
279 					return -EINVAL;
280 				}
281 			} else {
282 				/* pick a DA to use */
283 				*addr = i3c_addr_slots_next_free_find(
284 					&data->attached_dev.addr_slots, 0);
285 			}
286 		}
287 	} else {
288 		*addr = target->dynamic_addr;
289 	}
290 
291 	return 0;
292 }
293 
i3c_attach_i3c_device(struct i3c_device_desc * target)294 int i3c_attach_i3c_device(struct i3c_device_desc *target)
295 {
296 	struct i3c_driver_data *data = (struct i3c_driver_data *)target->bus->data;
297 	const struct i3c_driver_api *api = (const struct i3c_driver_api *)target->bus->api;
298 	sys_snode_t *node;
299 	uint8_t addr = 0;
300 	int status = 0;
301 
302 	/* check to see if the device has already been attached */
303 	if (!sys_slist_is_empty(&data->attached_dev.devices.i3c)) {
304 		SYS_SLIST_FOR_EACH_NODE(&data->attached_dev.devices.i3c, node) {
305 			if (node == &target->node) {
306 				return -EINVAL;
307 			}
308 		}
309 	}
310 
311 	status = i3c_determine_default_addr(target, &addr);
312 	if (status != 0) {
313 		return status;
314 	}
315 
316 	sys_slist_append(&data->attached_dev.devices.i3c, &target->node);
317 
318 	if (api->attach_i3c_device != NULL) {
319 		status = api->attach_i3c_device(target->bus, target, addr);
320 	}
321 
322 	i3c_addr_slots_mark_i3c(&data->attached_dev.addr_slots, addr);
323 
324 	return status;
325 }
326 
i3c_reattach_i3c_device(struct i3c_device_desc * target,uint8_t old_dyn_addr)327 int i3c_reattach_i3c_device(struct i3c_device_desc *target, uint8_t old_dyn_addr)
328 {
329 	struct i3c_driver_data *data = (struct i3c_driver_data *)target->bus->data;
330 	const struct i3c_driver_api *api = (const struct i3c_driver_api *)target->bus->api;
331 	int status = 0;
332 
333 	if (!i3c_addr_slots_is_free(&data->attached_dev.addr_slots, target->dynamic_addr)) {
334 		return -EINVAL;
335 	}
336 
337 	if (api->reattach_i3c_device != NULL) {
338 		status = api->reattach_i3c_device(target->bus, target, old_dyn_addr);
339 	}
340 
341 	if (old_dyn_addr) {
342 		/* mark the old address as free */
343 		i3c_addr_slots_mark_free(&data->attached_dev.addr_slots, old_dyn_addr);
344 	}
345 
346 	i3c_addr_slots_mark_i3c(&data->attached_dev.addr_slots, target->dynamic_addr);
347 
348 	return status;
349 }
350 
i3c_detach_i3c_device(struct i3c_device_desc * target)351 int i3c_detach_i3c_device(struct i3c_device_desc *target)
352 {
353 	struct i3c_driver_data *data = (struct i3c_driver_data *)target->bus->data;
354 	const struct i3c_driver_api *api = (const struct i3c_driver_api *)target->bus->api;
355 	int status = 0;
356 
357 	if (!sys_slist_is_empty(&data->attached_dev.devices.i3c)) {
358 		if (!sys_slist_find_and_remove(&data->attached_dev.devices.i3c, &target->node)) {
359 			return -EINVAL;
360 		}
361 	} else {
362 		return -EINVAL;
363 	}
364 
365 	if (api->detach_i3c_device != NULL) {
366 		status = api->detach_i3c_device(target->bus, target);
367 	}
368 
369 	i3c_addr_slots_mark_free(&data->attached_dev.addr_slots,
370 				 target->dynamic_addr ? target->dynamic_addr : target->static_addr);
371 
372 	return status;
373 }
374 
i3c_attach_i2c_device(struct i3c_i2c_device_desc * target)375 int i3c_attach_i2c_device(struct i3c_i2c_device_desc *target)
376 {
377 	struct i3c_driver_data *data = (struct i3c_driver_data *)target->bus->data;
378 	const struct i3c_driver_api *api = (const struct i3c_driver_api *)target->bus->api;
379 	sys_snode_t *node;
380 	int status = 0;
381 
382 	/* check to see if the device has already been attached */
383 	if (!sys_slist_is_empty(&data->attached_dev.devices.i2c)) {
384 		SYS_SLIST_FOR_EACH_NODE(&data->attached_dev.devices.i2c, node) {
385 			if (node == &target->node) {
386 				return -EINVAL;
387 			}
388 		}
389 	}
390 
391 	if (!i3c_addr_slots_is_free(&data->attached_dev.addr_slots, target->addr)) {
392 		return -EINVAL;
393 	}
394 
395 	sys_slist_append(&data->attached_dev.devices.i2c, &target->node);
396 
397 	if (api->attach_i2c_device != NULL) {
398 		status = api->attach_i2c_device(target->bus, target);
399 	}
400 
401 	i3c_addr_slots_mark_i2c(&data->attached_dev.addr_slots, target->addr);
402 
403 	return status;
404 }
405 
i3c_detach_i2c_device(struct i3c_i2c_device_desc * target)406 int i3c_detach_i2c_device(struct i3c_i2c_device_desc *target)
407 {
408 	struct i3c_driver_data *data = (struct i3c_driver_data *)target->bus->data;
409 	const struct i3c_driver_api *api = (const struct i3c_driver_api *)target->bus->api;
410 	int status = 0;
411 
412 	if (!sys_slist_is_empty(&data->attached_dev.devices.i2c)) {
413 		if (!sys_slist_find_and_remove(&data->attached_dev.devices.i2c, &target->node)) {
414 			return -EINVAL;
415 		}
416 	} else {
417 		return -EINVAL;
418 	}
419 
420 	if (api->detach_i2c_device != NULL) {
421 		status = api->detach_i2c_device(target->bus, target);
422 	}
423 
424 	i3c_addr_slots_mark_free(&data->attached_dev.addr_slots, target->addr);
425 
426 	return status;
427 }
428 
i3c_dev_list_daa_addr_helper(struct i3c_addr_slots * addr_slots,const struct i3c_dev_list * dev_list,uint64_t pid,bool must_match,bool assigned_okay,struct i3c_device_desc ** target,uint8_t * addr)429 int i3c_dev_list_daa_addr_helper(struct i3c_addr_slots *addr_slots,
430 				 const struct i3c_dev_list *dev_list,
431 				 uint64_t pid, bool must_match,
432 				 bool assigned_okay,
433 				 struct i3c_device_desc **target,
434 				 uint8_t *addr)
435 {
436 	struct i3c_device_desc *desc;
437 	const uint16_t vendor_id = (uint16_t)(pid >> 32);
438 	const uint32_t part_no = (uint32_t)(pid & 0xFFFFFFFFU);
439 	uint8_t dyn_addr = 0;
440 	int ret = 0;
441 	const struct i3c_device_id i3c_id = I3C_DEVICE_ID(pid);
442 
443 	desc = i3c_dev_list_find(dev_list, &i3c_id);
444 	if (must_match && (desc == NULL)) {
445 		/*
446 		 * No device descriptor matching incoming PID and
447 		 * that we want an exact match.
448 		 */
449 		ret = -ENODEV;
450 
451 		LOG_DBG("PID 0x%04x%08x is not in registered device list",
452 			vendor_id, part_no);
453 
454 		goto out;
455 	}
456 
457 	if (desc->dynamic_addr != 0U) {
458 		if (assigned_okay) {
459 			/* Return the already assigned address if desired so. */
460 			dyn_addr = desc->dynamic_addr;
461 			goto out;
462 		} else {
463 			/*
464 			 * Bail If target already has an assigned address.
465 			 * This is probably due to having the same PIDs for multiple targets
466 			 * in the device tree.
467 			 */
468 			LOG_ERR("PID 0x%04x%08x already has "
469 				"dynamic address (0x%02x) assigned",
470 				vendor_id, part_no, desc->dynamic_addr);
471 			ret = -EINVAL;
472 			goto err;
473 		}
474 	}
475 
476 	/*
477 	 * Use the desired dynamic address as the new dynamic address
478 	 * if the slot is free.
479 	 */
480 	if (desc->init_dynamic_addr != 0U) {
481 		if (i3c_addr_slots_is_free(addr_slots,
482 					   desc->init_dynamic_addr)) {
483 			dyn_addr = desc->init_dynamic_addr;
484 			goto out;
485 		}
486 	}
487 
488 	/*
489 	 * Find the next available address.
490 	 */
491 	dyn_addr = i3c_addr_slots_next_free_find(addr_slots, 0);
492 
493 	if (dyn_addr == 0U) {
494 		/* No free addresses available */
495 		LOG_DBG("No more free addresses available.");
496 		ret = -ENOSPC;
497 	}
498 
499 out:
500 	*addr = dyn_addr;
501 	*target = desc;
502 
503 err:
504 	return ret;
505 }
506 
i3c_device_basic_info_get(struct i3c_device_desc * target)507 int i3c_device_basic_info_get(struct i3c_device_desc *target)
508 {
509 	int ret;
510 	uint8_t tmp_bcr;
511 
512 	struct i3c_ccc_getbcr bcr = {0};
513 	struct i3c_ccc_getdcr dcr = {0};
514 	struct i3c_ccc_mrl mrl = {0};
515 	struct i3c_ccc_mwl mwl = {0};
516 
517 	/*
518 	 * Since some CCC functions requires BCR to function
519 	 * correctly, we save the BCR here and update the BCR
520 	 * in the descriptor. If any following operations fails,
521 	 * we can restore the BCR.
522 	 */
523 	tmp_bcr = target->bcr;
524 
525 	/* GETBCR */
526 	ret = i3c_ccc_do_getbcr(target, &bcr);
527 	if (ret != 0) {
528 		goto out;
529 	}
530 
531 	target->bcr = bcr.bcr;
532 
533 	/* GETDCR */
534 	ret = i3c_ccc_do_getdcr(target, &dcr);
535 	if (ret != 0) {
536 		goto out;
537 	}
538 
539 	/* GETMRL */
540 	if (i3c_ccc_do_getmrl(target, &mrl) != 0) {
541 		/* GETMRL may be optionally supported if no settable limit */
542 		LOG_DBG("No settable limit for GETMRL");
543 	}
544 
545 	/* GETMWL */
546 	if (i3c_ccc_do_getmwl(target, &mwl) != 0) {
547 		/* GETMWL may be optionally supported if no settable limit */
548 		LOG_DBG("No settable limit for GETMWL");
549 	}
550 
551 	target->dcr = dcr.dcr;
552 	target->data_length.mrl = mrl.len;
553 	target->data_length.mwl = mwl.len;
554 	target->data_length.max_ibi = mrl.ibi_len;
555 
556 out:
557 	if (ret != 0) {
558 		/* Restore BCR is any CCC fails. */
559 		target->bcr = tmp_bcr;
560 	}
561 	return ret;
562 }
563 
564 /**
565  * @brief Do SETDASA to set static address as dynamic address.
566  *
567  * @param dev Pointer to the device driver instance.
568  * @param[out] True if DAA is still needed. False if all registered
569  *             devices have static addresses.
570  *
571  * @retval 0 if successful.
572  */
i3c_bus_setdasa(const struct device * dev,const struct i3c_dev_list * dev_list,bool * need_daa)573 static int i3c_bus_setdasa(const struct device *dev,
574 			   const struct i3c_dev_list *dev_list,
575 			   bool *need_daa)
576 {
577 	int i, ret;
578 
579 	*need_daa = false;
580 
581 	/* Loop through the registered I3C devices */
582 	for (i = 0; i < dev_list->num_i3c; i++) {
583 		struct i3c_device_desc *desc = &dev_list->i3c[i];
584 
585 		/*
586 		 * A device without static address => need to do
587 		 * dynamic address assignment.
588 		 */
589 		if (desc->static_addr == 0U) {
590 			*need_daa = true;
591 			continue;
592 		}
593 
594 		LOG_DBG("SETDASA for 0x%x", desc->static_addr);
595 
596 		ret = i3c_ccc_do_setdasa(desc);
597 		if (ret == 0) {
598 			desc->dynamic_addr = (desc->init_dynamic_addr ? desc->init_dynamic_addr
599 								      : desc->static_addr);
600 			if (desc->dynamic_addr != desc->static_addr) {
601 				if (i3c_reattach_i3c_device(desc, desc->static_addr) != 0) {
602 					LOG_ERR("Failed to reattach %s (%d)", desc->dev->name, ret);
603 				}
604 			}
605 		} else {
606 			/* SETDASA failed, detach it from the controller */
607 			if (i3c_detach_i3c_device(desc) != 0) {
608 				LOG_ERR("Failed to detach %s (%d)", desc->dev->name, ret);
609 			}
610 			LOG_ERR("SETDASA error on address 0x%x (%d)",
611 				desc->static_addr, ret);
612 			continue;
613 		}
614 	}
615 
616 	return 0;
617 }
618 
i3c_bus_init(const struct device * dev,const struct i3c_dev_list * dev_list)619 int i3c_bus_init(const struct device *dev, const struct i3c_dev_list *dev_list)
620 {
621 	int i, ret = 0;
622 	bool need_daa = true;
623 	struct i3c_ccc_events i3c_events;
624 
625 	/*
626 	 * Reset all connected targets. Also reset dynamic
627 	 * addresses for all devices as we have no idea what
628 	 * dynamic addresses the connected devices have
629 	 * (e.g. assigned during previous power cycle).
630 	 *
631 	 * Note that we ignore error for both RSTACT and RSTDAA
632 	 * as there may not be any connected devices responding
633 	 * to these CCCs.
634 	 */
635 	if (i3c_ccc_do_rstact_all(dev, I3C_CCC_RSTACT_RESET_WHOLE_TARGET) != 0) {
636 		/*
637 		 * Reset Whole Target support is not required so
638 		 * if there is any NACK, we want to at least reset
639 		 * the I3C peripheral of targets.
640 		 */
641 		LOG_DBG("Broadcast RSTACT (whole target) was NACK.");
642 
643 		if (i3c_ccc_do_rstact_all(dev, I3C_CCC_RSTACT_PERIPHERAL_ONLY) != 0) {
644 			LOG_DBG("Broadcast RSTACT (peripehral) was NACK.");
645 		}
646 	}
647 
648 	if (i3c_ccc_do_rstdaa_all(dev) != 0) {
649 		LOG_DBG("Broadcast RSTDAA was NACK.");
650 	}
651 
652 	/*
653 	 * Disable all events from targets to avoid them
654 	 * interfering with bus initialization,
655 	 * especially during DAA.
656 	 */
657 	i3c_events.events = I3C_CCC_EVT_ALL;
658 	ret = i3c_ccc_do_events_all_set(dev, false, &i3c_events);
659 	if (ret != 0) {
660 		LOG_DBG("Broadcast DISEC was NACK.");
661 	}
662 
663 	/*
664 	 * Set static addresses as dynamic addresses.
665 	 */
666 	ret = i3c_bus_setdasa(dev, dev_list, &need_daa);
667 	if (ret != 0) {
668 		goto err_out;
669 	}
670 
671 	/*
672 	 * Perform Dynamic Address Assignment if needed.
673 	 */
674 	if (need_daa) {
675 		ret = i3c_do_daa(dev);
676 		if (ret != 0) {
677 			/*
678 			 * Spec says to try once more
679 			 * if DAA fails the first time.
680 			 */
681 			ret = i3c_do_daa(dev);
682 			if (ret != 0) {
683 				/*
684 				 * Failure to finish dynamic address assignment
685 				 * is not the end of world... hopefully.
686 				 * Continue on so the devices already have
687 				 * addresses can still function.
688 				 */
689 				LOG_ERR("DAA was not successful.");
690 			}
691 		}
692 	}
693 
694 	/*
695 	 * Loop through the registered I3C devices to retrieve
696 	 * basic target information.
697 	 */
698 	for (i = 0; i < dev_list->num_i3c; i++) {
699 		struct i3c_device_desc *desc = &dev_list->i3c[i];
700 
701 		if (desc->dynamic_addr == 0U) {
702 			continue;
703 		}
704 
705 		ret = i3c_device_basic_info_get(desc);
706 		if (ret != 0) {
707 			LOG_ERR("Error getting basic device info for 0x%02x",
708 				desc->static_addr);
709 		} else {
710 			LOG_DBG("Target 0x%02x, BCR 0x%02x, DCR 0x%02x, MRL %d, MWL %d, IBI %d",
711 				desc->dynamic_addr, desc->bcr, desc->dcr,
712 				desc->data_length.mrl, desc->data_length.mwl,
713 				desc->data_length.max_ibi);
714 		}
715 	}
716 
717 	/*
718 	 * Only re-enable Hot-Join from targets.
719 	 * Target interrupts will be enabled when IBI is enabled.
720 	 * And transferring controller role is not supported so not need to
721 	 * enable the event.
722 	 */
723 	i3c_events.events = I3C_CCC_EVT_HJ;
724 	ret = i3c_ccc_do_events_all_set(dev, true, &i3c_events);
725 	if (ret != 0) {
726 		LOG_DBG("Broadcast ENEC was NACK.");
727 	}
728 
729 err_out:
730 	return ret;
731 }
732