mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 15:29:16 +00:00
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 <davem@davemloft.net>
This commit is contained in:
commit
525d0ae7a2
@ -323,6 +323,7 @@ static const struct {
|
||||
{ 0x410e, "BCM43341B0" }, /* 002.001.014 */
|
||||
{ 0x4406, "BCM4324B3" }, /* 002.004.006 */
|
||||
{ 0x610c, "BCM4354" }, /* 003.001.012 */
|
||||
{ 0x2122, "BCM4343A0" }, /* 001.001.034 */
|
||||
{ 0x2209, "BCM43430A1" }, /* 001.002.009 */
|
||||
{ 0x6119, "BCM4345C0" }, /* 003.001.025 */
|
||||
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
@ -569,6 +570,160 @@ struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_regmap_init);
|
||||
|
||||
int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param)
|
||||
{
|
||||
struct intel_reset params = { 0x00, 0x01, 0x00, 0x01, 0x00000000 };
|
||||
struct sk_buff *skb;
|
||||
|
||||
params.boot_param = cpu_to_le32(boot_param);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), ¶ms,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
bt_dev_err(hdev, "Failed to send Intel Reset command");
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_send_intel_reset);
|
||||
|
||||
int btintel_read_boot_params(struct hci_dev *hdev,
|
||||
struct intel_boot_params *params)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)",
|
||||
PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*params)) {
|
||||
bt_dev_err(hdev, "Intel boot parameters size mismatch");
|
||||
kfree_skb(skb);
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
memcpy(params, skb->data, sizeof(*params));
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
if (params->status) {
|
||||
bt_dev_err(hdev, "Intel boot parameters command failed (%02x)",
|
||||
params->status);
|
||||
return -bt_to_errno(params->status);
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "Device revision is %u",
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
bt_dev_info(hdev, "Secure boot is %s",
|
||||
params->secure_boot ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "OTP lock is %s",
|
||||
params->otp_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "API lock is %s",
|
||||
params->api_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "Debug lock is %s",
|
||||
params->debug_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
|
||||
params->min_fw_build_nn, params->min_fw_build_cw,
|
||||
2000 + params->min_fw_build_yy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_read_boot_params);
|
||||
|
||||
int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw,
|
||||
u32 *boot_param)
|
||||
{
|
||||
int err;
|
||||
const u8 *fw_ptr;
|
||||
u32 frag_len;
|
||||
|
||||
/* Start the firmware download transaction with the Init fragment
|
||||
* represented by the 128 bytes of CSS header.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x00, 128, fw->data);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware header (%d)", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of public key information from the firmware
|
||||
* as the PKey fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of signature information from the firmware
|
||||
* as the Sign fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware signature (%d)", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr = fw->data + 644;
|
||||
frag_len = 0;
|
||||
|
||||
while (fw_ptr - fw->data < fw->size) {
|
||||
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
|
||||
|
||||
/* Each SKU has a different reset parameter to use in the
|
||||
* HCI_Intel_Reset command and it is embedded in the firmware
|
||||
* data. So, instead of using static value per SKU, check
|
||||
* the firmware data and save it for later use.
|
||||
*/
|
||||
if (le16_to_cpu(cmd->opcode) == 0xfc0e) {
|
||||
/* The boot parameter is the first 32-bit value
|
||||
* and rest of 3 octets are reserved.
|
||||
*/
|
||||
*boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
|
||||
|
||||
bt_dev_dbg(hdev, "boot_param=0x%x", *boot_param);
|
||||
}
|
||||
|
||||
frag_len += sizeof(*cmd) + cmd->plen;
|
||||
|
||||
/* The parameter length of the secure send command requires
|
||||
* a 4 byte alignment. It happens so that the firmware file
|
||||
* contains proper Intel_NOP commands to align the fragments
|
||||
* as needed.
|
||||
*
|
||||
* Send set of commands with 4 byte alignment from the
|
||||
* firmware data buffer as a single Data fragement.
|
||||
*/
|
||||
if (!(frag_len % 4)) {
|
||||
err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev,
|
||||
"Failed to send firmware data (%d)",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr += frag_len;
|
||||
frag_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_download_firmware);
|
||||
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
|
@ -69,6 +69,14 @@ struct intel_secure_send_result {
|
||||
__u8 status;
|
||||
} __packed;
|
||||
|
||||
struct intel_reset {
|
||||
__u8 reset_type;
|
||||
__u8 patch_enable;
|
||||
__u8 ddc_reload;
|
||||
__u8 boot_option;
|
||||
__le32 boot_param;
|
||||
} __packed;
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_INTEL)
|
||||
|
||||
int btintel_check_bdaddr(struct hci_dev *hdev);
|
||||
@ -89,7 +97,11 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver);
|
||||
|
||||
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
|
||||
u16 opcode_write);
|
||||
|
||||
int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param);
|
||||
int btintel_read_boot_params(struct hci_dev *hdev,
|
||||
struct intel_boot_params *params);
|
||||
int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw,
|
||||
u32 *boot_param);
|
||||
#else
|
||||
|
||||
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,
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline int btintel_send_intel_reset(struct hci_dev *hdev,
|
||||
u32 reset_param)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int btintel_read_boot_params(struct hci_dev *hdev,
|
||||
struct intel_boot_params *params)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int btintel_download_firmware(struct hci_dev *dev,
|
||||
const struct firmware *fw,
|
||||
u32 *boot_param)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
@ -2009,15 +2009,11 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
{
|
||||
static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
|
||||
0x00, 0x08, 0x04, 0x00 };
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
struct sk_buff *skb;
|
||||
struct intel_version ver;
|
||||
struct intel_boot_params *params;
|
||||
struct intel_boot_params params;
|
||||
const struct firmware *fw;
|
||||
const u8 *fw_ptr;
|
||||
u32 frag_len;
|
||||
u32 boot_param;
|
||||
char fwname[64];
|
||||
ktime_t calltime, delta, rettime;
|
||||
unsigned long long duration;
|
||||
@ -2025,6 +2021,12 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
/* Set the default boot parameter to 0x0 and it is updated to
|
||||
* SKU specific boot parameter after reading Intel_Write_Boot_Params
|
||||
* command while downloading the firmware.
|
||||
*/
|
||||
boot_param = 0x00000000;
|
||||
|
||||
calltime = ktime_get();
|
||||
|
||||
/* Read the Intel version information to determine if the device
|
||||
@ -2095,55 +2097,24 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
/* Read the secure boot parameters to identify the operating
|
||||
* details of the bootloader.
|
||||
*/
|
||||
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("%s: Reading Intel boot parameters failed (%ld)",
|
||||
hdev->name, PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*params)) {
|
||||
BT_ERR("%s: Intel boot parameters size mismatch", hdev->name);
|
||||
kfree_skb(skb);
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
params = (struct intel_boot_params *)skb->data;
|
||||
|
||||
bt_dev_info(hdev, "Device revision is %u",
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
bt_dev_info(hdev, "Secure boot is %s",
|
||||
params->secure_boot ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "OTP lock is %s",
|
||||
params->otp_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "API lock is %s",
|
||||
params->api_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "Debug lock is %s",
|
||||
params->debug_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
|
||||
params->min_fw_build_nn, params->min_fw_build_cw,
|
||||
2000 + params->min_fw_build_yy);
|
||||
err = btintel_read_boot_params(hdev, ¶ms);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* It is required that every single firmware fragment is acknowledged
|
||||
* with a command complete event. If the boot parameters indicate
|
||||
* that this bootloader does not send them, then abort the setup.
|
||||
*/
|
||||
if (params->limited_cce != 0x00) {
|
||||
if (params.limited_cce != 0x00) {
|
||||
BT_ERR("%s: Unsupported Intel firmware loading method (%u)",
|
||||
hdev->name, params->limited_cce);
|
||||
kfree_skb(skb);
|
||||
hdev->name, params.limited_cce);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If the OTP has no valid Bluetooth device address, then there will
|
||||
* also be no valid address for the operational firmware.
|
||||
*/
|
||||
if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) {
|
||||
if (!bacmp(¶ms.otp_bdaddr, BDADDR_ANY)) {
|
||||
bt_dev_info(hdev, "No device address configured");
|
||||
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
|
||||
}
|
||||
@ -2174,7 +2145,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params->dev_revid));
|
||||
le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x11: /* JfP */
|
||||
case 0x12: /* ThP */
|
||||
@ -2192,7 +2163,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to load Intel firmware file (%d)",
|
||||
hdev->name, err);
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2206,7 +2176,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params->dev_revid));
|
||||
le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x11: /* JfP */
|
||||
case 0x12: /* ThP */
|
||||
@ -2220,8 +2190,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
if (fw->size < 644) {
|
||||
BT_ERR("%s: Invalid size of firmware file (%zu)",
|
||||
hdev->name, fw->size);
|
||||
@ -2231,64 +2199,10 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
|
||||
set_bit(BTUSB_DOWNLOADING, &data->flags);
|
||||
|
||||
/* Start the firmware download transaction with the Init fragment
|
||||
* represented by the 128 bytes of CSS header.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x00, 128, fw->data);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware header (%d)",
|
||||
hdev->name, err);
|
||||
/* Start firmware downloading and get boot parameter */
|
||||
err = btintel_download_firmware(hdev, fw, &boot_param);
|
||||
if (err < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of public key information from the firmware
|
||||
* as the PKey fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware public key (%d)",
|
||||
hdev->name, err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of signature information from the firmware
|
||||
* as the Sign fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware signature (%d)",
|
||||
hdev->name, err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr = fw->data + 644;
|
||||
frag_len = 0;
|
||||
|
||||
while (fw_ptr - fw->data < fw->size) {
|
||||
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
|
||||
|
||||
frag_len += sizeof(*cmd) + cmd->plen;
|
||||
|
||||
/* The parameter length of the secure send command requires
|
||||
* a 4 byte alignment. It happens so that the firmware file
|
||||
* contains proper Intel_NOP commands to align the fragments
|
||||
* as needed.
|
||||
*
|
||||
* Send set of commands with 4 byte alignment from the
|
||||
* firmware data buffer as a single Data fragement.
|
||||
*/
|
||||
if (!(frag_len % 4)) {
|
||||
err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware data (%d)",
|
||||
hdev->name, err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr += frag_len;
|
||||
frag_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
|
||||
|
||||
@ -2341,12 +2255,9 @@ done:
|
||||
|
||||
set_bit(BTUSB_BOOTING, &data->flags);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
kfree_skb(skb);
|
||||
err = btintel_send_intel_reset(hdev, boot_param);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The bootloader will not indicate when the device is ready. This
|
||||
* is done by the operational firmware sending bootup notification.
|
||||
|
@ -412,8 +412,11 @@ out:
|
||||
return 0;
|
||||
|
||||
err_unset_hu:
|
||||
if (hu->serdev)
|
||||
serdev_device_close(hu->serdev);
|
||||
#ifdef CONFIG_PM
|
||||
bcm->dev->hu = NULL;
|
||||
else
|
||||
bcm->dev->hu = NULL;
|
||||
#endif
|
||||
err_free:
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
|
@ -540,18 +540,15 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed)
|
||||
|
||||
static int intel_setup(struct hci_uart *hu)
|
||||
{
|
||||
static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
|
||||
0x00, 0x08, 0x04, 0x00 };
|
||||
struct intel_data *intel = hu->priv;
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
struct sk_buff *skb;
|
||||
struct intel_version ver;
|
||||
struct intel_boot_params *params;
|
||||
struct intel_boot_params params;
|
||||
struct list_head *p;
|
||||
const struct firmware *fw;
|
||||
const u8 *fw_ptr;
|
||||
char fwname[64];
|
||||
u32 frag_len;
|
||||
u32 boot_param;
|
||||
ktime_t calltime, delta, rettime;
|
||||
unsigned long long duration;
|
||||
unsigned int init_speed, oper_speed;
|
||||
@ -563,6 +560,12 @@ static int intel_setup(struct hci_uart *hu)
|
||||
hu->hdev->set_diag = btintel_set_diag;
|
||||
hu->hdev->set_bdaddr = btintel_set_bdaddr;
|
||||
|
||||
/* Set the default boot parameter to 0x0 and it is updated to
|
||||
* SKU specific boot parameter after reading Intel_Write_Boot_Params
|
||||
* command while downloading the firmware.
|
||||
*/
|
||||
boot_param = 0x00000000;
|
||||
|
||||
calltime = ktime_get();
|
||||
|
||||
if (hu->init_speed)
|
||||
@ -656,85 +659,95 @@ static int intel_setup(struct hci_uart *hu)
|
||||
/* Read the secure boot parameters to identify the operating
|
||||
* details of the bootloader.
|
||||
*/
|
||||
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)",
|
||||
PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*params)) {
|
||||
bt_dev_err(hdev, "Intel boot parameters size mismatch");
|
||||
kfree_skb(skb);
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
params = (struct intel_boot_params *)skb->data;
|
||||
if (params->status) {
|
||||
bt_dev_err(hdev, "Intel boot parameters command failure (%02x)",
|
||||
params->status);
|
||||
err = -bt_to_errno(params->status);
|
||||
kfree_skb(skb);
|
||||
err = btintel_read_boot_params(hdev, ¶ms);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "Device revision is %u",
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
bt_dev_info(hdev, "Secure boot is %s",
|
||||
params->secure_boot ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
|
||||
params->min_fw_build_nn, params->min_fw_build_cw,
|
||||
2000 + params->min_fw_build_yy);
|
||||
|
||||
/* It is required that every single firmware fragment is acknowledged
|
||||
* with a command complete event. If the boot parameters indicate
|
||||
* that this bootloader does not send them, then abort the setup.
|
||||
*/
|
||||
if (params->limited_cce != 0x00) {
|
||||
if (params.limited_cce != 0x00) {
|
||||
bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)",
|
||||
params->limited_cce);
|
||||
kfree_skb(skb);
|
||||
params.limited_cce);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If the OTP has no valid Bluetooth device address, then there will
|
||||
* also be no valid address for the operational firmware.
|
||||
*/
|
||||
if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) {
|
||||
if (!bacmp(¶ms.otp_bdaddr, BDADDR_ANY)) {
|
||||
bt_dev_info(hdev, "No device address configured");
|
||||
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
|
||||
}
|
||||
|
||||
/* With this Intel bootloader only the hardware variant and device
|
||||
* revision information are used to select the right firmware.
|
||||
* revision information are used to select the right firmware for SfP
|
||||
* and WsP.
|
||||
*
|
||||
* The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi.
|
||||
*
|
||||
* Currently the supported hardware variants are:
|
||||
* 11 (0x0b) for iBT 3.0 (LnP/SfP)
|
||||
* 12 (0x0c) for iBT 3.5 (WsP)
|
||||
*
|
||||
* For ThP/JfP and for future SKU's, the FW name varies based on HW
|
||||
* variant, HW revision and FW revision, as these are dependent on CNVi
|
||||
* and RF Combination.
|
||||
*
|
||||
* 18 (0x12) for iBT3.5 (ThP/JfP)
|
||||
*
|
||||
* The firmware file name for these will be
|
||||
* ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi.
|
||||
*
|
||||
*/
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params->dev_revid));
|
||||
switch (ver.hw_variant) {
|
||||
case 0x0b: /* SfP */
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x12: /* ThP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(ver.hw_revision),
|
||||
le16_to_cpu(ver.fw_revision));
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
|
||||
ver.hw_variant);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = request_firmware(&fw, fwname, &hdev->dev);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to load Intel firmware file (%d)",
|
||||
err);
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "Found device firmware: %s", fwname);
|
||||
|
||||
/* Save the DDC file name for later */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
kfree_skb(skb);
|
||||
switch (ver.hw_variant) {
|
||||
case 0x0b: /* SfP */
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x12: /* ThP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(ver.hw_revision),
|
||||
le16_to_cpu(ver.fw_revision));
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
|
||||
ver.hw_variant);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fw->size < 644) {
|
||||
bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
|
||||
@ -745,70 +758,10 @@ static int intel_setup(struct hci_uart *hu)
|
||||
|
||||
set_bit(STATE_DOWNLOADING, &intel->flags);
|
||||
|
||||
/* Start the firmware download transaction with the Init fragment
|
||||
* represented by the 128 bytes of CSS header.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x00, 128, fw->data);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware header (%d)", err);
|
||||
/* Start firmware downloading and get boot parameter */
|
||||
err = btintel_download_firmware(hdev, fw, &boot_param);
|
||||
if (err < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of public key information from the firmware
|
||||
* as the PKey fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware public key (%d)",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of signature information from the firmware
|
||||
* as the Sign fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware signature (%d)",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr = fw->data + 644;
|
||||
frag_len = 0;
|
||||
|
||||
while (fw_ptr - fw->data < fw->size) {
|
||||
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
|
||||
|
||||
frag_len += sizeof(*cmd) + cmd->plen;
|
||||
|
||||
bt_dev_dbg(hdev, "Patching %td/%zu", (fw_ptr - fw->data),
|
||||
fw->size);
|
||||
|
||||
/* The parameter length of the secure send command requires
|
||||
* a 4 byte alignment. It happens so that the firmware file
|
||||
* contains proper Intel_NOP commands to align the fragments
|
||||
* as needed.
|
||||
*
|
||||
* Send set of commands with 4 byte alignment from the
|
||||
* firmware data buffer as a single Data fragement.
|
||||
*/
|
||||
if (frag_len % 4)
|
||||
continue;
|
||||
|
||||
/* Send each command from the firmware data buffer as
|
||||
* a single Data fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware data (%d)",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr += frag_len;
|
||||
frag_len = 0;
|
||||
}
|
||||
|
||||
set_bit(STATE_FIRMWARE_LOADED, &intel->flags);
|
||||
|
||||
@ -869,12 +822,9 @@ done:
|
||||
|
||||
set_bit(STATE_BOOTING, &intel->flags);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
|
||||
HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
kfree_skb(skb);
|
||||
err = btintel_send_intel_reset(hdev, boot_param);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The bootloader will not indicate when the device is ready. This
|
||||
* is done by the operational firmware sending bootup notification.
|
||||
|
@ -225,6 +225,18 @@ void serdev_device_set_flow_control(struct serdev_device *serdev, bool enable)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serdev_device_set_flow_control);
|
||||
|
||||
int serdev_device_set_parity(struct serdev_device *serdev,
|
||||
enum serdev_parity parity)
|
||||
{
|
||||
struct serdev_controller *ctrl = serdev->ctrl;
|
||||
|
||||
if (!ctrl || !ctrl->ops->set_parity)
|
||||
return -ENOTSUPP;
|
||||
|
||||
return ctrl->ops->set_parity(ctrl, parity);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serdev_device_set_parity);
|
||||
|
||||
void serdev_device_wait_until_sent(struct serdev_device *serdev, long timeout)
|
||||
{
|
||||
struct serdev_controller *ctrl = serdev->ctrl;
|
||||
|
@ -190,6 +190,29 @@ static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable
|
||||
tty_set_termios(tty, &ktermios);
|
||||
}
|
||||
|
||||
static int ttyport_set_parity(struct serdev_controller *ctrl,
|
||||
enum serdev_parity parity)
|
||||
{
|
||||
struct serport *serport = serdev_controller_get_drvdata(ctrl);
|
||||
struct tty_struct *tty = serport->tty;
|
||||
struct ktermios ktermios = tty->termios;
|
||||
|
||||
ktermios.c_cflag &= ~(PARENB | PARODD | CMSPAR);
|
||||
if (parity != SERDEV_PARITY_NONE) {
|
||||
ktermios.c_cflag |= PARENB;
|
||||
if (parity == SERDEV_PARITY_ODD)
|
||||
ktermios.c_cflag |= PARODD;
|
||||
}
|
||||
|
||||
tty_set_termios(tty, &ktermios);
|
||||
|
||||
if ((tty->termios.c_cflag & (PARENB | PARODD | CMSPAR)) !=
|
||||
(ktermios.c_cflag & (PARENB | PARODD | CMSPAR)))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ttyport_wait_until_sent(struct serdev_controller *ctrl, long timeout)
|
||||
{
|
||||
struct serport *serport = serdev_controller_get_drvdata(ctrl);
|
||||
@ -227,6 +250,7 @@ static const struct serdev_controller_ops ctrl_ops = {
|
||||
.open = ttyport_open,
|
||||
.close = ttyport_close,
|
||||
.set_flow_control = ttyport_set_flow_control,
|
||||
.set_parity = ttyport_set_parity,
|
||||
.set_baudrate = ttyport_set_baudrate,
|
||||
.wait_until_sent = ttyport_wait_until_sent,
|
||||
.get_tiocm = ttyport_get_tiocm,
|
||||
|
@ -76,6 +76,12 @@ static inline struct serdev_device_driver *to_serdev_device_driver(struct device
|
||||
return container_of(d, struct serdev_device_driver, driver);
|
||||
}
|
||||
|
||||
enum serdev_parity {
|
||||
SERDEV_PARITY_NONE,
|
||||
SERDEV_PARITY_EVEN,
|
||||
SERDEV_PARITY_ODD,
|
||||
};
|
||||
|
||||
/*
|
||||
* serdev controller structures
|
||||
*/
|
||||
@ -86,6 +92,7 @@ struct serdev_controller_ops {
|
||||
int (*open)(struct serdev_controller *);
|
||||
void (*close)(struct serdev_controller *);
|
||||
void (*set_flow_control)(struct serdev_controller *, bool);
|
||||
int (*set_parity)(struct serdev_controller *, enum serdev_parity);
|
||||
unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int);
|
||||
void (*wait_until_sent)(struct serdev_controller *, long);
|
||||
int (*get_tiocm)(struct serdev_controller *);
|
||||
@ -298,6 +305,9 @@ static inline int serdev_device_set_rts(struct serdev_device *serdev, bool enabl
|
||||
return serdev_device_set_tiocm(serdev, 0, TIOCM_RTS);
|
||||
}
|
||||
|
||||
int serdev_device_set_parity(struct serdev_device *serdev,
|
||||
enum serdev_parity parity);
|
||||
|
||||
/*
|
||||
* serdev hooks into TTY core
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user