#ifndef __ASV_EXYNOS9810_H__ #define __ASV_EXYNOS9810_H__ #include #include #include #include #define ASV_TABLE_BASE (0x10009000) #define ID_TABLE_BASE (0x10000000) #define unsign2sign8bit(a) (((a) >= 128) ? ((a) - 256) : (a)) static struct asv_power_model { unsigned power_model_0:8; unsigned power_model_1:8; unsigned power_model_2:8; unsigned mcd_ver:8; unsigned power_model_3:8; unsigned reserved_0:8; unsigned reserved_1:8; unsigned mht_ver:8; } power_model; static struct asv_modify_power_model { unsigned power_model_0:8; unsigned power_model_1:8; unsigned power_model_2:8; unsigned mcd_ver:8; unsigned power_model_3:8; unsigned reserved_0:8; unsigned reserved_1:8; unsigned mht_ver:8; } modify_power_model; static struct dentry *rootdir; struct asv_tbl_info { unsigned bigcpu_asv_group:4; unsigned midcpu_asv_group:4; unsigned littlecpu_asv_group:4; unsigned g3d_asv_group:4; unsigned mif_asv_group:4; unsigned int_h_asv_group:4; unsigned cam_h_asv_group:4; unsigned npu_h_asv_group:4; unsigned cp_h_asv_group:4; unsigned modem_h_asv_group:4; unsigned dsu_asv_group:4; unsigned sci_asv_group:4; unsigned sci_modify_group:4; unsigned dsu_modify_group:4; unsigned modem_h_modify_group:4; unsigned cp_h_modify_group:4; unsigned bigcpu_modify_group:4; unsigned midcpu_modify_group:4; unsigned littlecpu_modify_group:4; unsigned g3d_modify_group:4; unsigned mif_modify_group:4; unsigned int_h_modify_group:4; unsigned cam_h_modify_group:4; unsigned npu_h_modify_group:4; unsigned asv_table_version:7; unsigned asv_method:1; unsigned asb_version:7; unsigned vtyp_modify_enable:1; unsigned asvg_version:4; unsigned asb_pgm_reserved:12; }; struct id_tbl_info { unsigned int reserved_0; unsigned int chip_id_2; unsigned chip_id_1:12; unsigned reserved_2_1:4; unsigned char ids_bigcpu:8; unsigned char ids_g3d:8; unsigned char ids_others:8; /* int,cam */ unsigned asb_version:8; unsigned char ids_midcpu:8; unsigned char ids_litcpu:8; unsigned char ids_mif:8; unsigned char ids_npu:8; unsigned short sub_rev:4; unsigned short main_rev:4; unsigned reserved_3:8; unsigned reserved_4_1:8; unsigned reserved_4_2:8; unsigned reserved_4_3:8; unsigned char ids_cp:8; unsigned int reserved_6_1; unsigned int reserved_6_2; unsigned int reserved_6_3; unsigned int reserved_6_4; unsigned int reserved_6_5; unsigned int reserved_6_6; unsigned int reserved_6_7; unsigned int reserved_6_8; unsigned int reserved_6_9; unsigned int_l_asv_group:4; unsigned cam_l_asv_group:4; unsigned npu_l_asv_group:4; unsigned cp_l_asv_group:4; unsigned modem_l_asv_group:4; //ASV G, so not used unsigned reserved_7:12; unsigned int_l_modify_group:4; unsigned cam_l_modify_group:4; unsigned npu_l_modify_group:4; unsigned cp_l_modify_group:4; unsigned modem_l_modify_group:4; //ASV G, so not used }; #define ASV_INFO_ADDR_CNT (sizeof(struct asv_tbl_info) / 4) #define ID_INFO_ADDR_CNT (sizeof(struct id_tbl_info) / 4) static struct asv_tbl_info asv_tbl; static struct id_tbl_info id_tbl; int asv_get_grp(unsigned int id) { int grp = -1; switch (id) { case MIF: grp = asv_tbl.mif_asv_group + asv_tbl.mif_modify_group; break; case INT: case INTCAM: grp = asv_tbl.int_h_asv_group + asv_tbl.int_h_modify_group; break; case CPUCL0: grp = asv_tbl.littlecpu_asv_group + asv_tbl.littlecpu_modify_group; break; case DSU: grp = asv_tbl.dsu_asv_group + asv_tbl.dsu_modify_group; break; case CPUCL1: grp = asv_tbl.midcpu_asv_group + asv_tbl.midcpu_modify_group; break; case CPUCL2: grp = asv_tbl.bigcpu_asv_group + asv_tbl.bigcpu_modify_group; break; case G3D: grp = asv_tbl.g3d_asv_group + asv_tbl.g3d_modify_group; break; case CAM: case DISP: grp = asv_tbl.cam_h_asv_group + asv_tbl.cam_h_modify_group; break; case NPU: case AUD: grp = asv_tbl.npu_h_asv_group + asv_tbl.npu_h_modify_group; break; case CP: grp = asv_tbl.cp_h_asv_group + asv_tbl.cp_h_modify_group; break; case INTSCI: grp = asv_tbl.sci_asv_group + asv_tbl.sci_modify_group; break; default: pr_info("Un-support asv grp %d\n", id); } return grp; } int asv_get_ids_info(unsigned int id) { int ids = 0; switch (id) { case G3D: ids = id_tbl.ids_g3d; break; case CPUCL2: ids = id_tbl.ids_bigcpu; break; case CPUCL1: ids = id_tbl.ids_midcpu; break; case CPUCL0: ids = id_tbl.ids_litcpu; break; case MIF: ids = id_tbl.ids_mif; break; case CP: ids = id_tbl.ids_cp; break; case INT: case INTCAM: case CAM: case NPU: case DISP: case AUD: ids = id_tbl.ids_others; break; default: pr_info("Un-support ids info %d\n", id); } return ids; } int asv_get_table_ver(void) { return asv_tbl.asv_table_version; } void id_get_rev(unsigned int *main_rev, unsigned int *sub_rev) { *main_rev = id_tbl.main_rev; *sub_rev = id_tbl.sub_rev; } int id_get_product_line(void) { return id_tbl.chip_id_1 >> 10; } EXPORT_SYMBOL(id_get_product_line); int id_get_asb_ver(void) { return id_tbl.asb_version; } EXPORT_SYMBOL(id_get_asb_ver); #if IS_ENABLED(CONFIG_SHOW_ASV) int print_asv_table(char *buf) { ssize_t size = 0; size += sprintf(buf + size, "chipid : 0x%03x%08x\n", id_tbl.chip_id_1, id_tbl.chip_id_2); size += sprintf(buf + size, "main revision : %d\n", id_tbl.main_rev); size += sprintf(buf + size, "sub revision : %d\n", id_tbl.sub_rev); size += sprintf(buf + size, "\n"); size += sprintf(buf + size, " asv_table_version : %d\n", asv_tbl.asv_table_version); size += sprintf(buf + size, "\n"); size += sprintf(buf + size, " little cpu grp : %d, ids : %d\n", asv_tbl.littlecpu_asv_group + asv_tbl.littlecpu_modify_group, id_tbl.ids_litcpu); size += sprintf(buf + size, " mid cpu grp : %d, ids : %d\n", asv_tbl.midcpu_asv_group + asv_tbl.midcpu_modify_group, id_tbl.ids_midcpu); size += sprintf(buf + size, " big cpu grp : %d, ids : %d\n", asv_tbl.bigcpu_asv_group + asv_tbl.bigcpu_modify_group, id_tbl.ids_bigcpu); size += sprintf(buf + size, " dsu grp : %d\n", asv_tbl.dsu_asv_group + asv_tbl.dsu_modify_group); size += sprintf(buf + size, " mif grp : %d, ids : %d\n", asv_tbl.mif_asv_group + asv_tbl.mif_modify_group, id_tbl.ids_mif); size += sprintf(buf + size, " sci grp : %d\n", asv_tbl.sci_asv_group + asv_tbl.sci_modify_group); size += sprintf(buf + size, " g3d grp : %d, ids : %d\n", asv_tbl.g3d_asv_group + asv_tbl.g3d_modify_group, id_tbl.ids_g3d); size += sprintf(buf + size, "\n"); size += sprintf(buf + size, " int H grp : %d, ids : %d\n", asv_tbl.int_h_asv_group + asv_tbl.int_h_modify_group, id_tbl.ids_others); size += sprintf(buf + size, " cam H grp : %d, ids : %d\n", asv_tbl.cam_h_asv_group + asv_tbl.cam_h_modify_group, id_tbl.ids_others); size += sprintf(buf + size, " npu H grp : %d, ids : %d\n", asv_tbl.npu_h_asv_group + asv_tbl.npu_h_modify_group, id_tbl.ids_npu); size += sprintf(buf + size, " cp H grp : %d, ids : %d\n", asv_tbl.cp_h_asv_group + asv_tbl.cp_h_modify_group, id_tbl.ids_cp); size += sprintf(buf + size, " modem grp : %d\n", asv_tbl.modem_h_asv_group + asv_tbl.modem_h_modify_group); size += sprintf(buf + size, "\n"); size += sprintf(buf + size, " asb_version : %d\n", id_tbl.asb_version); size += sprintf(buf + size, "\n"); size += sprintf(buf + size, " power_model_0 : %d\n", power_model.power_model_0 + unsign2sign8bit(modify_power_model.power_model_0)); size += sprintf(buf + size, " power_model_1 : %d\n", power_model.power_model_1 + unsign2sign8bit(modify_power_model.power_model_1)); size += sprintf(buf + size, " power_model_2 : %d\n", power_model.power_model_2 + unsign2sign8bit(modify_power_model.power_model_2)); size += sprintf(buf + size, " power_model_3 : %d\n", power_model.power_model_3 + unsign2sign8bit(modify_power_model.power_model_3)); size += sprintf(buf + size, " mcd ver : %d\n", power_model.mcd_ver + unsign2sign8bit(modify_power_model.mcd_ver)); size += sprintf(buf + size, " mht power : %d\n", power_model.mht_ver + unsign2sign8bit(modify_power_model.mht_ver)); size += sprintf(buf + size, "\n"); return size; } static ssize_t asv_info_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { char *buf; int r; buf = kzalloc(sizeof(char) * 2048, GFP_KERNEL); r = print_asv_table(buf); r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r); kfree(buf); return r; } static const struct file_operations asv_info_fops = { .open = simple_open, .read = asv_info_read, .llseek = seq_lseek, }; static ssize_t show_asv_info(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return print_asv_table(buf); } static struct kobj_attribute asv_info = __ATTR(asv_info, 0400, show_asv_info, NULL); #endif static ssize_t show_power_model_0(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%d\n", power_model.power_model_0 + unsign2sign8bit(modify_power_model.power_model_0)); } static struct kobj_attribute power_model_0 = __ATTR(power_model_0, 0400, show_power_model_0, NULL); static ssize_t show_power_model_1(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%d\n", power_model.power_model_1 + unsign2sign8bit(modify_power_model.power_model_1)); } static struct kobj_attribute power_model_1 = __ATTR(power_model_1, 0400, show_power_model_1, NULL); static ssize_t show_power_model_2(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%d\n", power_model.power_model_2 + unsign2sign8bit(modify_power_model.power_model_2)); } static struct kobj_attribute power_model_2 = __ATTR(power_model_2, 0400, show_power_model_2, NULL); static ssize_t show_power_model_3(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%d\n", power_model.power_model_3 + unsign2sign8bit(modify_power_model.power_model_3)); } static struct kobj_attribute power_model_3 = __ATTR(power_model_3, 0400, show_power_model_3, NULL); static ssize_t show_mcd_ver(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%d\n", power_model.mcd_ver + unsign2sign8bit(modify_power_model.mcd_ver)); } static struct kobj_attribute mcd_ver = __ATTR(mcd_ver, 0400, show_mcd_ver, NULL); static ssize_t show_mht_ver(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%d\n", power_model.mht_ver + unsign2sign8bit(modify_power_model.mht_ver)); } static struct kobj_attribute mht_ver = __ATTR(mht_ver, 0400, show_mht_ver, NULL); static struct attribute *asv_info_attrs[] = { #if IS_ENABLED(CONFIG_SHOW_ASV) &asv_info.attr, #endif &power_model_0.attr, &power_model_1.attr, &power_model_2.attr, &power_model_3.attr, &mcd_ver.attr, &mht_ver.attr, NULL, }; static const struct attribute_group asv_info_grp = { .attrs = asv_info_attrs, }; int asv_debug_init(void) { struct kobject *kobj; #if IS_ENABLED(CONFIG_SHOW_ASV) struct dentry *d; rootdir = debugfs_create_dir("asv", NULL); if (!rootdir) return -ENOMEM; d = debugfs_create_file("asv_info", 0600, rootdir, NULL, &asv_info_fops); if (!d) return -ENOMEM; #endif kobj = kobject_create_and_add("asv", kernel_kobj); if (!kobj) pr_err("Fail to create asv kboject\n"); if (sysfs_create_group(kobj, &asv_info_grp)) pr_err("Fail to create asv_info group\n"); return 0; } int asv_table_init(void) { int i; unsigned int *p_table; unsigned int *regs; unsigned long tmp; p_table = (unsigned int *)&asv_tbl; for (i = 0; i < ASV_INFO_ADDR_CNT; i++) { exynos_smc_readsfr((unsigned long)(ASV_TABLE_BASE + 0x4 * i), &tmp); *(p_table + i) = (unsigned int)tmp; } p_table = (unsigned int *)&id_tbl; regs = (unsigned int *)ioremap(ID_TABLE_BASE, ID_INFO_ADDR_CNT * sizeof(int)); for (i = 0; i < ID_INFO_ADDR_CNT; i++) *(p_table + i) = (unsigned int)regs[i]; p_table = (unsigned int *)&power_model; regs = (unsigned int *)ioremap(ID_TABLE_BASE + 0xF064, sizeof(struct asv_power_model)); *p_table = *regs; *(p_table + 1) = *(unsigned int *)(regs + 1); p_table = (unsigned int *)&modify_power_model; regs = (unsigned int *)ioremap(ID_TABLE_BASE + 0xF058, sizeof(struct asv_power_model)); *p_table = *regs; *(p_table + 1) = *(unsigned int *)(regs + 1); asv_debug_init(); #if IS_ENABLED(CONFIG_SEC_DEBUG_EXTRA_INFO) secdbg_exin_set_asv(asv_get_grp(CPUCL2), asv_get_grp(CPUCL1), asv_get_grp(CPUCL0), asv_get_grp(G3D), asv_get_grp(MIF)); secdbg_exin_set_ids(asv_get_ids_info(CPUCL2), asv_get_ids_info(CPUCL1), asv_get_ids_info(CPUCL0), asv_get_ids_info(G3D)); #endif return asv_tbl.asv_table_version; } #endif