xref: /openbmc/linux/drivers/bluetooth/hci_bcm4377.c (revision 7e24a55b2122746c2eef192296fc84624354f895)
18a061276SSven Peter // SPDX-License-Identifier: GPL-2.0-only OR MIT
28a061276SSven Peter /*
38a061276SSven Peter  * Bluetooth HCI driver for Broadcom 4377/4378/4387 devices attached via PCIe
48a061276SSven Peter  *
58a061276SSven Peter  * Copyright (C) The Asahi Linux Contributors
68a061276SSven Peter  */
78a061276SSven Peter 
88a061276SSven Peter #include <linux/async.h>
98a061276SSven Peter #include <linux/bitfield.h>
108a061276SSven Peter #include <linux/completion.h>
118a061276SSven Peter #include <linux/dma-mapping.h>
128a061276SSven Peter #include <linux/dmi.h>
138a061276SSven Peter #include <linux/firmware.h>
148a061276SSven Peter #include <linux/module.h>
158a061276SSven Peter #include <linux/msi.h>
168a061276SSven Peter #include <linux/of.h>
178a061276SSven Peter #include <linux/pci.h>
188a061276SSven Peter #include <linux/printk.h>
198a061276SSven Peter 
208a061276SSven Peter #include <asm/unaligned.h>
218a061276SSven Peter 
228a061276SSven Peter #include <net/bluetooth/bluetooth.h>
238a061276SSven Peter #include <net/bluetooth/hci_core.h>
248a061276SSven Peter 
258a061276SSven Peter enum bcm4377_chip {
268a061276SSven Peter 	BCM4377 = 0,
278a061276SSven Peter 	BCM4378,
288a061276SSven Peter 	BCM4387,
298a061276SSven Peter };
308a061276SSven Peter 
318a061276SSven Peter #define BCM4377_DEVICE_ID 0x5fa0
328a061276SSven Peter #define BCM4378_DEVICE_ID 0x5f69
338a061276SSven Peter #define BCM4387_DEVICE_ID 0x5f71
348a061276SSven Peter 
35*424b424fSSven Peter #define BCM4377_TIMEOUT msecs_to_jiffies(1000)
368a061276SSven Peter 
378a061276SSven Peter /*
388a061276SSven Peter  * These devices only support DMA transactions inside a 32bit window
398a061276SSven Peter  * (possibly to avoid 64 bit arithmetic). The window size cannot exceed
408a061276SSven Peter  * 0xffffffff but is always aligned down to the previous 0x200 byte boundary
418a061276SSven Peter  * which effectively limits the window to [start, start+0xfffffe00].
428a061276SSven Peter  * We just limit the DMA window to [0, 0xfffffe00] to make sure we don't
438a061276SSven Peter  * run into this limitation.
448a061276SSven Peter  */
458a061276SSven Peter #define BCM4377_DMA_MASK 0xfffffe00
468a061276SSven Peter 
478a061276SSven Peter #define BCM4377_PCIECFG_BAR0_WINDOW1	   0x80
488a061276SSven Peter #define BCM4377_PCIECFG_BAR0_WINDOW2	   0x70
498a061276SSven Peter #define BCM4377_PCIECFG_BAR0_CORE2_WINDOW1 0x74
508a061276SSven Peter #define BCM4377_PCIECFG_BAR0_CORE2_WINDOW2 0x78
518a061276SSven Peter #define BCM4377_PCIECFG_BAR2_WINDOW	   0x84
528a061276SSven Peter 
538a061276SSven Peter #define BCM4377_PCIECFG_BAR0_CORE2_WINDOW1_DEFAULT 0x18011000
548a061276SSven Peter #define BCM4377_PCIECFG_BAR2_WINDOW_DEFAULT	   0x19000000
558a061276SSven Peter 
568a061276SSven Peter #define BCM4377_PCIECFG_SUBSYSTEM_CTRL 0x88
578a061276SSven Peter 
588a061276SSven Peter #define BCM4377_BAR0_FW_DOORBELL 0x140
598a061276SSven Peter #define BCM4377_BAR0_RTI_CONTROL 0x144
608a061276SSven Peter 
618a061276SSven Peter #define BCM4377_BAR0_SLEEP_CONTROL	      0x150
628a061276SSven Peter #define BCM4377_BAR0_SLEEP_CONTROL_UNQUIESCE  0
638a061276SSven Peter #define BCM4377_BAR0_SLEEP_CONTROL_AWAKE      2
648a061276SSven Peter #define BCM4377_BAR0_SLEEP_CONTROL_QUIESCE    3
658a061276SSven Peter 
668a061276SSven Peter #define BCM4377_BAR0_DOORBELL	    0x174
678a061276SSven Peter #define BCM4377_BAR0_DOORBELL_VALUE GENMASK(31, 16)
688a061276SSven Peter #define BCM4377_BAR0_DOORBELL_IDX   GENMASK(15, 8)
698a061276SSven Peter #define BCM4377_BAR0_DOORBELL_RING  BIT(5)
708a061276SSven Peter 
718a061276SSven Peter #define BCM4377_BAR0_HOST_WINDOW_LO   0x590
728a061276SSven Peter #define BCM4377_BAR0_HOST_WINDOW_HI   0x594
738a061276SSven Peter #define BCM4377_BAR0_HOST_WINDOW_SIZE 0x598
748a061276SSven Peter 
758a061276SSven Peter #define BCM4377_BAR2_BOOTSTAGE 0x200454
768a061276SSven Peter 
778a061276SSven Peter #define BCM4377_BAR2_FW_LO   0x200478
788a061276SSven Peter #define BCM4377_BAR2_FW_HI   0x20047c
798a061276SSven Peter #define BCM4377_BAR2_FW_SIZE 0x200480
808a061276SSven Peter 
818a061276SSven Peter #define BCM4377_BAR2_CONTEXT_ADDR_LO 0x20048c
828a061276SSven Peter #define BCM4377_BAR2_CONTEXT_ADDR_HI 0x200450
838a061276SSven Peter 
848a061276SSven Peter #define BCM4377_BAR2_RTI_STATUS	     0x20045c
858a061276SSven Peter #define BCM4377_BAR2_RTI_WINDOW_LO   0x200494
868a061276SSven Peter #define BCM4377_BAR2_RTI_WINDOW_HI   0x200498
878a061276SSven Peter #define BCM4377_BAR2_RTI_WINDOW_SIZE 0x20049c
888a061276SSven Peter 
898a061276SSven Peter #define BCM4377_OTP_SIZE	  0xe0
908a061276SSven Peter #define BCM4377_OTP_SYS_VENDOR	  0x15
918a061276SSven Peter #define BCM4377_OTP_CIS		  0x80
928a061276SSven Peter #define BCM4377_OTP_VENDOR_HDR	  0x00000008
938a061276SSven Peter #define BCM4377_OTP_MAX_PARAM_LEN 16
948a061276SSven Peter 
958a061276SSven Peter #define BCM4377_N_TRANSFER_RINGS   9
968a061276SSven Peter #define BCM4377_N_COMPLETION_RINGS 6
978a061276SSven Peter 
988a061276SSven Peter #define BCM4377_MAX_RING_SIZE 256
998a061276SSven Peter 
1008a061276SSven Peter #define BCM4377_MSGID_GENERATION GENMASK(15, 8)
1018a061276SSven Peter #define BCM4377_MSGID_ID	 GENMASK(7, 0)
1028a061276SSven Peter 
1038a061276SSven Peter #define BCM4377_RING_N_ENTRIES 128
1048a061276SSven Peter 
1058a061276SSven Peter #define BCM4377_CONTROL_MSG_SIZE		   0x34
1068a061276SSven Peter #define BCM4377_XFER_RING_MAX_INPLACE_PAYLOAD_SIZE (4 * 0xff)
1078a061276SSven Peter 
1088a061276SSven Peter #define MAX_ACL_PAYLOAD_SIZE   (HCI_MAX_FRAME_SIZE + HCI_ACL_HDR_SIZE)
1098a061276SSven Peter #define MAX_SCO_PAYLOAD_SIZE   (HCI_MAX_SCO_SIZE + HCI_SCO_HDR_SIZE)
1108a061276SSven Peter #define MAX_EVENT_PAYLOAD_SIZE (HCI_MAX_EVENT_SIZE + HCI_EVENT_HDR_SIZE)
1118a061276SSven Peter 
1128a061276SSven Peter enum bcm4377_otp_params_type {
1138a061276SSven Peter 	BCM4377_OTP_BOARD_PARAMS,
1148a061276SSven Peter 	BCM4377_OTP_CHIP_PARAMS
1158a061276SSven Peter };
1168a061276SSven Peter 
1178a061276SSven Peter enum bcm4377_transfer_ring_id {
1188a061276SSven Peter 	BCM4377_XFER_RING_CONTROL = 0,
1198a061276SSven Peter 	BCM4377_XFER_RING_HCI_H2D = 1,
1208a061276SSven Peter 	BCM4377_XFER_RING_HCI_D2H = 2,
1218a061276SSven Peter 	BCM4377_XFER_RING_SCO_H2D = 3,
1228a061276SSven Peter 	BCM4377_XFER_RING_SCO_D2H = 4,
1238a061276SSven Peter 	BCM4377_XFER_RING_ACL_H2D = 5,
1248a061276SSven Peter 	BCM4377_XFER_RING_ACL_D2H = 6,
1258a061276SSven Peter };
1268a061276SSven Peter 
1278a061276SSven Peter enum bcm4377_completion_ring_id {
1288a061276SSven Peter 	BCM4377_ACK_RING_CONTROL = 0,
1298a061276SSven Peter 	BCM4377_ACK_RING_HCI_ACL = 1,
1308a061276SSven Peter 	BCM4377_EVENT_RING_HCI_ACL = 2,
1318a061276SSven Peter 	BCM4377_ACK_RING_SCO = 3,
1328a061276SSven Peter 	BCM4377_EVENT_RING_SCO = 4,
1338a061276SSven Peter };
1348a061276SSven Peter 
1358a061276SSven Peter enum bcm4377_doorbell {
1368a061276SSven Peter 	BCM4377_DOORBELL_CONTROL = 0,
1378a061276SSven Peter 	BCM4377_DOORBELL_HCI_H2D = 1,
1388a061276SSven Peter 	BCM4377_DOORBELL_HCI_D2H = 2,
1398a061276SSven Peter 	BCM4377_DOORBELL_ACL_H2D = 3,
1408a061276SSven Peter 	BCM4377_DOORBELL_ACL_D2H = 4,
1418a061276SSven Peter 	BCM4377_DOORBELL_SCO = 6,
1428a061276SSven Peter };
1438a061276SSven Peter 
1448a061276SSven Peter /*
1458a061276SSven Peter  * Transfer ring entry
1468a061276SSven Peter  *
1478a061276SSven Peter  * flags: Flags to indicate if the payload is appended or mapped
1488a061276SSven Peter  * len: Payload length
1498a061276SSven Peter  * payload: Optional payload DMA address
1508a061276SSven Peter  * id: Message id to recognize the answer in the completion ring entry
1518a061276SSven Peter  */
1528a061276SSven Peter struct bcm4377_xfer_ring_entry {
1538a061276SSven Peter #define BCM4377_XFER_RING_FLAG_PAYLOAD_MAPPED	 BIT(0)
1548a061276SSven Peter #define BCM4377_XFER_RING_FLAG_PAYLOAD_IN_FOOTER BIT(1)
1558a061276SSven Peter 	u8 flags;
1568a061276SSven Peter 	__le16 len;
1578a061276SSven Peter 	u8 _unk0;
1588a061276SSven Peter 	__le64 payload;
1598a061276SSven Peter 	__le16 id;
1608a061276SSven Peter 	u8 _unk1[2];
1618a061276SSven Peter } __packed;
1628a061276SSven Peter static_assert(sizeof(struct bcm4377_xfer_ring_entry) == 0x10);
1638a061276SSven Peter 
1648a061276SSven Peter /*
1658a061276SSven Peter  * Completion ring entry
1668a061276SSven Peter  *
1678a061276SSven Peter  * flags: Flags to indicate if the payload is appended or mapped. If the payload
1688a061276SSven Peter  *        is mapped it can be found in the buffer of the corresponding transfer
1698a061276SSven Peter  *        ring message.
1708a061276SSven Peter  * ring_id: Transfer ring ID which required this message
1718a061276SSven Peter  * msg_id: Message ID specified in transfer ring entry
1728a061276SSven Peter  * len: Payload length
1738a061276SSven Peter  */
1748a061276SSven Peter struct bcm4377_completion_ring_entry {
1758a061276SSven Peter 	u8 flags;
1768a061276SSven Peter 	u8 _unk0;
1778a061276SSven Peter 	__le16 ring_id;
1788a061276SSven Peter 	__le16 msg_id;
1798a061276SSven Peter 	__le32 len;
1808a061276SSven Peter 	u8 _unk1[6];
1818a061276SSven Peter } __packed;
1828a061276SSven Peter static_assert(sizeof(struct bcm4377_completion_ring_entry) == 0x10);
1838a061276SSven Peter 
1848a061276SSven Peter enum bcm4377_control_message_type {
1858a061276SSven Peter 	BCM4377_CONTROL_MSG_CREATE_XFER_RING = 1,
1868a061276SSven Peter 	BCM4377_CONTROL_MSG_CREATE_COMPLETION_RING = 2,
1878a061276SSven Peter 	BCM4377_CONTROL_MSG_DESTROY_XFER_RING = 3,
1888a061276SSven Peter 	BCM4377_CONTROL_MSG_DESTROY_COMPLETION_RING = 4,
1898a061276SSven Peter };
1908a061276SSven Peter 
1918a061276SSven Peter /*
1928a061276SSven Peter  * Control message used to create a completion ring
1938a061276SSven Peter  *
1948a061276SSven Peter  * msg_type: Must be BCM4377_CONTROL_MSG_CREATE_COMPLETION_RING
1958a061276SSven Peter  * header_size: Unknown, but probably reserved space in front of the entry
1968a061276SSven Peter  * footer_size: Number of 32 bit words reserved for payloads after the entry
1978a061276SSven Peter  * id/id_again: Completion ring index
1988a061276SSven Peter  * ring_iova: DMA address of the ring buffer
1998a061276SSven Peter  * n_elements: Number of elements inside the ring buffer
2008a061276SSven Peter  * msi: MSI index, doesn't work for all rings though and should be zero
2018a061276SSven Peter  * intmod_delay: Unknown delay
2028a061276SSven Peter  * intmod_bytes: Unknown
2038a061276SSven Peter  */
2048a061276SSven Peter struct bcm4377_create_completion_ring_msg {
2058a061276SSven Peter 	u8 msg_type;
2068a061276SSven Peter 	u8 header_size;
2078a061276SSven Peter 	u8 footer_size;
2088a061276SSven Peter 	u8 _unk0;
2098a061276SSven Peter 	__le16 id;
2108a061276SSven Peter 	__le16 id_again;
2118a061276SSven Peter 	__le64 ring_iova;
2128a061276SSven Peter 	__le16 n_elements;
2138a061276SSven Peter 	__le32 unk;
2148a061276SSven Peter 	u8 _unk1[6];
2158a061276SSven Peter 	__le16 msi;
2168a061276SSven Peter 	__le16 intmod_delay;
2178a061276SSven Peter 	__le32 intmod_bytes;
2188a061276SSven Peter 	__le16 _unk2;
2198a061276SSven Peter 	__le32 _unk3;
2208a061276SSven Peter 	u8 _unk4[10];
2218a061276SSven Peter } __packed;
2228a061276SSven Peter static_assert(sizeof(struct bcm4377_create_completion_ring_msg) ==
2238a061276SSven Peter 	      BCM4377_CONTROL_MSG_SIZE);
2248a061276SSven Peter 
2258a061276SSven Peter /*
2268a061276SSven Peter  * Control ring message used to destroy a completion ring
2278a061276SSven Peter  *
2288a061276SSven Peter  * msg_type: Must be BCM4377_CONTROL_MSG_DESTROY_COMPLETION_RING
2298a061276SSven Peter  * ring_id: Completion ring to be destroyed
2308a061276SSven Peter  */
2318a061276SSven Peter struct bcm4377_destroy_completion_ring_msg {
2328a061276SSven Peter 	u8 msg_type;
2338a061276SSven Peter 	u8 _pad0;
2348a061276SSven Peter 	__le16 ring_id;
2358a061276SSven Peter 	u8 _pad1[48];
2368a061276SSven Peter } __packed;
2378a061276SSven Peter static_assert(sizeof(struct bcm4377_destroy_completion_ring_msg) ==
2388a061276SSven Peter 	      BCM4377_CONTROL_MSG_SIZE);
2398a061276SSven Peter 
2408a061276SSven Peter /*
2418a061276SSven Peter  * Control message used to create a transfer ring
2428a061276SSven Peter  *
2438a061276SSven Peter  * msg_type: Must be BCM4377_CONTROL_MSG_CREATE_XFER_RING
2448a061276SSven Peter  * header_size: Number of 32 bit words reserved for unknown content before the
2458a061276SSven Peter  *              entry
2468a061276SSven Peter  * footer_size: Number of 32 bit words reserved for payloads after the entry
2478a061276SSven Peter  * ring_id/ring_id_again: Transfer ring index
2488a061276SSven Peter  * ring_iova: DMA address of the ring buffer
2498a061276SSven Peter  * n_elements: Number of elements inside the ring buffer
2508a061276SSven Peter  * completion_ring_id: Completion ring index for acknowledgements and events
2518a061276SSven Peter  * doorbell: Doorbell index used to notify device of new entries
2528a061276SSven Peter  * flags: Transfer ring flags
2538a061276SSven Peter  *          - virtual: set if there is no associated shared memory and only the
2548a061276SSven Peter  *                     corresponding completion ring is used
2558a061276SSven Peter  *          - sync: only set for the SCO rings
2568a061276SSven Peter  */
2578a061276SSven Peter struct bcm4377_create_transfer_ring_msg {
2588a061276SSven Peter 	u8 msg_type;
2598a061276SSven Peter 	u8 header_size;
2608a061276SSven Peter 	u8 footer_size;
2618a061276SSven Peter 	u8 _unk0;
2628a061276SSven Peter 	__le16 ring_id;
2638a061276SSven Peter 	__le16 ring_id_again;
2648a061276SSven Peter 	__le64 ring_iova;
2658a061276SSven Peter 	u8 _unk1[8];
2668a061276SSven Peter 	__le16 n_elements;
2678a061276SSven Peter 	__le16 completion_ring_id;
2688a061276SSven Peter 	__le16 doorbell;
2698a061276SSven Peter #define BCM4377_XFER_RING_FLAG_VIRTUAL BIT(7)
2708a061276SSven Peter #define BCM4377_XFER_RING_FLAG_SYNC    BIT(8)
2718a061276SSven Peter 	__le16 flags;
2728a061276SSven Peter 	u8 _unk2[20];
2738a061276SSven Peter } __packed;
2748a061276SSven Peter static_assert(sizeof(struct bcm4377_create_transfer_ring_msg) ==
2758a061276SSven Peter 	      BCM4377_CONTROL_MSG_SIZE);
2768a061276SSven Peter 
2778a061276SSven Peter /*
2788a061276SSven Peter  * Control ring message used to destroy a transfer ring
2798a061276SSven Peter  *
2808a061276SSven Peter  * msg_type: Must be BCM4377_CONTROL_MSG_DESTROY_XFER_RING
2818a061276SSven Peter  * ring_id: Transfer ring to be destroyed
2828a061276SSven Peter  */
2838a061276SSven Peter struct bcm4377_destroy_transfer_ring_msg {
2848a061276SSven Peter 	u8 msg_type;
2858a061276SSven Peter 	u8 _pad0;
2868a061276SSven Peter 	__le16 ring_id;
2878a061276SSven Peter 	u8 _pad1[48];
2888a061276SSven Peter } __packed;
2898a061276SSven Peter static_assert(sizeof(struct bcm4377_destroy_transfer_ring_msg) ==
2908a061276SSven Peter 	      BCM4377_CONTROL_MSG_SIZE);
2918a061276SSven Peter 
2928a061276SSven Peter /*
2938a061276SSven Peter  * "Converged IPC" context struct used to make the device aware of all other
2948a061276SSven Peter  * shared memory structures. A pointer to this structure is configured inside a
2958a061276SSven Peter  * MMIO register.
2968a061276SSven Peter  *
2978a061276SSven Peter  * version: Protocol version, must be 2.
2988a061276SSven Peter  * size: Size of this structure, must be 0x68.
2998a061276SSven Peter  * enabled_caps: Enabled capabilities. Unknown bitfield but should be 2.
3008a061276SSven Peter  * peripheral_info_addr: DMA address for a 0x20 buffer to which the device will
3018a061276SSven Peter  *                       write unknown contents
3028a061276SSven Peter  * {completion,xfer}_ring_{tails,heads}_addr: DMA pointers to ring heads/tails
3038a061276SSven Peter  * n_completion_rings: Number of completion rings, the firmware only works if
3048a061276SSven Peter  *                     this is set to BCM4377_N_COMPLETION_RINGS.
3058a061276SSven Peter  * n_xfer_rings: Number of transfer rings, the firmware only works if
3068a061276SSven Peter  *               this is set to BCM4377_N_TRANSFER_RINGS.
3078a061276SSven Peter  * control_completion_ring_addr: Control completion ring buffer DMA address
3088a061276SSven Peter  * control_xfer_ring_addr: Control transfer ring buffer DMA address
3098a061276SSven Peter  * control_xfer_ring_n_entries: Number of control transfer ring entries
3108a061276SSven Peter  * control_completion_ring_n_entries: Number of control completion ring entries
3118a061276SSven Peter  * control_xfer_ring_doorbell: Control transfer ring doorbell
3128a061276SSven Peter  * control_completion_ring_doorbell: Control completion ring doorbell,
3138a061276SSven Peter  *                                   must be set to 0xffff
3148a061276SSven Peter  * control_xfer_ring_msi: Control completion ring MSI index, must be 0
3158a061276SSven Peter  * control_completion_ring_msi: Control completion ring MSI index, must be 0.
3168a061276SSven Peter  * control_xfer_ring_header_size: Number of 32 bit words reserved in front of
3178a061276SSven Peter  *                                every control transfer ring entry
3188a061276SSven Peter  * control_xfer_ring_footer_size: Number of 32 bit words reserved after every
3198a061276SSven Peter  *                                control transfer ring entry
3208a061276SSven Peter  * control_completion_ring_header_size: Number of 32 bit words reserved in front
3218a061276SSven Peter  *                                      of every control completion ring entry
3228a061276SSven Peter  * control_completion_ring_footer_size: Number of 32 bit words reserved after
3238a061276SSven Peter  *                                      every control completion ring entry
3248a061276SSven Peter  * scratch_pad: Optional scratch pad DMA address
3258a061276SSven Peter  * scratch_pad_size: Scratch pad size
3268a061276SSven Peter  */
3278a061276SSven Peter struct bcm4377_context {
3288a061276SSven Peter 	__le16 version;
3298a061276SSven Peter 	__le16 size;
3308a061276SSven Peter 	__le32 enabled_caps;
3318a061276SSven Peter 
3328a061276SSven Peter 	__le64 peripheral_info_addr;
3338a061276SSven Peter 
3348a061276SSven Peter 	/* ring heads and tails */
3358a061276SSven Peter 	__le64 completion_ring_heads_addr;
3368a061276SSven Peter 	__le64 xfer_ring_tails_addr;
3378a061276SSven Peter 	__le64 completion_ring_tails_addr;
3388a061276SSven Peter 	__le64 xfer_ring_heads_addr;
3398a061276SSven Peter 	__le16 n_completion_rings;
3408a061276SSven Peter 	__le16 n_xfer_rings;
3418a061276SSven Peter 
3428a061276SSven Peter 	/* control ring configuration */
3438a061276SSven Peter 	__le64 control_completion_ring_addr;
3448a061276SSven Peter 	__le64 control_xfer_ring_addr;
3458a061276SSven Peter 	__le16 control_xfer_ring_n_entries;
3468a061276SSven Peter 	__le16 control_completion_ring_n_entries;
3478a061276SSven Peter 	__le16 control_xfer_ring_doorbell;
3488a061276SSven Peter 	__le16 control_completion_ring_doorbell;
3498a061276SSven Peter 	__le16 control_xfer_ring_msi;
3508a061276SSven Peter 	__le16 control_completion_ring_msi;
3518a061276SSven Peter 	u8 control_xfer_ring_header_size;
3528a061276SSven Peter 	u8 control_xfer_ring_footer_size;
3538a061276SSven Peter 	u8 control_completion_ring_header_size;
3548a061276SSven Peter 	u8 control_completion_ring_footer_size;
3558a061276SSven Peter 
3568a061276SSven Peter 	__le16 _unk0;
3578a061276SSven Peter 	__le16 _unk1;
3588a061276SSven Peter 
3598a061276SSven Peter 	__le64 scratch_pad;
3608a061276SSven Peter 	__le32 scratch_pad_size;
3618a061276SSven Peter 
3628a061276SSven Peter 	__le32 _unk3;
3638a061276SSven Peter } __packed;
3648a061276SSven Peter static_assert(sizeof(struct bcm4377_context) == 0x68);
3658a061276SSven Peter 
3668a061276SSven Peter #define BCM4378_CALIBRATION_CHUNK_SIZE 0xe6
3678a061276SSven Peter struct bcm4378_hci_send_calibration_cmd {
3688a061276SSven Peter 	u8 unk;
3698a061276SSven Peter 	__le16 blocks_left;
3708a061276SSven Peter 	u8 data[BCM4378_CALIBRATION_CHUNK_SIZE];
3718a061276SSven Peter } __packed;
3728a061276SSven Peter 
3738a061276SSven Peter #define BCM4378_PTB_CHUNK_SIZE 0xcf
3748a061276SSven Peter struct bcm4378_hci_send_ptb_cmd {
3758a061276SSven Peter 	__le16 blocks_left;
3768a061276SSven Peter 	u8 data[BCM4378_PTB_CHUNK_SIZE];
3778a061276SSven Peter } __packed;
3788a061276SSven Peter 
3798a061276SSven Peter /*
3808a061276SSven Peter  * Shared memory structure used to store the ring head and tail pointers.
3818a061276SSven Peter  */
3828a061276SSven Peter struct bcm4377_ring_state {
3838a061276SSven Peter 	__le16 completion_ring_head[BCM4377_N_COMPLETION_RINGS];
3848a061276SSven Peter 	__le16 completion_ring_tail[BCM4377_N_COMPLETION_RINGS];
3858a061276SSven Peter 	__le16 xfer_ring_head[BCM4377_N_TRANSFER_RINGS];
3868a061276SSven Peter 	__le16 xfer_ring_tail[BCM4377_N_TRANSFER_RINGS];
3878a061276SSven Peter };
3888a061276SSven Peter 
3898a061276SSven Peter /*
3908a061276SSven Peter  * A transfer ring can be used in two configurations:
3918a061276SSven Peter  *  1) Send control or HCI messages to the device which are then acknowledged
3928a061276SSven Peter  *     in the corresponding completion ring
3938a061276SSven Peter  *  2) Receiving HCI frames from the devices. In this case the transfer ring
3948a061276SSven Peter  *     itself contains empty messages that are acknowledged once data is
3958a061276SSven Peter  *     available from the device. If the payloads fit inside the footers
3968a061276SSven Peter  *     of the completion ring the transfer ring can be configured to be
3978a061276SSven Peter  *     virtual such that it has no ring buffer.
3988a061276SSven Peter  *
3998a061276SSven Peter  * ring_id: ring index hardcoded in the firmware
4008a061276SSven Peter  * doorbell: doorbell index to notify device of new entries
4018a061276SSven Peter  * payload_size: optional in-place payload size
4028a061276SSven Peter  * mapped_payload_size: optional out-of-place payload size
4038a061276SSven Peter  * completion_ring: index of corresponding completion ring
4048a061276SSven Peter  * n_entries: number of entries inside this ring
4058a061276SSven Peter  * generation: ring generation; incremented on hci_open to detect stale messages
4068a061276SSven Peter  * sync: set to true for SCO rings
4078a061276SSven Peter  * virtual: set to true if this ring has no entries and is just required to
4088a061276SSven Peter  *          setup a corresponding completion ring for device->host messages
4098a061276SSven Peter  * d2h_buffers_only: set to true if this ring is only used to provide large
4108a061276SSven Peter  *                   buffers used by device->host messages in the completion
4118a061276SSven Peter  *                   ring
4128a061276SSven Peter  * allow_wait: allow to wait for messages to be acknowledged
4138a061276SSven Peter  * enabled: true once the ring has been created and can be used
4148a061276SSven Peter  * ring: ring buffer for entries (struct bcm4377_xfer_ring_entry)
4158a061276SSven Peter  * ring_dma: DMA address for ring entry buffer
4168a061276SSven Peter  * payloads: payload buffer for mapped_payload_size payloads
4178a061276SSven Peter  * payloads_dma:DMA address for payload buffer
4188a061276SSven Peter  * events: pointer to array of completions if waiting is allowed
4198a061276SSven Peter  * msgids: bitmap to keep track of used message ids
4208a061276SSven Peter  * lock: Spinlock to protect access to ring structurs used in the irq handler
4218a061276SSven Peter  */
4228a061276SSven Peter struct bcm4377_transfer_ring {
4238a061276SSven Peter 	enum bcm4377_transfer_ring_id ring_id;
4248a061276SSven Peter 	enum bcm4377_doorbell doorbell;
4258a061276SSven Peter 	size_t payload_size;
4268a061276SSven Peter 	size_t mapped_payload_size;
4278a061276SSven Peter 	u8 completion_ring;
4288a061276SSven Peter 	u16 n_entries;
4298a061276SSven Peter 	u8 generation;
4308a061276SSven Peter 
4318a061276SSven Peter 	bool sync;
4328a061276SSven Peter 	bool virtual;
4338a061276SSven Peter 	bool d2h_buffers_only;
4348a061276SSven Peter 	bool allow_wait;
4358a061276SSven Peter 	bool enabled;
4368a061276SSven Peter 
4378a061276SSven Peter 	void *ring;
4388a061276SSven Peter 	dma_addr_t ring_dma;
4398a061276SSven Peter 
4408a061276SSven Peter 	void *payloads;
4418a061276SSven Peter 	dma_addr_t payloads_dma;
4428a061276SSven Peter 
4438a061276SSven Peter 	struct completion **events;
4448a061276SSven Peter 	DECLARE_BITMAP(msgids, BCM4377_MAX_RING_SIZE);
4458a061276SSven Peter 	spinlock_t lock;
4468a061276SSven Peter };
4478a061276SSven Peter 
4488a061276SSven Peter /*
4498a061276SSven Peter  * A completion ring can be either used to either acknowledge messages sent in
4508a061276SSven Peter  * the corresponding transfer ring or to receive messages associated with the
4518a061276SSven Peter  * transfer ring. When used to receive messages the transfer ring either
4528a061276SSven Peter  * has no ring buffer and is only advanced ("virtual transfer ring") or it
4538a061276SSven Peter  * only contains empty DMA buffers to be used for the payloads.
4548a061276SSven Peter  *
4558a061276SSven Peter  * ring_id: completion ring id, hardcoded in firmware
4568a061276SSven Peter  * payload_size: optional payload size after each entry
4578a061276SSven Peter  * delay: unknown delay
4588a061276SSven Peter  * n_entries: number of entries in this ring
4598a061276SSven Peter  * enabled: true once the ring has been created and can be used
4608a061276SSven Peter  * ring: ring buffer for entries (struct bcm4377_completion_ring_entry)
4618a061276SSven Peter  * ring_dma: DMA address of ring buffer
4628a061276SSven Peter  * transfer_rings: bitmap of corresponding transfer ring ids
4638a061276SSven Peter  */
4648a061276SSven Peter struct bcm4377_completion_ring {
4658a061276SSven Peter 	enum bcm4377_completion_ring_id ring_id;
4668a061276SSven Peter 	u16 payload_size;
4678a061276SSven Peter 	u16 delay;
4688a061276SSven Peter 	u16 n_entries;
4698a061276SSven Peter 	bool enabled;
4708a061276SSven Peter 
4718a061276SSven Peter 	void *ring;
4728a061276SSven Peter 	dma_addr_t ring_dma;
4738a061276SSven Peter 
4748a061276SSven Peter 	unsigned long transfer_rings;
4758a061276SSven Peter };
4768a061276SSven Peter 
4778a061276SSven Peter struct bcm4377_data;
4788a061276SSven Peter 
4798a061276SSven Peter /*
4808a061276SSven Peter  * Chip-specific configuration struct
4818a061276SSven Peter  *
4828a061276SSven Peter  * id: Chip id (e.g. 0x4377 for BCM4377)
4838a061276SSven Peter  * otp_offset: Offset to the start of the OTP inside BAR0
4848a061276SSven Peter  * bar0_window1: Backplane address mapped to the first window in BAR0
4858a061276SSven Peter  * bar0_window2: Backplane address mapped to the second window in BAR0
4868a061276SSven Peter  * bar0_core2_window2: Optional backplane address mapped to the second core's
4878a061276SSven Peter  *                     second window in BAR0
4888a061276SSven Peter  * has_bar0_core2_window2: Set to true if this chip requires the second core's
4898a061276SSven Peter  *                         second window to be configured
4908a061276SSven Peter  * clear_pciecfg_subsystem_ctrl_bit19: Set to true if bit 19 in the
4918a061276SSven Peter  *                                     vendor-specific subsystem control
4928a061276SSven Peter  *                                     register has to be cleared
4938a061276SSven Peter  * disable_aspm: Set to true if ASPM must be disabled due to hardware errata
4948a061276SSven Peter  * broken_ext_scan: Set to true if the chip erroneously claims to support
4958a061276SSven Peter  *                  extended scanning
4968a061276SSven Peter  * broken_mws_transport_config: Set to true if the chip erroneously claims to
4978a061276SSven Peter  *                              support MWS Transport Configuration
4988a061276SSven Peter  * send_calibration: Optional callback to send calibration data
4998a061276SSven Peter  * send_ptb: Callback to send "PTB" regulatory/calibration data
5008a061276SSven Peter  */
5018a061276SSven Peter struct bcm4377_hw {
5028a061276SSven Peter 	unsigned int id;
5038a061276SSven Peter 
5048a061276SSven Peter 	u32 otp_offset;
5058a061276SSven Peter 
5068a061276SSven Peter 	u32 bar0_window1;
5078a061276SSven Peter 	u32 bar0_window2;
5088a061276SSven Peter 	u32 bar0_core2_window2;
5098a061276SSven Peter 
5108a061276SSven Peter 	unsigned long has_bar0_core2_window2 : 1;
5118a061276SSven Peter 	unsigned long clear_pciecfg_subsystem_ctrl_bit19 : 1;
5128a061276SSven Peter 	unsigned long disable_aspm : 1;
5138a061276SSven Peter 	unsigned long broken_ext_scan : 1;
5148a061276SSven Peter 	unsigned long broken_mws_transport_config : 1;
5155c9e997aSJanne Grunau 	unsigned long broken_le_coded : 1;
5168a061276SSven Peter 
5178a061276SSven Peter 	int (*send_calibration)(struct bcm4377_data *bcm4377);
5188a061276SSven Peter 	int (*send_ptb)(struct bcm4377_data *bcm4377,
5198a061276SSven Peter 			const struct firmware *fw);
5208a061276SSven Peter };
5218a061276SSven Peter 
5228a061276SSven Peter static const struct bcm4377_hw bcm4377_hw_variants[];
5238a061276SSven Peter static const struct dmi_system_id bcm4377_dmi_board_table[];
5248a061276SSven Peter 
5258a061276SSven Peter /*
5268a061276SSven Peter  * Private struct associated with each device containing global state
5278a061276SSven Peter  *
5288a061276SSven Peter  * pdev: Pointer to associated struct pci_dev
5298a061276SSven Peter  * hdev: Pointer to associated strucy hci_dev
5308a061276SSven Peter  * bar0: iomem pointing to BAR0
5318a061276SSven Peter  * bar1: iomem pointing to BAR2
5328a061276SSven Peter  * bootstage: Current value of the bootstage
5338a061276SSven Peter  * rti_status: Current "RTI" status value
5348a061276SSven Peter  * hw: Pointer to chip-specific struct bcm4377_hw
5358a061276SSven Peter  * taurus_cal_blob: "Taurus" calibration blob used for some chips
5368a061276SSven Peter  * taurus_cal_size: "Taurus" calibration blob size
5378a061276SSven Peter  * taurus_beamforming_cal_blob: "Taurus" beamforming calibration blob used for
5388a061276SSven Peter  *                              some chips
5398a061276SSven Peter  * taurus_beamforming_cal_size: "Taurus" beamforming calibration blob size
5408a061276SSven Peter  * stepping: Chip stepping read from OTP; used for firmware selection
5418a061276SSven Peter  * vendor: Antenna vendor read from OTP; used for firmware selection
5428a061276SSven Peter  * board_type: Board type from FDT or DMI match; used for firmware selection
5438a061276SSven Peter  * event: Event for changed bootstage or rti_status; used for booting firmware
5448a061276SSven Peter  * ctx: "Converged IPC" context
5458a061276SSven Peter  * ctx_dma: "Converged IPC" context DMA address
5468a061276SSven Peter  * ring_state: Shared memory buffer containing ring head and tail indexes
5478a061276SSven Peter  * ring_state_dma: DMA address for ring_state
5488a061276SSven Peter  * {control,hci_acl,sco}_ack_ring: Completion rings used to acknowledge messages
5498a061276SSven Peter  * {hci_acl,sco}_event_ring: Completion rings used for device->host messages
5508a061276SSven Peter  * control_h2d_ring: Transfer ring used for control messages
5518a061276SSven Peter  * {hci,sco,acl}_h2d_ring: Transfer ring used to transfer HCI frames
5528a061276SSven Peter  * {hci,sco,acl}_d2h_ring: Transfer ring used to receive HCI frames in the
5538a061276SSven Peter  *                         corresponding completion ring
5548a061276SSven Peter  */
5558a061276SSven Peter struct bcm4377_data {
5568a061276SSven Peter 	struct pci_dev *pdev;
5578a061276SSven Peter 	struct hci_dev *hdev;
5588a061276SSven Peter 
5598a061276SSven Peter 	void __iomem *bar0;
5608a061276SSven Peter 	void __iomem *bar2;
5618a061276SSven Peter 
5628a061276SSven Peter 	u32 bootstage;
5638a061276SSven Peter 	u32 rti_status;
5648a061276SSven Peter 
5658a061276SSven Peter 	const struct bcm4377_hw *hw;
5668a061276SSven Peter 
5678a061276SSven Peter 	const void *taurus_cal_blob;
5688a061276SSven Peter 	int taurus_cal_size;
5698a061276SSven Peter 	const void *taurus_beamforming_cal_blob;
5708a061276SSven Peter 	int taurus_beamforming_cal_size;
5718a061276SSven Peter 
5728a061276SSven Peter 	char stepping[BCM4377_OTP_MAX_PARAM_LEN];
5738a061276SSven Peter 	char vendor[BCM4377_OTP_MAX_PARAM_LEN];
5748a061276SSven Peter 	const char *board_type;
5758a061276SSven Peter 
5768a061276SSven Peter 	struct completion event;
5778a061276SSven Peter 
5788a061276SSven Peter 	struct bcm4377_context *ctx;
5798a061276SSven Peter 	dma_addr_t ctx_dma;
5808a061276SSven Peter 
5818a061276SSven Peter 	struct bcm4377_ring_state *ring_state;
5828a061276SSven Peter 	dma_addr_t ring_state_dma;
5838a061276SSven Peter 
5848a061276SSven Peter 	/*
5858a061276SSven Peter 	 * The HCI and ACL rings have to be merged because this structure is
5868a061276SSven Peter 	 * hardcoded in the firmware.
5878a061276SSven Peter 	 */
5888a061276SSven Peter 	struct bcm4377_completion_ring control_ack_ring;
5898a061276SSven Peter 	struct bcm4377_completion_ring hci_acl_ack_ring;
5908a061276SSven Peter 	struct bcm4377_completion_ring hci_acl_event_ring;
5918a061276SSven Peter 	struct bcm4377_completion_ring sco_ack_ring;
5928a061276SSven Peter 	struct bcm4377_completion_ring sco_event_ring;
5938a061276SSven Peter 
5948a061276SSven Peter 	struct bcm4377_transfer_ring control_h2d_ring;
5958a061276SSven Peter 	struct bcm4377_transfer_ring hci_h2d_ring;
5968a061276SSven Peter 	struct bcm4377_transfer_ring hci_d2h_ring;
5978a061276SSven Peter 	struct bcm4377_transfer_ring sco_h2d_ring;
5988a061276SSven Peter 	struct bcm4377_transfer_ring sco_d2h_ring;
5998a061276SSven Peter 	struct bcm4377_transfer_ring acl_h2d_ring;
6008a061276SSven Peter 	struct bcm4377_transfer_ring acl_d2h_ring;
6018a061276SSven Peter };
6028a061276SSven Peter 
bcm4377_ring_doorbell(struct bcm4377_data * bcm4377,u8 doorbell,u16 val)6038a061276SSven Peter static void bcm4377_ring_doorbell(struct bcm4377_data *bcm4377, u8 doorbell,
6048a061276SSven Peter 				  u16 val)
6058a061276SSven Peter {
6068a061276SSven Peter 	u32 db = 0;
6078a061276SSven Peter 
6088a061276SSven Peter 	db |= FIELD_PREP(BCM4377_BAR0_DOORBELL_VALUE, val);
6098a061276SSven Peter 	db |= FIELD_PREP(BCM4377_BAR0_DOORBELL_IDX, doorbell);
6108a061276SSven Peter 	db |= BCM4377_BAR0_DOORBELL_RING;
6118a061276SSven Peter 
6128a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "write %d to doorbell #%d (0x%x)\n", val,
6138a061276SSven Peter 		doorbell, db);
6148a061276SSven Peter 	iowrite32(db, bcm4377->bar0 + BCM4377_BAR0_DOORBELL);
6158a061276SSven Peter }
6168a061276SSven Peter 
bcm4377_extract_msgid(struct bcm4377_data * bcm4377,struct bcm4377_transfer_ring * ring,u16 raw_msgid,u8 * msgid)6178a061276SSven Peter static int bcm4377_extract_msgid(struct bcm4377_data *bcm4377,
6188a061276SSven Peter 				 struct bcm4377_transfer_ring *ring,
6198a061276SSven Peter 				 u16 raw_msgid, u8 *msgid)
6208a061276SSven Peter {
6218a061276SSven Peter 	u8 generation = FIELD_GET(BCM4377_MSGID_GENERATION, raw_msgid);
6228a061276SSven Peter 	*msgid = FIELD_GET(BCM4377_MSGID_ID, raw_msgid);
6238a061276SSven Peter 
6248a061276SSven Peter 	if (generation != ring->generation) {
6258a061276SSven Peter 		dev_warn(
6268a061276SSven Peter 			&bcm4377->pdev->dev,
6278a061276SSven Peter 			"invalid message generation %d should be %d in entry for ring %d\n",
6288a061276SSven Peter 			generation, ring->generation, ring->ring_id);
6298a061276SSven Peter 		return -EINVAL;
6308a061276SSven Peter 	}
6318a061276SSven Peter 
6328a061276SSven Peter 	if (*msgid >= ring->n_entries) {
6338a061276SSven Peter 		dev_warn(&bcm4377->pdev->dev,
6348a061276SSven Peter 			 "invalid message id in entry for ring %d: %d > %d\n",
6358a061276SSven Peter 			 ring->ring_id, *msgid, ring->n_entries);
6368a061276SSven Peter 		return -EINVAL;
6378a061276SSven Peter 	}
6388a061276SSven Peter 
6398a061276SSven Peter 	return 0;
6408a061276SSven Peter }
6418a061276SSven Peter 
bcm4377_handle_event(struct bcm4377_data * bcm4377,struct bcm4377_transfer_ring * ring,u16 raw_msgid,u8 entry_flags,u8 type,void * payload,size_t len)6428a061276SSven Peter static void bcm4377_handle_event(struct bcm4377_data *bcm4377,
6438a061276SSven Peter 				 struct bcm4377_transfer_ring *ring,
6448a061276SSven Peter 				 u16 raw_msgid, u8 entry_flags, u8 type,
6458a061276SSven Peter 				 void *payload, size_t len)
6468a061276SSven Peter {
6478a061276SSven Peter 	struct sk_buff *skb;
6488a061276SSven Peter 	u16 head;
6498a061276SSven Peter 	u8 msgid;
6508a061276SSven Peter 	unsigned long flags;
6518a061276SSven Peter 
6528a061276SSven Peter 	spin_lock_irqsave(&ring->lock, flags);
6538a061276SSven Peter 	if (!ring->enabled) {
6548a061276SSven Peter 		dev_warn(&bcm4377->pdev->dev,
6558a061276SSven Peter 			 "event for disabled transfer ring %d\n",
6568a061276SSven Peter 			 ring->ring_id);
6578a061276SSven Peter 		goto out;
6588a061276SSven Peter 	}
6598a061276SSven Peter 
6608a061276SSven Peter 	if (ring->d2h_buffers_only &&
6618a061276SSven Peter 	    entry_flags & BCM4377_XFER_RING_FLAG_PAYLOAD_MAPPED) {
6628a061276SSven Peter 		if (bcm4377_extract_msgid(bcm4377, ring, raw_msgid, &msgid))
6638a061276SSven Peter 			goto out;
6648a061276SSven Peter 
6658a061276SSven Peter 		if (len > ring->mapped_payload_size) {
6668a061276SSven Peter 			dev_warn(
6678a061276SSven Peter 				&bcm4377->pdev->dev,
6688a061276SSven Peter 				"invalid payload len in event for ring %d: %zu > %zu\n",
6698a061276SSven Peter 				ring->ring_id, len, ring->mapped_payload_size);
6708a061276SSven Peter 			goto out;
6718a061276SSven Peter 		}
6728a061276SSven Peter 
6738a061276SSven Peter 		payload = ring->payloads + msgid * ring->mapped_payload_size;
6748a061276SSven Peter 	}
6758a061276SSven Peter 
6768a061276SSven Peter 	skb = bt_skb_alloc(len, GFP_ATOMIC);
6778a061276SSven Peter 	if (!skb)
6788a061276SSven Peter 		goto out;
6798a061276SSven Peter 
6808a061276SSven Peter 	memcpy(skb_put(skb, len), payload, len);
6818a061276SSven Peter 	hci_skb_pkt_type(skb) = type;
6828a061276SSven Peter 	hci_recv_frame(bcm4377->hdev, skb);
6838a061276SSven Peter 
6848a061276SSven Peter out:
6858a061276SSven Peter 	head = le16_to_cpu(bcm4377->ring_state->xfer_ring_head[ring->ring_id]);
6868a061276SSven Peter 	head = (head + 1) % ring->n_entries;
6878a061276SSven Peter 	bcm4377->ring_state->xfer_ring_head[ring->ring_id] = cpu_to_le16(head);
6888a061276SSven Peter 
6898a061276SSven Peter 	bcm4377_ring_doorbell(bcm4377, ring->doorbell, head);
6908a061276SSven Peter 
6918a061276SSven Peter 	spin_unlock_irqrestore(&ring->lock, flags);
6928a061276SSven Peter }
6938a061276SSven Peter 
bcm4377_handle_ack(struct bcm4377_data * bcm4377,struct bcm4377_transfer_ring * ring,u16 raw_msgid)6948a061276SSven Peter static void bcm4377_handle_ack(struct bcm4377_data *bcm4377,
6958a061276SSven Peter 			       struct bcm4377_transfer_ring *ring,
6968a061276SSven Peter 			       u16 raw_msgid)
6978a061276SSven Peter {
6988a061276SSven Peter 	unsigned long flags;
6998a061276SSven Peter 	u8 msgid;
7008a061276SSven Peter 
7018a061276SSven Peter 	spin_lock_irqsave(&ring->lock, flags);
7028a061276SSven Peter 
7038a061276SSven Peter 	if (bcm4377_extract_msgid(bcm4377, ring, raw_msgid, &msgid))
7048a061276SSven Peter 		goto unlock;
7058a061276SSven Peter 
7068a061276SSven Peter 	if (!test_bit(msgid, ring->msgids)) {
7078a061276SSven Peter 		dev_warn(
7088a061276SSven Peter 			&bcm4377->pdev->dev,
7098a061276SSven Peter 			"invalid message id in ack for ring %d: %d is not used\n",
7108a061276SSven Peter 			ring->ring_id, msgid);
7118a061276SSven Peter 		goto unlock;
7128a061276SSven Peter 	}
7138a061276SSven Peter 
7148a061276SSven Peter 	if (ring->allow_wait && ring->events[msgid]) {
7158a061276SSven Peter 		complete(ring->events[msgid]);
7168a061276SSven Peter 		ring->events[msgid] = NULL;
7178a061276SSven Peter 	}
7188a061276SSven Peter 
719a635d93aSHector Martin 	bitmap_release_region(ring->msgids, msgid, 0);
7208a061276SSven Peter 
7218a061276SSven Peter unlock:
7228a061276SSven Peter 	spin_unlock_irqrestore(&ring->lock, flags);
7238a061276SSven Peter }
7248a061276SSven Peter 
bcm4377_handle_completion(struct bcm4377_data * bcm4377,struct bcm4377_completion_ring * ring,u16 pos)7258a061276SSven Peter static void bcm4377_handle_completion(struct bcm4377_data *bcm4377,
7268a061276SSven Peter 				      struct bcm4377_completion_ring *ring,
7278a061276SSven Peter 				      u16 pos)
7288a061276SSven Peter {
7298a061276SSven Peter 	struct bcm4377_completion_ring_entry *entry;
7308a061276SSven Peter 	u16 msg_id, transfer_ring;
7318a061276SSven Peter 	size_t entry_size, data_len;
7328a061276SSven Peter 	void *data;
7338a061276SSven Peter 
7348a061276SSven Peter 	if (pos >= ring->n_entries) {
7358a061276SSven Peter 		dev_warn(&bcm4377->pdev->dev,
7368a061276SSven Peter 			 "invalid offset %d for completion ring %d\n", pos,
7378a061276SSven Peter 			 ring->ring_id);
7388a061276SSven Peter 		return;
7398a061276SSven Peter 	}
7408a061276SSven Peter 
7418a061276SSven Peter 	entry_size = sizeof(*entry) + ring->payload_size;
7428a061276SSven Peter 	entry = ring->ring + pos * entry_size;
7438a061276SSven Peter 	data = ring->ring + pos * entry_size + sizeof(*entry);
7448a061276SSven Peter 	data_len = le32_to_cpu(entry->len);
7458a061276SSven Peter 	msg_id = le16_to_cpu(entry->msg_id);
7468a061276SSven Peter 	transfer_ring = le16_to_cpu(entry->ring_id);
7478a061276SSven Peter 
7488a061276SSven Peter 	if ((ring->transfer_rings & BIT(transfer_ring)) == 0) {
7498a061276SSven Peter 		dev_warn(
7508a061276SSven Peter 			&bcm4377->pdev->dev,
7518a061276SSven Peter 			"invalid entry at offset %d for transfer ring %d in completion ring %d\n",
7528a061276SSven Peter 			pos, transfer_ring, ring->ring_id);
7538a061276SSven Peter 		return;
7548a061276SSven Peter 	}
7558a061276SSven Peter 
7568a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev,
7578a061276SSven Peter 		"entry in completion ring %d for transfer ring %d with msg_id %d\n",
7588a061276SSven Peter 		ring->ring_id, transfer_ring, msg_id);
7598a061276SSven Peter 
7608a061276SSven Peter 	switch (transfer_ring) {
7618a061276SSven Peter 	case BCM4377_XFER_RING_CONTROL:
7628a061276SSven Peter 		bcm4377_handle_ack(bcm4377, &bcm4377->control_h2d_ring, msg_id);
7638a061276SSven Peter 		break;
7648a061276SSven Peter 	case BCM4377_XFER_RING_HCI_H2D:
7658a061276SSven Peter 		bcm4377_handle_ack(bcm4377, &bcm4377->hci_h2d_ring, msg_id);
7668a061276SSven Peter 		break;
7678a061276SSven Peter 	case BCM4377_XFER_RING_SCO_H2D:
7688a061276SSven Peter 		bcm4377_handle_ack(bcm4377, &bcm4377->sco_h2d_ring, msg_id);
7698a061276SSven Peter 		break;
7708a061276SSven Peter 	case BCM4377_XFER_RING_ACL_H2D:
7718a061276SSven Peter 		bcm4377_handle_ack(bcm4377, &bcm4377->acl_h2d_ring, msg_id);
7728a061276SSven Peter 		break;
7738a061276SSven Peter 
7748a061276SSven Peter 	case BCM4377_XFER_RING_HCI_D2H:
7758a061276SSven Peter 		bcm4377_handle_event(bcm4377, &bcm4377->hci_d2h_ring, msg_id,
7768a061276SSven Peter 				     entry->flags, HCI_EVENT_PKT, data,
7778a061276SSven Peter 				     data_len);
7788a061276SSven Peter 		break;
7798a061276SSven Peter 	case BCM4377_XFER_RING_SCO_D2H:
7808a061276SSven Peter 		bcm4377_handle_event(bcm4377, &bcm4377->sco_d2h_ring, msg_id,
7818a061276SSven Peter 				     entry->flags, HCI_SCODATA_PKT, data,
7828a061276SSven Peter 				     data_len);
7838a061276SSven Peter 		break;
7848a061276SSven Peter 	case BCM4377_XFER_RING_ACL_D2H:
7858a061276SSven Peter 		bcm4377_handle_event(bcm4377, &bcm4377->acl_d2h_ring, msg_id,
7868a061276SSven Peter 				     entry->flags, HCI_ACLDATA_PKT, data,
7878a061276SSven Peter 				     data_len);
7888a061276SSven Peter 		break;
7898a061276SSven Peter 
7908a061276SSven Peter 	default:
7918a061276SSven Peter 		dev_warn(
7928a061276SSven Peter 			&bcm4377->pdev->dev,
7938a061276SSven Peter 			"entry in completion ring %d for unknown transfer ring %d with msg_id %d\n",
7948a061276SSven Peter 			ring->ring_id, transfer_ring, msg_id);
7958a061276SSven Peter 	}
7968a061276SSven Peter }
7978a061276SSven Peter 
bcm4377_poll_completion_ring(struct bcm4377_data * bcm4377,struct bcm4377_completion_ring * ring)7988a061276SSven Peter static void bcm4377_poll_completion_ring(struct bcm4377_data *bcm4377,
7998a061276SSven Peter 					 struct bcm4377_completion_ring *ring)
8008a061276SSven Peter {
8018a061276SSven Peter 	u16 tail;
8028a061276SSven Peter 	__le16 *heads = bcm4377->ring_state->completion_ring_head;
8038a061276SSven Peter 	__le16 *tails = bcm4377->ring_state->completion_ring_tail;
8048a061276SSven Peter 
8058a061276SSven Peter 	if (!ring->enabled)
8068a061276SSven Peter 		return;
8078a061276SSven Peter 
8088a061276SSven Peter 	tail = le16_to_cpu(tails[ring->ring_id]);
8098a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev,
8108a061276SSven Peter 		"completion ring #%d: head: %d, tail: %d\n", ring->ring_id,
8118a061276SSven Peter 		le16_to_cpu(heads[ring->ring_id]), tail);
8128a061276SSven Peter 
8138a061276SSven Peter 	while (tail != le16_to_cpu(READ_ONCE(heads[ring->ring_id]))) {
8148a061276SSven Peter 		/*
8158a061276SSven Peter 		 * ensure the CPU doesn't speculate through the comparison.
8168a061276SSven Peter 		 * otherwise it might already read the (empty) queue entry
8178a061276SSven Peter 		 * before the updated head has been loaded and checked.
8188a061276SSven Peter 		 */
8198a061276SSven Peter 		dma_rmb();
8208a061276SSven Peter 
8218a061276SSven Peter 		bcm4377_handle_completion(bcm4377, ring, tail);
8228a061276SSven Peter 
8238a061276SSven Peter 		tail = (tail + 1) % ring->n_entries;
8248a061276SSven Peter 		tails[ring->ring_id] = cpu_to_le16(tail);
8258a061276SSven Peter 	}
8268a061276SSven Peter }
8278a061276SSven Peter 
bcm4377_irq(int irq,void * data)8288a061276SSven Peter static irqreturn_t bcm4377_irq(int irq, void *data)
8298a061276SSven Peter {
8308a061276SSven Peter 	struct bcm4377_data *bcm4377 = data;
8318a061276SSven Peter 	u32 bootstage, rti_status;
8328a061276SSven Peter 
8338a061276SSven Peter 	bootstage = ioread32(bcm4377->bar2 + BCM4377_BAR2_BOOTSTAGE);
8348a061276SSven Peter 	rti_status = ioread32(bcm4377->bar2 + BCM4377_BAR2_RTI_STATUS);
8358a061276SSven Peter 
8368a061276SSven Peter 	if (bootstage != bcm4377->bootstage ||
8378a061276SSven Peter 	    rti_status != bcm4377->rti_status) {
8388a061276SSven Peter 		dev_dbg(&bcm4377->pdev->dev,
8398a061276SSven Peter 			"bootstage = %d -> %d, rti state = %d -> %d\n",
8408a061276SSven Peter 			bcm4377->bootstage, bootstage, bcm4377->rti_status,
8418a061276SSven Peter 			rti_status);
8428a061276SSven Peter 		complete(&bcm4377->event);
8438a061276SSven Peter 		bcm4377->bootstage = bootstage;
8448a061276SSven Peter 		bcm4377->rti_status = rti_status;
8458a061276SSven Peter 	}
8468a061276SSven Peter 
8478a061276SSven Peter 	if (rti_status > 2)
8488a061276SSven Peter 		dev_err(&bcm4377->pdev->dev, "RTI status is %d\n", rti_status);
8498a061276SSven Peter 
8508a061276SSven Peter 	bcm4377_poll_completion_ring(bcm4377, &bcm4377->control_ack_ring);
8518a061276SSven Peter 	bcm4377_poll_completion_ring(bcm4377, &bcm4377->hci_acl_event_ring);
8528a061276SSven Peter 	bcm4377_poll_completion_ring(bcm4377, &bcm4377->hci_acl_ack_ring);
8538a061276SSven Peter 	bcm4377_poll_completion_ring(bcm4377, &bcm4377->sco_ack_ring);
8548a061276SSven Peter 	bcm4377_poll_completion_ring(bcm4377, &bcm4377->sco_event_ring);
8558a061276SSven Peter 
8568a061276SSven Peter 	return IRQ_HANDLED;
8578a061276SSven Peter }
8588a061276SSven Peter 
bcm4377_enqueue(struct bcm4377_data * bcm4377,struct bcm4377_transfer_ring * ring,void * data,size_t len,bool wait)8598a061276SSven Peter static int bcm4377_enqueue(struct bcm4377_data *bcm4377,
8608a061276SSven Peter 			   struct bcm4377_transfer_ring *ring, void *data,
8618a061276SSven Peter 			   size_t len, bool wait)
8628a061276SSven Peter {
8638a061276SSven Peter 	unsigned long flags;
8648a061276SSven Peter 	struct bcm4377_xfer_ring_entry *entry;
8658a061276SSven Peter 	void *payload;
8668a061276SSven Peter 	size_t offset;
8678a061276SSven Peter 	u16 head, tail, new_head;
8688a061276SSven Peter 	u16 raw_msgid;
8698a061276SSven Peter 	int ret, msgid;
8708a061276SSven Peter 	DECLARE_COMPLETION_ONSTACK(event);
8718a061276SSven Peter 
8728a061276SSven Peter 	if (len > ring->payload_size && len > ring->mapped_payload_size) {
8738a061276SSven Peter 		dev_warn(
8748a061276SSven Peter 			&bcm4377->pdev->dev,
8758a061276SSven Peter 			"payload len %zu is too large for ring %d (max is %zu or %zu)\n",
8768a061276SSven Peter 			len, ring->ring_id, ring->payload_size,
8778a061276SSven Peter 			ring->mapped_payload_size);
8788a061276SSven Peter 		return -EINVAL;
8798a061276SSven Peter 	}
8808a061276SSven Peter 	if (wait && !ring->allow_wait)
8818a061276SSven Peter 		return -EINVAL;
8828a061276SSven Peter 	if (ring->virtual)
8838a061276SSven Peter 		return -EINVAL;
8848a061276SSven Peter 
8858a061276SSven Peter 	spin_lock_irqsave(&ring->lock, flags);
8868a061276SSven Peter 
8878a061276SSven Peter 	head = le16_to_cpu(bcm4377->ring_state->xfer_ring_head[ring->ring_id]);
8888a061276SSven Peter 	tail = le16_to_cpu(bcm4377->ring_state->xfer_ring_tail[ring->ring_id]);
8898a061276SSven Peter 
8908a061276SSven Peter 	new_head = (head + 1) % ring->n_entries;
8918a061276SSven Peter 
8928a061276SSven Peter 	if (new_head == tail) {
8938a061276SSven Peter 		dev_warn(&bcm4377->pdev->dev,
8948a061276SSven Peter 			 "can't send message because ring %d is full\n",
8958a061276SSven Peter 			 ring->ring_id);
8968a061276SSven Peter 		ret = -EINVAL;
8978a061276SSven Peter 		goto out;
8988a061276SSven Peter 	}
8998a061276SSven Peter 
9008a061276SSven Peter 	msgid = bitmap_find_free_region(ring->msgids, ring->n_entries, 0);
9018a061276SSven Peter 	if (msgid < 0) {
9028a061276SSven Peter 		dev_warn(&bcm4377->pdev->dev,
9038a061276SSven Peter 			 "can't find message id for ring %d\n", ring->ring_id);
9048a061276SSven Peter 		ret = -EINVAL;
9058a061276SSven Peter 		goto out;
9068a061276SSven Peter 	}
9078a061276SSven Peter 
9088a061276SSven Peter 	raw_msgid = FIELD_PREP(BCM4377_MSGID_GENERATION, ring->generation);
9098a061276SSven Peter 	raw_msgid |= FIELD_PREP(BCM4377_MSGID_ID, msgid);
9108a061276SSven Peter 
9118a061276SSven Peter 	offset = head * (sizeof(*entry) + ring->payload_size);
9128a061276SSven Peter 	entry = ring->ring + offset;
9138a061276SSven Peter 
9148a061276SSven Peter 	memset(entry, 0, sizeof(*entry));
9158a061276SSven Peter 	entry->id = cpu_to_le16(raw_msgid);
9168a061276SSven Peter 	entry->len = cpu_to_le16(len);
9178a061276SSven Peter 
9188a061276SSven Peter 	if (len <= ring->payload_size) {
9198a061276SSven Peter 		entry->flags = BCM4377_XFER_RING_FLAG_PAYLOAD_IN_FOOTER;
9208a061276SSven Peter 		payload = ring->ring + offset + sizeof(*entry);
9218a061276SSven Peter 	} else {
9228a061276SSven Peter 		entry->flags = BCM4377_XFER_RING_FLAG_PAYLOAD_MAPPED;
9238a061276SSven Peter 		entry->payload = cpu_to_le64(ring->payloads_dma +
9248a061276SSven Peter 					     msgid * ring->mapped_payload_size);
9258a061276SSven Peter 		payload = ring->payloads + msgid * ring->mapped_payload_size;
9268a061276SSven Peter 	}
9278a061276SSven Peter 
9288a061276SSven Peter 	memcpy(payload, data, len);
9298a061276SSven Peter 
9308a061276SSven Peter 	if (wait)
9318a061276SSven Peter 		ring->events[msgid] = &event;
9328a061276SSven Peter 
9338a061276SSven Peter 	/*
9348a061276SSven Peter 	 * The 4377 chips stop responding to any commands as soon as they
9358a061276SSven Peter 	 * have been idle for a while. Poking the sleep control register here
9368a061276SSven Peter 	 * makes them come alive again.
9378a061276SSven Peter 	 */
9388a061276SSven Peter 	iowrite32(BCM4377_BAR0_SLEEP_CONTROL_AWAKE,
9398a061276SSven Peter 		  bcm4377->bar0 + BCM4377_BAR0_SLEEP_CONTROL);
9408a061276SSven Peter 
9418a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev,
9428a061276SSven Peter 		"updating head for transfer queue #%d to %d\n", ring->ring_id,
9438a061276SSven Peter 		new_head);
9448a061276SSven Peter 	bcm4377->ring_state->xfer_ring_head[ring->ring_id] =
9458a061276SSven Peter 		cpu_to_le16(new_head);
9468a061276SSven Peter 
9478a061276SSven Peter 	if (!ring->sync)
9488a061276SSven Peter 		bcm4377_ring_doorbell(bcm4377, ring->doorbell, new_head);
9498a061276SSven Peter 	ret = 0;
9508a061276SSven Peter 
9518a061276SSven Peter out:
9528a061276SSven Peter 	spin_unlock_irqrestore(&ring->lock, flags);
9538a061276SSven Peter 
9548a061276SSven Peter 	if (ret == 0 && wait) {
9558a061276SSven Peter 		ret = wait_for_completion_interruptible_timeout(
9568a061276SSven Peter 			&event, BCM4377_TIMEOUT);
9578a061276SSven Peter 		if (ret == 0)
9588a061276SSven Peter 			ret = -ETIMEDOUT;
9598a061276SSven Peter 		else if (ret > 0)
9608a061276SSven Peter 			ret = 0;
9618a061276SSven Peter 
9628a061276SSven Peter 		spin_lock_irqsave(&ring->lock, flags);
9638a061276SSven Peter 		ring->events[msgid] = NULL;
9648a061276SSven Peter 		spin_unlock_irqrestore(&ring->lock, flags);
9658a061276SSven Peter 	}
9668a061276SSven Peter 
9678a061276SSven Peter 	return ret;
9688a061276SSven Peter }
9698a061276SSven Peter 
bcm4377_create_completion_ring(struct bcm4377_data * bcm4377,struct bcm4377_completion_ring * ring)9708a061276SSven Peter static int bcm4377_create_completion_ring(struct bcm4377_data *bcm4377,
9718a061276SSven Peter 					  struct bcm4377_completion_ring *ring)
9728a061276SSven Peter {
9738a061276SSven Peter 	struct bcm4377_create_completion_ring_msg msg;
9748a061276SSven Peter 	int ret;
9758a061276SSven Peter 
9768a061276SSven Peter 	if (ring->enabled) {
9778a061276SSven Peter 		dev_warn(&bcm4377->pdev->dev,
9788a061276SSven Peter 			 "completion ring %d already enabled\n", ring->ring_id);
9798a061276SSven Peter 		return 0;
9808a061276SSven Peter 	}
9818a061276SSven Peter 
9828a061276SSven Peter 	memset(ring->ring, 0,
9838a061276SSven Peter 	       ring->n_entries * (sizeof(struct bcm4377_completion_ring_entry) +
9848a061276SSven Peter 				  ring->payload_size));
9858a061276SSven Peter 	memset(&msg, 0, sizeof(msg));
9868a061276SSven Peter 	msg.msg_type = BCM4377_CONTROL_MSG_CREATE_COMPLETION_RING;
9878a061276SSven Peter 	msg.id = cpu_to_le16(ring->ring_id);
9888a061276SSven Peter 	msg.id_again = cpu_to_le16(ring->ring_id);
9898a061276SSven Peter 	msg.ring_iova = cpu_to_le64(ring->ring_dma);
9908a061276SSven Peter 	msg.n_elements = cpu_to_le16(ring->n_entries);
9918a061276SSven Peter 	msg.intmod_bytes = cpu_to_le32(0xffffffff);
9928a061276SSven Peter 	msg.unk = cpu_to_le32(0xffffffff);
9938a061276SSven Peter 	msg.intmod_delay = cpu_to_le16(ring->delay);
9948a061276SSven Peter 	msg.footer_size = ring->payload_size / 4;
9958a061276SSven Peter 
9968a061276SSven Peter 	ret = bcm4377_enqueue(bcm4377, &bcm4377->control_h2d_ring, &msg,
9978a061276SSven Peter 			      sizeof(msg), true);
9988a061276SSven Peter 	if (!ret)
9998a061276SSven Peter 		ring->enabled = true;
10008a061276SSven Peter 
10018a061276SSven Peter 	return ret;
10028a061276SSven Peter }
10038a061276SSven Peter 
bcm4377_destroy_completion_ring(struct bcm4377_data * bcm4377,struct bcm4377_completion_ring * ring)10048a061276SSven Peter static int bcm4377_destroy_completion_ring(struct bcm4377_data *bcm4377,
10058a061276SSven Peter 					   struct bcm4377_completion_ring *ring)
10068a061276SSven Peter {
10078a061276SSven Peter 	struct bcm4377_destroy_completion_ring_msg msg;
10088a061276SSven Peter 	int ret;
10098a061276SSven Peter 
10108a061276SSven Peter 	memset(&msg, 0, sizeof(msg));
10118a061276SSven Peter 	msg.msg_type = BCM4377_CONTROL_MSG_DESTROY_COMPLETION_RING;
10128a061276SSven Peter 	msg.ring_id = cpu_to_le16(ring->ring_id);
10138a061276SSven Peter 
10148a061276SSven Peter 	ret = bcm4377_enqueue(bcm4377, &bcm4377->control_h2d_ring, &msg,
10158a061276SSven Peter 			      sizeof(msg), true);
10168a061276SSven Peter 	if (ret)
10178a061276SSven Peter 		dev_warn(&bcm4377->pdev->dev,
10188a061276SSven Peter 			 "failed to destroy completion ring %d\n",
10198a061276SSven Peter 			 ring->ring_id);
10208a061276SSven Peter 
10218a061276SSven Peter 	ring->enabled = false;
10228a061276SSven Peter 	return ret;
10238a061276SSven Peter }
10248a061276SSven Peter 
bcm4377_create_transfer_ring(struct bcm4377_data * bcm4377,struct bcm4377_transfer_ring * ring)10258a061276SSven Peter static int bcm4377_create_transfer_ring(struct bcm4377_data *bcm4377,
10268a061276SSven Peter 					struct bcm4377_transfer_ring *ring)
10278a061276SSven Peter {
10288a061276SSven Peter 	struct bcm4377_create_transfer_ring_msg msg;
10298a061276SSven Peter 	u16 flags = 0;
10308a061276SSven Peter 	int ret, i;
10318a061276SSven Peter 	unsigned long spinlock_flags;
10328a061276SSven Peter 
10338a061276SSven Peter 	if (ring->virtual)
10348a061276SSven Peter 		flags |= BCM4377_XFER_RING_FLAG_VIRTUAL;
10358a061276SSven Peter 	if (ring->sync)
10368a061276SSven Peter 		flags |= BCM4377_XFER_RING_FLAG_SYNC;
10378a061276SSven Peter 
10388a061276SSven Peter 	spin_lock_irqsave(&ring->lock, spinlock_flags);
10398a061276SSven Peter 	memset(&msg, 0, sizeof(msg));
10408a061276SSven Peter 	msg.msg_type = BCM4377_CONTROL_MSG_CREATE_XFER_RING;
10418a061276SSven Peter 	msg.ring_id = cpu_to_le16(ring->ring_id);
10428a061276SSven Peter 	msg.ring_id_again = cpu_to_le16(ring->ring_id);
10438a061276SSven Peter 	msg.ring_iova = cpu_to_le64(ring->ring_dma);
10448a061276SSven Peter 	msg.n_elements = cpu_to_le16(ring->n_entries);
10458a061276SSven Peter 	msg.completion_ring_id = cpu_to_le16(ring->completion_ring);
10468a061276SSven Peter 	msg.doorbell = cpu_to_le16(ring->doorbell);
10478a061276SSven Peter 	msg.flags = cpu_to_le16(flags);
10488a061276SSven Peter 	msg.footer_size = ring->payload_size / 4;
10498a061276SSven Peter 
10508a061276SSven Peter 	bcm4377->ring_state->xfer_ring_head[ring->ring_id] = 0;
10518a061276SSven Peter 	bcm4377->ring_state->xfer_ring_tail[ring->ring_id] = 0;
10528a061276SSven Peter 	ring->generation++;
10538a061276SSven Peter 	spin_unlock_irqrestore(&ring->lock, spinlock_flags);
10548a061276SSven Peter 
10558a061276SSven Peter 	ret = bcm4377_enqueue(bcm4377, &bcm4377->control_h2d_ring, &msg,
10568a061276SSven Peter 			      sizeof(msg), true);
10578a061276SSven Peter 
10588a061276SSven Peter 	spin_lock_irqsave(&ring->lock, spinlock_flags);
10598a061276SSven Peter 
10608a061276SSven Peter 	if (ring->d2h_buffers_only) {
10618a061276SSven Peter 		for (i = 0; i < ring->n_entries; ++i) {
10628a061276SSven Peter 			struct bcm4377_xfer_ring_entry *entry =
10638a061276SSven Peter 				ring->ring + i * sizeof(*entry);
10648a061276SSven Peter 			u16 raw_msgid = FIELD_PREP(BCM4377_MSGID_GENERATION,
10658a061276SSven Peter 						   ring->generation);
10668a061276SSven Peter 			raw_msgid |= FIELD_PREP(BCM4377_MSGID_ID, i);
10678a061276SSven Peter 
10688a061276SSven Peter 			memset(entry, 0, sizeof(*entry));
10698a061276SSven Peter 			entry->id = cpu_to_le16(raw_msgid);
10708a061276SSven Peter 			entry->len = cpu_to_le16(ring->mapped_payload_size);
10718a061276SSven Peter 			entry->flags = BCM4377_XFER_RING_FLAG_PAYLOAD_MAPPED;
10728a061276SSven Peter 			entry->payload =
10738a061276SSven Peter 				cpu_to_le64(ring->payloads_dma +
10748a061276SSven Peter 					    i * ring->mapped_payload_size);
10758a061276SSven Peter 		}
10768a061276SSven Peter 	}
10778a061276SSven Peter 
10788a061276SSven Peter 	/*
10798a061276SSven Peter 	 * send some messages if this is a device->host ring to allow the device
10808a061276SSven Peter 	 * to reply by acknowledging them in the completion ring
10818a061276SSven Peter 	 */
10828a061276SSven Peter 	if (ring->virtual || ring->d2h_buffers_only) {
10838a061276SSven Peter 		bcm4377->ring_state->xfer_ring_head[ring->ring_id] =
10848a061276SSven Peter 			cpu_to_le16(0xf);
10858a061276SSven Peter 		bcm4377_ring_doorbell(bcm4377, ring->doorbell, 0xf);
10868a061276SSven Peter 	}
10878a061276SSven Peter 
10888a061276SSven Peter 	ring->enabled = true;
10898a061276SSven Peter 	spin_unlock_irqrestore(&ring->lock, spinlock_flags);
10908a061276SSven Peter 
10918a061276SSven Peter 	return ret;
10928a061276SSven Peter }
10938a061276SSven Peter 
bcm4377_destroy_transfer_ring(struct bcm4377_data * bcm4377,struct bcm4377_transfer_ring * ring)10948a061276SSven Peter static int bcm4377_destroy_transfer_ring(struct bcm4377_data *bcm4377,
10958a061276SSven Peter 					 struct bcm4377_transfer_ring *ring)
10968a061276SSven Peter {
10978a061276SSven Peter 	struct bcm4377_destroy_transfer_ring_msg msg;
10988a061276SSven Peter 	int ret;
10998a061276SSven Peter 
11008a061276SSven Peter 	memset(&msg, 0, sizeof(msg));
11018a061276SSven Peter 	msg.msg_type = BCM4377_CONTROL_MSG_DESTROY_XFER_RING;
11028a061276SSven Peter 	msg.ring_id = cpu_to_le16(ring->ring_id);
11038a061276SSven Peter 
11048a061276SSven Peter 	ret = bcm4377_enqueue(bcm4377, &bcm4377->control_h2d_ring, &msg,
11058a061276SSven Peter 			      sizeof(msg), true);
11068a061276SSven Peter 	if (ret)
11078a061276SSven Peter 		dev_warn(&bcm4377->pdev->dev,
11088a061276SSven Peter 			 "failed to destroy transfer ring %d\n", ring->ring_id);
11098a061276SSven Peter 
11108a061276SSven Peter 	ring->enabled = false;
11118a061276SSven Peter 	return ret;
11128a061276SSven Peter }
11138a061276SSven Peter 
__bcm4378_send_calibration_chunk(struct bcm4377_data * bcm4377,const void * data,size_t data_len,u16 blocks_left)11148a061276SSven Peter static int __bcm4378_send_calibration_chunk(struct bcm4377_data *bcm4377,
11158a061276SSven Peter 					    const void *data, size_t data_len,
11168a061276SSven Peter 					    u16 blocks_left)
11178a061276SSven Peter {
11188a061276SSven Peter 	struct bcm4378_hci_send_calibration_cmd cmd;
11198a061276SSven Peter 	struct sk_buff *skb;
11208a061276SSven Peter 
11218a061276SSven Peter 	if (data_len > sizeof(cmd.data))
11228a061276SSven Peter 		return -EINVAL;
11238a061276SSven Peter 
11248a061276SSven Peter 	memset(&cmd, 0, sizeof(cmd));
11258a061276SSven Peter 	cmd.unk = 0x03;
11268a061276SSven Peter 	cmd.blocks_left = cpu_to_le16(blocks_left);
11278a061276SSven Peter 	memcpy(cmd.data, data, data_len);
11288a061276SSven Peter 
11298a061276SSven Peter 	skb = __hci_cmd_sync(bcm4377->hdev, 0xfd97, sizeof(cmd), &cmd,
11308a061276SSven Peter 			     HCI_INIT_TIMEOUT);
11318a061276SSven Peter 	if (IS_ERR(skb))
11328a061276SSven Peter 		return PTR_ERR(skb);
11338a061276SSven Peter 
11348a061276SSven Peter 	kfree_skb(skb);
11358a061276SSven Peter 	return 0;
11368a061276SSven Peter }
11378a061276SSven Peter 
__bcm4378_send_calibration(struct bcm4377_data * bcm4377,const void * data,size_t data_size)11388a061276SSven Peter static int __bcm4378_send_calibration(struct bcm4377_data *bcm4377,
11398a061276SSven Peter 				      const void *data, size_t data_size)
11408a061276SSven Peter {
11418a061276SSven Peter 	int ret;
11428a061276SSven Peter 	size_t i, left, transfer_len;
11438a061276SSven Peter 	size_t blocks =
11448a061276SSven Peter 		DIV_ROUND_UP(data_size, (size_t)BCM4378_CALIBRATION_CHUNK_SIZE);
11458a061276SSven Peter 
11468a061276SSven Peter 	if (!data) {
11478a061276SSven Peter 		dev_err(&bcm4377->pdev->dev,
11488a061276SSven Peter 			"no calibration data available.\n");
11498a061276SSven Peter 		return -ENOENT;
11508a061276SSven Peter 	}
11518a061276SSven Peter 
11528a061276SSven Peter 	for (i = 0, left = data_size; i < blocks; ++i, left -= transfer_len) {
11538a061276SSven Peter 		transfer_len =
11548a061276SSven Peter 			min_t(size_t, left, BCM4378_CALIBRATION_CHUNK_SIZE);
11558a061276SSven Peter 
11568a061276SSven Peter 		ret = __bcm4378_send_calibration_chunk(
11578a061276SSven Peter 			bcm4377, data + i * BCM4378_CALIBRATION_CHUNK_SIZE,
11588a061276SSven Peter 			transfer_len, blocks - i - 1);
11598a061276SSven Peter 		if (ret) {
11608a061276SSven Peter 			dev_err(&bcm4377->pdev->dev,
11618a061276SSven Peter 				"send calibration chunk failed with %d\n", ret);
11628a061276SSven Peter 			return ret;
11638a061276SSven Peter 		}
11648a061276SSven Peter 	}
11658a061276SSven Peter 
11668a061276SSven Peter 	return 0;
11678a061276SSven Peter }
11688a061276SSven Peter 
bcm4378_send_calibration(struct bcm4377_data * bcm4377)11698a061276SSven Peter static int bcm4378_send_calibration(struct bcm4377_data *bcm4377)
11708a061276SSven Peter {
11718a061276SSven Peter 	if ((strcmp(bcm4377->stepping, "b1") == 0) ||
11728a061276SSven Peter 	    strcmp(bcm4377->stepping, "b3") == 0)
11738a061276SSven Peter 		return __bcm4378_send_calibration(
11748a061276SSven Peter 			bcm4377, bcm4377->taurus_beamforming_cal_blob,
11758a061276SSven Peter 			bcm4377->taurus_beamforming_cal_size);
11768a061276SSven Peter 	else
11778a061276SSven Peter 		return __bcm4378_send_calibration(bcm4377,
11788a061276SSven Peter 						  bcm4377->taurus_cal_blob,
11798a061276SSven Peter 						  bcm4377->taurus_cal_size);
11808a061276SSven Peter }
11818a061276SSven Peter 
bcm4387_send_calibration(struct bcm4377_data * bcm4377)11828a061276SSven Peter static int bcm4387_send_calibration(struct bcm4377_data *bcm4377)
11838a061276SSven Peter {
11848a061276SSven Peter 	if (strcmp(bcm4377->stepping, "c2") == 0)
11858a061276SSven Peter 		return __bcm4378_send_calibration(
11868a061276SSven Peter 			bcm4377, bcm4377->taurus_beamforming_cal_blob,
11878a061276SSven Peter 			bcm4377->taurus_beamforming_cal_size);
11888a061276SSven Peter 	else
11898a061276SSven Peter 		return __bcm4378_send_calibration(bcm4377,
11908a061276SSven Peter 						  bcm4377->taurus_cal_blob,
11918a061276SSven Peter 						  bcm4377->taurus_cal_size);
11928a061276SSven Peter }
11938a061276SSven Peter 
bcm4377_request_blob(struct bcm4377_data * bcm4377,const char * suffix)11948a061276SSven Peter static const struct firmware *bcm4377_request_blob(struct bcm4377_data *bcm4377,
11958a061276SSven Peter 						   const char *suffix)
11968a061276SSven Peter {
11978a061276SSven Peter 	const struct firmware *fw;
11988a061276SSven Peter 	char name0[64], name1[64];
11998a061276SSven Peter 	int ret;
12008a061276SSven Peter 
12018a061276SSven Peter 	snprintf(name0, sizeof(name0), "brcm/brcmbt%04x%s-%s-%s.%s",
12028a061276SSven Peter 		 bcm4377->hw->id, bcm4377->stepping, bcm4377->board_type,
12038a061276SSven Peter 		 bcm4377->vendor, suffix);
12048a061276SSven Peter 	snprintf(name1, sizeof(name1), "brcm/brcmbt%04x%s-%s.%s",
12058a061276SSven Peter 		 bcm4377->hw->id, bcm4377->stepping, bcm4377->board_type,
12068a061276SSven Peter 		 suffix);
12078a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "Trying to load firmware: '%s' or '%s'\n",
12088a061276SSven Peter 		name0, name1);
12098a061276SSven Peter 
12108a061276SSven Peter 	ret = firmware_request_nowarn(&fw, name0, &bcm4377->pdev->dev);
12118a061276SSven Peter 	if (!ret)
12128a061276SSven Peter 		return fw;
12138a061276SSven Peter 	ret = firmware_request_nowarn(&fw, name1, &bcm4377->pdev->dev);
12148a061276SSven Peter 	if (!ret)
12158a061276SSven Peter 		return fw;
12168a061276SSven Peter 
12178a061276SSven Peter 	dev_err(&bcm4377->pdev->dev,
12188a061276SSven Peter 		"Unable to load firmware; tried '%s' and '%s'\n", name0, name1);
12198a061276SSven Peter 	return NULL;
12208a061276SSven Peter }
12218a061276SSven Peter 
bcm4377_send_ptb(struct bcm4377_data * bcm4377,const struct firmware * fw)12228a061276SSven Peter static int bcm4377_send_ptb(struct bcm4377_data *bcm4377,
12238a061276SSven Peter 			    const struct firmware *fw)
12248a061276SSven Peter {
12258a061276SSven Peter 	struct sk_buff *skb;
12268a061276SSven Peter 
12278a061276SSven Peter 	skb = __hci_cmd_sync(bcm4377->hdev, 0xfd98, fw->size, fw->data,
12288a061276SSven Peter 			     HCI_INIT_TIMEOUT);
12298a061276SSven Peter 	/*
12308a061276SSven Peter 	 * This command seems to always fail on more recent firmware versions
12318a061276SSven Peter 	 * (even in traces taken from the macOS driver). It's unclear why this
12328a061276SSven Peter 	 * happens but because the PTB file contains calibration and/or
12338a061276SSven Peter 	 * regulatory data and may be required on older firmware we still try to
12348a061276SSven Peter 	 * send it here just in case and just ignore if it fails.
12358a061276SSven Peter 	 */
12368a061276SSven Peter 	if (!IS_ERR(skb))
12378a061276SSven Peter 		kfree_skb(skb);
12388a061276SSven Peter 	return 0;
12398a061276SSven Peter }
12408a061276SSven Peter 
bcm4378_send_ptb_chunk(struct bcm4377_data * bcm4377,const void * data,size_t data_len,u16 blocks_left)12418a061276SSven Peter static int bcm4378_send_ptb_chunk(struct bcm4377_data *bcm4377,
12428a061276SSven Peter 				  const void *data, size_t data_len,
12438a061276SSven Peter 				  u16 blocks_left)
12448a061276SSven Peter {
12458a061276SSven Peter 	struct bcm4378_hci_send_ptb_cmd cmd;
12468a061276SSven Peter 	struct sk_buff *skb;
12478a061276SSven Peter 
12488a061276SSven Peter 	if (data_len > BCM4378_PTB_CHUNK_SIZE)
12498a061276SSven Peter 		return -EINVAL;
12508a061276SSven Peter 
12518a061276SSven Peter 	memset(&cmd, 0, sizeof(cmd));
12528a061276SSven Peter 	cmd.blocks_left = cpu_to_le16(blocks_left);
12538a061276SSven Peter 	memcpy(cmd.data, data, data_len);
12548a061276SSven Peter 
12558a061276SSven Peter 	skb = __hci_cmd_sync(bcm4377->hdev, 0xfe0d, sizeof(cmd), &cmd,
12568a061276SSven Peter 			     HCI_INIT_TIMEOUT);
12578a061276SSven Peter 	if (IS_ERR(skb))
12588a061276SSven Peter 		return PTR_ERR(skb);
12598a061276SSven Peter 
12608a061276SSven Peter 	kfree_skb(skb);
12618a061276SSven Peter 	return 0;
12628a061276SSven Peter }
12638a061276SSven Peter 
bcm4378_send_ptb(struct bcm4377_data * bcm4377,const struct firmware * fw)12648a061276SSven Peter static int bcm4378_send_ptb(struct bcm4377_data *bcm4377,
12658a061276SSven Peter 			    const struct firmware *fw)
12668a061276SSven Peter {
12678a061276SSven Peter 	size_t chunks = DIV_ROUND_UP(fw->size, (size_t)BCM4378_PTB_CHUNK_SIZE);
12688a061276SSven Peter 	size_t i, left, transfer_len;
12698a061276SSven Peter 	int ret;
12708a061276SSven Peter 
12718a061276SSven Peter 	for (i = 0, left = fw->size; i < chunks; ++i, left -= transfer_len) {
12728a061276SSven Peter 		transfer_len = min_t(size_t, left, BCM4378_PTB_CHUNK_SIZE);
12738a061276SSven Peter 
12748a061276SSven Peter 		dev_dbg(&bcm4377->pdev->dev, "sending ptb chunk %zu/%zu\n",
12758a061276SSven Peter 			i + 1, chunks);
12768a061276SSven Peter 		ret = bcm4378_send_ptb_chunk(
12778a061276SSven Peter 			bcm4377, fw->data + i * BCM4378_PTB_CHUNK_SIZE,
12788a061276SSven Peter 			transfer_len, chunks - i - 1);
12798a061276SSven Peter 		if (ret) {
12808a061276SSven Peter 			dev_err(&bcm4377->pdev->dev,
12818a061276SSven Peter 				"sending ptb chunk %zu failed (%d)", i, ret);
12828a061276SSven Peter 			return ret;
12838a061276SSven Peter 		}
12848a061276SSven Peter 	}
12858a061276SSven Peter 
12868a061276SSven Peter 	return 0;
12878a061276SSven Peter }
12888a061276SSven Peter 
bcm4377_hci_open(struct hci_dev * hdev)12898a061276SSven Peter static int bcm4377_hci_open(struct hci_dev *hdev)
12908a061276SSven Peter {
12918a061276SSven Peter 	struct bcm4377_data *bcm4377 = hci_get_drvdata(hdev);
12928a061276SSven Peter 	int ret;
12938a061276SSven Peter 
12948a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "creating rings\n");
12958a061276SSven Peter 
12968a061276SSven Peter 	ret = bcm4377_create_completion_ring(bcm4377,
12978a061276SSven Peter 					     &bcm4377->hci_acl_ack_ring);
12988a061276SSven Peter 	if (ret)
12998a061276SSven Peter 		return ret;
13008a061276SSven Peter 	ret = bcm4377_create_completion_ring(bcm4377,
13018a061276SSven Peter 					     &bcm4377->hci_acl_event_ring);
13028a061276SSven Peter 	if (ret)
13038a061276SSven Peter 		goto destroy_hci_acl_ack;
13048a061276SSven Peter 	ret = bcm4377_create_completion_ring(bcm4377, &bcm4377->sco_ack_ring);
13058a061276SSven Peter 	if (ret)
13068a061276SSven Peter 		goto destroy_hci_acl_event;
13078a061276SSven Peter 	ret = bcm4377_create_completion_ring(bcm4377, &bcm4377->sco_event_ring);
13088a061276SSven Peter 	if (ret)
13098a061276SSven Peter 		goto destroy_sco_ack;
13108a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev,
13118a061276SSven Peter 		"all completion rings successfully created!\n");
13128a061276SSven Peter 
13138a061276SSven Peter 	ret = bcm4377_create_transfer_ring(bcm4377, &bcm4377->hci_h2d_ring);
13148a061276SSven Peter 	if (ret)
13158a061276SSven Peter 		goto destroy_sco_event;
13168a061276SSven Peter 	ret = bcm4377_create_transfer_ring(bcm4377, &bcm4377->hci_d2h_ring);
13178a061276SSven Peter 	if (ret)
13188a061276SSven Peter 		goto destroy_hci_h2d;
13198a061276SSven Peter 	ret = bcm4377_create_transfer_ring(bcm4377, &bcm4377->sco_h2d_ring);
13208a061276SSven Peter 	if (ret)
13218a061276SSven Peter 		goto destroy_hci_d2h;
13228a061276SSven Peter 	ret = bcm4377_create_transfer_ring(bcm4377, &bcm4377->sco_d2h_ring);
13238a061276SSven Peter 	if (ret)
13248a061276SSven Peter 		goto destroy_sco_h2d;
13258a061276SSven Peter 	ret = bcm4377_create_transfer_ring(bcm4377, &bcm4377->acl_h2d_ring);
13268a061276SSven Peter 	if (ret)
13278a061276SSven Peter 		goto destroy_sco_d2h;
13288a061276SSven Peter 	ret = bcm4377_create_transfer_ring(bcm4377, &bcm4377->acl_d2h_ring);
13298a061276SSven Peter 	if (ret)
13308a061276SSven Peter 		goto destroy_acl_h2d;
13318a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev,
13328a061276SSven Peter 		"all transfer rings successfully created!\n");
13338a061276SSven Peter 
13348a061276SSven Peter 	return 0;
13358a061276SSven Peter 
13368a061276SSven Peter destroy_acl_h2d:
13378a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->acl_h2d_ring);
13388a061276SSven Peter destroy_sco_d2h:
13398a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->sco_d2h_ring);
13408a061276SSven Peter destroy_sco_h2d:
13418a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->sco_h2d_ring);
13428a061276SSven Peter destroy_hci_d2h:
13438a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->hci_h2d_ring);
13448a061276SSven Peter destroy_hci_h2d:
13458a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->hci_d2h_ring);
13468a061276SSven Peter destroy_sco_event:
13478a061276SSven Peter 	bcm4377_destroy_completion_ring(bcm4377, &bcm4377->sco_event_ring);
13488a061276SSven Peter destroy_sco_ack:
13498a061276SSven Peter 	bcm4377_destroy_completion_ring(bcm4377, &bcm4377->sco_ack_ring);
13508a061276SSven Peter destroy_hci_acl_event:
13518a061276SSven Peter 	bcm4377_destroy_completion_ring(bcm4377, &bcm4377->hci_acl_event_ring);
13528a061276SSven Peter destroy_hci_acl_ack:
13538a061276SSven Peter 	bcm4377_destroy_completion_ring(bcm4377, &bcm4377->hci_acl_ack_ring);
13548a061276SSven Peter 
13558a061276SSven Peter 	dev_err(&bcm4377->pdev->dev, "Creating rings failed with %d\n", ret);
13568a061276SSven Peter 	return ret;
13578a061276SSven Peter }
13588a061276SSven Peter 
bcm4377_hci_close(struct hci_dev * hdev)13598a061276SSven Peter static int bcm4377_hci_close(struct hci_dev *hdev)
13608a061276SSven Peter {
13618a061276SSven Peter 	struct bcm4377_data *bcm4377 = hci_get_drvdata(hdev);
13628a061276SSven Peter 
13638a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "destroying rings in hci_close\n");
13648a061276SSven Peter 
13658a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->acl_d2h_ring);
13668a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->acl_h2d_ring);
13678a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->sco_d2h_ring);
13688a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->sco_h2d_ring);
13698a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->hci_d2h_ring);
13708a061276SSven Peter 	bcm4377_destroy_transfer_ring(bcm4377, &bcm4377->hci_h2d_ring);
13718a061276SSven Peter 
13728a061276SSven Peter 	bcm4377_destroy_completion_ring(bcm4377, &bcm4377->sco_event_ring);
13738a061276SSven Peter 	bcm4377_destroy_completion_ring(bcm4377, &bcm4377->sco_ack_ring);
13748a061276SSven Peter 	bcm4377_destroy_completion_ring(bcm4377, &bcm4377->hci_acl_event_ring);
13758a061276SSven Peter 	bcm4377_destroy_completion_ring(bcm4377, &bcm4377->hci_acl_ack_ring);
13768a061276SSven Peter 
13778a061276SSven Peter 	return 0;
13788a061276SSven Peter }
13798a061276SSven Peter 
bcm4377_is_valid_bdaddr(struct bcm4377_data * bcm4377,bdaddr_t * addr)13808a061276SSven Peter static bool bcm4377_is_valid_bdaddr(struct bcm4377_data *bcm4377,
13818a061276SSven Peter 				    bdaddr_t *addr)
13828a061276SSven Peter {
13838a061276SSven Peter 	if (addr->b[0] != 0x93)
13848a061276SSven Peter 		return true;
13858a061276SSven Peter 	if (addr->b[1] != 0x76)
13868a061276SSven Peter 		return true;
13878a061276SSven Peter 	if (addr->b[2] != 0x00)
13888a061276SSven Peter 		return true;
13898a061276SSven Peter 	if (addr->b[4] != (bcm4377->hw->id & 0xff))
13908a061276SSven Peter 		return true;
13918a061276SSven Peter 	if (addr->b[5] != (bcm4377->hw->id >> 8))
13928a061276SSven Peter 		return true;
13938a061276SSven Peter 	return false;
13948a061276SSven Peter }
13958a061276SSven Peter 
bcm4377_check_bdaddr(struct bcm4377_data * bcm4377)13968a061276SSven Peter static int bcm4377_check_bdaddr(struct bcm4377_data *bcm4377)
13978a061276SSven Peter {
13988a061276SSven Peter 	struct hci_rp_read_bd_addr *bda;
13998a061276SSven Peter 	struct sk_buff *skb;
14008a061276SSven Peter 
14018a061276SSven Peter 	skb = __hci_cmd_sync(bcm4377->hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
14028a061276SSven Peter 			     HCI_INIT_TIMEOUT);
14038a061276SSven Peter 	if (IS_ERR(skb)) {
14048a061276SSven Peter 		int err = PTR_ERR(skb);
14058a061276SSven Peter 
14068a061276SSven Peter 		dev_err(&bcm4377->pdev->dev, "HCI_OP_READ_BD_ADDR failed (%d)",
14078a061276SSven Peter 			err);
14088a061276SSven Peter 		return err;
14098a061276SSven Peter 	}
14108a061276SSven Peter 
14118a061276SSven Peter 	if (skb->len != sizeof(*bda)) {
14128a061276SSven Peter 		dev_err(&bcm4377->pdev->dev,
14138a061276SSven Peter 			"HCI_OP_READ_BD_ADDR reply length invalid");
14148a061276SSven Peter 		kfree_skb(skb);
14158a061276SSven Peter 		return -EIO;
14168a061276SSven Peter 	}
14178a061276SSven Peter 
14188a061276SSven Peter 	bda = (struct hci_rp_read_bd_addr *)skb->data;
14198a061276SSven Peter 	if (!bcm4377_is_valid_bdaddr(bcm4377, &bda->bdaddr))
14200be289baSJohan Hovold 		set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &bcm4377->hdev->quirks);
14218a061276SSven Peter 
14228a061276SSven Peter 	kfree_skb(skb);
14238a061276SSven Peter 	return 0;
14248a061276SSven Peter }
14258a061276SSven Peter 
bcm4377_hci_setup(struct hci_dev * hdev)14268a061276SSven Peter static int bcm4377_hci_setup(struct hci_dev *hdev)
14278a061276SSven Peter {
14288a061276SSven Peter 	struct bcm4377_data *bcm4377 = hci_get_drvdata(hdev);
14298a061276SSven Peter 	const struct firmware *fw;
14308a061276SSven Peter 	int ret;
14318a061276SSven Peter 
14328a061276SSven Peter 	if (bcm4377->hw->send_calibration) {
14338a061276SSven Peter 		ret = bcm4377->hw->send_calibration(bcm4377);
14348a061276SSven Peter 		if (ret)
14358a061276SSven Peter 			return ret;
14368a061276SSven Peter 	}
14378a061276SSven Peter 
14388a061276SSven Peter 	fw = bcm4377_request_blob(bcm4377, "ptb");
14398a061276SSven Peter 	if (!fw) {
14408a061276SSven Peter 		dev_err(&bcm4377->pdev->dev, "failed to load PTB data");
14418a061276SSven Peter 		return -ENOENT;
14428a061276SSven Peter 	}
14438a061276SSven Peter 
14448a061276SSven Peter 	ret = bcm4377->hw->send_ptb(bcm4377, fw);
14458a061276SSven Peter 	release_firmware(fw);
14468a061276SSven Peter 	if (ret)
14478a061276SSven Peter 		return ret;
14488a061276SSven Peter 
14498a061276SSven Peter 	return bcm4377_check_bdaddr(bcm4377);
14508a061276SSven Peter }
14518a061276SSven Peter 
bcm4377_hci_send_frame(struct hci_dev * hdev,struct sk_buff * skb)14528a061276SSven Peter static int bcm4377_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
14538a061276SSven Peter {
14548a061276SSven Peter 	struct bcm4377_data *bcm4377 = hci_get_drvdata(hdev);
14558a061276SSven Peter 	struct bcm4377_transfer_ring *ring;
14568a061276SSven Peter 	int ret;
14578a061276SSven Peter 
14588a061276SSven Peter 	switch (hci_skb_pkt_type(skb)) {
14598a061276SSven Peter 	case HCI_COMMAND_PKT:
14608a061276SSven Peter 		hdev->stat.cmd_tx++;
14618a061276SSven Peter 		ring = &bcm4377->hci_h2d_ring;
14628a061276SSven Peter 		break;
14638a061276SSven Peter 
14648a061276SSven Peter 	case HCI_ACLDATA_PKT:
14658a061276SSven Peter 		hdev->stat.acl_tx++;
14668a061276SSven Peter 		ring = &bcm4377->acl_h2d_ring;
14678a061276SSven Peter 		break;
14688a061276SSven Peter 
14698a061276SSven Peter 	case HCI_SCODATA_PKT:
14708a061276SSven Peter 		hdev->stat.sco_tx++;
14718a061276SSven Peter 		ring = &bcm4377->sco_h2d_ring;
14728a061276SSven Peter 		break;
14738a061276SSven Peter 
14748a061276SSven Peter 	default:
14758a061276SSven Peter 		return -EILSEQ;
14768a061276SSven Peter 	}
14778a061276SSven Peter 
14788a061276SSven Peter 	ret = bcm4377_enqueue(bcm4377, ring, skb->data, skb->len, false);
14798a061276SSven Peter 	if (ret < 0) {
14808a061276SSven Peter 		hdev->stat.err_tx++;
14818a061276SSven Peter 		return ret;
14828a061276SSven Peter 	}
14838a061276SSven Peter 
14848a061276SSven Peter 	hdev->stat.byte_tx += skb->len;
14858a061276SSven Peter 	kfree_skb(skb);
14868a061276SSven Peter 	return ret;
14878a061276SSven Peter }
14888a061276SSven Peter 
bcm4377_hci_set_bdaddr(struct hci_dev * hdev,const bdaddr_t * bdaddr)14898a061276SSven Peter static int bcm4377_hci_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
14908a061276SSven Peter {
14918a061276SSven Peter 	struct bcm4377_data *bcm4377 = hci_get_drvdata(hdev);
14928a061276SSven Peter 	struct sk_buff *skb;
14938a061276SSven Peter 	int err;
14948a061276SSven Peter 
14958a061276SSven Peter 	skb = __hci_cmd_sync(hdev, 0xfc01, 6, bdaddr, HCI_INIT_TIMEOUT);
14968a061276SSven Peter 	if (IS_ERR(skb)) {
14978a061276SSven Peter 		err = PTR_ERR(skb);
14988a061276SSven Peter 		dev_err(&bcm4377->pdev->dev,
14998a061276SSven Peter 			"Change address command failed (%d)", err);
15008a061276SSven Peter 		return err;
15018a061276SSven Peter 	}
15028a061276SSven Peter 	kfree_skb(skb);
15038a061276SSven Peter 
15048a061276SSven Peter 	return 0;
15058a061276SSven Peter }
15068a061276SSven Peter 
bcm4377_alloc_transfer_ring(struct bcm4377_data * bcm4377,struct bcm4377_transfer_ring * ring)15078a061276SSven Peter static int bcm4377_alloc_transfer_ring(struct bcm4377_data *bcm4377,
15088a061276SSven Peter 				       struct bcm4377_transfer_ring *ring)
15098a061276SSven Peter {
15108a061276SSven Peter 	size_t entry_size;
15118a061276SSven Peter 
15128a061276SSven Peter 	spin_lock_init(&ring->lock);
15138a061276SSven Peter 	ring->payload_size = ALIGN(ring->payload_size, 4);
15148a061276SSven Peter 	ring->mapped_payload_size = ALIGN(ring->mapped_payload_size, 4);
15158a061276SSven Peter 
15168a061276SSven Peter 	if (ring->payload_size > BCM4377_XFER_RING_MAX_INPLACE_PAYLOAD_SIZE)
15178a061276SSven Peter 		return -EINVAL;
15188a061276SSven Peter 	if (ring->n_entries > BCM4377_MAX_RING_SIZE)
15198a061276SSven Peter 		return -EINVAL;
15208a061276SSven Peter 	if (ring->virtual && ring->allow_wait)
15218a061276SSven Peter 		return -EINVAL;
15228a061276SSven Peter 
15238a061276SSven Peter 	if (ring->d2h_buffers_only) {
15248a061276SSven Peter 		if (ring->virtual)
15258a061276SSven Peter 			return -EINVAL;
15268a061276SSven Peter 		if (ring->payload_size)
15278a061276SSven Peter 			return -EINVAL;
15288a061276SSven Peter 		if (!ring->mapped_payload_size)
15298a061276SSven Peter 			return -EINVAL;
15308a061276SSven Peter 	}
15318a061276SSven Peter 	if (ring->virtual)
15328a061276SSven Peter 		return 0;
15338a061276SSven Peter 
15348a061276SSven Peter 	entry_size =
15358a061276SSven Peter 		ring->payload_size + sizeof(struct bcm4377_xfer_ring_entry);
15368a061276SSven Peter 	ring->ring = dmam_alloc_coherent(&bcm4377->pdev->dev,
15378a061276SSven Peter 					 ring->n_entries * entry_size,
15388a061276SSven Peter 					 &ring->ring_dma, GFP_KERNEL);
15398a061276SSven Peter 	if (!ring->ring)
15408a061276SSven Peter 		return -ENOMEM;
15418a061276SSven Peter 
15428a061276SSven Peter 	if (ring->allow_wait) {
15438a061276SSven Peter 		ring->events = devm_kcalloc(&bcm4377->pdev->dev,
15448a061276SSven Peter 					    ring->n_entries,
15458a061276SSven Peter 					    sizeof(*ring->events), GFP_KERNEL);
15468a061276SSven Peter 		if (!ring->events)
15478a061276SSven Peter 			return -ENOMEM;
15488a061276SSven Peter 	}
15498a061276SSven Peter 
15508a061276SSven Peter 	if (ring->mapped_payload_size) {
15518a061276SSven Peter 		ring->payloads = dmam_alloc_coherent(
15528a061276SSven Peter 			&bcm4377->pdev->dev,
15538a061276SSven Peter 			ring->n_entries * ring->mapped_payload_size,
15548a061276SSven Peter 			&ring->payloads_dma, GFP_KERNEL);
15558a061276SSven Peter 		if (!ring->payloads)
15568a061276SSven Peter 			return -ENOMEM;
15578a061276SSven Peter 	}
15588a061276SSven Peter 
15598a061276SSven Peter 	return 0;
15608a061276SSven Peter }
15618a061276SSven Peter 
bcm4377_alloc_completion_ring(struct bcm4377_data * bcm4377,struct bcm4377_completion_ring * ring)15628a061276SSven Peter static int bcm4377_alloc_completion_ring(struct bcm4377_data *bcm4377,
15638a061276SSven Peter 					 struct bcm4377_completion_ring *ring)
15648a061276SSven Peter {
15658a061276SSven Peter 	size_t entry_size;
15668a061276SSven Peter 
15678a061276SSven Peter 	ring->payload_size = ALIGN(ring->payload_size, 4);
15688a061276SSven Peter 	if (ring->payload_size > BCM4377_XFER_RING_MAX_INPLACE_PAYLOAD_SIZE)
15698a061276SSven Peter 		return -EINVAL;
15708a061276SSven Peter 	if (ring->n_entries > BCM4377_MAX_RING_SIZE)
15718a061276SSven Peter 		return -EINVAL;
15728a061276SSven Peter 
15738a061276SSven Peter 	entry_size = ring->payload_size +
15748a061276SSven Peter 		     sizeof(struct bcm4377_completion_ring_entry);
15758a061276SSven Peter 
15768a061276SSven Peter 	ring->ring = dmam_alloc_coherent(&bcm4377->pdev->dev,
15778a061276SSven Peter 					 ring->n_entries * entry_size,
15788a061276SSven Peter 					 &ring->ring_dma, GFP_KERNEL);
15798a061276SSven Peter 	if (!ring->ring)
15808a061276SSven Peter 		return -ENOMEM;
15818a061276SSven Peter 	return 0;
15828a061276SSven Peter }
15838a061276SSven Peter 
bcm4377_init_context(struct bcm4377_data * bcm4377)15848a061276SSven Peter static int bcm4377_init_context(struct bcm4377_data *bcm4377)
15858a061276SSven Peter {
15868a061276SSven Peter 	struct device *dev = &bcm4377->pdev->dev;
15878a061276SSven Peter 	dma_addr_t peripheral_info_dma;
15888a061276SSven Peter 
15898a061276SSven Peter 	bcm4377->ctx = dmam_alloc_coherent(dev, sizeof(*bcm4377->ctx),
15908a061276SSven Peter 					   &bcm4377->ctx_dma, GFP_KERNEL);
15918a061276SSven Peter 	if (!bcm4377->ctx)
15928a061276SSven Peter 		return -ENOMEM;
15938a061276SSven Peter 	memset(bcm4377->ctx, 0, sizeof(*bcm4377->ctx));
15948a061276SSven Peter 
15958a061276SSven Peter 	bcm4377->ring_state =
15968a061276SSven Peter 		dmam_alloc_coherent(dev, sizeof(*bcm4377->ring_state),
15978a061276SSven Peter 				    &bcm4377->ring_state_dma, GFP_KERNEL);
15988a061276SSven Peter 	if (!bcm4377->ring_state)
15998a061276SSven Peter 		return -ENOMEM;
16008a061276SSven Peter 	memset(bcm4377->ring_state, 0, sizeof(*bcm4377->ring_state));
16018a061276SSven Peter 
16028a061276SSven Peter 	bcm4377->ctx->version = cpu_to_le16(1);
16038a061276SSven Peter 	bcm4377->ctx->size = cpu_to_le16(sizeof(*bcm4377->ctx));
16048a061276SSven Peter 	bcm4377->ctx->enabled_caps = cpu_to_le32(2);
16058a061276SSven Peter 
16068a061276SSven Peter 	/*
16078a061276SSven Peter 	 * The BT device will write 0x20 bytes of data to this buffer but
16088a061276SSven Peter 	 * the exact contents are unknown. It only needs to exist for BT
16098a061276SSven Peter 	 * to work such that we can just allocate and then ignore it.
16108a061276SSven Peter 	 */
16118a061276SSven Peter 	if (!dmam_alloc_coherent(&bcm4377->pdev->dev, 0x20,
16128a061276SSven Peter 				 &peripheral_info_dma, GFP_KERNEL))
16138a061276SSven Peter 		return -ENOMEM;
16148a061276SSven Peter 	bcm4377->ctx->peripheral_info_addr = cpu_to_le64(peripheral_info_dma);
16158a061276SSven Peter 
16168a061276SSven Peter 	bcm4377->ctx->xfer_ring_heads_addr = cpu_to_le64(
16178a061276SSven Peter 		bcm4377->ring_state_dma +
16188a061276SSven Peter 		offsetof(struct bcm4377_ring_state, xfer_ring_head));
16198a061276SSven Peter 	bcm4377->ctx->xfer_ring_tails_addr = cpu_to_le64(
16208a061276SSven Peter 		bcm4377->ring_state_dma +
16218a061276SSven Peter 		offsetof(struct bcm4377_ring_state, xfer_ring_tail));
16228a061276SSven Peter 	bcm4377->ctx->completion_ring_heads_addr = cpu_to_le64(
16238a061276SSven Peter 		bcm4377->ring_state_dma +
16248a061276SSven Peter 		offsetof(struct bcm4377_ring_state, completion_ring_head));
16258a061276SSven Peter 	bcm4377->ctx->completion_ring_tails_addr = cpu_to_le64(
16268a061276SSven Peter 		bcm4377->ring_state_dma +
16278a061276SSven Peter 		offsetof(struct bcm4377_ring_state, completion_ring_tail));
16288a061276SSven Peter 
16298a061276SSven Peter 	bcm4377->ctx->n_completion_rings =
16308a061276SSven Peter 		cpu_to_le16(BCM4377_N_COMPLETION_RINGS);
16318a061276SSven Peter 	bcm4377->ctx->n_xfer_rings = cpu_to_le16(BCM4377_N_TRANSFER_RINGS);
16328a061276SSven Peter 
16338a061276SSven Peter 	bcm4377->ctx->control_completion_ring_addr =
16348a061276SSven Peter 		cpu_to_le64(bcm4377->control_ack_ring.ring_dma);
16358a061276SSven Peter 	bcm4377->ctx->control_completion_ring_n_entries =
16368a061276SSven Peter 		cpu_to_le16(bcm4377->control_ack_ring.n_entries);
16378a061276SSven Peter 	bcm4377->ctx->control_completion_ring_doorbell = cpu_to_le16(0xffff);
16388a061276SSven Peter 	bcm4377->ctx->control_completion_ring_msi = 0;
16398a061276SSven Peter 	bcm4377->ctx->control_completion_ring_header_size = 0;
16408a061276SSven Peter 	bcm4377->ctx->control_completion_ring_footer_size = 0;
16418a061276SSven Peter 
16428a061276SSven Peter 	bcm4377->ctx->control_xfer_ring_addr =
16438a061276SSven Peter 		cpu_to_le64(bcm4377->control_h2d_ring.ring_dma);
16448a061276SSven Peter 	bcm4377->ctx->control_xfer_ring_n_entries =
16458a061276SSven Peter 		cpu_to_le16(bcm4377->control_h2d_ring.n_entries);
16468a061276SSven Peter 	bcm4377->ctx->control_xfer_ring_doorbell =
16478a061276SSven Peter 		cpu_to_le16(bcm4377->control_h2d_ring.doorbell);
16488a061276SSven Peter 	bcm4377->ctx->control_xfer_ring_msi = 0;
16498a061276SSven Peter 	bcm4377->ctx->control_xfer_ring_header_size = 0;
16508a061276SSven Peter 	bcm4377->ctx->control_xfer_ring_footer_size =
16518a061276SSven Peter 		bcm4377->control_h2d_ring.payload_size / 4;
16528a061276SSven Peter 
16538a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "context initialized at IOVA %pad",
16548a061276SSven Peter 		&bcm4377->ctx_dma);
16558a061276SSven Peter 
16568a061276SSven Peter 	return 0;
16578a061276SSven Peter }
16588a061276SSven Peter 
bcm4377_prepare_rings(struct bcm4377_data * bcm4377)16598a061276SSven Peter static int bcm4377_prepare_rings(struct bcm4377_data *bcm4377)
16608a061276SSven Peter {
16618a061276SSven Peter 	int ret;
16628a061276SSven Peter 
16638a061276SSven Peter 	/*
16648a061276SSven Peter 	 * Even though many of these settings appear to be configurable
16658a061276SSven Peter 	 * when sending the "create ring" messages most of these are
16668a061276SSven Peter 	 * actually hardcoded in some (and quite possibly all) firmware versions
16678a061276SSven Peter 	 * and changing them on the host has no effect.
16688a061276SSven Peter 	 * Specifically, this applies to at least the doorbells, the transfer
16698a061276SSven Peter 	 * and completion ring ids and their mapping (e.g. both HCI and ACL
16708a061276SSven Peter 	 * entries will always be queued in completion rings 1 and 2 no matter
16718a061276SSven Peter 	 * what we configure here).
16728a061276SSven Peter 	 */
16738a061276SSven Peter 	bcm4377->control_ack_ring.ring_id = BCM4377_ACK_RING_CONTROL;
16748a061276SSven Peter 	bcm4377->control_ack_ring.n_entries = 32;
16758a061276SSven Peter 	bcm4377->control_ack_ring.transfer_rings =
16768a061276SSven Peter 		BIT(BCM4377_XFER_RING_CONTROL);
16778a061276SSven Peter 
16788a061276SSven Peter 	bcm4377->hci_acl_ack_ring.ring_id = BCM4377_ACK_RING_HCI_ACL;
16798a061276SSven Peter 	bcm4377->hci_acl_ack_ring.n_entries = 2 * BCM4377_RING_N_ENTRIES;
16808a061276SSven Peter 	bcm4377->hci_acl_ack_ring.transfer_rings =
16818a061276SSven Peter 		BIT(BCM4377_XFER_RING_HCI_H2D) | BIT(BCM4377_XFER_RING_ACL_H2D);
16828a061276SSven Peter 	bcm4377->hci_acl_ack_ring.delay = 1000;
16838a061276SSven Peter 
16848a061276SSven Peter 	/*
16858a061276SSven Peter 	 * A payload size of MAX_EVENT_PAYLOAD_SIZE is enough here since large
16868a061276SSven Peter 	 * ACL packets will be transmitted inside buffers mapped via
16878a061276SSven Peter 	 * acl_d2h_ring anyway.
16888a061276SSven Peter 	 */
16898a061276SSven Peter 	bcm4377->hci_acl_event_ring.ring_id = BCM4377_EVENT_RING_HCI_ACL;
16908a061276SSven Peter 	bcm4377->hci_acl_event_ring.payload_size = MAX_EVENT_PAYLOAD_SIZE;
16918a061276SSven Peter 	bcm4377->hci_acl_event_ring.n_entries = 2 * BCM4377_RING_N_ENTRIES;
16928a061276SSven Peter 	bcm4377->hci_acl_event_ring.transfer_rings =
16938a061276SSven Peter 		BIT(BCM4377_XFER_RING_HCI_D2H) | BIT(BCM4377_XFER_RING_ACL_D2H);
16948a061276SSven Peter 	bcm4377->hci_acl_event_ring.delay = 1000;
16958a061276SSven Peter 
16968a061276SSven Peter 	bcm4377->sco_ack_ring.ring_id = BCM4377_ACK_RING_SCO;
16978a061276SSven Peter 	bcm4377->sco_ack_ring.n_entries = BCM4377_RING_N_ENTRIES;
16988a061276SSven Peter 	bcm4377->sco_ack_ring.transfer_rings = BIT(BCM4377_XFER_RING_SCO_H2D);
16998a061276SSven Peter 
17008a061276SSven Peter 	bcm4377->sco_event_ring.ring_id = BCM4377_EVENT_RING_SCO;
17018a061276SSven Peter 	bcm4377->sco_event_ring.payload_size = MAX_SCO_PAYLOAD_SIZE;
17028a061276SSven Peter 	bcm4377->sco_event_ring.n_entries = BCM4377_RING_N_ENTRIES;
17038a061276SSven Peter 	bcm4377->sco_event_ring.transfer_rings = BIT(BCM4377_XFER_RING_SCO_D2H);
17048a061276SSven Peter 
17058a061276SSven Peter 	bcm4377->control_h2d_ring.ring_id = BCM4377_XFER_RING_CONTROL;
17068a061276SSven Peter 	bcm4377->control_h2d_ring.doorbell = BCM4377_DOORBELL_CONTROL;
17078a061276SSven Peter 	bcm4377->control_h2d_ring.payload_size = BCM4377_CONTROL_MSG_SIZE;
17088a061276SSven Peter 	bcm4377->control_h2d_ring.completion_ring = BCM4377_ACK_RING_CONTROL;
17098a061276SSven Peter 	bcm4377->control_h2d_ring.allow_wait = true;
17108a061276SSven Peter 	bcm4377->control_h2d_ring.n_entries = BCM4377_RING_N_ENTRIES;
17118a061276SSven Peter 
17128a061276SSven Peter 	bcm4377->hci_h2d_ring.ring_id = BCM4377_XFER_RING_HCI_H2D;
17138a061276SSven Peter 	bcm4377->hci_h2d_ring.doorbell = BCM4377_DOORBELL_HCI_H2D;
17148a061276SSven Peter 	bcm4377->hci_h2d_ring.payload_size = MAX_EVENT_PAYLOAD_SIZE;
17158a061276SSven Peter 	bcm4377->hci_h2d_ring.completion_ring = BCM4377_ACK_RING_HCI_ACL;
17168a061276SSven Peter 	bcm4377->hci_h2d_ring.n_entries = BCM4377_RING_N_ENTRIES;
17178a061276SSven Peter 
17188a061276SSven Peter 	bcm4377->hci_d2h_ring.ring_id = BCM4377_XFER_RING_HCI_D2H;
17198a061276SSven Peter 	bcm4377->hci_d2h_ring.doorbell = BCM4377_DOORBELL_HCI_D2H;
17208a061276SSven Peter 	bcm4377->hci_d2h_ring.completion_ring = BCM4377_EVENT_RING_HCI_ACL;
17218a061276SSven Peter 	bcm4377->hci_d2h_ring.virtual = true;
17228a061276SSven Peter 	bcm4377->hci_d2h_ring.n_entries = BCM4377_RING_N_ENTRIES;
17238a061276SSven Peter 
17248a061276SSven Peter 	bcm4377->sco_h2d_ring.ring_id = BCM4377_XFER_RING_SCO_H2D;
17258a061276SSven Peter 	bcm4377->sco_h2d_ring.doorbell = BCM4377_DOORBELL_SCO;
17268a061276SSven Peter 	bcm4377->sco_h2d_ring.payload_size = MAX_SCO_PAYLOAD_SIZE;
17278a061276SSven Peter 	bcm4377->sco_h2d_ring.completion_ring = BCM4377_ACK_RING_SCO;
17288a061276SSven Peter 	bcm4377->sco_h2d_ring.sync = true;
17298a061276SSven Peter 	bcm4377->sco_h2d_ring.n_entries = BCM4377_RING_N_ENTRIES;
17308a061276SSven Peter 
17318a061276SSven Peter 	bcm4377->sco_d2h_ring.ring_id = BCM4377_XFER_RING_SCO_D2H;
17328a061276SSven Peter 	bcm4377->sco_d2h_ring.doorbell = BCM4377_DOORBELL_SCO;
17338a061276SSven Peter 	bcm4377->sco_d2h_ring.completion_ring = BCM4377_EVENT_RING_SCO;
17348a061276SSven Peter 	bcm4377->sco_d2h_ring.virtual = true;
17358a061276SSven Peter 	bcm4377->sco_d2h_ring.sync = true;
17368a061276SSven Peter 	bcm4377->sco_d2h_ring.n_entries = BCM4377_RING_N_ENTRIES;
17378a061276SSven Peter 
17388a061276SSven Peter 	/*
17398a061276SSven Peter 	 * This ring has to use mapped_payload_size because the largest ACL
17408a061276SSven Peter 	 * packet doesn't fit inside the largest possible footer
17418a061276SSven Peter 	 */
17428a061276SSven Peter 	bcm4377->acl_h2d_ring.ring_id = BCM4377_XFER_RING_ACL_H2D;
17438a061276SSven Peter 	bcm4377->acl_h2d_ring.doorbell = BCM4377_DOORBELL_ACL_H2D;
17448a061276SSven Peter 	bcm4377->acl_h2d_ring.mapped_payload_size = MAX_ACL_PAYLOAD_SIZE;
17458a061276SSven Peter 	bcm4377->acl_h2d_ring.completion_ring = BCM4377_ACK_RING_HCI_ACL;
17468a061276SSven Peter 	bcm4377->acl_h2d_ring.n_entries = BCM4377_RING_N_ENTRIES;
17478a061276SSven Peter 
17488a061276SSven Peter 	/*
17498a061276SSven Peter 	 * This ring only contains empty buffers to be used by incoming
17508a061276SSven Peter 	 * ACL packets that do not fit inside the footer of hci_acl_event_ring
17518a061276SSven Peter 	 */
17528a061276SSven Peter 	bcm4377->acl_d2h_ring.ring_id = BCM4377_XFER_RING_ACL_D2H;
17538a061276SSven Peter 	bcm4377->acl_d2h_ring.doorbell = BCM4377_DOORBELL_ACL_D2H;
17548a061276SSven Peter 	bcm4377->acl_d2h_ring.completion_ring = BCM4377_EVENT_RING_HCI_ACL;
17558a061276SSven Peter 	bcm4377->acl_d2h_ring.d2h_buffers_only = true;
17568a061276SSven Peter 	bcm4377->acl_d2h_ring.mapped_payload_size = MAX_ACL_PAYLOAD_SIZE;
17578a061276SSven Peter 	bcm4377->acl_d2h_ring.n_entries = BCM4377_RING_N_ENTRIES;
17588a061276SSven Peter 
17598a061276SSven Peter 	/*
17608a061276SSven Peter 	 * no need for any cleanup since this is only called from _probe
17618a061276SSven Peter 	 * and only devres-managed allocations are used
17628a061276SSven Peter 	 */
17638a061276SSven Peter 	ret = bcm4377_alloc_transfer_ring(bcm4377, &bcm4377->control_h2d_ring);
17648a061276SSven Peter 	if (ret)
17658a061276SSven Peter 		return ret;
17668a061276SSven Peter 	ret = bcm4377_alloc_transfer_ring(bcm4377, &bcm4377->hci_h2d_ring);
17678a061276SSven Peter 	if (ret)
17688a061276SSven Peter 		return ret;
17698a061276SSven Peter 	ret = bcm4377_alloc_transfer_ring(bcm4377, &bcm4377->hci_d2h_ring);
17708a061276SSven Peter 	if (ret)
17718a061276SSven Peter 		return ret;
17728a061276SSven Peter 	ret = bcm4377_alloc_transfer_ring(bcm4377, &bcm4377->sco_h2d_ring);
17738a061276SSven Peter 	if (ret)
17748a061276SSven Peter 		return ret;
17758a061276SSven Peter 	ret = bcm4377_alloc_transfer_ring(bcm4377, &bcm4377->sco_d2h_ring);
17768a061276SSven Peter 	if (ret)
17778a061276SSven Peter 		return ret;
17788a061276SSven Peter 	ret = bcm4377_alloc_transfer_ring(bcm4377, &bcm4377->acl_h2d_ring);
17798a061276SSven Peter 	if (ret)
17808a061276SSven Peter 		return ret;
17818a061276SSven Peter 	ret = bcm4377_alloc_transfer_ring(bcm4377, &bcm4377->acl_d2h_ring);
17828a061276SSven Peter 	if (ret)
17838a061276SSven Peter 		return ret;
17848a061276SSven Peter 
17858a061276SSven Peter 	ret = bcm4377_alloc_completion_ring(bcm4377,
17868a061276SSven Peter 					    &bcm4377->control_ack_ring);
17878a061276SSven Peter 	if (ret)
17888a061276SSven Peter 		return ret;
17898a061276SSven Peter 	ret = bcm4377_alloc_completion_ring(bcm4377,
17908a061276SSven Peter 					    &bcm4377->hci_acl_ack_ring);
17918a061276SSven Peter 	if (ret)
17928a061276SSven Peter 		return ret;
17938a061276SSven Peter 	ret = bcm4377_alloc_completion_ring(bcm4377,
17948a061276SSven Peter 					    &bcm4377->hci_acl_event_ring);
17958a061276SSven Peter 	if (ret)
17968a061276SSven Peter 		return ret;
17978a061276SSven Peter 	ret = bcm4377_alloc_completion_ring(bcm4377, &bcm4377->sco_ack_ring);
17988a061276SSven Peter 	if (ret)
17998a061276SSven Peter 		return ret;
18008a061276SSven Peter 	ret = bcm4377_alloc_completion_ring(bcm4377, &bcm4377->sco_event_ring);
18018a061276SSven Peter 	if (ret)
18028a061276SSven Peter 		return ret;
18038a061276SSven Peter 
18048a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "all rings allocated and prepared\n");
18058a061276SSven Peter 
18068a061276SSven Peter 	return 0;
18078a061276SSven Peter }
18088a061276SSven Peter 
bcm4377_boot(struct bcm4377_data * bcm4377)18098a061276SSven Peter static int bcm4377_boot(struct bcm4377_data *bcm4377)
18108a061276SSven Peter {
18118a061276SSven Peter 	const struct firmware *fw;
18128a061276SSven Peter 	void *bfr;
18138a061276SSven Peter 	dma_addr_t fw_dma;
18148a061276SSven Peter 	int ret = 0;
18158a061276SSven Peter 	u32 bootstage, rti_status;
18168a061276SSven Peter 
18178a061276SSven Peter 	bootstage = ioread32(bcm4377->bar2 + BCM4377_BAR2_BOOTSTAGE);
18188a061276SSven Peter 	rti_status = ioread32(bcm4377->bar2 + BCM4377_BAR2_RTI_STATUS);
18198a061276SSven Peter 
18208a061276SSven Peter 	if (bootstage != 0) {
18218a061276SSven Peter 		dev_err(&bcm4377->pdev->dev, "bootstage is %d and not 0\n",
18228a061276SSven Peter 			bootstage);
18238a061276SSven Peter 		return -EINVAL;
18248a061276SSven Peter 	}
18258a061276SSven Peter 
18268a061276SSven Peter 	if (rti_status != 0) {
18278a061276SSven Peter 		dev_err(&bcm4377->pdev->dev, "RTI status is %d and not 0\n",
18288a061276SSven Peter 			rti_status);
18298a061276SSven Peter 		return -EINVAL;
18308a061276SSven Peter 	}
18318a061276SSven Peter 
18328a061276SSven Peter 	fw = bcm4377_request_blob(bcm4377, "bin");
18338a061276SSven Peter 	if (!fw) {
18348a061276SSven Peter 		dev_err(&bcm4377->pdev->dev, "Failed to load firmware\n");
18358a061276SSven Peter 		return -ENOENT;
18368a061276SSven Peter 	}
18378a061276SSven Peter 
18388a061276SSven Peter 	bfr = dma_alloc_coherent(&bcm4377->pdev->dev, fw->size, &fw_dma,
18398a061276SSven Peter 				 GFP_KERNEL);
18408a061276SSven Peter 	if (!bfr) {
18418a061276SSven Peter 		ret = -ENOMEM;
18428a061276SSven Peter 		goto out_release_fw;
18438a061276SSven Peter 	}
18448a061276SSven Peter 
18458a061276SSven Peter 	memcpy(bfr, fw->data, fw->size);
18468a061276SSven Peter 
18478a061276SSven Peter 	iowrite32(0, bcm4377->bar0 + BCM4377_BAR0_HOST_WINDOW_LO);
18488a061276SSven Peter 	iowrite32(0, bcm4377->bar0 + BCM4377_BAR0_HOST_WINDOW_HI);
18498a061276SSven Peter 	iowrite32(BCM4377_DMA_MASK,
18508a061276SSven Peter 		  bcm4377->bar0 + BCM4377_BAR0_HOST_WINDOW_SIZE);
18518a061276SSven Peter 
18528a061276SSven Peter 	iowrite32(lower_32_bits(fw_dma), bcm4377->bar2 + BCM4377_BAR2_FW_LO);
18538a061276SSven Peter 	iowrite32(upper_32_bits(fw_dma), bcm4377->bar2 + BCM4377_BAR2_FW_HI);
18548a061276SSven Peter 	iowrite32(fw->size, bcm4377->bar2 + BCM4377_BAR2_FW_SIZE);
18558a061276SSven Peter 	iowrite32(0, bcm4377->bar0 + BCM4377_BAR0_FW_DOORBELL);
18568a061276SSven Peter 
18578a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "waiting for firmware to boot\n");
18588a061276SSven Peter 
18598a061276SSven Peter 	ret = wait_for_completion_interruptible_timeout(&bcm4377->event,
18608a061276SSven Peter 							BCM4377_TIMEOUT);
18618a061276SSven Peter 	if (ret == 0) {
18628a061276SSven Peter 		ret = -ETIMEDOUT;
18638a061276SSven Peter 		goto out_dma_free;
18648a061276SSven Peter 	} else if (ret < 0) {
18658a061276SSven Peter 		goto out_dma_free;
18668a061276SSven Peter 	}
18678a061276SSven Peter 
18688a061276SSven Peter 	if (bcm4377->bootstage != 2) {
18698a061276SSven Peter 		dev_err(&bcm4377->pdev->dev, "boostage %d != 2\n",
18708a061276SSven Peter 			bcm4377->bootstage);
18718a061276SSven Peter 		ret = -ENXIO;
18728a061276SSven Peter 		goto out_dma_free;
18738a061276SSven Peter 	}
18748a061276SSven Peter 
18758a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "firmware has booted (stage = %x)\n",
18768a061276SSven Peter 		bcm4377->bootstage);
18778a061276SSven Peter 	ret = 0;
18788a061276SSven Peter 
18798a061276SSven Peter out_dma_free:
18808a061276SSven Peter 	dma_free_coherent(&bcm4377->pdev->dev, fw->size, bfr, fw_dma);
18818a061276SSven Peter out_release_fw:
18828a061276SSven Peter 	release_firmware(fw);
18838a061276SSven Peter 	return ret;
18848a061276SSven Peter }
18858a061276SSven Peter 
bcm4377_setup_rti(struct bcm4377_data * bcm4377)18868a061276SSven Peter static int bcm4377_setup_rti(struct bcm4377_data *bcm4377)
18878a061276SSven Peter {
18888a061276SSven Peter 	int ret;
18898a061276SSven Peter 
18908a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "starting RTI\n");
18918a061276SSven Peter 	iowrite32(1, bcm4377->bar0 + BCM4377_BAR0_RTI_CONTROL);
18928a061276SSven Peter 
18938a061276SSven Peter 	ret = wait_for_completion_interruptible_timeout(&bcm4377->event,
18948a061276SSven Peter 							BCM4377_TIMEOUT);
18958a061276SSven Peter 	if (ret == 0) {
18968a061276SSven Peter 		dev_err(&bcm4377->pdev->dev,
18978a061276SSven Peter 			"timed out while waiting for RTI to transition to state 1");
18988a061276SSven Peter 		return -ETIMEDOUT;
18998a061276SSven Peter 	} else if (ret < 0) {
19008a061276SSven Peter 		return ret;
19018a061276SSven Peter 	}
19028a061276SSven Peter 
19038a061276SSven Peter 	if (bcm4377->rti_status != 1) {
19048a061276SSven Peter 		dev_err(&bcm4377->pdev->dev, "RTI did not ack state 1 (%d)\n",
19058a061276SSven Peter 			bcm4377->rti_status);
19068a061276SSven Peter 		return -ENODEV;
19078a061276SSven Peter 	}
19088a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "RTI is in state 1\n");
19098a061276SSven Peter 
19108a061276SSven Peter 	/* allow access to the entire IOVA space again */
19118a061276SSven Peter 	iowrite32(0, bcm4377->bar2 + BCM4377_BAR2_RTI_WINDOW_LO);
19128a061276SSven Peter 	iowrite32(0, bcm4377->bar2 + BCM4377_BAR2_RTI_WINDOW_HI);
19138a061276SSven Peter 	iowrite32(BCM4377_DMA_MASK,
19148a061276SSven Peter 		  bcm4377->bar2 + BCM4377_BAR2_RTI_WINDOW_SIZE);
19158a061276SSven Peter 
19168a061276SSven Peter 	/* setup "Converged IPC" context */
19178a061276SSven Peter 	iowrite32(lower_32_bits(bcm4377->ctx_dma),
19188a061276SSven Peter 		  bcm4377->bar2 + BCM4377_BAR2_CONTEXT_ADDR_LO);
19198a061276SSven Peter 	iowrite32(upper_32_bits(bcm4377->ctx_dma),
19208a061276SSven Peter 		  bcm4377->bar2 + BCM4377_BAR2_CONTEXT_ADDR_HI);
19218a061276SSven Peter 	iowrite32(2, bcm4377->bar0 + BCM4377_BAR0_RTI_CONTROL);
19228a061276SSven Peter 
19238a061276SSven Peter 	ret = wait_for_completion_interruptible_timeout(&bcm4377->event,
19248a061276SSven Peter 							BCM4377_TIMEOUT);
19258a061276SSven Peter 	if (ret == 0) {
19268a061276SSven Peter 		dev_err(&bcm4377->pdev->dev,
19278a061276SSven Peter 			"timed out while waiting for RTI to transition to state 2");
19288a061276SSven Peter 		return -ETIMEDOUT;
19298a061276SSven Peter 	} else if (ret < 0) {
19308a061276SSven Peter 		return ret;
19318a061276SSven Peter 	}
19328a061276SSven Peter 
19338a061276SSven Peter 	if (bcm4377->rti_status != 2) {
19348a061276SSven Peter 		dev_err(&bcm4377->pdev->dev, "RTI did not ack state 2 (%d)\n",
19358a061276SSven Peter 			bcm4377->rti_status);
19368a061276SSven Peter 		return -ENODEV;
19378a061276SSven Peter 	}
19388a061276SSven Peter 
19398a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev,
19408a061276SSven Peter 		"RTI is in state 2; control ring is ready\n");
19418a061276SSven Peter 	bcm4377->control_ack_ring.enabled = true;
19428a061276SSven Peter 
19438a061276SSven Peter 	return 0;
19448a061276SSven Peter }
19458a061276SSven Peter 
bcm4377_parse_otp_board_params(struct bcm4377_data * bcm4377,char tag,const char * val,size_t len)19468a061276SSven Peter static int bcm4377_parse_otp_board_params(struct bcm4377_data *bcm4377,
19478a061276SSven Peter 					  char tag, const char *val, size_t len)
19488a061276SSven Peter {
19498a061276SSven Peter 	if (tag != 'V')
19508a061276SSven Peter 		return 0;
19518a061276SSven Peter 	if (len >= sizeof(bcm4377->vendor))
19528a061276SSven Peter 		return -EINVAL;
19538a061276SSven Peter 
19548a061276SSven Peter 	strscpy(bcm4377->vendor, val, len + 1);
19558a061276SSven Peter 	return 0;
19568a061276SSven Peter }
19578a061276SSven Peter 
bcm4377_parse_otp_chip_params(struct bcm4377_data * bcm4377,char tag,const char * val,size_t len)19588a061276SSven Peter static int bcm4377_parse_otp_chip_params(struct bcm4377_data *bcm4377, char tag,
19598a061276SSven Peter 					 const char *val, size_t len)
19608a061276SSven Peter {
19618a061276SSven Peter 	size_t idx = 0;
19628a061276SSven Peter 
19638a061276SSven Peter 	if (tag != 's')
19648a061276SSven Peter 		return 0;
19658a061276SSven Peter 	if (len >= sizeof(bcm4377->stepping))
19668a061276SSven Peter 		return -EINVAL;
19678a061276SSven Peter 
19688a061276SSven Peter 	while (len != 0) {
19698a061276SSven Peter 		bcm4377->stepping[idx] = tolower(val[idx]);
19708a061276SSven Peter 		if (val[idx] == '\0')
19718a061276SSven Peter 			return 0;
19728a061276SSven Peter 
19738a061276SSven Peter 		idx++;
19748a061276SSven Peter 		len--;
19758a061276SSven Peter 	}
19768a061276SSven Peter 
19778a061276SSven Peter 	bcm4377->stepping[idx] = '\0';
19788a061276SSven Peter 	return 0;
19798a061276SSven Peter }
19808a061276SSven Peter 
bcm4377_parse_otp_str(struct bcm4377_data * bcm4377,const u8 * str,enum bcm4377_otp_params_type type)19818a061276SSven Peter static int bcm4377_parse_otp_str(struct bcm4377_data *bcm4377, const u8 *str,
19828a061276SSven Peter 				 enum bcm4377_otp_params_type type)
19838a061276SSven Peter {
19848a061276SSven Peter 	const char *p;
19858a061276SSven Peter 	int ret;
19868a061276SSven Peter 
19878a061276SSven Peter 	p = skip_spaces(str);
19888a061276SSven Peter 	while (*p) {
19898a061276SSven Peter 		char tag = *p++;
19908a061276SSven Peter 		const char *end;
19918a061276SSven Peter 		size_t len;
19928a061276SSven Peter 
19938a061276SSven Peter 		if (*p++ != '=') /* implicit NUL check */
19948a061276SSven Peter 			return -EINVAL;
19958a061276SSven Peter 
19968a061276SSven Peter 		/* *p might be NUL here, if so end == p and len == 0 */
19978a061276SSven Peter 		end = strchrnul(p, ' ');
19988a061276SSven Peter 		len = end - p;
19998a061276SSven Peter 
20008a061276SSven Peter 		/* leave 1 byte for NUL in destination string */
20018a061276SSven Peter 		if (len > (BCM4377_OTP_MAX_PARAM_LEN - 1))
20028a061276SSven Peter 			return -EINVAL;
20038a061276SSven Peter 
20048a061276SSven Peter 		switch (type) {
20058a061276SSven Peter 		case BCM4377_OTP_BOARD_PARAMS:
20068a061276SSven Peter 			ret = bcm4377_parse_otp_board_params(bcm4377, tag, p,
20078a061276SSven Peter 							     len);
20088a061276SSven Peter 			break;
20098a061276SSven Peter 		case BCM4377_OTP_CHIP_PARAMS:
20108a061276SSven Peter 			ret = bcm4377_parse_otp_chip_params(bcm4377, tag, p,
20118a061276SSven Peter 							    len);
20128a061276SSven Peter 			break;
20138a061276SSven Peter 		default:
20148a061276SSven Peter 			ret = -EINVAL;
20158a061276SSven Peter 			break;
20168a061276SSven Peter 		}
20178a061276SSven Peter 
20188a061276SSven Peter 		if (ret)
20198a061276SSven Peter 			return ret;
20208a061276SSven Peter 
20218a061276SSven Peter 		/* Skip to next arg, if any */
20228a061276SSven Peter 		p = skip_spaces(end);
20238a061276SSven Peter 	}
20248a061276SSven Peter 
20258a061276SSven Peter 	return 0;
20268a061276SSven Peter }
20278a061276SSven Peter 
bcm4377_parse_otp_sys_vendor(struct bcm4377_data * bcm4377,u8 * otp,size_t size)20288a061276SSven Peter static int bcm4377_parse_otp_sys_vendor(struct bcm4377_data *bcm4377, u8 *otp,
20298a061276SSven Peter 					size_t size)
20308a061276SSven Peter {
20318a061276SSven Peter 	int idx = 4;
20328a061276SSven Peter 	const char *chip_params;
20338a061276SSven Peter 	const char *board_params;
20348a061276SSven Peter 	int ret;
20358a061276SSven Peter 
20368a061276SSven Peter 	/* 4-byte header and two empty strings */
20378a061276SSven Peter 	if (size < 6)
20388a061276SSven Peter 		return -EINVAL;
20398a061276SSven Peter 
20408a061276SSven Peter 	if (get_unaligned_le32(otp) != BCM4377_OTP_VENDOR_HDR)
20418a061276SSven Peter 		return -EINVAL;
20428a061276SSven Peter 
20438a061276SSven Peter 	chip_params = &otp[idx];
20448a061276SSven Peter 
20458a061276SSven Peter 	/* Skip first string, including terminator */
20468a061276SSven Peter 	idx += strnlen(chip_params, size - idx) + 1;
20478a061276SSven Peter 	if (idx >= size)
20488a061276SSven Peter 		return -EINVAL;
20498a061276SSven Peter 
20508a061276SSven Peter 	board_params = &otp[idx];
20518a061276SSven Peter 
20528a061276SSven Peter 	/* Skip to terminator of second string */
20538a061276SSven Peter 	idx += strnlen(board_params, size - idx);
20548a061276SSven Peter 	if (idx >= size)
20558a061276SSven Peter 		return -EINVAL;
20568a061276SSven Peter 
20578a061276SSven Peter 	/* At this point both strings are guaranteed NUL-terminated */
20588a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev,
20598a061276SSven Peter 		"OTP: chip_params='%s' board_params='%s'\n", chip_params,
20608a061276SSven Peter 		board_params);
20618a061276SSven Peter 
20628a061276SSven Peter 	ret = bcm4377_parse_otp_str(bcm4377, chip_params,
20638a061276SSven Peter 				    BCM4377_OTP_CHIP_PARAMS);
20648a061276SSven Peter 	if (ret)
20658a061276SSven Peter 		return ret;
20668a061276SSven Peter 
20678a061276SSven Peter 	ret = bcm4377_parse_otp_str(bcm4377, board_params,
20688a061276SSven Peter 				    BCM4377_OTP_BOARD_PARAMS);
20698a061276SSven Peter 	if (ret)
20708a061276SSven Peter 		return ret;
20718a061276SSven Peter 
20728a061276SSven Peter 	if (!bcm4377->stepping[0] || !bcm4377->vendor[0])
20738a061276SSven Peter 		return -EINVAL;
20748a061276SSven Peter 
20758a061276SSven Peter 	dev_dbg(&bcm4377->pdev->dev, "OTP: stepping=%s, vendor=%s\n",
20768a061276SSven Peter 		bcm4377->stepping, bcm4377->vendor);
20778a061276SSven Peter 	return 0;
20788a061276SSven Peter }
20798a061276SSven Peter 
bcm4377_parse_otp(struct bcm4377_data * bcm4377)20808a061276SSven Peter static int bcm4377_parse_otp(struct bcm4377_data *bcm4377)
20818a061276SSven Peter {
20828a061276SSven Peter 	u8 *otp;
20838a061276SSven Peter 	int i;
20848a061276SSven Peter 	int ret = -ENOENT;
20858a061276SSven Peter 
20868a061276SSven Peter 	otp = kzalloc(BCM4377_OTP_SIZE, GFP_KERNEL);
20878a061276SSven Peter 	if (!otp)
20888a061276SSven Peter 		return -ENOMEM;
20898a061276SSven Peter 
20908a061276SSven Peter 	for (i = 0; i < BCM4377_OTP_SIZE; ++i)
20918a061276SSven Peter 		otp[i] = ioread8(bcm4377->bar0 + bcm4377->hw->otp_offset + i);
20928a061276SSven Peter 
20938a061276SSven Peter 	i = 0;
20948a061276SSven Peter 	while (i < (BCM4377_OTP_SIZE - 1)) {
20958a061276SSven Peter 		u8 type = otp[i];
20968a061276SSven Peter 		u8 length = otp[i + 1];
20978a061276SSven Peter 
20988a061276SSven Peter 		if (type == 0)
20998a061276SSven Peter 			break;
21008a061276SSven Peter 
21018a061276SSven Peter 		if ((i + 2 + length) > BCM4377_OTP_SIZE)
21028a061276SSven Peter 			break;
21038a061276SSven Peter 
21048a061276SSven Peter 		switch (type) {
21058a061276SSven Peter 		case BCM4377_OTP_SYS_VENDOR:
21068a061276SSven Peter 			dev_dbg(&bcm4377->pdev->dev,
21078a061276SSven Peter 				"OTP @ 0x%x (%d): SYS_VENDOR", i, length);
21088a061276SSven Peter 			ret = bcm4377_parse_otp_sys_vendor(bcm4377, &otp[i + 2],
21098a061276SSven Peter 							   length);
21108a061276SSven Peter 			break;
21118a061276SSven Peter 		case BCM4377_OTP_CIS:
21128a061276SSven Peter 			dev_dbg(&bcm4377->pdev->dev, "OTP @ 0x%x (%d): CIS", i,
21138a061276SSven Peter 				length);
21148a061276SSven Peter 			break;
21158a061276SSven Peter 		default:
21168a061276SSven Peter 			dev_dbg(&bcm4377->pdev->dev, "OTP @ 0x%x (%d): unknown",
21178a061276SSven Peter 				i, length);
21188a061276SSven Peter 			break;
21198a061276SSven Peter 		}
21208a061276SSven Peter 
21218a061276SSven Peter 		i += 2 + length;
21228a061276SSven Peter 	}
21238a061276SSven Peter 
21248a061276SSven Peter 	kfree(otp);
21258a061276SSven Peter 	return ret;
21268a061276SSven Peter }
21278a061276SSven Peter 
bcm4377_init_cfg(struct bcm4377_data * bcm4377)21288a061276SSven Peter static int bcm4377_init_cfg(struct bcm4377_data *bcm4377)
21298a061276SSven Peter {
21308a061276SSven Peter 	int ret;
21318a061276SSven Peter 	u32 ctrl;
21328a061276SSven Peter 
21338a061276SSven Peter 	ret = pci_write_config_dword(bcm4377->pdev,
21348a061276SSven Peter 				     BCM4377_PCIECFG_BAR0_WINDOW1,
21358a061276SSven Peter 				     bcm4377->hw->bar0_window1);
21368a061276SSven Peter 	if (ret)
21378a061276SSven Peter 		return ret;
21388a061276SSven Peter 
21398a061276SSven Peter 	ret = pci_write_config_dword(bcm4377->pdev,
21408a061276SSven Peter 				     BCM4377_PCIECFG_BAR0_WINDOW2,
21418a061276SSven Peter 				     bcm4377->hw->bar0_window2);
21428a061276SSven Peter 	if (ret)
21438a061276SSven Peter 		return ret;
21448a061276SSven Peter 
21458a061276SSven Peter 	ret = pci_write_config_dword(
21468a061276SSven Peter 		bcm4377->pdev, BCM4377_PCIECFG_BAR0_CORE2_WINDOW1,
21478a061276SSven Peter 		BCM4377_PCIECFG_BAR0_CORE2_WINDOW1_DEFAULT);
21488a061276SSven Peter 	if (ret)
21498a061276SSven Peter 		return ret;
21508a061276SSven Peter 
21518a061276SSven Peter 	if (bcm4377->hw->has_bar0_core2_window2) {
21528a061276SSven Peter 		ret = pci_write_config_dword(bcm4377->pdev,
21538a061276SSven Peter 					     BCM4377_PCIECFG_BAR0_CORE2_WINDOW2,
21548a061276SSven Peter 					     bcm4377->hw->bar0_core2_window2);
21558a061276SSven Peter 		if (ret)
21568a061276SSven Peter 			return ret;
21578a061276SSven Peter 	}
21588a061276SSven Peter 
21598a061276SSven Peter 	ret = pci_write_config_dword(bcm4377->pdev, BCM4377_PCIECFG_BAR2_WINDOW,
21608a061276SSven Peter 				     BCM4377_PCIECFG_BAR2_WINDOW_DEFAULT);
21618a061276SSven Peter 	if (ret)
21628a061276SSven Peter 		return ret;
21638a061276SSven Peter 
21648a061276SSven Peter 	ret = pci_read_config_dword(bcm4377->pdev,
21658a061276SSven Peter 				    BCM4377_PCIECFG_SUBSYSTEM_CTRL, &ctrl);
21668a061276SSven Peter 	if (ret)
21678a061276SSven Peter 		return ret;
21688a061276SSven Peter 
21698a061276SSven Peter 	if (bcm4377->hw->clear_pciecfg_subsystem_ctrl_bit19)
21708a061276SSven Peter 		ctrl &= ~BIT(19);
21718a061276SSven Peter 	ctrl |= BIT(16);
21728a061276SSven Peter 
21738a061276SSven Peter 	return pci_write_config_dword(bcm4377->pdev,
21748a061276SSven Peter 				      BCM4377_PCIECFG_SUBSYSTEM_CTRL, ctrl);
21758a061276SSven Peter }
21768a061276SSven Peter 
bcm4377_probe_dmi(struct bcm4377_data * bcm4377)21778a061276SSven Peter static int bcm4377_probe_dmi(struct bcm4377_data *bcm4377)
21788a061276SSven Peter {
21798a061276SSven Peter 	const struct dmi_system_id *board_type_dmi_id;
21808a061276SSven Peter 
21818a061276SSven Peter 	board_type_dmi_id = dmi_first_match(bcm4377_dmi_board_table);
21828a061276SSven Peter 	if (board_type_dmi_id && board_type_dmi_id->driver_data) {
21838a061276SSven Peter 		bcm4377->board_type = board_type_dmi_id->driver_data;
21848a061276SSven Peter 		dev_dbg(&bcm4377->pdev->dev,
21858a061276SSven Peter 			"found board type via DMI match: %s\n",
21868a061276SSven Peter 			bcm4377->board_type);
21878a061276SSven Peter 	}
21888a061276SSven Peter 
21898a061276SSven Peter 	return 0;
21908a061276SSven Peter }
21918a061276SSven Peter 
bcm4377_probe_of(struct bcm4377_data * bcm4377)21928a061276SSven Peter static int bcm4377_probe_of(struct bcm4377_data *bcm4377)
21938a061276SSven Peter {
21948a061276SSven Peter 	struct device_node *np = bcm4377->pdev->dev.of_node;
21958a061276SSven Peter 	int ret;
21968a061276SSven Peter 
21978a061276SSven Peter 	if (!np)
21988a061276SSven Peter 		return 0;
21998a061276SSven Peter 
22008a061276SSven Peter 	ret = of_property_read_string(np, "brcm,board-type",
22018a061276SSven Peter 				      &bcm4377->board_type);
22028a061276SSven Peter 	if (ret) {
22038a061276SSven Peter 		dev_err(&bcm4377->pdev->dev, "no brcm,board-type property\n");
22048a061276SSven Peter 		return ret;
22058a061276SSven Peter 	}
22068a061276SSven Peter 
22078a061276SSven Peter 	bcm4377->taurus_beamforming_cal_blob =
22088a061276SSven Peter 		of_get_property(np, "brcm,taurus-bf-cal-blob",
22098a061276SSven Peter 				&bcm4377->taurus_beamforming_cal_size);
22108a061276SSven Peter 	if (!bcm4377->taurus_beamforming_cal_blob) {
22118a061276SSven Peter 		dev_err(&bcm4377->pdev->dev,
22128a061276SSven Peter 			"no brcm,taurus-bf-cal-blob property\n");
22138a061276SSven Peter 		return -ENOENT;
22148a061276SSven Peter 	}
22158a061276SSven Peter 	bcm4377->taurus_cal_blob = of_get_property(np, "brcm,taurus-cal-blob",
22168a061276SSven Peter 						   &bcm4377->taurus_cal_size);
22178a061276SSven Peter 	if (!bcm4377->taurus_cal_blob) {
22188a061276SSven Peter 		dev_err(&bcm4377->pdev->dev,
22198a061276SSven Peter 			"no brcm,taurus-cal-blob property\n");
22208a061276SSven Peter 		return -ENOENT;
22218a061276SSven Peter 	}
22228a061276SSven Peter 
22238a061276SSven Peter 	return 0;
22248a061276SSven Peter }
22258a061276SSven Peter 
bcm4377_disable_aspm(struct bcm4377_data * bcm4377)22268a061276SSven Peter static void bcm4377_disable_aspm(struct bcm4377_data *bcm4377)
22278a061276SSven Peter {
22288a061276SSven Peter 	pci_disable_link_state(bcm4377->pdev,
22298a061276SSven Peter 			       PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
22308a061276SSven Peter 
22318a061276SSven Peter 	/*
22328a061276SSven Peter 	 * pci_disable_link_state can fail if either CONFIG_PCIEASPM is disabled
22338a061276SSven Peter 	 * or if the BIOS hasn't handed over control to us. We must *always*
22348a061276SSven Peter 	 * disable ASPM for this device due to hardware errata though.
22358a061276SSven Peter 	 */
22368a061276SSven Peter 	pcie_capability_clear_word(bcm4377->pdev, PCI_EXP_LNKCTL,
22378a061276SSven Peter 				   PCI_EXP_LNKCTL_ASPMC);
22388a061276SSven Peter }
22398a061276SSven Peter 
bcm4377_pci_free_irq_vectors(void * data)22408a061276SSven Peter static void bcm4377_pci_free_irq_vectors(void *data)
22418a061276SSven Peter {
22428a061276SSven Peter 	pci_free_irq_vectors(data);
22438a061276SSven Peter }
22448a061276SSven Peter 
bcm4377_hci_free_dev(void * data)22458a061276SSven Peter static void bcm4377_hci_free_dev(void *data)
22468a061276SSven Peter {
22478a061276SSven Peter 	hci_free_dev(data);
22488a061276SSven Peter }
22498a061276SSven Peter 
bcm4377_hci_unregister_dev(void * data)22508a061276SSven Peter static void bcm4377_hci_unregister_dev(void *data)
22518a061276SSven Peter {
22528a061276SSven Peter 	hci_unregister_dev(data);
22538a061276SSven Peter }
22548a061276SSven Peter 
bcm4377_probe(struct pci_dev * pdev,const struct pci_device_id * id)22558a061276SSven Peter static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id)
22568a061276SSven Peter {
22578a061276SSven Peter 	struct bcm4377_data *bcm4377;
22588a061276SSven Peter 	struct hci_dev *hdev;
22598a061276SSven Peter 	int ret, irq;
22608a061276SSven Peter 
22618a061276SSven Peter 	ret = dma_set_mask_and_coherent(&pdev->dev, BCM4377_DMA_MASK);
22628a061276SSven Peter 	if (ret)
22638a061276SSven Peter 		return ret;
22648a061276SSven Peter 
22658a061276SSven Peter 	bcm4377 = devm_kzalloc(&pdev->dev, sizeof(*bcm4377), GFP_KERNEL);
22668a061276SSven Peter 	if (!bcm4377)
22678a061276SSven Peter 		return -ENOMEM;
22688a061276SSven Peter 
22698a061276SSven Peter 	bcm4377->pdev = pdev;
22708a061276SSven Peter 	bcm4377->hw = &bcm4377_hw_variants[id->driver_data];
22718a061276SSven Peter 	init_completion(&bcm4377->event);
22728a061276SSven Peter 
22738a061276SSven Peter 	ret = bcm4377_prepare_rings(bcm4377);
22748a061276SSven Peter 	if (ret)
22758a061276SSven Peter 		return ret;
22768a061276SSven Peter 
22778a061276SSven Peter 	ret = bcm4377_init_context(bcm4377);
22788a061276SSven Peter 	if (ret)
22798a061276SSven Peter 		return ret;
22808a061276SSven Peter 
22818a061276SSven Peter 	ret = bcm4377_probe_dmi(bcm4377);
22828a061276SSven Peter 	if (ret)
22838a061276SSven Peter 		return ret;
22848a061276SSven Peter 	ret = bcm4377_probe_of(bcm4377);
22858a061276SSven Peter 	if (ret)
22868a061276SSven Peter 		return ret;
22878a061276SSven Peter 	if (!bcm4377->board_type) {
22888a061276SSven Peter 		dev_err(&pdev->dev, "unable to determine board type\n");
22898a061276SSven Peter 		return -ENODEV;
22908a061276SSven Peter 	}
22918a061276SSven Peter 
22928a061276SSven Peter 	if (bcm4377->hw->disable_aspm)
22938a061276SSven Peter 		bcm4377_disable_aspm(bcm4377);
22948a061276SSven Peter 
22958a061276SSven Peter 	ret = pci_reset_function_locked(pdev);
22968a061276SSven Peter 	if (ret)
22978a061276SSven Peter 		dev_warn(
22988a061276SSven Peter 			&pdev->dev,
22998a061276SSven Peter 			"function level reset failed with %d; trying to continue anyway\n",
23008a061276SSven Peter 			ret);
23018a061276SSven Peter 
23028a061276SSven Peter 	/*
23038a061276SSven Peter 	 * If this number is too low and we try to access any BAR too
23048a061276SSven Peter 	 * early the device will crash. Experiments have shown that
23058a061276SSven Peter 	 * approximately 50 msec is the minimum amount we have to wait.
23068a061276SSven Peter 	 * Let's double that to be safe.
23078a061276SSven Peter 	 */
23088a061276SSven Peter 	msleep(100);
23098a061276SSven Peter 
2310b1e05cfbSYang Yingliang 	ret = pcim_enable_device(pdev);
23118a061276SSven Peter 	if (ret)
23128a061276SSven Peter 		return ret;
23138a061276SSven Peter 	pci_set_master(pdev);
23148a061276SSven Peter 
23158a061276SSven Peter 	ret = bcm4377_init_cfg(bcm4377);
23168a061276SSven Peter 	if (ret)
23178a061276SSven Peter 		return ret;
23188a061276SSven Peter 
23198a061276SSven Peter 	bcm4377->bar0 = pcim_iomap(pdev, 0, 0);
23208a061276SSven Peter 	if (!bcm4377->bar0)
23218a061276SSven Peter 		return -EBUSY;
23228a061276SSven Peter 	bcm4377->bar2 = pcim_iomap(pdev, 2, 0);
23238a061276SSven Peter 	if (!bcm4377->bar2)
23248a061276SSven Peter 		return -EBUSY;
23258a061276SSven Peter 
23268a061276SSven Peter 	ret = bcm4377_parse_otp(bcm4377);
23278a061276SSven Peter 	if (ret) {
23288a061276SSven Peter 		dev_err(&pdev->dev, "Reading OTP failed with %d\n", ret);
23298a061276SSven Peter 		return ret;
23308a061276SSven Peter 	}
23318a061276SSven Peter 
23328a061276SSven Peter 	/*
23338a061276SSven Peter 	 * Legacy interrupts result in an IRQ storm because we don't know where
23348a061276SSven Peter 	 * the interrupt mask and status registers for these chips are.
23358a061276SSven Peter 	 * MSIs are acked automatically instead.
23368a061276SSven Peter 	 */
23378a061276SSven Peter 	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
23388a061276SSven Peter 	if (ret < 0)
23398a061276SSven Peter 		return -ENODEV;
23408a061276SSven Peter 	ret = devm_add_action_or_reset(&pdev->dev, bcm4377_pci_free_irq_vectors,
23418a061276SSven Peter 				       pdev);
23428a061276SSven Peter 	if (ret)
23438a061276SSven Peter 		return ret;
23448a061276SSven Peter 
23458a061276SSven Peter 	irq = pci_irq_vector(pdev, 0);
23468a061276SSven Peter 	if (irq <= 0)
23478a061276SSven Peter 		return -ENODEV;
23488a061276SSven Peter 
23498a061276SSven Peter 	ret = devm_request_irq(&pdev->dev, irq, bcm4377_irq, 0, "bcm4377",
23508a061276SSven Peter 			       bcm4377);
23518a061276SSven Peter 	if (ret)
23528a061276SSven Peter 		return ret;
23538a061276SSven Peter 
23548a061276SSven Peter 	hdev = hci_alloc_dev();
23558a061276SSven Peter 	if (!hdev)
23568a061276SSven Peter 		return -ENOMEM;
23578a061276SSven Peter 	ret = devm_add_action_or_reset(&pdev->dev, bcm4377_hci_free_dev, hdev);
23588a061276SSven Peter 	if (ret)
23598a061276SSven Peter 		return ret;
23608a061276SSven Peter 
23618a061276SSven Peter 	bcm4377->hdev = hdev;
23628a061276SSven Peter 
23638a061276SSven Peter 	hdev->bus = HCI_PCI;
23648a061276SSven Peter 	hdev->open = bcm4377_hci_open;
23658a061276SSven Peter 	hdev->close = bcm4377_hci_close;
23668a061276SSven Peter 	hdev->send = bcm4377_hci_send_frame;
23678a061276SSven Peter 	hdev->set_bdaddr = bcm4377_hci_set_bdaddr;
23688a061276SSven Peter 	hdev->setup = bcm4377_hci_setup;
23698a061276SSven Peter 
23708a061276SSven Peter 	if (bcm4377->hw->broken_mws_transport_config)
23718a061276SSven Peter 		set_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &hdev->quirks);
23728a061276SSven Peter 	if (bcm4377->hw->broken_ext_scan)
23738a061276SSven Peter 		set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
23745c9e997aSJanne Grunau 	if (bcm4377->hw->broken_le_coded)
23755c9e997aSJanne Grunau 		set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks);
23768a061276SSven Peter 
23778a061276SSven Peter 	pci_set_drvdata(pdev, bcm4377);
23788a061276SSven Peter 	hci_set_drvdata(hdev, bcm4377);
23798a061276SSven Peter 	SET_HCIDEV_DEV(hdev, &pdev->dev);
23808a061276SSven Peter 
23818a061276SSven Peter 	ret = bcm4377_boot(bcm4377);
23828a061276SSven Peter 	if (ret)
23838a061276SSven Peter 		return ret;
23848a061276SSven Peter 
23858a061276SSven Peter 	ret = bcm4377_setup_rti(bcm4377);
23868a061276SSven Peter 	if (ret)
23878a061276SSven Peter 		return ret;
23888a061276SSven Peter 
23898a061276SSven Peter 	ret = hci_register_dev(hdev);
23908a061276SSven Peter 	if (ret)
23918a061276SSven Peter 		return ret;
23928a061276SSven Peter 	return devm_add_action_or_reset(&pdev->dev, bcm4377_hci_unregister_dev,
23938a061276SSven Peter 					hdev);
23948a061276SSven Peter }
23958a061276SSven Peter 
bcm4377_suspend(struct pci_dev * pdev,pm_message_t state)23968a061276SSven Peter static int bcm4377_suspend(struct pci_dev *pdev, pm_message_t state)
23978a061276SSven Peter {
23988a061276SSven Peter 	struct bcm4377_data *bcm4377 = pci_get_drvdata(pdev);
23998a061276SSven Peter 	int ret;
24008a061276SSven Peter 
24018a061276SSven Peter 	ret = hci_suspend_dev(bcm4377->hdev);
24028a061276SSven Peter 	if (ret)
24038a061276SSven Peter 		return ret;
24048a061276SSven Peter 
24058a061276SSven Peter 	iowrite32(BCM4377_BAR0_SLEEP_CONTROL_QUIESCE,
24068a061276SSven Peter 		  bcm4377->bar0 + BCM4377_BAR0_SLEEP_CONTROL);
24078a061276SSven Peter 
24088a061276SSven Peter 	return 0;
24098a061276SSven Peter }
24108a061276SSven Peter 
bcm4377_resume(struct pci_dev * pdev)24118a061276SSven Peter static int bcm4377_resume(struct pci_dev *pdev)
24128a061276SSven Peter {
24138a061276SSven Peter 	struct bcm4377_data *bcm4377 = pci_get_drvdata(pdev);
24148a061276SSven Peter 
24158a061276SSven Peter 	iowrite32(BCM4377_BAR0_SLEEP_CONTROL_UNQUIESCE,
24168a061276SSven Peter 		  bcm4377->bar0 + BCM4377_BAR0_SLEEP_CONTROL);
24178a061276SSven Peter 
24188a061276SSven Peter 	return hci_resume_dev(bcm4377->hdev);
24198a061276SSven Peter }
24208a061276SSven Peter 
24218a061276SSven Peter static const struct dmi_system_id bcm4377_dmi_board_table[] = {
24228a061276SSven Peter 	{
24238a061276SSven Peter 		.matches = {
24248a061276SSven Peter 			DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
24258a061276SSven Peter 			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir9,1"),
24268a061276SSven Peter 		},
24278a061276SSven Peter 		.driver_data = "apple,formosa",
24288a061276SSven Peter 	},
24298a061276SSven Peter 	{
24308a061276SSven Peter 		.matches = {
24318a061276SSven Peter 			DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
24328a061276SSven Peter 			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro15,4"),
24338a061276SSven Peter 		},
24348a061276SSven Peter 		.driver_data = "apple,formosa",
24358a061276SSven Peter 	},
24368a061276SSven Peter 	{
24378a061276SSven Peter 		.matches = {
24388a061276SSven Peter 			DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
24398a061276SSven Peter 			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,3"),
24408a061276SSven Peter 		},
24418a061276SSven Peter 		.driver_data = "apple,formosa",
24428a061276SSven Peter 	},
24438a061276SSven Peter 	{}
24448a061276SSven Peter };
24458a061276SSven Peter 
24468a061276SSven Peter static const struct bcm4377_hw bcm4377_hw_variants[] = {
24478a061276SSven Peter 	[BCM4377] = {
24488a061276SSven Peter 		.id = 0x4377,
24498a061276SSven Peter 		.otp_offset = 0x4120,
24508a061276SSven Peter 		.bar0_window1 = 0x1800b000,
24518a061276SSven Peter 		.bar0_window2 = 0x1810c000,
24528a061276SSven Peter 		.disable_aspm = true,
24538a061276SSven Peter 		.broken_ext_scan = true,
24548a061276SSven Peter 		.send_ptb = bcm4377_send_ptb,
24558a061276SSven Peter 	},
24568a061276SSven Peter 
24578a061276SSven Peter 	[BCM4378] = {
24588a061276SSven Peter 		.id = 0x4378,
24598a061276SSven Peter 		.otp_offset = 0x4120,
24608a061276SSven Peter 		.bar0_window1 = 0x18002000,
24618a061276SSven Peter 		.bar0_window2 = 0x1810a000,
24628a061276SSven Peter 		.bar0_core2_window2 = 0x18107000,
24638a061276SSven Peter 		.has_bar0_core2_window2 = true,
24648a061276SSven Peter 		.broken_mws_transport_config = true,
24655c9e997aSJanne Grunau 		.broken_le_coded = true,
24668a061276SSven Peter 		.send_calibration = bcm4378_send_calibration,
24678a061276SSven Peter 		.send_ptb = bcm4378_send_ptb,
24688a061276SSven Peter 	},
24698a061276SSven Peter 
24708a061276SSven Peter 	[BCM4387] = {
24718a061276SSven Peter 		.id = 0x4387,
24728a061276SSven Peter 		.otp_offset = 0x413c,
24738a061276SSven Peter 		.bar0_window1 = 0x18002000,
24748a061276SSven Peter 		.bar0_window2 = 0x18109000,
24758a061276SSven Peter 		.bar0_core2_window2 = 0x18106000,
24768a061276SSven Peter 		.has_bar0_core2_window2 = true,
24778a061276SSven Peter 		.clear_pciecfg_subsystem_ctrl_bit19 = true,
24788a061276SSven Peter 		.broken_mws_transport_config = true,
24795c9e997aSJanne Grunau 		.broken_le_coded = true,
24808a061276SSven Peter 		.send_calibration = bcm4387_send_calibration,
24818a061276SSven Peter 		.send_ptb = bcm4378_send_ptb,
24828a061276SSven Peter 	},
24838a061276SSven Peter };
24848a061276SSven Peter 
24858a061276SSven Peter #define BCM4377_DEVID_ENTRY(id)                                             \
24868a061276SSven Peter 	{                                                                   \
24878a061276SSven Peter 		PCI_VENDOR_ID_BROADCOM, BCM##id##_DEVICE_ID, PCI_ANY_ID,    \
24888a061276SSven Peter 			PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \
24898a061276SSven Peter 			BCM##id                                             \
24908a061276SSven Peter 	}
24918a061276SSven Peter 
24928a061276SSven Peter static const struct pci_device_id bcm4377_devid_table[] = {
24938a061276SSven Peter 	BCM4377_DEVID_ENTRY(4377),
24948a061276SSven Peter 	BCM4377_DEVID_ENTRY(4378),
24958a061276SSven Peter 	BCM4377_DEVID_ENTRY(4387),
24968a061276SSven Peter 	{},
24978a061276SSven Peter };
24988a061276SSven Peter MODULE_DEVICE_TABLE(pci, bcm4377_devid_table);
24998a061276SSven Peter 
25008a061276SSven Peter static struct pci_driver bcm4377_pci_driver = {
25018a061276SSven Peter 	.name = "hci_bcm4377",
25028a061276SSven Peter 	.id_table = bcm4377_devid_table,
25038a061276SSven Peter 	.probe = bcm4377_probe,
25048a061276SSven Peter 	.suspend = bcm4377_suspend,
25058a061276SSven Peter 	.resume = bcm4377_resume,
25068a061276SSven Peter };
25078a061276SSven Peter module_pci_driver(bcm4377_pci_driver);
25088a061276SSven Peter 
25098a061276SSven Peter MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>");
25108a061276SSven Peter MODULE_DESCRIPTION("Bluetooth support for Broadcom 4377/4378/4387 devices");
25118a061276SSven Peter MODULE_LICENSE("Dual MIT/GPL");
25128a061276SSven Peter MODULE_FIRMWARE("brcm/brcmbt4377*.bin");
25138a061276SSven Peter MODULE_FIRMWARE("brcm/brcmbt4377*.ptb");
25148a061276SSven Peter MODULE_FIRMWARE("brcm/brcmbt4378*.bin");
25158a061276SSven Peter MODULE_FIRMWARE("brcm/brcmbt4378*.ptb");
25168a061276SSven Peter MODULE_FIRMWARE("brcm/brcmbt4387*.bin");
25178a061276SSven Peter MODULE_FIRMWARE("brcm/brcmbt4387*.ptb");
2518