mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-30 15:48:52 +01:00
1068 lines
28 KiB
C
1068 lines
28 KiB
C
#include "../pwrcal.h"
|
|
#include "../pwrcal-env.h"
|
|
#include "../pwrcal-rae.h"
|
|
#include "../pwrcal-vclk.h"
|
|
#include "../pwrcal-asv.h"
|
|
#include "S5E7570-cmusfr.h"
|
|
#include "S5E7570-sysreg.h"
|
|
#include "S5E7570-vclk.h"
|
|
#include "S5E7570-vclk-internal.h"
|
|
|
|
#define S5P_VA_APM_SRAM ((void *)0x11200000)
|
|
#define EXYNOS_MAILBOX_RCC_MIN_MAX(x) (S5P_VA_APM_SRAM + (0x3700) + (x * 0x4))
|
|
#define EXYNOS_MAILBOX_ATLAS_RCC(x) (S5P_VA_APM_SRAM + (0x3730) + (x * 0x4))
|
|
#define EXYNOS_MAILBOX_APOLLO_RCC(x) (S5P_VA_APM_SRAM + (0x3798) + (x * 0x4))
|
|
#define EXYNOS_MAILBOX_G3D_RCC(x) (S5P_VA_APM_SRAM + (0x37EC) + (x * 0x4))
|
|
#define EXYNOS_MAILBOX_MIF_RCC(x) (S5P_VA_APM_SRAM + (0x381C) + (x * 0x4))
|
|
|
|
enum dvfs_id {
|
|
cal_asv_dvfs_cpucl0,
|
|
cal_asv_dvfs_g3d,
|
|
cal_asv_dvfs_mif,
|
|
cal_asv_dvfs_int,
|
|
cal_asv_dvfs_cam,
|
|
cal_asv_dvfs_disp,
|
|
num_of_dvfs,
|
|
};
|
|
|
|
#define MAX_ASV_GROUP 16
|
|
#define NUM_OF_ASVTABLE 1
|
|
#define PWRCAL_ASV_LIST(table) {table, sizeof(table) / sizeof(table[0])}
|
|
|
|
struct asv_table_entry {
|
|
unsigned int index;
|
|
unsigned int *voltage;
|
|
};
|
|
|
|
struct asv_table_list {
|
|
struct asv_table_entry *table;
|
|
unsigned int table_size;
|
|
unsigned int voltage_count;
|
|
};
|
|
|
|
#define FORCE_ASV_MAGIC 0x57E90000
|
|
static unsigned int force_asv_group[num_of_dvfs];
|
|
|
|
struct asv_tbl_info {
|
|
unsigned cpucl0_asv_group:4;
|
|
int cpucl0_modified_group:4;
|
|
unsigned cpucl0_ssa10:2;
|
|
unsigned cpucl0_ssa11:2;
|
|
unsigned cpucl0_ssa0:4;
|
|
unsigned reserverd_0123:16;
|
|
|
|
unsigned g3d_asv_group:4;
|
|
int g3d_modified_group:4;
|
|
unsigned g3d_ssa10:2;
|
|
unsigned g3d_ssa11:2;
|
|
unsigned g3d_ssa0:4;
|
|
unsigned mif_asv_group:4;
|
|
int mif_modified_group:4;
|
|
unsigned mif_ssa10:2;
|
|
unsigned mif_ssa11:2;
|
|
unsigned mif_ssa0:4;
|
|
|
|
unsigned int_asv_group:4;
|
|
int int_modified_group:4;
|
|
unsigned int_ssa10:2;
|
|
unsigned int_ssa11:2;
|
|
unsigned int_ssa0:4;
|
|
unsigned disp_asv_group:4; /* CAM = DISP */
|
|
int disp_modified_group:4;
|
|
unsigned disp_ssa10:2;
|
|
unsigned disp_ssa11:2;
|
|
unsigned disp_ssa0:4;
|
|
|
|
unsigned asv_table_ver:7;
|
|
unsigned fused_grp:1;
|
|
unsigned asb_pgm_version:8;
|
|
unsigned cp_asv_group:4;
|
|
int cp_modified_group:4;
|
|
unsigned cp_ssa10:2;
|
|
unsigned cp_ssa11:2;
|
|
unsigned cp_ssa0:4;
|
|
unsigned cpucl0_vthr:2;
|
|
unsigned cpucl0_delta:2;
|
|
unsigned reserved_45:4;
|
|
unsigned g3d_vthr:2;
|
|
unsigned g3d_delta:2;
|
|
unsigned int_vthr:2;
|
|
unsigned int_delta:2;
|
|
unsigned mif_vthr:2;
|
|
unsigned mif_delta:2;
|
|
|
|
unsigned cpu_cl_ema:3;
|
|
unsigned cpu_cl_emas:1;
|
|
unsigned cpu_cl_emaw:2;
|
|
unsigned reserved_6:2;
|
|
unsigned g3d_ema:3;
|
|
unsigned g3d_emas:1;
|
|
unsigned g3d_emaw:2;
|
|
unsigned reserved_7:2;
|
|
unsigned cp_ema:6;
|
|
unsigned reserved_80:6; //reserved_8 = 278 = 4 * 64 + 22
|
|
unsigned reserved_81:16;
|
|
unsigned long long reserved_82:64;
|
|
unsigned long long reserved_83:64;
|
|
unsigned long long reserved_84:64;
|
|
unsigned long long reserved_85:64;
|
|
unsigned reserved_9:32;
|
|
};
|
|
#define ASV_INFO_ADDR_BASE (0x100D9000)
|
|
#define ASV_INFO_ADDR_CNT (sizeof(struct asv_tbl_info) / 4)
|
|
|
|
static struct asv_tbl_info asv_tbl_info;
|
|
|
|
static struct asv_table_list *pwrcal_cpucl0_asv_table;
|
|
static struct asv_table_list *pwrcal_g3d_asv_table;
|
|
static struct asv_table_list *pwrcal_mif_asv_table;
|
|
static struct asv_table_list *pwrcal_int_asv_table;
|
|
static struct asv_table_list *pwrcal_disp_asv_table;
|
|
static struct asv_table_list *pwrcal_cam_asv_table;
|
|
|
|
static struct asv_table_list *pwrcal_cpucl0_rcc_table;
|
|
static struct asv_table_list *pwrcal_g3d_rcc_table;
|
|
static struct asv_table_list *pwrcal_mif_rcc_table;
|
|
|
|
static struct pwrcal_vclk_dfs *asv_dvfs_cpucl0;
|
|
static struct pwrcal_vclk_dfs *asv_dvfs_g3d;
|
|
static struct pwrcal_vclk_dfs *asv_dvfs_mif;
|
|
static struct pwrcal_vclk_dfs *asv_dvfs_int;
|
|
static struct pwrcal_vclk_dfs *asv_dvfs_disp;
|
|
static struct pwrcal_vclk_dfs *asv_dvfs_cam;
|
|
|
|
static unsigned int cpucl0_subgrp_index = 256;
|
|
static unsigned int g3d_subgrp_index = 256;
|
|
static unsigned int mif_subgrp_index = 256;
|
|
static unsigned int int_subgrp_index = 256;
|
|
static unsigned int cam_subgrp_index = 256;
|
|
static unsigned int disp_subgrp_index = 256;
|
|
|
|
static unsigned int cpucl0_ssa1_table[8];
|
|
static unsigned int g3d_ssa1_table[8];
|
|
static unsigned int mif_ssa1_table[8];
|
|
static unsigned int int_ssa1_table[8];
|
|
static unsigned int cam_ssa1_table[8];
|
|
static unsigned int disp_ssa1_table[8];
|
|
|
|
static unsigned int cpucl0_ssa0_base;
|
|
static unsigned int g3d_ssa0_base;
|
|
static unsigned int mif_ssa0_base;
|
|
static unsigned int int_ssa0_base;
|
|
static unsigned int cam_ssa0_base;
|
|
static unsigned int disp_ssa0_base;
|
|
|
|
static unsigned int cpucl0_ssa0_offset;
|
|
static unsigned int g3d_ssa0_offset;
|
|
static unsigned int mif_ssa0_offset;
|
|
static unsigned int int_ssa0_offset;
|
|
static unsigned int cam_ssa0_offset;
|
|
static unsigned int disp_ssa0_offset;
|
|
|
|
static void asv_set_grp(unsigned int id, unsigned int asvgrp)
|
|
{
|
|
force_asv_group[id & 0x0000FFFF] = FORCE_ASV_MAGIC | asvgrp;
|
|
}
|
|
|
|
static void asv_set_tablever(unsigned int version)
|
|
{
|
|
asv_tbl_info.asv_table_ver = version;
|
|
|
|
return;
|
|
}
|
|
|
|
static void asv_set_ssa0(unsigned int id, unsigned int ssa0)
|
|
{
|
|
switch (id & 0x0000FFFF) {
|
|
case cal_asv_dvfs_cpucl0:
|
|
asv_tbl_info.cpucl0_ssa0 = ssa0;
|
|
break;
|
|
case cal_asv_dvfs_g3d:
|
|
asv_tbl_info.g3d_ssa0 = ssa0;
|
|
break;
|
|
case cal_asv_dvfs_mif:
|
|
asv_tbl_info.mif_ssa0 = ssa0;
|
|
break;
|
|
case cal_asv_dvfs_int:
|
|
asv_tbl_info.int_ssa0 = ssa0;
|
|
break;
|
|
case cal_asv_dvfs_cam:
|
|
asv_tbl_info.disp_ssa0 = ssa0;
|
|
break;
|
|
case cal_asv_dvfs_disp:
|
|
asv_tbl_info.disp_ssa0 = ssa0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
static void asv_set_ssa1(unsigned int id, unsigned int gnum, unsigned int ssa1)
|
|
{
|
|
switch (id & 0x0000FFFF) {
|
|
case cal_asv_dvfs_cpucl0:
|
|
if (gnum == 0)
|
|
asv_tbl_info.cpucl0_ssa10 = ssa1;
|
|
else
|
|
asv_tbl_info.cpucl0_ssa11 = ssa1;
|
|
break;
|
|
case cal_asv_dvfs_g3d:
|
|
if (gnum == 0)
|
|
asv_tbl_info.g3d_ssa10 = ssa1;
|
|
else
|
|
asv_tbl_info.g3d_ssa11 = ssa1;
|
|
break;
|
|
case cal_asv_dvfs_mif:
|
|
if (gnum == 0)
|
|
asv_tbl_info.mif_ssa10 = ssa1;
|
|
else
|
|
asv_tbl_info.mif_ssa11 = ssa1;
|
|
break;
|
|
case cal_asv_dvfs_int:
|
|
if (gnum == 0)
|
|
asv_tbl_info.int_ssa10 = ssa1;
|
|
else
|
|
asv_tbl_info.int_ssa11 = ssa1;
|
|
break;
|
|
case cal_asv_dvfs_cam:
|
|
if (gnum == 0)
|
|
asv_tbl_info.disp_ssa10 = ssa1;
|
|
else
|
|
asv_tbl_info.disp_ssa11 = ssa1;
|
|
break;
|
|
case cal_asv_dvfs_disp:
|
|
if (gnum == 0)
|
|
asv_tbl_info.disp_ssa10 = ssa1;
|
|
else
|
|
asv_tbl_info.disp_ssa11 = ssa1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
static int get_max_freq_lv(struct ect_voltage_domain *domain, unsigned int version)
|
|
{
|
|
int i;
|
|
int ret = -1;
|
|
|
|
for (i = 0; i < domain->num_of_level; i++) {
|
|
if (domain->table_list[version].level_en[i]) {
|
|
ret = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int get_min_freq_lv(struct ect_voltage_domain *domain, unsigned int version)
|
|
{
|
|
int i;
|
|
int ret = -1;
|
|
|
|
for (i = domain->num_of_level - 1; i >= 0; i--) {
|
|
if (domain->table_list[version].level_en[i]) {
|
|
ret = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void asv_set_freq_limit(void)
|
|
{
|
|
void *asv_block;
|
|
struct ect_voltage_domain *domain;
|
|
int lv;
|
|
|
|
asv_block = ect_get_block("ASV");
|
|
if (asv_block == NULL)
|
|
BUG();
|
|
|
|
if (!asv_tbl_info.fused_grp)
|
|
goto notfused;
|
|
|
|
domain = ect_asv_get_domain(asv_block, "dvfs_cpucl0");
|
|
if (!domain)
|
|
BUG();
|
|
|
|
if (asv_tbl_info.asv_table_ver >= domain->num_of_table) {
|
|
pr_err("!! CHECK !!\n");
|
|
pr_err("ASV Table version higher than ECT(Fused ver:%d)\n",
|
|
asv_tbl_info.asv_table_ver);
|
|
pr_err("!! CHECK !!\n");
|
|
asv_tbl_info.asv_table_ver = domain->num_of_table - 1;
|
|
}
|
|
|
|
lv = get_max_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_cpucl0->table->max_freq = domain->level_list[lv] * 1000;
|
|
lv = get_min_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_cpucl0->table->min_freq = domain->level_list[lv] * 1000;
|
|
|
|
domain = ect_asv_get_domain(asv_block, "dvfs_g3d");
|
|
if (!domain)
|
|
BUG();
|
|
lv = get_max_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_g3d->table->max_freq = domain->level_list[lv] * 1000;
|
|
lv = get_min_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_g3d->table->min_freq = domain->level_list[lv] * 1000;
|
|
|
|
domain = ect_asv_get_domain(asv_block, "dvfs_mif");
|
|
if (!domain)
|
|
BUG();
|
|
lv = get_max_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_mif->table->max_freq = domain->level_list[lv] * 1000;
|
|
lv = get_min_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_mif->table->min_freq = domain->level_list[lv] * 1000;
|
|
|
|
domain = ect_asv_get_domain(asv_block, "dvfs_int");
|
|
if (!domain)
|
|
BUG();
|
|
lv = get_max_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_int->table->max_freq = domain->level_list[lv] * 1000;
|
|
lv = get_min_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_int->table->min_freq = domain->level_list[lv] * 1000;
|
|
|
|
domain = ect_asv_get_domain(asv_block, "dvfs_disp");
|
|
if (!domain)
|
|
BUG();
|
|
lv = get_max_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_disp->table->max_freq = domain->level_list[lv] * 1000;
|
|
lv = get_min_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_disp->table->min_freq = domain->level_list[lv] * 1000;
|
|
|
|
domain = ect_asv_get_domain(asv_block, "dvfs_cam");
|
|
if (!domain)
|
|
BUG();
|
|
lv = get_max_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_cam->table->max_freq = domain->level_list[lv] * 1000;
|
|
lv = get_min_freq_lv(domain, asv_tbl_info.asv_table_ver);
|
|
if (lv >= 0)
|
|
asv_dvfs_cam->table->min_freq = domain->level_list[lv] * 1000;
|
|
|
|
return;
|
|
|
|
notfused:
|
|
|
|
#ifdef PWRCAL_TARGET_LINUX
|
|
#ifdef CONFIG_SOC_EXYNOS7570_DUAL
|
|
asv_dvfs_cpucl0->table->max_freq = 1014000;
|
|
asv_dvfs_g3d->table->max_freq = 560000;
|
|
asv_dvfs_mif->table->max_freq = 676000;
|
|
#else
|
|
asv_dvfs_cpucl0->table->max_freq = 1378000;
|
|
asv_dvfs_g3d->table->max_freq = 830000;
|
|
asv_dvfs_mif->table->max_freq = 830000;
|
|
#endif
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
static void asv_get_asvinfo(void)
|
|
{
|
|
#if !defined(CONFIG_BOARD_ZEBU)
|
|
int i;
|
|
unsigned int *pasv_table;
|
|
unsigned long tmp;
|
|
|
|
pasv_table = (unsigned int *)&asv_tbl_info;
|
|
for (i = 0; i < ASV_INFO_ADDR_CNT; i++) {
|
|
#ifdef PWRCAL_TARGET_LINUX
|
|
exynos_smc_readsfr((unsigned long)(ASV_INFO_ADDR_BASE + 0x4 * i), &tmp);
|
|
#else
|
|
#if (CONFIG_STARTUP_EL_MODE == STARTUP_EL3)
|
|
tmp = *((volatile unsigned int *)(unsigned long)(ASV_INFO_ADDR_BASE + 0x4 * i));
|
|
#else
|
|
smc_readsfr((unsigned long)(ASV_INFO_ADDR_BASE + 0x4 * i), &tmp);
|
|
#endif
|
|
#endif
|
|
*(pasv_table + i) = (unsigned int)tmp;
|
|
}
|
|
#endif
|
|
|
|
if (!asv_tbl_info.fused_grp) {
|
|
asv_tbl_info.cpucl0_asv_group = 0;
|
|
asv_tbl_info.cpucl0_modified_group = 0;
|
|
asv_tbl_info.cpucl0_ssa10 = 0;
|
|
asv_tbl_info.cpucl0_ssa11 = 0;
|
|
asv_tbl_info.cpucl0_ssa0 = 0;
|
|
|
|
asv_tbl_info.g3d_asv_group = 0;
|
|
asv_tbl_info.g3d_modified_group = 0;
|
|
asv_tbl_info.g3d_ssa10 = 0;
|
|
asv_tbl_info.g3d_ssa11 = 0;
|
|
asv_tbl_info.g3d_ssa0 = 0;
|
|
asv_tbl_info.mif_asv_group = 0;
|
|
asv_tbl_info.mif_modified_group = 0;
|
|
asv_tbl_info.mif_ssa10 = 0;
|
|
asv_tbl_info.mif_ssa11 = 0;
|
|
asv_tbl_info.mif_ssa0 = 0;
|
|
|
|
asv_tbl_info.int_asv_group = 0;
|
|
asv_tbl_info.int_modified_group = 0;
|
|
asv_tbl_info.int_ssa10 = 0;
|
|
asv_tbl_info.int_ssa11 = 0;
|
|
asv_tbl_info.int_ssa0 = 0;
|
|
asv_tbl_info.disp_asv_group = 0;
|
|
asv_tbl_info.disp_modified_group = 0;
|
|
asv_tbl_info.disp_ssa10 = 0;
|
|
asv_tbl_info.disp_ssa11 = 0;
|
|
asv_tbl_info.disp_ssa0 = 0;
|
|
|
|
asv_tbl_info.asv_table_ver = 0;
|
|
asv_tbl_info.fused_grp = 0;
|
|
asv_tbl_info.asb_pgm_version = 0;
|
|
asv_tbl_info.cp_asv_group = 0;
|
|
asv_tbl_info.cp_modified_group = 0;
|
|
asv_tbl_info.cp_ssa10 = 0;
|
|
asv_tbl_info.cp_ssa11 = 0;
|
|
asv_tbl_info.cp_ssa0 = 0;
|
|
asv_tbl_info.cpucl0_vthr = 0;
|
|
asv_tbl_info.cpucl0_delta = 0;
|
|
asv_tbl_info.g3d_vthr = 0;
|
|
asv_tbl_info.g3d_delta = 0;
|
|
asv_tbl_info.int_vthr = 0;
|
|
asv_tbl_info.int_delta = 0;
|
|
asv_tbl_info.mif_vthr = 0;
|
|
asv_tbl_info.mif_vthr = 0;
|
|
|
|
asv_tbl_info.cpu_cl_ema = 0;
|
|
asv_tbl_info.cpu_cl_emas = 0;
|
|
asv_tbl_info.cpu_cl_emaw = 0;
|
|
|
|
asv_tbl_info.g3d_ema = 0;
|
|
asv_tbl_info.g3d_emas = 0;
|
|
asv_tbl_info.g3d_emaw = 0;
|
|
|
|
asv_tbl_info.cp_ema = 0;
|
|
|
|
}
|
|
asv_set_freq_limit();
|
|
}
|
|
|
|
|
|
static int get_asv_group(enum dvfs_id domain, unsigned int lv)
|
|
{
|
|
int asv = 0;
|
|
int mod = 0;
|
|
|
|
switch (domain) {
|
|
case cal_asv_dvfs_cpucl0:
|
|
asv = asv_tbl_info.cpucl0_asv_group;
|
|
mod = asv_tbl_info.cpucl0_modified_group;
|
|
break;
|
|
case cal_asv_dvfs_g3d:
|
|
asv = asv_tbl_info.g3d_asv_group;
|
|
mod = asv_tbl_info.g3d_modified_group;
|
|
break;
|
|
case cal_asv_dvfs_mif:
|
|
asv = asv_tbl_info.mif_asv_group;
|
|
mod = asv_tbl_info.mif_modified_group;
|
|
break;
|
|
case cal_asv_dvfs_int:
|
|
asv = asv_tbl_info.int_asv_group;
|
|
mod = asv_tbl_info.int_modified_group;
|
|
break;
|
|
case cal_asv_dvfs_cam:
|
|
asv = asv_tbl_info.disp_asv_group;
|
|
mod = asv_tbl_info.disp_modified_group;
|
|
break;
|
|
case cal_asv_dvfs_disp:
|
|
asv = asv_tbl_info.disp_asv_group;
|
|
mod = asv_tbl_info.disp_modified_group;
|
|
break;
|
|
default:
|
|
BUG(); /* Never reach */
|
|
break;
|
|
}
|
|
|
|
if ((force_asv_group[domain & 0x0000FFFF] & 0xFFFF0000) != FORCE_ASV_MAGIC) {
|
|
if (mod)
|
|
asv += mod;
|
|
} else {
|
|
asv = force_asv_group[domain & 0x0000FFFF] & 0x0000FFFF;
|
|
}
|
|
|
|
if (asv < 0 || asv >= MAX_ASV_GROUP)
|
|
BUG(); /* Never reach */
|
|
|
|
return asv;
|
|
}
|
|
|
|
static unsigned int get_asv_voltage(enum dvfs_id domain, unsigned int lv)
|
|
{
|
|
int asv;
|
|
unsigned int ssa10, ssa11;
|
|
unsigned int ssa0;
|
|
unsigned int subgrp_index;
|
|
const unsigned int *table;
|
|
unsigned int volt;
|
|
unsigned int *ssa1_table = NULL;
|
|
unsigned int ssa0_base = 0, ssa0_offset = 0;
|
|
|
|
switch (domain) {
|
|
case cal_asv_dvfs_cpucl0:
|
|
asv = get_asv_group(cal_asv_dvfs_cpucl0, lv);
|
|
ssa10 = asv_tbl_info.cpucl0_ssa10;
|
|
ssa11 = asv_tbl_info.cpucl0_ssa11;
|
|
ssa0 = asv_tbl_info.cpucl0_ssa0;
|
|
subgrp_index = cpucl0_subgrp_index;
|
|
ssa0_base = cpucl0_ssa0_base;
|
|
ssa0_offset = cpucl0_ssa0_offset;
|
|
ssa1_table = cpucl0_ssa1_table;
|
|
table = pwrcal_cpucl0_asv_table[asv_tbl_info.asv_table_ver].table[lv].voltage;
|
|
break;
|
|
case cal_asv_dvfs_g3d:
|
|
asv = get_asv_group(cal_asv_dvfs_g3d, lv);
|
|
ssa10 = asv_tbl_info.g3d_ssa10;
|
|
ssa11 = asv_tbl_info.g3d_ssa11;
|
|
ssa0 = asv_tbl_info.g3d_ssa0;
|
|
subgrp_index = g3d_subgrp_index;
|
|
ssa0_base = g3d_ssa0_base;
|
|
ssa0_offset = g3d_ssa0_offset;
|
|
ssa1_table = g3d_ssa1_table;
|
|
table = pwrcal_g3d_asv_table[asv_tbl_info.asv_table_ver].table[lv].voltage;
|
|
break;
|
|
case cal_asv_dvfs_mif:
|
|
asv = get_asv_group(cal_asv_dvfs_mif, lv);
|
|
ssa10 = asv_tbl_info.mif_ssa10;
|
|
ssa11 = asv_tbl_info.mif_ssa11;
|
|
ssa0 = asv_tbl_info.mif_ssa0;
|
|
subgrp_index = mif_subgrp_index;
|
|
ssa0_base = mif_ssa0_base;
|
|
ssa0_offset = mif_ssa0_offset;
|
|
ssa1_table = mif_ssa1_table;
|
|
table = pwrcal_mif_asv_table[asv_tbl_info.asv_table_ver].table[lv].voltage;
|
|
break;
|
|
case cal_asv_dvfs_int:
|
|
asv = get_asv_group(cal_asv_dvfs_int, lv);
|
|
ssa10 = asv_tbl_info.int_ssa10;
|
|
ssa11 = asv_tbl_info.int_ssa11;
|
|
ssa0 = asv_tbl_info.int_ssa0;
|
|
subgrp_index = int_subgrp_index;
|
|
ssa0_base = int_ssa0_base;
|
|
ssa0_offset = int_ssa0_offset;
|
|
ssa1_table = int_ssa1_table;
|
|
table = pwrcal_int_asv_table[asv_tbl_info.asv_table_ver].table[lv].voltage;
|
|
break;
|
|
case cal_asv_dvfs_cam:
|
|
asv = get_asv_group(cal_asv_dvfs_cam, lv);
|
|
ssa10 = asv_tbl_info.disp_ssa10;
|
|
ssa11 = asv_tbl_info.disp_ssa11;
|
|
ssa0 = asv_tbl_info.disp_ssa0;
|
|
subgrp_index = cam_subgrp_index;
|
|
ssa0_base = cam_ssa0_base;
|
|
ssa0_offset = cam_ssa0_offset;
|
|
ssa1_table = cam_ssa1_table;
|
|
table = pwrcal_cam_asv_table[asv_tbl_info.asv_table_ver].table[lv].voltage;
|
|
break;
|
|
case cal_asv_dvfs_disp:
|
|
asv = get_asv_group(cal_asv_dvfs_disp, lv);
|
|
ssa10 = asv_tbl_info.disp_ssa10;
|
|
ssa11 = asv_tbl_info.disp_ssa11;
|
|
ssa0 = asv_tbl_info.disp_ssa0;
|
|
subgrp_index = disp_subgrp_index;
|
|
ssa0_base = disp_ssa0_base;
|
|
ssa0_offset = disp_ssa0_offset;
|
|
ssa1_table = disp_ssa1_table;
|
|
table = pwrcal_disp_asv_table[asv_tbl_info.asv_table_ver].table[lv].voltage;
|
|
break;
|
|
default:
|
|
BUG(); /* Never reach */
|
|
break;
|
|
}
|
|
|
|
volt = table[asv];
|
|
|
|
if (ssa1_table) {
|
|
if (lv < subgrp_index)
|
|
volt += ssa1_table[ssa10];
|
|
else
|
|
volt += ssa1_table[ssa11 + 4];
|
|
}
|
|
if (ssa0_base)
|
|
if (volt < ssa0_base + ssa0 * ssa0_offset)
|
|
volt = ssa0_base + ssa0 * ssa0_offset;
|
|
|
|
return volt;
|
|
|
|
}
|
|
|
|
static int dvfscpucl0_get_asv_table(unsigned int *table)
|
|
{
|
|
int lv, max_lv;
|
|
|
|
max_lv = asv_dvfs_cpucl0->table->num_of_lv;
|
|
|
|
for (lv = 0; lv < max_lv; lv++)
|
|
table[lv] = get_asv_voltage(cal_asv_dvfs_cpucl0, lv);
|
|
|
|
return max_lv;
|
|
}
|
|
|
|
static int dfscpu_set_ema(unsigned int volt)
|
|
{
|
|
unsigned int cpu_ema, ema_temp;
|
|
|
|
if (volt >= 950000) {
|
|
ema_temp = (asv_tbl_info.cpu_cl_ema << 3) | (asv_tbl_info.cpu_cl_emaw << 1) | asv_tbl_info.cpu_cl_emas;
|
|
cpu_ema = (ema_temp << 12) | (ema_temp << 6) | ema_temp;
|
|
if (cpu_ema == 0)
|
|
cpu_ema = 0x12492;
|
|
pwrcal_writel(CPUCL0_EMA_CON, cpu_ema);
|
|
} else {
|
|
pwrcal_writel(CPUCL0_EMA_CON, 0x12492);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dvfsg3d_get_asv_table(unsigned int *table)
|
|
{
|
|
int lv, max_lv;
|
|
|
|
max_lv = asv_dvfs_g3d->table->num_of_lv;
|
|
|
|
for (lv = 0; lv < max_lv; lv++)
|
|
table[lv] = get_asv_voltage(cal_asv_dvfs_g3d, lv);
|
|
|
|
return max_lv;
|
|
}
|
|
|
|
static int dfsg3d_set_ema(unsigned int volt)
|
|
{
|
|
unsigned int g3d_ema;
|
|
|
|
if (asv_dvfs_g3d->vclk.ref_count == 0)
|
|
return 0;
|
|
|
|
if (volt >= 750000) {
|
|
g3d_ema = (asv_tbl_info.g3d_emas << 8) | (asv_tbl_info.g3d_emaw << 4) | asv_tbl_info.g3d_ema;
|
|
if (g3d_ema != 0) {
|
|
pwrcal_writel(G3D_EMA_RA1_HS_CON, g3d_ema);
|
|
pwrcal_writel(G3D_EMA_RF1_HS_CON, g3d_ema);
|
|
} else {
|
|
pwrcal_writel(G3D_EMA_RA1_HS_CON, 0x12);
|
|
pwrcal_writel(G3D_EMA_RF1_HS_CON, 0x12);
|
|
}
|
|
} else {
|
|
pwrcal_writel(G3D_EMA_RA1_HS_CON, 0x12);
|
|
pwrcal_writel(G3D_EMA_RF1_HS_CON, 0x12);
|
|
}
|
|
/*
|
|
if (volt >= 600000)
|
|
pwrcal_write(G3D_EMA_UHD_CON, 0x0);
|
|
else
|
|
pwrcal_write(G3D_EMA_UHD_CON, 0x4);
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
static int dvfsmif_get_asv_table(unsigned int *table)
|
|
{
|
|
int lv, max_lv;
|
|
|
|
max_lv = asv_dvfs_mif->table->num_of_lv;
|
|
|
|
for (lv = 0; lv < max_lv; lv++)
|
|
table[lv] = get_asv_voltage(cal_asv_dvfs_mif, lv);
|
|
|
|
return max_lv;
|
|
}
|
|
|
|
static int dvfsint_get_asv_table(unsigned int *table)
|
|
{
|
|
int lv, max_lv;
|
|
|
|
max_lv = asv_dvfs_int->table->num_of_lv;
|
|
|
|
for (lv = 0; lv < max_lv; lv++)
|
|
table[lv] = get_asv_voltage(cal_asv_dvfs_int, lv);
|
|
|
|
return max_lv;
|
|
}
|
|
|
|
static int dvfsdisp_get_asv_table(unsigned int *table)
|
|
{
|
|
int lv, max_lv;
|
|
|
|
max_lv = asv_dvfs_disp->table->num_of_lv;
|
|
|
|
for (lv = 0; lv < max_lv; lv++)
|
|
table[lv] = get_asv_voltage(cal_asv_dvfs_disp, lv);
|
|
|
|
return max_lv;
|
|
}
|
|
|
|
static int dvfscam_get_asv_table(unsigned int *table)
|
|
{
|
|
int lv, max_lv;
|
|
|
|
max_lv = asv_dvfs_cam->table->num_of_lv;
|
|
|
|
for (lv = 0; lv < max_lv; lv++)
|
|
table[lv] = get_asv_voltage(cal_asv_dvfs_cam, lv);
|
|
|
|
return max_lv;
|
|
}
|
|
|
|
static int asv_rcc_set_table(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void asv_voltage_init_table(struct asv_table_list **asv_table, struct pwrcal_vclk_dfs *dfs)
|
|
{
|
|
int i, j, k;
|
|
void *asv_block, *margin_block;
|
|
struct ect_voltage_domain *domain;
|
|
struct ect_voltage_table *table;
|
|
struct asv_table_entry *asv_entry;
|
|
struct ect_margin_domain *margin_domain = NULL;
|
|
|
|
asv_block = ect_get_block("ASV");
|
|
if (asv_block == NULL)
|
|
return;
|
|
|
|
margin_block = ect_get_block("MARGIN");
|
|
|
|
domain = ect_asv_get_domain(asv_block, dfs->vclk.name);
|
|
if (domain == NULL)
|
|
return;
|
|
|
|
if (margin_block)
|
|
margin_domain = ect_margin_get_domain(margin_block, dfs->vclk.name);
|
|
|
|
*asv_table = kzalloc(sizeof(struct asv_table_list) * domain->num_of_table, GFP_KERNEL);
|
|
if (*asv_table == NULL)
|
|
return;
|
|
|
|
for (i = 0; i < domain->num_of_table; ++i) {
|
|
table = &domain->table_list[i];
|
|
|
|
(*asv_table)[i].table_size = domain->num_of_table;
|
|
(*asv_table)[i].table = kzalloc(sizeof(struct asv_table_entry) * domain->num_of_level, GFP_KERNEL);
|
|
if ((*asv_table)[i].table == NULL)
|
|
return;
|
|
|
|
for (j = 0; j < domain->num_of_level; ++j) {
|
|
asv_entry = &(*asv_table)[i].table[j];
|
|
|
|
asv_entry->index = domain->level_list[j];
|
|
asv_entry->voltage = kzalloc(sizeof(unsigned int) * domain->num_of_group, GFP_KERNEL);
|
|
|
|
for (k = 0; k < domain->num_of_group; ++k) {
|
|
if (table->voltages != NULL)
|
|
asv_entry->voltage[k] = table->voltages[j * domain->num_of_group + k];
|
|
else if (table->voltages_step != NULL)
|
|
asv_entry->voltage[k] = table->voltages_step[j * domain->num_of_group + k] * table->volt_step;
|
|
|
|
if (margin_domain != NULL) {
|
|
if (margin_domain->offset != NULL)
|
|
asv_entry->voltage[k] += margin_domain->offset[j * margin_domain->num_of_group + k];
|
|
else
|
|
asv_entry->voltage[k] += margin_domain->offset_compact[j * margin_domain->num_of_group + k] * margin_domain->volt_step;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void asv_rcc_init_table(struct asv_table_list **rcc_table, struct pwrcal_vclk_dfs *dfs)
|
|
|
|
{
|
|
int i, j, k;
|
|
void *rcc_block;
|
|
struct ect_rcc_domain *domain;
|
|
struct ect_rcc_table *table;
|
|
struct asv_table_entry *rcc_entry;
|
|
|
|
rcc_block = ect_get_block("RCC");
|
|
if (rcc_block == NULL)
|
|
return;
|
|
|
|
domain = ect_rcc_get_domain(rcc_block, dfs->vclk.name);
|
|
if (domain == NULL)
|
|
return;
|
|
|
|
*rcc_table = kzalloc(sizeof(struct asv_table_list) * domain->num_of_table, GFP_KERNEL);
|
|
if (*rcc_table == NULL)
|
|
return;
|
|
|
|
for (i = 0; i < domain->num_of_table; ++i) {
|
|
table = &domain->table_list[i];
|
|
|
|
(*rcc_table)[i].table_size = domain->num_of_table;
|
|
(*rcc_table)[i].table = kzalloc(sizeof(struct asv_table_entry) * domain->num_of_level, GFP_KERNEL);
|
|
if ((*rcc_table)[i].table == NULL)
|
|
return;
|
|
|
|
for (j = 0; j < domain->num_of_level; ++j) {
|
|
rcc_entry = &(*rcc_table)[i].table[j];
|
|
|
|
rcc_entry->index = domain->level_list[j];
|
|
rcc_entry->voltage = kzalloc(sizeof(unsigned int) * domain->num_of_group, GFP_KERNEL);
|
|
|
|
for (k = 0; k < domain->num_of_group; ++k) {
|
|
if (table->rcc != NULL)
|
|
rcc_entry->voltage[k] = table->rcc[j * domain->num_of_group + k];
|
|
else
|
|
rcc_entry->voltage[k] = table->rcc_compact[j * domain->num_of_group + k];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void asv_voltage_table_init(void)
|
|
{
|
|
asv_voltage_init_table(&pwrcal_cpucl0_asv_table, asv_dvfs_cpucl0);
|
|
asv_voltage_init_table(&pwrcal_g3d_asv_table, asv_dvfs_g3d);
|
|
asv_voltage_init_table(&pwrcal_mif_asv_table, asv_dvfs_mif);
|
|
asv_voltage_init_table(&pwrcal_int_asv_table, asv_dvfs_int);
|
|
asv_voltage_init_table(&pwrcal_cam_asv_table, asv_dvfs_cam);
|
|
asv_voltage_init_table(&pwrcal_disp_asv_table, asv_dvfs_disp);
|
|
}
|
|
|
|
static void asv_rcc_table_init(void)
|
|
{
|
|
asv_rcc_init_table(&pwrcal_cpucl0_rcc_table, asv_dvfs_cpucl0);
|
|
asv_rcc_init_table(&pwrcal_g3d_rcc_table, asv_dvfs_g3d);
|
|
asv_rcc_init_table(&pwrcal_mif_rcc_table, asv_dvfs_mif);
|
|
}
|
|
|
|
static void asv_ssa_init(void)
|
|
{
|
|
int i;
|
|
void *gen_block;
|
|
struct ect_gen_param_table *param;
|
|
unsigned int asv_table_version = asv_tbl_info.asv_table_ver;
|
|
|
|
gen_block = ect_get_block("GEN");
|
|
if (gen_block == NULL)
|
|
return;
|
|
|
|
param = ect_gen_param_get_table(gen_block, "SSA_CPUCL0");
|
|
if (param) {
|
|
if (asv_table_version > (unsigned int)(param->num_of_row - 1)) {
|
|
pr_err("!! CHECK !!\n");
|
|
pr_err("ASV Table version higher than SSA section of ECT(Fused ver:%d)\n",
|
|
asv_tbl_info.asv_table_ver);
|
|
pr_err("!! CHECK !!\n");
|
|
asv_table_version = (unsigned int)(param->num_of_row - 1);
|
|
}
|
|
|
|
cpucl0_subgrp_index = param->parameter[asv_table_version * param->num_of_col + 1];
|
|
cpucl0_ssa0_base = param->parameter[asv_table_version * param->num_of_col + 2];
|
|
cpucl0_ssa0_offset = param->parameter[asv_table_version * param->num_of_col + 3];
|
|
for (i = 0; i < 8; i++)
|
|
cpucl0_ssa1_table[i] = param->parameter[asv_table_version * param->num_of_col + 4 + i];
|
|
}
|
|
param = ect_gen_param_get_table(gen_block, "SSA_G3D");
|
|
if (param) {
|
|
g3d_subgrp_index = param->parameter[asv_table_version * param->num_of_col + 1];
|
|
g3d_ssa0_base = param->parameter[asv_table_version * param->num_of_col + 2];
|
|
g3d_ssa0_offset = param->parameter[asv_table_version * param->num_of_col + 3];
|
|
for (i = 0; i < 8; i++)
|
|
g3d_ssa1_table[i] = param->parameter[asv_table_version * param->num_of_col + 4 + i];
|
|
}
|
|
param = ect_gen_param_get_table(gen_block, "SSA_MIF");
|
|
if (param) {
|
|
mif_subgrp_index = param->parameter[asv_table_version * param->num_of_col + 1];
|
|
mif_ssa0_base = param->parameter[asv_table_version * param->num_of_col + 2];
|
|
mif_ssa0_offset = param->parameter[asv_table_version * param->num_of_col + 3];
|
|
for (i = 0; i < 8; i++)
|
|
mif_ssa1_table[i] = param->parameter[asv_table_version * param->num_of_col + 4 + i];
|
|
}
|
|
param = ect_gen_param_get_table(gen_block, "SSA_INT");
|
|
if (param) {
|
|
int_subgrp_index = param->parameter[asv_table_version * param->num_of_col + 1];
|
|
int_ssa0_base = param->parameter[asv_table_version * param->num_of_col + 2];
|
|
int_ssa0_offset = param->parameter[asv_table_version * param->num_of_col + 3];
|
|
for (i = 0; i < 8; i++)
|
|
int_ssa1_table[i] = param->parameter[asv_table_version * param->num_of_col + 4 + i];
|
|
}
|
|
param = ect_gen_param_get_table(gen_block, "SSA_CAM");
|
|
if (param) {
|
|
cam_subgrp_index = param->parameter[asv_table_version * param->num_of_col + 1];
|
|
cam_ssa0_base = param->parameter[asv_table_version * param->num_of_col + 2];
|
|
cam_ssa0_offset = param->parameter[asv_table_version * param->num_of_col + 3];
|
|
for (i = 0; i < 8; i++)
|
|
cam_ssa1_table[i] = param->parameter[asv_table_version * param->num_of_col + 4 + i];
|
|
}
|
|
param = ect_gen_param_get_table(gen_block, "SSA_DISP");
|
|
if (param) {
|
|
disp_subgrp_index = param->parameter[asv_table_version * param->num_of_col + 1];
|
|
disp_ssa0_base = param->parameter[asv_table_version * param->num_of_col + 2];
|
|
disp_ssa0_offset = param->parameter[asv_table_version * param->num_of_col + 3];
|
|
for (i = 0; i < 8; i++)
|
|
disp_ssa1_table[i] = param->parameter[asv_table_version * param->num_of_col + 4 + i];
|
|
}
|
|
}
|
|
|
|
int cal_asv_init(void)
|
|
{
|
|
struct vclk *vclk;
|
|
|
|
vclk = cal_get_vclk(dvfs_cpucl0);
|
|
asv_dvfs_cpucl0 = to_dfs(vclk);
|
|
asv_dvfs_cpucl0->dfsops->get_asv_table = dvfscpucl0_get_asv_table;
|
|
asv_dvfs_cpucl0->dfsops->set_ema = dfscpu_set_ema;
|
|
|
|
vclk = cal_get_vclk(dvfs_g3d);
|
|
asv_dvfs_g3d = to_dfs(vclk);
|
|
asv_dvfs_g3d->dfsops->get_asv_table = dvfsg3d_get_asv_table;
|
|
asv_dvfs_g3d->dfsops->set_ema = dfsg3d_set_ema;
|
|
|
|
vclk = cal_get_vclk(dvfs_mif);
|
|
asv_dvfs_mif = to_dfs(vclk);
|
|
asv_dvfs_mif->dfsops->get_asv_table = dvfsmif_get_asv_table;
|
|
|
|
vclk = cal_get_vclk(dvfs_int);
|
|
asv_dvfs_int = to_dfs(vclk);
|
|
asv_dvfs_int->dfsops->get_asv_table = dvfsint_get_asv_table;
|
|
|
|
vclk = cal_get_vclk(dvfs_disp);
|
|
asv_dvfs_disp = to_dfs(vclk);
|
|
asv_dvfs_disp->dfsops->get_asv_table = dvfsdisp_get_asv_table;
|
|
|
|
vclk = cal_get_vclk(dvfs_cam);
|
|
asv_dvfs_cam = to_dfs(vclk);
|
|
asv_dvfs_cam->dfsops->get_asv_table = dvfscam_get_asv_table;
|
|
|
|
pwrcal_cpucl0_asv_table = NULL;
|
|
pwrcal_g3d_asv_table = NULL;
|
|
pwrcal_mif_asv_table = NULL;
|
|
pwrcal_int_asv_table = NULL;
|
|
pwrcal_disp_asv_table = NULL;
|
|
pwrcal_cam_asv_table = NULL;
|
|
|
|
pwrcal_cpucl0_rcc_table = NULL;
|
|
pwrcal_g3d_rcc_table = NULL;
|
|
pwrcal_mif_rcc_table = NULL;
|
|
|
|
asv_get_asvinfo();
|
|
asv_voltage_table_init();
|
|
asv_rcc_table_init();
|
|
asv_ssa_init();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void asv_print_info(void)
|
|
{
|
|
pr_info("asv_table_ver : %d\n", asv_tbl_info.asv_table_ver);
|
|
pr_info("fused_grp : %d\n", asv_tbl_info.fused_grp);
|
|
|
|
pr_info("cpucl0_asv_group : %d\n", asv_tbl_info.cpucl0_asv_group);
|
|
|
|
pr_info("g3d_asv_group : %d\n", asv_tbl_info.g3d_asv_group);
|
|
pr_info("mif_asv_group : %d\n", asv_tbl_info.mif_asv_group);
|
|
|
|
pr_info("int_asv_group : %d\n", asv_tbl_info.int_asv_group);
|
|
pr_info("disp_asv_group : %d\n", asv_tbl_info.disp_asv_group);
|
|
}
|
|
|
|
static void rcc_print_info(void)
|
|
{
|
|
|
|
}
|
|
|
|
static int asv_get_grp(unsigned int id, unsigned int lv)
|
|
{
|
|
return get_asv_group((enum dvfs_id)id, lv);
|
|
}
|
|
|
|
static int asv_get_tablever(void)
|
|
{
|
|
return (int)(asv_tbl_info.asv_table_ver);
|
|
}
|
|
|
|
static int asv_get_ids_info(unsigned int domain)
|
|
{
|
|
#ifdef PWRCAL_TARGET_LINUX
|
|
int ret = 0;
|
|
unsigned long val = 0;
|
|
|
|
if (domain >= 1) {
|
|
pr_err("[GET_IDS_INFO] Domain is invalid (domain : %d)\n", domain);
|
|
return -1;
|
|
}
|
|
|
|
ret = exynos_smc_readsfr(0x100DA000, &val);
|
|
|
|
if(ret) {
|
|
pr_err("[GET_IDS_NFO] SMC error (0x%X)\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
if (domain == 0) /* CPU */
|
|
ret = (int)(val & 0xFF);
|
|
|
|
return ret;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
#if defined(CONFIG_SEC_FACTORY)
|
|
enum ids_info
|
|
{
|
|
table_ver,
|
|
big_asv,
|
|
g3d_asv,
|
|
cpu_ids,
|
|
};
|
|
|
|
int asv_ids_information(enum ids_info id)
|
|
{
|
|
int res = 0;
|
|
|
|
switch (id) {
|
|
case table_ver:
|
|
res = asv_tbl_info.asv_table_ver;
|
|
break;
|
|
case big_asv:
|
|
res = asv_tbl_info.cpucl0_asv_group;
|
|
break;
|
|
case g3d_asv:
|
|
res = asv_tbl_info.g3d_asv_group;
|
|
break;
|
|
case cpu_ids:
|
|
res = asv_get_ids_info(0);
|
|
break;
|
|
default:
|
|
break;
|
|
};
|
|
|
|
return res;
|
|
}
|
|
#endif /* CONFIG_SEC_FACTORY */
|
|
|
|
struct cal_asv_ops cal_asv_ops = {
|
|
.print_asv_info = asv_print_info,
|
|
.print_rcc_info = rcc_print_info,
|
|
.asv_init = cal_asv_init,
|
|
.set_grp = asv_set_grp,
|
|
.get_grp = asv_get_grp,
|
|
.set_tablever = asv_set_tablever,
|
|
.get_tablever = asv_get_tablever,
|
|
.set_rcc_table = asv_rcc_set_table,
|
|
.get_ids_info = asv_get_ids_info,
|
|
.set_ssa0 = asv_set_ssa0,
|
|
.set_ssa1 = asv_set_ssa1,
|
|
};
|