Bluetooth: btbcm: Add helper functions for UART setup
authorFrederic Danis <frederic.danis@linux.intel.com>
Thu, 28 May 2015 09:25:04 +0000 (11:25 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Sat, 6 Jun 2015 05:33:25 +0000 (07:33 +0200)
Firmware loading may reset the controller UART speed and needs to set
host UART speed back to init speed.

UART drivers setup is split in 3 parts:
- btbcm_initialize() resets the controller and returns the firmware
  name based on controller revision and sub_version.
- btbtcm_patchram() (already existing and public), which takes the
  firmware name as parameter, requests the firmware and loads it to
  the controller.
- btbcm_finalize() which resets the controller, reads local version
  and checks if the controller address is a default one or not.

Remove firmware name retrieval for UART controllers from
btbcm_setup_patchram().

Signed-off-by: Frederic Danis <frederic.danis@linux.intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
drivers/bluetooth/btbcm.c
drivers/bluetooth/btbcm.h

index 14e4647686bd56b0ea92bea4e225697611920fd6..8e2f6b6251c4c2ef3e866860aef8abc491b8a5de 100644 (file)
@@ -246,6 +246,95 @@ static const struct {
        { }
 };
 
+int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len)
+{
+       u16 subver, rev;
+       const char *hw_name = NULL;
+       struct sk_buff *skb;
+       struct hci_rp_read_local_version *ver;
+       int i, err;
+
+       /* Reset */
+       err = btbcm_reset(hdev);
+       if (err)
+               return err;
+
+       /* Read Local Version Info */
+       skb = btbcm_read_local_version(hdev);
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       ver = (struct hci_rp_read_local_version *)skb->data;
+       rev = le16_to_cpu(ver->hci_rev);
+       subver = le16_to_cpu(ver->lmp_subver);
+       kfree_skb(skb);
+
+       /* Read Verbose Config Version Info */
+       skb = btbcm_read_verbose_config(hdev);
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
+       kfree_skb(skb);
+
+       switch ((rev & 0xf000) >> 12) {
+       case 0:
+       case 3:
+               for (i = 0; bcm_uart_subver_table[i].name; i++) {
+                       if (subver == bcm_uart_subver_table[i].subver) {
+                               hw_name = bcm_uart_subver_table[i].name;
+                               break;
+                       }
+               }
+
+               snprintf(fw_name, len, "brcm/%s.hcd", hw_name ? : "BCM");
+               break;
+       default:
+               return 0;
+       }
+
+       BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name,
+               hw_name ? : "BCM", (subver & 0x7000) >> 13,
+               (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(btbcm_initialize);
+
+int btbcm_finalize(struct hci_dev *hdev)
+{
+       struct sk_buff *skb;
+       struct hci_rp_read_local_version *ver;
+       u16 subver, rev;
+       int err;
+
+       /* Reset */
+       err = btbcm_reset(hdev);
+       if (err)
+               return err;
+
+       /* Read Local Version Info */
+       skb = btbcm_read_local_version(hdev);
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       ver = (struct hci_rp_read_local_version *)skb->data;
+       rev = le16_to_cpu(ver->hci_rev);
+       subver = le16_to_cpu(ver->lmp_subver);
+       kfree_skb(skb);
+
+       BT_INFO("%s: BCM (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name,
+               (subver & 0x7000) >> 13, (subver & 0x1f00) >> 8,
+               (subver & 0x00ff), rev & 0x0fff);
+
+       btbcm_check_bdaddr(hdev);
+
+       set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(btbcm_finalize);
+
 static const struct {
        u16 subver;
        const char *name;
index 42f26a6c7f8184f8406b472ea40941aeaff4eb0c..f405f84243993e96af51f873638cc5880d3a77a9 100644 (file)
@@ -30,6 +30,9 @@ int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw);
 int btbcm_setup_patchram(struct hci_dev *hdev);
 int btbcm_setup_apple(struct hci_dev *hdev);
 
+int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len);
+int btbcm_finalize(struct hci_dev *hdev);
+
 #else
 
 static inline int btbcm_check_bdaddr(struct hci_dev *hdev)
@@ -57,4 +60,15 @@ static inline int btbcm_setup_apple(struct hci_dev *hdev)
        return 0;
 }
 
+static inline int btbcm_initialize(struct hci_dev *hdev, char *fw_name,
+                                  size_t len)
+{
+       return 0;
+}
+
+static inline int btbcm_finalize(struct hci_dev *hdev)
+{
+       return 0;
+}
+
 #endif