Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61b2fc2b authored by Frederic Danis's avatar Frederic Danis Committed by Marcel Holtmann
Browse files

Bluetooth: hci_uart: Add bcm_set_baudrate()



Add vendor specific command to change controller device speed.

Signed-off-by: default avatarFrederic Danis <frederic.danis@linux.intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent c9d44203
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,18 @@
 *
 *
 */
 */


#define BCM_UART_CLOCK_48MHZ	0x01
#define BCM_UART_CLOCK_24MHZ	0x02

struct bcm_update_uart_baud_rate {
	__le16 zero;
	__le32 baud_rate;
} __packed;

struct bcm_write_uart_clock_setting {
	__u8 type;
} __packed;

#if IS_ENABLED(CONFIG_BT_BCM)
#if IS_ENABLED(CONFIG_BT_BCM)


int btbcm_check_bdaddr(struct hci_dev *hdev);
int btbcm_check_bdaddr(struct hci_dev *hdev);
+58 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,55 @@ struct bcm_data {
	struct sk_buff_head txq;
	struct sk_buff_head txq;
};
};


static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
{
	struct hci_dev *hdev = hu->hdev;
	struct sk_buff *skb;
	struct bcm_update_uart_baud_rate param;

	if (speed > 3000000) {
		struct bcm_write_uart_clock_setting clock;

		clock.type = BCM_UART_CLOCK_48MHZ;

		BT_DBG("%s: Set Controller clock (%d)", hdev->name, clock.type);

		/* This Broadcom specific command changes the UART's controller
		 * clock for baud rate > 3000000.
		 */
		skb = __hci_cmd_sync(hdev, 0xfc45, 1, &clock, HCI_INIT_TIMEOUT);
		if (IS_ERR(skb)) {
			int err = PTR_ERR(skb);
			BT_ERR("%s: BCM: failed to write clock command (%d)",
			       hdev->name, err);
			return err;
		}

		kfree_skb(skb);
	}

	BT_DBG("%s: Set Controller UART speed to %d bit/s", hdev->name, speed);

	param.zero = cpu_to_le16(0);
	param.baud_rate = cpu_to_le32(speed);

	/* This Broadcom specific command changes the UART's controller baud
	 * rate.
	 */
	skb = __hci_cmd_sync(hdev, 0xfc18, sizeof(param), &param,
			     HCI_INIT_TIMEOUT);
	if (IS_ERR(skb)) {
		int err = PTR_ERR(skb);
		BT_ERR("%s: BCM: failed to write update baudrate command (%d)",
		       hdev->name, err);
		return err;
	}

	kfree_skb(skb);

	return 0;
}

static int bcm_open(struct hci_uart *hu)
static int bcm_open(struct hci_uart *hu)
{
{
	struct bcm_data *bcm;
	struct bcm_data *bcm;
@@ -107,6 +156,12 @@ static int bcm_setup(struct hci_uart *hu)
	if (hu->proto->init_speed)
	if (hu->proto->init_speed)
		hci_uart_set_baudrate(hu, hu->proto->init_speed);
		hci_uart_set_baudrate(hu, hu->proto->init_speed);


	if (hu->proto->oper_speed) {
		err = bcm_set_baudrate(hu, hu->proto->oper_speed);
		if (!err)
			hci_uart_set_baudrate(hu, hu->proto->oper_speed);
	}

finalize:
finalize:
	release_firmware(fw);
	release_firmware(fw);


@@ -162,10 +217,13 @@ static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
static const struct hci_uart_proto bcm_proto = {
static const struct hci_uart_proto bcm_proto = {
	.id		= HCI_UART_BCM,
	.id		= HCI_UART_BCM,
	.name		= "BCM",
	.name		= "BCM",
	.init_speed	= 115200,
	.oper_speed	= 4000000,
	.open		= bcm_open,
	.open		= bcm_open,
	.close		= bcm_close,
	.close		= bcm_close,
	.flush		= bcm_flush,
	.flush		= bcm_flush,
	.setup		= bcm_setup,
	.setup		= bcm_setup,
	.set_baudrate	= bcm_set_baudrate,
	.recv		= bcm_recv,
	.recv		= bcm_recv,
	.enqueue	= bcm_enqueue,
	.enqueue	= bcm_enqueue,
	.dequeue	= bcm_dequeue,
	.dequeue	= bcm_dequeue,