diff mbox series

Bluetooth: hci_bcm4377: Add BCM4388 support

Message ID 20240602-btbcm4388-v1-1-210e4b4eeb3b@svenpeter.dev (mailing list archive)
State Accepted
Commit 0b22b7f8aef3450dd9a035ccdb9ff3419530d892
Headers show
Series Bluetooth: hci_bcm4377: Add BCM4388 support | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
tedd_an/CheckPatch success CheckPatch PASS
tedd_an/GitLint success Gitlint PASS
tedd_an/SubjectPrefix success Gitlint PASS
tedd_an/BuildKernel success BuildKernel PASS
tedd_an/CheckAllWarning success CheckAllWarning PASS
tedd_an/CheckSparse success CheckSparse PASS
tedd_an/CheckSmatch fail CheckSparse: FAIL: Segmentation fault (core dumped) make[4]: *** [scripts/Makefile.build:244: net/bluetooth/hci_core.o] Error 139 make[4]: *** Deleting file 'net/bluetooth/hci_core.o' make[3]: *** [scripts/Makefile.build:485: net/bluetooth] Error 2 make[2]: *** [scripts/Makefile.build:485: net] Error 2 make[2]: *** Waiting for unfinished jobs.... Segmentation fault (core dumped) make[4]: *** [scripts/Makefile.build:244: drivers/bluetooth/bcm203x.o] Error 139 make[4]: *** Deleting file 'drivers/bluetooth/bcm203x.o' make[4]: *** Waiting for unfinished jobs.... make[3]: *** [scripts/Makefile.build:485: drivers/bluetooth] Error 2 make[2]: *** [scripts/Makefile.build:485: drivers] Error 2 make[1]: *** [/github/workspace/src/src/Makefile:1919: .] Error 2 make: *** [Makefile:240: __sub-make] Error 2
tedd_an/BuildKernel32 success BuildKernel32 PASS
tedd_an/TestRunnerSetup success TestRunnerSetup PASS
tedd_an/TestRunner_l2cap-tester success TestRunner PASS
tedd_an/TestRunner_iso-tester fail TestRunner_iso-tester: Total: 122, Passed: 117 (95.9%), Failed: 1, Not Run: 4
tedd_an/TestRunner_bnep-tester success TestRunner PASS
tedd_an/TestRunner_mgmt-tester fail TestRunner_mgmt-tester: Total: 492, Passed: 488 (99.2%), Failed: 2, Not Run: 2
tedd_an/TestRunner_rfcomm-tester success TestRunner PASS
tedd_an/TestRunner_sco-tester success TestRunner PASS
tedd_an/TestRunner_ioctl-tester success TestRunner PASS
tedd_an/TestRunner_mesh-tester success TestRunner PASS
tedd_an/TestRunner_smp-tester success TestRunner PASS
tedd_an/TestRunner_userchan-tester success TestRunner PASS
tedd_an/IncrementalBuild success Incremental Build PASS

Commit Message

Sven Peter via B4 Relay June 2, 2024, 9:57 a.m. UTC
From: Hector Martin <marcan@marcan.st>

This new variant needs a different core2_window1 and always uses
beamforming.
The BAR2 also has an offset (RAM start, presumably), so add that.

Signed-off-by: Hector Martin <marcan@marcan.st>
Reviewed-by: Sven Peter <sven@svenpeter.dev>
[sven: rebased, updated some comments, mentioned 4388 in Kconfig]
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
Hi,

This is just a single commit mostly written by Hector that adds support
for BCM4388 chips. I've just rebased this to the current bluetooth-next
since it also needs 9dc8ac15ca5 and adjusted some comments.

Best,

Sven
---
 drivers/bluetooth/Kconfig       |  6 ++--
 drivers/bluetooth/hci_bcm4377.c | 61 +++++++++++++++++++++++++++++++----------
 2 files changed, 50 insertions(+), 17 deletions(-)


---
base-commit: 3c376f35eb13a144d5039d911b35110c2beef815
change-id: 20240602-btbcm4388-431aed90d763

Best regards,

Comments

bluez.test.bot@gmail.com June 2, 2024, 10:32 a.m. UTC | #1
This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=858002

---Test result---

