/*
 * Copyright (C) 2018 MediaTek Inc.
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
 */

#include <helio-dvfsrc_v2.h>
#include <helio-dvfsrc-opp.h>
#include <helio-dvfsrc-ipi.h>

static struct opp_profile opp_table[VCORE_DVFS_OPP_NUM];
static int vcore_dvfs_to_vcore_opp[VCORE_DVFS_OPP_NUM];
static int vcore_dvfs_to_ddr_opp[VCORE_DVFS_OPP_NUM];
static int vcore_uv_table[VCORE_OPP_NUM];
static int vcore_opp_to_pwrap_cmd[VCORE_OPP_NUM];
static int ddr_table[DDR_OPP_NUM];


/* ToDo: Copy Opp Table to AEE Dump */
int get_cur_vcore_dvfs_opp(void)
{
#if defined(VCOREFS_LEVEL_POSITIVE)
	return __builtin_ffs(spm_get_dvfs_level());
#else
	return VCORE_DVFS_OPP_NUM - __builtin_ffs(get_dvfs_final_level());
#endif
}

void set_opp_table(unsigned int vcore_dvfs_opp, int vcore_uv, int ddr_khz)
{
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
	struct qos_ipi_data qos_d;

	qos_d.cmd = QOS_IPI_OPP_TABLE;
	qos_d.u.opp_table.vcore_dvfs_opp = vcore_dvfs_opp;
	qos_d.u.opp_table.vcore_uv = vcore_uv;
	qos_d.u.opp_table.ddr_khz = ddr_khz;
	qos_ipi_to_sspm_command(&qos_d, 4);
#endif

	if (vcore_dvfs_opp >= VCORE_DVFS_OPP_NUM)
		return;

	opp_table[vcore_dvfs_opp].vcore_uv = vcore_uv;
	opp_table[vcore_dvfs_opp].ddr_khz = ddr_khz;
}

void set_vcore_opp(unsigned int vcore_dvfs_opp, int vcore_opp)
{
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
	struct qos_ipi_data qos_d;

	qos_d.cmd = QOS_IPI_VCORE_OPP;
	qos_d.u.vcore_opp.vcore_dvfs_opp = vcore_dvfs_opp;
	qos_d.u.vcore_opp.vcore_opp = vcore_opp;
	qos_ipi_to_sspm_command(&qos_d, 3);
#endif

	if (vcore_dvfs_opp >= VCORE_DVFS_OPP_NUM)
		return;

	vcore_dvfs_to_vcore_opp[vcore_dvfs_opp] = vcore_opp;
}

int get_vcore_opp(unsigned int opp)
{
	if (opp >= VCORE_DVFS_OPP_NUM)
		return 0;

	return vcore_dvfs_to_vcore_opp[opp];
}

int get_vcore_uv(unsigned int opp)
{
	if (opp >= VCORE_DVFS_OPP_NUM)
		return 0;

	return opp_table[opp].vcore_uv;
}

int get_cur_vcore_opp(void)
{
	unsigned int idx;

	if (!is_qos_enabled())
		return VCORE_OPP_UNREQ;

	idx = get_cur_vcore_dvfs_opp();

	if (idx >= VCORE_DVFS_OPP_NUM)
		return VCORE_OPP_UNREQ;

	return vcore_dvfs_to_vcore_opp[idx];
}

int get_cur_vcore_uv(void)
{
	unsigned int idx;

	if (!is_qos_enabled())
		return 0;

	idx = get_cur_vcore_dvfs_opp();

	if (idx >= VCORE_DVFS_OPP_NUM)
		return 0;

	return opp_table[idx].vcore_uv;
}

void set_ddr_opp(unsigned int vcore_dvfs_opp, int ddr_opp)
{
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
	struct qos_ipi_data qos_d;

	qos_d.cmd = QOS_IPI_DDR_OPP;
	qos_d.u.ddr_opp.vcore_dvfs_opp = vcore_dvfs_opp;
	qos_d.u.ddr_opp.ddr_opp = ddr_opp;
	qos_ipi_to_sspm_command(&qos_d, 3);
#endif
	if (vcore_dvfs_opp >= VCORE_DVFS_OPP_NUM)
		return;

	vcore_dvfs_to_ddr_opp[vcore_dvfs_opp] = ddr_opp;
}

int get_ddr_opp(unsigned int opp)
{
	if (opp >= VCORE_DVFS_OPP_NUM)
		return 0;

	return vcore_dvfs_to_ddr_opp[opp];
}

int get_ddr_khz(unsigned int opp)
{
	if (opp >= VCORE_DVFS_OPP_NUM)
		return 0;

	return opp_table[opp].ddr_khz;
}

int get_cur_ddr_opp(void)
{
	unsigned int idx;

	if (!is_qos_enabled())
		return DDR_OPP_UNREQ;

	idx = get_cur_vcore_dvfs_opp();

	if (idx >= VCORE_DVFS_OPP_NUM)
		return DDR_OPP_UNREQ;

	return vcore_dvfs_to_ddr_opp[idx];
}

int get_cur_ddr_khz(void)
{
	unsigned int idx;

	if (!is_qos_enabled())
		return 0;

	idx = get_cur_vcore_dvfs_opp();

	if (idx >= VCORE_DVFS_OPP_NUM)
		return 0;

	return opp_table[idx].ddr_khz;
}

void set_vcore_uv_table(unsigned int vcore_opp, int vcore_uv)
{
	if (vcore_opp >= VCORE_OPP_NUM)
		return;

	spm_dvfs_pwrap_cmd(get_pwrap_cmd(vcore_opp),
			vcore_uv_to_pmic(vcore_uv));

	vcore_uv_table[vcore_opp] = vcore_uv;
}

int get_opp_ddr_freq(unsigned int ddr_opp)
{
	if (ddr_opp >= DDR_OPP_NUM)
		return 0;

	return ddr_table[ddr_opp];
}

void set_opp_ddr_freq(unsigned int ddr_opp, int ddr_freq)
{
	if (ddr_opp >= DDR_OPP_NUM)
		return;

	ddr_table[ddr_opp] = ddr_freq;
}

int get_vcore_uv_table(unsigned int vcore_opp)
{
	if (vcore_opp >= VCORE_OPP_NUM)
		return 0;

	return vcore_uv_table[vcore_opp];
}

void set_pwrap_cmd(unsigned int vcore_opp, int pwrap_cmd)
{
	if (vcore_opp >= VCORE_OPP_NUM)
		return;

	vcore_opp_to_pwrap_cmd[vcore_opp] = pwrap_cmd;
}

int get_pwrap_cmd(unsigned int vcore_opp)
{
	if (vcore_opp >= VCORE_OPP_NUM)
		return 0;

	return vcore_opp_to_pwrap_cmd[vcore_opp];
}
