cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

btbcm.c (17585B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *
      4 *  Bluetooth support for Broadcom devices
      5 *
      6 *  Copyright (C) 2015  Intel Corporation
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/firmware.h>
     11#include <linux/dmi.h>
     12#include <linux/of.h>
     13#include <asm/unaligned.h>
     14
     15#include <net/bluetooth/bluetooth.h>
     16#include <net/bluetooth/hci_core.h>
     17
     18#include "btbcm.h"
     19
     20#define VERSION "0.1"
     21
     22#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
     23#define BDADDR_BCM20702A1 (&(bdaddr_t) {{0x00, 0x00, 0xa0, 0x02, 0x70, 0x20}})
     24#define BDADDR_BCM2076B1 (&(bdaddr_t) {{0x79, 0x56, 0x00, 0xa0, 0x76, 0x20}})
     25#define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}})
     26#define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}})
     27#define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}})
     28#define BDADDR_BCM4334B0 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb0, 0x34, 0x43}})
     29#define BDADDR_BCM4345C5 (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0xc5, 0x45, 0x43}})
     30#define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}})
     31
     32#define BCM_FW_NAME_LEN			64
     33#define BCM_FW_NAME_COUNT_MAX		4
     34/* For kmalloc-ing the fw-name array instead of putting it on the stack */
     35typedef char bcm_fw_name[BCM_FW_NAME_LEN];
     36
     37int btbcm_check_bdaddr(struct hci_dev *hdev)
     38{
     39	struct hci_rp_read_bd_addr *bda;
     40	struct sk_buff *skb;
     41
     42	skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
     43			     HCI_INIT_TIMEOUT);
     44	if (IS_ERR(skb)) {
     45		int err = PTR_ERR(skb);
     46
     47		bt_dev_err(hdev, "BCM: Reading device address failed (%d)", err);
     48		return err;
     49	}
     50
     51	if (skb->len != sizeof(*bda)) {
     52		bt_dev_err(hdev, "BCM: Device address length mismatch");
     53		kfree_skb(skb);
     54		return -EIO;
     55	}
     56
     57	bda = (struct hci_rp_read_bd_addr *)skb->data;
     58
     59	/* Check if the address indicates a controller with either an
     60	 * invalid or default address. In both cases the device needs
     61	 * to be marked as not having a valid address.
     62	 *
     63	 * The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller
     64	 * with no configured address.
     65	 *
     66	 * The address 20:70:02:A0:00:00 indicates a BCM20702A1 controller
     67	 * with no configured address.
     68	 *
     69	 * The address 20:76:A0:00:56:79 indicates a BCM2076B1 controller
     70	 * with no configured address.
     71	 *
     72	 * The address 43:24:B3:00:00:00 indicates a BCM4324B3 controller
     73	 * with waiting for configuration state.
     74	 *
     75	 * The address 43:30:B1:00:00:00 indicates a BCM4330B1 controller
     76	 * with waiting for configuration state.
     77	 *
     78	 * The address 43:43:A0:12:1F:AC indicates a BCM43430A0 controller
     79	 * with no configured address.
     80	 */
     81	if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) ||
     82	    !bacmp(&bda->bdaddr, BDADDR_BCM20702A1) ||
     83	    !bacmp(&bda->bdaddr, BDADDR_BCM2076B1) ||
     84	    !bacmp(&bda->bdaddr, BDADDR_BCM4324B3) ||
     85	    !bacmp(&bda->bdaddr, BDADDR_BCM4330B1) ||
     86	    !bacmp(&bda->bdaddr, BDADDR_BCM4334B0) ||
     87	    !bacmp(&bda->bdaddr, BDADDR_BCM4345C5) ||
     88	    !bacmp(&bda->bdaddr, BDADDR_BCM43430A0) ||
     89	    !bacmp(&bda->bdaddr, BDADDR_BCM43341B)) {
     90		bt_dev_info(hdev, "BCM: Using default device address (%pMR)",
     91			    &bda->bdaddr);
     92		set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
     93	}
     94
     95	kfree_skb(skb);
     96
     97	return 0;
     98}
     99EXPORT_SYMBOL_GPL(btbcm_check_bdaddr);
    100
    101int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
    102{
    103	struct sk_buff *skb;
    104	int err;
    105
    106	skb = __hci_cmd_sync(hdev, 0xfc01, 6, bdaddr, HCI_INIT_TIMEOUT);
    107	if (IS_ERR(skb)) {
    108		err = PTR_ERR(skb);
    109		bt_dev_err(hdev, "BCM: Change address command failed (%d)", err);
    110		return err;
    111	}
    112	kfree_skb(skb);
    113
    114	return 0;
    115}
    116EXPORT_SYMBOL_GPL(btbcm_set_bdaddr);
    117
    118int btbcm_read_pcm_int_params(struct hci_dev *hdev,
    119			      struct bcm_set_pcm_int_params *params)
    120{
    121	struct sk_buff *skb;
    122	int err = 0;
    123
    124	skb = __hci_cmd_sync(hdev, 0xfc1d, 0, NULL, HCI_INIT_TIMEOUT);
    125	if (IS_ERR(skb)) {
    126		err = PTR_ERR(skb);
    127		bt_dev_err(hdev, "BCM: Read PCM int params failed (%d)", err);
    128		return err;
    129	}
    130
    131	if (skb->len != 6 || skb->data[0]) {
    132		bt_dev_err(hdev, "BCM: Read PCM int params length mismatch");
    133		kfree_skb(skb);
    134		return -EIO;
    135	}
    136
    137	if (params)
    138		memcpy(params, skb->data + 1, 5);
    139
    140	kfree_skb(skb);
    141
    142	return 0;
    143}
    144EXPORT_SYMBOL_GPL(btbcm_read_pcm_int_params);
    145
    146int btbcm_write_pcm_int_params(struct hci_dev *hdev,
    147			       const struct bcm_set_pcm_int_params *params)
    148{
    149	struct sk_buff *skb;
    150	int err;
    151
    152	skb = __hci_cmd_sync(hdev, 0xfc1c, 5, params, HCI_INIT_TIMEOUT);
    153	if (IS_ERR(skb)) {
    154		err = PTR_ERR(skb);
    155		bt_dev_err(hdev, "BCM: Write PCM int params failed (%d)", err);
    156		return err;
    157	}
    158	kfree_skb(skb);
    159
    160	return 0;
    161}
    162EXPORT_SYMBOL_GPL(btbcm_write_pcm_int_params);
    163
    164int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw)
    165{
    166	const struct hci_command_hdr *cmd;
    167	const u8 *fw_ptr;
    168	size_t fw_size;
    169	struct sk_buff *skb;
    170	u16 opcode;
    171	int err = 0;
    172
    173	/* Start Download */
    174	skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT);
    175	if (IS_ERR(skb)) {
    176		err = PTR_ERR(skb);
    177		bt_dev_err(hdev, "BCM: Download Minidrv command failed (%d)",
    178			   err);
    179		goto done;
    180	}
    181	kfree_skb(skb);
    182
    183	/* 50 msec delay after Download Minidrv completes */
    184	msleep(50);
    185
    186	fw_ptr = fw->data;
    187	fw_size = fw->size;
    188
    189	while (fw_size >= sizeof(*cmd)) {
    190		const u8 *cmd_param;
    191
    192		cmd = (struct hci_command_hdr *)fw_ptr;
    193		fw_ptr += sizeof(*cmd);
    194		fw_size -= sizeof(*cmd);
    195
    196		if (fw_size < cmd->plen) {
    197			bt_dev_err(hdev, "BCM: Patch is corrupted");
    198			err = -EINVAL;
    199			goto done;
    200		}
    201
    202		cmd_param = fw_ptr;
    203		fw_ptr += cmd->plen;
    204		fw_size -= cmd->plen;
    205
    206		opcode = le16_to_cpu(cmd->opcode);
    207
    208		skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param,
    209				     HCI_INIT_TIMEOUT);
    210		if (IS_ERR(skb)) {
    211			err = PTR_ERR(skb);
    212			bt_dev_err(hdev, "BCM: Patch command %04x failed (%d)",
    213				   opcode, err);
    214			goto done;
    215		}
    216		kfree_skb(skb);
    217	}
    218
    219	/* 250 msec delay after Launch Ram completes */
    220	msleep(250);
    221
    222done:
    223	return err;
    224}
    225EXPORT_SYMBOL(btbcm_patchram);
    226
    227static int btbcm_reset(struct hci_dev *hdev)
    228{
    229	struct sk_buff *skb;
    230
    231	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
    232	if (IS_ERR(skb)) {
    233		int err = PTR_ERR(skb);
    234
    235		bt_dev_err(hdev, "BCM: Reset failed (%d)", err);
    236		return err;
    237	}
    238	kfree_skb(skb);
    239
    240	/* 100 msec delay for module to complete reset process */
    241	msleep(100);
    242
    243	return 0;
    244}
    245
    246static struct sk_buff *btbcm_read_local_name(struct hci_dev *hdev)
    247{
    248	struct sk_buff *skb;
    249
    250	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL,
    251			     HCI_INIT_TIMEOUT);
    252	if (IS_ERR(skb)) {
    253		bt_dev_err(hdev, "BCM: Reading local name failed (%ld)",
    254			   PTR_ERR(skb));
    255		return skb;
    256	}
    257
    258	if (skb->len != sizeof(struct hci_rp_read_local_name)) {
    259		bt_dev_err(hdev, "BCM: Local name length mismatch");
    260		kfree_skb(skb);
    261		return ERR_PTR(-EIO);
    262	}
    263
    264	return skb;
    265}
    266
    267static struct sk_buff *btbcm_read_local_version(struct hci_dev *hdev)
    268{
    269	struct sk_buff *skb;
    270
    271	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
    272			     HCI_INIT_TIMEOUT);
    273	if (IS_ERR(skb)) {
    274		bt_dev_err(hdev, "BCM: Reading local version info failed (%ld)",
    275			   PTR_ERR(skb));
    276		return skb;
    277	}
    278
    279	if (skb->len != sizeof(struct hci_rp_read_local_version)) {
    280		bt_dev_err(hdev, "BCM: Local version length mismatch");
    281		kfree_skb(skb);
    282		return ERR_PTR(-EIO);
    283	}
    284
    285	return skb;
    286}
    287
    288static struct sk_buff *btbcm_read_verbose_config(struct hci_dev *hdev)
    289{
    290	struct sk_buff *skb;
    291
    292	skb = __hci_cmd_sync(hdev, 0xfc79, 0, NULL, HCI_INIT_TIMEOUT);
    293	if (IS_ERR(skb)) {
    294		bt_dev_err(hdev, "BCM: Read verbose config info failed (%ld)",
    295			   PTR_ERR(skb));
    296		return skb;
    297	}
    298
    299	if (skb->len != 7) {
    300		bt_dev_err(hdev, "BCM: Verbose config length mismatch");
    301		kfree_skb(skb);
    302		return ERR_PTR(-EIO);
    303	}
    304
    305	return skb;
    306}
    307
    308static struct sk_buff *btbcm_read_controller_features(struct hci_dev *hdev)
    309{
    310	struct sk_buff *skb;
    311
    312	skb = __hci_cmd_sync(hdev, 0xfc6e, 0, NULL, HCI_INIT_TIMEOUT);
    313	if (IS_ERR(skb)) {
    314		bt_dev_err(hdev, "BCM: Read controller features failed (%ld)",
    315			   PTR_ERR(skb));
    316		return skb;
    317	}
    318
    319	if (skb->len != 9) {
    320		bt_dev_err(hdev, "BCM: Controller features length mismatch");
    321		kfree_skb(skb);
    322		return ERR_PTR(-EIO);
    323	}
    324
    325	return skb;
    326}
    327
    328static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev)
    329{
    330	struct sk_buff *skb;
    331
    332	skb = __hci_cmd_sync(hdev, 0xfc5a, 0, NULL, HCI_INIT_TIMEOUT);
    333	if (IS_ERR(skb)) {
    334		bt_dev_err(hdev, "BCM: Read USB product info failed (%ld)",
    335			   PTR_ERR(skb));
    336		return skb;
    337	}
    338
    339	if (skb->len != 5) {
    340		bt_dev_err(hdev, "BCM: USB product length mismatch");
    341		kfree_skb(skb);
    342		return ERR_PTR(-EIO);
    343	}
    344
    345	return skb;
    346}
    347
    348static const struct dmi_system_id disable_broken_read_transmit_power[] = {
    349	{
    350		 .matches = {
    351			DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
    352			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,1"),
    353		},
    354	},
    355	{
    356		 .matches = {
    357			DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
    358			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,2"),
    359		},
    360	},
    361	{
    362		 .matches = {
    363			DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
    364			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,4"),
    365		},
    366	},
    367	{
    368		 .matches = {
    369			DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
    370			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir8,1"),
    371		},
    372	},
    373	{
    374		 .matches = {
    375			DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
    376			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir8,2"),
    377		},
    378	},
    379	{
    380		 .matches = {
    381			DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
    382			DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,1"),
    383		},
    384	},
    385	{
    386		 .matches = {
    387			DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
    388			DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,2"),
    389		},
    390	},
    391	{ }
    392};
    393
    394static int btbcm_read_info(struct hci_dev *hdev)
    395{
    396	struct sk_buff *skb;
    397
    398	/* Read Verbose Config Version Info */
    399	skb = btbcm_read_verbose_config(hdev);
    400	if (IS_ERR(skb))
    401		return PTR_ERR(skb);
    402
    403	bt_dev_info(hdev, "BCM: chip id %u", skb->data[1]);
    404	kfree_skb(skb);
    405
    406	/* Read Controller Features */
    407	skb = btbcm_read_controller_features(hdev);
    408	if (IS_ERR(skb))
    409		return PTR_ERR(skb);
    410
    411	bt_dev_info(hdev, "BCM: features 0x%2.2x", skb->data[1]);
    412	kfree_skb(skb);
    413
    414	/* Read DMI and disable broken Read LE Min/Max Tx Power */
    415	if (dmi_first_match(disable_broken_read_transmit_power))
    416		set_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks);
    417
    418	return 0;
    419}
    420
    421static int btbcm_print_local_name(struct hci_dev *hdev)
    422{
    423	struct sk_buff *skb;
    424
    425	/* Read Local Name */
    426	skb = btbcm_read_local_name(hdev);
    427	if (IS_ERR(skb))
    428		return PTR_ERR(skb);
    429
    430	bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
    431	kfree_skb(skb);
    432
    433	return 0;
    434}
    435
    436struct bcm_subver_table {
    437	u16 subver;
    438	const char *name;
    439};
    440
    441static const struct bcm_subver_table bcm_uart_subver_table[] = {
    442	{ 0x1111, "BCM4362A2"	},	/* 000.017.017 */
    443	{ 0x4103, "BCM4330B1"	},	/* 002.001.003 */
    444	{ 0x410d, "BCM4334B0"	},	/* 002.001.013 */
    445	{ 0x410e, "BCM43341B0"	},	/* 002.001.014 */
    446	{ 0x4204, "BCM2076B1"	},	/* 002.002.004 */
    447	{ 0x4406, "BCM4324B3"	},	/* 002.004.006 */
    448	{ 0x4606, "BCM4324B5"	},	/* 002.006.006 */
    449	{ 0x6109, "BCM4335C0"	},	/* 003.001.009 */
    450	{ 0x610c, "BCM4354"	},	/* 003.001.012 */
    451	{ 0x2122, "BCM4343A0"	},	/* 001.001.034 */
    452	{ 0x2209, "BCM43430A1"  },	/* 001.002.009 */
    453	{ 0x6119, "BCM4345C0"	},	/* 003.001.025 */
    454	{ 0x6606, "BCM4345C5"	},	/* 003.006.006 */
    455	{ 0x230f, "BCM4356A2"	},	/* 001.003.015 */
    456	{ 0x220e, "BCM20702A1"  },	/* 001.002.014 */
    457	{ 0x4217, "BCM4329B1"   },	/* 002.002.023 */
    458	{ 0x6106, "BCM4359C0"	},	/* 003.001.006 */
    459	{ 0x4106, "BCM4335A0"	},	/* 002.001.006 */
    460	{ 0x410c, "BCM43430B0"	},	/* 002.001.012 */
    461	{ 0x2119, "BCM4373A0"	},	/* 001.001.025 */
    462	{ }
    463};
    464
    465static const struct bcm_subver_table bcm_usb_subver_table[] = {
    466	{ 0x2105, "BCM20703A1"	},	/* 001.001.005 */
    467	{ 0x210b, "BCM43142A0"	},	/* 001.001.011 */
    468	{ 0x2112, "BCM4314A0"	},	/* 001.001.018 */
    469	{ 0x2118, "BCM20702A0"	},	/* 001.001.024 */
    470	{ 0x2126, "BCM4335A0"	},	/* 001.001.038 */
    471	{ 0x220e, "BCM20702A1"	},	/* 001.002.014 */
    472	{ 0x230f, "BCM4356A2"	},	/* 001.003.015 */
    473	{ 0x4106, "BCM4335B0"	},	/* 002.001.006 */
    474	{ 0x410e, "BCM20702B0"	},	/* 002.001.014 */
    475	{ 0x6109, "BCM4335C0"	},	/* 003.001.009 */
    476	{ 0x610c, "BCM4354"	},	/* 003.001.012 */
    477	{ 0x6607, "BCM4350C5"	},	/* 003.006.007 */
    478	{ }
    479};
    480
    481/*
    482 * This currently only looks up the device tree board appendix,
    483 * but can be expanded to other mechanisms.
    484 */
    485static const char *btbcm_get_board_name(struct device *dev)
    486{
    487#ifdef CONFIG_OF
    488	struct device_node *root;
    489	char *board_type;
    490	const char *tmp;
    491	int len;
    492	int i;
    493
    494	root = of_find_node_by_path("/");
    495	if (!root)
    496		return NULL;
    497
    498	if (of_property_read_string_index(root, "compatible", 0, &tmp))
    499		return NULL;
    500
    501	/* get rid of any '/' in the compatible string */
    502	len = strlen(tmp) + 1;
    503	board_type = devm_kzalloc(dev, len, GFP_KERNEL);
    504	strscpy(board_type, tmp, len);
    505	for (i = 0; i < board_type[i]; i++) {
    506		if (board_type[i] == '/')
    507			board_type[i] = '-';
    508	}
    509	of_node_put(root);
    510
    511	return board_type;
    512#else
    513	return NULL;
    514#endif
    515}
    516
    517int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
    518{
    519	u16 subver, rev, pid, vid;
    520	struct sk_buff *skb;
    521	struct hci_rp_read_local_version *ver;
    522	const struct bcm_subver_table *bcm_subver_table;
    523	const char *hw_name = NULL;
    524	const char *board_name;
    525	char postfix[16] = "";
    526	int fw_name_count = 0;
    527	bcm_fw_name *fw_name;
    528	const struct firmware *fw;
    529	int i, err;
    530
    531	board_name = btbcm_get_board_name(&hdev->dev);
    532
    533	/* Reset */
    534	err = btbcm_reset(hdev);
    535	if (err)
    536		return err;
    537
    538	/* Read Local Version Info */
    539	skb = btbcm_read_local_version(hdev);
    540	if (IS_ERR(skb))
    541		return PTR_ERR(skb);
    542
    543	ver = (struct hci_rp_read_local_version *)skb->data;
    544	rev = le16_to_cpu(ver->hci_rev);
    545	subver = le16_to_cpu(ver->lmp_subver);
    546	kfree_skb(skb);
    547
    548	/* Read controller information */
    549	if (!(*fw_load_done)) {
    550		err = btbcm_read_info(hdev);
    551		if (err)
    552			return err;
    553	}
    554	err = btbcm_print_local_name(hdev);
    555	if (err)
    556		return err;
    557
    558	bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table :
    559						    bcm_uart_subver_table;
    560
    561	for (i = 0; bcm_subver_table[i].name; i++) {
    562		if (subver == bcm_subver_table[i].subver) {
    563			hw_name = bcm_subver_table[i].name;
    564			break;
    565		}
    566	}
    567
    568	bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u",
    569		    hw_name ? hw_name : "BCM", (subver & 0xe000) >> 13,
    570		    (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
    571
    572	if (*fw_load_done)
    573		return 0;
    574
    575	if (hdev->bus == HCI_USB) {
    576		/* Read USB Product Info */
    577		skb = btbcm_read_usb_product(hdev);
    578		if (IS_ERR(skb))
    579			return PTR_ERR(skb);
    580
    581		vid = get_unaligned_le16(skb->data + 1);
    582		pid = get_unaligned_le16(skb->data + 3);
    583		kfree_skb(skb);
    584
    585		snprintf(postfix, sizeof(postfix), "-%4.4x-%4.4x", vid, pid);
    586	}
    587
    588	fw_name = kmalloc(BCM_FW_NAME_COUNT_MAX * BCM_FW_NAME_LEN, GFP_KERNEL);
    589	if (!fw_name)
    590		return -ENOMEM;
    591
    592	if (hw_name) {
    593		if (board_name) {
    594			snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
    595				 "brcm/%s%s.%s.hcd", hw_name, postfix, board_name);
    596			fw_name_count++;
    597		}
    598		snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
    599			 "brcm/%s%s.hcd", hw_name, postfix);
    600		fw_name_count++;
    601	}
    602
    603	if (board_name) {
    604		snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
    605			 "brcm/BCM%s.%s.hcd", postfix, board_name);
    606		fw_name_count++;
    607	}
    608	snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
    609		 "brcm/BCM%s.hcd", postfix);
    610	fw_name_count++;
    611
    612	for (i = 0; i < fw_name_count; i++) {
    613		err = firmware_request_nowarn(&fw, fw_name[i], &hdev->dev);
    614		if (err == 0) {
    615			bt_dev_info(hdev, "%s '%s' Patch",
    616				    hw_name ? hw_name : "BCM", fw_name[i]);
    617			*fw_load_done = true;
    618			break;
    619		}
    620	}
    621
    622	if (*fw_load_done) {
    623		err = btbcm_patchram(hdev, fw);
    624		if (err)
    625			bt_dev_info(hdev, "BCM: Patch failed (%d)", err);
    626
    627		release_firmware(fw);
    628	} else {
    629		bt_dev_err(hdev, "BCM: firmware Patch file not found, tried:");
    630		for (i = 0; i < fw_name_count; i++)
    631			bt_dev_err(hdev, "BCM: '%s'", fw_name[i]);
    632	}
    633
    634	kfree(fw_name);
    635	return 0;
    636}
    637EXPORT_SYMBOL_GPL(btbcm_initialize);
    638
    639int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done)
    640{
    641	int err;
    642
    643	/* Re-initialize if necessary */
    644	if (*fw_load_done) {
    645		err = btbcm_initialize(hdev, fw_load_done);
    646		if (err)
    647			return err;
    648	}
    649
    650	btbcm_check_bdaddr(hdev);
    651
    652	set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
    653
    654	return 0;
    655}
    656EXPORT_SYMBOL_GPL(btbcm_finalize);
    657
    658int btbcm_setup_patchram(struct hci_dev *hdev)
    659{
    660	bool fw_load_done = false;
    661	int err;
    662
    663	/* Initialize */
    664	err = btbcm_initialize(hdev, &fw_load_done);
    665	if (err)
    666		return err;
    667
    668	/* Re-initialize after loading Patch */
    669	return btbcm_finalize(hdev, &fw_load_done);
    670}
    671EXPORT_SYMBOL_GPL(btbcm_setup_patchram);
    672
    673int btbcm_setup_apple(struct hci_dev *hdev)
    674{
    675	struct sk_buff *skb;
    676	int err;
    677
    678	/* Reset */
    679	err = btbcm_reset(hdev);
    680	if (err)
    681		return err;
    682
    683	/* Read Verbose Config Version Info */
    684	skb = btbcm_read_verbose_config(hdev);
    685	if (!IS_ERR(skb)) {
    686		bt_dev_info(hdev, "BCM: chip id %u build %4.4u",
    687			    skb->data[1], get_unaligned_le16(skb->data + 5));
    688		kfree_skb(skb);
    689	}
    690
    691	/* Read USB Product Info */
    692	skb = btbcm_read_usb_product(hdev);
    693	if (!IS_ERR(skb)) {
    694		bt_dev_info(hdev, "BCM: product %4.4x:%4.4x",
    695			    get_unaligned_le16(skb->data + 1),
    696			    get_unaligned_le16(skb->data + 3));
    697		kfree_skb(skb);
    698	}
    699
    700	/* Read Controller Features */
    701	skb = btbcm_read_controller_features(hdev);
    702	if (!IS_ERR(skb)) {
    703		bt_dev_info(hdev, "BCM: features 0x%2.2x", skb->data[1]);
    704		kfree_skb(skb);
    705	}
    706
    707	/* Read Local Name */
    708	skb = btbcm_read_local_name(hdev);
    709	if (!IS_ERR(skb)) {
    710		bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
    711		kfree_skb(skb);
    712	}
    713
    714	set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
    715
    716	return 0;
    717}
    718EXPORT_SYMBOL_GPL(btbcm_setup_apple);
    719
    720MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
    721MODULE_DESCRIPTION("Bluetooth support for Broadcom devices ver " VERSION);
    722MODULE_VERSION(VERSION);
    723MODULE_LICENSE("GPL");