static int qca_serdev_probe()

in hci_qca.c [2018:2137]


static int qca_serdev_probe(struct serdev_device *serdev)
{
	struct qca_serdev *qcadev;
	struct hci_dev *hdev;
	const struct qca_device_data *data;
	int err;
	bool power_ctrl_enabled = true;

	qcadev = devm_kzalloc(&serdev->dev, sizeof(*qcadev), GFP_KERNEL);
	if (!qcadev)
		return -ENOMEM;

	qcadev->serdev_hu.serdev = serdev;
	data = device_get_match_data(&serdev->dev);
	serdev_device_set_drvdata(serdev, qcadev);
	device_property_read_string(&serdev->dev, "firmware-name",
					 &qcadev->firmware_name);
	device_property_read_u32(&serdev->dev, "max-speed",
				 &qcadev->oper_speed);
	if (!qcadev->oper_speed)
		BT_DBG("UART will pick default operating speed");

	if (data &&
	    (qca_is_wcn399x(data->soc_type) ||
	    qca_is_wcn6750(data->soc_type))) {
		qcadev->btsoc_type = data->soc_type;
		qcadev->bt_power = devm_kzalloc(&serdev->dev,
						sizeof(struct qca_power),
						GFP_KERNEL);
		if (!qcadev->bt_power)
			return -ENOMEM;

		qcadev->bt_power->dev = &serdev->dev;
		err = qca_init_regulators(qcadev->bt_power, data->vregs,
					  data->num_vregs);
		if (err) {
			BT_ERR("Failed to init regulators:%d", err);
			return err;
		}

		qcadev->bt_power->vregs_on = false;

		qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
					       GPIOD_OUT_LOW);
		if (IS_ERR_OR_NULL(qcadev->bt_en) && data->soc_type == QCA_WCN6750) {
			dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n");
			power_ctrl_enabled = false;
		}

		qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl",
					       GPIOD_IN);
		if (IS_ERR_OR_NULL(qcadev->sw_ctrl) && data->soc_type == QCA_WCN6750)
			dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n");

		qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
		if (IS_ERR(qcadev->susclk)) {
			dev_err(&serdev->dev, "failed to acquire clk\n");
			return PTR_ERR(qcadev->susclk);
		}

		err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto);
		if (err) {
			BT_ERR("wcn3990 serdev registration failed");
			return err;
		}
	} else {
		if (data)
			qcadev->btsoc_type = data->soc_type;
		else
			qcadev->btsoc_type = QCA_ROME;

		qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
					       GPIOD_OUT_LOW);
		if (IS_ERR_OR_NULL(qcadev->bt_en)) {
			dev_warn(&serdev->dev, "failed to acquire enable gpio\n");
			power_ctrl_enabled = false;
		}

		qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
		if (IS_ERR(qcadev->susclk)) {
			dev_warn(&serdev->dev, "failed to acquire clk\n");
			return PTR_ERR(qcadev->susclk);
		}
		err = clk_set_rate(qcadev->susclk, SUSCLK_RATE_32KHZ);
		if (err)
			return err;

		err = clk_prepare_enable(qcadev->susclk);
		if (err)
			return err;

		err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto);
		if (err) {
			BT_ERR("Rome serdev registration failed");
			clk_disable_unprepare(qcadev->susclk);
			return err;
		}
	}

	hdev = qcadev->serdev_hu.hdev;

	if (power_ctrl_enabled) {
		set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
		hdev->shutdown = qca_power_off;
	}

	if (data) {
		/* Wideband speech support must be set per driver since it can't
		 * be queried via hci. Same with the valid le states quirk.
		 */
		if (data->capabilities & QCA_CAP_WIDEBAND_SPEECH)
			set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
				&hdev->quirks);

		if (data->capabilities & QCA_CAP_VALID_LE_STATES)
			set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
	}

	return 0;
}