From 15ade055295d13f95d49e3d99b09f3bbfb4a43e7 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 06 Nov 2023 07:25:24 +0000 Subject: [PATCH] add at24 driver --- kernel/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c | 191 ++++++++++++++++++++++++++++++++--------------- 1 files changed, 130 insertions(+), 61 deletions(-) diff --git a/kernel/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c b/kernel/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c index dfe74e0..d4a4fdb 100644 --- a/kernel/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c +++ b/kernel/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c @@ -60,6 +60,10 @@ /* interrupt read back in table buffer */ u32 tb_reg_int; bool hack_setup; + u32 tb_reg_cycle; + u32 tb_reg_out; + u32 tb_reg_ref_s; + u32 tb_reg_ref_e; struct rkvdec_link_status reg_status; }; @@ -113,6 +117,7 @@ }, .tb_reg_int = 164, .hack_setup = 1, + .tb_reg_cycle = 179, .reg_status = { .dec_num_mask = 0x3fffffff, .err_flag_base = 0x010, @@ -122,7 +127,7 @@ /* vdpu382 link hw info */ struct rkvdec_link_info rkvdec_link_v2_hw_info = { - .tb_reg_num = 218, + .tb_reg_num = 222, .tb_reg_next = 0, .tb_reg_r = 1, .tb_reg_second_en = 8, @@ -162,21 +167,27 @@ .part_r[0] = { .tb_reg_off = 180, .reg_start = 224, - .reg_num = 10, + .reg_num = 12, }, .part_r[1] = { - .tb_reg_off = 190, + .tb_reg_off = 192, .reg_start = 258, - .reg_num = 28, + .reg_num = 30, }, - .tb_reg_int = 180, - .hack_setup = 0, + .tb_reg_int = 180, + .hack_setup = 0, + .tb_reg_cycle = 197, + .tb_reg_out = 86, + .tb_reg_ref_s = 104, + .tb_reg_ref_e = 119, .reg_status = { .dec_num_mask = 0x000fffff, .err_flag_base = 0x024, .err_flag_bit = BIT(8), }, }; + +static void rkvdec2_link_free_task(struct kref *ref); static void rkvdec_link_status_update(struct rkvdec_link_dev *dev) { @@ -426,8 +437,6 @@ memcpy(&tb_reg[off], &task->reg[s], n * sizeof(u32)); } - /* setup error mode flag */ - tb_reg[9] |= BIT(18) | BIT(9); tb_reg[info->tb_reg_second_en] |= RKVDEC_WAIT_RESET_EN; /* memset read registers */ @@ -514,6 +523,7 @@ } if (!resend) { + u32 timing_en = dev->mpp->srv->timing_en; u32 i; for (i = 0; i < task_to_run; i++) { @@ -523,10 +533,8 @@ if (!task_ddr) continue; - set_bit(TASK_STATE_START, &task_ddr->state); - schedule_delayed_work(&task_ddr->timeout_work, - msecs_to_jiffies(200)); - mpp_time_record(task_ddr); + mpp_task_run_begin(task_ddr, timing_en, MPP_WORK_TIMEOUT_DELAY); + mpp_task_run_end(task_ddr, timing_en); } } else { if (task_total) @@ -538,6 +546,8 @@ /* start config before all registers are set */ wmb(); + + mpp_iommu_flush_tlb(dev->mpp->iommu_info); /* configure done */ writel(RKVDEC_LINK_BIT_CFG_DONE, reg_base + RKVDEC_LINK_CFG_CTRL_BASE); @@ -591,6 +601,7 @@ struct rkvdec_link_info *info = link_dec->info; u32 *table_base = (u32 *)link_dec->table->vaddr; int i; + struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); for (i = 0; i < count; i++) { int idx = rkvdec_link_get_task_read(link_dec); @@ -599,15 +610,15 @@ u32 *regs = NULL; u32 irq_status = 0; - if (!mpp_task) { + if (!mpp_task && info->hack_setup) { regs = table_base + idx * link_dec->link_reg_count; mpp_dbg_link_flow("slot %d read task stuff\n", idx); link_dec->stuff_total++; if (link_dec->statistic_count && - regs[RKVDEC_LINK_REG_CYCLE_CNT]) { + regs[info->tb_reg_cycle]) { link_dec->stuff_cycle_sum += - regs[RKVDEC_LINK_REG_CYCLE_CNT]; + regs[info->tb_reg_cycle]; link_dec->stuff_cnt++; if (link_dec->stuff_cnt >= link_dec->statistic_count) { @@ -648,22 +659,27 @@ continue; } - mpp_time_diff(mpp_task); + if (!mpp_task) + return 0; + task = to_rkvdec2_task(mpp_task); regs = table_base + idx * link_dec->link_reg_count; + link_dec->error_iova = regs[info->tb_reg_out]; irq_status = regs[info->tb_reg_int]; + mpp_task->hw_cycles = regs[info->tb_reg_cycle]; + mpp_time_diff_with_hw_time(mpp_task, dec->aclk_info.real_rate_hz); mpp_dbg_link_flow("slot %d rd task %d\n", idx, mpp_task->task_index); task->irq_status = irq_status ? irq_status : mpp->irq_status; - + mpp_debug(DEBUG_IRQ_STATUS, "irq_status: %08x\n", task->irq_status); cancel_delayed_work_sync(&mpp_task->timeout_work); set_bit(TASK_STATE_HANDLE, &mpp_task->state); if (link_dec->statistic_count && - regs[RKVDEC_LINK_REG_CYCLE_CNT]) { + regs[info->tb_reg_cycle]) { link_dec->task_cycle_sum += - regs[RKVDEC_LINK_REG_CYCLE_CNT]; + regs[info->tb_reg_cycle]; link_dec->task_cnt++; if (link_dec->task_cnt >= link_dec->statistic_count) { dev_info(link_dec->dev, "hw cycle %u\n", @@ -691,6 +707,8 @@ set_bit(TASK_STATE_PROC_DONE, &mpp_task->state); /* Wake up the GET thread */ wake_up(&task->wait); + kref_put(&mpp_task->ref, rkvdec2_link_free_task); + link_dec->tasks_hw[idx] = NULL; } return 0; @@ -729,7 +747,6 @@ static int rkvdec2_link_reset(struct mpp_dev *mpp) { - struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); dev_info(mpp->dev, "resetting...\n"); @@ -740,11 +757,8 @@ rockchip_save_qos(mpp->dev); - mutex_lock(&dec->sip_reset_lock); - rockchip_dmcfreq_lock(); - sip_smc_vpu_reset(0, 0, 0); - rockchip_dmcfreq_unlock(); - mutex_unlock(&dec->sip_reset_lock); + if (mpp->hw_ops->reset) + mpp->hw_ops->reset(mpp); rockchip_restore_qos(mpp->dev); @@ -762,6 +776,49 @@ return 0; } +static void rkvdec2_check_err_ref(struct mpp_dev *mpp) +{ + struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); + struct rkvdec_link_dev *link_dec = dec->link_dec; + struct rkvdec_link_info *link_info = link_dec->info; + struct mpp_taskqueue *queue = mpp->queue; + struct mpp_task *mpp_task = NULL, *n; + struct rkvdec2_task *task; + int i; + + if (!link_dec->error_iova || !dec->err_ref_hack) + return; + + dev_err(mpp->dev, "err task iova %#08x\n", link_dec->error_iova); + list_for_each_entry_safe(mpp_task, n, &queue->running_list, queue_link) { + if (mpp_task) { + u32 *regs = NULL; + u32 *table_base = (u32 *)link_dec->table->vaddr; + + task = to_rkvdec2_task(mpp_task); + regs = table_base + task->slot_idx * link_dec->link_reg_count; + + for (i = link_info->tb_reg_ref_s; i <= link_info->tb_reg_ref_e; i++) { + if (regs[i] == link_dec->error_iova) + regs[i] = 0; + } + } + } + + mutex_lock(&queue->pending_lock); + list_for_each_entry_safe(mpp_task, n, &queue->pending_list, queue_link) { + task = to_rkvdec2_task(mpp_task); + + /* ref frame reg index start - end */ + for (i = 164; i <= 179; i++) { + if (task->reg[i] == link_dec->error_iova) + task->reg[i] = 0; + } + } + mutex_unlock(&queue->pending_lock); + link_dec->error_iova = 0; +} + static int rkvdec2_link_irq(struct mpp_dev *mpp) { struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); @@ -774,9 +831,6 @@ } irq_status = readl(link_dec->reg_base + RKVDEC_LINK_IRQ_BASE); - - mpp_debug(DEBUG_IRQ_STATUS, "irq_status: %08x\n", irq_status); - mpp_dbg_link_flow("link irq %08x\n", irq_status); if (irq_status & RKVDEC_LINK_BIT_IRQ_RAW) { u32 enabled = readl(link_dec->reg_base + RKVDEC_LINK_EN_BASE); @@ -795,7 +849,8 @@ writel_relaxed(0, link_dec->reg_base + RKVDEC_LINK_IRQ_BASE); } - + mpp_debug((DEBUG_IRQ_STATUS | DEBUG_LINK_TABLE), "irq_status: %08x : %08x\n", + irq_status, mpp->irq_status); return 0; } @@ -815,6 +870,7 @@ mpp_debug_enter(); disable_irq(mpp->irq); + mpp_iommu_disable_irq(mpp->iommu_info); rkvdec_link_status_update(link_dec); link_dec->irq_status = irq_status; prev_dec_num = link_dec->task_decoded; @@ -822,8 +878,10 @@ if (!link_dec->enabled || task_timeout) { u32 val; - if (task_timeout) + if (task_timeout) { rkvdec_link_reg_dump("timeout", link_dec); + link_dec->decoded += task_timeout; + } val = mpp_read(mpp, 224 * 4); if (link_info->hack_setup && !(val & BIT(2))) { @@ -838,6 +896,7 @@ if (link_dec->enabled && !count && !need_reset) { /* process extra isr when task is processed */ enable_irq(mpp->irq); + mpp_iommu_enable_irq(mpp->iommu_info); goto done; } @@ -851,15 +910,18 @@ goto do_reset; enable_irq(mpp->irq); + mpp_iommu_enable_irq(mpp->iommu_info); goto done; do_reset: + rkvdec2_check_err_ref(mpp); /* NOTE: irq may run with reset */ atomic_inc(&mpp->reset_request); rkvdec2_link_reset(mpp); link_dec->task_decoded = 0; link_dec->task_total = 0; enable_irq(mpp->irq); + mpp_iommu_enable_irq(mpp->iommu_info); if (link_dec->total == link_dec->decoded) goto done; @@ -881,6 +943,26 @@ mpp_debug_leave(); return IRQ_HANDLED; +} + +static int rkvdec2_link_iommu_handle(struct iommu_domain *iommu, + struct device *iommu_dev, + unsigned long iova, + int status, void *arg) +{ + struct mpp_dev *mpp = (struct mpp_dev *)arg; + + dev_err(iommu_dev, "fault addr 0x%08lx status %x arg %p\n", + iova, status, arg); + + if (!mpp) { + dev_err(iommu_dev, "pagefault without device to handle\n"); + return 0; + } + + rk_iommu_mask_irq(mpp->dev); + + return 0; } int rkvdec2_link_remove(struct mpp_dev *mpp, struct rkvdec_link_dev *link_dec) @@ -1016,7 +1098,8 @@ if (link_dec->info->hack_setup) rkvdec2_link_hack_data_setup(dec->fix); - + iommu_set_fault_handler(mpp->iommu_info->domain, + rkvdec2_link_iommu_handle, mpp); link_dec->mpp = mpp; link_dec->dev = dev; atomic_set(&link_dec->task_timeout, 0); @@ -1060,8 +1143,10 @@ } session = task->session; - mpp_debug_func(DEBUG_TASK_INFO, "task %d:%d state 0x%lx\n", - session->index, task->task_index, task->state); + mpp_debug_func(DEBUG_TASK_INFO, + "session %d:%d task %d state 0x%lx abort_request %d\n", + session->device_type, session->index, task->task_index, + task->state, atomic_read(&task->abort_request)); if (!session->mpp) { mpp_err("session %d session->mpp is null.\n", session->index); return; @@ -1112,6 +1197,7 @@ if (!link_dec->irq_enabled) { enable_irq(mpp->irq); + mpp_iommu_enable_irq(mpp->iommu_info); link_dec->irq_enabled = 1; } @@ -1146,6 +1232,7 @@ if (atomic_xchg(&link_dec->power_enabled, 0)) { disable_irq(mpp->irq); + mpp_iommu_disable_irq(mpp->iommu_info); link_dec->irq_enabled = 0; if (mpp->hw_ops->clk_off) @@ -1287,6 +1374,7 @@ u32 task_to_run = 0; int slot_idx = 0; int ret; + struct mpp_session *session = task->session; mpp_debug_enter(); @@ -1301,8 +1389,10 @@ } rkvdec2_link_power_on(mpp); - mpp_debug(DEBUG_TASK_INFO, "pid %d, start hw %s\n", - task->session->pid, dev_name(mpp->dev)); + mpp_debug_func(DEBUG_TASK_INFO, + "%s session %d:%d task=%d state=0x%lx\n", + dev_name(mpp->dev), session->device_type, + session->index, task->task_index, task->state); /* prepare the task for running */ if (test_and_set_bit(TASK_STATE_PREPARE, &task->state)) @@ -1372,7 +1462,6 @@ struct mpp_task *task) { set_bit(TASK_STATE_DONE, &task->state); - kref_put(&task->ref, rkvdec2_link_free_task); return 0; } @@ -1479,10 +1568,12 @@ goto done; disable_irq(mpp->irq); + mpp_iommu_disable_irq(mpp->iommu_info); rkvdec2_link_reset(mpp); link_dec->task_decoded = 0; link_dec->task_total = 0; enable_irq(mpp->irq); + mpp_iommu_enable_irq(mpp->iommu_info); } /* * process pending queue to find the task to accept. @@ -1500,7 +1591,6 @@ mutex_lock(&queue->pending_lock); list_del_init(&task->queue_link); - kref_get(&task->ref); set_bit(TASK_STATE_ABORT_READY, &task->state); set_bit(TASK_STATE_PROC_DONE, &task->state); @@ -1546,28 +1636,7 @@ rkvdec2_link_power_off(mpp); } - mutex_lock(&queue->session_lock); - while (queue->detach_count) { - struct mpp_session *session = NULL; - - session = list_first_entry_or_null(&queue->session_detach, struct mpp_session, - session_link); - if (session) { - list_del_init(&session->session_link); - queue->detach_count--; - } - - mutex_unlock(&queue->session_lock); - - if (session) { - mpp_dbg_session("%s detach count %d\n", dev_name(mpp->dev), - queue->detach_count); - mpp_session_deinit(session); - } - - mutex_lock(&queue->session_lock); - } - mutex_unlock(&queue->session_lock); + mpp_session_cleanup_detach(queue, work_s); } void rkvdec2_link_session_deinit(struct mpp_session *session) @@ -1580,9 +1649,9 @@ if (session->dma) { mpp_dbg_session("session %d destroy dma\n", session->index); - mpp_iommu_down_read(mpp->iommu_info); + mpp_iommu_down_write(mpp->iommu_info); mpp_dma_session_destroy(session->dma); - mpp_iommu_up_read(mpp->iommu_info); + mpp_iommu_up_write(mpp->iommu_info); session->dma = NULL; } if (session->srv) { -- Gitblit v1.6.2