msm: camera: cpp: Add cpp bus error handler
Reset and halt the bus when bus hang with cpp timeout. CRs-Fixed: 961394 Change-Id: Id3612b134e3db19f1f8e2e2b3b444f0b6284c4d1 Signed-off-by: Peter Liu <pingchie@codeaurora.org> Signed-off-by: Rajakumar Govindaram <rajakuma@codeaurora.org>
This commit is contained in:
parent
6428373814
commit
ea445a93a0
2 changed files with 86 additions and 0 deletions
|
@ -102,6 +102,7 @@
|
|||
#define IS_DEFAULT_OUTPUT_BUF_INDEX(index) \
|
||||
((index == DEFAULT_OUTPUT_BUF_INDEX) ? 1 : 0)
|
||||
|
||||
static struct msm_cpp_vbif_data cpp_vbif;
|
||||
static int msm_cpp_buffer_ops(struct cpp_device *cpp_dev,
|
||||
uint32_t buff_mgr_ops, uint32_t ids, void *arg);
|
||||
|
||||
|
@ -171,6 +172,26 @@ struct msm_cpp_timer_t {
|
|||
struct msm_cpp_timer_t cpp_timer;
|
||||
static void msm_cpp_set_vbif_reg_values(struct cpp_device *cpp_dev);
|
||||
|
||||
|
||||
void msm_cpp_vbif_register_error_handler(void *dev,
|
||||
enum cpp_vbif_client client,
|
||||
int (*client_vbif_error_handler)(void *, uint32_t))
|
||||
{
|
||||
if (dev == NULL || client >= VBIF_CLIENT_MAX) {
|
||||
pr_err("%s: Fail to register handler! dev = %p, client %d\n",
|
||||
__func__, dev, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client_vbif_error_handler != NULL) {
|
||||
cpp_vbif.dev[client] = dev;
|
||||
cpp_vbif.err_handler[client] = client_vbif_error_handler;
|
||||
} else {
|
||||
/* if handler = NULL, is unregister case */
|
||||
cpp_vbif.dev[client] = NULL;
|
||||
cpp_vbif.err_handler[client] = NULL;
|
||||
}
|
||||
}
|
||||
static int msm_cpp_init_bandwidth_mgr(struct cpp_device *cpp_dev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
@ -1215,6 +1236,32 @@ end:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int cpp_vbif_error_handler(void *dev, uint32_t vbif_error)
|
||||
{
|
||||
struct cpp_device *cpp_dev = NULL;
|
||||
|
||||
if (dev == NULL || vbif_error >= CPP_VBIF_ERROR_MAX) {
|
||||
pr_err("failed: dev %p, vbif error %d\n", dev, vbif_error);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cpp_dev = (struct cpp_device *) dev;
|
||||
|
||||
/* MMSS_A_CPP_IRQ_STATUS_0 = 0x10 */
|
||||
pr_err("%s: before reset halt... read MMSS_A_CPP_IRQ_STATUS_0 = 0x%x",
|
||||
__func__, msm_camera_io_r(cpp_dev->cpp_hw_base + 0x10));
|
||||
|
||||
pr_err("%s: start reset bus bridge on FD + CPP!\n", __func__);
|
||||
/* MMSS_A_CPP_RST_CMD_0 = 0x8, firmware reset = 0x3DF77 */
|
||||
msm_camera_io_w(0x3DF77, cpp_dev->cpp_hw_base + 0x8);
|
||||
|
||||
/* MMSS_A_CPP_IRQ_STATUS_0 = 0x10 */
|
||||
pr_err("%s: after reset halt... read MMSS_A_CPP_IRQ_STATUS_0 = 0x%x",
|
||||
__func__, msm_camera_io_r(cpp_dev->cpp_hw_base + 0x10));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
int rc;
|
||||
|
@ -1284,6 +1331,10 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
|||
rc = -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
msm_cpp_vbif_register_error_handler(cpp_dev,
|
||||
VBIF_CLIENT_CPP, cpp_vbif_error_handler);
|
||||
|
||||
mutex_unlock(&cpp_dev->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1383,6 +1434,9 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
|||
}
|
||||
}
|
||||
|
||||
/* unregister vbif error handler */
|
||||
msm_cpp_vbif_register_error_handler(cpp_dev,
|
||||
VBIF_CLIENT_CPP, NULL);
|
||||
mutex_unlock(&cpp_dev->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1637,6 +1691,15 @@ static void msm_cpp_do_timeout_work(struct work_struct *work)
|
|||
goto end;
|
||||
}
|
||||
|
||||
pr_err("%s: handle vbif hang...\n", __func__);
|
||||
for (i = 0; i < VBIF_CLIENT_MAX; i++) {
|
||||
if (cpp_dev->vbif_data->err_handler[i] == NULL)
|
||||
continue;
|
||||
|
||||
cpp_dev->vbif_data->err_handler[i](
|
||||
cpp_dev->vbif_data->dev[i], CPP_VBIF_ERROR_HANG);
|
||||
}
|
||||
|
||||
pr_debug("Reloading firmware %d\n", queue_len);
|
||||
rc = cpp_load_fw(cpp_timer.data.cpp_dev,
|
||||
cpp_timer.data.cpp_dev->fw_name_bin);
|
||||
|
@ -4195,6 +4258,8 @@ static int cpp_probe(struct platform_device *pdev)
|
|||
spin_lock_init(&cpp_timer.data.processed_frame_lock);
|
||||
|
||||
cpp_dev->pdev = pdev;
|
||||
memset(&cpp_vbif, 0, sizeof(struct msm_cpp_vbif_data));
|
||||
cpp_dev->vbif_data = &cpp_vbif;
|
||||
|
||||
cpp_dev->camss_cpp_base =
|
||||
msm_camera_get_reg_base(pdev, "camss_cpp", true);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "msm_sd.h"
|
||||
#include "cam_soc_api.h"
|
||||
#include "cam_hw_ops.h"
|
||||
#include <media/msmb_pproc.h>
|
||||
|
||||
/* hw version info:
|
||||
31:28 Major version
|
||||
|
@ -95,6 +96,22 @@
|
|||
#define MSM_CPP_TX_FIFO_LEVEL 16
|
||||
#define MSM_CPP_RX_FIFO_LEVEL 512
|
||||
|
||||
enum cpp_vbif_error {
|
||||
CPP_VBIF_ERROR_HANG,
|
||||
CPP_VBIF_ERROR_MAX,
|
||||
};
|
||||
|
||||
enum cpp_vbif_client {
|
||||
VBIF_CLIENT_CPP,
|
||||
VBIF_CLIENT_FD,
|
||||
VBIF_CLIENT_MAX,
|
||||
};
|
||||
|
||||
struct msm_cpp_vbif_data {
|
||||
int (*err_handler[VBIF_CLIENT_MAX])(void *, uint32_t);
|
||||
void *dev[VBIF_CLIENT_MAX];
|
||||
};
|
||||
|
||||
struct cpp_subscribe_info {
|
||||
struct v4l2_fh *vfh;
|
||||
uint32_t active;
|
||||
|
@ -266,6 +283,7 @@ struct cpp_device {
|
|||
uint32_t bus_master_flag;
|
||||
uint32_t micro_reset;
|
||||
struct msm_cpp_payload_params payload_params;
|
||||
struct msm_cpp_vbif_data *vbif_data;
|
||||
};
|
||||
|
||||
int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev);
|
||||
|
@ -274,5 +292,8 @@ int msm_cpp_get_clock_index(struct cpp_device *cpp_dev, const char *clk_name);
|
|||
long msm_cpp_set_core_clk(struct cpp_device *cpp_dev, long rate, int idx);
|
||||
void msm_cpp_fetch_dt_params(struct cpp_device *cpp_dev);
|
||||
int msm_cpp_read_payload_params_from_dt(struct cpp_device *cpp_dev);
|
||||
void msm_cpp_vbif_register_error_handler(void *dev,
|
||||
enum cpp_vbif_client client,
|
||||
int (*client_vbif_error_handler)(void *, uint32_t));
|
||||
|
||||
#endif /* __MSM_CPP_H__ */
|
||||
|
|
Loading…
Add table
Reference in a new issue