Skip to content

Commit 525d0ae

Browse files
committed
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says: ==================== pull request: bluetooth-next 2018-01-25 Here's one last bluetooth-next pull request for the 4.16 kernel: - Improved support for Intel controllers - New set_parity method to serdev (agreed with maintainers to be taken through bluetooth-next) - Fix error path in hci_bcm (missing call to serdev close) - New ID for BCM4343A0 UART controller Please let me know if there are any issues pulling. Thanks. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents d9ac2d9 + fbbe83c commit 525d0ae

File tree

9 files changed

+328
-231
lines changed

9 files changed

+328
-231
lines changed

drivers/bluetooth/btbcm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ static const struct {
323323
{ 0x410e, "BCM43341B0" }, /* 002.001.014 */
324324
{ 0x4406, "BCM4324B3" }, /* 002.004.006 */
325325
{ 0x610c, "BCM4354" }, /* 003.001.012 */
326+
{ 0x2122, "BCM4343A0" }, /* 001.001.034 */
326327
{ 0x2209, "BCM43430A1" }, /* 001.002.009 */
327328
{ 0x6119, "BCM4345C0" }, /* 003.001.025 */
328329
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */

drivers/bluetooth/btintel.c

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/module.h>
2525
#include <linux/firmware.h>
2626
#include <linux/regmap.h>
27+
#include <asm/unaligned.h>
2728

2829
#include <net/bluetooth/bluetooth.h>
2930
#include <net/bluetooth/hci_core.h>
@@ -569,6 +570,160 @@ struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
569570
}
570571
EXPORT_SYMBOL_GPL(btintel_regmap_init);
571572

573+
int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param)
574+
{
575+
struct intel_reset params = { 0x00, 0x01, 0x00, 0x01, 0x00000000 };
576+
struct sk_buff *skb;
577+
578+
params.boot_param = cpu_to_le32(boot_param);
579+
580+
skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), &params,
581+
HCI_INIT_TIMEOUT);
582+
if (IS_ERR(skb)) {
583+
bt_dev_err(hdev, "Failed to send Intel Reset command");
584+
return PTR_ERR(skb);
585+
}
586+
587+
kfree_skb(skb);
588+
589+
return 0;
590+
}
591+
EXPORT_SYMBOL_GPL(btintel_send_intel_reset);
592+
593+
int btintel_read_boot_params(struct hci_dev *hdev,
594+
struct intel_boot_params *params)
595+
{
596+
struct sk_buff *skb;
597+
598+
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT);
599+
if (IS_ERR(skb)) {
600+
bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)",
601+
PTR_ERR(skb));
602+
return PTR_ERR(skb);
603+
}
604+
605+
if (skb->len != sizeof(*params)) {
606+
bt_dev_err(hdev, "Intel boot parameters size mismatch");
607+
kfree_skb(skb);
608+
return -EILSEQ;
609+
}
610+
611+
memcpy(params, skb->data, sizeof(*params));
612+
613+
kfree_skb(skb);
614+
615+
if (params->status) {
616+
bt_dev_err(hdev, "Intel boot parameters command failed (%02x)",
617+
params->status);
618+
return -bt_to_errno(params->status);
619+
}
620+
621+
bt_dev_info(hdev, "Device revision is %u",
622+
le16_to_cpu(params->dev_revid));
623+
624+
bt_dev_info(hdev, "Secure boot is %s",
625+
params->secure_boot ? "enabled" : "disabled");
626+
627+
bt_dev_info(hdev, "OTP lock is %s",
628+
params->otp_lock ? "enabled" : "disabled");
629+
630+
bt_dev_info(hdev, "API lock is %s",
631+
params->api_lock ? "enabled" : "disabled");
632+
633+
bt_dev_info(hdev, "Debug lock is %s",
634+
params->debug_lock ? "enabled" : "disabled");
635+
636+
bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
637+
params->min_fw_build_nn, params->min_fw_build_cw,
638+
2000 + params->min_fw_build_yy);
639+
640+
return 0;
641+
}
642+
EXPORT_SYMBOL_GPL(btintel_read_boot_params);
643+
644+
int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw,
645+
u32 *boot_param)
646+
{
647+
int err;
648+
const u8 *fw_ptr;
649+
u32 frag_len;
650+
651+
/* Start the firmware download transaction with the Init fragment
652+
* represented by the 128 bytes of CSS header.
653+
*/
654+
err = btintel_secure_send(hdev, 0x00, 128, fw->data);
655+
if (err < 0) {
656+
bt_dev_err(hdev, "Failed to send firmware header (%d)", err);
657+
goto done;
658+
}
659+
660+
/* Send the 256 bytes of public key information from the firmware
661+
* as the PKey fragment.
662+
*/
663+
err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
664+
if (err < 0) {
665+
bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err);
666+
goto done;
667+
}
668+
669+
/* Send the 256 bytes of signature information from the firmware
670+
* as the Sign fragment.
671+
*/
672+
err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
673+
if (err < 0) {
674+
bt_dev_err(hdev, "Failed to send firmware signature (%d)", err);
675+
goto done;
676+
}
677+
678+
fw_ptr = fw->data + 644;
679+
frag_len = 0;
680+
681+
while (fw_ptr - fw->data < fw->size) {
682+
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
683+
684+
/* Each SKU has a different reset parameter to use in the
685+
* HCI_Intel_Reset command and it is embedded in the firmware
686+
* data. So, instead of using static value per SKU, check
687+
* the firmware data and save it for later use.
688+
*/
689+
if (le16_to_cpu(cmd->opcode) == 0xfc0e) {
690+
/* The boot parameter is the first 32-bit value
691+
* and rest of 3 octets are reserved.
692+
*/
693+
*boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
694+
695+
bt_dev_dbg(hdev, "boot_param=0x%x", *boot_param);
696+
}
697+
698+
frag_len += sizeof(*cmd) + cmd->plen;
699+
700+
/* The parameter length of the secure send command requires
701+
* a 4 byte alignment. It happens so that the firmware file
702+
* contains proper Intel_NOP commands to align the fragments
703+
* as needed.
704+
*
705+
* Send set of commands with 4 byte alignment from the
706+
* firmware data buffer as a single Data fragement.
707+
*/
708+
if (!(frag_len % 4)) {
709+
err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
710+
if (err < 0) {
711+
bt_dev_err(hdev,
712+
"Failed to send firmware data (%d)",
713+
err);
714+
goto done;
715+
}
716+
717+
fw_ptr += frag_len;
718+
frag_len = 0;
719+
}
720+
}
721+
722+
done:
723+
return err;
724+
}
725+
EXPORT_SYMBOL_GPL(btintel_download_firmware);
726+
572727
MODULE_AUTHOR("Marcel Holtmann <[email protected]>");
573728
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
574729
MODULE_VERSION(VERSION);

