/* 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);
}
