You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
kernel_samsung_sm7125/drivers/samsung/debug/sec_hw_param.c

1467 lines
41 KiB

// SPDX-License-Identifier: GPL-2.0
/*
* drivers/samsung/debug/sec_hw_param.c
*
* COPYRIGHT(C) 2014-2019 Samsung Electronics Co., Ltd. All Right Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ":%s() " fmt, __func__
#include <linux/seq_file.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/of.h>
#include <soc/qcom/socinfo.h>
#include <linux/sec_smem.h>
#include <linux/sec_class.h>
#include <linux/sec_debug.h>
#ifdef CONFIG_SEC_PM
#include <linux/input/qpnp-power-on.h>
#endif
enum {
CONVERSION_SOC_REV_1_0 = 0,
CONVERSION_SOC_REV_2_0,
CONVERSION_SOC_REV_2_1,
CONVERSION_SOC_REV_2_2,
CONVERSION_SOC_REV_1_1,
CONVERSION_SOC_REV_UNKNOWN,
};
#define DEFAULT_LEN_STR 1023
#define SPECIAL_LEN_STR 2047
#define EXTRA_LEN_STR ((SPECIAL_LEN_STR) - (31 + 5))
#define default_scnprintf(buf, offset, fmt, ...) \
do { \
offset += scnprintf(&(buf)[offset], DEFAULT_LEN_STR - (size_t)offset, \
fmt, ##__VA_ARGS__); \
} while (0)
#define special_scnprintf(buf, offset, fmt, ...) \
do { \
offset += scnprintf(&(buf)[offset], SPECIAL_LEN_STR - (size_t)offset, \
fmt, ##__VA_ARGS__); \
} while (0)
#define extra_scnprintf(buf, offset, fmt, ...) \
do { \
offset += scnprintf(&(buf)[offset], EXTRA_LEN_STR - (size_t)offset, \
fmt, ##__VA_ARGS__); \
} while (0)
static unsigned int system_rev __read_mostly;
static int __init sec_hw_rev_setup(char *p)
{
int ret;
ret = kstrtouint(p, 0, &system_rev);
if (unlikely(ret < 0)) {
pr_warn("androidboot.revision is malformed (%s)\n", p);
return -EINVAL;
}
pr_info("androidboot.revision %x\n", system_rev);
return 0;
}
early_param("androidboot.revision", sec_hw_rev_setup);
static void check_format(char *buf, ssize_t *size, int max_len_str)
{
int i = 0, cnt = 0, pos = 0;
if (!buf || *size <= 0)
return;
if (*size >= max_len_str)
*size = max_len_str - 1;
while (i < *size && buf[i]) {
if (buf[i] == '"') {
cnt++;
pos = i;
}
if ((buf[i] < 0x20) || (buf[i] == 0x5C) || (buf[i] > 0x7E))
buf[i] = ' ';
i++;
}
if (cnt % 2) {
if (pos == *size - 1) {
buf[*size - 1] = '\0';
} else {
buf[*size - 1] = '"';
buf[*size] = '\0';
}
}
}
static bool __is_ready_debug_reset_header(void)
{
struct debug_reset_header *header = get_debug_reset_header();
if (!header)
return false;
kfree(header);
return true;
}
static bool __is_valid_reset_reason(unsigned int reset_reason)
{
if (reset_reason < USER_UPLOAD_CAUSE_MIN ||
reset_reason > USER_UPLOAD_CAUSE_MAX)
return false;
if (reset_reason == USER_UPLOAD_CAUSE_MANUAL_RESET ||
reset_reason == USER_UPLOAD_CAUSE_REBOOT ||
reset_reason == USER_UPLOAD_CAUSE_BOOTLOADER_REBOOT ||
reset_reason == USER_UPLOAD_CAUSE_POWER_ON)
return false;
return true;
}
static ap_health_t *phealth;
static bool batt_info_cleaned;
static void clean_batt_info(void)
{
if (phealth && !batt_info_cleaned) {
memset(&phealth->battery, 0x0, sizeof(battery_health_t));
batt_info_cleaned = true;
}
}
void battery_last_dcvs(int cap, int volt, int temp, int curr)
{
uint32_t tail = 0;
if (phealth == NULL || !batt_info_cleaned)
return;
if ((phealth->battery.tail & 0xf) >= MAX_BATT_DCVS)
phealth->battery.tail = 0x10;
tail = phealth->battery.tail & 0xf;
phealth->battery.batt[tail].ktime = local_clock();
phealth->battery.batt[tail].cap = cap;
phealth->battery.batt[tail].volt = volt;
phealth->battery.batt[tail].temp = temp;
phealth->battery.batt[tail].curr = curr;
phealth->battery.tail++;
}
EXPORT_SYMBOL_GPL(battery_last_dcvs);
static ssize_t show_last_dcvs(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t info_size = 0;
unsigned int reset_reason;
char *prefix[MAX_CLUSTER_NUM] = { "L3", "SC", "GC", "GP"};
size_t i;
if (!phealth)
phealth = ap_health_data_read();
if (!phealth) {
pr_err("fail to get ap health info\n");
return info_size;
}
reset_reason = sec_debug_get_reset_reason();
if (!__is_valid_reset_reason(reset_reason))
return info_size;
default_scnprintf(buf, info_size, "\"RR\":\"%s\",",
sec_debug_get_reset_reason_str(reset_reason));
default_scnprintf(buf, info_size, "\"RWC\":\"%d\",",
sec_debug_get_reset_write_cnt());
for (i = 0; i < MAX_CLUSTER_NUM; i++)
default_scnprintf(buf, info_size, "\"%sKHz\":\"%u\",",
prefix[i],
phealth->last_dcvs.apps[i].cpu_KHz);
default_scnprintf(buf, info_size, "\"DDRKHz\":\"%u\",",
phealth->last_dcvs.rpm.ddr_KHz);
default_scnprintf(buf, info_size, "\"BCAP\":\"%d\",",
phealth->last_dcvs.batt.cap);
default_scnprintf(buf, info_size, "\"BVOL\":\"%d\",",
phealth->last_dcvs.batt.volt);
default_scnprintf(buf, info_size, "\"BTEM\":\"%d\",",
phealth->last_dcvs.batt.temp);
default_scnprintf(buf, info_size, "\"BCUR\":\"%d\",",
phealth->last_dcvs.batt.curr);
default_scnprintf(buf, info_size, "\"PON\":\"%llx\",",
phealth->last_dcvs.pon.pon_reason);
default_scnprintf(buf, info_size, "\"PONF\":\"%llx\",",
phealth->last_dcvs.pon.fault_reason);
/* remove the last ',' character */
info_size--;
check_format(buf, &info_size, DEFAULT_LEN_STR);
return info_size;
}
static DEVICE_ATTR(last_dcvs, 0440, show_last_dcvs, NULL);
static ssize_t store_ap_health(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
char clear;
int err;
err = sscanf(buf, "%1c", &clear);
if ((err <= 0) || (clear != 'c' && clear != 'C')) {
pr_err("command error\n");
return count;
}
if (!phealth)
phealth = ap_health_data_read();
if (!phealth) {
pr_err("fail to get ap health info\n");
return -EINVAL;
}
pr_info("clear ap_health_data by HQM %zu\n", sizeof(ap_health_t));
/*++ add here need init data by HQM ++*/
memset(&(phealth->daily_rr), 0, sizeof(reset_reason_t));
memset(&(phealth->daily_cache), 0, sizeof(cache_health_t));
memset(&(phealth->daily_pcie), 0, sizeof(pcie_health_t) * MAX_PCIE_NUM);
ap_health_data_write(phealth);
return count;
}
static ssize_t show_ap_health(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t info_size = 0;
int cpu;
size_t i;
if (!phealth)
phealth = ap_health_data_read();
if (!phealth) {
pr_err("fail to get ap health info\n");
return info_size;
}
default_scnprintf(buf, info_size, "\"L1c\":\"");
for (cpu = 0; cpu < num_present_cpus(); cpu++) {
default_scnprintf(buf, info_size, "%d",
phealth->cache.edac[cpu][0].ce_cnt);
if (cpu == (num_present_cpus() - 1))
default_scnprintf(buf, info_size, "\",");
else
default_scnprintf(buf, info_size, ",");
}
default_scnprintf(buf, info_size, "\"L1u\":\"");
for (cpu = 0; cpu < num_present_cpus(); cpu++) {
default_scnprintf(buf, info_size, "%d",
phealth->cache.edac[cpu][0].ue_cnt);
if (cpu == (num_present_cpus() - 1))
default_scnprintf(buf, info_size, "\",");
else
default_scnprintf(buf, info_size, ",");
}
default_scnprintf(buf, info_size, "\"L2c\":\"");
for (cpu = 0; cpu < num_present_cpus(); cpu++) {
default_scnprintf(buf, info_size, "%d",
phealth->cache.edac[cpu][1].ce_cnt);
if (cpu == (num_present_cpus() - 1))
default_scnprintf(buf, info_size, "\",");
else
default_scnprintf(buf, info_size, ",");
}
default_scnprintf(buf, info_size, "\"L2u\":\"");
for (cpu = 0; cpu < num_present_cpus(); cpu++) {
default_scnprintf(buf, info_size, "%d",
phealth->cache.edac[cpu][1].ue_cnt);
if (cpu == (num_present_cpus() - 1))
default_scnprintf(buf, info_size, "\",");
else
default_scnprintf(buf, info_size, ",");
}
default_scnprintf(buf, info_size, "\"L3c\":\"%d\",",
phealth->cache.edac_l3.ce_cnt);
default_scnprintf(buf, info_size, "\"L3u\":\"%d\",",
phealth->cache.edac_l3.ue_cnt);
default_scnprintf(buf, info_size, "\"EDB\":\"%d\",",
phealth->cache.edac_bus_cnt);
default_scnprintf(buf, info_size, "\"LDc\":\"%d\",",
phealth->cache.edac_llcc_data_ram.ce_cnt);
default_scnprintf(buf, info_size, "\"LDu\":\"%d\",",
phealth->cache.edac_llcc_data_ram.ue_cnt);
default_scnprintf(buf, info_size, "\"LTc\":\"%d\",",
phealth->cache.edac_llcc_tag_ram.ce_cnt);
default_scnprintf(buf, info_size, "\"LTu\":\"%d\",",
phealth->cache.edac_llcc_tag_ram.ue_cnt);
default_scnprintf(buf, info_size, "\"dL1c\":\"");
for (cpu = 0; cpu < num_present_cpus(); cpu++) {
default_scnprintf(buf, info_size, "%d",
phealth->daily_cache.edac[cpu][0].ce_cnt);
if (cpu == (num_present_cpus() - 1))
default_scnprintf(buf, info_size, "\",");
else
default_scnprintf(buf, info_size, ",");
}
default_scnprintf(buf, info_size, "\"dL1u\":\"");
for (cpu = 0; cpu < num_present_cpus(); cpu++) {
default_scnprintf(buf, info_size, "%d",
phealth->daily_cache.edac[cpu][0].ue_cnt);
if (cpu == (num_present_cpus() - 1))
default_scnprintf(buf, info_size, "\",");
else
default_scnprintf(buf, info_size, ",");
}
default_scnprintf(buf, info_size, "\"dL2c\":\"");
for (cpu = 0; cpu < num_present_cpus(); cpu++) {
default_scnprintf(buf, info_size, "%d",
phealth->daily_cache.edac[cpu][1].ce_cnt);
if (cpu == (num_present_cpus() - 1))
default_scnprintf(buf, info_size, "\",");
else
default_scnprintf(buf, info_size, ",");
}
default_scnprintf(buf, info_size, "\"dL2u\":\"");
for (cpu = 0; cpu < num_present_cpus(); cpu++) {
default_scnprintf(buf, info_size, "%d",
phealth->daily_cache.edac[cpu][1].ue_cnt);
if (cpu == (num_present_cpus() - 1))
default_scnprintf(buf, info_size, "\",");
else
default_scnprintf(buf, info_size, ",");
}
default_scnprintf(buf, info_size, "\"dL3c\":\"%d\",",
phealth->daily_cache.edac_l3.ce_cnt);
default_scnprintf(buf, info_size, "\"dL3u\":\"%d\",",
phealth->daily_cache.edac_l3.ue_cnt);
default_scnprintf(buf, info_size, "\"dEDB\":\"%d\",",
phealth->daily_cache.edac_bus_cnt);
default_scnprintf(buf, info_size, "\"dLDc\":\"%d\",",
phealth->daily_cache.edac_llcc_data_ram.ce_cnt);
default_scnprintf(buf, info_size, "\"dLDu\":\"%d\",",
phealth->daily_cache.edac_llcc_data_ram.ue_cnt);
default_scnprintf(buf, info_size, "\"dLTc\":\"%d\",",
phealth->daily_cache.edac_llcc_tag_ram.ce_cnt);
default_scnprintf(buf, info_size, "\"dLTu\":\"%d\",",
phealth->daily_cache.edac_llcc_tag_ram.ue_cnt);
for (i = 0; i < MAX_PCIE_NUM; i++) {
default_scnprintf(buf, info_size, "\"P%zuPF\":\"%d\",", i,
phealth->pcie[i].phy_init_fail_cnt);
default_scnprintf(buf, info_size, "\"P%zuLD\":\"%d\",", i,
phealth->pcie[i].link_down_cnt);
default_scnprintf(buf, info_size, "\"P%zuLF\":\"%d\",", i,
phealth->pcie[i].link_up_fail_cnt);
default_scnprintf(buf, info_size, "\"P%zuLT\":\"%x\",", i,
phealth->pcie[i].link_up_fail_ltssm);
default_scnprintf(buf, info_size, "\"dP%zuPF\":\"%d\",", i,
phealth->daily_pcie[i].phy_init_fail_cnt);
default_scnprintf(buf, info_size, "\"dP%zuLD\":\"%d\",", i,
phealth->daily_pcie[i].link_down_cnt);
default_scnprintf(buf, info_size, "\"dP%zuLF\":\"%d\",", i,
phealth->daily_pcie[i].link_up_fail_cnt);
default_scnprintf(buf, info_size, "\"dP%zuLT\":\"%x\",", i,
phealth->daily_pcie[i].link_up_fail_ltssm);
}
default_scnprintf(buf, info_size, "\"dNP\":\"%d\",",
phealth->daily_rr.np);
default_scnprintf(buf, info_size, "\"dRP\":\"%d\",",
phealth->daily_rr.rp);
default_scnprintf(buf, info_size, "\"dMP\":\"%d\",",
phealth->daily_rr.mp);
default_scnprintf(buf, info_size, "\"dKP\":\"%d\",",
phealth->daily_rr.kp);
default_scnprintf(buf, info_size, "\"dDP\":\"%d\",",
phealth->daily_rr.dp);
default_scnprintf(buf, info_size, "\"dWP\":\"%d\",",
phealth->daily_rr.wp);
default_scnprintf(buf, info_size, "\"dTP\":\"%d\",",
phealth->daily_rr.tp);
default_scnprintf(buf, info_size, "\"dSP\":\"%d\",",
phealth->daily_rr.sp);
default_scnprintf(buf, info_size, "\"dPP\":\"%d\",",
phealth->daily_rr.pp);
default_scnprintf(buf, info_size, "\"dCP\":\"%d\"",
phealth->daily_rr.cp);
check_format(buf, &info_size, DEFAULT_LEN_STR);
return info_size;
}
static DEVICE_ATTR(ap_health, 0660, show_ap_health, store_ap_health);
#define for_each_dq(dq, max_dq) \
for (dq = 0; dq < max_dq; dq++)
#define for_each_cs(cs, max_cs) \
for (cs = 0; cs < max_cs; cs++)
#define for_each_cs_dq(cs, max_cs, dq, max_dq) \
for_each_cs(cs, max_cs) \
for_each_dq(dq, max_dq)
#define for_each_ch(ch, max_ch) \
for (ch = 0; ch < max_ch; ch++)
#define for_each_ch_dq(ch, max_ch, dq, max_dq) \
for_each_ch(ch, max_ch) \
for_each_dq(dq, max_dq)
#define for_each_ch_cs(ch, max_ch, cs, max_cs) \
for_each_ch(ch, max_ch) \
for_each_cs(cs, max_cs)
#define for_each_ch_cs_dq(ch, max_ch, cs, max_cs, dq, max_dq) \
for_each_ch(ch, max_ch) \
for_each_cs_dq(cs, max_cs, dq, max_dq)
static ssize_t show_ddr_info(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t info_size = 0;
uint32_t ch, cs, dq;
default_scnprintf(buf, info_size, "\"DDRV\":\"%s\",",
get_ddr_vendor_name());
default_scnprintf(buf, info_size, "\"DSF\":\"%d.%d\",",
(get_ddr_DSF_version() >> 16) & 0xFFFF,
get_ddr_DSF_version() & 0xFFFF);
for_each_ch_cs_dq(ch, NUM_CH, cs, NUM_CS, dq, NUM_DQ_PCH) {
default_scnprintf(buf, info_size, "\"RW_%d_%d_%d\":\"%d\",",
ch, cs, dq, get_ddr_rcw_tDQSCK(ch, cs, dq));
default_scnprintf(buf, info_size, "\"WC_%d_%d_%d\":\"%d\",",
ch, cs, dq, get_ddr_wr_coarseCDC(ch, cs, dq));
default_scnprintf(buf, info_size, "\"WF_%d_%d_%d\":\"%d\",",
ch, cs, dq, get_ddr_wr_fineCDC(ch, cs, dq));
}
/* remove the last ',' character */
info_size--;
check_format(buf, &info_size, DEFAULT_LEN_STR);
return info_size;
}
static DEVICE_ATTR(ddr_info, 0440, show_ddr_info, NULL);
#define PARAM0_IVALID 1
#define PARAM0_LESS_THAN_0 2
#if defined(CONFIG_SEC_NOEYEINFO)
static ssize_t eye_rd_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t info_size = 0;
default_scnprintf(buf, info_size, "\"DDRV\":\"%s\",",
get_ddr_vendor_name());
default_scnprintf(buf, info_size, "\"DSF\":\"%d.%d\",",
(get_ddr_DSF_version() >> 16) & 0xFFFF,
get_ddr_DSF_version() & 0xFFFF);
default_scnprintf(buf, info_size, "\"REV1\":\"%02x\",", get_ddr_revision_id_1());
default_scnprintf(buf, info_size, "\"REV2\":\"%02x\",", get_ddr_revision_id_2());
default_scnprintf(buf, info_size, "\"SIZE\":\"%02x\",", get_ddr_total_density());
/* remove the last ',' character */
info_size--;
check_format(buf, &info_size, DEFAULT_LEN_STR);
return info_size;
}
static DEVICE_ATTR(eye_rd_info, 0440, eye_rd_info_show, NULL);
#else
static ssize_t eye_rd_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t info_size = 0;
uint32_t ch, cs, dq;
default_scnprintf(buf, info_size, "\"DDRV\":\"%s\",",
get_ddr_vendor_name());
default_scnprintf(buf, info_size, "\"DSF\":\"%d.%d\",",
(get_ddr_DSF_version() >> 16) & 0xFFFF,
get_ddr_DSF_version() & 0xFFFF);
default_scnprintf(buf, info_size, "\"REV1\":\"%02x\",", get_ddr_revision_id_1());
default_scnprintf(buf, info_size, "\"REV2\":\"%02x\",", get_ddr_revision_id_2());
default_scnprintf(buf, info_size, "\"SIZE\":\"%02x\",", get_ddr_total_density());
default_scnprintf(buf, info_size, "\"CNT\":\"%d\",",
ddr_get_small_eye_detected());
default_scnprintf(buf, info_size, "\"rd_width\":\"R1\",");
for_each_ch_cs_dq(ch, NUM_CH, cs, NUM_CS, dq, NUM_DQ_PCH) {
default_scnprintf(buf, info_size, "\"RW%d_%d_%d\":\"%d\",",
ch, cs, dq,
ddr_get_rd_pr_width(ch, cs, dq));
}
default_scnprintf(buf, info_size, "\"rd_height\":\"R2\",");
for_each_ch_cs(ch, NUM_CH, cs, NUM_CS) {
default_scnprintf(buf, info_size, "\"RH%d_%d_x\":\"%d\",",
ch, cs,
ddr_get_rd_min_eye_height(ch, cs));
}
default_scnprintf(buf, info_size, "\"rd_vref\":\"Rx\",");
for_each_ch_cs_dq(ch, NUM_CH, cs, NUM_CS, dq, NUM_DQ_PCH) {
default_scnprintf(buf, info_size, "\"RV%d_%d_%d\":\"%d\",",
ch, cs, dq,
ddr_get_rd_best_vref(ch, cs, dq));
}
/* remove the last ',' character */
info_size--;
check_format(buf, &info_size, DEFAULT_LEN_STR);
return info_size;
}
static DEVICE_ATTR(eye_rd_info, 0440, eye_rd_info_show, NULL);
static ssize_t eye_dcc_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t info_size = 0;
uint32_t ch, cs, dq;
default_scnprintf(buf, info_size, "\"dqs_dcc\":\"D3\",");
for_each_ch_dq(ch, NUM_CH, dq, NUM_DQ_PCH) {
default_scnprintf(buf, info_size, "\"DS%d_x_%d\":\"%d\",",
ch, dq,
ddr_get_dqs_dcc_adj(ch, dq));
}
default_scnprintf(buf, info_size, "\"dq_dcc\":\"D5\",");
for_each_ch_cs_dq(ch, NUM_CH, cs, NUM_CS, dq, NUM_DQ_PCH) {
default_scnprintf(buf, info_size, "\"DQ%d_%d_%d\":\"%d\",",
ch, cs, dq,
ddr_get_dq_dcc_abs(ch, cs, dq));
}
/* remove the last ',' character */
info_size--;
check_format(buf, &info_size, DEFAULT_LEN_STR);
return info_size;
}
static DEVICE_ATTR(eye_dcc_info, 0440, eye_dcc_info_show, NULL);
static ssize_t eye_wr1_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t info_size = 0;
uint32_t ch, cs, dq;
default_scnprintf(buf, info_size, "\"wr_width\":\"W1\",");
for_each_ch_cs_dq(ch, NUM_CH, cs, NUM_CS, dq, NUM_DQ_PCH) {
default_scnprintf(buf, info_size, "\"WW%d_%d_%d\":\"%d\",",
ch, cs, dq,
ddr_get_wr_pr_width(ch, cs, dq));
}
default_scnprintf(buf, info_size, "\"wr_height\":\"W2\",");
for_each_ch_cs(ch, NUM_CH, cs, NUM_CS) {
default_scnprintf(buf, info_size, "\"WH%d_%d_x\":\"%d\",",
ch, cs,
ddr_get_wr_min_eye_height(ch, cs));
}
default_scnprintf(buf, info_size, "\"wr_vref\":\"Wx\",");
for_each_ch_cs(ch, NUM_CH, cs, NUM_CS) {
default_scnprintf(buf, info_size, "\"WV%d_%d_x\":\"%d\",",
ch, cs,
ddr_get_wr_best_vref(ch, cs));
}
/* remove the last ',' character */
info_size--;
check_format(buf, &info_size, DEFAULT_LEN_STR);
return info_size;
}
static DEVICE_ATTR(eye_wr1_info, 0440, eye_wr1_info_show, NULL);
static ssize_t eye_wr2_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t info_size = 0;
uint32_t ch, cs, dq;
default_scnprintf(buf, info_size, "\"wr_topw\":\"W4\",");
for_each_ch_cs_dq(ch, NUM_CH, cs, NUM_CS, dq, NUM_DQ_PCH) {
default_scnprintf(buf, info_size, "\"WT%d_%d_%d\":\"%d\",",
ch, cs, dq,
ddr_get_wr_vmax_to_vmid(ch, cs, dq));
}
default_scnprintf(buf, info_size, "\"wr_botw\":\"W4\",");
for_each_ch_cs_dq(ch, NUM_CH, cs, NUM_CS, dq, NUM_DQ_PCH) {
default_scnprintf(buf, info_size, "\"WB%d_%d_%d\":\"%d\",",
ch, cs, dq,
ddr_get_wr_vmid_to_vmin(ch, cs, dq));
}
/* remove the last ',' character */
info_size--;
check_format(buf, &info_size, DEFAULT_LEN_STR);
return info_size;
}
static DEVICE_ATTR(eye_wr2_info, 0440, eye_wr2_info_show, NULL);
#endif
static int get_param0(const char *name)
{
struct device_node *np = of_find_node_by_path("/soc/sec_hw_param");
u32 val;
int ret;
if (!np) {
pr_err("No sec_hw_param found\n");
return -PARAM0_IVALID;
}
ret = of_property_read_u32(np, name, &val);
if (ret) {
pr_err("failed to get %s from node\n", name);
return -PARAM0_LESS_THAN_0;
}
return val;
}
char * get_soc_hw_rev(void)
{
uint32_t soc_value;
soc_value = get_param0("soc_rev");
switch (soc_value) {
case CONVERSION_SOC_REV_1_0:
return "1.0";
break;
case CONVERSION_SOC_REV_2_0:
return "2.0";
break;
case CONVERSION_SOC_REV_2_1:
return "2.1";
break;
case CONVERSION_SOC_REV_2_2:
return "2.2";
break;
case CONVERSION_SOC_REV_1_1:
return "1.1";
break;
default:
return "unknown";
break;
}
}
static ssize_t show_ap_info(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t info_size = 0;
default_scnprintf(buf, info_size, "\"HW_REV\":\"%d\"", system_rev);
default_scnprintf(buf, info_size, ",\"SoC_ID\":\"%u\"", socinfo_get_id());
default_scnprintf(buf, info_size, ",\"SoC_REV\":\"%s\"", get_soc_hw_rev());
default_scnprintf(buf, info_size, ",\"GC_PRM\":\"%d\"", get_param0("g_iddq"));
default_scnprintf(buf, info_size, ",\"GC_OPV_3\":\"%d\"", get_param0("olv_perf_t"));
default_scnprintf(buf, info_size, ",\"DOUR\":\"%d\"", get_param0("dour"));
default_scnprintf(buf, info_size, ",\"DOUB\":\"%d\"", get_param0("doub"));
check_format(buf, &info_size, DEFAULT_LEN_STR);
return info_size;
}
static DEVICE_ATTR(ap_info, 0440, show_ap_info, NULL);
static ssize_t show_extra_info(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t offset = 0;
unsigned long long rem_nsec;
unsigned long long ts_nsec;
unsigned int reset_reason;
rst_exinfo_t *p_rst_exinfo = NULL;
_kern_ex_info_t *p_kinfo = NULL;
int cpu = -1;
if (!__is_ready_debug_reset_header()) {
pr_info("updated nothing.\n");
goto out;
}
reset_reason = sec_debug_get_reset_reason();
if (!__is_valid_reset_reason(reset_reason))
goto out;
p_rst_exinfo = kmalloc(sizeof(rst_exinfo_t), GFP_KERNEL);
if (!p_rst_exinfo)
goto out;
if (!read_debug_partition(debug_index_reset_ex_info, p_rst_exinfo)) {
pr_err("fail - get param!!\n");
goto out;
}
p_kinfo = &p_rst_exinfo->kern_ex_info.info;
cpu = p_kinfo->cpu;
extra_scnprintf(buf, offset, "\"RR\":\"%s\",",
sec_debug_get_reset_reason_str(reset_reason));
extra_scnprintf(buf, offset, "\"RWC\":\"%d\",",
sec_debug_get_reset_write_cnt());
ts_nsec = p_kinfo->ktime;
rem_nsec = do_div(ts_nsec, 1000000000ULL);
extra_scnprintf(buf, offset, "\"KTIME\":\"%llu.%06llu\",",
ts_nsec, rem_nsec / 1000ULL);
extra_scnprintf(buf, offset, "\"CPU\":\"%d\",",
p_kinfo->cpu);
extra_scnprintf(buf, offset, "\"TASK\":\"%s\",",
p_kinfo->task_name);
if (p_kinfo->smmu.fsr) {
extra_scnprintf(buf, offset, "\"SDN\":\"%s\",",
p_kinfo->smmu.dev_name);
extra_scnprintf(buf, offset, "\"FSR\":\"%x\",",
p_kinfo->smmu.fsr);
if (p_kinfo->smmu.fsynr0) {
extra_scnprintf(buf, offset, "\"FSY0\":\"%x\",",
p_kinfo->smmu.fsynr0);
extra_scnprintf(buf, offset, "\"FSY1\":\"%x\",",
p_kinfo->smmu.fsynr1);
extra_scnprintf(buf, offset, "\"IOVA\":\"%08lx\",",
p_kinfo->smmu.iova);
extra_scnprintf(buf, offset, "\"FAR\":\"%016lx\",",
p_kinfo->smmu.far);
extra_scnprintf(buf, offset, "\"SMN\":\"%s\",",
p_kinfo->smmu.mas_name);
extra_scnprintf(buf, offset, "\"CB\":\"%d\",",
p_kinfo->smmu.cbndx);
extra_scnprintf(buf, offset, "\"SOFT\":\"%016llx\",",
p_kinfo->smmu.phys_soft);
extra_scnprintf(buf, offset, "\"ATOS\":\"%016llx\",",
p_kinfo->smmu.phys_atos);
extra_scnprintf(buf, offset, "\"SID\":\"%x\",",
p_kinfo->smmu.sid);
}
}
if (p_kinfo->badmode.esr) {
extra_scnprintf(buf, offset,
"\"BDR\":\"%08x\",", p_kinfo->badmode.reason);
extra_scnprintf(buf, offset,
"\"BDRS\":\"%s\",", p_kinfo->badmode.handler_str);
extra_scnprintf(buf, offset,
"\"BDE\":\"%08x\",", p_kinfo->badmode.esr);
extra_scnprintf(buf, offset,
"\"BDES\":\"%s\",", p_kinfo->badmode.esr_str);
}
if ((cpu > -1) && (cpu < num_present_cpus())) {
if (p_kinfo->fault[cpu].esr) {
extra_scnprintf(buf, offset, "\"ESR\":\"%08x\",",
p_kinfo->fault[cpu].esr);
extra_scnprintf(buf, offset, "\"FNM\":\"%s\",",
p_kinfo->fault[cpu].str);
extra_scnprintf(buf, offset, "\"FV1\":\"%016llx\",",
p_kinfo->fault[cpu].var1);
extra_scnprintf(buf, offset, "\"FV2\":\"%016llx\",",
p_kinfo->fault[cpu].var2);
}
extra_scnprintf(buf, offset,
"\"FAULT\":\"pgd=%016llx VA=%016llx ",
p_kinfo->fault[cpu].pte[0],
p_kinfo->fault[cpu].pte[1]);
extra_scnprintf(buf, offset, "*pgd=%016llx *pud=%016llx ",
p_kinfo->fault[cpu].pte[2],
p_kinfo->fault[cpu].pte[3]);
extra_scnprintf(buf, offset, "*pmd=%016llx *pte=%016llx\",",
p_kinfo->fault[cpu].pte[4],
p_kinfo->fault[cpu].pte[5]);
}
extra_scnprintf(buf, offset, "\"BUG\":\"%s\",", p_kinfo->bug_buf);
if (strlen(p_kinfo->panic_buf)) {
extra_scnprintf(buf, offset, "\"PANIC\":\"%s\",", p_kinfo->panic_buf);
} else {
if (p_rst_exinfo->uc_ex_info.magic == RESTART_REASON_SEC_DEBUG_MODE) {
extra_scnprintf(buf, offset, "\"PANIC\":\"UCS-%s\",", p_rst_exinfo->uc_ex_info.str);
}
}
extra_scnprintf(buf, offset, "\"PC\":\"%s\",", p_kinfo->pc);
extra_scnprintf(buf, offset, "\"LR\":\"%s\",", p_kinfo->lr);
extra_scnprintf(buf, offset, "\"UFS\":\"%s\",", p_kinfo->ufs_err);
extra_scnprintf(buf, offset, "\"ROT\":\"W%dC%d\",",
get_param0("wb"), get_param0("ddi"));
extra_scnprintf(buf, offset, "\"STACK\":\"%s\"", p_kinfo->backtrace);
out:
kfree(p_rst_exinfo);
check_format(buf, &offset, EXTRA_LEN_STR);
return offset;
}
static DEVICE_ATTR(extra_info, 0440, show_extra_info, NULL);
static ssize_t show_extrb_info(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t offset = 0;
int idx, cnt, max_cnt;
unsigned long rem_nsec;
u64 ts_nsec;
unsigned int reset_reason;
char *tz_cpu_status[6] = { "NA", "R", "PC", "WB", "IW", "IWT" };
rst_exinfo_t *p_rst_exinfo = NULL;
__rpm_log_t *pRPMlog = NULL;
if (!__is_ready_debug_reset_header()) {
pr_info("updated nothing.\n");
goto out;
}
reset_reason = sec_debug_get_reset_reason();
if (!__is_valid_reset_reason(reset_reason))
goto out;
p_rst_exinfo = kmalloc(sizeof(rst_exinfo_t), GFP_KERNEL);
if (!p_rst_exinfo) {
pr_err("fail - kmalloc\n");
goto out;
}
if (!read_debug_partition(debug_index_reset_ex_info, p_rst_exinfo)) {
pr_err("fail - get param!!\n");
goto out;
}
special_scnprintf(buf, offset, "\"RR\":\"%s\",",
sec_debug_get_reset_reason_str(reset_reason));
special_scnprintf(buf, offset, "\"RWC\":\"%d\",",
sec_debug_get_reset_write_cnt());
if (p_rst_exinfo->rpm_ex_info.info.magic == RPM_EX_INFO_MAGIC
&& p_rst_exinfo->rpm_ex_info.info.nlog > 0) {
special_scnprintf(buf, offset, "\"RPM\":\"");
if (p_rst_exinfo->rpm_ex_info.info.nlog > 5) {
idx = p_rst_exinfo->rpm_ex_info.info.nlog % 5;
max_cnt = 5;
} else {
idx = 0;
max_cnt = p_rst_exinfo->rpm_ex_info.info.nlog;
}
for (cnt = 0; cnt < max_cnt; cnt++, idx++) {
pRPMlog = &p_rst_exinfo->rpm_ex_info.info.log[idx % 5];
ts_nsec = pRPMlog->nsec;
rem_nsec = do_div(ts_nsec, 1000000000);
special_scnprintf(buf, offset, "%lu.%06lu ",
(unsigned long)ts_nsec, rem_nsec / 1000);
special_scnprintf(buf, offset, "%s ", pRPMlog->msg);
special_scnprintf(buf, offset, "%x %x %x %x",
pRPMlog->arg[0], pRPMlog->arg[1],
pRPMlog->arg[2], pRPMlog->arg[3]);
if (cnt == max_cnt - 1)
special_scnprintf(buf, offset, "\",");
else
special_scnprintf(buf, offset, "/");
}
}
special_scnprintf(buf, offset, "\"TZ_RR\":\"%s\"",
p_rst_exinfo->tz_ex_info.msg);
special_scnprintf(buf, offset, ",\"TZBC\":\"");
max_cnt = sizeof(p_rst_exinfo->tz_ex_info.cpu_status);
max_cnt = max_cnt / sizeof(p_rst_exinfo->tz_ex_info.cpu_status[0]);
for (cnt = 0; cnt < max_cnt; cnt++) {
if (p_rst_exinfo->tz_ex_info.cpu_status[cnt] >
INVALID_WARM_TERM_ENTRY_EXIT_COUNT)
special_scnprintf(buf, offset, "%s", tz_cpu_status[0]);
else
special_scnprintf(buf, offset, "%s",
tz_cpu_status[p_rst_exinfo->tz_ex_info.cpu_status[cnt]]);
if (cnt != max_cnt - 1)
special_scnprintf(buf, offset, ",");
}
special_scnprintf(buf, offset, "\"");
special_scnprintf(buf, offset,
",\"PIMEM\":\"0x%08x,0x%08x,0x%08x,0x%08x\"",
p_rst_exinfo->pimem_info.esr,
p_rst_exinfo->pimem_info.ear0,
p_rst_exinfo->pimem_info.esr_sdi,
p_rst_exinfo->pimem_info.ear0_sdi);
special_scnprintf(buf, offset,
",\"COST\":\"%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld\"",
(long int)p_rst_exinfo->cpu_stuck_info.cpu[0],
(long int)p_rst_exinfo->cpu_stuck_info.cpu[1],
(long int)p_rst_exinfo->cpu_stuck_info.cpu[2],
(long int)p_rst_exinfo->cpu_stuck_info.cpu[3],
(long int)p_rst_exinfo->cpu_stuck_info.cpu[4],
(long int)p_rst_exinfo->cpu_stuck_info.cpu[5],
(long int)p_rst_exinfo->cpu_stuck_info.cpu[6],
(long int)p_rst_exinfo->cpu_stuck_info.cpu[7]);
special_scnprintf(buf, offset, ",\"HYC\":\"%d\"",
p_rst_exinfo->hyp_ex_info.s2_fault_counter);
special_scnprintf(buf, offset, ",\"HYP\":\"%s\"",
p_rst_exinfo->hyp_ex_info.msg);
special_scnprintf(buf, offset, ",\"LPM\":\"");
max_cnt = sizeof(p_rst_exinfo->kern_ex_info.info.lpm_state);
max_cnt = max_cnt/sizeof(p_rst_exinfo->kern_ex_info.info.lpm_state[0]);
for (idx = 0; idx < max_cnt; idx++) {
special_scnprintf(buf, offset, "%x",
p_rst_exinfo->kern_ex_info.info.lpm_state[idx]);
if (idx != max_cnt - 1)
special_scnprintf(buf, offset, ",");
}
special_scnprintf(buf, offset, "\"");
special_scnprintf(buf, offset, ",\"PKO\":\"%x\"",
p_rst_exinfo->kern_ex_info.info.pko);
special_scnprintf(buf, offset, ",\"LR\":\"");
max_cnt = sizeof(p_rst_exinfo->kern_ex_info.info.lr_val);
max_cnt = max_cnt/sizeof(p_rst_exinfo->kern_ex_info.info.lr_val[0]);
for (idx = 0; idx < max_cnt; idx++) {
special_scnprintf(buf, offset, "%llx",
p_rst_exinfo->kern_ex_info.info.lr_val[idx]);
if (idx != max_cnt - 1)
special_scnprintf(buf, offset, ",");
}
special_scnprintf(buf, offset, "\"");
special_scnprintf(buf, offset, ",\"PC\":\"");
max_cnt = sizeof(p_rst_exinfo->kern_ex_info.info.pc_val);
max_cnt = max_cnt/sizeof(p_rst_exinfo->kern_ex_info.info.pc_val[0]);
for (idx = 0; idx < max_cnt; idx++) {
special_scnprintf(buf, offset, "%llx",
p_rst_exinfo->kern_ex_info.info.pc_val[idx]);
if (idx != max_cnt - 1)
special_scnprintf(buf, offset, ",");
}
special_scnprintf(buf, offset, "\"");
out:
kfree(p_rst_exinfo);
check_format(buf, &offset, SPECIAL_LEN_STR);
return offset;
}
static DEVICE_ATTR(extrb_info, 0440, show_extrb_info, NULL);
static ssize_t show_extrc_info(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t offset = 0;
unsigned int reset_reason;
unsigned int i = 0;
char *extrc_buf = NULL;
if (!__is_ready_debug_reset_header()) {
pr_info("updated nothing.\n");
goto out;
}
reset_reason = sec_debug_get_reset_reason();
if (!__is_valid_reset_reason(reset_reason))
goto out;
extrc_buf = kmalloc(SEC_DEBUG_RESET_EXTRC_SIZE, GFP_KERNEL);
if (!extrc_buf) {
pr_err("fail - kmalloc\n");
goto out;
}
if (!read_debug_partition(debug_index_reset_extrc_info, extrc_buf)) {
pr_err("fail - get param!!\n");
goto out;
}
special_scnprintf(buf, offset, "\"RR\":\"%s\",",
sec_debug_get_reset_reason_str(reset_reason));
special_scnprintf(buf, offset, "\"RWC\":\"%d\",",
sec_debug_get_reset_write_cnt());
/* check " character and then change ' character */
for (i = 0; i < SEC_DEBUG_RESET_EXTRC_SIZE; i++) {
if (extrc_buf[i] == '"')
extrc_buf[i] = '\'';
if (extrc_buf[i] == '\0')
break;
}
extrc_buf[SEC_DEBUG_RESET_EXTRC_SIZE-1] = '\0';
special_scnprintf(buf, offset, "\"LKL\":\"%s\"", &extrc_buf[offset]);
out:
kfree(extrc_buf);
check_format(buf, &offset, SPECIAL_LEN_STR);
return offset;
}
static DEVICE_ATTR(extrc_info, 0440, show_extrc_info, NULL);
static ssize_t show_extrt_info(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t offset = 0;
unsigned int reset_reason;
struct tzdbg_t *tz_diag_info = NULL;
struct tzdbg_log_v9_2_t *log_v9_2 = NULL;
unsigned int i = 0;
if (!__is_ready_debug_reset_header()) {
pr_info("updated nothing.\n");
goto out;
}
reset_reason = sec_debug_get_reset_reason();
if (!__is_valid_reset_reason(reset_reason))
goto out;
tz_diag_info = kmalloc(SEC_DEBUG_RESET_TZLOG_SIZE, GFP_KERNEL);
if (!tz_diag_info) {
pr_err("%s : fail - kmalloc\n", __func__);
goto out;
}
if (!read_debug_partition(debug_index_reset_tzlog, tz_diag_info)) {
pr_err("%s : fail - get param!!\n", __func__);
goto out;
}
special_scnprintf(buf, offset, "\"RR\":\"%s\",",
sec_debug_get_reset_reason_str(reset_reason));
special_scnprintf(buf, offset, "\"RWC\":\"%d\",",
sec_debug_get_reset_write_cnt());
if (tz_diag_info->magic_num != TZ_DIAG_LOG_MAGIC) {
special_scnprintf(buf, offset,
"\"ERR\":\"tzlog magic num error\"");
goto out;
}
if (tz_diag_info->version > TZBSP_DIAG_VERSION_V9_2) {
struct tzbsp_encr_info_t *encr_info = (struct tzbsp_encr_info_t *)((void *)tz_diag_info
+ tz_diag_info->v9_3.encr_info_for_log_off);
if (encr_info->chunks[1].size_to_encr > 0x200) { /* 512 byte */
special_scnprintf(buf, offset,
"\"ERR\":\"tzlog size over\"");
goto out;
}
special_scnprintf(buf, offset, "\"TZDA\":\"");
special_scnprintf(buf, offset, "%08X%08X",
cpu_to_be32(tz_diag_info->magic_num),
cpu_to_be32(tz_diag_info->version));
special_scnprintf(buf, offset, "%08X%08X%08X%08X",
cpu_to_be32(tz_diag_info->ring_off),
cpu_to_be32(tz_diag_info->ring_len),
cpu_to_be32(tz_diag_info->v9_3.encr_info_for_log_off),
cpu_to_be32(encr_info->chunks[1].size_to_encr));
for (i = 0; i < TZBSP_AES_256_ENCRYPTED_KEY_SIZE; i++)
special_scnprintf(buf, offset, "%02X", encr_info->key[i]);
for (i = 0; i < TZBSP_NONCE_LEN; i++)
special_scnprintf(buf, offset, "%02X", encr_info->chunks[1].nonce[i]);
for (i = 0; i < TZBSP_TAG_LEN; i++)
special_scnprintf(buf, offset, "%02X", encr_info->chunks[1].tag[i]);
log_v9_2 = (struct tzdbg_log_v9_2_t *)((void *)tz_diag_info
+ tz_diag_info->ring_off - sizeof(struct tzdbg_log_pos_v9_2_t));
special_scnprintf(buf, offset, "%08X%08X",
cpu_to_be32(log_v9_2->log_pos.wrap),
cpu_to_be32(log_v9_2->log_pos.offset));
for (i = 0; i < encr_info->chunks[1].size_to_encr; i++)
special_scnprintf(buf, offset, "%02X", log_v9_2->log_buf[i]);
special_scnprintf(buf, offset, "\"");
} else {
if (tz_diag_info->ring_len > 0x200) { /* 512 byte */
special_scnprintf(buf, offset,
"\"ERR\":\"tzlog size over\"");
goto out;
}
special_scnprintf(buf, offset, "\"TZDA\":\"");
special_scnprintf(buf, offset, "%08X%08X",
tz_diag_info->magic_num,
tz_diag_info->version);
special_scnprintf(buf, offset, "%08X%08X%08X%08X",
tz_diag_info->cpu_count,
tz_diag_info->ring_off,
tz_diag_info->ring_len,
tz_diag_info->v9_2.num_interrupts);
for (i = 0; i < TZBSP_AES_256_ENCRYPTED_KEY_SIZE; i++)
special_scnprintf(buf, offset, "%02X",
tz_diag_info->v9_2.key[i]);
for (i = 0; i < TZBSP_NONCE_LEN; i++)
special_scnprintf(buf, offset, "%02X",
tz_diag_info->v9_2.nonce[i]);
for (i = 0; i < TZBSP_TAG_LEN; i++)
special_scnprintf(buf, offset, "%02X",
tz_diag_info->v9_2.tag[i]);
if (tz_diag_info->version == TZBSP_DIAG_VERSION_V9_2) {
log_v9_2 = (struct tzdbg_log_v9_2_t *)((void *)tz_diag_info
+ tz_diag_info->ring_off - sizeof(struct tzdbg_log_pos_v9_2_t));
special_scnprintf(buf, offset, "%08X%08X",
log_v9_2->log_pos.wrap,
log_v9_2->log_pos.offset);
for (i = 0; i < tz_diag_info->ring_len; i++)
special_scnprintf(buf, offset, "%02X",
log_v9_2->log_buf[i]);
} else {
struct tzdbg_log_t *log = (struct tzdbg_log_t *)((void *)tz_diag_info
+ tz_diag_info->ring_off - sizeof(struct tzdbg_log_pos_t));
special_scnprintf(buf, offset, "%04X%04X",
log->log_pos.wrap,
log->log_pos.offset);
for (i = 0; i < tz_diag_info->ring_len; i++)
special_scnprintf(buf, offset, "%02X", log->log_buf[i]);
}
special_scnprintf(buf, offset, "\"");
}
out:
kfree(tz_diag_info);
check_format(buf, &offset, SPECIAL_LEN_STR);
return offset;
}
static DEVICE_ATTR(extrt_info, 0440, show_extrt_info, NULL);
static ssize_t show_extrm_info(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t offset = 0;
unsigned int reset_reason;
char *extrm_buf = NULL;
if (!__is_ready_debug_reset_header()) {
pr_info("updated nothing.\n");
goto out;
}
reset_reason = sec_debug_get_reset_reason();
if (!__is_valid_reset_reason(reset_reason))
goto out;
extrm_buf = kmalloc(SEC_DEBUG_RESET_ETRM_SIZE, GFP_KERNEL);
if (!extrm_buf) {
pr_err("%s : fail - kmalloc\n", __func__);
goto out;
}
if (!read_debug_partition(debug_index_reset_rkplog, extrm_buf)) {
pr_err("%s : fail - get param!!\n", __func__);
goto out;
}
offset += scnprintf((char*)(buf + offset), SPECIAL_LEN_STR - offset,
"\"RR\":\"%s\",", sec_debug_get_reset_reason_str(reset_reason));
offset += scnprintf((char*)(buf + offset), SPECIAL_LEN_STR - offset,
"\"RWC\":\"%d\",", sec_debug_get_reset_write_cnt());
extrm_buf[SEC_DEBUG_RESET_ETRM_SIZE - 1] = '\0';
offset += scnprintf((char*)(buf + offset), SPECIAL_LEN_STR - offset,
"\"RKP\":\"%s\"", extrm_buf);
out:
if (extrm_buf)
kfree(extrm_buf);
check_format(buf, &offset, SPECIAL_LEN_STR);
return offset;
}
static DEVICE_ATTR(extrm_info, 0440, show_extrm_info, NULL);
static int sec_hw_param_dbg_part_notifier_callback(
struct notifier_block *nfb, unsigned long action, void *data)
{
switch (action) {
case DBG_PART_DRV_INIT_DONE:
phealth = ap_health_data_read();
clean_batt_info();
break;
default:
return NOTIFY_DONE;
}
return NOTIFY_OK;
}
static struct attribute *sec_hw_param_attributes[] = {
&dev_attr_ap_info.attr,
&dev_attr_ddr_info.attr,
&dev_attr_eye_rd_info.attr,
#if !defined(CONFIG_SEC_NOEYEINFO)
&dev_attr_eye_wr1_info.attr,
&dev_attr_eye_wr2_info.attr,
&dev_attr_eye_dcc_info.attr,
#endif
&dev_attr_ap_health.attr,
&dev_attr_last_dcvs.attr,
&dev_attr_extra_info.attr,
&dev_attr_extrb_info.attr,
&dev_attr_extrc_info.attr,
&dev_attr_extrt_info.attr,
&dev_attr_extrm_info.attr,
NULL,
};
static const struct attribute_group sec_hw_param_attribute_group = {
.attrs = sec_hw_param_attributes,
};
#define EXTEND_RR_SIZE 150
static int sec_errp_extra_show(struct seq_file *m, void *v)
{
ssize_t offset = 0;
unsigned int reset_reason;
rst_exinfo_t *p_rst_exinfo = NULL;
_kern_ex_info_t *p_kinfo = NULL;
int cpu = -1;
char upload_cause_str[80] = {0,};
char buf[EXTEND_RR_SIZE] = {0, };
if (!__is_ready_debug_reset_header()) {
pr_info("updated nothing.\n");
goto out;
}
reset_reason = sec_debug_get_reset_reason();
if (!__is_valid_reset_reason(reset_reason))
goto out;
p_rst_exinfo = kmalloc(sizeof(rst_exinfo_t), GFP_KERNEL);
if (!p_rst_exinfo)
goto out;
if (!read_debug_partition(debug_index_reset_ex_info, p_rst_exinfo)) {
pr_err("fail - get param!!\n");
goto out;
}
p_kinfo = &p_rst_exinfo->kern_ex_info.info;
cpu = p_kinfo->cpu;
offset += scnprintf((char*)(buf + offset), EXTEND_RR_SIZE - offset,
"RWC:%d", sec_debug_get_reset_write_cnt());
if (reset_reason == USER_UPLOAD_CAUSE_SMPL) {
if (strstr(p_kinfo->panic_buf, "SMPL")) {
offset += scnprintf((char*)(buf + offset), EXTEND_RR_SIZE - offset,
" PANIC:%s", p_kinfo->panic_buf);
}
goto out;
}
if (p_rst_exinfo->uc_ex_info.magic == RESTART_REASON_SEC_DEBUG_MODE) {
offset += scnprintf((char*)(buf + offset), EXTEND_RR_SIZE - offset,
" UPLOAD:%s", p_rst_exinfo->uc_ex_info.str);
} else {
sec_debug_upload_cause_str(p_kinfo->upload_cause,
upload_cause_str, sizeof(upload_cause_str));
offset += scnprintf((char*)(buf + offset), EXTEND_RR_SIZE - offset,
" UPLOAD:%s_0x%x", upload_cause_str, p_kinfo->upload_cause);
}
if (reset_reason == USER_UPLOAD_CAUSE_WATCHDOG) {
goto out;
} else if (reset_reason == USER_UPLOAD_CAUSE_WTSR
|| reset_reason == USER_UPLOAD_CAUSE_POWER_RESET) {
offset += scnprintf((char*)(buf + offset), EXTEND_RR_SIZE - offset,
" TZ_RR:%s", p_rst_exinfo->tz_ex_info.msg);
goto out;
}
offset += scnprintf((char*)(buf + offset), EXTEND_RR_SIZE - offset,
" PANIC:%s", p_kinfo->panic_buf);
offset += scnprintf((char*)(buf + offset), EXTEND_RR_SIZE - offset,
" PC:%s", p_kinfo->pc);
offset += scnprintf((char*)(buf + offset), EXTEND_RR_SIZE - offset,
" LR:%s", p_kinfo->lr);
out:
kfree(p_rst_exinfo);
if (offset != 0)
seq_puts(m, buf);
return 0;
}
#ifdef CONFIG_SEC_PM
static ssize_t show_pwrsrc(struct device *dev,
struct device_attribute *attr, char *buf)
{
return 0; //sec_get_pwrsrc(buf);
}
static DEVICE_ATTR(pwrsrc, 0440, show_pwrsrc, NULL);
#endif
static struct attribute *sec_reset_reason_attributes[] = {
#ifdef CONFIG_SEC_PM
&dev_attr_pwrsrc.attr,
#endif
NULL,
};
static const struct attribute_group sec_reset_reason_attribute_group = {
.attrs = sec_reset_reason_attributes,
};
static int sec_errp_extra_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, sec_errp_extra_show, NULL);
}
static const struct file_operations sec_errp_extra_proc_fops = {
.open = sec_errp_extra_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static struct notifier_block sec_hw_param_dbg_part_notifier = {
.notifier_call = sec_hw_param_dbg_part_notifier_callback,
};
static int __init sec_hw_param_init(void)
{
struct proc_dir_entry *entry;
struct device *sec_hw_param_dev;
struct device *sec_reset_reason_dev;
int err_hw_param;
int err_errp_extra = 0;
dbg_partition_notifier_register(&sec_hw_param_dbg_part_notifier);
sec_hw_param_dev = ___sec_device_create(NULL, "sec_hw_param");
if (IS_ERR(sec_hw_param_dev)) {
pr_err("Failed to create devce\n");
return -ENODEV;
}
err_hw_param = sysfs_create_group(&sec_hw_param_dev->kobj,
&sec_hw_param_attribute_group);
if (unlikely(err_hw_param)) {
pr_err("Failed to create device files!\n");
sec_device_destroy(sec_hw_param_dev->devt);
}
sec_reset_reason_dev = ___sec_device_create(NULL, "sec_reset_reason");
if (IS_ERR(sec_reset_reason_dev)) {
pr_err("Failed to create devce\n");
return -ENODEV;
}
entry = proc_create("extra", S_IWUGO, NULL,
&sec_errp_extra_proc_fops);
if (unlikely(!entry))
err_errp_extra = -ENODEV;
return (err_hw_param | err_errp_extra);
}
device_initcall(sec_hw_param_init);