drivers/bluetooth/btintel.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ struct intel_secure_send_result {
6969
__u8 status;
7070
} __packed;
7171

72+
struct intel_reset {
73+
__u8 reset_type;
74+
__u8 patch_enable;
75+
__u8 ddc_reload;
76+
__u8 boot_option;
77+
__le32 boot_param;
78+
} __packed;
79+
7280
#if IS_ENABLED(CONFIG_BT_INTEL)
7381

7482
int btintel_check_bdaddr(struct hci_dev *hdev);
@@ -89,7 +97,11 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver);
8997

9098
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
9199
u16 opcode_write);
92-
100+
int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param);
101+
int btintel_read_boot_params(struct hci_dev *hdev,
102+
struct intel_boot_params *params);
103+
int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw,
104+
u32 *boot_param);
93105
#else
94106

95107
static inline int btintel_check_bdaddr(struct hci_dev *hdev)
@@ -165,4 +177,23 @@ static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
165177
{
166178
return ERR_PTR(-EINVAL);
167179
}
180+
181+
static inline int btintel_send_intel_reset(struct hci_dev *hdev,
182+
u32 reset_param)
183+
{
184+
return -EOPNOTSUPP;
185+
}
186+
187+
static inline int btintel_read_boot_params(struct hci_dev *hdev,
188+
struct intel_boot_params *params)
189+
{
190+
return -EOPNOTSUPP;
191+
}
192+
193+
static inline int btintel_download_firmware(struct hci_dev *dev,
194+
const struct firmware *fw,
195+
u32 *boot_param)
196+
{
197+
return -EOPNOTSUPP;
198+
}
168199
#endif

0 commit comments

Comments
 (0)