/* * Copyright (c) 2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _BT_H #define _BT_H #include #include #include #include #include #include #include #include #include #include #define PAS_ID 0xC #define CMD_ID 0x14 #define BT_M0_WARM_RST_ORIDE 0x0 #define BT_M0_WARM_RST 0x4 #define IOCTL_IPC_BOOT 0xBE #define IPC_TX_QSIZE 0x20 #define TO_APPS_ADDR(a) (btmem->virt + (int)(uintptr_t)a) #define TO_BT_ADDR(a) (a - btmem->virt) #define IPC_LBUF_SZ(w, x, y, z) (((TO_BT_ADDR((void *)w) + w->x) - w->y) / w->z) #define IPC_MSG_HDR_SZ (4u) #define IPC_MSG_PLD_SZ (40u) #define IPC_TOTAL_MSG_SZ (IPC_MSG_HDR_SZ + IPC_MSG_PLD_SZ) #define IPC_LMSG_MASK (0x8000u) #define IPC_RACK_MASK (0x4000u) #define IPC_PKT_TYPE_MASK (0x0300u) #define IPC_MSG_ID_MASK (0x00FFu) #define IPC_LMSG_TYPE ((uint16_t) IPC_LMSG_MASK) #define IPC_SMSG_TYPE ((uint16_t) 0x0000u) #define IPC_REQ_ACK ((uint16_t) IPC_RACK_MASK) #define IPC_NO_ACK ((uint16_t) 0x0000u) #define IPC_PKT_TYPE_CUST ((uint16_t) 0x0000u) #define IPC_PKT_TYPE_HCI ((uint16_t) 0x0100u) #define IPC_PKT_TYPE_AUDIO ((uint16_t) 0x0200u) #define IPC_PKT_TYPE_RFU (IPC_PKT_TYPE_MASK) #define IPC_LMSG_SHIFT (15u) #define IPC_RACK_SHIFT (14u) #define IPC_PKT_TYPE_SHIFT (8u) #define GET_NO_OF_BLOCKS(a, b) ((a + b - 1) / b) #define GET_RX_INDEX_FROM_BUF(x, y) ((x - btmem->rx_ctxt->lring_buf) / y) #define GET_TX_INDEX_FROM_BUF(x, y) ((x - btmem->tx_ctxt->lring_buf) / y) #define IS_RX_MEM_NON_CONTIGIOUS(pBuf, len, sz) \ ((pBuf + len) > \ (btmem->rx_ctxt->lring_buf + \ (sz * btmem->rx_ctxt->lmsg_buf_cnt))) /** Message header format. * * --------------------------------------------------------------- * BitPos | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 - 0 | * --------------------------------------------------------------- * Field | Long Msg |rAck| RFU | PktType | msgID | * --------------------------------------------------------------- * * - Long Msg : * * - reqAck : This is interpreted by receiver for sending acknowledegement * to sender i.e. send a ack IPC interrupt if set. * Use @ref IS_REQ_ACK or @ref IS_NO_ACK * to determine ack is requested or not. * * - RFU : Reserved for future use. * * - pktType : * * - msgID : Contains unique message ID within a Category. * Use @ref IPC_GET_MSG_ID to get message ID. */ #define IPC_ConstructMsgHeader(msgID, reqAck, pktType, longMsg) \ (((uint8_t) longMsg << IPC_LMSG_SHIFT) | \ ((uint8_t) reqAck << IPC_RACK_SHIFT) | \ ((uint16_t) pktType << IPC_PKT_TYPE_SHIFT) | msgID) #define IPC_GET_PKT_TYPE(hdr) \ ((enum ipc_pkt_type)((hdr & IPC_PKT_TYPE_MASK) >> IPC_PKT_TYPE_SHIFT)) #define IS_LONG_MSG(hdr) ((hdr & IPC_LMSG_MASK) == IPC_LMSG_TYPE) #define IS_SHORT_MSG(hdr) ((hdr & IPC_LMSG_MASK) == IPC_SMSG_TYPE) #define IS_REQ_ACK(hdr) ((hdr & IPC_RACK_MASK) == IPC_REQ_ACK) #define IS_NO_ACK(hdr) ((hdr & IPC_RACK_MASK) == IPC_NO_ACK) #define IS_HCI_PKT(hdr) ((hdr & IPC_PKT_TYPE_MASK) == IPC_PKT_TYPE_HCI) #define IS_CUST_PKT(hdr) ((hdr & IPC_PKT_TYPE_MASK) == IPC_PKT_TYPE_CUST) #define IPC_GET_MSG_ID(hdr) ((uint8_t)(hdr & IPC_MSG_ID_MASK)) #define IPC_CMD_IPC_STOP (0x01) #define IPC_CMD_SWITCH_TO_UART (0x02) #define IPC_CMD_PREPARE_DUMP (0x03) #define IPC_CMD_COLLECT_DUMP (0x04) #define IPC_CMD_IPC_START (0x05) /*------------------------------------------------------------------------- * Type Declarations * ------------------------------------------------------------------------ */ enum ipc_pkt_type { IPC_CUST_PKT, IPC_HCI_PKT, IPC_AUDIO_PKT, IPC_PKT_MAX }; struct long_msg_info { uint16_t smsg_free_cnt; uint16_t lmsg_free_cnt; uint8_t ridx; uint8_t widx; }; struct ipc_aux_ptr { uint32_t len; uint32_t buf; }; struct ring_buffer { uint16_t msg_hdr; uint16_t len; union { uint8_t smsg_data[IPC_MSG_PLD_SZ]; uint32_t lmsg_data; } payload; }; struct ring_buffer_info { uint32_t rbuf; uint8_t ring_buf_cnt; uint8_t ridx; uint8_t widx; uint8_t tidx; uint32_t next; }; struct context_info { uint16_t TotalMemorySize; uint8_t lmsg_buf_cnt; uint8_t smsg_buf_cnt; struct ring_buffer_info sring_buf_info; uint32_t sring_buf; uint32_t lring_buf; uint32_t reserved; }; struct bt_mem { phys_addr_t phys; phys_addr_t reloc; void __iomem *virt; size_t size; struct context_info *tx_ctxt; struct context_info *rx_ctxt; struct long_msg_info lmsg_ctxt; }; struct bt_ipc { struct regmap *regmap; int offset; int bit; int irq; struct list_head tx_q; struct workqueue_struct *wq; struct work_struct work; wait_queue_head_t wait_q; atomic_t tx_q_cnt; }; struct bt_descriptor { struct tty_driver *tty_drv; struct tty_port tty_port; struct reserved_mem *rmem; const char *fw_name; struct platform_device *pdev; void __iomem *warm_reset; struct bt_ipc ipc; struct bt_mem btmem; struct reset_control *btss_reset; struct clk *lpo_clk; struct dentry *dbgfs; struct platform_device *rproc_pdev; int (*sendmsg_cb)(struct bt_descriptor *, unsigned char *, int); void (*recvmsg_cb)(struct bt_descriptor *, unsigned char *, int); spinlock_t lock; atomic_t state; struct notifier_block panic_nb; struct pinctrl *pinctrl; bool debug_en; bool nosecure; }; struct ipc_intent { uint8_t *buf; uint16_t len; struct list_head list; }; extern int bt_ipc_send_msg(struct bt_descriptor *btDesc, uint16_t msg_hdr, const uint8_t *pData, uint16_t len, bool dequeue); extern int bt_ipc_avail_size(struct bt_descriptor *btDesc); extern void bt_ipc_purge_tx_queue(struct bt_descriptor *btDesc); extern int bt_ipc_init(struct bt_descriptor *btDesc); extern void bt_ipc_deinit(struct bt_descriptor *btDesc); extern u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw); #endif /* _BT_H */