mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
tsec: add debugfs support
add a debugfs file to read-out firmware log messages Change-Id: I3501b117884a822bd835beecd8e3956481c37386 Signed-off-by: Mayuresh Kulkarni <mkulkarni@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2884815 (cherry picked from commit 590640045e9ba26914cad055000f7ce3618640b9) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2895857 Tested-by: Bharat Nihalani <bnihalani@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
df86f78c76
commit
d3bc17ca8b
@@ -103,6 +103,134 @@ static void tsec_set_cg_regs(struct tsec_device_data *pdata)
|
|||||||
tsec_writel(pdata, tsec_riscv_cg_r(), 0x3);
|
tsec_writel(pdata, tsec_riscv_cg_r(), 0x3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
||||||
|
struct nvriscv_log_buffer {
|
||||||
|
/* read offset updated by client RM */
|
||||||
|
uint32_t read_offset;
|
||||||
|
/* write offset updated by firmware RM */
|
||||||
|
uint32_t write_offset;
|
||||||
|
/* buffer size configured by client RM */
|
||||||
|
uint32_t buffer_size;
|
||||||
|
/* magic number for header validation in nvwatch */
|
||||||
|
uint32_t magic;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LOG_BUF_SIZE ((4 * SZ_1K) - sizeof(struct nvriscv_log_buffer))
|
||||||
|
#define INFO_BUF_SIZE (SZ_128)
|
||||||
|
static u8 log_buf[LOG_BUF_SIZE]; /* Read from DMEM into local buffer */
|
||||||
|
static u8 info_buf[INFO_BUF_SIZE];
|
||||||
|
|
||||||
|
static int tsec_debug_show(struct seq_file *s, void *unused)
|
||||||
|
{
|
||||||
|
int info_len = 0;
|
||||||
|
struct tsec_device_data *pdata = (struct tsec_device_data *)s->private;
|
||||||
|
|
||||||
|
/* Do not attempt to read DMEM if TSEC is power-down */
|
||||||
|
if (pdata->power_on) {
|
||||||
|
#define DMEM_PORT (0)
|
||||||
|
/* Offset of Log Buffer in DMEM */
|
||||||
|
u32 log_bug_off = tsec_dmem_logbuf_offset_f();
|
||||||
|
u32 dmemC = tsec_falcon_dmemc_r(DMEM_PORT);
|
||||||
|
u32 dmemD = tsec_falcon_dmemd_r(DMEM_PORT);
|
||||||
|
struct nvriscv_log_buffer log_buf_info;
|
||||||
|
|
||||||
|
/* Auto Increment Read */
|
||||||
|
u32 loop_index = 0;
|
||||||
|
|
||||||
|
tsec_writel(pdata, dmemC, log_bug_off | 0x02000000);
|
||||||
|
while (loop_index < LOG_BUF_SIZE) {
|
||||||
|
u32 reg_val;
|
||||||
|
|
||||||
|
reg_val = tsec_readl(pdata, dmemD);
|
||||||
|
log_buf[loop_index++] = (u8)((reg_val >> 0) & 0xFF);
|
||||||
|
log_buf[loop_index++] = (u8)((reg_val >> 8) & 0xFF);
|
||||||
|
log_buf[loop_index++] = (u8)((reg_val >> 16) & 0xFF);
|
||||||
|
log_buf[loop_index++] = (u8)((reg_val >> 24) & 0xFF);
|
||||||
|
}
|
||||||
|
log_buf_info.read_offset = tsec_readl(pdata, dmemD);
|
||||||
|
log_buf_info.write_offset = tsec_readl(pdata, dmemD);
|
||||||
|
log_buf_info.buffer_size = tsec_readl(pdata, dmemD);
|
||||||
|
log_buf_info.magic = tsec_readl(pdata, dmemD);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replace any null charecter with new line because tsec ucode
|
||||||
|
* does the reverse before dumping the logs in the buffer
|
||||||
|
*/
|
||||||
|
for (loop_index = 0; loop_index < LOG_BUF_SIZE; loop_index++) {
|
||||||
|
if (log_buf[loop_index] == 0)
|
||||||
|
log_buf[loop_index] = 0xA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert null charecter at end of log buffer */
|
||||||
|
log_buf[log_buf_info.write_offset] = 0;
|
||||||
|
|
||||||
|
/* Print log_buf */
|
||||||
|
info_len = sprintf(info_buf,
|
||||||
|
"Tsec Logs Start: read_offset=%d write_offset=%d buffer_size=%d magic=0x%x\n",
|
||||||
|
log_buf_info.read_offset, log_buf_info.write_offset,
|
||||||
|
log_buf_info.buffer_size, log_buf_info.magic);
|
||||||
|
if (info_len > 0)
|
||||||
|
seq_write(s, info_buf, info_len);
|
||||||
|
|
||||||
|
seq_write(s, log_buf,
|
||||||
|
(log_buf_info.write_offset - log_buf_info.read_offset));
|
||||||
|
|
||||||
|
info_len = strlen("Tsec Logs End\n");
|
||||||
|
strcpy(info_buf, "Tsec Logs End\n");
|
||||||
|
info_buf[info_len] = '\0';
|
||||||
|
seq_write(s, info_buf, info_len);
|
||||||
|
} else {
|
||||||
|
info_len = strlen("Tsec power-down\n");
|
||||||
|
strcpy(info_buf, "Tsec power-down\n");
|
||||||
|
info_buf[info_len] = '\0';
|
||||||
|
seq_write(s, info_buf, info_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tsec_debug_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, tsec_debug_show, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations tsec_debug_fops = {
|
||||||
|
.open = tsec_debug_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TSEC debugfs interface
|
||||||
|
* create: /sys/kernel/debug/tegra_tsec/fw_logs.
|
||||||
|
* cat /sys/kernel/debug/tegra_tsec/fw_logs will read the DMEM reserved for
|
||||||
|
* debug messages and print it on console.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int tsec_module_init_debugfs(struct platform_device *dev)
|
||||||
|
{
|
||||||
|
struct tsec_device_data *pdata = platform_get_drvdata(dev);
|
||||||
|
|
||||||
|
pdata->debug_root = debugfs_create_dir("tegra_tsec", NULL);
|
||||||
|
if (!pdata->debug_root)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
debugfs_create_file("fw_logs", 0444, pdata->debug_root,
|
||||||
|
pdata, &tsec_debug_fops);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tsec_module_deinit_debugfs(struct platform_device *dev)
|
||||||
|
{
|
||||||
|
struct tsec_device_data *pdata = platform_get_drvdata(dev);
|
||||||
|
|
||||||
|
debugfs_remove_recursive(pdata->debug_root);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DEBUG_FS */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TSEC Power Management Operations
|
* TSEC Power Management Operations
|
||||||
*/
|
*/
|
||||||
@@ -286,11 +414,25 @@ static int tsec_probe(struct platform_device *dev)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
if (debugfs_initialized()) {
|
||||||
|
err = tsec_module_init_debugfs(dev);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&dev->dev, "error %d in tsec_module_init_debugfs\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DEBUG_FS */
|
||||||
|
|
||||||
return tsec_kickoff_boot(dev);
|
return tsec_kickoff_boot(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tsec_remove(struct platform_device *dev)
|
static int tsec_remove(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
tsec_module_deinit_debugfs(dev);
|
||||||
|
#endif /* CONFIG_DEBUG_FS */
|
||||||
|
|
||||||
return tsec_poweroff(&dev->dev);
|
return tsec_poweroff(&dev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ struct tsec_device_data {
|
|||||||
char *riscv_desc_bin;
|
char *riscv_desc_bin;
|
||||||
/* name of riscv image binary */
|
/* name of riscv image binary */
|
||||||
char *riscv_image_bin;
|
char *riscv_image_bin;
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
struct dentry *debug_root;
|
||||||
|
#endif /* CONFIG_DEBUG_FS */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -29,5 +29,9 @@
|
|||||||
#include <linux/platform/tegra/tegra_mc.h> /* for mc_get_carveout_info */
|
#include <linux/platform/tegra/tegra_mc.h> /* for mc_get_carveout_info */
|
||||||
#include <asm/cacheflush.h> /* for __flush_dcache_area */
|
#include <asm/cacheflush.h> /* for __flush_dcache_area */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
#include <linux/debugfs.h> /* for debugfs APIs */
|
||||||
|
#endif
|
||||||
|
#include <linux/sizes.h> /* for SZ_* size macros */
|
||||||
|
|
||||||
#endif /* TSEC_LINUX_H */
|
#endif /* TSEC_LINUX_H */
|
||||||
|
|||||||
@@ -251,4 +251,21 @@ static inline u32 tsec_riscv_br_retcode_result_pass_v(void)
|
|||||||
return 0x00000003;
|
return 0x00000003;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u32 tsec_falcon_dmemc_r(u32 r)
|
||||||
|
{
|
||||||
|
/* NV_PSEC_FALCON_DMEMC_0 */
|
||||||
|
return (0x11c0 + (r) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 tsec_falcon_dmemd_r(u32 r)
|
||||||
|
{
|
||||||
|
/* NV_PSEC_FALCON_DMEMD_0 */
|
||||||
|
return (0x11c4 + (r) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 tsec_dmem_logbuf_offset_f(void)
|
||||||
|
{
|
||||||
|
return 0x14000;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* TSEC_REGS_H */
|
#endif /* TSEC_REGS_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user