static int qca_setup()

in hci_qca.c [1693:1805]


static int qca_setup(struct hci_uart *hu)
{
	struct hci_dev *hdev = hu->hdev;
	struct qca_data *qca = hu->priv;
	unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200;
	unsigned int retries = 0;
	enum qca_btsoc_type soc_type = qca_soc_type(hu);
	const char *firmware_name = qca_get_firmware_name(hu);
	int ret;
	struct qca_btsoc_version ver;

	ret = qca_check_speeds(hu);
	if (ret)
		return ret;

	clear_bit(QCA_ROM_FW, &qca->flags);
	/* Patch downloading has to be done without IBS mode */
	set_bit(QCA_IBS_DISABLED, &qca->flags);

	/* Enable controller to do both LE scan and BR/EDR inquiry
	 * simultaneously.
	 */
	set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);

	bt_dev_info(hdev, "setting up %s",
		qca_is_wcn399x(soc_type) ? "wcn399x" :
		(soc_type == QCA_WCN6750) ? "wcn6750" : "ROME/QCA6390");

	qca->memdump_state = QCA_MEMDUMP_IDLE;

retry:
	ret = qca_power_on(hdev);
	if (ret)
		goto out;

	clear_bit(QCA_SSR_TRIGGERED, &qca->flags);

	if (qca_is_wcn399x(soc_type) ||
	    qca_is_wcn6750(soc_type)) {
		set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
		hci_set_aosp_capable(hdev);

		ret = qca_read_soc_version(hdev, &ver, soc_type);
		if (ret)
			goto out;
	} else {
		qca_set_speed(hu, QCA_INIT_SPEED);
	}

	/* Setup user speed if needed */
	speed = qca_get_speed(hu, QCA_OPER_SPEED);
	if (speed) {
		ret = qca_set_speed(hu, QCA_OPER_SPEED);
		if (ret)
			goto out;

		qca_baudrate = qca_get_baudrate_value(speed);
	}

	if (!(qca_is_wcn399x(soc_type) ||
	     qca_is_wcn6750(soc_type))) {
		/* Get QCA version information */
		ret = qca_read_soc_version(hdev, &ver, soc_type);
		if (ret)
			goto out;
	}

	/* Setup patch / NVM configurations */
	ret = qca_uart_setup(hdev, qca_baudrate, soc_type, ver,
			firmware_name);
	if (!ret) {
		clear_bit(QCA_IBS_DISABLED, &qca->flags);
		qca_debugfs_init(hdev);
		hu->hdev->hw_error = qca_hw_error;
		hu->hdev->cmd_timeout = qca_cmd_timeout;
		hu->hdev->wakeup = qca_wakeup;
	} else if (ret == -ENOENT) {
		/* No patch/nvm-config found, run with original fw/config */
		set_bit(QCA_ROM_FW, &qca->flags);
		ret = 0;
	} else if (ret == -EAGAIN) {
		/*
		 * Userspace firmware loader will return -EAGAIN in case no
		 * patch/nvm-config is found, so run with original fw/config.
		 */
		set_bit(QCA_ROM_FW, &qca->flags);
		ret = 0;
	}

out:
	if (ret && retries < MAX_INIT_RETRIES) {
		bt_dev_warn(hdev, "Retry BT power ON:%d", retries);
		qca_power_shutdown(hu);
		if (hu->serdev) {
			serdev_device_close(hu->serdev);
			ret = serdev_device_open(hu->serdev);
			if (ret) {
				bt_dev_err(hdev, "failed to open port");
				return ret;
			}
		}
		retries++;
		goto retry;
	}

	/* Setup bdaddr */
	if (soc_type == QCA_ROME)
		hu->hdev->set_bdaddr = qca_set_bdaddr_rome;
	else
		hu->hdev->set_bdaddr = qca_set_bdaddr;

	return ret;
}