/** ****************************************************************************** * * rwnx_cmds.h * * Copyright (C) RivieraWaves 2014-2019 * ****************************************************************************** */ #ifndef _AIC_BSP_DRIVER_H #define _AIC_BSP_DRIVER_H #include #include #include #include "aic_bsp_export.h" #define RWNX_80211_CMD_TIMEOUT_MS 3000//500//300 #define RWNX_CMD_FLAG_NONBLOCK BIT(0) #define RWNX_CMD_FLAG_REQ_CFM BIT(1) #define RWNX_CMD_FLAG_WAIT_PUSH BIT(2) #define RWNX_CMD_FLAG_WAIT_ACK BIT(3) #define RWNX_CMD_FLAG_WAIT_CFM BIT(4) #define RWNX_CMD_FLAG_DONE BIT(5) /* ATM IPC design makes it possible to get the CFM before the ACK, * otherwise this could have simply been a state enum */ #define RWNX_CMD_WAIT_COMPLETE(flags) \ (!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM))) #define RWNX_CMD_MAX_QUEUED 8 #define IPC_E2A_MSG_PARAM_SIZE 256 #define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ /* message levels */ #define LOGERROR 0x0001 #define LOGINFO 0x0002 #define LOGTRACE 0x0004 #define LOGDEBUG 0x0008 #define LOGDATA 0x0010 extern int aicwf_dbg_level_bsp; #define AICWF_LOG "AICWFDBG(" #define AICWFDBG(level, args, arg...) \ do { \ if (aicwf_dbg_level_bsp & level) { \ printk(AICWF_LOG#level")\t" args, ##arg); \ } \ } while (0) #define RWNX_DBG(fmt, ...) \ do { \ if (aicwf_dbg_level_bsp & LOGTRACE) { \ printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \ } \ } while (0) /// Message structure for MSGs from Emb to App struct ipc_e2a_msg { u16 id; ///< Message id. u16 dummy_dest_id; u16 dummy_src_id; u16 param_len; ///< Parameter embedded struct length. u32 pattern; ///< Used to stamp a valid MSG buffer u32 param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned. }; typedef u16 lmac_msg_id_t; typedef u16 lmac_task_id_t; struct lmac_msg { lmac_msg_id_t id; ///< Message id. lmac_task_id_t dest_id; ///< Destination kernel identifier. lmac_task_id_t src_id; ///< Source kernel identifier. u16 param_len; ///< Parameter embedded struct length. u32 param[]; ///< Parameter embedded struct. Must be word-aligned. }; #define rwnx_cmd_e2amsg ipc_e2a_msg #define rwnx_cmd_a2emsg lmac_msg #define RWNX_CMD_A2EMSG_LEN(m) (sizeof(struct lmac_msg) + m->param_len) #define RWNX_CMD_E2AMSG_LEN_MAX (IPC_E2A_MSG_PARAM_SIZE * 4) static inline void put_u16(u8 *buf, u16 data) { buf[0] = (u8)(data&0x00ff); buf[1] = (u8)((data >> 8)&0x00ff); } enum rwnx_cmd_mgr_state { RWNX_CMD_MGR_STATE_DEINIT, RWNX_CMD_MGR_STATE_INITED, RWNX_CMD_MGR_STATE_CRASHED, }; struct rwnx_cmd { struct list_head list; lmac_msg_id_t id; lmac_msg_id_t reqid; struct rwnx_cmd_a2emsg *a2e_msg; char *e2a_msg; u32 tkn; u16 flags; struct completion complete; u32 result; }; struct aic_sdio_dev; struct rwnx_cmd; typedef int (*msg_cb_fct)(struct rwnx_cmd *cmd, struct rwnx_cmd_e2amsg *msg); struct rwnx_cmd_mgr { enum rwnx_cmd_mgr_state state; spinlock_t lock; u32 next_tkn; u32 queue_sz; u32 max_queue_sz; spinlock_t cb_lock; void *sdiodev; struct list_head cmds; int (*queue)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); int (*llind)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); int (*msgind)(struct rwnx_cmd_mgr *, struct rwnx_cmd_e2amsg *, msg_cb_fct); void (*print)(struct rwnx_cmd_mgr *); void (*drain)(struct rwnx_cmd_mgr *); struct work_struct cmdWork; struct workqueue_struct *cmd_wq; }; void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr); void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr); int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd); void rwnx_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len); enum { TASK_NONE = (u8) -1, // MAC Management task. TASK_MM = 0, // DEBUG task TASK_DBG, /// SCAN task TASK_SCAN, /// TDLS task TASK_TDLS, /// SCANU task TASK_SCANU, /// ME task TASK_ME, /// SM task TASK_SM, /// APM task TASK_APM, /// BAM task TASK_BAM, /// MESH task TASK_MESH, /// RXU task TASK_RXU, // This is used to define the last task that is running on the EMB processor TASK_LAST_EMB = TASK_RXU, // nX API task TASK_API, TASK_MAX, }; #define LMAC_FIRST_MSG(task) ((lmac_msg_id_t)((task) << 10)) #define DRV_TASK_ID 100 #define MSG_I(msg) ((msg) & ((1<<10)-1)) #define MSG_T(msg) ((lmac_task_id_t)((msg) >> 10)) enum dbg_msg_tag { /// Memory read request DBG_MEM_READ_REQ = LMAC_FIRST_MSG(TASK_DBG), /// Memory read confirm DBG_MEM_READ_CFM, /// Memory write request DBG_MEM_WRITE_REQ, /// Memory write confirm DBG_MEM_WRITE_CFM, /// Module filter request DBG_SET_MOD_FILTER_REQ, /// Module filter confirm DBG_SET_MOD_FILTER_CFM, /// Severity filter request DBG_SET_SEV_FILTER_REQ, /// Severity filter confirm DBG_SET_SEV_FILTER_CFM, /// LMAC/MAC HW fatal error indication DBG_ERROR_IND, /// Request to get system statistics DBG_GET_SYS_STAT_REQ, /// COnfirmation of system statistics DBG_GET_SYS_STAT_CFM, /// Memory block write request DBG_MEM_BLOCK_WRITE_REQ, /// Memory block write confirm DBG_MEM_BLOCK_WRITE_CFM, /// Start app request DBG_START_APP_REQ, /// Start app confirm DBG_START_APP_CFM, /// Start npc request DBG_START_NPC_REQ, /// Start npc confirm DBG_START_NPC_CFM, /// Memory mask write request DBG_MEM_MASK_WRITE_REQ, /// Memory mask write confirm DBG_MEM_MASK_WRITE_CFM, DBG_RFTEST_CMD_REQ, DBG_RFTEST_CMD_CFM, DBG_BINDING_REQ, DBG_BINDING_CFM, DBG_BINDING_IND, DBG_CUSTOM_MSG_REQ, DBG_CUSTOM_MSG_CFM, DBG_CUSTOM_MSG_IND, DBG_GPIO_WRITE_REQ, DBG_GPIO_WRITE_CFM, /// Max number of Debug messages DBG_MAX, }; enum { HOST_START_APP_AUTO = 1, HOST_START_APP_CUSTOM, HOST_START_APP_FNCALL = 4, HOST_START_APP_DUMMY = 5, }; struct dbg_mem_block_write_req { u32 memaddr; u32 memsize; u32 memdata[1024 / sizeof(u32)]; }; /// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_CFM message. struct dbg_mem_block_write_cfm { u32 wstatus; }; /// Structure containing the parameters of the @ref DBG_MEM_WRITE_REQ message. struct dbg_mem_write_req { u32 memaddr; u32 memdata; }; /// Structure containing the parameters of the @ref DBG_MEM_WRITE_CFM message. struct dbg_mem_write_cfm { u32 memaddr; u32 memdata; }; /// Structure containing the parameters of the @ref DBG_MEM_READ_REQ message. struct dbg_mem_read_req { u32 memaddr; }; /// Structure containing the parameters of the @ref DBG_MEM_READ_CFM message. struct dbg_mem_read_cfm { u32 memaddr; u32 memdata; }; /// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_REQ message. struct dbg_mem_mask_write_req { u32 memaddr; u32 memmask; u32 memdata; }; /// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_CFM message. struct dbg_mem_mask_write_cfm { u32 memaddr; u32 memdata; }; /// Structure containing the parameters of the @ref DBG_START_APP_REQ message. struct dbg_start_app_req { u32 bootaddr; u32 boottype; }; /// Structure containing the parameters of the @ref DBG_START_APP_CFM message. struct dbg_start_app_cfm { u32 bootstatus; }; int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device); int aicwf_patch_table_load(struct aic_sdio_dev *rwnx_hw, char *filename); int rwnx_send_dbg_mem_read_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, struct dbg_mem_read_cfm *cfm); int rwnx_send_dbg_mem_block_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_size, u32 *mem_data); int rwnx_send_dbg_mem_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_data); int rwnx_send_dbg_mem_mask_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_mask, u32 mem_data); int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type, struct dbg_start_app_cfm *start_app_cfm); int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr, const char *filename); void rwnx_rx_handle_msg(struct aic_sdio_dev *sdiodev, struct ipc_e2a_msg *msg); int aicbsp_platform_init(struct aic_sdio_dev *sdiodev); void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev); int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev); #define AICBSP_FW_PATH CONFIG_AIC_FW_PATH #define AICBSP_FW_PATH_MAX 200 #define RAM_FMAC_FW_ADDR 0x00120000 #define FW_RAM_ADID_BASE_ADDR 0x00161928 #define FW_RAM_ADID_BASE_ADDR_U03 0x00161928 #define FW_RAM_PATCH_BASE_ADDR 0x00100000 #define RAM_8800DC_U01_ADID_ADDR 0x00101788 #define RAM_8800DC_U02_ADID_ADDR 0x001017d8 #define RAM_8800DC_FW_PATCH_ADDR 0x00184000 #define FW_RESET_START_ADDR 0x40500128 #define FW_RESET_START_VAL 0x40 #define FW_ADID_FLAG_ADDR 0x40500150 #define FW_ADID_FLAG_VAL 0x01 #define FW_RAM_ADID_BASE_ADDR_8800D80 0x002017E0 #define FW_RAM_PATCH_BASE_ADDR_8800D80 0x0020B2B0 #define FW_RAM_ADID_BASE_ADDR_8800D80_U02 0x00201940 #define FW_RAM_PATCH_BASE_ADDR_8800D80_U02 0x0020b43c #define AICBT_PT_TAG "AICBT_PT_TAG" /***************************************************************************** * Addresses within RWNX_ADDR_CPU *****************************************************************************/ #define RAM_LMAC_FW_ADDR 0x00150000 #define ROM_FMAC_FW_ADDR 0x00010000 #define ROM_FMAC_PATCH_ADDR 0x00180000 #define RWNX_MAC_FW_RF_BASE_NAME_8800DC "lmacfw_rf_8800dc.bin" #ifdef CONFIG_FOR_IPCOM #define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc_ipc" #define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin" #else #define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc" #define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin" #define RWNX_MAC_PATCH_NAME2_8800DC_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_u02.bin" #endif #define RWNX_MAC_PATCH_TABLE_NAME_8800DC "fmacfw_patch_tbl_8800dc" #define RWNX_MAC_PATCH_TABLE_8800DC RWNX_MAC_PATCH_TABLE_NAME_8800DC ".bin" #define RWNX_MAC_PATCH_TABLE_8800DC_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_u02.bin" #define RWNX_MAC_RF_PATCH_BASE_NAME_8800DC "fmacfw_rf_patch_8800dc" #define RWNX_MAC_RF_PATCH_NAME_8800DC RWNX_MAC_RF_PATCH_BASE_NAME_8800DC".bin" #define FW_USERCONFIG_NAME_8800DC "aic_userconfig_8800dc.txt" enum aicbt_patch_table_type { AICBT_PT_INF = 0x00, AICBT_PT_TRAP = 0x1, AICBT_PT_B4, AICBT_PT_BTMODE, AICBT_PT_PWRON, AICBT_PT_AF, AICBT_PT_VER, }; enum aicbt_btport_type { AICBT_BTPORT_NULL, AICBT_BTPORT_MB, AICBT_BTPORT_UART, }; /* btmode * used for force bt mode,if not AICBSP_MODE_NULL * efuse valid and vendor_info will be invalid, even has beed set valid */ enum aicbt_btmode_type { AICBT_BTMODE_BT_ONLY_SW = 0x0, // bt only mode with switch AICBT_BTMODE_BT_WIFI_COMBO, // wifi/bt combo mode AICBT_BTMODE_BT_ONLY, // bt only mode without switch AICBT_BTMODE_BT_ONLY_TEST, // bt only test mode AICBT_BTMODE_BT_WIFI_COMBO_TEST, // wifi/bt combo test mode AICBT_BTMODE_BT_ONLY_COANT, // bt only mode with no external switch AICBT_MODE_NULL = 0xFF, // invalid value }; /* uart_baud * used for config uart baud when btport set to uart, * otherwise meaningless */ enum aicbt_uart_baud_type { AICBT_UART_BAUD_115200 = 115200, AICBT_UART_BAUD_921600 = 921600, AICBT_UART_BAUD_1_5M = 1500000, AICBT_UART_BAUD_3_25M = 3250000, }; enum aicbt_uart_flowctrl_type { AICBT_UART_FLOWCTRL_DISABLE = 0x0, // uart without flow ctrl AICBT_UART_FLOWCTRL_ENABLE, // uart with flow ctrl }; enum aicbsp_cpmode_type { AICBSP_CPMODE_WORK, AICBSP_CPMODE_TEST, AICBSP_CPMODE_MAX, }; enum chip_rev { CHIP_REV_U01 = 1, CHIP_REV_U02 = 3, CHIP_REV_U03 = 7, CHIP_REV_U04 = 7, }; ///aic bt tx pwr lvl :lsb->msb: first byte, min pwr lvl; second byte, max pwr lvl; ///pwr lvl:20(min), 30 , 40 , 50 , 60(max) #define AICBT_TXPWR_LVL 0x00006020 #define AICBT_TXPWR_LVL_8800dc 0x00006f2f #define AICBT_TXPWR_LVL_8800d80 0x00006f2f #define AICBSP_HWINFO_DEFAULT (-1) #define AICBSP_CPMODE_DEFAULT AICBSP_CPMODE_WORK #define AICBSP_FWLOG_EN_DEFAULT 0 #define AICBT_BTMODE_DEFAULT AICBT_BTMODE_BT_ONLY_SW #define AICBT_BTPORT_DEFAULT AICBT_BTPORT_UART #define AICBT_UART_BAUD_DEFAULT AICBT_UART_BAUD_1_5M #define AICBT_UART_FC_DEFAULT AICBT_UART_FLOWCTRL_ENABLE #define AICBT_LPM_ENABLE_DEFAULT 0 #define AICBT_TXPWR_LVL_DEFAULT AICBT_TXPWR_LVL #define FEATURE_SDIO_CLOCK 50000000 // 0: default, other: target clock rate #define FEATURE_SDIO_CLOCK_V3 150000000 // 0: default, other: target clock rate #define FEATURE_SDIO_PHASE 2 // 0: default, 2: 180° struct aicbt_patch_table { char *name; uint32_t type; uint32_t *data; uint32_t len; struct aicbt_patch_table *next; }; struct aicbt_info_t { uint32_t btmode; uint32_t btport; uint32_t uart_baud; uint32_t uart_flowctrl; uint32_t lpm_enable; uint32_t txpwr_lvl; }; struct aicbt_patch_info_t { uint32_t info_len; uint32_t adid_addrinf; uint32_t addr_adid; uint32_t patch_addrinf; uint32_t addr_patch; uint32_t reset_addr; uint32_t reset_val; uint32_t adid_flag_addr; uint32_t adid_flag; }; struct aicbsp_firmware { const char *desc; const char *bt_adid; const char *bt_patch; const char *bt_table; const char *wl_fw; }; struct aicbsp_info_t { int hwinfo; int hwinfo_r; uint32_t cpmode; uint32_t chip_rev; bool fwlog_en; }; extern struct aicbsp_info_t aicbsp_info; extern struct mutex aicbsp_power_lock; extern const struct aicbsp_firmware *aicbsp_firmware_list; extern const struct aicbsp_firmware fw_u02[]; extern const struct aicbsp_firmware fw_u03[]; extern const struct aicbsp_firmware fw_8800dc_u01[]; extern const struct aicbsp_firmware fw_8800dc_u02[]; extern const struct aicbsp_firmware fw_8800d80_u01[]; extern const struct aicbsp_firmware fw_8800d80_u02[]; #endif