Commit 5d6f3910 authored by Abhishek Pandit-Subedi's avatar Abhishek Pandit-Subedi Committed by Johan Hedberg
Browse files

Bluetooth: hci_bcm: Disallow set_baudrate for BCM4354



Without updating the patchram, the BCM4354 does not support a higher
operating speed. The normal bcm_setup follows the correct order
(init_speed, patchram and then oper_speed) but the serdev driver will
set the operating speed before calling the hu->setup function. Thus,
for the BCM4354, don't set the operating speed before patchram.

Signed-off-by: default avatarAbhishek Pandit-Subedi <abhishekpandit@chromium.org>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent 34682110
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -47,6 +47,14 @@

#define BCM_NUM_SUPPLIES 2

/**
 * struct bcm_device_data - device specific data
 * @no_early_set_baudrate: Disallow set baudrate before driver setup()
 */
struct bcm_device_data {
	bool	no_early_set_baudrate;
};

/**
 * struct bcm_device - device driver resources
 * @serdev_hu: HCI UART controller struct
@@ -79,6 +87,7 @@
 * @hu: pointer to HCI UART controller struct,
 *	used to disable flow control during runtime suspend and system sleep
 * @is_suspended: whether flow control is currently disabled
 * @no_early_set_baudrate: don't set_baudrate before setup()
 */
struct bcm_device {
	/* Must be the first member, hci_serdev.c expects this. */
@@ -112,6 +121,7 @@ struct bcm_device {
	struct hci_uart		*hu;
	bool			is_suspended;
#endif
	bool			no_early_set_baudrate;
};

/* generic bcm uart resources */
@@ -447,7 +457,13 @@ out:
	if (bcm->dev) {
		hci_uart_set_flow_control(hu, true);
		hu->init_speed = bcm->dev->init_speed;

		/* If oper_speed is set, ldisc/serdev will set the baudrate
		 * before calling setup()
		 */
		if (!bcm->dev->no_early_set_baudrate)
			hu->oper_speed = bcm->dev->oper_speed;

		err = bcm_gpio_set_power(bcm->dev, true);
		hci_uart_set_flow_control(hu, false);
		if (err)
@@ -565,6 +581,8 @@ static int bcm_setup(struct hci_uart *hu)
	/* Operational speed if any */
	if (hu->oper_speed)
		speed = hu->oper_speed;
	else if (bcm->dev && bcm->dev->oper_speed)
		speed = bcm->dev->oper_speed;
	else if (hu->proto->oper_speed)
		speed = hu->proto->oper_speed;
	else
@@ -1374,6 +1392,7 @@ static struct platform_driver bcm_driver = {
static int bcm_serdev_probe(struct serdev_device *serdev)
{
	struct bcm_device *bcmdev;
	const struct bcm_device_data *data;
	int err;

	bcmdev = devm_kzalloc(&serdev->dev, sizeof(*bcmdev), GFP_KERNEL);
@@ -1408,6 +1427,10 @@ static int bcm_serdev_probe(struct serdev_device *serdev)
	if (err)
		dev_err(&serdev->dev, "Failed to power down\n");

	data = device_get_match_data(bcmdev->dev);
	if (data)
		bcmdev->no_early_set_baudrate = data->no_early_set_baudrate;

	return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto);
}

@@ -1419,12 +1442,16 @@ static void bcm_serdev_remove(struct serdev_device *serdev)
}

#ifdef CONFIG_OF
static struct bcm_device_data bcm4354_device_data = {
	.no_early_set_baudrate = true,
};

static const struct of_device_id bcm_bluetooth_of_match[] = {
	{ .compatible = "brcm,bcm20702a1" },
	{ .compatible = "brcm,bcm4345c5" },
	{ .compatible = "brcm,bcm4330-bt" },
	{ .compatible = "brcm,bcm43438-bt" },
	{ .compatible = "brcm,bcm43540-bt" },
	{ .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data },
	{ .compatible = "brcm,bcm4335a0" },
	{ },
};