Test Summary:
CheckPatch                    PASS      0.87 seconds
GitLint                       PASS      0.28 seconds
SubjectPrefix                 PASS      0.10 seconds
BuildKernel                   PASS      29.38 seconds
CheckAllWarning               PASS      32.57 seconds
CheckSparse                   PASS      37.35 seconds
CheckSmatch                   FAIL      34.82 seconds
BuildKernel32                 PASS      28.38 seconds
TestRunnerSetup               PASS      513.41 seconds
TestRunner_l2cap-tester       PASS      20.19 seconds
TestRunner_iso-tester         FAIL      30.48 seconds
TestRunner_bnep-tester        PASS      4.81 seconds
TestRunner_mgmt-tester        FAIL      110.91 seconds
TestRunner_rfcomm-tester      PASS      7.42 seconds
TestRunner_sco-tester         PASS      15.02 seconds
TestRunner_ioctl-tester       PASS      7.82 seconds
TestRunner_mesh-tester        PASS      5.97 seconds
TestRunner_smp-tester         PASS      6.90 seconds
TestRunner_userchan-tester    PASS      6.49 seconds
IncrementalBuild              PASS      28.22 seconds

Details
##############################
Test: CheckSmatch - FAIL
Desc: Run smatch tool with source
Output:

Segmentation fault (core dumped)
make[4]: *** [scripts/Makefile.build:244: net/bluetooth/hci_core.o] Error 139
make[4]: *** Deleting file 'net/bluetooth/hci_core.o'
make[3]: *** [scripts/Makefile.build:485: net/bluetooth] Error 2
make[2]: *** [scripts/Makefile.build:485: net] Error 2
make[2]: *** Waiting for unfinished jobs....
Segmentation fault (core dumped)
make[4]: *** [scripts/Makefile.build:244: drivers/bluetooth/bcm203x.o] Error 139
make[4]: *** Deleting file 'drivers/bluetooth/bcm203x.o'
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [scripts/Makefile.build:485: drivers/bluetooth] Error 2
make[2]: *** [scripts/Makefile.build:485: drivers] Error 2
make[1]: *** [/github/workspace/src/src/Makefile:1919: .] Error 2
make: *** [Makefile:240: __sub-make] Error 2
##############################
Test: TestRunner_iso-tester - FAIL
Desc: Run iso-tester with test-runner
Output:
Total: 122, Passed: 117 (95.9%), Failed: 1, Not Run: 4

Failed Test Cases
ISO Connect2 Suspend - Success                       Failed       4.240 seconds
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 492, Passed: 488 (99.2%), Failed: 2, Not Run: 2

Failed Test Cases
LL Privacy - Add Device 5 (2 Devices to RL)          Failed       0.170 seconds
LL Privacy - Add Device 7 (AL is full)               Failed       0.198 seconds


