static int hci_cmd_v2_daa()

in master/mipi-i3c-hci/cmd_v2.c [239:309]


static int hci_cmd_v2_daa(struct i3c_hci *hci)
{
	struct hci_xfer *xfer;
	int ret;
	u8 next_addr = 0;
	u32 device_id[2];
	u64 pid;
	unsigned int dcr, bcr;
	DECLARE_COMPLETION_ONSTACK(done);

	xfer = hci_alloc_xfer(2);
	if (!xfer)
		return -ENOMEM;

	xfer[0].data = &device_id;
	xfer[0].data_len = 8;
	xfer[0].rnw = true;
	xfer[0].cmd_desc[1] = CMD_A1_DATA_LENGTH(8);
	xfer[1].completion = &done;

	for (;;) {
		ret = i3c_master_get_free_addr(&hci->master, next_addr);
		if (ret < 0)
			break;
		next_addr = ret;
		DBG("next_addr = 0x%02x", next_addr);
		xfer[0].cmd_tid = hci_get_tid();
		xfer[0].cmd_desc[0] =
			CMD_0_ATTR_A |
			CMD_A0_TID(xfer[0].cmd_tid) |
			CMD_A0_ROC;
		xfer[1].cmd_tid = hci_get_tid();
		xfer[1].cmd_desc[0] =
			CMD_0_ATTR_A |
			CMD_A0_TID(xfer[1].cmd_tid) |
			CMD_A0_ASSIGN_ADDRESS(next_addr) |
			CMD_A0_ROC |
			CMD_A0_TOC;
		hci->io->queue_xfer(hci, xfer, 2);
		if (!wait_for_completion_timeout(&done, HZ) &&
		    hci->io->dequeue_xfer(hci, xfer, 2)) {
			ret = -ETIME;
			break;
		}
		if (RESP_STATUS(xfer[0].response) != RESP_SUCCESS) {
			ret = 0;  /* no more devices to be assigned */
			break;
		}
		if (RESP_STATUS(xfer[1].response) != RESP_SUCCESS) {
			ret = -EIO;
			break;
		}

		pid = FIELD_GET(W1_MASK(47, 32), device_id[1]);
		pid = (pid << 32) | device_id[0];
		bcr = FIELD_GET(W1_MASK(55, 48), device_id[1]);
		dcr = FIELD_GET(W1_MASK(63, 56), device_id[1]);
		DBG("assigned address %#x to device PID=0x%llx DCR=%#x BCR=%#x",
		    next_addr, pid, dcr, bcr);
		/*
		 * 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;
	}

	hci_free_xfer(xfer, 2);
	return ret;
}