diff --git a/bt_kernel_product_board.mk b/bt_kernel_product_board.mk index 15d265662e..50a9ceb200 100644 --- a/bt_kernel_product_board.mk +++ b/bt_kernel_product_board.mk @@ -1,5 +1,6 @@ # Build BT kernel drivers +ifneq ($(TARGET_BOARD_PLATFORM), niobe) PRODUCT_PACKAGES += $(KERNEL_MODULES_OUT)/btpower.ko\ $(KERNEL_MODULES_OUT)/bt_fm_slim.ko \ $(KERNEL_MODULES_OUT)/radio-i2c-rtc6226-qca.ko - +endif diff --git a/bt_kernel_vendor_board.mk b/bt_kernel_vendor_board.mk index 1c8ce659ce..aa6b68370e 100644 --- a/bt_kernel_vendor_board.mk +++ b/bt_kernel_vendor_board.mk @@ -11,10 +11,12 @@ ifeq ($(TARGET_USES_QMAA),true) endif else ifeq ($(call is-board-platform-in-list,$(TARGET_BOARD_PLATFORM)),true) - BT_KERNEL_DRIVER := $(KERNEL_MODULES_OUT)/btpower.ko\ + ifneq ($(TARGET_BOARD_PLATFORM), niobe) + BT_KERNEL_DRIVER := $(KERNEL_MODULES_OUT)/btpower.ko\ $(KERNEL_MODULES_OUT)/bt_fm_slim.ko \ $(KERNEL_MODULES_OUT)/radio-i2c-rtc6226-qca.ko - BOARD_VENDOR_KERNEL_MODULES += $(BT_KERNEL_DRIVER) + BOARD_VENDOR_KERNEL_MODULES += $(BT_KERNEL_DRIVER) + endif endif endif endif diff --git a/btfmcodec/btfm_codec.c b/btfmcodec/btfm_codec.c index 5b62021bd0..90431320ea 100644 --- a/btfmcodec/btfm_codec.c +++ b/btfmcodec/btfm_codec.c @@ -119,9 +119,12 @@ static int btfmcodec_dev_release(struct inode *inode, struct file *file) wake_up_interruptible(&btfmcodec_dev->rsp_wait_q[idx]); } - cancel_work_sync(&btfmcodec_dev->wq_hwep_shutdown); - cancel_work_sync(&btfmcodec_dev->wq_hwep_configure); - cancel_work_sync(&btfmcodec_dev->wq_prepare_bearer); + if (btfmcodec_dev->wq_hwep_shutdown.func) + cancel_work_sync(&btfmcodec_dev->wq_hwep_shutdown); + if (btfmcodec_dev->wq_hwep_configure.func) + cancel_work_sync(&btfmcodec_dev->wq_hwep_configure); + if (btfmcodec_dev->wq_prepare_bearer.func) + cancel_work_sync(&btfmcodec_dev->wq_prepare_bearer); btfmcodec->states.current_state = IDLE; btfmcodec->states.next_state = IDLE; diff --git a/include/btpower.h b/include/btpower.h index 29b5887819..0beb4c4c9c 100644 --- a/include/btpower.h +++ b/include/btpower.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __LINUX_BLUETOOTH_POWER_H @@ -11,14 +11,789 @@ #include #include #include +#include +#include + /* * voltage regulator information required for configuring the * bluetooth chipset */ -enum bt_power_modes { - BT_POWER_DISABLE = 0, - BT_POWER_ENABLE, - BT_POWER_RETENTION + +enum power_modes { + POWER_DISABLE = 0, + POWER_ENABLE, + POWER_RETENTION, + POWER_DISABLE_RETENTION, +}; + +enum SubSystem { + BLUETOOTH = 1, + UWB, +}; + +enum power_states { + IDLE = 0, + BT_ON, + UWB_ON, + ALL_CLIENTS_ON, +}; + +enum retention_states { + /* Default state */ + RETENTION_IDLE = 0, + /* When BT is only client and it is in retention_state */ + BT_IN_RETENTION, + /* BT is retention mode and UWB powered ON triggered */ + BT_OUT_OF_RETENTION, + /* When UWB is only client and it is in retention_state */ + UWB_IN_RETENTION, + /* UWB is retention mode and BT powered ON triggered */ + UWB_OUT_OF_RETENTION, + /* Both clients are voted for retention */ + BOTH_CLIENTS_IN_RETENTION, +}; + +enum grant_return_values { + ACCESS_GRANTED = 0, + ACCESS_DENIED = 1, + ACCESS_RELEASED = 2, + ACCESS_DISALLOWED = -1, +}; + +enum grant_states { + /* Default state */ + NO_GRANT_FOR_ANY_SS = 0, + NO_OTHER_CLIENT_WAITING_FOR_GRANT, + BT_HAS_GRANT, + UWB_HAS_GRANT, + BT_WAITING_FOR_GRANT, + UWB_WAITING_FOR_GRANT, +}; + +static inline char *ConvertGrantRetToString(enum grant_return_values state) +{ + switch (state) { + case ACCESS_GRANTED: + return "ACCESS_GRANTED"; + case ACCESS_DENIED: + return "ACCESS_DENIED"; + case ACCESS_RELEASED: + return "ACCESS_RELEASED"; + case ACCESS_DISALLOWED: + return "ACCESS_DISALLOWED"; + default: + return "INVALID State"; + } +} + +static inline char *ConvertGrantToString(enum grant_states state) +{ + switch (state) { + case NO_GRANT_FOR_ANY_SS: + return "NO_GRANT_FOR_ANY_SS"; + case NO_OTHER_CLIENT_WAITING_FOR_GRANT: + return "NO_OTHER_CLIENT_WAITING_FOR_GRANT"; + case BT_HAS_GRANT : + return "BT_HAS_GRANT"; + case UWB_HAS_GRANT: + return "UWB_HAS_GRANT"; + case BT_WAITING_FOR_GRANT : + return "BT_WAITING_FOR_GRANT"; + case UWB_WAITING_FOR_GRANT: + return "UWB_WAITING_FOR_GRANT"; + default: + return "INVALID STATE"; + } +} + +enum cores { + BT_CORE = 0, + UWB_CORE, + PLATFORM_CORE +}; + +enum ssr_states { + SUB_STATE_IDLE = 0, + SSR_ON_BT, + BT_SSR_COMPLETED, + SSR_ON_UWB, + UWB_SSR_COMPLETED, + REG_BT_PID, + REG_UWB_PID, +}; + +enum plt_pwr_state { + POWER_ON_BT = 0, + POWER_OFF_BT, + POWER_ON_UWB, + POWER_OFF_UWB, + POWER_ON_BT_RETENION, + POWER_ON_UWB_RETENION, + BT_ACCESS_REQ, + UWB_ACCESS_REQ, + BT_RELEASE_ACCESS, + UWB_RELEASE_ACCESS, + BT_MAX_PWR_STATE, +}; + +enum { + PWR_WAITING_RSP = -2, + PWR_RSP_RECV = 0, + PWR_FAIL_RSP_RECV = -1, + PWR_CLIENT_KILLED, +}; + +enum BtPrimaryReasonCode { + BT_DEFAULT_NONE = 0x00, //INVALID REASON + BT_SOC_CRASHED = 0x01, //SOC WAS CRASHED + BT_SOC_CRASHED_DIAG_SSR = 0x02, //SOC CRASHED DIAG INITIATED SSR + BT_INIT_FAILED = 0x03, //HOST INITIALIZATION FAILED + BT_CLOSE_RCVD_DURING_INIT = 0x04, //CLOSE RECEIVED FROM STACK DURING SOC INIT + BT_ERROR_READING_DATA_FROM_UART = 0x05, //ERROR READING DATA FROM UART + BT_WRITE_FAIL_SPCL_BUFF_CRASH_SOC = 0x06, //FAILED TO WRITE SPECIAL BYTES TO CRASH SOC + BT_RX_THREAD_STUCK = 0x07, //RX THREAD STUCK + BT_SSR_CMD_TIMEDOUT = 0x08, //SSR DUE TO CMD TIMED OUT + BT_SSR_SPURIOUS_WAKEUP = 0x09, //SSR DUE TO SPURIOUS WAKE UP + BT_SSR_INVALID_BYTES_RCVD = 0x0A, //INVALID HCI CMD TYPE RECEIVED + BT_SSR_RCVD_LARGE_PKT_FROM_SOC = 0x0B, //SSR DUE TO LARGE PKT RECVIVED FROM SOC + BT_SSR_UNABLE_TO_WAKEUP_SOC = 0x0C, //UNABLE TO WAKE UP SOC + BT_CMD_TIMEDOUT_SOC_WAIT_TIMEOUT = 0x0D, //COMMAND TIMEOUT AND SOC CRASH WAIT TIMEOUT + BT_SPURIOUS_WAKEUP_SOC_WAIT_TIMEOUT = 0x0E, //SPURIOUS WAKE AND SOC CRASH WAIT TIMEOUT + BT_INV_BYTES_SOC_WAIT_TIMEOUT = 0x0F, //INVALID BYTES AND SOC CRASH WAIT TIMEOUT + BT_SOC_WAKEUP_FAILED_SOC_WAIT_TIMEOUT = 0x10, //SOC WAKEUP FAILURE AND SOC CRASH WAIT TIMEOUT + BT_SOC_CRASHED_DIAG_SSR_SOC_WAIT_TIMEOUT = 0x11, //SOC CRASHED DIAG INITIATED SSR CRASH WAIT TIMEOUT + BT_NONE_SOC_WAIT_TIMEOUT = 0x12, //INVALID FAILURE AND SOC CRASH WAIT TIMEOUT + BT_SOC_DEINIT_STUCK = 0x13, //SOC DEINIT STUCK + BT_SSR_INTERNAL_CMD_TIMEDOUT = 0x14, //SSR DUE TO CMD INTERNAL TIMED OUT + BT_FAILED_TO_SEND_INTERNAL_CMD = 0x15, //FAILED TO SEND INTERNAL CMD + BT_SSR_SLEEP_IND_NOT_RCVD = 0x16, //SOC DID NOT RCVD SLEEP IND DURING CLOSE + BT_DIAG_LOG_API_STUCK = 0x39, //DIAG log API stuck. + BT_PERI_SOC_CRASHED_DIAG_SSR = 0x17, //PERI SOC CRASHED DIAG INITIATED SSR + BT_PERI_SOC_CRASHED = 0X18, //PERI SOC WAS CRASHED + BT_PERI_SOC_CRASHED_ON_OTHER_SUB_SYSTEM = 0x3A, //Peripheral core crash detected in UWB SS + BT_PERI_SUB_SYSTEM_FAILED_UPDATE_SSR_COMPLETE = 0x3B // UWB FAILED TO UPDATE THE SSR COMPLETE STATUS +}; + +enum BtSecondaryReasonCode { + BT_SOC_REASON_DEFAULT = 0x00, + BT_SOC_REASON_UNKNOWN = 0x81, + BT_SOC_REASON_SW_REQUESTED = 0x82, + BT_SOC_REASON_STACK_OVERFLOW = 0x83, + BT_SOC_REASON_EXCEPTION = 0x84, + BT_SOC_REASON_ASSERT = 0x85, + BT_SOC_REASON_TRAP = 0x86, + BT_SOC_REASON_OS_FATAL = 0x87, + BT_SOC_REASON_HCI_RESET = 0x88, + BT_SOC_REASON_PATCH_RESET = 0x89, + BT_SOC_REASON_ABT = 0x8A, + BT_SOC_REASON_RAMMASK = 0x8B, + BT_SOC_REASON_PREBARK = 0x8C, + BT_SOC_REASON_BUSERROR = 0x8D, + BT_SOC_REASON_IO_FATAL = 0x8E, + BT_SOC_REASON_SSR_CMD = 0x8F, + BT_SOC_REASON_POWERON = 0x90, + BT_SOC_REASON_WATCHDOG = 0x91, + BT_SOC_REASON_RAMMASK_RGN1 = 0x92, + BT_SOC_REASON_RAMMASK_RGN0 = 0x93, + BT_SOC_REASON_Q6_WATCHDOG = 0x94, + BT_SOC_REASON_ZEALIS_RAM_MASK_RGN0 = 0x95, + BT_SOC_REASON_ZEALIS_RAM_MASK_RGN1 = 0x96, + BT_SOC_REASON_APSS_RESET = 0x97, + BT_SOC_REASON_TIME_RESET = 0x98, + BT_SOC_REASON_AUDIOSS_RESET = 0x99, + BT_SOC_REASON_HOST_WARMRESET = 0x9A, + BT_SOC_REASON_HOST_NMI_INIT = 0x9B, + BT_SOC_REASON_PANIC_FAULT = 0x9C, + BT_SOC_REASON_EARLY_TRAP = 0x9D, + BT_SOC_REASON_INSTR_ADDR_MISALIGN = 0x9E, + BT_SOC_REASON_INSTR_ACCESS_FAULT = 0x9F, + BT_SOC_REASON_ILLEGAL_INSTR = 0xA0, + BT_SOC_REASON_BREAKPOINT_EXCEPTION = 0xA1, + BT_SOC_REASON_LOAD_ADDR_MISALIGN = 0xA2, + BT_SOC_REASON_LOAD_ACCESS_FAULT = 0xA3, + BT_SOC_REASON_STORE_ADDR_MISALIGN = 0xA4, + BT_SOC_REASON_STORE_ACCESS_FAULT = 0xA5, + BT_SOC_REASON_ECALL_UMODE = 0xA6, + BT_SOC_REASON_ECALL_MMODE = 0xA7, + BT_SOC_REASON_STACK_UNDERFLOW = 0xA8, + BT_SOC_REASON_MACHINE_EXT_INT = 0xA9, + BT_SOC_REASON_PERF_MONITOR_OVERFLOW= 0xAA, + BT_SOC_REASON_EXT_SUBSYS_RESET = 0xAB, + BT_SOC_REASON_IPC_STALL = 0xAC, + BT_SOC_REASON_PEER_CPU0_NMI = 0xAD, + BT_SOC_REASON_PEER_CPU1_NMI = 0xAE, + BT_SOC_REASON_PEER_CPU2_NMI = 0xAF, + BT_SOC_REASON_TX_RX_INVALID_PKT_FATAL = 0xC0, + BT_SOC_REASON_TX_RX_INVALID_LEN_FATAL = 0xC1, + BT_SOC_REASON_INVALID_STACK = 0xF0, + BT_SOC_REASON_INVALID_MCI_MSG_RCVD = 0xF1, + BT_HOST_REASON_UARTINIT_STUCK = 0x17, + BT_HOST_REASON_GETVER_SEND_STUCK = 0x18, + BT_HOST_REASON_GETVER_NO_RSP_RCVD = 0x19, + BT_HOST_REASON_SETBAUDRATE_CMD_STUCK = 0x1A, + BT_HOST_REASON_PATCH_DNLD_STUCK = 0x1B, + BT_HOST_REASON_GETBOARDID_CMD_STUCK = 0x1C, + BT_HOST_REASON_NVM_DNLD_STUCK = 0x1D, + BT_HOST_REASON_HCI_RESET_STUCK = 0x1E, + BT_HOST_REASON_GETBLDINFO_CMD_STUCK = 0x1F, + BT_HOST_REASON_ADDONFEAT_CMD_STUCK = 0x20, + BT_HOST_REASON_ENHLOG_CMD_STUCK = 0x21, + BT_HOST_REASON_DIAGINIT_STUCK = 0x22, + BT_HOST_REASON_DIAGDEINIT_STUCK = 0x23, + BT_HOST_REASON_XMEM_NVM_DNLD_STUCK = 0x24, + BT_HOST_REASON_XMEM_PATCH_DNLD_STUCK = 0x25, + BT_HOST_REASON_SECURE_BRIDGE_CMD_STUCK = 0x26, + BT_HOST_REASON_FAILED_TO_SEND_CMD = 0x27, + BT_HOST_REASON_HCI_RESET_CC_NOT_RCVD = 0x28, + BT_HOST_REASON_HCI_PRE_SHUTDOWN_CC_NOT_RCVD = 0x29, + BT_HOST_REASON_HCI_SET_BD_ADDRESS_CC_NOT_RCVD = 0x2A, + BT_HOST_REASON_FAILED_TO_RECEIVE_SLEEP_IND = 0x2B, + BT_HOST_REASON_POWER_ON_REGS_STUCK = 0x2C, + BT_HOST_REASON_RX_THREAD_START_STUCK = 0x2D, + BT_HOST_REASON_GET_LOCALADDR_STUCK = 0x2E, + BT_HOST_REASON_OTP_INFO_GET_CMD_STUCK = 0x2F, + BT_HOST_REASON_FILE_SYSTEM_CALL_STUCK = 0x30, + BT_HOST_REASON_PROPERTY_GET_STUCK = 0x31, + BT_HOST_REASON_PROPERTY_SET_STUCK = 0x32, + BT_HOST_REASON_RAM_PATCH_READ_STUCK = 0x33, + BT_HOST_REASON_NVM_PATCH_READ_STUCK = 0x34, + BT_HOST_REASON_UART_IOCTL_STUCK = 0x35, + BT_HOST_REASON_POWER_IOCTL_STUCK = 0x36, + BT_HOST_REASON_PATCH_CONFIG_CMD_STUCK = 0x37, + BT_HOST_REASON_GET_APP_VER_CMD_STUCK = 0x38, + BT_HOST_REASON_SOC_NAME_UNKOWN = 0x3A, + SOC_REASON_START_TX_IOS_SOC_RFR_HIGH_DURING_INIT = 0x3B, + BT_HOST_REASON_GETVER_CMD_FAILED = 0x3C, + BT_HOST_REASON_BAUDRATE_CHANGE_FAILED = 0x3D, + BT_HOST_REASON_TLV_DOWNLOAD_FAILED = 0x3E, + BT_HOST_REASON_FW_BUILD_INFO_CMD_FAILED = 0x3F, + BT_HOST_REASON_HCI_RESET_CMD_FAILED = 0x40, + BT_HOST_REASON_UART_INIT_FAILED = 0x41, + BT_HOST_REASON_MEMORY_ALLOCATION_FAILED = 0x42, + BT_HOST_REASON_READ_THREAD_START_FAILED = 0x43, + BT_HOST_REASON_HW_FLOW_ON_FAILED = 0x44, + BT_HOST_REASON_NVM_FILE_NOT_FOUND = 0x45, + BT_HOST_REASON_UART_BAUDRATE_CHANGE_FAILED = 0x46, + BT_HOST_REASON_PATCH_CONFIG_FAILED = 0x47, + BT_HOST_REASON_HCI_SET_OFFLOAD_HOST_CONFIG_CC_NOT_RCVD = 0x48, + BT_HOST_REASON_BT_EN_PIN_LOW = 0x49, + UART_REASON_DEFAULT = 0x51, + UART_REASON_INVALID_FW_LOADED = 0x52, + UART_REASON_CLK_GET_FAIL = 0x53, + UART_REASON_SE_CLK_RATE_FIND_FAIL = 0x54, + UART_REASON_SE_RESOURCES_INIT_FAIL = 0x55, + UART_REASON_SE_RESOURCES_ON_FAIL = 0x56, + UART_REASON_SE_RESOURCES_OFF_FAIL = 0x57, + UART_REASON_TX_DMA_MAP_FAIL = 0x58, + UART_REASON_TX_CANCEL_FAIL = 0x59, + UART_REASON_TX_ABORT_FAIL = 0x5A, + UART_REASON_TX_FSM_RESET_FAIL = 0x5B, + UART_REASON_RX_CANCEL_FAIL = 0x5C, + UART_REASON_RX_ABORT_FAIL = 0x5D, + UART_REASON_RX_FSM_RESET_FAIL = 0x5E, + UART_REASON_RX_TTY_INSET_FAIL = 0x5F, + UART_REASON_ILLEGAL_INTERRUPT = 0x60, + UART_REASON_BUFFER_OVERRUN = 0x61, + UART_REASON_RX_PARITY_REASON = 0x62, + UART_REASON_RX_BREAK_REASON = 0x63, + UART_REASON_RX_SBE_REASON = 0x64, + SOC_REASON_START_TX_IOS_SOC_RFR_HIGH = 0x65, + UART_REASON_FLOW_OFF = 0x66, + BT_HOST_REASON_PERI_ARBITRATION_CMD_STUCK = 0x67, + BT_HOST_REASON_PERI_ARBITRATION_NTF_STUCK = 0x68, + BT_HOST_REASON_BT_ACTIVATE_NTF_STUCK = 0x69, + BT_HOST_REASON_PERI_GETVER_SEND_STUCK = 0x6A, + BT_HOST_REASON_PERI_GETBLDINFO_CMD_STUCK = 0x6B, + BT_HOST_REASON_PERI_RAM_PATCH_READ_STUCK = 0x6C, + BT_HOST_REASON_PERI_RESET_STUCK = 0x6D, + BT_HOST_REASON_PERI_PATCH_CONFIG_CMD_STUCK = 0x6E, + BT_HOST_REASON_PERI_PATCH_DNLD_STUCK = 0x6F, + BT_HOST_REASON_PERI_RESET_CMD_FAILED = 0x70, + BT_HOST_REASON_BT_ACTIVATE_CMD_STUCK = 0x71, + BT_HOST_REASON_BT_ACTIVATE_CMD_FAILED = 0x72, + BT_HOST_REASON_PERI_GETVER_CMD_FAILED = 0x73, + BT_HOST_REASON_PERI_PATCH_CONFIG_FAILED = 0x74, + BT_HOST_REASON_PERI_TLV_DOWNLOAD_FAILED = 0x75, + BT_HOST_REASON_PERI_GETBOARDID_CMD_STUCK = 0x76, + BT_HOST_REASON_PERI_NVM_PATCH_READ_STUCK = 0x77, + BT_HOST_REASON_PERI_NVM_FILE_NOT_FOUND = 0x78, + BT_HOST_REASON_PERI_NVM_DNLD_STUCK = 0X79, + BT_HOST_REASON_PERI_GETBLDINFO_CMD_FAILED = 0X7A, + BT_HOST_REASON_PERI_GETVER_NO_RSP_RCVD = 0X7B, + BT_HOST_REASON_PERI_ARB_NOTIFY_FAILED = 0x7C, + BT_HOST_REASON_PERI_SETBAUDRATE_CMD_STUCK = 0x7D, + BT_HOST_REASON_PERI_SETBAUD_CMD_FAILED = 0x7E, + BT_HOST_REASON_MEMORY_ALLOCATION_FAILED_PERI = 0x7F, + BT_HOST_REASON_HCI_ACTIVATE_CC_NOT_RCVD = 0xB0, + BT_HOST_REASON_PERI_FILE_SYSTEM_CALL_STUCK = 0xB1, + BT_HOST_REASON_PERI_POWER_IOCTL_STUCK = 0xB2, + BT_HOST_REASON_PERI_SETBAUD_CC_NOT_RCVD = 0xB3, + BT_HOST_REASON_PERI_ACCESS_STUCK = 0xB4, + BT_HOST_REASON_PERI_ACCESS_DISALLOWED = 0xB5, + PERI_SOC_REASON_DEFAULT = 0xB6 +}; + +enum UwbPrimaryReasonCode{ + UWB_HOST_REASON_DEFAULT_NONE = 0x00, //INVALID REASON + UWB_HOST_REASON_PERI_SOC_CRASHED = 0x01, //PERI SOC WAS CRASHED + UWB_HOST_REASON_PERI_SOC_CRASHED_DIAG_SSR = 0x02, //PERI SOC CRASHED DIAG INITIATED SSR + UWB_HOST_REASON_INIT_FAILED = 0x03, //HOST INITIALIZATION FAILED + UWB_HOST_REASON_CLOSE_RCVD_DURING_INIT = 0x04, //CLOSE RECEIVED FROM STACK DURING SOC INIT + UWB_HOST_REASON_ERROR_READING_DATA_FROM_Q2SPI = 0x05, //ERROR READING DATA FROM Q2SPI + UWB_HOST_REASON_WRITE_FAIL_SPCL_BUFF_CRASH_SOC = 0x06, //FAILED TO WRITE SPECIAL BYTES TO CRASH SOC + UWB_HOST_REASON_RX_THREAD_STUCK = 0x07, //RX THREAD STUCK + UWB_HOST_REASON_SSR_CMD_TIMEDOUT = 0x08, //SSR DUE TO CMD TIMED OUT + UWB_HOST_REASON_SSR_INVALID_BYTES_RCVD = 0x0A, //INVALID HCI CMD TYPE RECEIVED + UWB_HOST_REASON_SSR_RCVD_LARGE_PKT_FROM_SOC = 0x0B, //SSR DUE TO LARGE PKT RECVIVED FROM SOC + UWB_HOST_REASON_SSR_UNABLE_TO_WAKEUP_SOC = 0x0C, //UNABLE TO WAKE UP SOC + UWB_HOST_REASON_CMD_TIMEDOUT_SOC_WAIT_TIMEOUT = 0x0D, //COMMAND TIMEOUT AND SOC CRASH WAIT TIMEOUT + UWB_HOST_REASON_INV_BYTES_SOC_WAIT_TIMEOUT = 0x0F, //INVALID BYTES AND SOC CRASH WAIT TIMEOUT + UWB_HOST_REASON_SOC_WAKEUP_FAILED_SOC_WAIT_TIMEOUT = 0x10, //SOC WAKEUP FAILURE AND SOC CRASH WAIT TIMEOUT + UWB_HOST_REASON_SOC_CRASHED_DIAG_SSR_SOC_WAIT_TIMEOUT = 0x11, //SOC CRASHED DIAG INITIATED SSR CRASH WAIT TIMEOUT + UWB_HOST_REASON_NONE_SOC_WAIT_TIMEOUT = 0x12, //INVALID FAILURE AND SOC CRASH WAIT TIMEOUT + UWB_HOST_REASON_SOC_DEINIT_STUCK = 0x13, //SOC DEINIT STUCK + UWB_HOST_REASON_SSR_INTERNAL_CMD_TIMEDOUT = 0x14, //SSR DUE TO CMD INTERNAL TIMED OUT + UWB_HOST_REASON_FAILED_TO_SEND_INTERNAL_CMD = 0x15, //FAILED TO SEND INTERNAL CMD + UWB_HOST_REASON_SSR_SLEEP_IND_NOT_RCVD = 0x16, //SOC DID NOT RCVD SLEEP IND DURING CLOSE + UWB_HOST_REASON_UWB_SOC_CRASHED = 0xC1, //UWB SOC WAS CRASHED + UWB_HOST_REASON_UWB_SOC_CRASHED_DIAG_SSR = 0xC2, //UWB SOC CRASHED DIAG INITIATED SSR + UWB_HOST_REASON_DIAG_LOG_API_STUCK = 0x39, //DIAG log API stuck. + UWB_HOST_REASON_PERI_CRASH_ON_OTHER_SS = 0x3A, //Peripheral core crash detected in BT SS + UWB_HOST_REASON_CRASH_EVT_INDUCED = 0x60, //Packet Type from SoC for inducing crash +}; + +enum UwbSecondaryReasonCode{ + UWB_SOC_REASON_DEFAULT = 0x00, + UWB_SOC_REASON_TX_RX_INVALID_PKT = 0x40, + UWB_SOC_REASON_TX_RX_INVALID_PKT_LENE = 0x41, + UWB_SOC_REASON_TX_RX_OVERFLOW_BUFF = 0x42, + UWB_SOC_REASON_UNKNOWN = 0x81, + UWB_SOC_REASON_SW_REQUESTED = 0x82, + UWB_SOC_REASON_STACK_OVERFLOW = 0x83, + UWB_SOC_REASON_EXCEPTION = 0x84, + UWB_SOC_REASON_ASSERT = 0x85, + UWB_SOC_REASON_TRAP = 0x86, + UWB_SOC_REASON_OS_FATAL = 0x87, + UWB_SOC_REASON_HCI_RESET = 0x88, + UWB_SOC_REASON_PATCH_RESET = 0x89, + UWB_SOC_REASON_ABT = 0x8A, + UWB_SOC_REASON_RAMMASK = 0x8B, + UWB_SOC_REASON_PREBARK = 0x8C, + UWB_SOC_REASON_BUSERROR = 0x8D, + UWB_SOC_REASON_IO_FATAL = 0x8E, + UWB_SOC_REASON_SSR_CMD = 0x8F, + UWB_SOC_REASON_POWERON = 0x90, + UWB_SOC_REASON_WATCHDOG = 0x91, + UWB_SOC_REASON_RAMMASK_RGN1 = 0x92, + UWB_SOC_REASON_RAMMASK_RGN0 = 0x93, + UWB_SOC_REASON_Q6_WATCHDOG = 0x94, + UWB_SOC_REASON_ZEALIS_RAM_MASK_RGN0 = 0x95, + UWB_SOC_REASON_ZEALIS_RAM_MASK_RGN1 = 0x96, + UWB_SOC_REASON_APSS_RESET = 0x97, + UWB_SOC_REASON_TIME_RESET = 0x98, + UWB_SOC_REASON_AUDIOSS_RESET = 0x99, + UWB_SOC_REASON_HOST_WARMRESET = 0x9A, + UWB_SOC_REASON_HOST_NMI_INIT = 0x9B, + UWB_SOC_REASON_TX_RX_INVALID_PKT_FATAL = 0xC0, + UWB_SOC_REASON_TX_RX_INVALID_LEN_FATAL = 0xC1, + UWB_SOC_REASON_TX_RX_OVERFLOW_FATAL = 0xC2, + UWB_SOC_REASON_INVALID_STACK = 0xF0, + UWB_HOST_REASON_PERI_GETVER_SEND_STUCK = 0x18, + UWB_HOST_REASON_PERI_GETVER_NO_RSP_RCVD = 0x19, + UWB_HOST_REASON_PERI_PATCH_DNLD_STUCK = 0x1B, + UWB_HOST_REASON_PERI_GETBOARDID_CMD_STUCK = 0x1C, + UWB_HOST_REASON_PERI_NVM_DNLD_STUCK = 0x1D, + UWB_HOST_REASON_PERI_RESET_STUCK = 0x1E, + UWB_HOST_REASON_PERI_GETBLDINFO_CMD_STUCK = 0x1F, + UWB_HOST_REASON_PERI_ENHLOG_CMD_STUCK = 0x21, + UWB_HOST_REASON_DIAGINIT_STUCK = 0x22, + UWB_HOST_REASON_DIAGDEINIT_STUCK = 0x23, + UWB_HOST_REASON_SECURE_BRIDGE_CMD_STUCK = 0x26, + UWB_HOST_REASON_FAILED_TO_SEND_CMD = 0x27, + UWB_HOST_REASON_PERI_RESET_CC_NOT_RCVD = 0x28, + UWB_HOST_REASON_HCI_PRE_SHUTDOWN_CC_NOT_RCVD = 0x29, + UWB_HOST_REASON_FAILED_TO_RECEIVE_SLEEP_IND = 0x2B, + UWB_HOST_REASON_POWER_ON_REGS_STUCK = 0x2C, + UWB_HOST_REASON_RX_THREAD_START_STUCK = 0x2D, + UWB_HOST_REASON_GET_LOCALADDR_STUCK = 0x2E, + UWB_HOST_REASON_OTP_INFO_GET_CMD_STUCK = 0x2F, + UWB_HOST_REASON_FILE_SYSTEM_CALL_STUCK = 0x30, + UWB_HOST_REASON_PROPERTY_GET_STUCK = 0x31, + UWB_HOST_REASON_PROPERTY_SET_STUCK = 0x32, + UWB_HOST_REASON_PERI_RAM_PATCH_READ_STUCK = 0x33, + UWB_HOST_REASON_PERI_NVM_PATCH_READ_STUCK = 0x34, + UWB_HOST_REASON_POWER_IOCTL_STUCK = 0x36, + UWB_HOST_REASON_PERI_PATCH_CONFIG_CMD_STUCK = 0x37, + UWB_HOST_REASON_PERI_PATCH_CONFIG_FAILED = 0x38, + UWB_HOST_REASON_UWB_GETVER_SEND_STUCK = 0x39, + UWB_HOST_REASON_UWB_GETVER_NO_RSP_RCVD = 0x3A, + UWB_HOST_REASON_SOC_NAME_UNKOWN = 0x3B, + UWB_HOST_REASON_PERI_GETVER_CMD_FAILED = 0x3C, + UWB_HOST_REASON_BAUDRATE_CHANGE_FAILED = 0x3D, + UWB_HOST_REASON_PERI_TLV_DOWNLOAD_FAILED = 0x3E, + UWB_HOST_REASON_PERI_GETBLDINFO_CMD_FAILED = 0x3F, + UWB_HOST_REASON_PERI_RESET_CMD_FAILED = 0x40, + UWB_HOST_REASON_MEMORY_ALLOCATION_FAILED = 0x42, + UWB_HOST_REASON_READ_THREAD_START_FAILED = 0x43, + UWB_HOST_REASON_HW_FLOW_ON_FAILED = 0x44, + UWB_HOST_REASON_PERI_NVM_FILE_NOT_FOUND = 0x45, + UWB_HOST_REASON_UWB_RAM_PATCH_READ_STUCK = 0x48, + UWB_HOST_REASON_UWB_NVM_PATCH_READ_STUCK = 0x49, + UWB_HOST_REASON_UWB_NVM_FILE_NOT_FOUND = 0x4A, + UWB_HOST_REASON_UWB_GETBLDINFO_CMD_FAILED = 0x4B, + UWB_HOST_REASON_UWB_PATCH_DNLD_STUCK = 0x4C, + UWB_HOST_REASON_UWB_NVM_DNLD_STUCK = 0x4D, + UWB_HOST_REASON_UWB_GETBLDINFO_CMD_STUCK = 0x4E, + UWB_HOST_REASON_PERI_ACTIVATE_CMD_STUCK = 0x4F, + UWB_HOST_REASON_PERI_ARBITRATION_CMD_STUCK = 0x50, + UWB_HOST_REASON_PERI_ARBITRATION_NTF_STUCK = 0x51, + UWB_HOST_REASON_INITIALIZATION_FAILED = 0x52, + UWB_HOST_REASON_UWB_RESET_CC_NOT_RCVD = 0x53, + UWB_HOST_REASON_UWB_ACTIVATE_CC_NOT_RCVD = 0x54, + UWB_HOST_REASON_TME_ACTIVATE_CC_NOT_RCVD = 0x55, + UWB_HOST_REASON_Q2SPI_INIT_STUCK = 0x56, + UWB_HOST_REASON_Q2SPI_INIT_FAILED = 0x57, + UWB_HOST_REASON_UWB_TLV_DOWNLOAD_FAILED = 0x58, + UWB_HOST_REASON_UWB_ENHLOG_CMD_STUCK = 0x59, + UWB_HOST_REASON_UWB_GETVER_CMD_FAILED = 0x5A, + UWB_HOST_REASON_UWB_PATCH_CONFIG_CMD_STUCK = 0x5B, + UWB_HOST_REASON_UWB_PATCH_CONFIG_CMD_FAILED = 0x5C, + UWB_HOST_REASON_UWB_RESET_STUCK = 0x5D, + UWB_HOST_REASON_PERI_ACTIVATE_NTF_STUCK = 0x5E, + UWB_HOST_REASON_UWB_CORE_RESET_CMD_FAILED = 0x5F, + UWB_HOST_REASON_TME_ARBITRATION_CMD_STUCK = 0x60, + UWB_HOST_REASON_TME_ARBITRATION_NTF_STUCK = 0x61, + UWB_HOST_REASON_TME_GETVER_SEND_STUCK = 0x62, + UWB_HOST_REASON_TME_GETVER_NO_RSP_RCVD = 0x63, + UWB_HOST_REASON_TME_GETVER_CMD_FAILED = 0x64, + UWB_HOST_REASON_TME_PATCH_DNLD_STUCK = 0x65, + UWB_HOST_REASON_TME_RESET_STUCK = 0x66, + UWB_HOST_REASON_TME_GETBLDINFO_CMD_STUCK = 0x67, + UWB_HOST_REASON_TME_GETBLDINFO_CMD_FAILED = 0x68, + UWB_HOST_REASON_TME_RAM_PATCH_READ_STUCK = 0x69, + Q2SPI_REASON_DEFAULT = 0xFF +}; + +typedef struct { + enum BtSecondaryReasonCode reason; + char reasonstr[50]; +} BtSecondaryReasonMap; + +typedef struct { + enum BtPrimaryReasonCode reason; + char reasonstr[100]; +} BtPrimaryReasonMap; + +typedef struct { + enum UwbSecondaryReasonCode reason; + char reasonstr[50]; +} UwbSecondaryReasonMap; + +typedef struct { + enum UwbPrimaryReasonCode reason; + char reasonstr[100]; +} UwbPrimaryReasonMap; + +static BtPrimaryReasonMap btPriReasonMap[] = { + { BT_DEFAULT_NONE, "Invalid reason"}, + { BT_SOC_CRASHED, "SOC crashed"}, + { BT_SOC_CRASHED_DIAG_SSR, "SOC crashed with diag initiated SSR"}, + { BT_INIT_FAILED, "Init failed"}, + { BT_CLOSE_RCVD_DURING_INIT, "Close received from stack during SOC init"}, + { BT_ERROR_READING_DATA_FROM_UART, "Error reading data from UART"}, + { BT_WRITE_FAIL_SPCL_BUFF_CRASH_SOC, + "Failed to write special bytes to crash SOC"}, + { BT_RX_THREAD_STUCK, "Thread Stuck"}, + { BT_SSR_CMD_TIMEDOUT, "SSR due to command timed out"}, + { BT_SSR_SPURIOUS_WAKEUP, "SSR due to spurious wakeup"}, + { BT_SSR_INVALID_BYTES_RCVD, "Invalid HCI cmd type received"}, + { BT_SSR_RCVD_LARGE_PKT_FROM_SOC, "Large packet received from SOC"}, + { BT_SSR_UNABLE_TO_WAKEUP_SOC, "Unable to wake SOC"}, + { BT_CMD_TIMEDOUT_SOC_WAIT_TIMEOUT, + "Command timedout and SOC crash wait timeout"}, + { BT_SPURIOUS_WAKEUP_SOC_WAIT_TIMEOUT, + "Spurious wake and SOC crash wait timeout"}, + { BT_INV_BYTES_SOC_WAIT_TIMEOUT, + "Invalid bytes received and SOC crash wait timeout"}, + { BT_SOC_WAKEUP_FAILED_SOC_WAIT_TIMEOUT, + "SOC Wakeup failed and SOC crash wait timeout"}, + { BT_SOC_CRASHED_DIAG_SSR_SOC_WAIT_TIMEOUT, + "SOC crashed with diag initiated SSR and SOC wait timeout"}, + { BT_NONE_SOC_WAIT_TIMEOUT, + "Invalid Reason and SOC crash wait timeout"}, + { BT_SOC_DEINIT_STUCK, "SOC Deinit Stuck"}, + { BT_SSR_INTERNAL_CMD_TIMEDOUT, "SSR due to internal Command timeout"}, + { BT_FAILED_TO_SEND_INTERNAL_CMD, "Failed to send internal command"}, + { BT_SSR_SLEEP_IND_NOT_RCVD, "Failed to receive SLEEP IND during close"}, + { BT_DIAG_LOG_API_STUCK, "DIAG log API stuck"}, + { BT_PERI_SOC_CRASHED, "Peri SOC crashed"}, + { BT_PERI_SOC_CRASHED_DIAG_SSR, "Peri SOC crashed with diag initiated SSR"}, + { BT_PERI_SOC_CRASHED_ON_OTHER_SUB_SYSTEM, + "Peripheral core crash deteced in UWB SS"}, + { BT_PERI_SUB_SYSTEM_FAILED_UPDATE_SSR_COMPLETE, + "UWB Sub-System failed to update SSR complete status"}, +}; + +static UwbPrimaryReasonMap uwbPriReasonMap[] = { + {UWB_HOST_REASON_DEFAULT_NONE, "Invalid reason"}, + {UWB_HOST_REASON_PERI_SOC_CRASHED, "Peri SOC crashed"}, + {UWB_HOST_REASON_UWB_SOC_CRASHED, "UWB SOC crashed"}, + {UWB_HOST_REASON_PERI_SOC_CRASHED_DIAG_SSR, "Peri SOC crashed with diag initiated SSR"}, + {UWB_HOST_REASON_UWB_SOC_CRASHED_DIAG_SSR, "UWB SOC crashed with diag initiated SSR"}, + {UWB_HOST_REASON_INIT_FAILED, "Init failed"}, + {UWB_HOST_REASON_CLOSE_RCVD_DURING_INIT, "Close received from stack during SOC init"}, + {UWB_HOST_REASON_ERROR_READING_DATA_FROM_Q2SPI, "Error reading data from Q2SPI"}, + {UWB_HOST_REASON_WRITE_FAIL_SPCL_BUFF_CRASH_SOC, "Failed to write special bytes to crash SOC"}, + {UWB_HOST_REASON_RX_THREAD_STUCK, "Rx Thread Stuck"}, + {UWB_HOST_REASON_SSR_CMD_TIMEDOUT, "SSR due to command timed out"}, + {UWB_HOST_REASON_SSR_RCVD_LARGE_PKT_FROM_SOC, "Large packet received from SOC"}, + {UWB_HOST_REASON_SSR_UNABLE_TO_WAKEUP_SOC, "Unable to wake SOC"}, + {UWB_HOST_REASON_CMD_TIMEDOUT_SOC_WAIT_TIMEOUT, "Command timedout and SOC crash wait timeout"}, + {UWB_HOST_REASON_INV_BYTES_SOC_WAIT_TIMEOUT, + "Invalid bytes received and SOC crash wait timeout"}, + {UWB_HOST_REASON_SOC_WAKEUP_FAILED_SOC_WAIT_TIMEOUT, + "SOC Wakeup failed and SOC crash wait timeout"}, + {UWB_HOST_REASON_SOC_CRASHED_DIAG_SSR_SOC_WAIT_TIMEOUT, + "SOC crashed with diag initiated SSR and SOC wait timeout"}, + {UWB_HOST_REASON_NONE_SOC_WAIT_TIMEOUT, "Invalid Reason and SOC crash wait timeout"}, + {UWB_HOST_REASON_SOC_DEINIT_STUCK, "SOC Deinit Stuck"}, + {UWB_HOST_REASON_SSR_INTERNAL_CMD_TIMEDOUT, "SSR due to internal Command timeout"}, + {UWB_HOST_REASON_FAILED_TO_SEND_INTERNAL_CMD, "Failed to send internal command"}, + {UWB_HOST_REASON_SSR_SLEEP_IND_NOT_RCVD, "Failed to receive SLEEP IND during close"}, + {UWB_HOST_REASON_PERI_CRASH_ON_OTHER_SS, "Peri SOC crashed detected on BT SS"}, + {UWB_HOST_REASON_DIAG_LOG_API_STUCK, "DIAG log API stuck"} +}; + +static BtSecondaryReasonMap btSecReasonMap[] = { + { BT_SOC_REASON_DEFAULT, "Default"}, + { BT_SOC_REASON_UNKNOWN, "Unknown"}, + { BT_SOC_REASON_TX_RX_INVALID_PKT_FATAL, + "Tx/Rx invalid packet fatal error"}, + { BT_SOC_REASON_TX_RX_INVALID_LEN_FATAL, + "Tx/Rx invalid length fatal error"}, + { BT_SOC_REASON_SW_REQUESTED, "SW Requested"}, + { BT_SOC_REASON_STACK_OVERFLOW, "Stack Overflow"}, + { BT_SOC_REASON_EXCEPTION, "Exception"}, + { BT_SOC_REASON_ASSERT, "Assert"}, + { BT_SOC_REASON_TRAP, "Trap"}, + { BT_SOC_REASON_OS_FATAL, "OS Fatal"}, + { BT_SOC_REASON_HCI_RESET, "HCI Reset"}, + { BT_SOC_REASON_PATCH_RESET, "Patch Reset"}, + { BT_SOC_REASON_ABT, "SoC Abort"}, + { BT_SOC_REASON_RAMMASK, "RAM MASK"}, + { BT_SOC_REASON_PREBARK, "PREBARK"}, + { BT_SOC_REASON_BUSERROR, "Bus error"}, + { BT_SOC_REASON_IO_FATAL, "IO fatal eror"}, + { BT_SOC_REASON_SSR_CMD, "SSR CMD"}, + { BT_SOC_REASON_POWERON, "Power ON"}, + { BT_SOC_REASON_WATCHDOG, "Watchdog"}, + { BT_SOC_REASON_RAMMASK_RGN1, "RAMMASK RGN1"}, + { BT_SOC_REASON_RAMMASK_RGN0, "RAMMASK RGN0"}, + { BT_SOC_REASON_Q6_WATCHDOG, "Q6 Watchdog"}, + { BT_SOC_REASON_ZEALIS_RAM_MASK_RGN0, "ZEALIS RAM MASK RGN0"}, + { BT_SOC_REASON_ZEALIS_RAM_MASK_RGN1, "ZEALIS RAM MASK RGN1"}, + { BT_SOC_REASON_APSS_RESET, "APSS reset"}, + { BT_SOC_REASON_TIME_RESET, "Time reset"}, + { BT_SOC_REASON_AUDIOSS_RESET, "Audioss reset"}, + { BT_SOC_REASON_HOST_WARMRESET, "Host warm reset"}, + { BT_SOC_REASON_HOST_NMI_INIT, "Host NMI init"}, + { BT_SOC_REASON_INVALID_STACK, "Invalid Stack"}, + { BT_HOST_REASON_UARTINIT_STUCK, "UartInitStuck"}, + { BT_HOST_REASON_GETVER_SEND_STUCK, "GetVerSendStuck"}, + { BT_HOST_REASON_GETVER_NO_RSP_RCVD, "GetVerNoRspRcvd"}, + { BT_HOST_REASON_SETBAUDRATE_CMD_STUCK, "SetBaudRateStuck"}, + { BT_HOST_REASON_PATCH_DNLD_STUCK, "PatchDnldStuck"}, + { BT_HOST_REASON_GETBOARDID_CMD_STUCK, "GetBoardIdStuck"}, + { BT_HOST_REASON_NVM_DNLD_STUCK, "NvmDnldStuck"}, + { BT_HOST_REASON_HCI_RESET_STUCK, "HciResetStuck"}, + { BT_HOST_REASON_GETBLDINFO_CMD_STUCK, "GetBldInfoCmdStuck"}, + { BT_HOST_REASON_ADDONFEAT_CMD_STUCK, "AddOnFeatCmdStuck"}, + { BT_HOST_REASON_ENHLOG_CMD_STUCK, "EnhLogCmdStuck"}, + { BT_HOST_REASON_DIAGINIT_STUCK, "DiagInitStuck"}, + { BT_HOST_REASON_DIAGDEINIT_STUCK, "DiagDeinitStuck"}, + { BT_HOST_REASON_XMEM_NVM_DNLD_STUCK, "XMEM NVM Download stuck"}, + { BT_HOST_REASON_XMEM_PATCH_DNLD_STUCK, "XMEM patch download stuck"}, + { BT_HOST_REASON_SECURE_BRIDGE_CMD_STUCK, "Secure bridge cmd stuck"}, + { BT_HOST_REASON_FAILED_TO_SEND_CMD, "Failed to send internal cmd"}, + { BT_HOST_REASON_HCI_RESET_CC_NOT_RCVD, "HCI Reset Cmd CC Not Rcvd"}, + { BT_HOST_REASON_HCI_PRE_SHUTDOWN_CC_NOT_RCVD, "HCI Pre shutdown Cmd CC not Rcvd"}, + { BT_HOST_REASON_HCI_SET_BD_ADDRESS_CC_NOT_RCVD, "HCI BD address CC not Rcvd"}, + { BT_HOST_REASON_FAILED_TO_RECEIVE_SLEEP_IND, "Failed to receive SLEEP IND from SoC"}, + { BT_HOST_REASON_POWER_ON_REGS_STUCK, "SoC Power ON Sequence stuck"}, + { BT_HOST_REASON_POWER_IOCTL_STUCK, "Power driver IOCTL stuck"}, + { BT_HOST_REASON_RX_THREAD_START_STUCK, "RX thread start stuck"}, + { BT_HOST_REASON_GET_LOCALADDR_STUCK, "Get local BD address stuck"}, + { BT_HOST_REASON_OTP_INFO_GET_CMD_STUCK, "Get OTP info. cmd stuck"}, + { BT_HOST_REASON_FILE_SYSTEM_CALL_STUCK, "FILE system call stuck"}, + { BT_HOST_REASON_PROPERTY_GET_STUCK, "Property get call stuck"}, + { BT_HOST_REASON_PROPERTY_SET_STUCK, "Property set call stuck"}, + { BT_HOST_REASON_RAM_PATCH_READ_STUCK, "RAM patch open/read stuck"}, + { BT_HOST_REASON_NVM_PATCH_READ_STUCK, "NVM file open/read stuck"}, + { BT_HOST_REASON_UART_IOCTL_STUCK, "UART IOCTL stuck"}, + { BT_HOST_REASON_PATCH_CONFIG_CMD_STUCK, "Patch config cmd stuck"}, + { BT_HOST_REASON_GET_APP_VER_CMD_STUCK, "Get APP version cmd stuck"}, + { BT_HOST_REASON_SOC_NAME_UNKOWN, "SoC name unkown"}, + { SOC_REASON_START_TX_IOS_SOC_RFR_HIGH_DURING_INIT, "SoC RFR high during INIT"}, + { BT_HOST_REASON_GETVER_CMD_FAILED, "Get Version cmd failed"}, + { BT_HOST_REASON_BAUDRATE_CHANGE_FAILED, "Baudrate change failed"}, + { BT_HOST_REASON_TLV_DOWNLOAD_FAILED, "TLV/NVM download failed"}, + { BT_HOST_REASON_FW_BUILD_INFO_CMD_FAILED, "FW build info. cmd failed"}, + { BT_HOST_REASON_HCI_RESET_CMD_FAILED, "HCI RESET cmd failed"}, + { BT_HOST_REASON_UART_INIT_FAILED, "UART INIT failed"}, + { BT_HOST_REASON_MEMORY_ALLOCATION_FAILED, "Memory allocation failed"}, + { BT_HOST_REASON_READ_THREAD_START_FAILED, "Read thread start failed"}, + { BT_HOST_REASON_HW_FLOW_ON_FAILED, "HW Flow ON failed"}, + { BT_HOST_REASON_NVM_FILE_NOT_FOUND, "NVM file not found"}, + { BT_HOST_REASON_UART_BAUDRATE_CHANGE_FAILED, "UART baudrate change failed"}, + { BT_HOST_REASON_PATCH_CONFIG_FAILED, "Patch config cmd failed"}, + { BT_HOST_REASON_HCI_SET_OFFLOAD_HOST_CONFIG_CC_NOT_RCVD, "offload host config CC not Rcvd"}, + { BT_HOST_REASON_BT_EN_PIN_LOW, "BT EN pin pulled low"}, + { UART_REASON_DEFAULT, "UART reason Default"}, + { UART_REASON_INVALID_FW_LOADED, "UART invalid FW loaded"}, + { UART_REASON_CLK_GET_FAIL, "UART CLK get failed"}, + { UART_REASON_SE_CLK_RATE_FIND_FAIL, "UART CLK rate find failed"}, + { UART_REASON_SE_RESOURCES_INIT_FAIL, "UART resources init failed"}, + { UART_REASON_SE_RESOURCES_ON_FAIL, "UART resources ON failed"}, + { UART_REASON_SE_RESOURCES_OFF_FAIL, "UART resources OFF failed"}, + { UART_REASON_TX_DMA_MAP_FAIL, "UART DMA map failed"}, + { UART_REASON_TX_CANCEL_FAIL, "UART tx cancel failed"}, + { UART_REASON_TX_ABORT_FAIL, "UART tx abort failed"}, + { UART_REASON_TX_FSM_RESET_FAIL, "UART tx FSM reset failed"}, + { UART_REASON_RX_CANCEL_FAIL, "UART rx cancel failed"}, + { UART_REASON_RX_ABORT_FAIL, "UART rx abort failed"}, + { UART_REASON_RX_FSM_RESET_FAIL, "UART rx FSM reset failed"}, + { UART_REASON_RX_TTY_INSET_FAIL, "UART rx tty inset failed"}, + { UART_REASON_ILLEGAL_INTERRUPT, "UART illegal interrupt"}, + { UART_REASON_BUFFER_OVERRUN, "UART buffer overrun"}, + { UART_REASON_RX_PARITY_REASON, "UART rx parity error"}, + { UART_REASON_RX_BREAK_REASON, "UART rx break error"}, + { UART_REASON_RX_SBE_REASON, "UART rx SBE error"}, + { SOC_REASON_START_TX_IOS_SOC_RFR_HIGH, "SoC RFR high"}, + { UART_REASON_FLOW_OFF, "UART flow is OFF"}, + { BT_HOST_REASON_PERI_ARBITRATION_CMD_STUCK, "Peri arbitration cmd stuck"}, + { BT_HOST_REASON_PERI_GETBLDINFO_CMD_STUCK, "Peri Get Bld Info CmdStuck"}, + { BT_HOST_REASON_BT_ACTIVATE_CMD_STUCK, "Subsystem Activate cmd stuck"}, + { BT_HOST_REASON_BT_ACTIVATE_NTF_STUCK, "Subsystem Activate ntf stuck"}, + { BT_HOST_REASON_PERI_GETVER_SEND_STUCK, "Peri Get Ver Send Stuck"}, + { BT_HOST_REASON_PERI_GETBLDINFO_CMD_STUCK, "Peri Get Bld Info Cmd Stuck"}, + { BT_HOST_REASON_PERI_RAM_PATCH_READ_STUCK, "Peri RAM patch open/read stuck"}, + { BT_HOST_REASON_PERI_RESET_STUCK, "Peri Reset Stuck"}, + { BT_HOST_REASON_PERI_PATCH_CONFIG_CMD_STUCK, "Peri Patch config cmd stuck"}, + { BT_HOST_REASON_PERI_PATCH_DNLD_STUCK, "Peri Patch Dnld Stuck"}, + { BT_HOST_REASON_PERI_RESET_CMD_FAILED, "HCI Peri RESET cmd failed"}, + { BT_HOST_REASON_BT_ACTIVATE_CMD_STUCK, "BT activate cmd stuck"}, + { BT_HOST_REASON_BT_ACTIVATE_CMD_FAILED, "BT activate cmd failed"}, + { BT_HOST_REASON_PERI_GETVER_CMD_FAILED, "Peri Get Ver cmd failed"}, + { BT_HOST_REASON_PERI_PATCH_CONFIG_FAILED, "Peri Patch config cmd failed"}, + { BT_HOST_REASON_PERI_TLV_DOWNLOAD_FAILED, "Peri TLV/NVM download failed"}, + { BT_HOST_REASON_PERI_GETBOARDID_CMD_STUCK, "Peri Get BoardId Stuck"}, + { BT_HOST_REASON_PERI_NVM_PATCH_READ_STUCK, "Peri NVM file open/read stuck"}, + { BT_HOST_REASON_PERI_NVM_DNLD_STUCK, "Peri Nvm Dnld Stuck"}, + { BT_HOST_REASON_PERI_GETBLDINFO_CMD_FAILED, "Peri FW build info. cmd failed"}, + { BT_HOST_REASON_PERI_GETVER_NO_RSP_RCVD, "Peri Get Ver No Rsp Rcvd"}, + { BT_HOST_REASON_PERI_SETBAUDRATE_CMD_STUCK, "Peri Set baud rate stuck"}, + { BT_HOST_REASON_PERI_SETBAUD_CC_NOT_RCVD, "Peri set baudrate cc nor rcvd"}, + { BT_HOST_REASON_PERI_ACCESS_STUCK, "Peri Access stuck"}, + { BT_HOST_REASON_PERI_ACCESS_DISALLOWED, "Peri Access Disallowed"}, + { PERI_SOC_REASON_DEFAULT, "Default"}, +}; + +static UwbSecondaryReasonMap uwbSecReasonMap[] = { + { UWB_SOC_REASON_DEFAULT, "Default"}, + { UWB_SOC_REASON_TX_RX_INVALID_PKT, "Tx/Rx Inavlid Packet"}, + { UWB_SOC_REASON_TX_RX_INVALID_PKT_LENE, "Tx/Rx Invalid Pkt Len"}, + { UWB_SOC_REASON_TX_RX_OVERFLOW_BUFF, "Tx/Rx Overflow Buffer"}, + { UWB_SOC_REASON_UNKNOWN, "Unknown"}, + { UWB_SOC_REASON_TX_RX_INVALID_PKT_FATAL, "Tx/Rx invalid packet fatal error"}, + { UWB_SOC_REASON_TX_RX_INVALID_LEN_FATAL, "Tx/Rx invalid length fatal error"}, + { UWB_SOC_REASON_TX_RX_OVERFLOW_BUFF, "Tx/Rx Overflow Buffer"}, + { UWB_SOC_REASON_SW_REQUESTED, "SW Requested"}, + { UWB_SOC_REASON_STACK_OVERFLOW, "Stack Overflow"}, + { UWB_SOC_REASON_EXCEPTION, "Exception"}, + { UWB_SOC_REASON_ASSERT, "Assert"}, + { UWB_SOC_REASON_TRAP, "Trap"}, + { UWB_SOC_REASON_OS_FATAL, "OS Fatal"}, + { UWB_SOC_REASON_HCI_RESET, "HCI Reset"}, + { UWB_SOC_REASON_PATCH_RESET, "Patch Reset"}, + { UWB_SOC_REASON_ABT, "SoC Abort"}, + { UWB_SOC_REASON_RAMMASK, "RAM MASK"}, + { UWB_SOC_REASON_PREBARK, "PREBARK"}, + { UWB_SOC_REASON_BUSERROR, "Bus error"}, + { UWB_SOC_REASON_IO_FATAL, "IO fatal eror"}, + { UWB_SOC_REASON_SSR_CMD, "SSR CMD"}, + { UWB_SOC_REASON_POWERON, "Power ON"}, + { UWB_SOC_REASON_WATCHDOG, "Watchdog"}, + { UWB_SOC_REASON_RAMMASK_RGN1, "RAMMASK RGN1"}, + { UWB_SOC_REASON_RAMMASK_RGN0, "RAMMASK RGN0"}, + { UWB_SOC_REASON_Q6_WATCHDOG, "Q6 Watchdog"}, + { UWB_SOC_REASON_ZEALIS_RAM_MASK_RGN0, "ZEALIS RAM MASK RGN0"}, + { UWB_SOC_REASON_ZEALIS_RAM_MASK_RGN1, "ZEALIS RAM MASK RGN1"}, + { UWB_SOC_REASON_APSS_RESET, "APSS reset"}, + { UWB_SOC_REASON_TIME_RESET, "Time reset"}, + { UWB_SOC_REASON_AUDIOSS_RESET, "Audioss reset"}, + { UWB_SOC_REASON_HOST_WARMRESET, "Host warm reset"}, + { UWB_SOC_REASON_HOST_NMI_INIT, "Host NMI init"}, + { UWB_SOC_REASON_INVALID_STACK, "Invalid Stack"}, + { UWB_HOST_REASON_PERI_GETVER_SEND_STUCK, "PeriGetVerSendStuck"}, + { UWB_HOST_REASON_UWB_GETVER_SEND_STUCK, "UwbGetVerSendStuck"}, + { UWB_HOST_REASON_TME_GETVER_SEND_STUCK, "TmeGetVerSendStuck"}, + { UWB_HOST_REASON_PERI_GETVER_NO_RSP_RCVD, "PeriGetVerNoRspRcvd"}, + { UWB_HOST_REASON_UWB_GETVER_NO_RSP_RCVD, "UwbGetVerNoRspRcvd"}, + { UWB_HOST_REASON_TME_GETVER_NO_RSP_RCVD, "TmeGetVerNoRspRcvd"}, + { UWB_HOST_REASON_PERI_PATCH_DNLD_STUCK, "PeriPatchDnldStuck"}, + { UWB_HOST_REASON_UWB_PATCH_DNLD_STUCK, "UwbPatchDnldStuck"}, + { UWB_HOST_REASON_TME_PATCH_DNLD_STUCK, "TmePatchDnldStuck"}, + { UWB_HOST_REASON_PERI_GETBOARDID_CMD_STUCK, "PeriGetBoardIdStuck"}, + { UWB_HOST_REASON_PERI_NVM_DNLD_STUCK, "PeriNvmDnldStuck"}, + { UWB_HOST_REASON_UWB_NVM_DNLD_STUCK, "UwbNvmDnldStuck"}, + { UWB_HOST_REASON_PERI_RESET_STUCK, "PeriResetStuck"}, + { UWB_HOST_REASON_UWB_RESET_STUCK, "UwbResetStuck"}, + { UWB_HOST_REASON_TME_RESET_STUCK, "TmeResetStuck"}, + { UWB_HOST_REASON_PERI_GETBLDINFO_CMD_STUCK, "PeriGetBldInfoCmdStuck"}, + { UWB_HOST_REASON_UWB_GETBLDINFO_CMD_STUCK, "UwbGetBldInfoCmdStuck"}, + { UWB_HOST_REASON_TME_GETBLDINFO_CMD_STUCK, "TmeGetBldInfoCmdStuck"}, + { UWB_HOST_REASON_PERI_ENHLOG_CMD_STUCK, "Peri EnhLogCmdStuck"}, + { UWB_HOST_REASON_UWB_ENHLOG_CMD_STUCK, "Uwb EnhLogCmdStuck"}, + { UWB_HOST_REASON_DIAGINIT_STUCK, "DiagInitStuck"}, + { UWB_HOST_REASON_DIAGDEINIT_STUCK, "DiagDeinitStuck"}, + { UWB_HOST_REASON_FAILED_TO_SEND_CMD, "Failed to send internal cmd"}, + { UWB_HOST_REASON_PERI_RESET_CC_NOT_RCVD, "Peri Reset Cmd CC Not Rcvd"}, + { UWB_HOST_REASON_UWB_RESET_CC_NOT_RCVD, "UWB Reset Cmd CC Not Rcvd"}, + { UWB_HOST_REASON_UWB_ACTIVATE_CC_NOT_RCVD, "UWB Activate Cmd CC Not Rcvd"}, + { UWB_HOST_REASON_TME_ACTIVATE_CC_NOT_RCVD, "TME DeActivate Cmd CC Not Rcvd"}, + { UWB_HOST_REASON_POWER_ON_REGS_STUCK, "SoC Power ON Sequence stuck"}, + { UWB_HOST_REASON_POWER_IOCTL_STUCK, "Power driver IOCTL stuck"}, + { UWB_HOST_REASON_RX_THREAD_START_STUCK, "RX thread start stuck"}, + { UWB_HOST_REASON_OTP_INFO_GET_CMD_STUCK, "Get OTP info. cmd stuck"}, + { UWB_HOST_REASON_FILE_SYSTEM_CALL_STUCK, "FILE system call stuck"}, + { UWB_HOST_REASON_PROPERTY_GET_STUCK, "Property get call stuck"}, + { UWB_HOST_REASON_PROPERTY_SET_STUCK, "Property set call stuck"}, + { UWB_HOST_REASON_PERI_RAM_PATCH_READ_STUCK, "Peri RAM patch open/read stuck"}, + { UWB_HOST_REASON_UWB_RAM_PATCH_READ_STUCK, "UWB RAM patch open/read stuck"}, + { UWB_HOST_REASON_PERI_NVM_PATCH_READ_STUCK, "Peri NVM file open/read stuck"}, + { UWB_HOST_REASON_UWB_NVM_PATCH_READ_STUCK, "UWB NVM file open/read stuck"}, + { UWB_HOST_REASON_PERI_PATCH_CONFIG_CMD_STUCK, "Peri Patch config cmd stuck"}, + { UWB_HOST_REASON_PERI_PATCH_CONFIG_FAILED, "Peri Patch config cmd failed"}, + { UWB_HOST_REASON_UWB_PATCH_CONFIG_CMD_STUCK, "Uwb Patch config cmd stuck"}, + { UWB_HOST_REASON_UWB_PATCH_CONFIG_CMD_FAILED, "Uwb Patch config cmd stuck"}, + { UWB_HOST_REASON_SOC_NAME_UNKOWN, "SoC name unkown"}, + { UWB_HOST_REASON_PERI_TLV_DOWNLOAD_FAILED, "Peri TLV/NVM download failed"}, + { UWB_HOST_REASON_PERI_GETBLDINFO_CMD_FAILED, "Peri FW build info. cmd failed"}, + { UWB_HOST_REASON_UWB_GETBLDINFO_CMD_FAILED, "UWB build info. cmd failed"}, + { UWB_HOST_REASON_PERI_RESET_CMD_FAILED, "HCI Peri RESET cmd failed"}, + { UWB_HOST_REASON_UWB_CORE_RESET_CMD_FAILED, "UWB Core RESET cmd failed"}, + { UWB_HOST_REASON_MEMORY_ALLOCATION_FAILED, "Memory allocation failed"}, + { UWB_HOST_REASON_READ_THREAD_START_FAILED, "Read thread start failed"}, + { UWB_HOST_REASON_HW_FLOW_ON_FAILED, "HW Flow ON failed"}, + { UWB_HOST_REASON_PERI_ACTIVATE_CMD_STUCK, "Peri actvate cmd stuck"}, + { UWB_HOST_REASON_PERI_ACTIVATE_NTF_STUCK, "Peri activate ntf stuck"}, + { UWB_HOST_REASON_PERI_ARBITRATION_CMD_STUCK, "Peri arbitration cmd stuck"}, + { UWB_HOST_REASON_PERI_ARBITRATION_NTF_STUCK, "Peri arbitration ntf stuck"}, + { UWB_HOST_REASON_INITIALIZATION_FAILED, "Initialization Failed"}, + { UWB_HOST_REASON_Q2SPI_INIT_STUCK, "Q2SPI Init stuck"}, + { UWB_HOST_REASON_Q2SPI_INIT_FAILED, "Q2SPI Init Failed"}, + { UWB_HOST_REASON_UWB_TLV_DOWNLOAD_FAILED, "Uwb TLV/NVM download failed"}, + { Q2SPI_REASON_DEFAULT, "Q2SPI reason Default"}, }; struct log_index { @@ -26,7 +801,7 @@ struct log_index { int crash; }; -struct bt_power_vreg_data { +struct vreg_data { struct regulator *reg; /* voltage regulator handle */ const char *name; /* regulator name */ u32 min_vol; /* min voltage level */ @@ -37,10 +812,14 @@ struct bt_power_vreg_data { struct log_index indx; /* Index for reg. w.r.t init & crash */ }; -struct bt_power { +struct pwr_data { char compatible[32]; - struct bt_power_vreg_data *vregs; - int num_vregs; + struct vreg_data *bt_vregs; + int bt_num_vregs; + struct vreg_data *uwb_vregs; + int uwb_num_vregs; + struct vreg_data *platform_vregs; + int platform_num_vregs; }; struct bt_power_clk_data { @@ -49,10 +828,20 @@ struct bt_power_clk_data { bool is_enabled; /* is this clock enabled? */ }; +struct btpower_state_machine { + struct mutex state_machine_lock; + enum power_states power_state; + enum retention_states retention_mode; + enum grant_states grant_state; + enum grant_states grant_pending; +}; + +#define BTPWR_MAX_REQ BT_MAX_PWR_STATE + /* * Platform data for the bluetooth power driver. */ -struct btpower_platform_data { +struct platform_pwr_data { struct platform_device *pdev; int bt_gpio_sys_rst; /* Bluetooth reset gpio */ int wl_gpio_sys_rst; /* Wlan reset gpio */ @@ -67,14 +856,19 @@ struct btpower_platform_data { int sw_cntrl_gpio; int xo_gpio_clk; /* XO clock gpio*/ struct device *slim_dev; - struct bt_power_vreg_data *vreg_info; /* VDDIO voltage regulator */ + struct vreg_data *bt_vregs; + struct vreg_data *uwb_vregs; + struct vreg_data *platform_vregs; struct bt_power_clk_data *bt_chip_clk; /* bluetooth reference clock */ - int (*bt_power_setup)(int id); /* Bluetooth power setup function */ + int (*power_setup)(int core, int id); /* Bluetooth power setup function */ char compatible[32]; /*Bluetooth SoC name */ - int num_vregs; + int bt_num_vregs; + int uwb_num_vregs; + int platform_num_vregs; struct mbox_client mbox_client_data; struct mbox_chan *mbox_chan; const char *vreg_ipa; + bool is_ganges_dt; int pdc_init_table_len; const char **pdc_init_table; int bt_device_type; @@ -84,12 +878,35 @@ struct btpower_platform_data { struct file *reffilp_obs; struct task_struct *reftask_obs; #endif + struct task_struct *reftask; + struct task_struct *reftask_bt; + struct task_struct *reftask_uwb; + struct btpower_state_machine btpower_state; + enum ssr_states sub_state; + enum ssr_states wrkq_signal_state; + struct workqueue_struct *workq; + struct device_node *bt_of_node; + struct device_node *uwb_of_node; + struct work_struct bt_wq; + struct work_struct uwb_wq; + wait_queue_head_t rsp_wait_q[BTPWR_MAX_REQ]; + int wait_status[BTPWR_MAX_REQ]; + struct work_struct wq_pwr_voting; + struct sk_buff_head rxq; + struct mutex pwr_mtx; }; int btpower_register_slimdev(struct device *dev); int btpower_get_chipset_version(void); -int btpower_aop_mbox_init(struct btpower_platform_data *pdata); -int bt_aop_pdc_reconfig(struct btpower_platform_data *pdata); +int btpower_aop_mbox_init(struct platform_pwr_data *pdata); +int bt_aop_pdc_reconfig(struct platform_pwr_data *pdata); + +static const char *pwr_req[] = {"POWER_ON_BT", "POWER_OFF_BT", + "POWER_ON_UWB", "POWER_OFF_UWB", + "POWER_ON_BT_RETENION", + "POWER_ON_UWB_RETENION", + "BT_ACCESS_REQ", "UWB_ACCESS_REQ", + "BT_RELEASE_ACCESS", "UWB_RELEASE_ACCESS"}; #define WLAN_SW_CTRL_GPIO "qcom,wlan-sw-ctrl-gpio" #define BT_CMD_SLIM_TEST 0xbfac @@ -100,10 +917,17 @@ int bt_aop_pdc_reconfig(struct btpower_platform_data *pdata); #define BT_CMD_GETVAL_POWER_SRCS 0xbfb1 #define BT_CMD_SET_IPA_TCS_INFO 0xbfc0 #define BT_CMD_KERNEL_PANIC 0xbfc1 +#define UWB_CMD_KERNEL_PANIC 0xbfc2 +#define UWB_CMD_PWR_CTRL 0xbfe1 +#define BT_CMD_REGISTRATION 0xbfe2 +#define UWB_CMD_REGISTRATION 0xbfe3 +#define BT_CMD_ACCESS_CTRL 0xbfe4 +#define UWB_CMD_ACCESS_CTRL 0xbfe5 #ifdef CONFIG_MSM_BT_OOBS -#define BT_CMD_OBS_SIGNAL_TASK 0xbfd0 #define BT_CMD_OBS_VOTE_CLOCK 0xbfd1 + + /** * enum btpower_obs_param: OOBS low power param * @BTPOWER_OBS_CLK_OFF: Transport bus is no longer acquired @@ -119,4 +943,18 @@ enum btpower_obs_param { }; #endif +static const char * const bt_arg[]= {"power off BT", "power on BT", + "BT power retention"}; +static const char * const uwb_arg[]= {"power off UWB", "power on UWB", + "UWB power retention"}; +static const char * const pwr_states[]= {"Both Sub-System powered OFF", "BT powered ON", + "UWB powered ON", + "Both Sub-System powered ON"}; +static const char * const ssr_state[]= {"No SSR on Sub-Sytem", "SSR on BT", + "SSR Completed on BT", "SSR on UWB", + "SSR Completed on UWB"}; +static const char * const reg_mode[]= {"vote off", "vote on", "vote for retention", "vote off retention"}; +static const char * const retention_mode[]= {"IDLE", "BT_IN_RETENTION", "BT_OUT_OF_RETENTION", + "UWB_IN_RETENTION", "UWB_OUT_OF_RETENTION", + "BOTH_CLIENT_IN_RETENTION"}; #endif /* __LINUX_BLUETOOTH_POWER_H */ diff --git a/pwr/btpower.c b/pwr/btpower.c index e72f94c839..f2bec6b544 100644 --- a/pwr/btpower.c +++ b/pwr/btpower.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include "btpower.h" #if (defined CONFIG_BT_SLIM) @@ -49,6 +55,20 @@ #define BTPOWER_MBOX_MSG_MAX_LEN 64 #define BTPOWER_MBOX_TIMEOUT_MS 1000 #define XO_CLK_RETRY_COUNT_MAX 5 +#define MAX_PROP_SIZE 32 +#define BTPOWER_CONFIG_MAX_TIMEOUT 600 + +#define SIGIO_OOBS_SINGAL 0x00010000 +#define SIGIO_INTERACTION_SIGNAL 0x00020000 +#define SIGIO_SOC_ACCESS_SIGNAL 0x00040000 + +#define SIGIO_GPIO_HIGH 0x00000001 +#define SIGIO_GPIO_LOW 0x00000000 +#define SIGIO_SSR_ON_UWB 0x00000001 +#define SIGIO_UWB_SSR_COMPLETED 0x00000002 + +#define CRASH_REASON_NOT_FOUND ((char *)"Crash reason not found") + /** * enum btpower_vreg_param: Voltage regulator TCS param * @BTPOWER_VREG_VOLTAGE: Provides voltage level to be configured in TCS @@ -119,7 +139,7 @@ enum power_src_pos { }; // Regulator structure for QCA6174/QCA9377/QCA9379 BT SoC series -static struct bt_power_vreg_data bt_vregs_info_qca61x4_937x[] = { +static struct vreg_data bt_vregs_info_qca61x4_937x[] = { {NULL, "qcom,bt-vdd-aon", 928000, 928000, 0, false, false, {BT_VDD_AON_LDO, BT_VDD_AON_LDO_CURRENT}}, {NULL, "qcom,bt-vdd-io", 1710000, 3460000, 0, false, false, @@ -129,7 +149,7 @@ static struct bt_power_vreg_data bt_vregs_info_qca61x4_937x[] = { }; // Regulator structure for QCA6390,QCA6490 and WCN6750 BT SoC series -static struct bt_power_vreg_data bt_vregs_info_qca6xx0[] = { +static struct vreg_data bt_vregs_info_qca6xx0[] = { {NULL, "qcom,bt-vdd-io", 1800000, 1800000, 0, false, true, {BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}}, {NULL, "qcom,bt-vdd-aon", 966000, 966000, 0, false, true, @@ -151,34 +171,52 @@ static struct bt_power_vreg_data bt_vregs_info_qca6xx0[] = { {BT_VDD_IPA_2p2, BT_VDD_IPA_2p2_CURRENT}}, }; - // Regulator structure for kiwi BT SoC series -static struct bt_power_vreg_data bt_vregs_info_kiwi[] = { +static struct vreg_data bt_vregs_info_kiwi[] = { {NULL, "qcom,bt-vdd18-aon", 1800000, 1800000, 0, false, true, {BT_VDD_LDO, BT_VDD_LDO_CURRENT}}, {NULL, "qcom,bt-vdd12-io", 1200000, 1200000, 0, false, true, {BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}}, - {NULL, "qcom,bt-vdd-aon", 950000, 950000, 0, false, true, - {BT_VDD_AON_LDO, BT_VDD_AON_LDO_CURRENT}}, - {NULL, "qcom,bt-vdd-rfaOp8", 950000, 950000, 0, false, true, - {BT_VDD_RFACMN, BT_VDD_RFACMN_CURRENT}}, - /* BT_CX_MX */ - {NULL, "qcom,bt-vdd-dig", 950000, 950000, 0, false, true, - {BT_VDD_DIG_LDO, BT_VDD_DIG_LDO_CURRENT}}, - {NULL, "qcom,bt-vdd-rfaOp8", 950000, 952000, 0, false, true, - {BT_VDD_RFA_0p8, BT_VDD_RFA_0p8_CURRENT}}, - {NULL, "qcom,bt-vdd-rfa1", 1350000, 1350000, 0, false, true, - {BT_VDD_RFA1_LDO, BT_VDD_RFA1_LDO_CURRENT}}, - {NULL, "qcom,bt-vdd-rfa2", 1900000, 1900000, 0, false, true, - {BT_VDD_RFA2_LDO, BT_VDD_RFA2_LDO_CURRENT}}, {NULL, "qcom,bt-ant-ldo", 1776000, 1776000, 0, false, true, {BT_VDD_ANT_LDO, BT_VDD_ANT_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-dig", 950000, 950000, 0, false, true, + {BT_VDD_DIG_LDO, BT_VDD_DIG_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-aon", 950000, 950000, 0, false, true, + {BT_VDD_AON_LDO, BT_VDD_AON_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-rfaOp8", 950000, 952000, 0, false, true, + {BT_VDD_RFA_0p8, BT_VDD_RFA_0p8_CURRENT}}, + /* BT_CX_MX */ + {NULL, "qcom,bt-vdd-rfa2", 1900000, 1900000, 0, false, true, + {BT_VDD_RFA2_LDO, BT_VDD_RFA2_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-rfa1", 1350000, 1350000, 0, false, true, + {BT_VDD_RFA1_LDO, BT_VDD_RFA1_LDO_CURRENT}}, +}; + +// Regulator structure for kiwi BT SoC series +static struct vreg_data bt_vregs_info_peach[] = { + {NULL, "qcom,bt-vdd18-aon", 1800000, 1800000, 0, false, true, + {BT_VDD_LDO, BT_VDD_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd12-io", 1200000, 1200000, 0, false, true, + {BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}}, + {NULL, "qcom,bt-ant-ldo", 1776000, 1776000, 0, false, true, + {BT_VDD_ANT_LDO, BT_VDD_ANT_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-dig", 950000, 950000, 0, false, true, + {BT_VDD_DIG_LDO, BT_VDD_DIG_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-aon", 950000, 950000, 0, false, true, + {BT_VDD_AON_LDO, BT_VDD_AON_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-rfaOp8", 950000, 952000, 0, false, true, + {BT_VDD_RFA_0p8, BT_VDD_RFA_0p8_CURRENT}}, + /* BT_CX_MX */ + {NULL, "qcom,bt-vdd-rfa2", 1900000, 1900000, 0, false, true, + {BT_VDD_RFA2_LDO, BT_VDD_RFA2_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-rfa1", 1350000, 1350000, 0, false, true, + {BT_VDD_RFA1_LDO, BT_VDD_RFA1_LDO_CURRENT}}, }; // Regulator structure for WCN399x BT SoC series -static struct bt_power bt_vreg_info_wcn399x = { +static struct pwr_data bt_vreg_info_wcn399x = { .compatible = "qcom,wcn3990", - .vregs = (struct bt_power_vreg_data []) { + .bt_vregs = (struct vreg_data []) { {NULL, "qcom,bt-vdd-smps", 984000, 984000, 0, false, false, {BT_VDD_SMPS, BT_VDD_SMPS_CURRENT}}, {NULL, "qcom,bt-vdd-io", 1700000, 1900000, 0, false, false, @@ -190,49 +228,59 @@ static struct bt_power bt_vreg_info_wcn399x = { {NULL, "qcom,bt-vdd-xtal", 1700000, 1900000, 0, false, false, {BT_VDD_XTAL_LDO, BT_VDD_XTAL_LDO_CURRENT}}, }, - .num_vregs = 5, + .bt_num_vregs = 5, }; -static struct bt_power bt_vreg_info_qca6174 = { +static struct pwr_data bt_vreg_info_qca6174 = { .compatible = "qcom,qca6174", - .vregs = bt_vregs_info_qca61x4_937x, - .num_vregs = ARRAY_SIZE(bt_vregs_info_qca61x4_937x), + .bt_vregs = bt_vregs_info_qca61x4_937x, + .bt_num_vregs = ARRAY_SIZE(bt_vregs_info_qca61x4_937x), }; -static struct bt_power bt_vreg_info_qca6390 = { +static struct pwr_data bt_vreg_info_qca6390 = { .compatible = "qcom,qca6390", - .vregs = bt_vregs_info_qca6xx0, - .num_vregs = ARRAY_SIZE(bt_vregs_info_qca6xx0), + .bt_vregs = bt_vregs_info_qca6xx0, + .bt_num_vregs = ARRAY_SIZE(bt_vregs_info_qca6xx0), }; -static struct bt_power bt_vreg_info_qca6490 = { +static struct pwr_data bt_vreg_info_qca6490 = { .compatible = "qcom,qca6490", - .vregs = bt_vregs_info_qca6xx0, - .num_vregs = ARRAY_SIZE(bt_vregs_info_qca6xx0), + .bt_vregs = bt_vregs_info_qca6xx0, + .bt_num_vregs = ARRAY_SIZE(bt_vregs_info_qca6xx0), }; -static struct bt_power bt_vreg_info_kiwi = { +static struct pwr_data bt_vreg_info_kiwi = { .compatible = "qcom,kiwi", - .vregs = bt_vregs_info_kiwi, - .num_vregs = ARRAY_SIZE(bt_vregs_info_kiwi), + .bt_vregs = bt_vregs_info_kiwi, + .bt_num_vregs = ARRAY_SIZE(bt_vregs_info_kiwi), }; -static struct bt_power bt_vreg_info_kiwi_no_share_ant_power = { +static struct pwr_data bt_vreg_info_kiwi_no_share_ant_power = { .compatible = "qcom,kiwi-no-share-ant-power", - .vregs = bt_vregs_info_kiwi, - .num_vregs = ARRAY_SIZE(bt_vregs_info_kiwi), + .bt_vregs = bt_vregs_info_kiwi, + .bt_num_vregs = ARRAY_SIZE(bt_vregs_info_kiwi), }; -static struct bt_power bt_vreg_info_converged = { +static struct pwr_data bt_vreg_info_converged = { .compatible = "qcom,bt-qca-converged", - .vregs = bt_vregs_info_kiwi, - .num_vregs = ARRAY_SIZE(bt_vregs_info_kiwi), + .bt_vregs = bt_vregs_info_kiwi, + .bt_num_vregs = ARRAY_SIZE(bt_vregs_info_kiwi), }; -static struct bt_power bt_vreg_info_wcn6750 = { +static struct pwr_data bt_vreg_info_wcn6750 = { .compatible = "qcom,wcn6750-bt", - .vregs = bt_vregs_info_qca6xx0, - .num_vregs = ARRAY_SIZE(bt_vregs_info_qca6xx0), + .bt_vregs = bt_vregs_info_qca6xx0, + .bt_num_vregs = ARRAY_SIZE(bt_vregs_info_qca6xx0), +}; + +static struct pwr_data bt_vreg_info_peach = { + .compatible = "qcom,peach-bt", + .platform_vregs = bt_vregs_info_peach, + .platform_num_vregs = ARRAY_SIZE(bt_vregs_info_peach), + //.uwb_vregs = uwb_vregs_info, + //.bt_vregs = platform_vregs_info, + //.uwb_num_vregs = ARRAY_SIZE(uwb_vregs_info), + //.bt_num_vregs = ARRAY_SIZE(platform_vregs_info), }; static const struct of_device_id bt_power_match_table[] = { @@ -245,24 +293,27 @@ static const struct of_device_id bt_power_match_table[] = { .data = &bt_vreg_info_kiwi_no_share_ant_power}, { .compatible = "qcom,wcn6750-bt", .data = &bt_vreg_info_wcn6750}, { .compatible = "qcom,bt-qca-converged", .data = &bt_vreg_info_converged}, + { .compatible = "qcom,peach-bt", .data = &bt_vreg_info_peach}, {}, }; -static int bt_power_vreg_set(enum bt_power_modes mode); -static int btpower_enable_ipa_vreg(struct btpower_platform_data *pdata); - -static int bt_power_src_status[BT_POWER_SRC_SIZE]; -static struct btpower_platform_data *bt_power_pdata; +static int btpower_enable_ipa_vreg(struct platform_pwr_data *pdata); +static struct platform_pwr_data *pwr_data; static bool previous; -static int pwr_state; static struct class *bt_class; static int bt_major; static int soc_id; static bool probe_finished; +static void bt_power_vote(struct work_struct *work); +static struct { + int platform_state[BT_POWER_SRC_SIZE]; + int bt_state[BT_POWER_SRC_SIZE]; + int uwb_state[BT_POWER_SRC_SIZE]; +} power_src; #ifdef CONFIG_BT_HW_SECURE_DISABLE -int perisec_cnss_bt_hw_disable_check(struct btpower_platform_data *plat_priv) +int perisec_cnss_bt_hw_disable_check(struct platform_pwr_data *plat_priv) { struct Object client_env; struct Object app_object; @@ -289,7 +340,7 @@ int perisec_cnss_bt_hw_disable_check(struct btpower_platform_data *plat_priv) if (ret == PERISEC_FEATURE_NOT_SUPPORTED) { ret = 0; /* Do not Assert */ plat_priv->sec_peri_feature_disable = true; - pr_debug("Secure HW feature not supported\n"); + pr_err("Secure HW feature not supported\n"); } goto exit_release_clientenv; } @@ -299,12 +350,12 @@ int perisec_cnss_bt_hw_disable_check(struct btpower_platform_data *plat_priv) ret = Object_invoke(app_object, PERISEC_HW_OP_GET_STATE, obj_arg, ObjectCounts_pack(1, 1, 0, 0)); - pr_info("SMC invoke ret: %d state: %d\n", ret, state); + pr_err("SMC invoke ret: %d state: %d\n", ret, state); if (ret) { if (ret == PERISEC_PERIPHERAL_NOT_FOUND) { ret = 0; /* Do not Assert */ plat_priv->sec_peri_feature_disable = true; - pr_info("Secure HW mode is not updated. Peripheral not found\n"); + pr_err("Secure HW mode is not updated. Peripheral not found\n"); } } else { if (state == 1) @@ -323,7 +374,7 @@ end: return ret; } #else -int perisec_cnss_bt_hw_disable_check(struct btpower_platform_data *plat_priv) +int perisec_cnss_bt_hw_disable_check(struct platform_pwr_data *plat_priv) { return 0; } @@ -331,24 +382,29 @@ int perisec_cnss_bt_hw_disable_check(struct btpower_platform_data *plat_priv) #ifdef CONFIG_MSM_BT_OOBS -static void btpower_uart_transport_locked(struct btpower_platform_data *drvdata, - bool locked) +static void btpower_uart_transport_locked(struct platform_pwr_data *drvdata, + bool locked) { - pr_debug("%s: %s\n", __func__, (locked ? "busy" : "idle")); + pr_err("%s: %s\n", __func__, (locked ? "busy" : "idle")); } static irqreturn_t btpower_host_wake_isr(int irq, void *data) { - struct btpower_platform_data *drvdata = data; - int host_waking = gpio_get_value(drvdata->bt_gpio_host_wake); + struct platform_pwr_data *drvdata = data; struct kernel_siginfo siginfo; int rc = 0; + int host_waking = SIGIO_OOBS_SINGAL; - pr_debug("%s: bt-hostwake-gpio(%d) IRQ(%d) value(%d)\n", __func__, + if (gpio_get_value(drvdata->bt_gpio_host_wake)) + host_waking |= SIGIO_GPIO_HIGH; + else + host_waking |= SIGIO_GPIO_LOW; + + pr_err("%s: bt-hostwake-gpio(%d) IRQ(%d) value(%d)\n", __func__, drvdata->bt_gpio_host_wake, drvdata->irq, host_waking); - if (drvdata->reftask_obs == NULL) { - pr_info("%s: ignore BT-HOSTWAKE IRQ\n", __func__); + if (drvdata->reftask_bt == NULL) { + pr_err("%s: ignore BT-HOSTWAKE IRQ\n", __func__); return IRQ_HANDLED; } @@ -357,94 +413,103 @@ static irqreturn_t btpower_host_wake_isr(int irq, void *data) siginfo.si_signo = SIGIO; siginfo.si_code = SI_QUEUE; siginfo.si_int = host_waking; - rc = send_sig_info(siginfo.si_signo, &siginfo, drvdata->reftask_obs); + rc = send_sig_info(siginfo.si_signo, &siginfo, drvdata->reftask_bt); if (rc < 0) { pr_err("%s: failed (%d) to send SIG to HAL(%d)\n", __func__, - rc, drvdata->reftask_obs->pid); + rc, drvdata->reftask_bt->pid); } return IRQ_HANDLED; } #endif -static int bt_vreg_enable(struct bt_power_vreg_data *vreg) +static int vreg_configure(struct vreg_data *vreg, bool retention) { int rc = 0; - pr_debug("%s: vreg_en for : %s\n", __func__, vreg->name); + if ((vreg->min_vol != 0) && (vreg->max_vol != 0)) { + rc = regulator_set_voltage(vreg->reg, + (retention ? 0: vreg->min_vol), + vreg->max_vol); + if (rc < 0) { + pr_err("%s: regulator_set_voltage(%s) failed rc=%d\n", + __func__, vreg->name, rc); + return rc; + } + } + + if (vreg->load_curr >= 0) { + rc = regulator_set_load(vreg->reg, + (retention ? 0 : vreg->load_curr)); + if (rc < 0) { + pr_err("%s: regulator_set_load(%s) failed rc=%d\n", + __func__, vreg->name, rc); + return rc; + } + } + + return rc; +} + +static int vreg_enable(struct vreg_data *vreg) +{ + int rc = 0; + + pr_err("%s: vreg_en for : %s\n", __func__, vreg->name); if (!vreg->is_enabled) { - if ((vreg->min_vol != 0) && (vreg->max_vol != 0)) { - rc = regulator_set_voltage(vreg->reg, - vreg->min_vol, - vreg->max_vol); - if (rc < 0) { - pr_err("%s: regulator_set_voltage(%s) failed rc=%d\n", - __func__, vreg->name, rc); - goto out; - } - } - - if (vreg->load_curr >= 0) { - rc = regulator_set_load(vreg->reg, - vreg->load_curr); - if (rc < 0) { - pr_err("%s: regulator_set_load(%s) failed rc=%d\n", - __func__, vreg->name, rc); - goto out; - } - } - + if (vreg_configure(vreg, false) < 0) + return rc; rc = regulator_enable(vreg->reg); if (rc < 0) { pr_err("%s: regulator_enable(%s) failed. rc=%d\n", __func__, vreg->name, rc); - goto out; + return rc; } vreg->is_enabled = true; } -out: + return rc; } -static int bt_vreg_enable_retention(struct bt_power_vreg_data *vreg) +static int vreg_disable_retention(struct vreg_data *vreg) { int rc = 0; if (!vreg) return rc; - pr_debug("%s: enable_retention for : %s\n", __func__, vreg->name); + pr_err("%s: disable_retention for : %s\n", __func__, vreg->name); + + if ((vreg->is_enabled) && (vreg->is_retention_supp)) + rc = vreg_configure(vreg, false); - if ((vreg->is_enabled) && (vreg->is_retention_supp)) { - if ((vreg->min_vol != 0) && (vreg->max_vol != 0)) { - /* Set the min voltage to 0 */ - rc = regulator_set_voltage(vreg->reg, 0, vreg->max_vol); - if (rc < 0) { - pr_err("%s: regulator_set_voltage(%s) failed rc=%d\n", - __func__, vreg->name, rc); - goto out; - } - } - if (vreg->load_curr >= 0) { - rc = regulator_set_load(vreg->reg, 0); - if (rc < 0) { - pr_err("%s: regulator_set_load(%s) failed rc=%d\n", - __func__, vreg->name, rc); - } - } - } -out: return rc; } -static int bt_vreg_disable(struct bt_power_vreg_data *vreg) +static int vreg_enable_retention(struct vreg_data *vreg) { int rc = 0; if (!vreg) return rc; - pr_debug("%s for : %s\n", __func__, vreg->name); + pr_err("%s: enable_retention for : %s\n", __func__, vreg->name); + + if ((vreg->is_enabled) && (vreg->is_retention_supp)) + if ((vreg->min_vol != 0) && (vreg->max_vol != 0)) + rc = vreg_configure(vreg, true); + + return rc; +} + +static int vreg_disable(struct vreg_data *vreg) +{ + int rc = 0; + + if (!vreg) + return rc; + + pr_err("%s for : %s\n", __func__, vreg->name); if (vreg->is_enabled) { rc = regulator_disable(vreg->reg); @@ -481,7 +546,7 @@ static int bt_clk_enable(struct bt_power_clk_data *clk) { int rc = 0; - pr_info("%s: %s\n", __func__, clk->name); + pr_err("%s: %s\n", __func__, clk->name); /* Get the clock handle for vreg */ if (!clk->clk || clk->is_enabled) { @@ -505,7 +570,7 @@ static int bt_clk_disable(struct bt_power_clk_data *clk) { int rc = 0; - pr_debug("%s: %s\n", __func__, clk->name); + pr_err("%s: %s\n", __func__, clk->name); /* Get the clock handle for vreg */ if (!clk->clk || !clk->is_enabled) { @@ -521,7 +586,7 @@ static int bt_clk_disable(struct bt_power_clk_data *clk) static void btpower_set_xo_clk_gpio_state(bool enable) { - int xo_clk_gpio = bt_power_pdata->xo_gpio_clk; + int xo_clk_gpio = pwr_data->xo_gpio_clk; int retry = 0; int rc = 0; @@ -554,7 +619,7 @@ retry_gpio_req: gpio_direction_output(xo_clk_gpio, 0); } - pr_info("%s:gpio(%d) success\n", __func__, xo_clk_gpio); + pr_err("%s:gpio(%d) success\n", __func__, xo_clk_gpio); gpio_free(xo_clk_gpio); } @@ -562,36 +627,36 @@ retry_gpio_req: #ifdef CONFIG_MSM_BT_OOBS void bt_configure_wakeup_gpios(int on) { - int bt_gpio_dev_wake = bt_power_pdata->bt_gpio_dev_wake; - int bt_host_wake_gpio = bt_power_pdata->bt_gpio_host_wake; + int bt_gpio_dev_wake = pwr_data->bt_gpio_dev_wake; + int bt_host_wake_gpio = pwr_data->bt_gpio_host_wake; int rc; if (on) { if (gpio_is_valid(bt_gpio_dev_wake)) { gpio_set_value(bt_gpio_dev_wake, 1); - pr_debug("%s: BT-ON asserting BT_WAKE(%d)\n", __func__, + pr_err("%s: BT-ON asserting BT_WAKE(%d)\n", __func__, bt_gpio_dev_wake); } if (gpio_is_valid(bt_host_wake_gpio)) { - bt_power_pdata->irq = gpio_to_irq(bt_host_wake_gpio); - pr_debug("%s: BT-ON bt-host_wake-gpio(%d) IRQ(%d)\n", - __func__, bt_host_wake_gpio, bt_power_pdata->irq); - rc = request_irq(bt_power_pdata->irq, + pwr_data->irq = gpio_to_irq(bt_host_wake_gpio); + pr_err("%s: BT-ON bt-host_wake-gpio(%d) IRQ(%d)\n", + __func__, bt_host_wake_gpio, pwr_data->irq); + rc = request_irq(pwr_data->irq, btpower_host_wake_isr, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "btpower_hostwake_isr", bt_power_pdata); + "btpower_hostwake_isr", pwr_data); if (rc) pr_err("%s: unable to request IRQ %d (%d)\n", __func__, bt_host_wake_gpio, rc); } } else { if (gpio_is_valid(bt_host_wake_gpio)) { - pr_debug("%s: BT-OFF bt-hostwake-gpio(%d) IRQ(%d) value(%d)\n", - __func__, bt_host_wake_gpio, bt_power_pdata->irq, + pr_err("%s: BT-OFF bt-hostwake-gpio(%d) IRQ(%d) value(%d)\n", + __func__, bt_host_wake_gpio, pwr_data->irq, gpio_get_value(bt_host_wake_gpio)); - free_irq(bt_power_pdata->irq, bt_power_pdata); + free_irq(pwr_data->irq, pwr_data); } if (gpio_is_valid(bt_gpio_dev_wake)) @@ -603,10 +668,10 @@ void bt_configure_wakeup_gpios(int on) static int bt_configure_gpios(int on) { int rc = 0; - int bt_reset_gpio = bt_power_pdata->bt_gpio_sys_rst; - int wl_reset_gpio = bt_power_pdata->wl_gpio_sys_rst; - int bt_sw_ctrl_gpio = bt_power_pdata->bt_gpio_sw_ctrl; - int bt_debug_gpio = bt_power_pdata->bt_gpio_debug; + int bt_reset_gpio = pwr_data->bt_gpio_sys_rst; + int wl_reset_gpio = pwr_data->wl_gpio_sys_rst; + int bt_sw_ctrl_gpio = pwr_data->bt_gpio_sw_ctrl; + int bt_debug_gpio = pwr_data->bt_gpio_debug; int assert_dbg_gpio = 0; if (on) { @@ -616,79 +681,78 @@ static int bt_configure_gpios(int on) __func__, bt_reset_gpio, rc); return rc; } - - pr_info("BTON:Turn Bt OFF asserting BT_EN to low\n"); - pr_info("bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio, + pr_err("BTON:Turn Bt OFF asserting BT_EN to low\n"); + pr_err("bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio, gpio_get_value(bt_reset_gpio)); rc = gpio_direction_output(bt_reset_gpio, 0); if (rc) { pr_err("%s: Unable to set direction\n", __func__); return rc; } - bt_power_src_status[BT_RESET_GPIO] = + power_src.platform_state[BT_RESET_GPIO] = gpio_get_value(bt_reset_gpio); msleep(50); - pr_info("BTON:Turn Bt OFF post asserting BT_EN to low\n"); - pr_info("bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio, + pr_err("BTON:Turn Bt OFF post asserting BT_EN to low\n"); + pr_err("bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio, gpio_get_value(bt_reset_gpio)); if (bt_sw_ctrl_gpio >= 0) { - bt_power_src_status[BT_SW_CTRL_GPIO] = + power_src.platform_state[BT_SW_CTRL_GPIO] = gpio_get_value(bt_sw_ctrl_gpio); - rc = msm_gpio_mpm_wake_set(bt_power_pdata->sw_cntrl_gpio, 1); + rc = msm_gpio_mpm_wake_set(pwr_data->sw_cntrl_gpio, 1); if (rc < 0) { pr_err("Failed to set msm_gpio_mpm_wake_set for sw_cntrl gpio, ret: %d\n", rc); return rc; } else { - pr_info("Set msm_gpio_mpm_wake_set for sw_cntrl gpio successful\n"); + pr_err("Set msm_gpio_mpm_wake_set for sw_cntrl gpio successful\n"); } - pr_info("BTON:Turn Bt OFF bt-sw-ctrl-gpio(%d) value(%d)\n", + pr_err("BTON:Turn Bt OFF bt-sw-ctrl-gpio(%d) value(%d)\n", bt_sw_ctrl_gpio, - bt_power_src_status[BT_SW_CTRL_GPIO]); + power_src.platform_state[BT_SW_CTRL_GPIO]); } if (wl_reset_gpio >= 0) - pr_info("BTON:Turn Bt ON wl-reset-gpio(%d) value(%d)\n", + pr_err("BTON:Turn Bt ON wl-reset-gpio(%d) value(%d)\n", wl_reset_gpio, gpio_get_value(wl_reset_gpio)); if ((wl_reset_gpio < 0) || ((wl_reset_gpio >= 0) && gpio_get_value(wl_reset_gpio))) { btpower_set_xo_clk_gpio_state(true); - pr_info("BTON: WLAN ON Asserting BT_EN to high\n"); + pr_err("BTON: WLAN ON Asserting BT_EN to high\n"); rc = gpio_direction_output(bt_reset_gpio, 1); if (rc) { pr_err("%s: Unable to set direction\n", __func__); return rc; } - bt_power_src_status[BT_RESET_GPIO] = + power_src.platform_state[BT_RESET_GPIO] = gpio_get_value(bt_reset_gpio); btpower_set_xo_clk_gpio_state(false); } if ((wl_reset_gpio >= 0) && (gpio_get_value(wl_reset_gpio) == 0)) { if (gpio_get_value(bt_reset_gpio)) { - pr_info("BTON: WLAN OFF and BT ON are too close\n"); - pr_info("reset BT_EN, enable it after delay\n"); + pr_err("BTON: WLAN OFF and BT ON are too close\n"); + pr_err("reset BT_EN, enable it after delay\n"); rc = gpio_direction_output(bt_reset_gpio, 0); if (rc) { pr_err("%s: Unable to set direction\n", __func__); return rc; } - bt_power_src_status[BT_RESET_GPIO] = + power_src.platform_state[BT_RESET_GPIO] = gpio_get_value(bt_reset_gpio); } - pr_info("BTON: WLAN OFF waiting for 100ms delay\n"); - pr_info("for AON output to fully discharge\n"); + pr_err("BTON: WLAN OFF waiting for 100ms delay\n"); + pr_err("for AON output to fully discharge\n"); msleep(100); - pr_info("BTON: WLAN OFF Asserting BT_EN to high\n"); + pr_err("BTON: WLAN OFF Asserting BT_EN to high\n"); btpower_set_xo_clk_gpio_state(true); rc = gpio_direction_output(bt_reset_gpio, 1); if (rc) { pr_err("%s: Unable to set direction\n", __func__); return rc; } - bt_power_src_status[BT_RESET_GPIO] = + power_src.platform_state[BT_RESET_GPIO] = gpio_get_value(bt_reset_gpio); btpower_set_xo_clk_gpio_state(false); } @@ -698,14 +762,14 @@ static int bt_configure_gpios(int on) */ if (!gpio_get_value(bt_reset_gpio)) { btpower_set_xo_clk_gpio_state(true); - pr_info("BTON: WLAN ON and BT ON are too close\n"); - pr_info("Asserting BT_EN to high\n"); + pr_err("BTON: WLAN ON and BT ON are too close\n"); + pr_err("Asserting BT_EN to high\n"); rc = gpio_direction_output(bt_reset_gpio, 1); if (rc) { pr_err("%s: Unable to set direction\n", __func__); return rc; } - bt_power_src_status[BT_RESET_GPIO] = + power_src.platform_state[BT_RESET_GPIO] = gpio_get_value(bt_reset_gpio); btpower_set_xo_clk_gpio_state(false); } @@ -736,14 +800,14 @@ static int bt_configure_gpios(int on) __func__); } } - pr_info("BTON:Turn Bt On bt-reset-gpio(%d) value(%d)\n", + pr_err("BTON:Turn Bt On bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio, gpio_get_value(bt_reset_gpio)); if (bt_sw_ctrl_gpio >= 0) { - bt_power_src_status[BT_SW_CTRL_GPIO] = + power_src.platform_state[BT_SW_CTRL_GPIO] = gpio_get_value(bt_sw_ctrl_gpio); - pr_info("BTON: Turn BT ON bt-sw-ctrl-gpio(%d) value(%d)\n", + pr_err("BTON: Turn BT ON bt-sw-ctrl-gpio(%d) value(%d)\n", bt_sw_ctrl_gpio, - bt_power_src_status[BT_SW_CTRL_GPIO]); + power_src.platform_state[BT_SW_CTRL_GPIO]); } } else { #ifdef CONFIG_MSM_BT_OOBS @@ -751,102 +815,316 @@ static int bt_configure_gpios(int on) #endif gpio_set_value(bt_reset_gpio, 0); msleep(100); - pr_info("BT-OFF:bt-reset-gpio(%d) value(%d)\n", + pr_err("BT-OFF:bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio, gpio_get_value(bt_reset_gpio)); if (bt_sw_ctrl_gpio >= 0) { - pr_info("BT-OFF:bt-sw-ctrl-gpio(%d) value(%d)\n", + pr_err("BT-OFF:bt-sw-ctrl-gpio(%d) value(%d)\n", bt_sw_ctrl_gpio, gpio_get_value(bt_sw_ctrl_gpio)); } } - pr_info("%s: bt_gpio= %d on: %d\n", __func__, bt_reset_gpio, on); + pr_err("%s: bt_gpio= %d on: %d\n", __func__, bt_reset_gpio, on); return rc; } -static int bluetooth_power(int on) +static int bt_regulators_pwr(int pwr_state) { - int rc = 0; + int i, log_indx, bt_num_vregs, rc = 0; + struct vreg_data *bt_vregs = NULL; - pr_info("%s: on: %d\n", __func__, on); + rc = perisec_cnss_bt_hw_disable_check(pwr_data); - rc = perisec_cnss_bt_hw_disable_check(bt_power_pdata); - if (on == 1) { - if (bt_power_pdata->bt_sec_hw_disable) { + bt_num_vregs = pwr_data->bt_num_vregs; + + if (!bt_num_vregs) { + pr_warn("%s: not avilable to %s\n", + __func__, reg_mode[pwr_state]); + return 0; + } + + pr_err("%s: %s\n", __func__, reg_mode[pwr_state]); + + if (pwr_state == POWER_ENABLE) { + /* Power On */ + if (pwr_data->bt_sec_hw_disable) { pr_err("%s:secure hw mode on,BT ON not allowed", __func__); return -EINVAL; } - rc = bt_power_vreg_set(BT_POWER_ENABLE); - if (rc < 0) { - pr_err("%s: bt_power regulators config failed\n", - __func__); - goto regulator_fail; + + for (i = 0; i < bt_num_vregs; i++) { + bt_vregs = &pwr_data->bt_vregs[i]; + log_indx = bt_vregs->indx.init; + if (bt_vregs->reg) { + power_src.bt_state[log_indx] = DEFAULT_INVALID_VALUE; + rc = vreg_enable(bt_vregs); + if (rc < 0) { + pr_err("%s: bt_power regulators config failed\n", + __func__); + goto regulator_fail; + } + if (bt_vregs->is_enabled) + power_src.bt_state[log_indx] = + regulator_get_voltage(bt_vregs->reg); + } } + /* Parse dt_info and check if a target requires clock voting. * Enable BT clock when BT is on and disable it when BT is off */ - if (bt_power_pdata->bt_chip_clk) { - rc = bt_clk_enable(bt_power_pdata->bt_chip_clk); + if (pwr_data->bt_chip_clk) { + rc = bt_clk_enable(pwr_data->bt_chip_clk); if (rc < 0) { pr_err("%s: bt_power gpio config failed\n", __func__); goto clk_fail; } } - if (bt_power_pdata->bt_gpio_sys_rst > 0) { - bt_power_src_status[BT_RESET_GPIO] = - DEFAULT_INVALID_VALUE; - bt_power_src_status[BT_SW_CTRL_GPIO] = - DEFAULT_INVALID_VALUE; - rc = bt_configure_gpios(on); + if (pwr_data->bt_gpio_sys_rst > 0) { + power_src.bt_state[BT_RESET_GPIO] = DEFAULT_INVALID_VALUE; + power_src.bt_state[BT_SW_CTRL_GPIO] = DEFAULT_INVALID_VALUE; + rc = bt_configure_gpios(POWER_ENABLE); if (rc < 0) { pr_err("%s: bt_power gpio config failed\n", __func__); goto gpio_fail; } } - } else if (on == 0) { - // Power Off - if (bt_power_pdata->bt_gpio_sys_rst > 0) { - if (bt_power_pdata->bt_sec_hw_disable) { + } else if (pwr_state == POWER_DISABLE) { + /* Power Off */ + if (pwr_data->bt_gpio_sys_rst > 0) { + if (pwr_data->bt_sec_hw_disable) { pr_err("%s: secure hw mode on, not allowed to access gpio", __func__); }else { - bt_configure_gpios(on); + bt_configure_gpios(POWER_DISABLE); } } gpio_fail: - if (bt_power_pdata->bt_gpio_sys_rst > 0) - gpio_free(bt_power_pdata->bt_gpio_sys_rst); - if (bt_power_pdata->bt_gpio_debug > 0) - gpio_free(bt_power_pdata->bt_gpio_debug); - if (bt_power_pdata->bt_chip_clk) - bt_clk_disable(bt_power_pdata->bt_chip_clk); + if (pwr_data->bt_gpio_sys_rst > 0) + gpio_free(pwr_data->bt_gpio_sys_rst); + if (pwr_data->bt_gpio_debug > 0) + gpio_free(pwr_data->bt_gpio_debug); + if (pwr_data->bt_chip_clk) + bt_clk_disable(pwr_data->bt_chip_clk); clk_fail: regulator_fail: - bt_power_vreg_set(BT_POWER_DISABLE); - } else if (on == 2) { + for (i = 0; i < bt_num_vregs; i++) { + bt_vregs = &pwr_data->bt_vregs[i]; + rc = vreg_disable(bt_vregs); + } + } else if (pwr_state == POWER_RETENTION) { /* Retention mode */ - bt_power_vreg_set(BT_POWER_RETENTION); + for (i = 0; i < bt_num_vregs; i++) { + bt_vregs = &pwr_data->bt_vregs[i]; + rc = vreg_enable_retention(bt_vregs); + } } else { - pr_err("%s: Invalid power mode: %d\n", __func__, on); + pr_err("%s: Invalid power mode: %d\n", __func__, pwr_state); rc = -1; } return rc; } +static int uwb_regulators_pwr(int pwr_state) +{ + int i, log_indx, uwb_num_vregs, rc = 0; + struct vreg_data *uwb_vregs = NULL; + + rc = perisec_cnss_bt_hw_disable_check(pwr_data); + + uwb_num_vregs = pwr_data->uwb_num_vregs; + + if (!uwb_num_vregs) { + pr_warn("%s: not avilable to %s\n", + __func__, reg_mode[pwr_state]); + return 0; + } + + pr_err("%s: %s\n", __func__, reg_mode[pwr_state]); + + switch (pwr_state) { + case POWER_ENABLE: + for (i = 0; i < uwb_num_vregs; i++) { + uwb_vregs = &pwr_data->uwb_vregs[i]; + log_indx = uwb_vregs->indx.init; + if (uwb_vregs->reg) { + power_src.uwb_state[log_indx] = DEFAULT_INVALID_VALUE; + rc = vreg_enable(uwb_vregs); + if (rc < 0) { + pr_err("%s: UWB regulators config failed\n", + __func__); + goto UWB_regulator_fail; + } + if (uwb_vregs->is_enabled) + power_src.uwb_state[log_indx] = + regulator_get_voltage(uwb_vregs->reg); + } + } + + rc = bt_configure_gpios(POWER_ENABLE); + if (rc < 0) { + pr_err("%s: bt_power gpio config failed\n", + __func__); + goto UWB_gpio_fail; + } + + break; + case POWER_DISABLE: + rc = bt_configure_gpios(POWER_DISABLE); + if (rc < 0) { + pr_err("%s: bt_power gpio config failed\n", + __func__); + goto UWB_gpio_fail; + } +UWB_gpio_fail: + + +UWB_regulator_fail: + for (i = 0; i < uwb_num_vregs; i++) { + uwb_vregs = &pwr_data->uwb_vregs[i]; + rc = vreg_disable(uwb_vregs); + } + break; + case POWER_RETENTION: + for (i = 0; i < uwb_num_vregs; i++) { + uwb_vregs = &pwr_data->uwb_vregs[i]; + rc = vreg_enable_retention(uwb_vregs); + } + break; + } + return rc; +} + +static int platform_regulators_pwr(int pwr_state) +{ + int i, log_indx, platform_num_vregs, rc = 0; + struct vreg_data *platform_vregs = NULL; + + rc = perisec_cnss_bt_hw_disable_check(pwr_data); + + platform_num_vregs = pwr_data->platform_num_vregs; + + if (!platform_num_vregs) { + pr_warn("%s: not avilable to %s\n", + __func__, reg_mode[pwr_state]); + return 0; + } + + pr_err("%s: %s\n", __func__, reg_mode[pwr_state]); + + switch (pwr_state) { + case POWER_ENABLE: + for (i = 0; i < platform_num_vregs; i++) { + platform_vregs = &pwr_data->platform_vregs[i]; + log_indx = platform_vregs->indx.init; + if (platform_vregs->reg) { + power_src.platform_state[log_indx] = DEFAULT_INVALID_VALUE; + rc = vreg_enable(platform_vregs); + if (rc < 0) { + pr_err("%s: Platform regulators config failed\n", + __func__); + goto Platform_regulator_fail; + } + if (platform_vregs->is_enabled) { + power_src.platform_state[log_indx] = regulator_get_voltage(platform_vregs->reg); + } + } + } + + rc = bt_configure_gpios(POWER_ENABLE); + if (rc < 0) { + pr_err("%s: bt_power gpio config failed\n", + __func__); + goto Platform_gpio_fail; + } + + break; + case POWER_DISABLE: + rc = bt_configure_gpios(POWER_DISABLE); + if (rc < 0) { + pr_err("%s: bt_power gpio config failed\n", + __func__); + } + +Platform_gpio_fail: + if (pwr_data->bt_gpio_sys_rst > 0) + gpio_free(pwr_data->bt_gpio_sys_rst); + if (pwr_data->bt_gpio_debug > 0) + gpio_free(pwr_data->bt_gpio_debug); + +Platform_regulator_fail: + for (i = 0; i < platform_num_vregs; i++) { + platform_vregs = &pwr_data->platform_vregs[i]; + rc = vreg_disable(platform_vregs); + } + break; + case POWER_RETENTION: + for (i=0; i < platform_num_vregs; i++) { + platform_vregs = &pwr_data->platform_vregs[i]; + rc = vreg_enable_retention(platform_vregs); + } + break; + case POWER_DISABLE_RETENTION: + for (i = 0; i < platform_num_vregs; i++) { + platform_vregs = &pwr_data->platform_vregs[i]; + rc = vreg_disable_retention(platform_vregs); + } + break; + } + return rc; +} + +static int power_regulators(int core_type, int mode) { + + int ret = 0; + + if ((mode != POWER_DISABLE) && (mode != POWER_ENABLE) && + (mode != POWER_RETENTION)) { + pr_err("%s: Received wrong Mode to do regulator operation\n", + __func__); + return -1; + } + + switch (core_type) { + case BT_CORE: + ret = bt_regulators_pwr(mode); + if (ret) + pr_err("%s: Failed to configure BT regulators to mode(%d)\n", + __func__, mode); + break; + case UWB_CORE: + ret = uwb_regulators_pwr(mode); + if (ret) + pr_err("%s: Failed to configure UWB regulators to mode(%d)\n", + __func__, mode); + break; + case PLATFORM_CORE: + ret = platform_regulators_pwr(mode); + if (ret) + pr_err("%s: Failed to configure platform regulators to mode(%d)\n", + __func__, mode); + break; + default: + pr_err("%s: Received wrong Core Type to do regulator operation\n", + __func__); + return -1; + } + return ret; +} + static int btpower_toggle_radio(void *data, bool blocked) { int ret = 0; - int (*power_control)(int enable); + int (*power_control)(int Core, int enable); power_control = - ((struct btpower_platform_data *)data)->bt_power_setup; + ((struct platform_pwr_data *)data)->power_setup; if (previous != blocked) - ret = (*power_control)(!blocked); + ret = (*power_control)(BT_CORE, !blocked); if (!ret) previous = blocked; return ret; @@ -903,7 +1181,7 @@ static void btpower_rfkill_remove(struct platform_device *pdev) { struct rfkill *rfkill; - pr_debug("%s\n", __func__); + pr_info("%s\n", __func__); rfkill = platform_get_drvdata(pdev); if (rfkill) @@ -912,18 +1190,18 @@ static void btpower_rfkill_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); } -#define MAX_PROP_SIZE 32 -static int bt_dt_parse_vreg_info(struct device *dev, - struct bt_power_vreg_data *vreg_data) +static int dt_parse_vreg_info(struct device *dev, struct device_node *child, + struct vreg_data *vreg_data) { int len, ret = 0; const __be32 *prop; char prop_name[MAX_PROP_SIZE]; - struct bt_power_vreg_data *vreg = vreg_data; - struct device_node *np = dev->of_node; + struct vreg_data *vreg = vreg_data; + struct device_node *np = child; const char *vreg_name = vreg_data->name; - pr_debug("%s: vreg dev tree parse for %s\n", __func__, vreg_name); + if (!child) + np = dev->of_node; snprintf(prop_name, sizeof(prop_name), "%s-supply", vreg_name); if (of_parse_phandle(np, prop_name, 0)) { @@ -937,9 +1215,9 @@ static int bt_dt_parse_vreg_info(struct device *dev, } snprintf(prop_name, sizeof(prop_name), "%s-config", vreg->name); - prop = of_get_property(dev->of_node, prop_name, &len); + prop = of_get_property(np, prop_name, &len); if (!prop || len != (4 * sizeof(__be32))) { - pr_debug("%s: Property %s %s, use default\n", + pr_err("%s: Property %s %s, use default\n", __func__, prop_name, prop ? "invalid format" : "doesn't exist"); } else { @@ -949,14 +1227,13 @@ static int bt_dt_parse_vreg_info(struct device *dev, vreg->is_retention_supp = be32_to_cpup(&prop[3]); } - pr_debug("%s: Got regulator: %s, min_vol: %u, max_vol: %u, load_curr: %u,is_retention_supp: %u\n", + pr_err("%s: Got regulator: %s, min_vol: %u, max_vol: %u, load_curr: %u, is_retention_supp: %u\n", __func__, vreg->name, vreg->min_vol, vreg->max_vol, vreg->load_curr, vreg->is_retention_supp); } else { - pr_info("%s: %s is not provided in device tree\n", __func__, + pr_err("%s: %s is not provided in device tree\n", __func__, vreg_name); } - return ret; } @@ -967,7 +1244,7 @@ static int bt_dt_parse_clk_info(struct device *dev, struct bt_power_clk_data *clk = NULL; struct device_node *np = dev->of_node; - pr_debug("%s\n", __func__); + pr_info("%s\n", __func__); *clk_data = NULL; if (of_parse_phandle(np, "clocks", 0)) { @@ -1007,10 +1284,84 @@ err: return ret; } -static int bt_power_vreg_get(struct platform_device *pdev) +static void bt_power_vreg_put(void) { - int num_vregs, i = 0, ret = 0; - const struct bt_power *data; + int i = 0; + struct vreg_data *bt_vregs = NULL; + int bt_num_vregs = pwr_data->bt_num_vregs; + + for (; i < bt_num_vregs; i++) { + bt_vregs = &pwr_data->bt_vregs[i]; + if (bt_vregs->reg) + regulator_put(bt_vregs->reg); + } +} + +static int get_gpio_dt_pinfo(struct platform_device *pdev) { + + int ret; + struct device_node *child; + + child = pdev->dev.of_node; + + pwr_data->bt_gpio_sys_rst = + of_get_named_gpio(child, + "qcom,bt-reset-gpio", 0); + if (pwr_data->bt_gpio_sys_rst < 0) + pr_err("bt-reset-gpio not provided in devicetree\n"); + + pwr_data->wl_gpio_sys_rst = + of_get_named_gpio(child, + "qcom,wl-reset-gpio", 0); + if (pwr_data->wl_gpio_sys_rst < 0) + pr_err("%s: wl-reset-gpio not provided in device tree\n", + __func__); + + ret = of_property_read_u32(child, "mpm_wake_set_gpios", + &pwr_data->sw_cntrl_gpio); + if (ret) + pr_warn("sw_cntrl-gpio not provided in devicetree\n"); + + pwr_data->bt_gpio_sw_ctrl = + of_get_named_gpio(child, + "qcom,bt-sw-ctrl-gpio", 0); + if (pwr_data->bt_gpio_sw_ctrl < 0) + pr_err("bt-sw-ctrl-gpio not provided in devicetree\n"); + + pwr_data->bt_gpio_debug = + of_get_named_gpio(child, + "qcom,bt-debug-gpio", 0); + if (pwr_data->bt_gpio_debug < 0) + pr_warn("bt-debug-gpio not provided in devicetree\n"); + + pwr_data->xo_gpio_clk = + of_get_named_gpio(child, + "qcom,xo-clk-gpio", 0); + if (pwr_data->xo_gpio_clk < 0) + pr_warn("xo-clk-gpio not provided in devicetree\n"); + +#ifdef CONFIG_MSM_BT_OOBS + pwr_data->bt_gpio_dev_wake = + of_get_named_gpio(child, + "qcom,btwake_gpio", 0); + if (pwr_data->bt_gpio_dev_wake < 0) + pr_warn("%s: btwake-gpio not provided in device tree\n", + __func__); + + pwr_data->bt_gpio_host_wake = + of_get_named_gpio(child, + "qcom,bthostwake_gpio", 0); + if (pwr_data->bt_gpio_host_wake < 0) + pr_warn("%s: bthostwake_gpio not provided in device tree\n", + __func__); +#endif + return true; +} + +static int get_power_dt_pinfo(struct platform_device *pdev) +{ + int rc, i; + const struct pwr_data *data; data = of_device_get_match_data(&pdev->dev); if (!data) { @@ -1018,158 +1369,105 @@ static int bt_power_vreg_get(struct platform_device *pdev) return -EINVAL; } - memcpy(&bt_power_pdata->compatible, &data->compatible, MAX_PROP_SIZE); - bt_power_pdata->vreg_info = data->vregs; - num_vregs = bt_power_pdata->num_vregs = data->num_vregs; - for (; i < num_vregs; i++) { - ret = bt_dt_parse_vreg_info(&(pdev->dev), - &bt_power_pdata->vreg_info[i]); - /* No point to go further if failed to get regulator handler */ - if (ret) - break; - } + memcpy(&pwr_data->compatible, &data->compatible, MAX_PROP_SIZE); - return ret; -} + pwr_data->bt_vregs = data->bt_vregs; + pwr_data->bt_num_vregs = data->bt_num_vregs; -static int bt_power_vreg_set(enum bt_power_modes mode) -{ - int num_vregs, i = 0, ret = 0; - int log_indx; - struct bt_power_vreg_data *vreg_info = NULL; + if (pwr_data->is_ganges_dt) { + pwr_data->uwb_vregs = data->uwb_vregs; + pwr_data->platform_vregs = data->platform_vregs; + pwr_data->uwb_num_vregs = data->uwb_num_vregs; + pwr_data->platform_num_vregs = data->platform_num_vregs; - num_vregs = bt_power_pdata->num_vregs; - if (mode == BT_POWER_ENABLE) { - for (; i < num_vregs; i++) { - vreg_info = &bt_power_pdata->vreg_info[i]; - log_indx = vreg_info->indx.init; - if (vreg_info->reg) { - bt_power_src_status[log_indx] = - DEFAULT_INVALID_VALUE; - ret = bt_vreg_enable(vreg_info); - if (ret < 0) - goto out; - if (vreg_info->is_enabled) { - bt_power_src_status[log_indx] = - regulator_get_voltage( - vreg_info->reg); - } - } - } - } else if (mode == BT_POWER_DISABLE) { - for (; i < num_vregs; i++) { - vreg_info = &bt_power_pdata->vreg_info[i]; - ret = bt_vreg_disable(vreg_info); - } - } else if (mode == BT_POWER_RETENTION) { - for (; i < num_vregs; i++) { - vreg_info = &bt_power_pdata->vreg_info[i]; - ret = bt_vreg_enable_retention(vreg_info); - } + pr_err("%s: bt_num_vregs =%d uwb_num_vregs =%d platform_num_vregs=%d\n", + __func__, pwr_data->bt_num_vregs, pwr_data->uwb_num_vregs, + pwr_data->platform_num_vregs); } else { - pr_err("%s: Invalid power mode: %d\n", __func__, mode); - ret = -1; + pr_err("%s: bt_num_vregs =%d\n", __func__, pwr_data->bt_num_vregs); } -out: - return ret; -} -static void bt_power_vreg_put(void) -{ - int i = 0; - struct bt_power_vreg_data *vreg_info = NULL; - int num_vregs = bt_power_pdata->num_vregs; - - for (; i < num_vregs; i++) { - vreg_info = &bt_power_pdata->vreg_info[i]; - if (vreg_info->reg) - regulator_put(vreg_info->reg); + for (i = 0; i < pwr_data->bt_num_vregs; i++) { + rc = dt_parse_vreg_info(&(pdev->dev), pwr_data->bt_of_node, + &pwr_data->bt_vregs[i]); + /* No point to go further if failed to get regulator handler */ + if (rc) + return rc; } + + if(pwr_data->is_ganges_dt) { + for (i = 0; i < pwr_data->platform_num_vregs; i++) { + rc = dt_parse_vreg_info(&(pdev->dev), NULL, + &pwr_data->platform_vregs[i]); + /* No point to go further if failed to get regulator handler */ + if (rc) + return rc; + } + + for (i = 0; i < pwr_data->uwb_num_vregs; i++) { + rc = dt_parse_vreg_info(&(pdev->dev), pwr_data->uwb_of_node, + &pwr_data->uwb_vregs[i]); + /* No point to go further if failed to get regulator handler */ + if (rc) + return rc; + } + } + return rc; } static int bt_power_populate_dt_pinfo(struct platform_device *pdev) { + struct device_node *of_node; int rc; - pr_debug("%s\n", __func__); - if (!bt_power_pdata) + pr_info("%s\n", __func__); + + if (!pwr_data) return -ENOMEM; - if (pdev->dev.of_node) { - rc = bt_power_vreg_get(pdev); - if (rc) - return rc; - - bt_power_pdata->bt_gpio_sys_rst = - of_get_named_gpio(pdev->dev.of_node, - "qcom,bt-reset-gpio", 0); - if (bt_power_pdata->bt_gpio_sys_rst < 0) - pr_warn("bt-reset-gpio not provided in devicetree\n"); - - bt_power_pdata->wl_gpio_sys_rst = - of_get_named_gpio(pdev->dev.of_node, - "qcom,wl-reset-gpio", 0); - if (bt_power_pdata->wl_gpio_sys_rst < 0) - pr_err("%s: wl-reset-gpio not provided in device tree\n", - __func__); - - - bt_power_pdata->bt_gpio_sw_ctrl = - of_get_named_gpio(pdev->dev.of_node, - "qcom,bt-sw-ctrl-gpio", 0); - if (bt_power_pdata->bt_gpio_sw_ctrl < 0) - pr_warn("bt-sw-ctrl-gpio not provided in devicetree\n"); - - rc = of_property_read_u32(pdev->dev.of_node, - "mpm_wake_set_gpios",&bt_power_pdata->sw_cntrl_gpio); - if (rc) - pr_warn("sw_cntrl-gpio not provided in devicetree\n"); - - bt_power_pdata->bt_gpio_debug = - of_get_named_gpio(pdev->dev.of_node, - "qcom,bt-debug-gpio", 0); - if (bt_power_pdata->bt_gpio_debug < 0) - pr_warn("bt-debug-gpio not provided in devicetree\n"); - - bt_power_pdata->xo_gpio_clk = - of_get_named_gpio(pdev->dev.of_node, - "qcom,xo-clk-gpio", 0); - if (bt_power_pdata->xo_gpio_clk < 0) - pr_warn("xo-clk-gpio not provided in devicetree\n"); - - rc = bt_dt_parse_clk_info(&pdev->dev, - &bt_power_pdata->bt_chip_clk); - if (rc < 0) - pr_warn("%s: clock not provided in device tree\n", - __func__); -#ifdef CONFIG_MSM_BT_OOBS - bt_power_pdata->bt_gpio_dev_wake = - of_get_named_gpio(pdev->dev.of_node, - "qcom,btwake_gpio", 0); - if (bt_power_pdata->bt_gpio_dev_wake < 0) - pr_warn("%s: btwake-gpio not provided in device tree\n", - __func__); - - - bt_power_pdata->bt_gpio_host_wake = - of_get_named_gpio(pdev->dev.of_node, - "qcom,bthostwake_gpio", 0); - if (bt_power_pdata->bt_gpio_host_wake < 0) - pr_warn("%s: bthostwake_gpio not provided in device tree\n", - __func__); -#endif + if (pwr_data->is_ganges_dt) { + for_each_available_child_of_node(pdev->dev.of_node, of_node) { + if (!strcmp(of_node->name, "bt_ganges")) { + pwr_data->bt_of_node = of_node; + pr_err("%s: %s device node found\n", __func__, + pwr_data->bt_of_node->name); + } else if (!strcmp(of_node->name, "uwb_ganges")) { + pwr_data->uwb_of_node = of_node; + pr_err("%s: %s device node found\n", __func__, + pwr_data->uwb_of_node->name); + } + } } - bt_power_pdata->bt_power_setup = bluetooth_power; + rc = get_power_dt_pinfo(pdev); + if (rc < 0) + pr_err("%s: failed to get the pin info from the DTSI\n", + __func__); + + rc = get_gpio_dt_pinfo(pdev); + + if (rc < 0) + pr_err("%s: failed to get the gpio info from the DTSI\n", + __func__); + + bt_dt_parse_clk_info(&pdev->dev, + &pwr_data->bt_chip_clk); + + pwr_data->power_setup = power_regulators; return 0; } -static void bt_power_pdc_init_params (struct btpower_platform_data *pdata) +static inline bool bt_is_ganges_dt(struct platform_device *plat_dev) { + return of_property_read_bool(plat_dev->dev.of_node, "qcom,peach-bt"); +} + +static void bt_power_pdc_init_params(struct platform_pwr_data *pdata) { int ret; struct device *dev = &pdata->pdev->dev; + pdata->pdc_init_table_len = of_property_count_strings(dev->of_node, "qcom,pdc_init_table"); if (pdata->pdc_init_table_len > 0) { @@ -1180,34 +1478,100 @@ static void bt_power_pdc_init_params (struct btpower_platform_data *pdata) if (ret < 0) pr_err("Failed to get PDC Init Table\n"); else - pr_info("PDC Init table configured\n"); + pr_err("PDC Init table configured\n"); } else { - pr_debug("PDC Init Table not configured\n"); + pr_err("PDC Init Table not configured\n"); } } +static void bt_signal_handler(struct work_struct *w_arg) +{ + struct kernel_siginfo siginfo; + int rc = 0; + + // Sending signal to HAL layer + memset(&siginfo, 0, sizeof(siginfo)); + siginfo.si_signo = SIGIO; + siginfo.si_code = SI_QUEUE; + siginfo.si_int = pwr_data->wrkq_signal_state; + rc = send_sig_info(siginfo.si_signo, &siginfo, pwr_data->reftask_bt); + if (rc < 0) { + pr_err("%s: failed (%d) to send SIG to HAL(%d)\n", __func__, + rc, pwr_data->reftask_bt->pid); + return; + } + pr_err("%s Succesfull\n", __func__); +} + +static void uwb_signal_handler(struct work_struct *w_arg) +{ + struct kernel_siginfo siginfo; + int rc = 0; + + // Sending signal to HAL layer + memset(&siginfo, 0, sizeof(siginfo)); + siginfo.si_signo = SIGIO; + siginfo.si_code = SI_QUEUE; + siginfo.si_int = pwr_data->wrkq_signal_state; + rc = send_sig_info(siginfo.si_signo, &siginfo, pwr_data->reftask_uwb); + if (rc < 0) { + pr_err("%s: failed (%d) to send SIG to HAL(%d)\n", __func__, + rc, pwr_data->reftask_uwb->pid); + return; + } + pr_err("%s Succesfull\n", __func__); +} + static int bt_power_probe(struct platform_device *pdev) { int ret = 0; int itr; - pr_debug("%s\n", __func__); - /* Fill whole array with -2 i.e NOT_AVAILABLE state by default * for any GPIO or Reg handle. */ - for (itr = PWR_SRC_INIT_STATE_IDX; - itr < BT_POWER_SRC_SIZE; ++itr) - bt_power_src_status[itr] = PWR_SRC_NOT_AVAILABLE; + for (itr = PWR_SRC_INIT_STATE_IDX; itr < BT_POWER_SRC_SIZE; ++itr) { + power_src.bt_state[itr] = PWR_SRC_NOT_AVAILABLE; + power_src.platform_state[itr] = PWR_SRC_NOT_AVAILABLE; + power_src.uwb_state[itr] = PWR_SRC_NOT_AVAILABLE; + } - bt_power_pdata = kzalloc(sizeof(*bt_power_pdata), GFP_KERNEL); + pwr_data = kzalloc(sizeof(*pwr_data), GFP_KERNEL); - if (!bt_power_pdata) + if (!pwr_data) return -ENOMEM; - bt_power_pdata->pdev = pdev; + pwr_data->pdev = pdev; + + pwr_data->is_ganges_dt = of_property_read_bool(pdev->dev.of_node, + "qcom,peach-bt"); + + pr_info("%s: is_ganges_dt = %d\n", __func__, pwr_data->is_ganges_dt); + + pwr_data->workq = alloc_workqueue("workq", WQ_HIGHPRI, WQ_DFL_ACTIVE); + if (!pwr_data->workq) { + pr_err("%s: Failed to creat the Work Queue (workq)\n", + __func__); + return -ENOMEM; + } + + INIT_WORK(&pwr_data->uwb_wq, uwb_signal_handler); + INIT_WORK(&pwr_data->bt_wq, bt_signal_handler); + INIT_WORK(&pwr_data->wq_pwr_voting, bt_power_vote); + + for (itr = 0; itr < BTPWR_MAX_REQ; itr++) + init_waitqueue_head(&pwr_data->rsp_wait_q[itr]); + + skb_queue_head_init(&pwr_data->rxq); + mutex_init(&pwr_data->pwr_mtx); + mutex_init(&pwr_data->btpower_state.state_machine_lock); + pwr_data->btpower_state.power_state = IDLE; + pwr_data->btpower_state.retention_mode = RETENTION_IDLE; + pwr_data->btpower_state.grant_state = NO_GRANT_FOR_ANY_SS; + pwr_data->btpower_state.grant_pending = NO_OTHER_CLIENT_WAITING_FOR_GRANT; + + perisec_cnss_bt_hw_disable_check(pwr_data); - ret = perisec_cnss_bt_hw_disable_check(bt_power_pdata); if (pdev->dev.of_node) { ret = bt_power_populate_dt_pinfo(pdev); if (ret < 0) { @@ -1215,37 +1579,38 @@ static int bt_power_probe(struct platform_device *pdev) __func__); goto free_pdata; } - if (bt_power_pdata->bt_sec_hw_disable) { + if (pwr_data->bt_sec_hw_disable) { pr_info("%s: bt is in secure mode\n", __func__); } else { pr_info(" %s:send platform data of btpower\n", __func__); - pdev->dev.platform_data = bt_power_pdata; + pdev->dev.platform_data = pwr_data; } } else if (pdev->dev.platform_data) { /* Optional data set to default if not provided */ - if (!((struct btpower_platform_data *) - (pdev->dev.platform_data))->bt_power_setup) - ((struct btpower_platform_data *) - (pdev->dev.platform_data))->bt_power_setup = - bluetooth_power; + if (!((struct platform_pwr_data *) + (pdev->dev.platform_data))->power_setup) + ((struct platform_pwr_data *) + (pdev->dev.platform_data))->power_setup = + power_regulators; - memcpy(bt_power_pdata, pdev->dev.platform_data, - sizeof(struct btpower_platform_data)); - pwr_state = 0; + memcpy(pwr_data, pdev->dev.platform_data, + sizeof(struct platform_pwr_data)); } else { pr_err("%s: Failed to get platform data\n", __func__); goto free_pdata; } + if (btpower_rfkill_probe(pdev) < 0) goto free_pdata; - bt_power_pdc_init_params(bt_power_pdata); - btpower_aop_mbox_init(bt_power_pdata); + + bt_power_pdc_init_params(pwr_data); + btpower_aop_mbox_init(pwr_data); probe_finished = true; return 0; free_pdata: - kfree(bt_power_pdata); + kfree(pwr_data); return ret; } @@ -1257,150 +1622,783 @@ static int bt_power_remove(struct platform_device *pdev) btpower_rfkill_remove(pdev); bt_power_vreg_put(); - kfree(bt_power_pdata); + kfree(pwr_data); return 0; } int btpower_register_slimdev(struct device *dev) { - pr_debug("%s\n", __func__); - if (!bt_power_pdata || (dev == NULL)) { + pr_info("%s\n", __func__); + if (!pwr_data || (dev == NULL)) { pr_err("%s: Failed to allocate memory\n", __func__); return -EINVAL; } - bt_power_pdata->slim_dev = dev; + pwr_data->slim_dev = dev; return 0; } + EXPORT_SYMBOL(btpower_register_slimdev); int btpower_get_chipset_version(void) { - pr_debug("%s\n", __func__); + pr_info("%s\n", __func__); return soc_id; } EXPORT_SYMBOL(btpower_get_chipset_version); -static void set_pwr_srcs_status(struct bt_power_vreg_data *handle) -{ - int ldo_index; +static void set_pwr_srcs_status (struct vreg_data *handle, int core_type) { + int power_src_state; - if (handle) { - ldo_index = handle->indx.crash; - bt_power_src_status[ldo_index] = - DEFAULT_INVALID_VALUE; - if (handle->is_enabled && - (regulator_is_enabled(handle->reg))) { - bt_power_src_status[ldo_index] = - (int)regulator_get_voltage(handle->reg); - pr_err("%s(%p) value(%d)\n", handle->name, - handle, bt_power_src_status[ldo_index]); + if (!handle) + pr_err("%s: invalid handler received \n", __func__); + + if (handle->is_enabled) + power_src_state = (int)regulator_get_voltage(handle->reg); + else + power_src_state = DEFAULT_INVALID_VALUE; + + switch (core_type) { + case BT_CORE: + power_src.bt_state[handle->indx.crash] = power_src_state; + if (power_src_state != DEFAULT_INVALID_VALUE) { + pr_err("%s(%p) value(%d)\n", handle->name, handle, + power_src.bt_state[handle->indx.crash]); } else { - pr_err("%s:%s is_enabled: %d\n", - __func__, handle->name, + pr_err("%s:%s is_enabled: %d\n", __func__, handle->name, handle->is_enabled); } + break; + case UWB_CORE: + power_src.uwb_state[handle->indx.crash] = power_src_state; + if (power_src_state != DEFAULT_INVALID_VALUE) { + pr_err("%s(%p) value(%d)\n", handle->name, handle, + power_src.uwb_state[handle->indx.crash]); + } else { + pr_err("%s:%s is_enabled: %d\n", __func__, handle->name, + handle->is_enabled); + } + break; + case PLATFORM_CORE: + power_src.platform_state[handle->indx.crash] = power_src_state; + if (power_src_state != DEFAULT_INVALID_VALUE) { + pr_err("%s(%p) value(%d)\n", handle->name, handle, + power_src.platform_state[handle->indx.crash]); + } else { + pr_err("%s:%s is_enabled: %d\n", __func__, handle->name, + handle->is_enabled); + } + break; + default: + pr_err("%s: invalid core type received = %d\n", __func__, core_type); + break; + } + +} + +static inline void update_pwr_state(int state) +{ + mutex_lock(&pwr_data->btpower_state.state_machine_lock); + pwr_data->btpower_state.power_state = state; + mutex_unlock(&pwr_data->btpower_state.state_machine_lock); +} + +static inline int get_pwr_state(void) +{ + int state; + + mutex_lock(&pwr_data->btpower_state.state_machine_lock); + state = (int)pwr_data->btpower_state.power_state; + mutex_unlock(&pwr_data->btpower_state.state_machine_lock); + return state; +} + +static inline void btpower_set_retenion_mode_state(int state) +{ + mutex_lock(&pwr_data->btpower_state.state_machine_lock); + pwr_data->btpower_state.retention_mode = state; + mutex_unlock(&pwr_data->btpower_state.state_machine_lock); +} + +static inline int btpower_get_retenion_mode_state(void) +{ + int state; + + mutex_lock(&pwr_data->btpower_state.state_machine_lock); + state = (int)pwr_data->btpower_state.retention_mode; + mutex_unlock(&pwr_data->btpower_state.state_machine_lock); + return state; +} + +static inline void btpower_set_grant_pending_state(enum grant_states state) +{ + mutex_lock(&pwr_data->btpower_state.state_machine_lock); + pwr_data->btpower_state.grant_pending = state; + mutex_unlock(&pwr_data->btpower_state.state_machine_lock); +} + +static inline enum grant_states btpower_get_grant_pending_state(void) +{ + enum grant_states state; + + mutex_lock(&pwr_data->btpower_state.state_machine_lock); + state = pwr_data->btpower_state.grant_pending; + mutex_unlock(&pwr_data->btpower_state.state_machine_lock); + return state; +} + +static inline void btpower_set_grant_state(enum grant_states state) +{ + mutex_lock(&pwr_data->btpower_state.state_machine_lock); + pwr_data->btpower_state.grant_state = state; + mutex_unlock(&pwr_data->btpower_state.state_machine_lock); +} + +static inline enum grant_states btpower_get_grant_state(void) +{ + enum grant_states state; + + mutex_lock(&pwr_data->btpower_state.state_machine_lock); + state = pwr_data->btpower_state.grant_state; + mutex_unlock(&pwr_data->btpower_state.state_machine_lock); + return state; +} + +static void update_sub_state(int state) +{ + pwr_data->sub_state = state; +} + +static int get_sub_state(void) +{ + return (int)pwr_data->sub_state; +} + +int power_enable (enum SubSystem SubSystemType) +{ + int ret; + + switch (get_pwr_state()) { + case IDLE: + ret = power_regulators(PLATFORM_CORE, POWER_ENABLE); + if (SubSystemType == BLUETOOTH) { + ret = power_regulators(BT_CORE, POWER_ENABLE); + update_pwr_state(BT_ON); + } else { + ret = power_regulators(UWB_CORE, POWER_ENABLE); + update_pwr_state(UWB_ON); + } + break; + case BT_ON: + if (SubSystemType == BLUETOOTH) { + pr_err("%s: BT Regulators already Voted-On\n", + __func__); + return 0; + } + ret = power_regulators(UWB_CORE, POWER_ENABLE); + update_pwr_state(ALL_CLIENTS_ON); + break; + case UWB_ON: + if (SubSystemType == UWB) { + pr_err("%s: UWB Regulators already Voted-On\n", + __func__); + return 0; + } + ret = power_regulators(BT_CORE, POWER_ENABLE); + update_pwr_state(ALL_CLIENTS_ON); + break; + case ALL_CLIENTS_ON: + pr_err("%s: Both BT and UWB Regulators already Voted-On\n", + __func__); + return 0; + } + return ret; +} + +void send_signal_to_subsystem (int SubSystemType, int state) { + pwr_data->wrkq_signal_state = state; + if (SubSystemType == BLUETOOTH) + queue_work(pwr_data->workq, &pwr_data->bt_wq); + else + queue_work(pwr_data->workq, &pwr_data->uwb_wq); +} + +int power_disable(enum SubSystem SubSystemType) +{ + int ret = 0; + int ret_mode_state = btpower_get_retenion_mode_state(); + enum grant_states grant_state = btpower_get_grant_state(); + enum grant_states grant_pending = btpower_get_grant_pending_state(); + + switch (get_pwr_state()) { + case IDLE: + pr_err("%s: both BT and UWB regulators already voted-Off\n", __func__); + return 0; + case ALL_CLIENTS_ON: + if (SubSystemType == BLUETOOTH) { + ret = power_regulators(BT_CORE, POWER_DISABLE); + update_pwr_state(UWB_ON); + if (ret_mode_state == BOTH_CLIENTS_IN_RETENTION) + btpower_set_retenion_mode_state(UWB_IN_RETENTION); + else if (ret_mode_state == BT_IN_RETENTION) + btpower_set_retenion_mode_state(RETENTION_IDLE); + if (get_sub_state() == SSR_ON_BT) { + update_sub_state(SUB_STATE_IDLE); + send_signal_to_subsystem(UWB, BT_SSR_COMPLETED); + } + if (grant_state == BT_HAS_GRANT) { + if (grant_pending == UWB_WAITING_FOR_GRANT) { + send_signal_to_subsystem(UWB, + SIGIO_SOC_ACCESS_SIGNAL|(ACCESS_GRANTED + 1)); + btpower_set_grant_state(UWB_HAS_GRANT); + } else { + btpower_set_grant_state(NO_GRANT_FOR_ANY_SS); + } + } + if (grant_pending == BT_WAITING_FOR_GRANT) + btpower_set_grant_pending_state(NO_OTHER_CLIENT_WAITING_FOR_GRANT); + } else { + ret = power_regulators(UWB_CORE, POWER_DISABLE); + update_pwr_state(BT_ON); + if (ret_mode_state == BOTH_CLIENTS_IN_RETENTION) + btpower_set_retenion_mode_state(BT_IN_RETENTION); + else if (ret_mode_state == UWB_IN_RETENTION) + btpower_set_retenion_mode_state(RETENTION_IDLE); + if (get_sub_state() == SSR_ON_UWB) { + send_signal_to_subsystem(BLUETOOTH, + (SIGIO_INTERACTION_SIGNAL|SIGIO_UWB_SSR_COMPLETED)); + } + if (grant_state == UWB_HAS_GRANT) { + if (grant_pending == BT_WAITING_FOR_GRANT) { + send_signal_to_subsystem(BLUETOOTH, + SIGIO_SOC_ACCESS_SIGNAL|(ACCESS_GRANTED + 1)); + btpower_set_grant_state(BT_HAS_GRANT); + } else { + btpower_set_grant_state(NO_GRANT_FOR_ANY_SS); + } + } + if (grant_pending == UWB_WAITING_FOR_GRANT) + btpower_set_grant_pending_state(NO_OTHER_CLIENT_WAITING_FOR_GRANT); + } + break; + case UWB_ON: + if (SubSystemType == BLUETOOTH) { + pr_err("%s: BT Regulator already Voted-Off\n", __func__); + return 0; + } + ret = power_regulators(UWB_CORE, POWER_DISABLE); + ret = power_regulators(PLATFORM_CORE, POWER_DISABLE); + update_pwr_state(IDLE); + update_sub_state(SUB_STATE_IDLE); + btpower_set_retenion_mode_state(RETENTION_IDLE); + btpower_set_grant_state(NO_GRANT_FOR_ANY_SS); + btpower_set_grant_pending_state(NO_OTHER_CLIENT_WAITING_FOR_GRANT); + break; + case BT_ON: + if (SubSystemType == UWB) { + pr_err("%s: UWB Regulator already Voted-Off\n", __func__); + return 0; + } + ret = power_regulators(BT_CORE, POWER_DISABLE); + ret = power_regulators(PLATFORM_CORE, POWER_DISABLE); + update_pwr_state(IDLE); + update_sub_state(SUB_STATE_IDLE); + btpower_set_retenion_mode_state(RETENTION_IDLE); + btpower_set_grant_state(NO_GRANT_FOR_ANY_SS); + btpower_set_grant_pending_state(NO_OTHER_CLIENT_WAITING_FOR_GRANT); + break; + } + return ret; +} + +static int client_state_notified(int SubSystemType) { + if (get_sub_state() != SUB_STATE_IDLE) { + pr_err("%s: SSR is already running on other Sub-system\n", __func__); + return -1; + } + + if (SubSystemType == BLUETOOTH) { + update_sub_state(SSR_ON_BT); + if (get_pwr_state() == ALL_CLIENTS_ON) { + if (!pwr_data->reftask_uwb) { + pr_err("%s: UWB PID is not register to send signal\n", + __func__); + return -1; + } + send_signal_to_subsystem(UWB, SSR_ON_BT); + } + } else { + update_sub_state(SSR_ON_UWB); + if (get_pwr_state() == ALL_CLIENTS_ON) { + if (!pwr_data->reftask_bt) { + pr_err("%s: BT PID is not register to send signal\n", + __func__); + return -1; + } + send_signal_to_subsystem(BLUETOOTH, + (SIGIO_INTERACTION_SIGNAL|SIGIO_SSR_ON_UWB)); + } + } + return 0; +} + +void btpower_register_client(int client, int cmd) +{ + if (cmd == REG_BT_PID) { + pwr_data->reftask_bt = get_current(); + pr_info("%s: Registering BT Service(PID-%d) with Power driver\n", + __func__, pwr_data->reftask_bt->tgid); + return; + } else if (cmd == REG_UWB_PID) { + pwr_data->reftask_uwb = get_current(); + pr_info("%s: Registering UWB Service(PID-%d) with Power driver\n", + __func__, pwr_data->reftask_uwb->tgid); + return; + } + + if (client == BLUETOOTH) + client_state_notified(BLUETOOTH); + else + client_state_notified(UWB); +} + +void log_power_src_val(void) +{ + int itr = 0; + + power_src.platform_state[BT_SW_CTRL_GPIO_CURRENT] = + gpio_get_value(pwr_data->bt_gpio_sw_ctrl); + power_src.platform_state[BT_RESET_GPIO_CURRENT] = + gpio_get_value(pwr_data->bt_gpio_sys_rst); + + for (itr = 0; itr < pwr_data->bt_num_vregs; itr++) + set_pwr_srcs_status(&pwr_data->bt_vregs[itr], BT_CORE); + + for (itr = 0; itr < pwr_data->platform_num_vregs; itr++) + set_pwr_srcs_status(&pwr_data->platform_vregs[itr], PLATFORM_CORE); + + for (itr = 0; itr < pwr_data->uwb_num_vregs; itr++) + set_pwr_srcs_status(&pwr_data->uwb_vregs[itr], UWB_CORE); +} + +int btpower_retenion(enum plt_pwr_state client) +{ + int ret; + int current_pwr_state = get_pwr_state(); + int retention_mode_state = btpower_get_retenion_mode_state(); + + if (current_pwr_state == IDLE) { + pr_err("%s: invalid retention_mode request\n", __func__); + return -1; + } + + ret = power_regulators((client == POWER_ON_BT_RETENION ? BT_CORE : UWB_CORE), + POWER_RETENTION); + if (ret < 0) + return ret; + + if ((current_pwr_state == BT_ON || current_pwr_state == UWB_ON) && + retention_mode_state == IDLE) { + ret = power_regulators(PLATFORM_CORE, POWER_RETENTION); + if (ret < 0) + return ret; + btpower_set_retenion_mode_state(client == POWER_ON_BT_RETENION ? + BT_IN_RETENTION: UWB_IN_RETENTION); + } else if (current_pwr_state == ALL_CLIENTS_ON && + retention_mode_state == IDLE) { + btpower_set_retenion_mode_state(client == POWER_ON_BT_RETENION ? + BT_IN_RETENTION: UWB_IN_RETENTION); + } else if (current_pwr_state == ALL_CLIENTS_ON && + (retention_mode_state == BT_IN_RETENTION || + retention_mode_state == UWB_IN_RETENTION)) { + ret = power_regulators(PLATFORM_CORE, POWER_RETENTION); + if (ret < 0) + return ret; + btpower_set_retenion_mode_state(BOTH_CLIENTS_IN_RETENTION); + } else if (retention_mode_state == UWB_OUT_OF_RETENTION || + retention_mode_state == BT_OUT_OF_RETENTION) { + ret = power_regulators(PLATFORM_CORE, POWER_RETENTION); + if (ret < 0) + return ret; + btpower_set_retenion_mode_state(BOTH_CLIENTS_IN_RETENTION); + } + + return ret; +} + +int btpower_off(enum plt_pwr_state client) +{ + return power_disable((client == POWER_OFF_BT) ? BLUETOOTH : UWB); +} + +int btpower_on(enum plt_pwr_state client) +{ + int ret = 0; + int current_ssr_state = get_sub_state(); + int retention_mode_state = btpower_get_retenion_mode_state(); + + if (retention_mode_state == UWB_IN_RETENTION || + retention_mode_state == BT_IN_RETENTION) { + ret = platform_regulators_pwr(POWER_DISABLE_RETENTION); + if (ret < 0) + return ret; + if (retention_mode_state == BT_IN_RETENTION) + btpower_set_retenion_mode_state(BT_OUT_OF_RETENTION); + else + btpower_set_retenion_mode_state(UWB_OUT_OF_RETENTION); + } + + /* No Point in going further if SSR is on any subsystem */ + if (current_ssr_state != SUB_STATE_IDLE) { + pr_err("%s: %s not allowing to power on\n", __func__, + ssr_state[current_ssr_state]); + return -1; + } + + ret = power_enable(client == POWER_ON_BT ? BLUETOOTH : UWB); + + /* Return current state machine to clients */ + if (!ret) + ret = (int)get_pwr_state(); + + return ret; +} + +int STREAM_TO_UINT32(struct sk_buff *skb) +{ + return (skb->data[0] | (skb->data[1] << 8) | + (skb->data[2] << 16) | (skb->data[3] << 24)); +} + +int btpower_access_ctrl(enum plt_pwr_state request) +{ + enum grant_states grant_state = btpower_get_grant_state(); + enum grant_states grant_pending = btpower_get_grant_pending_state(); + int current_ssr_state = get_sub_state(); + + pr_info("%s: request for %s grant_state %s grant_pending %s\n", __func__, + pwr_req[(int)request], ConvertGrantToString(grant_state), + ConvertGrantToString(grant_pending)); + + if (current_ssr_state != SUB_STATE_IDLE && + (request == BT_ACCESS_REQ || request == UWB_ACCESS_REQ)) { + pr_err("%s: not allowing this request as %s\n", __func__, + ssr_state[current_ssr_state]); + return (int)ACCESS_DISALLOWED; + } + + if ((grant_state == NO_GRANT_FOR_ANY_SS && + grant_pending != NO_OTHER_CLIENT_WAITING_FOR_GRANT)) { + pr_err("%s: access ctrl gone for toss, resetting it back\n", __func__); + grant_pending = NO_OTHER_CLIENT_WAITING_FOR_GRANT; + btpower_set_grant_pending_state(NO_OTHER_CLIENT_WAITING_FOR_GRANT); + } + + if (request == BT_ACCESS_REQ && grant_state == NO_GRANT_FOR_ANY_SS) { + btpower_set_grant_state(BT_HAS_GRANT); + return ACCESS_GRANTED; + } else if (request == UWB_ACCESS_REQ && grant_state == NO_GRANT_FOR_ANY_SS) { + btpower_set_grant_state(UWB_HAS_GRANT); + return ACCESS_GRANTED; + } else if (request == BT_ACCESS_REQ && grant_state == UWB_HAS_GRANT) { + btpower_set_grant_pending_state(BT_WAITING_FOR_GRANT); + return ACCESS_DENIED; + } else if (request == UWB_ACCESS_REQ && grant_state == BT_HAS_GRANT) { + btpower_set_grant_pending_state(UWB_WAITING_FOR_GRANT); + return ACCESS_DENIED; + } else if (request == BT_RELEASE_ACCESS && grant_state == BT_HAS_GRANT) { + if (grant_pending == UWB_WAITING_FOR_GRANT) { + if (!pwr_data->reftask_uwb) { + pr_err("%s: UWB service got killed\n", __func__); + } else { + send_signal_to_subsystem(UWB, + SIGIO_SOC_ACCESS_SIGNAL|(ACCESS_GRANTED + 1)); + btpower_set_grant_state(UWB_HAS_GRANT); + } + btpower_set_grant_pending_state(NO_OTHER_CLIENT_WAITING_FOR_GRANT); + return ACCESS_RELEASED; + + } else { + btpower_set_grant_state(NO_GRANT_FOR_ANY_SS); + btpower_set_grant_pending_state(NO_OTHER_CLIENT_WAITING_FOR_GRANT); + return ACCESS_RELEASED; + } + } else if (request == UWB_RELEASE_ACCESS && grant_state == UWB_HAS_GRANT) { + if (grant_pending == BT_WAITING_FOR_GRANT) { + if (!pwr_data->reftask_uwb) { + pr_err("%s: BT service got killed\n", __func__); + } else { + send_signal_to_subsystem(BLUETOOTH, + SIGIO_SOC_ACCESS_SIGNAL|(ACCESS_GRANTED+1)); + btpower_set_grant_state(BT_HAS_GRANT); + } + } else { + btpower_set_grant_state(NO_GRANT_FOR_ANY_SS); + } + btpower_set_grant_pending_state(NO_OTHER_CLIENT_WAITING_FOR_GRANT); + return ACCESS_RELEASED; + } else { + pr_err("%s: unhandled event\n", __func__); + } + return ACCESS_DISALLOWED; +} + +static void bt_power_vote(struct work_struct *work) +{ + struct sk_buff *skb; + int request; + int ret; + + while (1) { + mutex_lock(&pwr_data->pwr_mtx); + skb = skb_dequeue(&pwr_data->rxq); + if (!skb) { + mutex_unlock(&pwr_data->pwr_mtx); + break; + } + request = STREAM_TO_UINT32(skb); + skb_pull(skb, sizeof(uint32_t)); + mutex_unlock(&pwr_data->pwr_mtx); + pr_err("%s: request from is %s cur state = %s %s retention %s access %s pending %s\n", + __func__, pwr_req[request], pwr_states[get_pwr_state()], + ssr_state[get_sub_state()], + retention_mode[btpower_get_retenion_mode_state()], + ConvertGrantToString(btpower_get_grant_state()), + ConvertGrantToString(btpower_get_grant_pending_state())); + if (request == POWER_ON_BT || request == POWER_ON_UWB) + ret = btpower_on((enum plt_pwr_state)request); + else if (request == POWER_OFF_UWB || request == POWER_OFF_BT) + ret = btpower_off((enum plt_pwr_state)request); + else if (request == POWER_ON_BT_RETENION || request == POWER_ON_UWB_RETENION) + ret = btpower_retenion(request); + else if (request >= BT_ACCESS_REQ && request <= UWB_RELEASE_ACCESS) { + ret = btpower_access_ctrl(request); + pr_info("%s: grant status %s\n", __func__, ConvertGrantRetToString((int)ret)); + } + pr_err("%s: request from is %s cur state = %s %s retention %s access %s pending %s\n", + __func__, pwr_req[request], pwr_states[get_pwr_state()], + ssr_state[get_sub_state()], + retention_mode[btpower_get_retenion_mode_state()], + ConvertGrantToString(btpower_get_grant_state()), + ConvertGrantToString(btpower_get_grant_pending_state())); + pwr_data->wait_status[request] = ret; + wake_up_interruptible(&pwr_data->rsp_wait_q[request]); } } -static void set_gpios_srcs_status(char *gpio_name, - int gpio_index, int handle) +int schedule_client_voting(enum plt_pwr_state request) { - if (handle >= 0) { - bt_power_src_status[gpio_index] = - DEFAULT_INVALID_VALUE; - bt_power_src_status[gpio_index] = - gpio_get_value(handle); - pr_err("%s(%d) value(%d)\n", gpio_name, - handle, bt_power_src_status[gpio_index]); - } else { - pr_err("%s: %s not configured\n", - __func__, gpio_name); + struct sk_buff *skb; + wait_queue_head_t *rsp_wait_q; + int *status; + int ret = 0; + uint32_t req = (uint32_t)request; + + mutex_lock(&pwr_data->pwr_mtx); + skb = alloc_skb(sizeof(uint32_t), GFP_KERNEL); + if (!skb) { + mutex_unlock(&pwr_data->pwr_mtx); + return -1; } + + rsp_wait_q = &pwr_data->rsp_wait_q[(u8)request]; + status = &pwr_data->wait_status[(u8)request]; + *status = PWR_WAITING_RSP; + skb_put_data(skb, &req, sizeof(uint32_t)); + skb_queue_tail(&pwr_data->rxq, skb); + queue_work(system_highpri_wq, &pwr_data->wq_pwr_voting); + mutex_unlock(&pwr_data->pwr_mtx); + ret = wait_event_interruptible_timeout(*rsp_wait_q, (*status) != PWR_WAITING_RSP, + msecs_to_jiffies(BTPOWER_CONFIG_MAX_TIMEOUT)); + pr_err("%s: %d\n", __func__, *status); + if (ret == 0) { + pr_err("%s: failed to vote %d due to timeout\n", __func__, request); + ret = -ETIMEDOUT; + } else { + ret = *status; + } + + return ret; +} + +char* GetBtSecondaryCrashReason(enum BtSecondaryReasonCode reason) +{ + for(int i =0; i < (int)(sizeof(btSecReasonMap)/sizeof(BtSecondaryReasonMap)); i++) + if (btSecReasonMap[i].reason == reason) + return btSecReasonMap[i].reasonstr; + + return CRASH_REASON_NOT_FOUND; +} + +char* GetBtPrimaryCrashReason(enum BtPrimaryReasonCode reason) +{ + for(int i =0; i < (int)(sizeof(btPriReasonMap)/sizeof(BtPrimaryReasonMap)); i++) + if (btPriReasonMap[i].reason == reason) + return btPriReasonMap[i].reasonstr; + + return CRASH_REASON_NOT_FOUND; +} + +char* GetUwbSecondaryCrashReason(enum UwbSecondaryReasonCode reason) +{ + for(int i =0; i < (int)(sizeof(uwbSecReasonMap)/sizeof(UwbSecondaryReasonMap)); i++) + if (uwbSecReasonMap[i].reason == reason) + return uwbSecReasonMap[i].reasonstr; + + return CRASH_REASON_NOT_FOUND; +} + +char* GetUwbPrimaryCrashReason(enum UwbPrimaryReasonCode reason) +{ + for(int i =0; i < (int)(sizeof(uwbPriReasonMap)/sizeof(UwbPrimaryReasonMap)); i++) + if (uwbPriReasonMap[i].reason == reason) + return uwbPriReasonMap[i].reasonstr; + + return CRASH_REASON_NOT_FOUND; +} + +int btpower_handle_client_request(unsigned int cmd, int arg) +{ + int ret = -1; + + pr_info("%s: %s cmd voted to %s, current state = %s, %s\n", __func__, + (cmd == BT_CMD_PWR_CTRL ? "BT_CMD_PWR_CTRL" : "UWB_CMD_PWR_CTRL"), + bt_arg[(int)arg], pwr_states[get_pwr_state()], + ssr_state[(int)get_sub_state()]); + + if (cmd == BT_CMD_PWR_CTRL) { + switch ((int)arg) { + case POWER_DISABLE: + ret = schedule_client_voting(POWER_OFF_BT); + break; + case POWER_ENABLE: + ret = schedule_client_voting(POWER_ON_BT); + break; + case POWER_RETENTION: + ret = schedule_client_voting(POWER_ON_BT_RETENION); + break; + } + } else if (cmd == UWB_CMD_PWR_CTRL) { + switch ((int)arg) { + case POWER_DISABLE: + ret = schedule_client_voting(POWER_OFF_UWB); + break; + case POWER_ENABLE: + ret = schedule_client_voting(POWER_ON_UWB); + break; + case POWER_RETENTION: + ret = schedule_client_voting(POWER_ON_UWB_RETENION); + break; + } + } + pr_err("%s: %s, SSR state = %s\n", __func__, + pwr_states[get_pwr_state()], ssr_state[(int)get_sub_state()]); + + return ret; +} + +int btpower_process_access_req(unsigned int cmd, int req) +{ + int ret = -1; + + pr_info("%s: by %s: request type %s\n", __func__, + cmd == BT_CMD_ACCESS_CTRL ? "BT" : "UWB", + req == 1 ? "Request" : "Release"); + if (cmd == BT_CMD_ACCESS_CTRL && req == 1) + ret = schedule_client_voting(BT_ACCESS_REQ); + else if (cmd == BT_CMD_ACCESS_CTRL && req == 2) + ret = schedule_client_voting(BT_RELEASE_ACCESS); + else if (cmd == UWB_CMD_ACCESS_CTRL && req == 1) + ret = schedule_client_voting(UWB_ACCESS_REQ); + else if (cmd == UWB_CMD_ACCESS_CTRL && req == 2) + ret = schedule_client_voting(UWB_RELEASE_ACCESS); + else + pr_err("%s: unhandled command %04x req %02x", __func__, cmd, req); + + return ret; } static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int ret = 0, pwr_cntrl = 0; + int ret = 0; int chipset_version = 0; - int itr, num_vregs; - struct bt_power_vreg_data *vreg_info = NULL; + int itr; + unsigned int panic_reason = 0; + unsigned short primary_reason = 0, sec_reason = 0; + #ifdef CONFIG_MSM_BT_OOBS enum btpower_obs_param clk_cntrl; #endif - if (!bt_power_pdata || !probe_finished) { + + if (!pwr_data || !probe_finished) { pr_err("%s: BTPower Probing Pending.Try Again\n", __func__); return -EAGAIN; } switch (cmd) { #ifdef CONFIG_MSM_BT_OOBS - case BT_CMD_OBS_SIGNAL_TASK: - bt_power_pdata->reffilp_obs = file; - bt_power_pdata->reftask_obs = get_current(); - pr_info("%s: BT_CMD_OBS_SIGNAL_TASK tid %d file %pK\n", - __func__, bt_power_pdata->reftask_obs->pid, file); - break; case BT_CMD_OBS_VOTE_CLOCK: - if (!gpio_is_valid(bt_power_pdata->bt_gpio_dev_wake)) { - pr_debug("%s: BT_CMD_OBS_VOTE_CLOCK bt_dev_wake_n(%d) not configured\n", - __func__, bt_power_pdata->bt_gpio_dev_wake); + if (!gpio_is_valid(pwr_data->bt_gpio_dev_wake)) { + pr_err("%s: BT_CMD_OBS_VOTE_CLOCK bt_dev_wake_n(%d) not configured\n", + __func__, pwr_data->bt_gpio_dev_wake); return -EIO; } clk_cntrl = (enum btpower_obs_param)arg; switch (clk_cntrl) { case BTPOWER_OBS_CLK_OFF: - btpower_uart_transport_locked(bt_power_pdata, false); + btpower_uart_transport_locked(pwr_data, false); ret = 0; break; case BTPOWER_OBS_CLK_ON: - btpower_uart_transport_locked(bt_power_pdata, true); + btpower_uart_transport_locked(pwr_data, true); ret = 0; break; case BTPOWER_OBS_DEV_OFF: - gpio_set_value(bt_power_pdata->bt_gpio_dev_wake, 0); + gpio_set_value(pwr_data->bt_gpio_dev_wake, 0); ret = 0; break; case BTPOWER_OBS_DEV_ON: - gpio_set_value(bt_power_pdata->bt_gpio_dev_wake, 1); + gpio_set_value(pwr_data->bt_gpio_dev_wake, 1); ret = 0; break; default: - pr_debug("%s: BT_CMD_OBS_VOTE_CLOCK clk_cntrl(%d)\n", + pr_err("%s: BT_CMD_OBS_VOTE_CLOCK clk_cntrl(%d)\n", __func__, clk_cntrl); return -EINVAL; } - pr_debug("%s: BT_CMD_OBS_VOTE_CLOCK clk_cntrl(%d) %s\n", + pr_err("%s: BT_CMD_OBS_VOTE_CLOCK clk_cntrl(%d) %s\n", __func__, clk_cntrl, - gpio_get_value(bt_power_pdata->bt_gpio_dev_wake) ? + gpio_get_value(pwr_data->bt_gpio_dev_wake) ? "Assert" : "Deassert"); break; #endif case BT_CMD_SLIM_TEST: #if (defined CONFIG_BT_SLIM) - if (!bt_power_pdata->slim_dev) { + if (!pwr_data->slim_dev) { pr_err("%s: slim_dev is null\n", __func__); return -EINVAL; } ret = btfm_slim_hw_init( - bt_power_pdata->slim_dev->platform_data + pwr_data->slim_dev->platform_data ); #endif break; case BT_CMD_PWR_CTRL: - pwr_cntrl = (int)arg; - pr_warn("%s: BT_CMD_PWR_CTRL pwr_cntrl: %d\n", - __func__, pwr_cntrl); - if (pwr_state != pwr_cntrl) { - ret = bluetooth_power(pwr_cntrl); - if (!ret) - pwr_state = pwr_cntrl; - } else { - pr_err("%s: BT chip state is already: %d no change\n", - __func__, pwr_state); - ret = 0; - } + case UWB_CMD_PWR_CTRL: { + ret = btpower_handle_client_request(cmd, (int)arg); break; + } + case BT_CMD_REGISTRATION: + btpower_register_client(BLUETOOTH, (int)arg); + break; + case UWB_CMD_REGISTRATION: + btpower_register_client(UWB, (int)arg); + break; + case BT_CMD_ACCESS_CTRL: + case UWB_CMD_ACCESS_CTRL: { + ret = btpower_process_access_req(cmd, (int)arg); + break; + } case BT_CMD_CHIPSET_VERS: chipset_version = (int)arg; pr_warn("%s: unified Current SOC Version : %x\n", __func__, @@ -1413,7 +2411,9 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } break; case BT_CMD_GET_CHIPSET_ID: - if (copy_to_user((void __user *)arg, bt_power_pdata->compatible, + pr_err("%s: BT_CMD_GET_CHIPSET_ID = %s\n", __func__, + pwr_data->compatible); + if (copy_to_user((void __user *)arg, pwr_data->compatible, MAX_PROP_SIZE)) { pr_err("%s: copy to user failed\n", __func__); ret = -EFAULT; @@ -1421,24 +2421,24 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; case BT_CMD_CHECK_SW_CTRL: /* Check if SW_CTRL is asserted */ - pr_info("BT_CMD_CHECK_SW_CTRL\n"); - if (bt_power_pdata->bt_gpio_sw_ctrl > 0) { - bt_power_src_status[BT_SW_CTRL_GPIO] = + pr_err("BT_CMD_CHECK_SW_CTRL\n"); + if (pwr_data->bt_gpio_sw_ctrl > 0) { + power_src.bt_state[BT_SW_CTRL_GPIO] = DEFAULT_INVALID_VALUE; ret = gpio_direction_input( - bt_power_pdata->bt_gpio_sw_ctrl); + pwr_data->bt_gpio_sw_ctrl); if (ret) { pr_err("%s:gpio_direction_input api\n", __func__); pr_err("%s:failed for SW_CTRL:%d\n", __func__, ret); } else { - bt_power_src_status[BT_SW_CTRL_GPIO] = + power_src.bt_state[BT_SW_CTRL_GPIO] = gpio_get_value( - bt_power_pdata->bt_gpio_sw_ctrl); - pr_info("bt-sw-ctrl-gpio(%d) value(%d)\n", - bt_power_pdata->bt_gpio_sw_ctrl, - bt_power_src_status[BT_SW_CTRL_GPIO]); + pwr_data->bt_gpio_sw_ctrl); + pr_err("bt-sw-ctrl-gpio(%d) value(%d)\n", + pwr_data->bt_gpio_sw_ctrl, + power_src.bt_state[BT_SW_CTRL_GPIO]); } } else { pr_err("bt_gpio_sw_ctrl not configured\n"); @@ -1446,30 +2446,54 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } break; case BT_CMD_GETVAL_POWER_SRCS: - pr_info("BT_CMD_GETVAL_POWER_SRCS\n"); - set_gpios_srcs_status("BT_RESET_GPIO", BT_RESET_GPIO_CURRENT, - bt_power_pdata->bt_gpio_sys_rst); - set_gpios_srcs_status("SW_CTRL_GPIO", BT_SW_CTRL_GPIO_CURRENT, - bt_power_pdata->bt_gpio_sw_ctrl); + pr_err("BT_CMD_GETVAL_POWER_SRCS\n"); - num_vregs = bt_power_pdata->num_vregs; - for (itr = 0; itr < num_vregs; itr++) { - vreg_info = &bt_power_pdata->vreg_info[itr]; - set_pwr_srcs_status(vreg_info); - } - if (copy_to_user((void __user *)arg, - bt_power_src_status, sizeof(bt_power_src_status))) { + power_src.platform_state[BT_SW_CTRL_GPIO_CURRENT] = + gpio_get_value(pwr_data->bt_gpio_sw_ctrl); + power_src.platform_state[BT_RESET_GPIO_CURRENT] = + gpio_get_value(pwr_data->bt_gpio_sys_rst); + + for (itr = 0; itr < pwr_data->bt_num_vregs; itr++) + set_pwr_srcs_status(&pwr_data->bt_vregs[itr], BT_CORE); + + for (itr = 0; itr < pwr_data->platform_num_vregs; itr++) + set_pwr_srcs_status(&pwr_data->platform_vregs[itr], PLATFORM_CORE); + + for (itr = 0; itr < pwr_data->uwb_num_vregs; itr++) + set_pwr_srcs_status(&pwr_data->uwb_vregs[itr], UWB_CORE); + + if (copy_to_user((void __user *)arg, &power_src, sizeof(power_src))) { pr_err("%s: copy to user failed\n", __func__); ret = -EFAULT; } break; case BT_CMD_SET_IPA_TCS_INFO: - pr_info("%s: BT_CMD_SET_IPA_TCS_INFO\n", __func__); - btpower_enable_ipa_vreg(bt_power_pdata); + pr_err("%s: BT_CMD_SET_IPA_TCS_INFO\n", __func__); + btpower_enable_ipa_vreg(pwr_data); break; case BT_CMD_KERNEL_PANIC: - pr_info("%s: BT_CMD_KERNEL_PANIC\n", __func__); - panic("subsys-restart: Resetting the SoC - Bluetooth crashed\n"); + pr_err("%s: BT_CMD_KERNEL_PANIC\n", __func__); + panic_reason = (unsigned int)arg; + primary_reason = panic_reason & 0xFFFF; + sec_reason = (panic_reason & 0xFFFF0000) >> 16; + pr_err("%s: BT kernel panic Primary reason = %s, Secondary reason = %s\n", + __func__, GetBtPrimaryCrashReason(primary_reason), + GetBtSecondaryCrashReason(sec_reason)); + panic("%s: BT kernel panic Primary reason = %s, Secondary reason = %s\n", + __func__, GetBtPrimaryCrashReason(primary_reason), + GetBtSecondaryCrashReason(sec_reason)); + break; + case UWB_CMD_KERNEL_PANIC: + pr_err("%s: UWB_CMD_KERNEL_PANIC\n", __func__); + panic_reason = (unsigned int)arg; + primary_reason = panic_reason & 0xFFFF; + sec_reason = (panic_reason & 0xFFFF0000) >> 16; + pr_err("%s: UWB kernel panic Primary reason = %s, Secondary reason = %s\n", + __func__, GetUwbPrimaryCrashReason(primary_reason), + GetUwbSecondaryCrashReason(sec_reason)); + panic("%s: UWB kernel panic Primary reason = %s, Secondary reason = %s\n", + __func__, GetUwbPrimaryCrashReason(primary_reason), + GetUwbSecondaryCrashReason(sec_reason)); break; default: return -ENOIOCTLCMD; @@ -1477,6 +2501,58 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ret; } +static int bt_power_release(struct inode *inode, struct file *file) +{ + if (!pwr_data || !probe_finished) { + pr_err("%s: BTPower Probing Pending.Try Again\n", __func__); + return -EAGAIN; + } + + pwr_data->reftask = get_current(); + + if (pwr_data->reftask_bt != NULL) { + if (pwr_data->reftask->tgid == pwr_data->reftask_bt->tgid) + { + pr_err("%s called by BT service(PID-%d)\n", + __func__, pwr_data->reftask->tgid); +/* + if(get_pwr_state() == BT_ON) + { + bt_regulators_pwr(POWER_DISABLE); + platform_regulators_pwr(POWER_DISABLE); + update_pwr_state(IDLE); + + } + else if (get_pwr_state() == ALL_CLIENTS_ON) + { + bt_regulators_pwr(POWER_DISABLE); + update_pwr_state(UWB_ON); + } +*/ + } + } else if (pwr_data->reftask_uwb != NULL) { + if (pwr_data->reftask->tgid == pwr_data->reftask_uwb->tgid) + { + pr_err("%s called by uwb service(PID-%d)\n", + __func__, pwr_data->reftask->tgid); +/* + if(get_pwr_state() == UWB_ON) + { + uwb_regulators_pwr(POWER_DISABLE); + platform_regulators_pwr(POWER_DISABLE); + update_pwr_state(IDLE); + } + else if (get_pwr_state() == ALL_CLIENTS_ON) + { + uwb_regulators_pwr(POWER_DISABLE); + update_pwr_state(BT_ON); + } +*/ + } + } + return 0; +} + static struct platform_driver bt_power_driver = { .probe = bt_power_probe, .remove = bt_power_remove, @@ -1489,6 +2565,7 @@ static struct platform_driver bt_power_driver = { static const struct file_operations bt_dev_fops = { .unlocked_ioctl = bt_ioctl, .compat_ioctl = bt_ioctl, + .release = bt_power_release, }; static int __init btpower_init(void) @@ -1549,12 +2626,13 @@ driver_err: * * Return: 0 for success */ - int bt_aop_send_msg(struct btpower_platform_data *plat_priv, char *mbox_msg) - { +int bt_aop_send_msg(struct platform_pwr_data *plat_priv, char *mbox_msg) +{ struct qmp_pkt pkt; int ret = 0; pkt.size = BTPOWER_MBOX_MSG_MAX_LEN; pkt.data = mbox_msg; + pr_err("%s: %s\n", __func__, mbox_msg); ret = mbox_send_message(plat_priv->mbox_chan, &pkt); if (ret < 0) pr_err("Failed to send AOP mbox msg: %s\n", mbox_msg); @@ -1562,15 +2640,15 @@ driver_err: ret =0; return ret; - } -int bt_aop_pdc_reconfig(struct btpower_platform_data *pdata) -{ +} +int bt_aop_pdc_reconfig(struct platform_pwr_data *pdata) +{ unsigned int i; int ret; if (pdata->pdc_init_table_len <= 0 || !pdata->pdc_init_table) return 0; - pr_debug("Setting PDC defaults"); + pr_err("Setting PDC defaults\n"); for (i = 0; i < pdata->pdc_init_table_len; i++) { ret =bt_aop_send_msg(pdata,(char *)pdata->pdc_init_table[i]); if (ret < 0) @@ -1579,8 +2657,7 @@ int bt_aop_pdc_reconfig(struct btpower_platform_data *pdata) return ret; } - -int btpower_aop_mbox_init(struct btpower_platform_data *pdata) +int btpower_aop_mbox_init(struct platform_pwr_data *pdata) { struct mbox_client *mbox = &pdata->mbox_client_data; struct mbox_chan *chan; @@ -1603,9 +2680,9 @@ int btpower_aop_mbox_init(struct btpower_platform_data *pdata) "qcom,vreg_ipa", &pdata->vreg_ipa); if (ret) - pr_info("%s: vreg for iPA not configured\n", __func__); + pr_err("%s: vreg for iPA not configured\n", __func__); else - pr_info("%s: Mbox channel initialized\n", __func__); + pr_err("%s: Mbox channel initialized\n", __func__); ret = bt_aop_pdc_reconfig(pdata); if (ret) @@ -1614,7 +2691,7 @@ int btpower_aop_mbox_init(struct btpower_platform_data *pdata) return 0; } -static int btpower_aop_set_vreg_param(struct btpower_platform_data *pdata, +static int btpower_aop_set_vreg_param(struct platform_pwr_data *pdata, const char *vreg_name, enum btpower_vreg_param param, enum btpower_tcs_seq seq, int val) @@ -1632,7 +2709,7 @@ static int btpower_aop_set_vreg_param(struct btpower_platform_data *pdata, "{class: wlan_pdc, res: %s.%s, %s: %d}", vreg_name, vreg_param_str[param], tcs_seq_str[seq], val); - pr_info("%s: sending AOP Mbox msg: %s\n", __func__, mbox_msg); + pr_err("%s: sending AOP Mbox msg: %s\n", __func__, mbox_msg); pkt.size = BTPOWER_MBOX_MSG_MAX_LEN; pkt.data = mbox_msg; @@ -1644,25 +2721,25 @@ static int btpower_aop_set_vreg_param(struct btpower_platform_data *pdata, return ret; } -static int btpower_enable_ipa_vreg(struct btpower_platform_data *pdata) +static int btpower_enable_ipa_vreg(struct platform_pwr_data *pdata) { int ret = 0; static bool config_done; if (config_done) { - pr_info("%s: IPA Vreg already configured\n", __func__); + pr_err("%s: IPA Vreg already configured\n", __func__); return 0; } if (!pdata->vreg_ipa || !pdata->mbox_chan) { - pr_info("%s: mbox/iPA vreg not configured\n", __func__); + pr_err("%s: mbox/iPA vreg not configured\n", __func__); } else { ret = btpower_aop_set_vreg_param(pdata, pdata->vreg_ipa, BTPOWER_VREG_ENABLE, BTPOWER_TCS_UP_SEQ, 1); if (ret >= 0) { - pr_info("%s:Enabled iPA\n", __func__); + pr_err("%s:Enabled iPA\n", __func__); config_done = true; } } diff --git a/soundwire/btfm_swr_hw_interface.c b/soundwire/btfm_swr_hw_interface.c index 200c4e7016..82731a2de0 100644 --- a/soundwire/btfm_swr_hw_interface.c +++ b/soundwire/btfm_swr_hw_interface.c @@ -122,8 +122,10 @@ static void btfm_swr_dai_shutdown(void *dai, int id) BTFMSWR_INFO(""); - if (btfmswr == NULL) - BTFMSWR_INFO("btfmswr is NULL\n"); + if (btfmswr == NULL || btfmswr->p_dai_port == NULL) { + BTFMSWR_INFO("port shutdown might have called with out open\n"); + return; + } switch (id) { case FMAUDIO_TX: diff --git a/target.bzl b/target.bzl index 7b52e44c56..0faff6ba6f 100644 --- a/target.bzl +++ b/target.bzl @@ -33,3 +33,19 @@ def define_blair(): "CONFIG_BT_HW_SECURE_DISABLE", ] ) + +def define_pitti(): + define_bt_modules( + target = "pitti", + modules = [ + "btpower", + "bt_fm_slim", + "radio-i2c-rtc6226-qca", + ], + config_options = [ + "CONFIG_MSM_BT_POWER", + "CONFIG_BTFM_SLIM", + "CONFIG_I2C_RTC6226_QCA", + "CONFIG_BT_HW_SECURE_DISABLE", + ] + )