506 lines
13 KiB
C
506 lines
13 KiB
C
|
/*
|
||
|
* Samsung Exynos SoC series VIPx driver
|
||
|
*
|
||
|
* Copyright (c) 2018 Samsung Electronics Co., Ltd
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License version 2 as
|
||
|
* published by the Free Software Foundation.
|
||
|
*/
|
||
|
|
||
|
#include <linux/io.h>
|
||
|
#include <linux/delay.h>
|
||
|
|
||
|
#include "vipx-log.h"
|
||
|
#include "vipx-system.h"
|
||
|
#include "platform/vipx-ctrl.h"
|
||
|
|
||
|
enum vipx_reg_ss1_id {
|
||
|
REG_SS1_VERSION_ID,
|
||
|
REG_SS1_QCHANNEL,
|
||
|
REG_SS1_IRQ_FROM_DEVICE,
|
||
|
REG_SS1_IRQ0_TO_DEVICE,
|
||
|
REG_SS1_IRQ1_TO_DEVICE,
|
||
|
REG_SS1_GLOBAL_CTRL,
|
||
|
REG_SS1_CORTEX_CONTROL,
|
||
|
REG_SS1_CPU_CTRL,
|
||
|
REG_SS1_PROGRAM_COUNTER,
|
||
|
REG_SS1_DEBUG0,
|
||
|
REG_SS1_DEBUG1,
|
||
|
REG_SS1_DEBUG2,
|
||
|
REG_SS1_DEBUG3,
|
||
|
REG_SS1_VIP_STATE,
|
||
|
REG_SS1_VIP_PWR_DWN,
|
||
|
REG_SS1_VIP_PC,
|
||
|
REG_SS1_VIP_LR,
|
||
|
REG_SS1_VIP_SP,
|
||
|
REG_SS1_VIP_SPV,
|
||
|
REG_SS1_VIP_SR,
|
||
|
REG_SS1_VIP_ILR,
|
||
|
REG_SS1_VIP_IM,
|
||
|
REG_SS1_VIP_IC0,
|
||
|
REG_SS1_VIP_IC1,
|
||
|
REG_SS1_VIP_IC2,
|
||
|
REG_SS1_VIP_IS0,
|
||
|
REG_SS1_VIP_IS1,
|
||
|
REG_SS1_VIP_IS2,
|
||
|
REG_SS1_VIP_LE0,
|
||
|
REG_SS1_VIP_LE1,
|
||
|
REG_SS1_VIP_LE2,
|
||
|
REG_SS1_CC_REQ_TO_VIP0,
|
||
|
REG_SS1_CC_REQ_TO_VIP1,
|
||
|
REG_SS1_INT_CC_REQ_MASK0,
|
||
|
REG_SS1_INT_CC_REQ_MASK1,
|
||
|
REG_SS1_CC_REQ_MASK0,
|
||
|
REG_SS1_CC_REQ_MASK1,
|
||
|
REG_SS1_VIP_DONE0,
|
||
|
REG_SS1_VIP_DONE1,
|
||
|
REG_SS1_INT_VIP_DONE_CC_MASK0,
|
||
|
REG_SS1_INT_VIP_DONE_CC_MASK1,
|
||
|
REG_SS1_INT_VIP_DONE_HOST_MASK0,
|
||
|
REG_SS1_INT_VIP_DONE_HOST_MASK1,
|
||
|
REG_SS1_SDMA_ERR_CODES,
|
||
|
REG_SS1_SDMA_STATUS_SE,
|
||
|
REG_SS1_SDMA_STATUS_INT_SOURCE,
|
||
|
REG_SS1_SDMA_STATUS_VC_INFO,
|
||
|
REG_SS1_MAX
|
||
|
};
|
||
|
|
||
|
enum vipx_reg_ss2_id {
|
||
|
REG_SS2_QCHANNEL,
|
||
|
REG_SS2_GLOBAL_CTRL,
|
||
|
REG_SS2_VIP_STATE,
|
||
|
REG_SS2_VIP_PWR_DWN,
|
||
|
REG_SS2_VIP_PC,
|
||
|
REG_SS2_VIP_LR,
|
||
|
REG_SS2_VIP_SP,
|
||
|
REG_SS2_VIP_SPV,
|
||
|
REG_SS2_VIP_SR,
|
||
|
REG_SS2_VIP_ILR,
|
||
|
REG_SS2_VIP_IM,
|
||
|
REG_SS2_VIP_IC0,
|
||
|
REG_SS2_VIP_IC1,
|
||
|
REG_SS2_VIP_IC2,
|
||
|
REG_SS2_VIP_IS0,
|
||
|
REG_SS2_VIP_IS1,
|
||
|
REG_SS2_VIP_IS2,
|
||
|
REG_SS2_VIP_LE0,
|
||
|
REG_SS2_VIP_LE1,
|
||
|
REG_SS2_VIP_LE2,
|
||
|
REG_SS2_CC_REQ_TO_VIP0,
|
||
|
REG_SS2_CC_REQ_TO_VIP1,
|
||
|
REG_SS2_INT_CC_REQ_MASK0,
|
||
|
REG_SS2_INT_CC_REQ_MASK1,
|
||
|
REG_SS2_CC_REQ_MASK0,
|
||
|
REG_SS2_CC_REQ_MASK1,
|
||
|
REG_SS2_VIP_DONE0,
|
||
|
REG_SS2_VIP_DONE1,
|
||
|
REG_SS2_INT_VIP_DONE_CC_MASK0,
|
||
|
REG_SS2_INT_VIP_DONE_CC_MASK1,
|
||
|
REG_SS2_INT_VIP_DONE_HOST_MASK0,
|
||
|
REG_SS2_INT_VIP_DONE_HOST_MASK1,
|
||
|
REG_SS2_SDMA_ERR_CODES,
|
||
|
REG_SS2_SDMA_STATUS_SE,
|
||
|
REG_SS2_SDMA_STATUS_INT_SOURCE,
|
||
|
REG_SS2_SDMA_STATUS_VC_INFO,
|
||
|
REG_SS2_MAX
|
||
|
};
|
||
|
|
||
|
enum vipx_reg_sysreg1_id {
|
||
|
REG_SYSREG1_SFR_APB,
|
||
|
REG_SYSREG1_BUS_COMPONENT_DRCG_EN,
|
||
|
REG_SYSREG1_MEMCLK,
|
||
|
REG_SYSREG1_AxCACHE,
|
||
|
REG_SYSREG1_AxQOS,
|
||
|
REG_SYSREG1_AxPROT,
|
||
|
REG_SYSREG1_AxCNTL,
|
||
|
REG_SYSREG1_CM7_STATUS0,
|
||
|
REG_SYSREG1_CM7_STATUS1,
|
||
|
REG_SYSREG1_CM7_STATUS2,
|
||
|
REG_SYSREG1_CM7_STATUS3,
|
||
|
REG_SYSREG1_SHARABILITY_CTRL,
|
||
|
REG_SYSREG1_VIPX1_DBG_MODE,
|
||
|
REG_SYSREG1_VIPX1_QCH_MON,
|
||
|
REG_SYSREG1_XIU_D_VIPX_S0,
|
||
|
REG_SYSREG1_XIU_D_VIPX1_S1,
|
||
|
REG_SYSREG1_XIU_D_VIPX_M0,
|
||
|
REG_SYSREG1_MAX
|
||
|
};
|
||
|
|
||
|
enum vipx_reg_sysreg2_id {
|
||
|
REG_SYSREG2_SFR_APB,
|
||
|
REG_SYSREG2_BUS_COMPONENT_DRCG_EN,
|
||
|
REG_SYSREG2_MEMCLK,
|
||
|
REG_SYSREG2_AxCACHE,
|
||
|
REG_SYSREG2_AxQOS,
|
||
|
REG_SYSREG2_AxPROT,
|
||
|
REG_SYSREG2_AxCNTL,
|
||
|
REG_SYSREG2_SHARABILITY_CTRL,
|
||
|
REG_SYSREG2_VIPX1_DBG_MODE,
|
||
|
REG_SYSREG2_VIPX1_QCH_MON,
|
||
|
REG_SYSREG2_MAX
|
||
|
};
|
||
|
|
||
|
static const struct vipx_reg regs_ss1[] = {
|
||
|
{ 0x0000, "SS1_VERSION_ID" },
|
||
|
{ 0x0004, "SS1_QCHANNEL" },
|
||
|
{ 0x0008, "SS1_IRQ_FROM_DEVICE" },
|
||
|
{ 0x000C, "SS1_IRQ0_TO_DEVICE" },
|
||
|
{ 0x0010, "SS1_IRQ1_TO_DEVICE" },
|
||
|
{ 0x0014, "SS1_GLOBAL_CTRL" },
|
||
|
{ 0x0018, "SS1_CORTEX_CONTROL" },
|
||
|
{ 0x001C, "SS1_CPU_CTRL" },
|
||
|
{ 0x0044, "SS1_PROGRAM_COUNTER" },
|
||
|
{ 0x0048, "SS1_DEBUG0" },
|
||
|
{ 0x004C, "SS1_DEBUG1" },
|
||
|
{ 0x0050, "SS1_DEBUG2" },
|
||
|
{ 0x0054, "SS1_DEBUG3" },
|
||
|
{ 0x8048, "SS1_VIP_STATE" },
|
||
|
{ 0x8058, "SS1_VIP_PWR_DWN" },
|
||
|
{ 0x8060, "SS1_VIP_PC" },
|
||
|
{ 0x8064, "SS1_VIP_LR" },
|
||
|
{ 0x8068, "SS1_VIP_SP" },
|
||
|
{ 0x806C, "SS1_VIP_SPV" },
|
||
|
{ 0x8070, "SS1_VIP_SR" },
|
||
|
{ 0x8074, "SS1_VIP_ILR" },
|
||
|
{ 0x8078, "SS1_VIP_IM" },
|
||
|
{ 0x807C, "SS1_VIP_IC0" },
|
||
|
{ 0x8080, "SS1_VIP_IC1" },
|
||
|
{ 0x8084, "SS1_VIP_IC2" },
|
||
|
{ 0x8088, "SS1_VIP_IS0" },
|
||
|
{ 0x808C, "SS1_VIP_IS1" },
|
||
|
{ 0x8090, "SS1_VIP_IS2" },
|
||
|
{ 0x8094, "SS1_VIP_LE0" },
|
||
|
{ 0x8098, "SS1_VIP_LE1" },
|
||
|
{ 0x809C, "SS1_VIP_LE2" },
|
||
|
{ 0x9000, "SS1_CC_REQ_TO_VIP0" },
|
||
|
{ 0x9004, "SS1_CC_REQ_TO_VIP1" },
|
||
|
{ 0x9010, "SS1_INT_CC_REQ_MASK0" },
|
||
|
{ 0x9014, "SS1_INT_CC_REQ_MASK1" },
|
||
|
{ 0x9020, "SS1_CC_REQ_MASK0" },
|
||
|
{ 0x9024, "SS1_CC_REQ_MASK1" },
|
||
|
{ 0x9040, "SS1_VIP_DONE0" },
|
||
|
{ 0x9044, "SS1_VIP_DONE1" },
|
||
|
{ 0x9050, "SS1_INT_VIP_DONE_CC_MASK0" },
|
||
|
{ 0x9054, "SS1_INT_VIP_DONE_CC_MASK1" },
|
||
|
{ 0x9058, "SS1_INT_VIP_DONE_HOST_MASK0" },
|
||
|
{ 0x905C, "SS1_INT_VIP_DONE_HOST_MASK1" },
|
||
|
{ 0xC028, "SS1_SDMA_ERR_CODES" },
|
||
|
{ 0xC500, "SS1_SDMA_STATUS_SE" },
|
||
|
{ 0xC504, "SS1_SDMA_STATUS_INT_SOURCE" },
|
||
|
{ 0xC508, "SS1_SDMA_STATUS_VC_INFO" },
|
||
|
};
|
||
|
|
||
|
static const struct vipx_reg regs_ss2[] = {
|
||
|
{ 0x0000, "SS2_QCHANNEL" },
|
||
|
{ 0x0004, "SS2_GLOBAL_CTRL" },
|
||
|
{ 0x8048, "SS2_VIP_STATE" },
|
||
|
{ 0x8058, "SS2_VIP_PWR_DWN" },
|
||
|
{ 0x8060, "SS2_VIP_PC" },
|
||
|
{ 0x8064, "SS2_VIP_LR" },
|
||
|
{ 0x8068, "SS2_VIP_SP" },
|
||
|
{ 0x806C, "SS2_VIP_SPV" },
|
||
|
{ 0x8070, "SS2_VIP_SR" },
|
||
|
{ 0x8074, "SS2_VIP_ILR" },
|
||
|
{ 0x8078, "SS2_VIP_IM" },
|
||
|
{ 0x807C, "SS2_VIP_IC0" },
|
||
|
{ 0x8080, "SS2_VIP_IC1" },
|
||
|
{ 0x8084, "SS2_VIP_IC2" },
|
||
|
{ 0x8088, "SS2_VIP_IS0" },
|
||
|
{ 0x808C, "SS2_VIP_IS1" },
|
||
|
{ 0x8090, "SS2_VIP_IS2" },
|
||
|
{ 0x8094, "SS2_VIP_LE0" },
|
||
|
{ 0x8098, "SS2_VIP_LE1" },
|
||
|
{ 0x809C, "SS2_VIP_LE2" },
|
||
|
{ 0x9000, "SS2_CC_REQ_TO_VIP0" },
|
||
|
{ 0x9004, "SS2_CC_REQ_TO_VIP1" },
|
||
|
{ 0x9010, "SS2_INT_CC_REQ_MASK0" },
|
||
|
{ 0x9014, "SS2_INT_CC_REQ_MASK1" },
|
||
|
{ 0x9020, "SS2_CC_REQ_MASK0" },
|
||
|
{ 0x9024, "SS2_CC_REQ_MASK1" },
|
||
|
{ 0x9040, "SS2_VIP_DONE0" },
|
||
|
{ 0x9044, "SS2_VIP_DONE1" },
|
||
|
{ 0x9050, "SS2_INT_VIP_DONE_CC_MASK0" },
|
||
|
{ 0x9054, "SS2_INT_VIP_DONE_CC_MASK1" },
|
||
|
{ 0x9058, "SS2_INT_VIP_DONE_HOST_MASK0" },
|
||
|
{ 0x905C, "SS2_INT_VIP_DONE_HOST_MASK1" },
|
||
|
{ 0xC028, "SS2_SDMA_ERR_CODES" },
|
||
|
{ 0xC500, "SS2_SDMA_STATUS_SE" },
|
||
|
{ 0xC504, "SS2_SDMA_STATUS_INT_SOURCE" },
|
||
|
{ 0xC508, "SS2_SDMA_STATUS_VC_INFO" },
|
||
|
};
|
||
|
|
||
|
static const struct vipx_reg regs_sysreg1[] = {
|
||
|
{ 0x0100, "SYSREG1_SFR_APB" },
|
||
|
{ 0x0104, "SYSREG1_BUS_COMPONENT_DRCG_EN" },
|
||
|
{ 0x0108, "SYSREG1_MEMCLK" },
|
||
|
{ 0x0400, "SYSREG1_AxCACHE" },
|
||
|
{ 0x0404, "SYSREG1_AxQOS" },
|
||
|
{ 0x0408, "SYSREG1_AxPROT" },
|
||
|
{ 0x040C, "SYSREG1_AxCNTL" },
|
||
|
{ 0x0410, "SYSREG1_CM7_STATUS0" },
|
||
|
{ 0x0414, "SYSREG1_CM7_STATUS1" },
|
||
|
{ 0x0418, "SYSREG1_CM7_STATUS2" },
|
||
|
{ 0x041C, "SYSREG1_CM7_STATUS3" },
|
||
|
{ 0x0420, "SYSREG1_SHARABILITY_CTRL" },
|
||
|
{ 0x0424, "SYSREG1_VIPX1_DBG_MODE" },
|
||
|
{ 0x0428, "SYSREG1_VIPX1_QCH_MON" },
|
||
|
{ 0x0430, "SYSREG1_XIU_D_VIPX_S0" },
|
||
|
{ 0x0434, "SYSREG1_XIU_D_VIPX1_S1" },
|
||
|
{ 0x0438, "SYSREG1_XIU_D_VIPX_M0" },
|
||
|
};
|
||
|
|
||
|
static const struct vipx_reg regs_sysreg2[] = {
|
||
|
{ 0x0100, "SYSREG2_SFR_APB" },
|
||
|
{ 0x0104, "SYSREG2_BUS_COMPONENT_DRCG_EN" },
|
||
|
{ 0x0108, "SYSREG2_MEMCLK" },
|
||
|
{ 0x0400, "SYSREG2_AxCACHE" },
|
||
|
{ 0x0404, "SYSREG2_AxQOS" },
|
||
|
{ 0x0408, "SYSREG2_AxPROT" },
|
||
|
{ 0x040C, "SYSREG2_AxCNTL" },
|
||
|
{ 0x0420, "SYSREG2_SHARABILITY_CTRL" },
|
||
|
{ 0x0424, "SYSREG2_VIPX1_DBG_MODE" },
|
||
|
{ 0x0428, "SYSREG2_VIPX1_QCH_MON" },
|
||
|
};
|
||
|
|
||
|
static int vipx_exynos9610_ctrl_reset(struct vipx_system *sys)
|
||
|
{
|
||
|
void __iomem *ss1, *ss2;
|
||
|
unsigned int val;
|
||
|
|
||
|
vipx_enter();
|
||
|
ss1 = sys->reg_ss[REG_SS1];
|
||
|
ss2 = sys->reg_ss[REG_SS2];
|
||
|
|
||
|
/* TODO: check delay */
|
||
|
val = readl(ss1 + regs_ss1[REG_SS1_GLOBAL_CTRL].offset);
|
||
|
writel(val | 0xF1, ss1 + regs_ss1[REG_SS1_GLOBAL_CTRL].offset);
|
||
|
udelay(10);
|
||
|
|
||
|
val = readl(ss2 + regs_ss2[REG_SS2_GLOBAL_CTRL].offset);
|
||
|
writel(val | 0xF1, ss2 + regs_ss2[REG_SS2_GLOBAL_CTRL].offset);
|
||
|
udelay(10);
|
||
|
|
||
|
val = readl(ss1 + regs_ss1[REG_SS1_CPU_CTRL].offset);
|
||
|
writel(val | 0x1, ss1 + regs_ss1[REG_SS1_CPU_CTRL].offset);
|
||
|
udelay(10);
|
||
|
|
||
|
val = readl(ss1 + regs_ss1[REG_SS1_CORTEX_CONTROL].offset);
|
||
|
writel(val | 0x1, ss1 + regs_ss1[REG_SS1_CORTEX_CONTROL].offset);
|
||
|
udelay(10);
|
||
|
|
||
|
writel(0x0, ss1 + regs_ss1[REG_SS1_CPU_CTRL].offset);
|
||
|
udelay(10);
|
||
|
|
||
|
val = readl(ss1 + regs_ss1[REG_SS1_QCHANNEL].offset);
|
||
|
writel(val | 0x1, ss1 + regs_ss1[REG_SS1_QCHANNEL].offset);
|
||
|
udelay(10);
|
||
|
|
||
|
val = readl(ss2 + regs_ss2[REG_SS2_QCHANNEL].offset);
|
||
|
writel(val | 0x1, ss2 + regs_ss2[REG_SS2_QCHANNEL].offset);
|
||
|
udelay(10);
|
||
|
|
||
|
vipx_leave();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int vipx_exynos9610_ctrl_start(struct vipx_system *sys)
|
||
|
{
|
||
|
vipx_enter();
|
||
|
writel(0x0, sys->reg_ss[REG_SS1] +
|
||
|
regs_ss1[REG_SS1_CORTEX_CONTROL].offset);
|
||
|
vipx_leave();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int vipx_exynos9610_ctrl_get_irq(struct vipx_system *sys, int direction)
|
||
|
{
|
||
|
unsigned int offset;
|
||
|
int val;
|
||
|
|
||
|
vipx_enter();
|
||
|
if (direction == IRQ0_TO_DEVICE) {
|
||
|
offset = regs_ss1[REG_SS1_IRQ0_TO_DEVICE].offset;
|
||
|
val = readl(sys->reg_ss[REG_SS1] + offset);
|
||
|
} else if (direction == IRQ1_TO_DEVICE) {
|
||
|
offset = regs_ss1[REG_SS1_IRQ1_TO_DEVICE].offset;
|
||
|
val = readl(sys->reg_ss[REG_SS1] + offset);
|
||
|
} else if (direction == IRQ_FROM_DEVICE) {
|
||
|
offset = regs_ss1[REG_SS1_IRQ_FROM_DEVICE].offset;
|
||
|
val = readl(sys->reg_ss[REG_SS1] + offset);
|
||
|
} else {
|
||
|
val = -EINVAL;
|
||
|
vipx_err("Failed to get irq due to invalid direction (%d)\n",
|
||
|
direction);
|
||
|
goto p_err;
|
||
|
}
|
||
|
|
||
|
vipx_leave();
|
||
|
return val;
|
||
|
p_err:
|
||
|
return val;
|
||
|
}
|
||
|
|
||
|
static int vipx_exynos9610_ctrl_set_irq(struct vipx_system *sys, int direction,
|
||
|
int val)
|
||
|
{
|
||
|
int ret;
|
||
|
unsigned int offset;
|
||
|
|
||
|
vipx_enter();
|
||
|
if (direction == IRQ0_TO_DEVICE) {
|
||
|
offset = regs_ss1[REG_SS1_IRQ0_TO_DEVICE].offset;
|
||
|
writel(val, sys->reg_ss[REG_SS1] + offset);
|
||
|
} else if (direction == IRQ1_TO_DEVICE) {
|
||
|
offset = regs_ss1[REG_SS1_IRQ1_TO_DEVICE].offset;
|
||
|
writel(val, sys->reg_ss[REG_SS1] + offset);
|
||
|
} else if (direction == IRQ_FROM_DEVICE) {
|
||
|
ret = -EINVAL;
|
||
|
vipx_err("Host can't set irq from device (%d)\n", direction);
|
||
|
goto p_err;
|
||
|
} else {
|
||
|
ret = -EINVAL;
|
||
|
vipx_err("Failed to set irq due to invalid direction (%d)\n",
|
||
|
direction);
|
||
|
goto p_err;
|
||
|
}
|
||
|
|
||
|
vipx_leave();
|
||
|
return 0;
|
||
|
p_err:
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int vipx_exynos9610_ctrl_clear_irq(struct vipx_system *sys,
|
||
|
int direction, int val)
|
||
|
{
|
||
|
int ret;
|
||
|
unsigned int offset;
|
||
|
|
||
|
vipx_enter();
|
||
|
if (direction == IRQ0_TO_DEVICE || direction == IRQ1_TO_DEVICE) {
|
||
|
ret = -EINVAL;
|
||
|
vipx_err("Irq to device must be cleared at device (%d)\n",
|
||
|
direction);
|
||
|
goto p_err;
|
||
|
} else if (direction == IRQ_FROM_DEVICE) {
|
||
|
offset = regs_ss1[REG_SS1_IRQ_FROM_DEVICE].offset;
|
||
|
writel(val, sys->reg_ss[REG_SS1] + offset);
|
||
|
} else {
|
||
|
ret = -EINVAL;
|
||
|
vipx_err("direction of irq is invalid (%d)\n", direction);
|
||
|
goto p_err;
|
||
|
}
|
||
|
|
||
|
vipx_leave();
|
||
|
return 0;
|
||
|
p_err:
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int vipx_exynos9610_ctrl_debug_dump(struct vipx_system *sys)
|
||
|
{
|
||
|
void __iomem *ss1, *ss2;
|
||
|
int idx;
|
||
|
unsigned int val;
|
||
|
const char *name;
|
||
|
|
||
|
vipx_enter();
|
||
|
ss1 = sys->reg_ss[REG_SS1];
|
||
|
ss2 = sys->reg_ss[REG_SS2];
|
||
|
|
||
|
vipx_info("SS1 SFR Dump (count:%d)\n", REG_SS1_MAX);
|
||
|
for (idx = 0; idx < REG_SS1_MAX; ++idx) {
|
||
|
val = readl(ss1 + regs_ss1[idx].offset);
|
||
|
name = regs_ss1[idx].name;
|
||
|
vipx_info("[%2d][%32s] 0x%08x\n", idx, name, val);
|
||
|
}
|
||
|
|
||
|
vipx_info("SS2 SFR Dump (count:%d)\n", REG_SS2_MAX);
|
||
|
for (idx = 0; idx < REG_SS2_MAX; ++idx) {
|
||
|
val = readl(ss2 + regs_ss2[idx].offset);
|
||
|
name = regs_ss2[idx].name;
|
||
|
vipx_info("[%2d][%32s] 0x%08x\n", idx, name, val);
|
||
|
}
|
||
|
|
||
|
vipx_leave();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int vipx_exynos9610_ctrl_hex_dump(struct vipx_system *sys)
|
||
|
{
|
||
|
unsigned int temp[64] = { 0, };
|
||
|
unsigned int temp_size;
|
||
|
int idx;
|
||
|
void __iomem *reg_base;
|
||
|
const struct vipx_reg *reg_offset;
|
||
|
|
||
|
vipx_enter();
|
||
|
temp_size = ARRAY_SIZE(temp);
|
||
|
if (temp_size < REG_SS1_MAX || temp_size < REG_SS2_MAX ||
|
||
|
temp_size < REG_SYSREG1_MAX ||
|
||
|
temp_size < REG_SYSREG2_MAX) {
|
||
|
vipx_err("temp size for dump is too small(%u/%u/%u/%u/%u)\n",
|
||
|
temp_size, REG_SS1_MAX, REG_SS2_MAX,
|
||
|
REG_SYSREG1_MAX, REG_SYSREG2_MAX);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
reg_base = sys->reg_ss[REG_SS1];
|
||
|
reg_offset = regs_ss1;
|
||
|
for (idx = 0; idx < REG_SS1_MAX; ++idx)
|
||
|
temp[idx] = readl(reg_base + reg_offset[idx].offset);
|
||
|
|
||
|
for (idx = 0; idx < REG_SS1_MAX; idx += 8)
|
||
|
vipx_info("[%2d] %8x %8x %8x %8x %8x %8x %8x %8x\n",
|
||
|
idx, temp[idx], temp[idx + 1], temp[idx + 2],
|
||
|
temp[idx + 3], temp[idx + 4], temp[idx + 5],
|
||
|
temp[idx + 6], temp[idx + 7]);
|
||
|
|
||
|
reg_base = sys->reg_ss[REG_SS2];
|
||
|
reg_offset = regs_ss2;
|
||
|
for (idx = 0; idx < REG_SS2_MAX; ++idx)
|
||
|
temp[idx] = readl(reg_base + reg_offset[idx].offset);
|
||
|
|
||
|
for (idx = 0; idx < REG_SS2_MAX; idx += 8)
|
||
|
vipx_info("[%2d] %8x %8x %8x %8x %8x %8x %8x %8x\n",
|
||
|
idx, temp[idx], temp[idx + 1], temp[idx + 2],
|
||
|
temp[idx + 3], temp[idx + 4], temp[idx + 5],
|
||
|
temp[idx + 6], temp[idx + 7]);
|
||
|
|
||
|
reg_base = sys->sysreg1;
|
||
|
reg_offset = regs_sysreg1;
|
||
|
for (idx = 0; idx < REG_SYSREG1_MAX; ++idx)
|
||
|
temp[idx] = readl(reg_base + reg_offset[idx].offset);
|
||
|
|
||
|
for (idx = 0; idx < REG_SYSREG1_MAX; idx += 8)
|
||
|
vipx_info("[%2d] %8x %8x %8x %8x %8x %8x %8x %8x\n",
|
||
|
idx, temp[idx], temp[idx + 1], temp[idx + 2],
|
||
|
temp[idx + 3], temp[idx + 4], temp[idx + 5],
|
||
|
temp[idx + 6], temp[idx + 7]);
|
||
|
|
||
|
reg_base = sys->sysreg2;
|
||
|
reg_offset = regs_sysreg2;
|
||
|
for (idx = 0; idx < REG_SYSREG2_MAX; ++idx)
|
||
|
temp[idx] = readl(reg_base + reg_offset[idx].offset);
|
||
|
|
||
|
for (idx = 0; idx < REG_SYSREG2_MAX; idx += 8)
|
||
|
vipx_info("[%2d] %8x %8x %8x %8x %8x %8x %8x %8x\n",
|
||
|
idx, temp[idx], temp[idx + 1], temp[idx + 2],
|
||
|
temp[idx + 3], temp[idx + 4], temp[idx + 5],
|
||
|
temp[idx + 6], temp[idx + 7]);
|
||
|
|
||
|
vipx_leave();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
const struct vipx_ctrl_ops vipx_ctrl_ops = {
|
||
|
.reset = vipx_exynos9610_ctrl_reset,
|
||
|
.start = vipx_exynos9610_ctrl_start,
|
||
|
.get_irq = vipx_exynos9610_ctrl_get_irq,
|
||
|
.set_irq = vipx_exynos9610_ctrl_set_irq,
|
||
|
.clear_irq = vipx_exynos9610_ctrl_clear_irq,
|
||
|
.debug_dump = vipx_exynos9610_ctrl_debug_dump,
|
||
|
.hex_dump = vipx_exynos9610_ctrl_hex_dump,
|
||
|
};
|