in master/mipi-i3c-hci/cmd_v1.c [292:371]
static int hci_cmd_v1_daa(struct i3c_hci *hci)
{
struct hci_xfer *xfer;
int ret, dat_idx = -1;
u8 next_addr = 0;
u64 pid;
unsigned int dcr, bcr;
DECLARE_COMPLETION_ONSTACK(done);
xfer = hci_alloc_xfer(2);
if (!xfer)
return -ENOMEM;
/*
* Simple for now: we allocate a temporary DAT entry, do a single
* DAA, register the device which will allocate its own DAT entry
* via the core callback, then free the temporary DAT entry.
* Loop until there is no more devices to assign an address to.
* Yes, there is room for improvements.
*/
for (;;) {
ret = mipi_i3c_hci_dat_v1.alloc_entry(hci);
if (ret < 0)
break;
dat_idx = ret;
ret = i3c_master_get_free_addr(&hci->master, next_addr);
if (ret < 0)
break;
next_addr = ret;
DBG("next_addr = 0x%02x, DAA using DAT %d", next_addr, dat_idx);
mipi_i3c_hci_dat_v1.set_dynamic_addr(hci, dat_idx, next_addr);
mipi_i3c_hci_dct_index_reset(hci);
xfer->cmd_tid = hci_get_tid();
xfer->cmd_desc[0] =
CMD_0_ATTR_A |
CMD_A0_TID(xfer->cmd_tid) |
CMD_A0_CMD(I3C_CCC_ENTDAA) |
CMD_A0_DEV_INDEX(dat_idx) |
CMD_A0_DEV_COUNT(1) |
CMD_A0_ROC | CMD_A0_TOC;
xfer->cmd_desc[1] = 0;
hci->io->queue_xfer(hci, xfer, 1);
if (!wait_for_completion_timeout(&done, HZ) &&
hci->io->dequeue_xfer(hci, xfer, 1)) {
ret = -ETIME;
break;
}
if (RESP_STATUS(xfer[0].response) == RESP_ERR_NACK &&
RESP_STATUS(xfer[0].response) == 1) {
ret = 0; /* no more devices to be assigned */
break;
}
if (RESP_STATUS(xfer[0].response) != RESP_SUCCESS) {
ret = -EIO;
break;
}
i3c_hci_dct_get_val(hci, 0, &pid, &dcr, &bcr);
DBG("assigned address %#x to device PID=0x%llx DCR=%#x BCR=%#x",
next_addr, pid, dcr, bcr);
mipi_i3c_hci_dat_v1.free_entry(hci, dat_idx);
dat_idx = -1;
/*
* TODO: Extend the subsystem layer to allow for registering
* new device and provide BCR/DCR/PID at the same time.
*/
ret = i3c_master_add_i3c_dev_locked(&hci->master, next_addr);
if (ret)
break;
}
if (dat_idx >= 0)
mipi_i3c_hci_dat_v1.free_entry(hci, dat_idx);
hci_free_xfer(xfer, 1);
return ret;
}