162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Bluetooth HCI UART driver for marvell devices 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2016 Marvell International Ltd. 762306a36Sopenharmony_ci * Copyright (C) 2016 Intel Corporation 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/errno.h> 1262306a36Sopenharmony_ci#include <linux/skbuff.h> 1362306a36Sopenharmony_ci#include <linux/firmware.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/tty.h> 1662306a36Sopenharmony_ci#include <linux/of.h> 1762306a36Sopenharmony_ci#include <linux/serdev.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <net/bluetooth/bluetooth.h> 2062306a36Sopenharmony_ci#include <net/bluetooth/hci_core.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "hci_uart.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define HCI_FW_REQ_PKT 0xA5 2562306a36Sopenharmony_ci#define HCI_CHIP_VER_PKT 0xAA 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define MRVL_ACK 0x5A 2862306a36Sopenharmony_ci#define MRVL_NAK 0xBF 2962306a36Sopenharmony_ci#define MRVL_RAW_DATA 0x1F 3062306a36Sopenharmony_ci#define MRVL_SET_BAUDRATE 0xFC09 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cienum { 3362306a36Sopenharmony_ci STATE_CHIP_VER_PENDING, 3462306a36Sopenharmony_ci STATE_FW_REQ_PENDING, 3562306a36Sopenharmony_ci STATE_FW_LOADED, 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistruct mrvl_data { 3962306a36Sopenharmony_ci struct sk_buff *rx_skb; 4062306a36Sopenharmony_ci struct sk_buff_head txq; 4162306a36Sopenharmony_ci struct sk_buff_head rawq; 4262306a36Sopenharmony_ci unsigned long flags; 4362306a36Sopenharmony_ci unsigned int tx_len; 4462306a36Sopenharmony_ci u8 id, rev; 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistruct mrvl_serdev { 4862306a36Sopenharmony_ci struct hci_uart hu; 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistruct hci_mrvl_pkt { 5262306a36Sopenharmony_ci __le16 lhs; 5362306a36Sopenharmony_ci __le16 rhs; 5462306a36Sopenharmony_ci} __packed; 5562306a36Sopenharmony_ci#define HCI_MRVL_PKT_SIZE 4 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic int mrvl_open(struct hci_uart *hu) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci struct mrvl_data *mrvl; 6062306a36Sopenharmony_ci int ret; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci BT_DBG("hu %p", hu); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (!hci_uart_has_flow_control(hu)) 6562306a36Sopenharmony_ci return -EOPNOTSUPP; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci mrvl = kzalloc(sizeof(*mrvl), GFP_KERNEL); 6862306a36Sopenharmony_ci if (!mrvl) 6962306a36Sopenharmony_ci return -ENOMEM; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci skb_queue_head_init(&mrvl->txq); 7262306a36Sopenharmony_ci skb_queue_head_init(&mrvl->rawq); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci set_bit(STATE_CHIP_VER_PENDING, &mrvl->flags); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci hu->priv = mrvl; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (hu->serdev) { 7962306a36Sopenharmony_ci ret = serdev_device_open(hu->serdev); 8062306a36Sopenharmony_ci if (ret) 8162306a36Sopenharmony_ci goto err; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_cierr: 8662306a36Sopenharmony_ci kfree(mrvl); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci return ret; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic int mrvl_close(struct hci_uart *hu) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci BT_DBG("hu %p", hu); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci if (hu->serdev) 9862306a36Sopenharmony_ci serdev_device_close(hu->serdev); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci skb_queue_purge(&mrvl->txq); 10162306a36Sopenharmony_ci skb_queue_purge(&mrvl->rawq); 10262306a36Sopenharmony_ci kfree_skb(mrvl->rx_skb); 10362306a36Sopenharmony_ci kfree(mrvl); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci hu->priv = NULL; 10662306a36Sopenharmony_ci return 0; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic int mrvl_flush(struct hci_uart *hu) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci BT_DBG("hu %p", hu); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci skb_queue_purge(&mrvl->txq); 11662306a36Sopenharmony_ci skb_queue_purge(&mrvl->rawq); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci return 0; 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic struct sk_buff *mrvl_dequeue(struct hci_uart *hu) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 12462306a36Sopenharmony_ci struct sk_buff *skb; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci skb = skb_dequeue(&mrvl->txq); 12762306a36Sopenharmony_ci if (!skb) { 12862306a36Sopenharmony_ci /* Any raw data ? */ 12962306a36Sopenharmony_ci skb = skb_dequeue(&mrvl->rawq); 13062306a36Sopenharmony_ci } else { 13162306a36Sopenharmony_ci /* Prepend skb with frame type */ 13262306a36Sopenharmony_ci memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci return skb; 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistatic int mrvl_enqueue(struct hci_uart *hu, struct sk_buff *skb) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci skb_queue_tail(&mrvl->txq, skb); 14362306a36Sopenharmony_ci return 0; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic void mrvl_send_ack(struct hci_uart *hu, unsigned char type) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 14962306a36Sopenharmony_ci struct sk_buff *skb; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* No H4 payload, only 1 byte header */ 15262306a36Sopenharmony_ci skb = bt_skb_alloc(0, GFP_ATOMIC); 15362306a36Sopenharmony_ci if (!skb) { 15462306a36Sopenharmony_ci bt_dev_err(hu->hdev, "Unable to alloc ack/nak packet"); 15562306a36Sopenharmony_ci return; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci hci_skb_pkt_type(skb) = type; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci skb_queue_tail(&mrvl->txq, skb); 16062306a36Sopenharmony_ci hci_uart_tx_wakeup(hu); 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic int mrvl_recv_fw_req(struct hci_dev *hdev, struct sk_buff *skb) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci struct hci_mrvl_pkt *pkt = (void *)skb->data; 16662306a36Sopenharmony_ci struct hci_uart *hu = hci_get_drvdata(hdev); 16762306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 16862306a36Sopenharmony_ci int ret = 0; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if ((pkt->lhs ^ pkt->rhs) != 0xffff) { 17162306a36Sopenharmony_ci bt_dev_err(hdev, "Corrupted mrvl header"); 17262306a36Sopenharmony_ci mrvl_send_ack(hu, MRVL_NAK); 17362306a36Sopenharmony_ci ret = -EINVAL; 17462306a36Sopenharmony_ci goto done; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci mrvl_send_ack(hu, MRVL_ACK); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (!test_bit(STATE_FW_REQ_PENDING, &mrvl->flags)) { 17962306a36Sopenharmony_ci bt_dev_err(hdev, "Received unexpected firmware request"); 18062306a36Sopenharmony_ci ret = -EINVAL; 18162306a36Sopenharmony_ci goto done; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci mrvl->tx_len = le16_to_cpu(pkt->lhs); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci clear_bit(STATE_FW_REQ_PENDING, &mrvl->flags); 18762306a36Sopenharmony_ci smp_mb__after_atomic(); 18862306a36Sopenharmony_ci wake_up_bit(&mrvl->flags, STATE_FW_REQ_PENDING); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cidone: 19162306a36Sopenharmony_ci kfree_skb(skb); 19262306a36Sopenharmony_ci return ret; 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic int mrvl_recv_chip_ver(struct hci_dev *hdev, struct sk_buff *skb) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci struct hci_mrvl_pkt *pkt = (void *)skb->data; 19862306a36Sopenharmony_ci struct hci_uart *hu = hci_get_drvdata(hdev); 19962306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 20062306a36Sopenharmony_ci u16 version = le16_to_cpu(pkt->lhs); 20162306a36Sopenharmony_ci int ret = 0; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if ((pkt->lhs ^ pkt->rhs) != 0xffff) { 20462306a36Sopenharmony_ci bt_dev_err(hdev, "Corrupted mrvl header"); 20562306a36Sopenharmony_ci mrvl_send_ack(hu, MRVL_NAK); 20662306a36Sopenharmony_ci ret = -EINVAL; 20762306a36Sopenharmony_ci goto done; 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci mrvl_send_ack(hu, MRVL_ACK); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci if (!test_bit(STATE_CHIP_VER_PENDING, &mrvl->flags)) { 21262306a36Sopenharmony_ci bt_dev_err(hdev, "Received unexpected chip version"); 21362306a36Sopenharmony_ci goto done; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci mrvl->id = version; 21762306a36Sopenharmony_ci mrvl->rev = version >> 8; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci bt_dev_info(hdev, "Controller id = %x, rev = %x", mrvl->id, mrvl->rev); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci clear_bit(STATE_CHIP_VER_PENDING, &mrvl->flags); 22262306a36Sopenharmony_ci smp_mb__after_atomic(); 22362306a36Sopenharmony_ci wake_up_bit(&mrvl->flags, STATE_CHIP_VER_PENDING); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cidone: 22662306a36Sopenharmony_ci kfree_skb(skb); 22762306a36Sopenharmony_ci return ret; 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci#define HCI_RECV_CHIP_VER \ 23162306a36Sopenharmony_ci .type = HCI_CHIP_VER_PKT, \ 23262306a36Sopenharmony_ci .hlen = HCI_MRVL_PKT_SIZE, \ 23362306a36Sopenharmony_ci .loff = 0, \ 23462306a36Sopenharmony_ci .lsize = 0, \ 23562306a36Sopenharmony_ci .maxlen = HCI_MRVL_PKT_SIZE 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci#define HCI_RECV_FW_REQ \ 23862306a36Sopenharmony_ci .type = HCI_FW_REQ_PKT, \ 23962306a36Sopenharmony_ci .hlen = HCI_MRVL_PKT_SIZE, \ 24062306a36Sopenharmony_ci .loff = 0, \ 24162306a36Sopenharmony_ci .lsize = 0, \ 24262306a36Sopenharmony_ci .maxlen = HCI_MRVL_PKT_SIZE 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic const struct h4_recv_pkt mrvl_recv_pkts[] = { 24562306a36Sopenharmony_ci { H4_RECV_ACL, .recv = hci_recv_frame }, 24662306a36Sopenharmony_ci { H4_RECV_SCO, .recv = hci_recv_frame }, 24762306a36Sopenharmony_ci { H4_RECV_EVENT, .recv = hci_recv_frame }, 24862306a36Sopenharmony_ci { HCI_RECV_FW_REQ, .recv = mrvl_recv_fw_req }, 24962306a36Sopenharmony_ci { HCI_RECV_CHIP_VER, .recv = mrvl_recv_chip_ver }, 25062306a36Sopenharmony_ci}; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic int mrvl_recv(struct hci_uart *hu, const void *data, int count) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (!test_bit(HCI_UART_REGISTERED, &hu->flags)) 25762306a36Sopenharmony_ci return -EUNATCH; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci /* We might receive some noise when there is no firmware loaded. Therefore, 26062306a36Sopenharmony_ci * we drop data if the firmware is not loaded yet and if there is no fw load 26162306a36Sopenharmony_ci * request pending. 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci if (!test_bit(STATE_FW_REQ_PENDING, &mrvl->flags) && 26462306a36Sopenharmony_ci !test_bit(STATE_FW_LOADED, &mrvl->flags)) 26562306a36Sopenharmony_ci return count; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci mrvl->rx_skb = h4_recv_buf(hu->hdev, mrvl->rx_skb, data, count, 26862306a36Sopenharmony_ci mrvl_recv_pkts, 26962306a36Sopenharmony_ci ARRAY_SIZE(mrvl_recv_pkts)); 27062306a36Sopenharmony_ci if (IS_ERR(mrvl->rx_skb)) { 27162306a36Sopenharmony_ci int err = PTR_ERR(mrvl->rx_skb); 27262306a36Sopenharmony_ci bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err); 27362306a36Sopenharmony_ci mrvl->rx_skb = NULL; 27462306a36Sopenharmony_ci return err; 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci return count; 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic int mrvl_load_firmware(struct hci_dev *hdev, const char *name) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci struct hci_uart *hu = hci_get_drvdata(hdev); 28362306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 28462306a36Sopenharmony_ci const struct firmware *fw = NULL; 28562306a36Sopenharmony_ci const u8 *fw_ptr, *fw_max; 28662306a36Sopenharmony_ci int err; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci err = request_firmware(&fw, name, &hdev->dev); 28962306a36Sopenharmony_ci if (err < 0) { 29062306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to load firmware file %s", name); 29162306a36Sopenharmony_ci return err; 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci fw_ptr = fw->data; 29562306a36Sopenharmony_ci fw_max = fw->data + fw->size; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci bt_dev_info(hdev, "Loading %s", name); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci set_bit(STATE_FW_REQ_PENDING, &mrvl->flags); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci while (fw_ptr <= fw_max) { 30262306a36Sopenharmony_ci struct sk_buff *skb; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci /* Controller drives the firmware load by sending firmware 30562306a36Sopenharmony_ci * request packets containing the expected fragment size. 30662306a36Sopenharmony_ci */ 30762306a36Sopenharmony_ci err = wait_on_bit_timeout(&mrvl->flags, STATE_FW_REQ_PENDING, 30862306a36Sopenharmony_ci TASK_INTERRUPTIBLE, 30962306a36Sopenharmony_ci msecs_to_jiffies(2000)); 31062306a36Sopenharmony_ci if (err == 1) { 31162306a36Sopenharmony_ci bt_dev_err(hdev, "Firmware load interrupted"); 31262306a36Sopenharmony_ci err = -EINTR; 31362306a36Sopenharmony_ci break; 31462306a36Sopenharmony_ci } else if (err) { 31562306a36Sopenharmony_ci bt_dev_err(hdev, "Firmware request timeout"); 31662306a36Sopenharmony_ci err = -ETIMEDOUT; 31762306a36Sopenharmony_ci break; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci bt_dev_dbg(hdev, "Firmware request, expecting %d bytes", 32162306a36Sopenharmony_ci mrvl->tx_len); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (fw_ptr == fw_max) { 32462306a36Sopenharmony_ci /* Controller requests a null size once firmware is 32562306a36Sopenharmony_ci * fully loaded. If controller expects more data, there 32662306a36Sopenharmony_ci * is an issue. 32762306a36Sopenharmony_ci */ 32862306a36Sopenharmony_ci if (!mrvl->tx_len) { 32962306a36Sopenharmony_ci bt_dev_info(hdev, "Firmware loading complete"); 33062306a36Sopenharmony_ci } else { 33162306a36Sopenharmony_ci bt_dev_err(hdev, "Firmware loading failure"); 33262306a36Sopenharmony_ci err = -EINVAL; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci break; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci if (fw_ptr + mrvl->tx_len > fw_max) { 33862306a36Sopenharmony_ci mrvl->tx_len = fw_max - fw_ptr; 33962306a36Sopenharmony_ci bt_dev_dbg(hdev, "Adjusting tx_len to %d", 34062306a36Sopenharmony_ci mrvl->tx_len); 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci skb = bt_skb_alloc(mrvl->tx_len, GFP_KERNEL); 34462306a36Sopenharmony_ci if (!skb) { 34562306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to alloc mem for FW packet"); 34662306a36Sopenharmony_ci err = -ENOMEM; 34762306a36Sopenharmony_ci break; 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci bt_cb(skb)->pkt_type = MRVL_RAW_DATA; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci skb_put_data(skb, fw_ptr, mrvl->tx_len); 35262306a36Sopenharmony_ci fw_ptr += mrvl->tx_len; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci set_bit(STATE_FW_REQ_PENDING, &mrvl->flags); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci skb_queue_tail(&mrvl->rawq, skb); 35762306a36Sopenharmony_ci hci_uart_tx_wakeup(hu); 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci release_firmware(fw); 36162306a36Sopenharmony_ci return err; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic int mrvl_setup(struct hci_uart *hu) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci int err; 36762306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci hci_uart_set_flow_control(hu, true); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci err = mrvl_load_firmware(hu->hdev, "mrvl/helper_uart_3000000.bin"); 37262306a36Sopenharmony_ci if (err) { 37362306a36Sopenharmony_ci bt_dev_err(hu->hdev, "Unable to download firmware helper"); 37462306a36Sopenharmony_ci return -EINVAL; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* Let the final ack go out before switching the baudrate */ 37862306a36Sopenharmony_ci hci_uart_wait_until_sent(hu); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if (hu->serdev) 38162306a36Sopenharmony_ci serdev_device_set_baudrate(hu->serdev, hu->oper_speed); 38262306a36Sopenharmony_ci else 38362306a36Sopenharmony_ci hci_uart_set_baudrate(hu, hu->oper_speed); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci hci_uart_set_flow_control(hu, false); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci err = mrvl_load_firmware(hu->hdev, "mrvl/uart8897_bt.bin"); 38862306a36Sopenharmony_ci if (err) 38962306a36Sopenharmony_ci return err; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci set_bit(STATE_FW_LOADED, &mrvl->flags); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci return 0; 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic int mrvl_set_baudrate(struct hci_uart *hu, unsigned int speed) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci int err; 39962306a36Sopenharmony_ci struct mrvl_data *mrvl = hu->priv; 40062306a36Sopenharmony_ci __le32 speed_le = cpu_to_le32(speed); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci /* The firmware might be loaded by the Wifi driver over SDIO. We wait 40362306a36Sopenharmony_ci * up to 10s for the CTS to go up. Afterward, we know that the firmware 40462306a36Sopenharmony_ci * is ready. 40562306a36Sopenharmony_ci */ 40662306a36Sopenharmony_ci err = serdev_device_wait_for_cts(hu->serdev, true, 10000); 40762306a36Sopenharmony_ci if (err) { 40862306a36Sopenharmony_ci bt_dev_err(hu->hdev, "Wait for CTS failed with %d\n", err); 40962306a36Sopenharmony_ci return err; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci set_bit(STATE_FW_LOADED, &mrvl->flags); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci err = __hci_cmd_sync_status(hu->hdev, MRVL_SET_BAUDRATE, 41562306a36Sopenharmony_ci sizeof(speed_le), &speed_le, 41662306a36Sopenharmony_ci HCI_INIT_TIMEOUT); 41762306a36Sopenharmony_ci if (err) { 41862306a36Sopenharmony_ci bt_dev_err(hu->hdev, "send command failed: %d", err); 41962306a36Sopenharmony_ci return err; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci serdev_device_set_baudrate(hu->serdev, speed); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci /* We forcefully have to send a command to the bluetooth module so that 42562306a36Sopenharmony_ci * the driver detects it after a baudrate change. This is foreseen by 42662306a36Sopenharmony_ci * hci_serdev by setting HCI_UART_VND_DETECT which then causes a dummy 42762306a36Sopenharmony_ci * local version read. 42862306a36Sopenharmony_ci */ 42962306a36Sopenharmony_ci set_bit(HCI_UART_VND_DETECT, &hu->hdev_flags); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci return 0; 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistatic const struct hci_uart_proto mrvl_proto_8897 = { 43562306a36Sopenharmony_ci .id = HCI_UART_MRVL, 43662306a36Sopenharmony_ci .name = "Marvell", 43762306a36Sopenharmony_ci .init_speed = 115200, 43862306a36Sopenharmony_ci .oper_speed = 3000000, 43962306a36Sopenharmony_ci .open = mrvl_open, 44062306a36Sopenharmony_ci .close = mrvl_close, 44162306a36Sopenharmony_ci .flush = mrvl_flush, 44262306a36Sopenharmony_ci .setup = mrvl_setup, 44362306a36Sopenharmony_ci .recv = mrvl_recv, 44462306a36Sopenharmony_ci .enqueue = mrvl_enqueue, 44562306a36Sopenharmony_ci .dequeue = mrvl_dequeue, 44662306a36Sopenharmony_ci}; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic const struct hci_uart_proto mrvl_proto_8997 = { 44962306a36Sopenharmony_ci .id = HCI_UART_MRVL, 45062306a36Sopenharmony_ci .name = "Marvell 8997", 45162306a36Sopenharmony_ci .init_speed = 115200, 45262306a36Sopenharmony_ci .oper_speed = 3000000, 45362306a36Sopenharmony_ci .open = mrvl_open, 45462306a36Sopenharmony_ci .close = mrvl_close, 45562306a36Sopenharmony_ci .flush = mrvl_flush, 45662306a36Sopenharmony_ci .set_baudrate = mrvl_set_baudrate, 45762306a36Sopenharmony_ci .recv = mrvl_recv, 45862306a36Sopenharmony_ci .enqueue = mrvl_enqueue, 45962306a36Sopenharmony_ci .dequeue = mrvl_dequeue, 46062306a36Sopenharmony_ci}; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_cistatic int mrvl_serdev_probe(struct serdev_device *serdev) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci struct mrvl_serdev *mrvldev; 46562306a36Sopenharmony_ci const struct hci_uart_proto *mrvl_proto = device_get_match_data(&serdev->dev); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci mrvldev = devm_kzalloc(&serdev->dev, sizeof(*mrvldev), GFP_KERNEL); 46862306a36Sopenharmony_ci if (!mrvldev) 46962306a36Sopenharmony_ci return -ENOMEM; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci mrvldev->hu.oper_speed = mrvl_proto->oper_speed; 47262306a36Sopenharmony_ci if (mrvl_proto->set_baudrate) 47362306a36Sopenharmony_ci of_property_read_u32(serdev->dev.of_node, "max-speed", &mrvldev->hu.oper_speed); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci mrvldev->hu.serdev = serdev; 47662306a36Sopenharmony_ci serdev_device_set_drvdata(serdev, mrvldev); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci return hci_uart_register_device(&mrvldev->hu, mrvl_proto); 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic void mrvl_serdev_remove(struct serdev_device *serdev) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci struct mrvl_serdev *mrvldev = serdev_device_get_drvdata(serdev); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci hci_uart_unregister_device(&mrvldev->hu); 48662306a36Sopenharmony_ci} 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_cistatic const struct of_device_id __maybe_unused mrvl_bluetooth_of_match[] = { 48962306a36Sopenharmony_ci { .compatible = "mrvl,88w8897", .data = &mrvl_proto_8897}, 49062306a36Sopenharmony_ci { .compatible = "mrvl,88w8997", .data = &mrvl_proto_8997}, 49162306a36Sopenharmony_ci { }, 49262306a36Sopenharmony_ci}; 49362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, mrvl_bluetooth_of_match); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_cistatic struct serdev_device_driver mrvl_serdev_driver = { 49662306a36Sopenharmony_ci .probe = mrvl_serdev_probe, 49762306a36Sopenharmony_ci .remove = mrvl_serdev_remove, 49862306a36Sopenharmony_ci .driver = { 49962306a36Sopenharmony_ci .name = "hci_uart_mrvl", 50062306a36Sopenharmony_ci .of_match_table = of_match_ptr(mrvl_bluetooth_of_match), 50162306a36Sopenharmony_ci }, 50262306a36Sopenharmony_ci}; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ciint __init mrvl_init(void) 50562306a36Sopenharmony_ci{ 50662306a36Sopenharmony_ci serdev_device_driver_register(&mrvl_serdev_driver); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci return hci_uart_register_proto(&mrvl_proto_8897); 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ciint __exit mrvl_deinit(void) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci serdev_device_driver_unregister(&mrvl_serdev_driver); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci return hci_uart_unregister_proto(&mrvl_proto_8897); 51662306a36Sopenharmony_ci} 517