// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019 Linaro Ltd.
*
* Author: Stanimir Varbanov <stanimir.varbanov@linaro.org>
*/
#include <linux/clk.h>
#include <linux/interconnect.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/types.h>
#include <media/v4l2-mem2mem.h>
#include "core.h"
#include "hfi_parser.h"
#include "hfi_venus_io.h"
#include "pm_helpers.h"
#include "hfi_platform.h"
static bool legacy_binding;
static int core_clks_get(struct venus_core *core)
{
const struct venus_resources *res = core->res;
struct device *dev = core->dev;
unsigned int i;
for (i = 0; i < res->clks_num; i++) {
core->clks[i] = devm_clk_get(dev, res->clks[i]);
if (IS_ERR(core->clks[i]))
return PTR_ERR(core->clks[i]);
}
return 0;
}
static int core_clks_enable(struct venus_core *core)
{
const struct venus_resources *res = core->res;
const struct freq_tbl *freq_tbl = core->res->freq_tbl;
unsigned int freq_tbl_size = core->res->freq_tbl_size;
unsigned long freq;
unsigned int i;
int ret;
if (!freq_tbl)
return -EINVAL;
freq = freq_tbl[freq_tbl_size - 1].freq;
for (i = 0; i < res->clks_num; i++) {
if (IS_V6(core)) {
ret = clk_set_rate(core->clks[i], freq);
if (ret)
goto err;
}
ret = clk_prepare_enable(core->clks[i]);
if (ret)
goto err;
}
return 0;
err:
while (i--)
clk_disable_unprepare(core->clks[i]);
return ret;
}
static void core_clks_disable(struct venus_core *core)
{
const struct venus_resources *res = core->res;
unsigned int i = res->clks_num;
while (i--)
clk_disable_unprepare(core->clks[i]);
}
static int core_clks_set_rate(struct venus_core *core, unsigned long freq)
{
int ret;
ret = dev_pm_opp_set_rate(core->dev, freq);
if (ret)
return ret;
ret = clk_set_rate(core->vcodec0_clks[0], freq);
if (ret)
return ret;
ret = clk_set_rate(core->vcodec1_clks[0], freq);
if (ret)
return ret;
return 0;
}
static int vcodec_clks_get(struct venus_core *core, struct device *dev,
struct clk **clks, const char * const *id)
{
const struct venus_resources *res = core->res;
unsigned int i;
for (i = 0; i < res->vcodec_clks_num; i++) {
if (!id[i])
continue;
clks[i] = devm_clk_get(dev, id[i]);
if (IS_ERR(clks[i]))
return PTR_ERR(clks[i]);
}
return 0;
}
static int vcodec_clks_enable(struct venus_core *core, struct clk **clks)
{
const struct venus_resources *res = core->res;
unsigned int i;
int ret;
for (i = 0; i < res->vcodec_clks_nu