static struct sk_buff *nokia_dequeue(struct hci_uart *hu) { struct nokia_bt_dev *btdev = hu->priv; struct device *dev = &btdev->serdev->dev; struct sk_buff *result = skb_dequeue(&btdev->txq); if (!btdev->initialized) return result; if (btdev->tx_enabled == !!result) return result; if (result) { pm_runtime_get_sync(dev); gpiod_set_value_cansleep(btdev->wakeup_bt, 1); } else { serdev_device_wait_until_sent(btdev->serdev, 0); gpiod_set_value_cansleep(btdev->wakeup_bt, 0); pm_runtime_put(dev); } btdev->tx_enabled = !!result; return result; }
static int sirf_write_raw(struct gnss_device *gdev, const unsigned char *buf, size_t count) { struct sirf_data *data = gnss_get_drvdata(gdev); struct serdev_device *serdev = data->serdev; int ret; /* write is only buffered synchronously */ ret = serdev_device_write(serdev, buf, count, 0); if (ret < 0) return ret; /* FIXME: determine if interrupted? */ serdev_device_wait_until_sent(serdev, 0); return count; }
static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) { struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; struct qca_serdev *qcadev; struct sk_buff *skb; u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 }; if (baudrate > QCA_BAUDRATE_3200000) return -EINVAL; cmd[4] = baudrate; skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL); if (!skb) { bt_dev_err(hdev, "Failed to allocate baudrate packet"); return -ENOMEM; } /* Assign commands to change baudrate and packet type. */ skb_put_data(skb, cmd, sizeof(cmd)); hci_skb_pkt_type(skb) = HCI_COMMAND_PKT; skb_queue_tail(&qca->txq, skb); hci_uart_tx_wakeup(hu); qcadev = serdev_device_get_drvdata(hu->serdev); /* Wait for the baudrate change request to be sent */ while (!skb_queue_empty(&qca->txq)) usleep_range(100, 200); serdev_device_wait_until_sent(hu->serdev, msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); /* Give the controller time to process the request */ if (qcadev->btsoc_type == QCA_WCN3990) msleep(10); else msleep(300); return 0; }
static int qca_send_power_pulse(struct hci_uart *hu, bool on) { int ret; int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS); u8 cmd = on ? QCA_WCN3990_POWERON_PULSE : QCA_WCN3990_POWEROFF_PULSE; /* These power pulses are single byte command which are sent * at required baudrate to wcn3990. On wcn3990, we have an external * circuit at Tx pin which decodes the pulse sent at specific baudrate. * For example, wcn3990 supports RF COEX antenna for both Wi-Fi/BT * and also we use the same power inputs to turn on and off for * Wi-Fi/BT. Powering up the power sources will not enable BT, until * we send a power on pulse at 115200 bps. This algorithm will help to * save power. Disabling hardware flow control is mandatory while * sending power pulses to SoC. */ bt_dev_dbg(hu->hdev, "sending power pulse %02x to controller", cmd); serdev_device_write_flush(hu->serdev); hci_uart_set_flow_control(hu, true); ret = serdev_device_write_buf(hu->serdev, &cmd, sizeof(cmd)); if (ret < 0) { bt_dev_err(hu->hdev, "failed to send power pulse %02x", cmd); return ret; } serdev_device_wait_until_sent(hu->serdev, timeout); hci_uart_set_flow_control(hu, false); /* Give to controller time to boot/shutdown */ if (on) msleep(100); else msleep(10); return 0; }