f0cfef2440
Driver is not polling for the PC Ready to be set and truning of the regulators/clocks. Fix the same. H2X Interrupt has to be enabled for every boot. CRs-Fixed: 2572953 Change-Id: Ib24b35dcebedf464bcd461718a18e732531ea4ce Signed-off-by: Manikanta Kanamarlapudi <kmanikan@codeaurora.org>
279 lines
9.9 KiB
C
279 lines
9.9 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
|
*/
|
|
|
|
#include "msm_vidc_debug.h"
|
|
#include "hfi_common.h"
|
|
|
|
#define VIDC_CPU_BASE_OFFS_AR50_LT 0x000A0000
|
|
#define VIDEO_GCC_BASE_OFFS_AR50_LT 0x00000000
|
|
#define VIDEO_CC_BASE_OFFS_AR50_LT 0x00100000
|
|
|
|
#define VIDC_CPU_CS_BASE_OFFS_AR50_LT (VIDC_CPU_BASE_OFFS_AR50_LT)
|
|
#define VIDC_CPU_IC_BASE_OFFS_AR50_LT (VIDC_CPU_BASE_OFFS_AR50_LT)
|
|
|
|
#define VIDC_CPU_CS_A2HSOFTINTCLR_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x1C)
|
|
#define VIDC_CPU_CS_VMIMSG_AR50_LTi (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x34)
|
|
#define VIDC_CPU_CS_VMIMSGAG0_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x38)
|
|
#define VIDC_CPU_CS_VMIMSGAG1_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x3C)
|
|
#define VIDC_CPU_CS_VMIMSGAG2_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x40)
|
|
#define VIDC_CPU_CS_VMIMSGAG3_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x44)
|
|
#define VIDC_CPU_CS_SCIACMD_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x48)
|
|
|
|
/* HFI_CTRL_STATUS */
|
|
#define VIDC_CPU_CS_SCIACMDARG0_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x4C)
|
|
#define VIDC_CPU_CS_SCIACMDARG0_BMSK_AR50_LT 0xff
|
|
#define VIDC_CPU_CS_SCIACMDARG0_SHFT_AR50_LT 0x0
|
|
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK_AR50_LT 0xfe
|
|
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_SHFT_AR50_LT 0x1
|
|
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_BMSK_AR50_LT 0x1
|
|
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_SHFT_AR50_LT 0x0
|
|
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY_AR50_LT 0x100
|
|
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK_AR50_LT 0x40000000
|
|
|
|
/* HFI_QTBL_INFO */
|
|
#define VIDC_CPU_CS_SCIACMDARG1_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x50)
|
|
|
|
/* HFI_QTBL_ADDR */
|
|
#define VIDC_CPU_CS_SCIACMDARG2_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x54)
|
|
|
|
/* HFI_VERSION_INFO */
|
|
#define VIDC_CPU_CS_SCIACMDARG3_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x58)
|
|
|
|
/* VIDC_SFR_ADDR */
|
|
#define VIDC_CPU_CS_SCIBCMD_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x5C)
|
|
|
|
/* VIDC_MMAP_ADDR */
|
|
#define VIDC_CPU_CS_SCIBCMDARG0_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x60)
|
|
|
|
/* VIDC_UC_REGION_ADDR */
|
|
#define VIDC_CPU_CS_SCIBARG1_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x64)
|
|
|
|
/* VIDC_UC_REGION_ADDR */
|
|
#define VIDC_CPU_CS_SCIBARG2_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x68)
|
|
|
|
#define VIDC_CPU_IC_SOFTINT_EN_AR50_LT (VIDC_CPU_IC_BASE_OFFS_AR50_LT + 0x148)
|
|
#define VIDC_CPU_IC_SOFTINT_AR50_LT (VIDC_CPU_IC_BASE_OFFS_AR50_LT + 0x150)
|
|
#define VIDC_CPU_IC_SOFTINT_H2A_BMSK_AR50_LT 0x8000
|
|
#define VIDC_CPU_IC_SOFTINT_H2A_SHFT_AR50_LT 0x1
|
|
|
|
/*
|
|
* --------------------------------------------------------------------------
|
|
* MODULE: vidc_wrapper
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
#define VIDC_WRAPPER_BASE_OFFS_AR50_LT 0x000B0000
|
|
|
|
#define VIDC_WRAPPER_HW_VERSION_AR50_LT (VIDC_WRAPPER_BASE_OFFS_AR50_LT + 0x00)
|
|
#define VIDC_WRAPPER_HW_VERSION_MAJOR_VERSION_MASK_AR50_LT 0x78000000
|
|
#define VIDC_WRAPPER_HW_VERSION_MAJOR_VERSION_SHIFT_AR50_LT 28
|
|
#define VIDC_WRAPPER_HW_VERSION_MINOR_VERSION_MASK_AR50_LT 0xFFF0000
|
|
#define VIDC_WRAPPER_HW_VERSION_MINOR_VERSION_SHIFT_AR50_LT 16
|
|
#define VIDC_WRAPPER_HW_VERSION_STEP_VERSION_MASK_AR50_LT 0xFFFF
|
|
|
|
#define VIDC_WRAPPER_CLOCK_CONFIG_AR50_LT (VIDC_WRAPPER_BASE_OFFS_AR50_LT + 0x04)
|
|
|
|
#define VIDC_WRAPPER_INTR_STATUS_AR50_LT (VIDC_WRAPPER_BASE_OFFS_AR50_LT + 0x0C)
|
|
#define VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK_AR50_LT 0x10
|
|
#define VIDC_WRAPPER_INTR_STATUS_A2HWD_SHFT_AR50_LT 0x4
|
|
#define VIDC_WRAPPER_INTR_STATUS_A2H_BMSK_AR50_LT 0x4
|
|
#define VIDC_WRAPPER_INTR_STATUS_A2H_SHFT_AR50_LT 0x2
|
|
|
|
#define VIDC_WRAPPER_INTR_MASK_AR50_LT (VIDC_WRAPPER_BASE_OFFS_AR50_LT + 0x10)
|
|
#define VIDC_WRAPPER_INTR_MASK_A2HWD_BMSK_AR50_LT 0x10
|
|
#define VIDC_WRAPPER_INTR_MASK_A2HWD_SHFT_AR50_LT 0x4
|
|
#define VIDC_WRAPPER_INTR_MASK_A2HVCODEC_BMSK_AR50_LT 0x8
|
|
#define VIDC_WRAPPER_INTR_MASK_A2HCPU_BMSK_AR50_LT 0x4
|
|
#define VIDC_WRAPPER_INTR_MASK_A2HCPU_SHFT_AR50_LT 0x2
|
|
|
|
#define VIDC_WRAPPER_INTR_CLEAR_AR50_LT (VIDC_WRAPPER_BASE_OFFS_AR50_LT + 0x14)
|
|
#define VIDC_WRAPPER_INTR_CLEAR_A2HWD_BMSK_AR50_LT 0x10
|
|
#define VIDC_WRAPPER_INTR_CLEAR_A2HWD_SHFT_AR50_LT 0x4
|
|
#define VIDC_WRAPPER_INTR_CLEAR_A2H_BMSK_AR50_LT 0x4
|
|
#define VIDC_WRAPPER_INTR_CLEAR_A2H_SHFT_AR50_LT 0x2
|
|
|
|
/*
|
|
* --------------------------------------------------------------------------
|
|
* MODULE: tz_wrapper
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
#define VIDC_WRAPPER_TZ_BASE_OFFS 0x000C0000
|
|
#define VIDC_WRAPPER_TZ_CPU_CLOCK_CONFIG (VIDC_WRAPPER_TZ_BASE_OFFS)
|
|
#define VIDC_WRAPPER_TZ_CPU_STATUS (VIDC_WRAPPER_TZ_BASE_OFFS + 0x10)
|
|
|
|
#define VIDC_CTRL_INIT_AR50_LT VIDC_CPU_CS_SCIACMD_AR50_LT
|
|
|
|
#define VIDC_CTRL_STATUS_AR50_LT VIDC_CPU_CS_SCIACMDARG0_AR50_LT
|
|
#define VIDC_CTRL_ERROR_STATUS__M_AR50_LT \
|
|
VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK_AR50_LT
|
|
#define VIDC_CTRL_INIT_IDLE_MSG_BMSK_AR50_LT \
|
|
VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK_AR50_LT
|
|
#define VIDC_CTRL_STATUS_PC_READY_AR50_LT \
|
|
VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY_AR50_LT
|
|
|
|
#define VIDC_QTBL_INFO_AR50_LT VIDC_CPU_CS_SCIACMDARG1_AR50_LT
|
|
#define VIDC_QTBL_ADDR_AR50_LT VIDC_CPU_CS_SCIACMDARG2_AR50_LT
|
|
#define VIDC_VERSION_INFO_AR50_LT VIDC_CPU_CS_SCIACMDARG3_AR50_LT
|
|
|
|
#define VIDC_SFR_ADDR_AR50_LT VIDC_CPU_CS_SCIBCMD_AR50_LT
|
|
#define VIDC_MMAP_ADDR_AR50_LT VIDC_CPU_CS_SCIBCMDARG0_AR50_LT
|
|
#define VIDC_UC_REGION_ADDR_AR50_LT VIDC_CPU_CS_SCIBARG1_AR50_LT
|
|
#define VIDC_UC_REGION_SIZE_AR50_LT VIDC_CPU_CS_SCIBARG2_AR50_LT
|
|
|
|
void __interrupt_init_ar50_lt(struct venus_hfi_device *device, u32 sid)
|
|
{
|
|
__write_register(device, VIDC_WRAPPER_INTR_MASK_AR50_LT,
|
|
VIDC_WRAPPER_INTR_MASK_A2HVCODEC_BMSK_AR50_LT, sid);
|
|
}
|
|
|
|
void __setup_ucregion_memory_map_ar50_lt(struct venus_hfi_device *device, u32 sid)
|
|
{
|
|
__write_register(device, VIDC_UC_REGION_ADDR_AR50_LT,
|
|
(u32)device->iface_q_table.align_device_addr, sid);
|
|
__write_register(device, VIDC_UC_REGION_SIZE_AR50_LT, SHARED_QSIZE, sid);
|
|
__write_register(device, VIDC_QTBL_ADDR_AR50_LT,
|
|
(u32)device->iface_q_table.align_device_addr, sid);
|
|
__write_register(device, VIDC_QTBL_INFO_AR50_LT, 0x01, sid);
|
|
if (device->sfr.align_device_addr)
|
|
__write_register(device, VIDC_SFR_ADDR_AR50_LT,
|
|
(u32)device->sfr.align_device_addr, sid);
|
|
if (device->qdss.align_device_addr)
|
|
__write_register(device, VIDC_MMAP_ADDR_AR50_LT,
|
|
(u32)device->qdss.align_device_addr, sid);
|
|
}
|
|
|
|
void __power_off_ar50_lt(struct venus_hfi_device *device)
|
|
{
|
|
if (!device->power_enabled)
|
|
return;
|
|
|
|
if (!(device->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK_AR50_LT))
|
|
disable_irq_nosync(device->hal_data->irq);
|
|
device->intr_status = 0;
|
|
|
|
__disable_unprepare_clks(device);
|
|
if (__disable_regulators(device))
|
|
d_vpr_e("Failed to disable regulators\n");
|
|
|
|
if (__unvote_buses(device, DEFAULT_SID))
|
|
d_vpr_e("Failed to unvote for buses\n");
|
|
device->power_enabled = false;
|
|
}
|
|
|
|
int __prepare_pc_ar50_lt(struct venus_hfi_device *device)
|
|
{
|
|
int rc = 0;
|
|
u32 wfi_status = 0, idle_status = 0, pc_ready = 0;
|
|
u32 ctrl_status = 0;
|
|
u32 count = 0, max_tries = 10;
|
|
|
|
ctrl_status = __read_register(device, VIDC_CTRL_STATUS_AR50_LT, DEFAULT_SID);
|
|
pc_ready = ctrl_status & VIDC_CTRL_STATUS_PC_READY_AR50_LT;
|
|
idle_status = ctrl_status & BIT(30);
|
|
|
|
if (pc_ready) {
|
|
d_vpr_l("Already in pc_ready state\n");
|
|
return 0;
|
|
}
|
|
|
|
wfi_status = BIT(0) & __read_register(device,
|
|
VIDC_WRAPPER_TZ_CPU_STATUS, DEFAULT_SID);
|
|
if (!wfi_status || !idle_status) {
|
|
d_vpr_e("Skipping PC, wfi status not set\n");
|
|
goto skip_power_off;
|
|
}
|
|
|
|
rc = __prepare_pc(device);
|
|
if (rc) {
|
|
d_vpr_e("Failed __prepare_pc %d\n", rc);
|
|
goto skip_power_off;
|
|
}
|
|
|
|
while (count < max_tries) {
|
|
wfi_status = BIT(0) & __read_register(device,
|
|
VIDC_WRAPPER_TZ_CPU_STATUS, DEFAULT_SID);
|
|
ctrl_status = __read_register(device,
|
|
VIDC_CTRL_STATUS_AR50_LT, DEFAULT_SID);
|
|
pc_ready = ctrl_status & VIDC_CTRL_STATUS_PC_READY_AR50_LT;
|
|
if (wfi_status && pc_ready)
|
|
break;
|
|
usleep_range(150, 250);
|
|
count++;
|
|
}
|
|
|
|
if (count == max_tries) {
|
|
d_vpr_e("Skip PC. Core is not in right state\n");
|
|
goto skip_power_off;
|
|
}
|
|
|
|
return rc;
|
|
|
|
skip_power_off:
|
|
d_vpr_e("Skip PC, wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n",
|
|
wfi_status, idle_status, pc_ready, ctrl_status);
|
|
return -EAGAIN;
|
|
}
|
|
|
|
void __raise_interrupt_ar50_lt(struct venus_hfi_device *device, u32 sid)
|
|
{
|
|
__write_register(device, VIDC_CPU_IC_SOFTINT_AR50_LT,
|
|
VIDC_CPU_IC_SOFTINT_H2A_SHFT_AR50_LT, sid);
|
|
}
|
|
|
|
void __core_clear_interrupt_ar50_lt(struct venus_hfi_device *device)
|
|
{
|
|
u32 intr_status = 0, mask = 0;
|
|
|
|
if (!device) {
|
|
d_vpr_e("%s: NULL device\n", __func__);
|
|
return;
|
|
}
|
|
|
|
intr_status = __read_register(device, VIDC_WRAPPER_INTR_STATUS_AR50_LT, DEFAULT_SID);
|
|
mask = (VIDC_WRAPPER_INTR_STATUS_A2H_BMSK_AR50_LT |
|
|
VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK_AR50_LT |
|
|
VIDC_CTRL_INIT_IDLE_MSG_BMSK_AR50_LT);
|
|
|
|
if (intr_status & mask) {
|
|
device->intr_status |= intr_status;
|
|
device->reg_count++;
|
|
d_vpr_l(
|
|
"INTERRUPT for device: %pK: times: %d interrupt_status: %d\n",
|
|
device, device->reg_count, intr_status);
|
|
} else {
|
|
device->spur_count++;
|
|
}
|
|
|
|
__write_register(device, VIDC_CPU_CS_A2HSOFTINTCLR_AR50_LT, 1, DEFAULT_SID);
|
|
__write_register(device, VIDC_WRAPPER_INTR_CLEAR_AR50_LT, intr_status, DEFAULT_SID);
|
|
}
|
|
|
|
int __boot_firmware_ar50_lt(struct venus_hfi_device *device, u32 sid)
|
|
{
|
|
int rc = 0;
|
|
u32 ctrl_init_val = 0, ctrl_status = 0, count = 0, max_tries = 1000;
|
|
|
|
ctrl_init_val = BIT(0);
|
|
|
|
__write_register(device, VIDC_CTRL_INIT_AR50_LT, ctrl_init_val, sid);
|
|
while (!ctrl_status && count < max_tries) {
|
|
ctrl_status = __read_register(device, VIDC_CTRL_STATUS_AR50_LT, sid);
|
|
if ((ctrl_status & VIDC_CTRL_ERROR_STATUS__M_AR50_LT) == 0x4) {
|
|
s_vpr_e(sid, "invalid setting for UC_REGION\n");
|
|
break;
|
|
}
|
|
usleep_range(50, 100);
|
|
count++;
|
|
}
|
|
|
|
if (count >= max_tries) {
|
|
s_vpr_e(sid, "Error booting up vidc firmware\n");
|
|
rc = -ETIME;
|
|
}
|
|
|
|
/* Enable interrupt before sending commands to venus */
|
|
__write_register(device, VIDC_CPU_IC_SOFTINT_EN_AR50_LT, 0x1, sid);
|
|
return rc;
|
|
}
|