blob: 15cd4b20594c4d5f0463821a731438c0e6ca7672 [file] [log] [blame]
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* drivers/vpu/aml_vpu_power_init.c
*
* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
*
*/
#include <config.h>
#include <linux/kernel.h>
#include <linux/arm-smccc.h>
#include <vpu.h>
#include "aml_vpu_reg.h"
#include "aml_vpu.h"
#ifdef CONFIG_AMLOGIC_TEE
//flag:(forward compatible)
// 0=set vpu sec without debug print
// 1=set vpu sec with after debug print
// 2=set vpu sec with before and after debug print
// 3=only debug print
unsigned long viu_init_psci_smc(unsigned long flag)
{
struct arm_smccc_res res;
VPUPR("%s\n", __func__);
arm_smccc_smc(0x82000080, flag, 0, 0,
0, 0, 0, 0, &res);
return res.a0;
}
#endif
void vpu_mem_pd_init_off(void)
{
return;
#ifdef VPU_DEBUG_PRINT
VPUPR("%s\n", __func__);
#endif
}
void vpu_module_init_config(void)
{
struct vpu_ctrl_s *ctrl_table;
unsigned int _reg, _val, _bit, _len;
int i = 0, cnt;
/* vpu clk gate init off */
cnt = vpu_conf.data->module_init_table_cnt;
ctrl_table = vpu_conf.data->module_init_table;
if (ctrl_table) {
i = 0;
while (i < cnt) {
if (ctrl_table[i].reg == VPU_REG_END)
break;
_reg = ctrl_table[i].reg;
_val = ctrl_table[i].val;
_bit = ctrl_table[i].bit;
_len = ctrl_table[i].len;
vpu_vcbus_setb(_reg, _val, _bit, _len);
i++;
}
}
vpu_hiu_setb(vpu_conf.data->vid_clk_reg, 0, 0, 8);
/* dmc_arb_config */
switch (vpu_conf.data->chip_type) {
case VPU_CHIP_GXBB:
case VPU_CHIP_GXTVBB:
case VPU_CHIP_GXL:
case VPU_CHIP_GXM:
case VPU_CHIP_TXL:
case VPU_CHIP_TXLX:
case VPU_CHIP_AXG:
case VPU_CHIP_TXHD:
case VPU_CHIP_G12A:
case VPU_CHIP_G12B:
case VPU_CHIP_SM1:
vpu_vcbus_write(VPU_RDARB_MODE_L1C1, 0x0); //0x210000
vpu_vcbus_write(VPU_RDARB_MODE_L1C2, 0x10000);
vpu_vcbus_write(VPU_RDARB_MODE_L2C1, 0x900000);
vpu_vcbus_write(VPU_WRARB_MODE_L2C1, 0x20000);
break;
case VPU_CHIP_TL1:
case VPU_CHIP_TM2:
case VPU_CHIP_T5:
case VPU_CHIP_T5D:
vpu_vcbus_write(VPU_RDARB_MODE_L1C1, 0x0); //0x210000
vpu_vcbus_write(VPU_RDARB_MODE_L1C2, 0x10000);
vpu_vcbus_write(VPU_RDARB_MODE_L2C1, 0x20000);
vpu_vcbus_write(VPU_WRARB_MODE_L2C1, 0x20000);
break;
default:
break;
}
#ifdef CONFIG_AMLOGIC_TEE
if (vpu_conf.data->chip_type == VPU_CHIP_T5W)
viu_init_psci_smc(0);
#endif
VPUPR("%s\n", __func__);
}
void vpu_power_on(void)
{
struct vpu_ctrl_s *ctrl_table;
struct vpu_reset_s *reset_table;
unsigned int _reg, _val, _start, _end, _len, mask;
int i = 0, j;
/* power on VPU_HDMI */
ctrl_table = vpu_conf.data->power_table;
if (ctrl_table) {
i = 0;
while (i < VPU_PWR_CNT_MAX) {
if (ctrl_table[i].reg == VPU_REG_END)
break;
_reg = ctrl_table[i].reg;
_val = 0;
_start = ctrl_table[i].bit;
_len = ctrl_table[i].len;
vpu_ao_setb(_reg, _val, _start, _len);
i++;
}
}
udelay(20);
/* power up memories */
ctrl_table = vpu_conf.data->mem_pd_table;
i = 0;
while (i < VPU_MEM_PD_CNT_MAX) {
if (ctrl_table[i].reg == VPU_REG_END)
break;
_reg = ctrl_table[i].reg;
_start = ctrl_table[i].bit;
_end = ctrl_table[i].len + ctrl_table[i].bit;
for (j = _start; j < _end; j+=2) {
vpu_hiu_setb(_reg, 0, j, 2);
udelay(5);
}
i++;
}
for (i = 8; i < 16; i++) {
vpu_hiu_setb(HHI_MEM_PD_REG0, 0, i, 1);
udelay(5);
}
udelay(20);
/* Reset VIU + VENC */
/* Reset VENCI + VENCP + VADC + VENCL */
/* Reset HDMI-APB + HDMI-SYS + HDMI-TX + HDMI-CEC */
reset_table = vpu_conf.data->reset_table;
i = 0;
while (i < VPU_RESET_CNT_MAX) {
if (reset_table[i].reg == VPU_REG_END)
break;
_reg = reset_table[i].reg;
mask = reset_table[i].mask;
vpu_cbus_clr_mask(_reg, mask);
i++;
}
udelay(5);
/* release Reset */
i = 0;
while (i < VPU_RESET_CNT_MAX) {
if (reset_table[i].reg == VPU_REG_END)
break;
_reg = reset_table[i].reg;
mask = reset_table[i].mask;
vpu_cbus_set_mask(_reg, mask);
i++;
}
/* Remove VPU_HDMI ISO */
ctrl_table = vpu_conf.data->iso_table;
if (ctrl_table) {
i = 0;
while (i < VPU_ISO_CNT_MAX) {
if (ctrl_table[i].reg == VPU_REG_END)
break;
_reg = ctrl_table[i].reg;
_val = 0;
_start = ctrl_table[i].bit;
_len = ctrl_table[i].len;
vpu_ao_setb(_reg, _val, _start, _len);
i++;
}
}
VPUPR("%s\n", __func__);
}
void vpu_power_off(void)
{
struct vpu_ctrl_s *ctrl_table;
unsigned int _reg, _start, _end, _len, _val;
int i = 0, j;
/* Enable Isolation */
ctrl_table = vpu_conf.data->iso_table;
if (ctrl_table) {
i = 0;
while (i < VPU_ISO_CNT_MAX) {
if (ctrl_table[i].reg == VPU_REG_END)
break;
_reg = ctrl_table[i].reg;
_val = 1;
_start = ctrl_table[i].bit;
_len = ctrl_table[i].len;
vpu_ao_setb(_reg, _val, _start, _len);
i++;
}
}
udelay(20);
/* power down memories */
ctrl_table = vpu_conf.data->mem_pd_table;
i = 0;
while (i < VPU_MEM_PD_CNT_MAX) {
if (ctrl_table[i].reg == VPU_REG_END)
break;
_reg = ctrl_table[i].reg;
_start = ctrl_table[i].bit;
_end = ctrl_table[i].len + ctrl_table[i].bit;
for (j = _start; j < _end; j+=2) {
vpu_hiu_setb(_reg, 0x3, j, 2);
udelay(5);
}
i++;
}
for (i = 8; i < 16; i++) {
vpu_hiu_setb(HHI_MEM_PD_REG0, 0x1, i, 1);
udelay(5);
}
udelay(20);
/* Power down VPU domain */
ctrl_table = vpu_conf.data->power_table;
if (ctrl_table) {
i = 0;
while (i < VPU_PWR_CNT_MAX) {
if (ctrl_table[i].reg == VPU_REG_END)
break;
_reg = ctrl_table[i].reg;
_val = ctrl_table[i].val;
_start = ctrl_table[i].bit;
_len = ctrl_table[i].len;
vpu_ao_setb(_reg, _val, _start, _len);
i++;
}
}
vpu_hiu_setb(vpu_conf.data->vapb_clk_reg, 0, 8, 1);
vpu_hiu_setb(vpu_conf.data->vpu_clk_reg, 0, 8, 1);
VPUPR("%s\n", __func__);
}
void vpu_power_on_new(void)
{
#ifdef CONFIG_SECURE_POWER_CONTROL
if (vpu_conf.data->pwrctrl_id < VPU_PWR_ID_INVALID)
pwr_ctrl_psci_smc(vpu_conf.data->pwrctrl_id, 1);
VPUPR("%s\n", __func__);
#else
VPUERR("%s: no CONFIG_SECURE_POWER_CONTROL\n", __func__);
#endif
}
void vpu_power_off_new(void)
{
#ifdef CONFIG_SECURE_POWER_CONTROL
VPUPR("%s\n", __func__);
if (vpu_conf.data->pwrctrl_id < VPU_PWR_ID_INVALID)
pwr_ctrl_psci_smc(vpu_conf.data->pwrctrl_id, 0);
#else
VPUERR("%s: no CONFIG_SECURE_POWER_CONTROL\n", __func__);
#endif
vpu_hiu_setb(vpu_conf.data->vapb_clk_reg, 0, 8, 1);
vpu_hiu_setb(vpu_conf.data->vpu_clk_reg, 0, 8, 1);
}