---
Regards,
Linux Bluetooth
Neal Gompa June 6, 2024, 5:02 p.m. UTC | #2
On Sun, Jun 2, 2024 at 2:57 AM Sven Peter via B4 Relay
<devnull+sven.svenpeter.dev@kernel.org> wrote:
>
> From: Hector Martin <marcan@marcan.st>
>
> This new variant needs a different core2_window1 and always uses
> beamforming.
> The BAR2 also has an offset (RAM start, presumably), so add that.
>
> Signed-off-by: Hector Martin <marcan@marcan.st>
> Reviewed-by: Sven Peter <sven@svenpeter.dev>
> [sven: rebased, updated some comments, mentioned 4388 in Kconfig]
> Signed-off-by: Sven Peter <sven@svenpeter.dev>
> ---
> Hi,
>
> This is just a single commit mostly written by Hector that adds support
> for BCM4388 chips. I've just rebased this to the current bluetooth-next
> since it also needs 9dc8ac15ca5 and adjusted some comments.
>
> Best,
>
> Sven
> ---
>  drivers/bluetooth/Kconfig       |  6 ++--
>  drivers/bluetooth/hci_bcm4377.c | 61 +++++++++++++++++++++++++++++++----------
>  2 files changed, 50 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
> index 0b5f218ac505..87484f5de8e3 100644
> --- a/drivers/bluetooth/Kconfig
> +++ b/drivers/bluetooth/Kconfig
> @@ -287,12 +287,12 @@ config BT_HCIBCM203X
>
>
>  config BT_HCIBCM4377
> -       tristate "HCI BCM4377/4378/4387 PCIe driver"
> +       tristate "HCI BCM4377/4378/4387/4388 PCIe driver"
>         depends on PCI
>         select FW_LOADER
>         help
> -         Support for Broadcom BCM4377/4378/4387 Bluetooth chipsets attached via
> -         PCIe. These are usually found in Apple machines.
> +         Support for Broadcom BCM4377/4378/4387/4388 Bluetooth chipsets
> +         attached via PCIe. These are usually found in Apple machines.
>
>           Say Y here to compile support for HCI BCM4377 family devices into the
>           kernel or say M to compile it as module (hci_bcm4377).
> diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c
> index e6644cb0163c..77a5454a8721 100644
> --- a/drivers/bluetooth/hci_bcm4377.c
> +++ b/drivers/bluetooth/hci_bcm4377.c
> @@ -1,6 +1,6 @@
>  // SPDX-License-Identifier: GPL-2.0-only OR MIT
>  /*
> - * Bluetooth HCI driver for Broadcom 4377/4378/4387 devices attached via PCIe
> + * Bluetooth HCI driver for Broadcom 4377/4378/4387/4388 devices attached via PCIe
>   *
>   * Copyright (C) The Asahi Linux Contributors
>   */
> @@ -26,11 +26,13 @@ enum bcm4377_chip {
>         BCM4377 = 0,
>         BCM4378,
>         BCM4387,
> +       BCM4388,
>  };
>
>  #define BCM4377_DEVICE_ID 0x5fa0
>  #define BCM4378_DEVICE_ID 0x5f69
>  #define BCM4387_DEVICE_ID 0x5f71
> +#define BCM4388_DEVICE_ID 0x5f72
>
>  #define BCM4377_TIMEOUT msecs_to_jiffies(1000)
>  #define BCM4377_BOOT_TIMEOUT msecs_to_jiffies(5000)
> @@ -488,6 +490,7 @@ struct bcm4377_data;
>   *                     second window in BAR0
>   * has_bar0_core2_window2: Set to true if this chip requires the second core's
>   *                         second window to be configured
> + * bar2_offset: Offset to the start of the variables in BAR2
>   * clear_pciecfg_subsystem_ctrl_bit19: Set to true if bit 19 in the
>   *                                     vendor-specific subsystem control
>   *                                     register has to be cleared
> @@ -511,6 +514,7 @@ struct bcm4377_hw {
>         u32 bar0_window1;
>         u32 bar0_window2;
>         u32 bar0_core2_window2;
> +       u32 bar2_offset;
>
>         unsigned long has_bar0_core2_window2 : 1;
>         unsigned long clear_pciecfg_subsystem_ctrl_bit19 : 1;
> @@ -836,8 +840,8 @@ static irqreturn_t bcm4377_irq(int irq, void *data)
>         struct bcm4377_data *bcm4377 = data;
>         u32 bootstage, rti_status;
>
> -       bootstage = ioread32(bcm4377->bar2 + BCM4377_BAR2_BOOTSTAGE);
> -       rti_status = ioread32(bcm4377->bar2 + BCM4377_BAR2_RTI_STATUS);
> +       bootstage = ioread32(bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_BOOTSTAGE);
> +       rti_status = ioread32(bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_RTI_STATUS);
>
>         if (bootstage != bcm4377->bootstage ||
>             rti_status != bcm4377->rti_status) {
> @@ -1197,6 +1201,14 @@ static int bcm4387_send_calibration(struct bcm4377_data *bcm4377)
>                                                   bcm4377->taurus_cal_size);
>  }
>
> +static int bcm4388_send_calibration(struct bcm4377_data *bcm4377)
> +{
> +       /* BCM4388 always uses beamforming */
> +       return __bcm4378_send_calibration(
> +               bcm4377, bcm4377->taurus_beamforming_cal_blob,
> +               bcm4377->taurus_beamforming_cal_size);
> +}
> +
>  static const struct firmware *bcm4377_request_blob(struct bcm4377_data *bcm4377,
>                                                    const char *suffix)
>  {
> @@ -1820,8 +1832,8 @@ static int bcm4377_boot(struct bcm4377_data *bcm4377)
>         int ret = 0;
>         u32 bootstage, rti_status;
>
> -       bootstage = ioread32(bcm4377->bar2 + BCM4377_BAR2_BOOTSTAGE);
> -       rti_status = ioread32(bcm4377->bar2 + BCM4377_BAR2_RTI_STATUS);
> +       bootstage = ioread32(bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_BOOTSTAGE);
> +       rti_status = ioread32(bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_RTI_STATUS);
>
>         if (bootstage != 0) {
>                 dev_err(&bcm4377->pdev->dev, "bootstage is %d and not 0\n",
> @@ -1855,9 +1867,12 @@ static int bcm4377_boot(struct bcm4377_data *bcm4377)
>         iowrite32(BCM4377_DMA_MASK,
>                   bcm4377->bar0 + BCM4377_BAR0_HOST_WINDOW_SIZE);
>
> -       iowrite32(lower_32_bits(fw_dma), bcm4377->bar2 + BCM4377_BAR2_FW_LO);
> -       iowrite32(upper_32_bits(fw_dma), bcm4377->bar2 + BCM4377_BAR2_FW_HI);
> -       iowrite32(fw->size, bcm4377->bar2 + BCM4377_BAR2_FW_SIZE);
> +       iowrite32(lower_32_bits(fw_dma),
> +                 bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_FW_LO);
> +       iowrite32(upper_32_bits(fw_dma),
> +                 bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_FW_HI);
> +       iowrite32(fw->size,
> +                 bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_FW_SIZE);
>         iowrite32(0, bcm4377->bar0 + BCM4377_BAR0_FW_DOORBELL);
>
>         dev_dbg(&bcm4377->pdev->dev, "waiting for firmware to boot\n");
> @@ -1914,16 +1929,16 @@ static int bcm4377_setup_rti(struct bcm4377_data *bcm4377)
>         dev_dbg(&bcm4377->pdev->dev, "RTI is in state 1\n");
>
>         /* allow access to the entire IOVA space again */
> -       iowrite32(0, bcm4377->bar2 + BCM4377_BAR2_RTI_WINDOW_LO);
> -       iowrite32(0, bcm4377->bar2 + BCM4377_BAR2_RTI_WINDOW_HI);
> +       iowrite32(0, bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_RTI_WINDOW_LO);
> +       iowrite32(0, bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_RTI_WINDOW_HI);
>         iowrite32(BCM4377_DMA_MASK,
> -                 bcm4377->bar2 + BCM4377_BAR2_RTI_WINDOW_SIZE);
> +                 bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_RTI_WINDOW_SIZE);
>
>         /* setup "Converged IPC" context */
>         iowrite32(lower_32_bits(bcm4377->ctx_dma),
> -                 bcm4377->bar2 + BCM4377_BAR2_CONTEXT_ADDR_LO);
> +                 bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_CONTEXT_ADDR_LO);
>         iowrite32(upper_32_bits(bcm4377->ctx_dma),
> -                 bcm4377->bar2 + BCM4377_BAR2_CONTEXT_ADDR_HI);
> +                 bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_CONTEXT_ADDR_HI);
>         iowrite32(2, bcm4377->bar0 + BCM4377_BAR0_RTI_CONTROL);
>
>         ret = wait_for_completion_interruptible_timeout(&bcm4377->event,
> @@ -2489,6 +2504,21 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
>                 .send_calibration = bcm4387_send_calibration,
>                 .send_ptb = bcm4378_send_ptb,
>         },
> +
> +       [BCM4388] = {
> +               .id = 0x4388,
> +               .otp_offset = 0x415c,
> +               .bar2_offset = 0x200000,
> +               .bar0_window1 = 0x18002000,
> +               .bar0_window2 = 0x18109000,
> +               .bar0_core2_window2 = 0x18106000,
> +               .has_bar0_core2_window2 = true,
> +               .broken_mws_transport_config = true,
> +               .broken_le_coded = true,
> +               .broken_le_ext_adv_report_phy = true,
> +               .send_calibration = bcm4388_send_calibration,
> +               .send_ptb = bcm4378_send_ptb,
> +       },
>  };
>
>  #define BCM4377_DEVID_ENTRY(id)                                             \
> @@ -2502,6 +2532,7 @@ static const struct pci_device_id bcm4377_devid_table[] = {
>         BCM4377_DEVID_ENTRY(4377),
>         BCM4377_DEVID_ENTRY(4378),
>         BCM4377_DEVID_ENTRY(4387),
> +       BCM4377_DEVID_ENTRY(4388),
>         {},
>  };
>  MODULE_DEVICE_TABLE(pci, bcm4377_devid_table);
> @@ -2516,7 +2547,7 @@ static struct pci_driver bcm4377_pci_driver = {
>  module_pci_driver(bcm4377_pci_driver);
>
>  MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>");
> -MODULE_DESCRIPTION("Bluetooth support for Broadcom 4377/4378/4387 devices");
> +MODULE_DESCRIPTION("Bluetooth support for Broadcom 4377/4378/4387/4388 devices");
>  MODULE_LICENSE("Dual MIT/GPL");
>  MODULE_FIRMWARE("brcm/brcmbt4377*.bin");
>  MODULE_FIRMWARE("brcm/brcmbt4377*.ptb");
> @@ -2524,3 +2555,5 @@ MODULE_FIRMWARE("brcm/brcmbt4378*.bin");
>  MODULE_FIRMWARE("brcm/brcmbt4378*.ptb");
>  MODULE_FIRMWARE("brcm/brcmbt4387*.bin");
>  MODULE_FIRMWARE("brcm/brcmbt4387*.ptb");
> +MODULE_FIRMWARE("brcm/brcmbt4388*.bin");
> +MODULE_FIRMWARE("brcm/brcmbt4388*.ptb");
>
> ---
> base-commit: 3c376f35eb13a144d5039d911b35110c2beef815
> change-id: 20240602-btbcm4388-431aed90d763
>

This looks good to me.

Reviewed-by: Neal Gompa <neal@gompa.dev>
patchwork-bot+bluetooth@kernel.org June 6, 2024, 7:40 p.m. UTC | #3
Hello:

This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Sun, 02 Jun 2024 09:57:05 +0000 you wrote:
> From: Hector Martin <marcan@marcan.st>
> 
> This new variant needs a different core2_window1 and always uses
> beamforming.
> The BAR2 also has an offset (RAM start, presumably), so add that.
> 
> Signed-off-by: Hector Martin <marcan@marcan.st>
> Reviewed-by: Sven Peter <sven@svenpeter.dev>
> [sven: rebased, updated some comments, mentioned 4388 in Kconfig]
> Signed-off-by: Sven Peter <sven@svenpeter.dev>
> 
> [...]

Here is the summary with links:
  - Bluetooth: hci_bcm4377: Add BCM4388 support
    https://git.kernel.org/bluetooth/bluetooth-next/c/0b22b7f8aef3

You are awesome, thank you!
diff mbox series

Patch

diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 0b5f218ac505..87484f5de8e3 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -287,12 +287,12 @@  config BT_HCIBCM203X
 
 
 config BT_HCIBCM4377
-	tristate "HCI BCM4377/4378/4387 PCIe driver"
+	tristate "HCI BCM4377/4378/4387/4388 PCIe driver"
 	depends on PCI
 	select FW_LOADER
 	help
-	  Support for Broadcom BCM4377/4378/4387 Bluetooth chipsets attached via
-	  PCIe. These are usually found in Apple machines.
+	  Support for Broadcom BCM4377/4378/4387/4388 Bluetooth chipsets
+	  attached via PCIe. These are usually found in Apple machines.
 
 	  Say Y here to compile support for HCI BCM4377 family devices into the
 	  kernel or say M to compile it as module (hci_bcm4377).
diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c
index e6644cb0163c..77a5454a8721 100644
--- a/drivers/bluetooth/hci_bcm4377.c
+++ b/drivers/bluetooth/hci_bcm4377.c
@@ -1,6 +1,6 @@ 
 // SPDX-License-Identifier: GPL-2.0-only OR MIT
 /*
- * Bluetooth HCI driver for Broadcom 4377/4378/4387 devices attached via PCIe
+ * Bluetooth HCI driver for Broadcom 4377/4378/4387/4388 devices attached via PCIe
  *
  * Copyright (C) The Asahi Linux Contributors
  */
@@ -26,11 +26,13 @@  enum bcm4377_chip {
 	BCM4377 = 0,
 	BCM4378,
 	BCM4387,
+	BCM4388,
 };
 
 #define BCM4377_DEVICE_ID 0x5fa0
 #define BCM4378_DEVICE_ID 0x5f69
 #define BCM4387_DEVICE_ID 0x5f71
+#define BCM4388_DEVICE_ID 0x5f72
 
 #define BCM4377_TIMEOUT msecs_to_jiffies(1000)
 #define BCM4377_BOOT_TIMEOUT msecs_to_jiffies(5000)
@@ -488,6 +490,7 @@  struct bcm4377_data;
  *                     second window in BAR0
  * has_bar0_core2_window2: Set to true if this chip requires the second core's
  *                         second window to be configured
+ * bar2_offset: Offset to the start of the variables in BAR2
  * clear_pciecfg_subsystem_ctrl_bit19: Set to true if bit 19 in the
  *                                     vendor-specific subsystem control
  *                                     register has to be cleared
@@ -511,6 +514,7 @@  struct bcm4377_hw {
 	u32 bar0_window1;
 	u32 bar0_window2;
 	u32 bar0_core2_window2;
+	u32 bar2_offset;
 
 	unsigned long has_bar0_core2_window2 : 1;
 	unsigned long clear_pciecfg_subsystem_ctrl_bit19 : 1;
@@ -836,8 +840,8 @@  static irqreturn_t bcm4377_irq(int irq, void *data)
 	struct bcm4377_data *bcm4377 = data;
 	u32 bootstage, rti_status;
 
-	bootstage = ioread32(bcm4377->bar2 + BCM4377_BAR2_BOOTSTAGE);
-	rti_status = ioread32(bcm4377->bar2 + BCM4377_BAR2_RTI_STATUS);
+	bootstage = ioread32(bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_BOOTSTAGE);
+	rti_status = ioread32(bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_RTI_STATUS);
 
 	if (bootstage != bcm4377->bootstage ||
 	    rti_status != bcm4377->rti_status) {
@@ -1197,6 +1201,14 @@  static int bcm4387_send_calibration(struct bcm4377_data *bcm4377)
 						  bcm4377->taurus_cal_size);
 }
 
+static int bcm4388_send_calibration(struct bcm4377_data *bcm4377)
+{
+	/* BCM4388 always uses beamforming */
+	return __bcm4378_send_calibration(
+		bcm4377, bcm4377->taurus_beamforming_cal_blob,
+		bcm4377->taurus_beamforming_cal_size);
+}
+
 static const struct firmware *bcm4377_request_blob(struct bcm4377_data *bcm4377,
 						   const char *suffix)
 {
@@ -1820,8 +1832,8 @@  static int bcm4377_boot(struct bcm4377_data *bcm4377)
 	int ret = 0;
 	u32 bootstage, rti_status;
 
-	bootstage = ioread32(bcm4377->bar2 + BCM4377_BAR2_BOOTSTAGE);
-	rti_status = ioread32(bcm4377->bar2 + BCM4377_BAR2_RTI_STATUS);
+	bootstage = ioread32(bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_BOOTSTAGE);
+	rti_status = ioread32(bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_RTI_STATUS);
 
 	if (bootstage != 0) {
 		dev_err(&bcm4377->pdev->dev, "bootstage is %d and not 0\n",
@@ -1855,9 +1867,12 @@  static int bcm4377_boot(struct bcm4377_data *bcm4377)
 	iowrite32(BCM4377_DMA_MASK,
 		  bcm4377->bar0 + BCM4377_BAR0_HOST_WINDOW_SIZE);
 
-	iowrite32(lower_32_bits(fw_dma), bcm4377->bar2 + BCM4377_BAR2_FW_LO);
-	iowrite32(upper_32_bits(fw_dma), bcm4377->bar2 + BCM4377_BAR2_FW_HI);
-	iowrite32(fw->size, bcm4377->bar2 + BCM4377_BAR2_FW_SIZE);
+	iowrite32(lower_32_bits(fw_dma),
+		  bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_FW_LO);
+	iowrite32(upper_32_bits(fw_dma),
+		  bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_FW_HI);
+	iowrite32(fw->size,
+		  bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_FW_SIZE);
 	iowrite32(0, bcm4377->bar0 + BCM4377_BAR0_FW_DOORBELL);
 
 	dev_dbg(&bcm4377->pdev->dev, "waiting for firmware to boot\n");
@@ -1914,16 +1929,16 @@  static int bcm4377_setup_rti(struct bcm4377_data *bcm4377)
 	dev_dbg(&bcm4377->pdev->dev, "RTI is in state 1\n");
 
 	/* allow access to the entire IOVA space again */
-	iowrite32(0, bcm4377->bar2 + BCM4377_BAR2_RTI_WINDOW_LO);
-	iowrite32(0, bcm4377->bar2 + BCM4377_BAR2_RTI_WINDOW_HI);
+	iowrite32(0, bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_RTI_WINDOW_LO);
+	iowrite32(0, bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_RTI_WINDOW_HI);
 	iowrite32(BCM4377_DMA_MASK,
-		  bcm4377->bar2 + BCM4377_BAR2_RTI_WINDOW_SIZE);
+		  bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_RTI_WINDOW_SIZE);
 
 	/* setup "Converged IPC" context */
 	iowrite32(lower_32_bits(bcm4377->ctx_dma),
-		  bcm4377->bar2 + BCM4377_BAR2_CONTEXT_ADDR_LO);
+		  bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_CONTEXT_ADDR_LO);
 	iowrite32(upper_32_bits(bcm4377->ctx_dma),
-		  bcm4377->bar2 + BCM4377_BAR2_CONTEXT_ADDR_HI);
+		  bcm4377->bar2 + bcm4377->hw->bar2_offset + BCM4377_BAR2_CONTEXT_ADDR_HI);
 	iowrite32(2, bcm4377->bar0 + BCM4377_BAR0_RTI_CONTROL);
 
 	ret = wait_for_completion_interruptible_timeout(&bcm4377->event,
@@ -2489,6 +2504,21 @@  static const struct bcm4377_hw bcm4377_hw_variants[] = {
 		.send_calibration = bcm4387_send_calibration,
 		.send_ptb = bcm4378_send_ptb,
 	},
+
+	[BCM4388] = {
+		.id = 0x4388,
+		.otp_offset = 0x415c,
+		.bar2_offset = 0x200000,
+		.bar0_window1 = 0x18002000,
+		.bar0_window2 = 0x18109000,
+		.bar0_core2_window2 = 0x18106000,
+		.has_bar0_core2_window2 = true,
+		.broken_mws_transport_config = true,
+		.broken_le_coded = true,
+		.broken_le_ext_adv_report_phy = true,
+		.send_calibration = bcm4388_send_calibration,
+		.send_ptb = bcm4378_send_ptb,
+	},
 };
 
 #define BCM4377_DEVID_ENTRY(id)                                             \
@@ -2502,6 +2532,7 @@  static const struct pci_device_id bcm4377_devid_table[] = {
 	BCM4377_DEVID_ENTRY(4377),
 	BCM4377_DEVID_ENTRY(4378),
 	BCM4377_DEVID_ENTRY(4387),
+	BCM4377_DEVID_ENTRY(4388),
 	{},
 };
 MODULE_DEVICE_TABLE(pci, bcm4377_devid_table);
@@ -2516,7 +2547,7 @@  static struct pci_driver bcm4377_pci_driver = {
 module_pci_driver(bcm4377_pci_driver);
 
 MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>");
-MODULE_DESCRIPTION("Bluetooth support for Broadcom 4377/4378/4387 devices");
+MODULE_DESCRIPTION("Bluetooth support for Broadcom 4377/4378/4387/4388 devices");
 MODULE_LICENSE("Dual MIT/GPL");
 MODULE_FIRMWARE("brcm/brcmbt4377*.bin");
 MODULE_FIRMWARE("brcm/brcmbt4377*.ptb");
@@ -2524,3 +2555,5 @@  MODULE_FIRMWARE("brcm/brcmbt4378*.bin");
 MODULE_FIRMWARE("brcm/brcmbt4378*.ptb");
 MODULE_FIRMWARE("brcm/brcmbt4387*.bin");
 MODULE_FIRMWARE("brcm/brcmbt4387*.ptb");
+MODULE_FIRMWARE("brcm/brcmbt4388*.bin");
+MODULE_FIRMWARE("brcm/brcmbt4388*.ptb");