msm: camera: isp: Isp irq injection framework
This change constructs a framework of ISP IRQ injection which adds support for HW err IRQ simulation. CRs-Fixed: 3430944 Change-Id: I9552d0aa8b4672bfa04bfc78714d87b72140ad9a Signed-off-by: Stark Lin <quic_starlin@quicinc.com>
This commit is contained in:

committed by
Camera Software Integration

parent
5346e6db3f
commit
c0377f2bff
@@ -44,6 +44,33 @@
|
||||
|
||||
#define MAX_INTERNAL_RECOVERY_ATTEMPTS 1
|
||||
|
||||
#define MAX_PARAMS_FOR_IRQ_INJECT 5
|
||||
#define IRQ_INJECT_DISPLAY_BUF_LEN 4096
|
||||
|
||||
|
||||
typedef int (*cam_isp_irq_inject_cmd_parse_handler)(
|
||||
struct cam_isp_irq_inject_param *irq_inject_param,
|
||||
uint32_t param_index, char *token, bool *is_query);
|
||||
|
||||
#define IRQ_INJECT_USAGE_STRING \
|
||||
"######################################################\n" \
|
||||
"Usage:\n" \
|
||||
"$INJECT_NODE : /sys/kernel/debug/camera/ife/isp_irq_inject\n\n" \
|
||||
" - cat $INJECT_NODE\n" \
|
||||
" print Usage, injected params and current active HW info.\n" \
|
||||
" Also we need to cat the node to get output info after echo params to node.\n\n"\
|
||||
" - echo ?:?:?:? > $INJECT_NODE\n" \
|
||||
" print query info, entering '?' to any param besides req_id to query.\n\n" \
|
||||
" - echo hw_type:hw_idx:res_id:irq_mask:req_id > $INJECT_NODE\n" \
|
||||
" hw_type : Hw to inject IRQ\n" \
|
||||
" hw_idx : Index of the selected hw\n" \
|
||||
" reg_unit : Register to set irq\n" \
|
||||
" irq_mask : IRQ to be triggered\n" \
|
||||
" req_id : Req to trigger the IRQ, entering 'now' to this param will trigger " \
|
||||
"irq immediately\n\n" \
|
||||
"Up to 10 sets of inject params are supported.\n" \
|
||||
"######################################################\n"
|
||||
|
||||
#define CAM_ISP_NON_RECOVERABLE_CSID_ERRORS \
|
||||
(CAM_ISP_HW_ERROR_CSID_LANE_FIFO_OVERFLOW | \
|
||||
CAM_ISP_HW_ERROR_CSID_PKT_HDR_CORRUPTED | \
|
||||
@@ -75,6 +102,7 @@ static struct cam_ife_hw_mgr g_ife_hw_mgr;
|
||||
static uint32_t g_num_ife_available, g_num_ife_lite_available, g_num_sfe_available;
|
||||
static uint32_t g_num_ife_functional, g_num_ife_lite_functional, g_num_sfe_functional;
|
||||
static uint32_t max_ife_out_res, max_sfe_out_res;
|
||||
static char irq_inject_display_buf[IRQ_INJECT_DISPLAY_BUF_LEN];
|
||||
|
||||
static int cam_ife_mgr_find_core_idx(int split_id, struct cam_ife_hw_mgr_ctx *ctx,
|
||||
enum cam_isp_hw_type hw_type, uint32_t *core_idx);
|
||||
@@ -6644,6 +6672,206 @@ static void cam_ife_mgr_send_frame_event(uint64_t request_id, uint32_t ctx_index
|
||||
}
|
||||
}
|
||||
|
||||
static void cam_isp_irq_inject_clear_params(
|
||||
struct cam_isp_irq_inject_param *param)
|
||||
{
|
||||
param->hw_type = -1;
|
||||
param->hw_idx = -1;
|
||||
param->reg_unit = -1;
|
||||
param->irq_mask = -1;
|
||||
param->req_id = 0;
|
||||
param->is_valid = false;
|
||||
memset(param->line_buf, '\0', LINE_BUFFER_LEN);
|
||||
}
|
||||
|
||||
static int cam_ife_hw_mgr_sfe_irq_inject_or_dump_desc(
|
||||
struct cam_ife_hw_mgr *hw_mgr,
|
||||
struct cam_isp_irq_inject_param *params,
|
||||
bool dump_irq_desc)
|
||||
{
|
||||
int i, rc = 0, offset = 0;
|
||||
char *line_buf = NULL;
|
||||
struct cam_hw_intf *hw_intf = NULL;
|
||||
|
||||
line_buf = kzalloc(sizeof(char) * LINE_BUFFER_LEN, GFP_KERNEL);
|
||||
if (!line_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < CAM_SFE_HW_NUM_MAX; i++) {
|
||||
if ((!hw_mgr->sfe_devices[i]) ||
|
||||
(hw_mgr->sfe_devices[i]->hw_intf->hw_idx != params->hw_idx))
|
||||
continue;
|
||||
|
||||
hw_intf = hw_mgr->sfe_devices[i]->hw_intf;
|
||||
|
||||
if (dump_irq_desc) {
|
||||
rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
|
||||
CAM_ISP_HW_CMD_DUMP_IRQ_DESCRIPTION, params,
|
||||
sizeof(struct cam_isp_irq_inject_param));
|
||||
goto clear_param;
|
||||
}
|
||||
|
||||
rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
|
||||
CAM_ISP_HW_CMD_IRQ_INJECTION, params,
|
||||
sizeof(struct cam_isp_irq_inject_param));
|
||||
if (rc)
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Injecting IRQ %x failed for SFE at req: %d\n",
|
||||
params->irq_mask, params->req_id);
|
||||
else
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"IRQ %#x injected for SFE at req: %d\n",
|
||||
params->irq_mask, params->req_id);
|
||||
break;
|
||||
}
|
||||
|
||||
clear_param:
|
||||
strlcat(irq_inject_display_buf, params->line_buf, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
strlcat(irq_inject_display_buf, line_buf, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
|
||||
/* Clear the param injected */
|
||||
cam_isp_irq_inject_clear_params(params);
|
||||
kfree(line_buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_ife_hw_mgr_vfe_irq_inject_or_dump_desc(
|
||||
struct cam_ife_hw_mgr *hw_mgr,
|
||||
struct cam_isp_irq_inject_param *params,
|
||||
bool dump_irq_desc)
|
||||
{
|
||||
int i, rc = 0, offset = 0;
|
||||
char *line_buf = NULL;
|
||||
struct cam_hw_intf *hw_intf = NULL;
|
||||
|
||||
line_buf = kzalloc(sizeof(char) * LINE_BUFFER_LEN, GFP_KERNEL);
|
||||
if (!line_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
|
||||
if ((!hw_mgr->ife_devices[i]) ||
|
||||
(hw_mgr->ife_devices[i]->hw_intf->hw_idx != params->hw_idx))
|
||||
continue;
|
||||
|
||||
hw_intf = hw_mgr->ife_devices[i]->hw_intf;
|
||||
|
||||
if (dump_irq_desc) {
|
||||
rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
|
||||
CAM_ISP_HW_CMD_DUMP_IRQ_DESCRIPTION, params,
|
||||
sizeof(struct cam_isp_irq_inject_param));
|
||||
goto clear_param;
|
||||
}
|
||||
|
||||
rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
|
||||
CAM_ISP_HW_CMD_IRQ_INJECTION, params,
|
||||
sizeof(struct cam_isp_irq_inject_param));
|
||||
if (rc)
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Injecting IRQ %x failed for IFE at req: %d\n",
|
||||
params->irq_mask, params->req_id);
|
||||
else
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"IRQ %#x injected for IFE at req: %d\n",
|
||||
params->irq_mask, params->req_id);
|
||||
break;
|
||||
}
|
||||
|
||||
clear_param:
|
||||
strlcat(irq_inject_display_buf, params->line_buf, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
strlcat(irq_inject_display_buf, line_buf, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
|
||||
/* Clear the param injected */
|
||||
cam_isp_irq_inject_clear_params(params);
|
||||
kfree(line_buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_ife_hw_mgr_csid_irq_inject_or_dump_desc(
|
||||
struct cam_ife_hw_mgr *hw_mgr,
|
||||
struct cam_isp_irq_inject_param *params,
|
||||
bool dump_irq_desc)
|
||||
{
|
||||
int i, rc = 0, offset = 0;
|
||||
char *line_buf = NULL;
|
||||
struct cam_hw_intf *hw_intf = NULL;
|
||||
|
||||
line_buf = kzalloc(sizeof(char) * LINE_BUFFER_LEN, GFP_KERNEL);
|
||||
if (!line_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
|
||||
if ((!hw_mgr->csid_devices[i]) ||
|
||||
(hw_mgr->csid_devices[i]->hw_idx != params->hw_idx))
|
||||
continue;
|
||||
|
||||
hw_intf = hw_mgr->csid_devices[i];
|
||||
|
||||
if (dump_irq_desc) {
|
||||
rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
|
||||
CAM_ISP_HW_CMD_DUMP_IRQ_DESCRIPTION, params,
|
||||
sizeof(struct cam_isp_irq_inject_param));
|
||||
goto clear_param;
|
||||
}
|
||||
|
||||
rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
|
||||
CAM_ISP_HW_CMD_IRQ_INJECTION, params,
|
||||
sizeof(struct cam_isp_irq_inject_param));
|
||||
if (rc)
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Injecting IRQ %x failed for CSID at req: %d\n",
|
||||
params->irq_mask, params->req_id);
|
||||
else
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"IRQ %#x injected for CSID at req: %d\n",
|
||||
params->irq_mask, params->req_id);
|
||||
break;
|
||||
}
|
||||
|
||||
clear_param:
|
||||
strlcat(irq_inject_display_buf, params->line_buf, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
strlcat(irq_inject_display_buf, line_buf, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
|
||||
/* Clear the param injected */
|
||||
cam_isp_irq_inject_clear_params(params);
|
||||
kfree(line_buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_ife_hw_mgr_irq_injection(struct cam_ife_hw_mgr *hw_mgr,
|
||||
uint64_t request_id)
|
||||
{
|
||||
int i, rc = 0;
|
||||
|
||||
for (i = 0; i < MAX_INJECT_SET; i++) {
|
||||
if ((!hw_mgr->irq_inject_param[i].is_valid) ||
|
||||
((hw_mgr->irq_inject_param[i].req_id != request_id) &&
|
||||
(hw_mgr->irq_inject_param[i].req_id != 0xFFFFFFFF)))
|
||||
continue;
|
||||
|
||||
switch (hw_mgr->irq_inject_param[i].hw_type) {
|
||||
case CAM_ISP_HW_TYPE_CSID:
|
||||
rc = cam_ife_hw_mgr_csid_irq_inject_or_dump_desc(
|
||||
hw_mgr, &hw_mgr->irq_inject_param[i], false);
|
||||
break;
|
||||
case CAM_ISP_HW_TYPE_VFE:
|
||||
rc = cam_ife_hw_mgr_vfe_irq_inject_or_dump_desc(
|
||||
hw_mgr, &hw_mgr->irq_inject_param[i], false);
|
||||
break;
|
||||
case CAM_ISP_HW_TYPE_SFE:
|
||||
rc = cam_ife_hw_mgr_sfe_irq_inject_or_dump_desc(
|
||||
hw_mgr, &hw_mgr->irq_inject_param[i], false);
|
||||
break;
|
||||
default:
|
||||
strlcat(irq_inject_display_buf, "No matched HW_TYPE\n",
|
||||
IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
rc = -EINVAL;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* entry function: config_hw */
|
||||
static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
|
||||
void *config_hw_args)
|
||||
@@ -6654,6 +6882,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
|
||||
struct cam_cdm_bl_request *cdm_cmd;
|
||||
struct cam_ife_hw_mgr_ctx *ctx;
|
||||
struct cam_isp_prepare_hw_update_data *hw_update_data;
|
||||
struct cam_ife_hw_mgr *ife_hw_mgr;
|
||||
unsigned long rem_jiffies = 0;
|
||||
bool is_cdm_hung = false;
|
||||
|
||||
@@ -6663,6 +6892,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
|
||||
hw_mgr_priv, config_hw_args);
|
||||
return -EINVAL;
|
||||
}
|
||||
ife_hw_mgr = (struct cam_ife_hw_mgr *)hw_mgr_priv;
|
||||
|
||||
cfg = config_hw_args;
|
||||
ctx = (struct cam_ife_hw_mgr_ctx *)cfg->ctxt_to_hw_map;
|
||||
@@ -6699,6 +6929,11 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
|
||||
ctx, ctx->ctx_index, cfg->request_id);
|
||||
}
|
||||
|
||||
rc = cam_ife_hw_mgr_irq_injection(ife_hw_mgr, cfg->request_id);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "Failed to inject IRQ at req %d",
|
||||
cfg->request_id);
|
||||
|
||||
hw_update_data = (struct cam_isp_prepare_hw_update_data *) cfg->priv;
|
||||
hw_update_data->isp_mgr_ctx = ctx;
|
||||
ctx->cdm_userdata.request_id = cfg->request_id;
|
||||
@@ -15477,6 +15712,469 @@ DEFINE_DEBUGFS_ATTRIBUTE(cam_ife_csid_testbus_debug,
|
||||
cam_ife_get_csid_testbus_debug,
|
||||
cam_ife_set_csid_testbus_debug, "%16llu");
|
||||
|
||||
static int cam_ife_hw_mgr_dump_irq_desc(struct cam_ife_hw_mgr *hw_mgr,
|
||||
struct cam_isp_irq_inject_param *param)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (param->hw_type) {
|
||||
case CAM_ISP_HW_TYPE_CSID:
|
||||
rc = cam_ife_hw_mgr_csid_irq_inject_or_dump_desc(
|
||||
hw_mgr, param, true);
|
||||
break;
|
||||
case CAM_ISP_HW_TYPE_VFE:
|
||||
rc = cam_ife_hw_mgr_vfe_irq_inject_or_dump_desc(
|
||||
hw_mgr, param, true);
|
||||
break;
|
||||
case CAM_ISP_HW_TYPE_SFE:
|
||||
rc = cam_ife_hw_mgr_sfe_irq_inject_or_dump_desc(
|
||||
hw_mgr, param, true);
|
||||
break;
|
||||
default:
|
||||
strlcat(irq_inject_display_buf, "No matched HW_TYPE\n", IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
rc = -EINVAL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void cam_ife_hw_mgr_dump_active_hw(char *buffer, int *offset)
|
||||
{
|
||||
uint32_t i;
|
||||
struct cam_ife_hw_mgr_ctx *ctx;
|
||||
struct cam_isp_hw_mgr_res *hw_mgr_res;
|
||||
struct cam_isp_hw_mgr_res *hw_mgr_res_temp;
|
||||
struct cam_ife_hw_mgr_ctx *ctx_temp;
|
||||
|
||||
mutex_lock(&g_ife_hw_mgr.ctx_mutex);
|
||||
if (list_empty(&g_ife_hw_mgr.used_ctx_list)) {
|
||||
*offset += scnprintf(buffer + *offset, LINE_BUFFER_LEN - *offset,
|
||||
"Currently no ctx in use\n");
|
||||
mutex_unlock(&g_ife_hw_mgr.ctx_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(ctx, ctx_temp,
|
||||
&g_ife_hw_mgr.used_ctx_list, list) {
|
||||
|
||||
list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp,
|
||||
&ctx->res_list_ife_csid, list) {
|
||||
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
|
||||
if (!hw_mgr_res->hw_res[i])
|
||||
continue;
|
||||
|
||||
*offset += scnprintf(buffer + *offset,
|
||||
LINE_BUFFER_LEN - *offset,
|
||||
"hw_type:CSID hw_idx:%d ctx id:%u res: %s\n",
|
||||
hw_mgr_res->hw_res[i]->hw_intf->hw_idx, ctx->ctx_index,
|
||||
hw_mgr_res->hw_res[i]->res_name);
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp,
|
||||
&ctx->res_list_ife_src, list) {
|
||||
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
|
||||
if (!hw_mgr_res->hw_res[i])
|
||||
continue;
|
||||
|
||||
*offset += scnprintf(buffer + *offset,
|
||||
LINE_BUFFER_LEN - *offset,
|
||||
"hw_type:IFE hw_idx:%d ctx id:%u res: %s\n",
|
||||
hw_mgr_res->hw_res[i]->hw_intf->hw_idx, ctx->ctx_index,
|
||||
hw_mgr_res->hw_res[i]->res_name);
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp,
|
||||
&ctx->res_list_sfe_src, list) {
|
||||
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
|
||||
if (!hw_mgr_res->hw_res[i])
|
||||
continue;
|
||||
|
||||
*offset += scnprintf(buffer + *offset,
|
||||
LINE_BUFFER_LEN - *offset,
|
||||
"hw_type:SFE hw_idx:%d ctx id:%u res: %s\n",
|
||||
hw_mgr_res->hw_res[i]->hw_intf->hw_idx, ctx->ctx_index,
|
||||
hw_mgr_res->hw_res[i]->res_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex_unlock(&g_ife_hw_mgr.ctx_mutex);
|
||||
}
|
||||
|
||||
static inline char *__cam_isp_irq_inject_reg_unit_to_name(int32_t reg_unit)
|
||||
{
|
||||
switch (reg_unit) {
|
||||
case CAM_ISP_CSID_TOP_REG:
|
||||
return "CAM_ISP_CSID_TOP_REG";
|
||||
case CAM_ISP_CSID_RX_REG:
|
||||
return "CAM_ISP_CSID_RX_REG";
|
||||
case CAM_ISP_CSID_PATH_IPP_REG:
|
||||
return "CAM_ISP_CSID_PATH_IPP_REG";
|
||||
case CAM_ISP_CSID_PATH_PPP_REG:
|
||||
return "CAM_ISP_CSID_PATH_PPP_REG";
|
||||
case CAM_ISP_CSID_PATH_RDI0_REG:
|
||||
return "CAM_ISP_CSID_PATH_RDI0_REG";
|
||||
case CAM_ISP_CSID_PATH_RDI1_REG:
|
||||
return "CAM_ISP_CSID_PATH_RDI1_REG";
|
||||
case CAM_ISP_CSID_PATH_RDI2_REG:
|
||||
return "CAM_ISP_CSID_PATH_RDI2_REG";
|
||||
case CAM_ISP_CSID_PATH_RDI3_REG:
|
||||
return "CAM_ISP_CSID_PATH_RDI3_REG";
|
||||
case CAM_ISP_CSID_PATH_RDI4_REG:
|
||||
return "CAM_ISP_CSID_PATH_RDI4_REG";
|
||||
case CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG:
|
||||
return "CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG";
|
||||
case CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_1_REG:
|
||||
return "CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_1_REG";
|
||||
case CAM_ISP_SFE_0_BUS_RD_INPUT_IF_IRQ_SET_REG:
|
||||
return "CAM_ISP_SFE_0_BUS_RD_INPUT_IF_IRQ_SET_REG";
|
||||
case CAM_ISP_SFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG:
|
||||
return "CAM_ISP_SFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG";
|
||||
default:
|
||||
return "Invalid reg_unit";
|
||||
}
|
||||
}
|
||||
|
||||
static inline char *__cam_isp_irq_inject_hw_type_to_name(int32_t hw_type)
|
||||
{
|
||||
switch (hw_type) {
|
||||
case CAM_ISP_HW_TYPE_CSID:
|
||||
return "CSID";
|
||||
case CAM_ISP_HW_TYPE_VFE:
|
||||
return "VFE";
|
||||
case CAM_ISP_HW_TYPE_SFE:
|
||||
return "SFE";
|
||||
default:
|
||||
return "Invalid hw_type";
|
||||
}
|
||||
}
|
||||
|
||||
static inline int cam_isp_irq_inject_get_hw_type(
|
||||
int32_t *hw_type, char *token)
|
||||
{
|
||||
if (strcmp(token, "CSID") == 0)
|
||||
*hw_type = CAM_ISP_HW_TYPE_CSID;
|
||||
else if (strcmp(token, "VFE") == 0)
|
||||
*hw_type = CAM_ISP_HW_TYPE_VFE;
|
||||
else if (strcmp(token, "SFE") == 0)
|
||||
*hw_type = CAM_ISP_HW_TYPE_SFE;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_isp_irq_inject_parse_common_params(
|
||||
struct cam_isp_irq_inject_param *irq_inject_param,
|
||||
uint32_t param_index, char *token, bool *is_query)
|
||||
{
|
||||
int i, rc = 0, offset = 0;
|
||||
char *line_buf = NULL;
|
||||
|
||||
line_buf = kzalloc(sizeof(char) * LINE_BUFFER_LEN, GFP_KERNEL);
|
||||
if (!line_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
switch (param_index) {
|
||||
case HW_TYPE:
|
||||
if (strnstr(token, "?", 1)) {
|
||||
*is_query = true;
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Interruptable HW : CSID | IFE | SFE\n");
|
||||
break;
|
||||
}
|
||||
rc = cam_isp_irq_inject_get_hw_type(&irq_inject_param->hw_type, token);
|
||||
if (rc) {
|
||||
irq_inject_param->hw_type = -1;
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Invalid camera hardware [ %s ]\n", token);
|
||||
}
|
||||
break;
|
||||
case HW_IDX:
|
||||
if (strnstr(token, "?", 1)) {
|
||||
*is_query = true;
|
||||
if (irq_inject_param->hw_type == -1) {
|
||||
offset += scnprintf(line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"HW_IDX : Enter hw_type first\n");
|
||||
break;
|
||||
}
|
||||
switch (irq_inject_param->hw_type) {
|
||||
case CAM_ISP_HW_TYPE_CSID:
|
||||
for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
|
||||
if (!g_ife_hw_mgr.csid_devices[i])
|
||||
break;
|
||||
}
|
||||
offset += scnprintf(line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"Max index of CSID : %d\n", i - 1);
|
||||
break;
|
||||
case CAM_ISP_HW_TYPE_VFE:
|
||||
for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
|
||||
if (!g_ife_hw_mgr.ife_devices[i])
|
||||
break;
|
||||
}
|
||||
offset += scnprintf(line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"Max index of VFE : %d\n", i - 1);
|
||||
break;
|
||||
case CAM_ISP_HW_TYPE_SFE:
|
||||
for (i = 0; i < CAM_SFE_HW_NUM_MAX; i++) {
|
||||
if (!g_ife_hw_mgr.sfe_devices[i])
|
||||
break;
|
||||
}
|
||||
offset += scnprintf(line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"Max index of SFE : %d\n", i - 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (kstrtou32(token, 0, &irq_inject_param->hw_idx)) {
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Invalid hw index %s\n", token);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
break;
|
||||
case REG_UNIT:
|
||||
if (strnstr(token, "?", 1)) {
|
||||
*is_query = true;
|
||||
if (irq_inject_param->hw_type == -1) {
|
||||
offset += scnprintf(line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"REG_UNIT : Enter hw_type first\n");
|
||||
break;
|
||||
}
|
||||
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Printing available res for hw_type: %s\n",
|
||||
__cam_isp_irq_inject_hw_type_to_name(
|
||||
irq_inject_param->hw_type));
|
||||
for (i = 0; i < CAM_ISP_REG_UNIT_MAX; i++) {
|
||||
if ((irq_inject_param->hw_type == CAM_ISP_HW_TYPE_CSID) &&
|
||||
i > CAM_ISP_CSID_PATH_RDI4_REG)
|
||||
continue;
|
||||
else if ((irq_inject_param->hw_type == CAM_ISP_HW_TYPE_VFE) &&
|
||||
((i < CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG) ||
|
||||
(i > CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_1_REG)))
|
||||
continue;
|
||||
else if ((irq_inject_param->hw_type == CAM_ISP_HW_TYPE_SFE) &&
|
||||
((i < CAM_ISP_SFE_0_BUS_RD_INPUT_IF_IRQ_SET_REG) ||
|
||||
(i > CAM_ISP_SFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG)))
|
||||
continue;
|
||||
|
||||
offset += scnprintf(line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset, "%d : %s\n", i,
|
||||
__cam_isp_irq_inject_reg_unit_to_name(i));
|
||||
}
|
||||
|
||||
} else if (kstrtou32(token, 0, &irq_inject_param->reg_unit)) {
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Invalid register %s\n", token);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
break;
|
||||
case IRQ_MASK:
|
||||
if (strnstr(token, "?", 1)) {
|
||||
*is_query = true;
|
||||
if ((irq_inject_param->hw_type == -1) ||
|
||||
(irq_inject_param->reg_unit == -1)) {
|
||||
offset += scnprintf(line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"IRQ_MASK : Enter hw_type and reg_unit first\n");
|
||||
break;
|
||||
}
|
||||
if (cam_ife_hw_mgr_dump_irq_desc(&g_ife_hw_mgr,
|
||||
irq_inject_param)) {
|
||||
offset += scnprintf(line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"Dump irq description failed\n");
|
||||
rc = -EINVAL;
|
||||
}
|
||||
} else if (kstrtou32(token, 0, &irq_inject_param->irq_mask)) {
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Invalid irq mask %s\n", token);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
break;
|
||||
case INJECT_REQ:
|
||||
if (strnstr(token, "now", 3)) {
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Trigger IRQ now\n");
|
||||
irq_inject_param->req_id = 0xFFFFFFFF;
|
||||
} else if (kstrtou64(token, 0, &irq_inject_param->req_id)) {
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Invalid request id %s\n", token);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Invalid extra parameter: %s\n", token);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
strlcat(irq_inject_display_buf, line_buf, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
|
||||
kfree(line_buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_isp_irq_inject_command_parser(
|
||||
struct cam_isp_irq_inject_param *irq_inject_param,
|
||||
char **msg, uint32_t max_params,
|
||||
cam_isp_irq_inject_cmd_parse_handler cmd_parse_cb,
|
||||
bool *is_query)
|
||||
{
|
||||
char *token = NULL;
|
||||
char *line_buf = NULL;
|
||||
int rc, param_index = 0, offset = 0;
|
||||
|
||||
line_buf = kzalloc(sizeof(char) * LINE_BUFFER_LEN, GFP_KERNEL);
|
||||
if (!line_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
token = strsep(msg, ":");
|
||||
while (token != NULL) {
|
||||
rc = cmd_parse_cb(irq_inject_param, param_index, token, is_query);
|
||||
if (rc) {
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Parsed Command failed rc: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
param_index++;
|
||||
if (param_index == max_params)
|
||||
break;
|
||||
token = strsep(msg, ":");
|
||||
}
|
||||
|
||||
if ((param_index < max_params) && !(*is_query)) {
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Insufficient parameters passed for total parameters: %u\n",
|
||||
param_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
strlcat(irq_inject_display_buf, line_buf, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
|
||||
kfree(line_buf);
|
||||
return param_index;
|
||||
}
|
||||
|
||||
static ssize_t cam_isp_irq_injection_read(struct file *file,
|
||||
char __user *ubuf,
|
||||
size_t size, loff_t *ppos)
|
||||
{
|
||||
int i, offset = 0;
|
||||
int count = 0;
|
||||
uint32_t hw_type = 0;
|
||||
char *line_buf = NULL;
|
||||
|
||||
line_buf = kzalloc(sizeof(char) * LINE_BUFFER_LEN, GFP_KERNEL);
|
||||
if (!line_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(*ppos) && strlen(irq_inject_display_buf))
|
||||
goto end;
|
||||
else if ((*ppos) && (strlen(irq_inject_display_buf) == 0))
|
||||
return 0;
|
||||
|
||||
strlcat(irq_inject_display_buf, IRQ_INJECT_USAGE_STRING, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
|
||||
for (i = 0; i < MAX_INJECT_SET; i++) {
|
||||
if (!g_ife_hw_mgr.irq_inject_param[i].is_valid)
|
||||
continue;
|
||||
|
||||
hw_type = g_ife_hw_mgr.irq_inject_param[i].hw_type;
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"injected param[%d] : hw_type:%s hw_idx:%d reg_unit:%d irq_mask:%#x req_id:%d\n",
|
||||
i, __cam_isp_irq_inject_hw_type_to_name(hw_type),
|
||||
g_ife_hw_mgr.irq_inject_param[i].hw_idx,
|
||||
g_ife_hw_mgr.irq_inject_param[i].reg_unit,
|
||||
g_ife_hw_mgr.irq_inject_param[i].irq_mask,
|
||||
g_ife_hw_mgr.irq_inject_param[i].req_id);
|
||||
}
|
||||
|
||||
cam_ife_hw_mgr_dump_active_hw(line_buf, &offset);
|
||||
|
||||
strlcat(irq_inject_display_buf, line_buf, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
|
||||
end:
|
||||
if (clear_user(ubuf, size))
|
||||
return -EIO;
|
||||
count = simple_read_from_buffer(ubuf, size, ppos, irq_inject_display_buf,
|
||||
strlen(irq_inject_display_buf));
|
||||
|
||||
memset(irq_inject_display_buf, '\0', IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
kfree(line_buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t cam_isp_irq_injection_write(struct file *file,
|
||||
const char __user *ubuf, size_t size, loff_t *ppos)
|
||||
{
|
||||
bool is_query = false;
|
||||
int i, rc = 0;
|
||||
int offset = 0;
|
||||
uint32_t hw_type = 0;
|
||||
char *msg = NULL;
|
||||
char *line_buf = NULL;
|
||||
char input_buf[LINE_BUFFER_LEN] = {'\0'};
|
||||
|
||||
line_buf = kzalloc(sizeof(char) * LINE_BUFFER_LEN, GFP_KERNEL);
|
||||
if (!line_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(irq_inject_display_buf, '\0', IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
|
||||
if (copy_from_user(input_buf, ubuf, sizeof(input_buf)))
|
||||
return -EFAULT;
|
||||
|
||||
msg = input_buf;
|
||||
|
||||
for (i = 0; i < MAX_INJECT_SET; i++) {
|
||||
if (g_ife_hw_mgr.irq_inject_param[i].is_valid)
|
||||
continue;
|
||||
|
||||
rc = cam_isp_irq_inject_command_parser(
|
||||
&g_ife_hw_mgr.irq_inject_param[i], &msg,
|
||||
MAX_PARAMS_FOR_IRQ_INJECT,
|
||||
cam_isp_irq_inject_parse_common_params, &is_query);
|
||||
if ((rc != MAX_PARAMS_FOR_IRQ_INJECT) || is_query) {
|
||||
cam_isp_irq_inject_clear_params(&g_ife_hw_mgr.irq_inject_param[i]);
|
||||
if (!is_query)
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Parsed Command failed, param_index = %d\n", rc);
|
||||
} else {
|
||||
g_ife_hw_mgr.irq_inject_param[i].is_valid = true;
|
||||
hw_type = g_ife_hw_mgr.irq_inject_param[i].hw_type;
|
||||
offset += scnprintf(line_buf + offset, LINE_BUFFER_LEN - offset,
|
||||
"Setting param[%d] : hw_type:%s hw_idx:%d reg_unit:%d irq_mask:%#x req_id:%d\n",
|
||||
i, __cam_isp_irq_inject_hw_type_to_name(hw_type),
|
||||
g_ife_hw_mgr.irq_inject_param[i].hw_idx,
|
||||
g_ife_hw_mgr.irq_inject_param[i].reg_unit,
|
||||
g_ife_hw_mgr.irq_inject_param[i].irq_mask,
|
||||
g_ife_hw_mgr.irq_inject_param[i].req_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
strlcat(irq_inject_display_buf, line_buf, IRQ_INJECT_DISPLAY_BUF_LEN);
|
||||
|
||||
kfree(line_buf);
|
||||
return size;
|
||||
}
|
||||
|
||||
static const struct file_operations cam_isp_irq_injection = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = cam_isp_irq_injection_read,
|
||||
.write = cam_isp_irq_injection_write,
|
||||
};
|
||||
|
||||
static int cam_ife_hw_mgr_debug_register(void)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -15537,6 +16235,8 @@ static int cam_ife_hw_mgr_debug_register(void)
|
||||
debugfs_create_bool("enable_presil_reg_dump", 0644,
|
||||
g_ife_hw_mgr.debug_cfg.dentry,
|
||||
&g_ife_hw_mgr.debug_cfg.enable_presil_reg_dump);
|
||||
debugfs_create_file("isp_irq_inject", 0644,
|
||||
g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_isp_irq_injection);
|
||||
end:
|
||||
g_ife_hw_mgr.debug_cfg.enable_csid_recovery = 1;
|
||||
return rc;
|
||||
@@ -15808,6 +16508,9 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl,
|
||||
memset(&g_ife_hw_mgr, 0, sizeof(g_ife_hw_mgr));
|
||||
memset(&path_port_map, 0, sizeof(path_port_map));
|
||||
|
||||
for (i = 0; i < MAX_INJECT_SET; i++)
|
||||
cam_isp_irq_inject_clear_params(&g_ife_hw_mgr.irq_inject_param[i]);
|
||||
|
||||
mutex_init(&g_ife_hw_mgr.ctx_mutex);
|
||||
spin_lock_init(&g_ife_hw_mgr.ctx_lock);
|
||||
|
||||
|
@@ -38,6 +38,9 @@ enum cam_ife_ctx_master_type {
|
||||
#define CAM_IFE_CTX_CFG_SW_SYNC_ON BIT(1)
|
||||
#define CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON BIT(2)
|
||||
|
||||
/* Maximum set for irq injection*/
|
||||
#define MAX_INJECT_SET 10
|
||||
|
||||
/**
|
||||
* struct cam_ife_hw_mgr_debug - contain the debug information
|
||||
*
|
||||
@@ -455,6 +458,36 @@ struct cam_isp_sfe_cache_info {
|
||||
bool activated[CAM_ISP_EXPOSURE_MAX];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_isp_irq_inject_irq_desc: Structure to hold IRQ description
|
||||
*
|
||||
* @bitmask : Bitmask of the IRQ
|
||||
* @desc : String to describe the IRQ bit
|
||||
*/
|
||||
struct cam_isp_irq_inject_irq_desc {
|
||||
uint32_t bitmask;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
/*
|
||||
* enum cam_isp_irq_inject_common_param_pos - Irq injection param
|
||||
*
|
||||
* HW_TYPE : hw to inject IRQ
|
||||
* HW_IDX : index of the selected hw
|
||||
* RES_ID : register to set irq
|
||||
* IRQ_MASK : IRQ to be triggered
|
||||
* INJECT_REQ : req to trigger the IRQ
|
||||
* INJECT_PARAM_MAX: max allowed num of injected param
|
||||
*/
|
||||
enum cam_isp_irq_inject_common_param_pos {
|
||||
HW_TYPE,
|
||||
HW_IDX,
|
||||
REG_UNIT,
|
||||
IRQ_MASK,
|
||||
INJECT_REQ,
|
||||
INJECT_PARAM_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_ife_hw_mgr - IFE HW Manager
|
||||
*
|
||||
@@ -486,6 +519,7 @@ struct cam_isp_sfe_cache_info {
|
||||
* @sfe_cache_info SFE Cache Info
|
||||
* @isp_device_type: If device supports single-context(ife) or multi-
|
||||
* context(mc_tfe)
|
||||
* @irq_inject_param Param for isp irq injection
|
||||
*/
|
||||
struct cam_ife_hw_mgr {
|
||||
struct cam_isp_hw_mgr mgr_common;
|
||||
@@ -519,6 +553,8 @@ struct cam_ife_hw_mgr {
|
||||
struct cam_isp_sys_cache_info sys_cache_info[CAM_LLCC_MAX];
|
||||
struct cam_isp_sfe_cache_info sfe_cache_info[CAM_SFE_HW_NUM_MAX];
|
||||
uint32_t isp_device_type;
|
||||
|
||||
struct cam_isp_irq_inject_param irq_inject_param[MAX_INJECT_SET];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -122,6 +122,10 @@ static const struct cam_ife_csid_irq_desc cam_ife_csid_780_rx_irq_desc[][32] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const uint32_t cam_ife_csid_780_num_rx_irq_desc[] = {
|
||||
ARRAY_SIZE(cam_ife_csid_780_rx_irq_desc[0]),
|
||||
};
|
||||
|
||||
static const struct cam_ife_csid_irq_desc cam_ife_csid_780_path_irq_desc[] = {
|
||||
{
|
||||
.bitmask = BIT(0),
|
||||
@@ -283,6 +287,10 @@ static const struct cam_ife_csid_top_irq_desc cam_ife_csid_780_top_irq_desc[][32
|
||||
},
|
||||
};
|
||||
|
||||
static const uint32_t cam_ife_csid_780_num_top_irq_desc[] = {
|
||||
ARRAY_SIZE(cam_ife_csid_780_top_irq_desc[0]),
|
||||
};
|
||||
|
||||
static struct cam_irq_register_set cam_ife_csid_780_irq_reg_set[9] = {
|
||||
/* Top */
|
||||
{
|
||||
@@ -354,8 +362,6 @@ static struct cam_irq_controller_reg_info cam_ife_csid_780_top_irq_reg_info[] =
|
||||
},
|
||||
};
|
||||
|
||||
static uint32_t cam_ife_csid_780_num_top_regs[] = {ARRAY_SIZE(cam_ife_csid_780_top_irq_reg_info),};
|
||||
|
||||
static struct cam_irq_controller_reg_info cam_ife_csid_780_rx_irq_reg_info[] = {
|
||||
{
|
||||
.num_registers = 1,
|
||||
@@ -1458,7 +1464,9 @@ static struct cam_ife_csid_ver2_reg_info cam_ife_csid_780_reg_info = {
|
||||
.rx_irq_desc = &cam_ife_csid_780_rx_irq_desc,
|
||||
.path_irq_desc = cam_ife_csid_780_path_irq_desc,
|
||||
.top_irq_desc = &cam_ife_csid_780_top_irq_desc,
|
||||
.num_top_err_irqs = cam_ife_csid_780_num_top_regs,
|
||||
.num_top_err_irqs = cam_ife_csid_780_num_top_irq_desc,
|
||||
.num_rx_err_irqs = cam_ife_csid_780_num_rx_irq_desc,
|
||||
.num_path_err_irqs = ARRAY_SIZE(cam_ife_csid_780_path_irq_desc),
|
||||
.num_top_regs = 1,
|
||||
.num_rx_regs = 1,
|
||||
};
|
||||
|
@@ -132,6 +132,10 @@ static const struct cam_ife_csid_irq_desc cam_ife_csid_880_rx_irq_desc[][32] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const uint32_t cam_ife_csid_880_num_rx_irq_desc[] = {
|
||||
ARRAY_SIZE(cam_ife_csid_880_rx_irq_desc[0]),
|
||||
};
|
||||
|
||||
static const struct cam_ife_csid_irq_desc cam_ife_csid_880_path_irq_desc[] = {
|
||||
{
|
||||
.bitmask = BIT(0),
|
||||
@@ -1496,10 +1500,12 @@ static struct cam_ife_csid_ver2_reg_info cam_ife_csid_880_reg_info = {
|
||||
},
|
||||
.need_top_cfg = 0x1,
|
||||
.csid_cust_node_map = {0x1, 0x0, 0x2},
|
||||
.top_irq_desc = &cam_ife_csid_880_top_irq_desc,
|
||||
.rx_irq_desc = &cam_ife_csid_880_rx_irq_desc,
|
||||
.path_irq_desc = cam_ife_csid_880_path_irq_desc,
|
||||
.top_irq_desc = &cam_ife_csid_880_top_irq_desc,
|
||||
.num_top_err_irqs = cam_ife_csid_880_num_top_irq_desc,
|
||||
.num_rx_err_irqs = cam_ife_csid_880_num_rx_irq_desc,
|
||||
.num_path_err_irqs = ARRAY_SIZE(cam_ife_csid_880_path_irq_desc),
|
||||
.num_top_regs = 1,
|
||||
.num_rx_regs = 1,
|
||||
};
|
||||
|
@@ -1795,11 +1795,12 @@ static struct cam_ife_csid_ver2_reg_info cam_ife_csid_980_reg_info = {
|
||||
.path_reg[CAM_IFE_PIX_PATH_RES_RDI_4] = &cam_ife_csid_980_rdi_4_reg_info,
|
||||
.ipp_mc_reg = &cam_ife_csid_980_ipp_mc_reg_info,
|
||||
.need_top_cfg = 0x0,
|
||||
.top_irq_desc = &cam_ife_csid_980_top_irq_desc,
|
||||
.rx_irq_desc = &cam_ife_csid_980_rx_irq_desc,
|
||||
.path_irq_desc = cam_ife_csid_980_path_irq_desc,
|
||||
.top_irq_desc = &cam_ife_csid_980_top_irq_desc,
|
||||
.num_top_err_irqs = cam_ife_csid_980_num_top_irq_desc,
|
||||
.num_rx_err_irqs = cam_ife_csid_980_num_rx_irq_desc,
|
||||
.num_path_err_irqs = ARRAY_SIZE(cam_ife_csid_980_path_irq_desc),
|
||||
.num_top_regs = 1,
|
||||
.num_rx_regs = 1,
|
||||
};
|
||||
|
@@ -6535,6 +6535,160 @@ end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_ife_csid_ver2_dump_irq_desc(
|
||||
struct cam_ife_csid_ver2_hw *csid_hw, void *args)
|
||||
{
|
||||
int i, offset = 0;
|
||||
struct cam_isp_irq_inject_param *inject_params = NULL;
|
||||
const struct cam_ife_csid_ver2_reg_info *csid_reg = NULL;
|
||||
|
||||
if (!args) {
|
||||
CAM_ERR(CAM_ISP, "Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
inject_params = (struct cam_isp_irq_inject_param *)args;
|
||||
csid_reg = (struct cam_ife_csid_ver2_reg_info *)
|
||||
csid_hw->core_info->csid_reg;
|
||||
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"Printing executable IRQ for hw_type: CSID reg_unit: %d\n",
|
||||
inject_params->reg_unit);
|
||||
|
||||
switch (inject_params->reg_unit) {
|
||||
case CAM_ISP_CSID_TOP_REG:
|
||||
for (i = 0; i < csid_reg->num_top_err_irqs[CAM_IFE_CSID_TOP_IRQ_STATUS_REG0]; i++) {
|
||||
if (!(*csid_reg->top_irq_desc)
|
||||
[CAM_IFE_CSID_TOP_IRQ_STATUS_REG0][i].bitmask)
|
||||
break;
|
||||
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset, "%#12x : %s - %s\n",
|
||||
(*csid_reg->top_irq_desc)
|
||||
[CAM_IFE_CSID_TOP_IRQ_STATUS_REG0][i].bitmask,
|
||||
(*csid_reg->top_irq_desc)
|
||||
[CAM_IFE_CSID_TOP_IRQ_STATUS_REG0][i].err_name,
|
||||
(*csid_reg->top_irq_desc)
|
||||
[CAM_IFE_CSID_TOP_IRQ_STATUS_REG0][i].desc);
|
||||
}
|
||||
break;
|
||||
case CAM_ISP_CSID_RX_REG:
|
||||
for (i = 0; i < csid_reg->num_rx_err_irqs[CAM_IFE_CSID_RX_IRQ_STATUS_REG0]; i++) {
|
||||
if (!(*csid_reg->rx_irq_desc)
|
||||
[CAM_IFE_CSID_RX_IRQ_STATUS_REG0][i].bitmask)
|
||||
break;
|
||||
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset, "%#12x : %s\n",
|
||||
(*csid_reg->rx_irq_desc)
|
||||
[CAM_IFE_CSID_RX_IRQ_STATUS_REG0][i].bitmask,
|
||||
(*csid_reg->rx_irq_desc)
|
||||
[CAM_IFE_CSID_RX_IRQ_STATUS_REG0][i].desc);
|
||||
}
|
||||
break;
|
||||
case CAM_ISP_CSID_PATH_IPP_REG:
|
||||
case CAM_ISP_CSID_PATH_PPP_REG:
|
||||
case CAM_ISP_CSID_PATH_RDI0_REG:
|
||||
case CAM_ISP_CSID_PATH_RDI1_REG:
|
||||
case CAM_ISP_CSID_PATH_RDI2_REG:
|
||||
case CAM_ISP_CSID_PATH_RDI3_REG:
|
||||
case CAM_ISP_CSID_PATH_RDI4_REG:
|
||||
for (i = 0; i < csid_reg->num_path_err_irqs; i++)
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset, "%#12x : %s\n",
|
||||
csid_reg->path_irq_desc[i].bitmask,
|
||||
csid_reg->path_irq_desc[i].desc);
|
||||
break;
|
||||
default:
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"No matched reg unit for injection\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_ife_csid_ver2_irq_inject(
|
||||
struct cam_ife_csid_ver2_hw *csid_hw, void *args)
|
||||
{
|
||||
uint32_t irq_set_addr = 0;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
struct cam_isp_irq_inject_param *inject_params = NULL;
|
||||
const struct cam_ife_csid_ver2_reg_info *csid_reg = NULL;
|
||||
void __iomem *mem_base;
|
||||
|
||||
if (!args) {
|
||||
CAM_ERR(CAM_ISP, "Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
inject_params = (struct cam_isp_irq_inject_param *)args;
|
||||
csid_reg = (struct cam_ife_csid_ver2_reg_info *)
|
||||
csid_hw->core_info->csid_reg;
|
||||
soc_info = &csid_hw->hw_info->soc_info;
|
||||
mem_base = soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base;
|
||||
|
||||
switch (inject_params->reg_unit) {
|
||||
case CAM_ISP_CSID_TOP_REG: {
|
||||
irq_set_addr =
|
||||
csid_reg->cmn_reg->top_irq_set_addr[CAM_IFE_CSID_TOP_IRQ_STATUS_REG0];
|
||||
break;
|
||||
}
|
||||
case CAM_ISP_CSID_RX_REG: {
|
||||
irq_set_addr =
|
||||
csid_reg->csi2_reg->irq_set_addr[CAM_IFE_CSID_RX_IRQ_STATUS_REG0];
|
||||
break;
|
||||
}
|
||||
case CAM_ISP_CSID_PATH_IPP_REG: {
|
||||
irq_set_addr =
|
||||
csid_reg->path_reg[CAM_IFE_PIX_PATH_RES_IPP]->irq_set_addr;
|
||||
break;
|
||||
}
|
||||
case CAM_ISP_CSID_PATH_PPP_REG: {
|
||||
irq_set_addr =
|
||||
csid_reg->path_reg[CAM_IFE_PIX_PATH_RES_PPP]->irq_set_addr;
|
||||
break;
|
||||
}
|
||||
case CAM_ISP_CSID_PATH_RDI0_REG: {
|
||||
irq_set_addr =
|
||||
csid_reg->path_reg[CAM_IFE_PIX_PATH_RES_RDI_0]->irq_set_addr;
|
||||
break;
|
||||
}
|
||||
case CAM_ISP_CSID_PATH_RDI1_REG: {
|
||||
irq_set_addr =
|
||||
csid_reg->path_reg[CAM_IFE_PIX_PATH_RES_RDI_1]->irq_set_addr;
|
||||
break;
|
||||
}
|
||||
case CAM_ISP_CSID_PATH_RDI2_REG: {
|
||||
irq_set_addr =
|
||||
csid_reg->path_reg[CAM_IFE_PIX_PATH_RES_RDI_2]->irq_set_addr;
|
||||
break;
|
||||
}
|
||||
case CAM_ISP_CSID_PATH_RDI3_REG: {
|
||||
irq_set_addr =
|
||||
csid_reg->path_reg[CAM_IFE_PIX_PATH_RES_RDI_3]->irq_set_addr;
|
||||
break;
|
||||
}
|
||||
case CAM_ISP_CSID_PATH_RDI4_REG: {
|
||||
irq_set_addr =
|
||||
csid_reg->path_reg[CAM_IFE_PIX_PATH_RES_RDI_4]->irq_set_addr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CAM_INFO(CAM_ISP, "No matched reg unit for injection");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cam_io_w_mb(inject_params->irq_mask, mem_base + irq_set_addr);
|
||||
cam_io_w_mb(0x10, mem_base + csid_reg->cmn_reg->irq_cmd_addr);
|
||||
CAM_INFO(CAM_ISP, "Injected : irq_mask %#x set_reg_offset %#x",
|
||||
inject_params->irq_mask, irq_set_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_ife_csid_ver2_reset_out_of_sync_cnt(
|
||||
struct cam_ife_csid_ver2_hw *csid_hw, void *args)
|
||||
{
|
||||
@@ -6784,6 +6938,12 @@ static int cam_ife_csid_ver2_process_cmd(void *hw_priv,
|
||||
case CAM_ISP_HW_CMD_IRQ_COMP_CFG:
|
||||
rc = cam_ife_csid_ver2_irq_comp_cfg(csid_hw, cmd_args, arg_size);
|
||||
break;
|
||||
case CAM_ISP_HW_CMD_IRQ_INJECTION:
|
||||
rc = cam_ife_csid_ver2_irq_inject(csid_hw, cmd_args);
|
||||
break;
|
||||
case CAM_ISP_HW_CMD_DUMP_IRQ_DESCRIPTION:
|
||||
rc = cam_ife_csid_ver2_dump_irq_desc(csid_hw, cmd_args);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ISP, "CSID:%u unsupported cmd:%d",
|
||||
csid_hw->hw_intf->hw_idx, cmd_type);
|
||||
|
@@ -733,11 +733,12 @@ struct cam_ife_csid_ver2_reg_info {
|
||||
CAM_IFE_CSID_HW_NUM_MAX];
|
||||
const int input_core_sel[
|
||||
CAM_IFE_CSID_HW_NUM_MAX][CAM_IFE_CSID_INPUT_CORE_SEL_MAX];
|
||||
const struct cam_ife_csid_top_irq_desc (*top_irq_desc)[][32];
|
||||
const struct cam_ife_csid_irq_desc (*rx_irq_desc)[][32];
|
||||
const struct cam_ife_csid_irq_desc *path_irq_desc;
|
||||
const struct cam_ife_csid_top_irq_desc (*top_irq_desc)[][32];
|
||||
const uint32_t *num_top_err_irqs;
|
||||
const uint32_t *num_rx_err_irqs;
|
||||
const uint32_t num_path_err_irqs;
|
||||
const uint32_t num_top_regs;
|
||||
const uint32_t num_rx_regs;
|
||||
};
|
||||
|
@@ -118,8 +118,6 @@ static const struct cam_ife_csid_irq_desc cam_ife_csid_lite_780_rx_irq_desc[][32
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
static const struct cam_ife_csid_irq_desc cam_ife_csid_lite_780_path_irq_desc[] = {
|
||||
{
|
||||
.bitmask = BIT(0),
|
||||
@@ -284,6 +282,9 @@ static const struct cam_ife_csid_top_irq_desc cam_ife_csid_lite_780_top_irq_desc
|
||||
static const uint32_t cam_ife_csid_lite_780_num_top_irq_desc[] = {
|
||||
ARRAY_SIZE(cam_ife_csid_lite_780_top_irq_desc[0]),
|
||||
};
|
||||
static const uint32_t cam_ife_csid_lite_780_num_rx_irq_desc[] = {
|
||||
ARRAY_SIZE(cam_ife_csid_lite_780_rx_irq_desc[0]),
|
||||
};
|
||||
|
||||
static struct cam_irq_register_set cam_ife_csid_lite_780_irq_reg_set[9] = {
|
||||
/* Top */
|
||||
@@ -1049,10 +1050,12 @@ static struct cam_ife_csid_ver2_reg_info cam_ife_csid_lite_780_reg_info = {
|
||||
.path_reg[CAM_IFE_PIX_PATH_RES_RDI_2] = &cam_ife_csid_lite_780_rdi_2_reg_info,
|
||||
.path_reg[CAM_IFE_PIX_PATH_RES_RDI_3] = &cam_ife_csid_lite_780_rdi_3_reg_info,
|
||||
.need_top_cfg = 0,
|
||||
.top_irq_desc = &cam_ife_csid_lite_780_top_irq_desc,
|
||||
.rx_irq_desc = &cam_ife_csid_lite_780_rx_irq_desc,
|
||||
.path_irq_desc = cam_ife_csid_lite_780_path_irq_desc,
|
||||
.top_irq_desc = &cam_ife_csid_lite_780_top_irq_desc,
|
||||
.num_top_err_irqs = cam_ife_csid_lite_780_num_top_irq_desc,
|
||||
.num_rx_err_irqs = cam_ife_csid_lite_780_num_rx_irq_desc,
|
||||
.num_path_err_irqs = ARRAY_SIZE(cam_ife_csid_lite_780_path_irq_desc),
|
||||
.num_top_regs = 1,
|
||||
.num_rx_regs = 1,
|
||||
};
|
||||
|
@@ -290,7 +290,11 @@ static const struct cam_ife_csid_top_irq_desc cam_ife_csid_lite_880_top_irq_desc
|
||||
};
|
||||
|
||||
static const uint32_t cam_ife_csid_lite_880_num_top_irq_desc[] = {
|
||||
ARRAY_SIZE(cam_ife_csid_lite_880_top_irq_desc[0])};
|
||||
ARRAY_SIZE(cam_ife_csid_lite_880_top_irq_desc[0]),
|
||||
};
|
||||
static const uint32_t cam_ife_csid_lite_880_num_rx_irq_desc[] = {
|
||||
ARRAY_SIZE(cam_ife_csid_lite_880_rx_irq_desc[0]),
|
||||
};
|
||||
|
||||
static struct cam_irq_register_set cam_ife_csid_lite_880_irq_reg_set[9] = {
|
||||
/* Top */
|
||||
@@ -1055,10 +1059,12 @@ static struct cam_ife_csid_ver2_reg_info cam_ife_csid_lite_880_reg_info = {
|
||||
.path_reg[CAM_IFE_PIX_PATH_RES_RDI_2] = &cam_ife_csid_lite_880_rdi_2_reg_info,
|
||||
.path_reg[CAM_IFE_PIX_PATH_RES_RDI_3] = &cam_ife_csid_lite_880_rdi_3_reg_info,
|
||||
.need_top_cfg = 0,
|
||||
.top_irq_desc = &cam_ife_csid_lite_880_top_irq_desc,
|
||||
.rx_irq_desc = &cam_ife_csid_lite_880_rx_irq_desc,
|
||||
.path_irq_desc = cam_ife_csid_lite_880_path_irq_desc,
|
||||
.top_irq_desc = &cam_ife_csid_lite_880_top_irq_desc,
|
||||
.num_top_err_irqs = cam_ife_csid_lite_880_num_top_irq_desc,
|
||||
.num_rx_err_irqs = cam_ife_csid_lite_880_num_rx_irq_desc,
|
||||
.num_path_err_irqs = ARRAY_SIZE(cam_ife_csid_lite_880_path_irq_desc),
|
||||
.num_top_regs = 1,
|
||||
.num_rx_regs = 1,
|
||||
};
|
||||
|
@@ -29,10 +29,12 @@ static struct cam_ife_csid_ver2_reg_info cam_ife_csid_lite_980_reg_info = {
|
||||
.path_reg[CAM_IFE_PIX_PATH_RES_RDI_2] = &cam_ife_csid_lite_880_rdi_2_reg_info,
|
||||
.path_reg[CAM_IFE_PIX_PATH_RES_RDI_3] = &cam_ife_csid_lite_880_rdi_3_reg_info,
|
||||
.need_top_cfg = 0,
|
||||
.top_irq_desc = &cam_ife_csid_lite_880_top_irq_desc,
|
||||
.rx_irq_desc = &cam_ife_csid_lite_880_rx_irq_desc,
|
||||
.path_irq_desc = cam_ife_csid_lite_880_path_irq_desc,
|
||||
.top_irq_desc = &cam_ife_csid_lite_880_top_irq_desc,
|
||||
.num_top_err_irqs = cam_ife_csid_lite_880_num_top_irq_desc,
|
||||
.num_rx_err_irqs = cam_ife_csid_lite_880_num_rx_irq_desc,
|
||||
.num_path_err_irqs = ARRAY_SIZE(cam_ife_csid_lite_880_path_irq_desc),
|
||||
.num_top_regs = 1,
|
||||
.num_rx_regs = 1,
|
||||
};
|
||||
|
@@ -28,6 +28,11 @@
|
||||
*/
|
||||
#define CAM_ISP_RES_NAME_LEN 16
|
||||
|
||||
/*
|
||||
* MAX len of line_buffer
|
||||
*/
|
||||
#define LINE_BUFFER_LEN 1500
|
||||
|
||||
/* Access core_info of isp resource node */
|
||||
#define cam_isp_res_core_info(res) (((struct cam_hw_info *)res->hw_intf->hw_priv)->core_info)
|
||||
|
||||
@@ -233,6 +238,8 @@ enum cam_isp_hw_cmd_type {
|
||||
CAM_ISP_HW_CMD_CSID_DUMP_CROP_REG,
|
||||
CAM_ISP_HW_CMD_MC_CTXT_SEL,
|
||||
CAM_ISP_HW_CMD_IRQ_COMP_CFG,
|
||||
CAM_ISP_HW_CMD_IRQ_INJECTION,
|
||||
CAM_ISP_HW_CMD_DUMP_IRQ_DESCRIPTION,
|
||||
CAM_ISP_HW_CMD_MAX,
|
||||
};
|
||||
|
||||
@@ -580,4 +587,59 @@ struct cam_isp_hw_overflow_info {
|
||||
bool is_bus_overflow;
|
||||
};
|
||||
|
||||
enum cam_isp_irq_inject_reg_unit_type {
|
||||
CAM_ISP_CSID_TOP_REG,
|
||||
CAM_ISP_CSID_RX_REG,
|
||||
CAM_ISP_CSID_PATH_IPP_REG,
|
||||
CAM_ISP_CSID_PATH_PPP_REG,
|
||||
CAM_ISP_CSID_PATH_RDI0_REG,
|
||||
CAM_ISP_CSID_PATH_RDI1_REG,
|
||||
CAM_ISP_CSID_PATH_RDI2_REG,
|
||||
CAM_ISP_CSID_PATH_RDI3_REG,
|
||||
CAM_ISP_CSID_PATH_RDI4_REG,
|
||||
CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG,
|
||||
CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_1_REG,
|
||||
CAM_ISP_SFE_0_BUS_RD_INPUT_IF_IRQ_SET_REG,
|
||||
CAM_ISP_SFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG,
|
||||
CAM_ISP_REG_UNIT_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_isp_irq_inject_param:
|
||||
*
|
||||
* @Brief: Params for isp irq injection
|
||||
*
|
||||
* @hw_type : Hw to inject IRQ
|
||||
* @hw_idx : Index of the selected hw
|
||||
* @reg_unit : Register to set irq
|
||||
* @irq_mask : IRQ to be triggered
|
||||
* @req_id : Req to trigger the IRQ
|
||||
* @is_valid : Flag to indicate current set of params is valid or not
|
||||
* @line_buf : Buffer to temporarily keep log
|
||||
*/
|
||||
struct cam_isp_irq_inject_param {
|
||||
int32_t hw_type;
|
||||
int32_t hw_idx;
|
||||
int32_t reg_unit;
|
||||
int32_t irq_mask;
|
||||
uint64_t req_id;
|
||||
bool is_valid;
|
||||
char line_buf[LINE_BUFFER_LEN];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_isp_params_injection:
|
||||
*
|
||||
* @Brief: args for irq injection or irq desc dump
|
||||
*
|
||||
* @param : Params for isp irq injection
|
||||
* @vfe_hw_info : Vfe hw info
|
||||
* @sfe_hw_info : Sfe hw info
|
||||
*/
|
||||
struct cam_isp_params_injection {
|
||||
struct cam_isp_irq_inject_param *param;
|
||||
void *vfe_hw_info;
|
||||
void *sfe_hw_info;
|
||||
};
|
||||
|
||||
#endif /* _CAM_ISP_HW_H_ */
|
||||
|
@@ -691,6 +691,18 @@ static struct cam_irq_register_set sfe780_bus_rd_irq_reg[1] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_sfe_bus_rd_err_irq_desc sfe780_bus_rd_irq_err_desc[] = {
|
||||
{
|
||||
.bitmask = BIT(0),
|
||||
.err_name = "INFO_CONS_VIOLATION",
|
||||
.desc = "Clients have illegal programming, check CONS_VIOLATION_STATUS",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(31),
|
||||
.err_name = "INFO_CCIF_VIOLATION",
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_sfe_bus_rd_constraint_error_desc
|
||||
sfe780_bus_rd_cons_error_desc[CAM_SFE_BUS_RD_CONS_ERR_MAX] = {
|
||||
{
|
||||
@@ -820,6 +832,8 @@ static struct cam_sfe_bus_rd_hw_info sfe780_bus_rd_hw_info = {
|
||||
.max_height = -1,
|
||||
},
|
||||
},
|
||||
.num_bus_rd_errors = ARRAY_SIZE(sfe780_bus_rd_irq_err_desc),
|
||||
.bus_rd_err_desc = sfe780_bus_rd_irq_err_desc,
|
||||
.top_irq_shift = 0x1,
|
||||
.latency_buf_allocation = 2048,
|
||||
.sys_cache_default_val = 0x20,
|
||||
@@ -828,6 +842,34 @@ static struct cam_sfe_bus_rd_hw_info sfe780_bus_rd_hw_info = {
|
||||
.constraint_error_info = &sfe780_bus_rd_constraint_error_info,
|
||||
};
|
||||
|
||||
static struct cam_sfe_bus_wr_err_irq_desc sfe780_bus_wr_irq_err_desc[] = {
|
||||
{
|
||||
.bitmask = BIT(26),
|
||||
.err_name = "IPCC_FENCE_DATA_ERR",
|
||||
.desc = "IPCC or FENCE Data was not available in the Input Fifo",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(27),
|
||||
.err_name = "IPCC_FENCE_ADDR_ERR",
|
||||
.desc = "IPCC or FENCE address fifo was empty and read was attempted",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(28),
|
||||
.err_name = "CONS_VIOLATION",
|
||||
.desc = "Programming of software registers violated the constraints",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(30),
|
||||
.err_name = "VIOLATION",
|
||||
.desc = "Client has a violation in ccif protocol at input",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(31),
|
||||
.err_name = "IMAGE_SIZE_VIOLATION",
|
||||
.desc = "Programmed image size is not same as image size from the CCIF",
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_sfe_bus_wr_constraint_error_desc
|
||||
sfe780_bus_wr_cons_error_desc[CAM_SFE_BUS_CONS_ERR_MAX] = {
|
||||
{
|
||||
@@ -1674,6 +1716,8 @@ static struct cam_sfe_bus_wr_hw_info sfe780_bus_wr_hw_info = {
|
||||
},
|
||||
},
|
||||
.constraint_error_info = &sfe780_bus_wr_constraint_error_info,
|
||||
.num_bus_wr_errors = ARRAY_SIZE(sfe780_bus_wr_irq_err_desc),
|
||||
.bus_wr_err_desc = sfe780_bus_wr_irq_err_desc,
|
||||
.comp_done_mask = {
|
||||
BIT(17), BIT(18), BIT(19), BIT(20), BIT(21), BIT(22), BIT(23),
|
||||
BIT(24), BIT(25), BIT(26),
|
||||
|
@@ -728,6 +728,18 @@ static struct cam_irq_register_set sfe880_bus_rd_irq_reg[1] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_sfe_bus_rd_err_irq_desc sfe880_bus_rd_irq_err_desc[] = {
|
||||
{
|
||||
.bitmask = BIT(0),
|
||||
.err_name = "INFO_CONS_VIOLATION",
|
||||
.desc = "Clients have illegal programming, check CONS_VIOLATION_STATUS",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(31),
|
||||
.err_name = "INFO_CCIF_VIOLATION",
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_sfe_bus_rd_constraint_error_desc
|
||||
sfe880_bus_rd_cons_error_desc[CAM_SFE_BUS_RD_CONS_ERR_MAX] = {
|
||||
{
|
||||
@@ -859,6 +871,8 @@ static struct cam_sfe_bus_rd_hw_info sfe880_bus_rd_hw_info = {
|
||||
.max_height = -1,
|
||||
},
|
||||
},
|
||||
.num_bus_rd_errors = ARRAY_SIZE(sfe880_bus_rd_irq_err_desc),
|
||||
.bus_rd_err_desc = sfe880_bus_rd_irq_err_desc,
|
||||
.top_irq_shift = 0x1,
|
||||
.latency_buf_allocation = 2048,
|
||||
.sys_cache_default_val = 0x20,
|
||||
@@ -867,6 +881,34 @@ static struct cam_sfe_bus_rd_hw_info sfe880_bus_rd_hw_info = {
|
||||
.constraint_error_info = &sfe880_bus_rd_constraint_error_info,
|
||||
};
|
||||
|
||||
static struct cam_sfe_bus_wr_err_irq_desc sfe880_bus_wr_irq_err_desc[] = {
|
||||
{
|
||||
.bitmask = BIT(26),
|
||||
.err_name = "IPCC_FENCE_DATA_ERR",
|
||||
.desc = "IPCC or FENCE Data was not available in the Input Fifo",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(27),
|
||||
.err_name = "IPCC_FENCE_ADDR_ERR",
|
||||
.desc = "IPCC or FENCE address fifo was empty and read was attempted",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(28),
|
||||
.err_name = "CONS_VIOLATION",
|
||||
.desc = "Programming of software registers violated the constraints",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(30),
|
||||
.err_name = "VIOLATION",
|
||||
.desc = "Client has a violation in ccif protocol at input",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(31),
|
||||
.err_name = "IMAGE_SIZE_VIOLATION",
|
||||
.desc = "Programmed image size is not same as image size from the CCIF",
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_sfe_bus_wr_constraint_error_desc
|
||||
sfe880_bus_wr_cons_error_desc[CAM_SFE_BUS_CONS_ERR_MAX] = {
|
||||
{
|
||||
@@ -1767,6 +1809,8 @@ static struct cam_sfe_bus_wr_hw_info sfe880_bus_wr_hw_info = {
|
||||
},
|
||||
},
|
||||
.constraint_error_info = &sfe880_bus_wr_constraint_error_info,
|
||||
.num_bus_wr_errors = ARRAY_SIZE(sfe880_bus_wr_irq_err_desc),
|
||||
.bus_wr_err_desc = sfe880_bus_wr_irq_err_desc,
|
||||
.comp_done_mask = {
|
||||
BIT(17), BIT(18), BIT(19), BIT(20), BIT(21), BIT(23),
|
||||
BIT(24), BIT(25), BIT(26), BIT(27), BIT(22),
|
||||
|
@@ -377,6 +377,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type,
|
||||
struct cam_hw_info *sfe_hw = hw_priv;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_sfe_hw_core_info *core_info = NULL;
|
||||
struct cam_sfe_hw_info *hw_info = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (!hw_priv) {
|
||||
@@ -386,6 +387,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type,
|
||||
|
||||
soc_info = &sfe_hw->soc_info;
|
||||
core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info;
|
||||
hw_info = core_info->sfe_hw_info;
|
||||
|
||||
switch (cmd_type) {
|
||||
case CAM_ISP_HW_CMD_GET_CHANGE_BASE:
|
||||
@@ -435,6 +437,8 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type,
|
||||
fallthrough;
|
||||
case CAM_ISP_HW_CMD_GET_RES_FOR_MID:
|
||||
case CAM_ISP_HW_CMD_DUMP_BUS_INFO:
|
||||
case CAM_ISP_HW_CMD_IRQ_INJECTION:
|
||||
case CAM_ISP_HW_CMD_DUMP_IRQ_DESCRIPTION:
|
||||
/* propagate to SFE bus wr */
|
||||
core_info->sfe_bus_wr->hw_ops.process_cmd(
|
||||
core_info->sfe_bus_wr->bus_priv, cmd_type,
|
||||
|
@@ -60,6 +60,7 @@ struct cam_sfe_bus_rd_common_data {
|
||||
void __iomem *mem_base;
|
||||
struct cam_hw_intf *hw_intf;
|
||||
struct cam_sfe_bus_rd_reg_offset_common *common_reg;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
uint32_t io_buf_update[
|
||||
MAX_REG_VAL_PAIR_SIZE];
|
||||
void *bus_irq_controller;
|
||||
@@ -1796,6 +1797,80 @@ end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_sfe_bus_rd_irq_inject(
|
||||
void *priv, void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
struct cam_sfe_bus_rd_priv *bus_priv = NULL;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_sfe_bus_rd_hw_info *bus_rd_hw_info = NULL;
|
||||
struct cam_irq_controller_reg_info *irq_reg_info = NULL;
|
||||
struct cam_irq_register_set *inject_reg = NULL;
|
||||
struct cam_isp_irq_inject_param *inject_params = NULL;
|
||||
|
||||
if (!cmd_args) {
|
||||
CAM_ERR(CAM_ISP, "Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus_priv = (struct cam_sfe_bus_rd_priv *)priv;
|
||||
soc_info = bus_priv->common_data.soc_info;
|
||||
bus_rd_hw_info = (struct cam_sfe_bus_rd_hw_info *)bus_priv->bus_rd_hw_info;
|
||||
irq_reg_info = &bus_rd_hw_info->common_reg.irq_reg_info;
|
||||
inject_reg = irq_reg_info->irq_reg_set;
|
||||
inject_params = (struct cam_isp_irq_inject_param *)cmd_args;
|
||||
|
||||
if (!inject_reg) {
|
||||
CAM_INFO(CAM_SFE, "Invalid inject_reg");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (inject_params->reg_unit ==
|
||||
CAM_ISP_SFE_0_BUS_RD_INPUT_IF_IRQ_SET_REG) {
|
||||
cam_io_w_mb(inject_params->irq_mask,
|
||||
soc_info->reg_map[SFE_CORE_BASE_IDX].mem_base +
|
||||
inject_reg->set_reg_offset);
|
||||
cam_io_w_mb(0x10, soc_info->reg_map[SFE_CORE_BASE_IDX].mem_base +
|
||||
irq_reg_info->global_irq_cmd_offset);
|
||||
CAM_INFO(CAM_SFE, "Injected : irq_mask %#x set_reg_offset %#x",
|
||||
inject_params->irq_mask, inject_reg->set_reg_offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_sfe_bus_rd_dump_irq_desc(
|
||||
void *priv, void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
int i, offset = 0;
|
||||
struct cam_sfe_bus_rd_priv *bus_priv = NULL;
|
||||
struct cam_sfe_bus_rd_hw_info *bus_rd_hw_info = NULL;
|
||||
struct cam_isp_irq_inject_param *inject_params = NULL;
|
||||
|
||||
if (!cmd_args) {
|
||||
CAM_ERR(CAM_ISP, "Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus_priv = (struct cam_sfe_bus_rd_priv *)priv;
|
||||
bus_rd_hw_info = (struct cam_sfe_bus_rd_hw_info *)bus_priv->bus_rd_hw_info;
|
||||
inject_params = (struct cam_isp_irq_inject_param *)cmd_args;
|
||||
|
||||
if (inject_params->reg_unit ==
|
||||
CAM_ISP_SFE_0_BUS_RD_INPUT_IF_IRQ_SET_REG) {
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"Printing executable IRQ for hw_type: SFE reg_unit: %d\n",
|
||||
inject_params->reg_unit);
|
||||
|
||||
for (i = 0; i < bus_rd_hw_info->num_bus_rd_errors; i++)
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset, "%#12x : %s - %s\n",
|
||||
bus_rd_hw_info->bus_rd_err_desc[i].bitmask,
|
||||
bus_rd_hw_info->bus_rd_err_desc[i].err_name,
|
||||
bus_rd_hw_info->bus_rd_err_desc[i].desc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_sfe_bus_init_hw(void *hw_priv,
|
||||
void *init_hw_args, uint32_t arg_size)
|
||||
{
|
||||
@@ -1974,6 +2049,12 @@ static int cam_sfe_bus_rd_process_cmd(
|
||||
(struct cam_sfe_bus_rd_priv *)priv);
|
||||
break;
|
||||
}
|
||||
case CAM_ISP_HW_CMD_IRQ_INJECTION:
|
||||
rc = cam_sfe_bus_rd_irq_inject(priv, cmd_args, arg_size);
|
||||
break;
|
||||
case CAM_ISP_HW_CMD_DUMP_IRQ_DESCRIPTION:
|
||||
rc = cam_sfe_bus_rd_dump_irq_desc(priv, cmd_args, arg_size);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR_RATE_LIMIT(CAM_SFE,
|
||||
"Invalid SFE BUS RD command type: %d",
|
||||
@@ -2032,6 +2113,7 @@ int cam_sfe_bus_rd_init(
|
||||
bus_priv->common_data.irq_err_mask = bus_rd_hw_info->irq_err_mask;
|
||||
bus_priv->common_data.cons_chk_en_avail =
|
||||
bus_rd_hw_info->constraint_error_info->cons_chk_en_avail;
|
||||
bus_priv->common_data.soc_info = soc_info;
|
||||
bus_priv->top_irq_shift = bus_rd_hw_info->top_irq_shift;
|
||||
bus_priv->latency_buf_allocation = bus_rd_hw_info->latency_buf_allocation;
|
||||
bus_priv->sys_cache_default_cfg = bus_rd_hw_info->sys_cache_default_val;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_SFE_BUS_RD_H_
|
||||
@@ -31,6 +31,17 @@ enum cam_sfe_bus_rd_type {
|
||||
CAM_SFE_BUS_RD_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_sfe_bus_rd_err_irq_desc:
|
||||
*
|
||||
* @Brief: Bus rd error irq description
|
||||
*/
|
||||
struct cam_sfe_bus_rd_err_irq_desc {
|
||||
uint32_t bitmask;
|
||||
char *err_name;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_sfe_bus_rd_constraint_error_desc:
|
||||
*
|
||||
@@ -133,6 +144,8 @@ struct cam_sfe_bus_rd_hw_info {
|
||||
uint32_t num_bus_rd_resc;
|
||||
struct cam_sfe_bus_rd_info
|
||||
sfe_bus_rd_info[CAM_SFE_BUS_RD_MAX];
|
||||
uint32_t num_bus_rd_errors;
|
||||
struct cam_sfe_bus_rd_err_irq_desc *bus_rd_err_desc;
|
||||
uint32_t top_irq_shift;
|
||||
uint32_t latency_buf_allocation;
|
||||
uint32_t sys_cache_default_val;
|
||||
|
@@ -94,6 +94,7 @@ struct cam_sfe_bus_wr_common_data {
|
||||
uint32_t sys_cache_default_cfg;
|
||||
uint32_t sfe_debug_cfg;
|
||||
struct cam_sfe_bus_cache_dbg_cfg cache_dbg_cfg;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
};
|
||||
|
||||
struct cam_sfe_wr_scratch_buf_info {
|
||||
@@ -195,7 +196,8 @@ struct cam_sfe_bus_wr_priv {
|
||||
int error_irq_handle;
|
||||
void *tasklet_info;
|
||||
struct cam_sfe_bus_wr_constraint_error_info *constraint_error_info;
|
||||
struct cam_sfe_bus_sfe_out_hw_info *sfe_out_hw_info;
|
||||
struct cam_sfe_bus_sfe_out_hw_info *sfe_out_hw_info;
|
||||
struct cam_sfe_bus_wr_hw_info *bus_wr_hw_info;
|
||||
};
|
||||
|
||||
static int cam_sfe_bus_subscribe_error_irq(
|
||||
@@ -3166,6 +3168,76 @@ end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_sfe_bus_wr_irq_inject(
|
||||
void *priv, void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
struct cam_sfe_bus_wr_priv *bus_priv = NULL;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_sfe_bus_wr_hw_info *bus_wr_hw_info = NULL;
|
||||
struct cam_irq_controller_reg_info *irq_reg_info = NULL;
|
||||
struct cam_irq_register_set *inject_reg = NULL;
|
||||
struct cam_isp_irq_inject_param *inject_params = NULL;
|
||||
|
||||
bus_priv = (struct cam_sfe_bus_wr_priv *)priv;
|
||||
soc_info = bus_priv->common_data.soc_info;
|
||||
bus_wr_hw_info = (struct cam_sfe_bus_wr_hw_info *)bus_priv->bus_wr_hw_info;
|
||||
irq_reg_info = &bus_wr_hw_info->common_reg.irq_reg_info;
|
||||
inject_reg = irq_reg_info->irq_reg_set;
|
||||
inject_params = (struct cam_isp_irq_inject_param *)cmd_args;
|
||||
|
||||
if (!inject_params || !inject_reg) {
|
||||
CAM_INFO(CAM_SFE, "Invalid inject_params or inject_reg");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (inject_params->reg_unit ==
|
||||
CAM_ISP_SFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG) {
|
||||
|
||||
cam_io_w_mb(inject_params->irq_mask,
|
||||
soc_info->reg_map[SFE_CORE_BASE_IDX].mem_base +
|
||||
inject_reg->set_reg_offset);
|
||||
cam_io_w_mb(0x10, soc_info->reg_map[SFE_CORE_BASE_IDX].mem_base +
|
||||
irq_reg_info->global_irq_cmd_offset);
|
||||
CAM_INFO(CAM_SFE, "Injected : irq_mask %#x set_reg_offset %#x",
|
||||
inject_params->irq_mask, inject_reg->set_reg_offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_sfe_bus_wr_dump_irq_desc(
|
||||
void *priv, void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
int i, offset = 0;
|
||||
struct cam_sfe_bus_wr_priv *bus_priv = NULL;
|
||||
struct cam_sfe_bus_wr_hw_info *bus_wr_hw_info = NULL;
|
||||
struct cam_isp_irq_inject_param *inject_params = NULL;
|
||||
|
||||
if (!cmd_args) {
|
||||
CAM_ERR(CAM_ISP, "Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus_priv = (struct cam_sfe_bus_wr_priv *)priv;
|
||||
bus_wr_hw_info = (struct cam_sfe_bus_wr_hw_info *)bus_priv->bus_wr_hw_info;
|
||||
inject_params = (struct cam_isp_irq_inject_param *)cmd_args;
|
||||
|
||||
if (inject_params->reg_unit ==
|
||||
CAM_ISP_SFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG) {
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"Printing executable IRQ for hw_type: SFE reg_unit: %d\n",
|
||||
inject_params->reg_unit);
|
||||
|
||||
for (i = 0; i < bus_wr_hw_info->num_bus_wr_errors; i++)
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset, "%#12x : %s - %s\n",
|
||||
bus_wr_hw_info->bus_wr_err_desc[i].bitmask,
|
||||
bus_wr_hw_info->bus_wr_err_desc[i].err_name,
|
||||
bus_wr_hw_info->bus_wr_err_desc[i].desc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_sfe_bus_wr_start_hw(void *hw_priv,
|
||||
void *start_hw_args, uint32_t arg_size)
|
||||
{
|
||||
@@ -3353,6 +3425,12 @@ static int cam_sfe_bus_wr_process_cmd(
|
||||
case CAM_ISP_HW_CMD_GET_RES_FOR_MID:
|
||||
rc = cam_sfe_bus_wr_get_res_for_mid(priv, cmd_args, arg_size);
|
||||
break;
|
||||
case CAM_ISP_HW_CMD_IRQ_INJECTION:
|
||||
rc = cam_sfe_bus_wr_irq_inject(priv, cmd_args, arg_size);
|
||||
break;
|
||||
case CAM_ISP_HW_CMD_DUMP_IRQ_DESCRIPTION:
|
||||
rc = cam_sfe_bus_wr_dump_irq_desc(priv, cmd_args, arg_size);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR_RATE_LIMIT(CAM_SFE, "Invalid HW command type:%d",
|
||||
cmd_type);
|
||||
@@ -3400,27 +3478,29 @@ int cam_sfe_bus_wr_init(
|
||||
}
|
||||
sfe_bus_local->bus_priv = bus_priv;
|
||||
|
||||
bus_priv->num_client = hw_info->num_client;
|
||||
bus_priv->num_out = hw_info->num_out;
|
||||
bus_priv->max_out_res = hw_info->max_out_res;
|
||||
bus_priv->num_comp_grp = hw_info->num_comp_grp;
|
||||
bus_priv->top_irq_shift = hw_info->top_irq_shift;
|
||||
bus_priv->common_data.num_sec_out = 0;
|
||||
bus_priv->common_data.secure_mode = CAM_SECURE_MODE_NON_SECURE;
|
||||
bus_priv->common_data.core_index = soc_info->index;
|
||||
bus_priv->common_data.mem_base =
|
||||
bus_priv->num_client = hw_info->num_client;
|
||||
bus_priv->num_out = hw_info->num_out;
|
||||
bus_priv->max_out_res = hw_info->max_out_res;
|
||||
bus_priv->num_comp_grp = hw_info->num_comp_grp;
|
||||
bus_priv->top_irq_shift = hw_info->top_irq_shift;
|
||||
bus_priv->common_data.num_sec_out = 0;
|
||||
bus_priv->common_data.secure_mode = CAM_SECURE_MODE_NON_SECURE;
|
||||
bus_priv->common_data.core_index = soc_info->index;
|
||||
bus_priv->common_data.mem_base =
|
||||
CAM_SOC_GET_REG_MAP_START(soc_info, SFE_CORE_BASE_IDX);
|
||||
bus_priv->common_data.hw_intf = hw_intf;
|
||||
bus_priv->common_data.common_reg = &hw_info->common_reg;
|
||||
bus_priv->common_data.line_done_cfg = hw_info->line_done_cfg;
|
||||
bus_priv->common_data.pack_align_shift = hw_info->pack_align_shift;
|
||||
bus_priv->common_data.max_bw_counter_limit = hw_info->max_bw_counter_limit;
|
||||
bus_priv->common_data.err_irq_subscribe = false;
|
||||
bus_priv->common_data.sfe_irq_controller = sfe_irq_controller;
|
||||
bus_priv->common_data.irq_err_mask = hw_info->irq_err_mask;
|
||||
bus_priv->common_data.hw_intf = hw_intf;
|
||||
bus_priv->common_data.common_reg = &hw_info->common_reg;
|
||||
bus_priv->common_data.line_done_cfg = hw_info->line_done_cfg;
|
||||
bus_priv->common_data.pack_align_shift = hw_info->pack_align_shift;
|
||||
bus_priv->common_data.max_bw_counter_limit = hw_info->max_bw_counter_limit;
|
||||
bus_priv->common_data.err_irq_subscribe = false;
|
||||
bus_priv->common_data.sfe_irq_controller = sfe_irq_controller;
|
||||
bus_priv->common_data.irq_err_mask = hw_info->irq_err_mask;
|
||||
bus_priv->common_data.sys_cache_default_cfg = hw_info->sys_cache_default_val;
|
||||
bus_priv->constraint_error_info = hw_info->constraint_error_info;
|
||||
bus_priv->sfe_out_hw_info = hw_info->sfe_out_hw_info;
|
||||
bus_priv->common_data.soc_info = soc_info;
|
||||
bus_priv->constraint_error_info = hw_info->constraint_error_info;
|
||||
bus_priv->sfe_out_hw_info = hw_info->sfe_out_hw_info;
|
||||
bus_priv->bus_wr_hw_info = hw_info;
|
||||
rc = cam_cpas_get_cpas_hw_version(&bus_priv->common_data.hw_version);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_SFE, "Failed to get hw_version rc:%d", rc);
|
||||
|
@@ -65,6 +65,17 @@ enum cam_sfe_bus_sfe_out_type {
|
||||
CAM_SFE_BUS_SFE_OUT_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_sfe_bus_wr_err_irq_desc:
|
||||
*
|
||||
* @Brief: Bus wr error irq description
|
||||
*/
|
||||
struct cam_sfe_bus_wr_err_irq_desc {
|
||||
uint32_t bitmask;
|
||||
char *err_name;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_sfe_constraint_error_desc:
|
||||
*
|
||||
@@ -198,6 +209,8 @@ struct cam_sfe_bus_wr_hw_info {
|
||||
sfe_out_hw_info[CAM_SFE_BUS_SFE_OUT_MAX];
|
||||
struct cam_sfe_bus_wr_constraint_error_info
|
||||
*constraint_error_info;
|
||||
uint32_t num_bus_wr_errors;
|
||||
struct cam_sfe_bus_wr_err_irq_desc *bus_wr_err_desc;
|
||||
uint32_t comp_done_mask[CAM_SFE_BUS_WR_COMP_GRP_MAX];
|
||||
uint32_t num_comp_grp;
|
||||
uint32_t line_done_cfg;
|
||||
|
@@ -486,6 +486,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
|
||||
struct cam_hw_info *vfe_hw = hw_priv;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_vfe_hw_core_info *core_info = NULL;
|
||||
struct cam_vfe_hw_info *hw_info = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (!hw_priv) {
|
||||
@@ -495,6 +496,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
|
||||
|
||||
soc_info = &vfe_hw->soc_info;
|
||||
core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info;
|
||||
hw_info = core_info->vfe_hw_info;
|
||||
|
||||
switch (cmd_type) {
|
||||
case CAM_ISP_HW_CMD_GET_CHANGE_BASE:
|
||||
@@ -535,6 +537,8 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
|
||||
case CAM_ISP_HW_CMD_BUF_UPDATE:
|
||||
case CAM_ISP_HW_USER_DUMP:
|
||||
case CAM_ISP_HW_CMD_MC_CTXT_SEL:
|
||||
case CAM_ISP_HW_CMD_IRQ_INJECTION:
|
||||
case CAM_ISP_HW_CMD_DUMP_IRQ_DESCRIPTION:
|
||||
rc = core_info->vfe_bus->hw_ops.process_cmd(
|
||||
core_info->vfe_bus->bus_priv, cmd_type, cmd_args,
|
||||
arg_size);
|
||||
|
@@ -963,6 +963,47 @@ static uint32_t vfe780_out_port_mid[][4] = {
|
||||
{22, 0, 0, 0},
|
||||
};
|
||||
|
||||
static struct cam_vfe_bus_ver3_err_irq_desc vfe780_bus_irq_err_desc_0[] = {
|
||||
{
|
||||
.bitmask = BIT(26),
|
||||
.err_name = "IPCC_FENCE_DATA_ERR",
|
||||
.desc = "IPCC or FENCE Data was not available in the Input Fifo",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(27),
|
||||
.err_name = "IPCC_FENCE_ADDR_ERR",
|
||||
.desc = "IPCC or FENCE address fifo was empty and read was attempted",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(28),
|
||||
.err_name = "CONS_VIOLATION",
|
||||
.desc = "Programming of software registers violated the constraints",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(30),
|
||||
.err_name = "VIOLATION",
|
||||
.desc = "Client has a violation in ccif protocol at input",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(31),
|
||||
.err_name = "IMAGE_SIZE_VIOLATION",
|
||||
.desc = "Programmed image size is not same as image size from the CCIF",
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_vfe_bus_ver3_err_irq_desc vfe780_bus_irq_err_desc_1[] = {
|
||||
{
|
||||
.bitmask = BIT(28),
|
||||
.err_name = "EARLY_DONE",
|
||||
.desc = "Buf done for each client. Early done irq for clients STATS_BAF",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(29),
|
||||
.err_name = "EARLY_DONE",
|
||||
.desc = "Buf done for each client. Early done irq for clients STATS_BAF",
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_vfe_bus_ver3_hw_info vfe780_bus_hw_info = {
|
||||
.common_reg = {
|
||||
.hw_version = 0x00000C00,
|
||||
@@ -2312,6 +2353,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe780_bus_hw_info = {
|
||||
.error_description = "Meta Stride unalign"
|
||||
},
|
||||
},
|
||||
.num_bus_errors_0 = ARRAY_SIZE(vfe780_bus_irq_err_desc_0),
|
||||
.num_bus_errors_1 = ARRAY_SIZE(vfe780_bus_irq_err_desc_1),
|
||||
.bus_err_desc_0 = vfe780_bus_irq_err_desc_0,
|
||||
.bus_err_desc_1 = vfe780_bus_irq_err_desc_1,
|
||||
.num_comp_grp = 15,
|
||||
.support_consumed_addr = true,
|
||||
.comp_done_mask = {
|
||||
|
@@ -1008,6 +1008,47 @@ static uint32_t vfe880_out_port_mid[][4] = {
|
||||
{30, 0, 0, 0},
|
||||
};
|
||||
|
||||
static struct cam_vfe_bus_ver3_err_irq_desc vfe880_bus_irq_err_desc_0[] = {
|
||||
{
|
||||
.bitmask = BIT(26),
|
||||
.err_name = "IPCC_FENCE_DATA_ERR",
|
||||
.desc = "IPCC or FENCE Data was not available in the Input Fifo",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(27),
|
||||
.err_name = "IPCC_FENCE_ADDR_ERR",
|
||||
.desc = "IPCC or FENCE address fifo was empty and read was attempted",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(28),
|
||||
.err_name = "CONS_VIOLATION",
|
||||
.desc = "Programming of software registers violated the constraints",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(30),
|
||||
.err_name = "VIOLATION",
|
||||
.desc = "Client has a violation in ccif protocol at input",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(31),
|
||||
.err_name = "IMAGE_SIZE_VIOLATION",
|
||||
.desc = "Programmed image size is not same as image size from the CCIF",
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_vfe_bus_ver3_err_irq_desc vfe880_bus_irq_err_desc_1[] = {
|
||||
{
|
||||
.bitmask = BIT(28),
|
||||
.err_name = "EARLY_DONE",
|
||||
.desc = "Buf done for each client. Early done irq for clients STATS_BAF",
|
||||
},
|
||||
{
|
||||
.bitmask = BIT(29),
|
||||
.err_name = "EARLY_DONE",
|
||||
.desc = "Buf done for each client. Early done irq for clients STATS_BAF",
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_vfe_bus_ver3_hw_info vfe880_bus_hw_info = {
|
||||
.common_reg = {
|
||||
.hw_version = 0x00000C00,
|
||||
@@ -2404,6 +2445,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe880_bus_hw_info = {
|
||||
.error_description = "Meta Stride unalign"
|
||||
},
|
||||
},
|
||||
.num_bus_errors_0 = ARRAY_SIZE(vfe880_bus_irq_err_desc_0),
|
||||
.num_bus_errors_1 = ARRAY_SIZE(vfe880_bus_irq_err_desc_1),
|
||||
.bus_err_desc_0 = vfe880_bus_irq_err_desc_0,
|
||||
.bus_err_desc_1 = vfe880_bus_irq_err_desc_1,
|
||||
.num_comp_grp = 16,
|
||||
.support_consumed_addr = true,
|
||||
.comp_done_mask = {
|
||||
|
@@ -88,6 +88,7 @@ struct cam_vfe_bus_ver3_common_data {
|
||||
void *vfe_irq_controller;
|
||||
void *buf_done_controller;
|
||||
void *priv;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
struct cam_vfe_bus_ver3_reg_offset_common *common_reg;
|
||||
struct cam_cdm_utils_ops *cdm_util_ops;
|
||||
uint32_t io_buf_update[
|
||||
@@ -209,24 +210,25 @@ struct cam_vfe_bus_ver3_vfe_out_data {
|
||||
};
|
||||
|
||||
struct cam_vfe_bus_ver3_priv {
|
||||
struct cam_vfe_bus_ver3_common_data common_data;
|
||||
uint32_t num_client;
|
||||
uint32_t num_out;
|
||||
uint32_t num_comp_grp;
|
||||
uint32_t top_irq_shift;
|
||||
struct cam_vfe_bus_ver3_common_data common_data;
|
||||
uint32_t num_client;
|
||||
uint32_t num_out;
|
||||
uint32_t num_comp_grp;
|
||||
uint32_t top_irq_shift;
|
||||
|
||||
struct cam_isp_resource_node *bus_client;
|
||||
struct cam_isp_resource_node *comp_grp;
|
||||
struct cam_isp_resource_node *vfe_out;
|
||||
struct cam_isp_resource_node *bus_client;
|
||||
struct cam_isp_resource_node *comp_grp;
|
||||
struct cam_isp_resource_node *vfe_out;
|
||||
uint32_t vfe_out_map_outtype[CAM_VFE_BUS_VER3_VFE_OUT_MAX];
|
||||
|
||||
int bus_irq_handle;
|
||||
int rup_irq_handle;
|
||||
int error_irq_handle;
|
||||
void *tasklet_info;
|
||||
uint32_t max_out_res;
|
||||
uint32_t num_cons_err;
|
||||
struct cam_vfe_constraint_error_info *constraint_error_list;
|
||||
int bus_irq_handle;
|
||||
int rup_irq_handle;
|
||||
int error_irq_handle;
|
||||
void *tasklet_info;
|
||||
uint32_t max_out_res;
|
||||
uint32_t num_cons_err;
|
||||
struct cam_vfe_constraint_error_info *constraint_error_list;
|
||||
struct cam_vfe_bus_ver3_hw_info *bus_hw_info;
|
||||
};
|
||||
|
||||
static void cam_vfe_bus_ver3_unsubscribe_init_irq(
|
||||
@@ -4179,6 +4181,95 @@ static int cam_vfe_bus_ver3_mc_ctxt_sel(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_vfe_bus_ver3_irq_inject(
|
||||
void *priv, void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
struct cam_vfe_bus_ver3_priv *bus_priv = NULL;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_vfe_bus_ver3_hw_info *bus_hw_info = NULL;
|
||||
struct cam_isp_irq_inject_param *inject_params = NULL;
|
||||
struct cam_irq_register_set *inject_reg = NULL;
|
||||
|
||||
if (!cmd_args) {
|
||||
CAM_ERR(CAM_ISP, "Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus_priv = (struct cam_vfe_bus_ver3_priv *)priv;
|
||||
soc_info = bus_priv->common_data.soc_info;
|
||||
bus_hw_info = (struct cam_vfe_bus_ver3_hw_info *)bus_priv->bus_hw_info;
|
||||
inject_params = (struct cam_isp_irq_inject_param *)cmd_args;
|
||||
|
||||
if (inject_params->reg_unit ==
|
||||
CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG)
|
||||
inject_reg = &bus_hw_info->common_reg.irq_reg_info.irq_reg_set[0];
|
||||
else if (inject_params->reg_unit ==
|
||||
CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_1_REG)
|
||||
inject_reg = &bus_hw_info->common_reg.irq_reg_info.irq_reg_set[1];
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (!inject_reg) {
|
||||
CAM_INFO(CAM_ISP, "Invalid inject_reg");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cam_io_w_mb(inject_params->irq_mask,
|
||||
soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base +
|
||||
inject_reg->set_reg_offset);
|
||||
cam_io_w_mb(0x10, soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base +
|
||||
bus_hw_info->common_reg.irq_reg_info.global_irq_cmd_offset);
|
||||
CAM_INFO(CAM_ISP, "Injected : irq_mask %#x set_reg_offset %#x",
|
||||
inject_params->irq_mask, inject_reg->set_reg_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_vfe_bus_ver3_dump_irq_desc(
|
||||
void *priv, void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
int i, offset = 0;
|
||||
int num_irq_desc = 0;
|
||||
struct cam_vfe_bus_ver3_priv *bus_priv = NULL;
|
||||
struct cam_vfe_bus_ver3_hw_info *bus_hw_info = NULL;
|
||||
struct cam_isp_irq_inject_param *inject_params = NULL;
|
||||
struct cam_vfe_bus_ver3_err_irq_desc *err_irq_desc = NULL;
|
||||
|
||||
if (!cmd_args) {
|
||||
CAM_ERR(CAM_ISP, "Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus_priv = (struct cam_vfe_bus_ver3_priv *)priv;
|
||||
bus_hw_info = (struct cam_vfe_bus_ver3_hw_info *)bus_priv->bus_hw_info;
|
||||
inject_params = (struct cam_isp_irq_inject_param *)cmd_args;
|
||||
|
||||
if (inject_params->reg_unit ==
|
||||
CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_0_REG) {
|
||||
err_irq_desc = bus_hw_info->bus_err_desc_0;
|
||||
num_irq_desc = bus_hw_info->num_bus_errors_0;
|
||||
} else if (inject_params->reg_unit ==
|
||||
CAM_ISP_IFE_0_BUS_WR_INPUT_IF_IRQ_SET_1_REG) {
|
||||
err_irq_desc = bus_hw_info->bus_err_desc_1;
|
||||
num_irq_desc = bus_hw_info->num_bus_errors_1;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset,
|
||||
"Printing executable IRQ for hw_type: VFE reg_unit: %d\n",
|
||||
inject_params->reg_unit);
|
||||
|
||||
for (i = 0; i < num_irq_desc; i++)
|
||||
offset += scnprintf(inject_params->line_buf + offset,
|
||||
LINE_BUFFER_LEN - offset, "%#12x : %s - %s\n",
|
||||
err_irq_desc[i].bitmask,
|
||||
err_irq_desc[i].err_name,
|
||||
err_irq_desc[i].desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_vfe_bus_ver3_start_hw(void *hw_priv,
|
||||
void *start_hw_args, uint32_t arg_size)
|
||||
{
|
||||
@@ -4412,6 +4503,12 @@ static int cam_vfe_bus_ver3_process_cmd(
|
||||
rc = cam_vfe_bus_ver3_mc_ctxt_sel(priv, cmd_args, arg_size);
|
||||
break;
|
||||
|
||||
case CAM_ISP_HW_CMD_IRQ_INJECTION:
|
||||
rc = cam_vfe_bus_ver3_irq_inject(priv, cmd_args, arg_size);
|
||||
break;
|
||||
case CAM_ISP_HW_CMD_DUMP_IRQ_DESCRIPTION:
|
||||
rc = cam_vfe_bus_ver3_dump_irq_desc(priv, cmd_args, arg_size);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR_RATE_LIMIT(CAM_ISP, "VFE:%u Invalid camif process command:%d",
|
||||
priv->hw_intf->hw_idx, cmd_type);
|
||||
@@ -4498,6 +4595,8 @@ int cam_vfe_bus_ver3_init(
|
||||
ver3_hw_info->max_bw_counter_limit;
|
||||
bus_priv->num_cons_err = ver3_hw_info->num_cons_err;
|
||||
bus_priv->constraint_error_list = ver3_hw_info->constraint_error_list;
|
||||
bus_priv->common_data.soc_info = soc_info;
|
||||
bus_priv->bus_hw_info = ver3_hw_info;
|
||||
|
||||
if (bus_priv->num_out >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) {
|
||||
CAM_ERR(CAM_ISP, "VFE:%u number of vfe out:%d more than max value:%d ",
|
||||
|
@@ -99,6 +99,17 @@ enum cam_vfe_bus_ver3_vfe_out_type {
|
||||
CAM_VFE_BUS_VER3_VFE_OUT_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_vfe_bus_ver3_err_irq_desc:
|
||||
*
|
||||
* @Brief: Bus error irq description
|
||||
*/
|
||||
struct cam_vfe_bus_ver3_err_irq_desc {
|
||||
uint32_t bitmask;
|
||||
char *err_name;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_vfe_constraint_error_info:
|
||||
*
|
||||
@@ -249,6 +260,10 @@ struct cam_vfe_bus_ver3_hw_info {
|
||||
uint32_t num_cons_err;
|
||||
struct cam_vfe_constraint_error_info
|
||||
constraint_error_list[CAM_VFE_BUS_VER3_CONS_ERR_MAX];
|
||||
uint32_t num_bus_errors_0;
|
||||
uint32_t num_bus_errors_1;
|
||||
struct cam_vfe_bus_ver3_err_irq_desc *bus_err_desc_0;
|
||||
struct cam_vfe_bus_ver3_err_irq_desc *bus_err_desc_1;
|
||||
uint32_t num_comp_grp;
|
||||
uint32_t comp_done_mask[CAM_VFE_BUS_VER3_COMP_GRP_MAX];
|
||||
uint32_t top_irq_shift;
|
||||
|
Reference in New Issue
Block a user