Ejemplo n.º 1
0
static int nokia_bluetooth_serdev_probe(struct serdev_device *serdev)
{
	struct device *dev = &serdev->dev;
	struct nokia_bt_dev *btdev;
	struct clk *sysclk;
	int err = 0;

	btdev = devm_kzalloc(dev, sizeof(*btdev), GFP_KERNEL);
	if (!btdev)
		return -ENOMEM;

	btdev->hu.serdev = btdev->serdev = serdev;
	serdev_device_set_drvdata(serdev, btdev);

	btdev->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
	if (IS_ERR(btdev->reset)) {
		err = PTR_ERR(btdev->reset);
		dev_err(dev, "could not get reset gpio: %d", err);
		return err;
	}

	btdev->wakeup_host = devm_gpiod_get(dev, "host-wakeup", GPIOD_IN);
	if (IS_ERR(btdev->wakeup_host)) {
		err = PTR_ERR(btdev->wakeup_host);
		dev_err(dev, "could not get host wakeup gpio: %d", err);
		return err;
	}

	btdev->wake_irq = gpiod_to_irq(btdev->wakeup_host);

	err = devm_request_threaded_irq(dev, btdev->wake_irq, NULL,
		wakeup_handler,
		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
		"wakeup", btdev);
	if (err) {
		dev_err(dev, "could request wakeup irq: %d", err);
		return err;
	}

	btdev->wakeup_bt = devm_gpiod_get(dev, "bluetooth-wakeup",
					   GPIOD_OUT_LOW);
	if (IS_ERR(btdev->wakeup_bt)) {
		err = PTR_ERR(btdev->wakeup_bt);
		dev_err(dev, "could not get BT wakeup gpio: %d", err);
		return err;
	}

	sysclk = devm_clk_get(dev, "sysclk");
	if (IS_ERR(sysclk)) {
		err = PTR_ERR(sysclk);
		dev_err(dev, "could not get sysclk: %d", err);
		return err;
	}

	clk_prepare_enable(sysclk);
	btdev->sysclk_speed = clk_get_rate(sysclk);
	clk_disable_unprepare(sysclk);

	skb_queue_head_init(&btdev->txq);

	btdev->hu.priv = btdev;
	btdev->hu.alignment = 2; /* Nokia H4+ is word aligned */

	err = hci_uart_register_device(&btdev->hu, &nokia_proto);
	if (err) {
		dev_err(dev, "could not register bluetooth uart: %d", err);
		return err;
	}

	return 0;
}
Ejemplo n.º 2
0
static int sirf_probe(struct serdev_device *serdev)
{
	struct device *dev = &serdev->dev;
	struct gnss_device *gdev;
	struct sirf_data *data;
	int ret;

	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	gdev = gnss_allocate_device(dev);
	if (!gdev)
		return -ENOMEM;

	gdev->type = GNSS_TYPE_SIRF;
	gdev->ops = &sirf_gnss_ops;
	gnss_set_drvdata(gdev, data);

	data->serdev = serdev;
	data->gdev = gdev;

	init_waitqueue_head(&data->power_wait);

	serdev_device_set_drvdata(serdev, data);
	serdev_device_set_client_ops(serdev, &sirf_serdev_ops);

	ret = sirf_parse_dt(serdev);
	if (ret)
		goto err_put_device;

	data->vcc = devm_regulator_get(dev, "vcc");
	if (IS_ERR(data->vcc)) {
		ret = PTR_ERR(data->vcc);
		goto err_put_device;
	}

	data->on_off = devm_gpiod_get_optional(dev, "sirf,onoff",
			GPIOD_OUT_LOW);
	if (IS_ERR(data->on_off))
		goto err_put_device;

	if (data->on_off) {
		data->wakeup = devm_gpiod_get_optional(dev, "sirf,wakeup",
				GPIOD_IN);
		if (IS_ERR(data->wakeup))
			goto err_put_device;

		/*
		 * Configurations where WAKEUP has been left not connected,
		 * are currently not supported.
		 */
		if (!data->wakeup) {
			dev_err(dev, "no wakeup gpio specified\n");
			ret = -ENODEV;
			goto err_put_device;
		}
	}

	if (data->wakeup) {
		ret = gpiod_to_irq(data->wakeup);
		if (ret < 0)
			goto err_put_device;

		data->irq = ret;

		ret = devm_request_threaded_irq(dev, data->irq, NULL,
				sirf_wakeup_handler,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
				"wakeup", data);
		if (ret)
			goto err_put_device;
	}

	if (data->on_off) {
		ret = regulator_enable(data->vcc);
		if (ret)
			goto err_put_device;

		/* Wait for chip to boot into hibernate mode */
		msleep(SIRF_BOOT_DELAY);
	}

	if (IS_ENABLED(CONFIG_PM)) {
		pm_runtime_set_suspended(dev);	/* clear runtime_error flag */
		pm_runtime_enable(dev);
	} else {
		ret = sirf_runtime_resume(dev);
		if (ret < 0)
			goto err_disable_vcc;
	}

	ret = gnss_register_device(gdev);
	if (ret)
		goto err_disable_rpm;

	return 0;

err_disable_rpm:
	if (IS_ENABLED(CONFIG_PM))
		pm_runtime_disable(dev);
	else
		sirf_runtime_suspend(dev);
err_disable_vcc:
	if (data->on_off)
		regulator_disable(data->vcc);
err_put_device:
	gnss_put_device(data->gdev);

	return ret;
}
Ejemplo n.º 3
0
static int qca_serdev_probe(struct serdev_device *serdev)
{
	struct qca_serdev *qcadev;
	const struct qca_vreg_data *data;
	int err;

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

	qcadev->serdev_hu.serdev = serdev;
	data = of_device_get_match_data(&serdev->dev);
	serdev_device_set_drvdata(serdev, qcadev);
	if (data && data->soc_type == QCA_WCN3990) {
		qcadev->btsoc_type = QCA_WCN3990;
		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;
		qcadev->bt_power->vreg_data = data;
		err = qca_init_regulators(qcadev->bt_power, data->vregs,
					  data->num_vregs);
		if (err) {
			BT_ERR("Failed to init regulators:%d", err);
			goto out;
		}

		qcadev->bt_power->vregs_on = false;

		device_property_read_u32(&serdev->dev, "max-speed",
					 &qcadev->oper_speed);
		if (!qcadev->oper_speed)
			BT_DBG("UART will pick default operating speed");

		err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto);
		if (err) {
			BT_ERR("wcn3990 serdev registration failed");
			goto out;
		}
	} else {
		qcadev->btsoc_type = QCA_ROME;
		qcadev->bt_en = devm_gpiod_get(&serdev->dev, "enable",
					       GPIOD_OUT_LOW);
		if (IS_ERR(qcadev->bt_en)) {
			dev_err(&serdev->dev, "failed to acquire enable gpio\n");
			return PTR_ERR(qcadev->bt_en);
		}

		qcadev->susclk = devm_clk_get(&serdev->dev, NULL);
		if (IS_ERR(qcadev->susclk)) {
			dev_err(&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)
			clk_disable_unprepare(qcadev->susclk);
	}

out:	return err;

}