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; }
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; }