kernel_samsung_a53x/include/soc/samsung/asv_g_spec.h
2024-06-15 16:02:09 -03:00

151 lines
4.3 KiB
C
Executable file

/* SPDX-License-Identifier: GPL-2.0-or-later */
/* include/soc/samsung/asv_g_spec.h
*
* Copyright (c) 2021 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* 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.
*/
#ifndef __ASV_G_SPEC_H__
#define __ASV_G_SPEC_H__
#include <soc/samsung/ect_parser.h>
#include <soc/samsung/cal-if.h>
#include <linux/io.h>
#include "../../../drivers/soc/samsung/cal-if/cmucal.h"
#include "../../../drivers/soc/samsung/cal-if/asv.h"
//#include "vclk.h"
extern struct vclk acpm_vclk_list[];
extern unsigned int acpm_vclk_size;
#define get_domain_name(type) (acpm_vclk_list[type].name)
#define SPEC_STR_SIZE (30)
#define asv_g_spec(domain, id, fused_addr, bit_num) \
static ssize_t show_asv_g_spec_##domain##_fused_volt \
(struct kobject *kobj, struct kobj_attribute *attr, char *buf) \
{ \
return show_asv_g_spec(id, ASV_G_FUSED, buf, fused_addr, bit_num); \
} \
static struct kobj_attribute asv_g_spec_##domain##_fused_volt = \
__ATTR(domain##_fused_volt, 0400, show_asv_g_spec_##domain##_fused_volt, NULL); \
static ssize_t show_asv_g_spec_##domain##_grp_volt \
(struct kobject *kobj, struct kobj_attribute *attr, char *buf) \
{ \
return show_asv_g_spec(id, ASV_G_GRP, buf, fused_addr, bit_num); \
} \
static struct kobj_attribute asv_g_spec_##domain##_grp_volt = \
__ATTR(domain##_grp_volt, 0400, show_asv_g_spec_##domain##_grp_volt, NULL)
#define asv_g_spec_attr(domain) \
&asv_g_spec_##domain##_fused_volt.attr, \
&asv_g_spec_##domain##_grp_volt.attr
enum spec_volt_type {
ASV_G_FUSED = 0,
ASV_G_GRP
};
static ssize_t show_asv_g_spec(int id, enum spec_volt_type type,
char *buf, unsigned int fused_addr, unsigned int bit_num)
{
void *gen_block;
struct ect_gen_param_table *spec;
int asv_tbl_ver, asv_grp, tbl_size, j, vtyp_freq, num_lv;
unsigned int fused_volt = 0, grp_volt = 0, volt;
struct dvfs_rate_volt rate_volt[48];
unsigned int *spec_table = NULL;
ssize_t size = 0, len = 0;
char spec_str[SPEC_STR_SIZE] = {0, };
unsigned long fused_val;
void __iomem *fused_addr_va;
if (id >= acpm_vclk_size) {
pr_err("%s: cannot found dvfs domain: %d\n", __func__, id);
goto out;
}
gen_block = ect_get_block("GEN");
if (gen_block == NULL) {
pr_err("%s: Failed to get gen block from ECT\n", __func__);
goto out;
}
asv_grp = asv_get_grp(id | ACPM_VCLK_TYPE);
if (!asv_grp) {
pr_err("%s: There has no ASV-G information for %s group 0\n",
__func__, get_domain_name(id));
goto out;
}
len = snprintf(spec_str, SPEC_STR_SIZE, "SPEC_%s", get_domain_name(id));
if (len < 0)
goto out;
spec = ect_gen_param_get_table(gen_block, spec_str);
if (spec == NULL) {
pr_err("%s: Failed to get spec table from ECT\n", __func__);
goto out;
}
asv_tbl_ver = asv_get_table_ver();
for (j = 0; j < spec->num_of_row; j++) {
spec_table = &spec->parameter[spec->num_of_col * j];
if (spec_table[0] == asv_tbl_ver) {
grp_volt = spec_table[asv_grp + 2];
vtyp_freq = spec_table[1];
break;
}
}
if (j == spec->num_of_row) {
pr_err("%s: Do not support ASV-G, asv table version:%d\n", __func__, asv_tbl_ver);
goto out;
}
if (!grp_volt) {
pr_err("%s: Failed to get grp volt\n", __func__);
goto out;
}
num_lv = cal_dfs_get_lv_num(id | ACPM_VCLK_TYPE);
tbl_size = cal_dfs_get_rate_asv_table(id | ACPM_VCLK_TYPE, rate_volt);
if (!tbl_size) {
pr_err("%s: Failed to get asv table\n", __func__);
goto out;
}
if (fused_addr) {
if ((fused_addr & 0x9000) == 0x9000) {
exynos_smc_readsfr((unsigned long)fused_addr, &fused_val);
} else {
fused_addr_va = ioremap(fused_addr, 4);
fused_val = __raw_readl(fused_addr_va);
iounmap(fused_addr_va);
}
fused_volt = (((unsigned int)fused_val & (0xff << bit_num)) >> bit_num) * 6250;
} else {
for (j = 0; j < num_lv; j++) {
if (rate_volt[j].rate == vtyp_freq) {
fused_volt = rate_volt[j].volt;
break;
}
}
if (j == num_lv) {
pr_err("%s: There has no frequency %d on %d domain\n", __func__,
vtyp_freq, get_domain_name(id));
goto out;
}
}
volt = (type == ASV_G_FUSED) ? fused_volt : grp_volt;
size += snprintf(buf + size, PAGE_SIZE, "%d\n", volt);
out:
return size;
}
#endif