brintos

brintos / linux-shallow public Read only

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