static int btmtkuart_probe()

in btmtkuart.c [966:1079]


static int btmtkuart_probe(struct serdev_device *serdev)
{
	struct btmtkuart_dev *bdev;
	struct hci_dev *hdev;
	int err;

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

	bdev->data = of_device_get_match_data(&serdev->dev);
	if (!bdev->data)
		return -ENODEV;

	bdev->serdev = serdev;
	serdev_device_set_drvdata(serdev, bdev);

	serdev_device_set_client_ops(serdev, &btmtkuart_client_ops);

	err = btmtkuart_parse_dt(serdev);
	if (err < 0)
		return err;

	INIT_WORK(&bdev->tx_work, btmtkuart_tx_work);
	skb_queue_head_init(&bdev->txq);

	/* Initialize and register HCI device */
	hdev = hci_alloc_dev();
	if (!hdev) {
		dev_err(&serdev->dev, "Can't allocate HCI device\n");
		return -ENOMEM;
	}

	bdev->hdev = hdev;

	hdev->bus = HCI_UART;
	hci_set_drvdata(hdev, bdev);

	hdev->open     = btmtkuart_open;
	hdev->close    = btmtkuart_close;
	hdev->flush    = btmtkuart_flush;
	hdev->setup    = btmtkuart_setup;
	hdev->shutdown = btmtkuart_shutdown;
	hdev->send     = btmtkuart_send_frame;
	SET_HCIDEV_DEV(hdev, &serdev->dev);

	hdev->manufacturer = 70;
	set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);

	if (btmtkuart_is_standalone(bdev)) {
		err = clk_prepare_enable(bdev->osc);
		if (err < 0)
			goto err_hci_free_dev;

		if (bdev->boot) {
			gpiod_set_value_cansleep(bdev->boot, 1);
		} else {
			/* Switch to the specific pin state for the booting
			 * requires.
			 */
			pinctrl_select_state(bdev->pinctrl, bdev->pins_boot);
		}

		/* Power on */
		err = regulator_enable(bdev->vcc);
		if (err < 0)
			goto err_clk_disable_unprepare;

		/* Reset if the reset-gpios is available otherwise the board
		 * -level design should be guaranteed.
		 */
		if (bdev->reset) {
			gpiod_set_value_cansleep(bdev->reset, 1);
			usleep_range(1000, 2000);
			gpiod_set_value_cansleep(bdev->reset, 0);
		}

		/* Wait some time until device got ready and switch to the pin
		 * mode the device requires for UART transfers.
		 */
		msleep(50);

		if (bdev->boot)
			devm_gpiod_put(&serdev->dev, bdev->boot);

		pinctrl_select_state(bdev->pinctrl, bdev->pins_runtime);

		/* A standalone device doesn't depends on power domain on SoC,
		 * so mark it as no callbacks.
		 */
		pm_runtime_no_callbacks(&serdev->dev);

		set_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state);
	}

	err = hci_register_dev(hdev);
	if (err < 0) {
		dev_err(&serdev->dev, "Can't register HCI device\n");
		goto err_regulator_disable;
	}

	return 0;

err_regulator_disable:
	if (btmtkuart_is_standalone(bdev))
		regulator_disable(bdev->vcc);
err_clk_disable_unprepare:
	if (btmtkuart_is_standalone(bdev))
		clk_disable_unprepare(bdev->osc);
err_hci_free_dev:
	hci_free_dev(hdev);

	return err;
}