diff options
author | David S. Miller <davem@davemloft.net> | 2018-01-25 16:32:28 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-25 16:32:28 -0500 |
commit | 525d0ae7a2ee1b70f09936dbac56b0d4920fa005 (patch) | |
tree | 684d4e6657b54d7279826eff9b6088e4ba0e16ef | |
parent | d9ac2d99787d08c0e3f777dac5aeaa3fed61b692 (diff) | |
parent | fbbe83c52bc0d52398de72d7df1857cc9b36244e (diff) |
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>
-rw-r--r-- | drivers/bluetooth/btbcm.c | 1 | ||||
-rw-r--r-- | drivers/bluetooth/btintel.c | 155 | ||||
-rw-r--r-- | drivers/bluetooth/btintel.h | 33 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 133 | ||||
-rw-r--r-- | drivers/bluetooth/hci_bcm.c | 5 | ||||
-rw-r--r-- | drivers/bluetooth/hci_intel.c | 186 | ||||
-rw-r--r-- | drivers/tty/serdev/core.c | 12 | ||||
-rw-r--r-- | drivers/tty/serdev/serdev-ttyport.c | 24 | ||||
-rw-r--r-- | include/linux/serdev.h | 10 |
9 files changed, 328 insertions, 231 deletions
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index afa4cb3b16e3..6659f113042c 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -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 */ diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 07f00e422e85..5270d5513201 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -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); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 1e8955aaafed..41c642cc523f 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -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 diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 29977ebfd031..2a55380ad730 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -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); - 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); + /* Start firmware downloading and get boot parameter */ + err = btintel_download_firmware(hdev, fw, &boot_param); + if (err < 0) 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. diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 64800cd2796c..0438a64b8185 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -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); diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index aad07e40ea4f..7c166e3b308b 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -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); - 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); + /* Start firmware downloading and get boot parameter */ + err = btintel_download_firmware(hdev, fw, &boot_param); + if (err < 0) 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. diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 1bef39828ca7..3c573a8caa80 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -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; diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index 247788a16f0b..1bdf2959ac5c 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -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, diff --git a/include/linux/serdev.h b/include/linux/serdev.h index d609e6dc5bad..a73d87b483b4 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h @@ -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 */ |