Loading drivers/cam_cdm/cam_cdm.h +2 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ #define CAM_CDM_RESET_HW_STATUS 0x4 #define CAM_CDM_ERROR_HW_STATUS 0x5 #define CAM_CDM_FLUSH_HW_STATUS 0x6 #define CAM_CDM_RESET_ERR_STATUS 0x7 /* Curent BL command masks and shifts */ #define CAM_CDM_CURRENT_BL_LEN 0xFFFFF Loading Loading @@ -376,6 +377,7 @@ enum cam_cdm_hw_process_intf_cmd { CAM_CDM_HW_INTF_CMD_FLUSH_HW, CAM_CDM_HW_INTF_CMD_HANDLE_ERROR, CAM_CDM_HW_INTF_CMD_HANG_DETECT, CAM_CDM_HW_INTF_DUMP_DBG_REGS, CAM_CDM_HW_INTF_CMD_INVALID, }; Loading drivers/cam_cdm/cam_cdm_core_common.c +16 −0 Original line number Diff line number Diff line Loading @@ -823,6 +823,22 @@ int cam_cdm_process_cmd(void *hw_priv, rc = cam_hw_cdm_hang_detect(cdm_hw, *handle); break; } case CAM_CDM_HW_INTF_DUMP_DBG_REGS: { uint32_t *handle = cmd_args; if (sizeof(uint32_t) != arg_size) { CAM_ERR(CAM_CDM, "Invalid CDM cmd %d size=%x for handle=0x%x", cmd, arg_size, *handle); return -EINVAL; } mutex_lock(&cdm_hw->hw_mutex); cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); mutex_unlock(&cdm_hw->hw_mutex); break; } default: CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd); break; Loading drivers/cam_cdm/cam_cdm_core_common.h +2 −0 Original line number Diff line number Diff line Loading @@ -56,5 +56,7 @@ struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag( uint32_t tag, struct list_head *bl_list); void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, enum cam_cdm_cb_status status, void *data); void cam_hw_cdm_dump_core_debug_registers( struct cam_hw_info *cdm_hw, bool pause_core); #endif /* _CAM_CDM_CORE_COMMON_H_ */ drivers/cam_cdm/cam_cdm_hw_core.c +132 −86 Original line number Diff line number Diff line Loading @@ -170,14 +170,14 @@ static int cam_hw_cdm_pause_core(struct cam_hw_info *cdm_hw, bool pause) return rc; } int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw) int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw, uint32_t value) { int rc = 0; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; if (cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->core_debug, 0x10100)) { value)) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); rc = -EIO; } Loading Loading @@ -264,24 +264,7 @@ int cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo( return rc; } int cam_hw_cdm_enable_core_dbg_per_fifo( struct cam_hw_info *cdm_hw, uint32_t fifo_idx) { int rc = 0; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; if (cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->core_debug, (0x10100 | fifo_idx << 20))) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); rc = -EIO; } return rc; } void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) static void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) { struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; int i, j; Loading @@ -290,12 +273,6 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw, i, &num_pending_req); if (cam_hw_cdm_enable_core_dbg_per_fifo(cdm_hw, i)) { CAM_ERR(CAM_CDM, "Problem in selecting the fifo for readback"); continue; } for (j = 0; j < num_pending_req ; j++) { cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->bl_fifo_rb, j); Loading @@ -317,89 +294,152 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) } } void cam_hw_cdm_dump_core_debug_registers( struct cam_hw_info *cdm_hw) void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, bool pause_core) { uint32_t dump_reg, core_dbg; uint32_t dump_reg[4], core_dbg = 0x100; int i; bool is_core_paused_already; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; const struct cam_cdm_icl_regs *inv_cmd_log = core->offsets->cmn_reg->icl_reg; cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW core status=%x", dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW core userdata=0x%x", dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg[0]); if (pause_core) { cam_hw_cdm_pause_core(cdm_hw, true); usleep_range(1000, 1010); } cam_hw_cdm_enable_core_dbg(cdm_hw, core_dbg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data, &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->debug_status, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_debug, &core_dbg); &dump_reg[2]); CAM_INFO(CAM_CDM, "Core stat 0x%x udata 0x%x dbg_stat 0x%x", dump_reg[0], dump_reg[1], dump_reg[2]); if (core_dbg & 0x100) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->last_ahb_addr, &dump_reg); CAM_INFO(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg); &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->last_ahb_data, &dump_reg); CAM_INFO(CAM_CDM, "AHB dump reglastdata=%x", dump_reg); &dump_reg[1]); CAM_INFO(CAM_CDM, "AHB dump lastaddr=0x%x lastdata=0x%x", dump_reg[0], dump_reg[1]); } else { CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable"); } if (inv_cmd_log) { if (inv_cmd_log->misc_regs) { cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->misc_regs->icl_status, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->misc_regs->icl_inv_bl_addr, &dump_reg[1]); CAM_INFO(CAM_CDM, "Last Inv Cmd Log(ICL)Status: 0x%x bl_addr: 0x%x", dump_reg[0], dump_reg[1]); } if (inv_cmd_log->data_regs) { cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_inv_data, &dump_reg[0]); CAM_INFO(CAM_CDM, "First word of Last Inv cmd: 0x%x", dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_last_data_0, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_last_data_1, &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_last_data_2, &dump_reg[2]); CAM_INFO(CAM_CDM, "Last good cmd word 0x%x 0x%x 0x%x", dump_reg[0], dump_reg[1], dump_reg[2]); } } if (core_dbg & 0x10000) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg[0]); is_core_paused_already = (bool)(dump_reg[0] & 0x20); if (!is_core_paused_already) { cam_hw_cdm_pause_core(cdm_hw, true); usleep_range(1000, 1010); } cam_hw_cdm_dump_bl_fifo_data(cdm_hw); CAM_INFO(CAM_CDM, "CDM HW default dump"); if (!is_core_paused_already) cam_hw_cdm_pause_core(cdm_hw, false); } cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_cfg, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW core cfg=%x", dump_reg); core->offsets->cmn_reg->core_cfg, &dump_reg[0]); CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg[0]); for (i = 0; i < core->offsets->reg_data->num_bl_fifo_irq; i++) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_status, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW irq status%d=%x", i, dump_reg); core->offsets->irq_reg[i]->irq_status, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_set, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW irq set%d=%x", i, dump_reg); core->offsets->irq_reg[i]->irq_set, &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_mask, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW irq mask%d=%x", i, dump_reg); core->offsets->irq_reg[i]->irq_mask, &dump_reg[2]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_clear, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW irq clear%d=%x", i, dump_reg); core->offsets->irq_reg[i]->irq_clear, &dump_reg[3]); CAM_INFO(CAM_CDM, "cnt %d irq status 0x%x set 0x%x mask 0x%x clear 0x%x", i, dump_reg[0], dump_reg[1], dump_reg[2], dump_reg[3]); } cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_bl_base, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW current BL base=%x", dump_reg); core->offsets->cmn_reg->current_bl_base, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_used_ahb_base, &dump_reg[1]); CAM_INFO(CAM_CDM, "curr BL base 0x%x AHB base 0x%x", dump_reg[0], dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_bl_len, &dump_reg); core->offsets->cmn_reg->wait_status, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->comp_wait[0]->comp_wait_status, &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->comp_wait[1]->comp_wait_status, &dump_reg[2]); CAM_INFO(CAM_CDM, "wait status 0x%x comp wait status 0x%x: 0x%x", dump_reg[0], dump_reg[1], dump_reg[2]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_bl_len, &dump_reg[0]); CAM_INFO(CAM_CDM, "CDM HW current BL len=%d ARB %d FIFO %d tag=%d, ", (dump_reg & CAM_CDM_CURRENT_BL_LEN), (dump_reg & CAM_CDM_CURRENT_BL_ARB) >> (dump_reg[0] & CAM_CDM_CURRENT_BL_LEN), (dump_reg[0] & CAM_CDM_CURRENT_BL_ARB) >> CAM_CDM_CURRENT_BL_ARB_SHIFT, (dump_reg & CAM_CDM_CURRENT_BL_FIFO) >> (dump_reg[0] & CAM_CDM_CURRENT_BL_FIFO) >> CAM_CDM_CURRENT_BL_FIFO_SHIFT, (dump_reg & CAM_CDM_CURRENT_BL_TAG) >> (dump_reg[0] & CAM_CDM_CURRENT_BL_TAG) >> CAM_CDM_CURRENT_BL_TAG_SHIFT); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_used_ahb_base, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW current AHB base=%x", dump_reg); cam_hw_cdm_disable_core_dbg(cdm_hw); if (pause_core) cam_hw_cdm_pause_core(cdm_hw, false); } enum cam_cdm_arbitration cam_cdm_get_arbitration_type( Loading Loading @@ -1107,11 +1147,15 @@ static void cam_hw_cdm_reset_cleanup( int i; struct cam_cdm_bl_cb_request_entry *node, *tnode; bool flush_hw = false; bool reset_err = false; if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) || test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status)) flush_hw = true; if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status)) reset_err = true; for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { list_for_each_entry_safe(node, tnode, &core->bl_fifo[i].bl_request_list, entry) { Loading @@ -1120,12 +1164,19 @@ static void cam_hw_cdm_reset_cleanup( CAM_DBG(CAM_CDM, "Notifying client %d for tag %d", node->client_hdl, node->bl_tag); if (flush_hw) if (flush_hw) { enum cam_cdm_cb_status status; status = reset_err ? CAM_CDM_CB_STATUS_HW_ERROR : CAM_CDM_CB_STATUS_HW_RESUBMIT; cam_cdm_notify_clients(cdm_hw, (node->client_hdl == handle) ? CAM_CDM_CB_STATUS_HW_FLUSH : CAM_CDM_CB_STATUS_HW_RESUBMIT, status, (void *)node); } else cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_HW_RESET_DONE, Loading Loading @@ -1268,7 +1319,7 @@ static void cam_hw_cdm_work(struct work_struct *work) * to dump debug info */ cam_hw_cdm_pause_core(cdm_hw, true); cam_hw_cdm_dump_core_debug_registers(cdm_hw); cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); if (payload->irq_status & CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) { Loading Loading @@ -1307,6 +1358,8 @@ static void cam_hw_cdm_work(struct work_struct *work) CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK)) clear_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); } else { CAM_ERR(CAM_CDM, "NULL payload"); } kfree(payload); payload = NULL; Loading @@ -1329,16 +1382,8 @@ static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_lock(&core->bl_fifo[i].fifo_lock); if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) { /* * First pause CDM, If it fails still proceed * to dump debug info */ cam_hw_cdm_pause_core(cdm_hw, true); cam_hw_cdm_dump_core_debug_registers(cdm_hw); /* Resume CDM back */ cam_hw_cdm_pause_core(cdm_hw, false); } else cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); } else CAM_INFO(CAM_CDM, "CDM hw is power in off state"); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&core->bl_fifo[i].fifo_lock); Loading Loading @@ -1647,7 +1692,7 @@ int cam_hw_cdm_handle_error_info( current_fifo, current_tag); /* dump cdm registers for further debug */ cam_hw_cdm_dump_core_debug_registers(cdm_hw); cam_hw_cdm_dump_core_debug_registers(cdm_hw, false); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { reset_val = reset_val | Loading @@ -1673,7 +1718,7 @@ int cam_hw_cdm_handle_error_info( if (time_left <= 0) { rc = -ETIMEDOUT; CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); goto end; set_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status); } rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw); Loading Loading @@ -1712,6 +1757,7 @@ int cam_hw_cdm_handle_error_info( end: clear_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); clear_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock); Loading drivers/cam_cdm/cam_cdm_intf.c +27 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include <linux/delay.h> Loading Loading @@ -506,6 +506,32 @@ int cam_cdm_detect_hang_error(uint32_t handle) } EXPORT_SYMBOL(cam_cdm_detect_hang_error); int cam_cdm_dump_debug_registers(uint32_t handle) { uint32_t hw_index; int rc = -EINVAL; struct cam_hw_intf *hw; if (get_cdm_mgr_refcount()) { CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); rc = -EPERM; return rc; } hw_index = CAM_CDM_GET_HW_IDX(handle); if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { hw = cdm_mgr.nodes[hw_index].device; if (hw && hw->hw_ops.process_cmd) rc = hw->hw_ops.process_cmd(hw->hw_priv, CAM_CDM_HW_INTF_DUMP_DBG_REGS, &handle, sizeof(handle)); } put_cdm_mgr_refcount(); return rc; } int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw, struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, uint32_t *index) Loading Loading
drivers/cam_cdm/cam_cdm.h +2 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ #define CAM_CDM_RESET_HW_STATUS 0x4 #define CAM_CDM_ERROR_HW_STATUS 0x5 #define CAM_CDM_FLUSH_HW_STATUS 0x6 #define CAM_CDM_RESET_ERR_STATUS 0x7 /* Curent BL command masks and shifts */ #define CAM_CDM_CURRENT_BL_LEN 0xFFFFF Loading Loading @@ -376,6 +377,7 @@ enum cam_cdm_hw_process_intf_cmd { CAM_CDM_HW_INTF_CMD_FLUSH_HW, CAM_CDM_HW_INTF_CMD_HANDLE_ERROR, CAM_CDM_HW_INTF_CMD_HANG_DETECT, CAM_CDM_HW_INTF_DUMP_DBG_REGS, CAM_CDM_HW_INTF_CMD_INVALID, }; Loading
drivers/cam_cdm/cam_cdm_core_common.c +16 −0 Original line number Diff line number Diff line Loading @@ -823,6 +823,22 @@ int cam_cdm_process_cmd(void *hw_priv, rc = cam_hw_cdm_hang_detect(cdm_hw, *handle); break; } case CAM_CDM_HW_INTF_DUMP_DBG_REGS: { uint32_t *handle = cmd_args; if (sizeof(uint32_t) != arg_size) { CAM_ERR(CAM_CDM, "Invalid CDM cmd %d size=%x for handle=0x%x", cmd, arg_size, *handle); return -EINVAL; } mutex_lock(&cdm_hw->hw_mutex); cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); mutex_unlock(&cdm_hw->hw_mutex); break; } default: CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd); break; Loading
drivers/cam_cdm/cam_cdm_core_common.h +2 −0 Original line number Diff line number Diff line Loading @@ -56,5 +56,7 @@ struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag( uint32_t tag, struct list_head *bl_list); void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, enum cam_cdm_cb_status status, void *data); void cam_hw_cdm_dump_core_debug_registers( struct cam_hw_info *cdm_hw, bool pause_core); #endif /* _CAM_CDM_CORE_COMMON_H_ */
drivers/cam_cdm/cam_cdm_hw_core.c +132 −86 Original line number Diff line number Diff line Loading @@ -170,14 +170,14 @@ static int cam_hw_cdm_pause_core(struct cam_hw_info *cdm_hw, bool pause) return rc; } int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw) int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw, uint32_t value) { int rc = 0; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; if (cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->core_debug, 0x10100)) { value)) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); rc = -EIO; } Loading Loading @@ -264,24 +264,7 @@ int cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo( return rc; } int cam_hw_cdm_enable_core_dbg_per_fifo( struct cam_hw_info *cdm_hw, uint32_t fifo_idx) { int rc = 0; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; if (cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->core_debug, (0x10100 | fifo_idx << 20))) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); rc = -EIO; } return rc; } void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) static void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) { struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; int i, j; Loading @@ -290,12 +273,6 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw, i, &num_pending_req); if (cam_hw_cdm_enable_core_dbg_per_fifo(cdm_hw, i)) { CAM_ERR(CAM_CDM, "Problem in selecting the fifo for readback"); continue; } for (j = 0; j < num_pending_req ; j++) { cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->bl_fifo_rb, j); Loading @@ -317,89 +294,152 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) } } void cam_hw_cdm_dump_core_debug_registers( struct cam_hw_info *cdm_hw) void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, bool pause_core) { uint32_t dump_reg, core_dbg; uint32_t dump_reg[4], core_dbg = 0x100; int i; bool is_core_paused_already; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; const struct cam_cdm_icl_regs *inv_cmd_log = core->offsets->cmn_reg->icl_reg; cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW core status=%x", dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW core userdata=0x%x", dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg[0]); if (pause_core) { cam_hw_cdm_pause_core(cdm_hw, true); usleep_range(1000, 1010); } cam_hw_cdm_enable_core_dbg(cdm_hw, core_dbg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data, &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->debug_status, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_debug, &core_dbg); &dump_reg[2]); CAM_INFO(CAM_CDM, "Core stat 0x%x udata 0x%x dbg_stat 0x%x", dump_reg[0], dump_reg[1], dump_reg[2]); if (core_dbg & 0x100) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->last_ahb_addr, &dump_reg); CAM_INFO(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg); &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->last_ahb_data, &dump_reg); CAM_INFO(CAM_CDM, "AHB dump reglastdata=%x", dump_reg); &dump_reg[1]); CAM_INFO(CAM_CDM, "AHB dump lastaddr=0x%x lastdata=0x%x", dump_reg[0], dump_reg[1]); } else { CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable"); } if (inv_cmd_log) { if (inv_cmd_log->misc_regs) { cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->misc_regs->icl_status, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->misc_regs->icl_inv_bl_addr, &dump_reg[1]); CAM_INFO(CAM_CDM, "Last Inv Cmd Log(ICL)Status: 0x%x bl_addr: 0x%x", dump_reg[0], dump_reg[1]); } if (inv_cmd_log->data_regs) { cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_inv_data, &dump_reg[0]); CAM_INFO(CAM_CDM, "First word of Last Inv cmd: 0x%x", dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_last_data_0, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_last_data_1, &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_last_data_2, &dump_reg[2]); CAM_INFO(CAM_CDM, "Last good cmd word 0x%x 0x%x 0x%x", dump_reg[0], dump_reg[1], dump_reg[2]); } } if (core_dbg & 0x10000) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg[0]); is_core_paused_already = (bool)(dump_reg[0] & 0x20); if (!is_core_paused_already) { cam_hw_cdm_pause_core(cdm_hw, true); usleep_range(1000, 1010); } cam_hw_cdm_dump_bl_fifo_data(cdm_hw); CAM_INFO(CAM_CDM, "CDM HW default dump"); if (!is_core_paused_already) cam_hw_cdm_pause_core(cdm_hw, false); } cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_cfg, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW core cfg=%x", dump_reg); core->offsets->cmn_reg->core_cfg, &dump_reg[0]); CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg[0]); for (i = 0; i < core->offsets->reg_data->num_bl_fifo_irq; i++) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_status, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW irq status%d=%x", i, dump_reg); core->offsets->irq_reg[i]->irq_status, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_set, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW irq set%d=%x", i, dump_reg); core->offsets->irq_reg[i]->irq_set, &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_mask, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW irq mask%d=%x", i, dump_reg); core->offsets->irq_reg[i]->irq_mask, &dump_reg[2]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_clear, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW irq clear%d=%x", i, dump_reg); core->offsets->irq_reg[i]->irq_clear, &dump_reg[3]); CAM_INFO(CAM_CDM, "cnt %d irq status 0x%x set 0x%x mask 0x%x clear 0x%x", i, dump_reg[0], dump_reg[1], dump_reg[2], dump_reg[3]); } cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_bl_base, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW current BL base=%x", dump_reg); core->offsets->cmn_reg->current_bl_base, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_used_ahb_base, &dump_reg[1]); CAM_INFO(CAM_CDM, "curr BL base 0x%x AHB base 0x%x", dump_reg[0], dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_bl_len, &dump_reg); core->offsets->cmn_reg->wait_status, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->comp_wait[0]->comp_wait_status, &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->comp_wait[1]->comp_wait_status, &dump_reg[2]); CAM_INFO(CAM_CDM, "wait status 0x%x comp wait status 0x%x: 0x%x", dump_reg[0], dump_reg[1], dump_reg[2]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_bl_len, &dump_reg[0]); CAM_INFO(CAM_CDM, "CDM HW current BL len=%d ARB %d FIFO %d tag=%d, ", (dump_reg & CAM_CDM_CURRENT_BL_LEN), (dump_reg & CAM_CDM_CURRENT_BL_ARB) >> (dump_reg[0] & CAM_CDM_CURRENT_BL_LEN), (dump_reg[0] & CAM_CDM_CURRENT_BL_ARB) >> CAM_CDM_CURRENT_BL_ARB_SHIFT, (dump_reg & CAM_CDM_CURRENT_BL_FIFO) >> (dump_reg[0] & CAM_CDM_CURRENT_BL_FIFO) >> CAM_CDM_CURRENT_BL_FIFO_SHIFT, (dump_reg & CAM_CDM_CURRENT_BL_TAG) >> (dump_reg[0] & CAM_CDM_CURRENT_BL_TAG) >> CAM_CDM_CURRENT_BL_TAG_SHIFT); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_used_ahb_base, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW current AHB base=%x", dump_reg); cam_hw_cdm_disable_core_dbg(cdm_hw); if (pause_core) cam_hw_cdm_pause_core(cdm_hw, false); } enum cam_cdm_arbitration cam_cdm_get_arbitration_type( Loading Loading @@ -1107,11 +1147,15 @@ static void cam_hw_cdm_reset_cleanup( int i; struct cam_cdm_bl_cb_request_entry *node, *tnode; bool flush_hw = false; bool reset_err = false; if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) || test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status)) flush_hw = true; if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status)) reset_err = true; for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { list_for_each_entry_safe(node, tnode, &core->bl_fifo[i].bl_request_list, entry) { Loading @@ -1120,12 +1164,19 @@ static void cam_hw_cdm_reset_cleanup( CAM_DBG(CAM_CDM, "Notifying client %d for tag %d", node->client_hdl, node->bl_tag); if (flush_hw) if (flush_hw) { enum cam_cdm_cb_status status; status = reset_err ? CAM_CDM_CB_STATUS_HW_ERROR : CAM_CDM_CB_STATUS_HW_RESUBMIT; cam_cdm_notify_clients(cdm_hw, (node->client_hdl == handle) ? CAM_CDM_CB_STATUS_HW_FLUSH : CAM_CDM_CB_STATUS_HW_RESUBMIT, status, (void *)node); } else cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_HW_RESET_DONE, Loading Loading @@ -1268,7 +1319,7 @@ static void cam_hw_cdm_work(struct work_struct *work) * to dump debug info */ cam_hw_cdm_pause_core(cdm_hw, true); cam_hw_cdm_dump_core_debug_registers(cdm_hw); cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); if (payload->irq_status & CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) { Loading Loading @@ -1307,6 +1358,8 @@ static void cam_hw_cdm_work(struct work_struct *work) CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK)) clear_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); } else { CAM_ERR(CAM_CDM, "NULL payload"); } kfree(payload); payload = NULL; Loading @@ -1329,16 +1382,8 @@ static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_lock(&core->bl_fifo[i].fifo_lock); if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) { /* * First pause CDM, If it fails still proceed * to dump debug info */ cam_hw_cdm_pause_core(cdm_hw, true); cam_hw_cdm_dump_core_debug_registers(cdm_hw); /* Resume CDM back */ cam_hw_cdm_pause_core(cdm_hw, false); } else cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); } else CAM_INFO(CAM_CDM, "CDM hw is power in off state"); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&core->bl_fifo[i].fifo_lock); Loading Loading @@ -1647,7 +1692,7 @@ int cam_hw_cdm_handle_error_info( current_fifo, current_tag); /* dump cdm registers for further debug */ cam_hw_cdm_dump_core_debug_registers(cdm_hw); cam_hw_cdm_dump_core_debug_registers(cdm_hw, false); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { reset_val = reset_val | Loading @@ -1673,7 +1718,7 @@ int cam_hw_cdm_handle_error_info( if (time_left <= 0) { rc = -ETIMEDOUT; CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); goto end; set_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status); } rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw); Loading Loading @@ -1712,6 +1757,7 @@ int cam_hw_cdm_handle_error_info( end: clear_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); clear_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock); Loading
drivers/cam_cdm/cam_cdm_intf.c +27 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include <linux/delay.h> Loading Loading @@ -506,6 +506,32 @@ int cam_cdm_detect_hang_error(uint32_t handle) } EXPORT_SYMBOL(cam_cdm_detect_hang_error); int cam_cdm_dump_debug_registers(uint32_t handle) { uint32_t hw_index; int rc = -EINVAL; struct cam_hw_intf *hw; if (get_cdm_mgr_refcount()) { CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); rc = -EPERM; return rc; } hw_index = CAM_CDM_GET_HW_IDX(handle); if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { hw = cdm_mgr.nodes[hw_index].device; if (hw && hw->hw_ops.process_cmd) rc = hw->hw_ops.process_cmd(hw->hw_priv, CAM_CDM_HW_INTF_DUMP_DBG_REGS, &handle, sizeof(handle)); } put_cdm_mgr_refcount(); return rc; } int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw, struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, uint32_t *index) Loading