Files
opensbi/lib/utils/cppc/fdt_cppc_sg2044.c
haijiao.liu 78f021d248 lib: Add SG2044 CPPC support
Signed-off-by: haijiao.liu <haijiao.liu@sophgo.com>
2025-04-25 06:30:33 +08:00

116 lines
2.2 KiB
C

/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 Sophgo Inc.
*
* Authors:
* Haijiao Liu <haijiao.liu@sophgo.com>
*/
#include <libfdt.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_string.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_clk.h>
#include <sbi/sbi_cppc.h>
#include <sbi_utils/cppc/fdt_cppc.h>
#define CPPC_REGISTER_WIDTH 64
#define CPPC_REGISTER_NOT_IMPLEMENTED 0
static char clock_names[64];
static uint64_t clk_granularity;
static int sg2044_cppc_read(unsigned long reg, u64 *val)
{
int rc = SBI_SUCCESS;
switch (reg) {
case SBI_CPPC_DESIRED_PERF:
*val = sbi_clk_get_rate(clock_names) / clk_granularity;
break;
default:
rc = SBI_ERR_NOT_SUPPORTED;
}
return rc;
}
static int sg2044_cppc_write(unsigned long reg, u64 val)
{
int rc = SBI_SUCCESS;
switch (reg) {
case SBI_CPPC_DESIRED_PERF:
rc = sbi_clk_set_rate(clock_names, val * clk_granularity);
break;
default:
rc = SBI_ERR_NOT_SUPPORTED;
}
return rc;
}
static int sg2044_cppc_probe(unsigned long reg)
{
int rc;
switch (reg) {
case SBI_CPPC_DESIRED_PERF:
rc = CPPC_REGISTER_WIDTH;
break;
default:
rc = CPPC_REGISTER_NOT_IMPLEMENTED;
}
return rc;
}
static struct sbi_cppc_device sbi_sg2044_cppc = {
.name = "sg2044-cppc",
.cppc_read = sg2044_cppc_read,
.cppc_write = sg2044_cppc_write,
.cppc_probe = sg2044_cppc_probe,
};
static int sg2044_cppc_cold_init(const void *fdt, int nodeoff,
const struct fdt_match *match)
{
const struct sbi_clk_device *clk;
const fdt32_t *val;
const char *name;
int len;
clk = sbi_clk_get_device(fdt);
if (!clk)
return SBI_ENODEV;
val = fdt_getprop(fdt, nodeoff, "step", &len);
if (!val)
return SBI_EINVAL;
clk_granularity = fdt32_to_cpu(val[0]);
clk_granularity = (clk_granularity << 32) | fdt32_to_cpu(val[1]);
name = fdt_getprop(fdt, nodeoff, "clock-names", &len);
if (!name)
return SBI_EINVAL;
sbi_strncpy(clock_names, name, MIN(sizeof(clock_names), len));
sbi_cppc_set_device(&sbi_sg2044_cppc);
return 0;
}
static const struct fdt_match sg2044_cppc_match[] = {
{ .compatible = "sophgo,sg2044-cppc" },
{},
};
struct fdt_driver fdt_cppc_sg2044 = {
.match_table = sg2044_cppc_match,
.init = sg2044_cppc_cold_init,
};