static void s5p_mfc_watchdog_worker(struct work_struct *work) { struct s5p_mfc_dev *dev; struct s5p_mfc_ctx *ctx; int i, ret; int mutex_locked; unsigned long flags; dev = container_of(work, struct s5p_mfc_dev, watchdog_work); mfc_err("Driver timeout error handling.\n"); /* Lock the mutex that protects open and release. * This is necessary as they may load and unload firmware. */ mutex_locked = mutex_trylock(&dev->mfc_mutex); if (!mutex_locked) mfc_err("This is not good. Some instance may be " "closing/opening.\n"); s5p_mfc_clock_off(); spin_lock_irqsave(&dev->irqlock, flags); for (i = 0; i < MFC_NUM_CONTEXTS; i++) { ctx = dev->ctx[i]; if (ctx) { ctx->state = MFCINST_ERROR; s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); clear_work_bit(ctx); wake_up_ctx(ctx, S5P_FIMV_R2H_CMD_ERR_RET, 0); } } dev->hw_lock = 0; spin_unlock_irqrestore(&dev->irqlock, flags); /* Double check if there is at least one instance running. * If no instance is in memory than no firmware should be present */ if (dev->num_inst > 0) { ret = s5p_mfc_load_firmware(dev); if (ret != 0) { mfc_err("Failed to reload FW.\n"); if (mutex_locked) mutex_unlock(&dev->mfc_mutex); return; } ret = s5p_mfc_init_hw(dev); if (ret != 0) { mfc_err("Failed to reinit FW.\n"); if (mutex_locked) mutex_unlock(&dev->mfc_mutex); return; } } if (mutex_locked) mutex_unlock(&dev->mfc_mutex); }
/* Initialize MFC V6 hardware */ static int s5p_mfc_init_hw_v6(struct s5p_mfc_dev *dev) { unsigned int ver; int ret; mfc_debug_enter(); ret = s5p_mfc_load_firmware(dev); if (ret) { mfc_err("Failed to reload FW\n"); return ret; } /* 0. MFC reset */ mfc_debug(2, "MFC reset..\n"); WARN_ON(dev->risc_on); s5p_mfc_clock_on(dev); ret = s5p_mfc_ctrl_ops_call(dev, reset, dev); if (ret) { mfc_err("Failed to reset MFC - timeout\n"); s5p_mfc_clock_off(dev); return ret; } mfc_debug(2, "Done MFC reset..\n"); /* 1. Set DRAM base Addr */ s5p_mfc_init_memctrl_v6(dev); /* 2. Release reset signal to the RISC */ s5p_mfc_clean_dev_int_flags(dev); mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); ret = s5p_mfc_init_fw(dev); if (ret) { s5p_mfc_clock_off(dev); return ret; } ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6); mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n", (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF); s5p_mfc_clock_off(dev); dev->risc_on = 1; mfc_debug_leave(); return ret; }