From: Alpha Lin Date: Thu, 4 Jun 2015 09:36:18 +0000 (+0800) Subject: VPU: add cru reset if vpu hardware hang or vpu report X-Git-Tag: firefly_0821_release~4071 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=801b12312df835b14e011eff8cedf8d8f0077c7f;p=firefly-linux-kernel-4.4.55.git VPU: add cru reset if vpu hardware hang or vpu report error. It depend on pmu driver. and require pmu to complete its idle request function. temporary, it haven't enable yet, because rk3368 pmu function had not completed. Signed-off-by: Alpha Lin --- diff --git a/arch/arm/mach-rockchip/vcodec_service.c b/arch/arm/mach-rockchip/vcodec_service.c index 03640267d98c..b9f93242aa7f 100755 --- a/arch/arm/mach-rockchip/vcodec_service.c +++ b/arch/arm/mach-rockchip/vcodec_service.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CONFIG_MFD_SYSCON #include #endif @@ -496,6 +497,7 @@ typedef struct vpu_service_info { struct device *dev; u32 irq_status; + atomic_t reset_request; #if defined(CONFIG_VCODEC_MMU) struct ion_client *ion_client; struct list_head mem_region_list; @@ -765,6 +767,26 @@ static void vpu_put_clk(struct vpu_service_info *pservice) #endif } +static const u8 pmu_idle_map[] = { + [IDLE_REQ_VIDEO] = 7, +}; + +extern void __iomem *rk_cru_base; +static void cru_writel(u32 val, u32 offset) +{ + writel_relaxed(val, rk_cru_base + (offset)); + dsb(sy); +} + +extern int rk3368_pmu_set_idle_request(enum pmu_idle_req req, bool idle); +static inline void rk3368_cru_set_soft_reset(u32 idx, bool on) +{ + u32 val = on ? 0x10001U << (idx & 0xf) : 0x10000U << (idx & 0xf); + cru_writel(val, 0x31c); +} +#define SOFT_RST_VCODEC_AXI (7*16) +#define SOFT_RST_VCODEC_AHB (7*16+1) + static void vpu_reset(struct vpu_subdev_data *data) { struct vpu_service_info *pservice = data->pservice; @@ -794,11 +816,28 @@ static void vpu_reset(struct vpu_subdev_data *data) cru_set_soft_reset(SOFT_RST_VCODEC_NIU_AXI, false); cru_set_soft_reset(SOFT_RST_CPU_VCODEC, false); pmu_set_idle_request(IDLE_REQ_VIDEO, false); +#else #endif + WARN_ON(pservice->reg_codec != NULL); + WARN_ON(pservice->reg_pproc != NULL); + WARN_ON(pservice->reg_resev != NULL); pservice->reg_codec = NULL; pservice->reg_pproc = NULL; pservice->reg_resev = NULL; + pr_info("for 3288/3368..."); + /**rk3368_pmu_set_idle_request(IDLE_REQ_VIDEO, true);*/ + /*rockchip_pmu_ops.set_idle_request(IDLE_REQ_VIDEO, true);*/ + /**rockchip_pmu_ops.set_power_domain(PD_VIDEO, false);*/ + /*rk3368_cru_set_soft_reset(SOFT_RST_VCODEC_AHB, true); + rk3368_cru_set_soft_reset(SOFT_RST_VCODEC_AXI, true); + mdelay(1); + rk3368_cru_set_soft_reset(SOFT_RST_VCODEC_AXI, false); + rk3368_cru_set_soft_reset(SOFT_RST_VCODEC_AHB, false);*/ + /**rockchip_pmu_ops.set_power_domain(PD_VIDEO, true);*/ + /*rockchip_pmu_ops.set_idle_request(IDLE_REQ_VIDEO, false);*/ + /**rk3368_pmu_set_idle_request(IDLE_REQ_VIDEO, false);*/ + #if defined(CONFIG_VCODEC_MMU) if (data->mmu_dev && test_bit(MMU_ACTIVATED, &data->state)) { clear_bit(MMU_ACTIVATED, &data->state); @@ -808,6 +847,8 @@ static void vpu_reset(struct vpu_subdev_data *data) BUG_ON(!atomic_read(&pservice->enabled)); } #endif + atomic_set(&pservice->reset_request, 0); + pr_info("done\n"); } static void reg_deinit(struct vpu_subdev_data *data, vpu_reg *reg); @@ -1517,41 +1558,55 @@ static void try_set_reg(struct vpu_subdev_data *data) vpu_debug_enter(); if (!list_empty(&pservice->waiting)) { int can_set = 0; + bool change_able = (NULL == pservice->reg_codec) && (NULL == pservice->reg_pproc); + int reset_request = atomic_read(&pservice->reset_request); vpu_reg *reg = list_entry(pservice->waiting.next, vpu_reg, status_link); vpu_service_power_on(pservice); - switch (reg->type) { - case VPU_ENC : { - if ((NULL == pservice->reg_codec) && (NULL == pservice->reg_pproc)) - can_set = 1; - } break; - case VPU_DEC : { - if (NULL == pservice->reg_codec) - can_set = 1; - if (pservice->auto_freq && (NULL != pservice->reg_pproc)) - can_set = 0; - } break; - case VPU_PP : { - if (NULL == pservice->reg_codec) { - if (NULL == pservice->reg_pproc) + // first check can_set flag + if (change_able || !reset_request) { + switch (reg->type) { + case VPU_ENC : { + if (change_able) can_set = 1; - } else { - if ((VPU_DEC == pservice->reg_codec->type) && (NULL == pservice->reg_pproc)) + } break; + case VPU_DEC : { + if (NULL == pservice->reg_codec) can_set = 1; - /* can not charge frequency when vpu is working */ - if (pservice->auto_freq) + if (pservice->auto_freq && (NULL != pservice->reg_pproc)) can_set = 0; - } - } break; - case VPU_DEC_PP : { - if ((NULL == pservice->reg_codec) && (NULL == pservice->reg_pproc)) - can_set = 1; } break; - default : { - printk("undefined reg type %d\n", reg->type); - } break; + case VPU_PP : { + if (NULL == pservice->reg_codec) { + if (NULL == pservice->reg_pproc) + can_set = 1; + } else { + if ((VPU_DEC == pservice->reg_codec->type) && (NULL == pservice->reg_pproc)) + can_set = 1; + /* can not charge frequency when vpu is working */ + if (pservice->auto_freq) + can_set = 0; + } + } break; + case VPU_DEC_PP : { + if (change_able) + can_set = 1; + } break; + default : { + printk("undefined reg type %d\n", reg->type); + } break; + } } + + // then check reset request + if (reset_request && !change_able) + reset_request = 0; + + // do reset before setting registers + if (reset_request) + vpu_reset(data); + if (can_set) { reg_from_wait_to_run(pservice, reg); reg_copy_to_hw(reg->data, reg); @@ -2287,6 +2342,7 @@ static void vcodec_init_drvdata(struct vpu_service_info *pservice) atomic_set(&pservice->enabled, 0); atomic_set(&pservice->power_on_cnt, 0); atomic_set(&pservice->power_off_cnt, 0); + atomic_set(&pservice->reset_request, 0); INIT_DELAYED_WORK(&pservice->power_off_work, vpu_power_off_work);