Make the driver more generic by adding a driver info struct. We also add support for devices without firmware (for example when the firmware is loaded by the WLAN driver on a combined module). Signed-off-by: Matthias Schiffer <matthias.schiffer@xxxxxxxxxxxxxxx> --- drivers/bluetooth/hci_mrvl.c | 57 +++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/drivers/bluetooth/hci_mrvl.c b/drivers/bluetooth/hci_mrvl.c index fbc3f7c3a5c7..5d191687a34a 100644 --- a/drivers/bluetooth/hci_mrvl.c +++ b/drivers/bluetooth/hci_mrvl.c @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/tty.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/serdev.h> #include <net/bluetooth/bluetooth.h> @@ -33,6 +34,20 @@ enum { STATE_FW_REQ_PENDING, }; +struct mrvl_driver_info { + const char *firmware_helper; + const char *firmware; +}; + +static const struct mrvl_driver_info mrvl_driver_info_8897 = { + .firmware_helper = "mrvl/helper_uart_3000000.bin", + .firmware = "mrvl/uart8897_bt.bin", +}; + +/* Fallback for non-OF instances */ +static const struct mrvl_driver_info *const mrvl_driver_info_default = + &mrvl_driver_info_8897; + struct mrvl_data { struct sk_buff *rx_skb; struct sk_buff_head txq; @@ -44,6 +59,7 @@ struct mrvl_data { struct mrvl_serdev { struct hci_uart hu; + const struct mrvl_driver_info *info; }; struct hci_mrvl_pkt { @@ -353,18 +369,29 @@ static int mrvl_load_firmware(struct hci_dev *hdev, const char *name) static int mrvl_setup(struct hci_uart *hu) { + const struct mrvl_driver_info *info; int err; - hci_uart_set_flow_control(hu, true); + if (hu->serdev) { + struct mrvl_serdev *mrvldev = serdev_device_get_drvdata(hu->serdev); - err = mrvl_load_firmware(hu->hdev, "mrvl/helper_uart_3000000.bin"); - if (err) { - bt_dev_err(hu->hdev, "Unable to download firmware helper"); - return -EINVAL; + info = mrvldev->info; + } else { + info = mrvl_driver_info_default; } - /* Let the final ack go out before switching the baudrate */ - hci_uart_wait_until_sent(hu); + if (info->firmware_helper) { + hci_uart_set_flow_control(hu, true); + + err = mrvl_load_firmware(hu->hdev, info->firmware_helper); + if (err) { + bt_dev_err(hu->hdev, "Unable to download firmware helper"); + return -EINVAL; + } + + /* Let the final ack go out before switching the baudrate */ + hci_uart_wait_until_sent(hu); + } if (hu->serdev) serdev_device_set_baudrate(hu->serdev, 3000000); @@ -373,9 +400,11 @@ static int mrvl_setup(struct hci_uart *hu) hci_uart_set_flow_control(hu, false); - err = mrvl_load_firmware(hu->hdev, "mrvl/uart8897_bt.bin"); - if (err) - return err; + if (info->firmware) { + err = mrvl_load_firmware(hu->hdev, info->firmware); + if (err) + return err; + } return 0; } @@ -401,6 +430,12 @@ static int mrvl_serdev_probe(struct serdev_device *serdev) if (!mrvldev) return -ENOMEM; + if (IS_ENABLED(CONFIG_OF)) { + mrvldev->info = of_device_get_match_data(&serdev->dev); + if (!mrvldev->info) + return -ENODEV; + } + mrvldev->hu.serdev = serdev; serdev_device_set_drvdata(serdev, mrvldev); @@ -416,7 +451,7 @@ static void mrvl_serdev_remove(struct serdev_device *serdev) #ifdef CONFIG_OF static const struct of_device_id mrvl_bluetooth_of_match[] = { - { .compatible = "mrvl,88w8897" }, + { .compatible = "mrvl,88w8897", .data = &mrvl_driver_info_8897 }, { }, }; MODULE_DEVICE_TABLE(of, mrvl_bluetooth_of_match); -- 2.25.1