| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- /* SPDX-License-Identifier: GPL-2.0-or-later */
- /*
- *
- * Bluetooth support for Intel PCIe devices
- *
- * Copyright (C) 2024 Intel Corporation
- */
- /* Control and Status Register(BTINTEL_PCIE_CSR) */
- #define BTINTEL_PCIE_CSR_BASE (0x000)
- #define BTINTEL_PCIE_CSR_FUNC_CTRL_REG (BTINTEL_PCIE_CSR_BASE + 0x024)
- #define BTINTEL_PCIE_CSR_HW_REV_REG (BTINTEL_PCIE_CSR_BASE + 0x028)
- #define BTINTEL_PCIE_CSR_RF_ID_REG (BTINTEL_PCIE_CSR_BASE + 0x09C)
- #define BTINTEL_PCIE_CSR_BOOT_STAGE_REG (BTINTEL_PCIE_CSR_BASE + 0x108)
- #define BTINTEL_PCIE_CSR_IPC_SLEEP_CTL_REG (BTINTEL_PCIE_CSR_BASE + 0x114)
- #define BTINTEL_PCIE_CSR_CI_ADDR_LSB_REG (BTINTEL_PCIE_CSR_BASE + 0x118)
- #define BTINTEL_PCIE_CSR_CI_ADDR_MSB_REG (BTINTEL_PCIE_CSR_BASE + 0x11C)
- #define BTINTEL_PCIE_CSR_IMG_RESPONSE_REG (BTINTEL_PCIE_CSR_BASE + 0x12C)
- #define BTINTEL_PCIE_CSR_HBUS_TARG_WRPTR (BTINTEL_PCIE_CSR_BASE + 0x460)
- /* BTINTEL_PCIE_CSR Function Control Register */
- #define BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_ENA (BIT(0))
- #define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT (BIT(6))
- #define BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_INIT (BIT(7))
- #define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS (BIT(20))
- #define BTINTEL_PCIE_CSR_FUNC_CTRL_SW_RESET (BIT(31))
- /* Value for BTINTEL_PCIE_CSR_BOOT_STAGE register */
- #define BTINTEL_PCIE_CSR_BOOT_STAGE_ROM (BIT(0))
- #define BTINTEL_PCIE_CSR_BOOT_STAGE_IML (BIT(1))
- #define BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW (BIT(2))
- #define BTINTEL_PCIE_CSR_BOOT_STAGE_ROM_LOCKDOWN (BIT(10))
- #define BTINTEL_PCIE_CSR_BOOT_STAGE_IML_LOCKDOWN (BIT(11))
- #define BTINTEL_PCIE_CSR_BOOT_STAGE_MAC_ACCESS_ON (BIT(16))
- #define BTINTEL_PCIE_CSR_BOOT_STAGE_ALIVE (BIT(23))
- #define BTINTEL_PCIE_CSR_BOOT_STAGE_D3_STATE_READY (BIT(24))
- /* Registers for MSI-X */
- #define BTINTEL_PCIE_CSR_MSIX_BASE (0x2000)
- #define BTINTEL_PCIE_CSR_MSIX_FH_INT_CAUSES (BTINTEL_PCIE_CSR_MSIX_BASE + 0x0800)
- #define BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK (BTINTEL_PCIE_CSR_MSIX_BASE + 0x0804)
- #define BTINTEL_PCIE_CSR_MSIX_HW_INT_CAUSES (BTINTEL_PCIE_CSR_MSIX_BASE + 0x0808)
- #define BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK (BTINTEL_PCIE_CSR_MSIX_BASE + 0x080C)
- #define BTINTEL_PCIE_CSR_MSIX_AUTOMASK_ST (BTINTEL_PCIE_CSR_MSIX_BASE + 0x0810)
- #define BTINTEL_PCIE_CSR_MSIX_AUTOMASK_EN (BTINTEL_PCIE_CSR_MSIX_BASE + 0x0814)
- #define BTINTEL_PCIE_CSR_MSIX_IVAR_BASE (BTINTEL_PCIE_CSR_MSIX_BASE + 0x0880)
- #define BTINTEL_PCIE_CSR_MSIX_IVAR(cause) (BTINTEL_PCIE_CSR_MSIX_IVAR_BASE + (cause))
- /* Causes for the FH register interrupts */
- enum msix_fh_int_causes {
- BTINTEL_PCIE_MSIX_FH_INT_CAUSES_0 = BIT(0), /* cause 0 */
- BTINTEL_PCIE_MSIX_FH_INT_CAUSES_1 = BIT(1), /* cause 1 */
- };
- /* Causes for the HW register interrupts */
- enum msix_hw_int_causes {
- BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0 = BIT(0), /* cause 32 */
- };
- /* PCIe device states
- * Host-Device interface is active
- * Host-Device interface is inactive(as reflected by IPC_SLEEP_CONTROL_CSR_AD)
- * Host-Device interface is inactive(as reflected by IPC_SLEEP_CONTROL_CSR_AD)
- */
- enum {
- BTINTEL_PCIE_STATE_D0 = 0,
- BTINTEL_PCIE_STATE_D3_HOT = 2,
- BTINTEL_PCIE_STATE_D3_COLD = 3,
- };
- #define BTINTEL_PCIE_MSIX_NON_AUTO_CLEAR_CAUSE BIT(7)
- /* Minimum and Maximum number of MSI-X Vector
- * Intel Bluetooth PCIe support only 1 vector
- */
- #define BTINTEL_PCIE_MSIX_VEC_MAX 1
- #define BTINTEL_PCIE_MSIX_VEC_MIN 1
- /* Default poll time for MAC access during init */
- #define BTINTEL_DEFAULT_MAC_ACCESS_TIMEOUT_US 200000
- /* Default interrupt timeout in msec */
- #define BTINTEL_DEFAULT_INTR_TIMEOUT_MS 3000
- /* The number of descriptors in TX queues */
- #define BTINTEL_PCIE_TX_DESCS_COUNT 32
- /* The number of descriptors in RX queues */
- #define BTINTEL_PCIE_RX_DESCS_COUNT 64
- /* Number of Queue for TX and RX
- * It indicates the index of the IA(Index Array)
- */
- enum {
- BTINTEL_PCIE_TXQ_NUM = 0,
- BTINTEL_PCIE_RXQ_NUM = 1,
- BTINTEL_PCIE_NUM_QUEUES = 2,
- };
- /* The size of DMA buffer for TX and RX in bytes */
- #define BTINTEL_PCIE_BUFFER_SIZE 4096
- /* DMA allocation alignment */
- #define BTINTEL_PCIE_DMA_POOL_ALIGNMENT 256
- #define BTINTEL_PCIE_TX_WAIT_TIMEOUT_MS 500
- /* Doorbell vector for TFD */
- #define BTINTEL_PCIE_TX_DB_VEC 0
- /* Doorbell vector for FRBD */
- #define BTINTEL_PCIE_RX_DB_VEC 513
- /* RBD buffer size mapping */
- #define BTINTEL_PCIE_RBD_SIZE_4K 0x04
- /*
- * Struct for Context Information (v2)
- *
- * All members are write-only for host and read-only for device.
- *
- * @version: Version of context information
- * @size: Size of context information
- * @config: Config with which host wants peripheral to execute
- * Subset of capability register published by device
- * @addr_tr_hia: Address of TR Head Index Array
- * @addr_tr_tia: Address of TR Tail Index Array
- * @addr_cr_hia: Address of CR Head Index Array
- * @addr_cr_tia: Address of CR Tail Index Array
- * @num_tr_ia: Number of entries in TR Index Arrays
- * @num_cr_ia: Number of entries in CR Index Arrays
- * @rbd_siz: RBD Size { 0x4=4K }
- * @addr_tfdq: Address of TFD Queue(tx)
- * @addr_urbdq0: Address of URBD Queue(tx)
- * @num_tfdq: Number of TFD in TFD Queue(tx)
- * @num_urbdq0: Number of URBD in URBD Queue(tx)
- * @tfdq_db_vec: Queue number of TFD
- * @urbdq0_db_vec: Queue number of URBD
- * @addr_frbdq: Address of FRBD Queue(rx)
- * @addr_urbdq1: Address of URBD Queue(rx)
- * @num_frbdq: Number of FRBD in FRBD Queue(rx)
- * @frbdq_db_vec: Queue number of FRBD
- * @num_urbdq1: Number of URBD in URBD Queue(rx)
- * @urbdq_db_vec: Queue number of URBDQ1
- * @tr_msi_vec: Transfer Ring MSI-X Vector
- * @cr_msi_vec: Completion Ring MSI-X Vector
- * @dbgc_addr: DBGC first fragment address
- * @dbgc_size: DBGC buffer size
- * @early_enable: Enarly debug enable
- * @dbg_output_mode: Debug output mode
- * Bit[4] DBGC O/P { 0=SRAM, 1=DRAM(not relevant for NPK) }
- * Bit[5] DBGC I/P { 0=BDBG, 1=DBGI }
- * Bits[6:7] DBGI O/P(relevant if bit[5] = 1)
- * 0=BT DBGC, 1=WiFi DBGC, 2=NPK }
- * @dbg_preset: Debug preset
- * @ext_addr: Address of context information extension
- * @ext_size: Size of context information part
- *
- * Total 38 DWords
- */
- struct ctx_info {
- u16 version;
- u16 size;
- u32 config;
- u32 reserved_dw02;
- u32 reserved_dw03;
- u64 addr_tr_hia;
- u64 addr_tr_tia;
- u64 addr_cr_hia;
- u64 addr_cr_tia;
- u16 num_tr_ia;
- u16 num_cr_ia;
- u32 rbd_size:4,
- reserved_dw13:28;
- u64 addr_tfdq;
- u64 addr_urbdq0;
- u16 num_tfdq;
- u16 num_urbdq0;
- u16 tfdq_db_vec;
- u16 urbdq0_db_vec;
- u64 addr_frbdq;
- u64 addr_urbdq1;
- u16 num_frbdq;
- u16 frbdq_db_vec;
- u16 num_urbdq1;
- u16 urbdq_db_vec;
- u16 tr_msi_vec;
- u16 cr_msi_vec;
- u32 reserved_dw27;
- u64 dbgc_addr;
- u32 dbgc_size;
- u32 early_enable:1,
- reserved_dw31:3,
- dbg_output_mode:4,
- dbg_preset:8,
- reserved2_dw31:16;
- u64 ext_addr;
- u32 ext_size;
- u32 test_param;
- u32 reserved_dw36;
- u32 reserved_dw37;
- } __packed;
- /* Transfer Descriptor for TX
- * @type: Not in use. Set to 0x0
- * @size: Size of data in the buffer
- * @addr: DMA Address of buffer
- */
- struct tfd {
- u8 type;
- u16 size;
- u8 reserved;
- u64 addr;
- u32 reserved1;
- } __packed;
- /* URB Descriptor for TX
- * @tfd_index: Index of TFD in TFDQ + 1
- * @num_txq: Queue index of TFD Queue
- * @cmpl_count: Completion count. Always 0x01
- * @immediate_cmpl: Immediate completion flag: Always 0x01
- */
- struct urbd0 {
- u32 tfd_index:16,
- num_txq:8,
- cmpl_count:4,
- reserved:3,
- immediate_cmpl:1;
- } __packed;
- /* FRB Descriptor for RX
- * @tag: RX buffer tag (index of RX buffer queue)
- * @addr: Address of buffer
- */
- struct frbd {
- u32 tag:16,
- reserved:16;
- u32 reserved2;
- u64 addr;
- } __packed;
- /* URB Descriptor for RX
- * @frbd_tag: Tag from FRBD
- * @status: Status
- */
- struct urbd1 {
- u32 frbd_tag:16,
- status:1,
- reserved:14,
- fixed:1;
- } __packed;
- /* RFH header in RX packet
- * @packet_len: Length of the data in the buffer
- * @rxq: RX Queue number
- * @cmd_id: Command ID. Not in Use
- */
- struct rfh_hdr {
- u64 packet_len:16,
- rxq:6,
- reserved:10,
- cmd_id:16,
- reserved1:16;
- } __packed;
- /* Internal data buffer
- * @data: pointer to the data buffer
- * @p_addr: physical address of data buffer
- */
- struct data_buf {
- u8 *data;
- dma_addr_t data_p_addr;
- };
- /* Index Array */
- struct ia {
- dma_addr_t tr_hia_p_addr;
- u16 *tr_hia;
- dma_addr_t tr_tia_p_addr;
- u16 *tr_tia;
- dma_addr_t cr_hia_p_addr;
- u16 *cr_hia;
- dma_addr_t cr_tia_p_addr;
- u16 *cr_tia;
- };
- /* Structure for TX Queue
- * @count: Number of descriptors
- * @tfds: Array of TFD
- * @urbd0s: Array of URBD0
- * @buf: Array of data_buf structure
- */
- struct txq {
- u16 count;
- dma_addr_t tfds_p_addr;
- struct tfd *tfds;
- dma_addr_t urbd0s_p_addr;
- struct urbd0 *urbd0s;
- dma_addr_t buf_p_addr;
- void *buf_v_addr;
- struct data_buf *bufs;
- };
- /* Structure for RX Queue
- * @count: Number of descriptors
- * @frbds: Array of FRBD
- * @urbd1s: Array of URBD1
- * @buf: Array of data_buf structure
- */
- struct rxq {
- u16 count;
- dma_addr_t frbds_p_addr;
- struct frbd *frbds;
- dma_addr_t urbd1s_p_addr;
- struct urbd1 *urbd1s;
- dma_addr_t buf_p_addr;
- void *buf_v_addr;
- struct data_buf *bufs;
- };
- /* struct btintel_pcie_data
- * @pdev: pci device
- * @hdev: hdev device
- * @flags: driver state
- * @irq_lock: spinlock for MSI-X
- * @hci_rx_lock: spinlock for HCI RX flow
- * @base_addr: pci base address (from BAR)
- * @msix_entries: array of MSI-X entries
- * @msix_enabled: true if MSI-X is enabled;
- * @alloc_vecs: number of interrupt vectors allocated
- * @def_irq: default irq for all causes
- * @fh_init_mask: initial unmasked rxq causes
- * @hw_init_mask: initial unmaksed hw causes
- * @boot_stage_cache: cached value of boot stage register
- * @img_resp_cache: cached value of image response register
- * @cnvi: CNVi register value
- * @cnvr: CNVr register value
- * @gp0_received: condition for gp0 interrupt
- * @gp0_wait_q: wait_q for gp0 interrupt
- * @tx_wait_done: condition for tx interrupt
- * @tx_wait_q: wait_q for tx interrupt
- * @workqueue: workqueue for RX work
- * @rx_skb_q: SKB queue for RX packet
- * @rx_work: RX work struct to process the RX packet in @rx_skb_q
- * @dma_pool: DMA pool for descriptors, index array and ci
- * @dma_p_addr: DMA address for pool
- * @dma_v_addr: address of pool
- * @ci_p_addr: DMA address for CI struct
- * @ci: CI struct
- * @ia: Index Array struct
- * @txq: TX Queue struct
- * @rxq: RX Queue struct
- * @alive_intr_ctxt: Alive interrupt context
- */
- struct btintel_pcie_data {
- struct pci_dev *pdev;
- struct hci_dev *hdev;
- unsigned long flags;
- /* lock used in MSI-X interrupt */
- spinlock_t irq_lock;
- /* lock to serialize rx events */
- spinlock_t hci_rx_lock;
- void __iomem *base_addr;
- struct msix_entry msix_entries[BTINTEL_PCIE_MSIX_VEC_MAX];
- bool msix_enabled;
- u32 alloc_vecs;
- u32 def_irq;
- u32 fh_init_mask;
- u32 hw_init_mask;
- u32 boot_stage_cache;
- u32 img_resp_cache;
- u32 cnvi;
- u32 cnvr;
- bool gp0_received;
- wait_queue_head_t gp0_wait_q;
- bool tx_wait_done;
- wait_queue_head_t tx_wait_q;
- struct workqueue_struct *workqueue;
- struct sk_buff_head rx_skb_q;
- struct work_struct rx_work;
- struct dma_pool *dma_pool;
- dma_addr_t dma_p_addr;
- void *dma_v_addr;
- dma_addr_t ci_p_addr;
- struct ctx_info *ci;
- struct ia ia;
- struct txq txq;
- struct rxq rxq;
- u32 alive_intr_ctxt;
- };
- static inline u32 btintel_pcie_rd_reg32(struct btintel_pcie_data *data,
- u32 offset)
- {
- return ioread32(data->base_addr + offset);
- }
- static inline void btintel_pcie_wr_reg8(struct btintel_pcie_data *data,
- u32 offset, u8 val)
- {
- iowrite8(val, data->base_addr + offset);
- }
- static inline void btintel_pcie_wr_reg32(struct btintel_pcie_data *data,
- u32 offset, u32 val)
- {
- iowrite32(val, data->base_addr + offset);
- }
- static inline void btintel_pcie_set_reg_bits(struct btintel_pcie_data *data,
- u32 offset, u32 bits)
- {
- u32 r;
- r = ioread32(data->base_addr + offset);
- r |= bits;
- iowrite32(r, data->base_addr + offset);
- }
- static inline void btintel_pcie_clr_reg_bits(struct btintel_pcie_data *data,
- u32 offset, u32 bits)
- {
- u32 r;
- r = ioread32(data->base_addr + offset);
- r &= ~bits;
- iowrite32(r, data->base_addr + offset);
- }
|